## modules/up/UP_extrnl_syntax.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. up_check_source_attr
2. up_check_country_attr
3. up_check_nicsuffixes
4. up_get_dates
5. up_changed_has_date
6. UP_get_current_date
7. up_add_dates
8. up_check_date_order
9. up_check_date
10. up_check_dates_syntax
11. up_check_changed_attr
12. up_check_an_inetnum_attr
13. up_check_a_status_attr
14. up_check_status_attr
15. up_add_keycert_attrs
16. up_reconstruct_object
17. UP_check_external_syntax
18. UP_generate_kc_attrs
19. up_assign_i6_status
20. up_add_inet6num_attrs
21. UP_generate_i6_attrs

       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)
         /* [<][>][^][v][top][bottom][index][help] */
      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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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()
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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){
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
    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)
         /* [<][>][^][v][top][bottom][index][help] */
    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)
         /* [<][>][^][v][top][bottom][index][help] */
    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)
         /* [<][>][^][v][top][bottom][index][help] */
    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)
         /* [<][>][^][v][top][bottom][index][help] */
    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)
         /* [<][>][^][v][top][bottom][index][help] */
    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

/* [<][>][^][v][top][bottom][index][help] */