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 |