Source File up/UP_extrnl_syntax.c

    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 |