1 | /***************************************
2 | $Revision: 1.12 $
3 |
4 | UP external syntax checks
5 |
6 | Status: REVIEWED, NOT TESTED
7 |
8 | Author(s): Engin Gunduz
9 |
10 | ******************/ /******************
11 | Modification History:
12 | engin (15/12/2000) Created.
13 | denis (31/08/2001) Modified for new API
14 | ******************/ /******************
15 | Copyright (c) 2001,2002 RIPE NCC
16 |
17 | All Rights Reserved
18 |
19 | Permission to use, copy, modify, and distribute this software and its
20 | documentation for any purpose and without fee is hereby granted,
21 | provided that the above copyright notice appear in all copies and that
22 | both that copyright notice and this permission notice appear in
23 | supporting documentation, and that the name of the author not be
24 | used in advertising or publicity pertaining to distribution of the
25 | software without specific, written prior permission.
26 |
27 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
28 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
29 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
30 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
31 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 | ***************************************/
34 |
35 |
36 | /*#include "rpsl/object.hh"*/
37 | #include "UP_extrnl_syntax.h"
38 | #include "dbupdate.h"
39 |
40 | #define UP_DATE_OK 0
41 | #define UP_DATE_SYNERR 1
42 | #define UP_DATE_FUTURE 2
43 | #define UP_DATE_TOOSMALL 3
44 | #define UP_DATE_INVMONTH 4
45 | #define UP_DATE_INVDAY 5
46 | #define UP_DATE_WRONGFORMAT 6
47 | #define UP_DATE_NOK 7
48 |
49 | char * up_date_errmsgs[]=
50 | {
51 |
52 | "OK",
53 | "Syntax error in date of 'changed' attribute",
54 | "Date in the future in 'changed' attribute",
55 | "Date is older than the database itself in 'changed' attribute",
56 | "Invalid month in date in 'changed' attribute",
57 | "Invalid day in date in 'changed' attribute",
58 | "Date must be in YYYYMMDD format in 'change' attribute",
59 | "Syntax error in date of 'changed' attribute"
60 | };
61 |
62 |
63 | extern int tracing;
64 |
65 | extern char * fingerprint;
66 | extern char * keyowner;
67 |
68 | extern char * allocmnt;
69 |
70 | extern char *sources[];
71 | extern char *countries[];
72 | extern char *nicsuffixes[];
73 |
74 |
75 | /* void up_check_source_attr
76 | checks for a valid source in the 'source' attributes */
77 | void up_check_source_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
78 | {
79 | int valid,i ;
80 | char *source_name;
81 | char *temp;
82 | GList *source_list;
83 |
84 | source_list = rpsl_object_get_attr(external_syntax_obj, "source");
85 |
86 | valid = i = 0 ;
87 | if ( source_list )
88 | {
89 | source_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(source_list->data) );
90 | while(sources[i])
91 | {
92 | if(strcasecmp(sources[i++],source_name) == 0)
93 | {
94 | valid = 1;
95 | break;
96 | }
97 | }
98 | free(source_name);
99 | g_list_free(source_list);
100 | }
101 |
102 | if (!valid)
103 | {
104 | /* the source is not recognised */
105 | if (result->error_str == NULL)
106 | {
107 | result->error_str = strdup("***Error: No such source");
108 | }
109 | else
110 | {
111 | temp = (char *)malloc(strlen(result->error_str)
112 | + strlen("***Error: No such source") + 2);
113 | sprintf(temp, "%s\n%s", result->error_str,
114 | "***Error: No such source");
115 | free(result->error_str);
116 | result->error_str = temp;
117 | }
118 | /* and here we have to change the result code of "result" here ... */
119 | switch (result->result)
120 | {
121 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
122 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
123 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
124 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
125 | default: ;
126 | }
127 | }
128 | }
129 |
130 |
131 | /* void up_check_country_attr
132 | checks for a valid country in the 'country' attributes */
133 | void up_check_country_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
134 | {
135 | int valid,i, matched ;
136 | char *country_name;
137 | char *temp;
138 | GList *country_list = NULL;
139 | GList *country_item = NULL;
140 |
141 | country_list = rpsl_object_get_attr(external_syntax_obj, "country");
142 |
143 | if ( country_list == NULL )
144 | return; /* only check if there is one */
145 |
146 | valid = 1 ;
147 | for ( country_item = country_list; country_item != NULL ; country_item = g_list_next(country_item) )
148 | {
149 | country_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(country_item->data) );
150 | matched = 0 ;
151 | i = 0 ;
152 | while(countries[i])
153 | {
154 | if(strcasecmp(countries[i++],country_name) == 0)
155 | {
156 | matched = 1;
157 | break;
158 | }
159 | }
160 |
161 | if ( ! matched )
162 | {
163 | valid = 0 ;
164 | break;
165 | }
166 | free(country_name);
167 | }
168 | g_list_free(country_list);
169 |
170 | if (!valid)
171 | {
172 | /* the country is not recognised */
173 | if (result->error_str == NULL)
174 | {
175 | result->error_str = malloc(strlen("***Error: No such country []") + strlen(country_name) +2);
176 | sprintf(result->error_str, "***Error: No such country [%s]", country_name);
177 | }
178 | else
179 | {
180 | temp = (char *)malloc(strlen(result->error_str)
181 | + strlen("***Error: No such country []") + strlen(country_name) + 2);
182 | sprintf(temp, "%s\n***Error: No such country [%s]", result->error_str,
183 | country_name);
184 | free(result->error_str);
185 | result->error_str = temp;
186 | }
187 |
188 | free(country_name);
189 |
190 | /* and here we have to change the result code of "result" here ... */
191 | switch (result->result)
192 | {
193 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
194 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
195 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
196 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
197 | default: ;
198 | }
199 | }
200 | }
201 |
202 | /* void up_check_nicsuffixes
203 | checks for a valid suffix at the end of a 'nic-hdl' attributes */
204 | void up_check_nicsuffixes(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
205 | {
206 | int valid,i ;
207 | char *name;
208 | char *temp;
209 | GList *list;
210 |
211 | list = rpsl_object_get_attr(external_syntax_obj, "nic-hdl");
212 |
213 | valid = i = 0 ;
214 | if ( list )
215 | {
216 | name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(list->data) );
217 | if ( !strchr(name,'-') || strncasecmp(name,"AUTO-",strlen("AUTO-")) == 0 )
218 | {
219 | valid = 1;
220 | }
221 | else
222 | {
223 | while (nicsuffixes[i])
224 | {
225 | if ( strcasecmp(nicsuffixes[i++],strchr(name,'-')+1) == 0 )
226 | {
227 | valid = 1;
228 | break;
229 | }
230 | }
231 | if ( ! valid )
232 | {
233 | i = 0;
234 | while (sources[i])
235 | {
236 | if (strcasecmp(sources[i++],strchr(name,'-')+1) == 0 )
237 | {
238 | valid = 1;
239 | break;
240 | }
241 | }
242 | if ( ! valid )
243 | {
244 | i = 0;
245 | while (countries[i])
246 | {
247 | if ( strcasecmp(countries[i++],strchr(name,'-')+1) == 0 )
248 | {
249 | valid = 1;
250 | break;
251 | }
252 | }
253 | }
254 | }
255 | }
256 | free(name);
257 | g_list_free(list);
258 |
259 | if (!valid)
260 | {
261 | /* the nicsuffix is not recognised */
262 | if (result->error_str == NULL)
263 | {
264 | result->error_str = strdup("***Error: Invalid nic-hdl suffix");
265 | }
266 | else
267 | {
268 | temp = (char *)malloc(strlen(result->error_str)
269 | + strlen("***Error: Invalid nic-hdl suffix") + 2);
270 | sprintf(temp, "%s\n%s", result->error_str,
271 | "***Error: Invalid nic-hdl suffix");
272 | free(result->error_str);
273 | result->error_str = temp;
274 | }
275 | /* and here we have to change the result code of "result" here ... */
276 | switch (result->result)
277 | {
278 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
279 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
280 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
281 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
282 | default: ;
283 | }
284 | }
285 | }
286 | }
287 |
288 |
289 | /* obtains a list of dates in the given
290 | list of attributes */
291 | GList * up_get_dates(GList * attribute_list)
292 | {
293 | GList * item;
294 | char * str, *temp;
295 | GList * list = NULL;
296 |
297 | for ( item = attribute_list; item != NULL ; item = g_list_next(item) )
298 | {
299 | /* is this a 'changed' attribute? */
300 | if ( strcmp(rpsl_attr_get_name((rpsl_attr_t *)(item->data)), "changed") == 0 )
301 | {
302 | str = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
303 |
304 |
305 | /* now, we have the 'changed' attribute's content in "normalized" form
306 | We are sure it contains a date. So, it must be the second (and last)
307 | word in the attrib. */
308 | assert(index(str,' ') != NULL);
309 | temp = (char *)malloc(strlen(str) - (index(str,' ') - str ));
310 | temp = strncpy(temp, index(str,' ') + 1, strlen(str) - (index(str,' ') - str ) - 1);
311 | temp[strlen(str) - (index(str,' ') - str ) - 1] = '\0'; /* NULL terminate it */
312 | list = g_list_append (list, temp);
313 | }
314 | }
315 |
316 | return list;
317 | }
318 |
319 |
320 |
321 |
322 | /* Does the 'changed' attribute we got have a date already?
323 | Returns 1 if it does, 0 if not. */
324 | int up_changed_has_date(char * value)
325 | {
326 | /* now, if there is still a white space, then we have a date in the string
327 | (it has to be something like "ripe-dbm@ripe.net 20001210") */
328 | if (index(value, ' ') != NULL)
329 | {
330 | return 1;
331 | }
332 | else
333 | {
334 | return 0;
335 | }
336 | }
337 |
338 |
339 |
340 |
341 | /* supplies the current date in YYYYMMDD format (for example 20011010) */
342 | char * UP_get_current_date()
343 | {
344 | /* We will use Glib's functions here */
345 |
346 | char * date;
347 | struct tm * time_struct;
348 |
349 | time_t * time_loc;
350 |
351 | time_loc = (time_t *)malloc(sizeof(time_t));
352 | time(time_loc);
353 |
354 | time_struct = localtime(time_loc);
355 |
356 |
357 | date = (char *)malloc(9);
358 | sprintf(date, "%04i%02i%02i",
359 | time_struct->tm_year + 1900,
360 | time_struct->tm_mon + 1,
361 | time_struct->tm_mday);
362 | return date;
363 | }
364 |
365 |
366 |
367 |
368 | /* int up_add_dates: adds dates to 'changed' attributes which
369 | are missing one.
370 | Returns 1 if no problems encountered
371 | Returns 0 if a problem encountered, and the error string is set */
372 | int up_add_dates(rpsl_object_t *external_syntax_obj, GList *attribute_list, char ** warning_str, char ** error_str)
373 | {
374 | GList * item;
375 | char * current_date;
376 | int count_no_date = 0;
377 | char * temp;
378 | rpsl_attr_t *changed;
379 | char *value;
380 | int pos;
381 |
382 | *warning_str = NULL;
383 | *error_str = NULL;
384 |
385 | /* get the current date in YYYYMMDD format (for example 20011010) */
386 | current_date = UP_get_current_date();
387 |
388 | for ( item = attribute_list; item != NULL ; item = g_list_next(item) )
389 | {
390 | /* is this a 'changed' attribute? */
391 | if (strcmp(rpsl_attr_get_name((rpsl_attr_t *)(item->data)), "changed") == 0)
392 | {
393 | /* if this attribute does not have a date in it, add it. Also add
394 | a warning message about this */
395 | value = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
396 | if ( !up_changed_has_date(value) )
397 | {
398 | count_no_date++;
399 | /* create a copy of this changed attribute and add the date to the value */
400 | changed = rpsl_attr_copy((rpsl_attr_t *)(item->data));
401 | temp = (char *)malloc(strlen(value) + strlen(current_date) + 2 );
402 | sprintf(temp, "%s %s", value, current_date);
403 | rpsl_attr_replace_value(changed, temp);
404 | free(temp);
405 | /* delete the original attribute from the object */
406 | pos = rpsl_attr_get_ofs(changed);
407 | rpsl_object_remove_attr(external_syntax_obj, pos, NULL);
408 | /* add the new changed attribute in the same position */
409 | rpsl_object_add_attr(external_syntax_obj, changed, pos, NULL);
410 | /* add a warning message */
411 | if ( *warning_str == NULL)
412 | {
413 | *warning_str = (char *)malloc(strlen("WARNING date '' added to 'changed' attribute") + 9 );
414 | sprintf(*warning_str, "WARNING date '%s' added to 'changed' attribute", current_date);
415 | }
416 | else
417 | {
418 | temp = (char *)malloc(strlen(*warning_str) + 1
419 | + strlen("WARNING date '' added to 'changed' attribute") + 9 );
420 | sprintf(temp, "%s\nWARNING date '%s' added to 'changed' attribute",
421 | *warning_str, current_date);
422 | free(*warning_str);
423 | *warning_str = temp;
424 | }
425 | }
426 | free(value);
427 | }
428 | }
429 |
430 | if (count_no_date > 1)
431 | {
432 | *error_str = strdup("***Error: More than one 'changed' attributes without dates");
433 | return 0;
434 | }
435 | else
436 | {
437 | return 1;
438 | }
439 | }
440 |
441 |
442 |
443 |
444 | /* Checks the order of dates in the given list.
445 | If they are in order, returns 1,
446 | if not, returns 0 */
447 | int up_check_date_order(GList * list)
448 | {
449 | GList * item;
450 | char * previous;
451 | char *value;
452 |
453 | /* if list is empty, return 1 immediately */
454 | if (list == NULL)
455 | {
456 | return 1;
457 | }
458 |
459 | /* initialize the 'previous' date */
460 | previous = strdup("00000000");
461 |
462 | for ( item = list; item != NULL ; item = g_list_next(item))
463 | {
464 | assert((item->data) != NULL);
465 | /* if the new date is smaller than the previous */
466 | value = (char *)(item->data);
467 | if ( strcmp(value, previous) < 0 )
468 | {
469 | free(previous);
470 | return 0;
471 | }
472 | free(previous);
473 | previous = strdup(value);
474 | }
475 |
476 | free(previous);
477 | /* Reached the end, without finding out-of-order date. Return 1, then */
478 | return 1;
479 | }
480 |
481 |
482 |
483 |
484 |
485 | /* up_check_date: checks the syntax of the date, given as the only
486 | argument (char *). The argument is checked if it is in YYYYMMDD
487 | format, and returns an error code accordingly */
488 | int up_check_date(const char * arg)
489 | {
490 | int date_int; /* integer representation of the date (arg) */
491 | char * current_date;
492 | int year, month, day; /* integers for the components of the date */
493 |
494 | errno = 0;
495 | date_int = atoi(arg);
496 |
497 | if (errno != 0)
498 | { /* there was an error in the conversion, syntax error */
499 | return UP_DATE_SYNERR;
500 | }
501 |
502 | /* wrong format */
503 | if (date_int <= 10000000 )
504 | { /* the date is not in YYYYMMDD format */
505 | return UP_DATE_WRONGFORMAT;
506 | }
507 |
508 | /* check if it is too small */
509 | if (date_int <= 19880000 )
510 | { /* the date is older than the DB itself! */
511 | return UP_DATE_TOOSMALL;
512 | }
513 |
514 | /* check if it is too big */
515 | if (date_int >= 100000000 )
516 | {/* too big: syntax error */
517 | return UP_DATE_SYNERR;
518 | }
519 |
520 | /* and now check year, month and day components */
521 | year = date_int / 10000;
522 | month = (date_int - (year * 10000) ) / 100;
523 | day = (date_int % 100);
524 |
525 | /* check year */
526 | if (year < 1988 )
527 | {
528 | return UP_DATE_TOOSMALL;
529 | }
530 |
531 | /* check month */
532 | if (month < 1 || month > 12)
533 | {
534 | return UP_DATE_INVMONTH;
535 | }
536 |
537 | /* check day */
538 | if (day < 1 || day > 31)
539 | {
540 | return UP_DATE_INVDAY;
541 | }
542 |
543 | switch ( month )
544 | {
545 | case 1: case 3: case 5: case 7:
546 | case 8: case 10: case 12:
547 | if (day > 31)
548 | {
549 | return UP_DATE_INVDAY;
550 | };
551 | break;
552 | case 2:
553 | if ( (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) && (day > 29 ))
554 | { /* leap year */
555 | return UP_DATE_INVDAY;
556 | }
557 | else if( (!(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) && (day > 28) )
558 | { /* non-leap year */
559 | return UP_DATE_INVDAY;
560 | };
561 | break;
562 | case 4: case 6: case 9: case 11:
563 | if (day > 30)
564 | {
565 | return UP_DATE_INVDAY;
566 | };
567 | break;
568 | default: return UP_DATE_INVMONTH;
569 | }
570 |
571 | /* check if the arg is in the future or not */
572 | current_date = UP_get_current_date();
573 | if (strcmp(current_date, arg) < 0 )
574 | { /* arg is in the future */
575 | free(current_date);
576 | return UP_DATE_FUTURE;
577 | }
578 | free(current_date);
579 |
580 | return UP_DATE_OK;
581 | }
582 |
583 |
584 |
585 | /* Checks the syntax of the dates in the list */
586 | date_syntax_struct * up_check_dates_syntax(GList * list)
587 | {
588 | GList * item;
589 | date_syntax_struct * result;
590 | int res;
591 |
592 | /* initialize the result struct */
593 | result = (date_syntax_struct *)malloc(sizeof(date_syntax_struct));
594 | result->result = UP_DATE_OK;
595 | result->error_str = NULL;
596 |
597 | /* if list is empty, return immediately */
598 | if (list == NULL)
599 | {
600 | return result;
601 | }
602 |
603 | /* loop through the members of the list, check each of them */
604 | for ( item = list; item != NULL ; item = g_list_next(item))
605 | {
606 | assert((item->data) != NULL);
607 |
608 | /* check the date */
609 | res = up_check_date((char *)(item->data));
610 | switch (res)
611 | {
612 | case UP_DATE_OK: break;
613 |
614 | case UP_DATE_FUTURE:
615 | case UP_DATE_TOOSMALL:
616 | case UP_DATE_INVDAY:
617 | case UP_DATE_INVMONTH:
618 | case UP_DATE_WRONGFORMAT:
619 |
620 | if (result->error_str == NULL)
621 | {
622 | result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[res])
623 | + strlen(": ") + strlen((char *)(item->data)) + 1);
624 | sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[res],
625 | (char *)(item->data));
626 | }
627 | else
628 | {
629 | result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1
630 | + strlen("***Error: ") + strlen(up_date_errmsgs[res])
631 | + strlen(": ") + strlen((char *)(item->data)) + 1);
632 | sprintf(result->error_str, "%s\n***Error: %s: %s",
633 | result->error_str, up_date_errmsgs[res], (char *)(item->data));
634 | }
635 | result->result = UP_DATE_NOK; /* Not OK */
636 |
637 | break;
638 |
639 |
640 | case UP_DATE_SYNERR: /* syntax error in the date */
641 |
642 | default:
643 | if (result->error_str == NULL)
644 | {
645 | result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR])
646 | + strlen(": ") + strlen((char *)(item->data)) + 1);
647 | sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[UP_DATE_SYNERR],
648 | (char *)(item->data));
649 | }
650 | else
651 | {
652 | result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1
653 | + strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR])
654 | + strlen(": ") + strlen((char *)(item->data)) + 1);
655 | sprintf(result->error_str, "%s\n***Error: %s: %s",
656 | result->error_str, up_date_errmsgs[UP_DATE_SYNERR], (char *)(item->data));
657 | }
658 | result->result = UP_DATE_NOK; /* Not OK */
659 | break;
660 | }
661 | }
662 |
663 | return result;
664 | }
665 |
666 |
667 |
668 | /* void up_check_changed_attr
669 | checks the order of dates in the 'changed' attributes */
670 | void up_check_changed_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
671 | {
672 | GList * date_list;
673 | int res;
674 | char ** warning, **error;
675 | char * temp;
676 | date_syntax_struct * date_check_res;
677 | GList *changed_list;
678 |
679 | warning = (char **)malloc(sizeof(char **));
680 | error = (char **)malloc(sizeof(char **));
681 | changed_list = rpsl_object_get_attr(external_syntax_obj, "changed");
682 |
683 | /* Now, add dates to the "changed" attributes */
684 | res = up_add_dates(external_syntax_obj, changed_list, warning, error);
685 | if (!res)
686 | {
687 | /* so, add the error string to result's error string */
688 | if (result->error_str == NULL)
689 | {
690 | result->error_str = strdup(*error);
691 | }
692 | else
693 | {
694 | temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2);
695 | sprintf(temp, "%s\n%s", result->error_str, *error);
696 | free(result->error_str);
697 | result->error_str = temp;
698 | }
699 | }
700 |
701 | /* and get the list of dates, we must check their order */
702 | /* we may have added a date to one of the changed attrs so get the list again */
703 | rpsl_attr_delete_list(changed_list);
704 | changed_list = rpsl_object_get_attr(external_syntax_obj, "changed");
705 | date_list = up_get_dates(changed_list);
706 | /* and check the order */
707 | res = up_check_date_order(date_list);
708 | if (!res)
709 | {
710 | /* so, add the error string to result's error string */
711 | if (result->error_str == NULL)
712 | {
713 | result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order");
714 | }
715 | else
716 | {
717 | temp = (char *)malloc(strlen(result->error_str)
718 | + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2);
719 | sprintf(temp, "%s\n%s", result->error_str,
720 | "***Error: The dates in the 'changed' attributes should be in order");
721 | free(result->error_str);
722 | result->error_str = temp;
723 | }
724 | /* and here we have to change the result code of "result" here ... */
725 | switch (result->result)
726 | {
727 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
728 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
729 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
730 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
731 | default: ;
732 | }
733 | }
734 |
735 | /* check the syntax of dates */
736 | date_check_res = up_check_dates_syntax(date_list);
737 | if (date_check_res->result != UP_DATE_OK)
738 | {
739 | /* so, add the error string to result's error string */
740 | if (result->error_str == NULL)
741 | {
742 | result->error_str = strdup(date_check_res->error_str);
743 | }
744 | else
745 | {
746 | temp = (char *)malloc(strlen(result->error_str)
747 | + strlen(date_check_res->error_str) + 2);
748 | sprintf(temp, "%s\n%s", result->error_str,
749 | date_check_res->error_str);
750 | free(result->error_str);
751 | result->error_str = temp;
752 | }
753 | /* and here we have to change the result code of "result" here ... */
754 | switch (result->result)
755 | {
756 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
757 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
758 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
759 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
760 | default: ;
761 | }
762 | }
763 | }
764 |
765 |
766 | /* performs a simple check on a inetnum attribute. Assumes that
767 | the RPSL parser has already checked it. Tries to see if the attr
768 | is a range or not */
769 | int up_check_an_inetnum_attr(const char * arg){
770 |
771 |
772 | char * str;
773 | char * pos;
774 |
775 | str = strdup(arg);
776 |
777 | while((pos = index(str, '\n')) != NULL){
778 | *pos = ' ';
779 | }
780 |
781 | /* strip off the comment */
782 | if((pos = index(str, '#')) != NULL){
783 | *pos = '\0';
784 | }
785 |
786 |
787 | /* Most of the syntax check is done by RPSL parser. We only need to check
788 | that the argument is a _range_ of IPv4 addresses. So it suffices to
789 | check the existence of '-' in the arg */
790 | if(index(str, '-') != NULL){
791 |
792 | free(str);
793 | return 1;
794 |
795 | }else{
796 |
797 | free(str);
798 | return 0;
799 |
800 | }
801 | }
802 |
803 |
804 |
805 | /* Performs a check on status attribute. It can be
806 | ALLOCATED PI or ALLOCATED PA only if the maintainers in the
807 | mnt-by attribute contain at least one of the names mentioned in
808 | ALLOCMNT config variable.
809 | */
810 | int up_check_a_status_attr(const char * arg, GList * mnt_by_list)
811 | {
812 | GList * item;
813 | int result;
814 | char * status, * mnt_by_attrib;
815 | char ** allocmnt_list;
816 | int i;
817 |
818 | status = strdup(arg);
819 | g_strdown(status);
820 |
821 | /* construct a list of mntners that are in allocmnt */
822 | allocmnt_list = g_strsplit(allocmnt, " ", 0); /* delimited by " " */
823 |
824 | if (strstr(status, "allocated") != NULL)
825 | {
826 | result = 1; /* initialize */
827 |
828 | for ( item = mnt_by_list; item != NULL ; item = g_list_next(item) )
829 | {
830 | mnt_by_attrib = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
831 | for (i=0; allocmnt_list[i] != NULL; i++)
832 | { /* loop thru the list of allocmnt maintainers */
833 | if ((strlen(allocmnt_list[i]) != 0) && strcasecmp(mnt_by_attrib, allocmnt_list[i]) == 0)
834 | {
835 | result = 0;
836 | }
837 | }
838 | free(mnt_by_attrib);
839 | }
840 |
841 | free(status);
842 | g_strfreev(allocmnt_list);
843 | return result;
844 |
845 | }
846 | else
847 | { /* the status attribute is not allocated */
848 | free(status);
849 | g_strfreev(allocmnt_list);
850 | return 0; /* so there is no problem */
851 |
852 | }
853 |
854 | }
855 |
856 |
857 |
858 |
859 |
860 | /* check for status attribute here: The status attribute can be
861 | ALLOCATED PI or ALLOCATED PA only if the maintainers in the
862 | mnt-by attribute contain at least one of the names mentioned in
863 | ALLOCMNT config variable.
864 | */
865 | void up_check_status_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
866 | {
867 | int res;
868 | char * temp;
869 | char *value;
870 | GList * item;
871 | GList * mnt_by_list = NULL;
872 | GList *status_list = NULL;
873 |
874 | /* Gather a list of mnt-by attributes */
875 | mnt_by_list = rpsl_object_get_attr(external_syntax_obj, "mnt-by");
876 | status_list = rpsl_object_get_attr(external_syntax_obj, "status");
877 |
878 | /* check the syntax */
879 | for ( item = status_list; item != NULL ; item = g_list_next(item) )
880 | {
881 | value = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
882 | res = up_check_a_status_attr(value, mnt_by_list);
883 | if (res != 0)
884 | { /* there was a problem */
885 | /* so, add the error string to result's error string */
886 | if (result->error_str == NULL)
887 | {
888 | result->error_str = (char *)UT_malloc(strlen("***Error: Status ALLOCATED can be set only by the following mntner(s):\n")
889 | +strlen("***Error: ") + strlen(allocmnt) + 2);
890 | sprintf(result->error_str, "%s%s%s", "***Error: Status ALLOCATED can be set only by the following mntner(s):\n",
891 | "***Error: ", allocmnt);
892 | }
893 | else
894 | {
895 | temp = (char *)malloc(strlen(result->error_str)
896 | + strlen("***Error: Status ALLOCATED can be set only by the following mntner(s):\n")
897 | + strlen("***Error: ") + strlen(allocmnt) + 2);
898 | sprintf(temp, "%s\n%s%s%s", result->error_str,
899 | "***Error: Status ALLOCATED can be set only by the following mntner(s):\n",
900 | "***Error: ", allocmnt);
901 | free(result->error_str);
902 | result->error_str = temp;
903 | }
904 | /* and here we have to change the result code of "result" here ... */
905 | switch (result->result)
906 | {
907 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break;
908 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break;
909 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
910 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
911 | default: ;
912 | }
913 | }
914 | free(value);
915 | }
916 | rpsl_attr_delete_list(mnt_by_list);
917 | rpsl_attr_delete_list(status_list);
918 | }
919 |
920 |
921 |
922 |
923 | /* void up_add_keycert_attrs
924 | adds the generated attrs of key-cert objects */
925 | void up_add_keycert_attrs(rpsl_object_t *generated_obj)
926 | {
927 | const char *type;
928 | char *attr_str;
929 | rpsl_attr_t *method_attr;
930 | rpsl_attr_t *owner_attr;
931 | rpsl_attr_t *fingerpr_attr;
932 |
933 | if (tracing)
934 | {
935 | printf("TRACING: UP_add_keycert_attrs: is running\n");
936 | }
937 |
938 | /* if this is a key-cert object */
939 | type = rpsl_object_get_class(generated_obj);
940 | if ( strcmp(type, "key-cert") == 0 )
941 | {
942 | method_attr = rpsl_attr_init("method: PGP", type);
943 | if ( method_attr )
944 | {
945 | rpsl_object_add_attr(generated_obj, method_attr, 1, NULL);
946 | }
947 |
948 | attr_str = (char *)malloc( sizeof("owner: ") + strlen(keyowner) +1 );
949 | strcpy(attr_str, "owner: ");
950 | strcat(attr_str, keyowner);
951 | if (tracing)
952 | {
953 | printf("TRACING: UP_add_keycert_attrs: owner attr_str [%s]\n", attr_str);
954 | }
955 | owner_attr = rpsl_attr_init(attr_str, "key-cert");
956 | if ( owner_attr )
957 | {
958 | rpsl_object_add_attr(generated_obj, owner_attr, 2, NULL);
959 | }
960 | free(attr_str);
961 |
962 | attr_str = (char *)malloc( sizeof("fingerpr: ") + strlen(fingerprint) +1 );
963 | strcpy(attr_str, "fingerpr: ");
964 | strcat(attr_str, fingerprint);
965 | if (tracing)
966 | {
967 | printf("TRACING: UP_add_keycert_attrs: fingerprint attr_str [%s]\n", attr_str);
968 | }
969 | fingerpr_attr = rpsl_attr_init(attr_str, "key-cert");
970 | if ( fingerpr_attr )
971 | {
972 | rpsl_object_add_attr(generated_obj, fingerpr_attr, 3, NULL);
973 | }
974 | free(attr_str);
975 | }
976 | }
977 |
978 |
979 |
980 | /* Constructs a list of all attributes of an object, and returns it
981 | as a list of attribute_struct */
982 | /*GSList * up_get_attribute_list(Object * o, char * text){
983 |
984 | char * value = NULL;
985 | char * type = NULL;
986 | Attr *attr;
987 | GSList *list_of_attributes = NULL;
988 | attribute_struct * attribute;
989 |
990 | for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
991 | value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
992 | strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
993 | attr->len - strlen(attr->type->name()) -2 );
994 | value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
995 | if(tracing) {
996 | cout << "TRACING: up_get_attributes: adding " << g_strstrip(value) << endl;
997 | }
998 | attribute = (attribute_struct *)malloc(sizeof(attribute_struct));
999 | attribute->content = value;
1000 | type = strdup(attr->type->name());
1001 | g_strdown(type);
1002 | attribute->type = type;
1003 | list_of_attributes = g_slist_append(list_of_attributes, attribute);
1004 | }
1005 |
1006 |
1007 | return list_of_attributes;
1008 |
1009 | }
1010 | */
1011 |
1012 |
1013 | /* up_reconstruct_object: Reconstructs the object's text representation
1014 | using the parsed object */
1015 | void up_reconstruct_object(rpsl_object_t *external_syntax_obj, external_syntax_struct *result)
1016 | {
1017 | char * recons_obj = NULL;
1018 |
1019 | recons_obj = rpsl_object_get_text(external_syntax_obj,RPSL_STD_COLUMN);
1020 |
1021 | result->new_obj = recons_obj;
1022 | }
1023 |
1024 |
1025 |
1026 | /* UP_check_external_syntax: Checks the syntax of attributes which are not checked
1027 | by RAToolSet syntax checker. */
1028 | external_syntax_struct * UP_check_external_syntax(rpsl_object_t *external_syntax_obj)
1029 | {
1030 | external_syntax_struct *result;
1031 |
1032 | if (tracing)
1033 | {
1034 | printf("TRACING: UP_check_external_syntax running\n");
1035 | }
1036 |
1037 | result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
1038 |
1039 | /* initialize the struct */
1040 | result->result = 0;
1041 | result->error_str = strdup("");
1042 | result->warning_str = strdup("");
1043 |
1044 | up_check_source_attr(external_syntax_obj, result);
1045 |
1046 | up_check_country_attr(external_syntax_obj, result);
1047 |
1048 | up_check_nicsuffixes(external_syntax_obj, result);
1049 |
1050 | up_check_changed_attr(external_syntax_obj, result);
1051 |
1052 | /* this will be done by the new API parser */
1053 | /* up_check_auth_attr (arg, obj_text, attribute_list, result); */
1054 |
1055 | /* this will be done by the new API parser */
1056 | /* up_check_inetnum_attr(arg, obj_text, attribute_list, result); */
1057 |
1058 | up_check_status_attr(external_syntax_obj, result);
1059 |
1060 |
1061 | up_reconstruct_object(external_syntax_obj, result);
1062 |
1063 | if (tracing)
1064 | {
1065 | printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
1066 | printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
1067 | }
1068 |
1069 | return result;
1070 | }
1071 |
1072 |
1073 |
1074 | /* generates the "generated" attributes of a key-cert object. Returns the
1075 | new object string*/
1076 | char *UP_generate_kc_attrs(rpsl_object_t *generated_obj)
1077 | {
1078 | external_syntax_struct *result;
1079 | char *obj_str;
1080 |
1081 | if (tracing)
1082 | {
1083 | printf("TRACING: UP_generate_kc_attrs: is running\n");
1084 | }
1085 |
1086 | result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
1087 |
1088 | /* initialize the struct */
1089 | result->result = 0;
1090 | result->error_str = strdup("");
1091 | result->warning_str = strdup("");
1092 |
1093 | up_check_changed_attr(generated_obj, result);
1094 | up_add_keycert_attrs(generated_obj);
1095 |
1096 | up_reconstruct_object(generated_obj, result);
1097 |
1098 | if (tracing)
1099 | {
1100 | printf("TRACING: UP_generate_kc_attrs: the reconstructed object is=[%s]\n", result->new_obj);
1101 | printf("TRACING: UP_generate_kc_attrs: ... and the result code is=[%i]\n", result->result);
1102 | }
1103 |
1104 | obj_str = strdup(result->new_obj);
1105 | free(result);
1106 | return obj_str;
1107 | }
1108 |
1109 |
1110 |
1111 | /* char * up_assign_i6_status: Determines the status attribute of
1112 | an inet6num object. It takes the inet6num attribute of the
1113 | object as its only argument. If prefix length is less than
1114 | 4, then returns NULL */
1115 | char * up_assign_i6_status(const char * inet6num_attr)
1116 | {
1117 |
1118 | char ** split_str;
1119 | int prefix_length;
1120 | int result;
1121 |
1122 | /* we need the prefix length here.*/
1123 | split_str = g_strsplit(inet6num_attr, "/", 0);
1124 | if(split_str[1] != NULL){
1125 |
1126 | result = sscanf(split_str[1], "%i", &prefix_length);
1127 | if(result != 0 && result != EOF){
1128 |
1129 | if(prefix_length >= 0 && prefix_length <= 3){
1130 |
1131 | g_strfreev(split_str);
1132 | return NULL;
1133 |
1134 | }else if(prefix_length >= 4 && prefix_length <= 15){
1135 |
1136 | g_strfreev(split_str);
1137 | return strdup("TLA");
1138 |
1139 | }else if(prefix_length >= 16 && prefix_length <= 35){
1140 |
1141 | g_strfreev(split_str);
1142 | return strdup("SUBTLA");
1143 |
1144 | }else if(prefix_length >= 36 && prefix_length <= 48){
1145 |
1146 | g_strfreev(split_str);
1147 | return strdup("NLA");
1148 |
1149 | }else if(prefix_length >= 48 && prefix_length <= 64){
1150 |
1151 | g_strfreev(split_str);
1152 | return strdup("SLA");
1153 |
1154 | }else{
1155 |
1156 | /* "default" status */
1157 | g_strfreev(split_str);
1158 | return strdup("SLA");
1159 |
1160 | }
1161 |
1162 | }else{
1163 |
1164 | /* return "default" status */
1165 | g_strfreev(split_str);
1166 | return strdup("SLA");
1167 |
1168 | }
1169 | }else{
1170 |
1171 | /* return "default" status */
1172 | g_strfreev(split_str);
1173 | return strdup("SLA");
1174 |
1175 | }
1176 |
1177 | }
1178 |
1179 |
1180 |
1181 | /* GSList * up_add_inet6num_attrs
1182 | adds the generated attrs of inet6num objects */
1183 | /*GSList * up_add_inet6num_attrs(Object * obj, char * obj_text, GSList * attribute_list,
1184 | external_syntax_struct * result)*/
1185 | void up_add_inet6num_attrs(rpsl_object_t *generated_obj)
1186 | {
1187 |
1188 | int attribute_no;
1189 | char *status_value;
1190 | rpsl_attr_t * status_attr;
1191 | char *inet6num_attr_str, *status_attr_str;
1192 | const char *type;
1193 | GList *attributes_changed;
1194 |
1195 |
1196 |
1197 | /* if this is an inet6num object */
1198 | type = rpsl_object_get_class(generated_obj);
1199 | if( ! strcmp(type, "inet6num") )
1200 | {
1201 | inet6num_attr_str = get_search_key(generated_obj, "inet6num");
1202 | status_value = up_assign_i6_status(inet6num_attr_str);
1203 | status_attr_str = (char *)UT_malloc(strlen("status: ") + strlen(status_value) + 1);
1204 | strcpy(status_attr_str, "status: ");
1205 | strcat(status_attr_str, status_value);
1206 | status_attr = rpsl_attr_init(status_attr_str, type);
1207 | free(status_attr_str);
1208 | if ( status_attr )
1209 | {
1210 | /* we will put the status attribute before the first 'changed' attribute */
1211 | attribute_no = 1; /* a default position (the second attribute) in case we cannot find
1212 | a 'changed' attribute */
1213 | attributes_changed = rpsl_object_get_attr(generated_obj, "changed");
1214 | if ( attributes_changed != NULL )
1215 | {
1216 | attribute_no = ((rpsl_attr_t *)(attributes_changed->data))->num;
1217 | }
1218 | rpsl_object_add_attr(generated_obj, status_attr, attribute_no, NULL);
1219 | }
1220 | }
1221 | }
1222 |
1223 |
1224 |
1225 | /* generates the "generated" attribute (status) of an inet6num object. Returns the
1226 | new object as a char * */
1227 | char *UP_generate_i6_attrs(rpsl_object_t *generated_obj)
1228 | {
1229 |
1230 | external_syntax_struct *result;
1231 | char *obj_str;
1232 |
1233 | result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
1234 |
1235 | /* initialize the struct */
1236 | result->result = 0;
1237 | result->error_str = strdup("");
1238 | result->warning_str = strdup("");
1239 |
1240 |
1241 | up_check_changed_attr(generated_obj, result);
1242 | up_add_inet6num_attrs(generated_obj);
1243 |
1244 | up_reconstruct_object(generated_obj, result);
1245 |
1246 | if (tracing)
1247 | {
1248 | printf("TRACING: UP_generate_i6_attrs: the reconstructed object is=[%s]\n", result->new_obj);
1249 | printf("TRACING: UP_generate_i6_attrs: ... and the result code is=[%i]\n", result->result);
1250 | }
1251 |
1252 | obj_str = strdup(result->new_obj);
1253 | free(result->error_str);
1254 | free(result->warning_str);
1255 | free(result->new_obj);
1256 | free(result);
1257 | return obj_str;
1258 | }
1259 |