## modules/up/UP_extrnl_syntax.c

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

## DEFINITIONS

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_add_keycert_attrs
14. up_reconstruct_object
15. UP_check_external_syntax
16. UP_generate_kc_attrs
17. up_assign_i6_status
18. up_add_inet6num_attrs

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

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