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 |