1 | /*************************************** 2 | $Revision: 1.16 $ 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 int num_sources; 69 | extern char *countries[]; 70 | extern char *nicsuffixes[]; 71 | extern ca_updDbSource_t **upd_source_hdl; 72 | 73 | 74 | /* void up_check_source_attr 75 | checks for a valid source in the 'source' attributes */ 76 | void up_check_source_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result) 77 | { 78 | int valid,i ; 79 | char *source_name; 80 | char *temp; 81 | GList *source_list; 82 | 83 | if (tracing) 84 | { 85 | printf("TRACING: up_check_source_attr running\n"); 86 | } 87 | 88 | source_list = rpsl_object_get_attr(external_syntax_obj, "source"); 89 | 90 | valid = i = 0 ; 91 | if ( source_list ) 92 | { 93 | source_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(source_list->data) ); 94 | for ( i=0; i<num_sources; i++ ) 95 | { 96 | if ( ! strcasecmp( source_name, upd_source_hdl[i]->name) ) 97 | { 98 | valid = 1; 99 | break; 100 | } 101 | } 102 | 103 | /* while(sources[i]) 104 | { 105 | if(strcasecmp(sources[i++],source_name) == 0) 106 | { 107 | valid = 1; 108 | break; 109 | } 110 | } */ 111 | 112 | g_list_free(source_list); 113 | } 114 | 115 | if (!valid) 116 | { 117 | /* the source is not recognised */ 118 | 119 | if (tracing) 120 | { 121 | printf("TRACING: invalid source [%s]\n", source_name ); 122 | } 123 | 124 | if (result->error_str == NULL) 125 | { 126 | result->error_str = strdup("***Error: No such source"); 127 | } 128 | else 129 | { 130 | temp = (char *)malloc(strlen(result->error_str) 131 | + strlen("***Error: No such source") + 2); 132 | sprintf(temp, "%s\n%s", result->error_str, 133 | "***Error: No such source"); 134 | free(result->error_str); 135 | result->error_str = temp; 136 | } 137 | /* and here we have to change the result code of "result" here ... */ 138 | switch (result->result) 139 | { 140 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break; 141 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break; 142 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 143 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 144 | default: result->result = UP_EXTSYN_ERR; break; 145 | } 146 | } 147 | 148 | free(source_name); 149 | } 150 | 151 | 152 | /* void up_check_country_attr 153 | checks for a valid country in the 'country' attributes */ 154 | void up_check_country_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result) 155 | { 156 | int valid,i, matched ; 157 | char *country_name; 158 | char *temp; 159 | GList *country_list = NULL; 160 | GList *country_item = NULL; 161 | 162 | country_list = rpsl_object_get_attr(external_syntax_obj, "country"); 163 | rpsl_attr_split_multiple(&country_list); 164 | 165 | if ( country_list == NULL ) 166 | return; /* only check if there is one */ 167 | 168 | valid = 1 ; 169 | for ( country_item = country_list; country_item != NULL ; country_item = g_list_next(country_item) ) 170 | { 171 | country_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(country_item->data) ); 172 | matched = 0 ; 173 | i = 0 ; 174 | while(countries[i]) 175 | { 176 | if(strcasecmp(countries[i++],country_name) == 0) 177 | { 178 | matched = 1; 179 | break; 180 | } 181 | } 182 | 183 | if ( ! matched ) 184 | { 185 | valid = 0 ; 186 | break; 187 | } 188 | free(country_name); 189 | } 190 | g_list_free(country_list); 191 | 192 | if (!valid) 193 | { 194 | /* the country is not recognised */ 195 | if (result->error_str == NULL) 196 | { 197 | result->error_str = malloc(strlen("***Error: No such country []") + strlen(country_name) +2); 198 | sprintf(result->error_str, "***Error: No such country [%s]", country_name); 199 | } 200 | else 201 | { 202 | temp = (char *)malloc(strlen(result->error_str) 203 | + strlen("***Error: No such country []") + strlen(country_name) + 2); 204 | sprintf(temp, "%s\n***Error: No such country [%s]", result->error_str, 205 | country_name); 206 | free(result->error_str); 207 | result->error_str = temp; 208 | } 209 | 210 | free(country_name); 211 | 212 | /* and here we have to change the result code of "result" here ... */ 213 | switch (result->result) 214 | { 215 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break; 216 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break; 217 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 218 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 219 | default: ; 220 | } 221 | } 222 | } 223 | 224 | /* void up_check_nicsuffixes 225 | checks for a valid suffix at the end of a 'nic-hdl' attributes */ 226 | void up_check_nicsuffixes(rpsl_object_t *external_syntax_obj, external_syntax_struct * result) 227 | { 228 | int valid,i ; 229 | char *name; 230 | char *temp; 231 | GList *list; 232 | 233 | if (tracing) 234 | { 235 | printf("TRACING: up_check_nicsuffixes running\n"); 236 | } 237 | 238 | list = rpsl_object_get_attr(external_syntax_obj, "nic-hdl"); 239 | 240 | valid = i = 0 ; 241 | if ( list ) 242 | { 243 | name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(list->data) ); 244 | if ( !strchr(name,'-') || strncasecmp(name,"AUTO-",strlen("AUTO-")) == 0 ) 245 | { 246 | valid = 1; 247 | } 248 | else 249 | { 250 | while (nicsuffixes[i]) 251 | { 252 | if ( strcasecmp(nicsuffixes[i++],strchr(name,'-')+1) == 0 ) 253 | { 254 | valid = 1; 255 | break; 256 | } 257 | } 258 | if ( ! valid ) 259 | { 260 | i = 0; 261 | for ( i=0; i<num_sources; i++ ) 262 | { 263 | if ( ! strcasecmp( upd_source_hdl[i]->name, strchr(name,'-')+1) ) 264 | { 265 | valid = 1; 266 | break; 267 | } 268 | } 269 | 270 | /* while (sources[i]) 271 | { 272 | if (strcasecmp(sources[i++],strchr(name,'-')+1) == 0 ) 273 | { 274 | valid = 1; 275 | break; 276 | } 277 | } */ 278 | 279 | if ( ! valid ) 280 | { 281 | i = 0; 282 | while (countries[i]) 283 | { 284 | if ( strcasecmp(countries[i++],strchr(name,'-')+1) == 0 ) 285 | { 286 | valid = 1; 287 | break; 288 | } 289 | } 290 | } 291 | } 292 | } 293 | free(name); 294 | g_list_free(list); 295 | 296 | if (!valid) 297 | { 298 | /* the nicsuffix is not recognised */ 299 | if (result->error_str == NULL) 300 | { 301 | result->error_str = strdup("***Error: Invalid nic-hdl suffix"); 302 | } 303 | else 304 | { 305 | temp = (char *)malloc(strlen(result->error_str) 306 | + strlen("***Error: Invalid nic-hdl suffix") + 2); 307 | sprintf(temp, "%s\n%s", result->error_str, 308 | "***Error: Invalid nic-hdl suffix"); 309 | free(result->error_str); 310 | result->error_str = temp; 311 | } 312 | /* and here we have to change the result code of "result" here ... */ 313 | switch (result->result) 314 | { 315 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break; 316 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break; 317 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 318 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 319 | default: ; 320 | } 321 | } 322 | } 323 | } 324 | 325 | 326 | /* obtains a list of dates in the given 327 | list of attributes */ 328 | GList * up_get_dates(GList * attribute_list) 329 | { 330 | GList * item; 331 | char * str, *temp; 332 | GList * list = NULL; 333 | 334 | for ( item = attribute_list; item != NULL ; item = g_list_next(item) ) 335 | { 336 | /* is this a 'changed' attribute? */ 337 | if ( strcmp(rpsl_attr_get_name((rpsl_attr_t *)(item->data)), "changed") == 0 ) 338 | { 339 | str = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data)); 340 | 341 | 342 | /* now, we have the 'changed' attribute's content in "normalized" form 343 | We are sure it contains a date. So, it must be the second (and last) 344 | word in the attrib. */ 345 | assert(index(str,' ') != NULL); 346 | temp = (char *)malloc(strlen(str) - (index(str,' ') - str )); 347 | temp = strncpy(temp, index(str,' ') + 1, strlen(str) - (index(str,' ') - str ) - 1); 348 | temp[strlen(str) - (index(str,' ') - str ) - 1] = '\0'; /* NULL terminate it */ 349 | list = g_list_append (list, temp); 350 | } 351 | } 352 | 353 | return list; 354 | } 355 | 356 | 357 | 358 | 359 | /* Does the 'changed' attribute we got have a date already? 360 | Returns 1 if it does, 0 if not. */ 361 | int up_changed_has_date(char * value) 362 | { 363 | /* now, if there is still a white space, then we have a date in the string 364 | (it has to be something like "ripe-dbm@ripe.net 20001210") */ 365 | if (index(value, ' ') != NULL) 366 | { 367 | return 1; 368 | } 369 | else 370 | { 371 | return 0; 372 | } 373 | } 374 | 375 | 376 | 377 | 378 | /* supplies the current date in YYYYMMDD format (for example 20011010) */ 379 | char * UP_get_current_date() 380 | { 381 | /* We will use Glib's functions here */ 382 | 383 | char * date; 384 | struct tm * time_struct; 385 | 386 | time_t * time_loc; 387 | 388 | time_loc = (time_t *)malloc(sizeof(time_t)); 389 | time(time_loc); 390 | 391 | time_struct = localtime(time_loc); 392 | 393 | 394 | date = (char *)malloc(9); 395 | sprintf(date, "%04i%02i%02i", 396 | time_struct->tm_year + 1900, 397 | time_struct->tm_mon + 1, 398 | time_struct->tm_mday); 399 | return date; 400 | } 401 | 402 | 403 | 404 | 405 | /* int up_add_dates: adds dates to 'changed' attributes which 406 | are missing one. 407 | Returns 1 if no problems encountered 408 | Returns 0 if a problem encountered, and the error string is set */ 409 | int up_add_dates(rpsl_object_t *external_syntax_obj, GList *attribute_list, char ** warning_str, char ** error_str) 410 | { 411 | GList * item; 412 | char * current_date; 413 | int count_no_date = 0; 414 | char * temp; 415 | rpsl_attr_t *changed; 416 | char *value; 417 | int pos; 418 | 419 | *warning_str = NULL; 420 | *error_str = NULL; 421 | 422 | /* get the current date in YYYYMMDD format (for example 20011010) */ 423 | current_date = UP_get_current_date(); 424 | 425 | for ( item = attribute_list; item != NULL ; item = g_list_next(item) ) 426 | { 427 | /* is this a 'changed' attribute? */ 428 | if (strcmp(rpsl_attr_get_name((rpsl_attr_t *)(item->data)), "changed") == 0) 429 | { 430 | /* if this attribute does not have a date in it, add it. Also add 431 | a warning message about this */ 432 | value = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data)); 433 | if ( !up_changed_has_date(value) ) 434 | { 435 | count_no_date++; 436 | /* create a copy of this changed attribute and add the date to the value */ 437 | changed = rpsl_attr_copy((rpsl_attr_t *)(item->data)); 438 | temp = (char *)malloc(strlen(value) + strlen(current_date) + 2 ); 439 | sprintf(temp, "%s %s", value, current_date); 440 | rpsl_attr_replace_value(changed, temp); 441 | free(temp); 442 | /* delete the original attribute from the object */ 443 | pos = rpsl_attr_get_ofs(changed); 444 | rpsl_object_remove_attr(external_syntax_obj, pos, NULL); 445 | /* add the new changed attribute in the same position */ 446 | rpsl_object_add_attr(external_syntax_obj, changed, pos, NULL); 447 | /* add a warning message */ 448 | if ( *warning_str == NULL) 449 | { 450 | *warning_str = (char *)malloc(strlen("WARNING date '' added to 'changed' attribute") + 9 ); 451 | sprintf(*warning_str, "WARNING date '%s' added to 'changed' attribute", current_date); 452 | } 453 | else 454 | { 455 | temp = (char *)malloc(strlen(*warning_str) + 1 456 | + strlen("WARNING date '' added to 'changed' attribute") + 9 ); 457 | sprintf(temp, "%s\nWARNING date '%s' added to 'changed' attribute", 458 | *warning_str, current_date); 459 | free(*warning_str); 460 | *warning_str = temp; 461 | } 462 | } 463 | free(value); 464 | } 465 | } 466 | 467 | if (count_no_date > 1) 468 | { 469 | *error_str = strdup("***Error: More than one 'changed' attributes without dates"); 470 | return 0; 471 | } 472 | else 473 | { 474 | return 1; 475 | } 476 | } 477 | 478 | 479 | 480 | 481 | /* Checks the order of dates in the given list. 482 | If they are in order, returns 1, 483 | if not, returns 0 */ 484 | int up_check_date_order(GList * list) 485 | { 486 | GList * item; 487 | char * previous; 488 | char *value; 489 | 490 | /* if list is empty, return 1 immediately */ 491 | if (list == NULL) 492 | { 493 | return 1; 494 | } 495 | 496 | /* initialize the 'previous' date */ 497 | previous = strdup("00000000"); 498 | 499 | for ( item = list; item != NULL ; item = g_list_next(item)) 500 | { 501 | assert((item->data) != NULL); 502 | /* if the new date is smaller than the previous */ 503 | value = (char *)(item->data); 504 | if ( strcmp(value, previous) < 0 ) 505 | { 506 | free(previous); 507 | return 0; 508 | } 509 | free(previous); 510 | previous = strdup(value); 511 | } 512 | 513 | free(previous); 514 | /* Reached the end, without finding out-of-order date. Return 1, then */ 515 | return 1; 516 | } 517 | 518 | 519 | 520 | 521 | 522 | /* up_check_date: checks the syntax of the date, given as the only 523 | argument (char *). The argument is checked if it is in YYYYMMDD 524 | format, and returns an error code accordingly */ 525 | int up_check_date(const char * arg) 526 | { 527 | int date_int; /* integer representation of the date (arg) */ 528 | char * current_date; 529 | int year, month, day; /* integers for the components of the date */ 530 | 531 | errno = 0; 532 | date_int = atoi(arg); 533 | 534 | if (errno != 0) 535 | { /* there was an error in the conversion, syntax error */ 536 | return UP_DATE_SYNERR; 537 | } 538 | 539 | /* wrong format */ 540 | if (date_int <= 10000000 ) 541 | { /* the date is not in YYYYMMDD format */ 542 | return UP_DATE_WRONGFORMAT; 543 | } 544 | 545 | /* check if it is too small */ 546 | if (date_int <= 19840000 ) 547 | { /* the date is older than the DB itself! */ 548 | return UP_DATE_TOOSMALL; 549 | } 550 | 551 | /* check if it is too big */ 552 | if (date_int >= 100000000 ) 553 | {/* too big: syntax error */ 554 | return UP_DATE_SYNERR; 555 | } 556 | 557 | /* and now check year, month and day components */ 558 | year = date_int / 10000; 559 | month = (date_int - (year * 10000) ) / 100; 560 | day = (date_int % 100); 561 | 562 | /* check year */ 563 | if (year < 1984 ) 564 | { 565 | return UP_DATE_TOOSMALL; 566 | } 567 | 568 | /* check month */ 569 | if (month < 1 || month > 12) 570 | { 571 | return UP_DATE_INVMONTH; 572 | } 573 | 574 | /* check day */ 575 | if (day < 1 || day > 31) 576 | { 577 | return UP_DATE_INVDAY; 578 | } 579 | 580 | switch ( month ) 581 | { 582 | case 1: case 3: case 5: case 7: 583 | case 8: case 10: case 12: 584 | if (day > 31) 585 | { 586 | return UP_DATE_INVDAY; 587 | }; 588 | break; 589 | case 2: 590 | if ( (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) && (day > 29 )) 591 | { /* leap year */ 592 | return UP_DATE_INVDAY; 593 | } 594 | else if( (!(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) && (day > 28) ) 595 | { /* non-leap year */ 596 | return UP_DATE_INVDAY; 597 | }; 598 | break; 599 | case 4: case 6: case 9: case 11: 600 | if (day > 30) 601 | { 602 | return UP_DATE_INVDAY; 603 | }; 604 | break; 605 | default: return UP_DATE_INVMONTH; 606 | } 607 | 608 | /* check if the arg is in the future or not */ 609 | current_date = UP_get_current_date(); 610 | if (strcmp(current_date, arg) < 0 ) 611 | { /* arg is in the future */ 612 | free(current_date); 613 | return UP_DATE_FUTURE; 614 | } 615 | free(current_date); 616 | 617 | return UP_DATE_OK; 618 | } 619 | 620 | 621 | 622 | /* Checks the syntax of the dates in the list */ 623 | date_syntax_struct * up_check_dates_syntax(GList * list) 624 | { 625 | GList * item; 626 | date_syntax_struct * result; 627 | int res; 628 | 629 | /* initialize the result struct */ 630 | result = (date_syntax_struct *)malloc(sizeof(date_syntax_struct)); 631 | result->result = UP_DATE_OK; 632 | result->error_str = NULL; 633 | 634 | /* if list is empty, return immediately */ 635 | if (list == NULL) 636 | { 637 | return result; 638 | } 639 | 640 | /* loop through the members of the list, check each of them */ 641 | for ( item = list; item != NULL ; item = g_list_next(item)) 642 | { 643 | assert((item->data) != NULL); 644 | 645 | /* check the date */ 646 | res = up_check_date((char *)(item->data)); 647 | switch (res) 648 | { 649 | case UP_DATE_OK: break; 650 | 651 | case UP_DATE_FUTURE: 652 | case UP_DATE_TOOSMALL: 653 | case UP_DATE_INVDAY: 654 | case UP_DATE_INVMONTH: 655 | case UP_DATE_WRONGFORMAT: 656 | 657 | if (result->error_str == NULL) 658 | { 659 | result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[res]) 660 | + strlen(": ") + strlen((char *)(item->data)) + 1); 661 | sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[res], 662 | (char *)(item->data)); 663 | } 664 | else 665 | { 666 | result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1 667 | + strlen("***Error: ") + strlen(up_date_errmsgs[res]) 668 | + strlen(": ") + strlen((char *)(item->data)) + 1); 669 | sprintf(result->error_str, "%s\n***Error: %s: %s", 670 | result->error_str, up_date_errmsgs[res], (char *)(item->data)); 671 | } 672 | result->result = UP_DATE_NOK; /* Not OK */ 673 | 674 | break; 675 | 676 | 677 | case UP_DATE_SYNERR: /* syntax error in the date */ 678 | 679 | default: 680 | if (result->error_str == NULL) 681 | { 682 | result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR]) 683 | + strlen(": ") + strlen((char *)(item->data)) + 1); 684 | sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[UP_DATE_SYNERR], 685 | (char *)(item->data)); 686 | } 687 | else 688 | { 689 | result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1 690 | + strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR]) 691 | + strlen(": ") + strlen((char *)(item->data)) + 1); 692 | sprintf(result->error_str, "%s\n***Error: %s: %s", 693 | result->error_str, up_date_errmsgs[UP_DATE_SYNERR], (char *)(item->data)); 694 | } 695 | result->result = UP_DATE_NOK; /* Not OK */ 696 | break; 697 | } 698 | } 699 | 700 | return result; 701 | } 702 | 703 | 704 | 705 | /* void up_check_changed_attr 706 | checks the order of dates in the 'changed' attributes */ 707 | void up_check_changed_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result) 708 | { 709 | GList * date_list; 710 | int res; 711 | char ** warning, **error; 712 | char * temp; 713 | date_syntax_struct * date_check_res; 714 | GList *changed_list; 715 | 716 | warning = (char **)malloc(sizeof(char **)); 717 | error = (char **)malloc(sizeof(char **)); 718 | changed_list = rpsl_object_get_attr(external_syntax_obj, "changed"); 719 | 720 | /* Now, add dates to the "changed" attributes */ 721 | res = up_add_dates(external_syntax_obj, changed_list, warning, error); 722 | if (!res) 723 | { 724 | /* so, add the error string to result's error string */ 725 | if (result->error_str == NULL) 726 | { 727 | result->error_str = strdup(*error); 728 | } 729 | else 730 | { 731 | temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2); 732 | sprintf(temp, "%s\n%s", result->error_str, *error); 733 | free(result->error_str); 734 | result->error_str = temp; 735 | } 736 | } 737 | 738 | /* and get the list of dates, we must check their order */ 739 | /* we may have added a date to one of the changed attrs so get the list again */ 740 | rpsl_attr_delete_list(changed_list); 741 | changed_list = rpsl_object_get_attr(external_syntax_obj, "changed"); 742 | date_list = up_get_dates(changed_list); 743 | /* and check the order */ 744 | res = up_check_date_order(date_list); 745 | if (!res) 746 | { 747 | /* so, add the error string to result's error string */ 748 | if (result->error_str == NULL) 749 | { 750 | result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order"); 751 | } 752 | else 753 | { 754 | temp = (char *)malloc(strlen(result->error_str) 755 | + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2); 756 | sprintf(temp, "%s\n%s", result->error_str, 757 | "***Error: The dates in the 'changed' attributes should be in order"); 758 | free(result->error_str); 759 | result->error_str = temp; 760 | } 761 | /* and here we have to change the result code of "result" here ... */ 762 | switch (result->result) 763 | { 764 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break; 765 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break; 766 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 767 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 768 | default: ; 769 | } 770 | } 771 | 772 | /* check the syntax of dates */ 773 | date_check_res = up_check_dates_syntax(date_list); 774 | if (date_check_res->result != UP_DATE_OK) 775 | { 776 | /* so, add the error string to result's error string */ 777 | if (result->error_str == NULL) 778 | { 779 | result->error_str = strdup(date_check_res->error_str); 780 | } 781 | else 782 | { 783 | temp = (char *)malloc(strlen(result->error_str) 784 | + strlen(date_check_res->error_str) + 2); 785 | sprintf(temp, "%s\n%s", result->error_str, 786 | date_check_res->error_str); 787 | free(result->error_str); 788 | result->error_str = temp; 789 | } 790 | /* and here we have to change the result code of "result" here ... */ 791 | switch (result->result) 792 | { 793 | case UP_EXTSYN_OK: result->result = UP_EXTSYN_ERR; break; 794 | case UP_EXTSYN_ERR: result->result = UP_EXTSYN_ERR; break; 795 | case UP_EXTSYN_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 796 | case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break; 797 | default: ; 798 | } 799 | } 800 | } 801 | 802 | 803 | /* performs a simple check on a inetnum attribute. Assumes that 804 | the RPSL parser has already checked it. Tries to see if the attr 805 | is a range or not */ 806 | int up_check_an_inetnum_attr(const char * arg){ 807 | 808 | 809 | char * str; 810 | char * pos; 811 | 812 | str = strdup(arg); 813 | 814 | while((pos = index(str, '\n')) != NULL){ 815 | *pos = ' '; 816 | } 817 | 818 | /* strip off the comment */ 819 | if((pos = index(str, '#')) != NULL){ 820 | *pos = '\0'; 821 | } 822 | 823 | 824 | /* Most of the syntax check is done by RPSL parser. We only need to check 825 | that the argument is a _range_ of IPv4 addresses. So it suffices to 826 | check the existence of '-' in the arg */ 827 | if(index(str, '-') != NULL){ 828 | 829 | free(str); 830 | return 1; 831 | 832 | }else{ 833 | 834 | free(str); 835 | return 0; 836 | 837 | } 838 | } 839 | 840 | 841 | /* void up_add_keycert_attrs 842 | adds the generated attrs of key-cert objects */ 843 | void up_add_keycert_attrs(rpsl_object_t *generated_obj) 844 | { 845 | const char *type; 846 | char *attr_str; 847 | rpsl_attr_t *method_attr; 848 | rpsl_attr_t *owner_attr; 849 | rpsl_attr_t *fingerpr_attr; 850 | 851 | if (tracing) 852 | { 853 | printf("TRACING: UP_add_keycert_attrs: is running\n"); 854 | } 855 | 856 | /* if this is a key-cert object */ 857 | type = rpsl_object_get_class(generated_obj); 858 | if ( strcmp(type, "key-cert") == 0 ) 859 | { 860 | method_attr = rpsl_attr_init("method: PGP", type); 861 | if ( method_attr ) 862 | { 863 | rpsl_object_add_attr(generated_obj, method_attr, 1, NULL); 864 | } 865 | 866 | attr_str = (char *)malloc( sizeof("owner: ") + strlen(keyowner) +1 ); 867 | strcpy(attr_str, "owner: "); 868 | strcat(attr_str, keyowner); 869 | if (tracing) 870 | { 871 | printf("TRACING: UP_add_keycert_attrs: owner attr_str [%s]\n", attr_str); 872 | } 873 | owner_attr = rpsl_attr_init(attr_str, "key-cert"); 874 | if ( owner_attr ) 875 | { 876 | rpsl_object_add_attr(generated_obj, owner_attr, 2, NULL); 877 | } 878 | free(attr_str); 879 | 880 | attr_str = (char *)malloc( sizeof("fingerpr: ") + strlen(fingerprint) +1 ); 881 | strcpy(attr_str, "fingerpr: "); 882 | strcat(attr_str, fingerprint); 883 | if (tracing) 884 | { 885 | printf("TRACING: UP_add_keycert_attrs: fingerprint attr_str [%s]\n", attr_str); 886 | } 887 | fingerpr_attr = rpsl_attr_init(attr_str, "key-cert"); 888 | if ( fingerpr_attr ) 889 | { 890 | rpsl_object_add_attr(generated_obj, fingerpr_attr, 3, NULL); 891 | } 892 | free(attr_str); 893 | } 894 | } 895 | 896 | 897 | /* up_reconstruct_object: Reconstructs the object's text representation 898 | using the parsed object */ 899 | void up_reconstruct_object(rpsl_object_t *external_syntax_obj, external_syntax_struct *result) 900 | { 901 | char * recons_obj = NULL; 902 | 903 | recons_obj = rpsl_object_get_text(external_syntax_obj,RPSL_STD_COLUMN); 904 | 905 | result->new_obj = recons_obj; 906 | } 907 | 908 | 909 | 910 | /* UP_check_external_syntax: Checks the syntax of attributes which are not checked 911 | by the api parser module. */ 912 | external_syntax_struct * UP_check_external_syntax(rpsl_object_t *external_syntax_obj) 913 | { 914 | external_syntax_struct *result; 915 | 916 | if (tracing) 917 | { 918 | printf("TRACING: UP_check_external_syntax running\n"); 919 | } 920 | 921 | result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct)); 922 | 923 | /* initialize the struct */ 924 | result->result = 0; 925 | result->error_str = strdup(""); 926 | result->warning_str = strdup(""); 927 | 928 | up_check_source_attr(external_syntax_obj, result); 929 | 930 | up_check_country_attr(external_syntax_obj, result); 931 | 932 | up_check_nicsuffixes(external_syntax_obj, result); 933 | 934 | up_check_changed_attr(external_syntax_obj, result); 935 | 936 | up_reconstruct_object(external_syntax_obj, result); 937 | 938 | if (tracing) 939 | { 940 | printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj); 941 | printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result); 942 | } 943 | 944 | return result; 945 | } 946 | 947 | 948 | 949 | /* generates the "generated" attributes of a key-cert object. Returns the 950 | new object string*/ 951 | char *UP_generate_kc_attrs(rpsl_object_t *generated_obj) 952 | { 953 | external_syntax_struct *result; 954 | char *obj_str; 955 | 956 | if (tracing) 957 | { 958 | printf("TRACING: UP_generate_kc_attrs: is running\n"); 959 | } 960 | 961 | result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct)); 962 | 963 | /* initialize the struct */ 964 | result->result = 0; 965 | result->error_str = strdup(""); 966 | result->warning_str = strdup(""); 967 | 968 | up_check_changed_attr(generated_obj, result); 969 | up_add_keycert_attrs(generated_obj); 970 | 971 | up_reconstruct_object(generated_obj, result); 972 | 973 | if (tracing) 974 | { 975 | printf("TRACING: UP_generate_kc_attrs: the reconstructed object is=[%s]\n", result->new_obj); 976 | printf("TRACING: UP_generate_kc_attrs: ... and the result code is=[%i]\n", result->result); 977 | } 978 | 979 | obj_str = strdup(result->new_obj); 980 | free(result); 981 | return obj_str; 982 | } 983 | 984 | 985 | 986 | /* char * up_assign_i6_status: Determines the status attribute of 987 | an inet6num object. It takes the inet6num attribute of the 988 | object as its only argument. If prefix length is less than 989 | 4, then returns NULL */ 990 | char * up_assign_i6_status(const char * inet6num_attr) 991 | { 992 | 993 | char ** split_str; 994 | int prefix_length; 995 | int result; 996 | 997 | /* we need the prefix length here.*/ 998 | split_str = g_strsplit(inet6num_attr, "/", 0); 999 | if(split_str[1] != NULL){ 1000 | 1001 | result = sscanf(split_str[1], "%i", &prefix_length); 1002 | if(result != 0 && result != EOF){ 1003 | 1004 | if(prefix_length >= 0 && prefix_length <= 3){ 1005 | 1006 | g_strfreev(split_str); 1007 | return NULL; 1008 | 1009 | }else if(prefix_length >= 4 && prefix_length <= 15){ 1010 | 1011 | g_strfreev(split_str); 1012 | return strdup("TLA"); 1013 | 1014 | }else if(prefix_length >= 16 && prefix_length <= 35){ 1015 | 1016 | g_strfreev(split_str); 1017 | return strdup("SUBTLA"); 1018 | 1019 | }else if(prefix_length >= 36 && prefix_length <= 48){ 1020 | 1021 | g_strfreev(split_str); 1022 | return strdup("NLA"); 1023 | 1024 | }else if(prefix_length >= 48 && prefix_length <= 64){ 1025 | 1026 | g_strfreev(split_str); 1027 | return strdup("SLA"); 1028 | 1029 | }else{ 1030 | 1031 | /* "default" status */ 1032 | g_strfreev(split_str); 1033 | return strdup("SLA"); 1034 | 1035 | } 1036 | 1037 | }else{ 1038 | 1039 | /* return "default" status */ 1040 | g_strfreev(split_str); 1041 | return strdup("SLA"); 1042 | 1043 | } 1044 | }else{ 1045 | 1046 | /* return "default" status */ 1047 | g_strfreev(split_str); 1048 | return strdup("SLA"); 1049 | 1050 | } 1051 | 1052 | } 1053 | 1054 | 1055 | 1056 | /* GSList * up_add_inet6num_attrs 1057 | adds the generated attrs of inet6num objects */ 1058 | /*GSList * up_add_inet6num_attrs(Object * obj, char * obj_text, GSList * attribute_list, 1059 | external_syntax_struct * result)*/ 1060 | void up_add_inet6num_attrs(rpsl_object_t *generated_obj) 1061 | { 1062 | 1063 | int attribute_no; 1064 | char *status_value; 1065 | rpsl_attr_t * status_attr; 1066 | char *inet6num_attr_str, *status_attr_str; 1067 | const char *type; 1068 | GList *attributes_changed; 1069 | 1070 | 1071 | 1072 | /* if this is an inet6num object */ 1073 | type = rpsl_object_get_class(generated_obj); 1074 | if( ! strcmp(type, "inet6num") ) 1075 | { 1076 | inet6num_attr_str = get_search_key(generated_obj, "inet6num"); 1077 | status_value = up_assign_i6_status(inet6num_attr_str); 1078 | status_attr_str = (char *)UT_malloc(strlen("status: ") + strlen(status_value) + 1); 1079 | strcpy(status_attr_str, "status: "); 1080 | strcat(status_attr_str, status_value); 1081 | status_attr = rpsl_attr_init(status_attr_str, type); 1082 | free(status_attr_str); 1083 | if ( status_attr ) 1084 | { 1085 | /* we will put the status attribute before the first 'changed' attribute */ 1086 | attribute_no = 1; /* a default position (the second attribute) in case we cannot find 1087 | a 'changed' attribute */ 1088 | attributes_changed = rpsl_object_get_attr(generated_obj, "changed"); 1089 | if ( attributes_changed != NULL ) 1090 | { 1091 | attribute_no = ((rpsl_attr_t *)(attributes_changed->data))->num; 1092 | } 1093 | rpsl_object_add_attr(generated_obj, status_attr, attribute_no, NULL); 1094 | } 1095 | } 1096 | } 1097 |