Source File up/UP_extrnl_syntax.c

    1    | /***************************************
    2    |   $Revision: 1.12 $
    3    |
    4    |   UP external syntax checks
    5    |
    6    |   Status: REVIEWED, NOT TESTED
    7    |
    8    |   Author(s):       Engin Gunduz
    9    |
    10   |   ******************/ /******************
    11   |   Modification History:
    12   |         engin (15/12/2000) Created.
    13   |         denis (31/08/2001) Modified for new API
    14   |   ******************/ /******************
    15   |   Copyright (c) 2001,2002                         RIPE NCC
    16   |
    17   |   All Rights Reserved
    18   |
    19   |   Permission to use, copy, modify, and distribute this software and its
    20   |   documentation for any purpose and without fee is hereby granted,
    21   |   provided that the above copyright notice appear in all copies and that
    22   |   both that copyright notice and this permission notice appear in
    23   |   supporting documentation, and that the name of the author not be
    24   |   used in advertising or publicity pertaining to distribution of the
    25   |   software without specific, written prior permission.
    26   |
    27   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    28   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    29   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    30   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    31   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    32   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    33   |  ***************************************/
    34   |
    35   |
    36   | /*#include "rpsl/object.hh"*/
    37   | #include "UP_extrnl_syntax.h"
    38   | #include "dbupdate.h"
    39   |
    40   | #define UP_DATE_OK      0
    41   | #define UP_DATE_SYNERR  1
    42   | #define UP_DATE_FUTURE  2
    43   | #define UP_DATE_TOOSMALL        3
    44   | #define UP_DATE_INVMONTH        4
    45   | #define UP_DATE_INVDAY  5
    46   | #define UP_DATE_WRONGFORMAT 6
    47   | #define UP_DATE_NOK    7
    48   |
    49   | char * up_date_errmsgs[]=
    50   | {
    51   |
    52   |   "OK",
    53   |   "Syntax error in date of 'changed' attribute",
    54   |   "Date in the future in 'changed' attribute",
    55   |   "Date is older than the database itself in 'changed' attribute",
    56   |   "Invalid month in date in 'changed' attribute",
    57   |   "Invalid day in date in 'changed' attribute",
    58   |   "Date must be in YYYYMMDD format in 'change' attribute",
    59   |   "Syntax error in date of 'changed' attribute"
    60   | };
    61   |
    62   |
    63   | extern int tracing;
    64   |
    65   | extern char * fingerprint;
    66   | extern char * keyowner;
    67   |
    68   | extern char * allocmnt;
    69   |
    70   | extern char    *sources[];
    71   | extern char    *countries[];
    72   | extern char    *nicsuffixes[];
    73   |
    74   |
    75   | /* void up_check_source_attr
    76   |    checks for a valid source in the 'source' attributes */
    77   | void up_check_source_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
    78   | {
    79   |   int valid,i ;
    80   |   char *source_name;
    81   |   char *temp;
    82   |   GList *source_list;
    83   |
    84   |   source_list = rpsl_object_get_attr(external_syntax_obj, "source");
    85   |
    86   |   valid = i = 0 ;
    87   |   if ( source_list )
    88   |   {
    89   |     source_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(source_list->data) );
    90   |     while(sources[i])
    91   |     {
    92   |       if(strcasecmp(sources[i++],source_name) == 0)
    93   |       {
    94   |         valid = 1;
    95   |         break;
    96   |       }
    97   |     }
    98   |     free(source_name);
    99   |     g_list_free(source_list);
    100  |   }
    101  |
    102  |   if (!valid)
    103  |   {
    104  |     /* the source is not recognised */
    105  |     if (result->error_str == NULL)
    106  | 	{
    107  |       result->error_str = strdup("***Error: No such source");
    108  |     }
    109  | 	else
    110  | 	{
    111  |       temp = (char *)malloc(strlen(result->error_str)
    112  |               + strlen("***Error: No such source") + 2);
    113  |       sprintf(temp, "%s\n%s", result->error_str,
    114  |               "***Error: No such source");
    115  |       free(result->error_str);
    116  |       result->error_str = temp;
    117  |     }
    118  |     /* and here we have to change the result code of "result" here ... */
    119  |     switch (result->result)
    120  | 	{
    121  |       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
    122  |       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
    123  |       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
    124  |       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
    125  |       default: ;
    126  |     }
    127  |   }
    128  | }
    129  |
    130  |
    131  | /* void up_check_country_attr
    132  |    checks for a valid country in the 'country' attributes */
    133  | void up_check_country_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
    134  | {
    135  |   int valid,i, matched ;
    136  |   char *country_name;
    137  |   char *temp;
    138  |   GList *country_list = NULL;
    139  |   GList *country_item = NULL;
    140  |
    141  |   country_list = rpsl_object_get_attr(external_syntax_obj, "country");
    142  |
    143  |   if ( country_list == NULL )
    144  |     return;		/* only check if there is one */
    145  |
    146  |   valid = 1 ;
    147  |   for ( country_item = country_list; country_item != NULL ; country_item = g_list_next(country_item) )
    148  |   {
    149  |     country_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(country_item->data) );
    150  |     matched = 0 ;
    151  |     i = 0 ;
    152  |     while(countries[i])
    153  |     {
    154  |       if(strcasecmp(countries[i++],country_name) == 0)
    155  |       {
    156  |         matched = 1;
    157  |         break;
    158  |       }
    159  |     }
    160  |
    161  |     if ( ! matched )
    162  |     {
    163  |       valid = 0 ;
    164  |       break;
    165  |     }
    166  |     free(country_name);
    167  |   }
    168  |   g_list_free(country_list);
    169  |
    170  |   if (!valid)
    171  |   {
    172  |     /* the country is not recognised */
    173  |     if (result->error_str == NULL)
    174  | 	{
    175  |       result->error_str = malloc(strlen("***Error: No such country []") + strlen(country_name) +2);
    176  |       sprintf(result->error_str, "***Error: No such country [%s]", country_name);
    177  |     }
    178  | 	else
    179  | 	{
    180  |       temp = (char *)malloc(strlen(result->error_str)
    181  |               + strlen("***Error: No such country []") + strlen(country_name) + 2);
    182  |       sprintf(temp, "%s\n***Error: No such country [%s]", result->error_str,
    183  |               country_name);
    184  |       free(result->error_str);
    185  |       result->error_str = temp;
    186  |     }
    187  |
    188  |     free(country_name);
    189  |
    190  |     /* and here we have to change the result code of "result" here ... */
    191  |     switch (result->result)
    192  | 	{
    193  |       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
    194  |       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
    195  |       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
    196  |       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
    197  |       default: ;
    198  |     }
    199  |   }
    200  | }
    201  |
    202  | /* void up_check_nicsuffixes
    203  |    checks for a valid suffix at the end of a 'nic-hdl' attributes */
    204  | void up_check_nicsuffixes(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
    205  | {
    206  |   int valid,i ;
    207  |   char *name;
    208  |   char *temp;
    209  |   GList *list;
    210  |
    211  |   list = rpsl_object_get_attr(external_syntax_obj, "nic-hdl");
    212  |
    213  |   valid = i = 0 ;
    214  |   if ( list )
    215  |   {
    216  |     name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(list->data) );
    217  |     if ( !strchr(name,'-') || strncasecmp(name,"AUTO-",strlen("AUTO-")) == 0 )
    218  |     {
    219  |       valid = 1;
    220  |     }
    221  |     else
    222  |     {
    223  |       while (nicsuffixes[i])
    224  |       {
    225  |         if ( strcasecmp(nicsuffixes[i++],strchr(name,'-')+1) == 0 )
    226  |         {
    227  |           valid = 1;
    228  |           break;
    229  |         }
    230  |       }
    231  |       if ( ! valid )
    232  |       {
    233  |         i = 0;
    234  |         while (sources[i])
    235  |         {
    236  |           if (strcasecmp(sources[i++],strchr(name,'-')+1) == 0 )
    237  |           {
    238  |             valid = 1;
    239  |             break;
    240  |           }
    241  |         }
    242  |         if ( ! valid )
    243  |         {
    244  |           i = 0;
    245  |           while (countries[i])
    246  |           {
    247  |             if ( strcasecmp(countries[i++],strchr(name,'-')+1) == 0 )
    248  |             {
    249  |               valid = 1;
    250  |               break;
    251  |             }
    252  |           }
    253  |         }
    254  |       }
    255  |     }
    256  |     free(name);
    257  |     g_list_free(list);
    258  |
    259  |     if (!valid)
    260  |     {
    261  |       /* the nicsuffix is not recognised */
    262  |       if (result->error_str == NULL)
    263  | 	  {
    264  |         result->error_str = strdup("***Error: Invalid nic-hdl suffix");
    265  |       }
    266  | 	  else
    267  | 	  {
    268  |         temp = (char *)malloc(strlen(result->error_str)
    269  |                 + strlen("***Error: Invalid nic-hdl suffix") + 2);
    270  |         sprintf(temp, "%s\n%s", result->error_str,
    271  |                 "***Error: Invalid nic-hdl suffix");
    272  |         free(result->error_str);
    273  |         result->error_str = temp;
    274  |       }
    275  |       /* and here we have to change the result code of "result" here ... */
    276  |       switch (result->result)
    277  | 	  {
    278  |         case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
    279  |         case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
    280  |         case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
    281  |         case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
    282  |         default: ;
    283  |       }
    284  |     }
    285  |   }
    286  | }
    287  |
    288  |
    289  | /* obtains a list of dates in the given
    290  |    list of attributes  */
    291  | GList * up_get_dates(GList * attribute_list)
    292  | {
    293  |   GList * item;
    294  |   char * str, *temp;
    295  |   GList * list = NULL;
    296  |
    297  |   for ( item = attribute_list; item != NULL ; item = g_list_next(item) )
    298  |   {
    299  |     /* is this a 'changed' attribute? */
    300  |     if ( strcmp(rpsl_attr_get_name((rpsl_attr_t *)(item->data)), "changed") == 0 )
    301  | 	{
    302  |       str = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
    303  |
    304  |
    305  |       /* now, we have the 'changed' attribute's content in "normalized" form
    306  |          We are sure it contains a date. So, it must be the second (and last)
    307  |          word in the attrib. */
    308  |       assert(index(str,' ') != NULL);
    309  |       temp = (char *)malloc(strlen(str) - (index(str,' ') - str ));
    310  |       temp = strncpy(temp, index(str,' ') + 1, strlen(str) - (index(str,' ') - str ) - 1);
    311  |       temp[strlen(str) - (index(str,' ') - str ) - 1] = '\0'; /* NULL terminate it */
    312  |       list = g_list_append (list, temp);
    313  |     }
    314  |   }
    315  |
    316  |   return list;
    317  | }
    318  |
    319  |
    320  |
    321  |
    322  | /* Does the 'changed' attribute we got have a date already?
    323  |    Returns 1 if it does, 0 if not. */
    324  | int up_changed_has_date(char * value)
    325  | {
    326  |   /* now, if there is still a white space, then we have a date in the string
    327  |      (it has to be something like "ripe-dbm@ripe.net 20001210") */
    328  |   if (index(value, ' ') != NULL)
    329  |   {
    330  |     return 1;
    331  |   }
    332  |   else
    333  |   {
    334  |     return 0;
    335  |   }
    336  | }
    337  |
    338  |
    339  |
    340  |
    341  | /* supplies the current date in YYYYMMDD format (for example 20011010) */
    342  | char * UP_get_current_date()
    343  | {
    344  |   /* We will use Glib's functions here */
    345  |
    346  |   char * date;
    347  |   struct tm * time_struct;
    348  |
    349  |   time_t * time_loc;
    350  |
    351  |   time_loc = (time_t *)malloc(sizeof(time_t));
    352  |   time(time_loc);
    353  |
    354  |   time_struct = localtime(time_loc);
    355  |
    356  |
    357  |   date = (char *)malloc(9);
    358  |   sprintf(date, "%04i%02i%02i",
    359  |           time_struct->tm_year + 1900,
    360  |           time_struct->tm_mon + 1,
    361  |           time_struct->tm_mday);
    362  |   return date;
    363  | }
    364  |
    365  |
    366  |
    367  |
    368  | /* int up_add_dates: adds dates to 'changed' attributes which
    369  |      are missing one.
    370  |      Returns 1 if no problems encountered
    371  |      Returns 0 if a problem encountered, and the error string is set */
    372  | int up_add_dates(rpsl_object_t *external_syntax_obj, GList *attribute_list, char ** warning_str, char ** error_str)
    373  | {
    374  |   GList * item;
    375  |   char * current_date;
    376  |   int count_no_date = 0;
    377  |   char * temp;
    378  |   rpsl_attr_t *changed;
    379  |   char *value;
    380  |   int pos;
    381  |
    382  |   *warning_str = NULL;
    383  |   *error_str   = NULL;
    384  |
    385  |   /* get the current date in YYYYMMDD format (for example 20011010) */
    386  |   current_date = UP_get_current_date();
    387  |
    388  |   for ( item = attribute_list; item != NULL ; item = g_list_next(item) )
    389  |   {
    390  |     /* is this a 'changed' attribute? */
    391  |     if (strcmp(rpsl_attr_get_name((rpsl_attr_t *)(item->data)), "changed") == 0)
    392  | 	{
    393  |       /* if this attribute does not have a date in it, add it. Also add
    394  |           a warning message about this */
    395  | 	  value = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
    396  |       if ( !up_changed_has_date(value) )
    397  | 	  {
    398  |         count_no_date++;
    399  | 		/* create a copy of this changed attribute and add the date to the value */
    400  | 		changed = rpsl_attr_copy((rpsl_attr_t *)(item->data));
    401  |         temp = (char *)malloc(strlen(value) + strlen(current_date) + 2 );
    402  |         sprintf(temp, "%s %s", value, current_date);
    403  |         rpsl_attr_replace_value(changed, temp);
    404  |         free(temp);
    405  | 		/* delete the original attribute from the object */
    406  | 		pos = rpsl_attr_get_ofs(changed);
    407  | 		rpsl_object_remove_attr(external_syntax_obj, pos, NULL);
    408  | 		/* add the new changed attribute in the same position */
    409  | 		rpsl_object_add_attr(external_syntax_obj, changed, pos, NULL);
    410  |         /* add a warning message */
    411  |         if ( *warning_str == NULL)
    412  | 		{
    413  |           *warning_str = (char *)malloc(strlen("WARNING  date '' added to 'changed' attribute") + 9 );
    414  |           sprintf(*warning_str, "WARNING  date '%s' added to 'changed' attribute", current_date);
    415  |         }
    416  | 		else
    417  | 		{
    418  |           temp = (char *)malloc(strlen(*warning_str) + 1
    419  |                                        + strlen("WARNING  date '' added to 'changed' attribute") + 9 );
    420  |           sprintf(temp, "%s\nWARNING  date '%s' added to 'changed' attribute",
    421  |                               *warning_str, current_date);
    422  |           free(*warning_str);
    423  |           *warning_str = temp;
    424  |         }
    425  |       }
    426  | 	  free(value);
    427  |     }
    428  |   }
    429  |
    430  |   if (count_no_date > 1)
    431  |   {
    432  |     *error_str = strdup("***Error: More than one 'changed' attributes without dates");
    433  |     return 0;
    434  |   }
    435  |   else
    436  |   {
    437  |     return 1;
    438  |   }
    439  | }
    440  |
    441  |
    442  |
    443  |
    444  | /* Checks the order of dates in the given list.
    445  |    If they are in order, returns 1,
    446  |    if not, returns 0 */
    447  | int up_check_date_order(GList * list)
    448  | {
    449  |   GList * item;
    450  |   char * previous;
    451  |   char *value;
    452  |
    453  |   /* if list is empty, return 1 immediately */
    454  |   if (list == NULL)
    455  |   {
    456  |     return 1;
    457  |   }
    458  |
    459  |   /* initialize the 'previous' date */
    460  |   previous = strdup("00000000");
    461  |
    462  |   for ( item = list; item != NULL ; item = g_list_next(item))
    463  |   {
    464  |     assert((item->data) != NULL);
    465  |     /* if the new date is smaller than the previous */
    466  | 	value = (char *)(item->data);
    467  |     if ( strcmp(value, previous) < 0 )
    468  | 	{
    469  |       free(previous);
    470  |       return 0;
    471  |     }
    472  |     free(previous);
    473  |     previous = strdup(value);
    474  |   }
    475  |
    476  |   free(previous);
    477  |   /* Reached the end, without finding out-of-order date. Return 1, then */
    478  |   return 1;
    479  | }
    480  |
    481  |
    482  |
    483  |
    484  |
    485  | /* up_check_date: checks the syntax of the date, given as the only
    486  |    argument (char *). The argument is checked if it is in YYYYMMDD
    487  |    format, and returns an error code accordingly */
    488  | int up_check_date(const char * arg)
    489  | {
    490  |   int date_int; /* integer representation of the date (arg) */
    491  |   char * current_date;
    492  |   int year, month, day; /* integers for the components of the date */
    493  |
    494  |   errno = 0;
    495  |   date_int = atoi(arg);
    496  |
    497  |   if (errno != 0)
    498  |   { /* there was an error in the conversion, syntax error */
    499  |     return UP_DATE_SYNERR;
    500  |   }
    501  |
    502  |   /* wrong format */
    503  |   if (date_int <= 10000000 )
    504  |   { /* the date is not in YYYYMMDD format */
    505  |     return UP_DATE_WRONGFORMAT;
    506  |   }
    507  |
    508  |   /* check if it is too small */
    509  |   if (date_int <= 19880000 )
    510  |   { /* the date is older than the DB itself! */
    511  |     return UP_DATE_TOOSMALL;
    512  |   }
    513  |
    514  |   /* check if it is too big */
    515  |   if (date_int >= 100000000 )
    516  |   {/* too big: syntax error */
    517  |     return UP_DATE_SYNERR;
    518  |   }
    519  |
    520  |   /* and now check year, month and day components */
    521  |   year = date_int / 10000;
    522  |   month = (date_int - (year * 10000) ) / 100;
    523  |   day = (date_int % 100);
    524  |
    525  |   /* check year */
    526  |   if (year < 1988 )
    527  |   {
    528  |     return UP_DATE_TOOSMALL;
    529  |   }
    530  |
    531  |   /* check month */
    532  |   if (month < 1 || month > 12)
    533  |   {
    534  |     return UP_DATE_INVMONTH;
    535  |   }
    536  |
    537  |   /* check day */
    538  |   if (day < 1 || day > 31)
    539  |   {
    540  |     return UP_DATE_INVDAY;
    541  |   }
    542  |
    543  |   switch ( month )
    544  |   {
    545  |     case 1: case 3: case 5: case 7:
    546  |     case 8: case 10: case 12:
    547  |          if (day > 31)
    548  | 		 {
    549  |            return UP_DATE_INVDAY;
    550  |          };
    551  |          break;
    552  |     case 2:
    553  |          if ( (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) && (day > 29 ))
    554  | 		 { /* leap year */
    555  |            return UP_DATE_INVDAY;
    556  |          }
    557  | 		 else if( (!(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) && (day > 28) )
    558  | 		 { /* non-leap year */
    559  |            return UP_DATE_INVDAY;
    560  |          };
    561  |          break;
    562  |     case 4: case 6: case 9: case 11:
    563  |          if (day > 30)
    564  | 		 {
    565  |            return UP_DATE_INVDAY;
    566  |          };
    567  |          break;
    568  |     default: return UP_DATE_INVMONTH;
    569  |   }
    570  |
    571  |   /* check if the arg is in the future or not */
    572  |   current_date = UP_get_current_date();
    573  |   if (strcmp(current_date, arg) < 0 )
    574  |   { /* arg is in the future */
    575  |     free(current_date);
    576  |     return UP_DATE_FUTURE;
    577  |   }
    578  |   free(current_date);
    579  |
    580  |   return UP_DATE_OK;
    581  | }
    582  |
    583  |
    584  |
    585  | /* Checks the syntax of the dates in the list */
    586  | date_syntax_struct * up_check_dates_syntax(GList * list)
    587  | {
    588  |   GList * item;
    589  |   date_syntax_struct * result;
    590  |   int res;
    591  |
    592  |   /* initialize the result struct */
    593  |   result = (date_syntax_struct *)malloc(sizeof(date_syntax_struct));
    594  |   result->result = UP_DATE_OK;
    595  |   result->error_str = NULL;
    596  |
    597  |   /* if list is empty, return immediately */
    598  |   if (list == NULL)
    599  |   {
    600  |     return result;
    601  |   }
    602  |
    603  |   /* loop through the members of the list, check each of them */
    604  |   for ( item = list; item != NULL ; item = g_list_next(item))
    605  |   {
    606  |     assert((item->data) != NULL);
    607  |
    608  |     /* check the date */
    609  |     res = up_check_date((char *)(item->data));
    610  |     switch (res)
    611  | 	{
    612  |       case UP_DATE_OK: break;
    613  |
    614  |       case UP_DATE_FUTURE:
    615  |       case UP_DATE_TOOSMALL:
    616  |       case UP_DATE_INVDAY:
    617  |       case UP_DATE_INVMONTH:
    618  |       case UP_DATE_WRONGFORMAT:
    619  |
    620  |              if (result->error_str == NULL)
    621  | 			 {
    622  |                result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[res])
    623  |                                                   + strlen(": ") + strlen((char *)(item->data)) + 1);
    624  |                sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[res],
    625  |                        (char *)(item->data));
    626  |              }
    627  | 			 else
    628  | 			 {
    629  |                result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1
    630  |                                                    + strlen("***Error: ") + strlen(up_date_errmsgs[res])
    631  |                                                    + strlen(": ") + strlen((char *)(item->data)) + 1);
    632  |                sprintf(result->error_str, "%s\n***Error: %s: %s",
    633  |                        result->error_str, up_date_errmsgs[res], (char *)(item->data));
    634  |              }
    635  |              result->result = UP_DATE_NOK; /* Not OK */
    636  |
    637  |              break;
    638  |
    639  |
    640  |       case UP_DATE_SYNERR: /* syntax error in the date */
    641  |
    642  |       default:
    643  |              if (result->error_str == NULL)
    644  | 			 {
    645  |                result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR])
    646  |                                                   + strlen(": ") + strlen((char *)(item->data)) + 1);
    647  |                sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[UP_DATE_SYNERR],
    648  |                        (char *)(item->data));
    649  |              }
    650  | 			 else
    651  | 			 {
    652  |                result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1
    653  |                                                    + strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR])
    654  |                                                    + strlen(": ") + strlen((char *)(item->data)) + 1);
    655  |                sprintf(result->error_str, "%s\n***Error: %s: %s",
    656  |                        result->error_str, up_date_errmsgs[UP_DATE_SYNERR], (char *)(item->data));
    657  |              }
    658  |              result->result = UP_DATE_NOK; /* Not OK */
    659  |              break;
    660  |     }
    661  |   }
    662  |
    663  |   return result;
    664  | }
    665  |
    666  |
    667  |
    668  | /* void up_check_changed_attr
    669  |    checks the order of dates in the 'changed' attributes */
    670  | void up_check_changed_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
    671  | {
    672  |   GList * date_list;
    673  |   int res;
    674  |   char ** warning, **error;
    675  |   char * temp;
    676  |   date_syntax_struct * date_check_res;
    677  |   GList *changed_list;
    678  |
    679  |   warning = (char **)malloc(sizeof(char **));
    680  |   error   = (char **)malloc(sizeof(char **));
    681  |   changed_list = rpsl_object_get_attr(external_syntax_obj, "changed");
    682  |
    683  |   /* Now, add dates to the "changed" attributes */
    684  |   res = up_add_dates(external_syntax_obj, changed_list, warning, error);
    685  |   if (!res)
    686  |   {
    687  |     /* so, add the error string to result's error string */
    688  |     if (result->error_str == NULL)
    689  | 	{
    690  |       result->error_str = strdup(*error);
    691  |     }
    692  | 	else
    693  | 	{
    694  |       temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2);
    695  |       sprintf(temp, "%s\n%s", result->error_str, *error);
    696  |       free(result->error_str);
    697  |       result->error_str = temp;
    698  |     }
    699  |   }
    700  |
    701  |   /* and get the list of dates, we must check their order */
    702  |   /* we may have added a date to one of the changed attrs so get the list again */
    703  |   rpsl_attr_delete_list(changed_list);
    704  |   changed_list = rpsl_object_get_attr(external_syntax_obj, "changed");
    705  |   date_list = up_get_dates(changed_list);
    706  |   /* and check the order */
    707  |   res = up_check_date_order(date_list);
    708  |   if (!res)
    709  |   {
    710  |     /* so, add the error string to result's error string */
    711  |     if (result->error_str == NULL)
    712  | 	{
    713  |       result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order");
    714  |     }
    715  | 	else
    716  | 	{
    717  |       temp = (char *)malloc(strlen(result->error_str)
    718  |               + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2);
    719  |       sprintf(temp, "%s\n%s", result->error_str,
    720  |               "***Error: The dates in the 'changed' attributes should be in order");
    721  |       free(result->error_str);
    722  |       result->error_str = temp;
    723  |     }
    724  |     /* and here we have to change the result code of "result" here ... */
    725  |     switch (result->result)
    726  | 	{
    727  |       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
    728  |       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
    729  |       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
    730  |       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
    731  |       default: ;
    732  |     }
    733  |   }
    734  |
    735  |   /* check the syntax of dates */
    736  |   date_check_res = up_check_dates_syntax(date_list);
    737  |   if (date_check_res->result != UP_DATE_OK)
    738  |   {
    739  |     /* so, add the error string to result's error string */
    740  |     if (result->error_str == NULL)
    741  | 	{
    742  |       result->error_str = strdup(date_check_res->error_str);
    743  |     }
    744  | 	else
    745  | 	{
    746  |       temp = (char *)malloc(strlen(result->error_str)
    747  |               + strlen(date_check_res->error_str) + 2);
    748  |       sprintf(temp, "%s\n%s", result->error_str,
    749  |               date_check_res->error_str);
    750  |       free(result->error_str);
    751  |       result->error_str = temp;
    752  |     }
    753  |     /* and here we have to change the result code of "result" here ... */
    754  |     switch (result->result)
    755  | 	{
    756  |       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
    757  |       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
    758  |       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
    759  |       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
    760  |       default: ;
    761  |     }
    762  |   }
    763  | }
    764  |
    765  |
    766  | /* performs a simple check on a inetnum attribute. Assumes that
    767  |    the RPSL parser has already checked it. Tries to see if the attr
    768  |    is a range or not  */
    769  | int up_check_an_inetnum_attr(const char * arg){
    770  |
    771  |
    772  |   char * str;
    773  |   char * pos;
    774  |
    775  |   str = strdup(arg);
    776  |
    777  |   while((pos = index(str, '\n')) != NULL){
    778  |     *pos = ' ';
    779  |   }
    780  |
    781  |   /* strip off the comment */
    782  |   if((pos = index(str, '#')) != NULL){
    783  |     *pos = '\0';
    784  |   }
    785  |
    786  |
    787  |   /* Most of the syntax check is done by RPSL parser. We only need to check
    788  |      that the argument is a _range_ of IPv4 addresses. So it suffices to
    789  |      check the existence of '-' in the arg */
    790  |   if(index(str, '-') != NULL){
    791  |
    792  |     free(str);
    793  |     return 1;
    794  |
    795  |   }else{
    796  |
    797  |     free(str);
    798  |     return 0;
    799  |
    800  |   }
    801  | }
    802  |
    803  |
    804  |
    805  | /* Performs a check on status attribute. It can be
    806  |    ALLOCATED PI or ALLOCATED PA only if the maintainers in the
    807  |    mnt-by attribute contain at least one of the names mentioned in
    808  |    ALLOCMNT config variable.
    809  | */
    810  | int up_check_a_status_attr(const char * arg, GList * mnt_by_list)
    811  | {
    812  |   GList * item;
    813  |   int result;
    814  |   char * status, * mnt_by_attrib;
    815  |   char ** allocmnt_list;
    816  |   int i;
    817  |
    818  |   status = strdup(arg);
    819  |   g_strdown(status);
    820  |
    821  |   /* construct a list of mntners that are in allocmnt */
    822  |   allocmnt_list = g_strsplit(allocmnt, " ", 0); /* delimited by " " */
    823  |
    824  |   if (strstr(status, "allocated") != NULL)
    825  |   {
    826  |     result = 1; /* initialize */
    827  |
    828  |     for ( item = mnt_by_list; item != NULL ; item = g_list_next(item) )
    829  | 	{
    830  |       mnt_by_attrib = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
    831  |       for (i=0; allocmnt_list[i] != NULL; i++)
    832  | 	  { /* loop thru the list of allocmnt maintainers */
    833  |         if ((strlen(allocmnt_list[i]) != 0) && strcasecmp(mnt_by_attrib, allocmnt_list[i]) == 0)
    834  | 		{
    835  |           result = 0;
    836  |         }
    837  |       }
    838  |       free(mnt_by_attrib);
    839  |     }
    840  |
    841  |     free(status);
    842  |     g_strfreev(allocmnt_list);
    843  |     return result;
    844  |
    845  |   }
    846  |   else
    847  |   {  /* the status attribute is not allocated */
    848  |     free(status);
    849  |     g_strfreev(allocmnt_list);
    850  |     return 0; /* so there is no problem */
    851  |
    852  |   }
    853  |
    854  | }
    855  |
    856  |
    857  |
    858  |
    859  |
    860  | /* check for status attribute here: The status attribute can be
    861  |    ALLOCATED PI or ALLOCATED PA only if the maintainers in the
    862  |    mnt-by attribute contain at least one of the names mentioned in
    863  |    ALLOCMNT config variable.
    864  | */
    865  | void up_check_status_attr(rpsl_object_t *external_syntax_obj, external_syntax_struct * result)
    866  | {
    867  |   int res;
    868  |   char * temp;
    869  |   char *value;
    870  |   GList * item;
    871  |   GList * mnt_by_list = NULL;
    872  |   GList *status_list = NULL;
    873  |
    874  |   /* Gather a list of mnt-by attributes */
    875  |   mnt_by_list = rpsl_object_get_attr(external_syntax_obj, "mnt-by");
    876  |   status_list = rpsl_object_get_attr(external_syntax_obj, "status");
    877  |
    878  |   /* check the syntax */
    879  |   for ( item = status_list; item != NULL ; item = g_list_next(item) )
    880  |   {
    881  |       value = rpsl_attr_get_clean_value((rpsl_attr_t *)(item->data));
    882  |       res = up_check_a_status_attr(value, mnt_by_list);
    883  |       if (res != 0)
    884  | 	  { /* there was a problem */
    885  |         /* so, add the error string to result's error string */
    886  |         if (result->error_str == NULL)
    887  | 		{
    888  |           result->error_str = (char *)UT_malloc(strlen("***Error: Status ALLOCATED can be set only by the following mntner(s):\n")
    889  |                                                 +strlen("***Error:    ") + strlen(allocmnt) + 2);
    890  |           sprintf(result->error_str, "%s%s%s", "***Error: Status ALLOCATED can be set only by the following mntner(s):\n",
    891  |                                                "***Error:    ", allocmnt);
    892  |         }
    893  | 		else
    894  | 		{
    895  |           temp = (char *)malloc(strlen(result->error_str)
    896  |                   + strlen("***Error: Status ALLOCATED can be set only by the following mntner(s):\n")
    897  |                   + strlen("***Error:    ") + strlen(allocmnt) + 2);
    898  |           sprintf(temp, "%s\n%s%s%s", result->error_str,
    899  |                   "***Error: Status ALLOCATED can be set only by the following mntner(s):\n",
    900  |                   "***Error:    ", allocmnt);
    901  |           free(result->error_str);
    902  |           result->error_str = temp;
    903  |         }
    904  |         /* and here we have to change the result code of "result" here ... */
    905  |         switch (result->result)
    906  | 		{
    907  |           case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
    908  |           case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
    909  |           case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
    910  |           case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
    911  |           default: ;
    912  |         }
    913  |       }
    914  | 	  free(value);
    915  |   }
    916  |   rpsl_attr_delete_list(mnt_by_list);
    917  |   rpsl_attr_delete_list(status_list);
    918  | }
    919  |
    920  |
    921  |
    922  |
    923  | /* void up_add_keycert_attrs
    924  |    adds the generated attrs of key-cert objects */
    925  | void up_add_keycert_attrs(rpsl_object_t *generated_obj)
    926  | {
    927  |   const char *type;
    928  |   char *attr_str;
    929  |   rpsl_attr_t *method_attr;
    930  |   rpsl_attr_t *owner_attr;
    931  |   rpsl_attr_t *fingerpr_attr;
    932  |
    933  |   if (tracing)
    934  |   {
    935  |     printf("TRACING: UP_add_keycert_attrs: is running\n");
    936  |   }
    937  |
    938  |   /* if this is a key-cert object */
    939  |   type = rpsl_object_get_class(generated_obj);
    940  |   if ( strcmp(type, "key-cert") == 0 )
    941  |   {
    942  |       method_attr = rpsl_attr_init("method: PGP", type);
    943  | 	  if ( method_attr )
    944  |       {
    945  |     	rpsl_object_add_attr(generated_obj, method_attr, 1, NULL);
    946  | 	  }
    947  |
    948  |       attr_str = (char *)malloc( sizeof("owner: ") + strlen(keyowner) +1 );
    949  | 	  strcpy(attr_str, "owner: ");
    950  | 	  strcat(attr_str, keyowner);
    951  |       if (tracing)
    952  |       {
    953  |         printf("TRACING: UP_add_keycert_attrs: owner attr_str [%s]\n", attr_str);
    954  |       }
    955  |       owner_attr = rpsl_attr_init(attr_str, "key-cert");
    956  | 	  if ( owner_attr )
    957  |       {
    958  |     	rpsl_object_add_attr(generated_obj, owner_attr, 2, NULL);
    959  | 	  }
    960  |       free(attr_str);
    961  |
    962  |       attr_str = (char *)malloc( sizeof("fingerpr: ") + strlen(fingerprint) +1 );
    963  | 	  strcpy(attr_str, "fingerpr: ");
    964  | 	  strcat(attr_str, fingerprint);
    965  |       if (tracing)
    966  |       {
    967  |         printf("TRACING: UP_add_keycert_attrs: fingerprint attr_str [%s]\n", attr_str);
    968  |       }
    969  |       fingerpr_attr = rpsl_attr_init(attr_str, "key-cert");
    970  | 	  if ( fingerpr_attr )
    971  |       {
    972  |     	rpsl_object_add_attr(generated_obj, fingerpr_attr, 3, NULL);
    973  | 	  }
    974  |       free(attr_str);
    975  |   }
    976  | }
    977  |
    978  |
    979  |
    980  | /* Constructs a list of all attributes of an object, and returns it
    981  |    as a list of attribute_struct */
    982  | /*GSList * up_get_attribute_list(Object * o, char * text){
    983  |
    984  |   char * value = NULL;
    985  |   char * type = NULL;
    986  |   Attr *attr;
    987  |   GSList *list_of_attributes = NULL;
    988  |   attribute_struct * attribute;
    989  |
    990  |   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    991  |     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    992  |     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
    993  |         attr->len - strlen(attr->type->name()) -2 );
    994  |     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    995  |       if(tracing) {
    996  |         cout << "TRACING: up_get_attributes: adding " << g_strstrip(value) << endl;
    997  |       }
    998  |       attribute = (attribute_struct *)malloc(sizeof(attribute_struct));
    999  |       attribute->content = value;
    1000 |       type = strdup(attr->type->name());
    1001 |       g_strdown(type);
    1002 |       attribute->type = type;
    1003 |       list_of_attributes = g_slist_append(list_of_attributes, attribute);
    1004 |   }
    1005 |
    1006 |
    1007 |   return list_of_attributes;
    1008 |
    1009 | }
    1010 | */
    1011 |
    1012 |
    1013 | /* up_reconstruct_object: Reconstructs the object's text representation
    1014 |      using the parsed object */
    1015 | void up_reconstruct_object(rpsl_object_t *external_syntax_obj, external_syntax_struct *result)
    1016 | {
    1017 |   char * recons_obj = NULL;
    1018 |
    1019 |   recons_obj = rpsl_object_get_text(external_syntax_obj,RPSL_STD_COLUMN);
    1020 |
    1021 |   result->new_obj = recons_obj;
    1022 | }
    1023 |
    1024 |
    1025 |
    1026 | /*  UP_check_external_syntax: Checks the syntax of attributes which are not checked
    1027 |        by RAToolSet syntax checker. */
    1028 | external_syntax_struct * UP_check_external_syntax(rpsl_object_t *external_syntax_obj)
    1029 | {
    1030 |   external_syntax_struct *result;
    1031 |
    1032 |   if (tracing)
    1033 |   {
    1034 | 	printf("TRACING: UP_check_external_syntax running\n");
    1035 |   }
    1036 |
    1037 |   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
    1038 |
    1039 |   /* initialize the struct */
    1040 |   result->result = 0;
    1041 |   result->error_str = strdup("");
    1042 |   result->warning_str = strdup("");
    1043 |
    1044 |   up_check_source_attr(external_syntax_obj, result);
    1045 |
    1046 |   up_check_country_attr(external_syntax_obj, result);
    1047 |
    1048 |   up_check_nicsuffixes(external_syntax_obj, result);
    1049 |
    1050 |   up_check_changed_attr(external_syntax_obj, result);
    1051 |
    1052 | /* this will be done by the new API parser */
    1053 | /*  up_check_auth_attr   (arg, obj_text, attribute_list, result);  */
    1054 |
    1055 | /* this will be done by the new API parser */
    1056 | /*  up_check_inetnum_attr(arg, obj_text, attribute_list, result); */
    1057 |
    1058 |   up_check_status_attr(external_syntax_obj, result);
    1059 |
    1060 |
    1061 |   up_reconstruct_object(external_syntax_obj, result);
    1062 |
    1063 |   if (tracing)
    1064 |   {
    1065 |     printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
    1066 |     printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
    1067 |   }
    1068 |
    1069 |   return result;
    1070 | }
    1071 |
    1072 |
    1073 |
    1074 | /* generates the "generated" attributes of a key-cert object. Returns the
    1075 |    new object string*/
    1076 | char *UP_generate_kc_attrs(rpsl_object_t *generated_obj)
    1077 | {
    1078 |   external_syntax_struct *result;
    1079 |   char *obj_str;
    1080 |
    1081 |   if (tracing)
    1082 |   {
    1083 |     printf("TRACING: UP_generate_kc_attrs: is running\n");
    1084 |   }
    1085 |
    1086 |   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
    1087 |
    1088 |   /* initialize the struct */
    1089 |   result->result = 0;
    1090 |   result->error_str = strdup("");
    1091 |   result->warning_str = strdup("");
    1092 |
    1093 |   up_check_changed_attr(generated_obj, result);
    1094 |   up_add_keycert_attrs(generated_obj);
    1095 |
    1096 |   up_reconstruct_object(generated_obj, result);
    1097 |
    1098 |   if (tracing)
    1099 |   {
    1100 |     printf("TRACING: UP_generate_kc_attrs: the reconstructed object is=[%s]\n", result->new_obj);
    1101 |     printf("TRACING: UP_generate_kc_attrs: ... and the result code is=[%i]\n", result->result);
    1102 |   }
    1103 |
    1104 |   obj_str = strdup(result->new_obj);
    1105 |   free(result);
    1106 |   return obj_str;
    1107 | }
    1108 |
    1109 |
    1110 |
    1111 | /* char * up_assign_i6_status: Determines the status attribute of
    1112 |     an inet6num object. It takes the inet6num attribute of the
    1113 |     object as its only argument. If prefix length is less than
    1114 |     4, then returns NULL */
    1115 | char * up_assign_i6_status(const char * inet6num_attr)
    1116 | {
    1117 |
    1118 |   char ** split_str;
    1119 |   int prefix_length;
    1120 |   int result;
    1121 |
    1122 |   /* we need the prefix length here.*/
    1123 |   split_str = g_strsplit(inet6num_attr, "/", 0);
    1124 |   if(split_str[1] != NULL){
    1125 |
    1126 |     result = sscanf(split_str[1], "%i", &prefix_length);
    1127 |     if(result != 0 && result != EOF){
    1128 |
    1129 |       if(prefix_length >= 0 && prefix_length <= 3){
    1130 |
    1131 |         g_strfreev(split_str);
    1132 |         return NULL;
    1133 |
    1134 |       }else if(prefix_length >= 4 && prefix_length <= 15){
    1135 |
    1136 |         g_strfreev(split_str);
    1137 |         return strdup("TLA");
    1138 |
    1139 |       }else if(prefix_length >= 16 && prefix_length <= 35){
    1140 |
    1141 |         g_strfreev(split_str);
    1142 |         return strdup("SUBTLA");
    1143 |
    1144 |       }else if(prefix_length >= 36 && prefix_length <= 48){
    1145 |
    1146 |         g_strfreev(split_str);
    1147 |         return strdup("NLA");
    1148 |
    1149 |       }else if(prefix_length >= 48 && prefix_length <= 64){
    1150 |
    1151 |         g_strfreev(split_str);
    1152 |         return strdup("SLA");
    1153 |
    1154 |       }else{
    1155 |
    1156 |         /* "default" status */
    1157 |         g_strfreev(split_str);
    1158 |         return strdup("SLA");
    1159 |
    1160 |       }
    1161 |
    1162 |     }else{
    1163 |
    1164 |       /* return "default" status */
    1165 |       g_strfreev(split_str);
    1166 |       return strdup("SLA");
    1167 |
    1168 |     }
    1169 |   }else{
    1170 |
    1171 |     /* return "default" status */
    1172 |     g_strfreev(split_str);
    1173 |     return strdup("SLA");
    1174 |
    1175 |   }
    1176 |
    1177 | }
    1178 |
    1179 |
    1180 |
    1181 | /* GSList * up_add_inet6num_attrs
    1182 |    adds the generated attrs of inet6num objects */
    1183 | /*GSList * up_add_inet6num_attrs(Object * obj, char * obj_text, GSList * attribute_list,
    1184 |                                external_syntax_struct * result)*/
    1185 | void up_add_inet6num_attrs(rpsl_object_t *generated_obj)
    1186 | {
    1187 |
    1188 |   int attribute_no;
    1189 |   char *status_value;
    1190 |   rpsl_attr_t * status_attr;
    1191 |   char *inet6num_attr_str, *status_attr_str;
    1192 |   const char *type;
    1193 |   GList *attributes_changed;
    1194 |
    1195 |
    1196 |
    1197 |   /* if this is an inet6num  object */
    1198 |   type = rpsl_object_get_class(generated_obj);
    1199 |   if( ! strcmp(type, "inet6num") )
    1200 |   {
    1201 |       inet6num_attr_str = get_search_key(generated_obj, "inet6num");
    1202 |       status_value = up_assign_i6_status(inet6num_attr_str);
    1203 |       status_attr_str = (char *)UT_malloc(strlen("status: ") + strlen(status_value) + 1);
    1204 |       strcpy(status_attr_str, "status: ");
    1205 |       strcat(status_attr_str, status_value);
    1206 |       status_attr = rpsl_attr_init(status_attr_str, type);
    1207 | 	  free(status_attr_str);
    1208 | 	  if ( status_attr )
    1209 |       {
    1210 |     	/* we will put the status attribute before the first 'changed' attribute */
    1211 |     	attribute_no = 1; /* a default position (the second attribute) in case we cannot find
    1212 |                         	 a 'changed' attribute */
    1213 |     	attributes_changed = rpsl_object_get_attr(generated_obj, "changed");
    1214 |     	if ( attributes_changed != NULL )
    1215 | 		{
    1216 |           attribute_no = ((rpsl_attr_t *)(attributes_changed->data))->num;
    1217 |     	}
    1218 |     	rpsl_object_add_attr(generated_obj, status_attr, attribute_no, NULL);
    1219 |       }
    1220 |   }
    1221 | }
    1222 |
    1223 |
    1224 |
    1225 | /* generates the "generated" attribute (status) of an inet6num object. Returns the
    1226 |    new object as a char * */
    1227 | char *UP_generate_i6_attrs(rpsl_object_t *generated_obj)
    1228 | {
    1229 |
    1230 |   external_syntax_struct *result;
    1231 |   char *obj_str;
    1232 |
    1233 |   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
    1234 |
    1235 |   /* initialize the struct */
    1236 |   result->result = 0;
    1237 |   result->error_str = strdup("");
    1238 |   result->warning_str = strdup("");
    1239 |
    1240 |
    1241 |   up_check_changed_attr(generated_obj, result);
    1242 |   up_add_inet6num_attrs(generated_obj);
    1243 |
    1244 |   up_reconstruct_object(generated_obj, result);
    1245 |
    1246 |   if (tracing)
    1247 |   {
    1248 |     printf("TRACING: UP_generate_i6_attrs: the reconstructed object is=[%s]\n", result->new_obj);
    1249 |     printf("TRACING: UP_generate_i6_attrs: ... and the result code is=[%i]\n", result->result);
    1250 |   }
    1251 |
    1252 |   obj_str = strdup(result->new_obj);
    1253 |   free(result->error_str);
    1254 |   free(result->warning_str);
    1255 |   free(result->new_obj);
    1256 |   free(result);
    1257 |   return obj_str;
    1258 | }
    1259 |