## modules/up/UP_util.cc

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

## FUNCTIONS

This source file includes following functions.

1. authorise
2. error_msg_cat
3. interpret_ripdb_result
4. get_assigned_nic
5. delete_override
6. up_get_transaction_id
7. send_object_db
8. get_class_type
9. get_search_key
10. send_and_get
11. count_objects
12. strip_lines
13. take_objects
14. take_object
15. get_as_block
16. get_aut_num_object
17. get_less_specific_domain
18. get_less_specific_set
19. get_less_specific
20. get_less_spec_inetnum
21. get_exact_match_inetnum
22. get_exact_match_routes
23. get_less_spec_routes
24. get_mntners
25. get_attributes
26. get_attribute
27. strstr_in_list
28. get_auths
29. get_attr_list
30. get_mnt_lowers
31. get_mnt_routes
32. get_mnt_routes_from_list
33. get_mnt_lowers_from_list
34. get_override
35. check_override
36. add_to_auth_vector
37. get_auth_vector
38. get_mntnfy_vector
39. get_updto_vector
40. filter_out_diff_origins
41. filter_out_same_origins
42. check_auth
43. get_old_version
44. process_mail_header
45. up_string_pack
46. delete_delete_attrib
47. UP_replace_strings
48. UP_replace_GStrings
49. identical
50. find_initials
51. get_combination_from_autonic
52. replace_AUTO_NIC_hdl
53. replace_refs_to_AUTO_NIC_hdl
54. UP_put_assigned_NIC
55. has_AUTO_NIC_hdl
56. has_ref_to_AUTO_nic_hdl
57. find_email_address
58. UP_remove_EOLs
59. UP_replace_globals
60. get_class_type_char
61. UP_add_to_upd_log
62. UP_log_networkupdate

       1 /***************************************
       2   $Revision: 1.71 $
       3
       4   UP module utilities
       5
       6   Status: NOT REVIEWED, NOT TESTED
       7
       8   Author(s):       Engin Gunduz
       9
      10   ******************/ /******************
      11   Modification History:
      12         engin (17/01/2000) Created.
      13   ******************/ /******************
      14   Copyright (c) 2000                              RIPE NCC
      15
      16   All Rights Reserved
      17
      18   Permission to use, copy, modify, and distribute this software and its
      19   documentation for any purpose and without fee is hereby granted,
      20   provided that the above copyright notice appear in all copies and that
      21   both that copyright notice and this permission notice appear in
      22   supporting documentation, and that the name of the author not be
      23   used in advertising or publicity pertaining to distribution of the
      24   software without specific, written prior permission.
      25
      26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
      27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
      28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
      29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      32  ***************************************/
      33
      34 #include <time.h>
      35 #include "dbupdate.h"
      36 #include "UP_extrnl_syntax.h"
      37 #include "ud.h"
      38
      39 int error = 0; // a global variable to store the errors
      40 char * error_msg = NULL; // a global variable to store the error messages
      41 extern int tracing;
      42 extern char * overridecryptedpw;
      43 extern int test_mode;
      44 extern char * updlog;
      45 extern char * update_host;
      46 extern int update_port;
      47 extern char * query_host;
      48 extern int query_port;
      49 extern char * humailbox;
      50 extern char * autobox;
      51 extern char * netupdclientIP;
      52
      53 extern int reading_from_mail;
      54 extern int networkupdate;
      55
      56
      57 extern char *update_mail_sender;
      58 extern char *update_mail_subject;
      59 extern char *update_mail_date;
      60 extern char *update_mail_ID;
      61 extern char *update_mail_cc;
      62
      63 extern char *DBhost;
      64 extern int  DBport;
      65 extern char *DBuser;
      66 extern char *DBname;
      67 extern char *DBpasswd;
      68
      69
      70 /* authorise function takes the auth_vector, credentials struct, and 'overriden'
      71    variable. If overriden == 1, then it immediately returns UP_AUTH_OK
      72    (because this means that the update contained a valid override attribute).
      73    Else, it goes through the auth_vector and when it finds a an "auth:"
      74    attribute which passes, then it returns UP_AUTH_OK. Otherwise, it returns
      75    UP_AUF (authorisation failed) */
      76
      77 int authorise(GSList * auth_vector, credentials_struct credentials, int overriden){
         /* [<][>][^][v][top][bottom][index][help] */
      78
      79   int result = 0;
      80
      81   if(tracing){
      82     printf("TRACING: authorise started with override: %i\n", overriden);
      83   }
      84
      85   /* If 'overriden' variable is 1, then return UP_AUTH_OK immediately */
      86   if(overriden == 1){
      87     return UP_AUTH_OK;
      88   }
      89
      90   else{
      91     result = AU_authorise(auth_vector, credentials);
      92     if(tracing){
      93       printf("TRACING: authorise: AU_authorise returned %i\n", result);
      94     }
      95     if(result > 0){
      96       return UP_AUTH_OK;
      97     }
      98     else{
      99       return UP_AUF; /* authorisation failed */
     100     }
     101   }
     102 }
     103
     104 /* concatanates the string at the end of error_msg */
     105 void error_msg_cat(const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
     106
     107   if(string == NULL){
     108     return;
     109   }
     110   if(error_msg == NULL){
     111     error_msg = strdup(string);
     112   }else{
     113     error_msg = (char *)realloc(error_msg, strlen(error_msg) + strlen(string) + 2);
     114     error_msg = strcat(error_msg, "\n");
     115     error_msg = strcat(error_msg, string);
     116   }
     117 }
     118
     119
     120 /* interprets the result string coming from RIPupd
     121    It is called by send_object_db.
     122    It returns the error no returned from RIPupd.  */
     123
     124 int interpret_ripdb_result(const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
     125    char * error_no = NULL;
     126    char ** temp = NULL, ** temp2 = NULL;
     127    int i;
     128    int err = 0;
     129
     130   /* if the string is NULL or empty, then return error */
     131   if(string == NULL || strlen(string) == 0){
     132     error = UP_INT; /* internal error, RIPupd should return something */
     133     error_msg_cat("Internal error. RIPupd didn't return anything.");
     134     return 0;
     135   }
     136
     137   /* split the string into lines */
     138   temp = g_strsplit(string , "\n", 0);
     139   for(i = 0; temp[i] != NULL; i++){
     140     if(i == 0){/* this line must contain "%ERROR " string in the beginning */
     141       temp2 = g_strsplit(temp[0], " ", 0);
     142       error_no = strdup(temp2[1]);
     143       g_strfreev(temp2);
     144       err = atoi(error_no);
     145       if(tracing){
     146         printf("TRACING: interpret_ripdb_result: error_no is [%s]\n", error_no);
     147       }
     148     }else if(error_no != NULL && strcmp(error_no, "0") != 0){
     149       error_msg_cat(temp[i]);
     150     }
     151   }
     152   g_strfreev(temp);
     153   if(error_no != NULL){
     154     free(error_no);
     155   }
     156   return err; /* 0 means no error in this context */
     157 }
     158
     159
     160
     161 /* Gets assigned NIC hdl from the string that is returned from
     162    RIPupdate */
     163 void get_assigned_nic(char * nic_hdl, const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
     164    char * error_no = NULL;
     165    char ** temp = NULL, ** temp2 = NULL;
     166    int i;
     167
     168   /* if the string is NULL or empty, then return error */
     169   if(string == NULL || strlen(string) == 0){
     170     error = UP_INT; /* internal error, RIPupd should return something */
     171     error_msg_cat("Internal error. RIPupd didn't return anything.");
     172     return;
     173   }
     174
     175   /* split the string into lines */
     176   temp = g_strsplit(string , "\n", 0);
     177   for(i = 0; temp[i] != NULL; i++){
     178     if(i == 0){/* this line must contain "%ERROR " string in the beginning */
     179       temp2 = g_strsplit(temp[0], " ", 0);
     180       error_no = strdup(temp2[1]);
     181       g_strfreev(temp2);
     182       if(tracing){
     183         printf("TRACING: get_assigned_nic: error_no is [%s]\n", error_no);
     184       }
     185     }else if(error_no != NULL && strcmp(error_no, "0") != 0){
     186       error_msg_cat(temp[i]);
     187     }else if(error_no != NULL && strcmp(error_no, "0") == 0 && i == 1){/* look for assigned NIC hdl */
     188       /* in the second line RIPupdate returns for example "I[65][EK3-RIPE]" We
     189          need to extract EK3-RIPE part */
     190       //to_be_returned = (char *)malloc(128); /* 128 should be enough for a NIC hdl */
     191       nic_hdl = strncpy(nic_hdl, rindex(temp[i],'[') + 1 ,
     192                                  rindex(temp[i],']') - rindex(temp[i],'[') - 1);
     193       nic_hdl[rindex(temp[i],']') - rindex(temp[i],'[') - 1] = '\0';
     194       if(tracing && nic_hdl != NULL){
     195         printf("TRACING: get_assigned_nic will return [%s]\n", nic_hdl);
     196       }
     197       g_strfreev(temp);
     198       return;
     199     }
     200   }
     201   g_strfreev(temp);
     202   if(tracing && error_no != NULL && error_msg != NULL){
     203     printf("TRACING: interpret_ripdb_result: Error: [%s][%s]\n", error_no, error_msg);
     204   }
     205   return;
     206 }
     207
     208
     209
     210
     211
     212
     213 /* strips lines beginning with "override:" off  */
     214 char * delete_override(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     215
     216     char ** temp = NULL;
     217     char * string = NULL;
     218     int i;
     219
     220     if(arg == NULL){
     221        return NULL;
     222     }
     223
     224     /* split the string into lines */
     225     temp = g_strsplit (arg, "\n", 0);
     226
     227     for(i=0; temp[i] != NULL; i++){
     228       /* if the line begins with "override:", then do not copy it */
     229       if(strstr(temp[i], "override:") != temp[i]){
     230         if(string == NULL){
     231           string = strdup(temp[i]);
     232         }else{
     233           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 2);
     234           string = strcat(string, "\n");
     235           string = strcat(string, temp[i]);
     236         }
     237       }
     238     }
     239     g_strfreev(temp);
     240     return string;
     241 }
     242
     243
     244
     245
     246
     247 /* Obtains a transaction ID for an object. Will be called from send_object_db */
     248 int up_get_transaction_id(){
         /* [<][>][^][v][top][bottom][index][help] */
     249
     250   SQ_connection_t * sql_connection;
     251   SQ_result_set_t *result;
     252   int error;
     253   long new_id;
     254
     255   sql_connection = SQ_get_connection(DBhost, DBport, DBname, DBuser, DBpasswd);
     256   if(!sql_connection){
     257     fprintf(stderr, "No SQL connection\n");
     258     exit(1);
     259   }
     260   error = SQ_execute_query(sql_connection, "INSERT INTO tid VALUES(NULL)", &result);
     261   if(error){
     262     fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
     263     exit(1);
     264   }
     265
     266   new_id = mysql_insert_id(sql_connection);
     267
     268   SQ_close_connection(sql_connection);
     269
     270   return new_id;
     271 }
     272
     273
     274
     275
     276
     277
     278 /* sends the object to the database. char * operation is either 'ADD' ,'DEL' or 'UPD'
     279    assigned_NIC is filled in if this is a person/role creation with AUTO nic hdl
     280    assigned_NIC must be allocated enough memory before send_object_db is called
     281
     282    If the called do not expect a NIC hdl back, then assigned_NIC can be given NULL
     283    */
     284 up_ripupd_result_struct * send_object_db(char * arg, char * assigned_NIC, char * operation){
         /* [<][>][^][v][top][bottom][index][help] */
     285
     286         int sockfd, numbytes;
     287         char buf[MAXDATASIZE + 1];
     288         struct hostent *he;
     289         struct sockaddr_in their_addr; /* connector's address information */
     290         char *result_string = NULL;
     291         char *to_be_returned = NULL;
     292         int err = 0;
     293         char *to_be_sent = NULL;
     294         int tr_id;
     295         char * tr_id_str;
     296         char * tempstr;
     297
     298         up_ripupd_result_struct * return_struct;
     299
     300         return_struct = (up_ripupd_result_struct *)malloc(sizeof(up_ripupd_result_struct));
     301         return_struct->error_str = NULL;
     302
     303         to_be_sent = delete_override(arg);
     304
     305         /* get the transaction ID, to be sent to RIPupdate*/
     306         tr_id = up_get_transaction_id();
     307
     308         /* convert it into a string */
     309         tr_id_str = (char *)malloc(64);
     310         sprintf(tr_id_str, "%d", tr_id);
     311
     312         if ((he=gethostbyname(update_host)) == NULL) {  /* get the host info */
     313             perror("gethostbyname");
     314             exit(1);
     315         }
     316
     317         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     318             perror("socket");
     319             exit(1);
     320         }
     321
     322         their_addr.sin_family = AF_INET;      /* host byte order */
     323         their_addr.sin_port = htons(update_port);    /* short, network byte order */
     324         their_addr.sin_addr = *((struct in_addr *)he->h_addr);
     325         bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
     326
     327
     328         if (connect(sockfd, (struct sockaddr *)&their_addr,
     329                                               sizeof(struct sockaddr)) == -1) {
     330             perror("connect");
     331             exit(1);
     332         }
     333
     334         if (send(sockfd, operation , strlen(operation), 0) == -1)
     335             perror("send");
     336         if (send(sockfd, " ", strlen(" "), 0) == -1)
     337             perror("send");
     338         if (send(sockfd, tr_id_str, strlen(tr_id_str), 0) == -1)
     339             perror("send");
     340         if (send(sockfd, "\n\n" , strlen("\n\n"), 0) == -1)
     341             perror("send");
     342         if (send(sockfd, to_be_sent, strlen(to_be_sent), 0) == -1)
     343             perror("send");
     344         if (send(sockfd, "\n\n", 2, 0)  == -1)
     345             perror("send");
     346         /* send the ACK now */
     347         if (send(sockfd, "ACK ",strlen("ACK "), 0)  == -1)
     348             perror("send");
     349         if (send(sockfd, tr_id_str, strlen(tr_id_str), 0) == -1)
     350             perror("send");
     351         if (send(sockfd, "\n\n",strlen("\n\n"), 0)  == -1)
     352             perror("send");
     353
     354
     355         while ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) != 0) {
     356             buf[numbytes] = '\0';
     357             if(tracing){
     358               printf("%s",buf);
     359             }
     360             if(result_string == NULL){
     361               result_string = strdup(buf);
     362             }else{
     363               result_string = (char *)realloc(result_string,
     364                                  strlen(result_string) + strlen(buf) + 1);
     365               result_string = strcat(result_string, buf);
     366             }
     367             if(strstr(result_string,"\n\n") != NULL){/* if the result_string contains
     368                                                         an empty line at the end, we will close */
     369               break;
     370             };
     371         }
     372
     373         err = interpret_ripdb_result(result_string);
     374         if(assigned_NIC != NULL){ /* if the caller of the function expected to get a NIC handle */
     375           get_assigned_nic(assigned_NIC, result_string);
     376         }
     377         close(sockfd);
     378         free(to_be_sent);
     379         return_struct->result = err;
     380
     381         //return_struct->error_str = strdup(result_string);
     382         /* According to the error no got from RIPupdate, construct an error string  */
     383         switch (return_struct->result){
     384           case 0: break;
     385           case ERROR_U_MEM:
     386           case ERROR_U_DBS:
     387           case ERROR_U_BADOP:
     388           case ERROR_U_COP:
     389           case ERROR_U_NSUP:
     390           case ERROR_U_BUG:
     391             tempstr = (char *)malloc(1024);
     392             snprintf(tempstr, 1024, "***Error: Please contact database admin: Error no %i",
     393                 return_struct->result);
     394             return_struct->error_str = tempstr;
     395             break;
     396           case ERROR_U_OBJ:
     397             tempstr = (char *)malloc(1024);
     398             /* if the object contains refs to unknown objects */
     399             if(strstr(result_string, "dummy") != NULL){
     400
     401               /* if the response from RIPupd contains "dummy not allowed" string */
     402               snprintf(tempstr, 1024, "***Error: Unknown object referenced");
     403
     404             }else{
     405
     406               snprintf(tempstr, 1024, "***Error: Object is referenced from other objects");
     407
     408             }
     409             return_struct->error_str = tempstr;
     410             break;
     411           case ERROR_U_AUT:
     412             tempstr = (char *)malloc(1024);
     413             snprintf(tempstr, 1024, "***Error: Membership authorisation failure");
     414             return_struct->error_str = tempstr;
     415             break;
     416           default:
     417             tempstr = (char *)malloc(1024);
     418             snprintf(tempstr, 1024, "***Error: Please contact database admin: Error no %i",
     419                 return_struct->result);
     420             return_struct->error_str = tempstr;
     421             break;
     422         }
     423         return return_struct;
     424 }
     425
     426
     427
     428
     429
     430
     431 /* takes a pre-parsed object, and returns its type */
     432 char * get_class_type(Object *arg){
         /* [<][>][^][v][top][bottom][index][help] */
     433
     434     char * be_returned = NULL;
     435     if(arg == NULL) return NULL;
     436     be_returned = strdup(arg->type->getName());
     437     return g_strstrip(be_returned);
     438 }
     439
     440
     441
     442
     443
     444
     445 /* takes an object (pre-parsed) and returns its first attrib if it is not
     446    a person, and returns the nic-hdl if it is a person object */
     447 char * get_search_key(Object *arg, char * type, const char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     448
     449
     450     Attr *attr;
     451     char *primary_key = NULL, *value = NULL;
     452
     453     if(arg == NULL) return NULL;
     454
     455     for(attr = arg->attrs.head(); attr; attr = arg->attrs.next(attr)){
     456        if(attr->type != NULL ){
     457          value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     458          strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     459              attr->len - strlen(attr->type->name()) -2 );
     460              value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     461          if(strcmp(attr->type->name(),type) == 0 &&
     462                 strcmp(type,"person") != 0 && strcmp(type,"role") != 0  ){
     463            primary_key = strdup(value);
     464            free(value);
     465            break;
     466          }
     467          if(strcmp(attr->type->name(),"nic-hdl") == 0 &&
     468               (strcmp(type,"person") == 0 || strcmp(type,"role") == 0 )){
     469            primary_key = strdup(value);
     470            free(value);
     471            break;
     472          }
     473          free(value);
     474        }
     475     }
     476     if(primary_key != NULL){
     477       return g_strstrip(primary_key);
     478     }else{
     479       return NULL;
     480     }
     481 }
     482
     483
     484
     485
     486 /* sends char * arg to the specified host's specified port, and
     487    returns the reply as a string. This is used to query the
     488    whois host. Probably we must use WC (whois client) module here,
     489    but it must be extented */
     490 char * send_and_get(char * host, int port, char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     491
     492         int sockfd, numbytes;
     493         char * result = NULL;
     494         char buf[MAXDATASIZE + 1];
     495         struct hostent *he;
     496         struct sockaddr_in their_addr; /* connector's address information */
     497
     498         if(tracing) {
     499           printf("TRACING: send_and_get: arg : [%s]; port: [%i]; host: [%s]\n", arg, port, host);
     500         }
     501
     502         if ((he=gethostbyname(host)) == NULL) {  /* get the host info */
     503             perror("gethostbyname");
     504             exit(1);
     505         }
     506
     507         if(tracing) {
     508           printf("TRACING: send_and_get: called gethostbyname\n");
     509         }
     510
     511         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     512             perror("socket");
     513             exit(1);
     514         }
     515
     516         if(tracing) {
     517           printf("TRACING: send_and_get: called socket\n");
     518         }
     519
     520
     521         their_addr.sin_family = AF_INET;      /* host byte order */
     522         their_addr.sin_port = htons(port);    /* short, network byte order */
     523         their_addr.sin_addr = *((struct in_addr *)he->h_addr);
     524         bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
     525
     526         if (connect(sockfd, (struct sockaddr *)&their_addr,
     527                                               sizeof(struct sockaddr)) == -1) {
     528             perror("connect");
     529             exit(1);
     530         }
     531         if (send(sockfd, arg , strlen(arg), 0) == -1)
     532                perror("send");
     533         if (send(sockfd, "\n",1,0)  == -1)
     534                perror("send");
     535
     536
     537         while ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) != 0) {
     538             buf[numbytes] = '\0';
     539             if(result == NULL){
     540               result = strdup(buf);
     541             }else{
     542               result = (char *)realloc(result, strlen(result) + strlen(buf) + 1);
     543               result = strcat(result, buf);
     544             }
     545         }
     546
     547         close(sockfd);
     548         return result;
     549
     550
     551 }
     552
     553
     554
     555 /* counts the number of objects in a string */
     556 int count_objects(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     557     int count = 0;
     558     char *pos = NULL;
     559     char *temp = NULL;
     560
     561     if(tracing) {
     562       printf("TRACING: count_objects running\n");
     563     }
     564
     565     if(arg != NULL){
     566       temp = strdup(arg);
     567     }else{
     568       return 0;
     569     }
     570
     571     if(isalpha(arg[0])){
     572       count++;
     573     }else if(arg[0] == '\n' && isalpha(arg[1])){
     574       count++;
     575     }
     576     while(pos = strstr(temp,"\n\n")){
     577       pos[0] = 'a'; /* something non-EOL so that it won't be caught in the next loop */
     578       if(isalpha(pos[2])){
     579         count++;
     580       }
     581     }
     582     if(tracing) {
     583       cout << "TRACING: count_objects returning " << count << endl;
     584     }
     585     free(temp);
     586     return count;
     587 }
     588
     589
     590 /* strips lines beginning with '%' off  */
     591 char * strip_lines(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     592
     593     char ** temp = NULL;
     594     char * string = NULL;
     595     int i;
     596
     597     if(arg == NULL){
     598        return NULL;
     599     }
     600
     601     /* split the string into lines */
     602     temp = g_strsplit (arg, "\n", 0);
     603
     604     for(i=0; temp[i] != NULL; i++){
     605       if(temp[i][0] != '%'){
     606         if(string == NULL){
     607           string = strdup(temp[i]);
     608         }else{
     609           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 2);
     610           string = strcat(string, "\n");
     611           string = strcat(string, temp[i]);
     612         }
     613       }
     614     }
     615     return string;
     616 }
     617
     618 /* Separates the objects in the given char * arg using "\n\n" as
     619    separator. Returns a linked list whose data consist of separated
     620    objects as  char *  */
     621
     622 GSList * take_objects(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     623     char ** objects=NULL;
     624     char ** temp = NULL;
     625     GSList * tobereturned = NULL;
     626     int i;
     627
     628     arg = strip_lines(arg);
     629
     630     objects =  g_strsplit(arg, "\n\n", 1000);
     631     temp = objects;
     632     for(i=0; temp[i] != NULL; i++){
     633       /* stripe off the trailing and leading white spaces-eols*/
     634       g_strstrip(temp[i]);
     635       if(strlen(temp[i]) > 0){/* if not an empty string */
     636         tobereturned = g_slist_append(tobereturned, temp[i]);
     637       }
     638     }
     639     return tobereturned;
     640 }
     641
     642
     643
     644
     645
     646 /* takes the first object in the given char *, using empty lines as
     647    separator */
     648 char * take_object(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     649     GSList * objects;
     650     char * object;
     651
     652     objects = take_objects(arg);
     653     if(g_slist_length(objects) > 0){
     654       object = strdup((char *)(g_slist_nth_data(objects, 0)));
     655     }else{
     656       return NULL;
     657     }
     658     g_slist_free(objects);
     659     return object;
     660
     661 }
     662
     663
     664
     665
     666
     667 /* Takes an autnum_object, and returns the as-block containing this aut-num */
     668 char * get_as_block(char *autnum_object){
         /* [<][>][^][v][top][bottom][index][help] */
     669   bool code;
     670   char * search_key = NULL, * query_string = NULL;
     671   char * result = NULL;
     672   Object * o = new Object();
     673
     674   code = o->scan_silent(autnum_object, strlen(autnum_object));
     675   search_key = get_search_key(o,"aut-num",autnum_object);
     676
     677   query_string = (char *)malloc(strlen("-Tas-block -r ")+strlen(search_key)+1);
     678   sprintf(query_string, "-Tas-block -r %s",search_key);
     679   result = send_and_get(query_host, query_port, query_string);
     680   if(count_objects(result) == 0){
     681     if(tracing){
     682       cout << "No such as-block" << endl;
     683     }
     684     return NULL;
     685   }else if(count_objects(result) > 1){
     686     if(tracing){
     687       cout << "More than one as-block returned" << endl;
     688     }
     689     return NULL;
     690   }else{ /* count_objects(result) == 1 */
     691     return take_object(result);
     692   }
     693
     694 }
     695
     696
     697 /* Takes a route_object, and returns the aut-num mentioned in origin
     698    attribute of this route */
     699 char * get_aut_num_object(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     700   bool code;
     701   char * search_key = NULL, * query_string = NULL;
     702   char * result = NULL;
     703   Object * o = new Object();
     704
     705   code = o->scan_silent(route_object, strlen(route_object));
     706   search_key = get_search_key(o,"origin",route_object);
     707
     708   query_string = (char *)malloc(strlen("-Taut-num  -r ")+strlen(search_key)+1);
     709   sprintf(query_string, "-Taut-num -r %s",search_key);
     710   result = send_and_get(query_host, query_port, query_string);
     711   if(count_objects(result) == 0){
     712     if(tracing){
     713       cout << "No such aut-num" << endl;
     714     }
     715     return NULL;
     716   }else if(count_objects(result) > 1){
     717     if(tracing){
     718       cout << "More than one aut-num returned" << endl;
     719     }
     720     return NULL;
     721   }else{ /* count_objects(result) == 1 */
     722     return take_object(result);
     723   }
     724
     725 }
     726
     727
     728
     729
     730 /* Takes a domain_object, and returns the less specific domain of it */
     731 char * get_less_specific_domain(char *domain_object){
         /* [<][>][^][v][top][bottom][index][help] */
     732   bool code;
     733   char * search_key = NULL, * query_string = NULL;
     734   char * result = NULL, * domain = NULL;
     735   Object * o = new Object();
     736   int i,j, length;
     737   char * temp = NULL;
     738   char ** splitted;
     739
     740   code = o->scan_silent(domain_object, strlen(domain_object));
     741   domain = get_search_key(o,"domain",domain_object);
     742
     743   /* split the domain from its dots ('50' is the max # of pieces, this number is just arbitrary) */
     744   splitted =   g_strsplit((char *)strdup(domain), ".", 50);
     745
     746   for(i=1; splitted[i] != NULL; i++){
     747     /* in the following for loop, we will construct the 'less spec' domains
     748        to be looked up in the DB */
     749     for(j=i; splitted[j] !=NULL; j++){
     750       length = 0;
     751       if(temp!=NULL){
     752         length = strlen(temp);
     753       }
     754       temp = (char *)realloc(temp, length + strlen(splitted[j]) + 2);
     755       if(j==i){
     756         temp = (char *)strdup(splitted[j]);
     757       }else{
     758         sprintf(temp, "%s.%s", temp, splitted[j]);
     759       }
     760     }
     761     query_string = (char *)malloc(strlen("-Tdomain -r -R ")+strlen(temp)+1);
     762     sprintf(query_string, "-Tdomain -r -R %s", temp);
     763     result = send_and_get(query_host, query_port, query_string);
     764     if(count_objects(result) == 0){
     765     }else if(count_objects(result) > 1){
     766       if(tracing){
     767         cout << "TRACING: get_less_specific_domain: More than one domains returned" << endl;
     768       }
     769       return NULL; /* error condition */
     770     }else{ /* count_objects(result) == 1 */
     771       return take_object(result);
     772     }
     773
     774   }
     775   /* release the memory allocated to **splitted */
     776   for(i=0; splitted[i] != NULL; i++){
     777     free(splitted[i]);
     778   }
     779   /* so, we couldn't  find any 'less specific' domain */
     780   return NULL;
     781 }
     782
     783
     784
     785
     786
     787 /* Takes a hierarchical set_object, and returns the less specific set or auth-num of it
     788    by striping down the object's name ( eg, for as35:rs-trial:rs-myset,
     789    as35:rs-trial is tried ) */
     790 char * get_less_specific_set(char *set_object, char *type){
         /* [<][>][^][v][top][bottom][index][help] */
     791   bool code;
     792   char * search_key = NULL, * query_string = NULL;
     793   char * result = NULL;
     794   Object * o = new Object();
     795   int i;
     796
     797   code = o->scan_silent(set_object, strlen(set_object));
     798   search_key = get_search_key(o, type, set_object);
     799   delete(o);
     800
     801   for(i = strlen(search_key) -1; i > -1; i--){
     802     if(search_key[i] == ':'){
     803       search_key[i] = '\0'; /* truncate the string */
     804       break;
     805     }
     806     if(i == 0){/* if we've reached the beginning of the string
     807                 (this means there wasn't any ';' in the string) */
     808       free(search_key);
     809       search_key = NULL;
     810     }
     811   }
     812   if( search_key == NULL || strlen(search_key) == 0){/* this mustn't happen in fact, since
     813                                                         we make sure that the name of the
     814                                                         set_object contains a ':' in a proper place */
     815     return NULL;
     816   }
     817
     818
     819   query_string = (char *)malloc(strlen("-Taut-num,as-set,rtr-set,peering-set,filter-set -r ")+strlen(search_key)+1);
     820   sprintf(query_string, "-Taut-num,as-set,rtr-set,peering-set,filter-set -r  %s", search_key);
     821   result = send_and_get(query_host, query_port, query_string);
     822   if(count_objects(result) == 0){
     823     cout << "No such object"  << endl;
     824     return NULL;
     825   }else if(count_objects(result) > 1){
     826     cout << "More than one objects returned" << endl;
     827     return NULL;
     828   }else{ /* count_objects(result) == 1 */
     829     return take_object(result);
     830   }
     831
     832 }
     833
     834
     835
     836
     837
     838
     839
     840 /* Takes an inetnum or inet6num object and returns one less specific of it */
     841 char * get_less_specific(char *inetnum_object, char *type){
         /* [<][>][^][v][top][bottom][index][help] */
     842   bool code;
     843   char * search_key = NULL, * query_string = NULL;
     844   char * result = NULL;
     845   Object * o = new Object();
     846
     847   code = o->scan_silent(inetnum_object, strlen(inetnum_object));
     848   search_key = get_search_key(o, type, inetnum_object);
     849
     850   query_string = (char *)malloc(strlen("-Tinet6num -r -l ") + strlen(search_key) + 1);
     851   sprintf(query_string, "-T%s -r -l %s",type, search_key);
     852   result = send_and_get(query_host, query_port, query_string);
     853   if(count_objects(result) == 0){
     854     cout << "No such " << type << endl;
     855     return NULL;
     856   }else if(count_objects(result) > 1){
     857     cout << "More than one " << type << " returned" << endl;
     858     return NULL;
     859   }else{ /* count_objects(result) == 1 */
     860     return take_object(result);
     861   }
     862
     863 }
     864
     865
     866
     867 /* Takes a route object and returns one less specific inetnum */
     868 char * get_less_spec_inetnum(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     869   bool code;
     870   char * search_key = NULL, * query_string = NULL;
     871   char * result = NULL;
     872   Object * o = new Object();
     873
     874   code = o->scan_silent(route_object, strlen(route_object));
     875   search_key = get_search_key(o, "route", route_object);
     876
     877   query_string = (char *)malloc(strlen("-Tinetnum -r -l ") + strlen(search_key) + 1);
     878   sprintf(query_string, "-Tinetnum -r -l %s", search_key);
     879   result = send_and_get(query_host, query_port, query_string);
     880   if(count_objects(result) == 0){
     881     cout << "No such inetnum" << endl;
     882     return NULL;
     883   }else if(count_objects(result) > 1){
     884     cout << "More than one inetnums returned" << endl;
     885     return NULL;
     886   }else{ /* count_objects(result) == 1 */
     887     return take_object(result);
     888   }
     889
     890 }
     891
     892
     893 /* Takes a route object and returns exact match inetnum */
     894 char * get_exact_match_inetnum(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     895   bool code;
     896   char * search_key = NULL, * query_string = NULL;
     897   char * result = NULL;
     898   Object * o = new Object();
     899
     900   code = o->scan_silent(route_object, strlen(route_object));
     901   search_key = get_search_key(o, "route", route_object);
     902
     903   query_string = (char *)malloc(strlen("-Tinetnum -r -x ") + strlen(search_key) + 1);
     904   sprintf(query_string, "-Tinetnum -r -x %s", search_key);
     905   result = send_and_get(query_host, query_port, query_string);
     906   if(count_objects(result) == 0){
     907     cout << "No such inetnum" << endl;
     908     return NULL;
     909   }else if(count_objects(result) > 1){
     910     cout << "More than one inetnums returned" << endl;
     911     return NULL;
     912   }else{ /* count_objects(result) == 1 */
     913     return take_object(result);
     914   }
     915
     916 }
     917
     918
     919
     920 /* Takes a route object and returns exact matches of this route */
     921 GSList * get_exact_match_routes(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     922   bool code;
     923   char * search_key = NULL, * query_string = NULL;
     924   char * result = NULL;
     925   Object * o = new Object();
     926
     927   code = o->scan_silent(route_object, strlen(route_object));
     928   search_key = get_search_key(o, "route", route_object);
     929
     930   query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(search_key) + 1);
     931   sprintf(query_string, "-Troute -r -x %s", search_key);
     932   result = send_and_get(query_host, query_port, query_string);
     933   if(count_objects(result) == 0){
     934     //cout << "get_exact_match_routes: No such route" << endl;
     935     return NULL;
     936   }else{ /* count_objects(result) == 1 */
     937     return take_objects(result);
     938   }
     939
     940 }
     941
     942
     943
     944
     945
     946 /* Takes a route object and returns (immediate) less specifics of this route */
     947 GSList * get_less_spec_routes(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     948   bool code;
     949   char * search_key = NULL, * query_string = NULL;
     950   char * result = NULL;
     951   Object * o = new Object();
     952
     953   code = o->scan_silent(route_object, strlen(route_object));
     954   search_key = get_search_key(o, "route", route_object);
     955
     956   query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(search_key) + 1);
     957   sprintf(query_string, "-Troute -r -l %s", search_key);
     958   result = send_and_get(query_host, query_port, query_string);
     959   if(count_objects(result) == 0){
     960     cout << "get_less_spec_routes: No such route" << endl;
     961     return NULL;
     962   }else{ /* count_objects(result) == 1 */
     963     return take_objects(result);
     964   }
     965
     966 }
     967
     968
     969
     970 /* Gets an object as a string and returns its 'mnt-by' attributes as a
     971    GSList (linked list)   */
     972
     973 GSList *get_mntners(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     974   bool code;
     975   Object * o;
     976   Attr *attr;
     977   char *value  = NULL;
     978   GSList *list_of_mntners = NULL;
     979   char * object;
     980
     981   /* if there is no '\n' at the end of char * already, o->scan chokes. So, add it.
     982    (no harm in having more than one) */
     983   object = (char *)malloc(strlen(arg) + 2);
     984   sprintf(object, "%s\n", arg);
     985
     986   if(tracing) {
     987     printf("TRACING: get_mntners is running\n");
     988   }
     989   o = new Object;
     990   code = o->scan_silent(object,strlen(object));
     991
     992   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     993     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     994     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
     995         attr->len - strlen(attr->type->name()) -2 );
     996     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     997     if(strcmp(attr->type->name(),"mnt-by") == 0){
     998       if(tracing) {
     999         cout << "TRACING: get_mntners: adding " << g_strstrip(value) << endl;
    1000       }
    1001       list_of_mntners = g_slist_append(list_of_mntners, strdup(g_strstrip(value)));
    1002     }
    1003     free(value);
    1004   }
    1005
    1006   free(object);
    1007   return list_of_mntners;
    1008 }
    1009
    1010
    1011
    1012
    1013
    1014
    1015 /* Gets a preparsed object, its text and an attribute name. Returns a list of
    1016    attribute values */
    1017 GSList *get_attributes(Object * o, const char * attrib, const char * text){
         /* [<][>][^][v][top][bottom][index][help] */
    1018
    1019   char * value = NULL;
    1020   Attr *attr;
    1021   GSList *list_of_attributes = NULL;
    1022
    1023
    1024   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1025     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1026     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
    1027         attr->len - strlen(attr->type->name()) -2 );
    1028     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1029     if(strcmp(attr->type->name(), attrib) == 0){
    1030       if(tracing) {
    1031         cout << "TRACING: get_attributes: adding " << g_strstrip(value) << endl;
    1032       }
    1033       list_of_attributes = g_slist_append(list_of_attributes, g_strstrip(value));
    1034     }
    1035   }
    1036
    1037
    1038   return list_of_attributes;
    1039 }
    1040
    1041
    1042 /* Gets a preparsed object, an attribute name. Returns the value of first occurence
    1043    of this attribute */
    1044 char *get_attribute(Object * o, const char * attrib, char * text){
         /* [<][>][^][v][top][bottom][index][help] */
    1045
    1046   char * value = NULL;
    1047   Attr *attr;
    1048
    1049   if(tracing) {
    1050     printf("TRACING: get_attributes is running\n");
    1051   }
    1052
    1053   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1054     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1055     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
    1056         attr->len - strlen(attr->type->name()) -2 );
    1057     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1058     if(strcmp(attr->type->name(), attrib) == 0){
    1059       if(tracing) {
    1060         cout << "TRACING: get_attribute: will return " << value << endl;
    1061       }
    1062       return value;
    1063     }else{
    1064       free(value);
    1065     }
    1066   }
    1067
    1068   if(tracing) {
    1069     printf("TRACING: get_attribute is returning\n");
    1070   }
    1071
    1072   return NULL;
    1073 }
    1074
    1075
    1076
    1077 /* Gets a GSList of strings and returns 1 if one of them starts with substr, 0 otherwise */
    1078 int strstr_in_list(GSList * list, const char * substr){
         /* [<][>][^][v][top][bottom][index][help] */
    1079
    1080  GSList * next = NULL;
    1081  char * word;
    1082
    1083   if(tracing) {
    1084     printf("TRACING: strstr_in_list is running\n");
    1085   }
    1086
    1087  for( next = list; next != NULL ; next = g_slist_next(next) ){
    1088    word = strdup((char *)next->data);
    1089    g_strup(word);
    1090    if(strstr(word, substr) == word){
    1091      free(word);
    1092      return 1;
    1093    }
    1094    free(word);
    1095  }
    1096  /* none of them matched, so return 0 */
    1097  return 0;
    1098 }
    1099
    1100
    1101
    1102
    1103
    1104 /* Gets a (maintainer) object as a string and returns its 'auth' attributes
    1105    as a GSList (linked list) */
    1106
    1107 GSList *get_auths(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1108   bool code;
    1109   Object * o;
    1110   Attr *attr;
    1111   char *value  = NULL;
    1112   GSList *list_of_auths = NULL;
    1113
    1114   if(tracing){
    1115     printf("TRACING: get_auths is running\n");
    1116   }
    1117   o = new Object;
    1118   code = o->scan_silent(object,strlen(object));
    1119
    1120   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1121     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1122     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1123         attr->len - strlen(attr->type->name()) -2 );
    1124     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1125     if(strcmp(attr->type->name(),"auth") == 0){
    1126       if(tracing) {
    1127         cout << "TRACING: get_auths: adding " << g_strstrip(value) << endl;
    1128       }
    1129       list_of_auths = g_slist_append(list_of_auths, strdup(g_strstrip(value)));
    1130       if(tracing) {
    1131         cout << "TRACING: get_auths: # of nodes in list_of_auths is now " << g_slist_length(list_of_auths) << endl;
    1132       }
    1133     }
    1134   }
    1135
    1136   if(tracing) {
    1137     cout << "TRACING: get_auths: returning (with " << g_slist_length(list_of_auths) << " nodes)" << endl;
    1138   }
    1139   return list_of_auths;
    1140 }
    1141
    1142
    1143
    1144
    1145 /* Gets an object as a string an returns its 'attr_type' attributes as a
    1146    GSList (linked list) */
    1147
    1148 GSList *get_attr_list(char * arg, char * attr_type){
         /* [<][>][^][v][top][bottom][index][help] */
    1149   bool code;
    1150   Object * o;
    1151   Attr *attr;
    1152   char *value  = NULL;
    1153   GSList *list_of_attrs = NULL;
    1154   char * object;
    1155
    1156   /* if there is no '\n' at the end of char * already, o->scan chokes. So, add it.
    1157    (no harm in having more than one) */
    1158   object = (char *)malloc(strlen(arg) + 2);
    1159   sprintf(object, "%s\n", arg);
    1160
    1161   if(tracing) {
    1162     printf("TRACING: get_attr_list is running, object is \n#%s#\n", object);
    1163   }
    1164   o = new Object;
    1165   code = o->scan_silent(object,strlen(object));
    1166
    1167   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1168     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1169     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1170         attr->len - strlen(attr->type->name()) -2 );
    1171     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1172     if(strcmp(attr->type->name(), attr_type) == 0){
    1173       if(tracing) {
    1174         cout << "TRACING: get_attr_list: adding " << g_strstrip(value) << endl;
    1175       }
    1176       list_of_attrs = g_slist_append(list_of_attrs, g_strstrip(value));
    1177     }
    1178   }
    1179
    1180   free(object);
    1181   return list_of_attrs;
    1182 }
    1183
    1184
    1185
    1186
    1187
    1188
    1189 /* Gets an object as a string an returns its mnt_lower attributes as a
    1190    GSList (linked list) */
    1191
    1192 GSList *get_mnt_lowers(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1193   bool code;
    1194   Object * o;
    1195   Attr *attr;
    1196   char *value  = NULL;
    1197   GSList *list_of_mnt_lowers = NULL;
    1198
    1199
    1200   if(tracing) {
    1201     printf("TRACING: get_mnt_lowers is running\n");
    1202   }
    1203   o = new Object;
    1204   code = o->scan_silent(object,strlen(object));
    1205
    1206   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1207     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1208     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1209         attr->len - strlen(attr->type->name()) -2 );
    1210     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1211     if(strcmp(attr->type->name(),"mnt-lower") == 0){
    1212       if(tracing) {
    1213         cout << "TRACING: get_mnt_lowers: adding " << g_strstrip(value) << endl;
    1214       }
    1215       list_of_mnt_lowers = g_slist_append(list_of_mnt_lowers, strdup(g_strstrip(value)));
    1216     }
    1217   }
    1218
    1219
    1220   return list_of_mnt_lowers;
    1221 }
    1222
    1223
    1224 /* Gets an object as a string an returns its mnt_routes attributes as a
    1225    GSList (linked list) */
    1226
    1227 GSList *get_mnt_routes(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1228   bool code;
    1229   Object * o;
    1230   Attr *attr;
    1231   char *value  = NULL;
    1232   GSList *list_of_mnt_routes = NULL;
    1233
    1234   if(tracing) {
    1235   cout << "TRACING: get_mnt_routes is running" << endl;
    1236   }
    1237   o = new Object;
    1238   code = o->scan_silent(object,strlen(object));
    1239
    1240   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1241     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1242     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1243         attr->len - strlen(attr->type->name()) -2 );
    1244     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1245     if(strcmp(attr->type->name(),"mnt-routes") == 0){
    1246       if(tracing) {
    1247         cout << "TRACING: get_mnt_routes: adding " << g_strstrip(value) << endl;
    1248       }
    1249       list_of_mnt_routes = g_slist_append(list_of_mnt_routes, strdup(g_strstrip(value)));
    1250     }
    1251   }
    1252
    1253   return list_of_mnt_routes;
    1254 }
    1255
    1256
    1257 /* Gets a linked list of objects and returns the mnt_routes attribs of
    1258    them in a linked list */
    1259 GSList *get_mnt_routes_from_list(GSList * objects){
         /* [<][>][^][v][top][bottom][index][help] */
    1260   GSList *next = NULL;
    1261   GSList *list_of_mnt_routes = NULL;
    1262
    1263   for( next = objects; next != NULL ; next = g_slist_next(next) ){
    1264     list_of_mnt_routes = g_slist_concat(list_of_mnt_routes, get_mnt_routes((char *)next->data));
    1265   }
    1266
    1267   return list_of_mnt_routes;
    1268 }
    1269
    1270
    1271
    1272 /* Gets a linked list of objects and returns the mnt_routes attribs of
    1273    them in a linked list */
    1274 GSList *get_mnt_lowers_from_list(GSList * objects){
         /* [<][>][^][v][top][bottom][index][help] */
    1275   GSList *next = NULL;
    1276   GSList *list_of_mnt_lowers = NULL;
    1277
    1278   for( next = objects; next != NULL ; next = g_slist_next(next) ){
    1279     list_of_mnt_lowers = g_slist_concat(list_of_mnt_lowers, get_mnt_lowers((char *)next->data));
    1280   }
    1281
    1282   return list_of_mnt_lowers;
    1283 }
    1284
    1285
    1286
    1287 /* retrieves the override password from the 'override' attribute
    1288    of the object. If none, it returns NULL   */
    1289 char *get_override(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1290   bool code;
    1291   Object * o;
    1292   Attr *attr;
    1293   char *value  = NULL;
    1294
    1295   if(tracing){
    1296     printf("TRACING: get_override is running\n");
    1297   }
    1298   o = new Object;
    1299   code = o->scan_silent(object,strlen(object));
    1300
    1301   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1302     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1303     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1304         attr->len - strlen(attr->type->name()) -2 );
    1305     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1306     if(strcmp(attr->type->name(),"override") == 0){
    1307       if(tracing) {
    1308         cout << "TRACING: get_override: returning " << g_strstrip(value) << endl;
    1309       }
    1310       return  strdup(g_strstrip(value));
    1311     }
    1312   }
    1313   /* there was no 'override' attrib, so return NULL */
    1314   return NULL;
    1315 }
    1316
    1317
    1318
    1319
    1320
    1321
    1322 /* checks override string (password)
    1323    returns OVR_OK if it is correct password */
    1324 int check_override(char * string){
         /* [<][>][^][v][top][bottom][index][help] */
    1325    char ** temp;
    1326    int i;
    1327    char * crypted_password = strdup(overridecryptedpw);
    1328    if(string == NULL) {
    1329      if(tracing) {
    1330        printf("TRACING: check_override is returning FAILED\n");
    1331      }
    1332      return UP_OVF; /* override attempt failed */
    1333    }else{
    1334     /* split the string */
    1335      temp = g_strsplit (string, " ", 0);
    1336
    1337      for(i=0; temp[i] != NULL; i++){
    1338        if(strlen(temp[i]) != 0){
    1339          if(strcmp(AU_crypt(temp[i], crypted_password), crypted_password) == 0){
    1340            g_strfreev(temp);
    1341            if(tracing) {
    1342              printf("TRACING: check_override is returning OK\n", string);
    1343            }
    1344            return OVR_OK;
    1345          }
    1346        }
    1347      }
    1348
    1349      g_strfreev(temp);
    1350      /* we couldn't find a word matching the override password */
    1351           return UP_OVF; /* override attempt failed */
    1352    }
    1353 }
    1354
    1355
    1356
    1357
    1358
    1359
    1360
    1361
    1362
    1363
    1364
    1365
    1366 /* takes a GSList of struct auth_struct and a GSList of auths, and a mntner name,
    1367    add new elements to GSList of struct auth_struct and  returns the new
    1368    GSList of struct auth_struct  */
    1369
    1370 GSList * add_to_auth_vector(GSList * list_of_auth_struct, GSList * auths, char * mntner_name){
         /* [<][>][^][v][top][bottom][index][help] */
    1371    GSList * next;
    1372    char * auth_attrib = NULL;
    1373    char * auth_attrib_uppercase = NULL, * argument = NULL;
    1374    auth_struct * temp = NULL;
    1375    int index = 1;
    1376
    1377    for(next = auths; next != NULL; next = g_slist_next(next)){
    1378      auth_attrib = strdup((char *)next->data);
    1379      auth_attrib = g_strstrip(auth_attrib);
    1380      if(tracing) {
    1381        cout << "TRACING: add_to_auth_vector: " << auth_attrib << endl;
    1382      }
    1383      /* Take the auth attribute and convert it into uppercase for comparisons */
    1384      auth_attrib_uppercase = strdup(auth_attrib);
    1385      g_strup(auth_attrib_uppercase);
    1386
    1387      if(strstr(auth_attrib_uppercase,"CRYPT-PW") == auth_attrib_uppercase){
    1388        /* take the argument of the auth attribute */
    1389        argument = strdup(auth_attrib + strlen("CRYPT-PW"));
    1390        g_strstrip(argument);
    1391        if(tracing) {
    1392          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1393        }
    1394        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1395        temp->type = AU_CRYPT_PW;
    1396        temp->auth = argument;
    1397        temp->mntner_name = mntner_name;
    1398        temp->index = index++;
    1399        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1400      }else if(strstr(auth_attrib_uppercase,"MAIL-FROM") == auth_attrib_uppercase){
    1401        /* take the argument of the auth attribute */
    1402        argument = strdup(auth_attrib + strlen("MAIL-FROM"));
    1403        g_strstrip(argument);
    1404        if(tracing) {
    1405          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1406        }
    1407        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1408        temp->type = AU_MAIL_FROM;
    1409        temp->auth = argument;
    1410        temp->mntner_name = mntner_name;
    1411        temp->index = index++;
    1412        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1413      }else if(strstr(auth_attrib_uppercase,"NONE") == auth_attrib_uppercase){
    1414        /* take the argument of the auth attribute */
    1415        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1416        temp->type = AU_NONE;
    1417        temp->auth = NULL;
    1418        temp->mntner_name = mntner_name;
    1419        temp->index = index++;
    1420        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1421     }else if(strstr(auth_attrib_uppercase,"PGPKEY-") == auth_attrib_uppercase){
    1422        argument = strdup(auth_attrib + strlen("PGPKEY-"));
    1423        g_strstrip(argument);
    1424        if(tracing) {
    1425          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1426        }
    1427        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1428        temp->type = AU_PGP;
    1429        temp->mntner_name = mntner_name;
    1430        temp->index = index++;
    1431        temp->auth = argument;
    1432        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1433      }else{
    1434        if(tracing){
    1435          cout << "TRACING: Error: invalid auth attrib: " << auth_attrib << endl;
    1436        }
    1437        return NULL;
    1438      }
    1439    }
    1440    free(auth_attrib_uppercase);
    1441    free(auth_attrib);
    1442    return list_of_auth_struct;
    1443
    1444 }
    1445
    1446
    1447
    1448
    1449
    1450
    1451
    1452
    1453
    1454 /* Gets a list of mntner names, retrieves those mntners from
    1455    the database and extracts the 'auth' attributes, and
    1456    constructs the authorisation vector, which is a GSList of
    1457    struct auth_struct */
    1458
    1459 GSList * get_auth_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1460   GSList * list_of_auths = NULL;
    1461   GSList * next = NULL;
    1462   GSList * to_be_returned = NULL;
    1463   char * query_string = NULL, * result = NULL, * object = NULL;
    1464   GSList * temp;
    1465
    1466   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1467     if(tracing) {
    1468       cout << "=====" << endl << "Got a mntner" << endl;
    1469       cout << (char *)next->data << endl;
    1470     }
    1471     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1472     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1473     result = send_and_get(query_host, query_port, query_string);
    1474     if(count_objects(result) == 0){
    1475       /* no such maintainer */
    1476       return NULL;
    1477     }else if(count_objects(result) > 1){
    1478       if(tracing) {
    1479         cout << "More than one objects returned" << endl;
    1480       }
    1481     }else{ /* count_objects(result) == 1 */
    1482       object = take_object(result);
    1483       if(tracing) {
    1484         printf("TRACING: get_auth_vector: Calling get_auths(char *)\n");
    1485       }
    1486       temp = get_auths(object);
    1487       if(tracing) {
    1488         cout << "TRACING: get_auth_vector: get_auths(char *) returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1489       }
    1490       list_of_auths = g_slist_concat(list_of_auths, temp);
    1491       if(tracing) {
    1492         cout << "TRACING: get_auth_vector: list_of_auths has now " <<  g_slist_length(list_of_auths) << " nodes" << endl;
    1493       }
    1494       /* add this to the auth_vector. ( next->data is the name of the maintainer  ) */
    1495       if(tracing) {
    1496        cout << "TRACING: get_auth_vector: to_be_returned has now " <<  g_slist_length(to_be_returned) << " nodes" << endl;
    1497       }
    1498       to_be_returned = add_to_auth_vector(to_be_returned, list_of_auths, (char *)next->data);
    1499     }
    1500   }
    1501
    1502   if(tracing) {
    1503     printf("TRACING: get_auth_vector: to_be_returned has %i nodes\n", g_slist_length(to_be_returned));
    1504   }
    1505   return to_be_returned;
    1506 }
    1507
    1508
    1509
    1510
    1511
    1512
    1513
    1514 /* Gets a list of mntner names, retrieves those mntners from
    1515    the database and extracts the 'mnt-by' attributes, and
    1516    returns them as a GSList */
    1517
    1518 GSList * get_mntnfy_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1519   GSList * list_of_mntnfy = NULL;
    1520   GSList * next = NULL;
    1521   //GSList * to_be_returned = NULL;
    1522   char * query_string = NULL, * result = NULL, * object = NULL;
    1523   GSList * temp;
    1524
    1525   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1526     if(tracing) {
    1527       cout << "=====" << endl << "Got a mntner" << endl;
    1528       cout << (char *)next->data << endl;
    1529     }
    1530     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1531     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1532     result = send_and_get(query_host, query_port, query_string);
    1533     if(count_objects(result) == 0){
    1534       /* no such maintainer */
    1535     }else if(count_objects(result) > 1){
    1536       if(tracing) {
    1537         cout << "More than one objects returned" << endl;
    1538       }
    1539     }else{ /* count_objects(result) == 1 */
    1540       object = take_object(result);
    1541       if(tracing) {
    1542         printf("TRACING: get_mntnfy_vector: Calling get_attr_list\n");
    1543       }
    1544       temp = get_attr_list(object, "mnt-nfy");
    1545       if(tracing) {
    1546         cout << "TRACING: get_mntnfy_vector: get_attr_list returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1547       }
    1548       list_of_mntnfy = g_slist_concat(list_of_mntnfy, temp);
    1549       if(tracing) {
    1550         cout << "TRACING: get_mntnfy_vector: list_of_mntnfy has now " <<  g_slist_length(list_of_mntnfy) << " nodes" << endl;
    1551       }
    1552     }
    1553   }
    1554
    1555   if(tracing) {
    1556     printf("TRACING: get_auth_vector: list_of_mntnfy has %i nodes\n", g_slist_length(list_of_mntnfy));
    1557   }
    1558   return list_of_mntnfy;
    1559 }
    1560
    1561
    1562
    1563
    1564
    1565
    1566 /* Gets a list of mntner names, retrieves those mntners from
    1567    the database and extracts the 'upd-to' attributes, and
    1568    returns them as a GSList */
    1569
    1570 GSList * get_updto_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1571   GSList * list_of_updto = NULL;
    1572   GSList * next = NULL;
    1573   char * query_string = NULL, * result = NULL, * object = NULL;
    1574   GSList * temp;
    1575
    1576   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1577     if(tracing) {
    1578       cout << "=====" << endl << "Got a mntner" << endl;
    1579       cout << (char *)next->data << endl;
    1580     }
    1581     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1582     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1583     result = send_and_get(query_host, query_port, query_string);
    1584     if(count_objects(result) == 0){
    1585       /* no such maintainer */
    1586     }else if(count_objects(result) > 1){
    1587       if(tracing) {
    1588         cout << "More than one objects returned" << endl;
    1589       }
    1590     }else{ /* count_objects(result) == 1 */
    1591       object = take_object(result);
    1592       if(tracing) {
    1593         printf("TRACING: get_mntnfy_vector: Calling get_attr_list\n");
    1594       }
    1595       temp = get_attr_list(object, "upd-to");
    1596       if(tracing) {
    1597         cout << "TRACING: get_updto_vector: get_attr_list returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1598       }
    1599       list_of_updto = g_slist_concat(list_of_updto, temp);
    1600       if(tracing) {
    1601         cout << "TRACING: get_updto_vector: list_of_mntnfy has now " <<  g_slist_length(list_of_updto) << " nodes" << endl;
    1602       }
    1603     }
    1604   }
    1605
    1606   if(tracing) {
    1607     printf("TRACING: get_updto_vector: list_of_updto has %i nodes\n", g_slist_length(list_of_updto));
    1608   }
    1609   return list_of_updto;
    1610 }
    1611
    1612
    1613
    1614
    1615
    1616
    1617
    1618
    1619
    1620
    1621 /* gets one or more route objects filters out the ones which don't have the same
    1622    origin as 'char * origin' argument */
    1623 char * filter_out_diff_origins(char * objects, char * origin){
         /* [<][>][^][v][top][bottom][index][help] */
    1624   GSList * object_list = NULL, * next =NULL;
    1625   char * objects_to_be_returned = NULL;
    1626   bool code;
    1627   char * key = NULL;
    1628   Object * o = new Object();
    1629
    1630
    1631   if(tracing) {
    1632     printf("TRACING: filter_out_diff_origins\n");
    1633   }
    1634
    1635   /* strip the lines beginning with '%' off */
    1636   objects = strip_lines(objects);
    1637
    1638   /* separate the objects, store them in a linked list */
    1639   object_list = take_objects(objects);
    1640
    1641   for(next = object_list; next != NULL; next = g_slist_next(next)){
    1642     code = o->scan_silent((char *)next->data, strlen((char *)next->data));
    1643     key = get_search_key(o, "origin", (char *)next->data);
    1644     if(key != NULL && strcasecmp(g_strstrip(origin), key) == 0){
    1645       if(objects_to_be_returned == NULL){
    1646         objects_to_be_returned = strdup((char *)next->data);
    1647       }else{
    1648         objects_to_be_returned = (char *)realloc(objects_to_be_returned,
    1649                       strlen(objects_to_be_returned) + strlen((char *)next->data) + 2);
    1650         objects_to_be_returned = strcat(objects_to_be_returned, "\n");
    1651         objects_to_be_returned = strcat(objects_to_be_returned, (char *)next->data);
    1652       }
    1653     }
    1654   }
    1655
    1656   delete(o);
    1657   if(tracing) {
    1658     if(objects_to_be_returned != NULL){
    1659       printf("TRACING: filter_out_diff_origins: returning:\n%s\n", objects_to_be_returned? "(NULL)":objects_to_be_returned);
    1660     }else {
    1661       printf("TRACING: filter_out_diff_origins: returning NULL\n");
    1662
    1663     }
    1664   }
    1665   return objects_to_be_returned;
    1666
    1667 }
    1668
    1669
    1670
    1671
    1672
    1673
    1674
    1675
    1676 /* gets one or more route objects, filters out the ones which have the same
    1677    origin as 'char * origin' argument */
    1678 char * filter_out_same_origins(char * objects, char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1679   GSList * object_list = NULL, * next =NULL;
    1680   char * objects_to_be_returned = NULL;
    1681   bool code;
    1682   char * key = NULL;
    1683   Object * o = new Object();
    1684   Object * o2 = new Object();
    1685   char * origin;
    1686
    1687
    1688   if(tracing) {
    1689     printf("TRACING: filter_out_diff_origins\n");
    1690   }
    1691
    1692   code = o2->scan_silent(object, strlen(object));
    1693   origin = get_search_key(o2, "origin", object);
    1694
    1695
    1696   /* strip the lines beginning with '%' off */
    1697   objects = strip_lines(objects);
    1698
    1699   /* separate the objects, store them in a linked list */
    1700   object_list = take_objects(objects);
    1701
    1702   for(next = object_list; next != NULL; next = g_slist_next(next)){
    1703     code = o->scan_silent((char *)next->data, strlen((char *)next->data));
    1704     key = get_search_key(o, "origin", (char *)next->data);
    1705     if(key != NULL && strcasecmp(g_strstrip(origin), key) != 0){
    1706       if(objects_to_be_returned == NULL){
    1707         objects_to_be_returned = strdup((char *)next->data);
    1708       }else{
    1709         objects_to_be_returned = (char *)realloc(objects_to_be_returned,
    1710                       strlen(objects_to_be_returned) + strlen((char *)next->data) + 2);
    1711         objects_to_be_returned = strcat(objects_to_be_returned, "\n");
    1712         objects_to_be_returned = strcat(objects_to_be_returned, (char *)next->data);
    1713       }
    1714     }
    1715   }
    1716
    1717   delete(o);
    1718   if(tracing) {
    1719     if(objects_to_be_returned != NULL){
    1720       printf("TRACING: filter_out_same_origins: returning:\n%s\n", objects_to_be_returned? "(NULL)":objects_to_be_returned);
    1721     }else {
    1722       printf("TRACING: filter_out_same_origins: returning NULL\n");
    1723
    1724     }
    1725   }
    1726   return objects_to_be_returned;
    1727
    1728 }
    1729
    1730
    1731
    1732
    1733
    1734
    1735
    1736
    1737 /* Check authorisation
    1738    Applies authorisation rules according to the object type
    1739
    1740    Arguments:
    1741       char *new_object: the new object,
    1742       char *old_object: the old object, as found in the database,
    1743       char *type: type of the object
    1744       credentials_struct credentials: a struct which
    1745         contains credentials of the update, such as 'From:' field of
    1746         the e-mail header and passwords in the update   */
    1747
    1748 int check_auth(char *new_object, char *old_object, char *type, credentials_struct credentials){
         /* [<][>][^][v][top][bottom][index][help] */
    1749
    1750    GSList *old_mntners = NULL, *new_mntners = NULL;
    1751    GSList *old_auths = NULL, *new_auths = NULL;
    1752    GSList *as_block_mnt_lowers = NULL;
    1753    GSList *old_auth_vector = NULL, *new_auth_vector = NULL, *as_block_auth_vector = NULL;
    1754    GSList *less_specific_auth_vector = NULL, *less_specific_mnt_lowers = NULL;
    1755    GSList *less_specific_mntners = NULL;
    1756    GSList *aut_num_maintainers = NULL;
    1757    GSList *aut_num_auth_vector = NULL;
    1758    GSList *exact_match_routes = NULL;
    1759    GSList *exact_match_routes_maintainers = NULL;
    1760    GSList *exact_match_routes_auth_vector = NULL;
    1761    GSList *less_spec_routes = NULL;
    1762    GSList *less_spec_routes_mntners = NULL;
    1763    GSList *less_spec_routes_auth_vector = NULL;
    1764    GSList *exact_match_inetnum_mnt_routes = NULL;
    1765    GSList *exact_match_inetnum_auth_vector = NULL;
    1766    GSList *less_spec_inetnum_mntners = NULL;
    1767    GSList *less_spec_inetnum_auth_vector = NULL;
    1768    GSList *exact_match_intenum_auth_vector = NULL;
    1769    GSList *exact_match_auth_vector = NULL;
    1770
    1771    GSList *old_name = NULL;
    1772    GSList *new_name = NULL;
    1773
    1774    char *as_block_object = NULL, *less_specific_object = NULL;
    1775    char *less_specific_domain = NULL;
    1776    char *less_spec_inetnum = NULL;
    1777    char *exact_match_inetnum = NULL;
    1778    char *less_specific_object_type = NULL;
    1779    char *override_string = NULL;
    1780    char *set_name = NULL;
    1781    char * aut_num_object = NULL;
    1782    char * name_old = NULL;
    1783    char * name_new = NULL;
    1784    Object *set_object = new Object();
    1785    Object *temp_obj;
    1786    bool code;
    1787    bool aut_num_auth_OK = false;
    1788
    1789    int overriden = 0;
    1790
    1791    /* first check if it is overriden or not. if overriden, check the override
    1792       password. If it is correct, continue, setting "overriden" to 1. If not,
    1793       immediately exit returning ERR_UP_OVF                                   */
    1794    override_string = get_override((new_object == NULL) ? old_object : new_object );
    1795    if(override_string == NULL){
    1796      overriden = 0;
    1797    }else if(check_override(override_string) == OVR_OK){
    1798      overriden = 1; /* authorisation is overriden */
    1799      free(override_string);override_string = NULL;
    1800    }else if(check_override(override_string) == UP_OVS){
    1801      free(override_string);override_string = NULL;
    1802      return UP_OVS; /* override syntax error --it must have at least two words */
    1803    }else{
    1804      free(override_string);override_string = NULL;
    1805      return UP_OVF; /* override failed! */
    1806    }
    1807
    1808
    1809    /*
    1810     *  Handle the "person", "role", "limerick", "inet-rtr", "key-cert" types
    1811     */
    1812    if(strcmp(type,"person")   == 0 || strcmp(type,"role")     == 0 ||
    1813       strcmp(type,"limerick") == 0 || strcmp(type,"inet-rtr") == 0 ||
    1814       strcmp(type,"key-cert") == 0 ){
    1815      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1816        old_mntners = get_mntners(old_object);
    1817        old_auth_vector = get_auth_vector(old_mntners);
    1818        return authorise(old_auth_vector, credentials, overriden);
    1819      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1820        new_mntners = get_mntners(new_object);
    1821        new_auth_vector = get_auth_vector(new_mntners);
    1822        if(new_mntners != NULL && new_auth_vector == NULL){
    1823          /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1824          return UP_AUF; /* auth failed */
    1825        }
    1826        return authorise(new_auth_vector, credentials, overriden);
    1827      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1828        /* check name change of person */
    1829        if(strcmp(type,"person") == 0){
    1830          old_name = get_attr_list(old_object, "person");
    1831          new_name = get_attr_list(new_object, "person");
    1832          if(old_name != NULL && new_name != NULL
    1833              && g_slist_nth(old_name, 0) != NULL && g_slist_nth(new_name, 0) != NULL
    1834              && (g_slist_nth(old_name, 0)->data) != NULL
    1835              && (g_slist_nth(new_name, 0)->data) != NULL)
    1836            {
    1837
    1838            name_old = strdup((char *)(g_slist_nth(old_name, 0)->data));
    1839            name_new = strdup((char *)(g_slist_nth(new_name, 0)->data));
    1840            if(!identical(name_old, name_new)){
    1841              return UP_AUF; /* names were different!  (XXX return a proper error code here!) */
    1842            }
    1843
    1844          }else{
    1845            return UP_INT; /* there was a problem with obtaining the name of person obj */
    1846          }
    1847        }
    1848
    1849        /* check name change of role */
    1850        if(strcmp(type,"role") == 0){
    1851          old_name = get_attr_list(old_object, "role");
    1852          new_name = get_attr_list(new_object, "role");
    1853          if(old_name != NULL && new_name != NULL
    1854              && g_slist_nth(old_name, 0) != NULL && g_slist_nth(new_name, 0) != NULL
    1855              && (g_slist_nth(old_name, 0)->data) != NULL
    1856              && (g_slist_nth(new_name, 0)->data) != NULL)
    1857            {
    1858
    1859            name_old = strdup((char *)(g_slist_nth(old_name, 0)->data));
    1860            name_new = strdup((char *)(g_slist_nth(new_name, 0)->data));
    1861            if(!identical(name_old, name_new)){
    1862              return UP_AUF; /* names were different! */
    1863            }
    1864
    1865          }else{
    1866            return UP_INT; /* there was a problem with obtaining the name of role obj */
    1867          }
    1868        }
    1869
    1870        old_mntners = get_mntners(old_object);
    1871        old_auth_vector = get_auth_vector(old_mntners);
    1872        if(old_mntners != NULL && old_auth_vector == NULL){
    1873          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1874          return UP_AUF; /* auth failed */
    1875        }
    1876        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1877          return authorise(old_auth_vector, credentials, overriden);
    1878        }else{
    1879          new_mntners = get_mntners(new_object);
    1880          new_auth_vector = get_auth_vector(new_mntners);
    1881          if(new_mntners != NULL && new_auth_vector == NULL){
    1882            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1883            return UP_AUF; /* auth failed */
    1884          }
    1885          return authorise(new_auth_vector, credentials, overriden);
    1886        }
    1887      }else{ // both are NULL, mustn't happen
    1888          if(tracing){
    1889            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1890          }
    1891          return UP_INT; /* internal error */
    1892      }
    1893    }
    1894
    1895    /*
    1896     *  Handle the "aut-num" type
    1897     */
    1898    else if(strcmp(type,"aut-num")  == 0 ){
    1899      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1900        old_mntners = get_mntners(old_object);
    1901        old_auth_vector = get_auth_vector(old_mntners);
    1902        if(old_mntners != NULL && old_auth_vector == NULL){
    1903          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1904          return UP_AUF; /* auth failed */
    1905        }
    1906        return authorise(old_auth_vector, credentials, overriden);
    1907      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1908        as_block_object = get_as_block(new_object);
    1909        if(as_block_object == NULL ){
    1910          return UP_ABN; /* As-block does not exist */
    1911          }else{
    1912            as_block_mnt_lowers = get_mnt_lowers(as_block_object);
    1913            as_block_auth_vector = get_auth_vector(as_block_mnt_lowers);
    1914            if(as_block_mnt_lowers != NULL && as_block_auth_vector == NULL){
    1915              /* then, the mntners in 'as_block_mnt_lowers' do not exist. Problem. */
    1916              return UP_AUF; /* auth failed */
    1917            }
    1918          if(authorise(as_block_auth_vector, credentials, overriden) == UP_AUTH_OK ){
    1919            new_mntners = get_mntners(new_object);
    1920            new_auth_vector = get_auth_vector(new_mntners);
    1921            if(new_mntners != NULL && new_auth_vector == NULL){
    1922              /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1923              return UP_AUF; /* auth failed */
    1924            }
    1925            return authorise(new_auth_vector, credentials, overriden);
    1926          }else{
    1927            return UP_HOF; /* hierarchical auth failed */
    1928          }
    1929        }
    1930      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1931        old_mntners = get_mntners(old_object);
    1932        old_auth_vector = get_auth_vector(old_mntners);
    1933        if(old_mntners != NULL && old_auth_vector == NULL){
    1934          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1935          return UP_AUF; /* auth failed */
    1936        }
    1937        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1938          return authorise(old_auth_vector, credentials, overriden);
    1939        }else{
    1940          new_mntners = get_mntners(new_object);
    1941          new_auth_vector = get_auth_vector(new_mntners);
    1942          if(new_mntners != NULL && new_auth_vector == NULL){
    1943            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1944            return UP_AUF; /* auth failed */
    1945          }
    1946          return authorise(new_auth_vector, credentials, overriden);
    1947        }
    1948      }else{ /* both are NULL, mustn't happen */
    1949          if(tracing) {
    1950            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1951          }
    1952          return UP_INT; /* internal error */
    1953      }
    1954    }
    1955
    1956    /*
    1957     *  Handle the "mntner/as-block" types
    1958     */
    1959    else if(strcmp(type,"mntner")  == 0 || strcmp(type,"as-block")  == 0 ){
    1960      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1961        old_mntners = get_mntners(old_object);
    1962        old_auth_vector = get_auth_vector(old_mntners);
    1963        if(old_mntners != NULL && old_auth_vector == NULL){
    1964          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1965          return UP_AUF; /* auth failed */
    1966        }
    1967        return authorise(old_auth_vector, credentials, overriden);
    1968      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1969        if(overriden || test_mode){
    1970          return UP_AUTH_OK;
    1971        }else{/* If not overriden, must be forwarded to <HUMAILBOX> */
    1972          if(tracing) {
    1973            cout << "TRACING: check_auth: '" << type << "' creation requested" << endl;
    1974          }
    1975          return UP_FWD; /* must be forwarded to <HUMAILBOX> */
    1976        }
    1977      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1978        old_mntners = get_mntners(old_object);
    1979        old_auth_vector = get_auth_vector(old_mntners);
    1980        if(old_mntners != NULL && old_auth_vector == NULL){
    1981          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1982          return UP_AUF; /* auth failed */
    1983        }
    1984        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1985          return authorise(old_auth_vector, credentials, overriden);
    1986        }else{
    1987          new_mntners = get_mntners(new_object);
    1988          new_auth_vector = get_auth_vector(new_mntners);
    1989          if(new_mntners != NULL && new_auth_vector == NULL){
    1990            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1991            return UP_AUF; /* auth failed */
    1992          }
    1993          return authorise(new_auth_vector, credentials, overriden);
    1994        }
    1995      }else{ // both are NULL, mustn't happen
    1996          if(tracing){
    1997            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1998          }
    1999          return UP_INT; /* internal error */
    2000      }
    2001    }
    2002
    2003    /*
    2004     *  Handle the "inetnum/inet6num" types
    2005     */
    2006    else if(strcmp(type,"inetnum")  == 0 || strcmp(type,"inet6num")  == 0 ){
    2007      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    2008        old_mntners = get_mntners(old_object);
    2009        old_auth_vector = get_auth_vector(old_mntners);
    2010        if(old_mntners != NULL && old_auth_vector == NULL){
    2011          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    2012          return UP_AUF; /* auth failed */
    2013        }
    2014        return authorise(old_auth_vector, credentials, overriden);
    2015      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    2016        less_specific_object = get_less_specific(new_object, type);
    2017        if(less_specific_object == NULL){
    2018          if(overriden){
    2019            return UP_AUTH_OK;
    2020          }else{
    2021            return UP_HOF; /* hierarchical authorisation failed */
    2022          }
    2023        }else{ /* if we got an inet(6)num object */
    2024          less_specific_mnt_lowers = get_mnt_lowers(less_specific_object);
    2025          less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    2026          if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    2027            /* then, the mntners in 'less_specific_mnt_lowers' do not exist. Problem. */
    2028            return UP_AUF; /* auth failed */
    2029          }
    2030          if(authorise(less_specific_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2031            new_mntners = get_mntners(new_object);
    2032            new_auth_vector = get_auth_vector(new_mntners);
    2033            if(new_mntners != NULL && new_auth_vector == NULL){
    2034              /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2035              return UP_AUF; /* auth failed */
    2036            }
    2037            return authorise(new_auth_vector, credentials, overriden);
    2038          }else{
    2039            return UP_HOF; /* hierarchical authorisation failed */
    2040          }
    2041        }
    2042      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    2043        old_mntners = get_mntners(old_object);
    2044        old_auth_vector = get_auth_vector(old_mntners);
    2045        if(old_mntners != NULL && old_auth_vector == NULL){
    2046          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    2047          return UP_AUF; /* auth failed */
    2048        }
    2049        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    2050          return authorise(old_auth_vector, credentials, overriden);
    2051        }else{
    2052          new_mntners = get_mntners(new_object);
    2053          new_auth_vector = get_auth_vector(new_mntners);
    2054          if(new_mntners != NULL && new_auth_vector == NULL){
    2055            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2056            return UP_AUF; /* auth failed */
    2057          }
    2058          return authorise(new_auth_vector, credentials, overriden);
    2059        }
    2060      }else{ /* both are NULL, mustn't happen */
    2061          if(tracing){
    2062            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    2063          }
    2064          return UP_INT; /* internal error */
    2065      }
    2066    }
    2067
    2068
    2069
    2070    /*
    2071     *  Handle the "domain" type
    2072     */
    2073    else if(strcmp(type,"domain")  == 0){
    2074      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    2075        old_mntners = get_mntners(old_object);
    2076        old_auth_vector = get_auth_vector(old_mntners);
    2077        if(old_mntners != NULL && old_auth_vector == NULL){
    2078          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    2079          return UP_AUF; /* auth failed */
    2080        }
    2081        return authorise(old_auth_vector, credentials, overriden);
    2082      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    2083        /* now, we have to find a 'less specific domain object' for this.
    2084           If there is no less specific object, then creation is possible
    2085           only with overriding. */
    2086       less_specific_domain = get_less_specific_domain(new_object);
    2087       if(less_specific_domain == NULL){
    2088         if(overriden){/* we didn't get a 'less specific' domain object */
    2089            return UP_AUTH_OK;
    2090          }else{
    2091            return UP_HOF; /* hierarchical authorisation failed */
    2092          }
    2093       }else{ /* we get a 'less specific' domain object */
    2094          less_specific_mnt_lowers = get_mnt_lowers(less_specific_domain);
    2095          less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    2096          if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    2097            /* then, the mntners in 'less_specific_mnt_lowers' do not exist. Problem. */
    2098            return UP_AUF; /* auth failed */
    2099          }
    2100          if(authorise(less_specific_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2101            new_mntners = get_mntners(new_object);
    2102            new_auth_vector = get_auth_vector(new_mntners);
    2103            if(new_mntners != NULL && new_auth_vector == NULL){
    2104              /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2105              return UP_AUF; /* auth failed */
    2106            }
    2107            return authorise(new_auth_vector, credentials, overriden);
    2108          }else{
    2109            return UP_HOF; /* hierarchical authorisation failed */
    2110          }
    2111
    2112       }
    2113      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    2114        old_mntners = get_mntners(old_object);
    2115        old_auth_vector = get_auth_vector(old_mntners);
    2116        if(old_mntners != NULL && old_auth_vector == NULL){
    2117          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    2118          return UP_AUF; /* auth failed */
    2119        }
    2120        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    2121          return authorise(old_auth_vector, credentials, overriden);
    2122        }else{
    2123          new_mntners = get_mntners(new_object);
    2124          new_auth_vector = get_auth_vector(new_mntners);
    2125          if(new_mntners != NULL && new_auth_vector == NULL){
    2126            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2127            return UP_AUF; /* auth failed */
    2128          }
    2129          return authorise(new_auth_vector, credentials, overriden);
    2130        }
    2131      }else{ /* both are NULL, mustn't happen */
    2132          if(tracing){
    2133            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    2134          }
    2135          return UP_INT; /* internal error */
    2136      }
    2137    }
    2138
    2139
    2140    /*
    2141     *  Handle the "route" type
    2142     */
    2143    else if(strcmp(type,"route")  == 0){
    2144      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    2145        old_mntners = get_mntners(old_object);
    2146        old_auth_vector = get_auth_vector(old_mntners);
    2147        if(old_mntners != NULL && old_auth_vector == NULL){
    2148          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    2149          return UP_AUF; /* auth failed */
    2150        }
    2151        return authorise(old_auth_vector, credentials, overriden);
    2152      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    2153        /* first we have to find the aut-num object mentioned in the
    2154           origin attribute */
    2155
    2156        aut_num_object = get_aut_num_object(new_object);
    2157        if(aut_num_object == NULL){
    2158          if(overriden){
    2159            return UP_AUTH_OK;
    2160          }else{
    2161            return UP_HOF; /* hierarchical authorisation failed */
    2162          }
    2163        }else{/* there is a corresponding aut-num in the db */
    2164          if(tracing){
    2165            printf("TRACING: check_auth: will try to authorise the route using aut-num\n");
    2166          }
    2167          aut_num_maintainers = get_mnt_routes(aut_num_object);
    2168          if(aut_num_maintainers != NULL){
    2169            aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    2170            if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2171              aut_num_auth_OK = true;
    2172            }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    2173              return UP_HOF;
    2174            }
    2175          }else{/* aut_num_maintainers is NULL */
    2176             aut_num_maintainers = get_mnt_lowers(aut_num_object);
    2177             if(aut_num_maintainers != NULL){
    2178               aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    2179               if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2180                 aut_num_auth_OK = TRUE;
    2181               }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    2182                 return UP_HOF; /* hierarchical authorisation failed */
    2183               }
    2184             }else{/* aut_num_maintainers is NULL */
    2185               aut_num_maintainers = get_mntners(aut_num_object);
    2186               if(aut_num_maintainers != NULL){
    2187                 aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    2188                 if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2189                   aut_num_auth_OK = TRUE;
    2190                 }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    2191                   return UP_HOF; /* hierarchical authorisation failed */
    2192                 }
    2193               }else{/* aut_num_maintainers is NULL */
    2194                 aut_num_auth_OK = TRUE;
    2195               }
    2196
    2197             }
    2198          }
    2199          if(aut_num_auth_OK){
    2200            /* now, we have to find an exact match for this route object.
    2201               If there is no exact match object, then we will go on to find
    2202               less specific. */
    2203            exact_match_routes = get_exact_match_routes(new_object);
    2204            if(exact_match_routes != NULL){
    2205              exact_match_routes_maintainers = get_mnt_routes_from_list(exact_match_routes);
    2206              exact_match_routes_auth_vector = get_auth_vector(exact_match_routes_maintainers);
    2207              if(exact_match_routes_maintainers != NULL && exact_match_routes_auth_vector == NULL){
    2208                /* then, the mntners in 'exact_match_routes_maintainers' do not exist. Problem. */
    2209                return UP_AUF; /* auth failed */
    2210               }
    2211              if(authorise(exact_match_routes_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2212                /* then, check mnt_bys of the route itself */
    2213                new_mntners = get_mntners(new_object);
    2214                new_auth_vector = get_auth_vector(new_mntners);
    2215                if(new_mntners != NULL && new_auth_vector == NULL){
    2216                  /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2217                  return UP_AUF; /* auth failed */
    2218                }
    2219                return authorise(new_auth_vector, credentials, overriden);
    2220              }else{/*authorise(exact_match_routes_auth_vector, credentials, overriden) != UP_AUTH_OK*/
    2221                return UP_HOF; /* hierarchical authorisation failed */
    2222              }
    2223            }else{ /* exact_match_routes == NULL */
    2224              /* then we have to look for less specific route objs */
    2225              less_spec_routes = get_less_spec_routes(new_object);
    2226              if(less_spec_routes != NULL){
    2227                less_spec_routes_mntners = get_mnt_routes_from_list(less_spec_routes);
    2228                less_spec_routes_mntners = g_slist_concat(less_spec_routes_mntners,
    2229                                              get_mnt_lowers_from_list(less_spec_routes));
    2230                less_spec_routes_auth_vector = get_auth_vector(less_spec_routes_mntners);
    2231                if(less_spec_routes_mntners != NULL && less_spec_routes_auth_vector == NULL){
    2232                  /* then, the mntners in 'less_spec_routes_mntners' do not exist. Problem. */
    2233                  return UP_AUF; /* auth failed */
    2234                }
    2235                if(authorise(less_spec_routes_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2236                  /* then, check mnt_bys of the route itself */
    2237                  new_mntners = get_mntners(new_object);
    2238                  new_auth_vector = get_auth_vector(new_mntners);
    2239                  if(new_mntners != NULL && new_auth_vector == NULL){
    2240                    /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2241                    return UP_AUF; /* auth failed */
    2242                  }
    2243                  return authorise(new_auth_vector, credentials, overriden);
    2244                }else{/*authorise(less_spec_routes_auth_vector, credentials, overriden) != UP_AUTH_OK*/
    2245                  return UP_HOF; /* hierarchical authorisation failed */
    2246                }
    2247             }else{/* less_spec_routes == NULL */
    2248                /* so, we have to get the exact match inetnum */
    2249                exact_match_inetnum = get_exact_match_inetnum(new_object);
    2250                if(exact_match_inetnum != NULL){
    2251                  exact_match_inetnum_mnt_routes = get_mnt_routes(exact_match_inetnum);
    2252                  exact_match_inetnum_auth_vector = get_auth_vector(exact_match_inetnum_mnt_routes);
    2253                  if(exact_match_inetnum_mnt_routes != NULL && exact_match_inetnum_auth_vector == NULL){
    2254                    /* then, the mntners in 'exact_match_inetnum_mnt_routes' do not exist. Problem. */
    2255                    return UP_AUF; /* auth failed */
    2256                  }
    2257                  if(authorise(exact_match_intenum_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2258                    /* then, check mnt_bys of the route itself */
    2259                    new_mntners = get_mntners(new_object);
    2260                    new_auth_vector = get_auth_vector(new_mntners);
    2261                    if(new_mntners != NULL && new_auth_vector == NULL){
    2262                      /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2263                      return UP_AUF; /* auth failed */
    2264                    }
    2265                    return authorise(new_auth_vector, credentials, overriden);
    2266                  }else{
    2267                    return UP_HOF; /* hierarchical authorisation failed */
    2268                  }
    2269                }else{/* exact_match_inetnum == NULL */
    2270                  /* then, we will try to find less spec inetnums */
    2271                  less_spec_inetnum = get_less_spec_inetnum(new_object);
    2272                  if(less_spec_inetnum != NULL){
    2273                    less_spec_inetnum_mntners = get_mnt_routes(less_spec_inetnum);
    2274                    less_spec_inetnum_mntners = g_slist_concat(less_spec_inetnum_mntners,
    2275                                   get_mnt_lowers(less_spec_inetnum));
    2276                    less_spec_inetnum_auth_vector = get_auth_vector(less_spec_inetnum_mntners);
    2277                    if(less_spec_inetnum_mntners != NULL && less_spec_inetnum_auth_vector == NULL){
    2278                      /* then, the mntners in 'less_spec_inetnum_mntners' do not exist. Problem. */
    2279                      return UP_AUF; /* auth failed */
    2280                    }
    2281                    if(authorise(exact_match_auth_vector, credentials, overriden) == UP_AUTH_OK){
    2282                      /* then, check mnt_bys of the route itself */
    2283                      new_mntners = get_mntners(new_object);
    2284                      new_auth_vector = get_auth_vector(new_mntners);
    2285                      if(new_mntners != NULL && new_auth_vector == NULL){
    2286                        /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2287                        return UP_AUF; /* auth failed */
    2288                      }
    2289                      return authorise(new_auth_vector, credentials, overriden);
    2290                    }else{/* authorise(exact_match_auth_vector, credentials, overriden) != UP_AUTH_OK */
    2291                      return UP_HOF; /* hierarchical authorisation failed */
    2292                    }
    2293                  }else{/* less_spec_inetnum == NULL */
    2294                    /* now that we couldn't find any route or inetnum object
    2295                       to be used in authentication. So, only if the auth is
    2296                       overriden the object will be created. */
    2297                    if(overriden){
    2298                      return UP_AUTH_OK;
    2299                    }else{
    2300                      return UP_HOF; /* hierarchical authorisation failed */
    2301                    }
    2302                  }
    2303                }
    2304              }
    2305            }
    2306          }else{/* ! aut_num_auth_OK */
    2307            return UP_HOF; /* hierarchical auth failed */
    2308          }
    2309
    2310        }
    2311
    2312      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    2313        old_mntners = get_mntners(old_object);
    2314        old_auth_vector = get_auth_vector(old_mntners);
    2315        if(old_mntners != NULL && old_auth_vector == NULL){
    2316          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    2317          return UP_AUF; /* auth failed */
    2318        }
    2319        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    2320          return authorise(old_auth_vector, credentials, overriden);
    2321        }else{
    2322          new_mntners = get_mntners(new_object);
    2323          new_auth_vector = get_auth_vector(new_mntners);
    2324          if(new_mntners != NULL && new_auth_vector == NULL){
    2325            /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2326            return UP_AUF; /* auth failed */
    2327          }
    2328          return authorise(new_auth_vector, credentials, overriden);
    2329        }
    2330      }else{ /* both are NULL, mustn't happen */
    2331          if(tracing){
    2332            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    2333          }
    2334          return UP_INT; /* internal error */
    2335      }
    2336    }
    2337
    2338
    2339    /*
    2340     *  Handle the set objects ("as-set","rtr-set", "peering-set", "route-set" and "filter-set" types
    2341     */
    2342    else if(strcmp(type,"as-set")       == 0 || strcmp(type,"rtr-set")     == 0 ||
    2343            strcmp(type,"peering-set")  == 0 || strcmp(type,"filter-set")  == 0 ||
    2344            strcmp(type,"route-set")    == 0 ){
    2345      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    2346        old_mntners = get_mntners(old_object);
    2347        old_auth_vector = get_auth_vector(old_mntners);
    2348        if(old_mntners != NULL && old_auth_vector == NULL){
    2349          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    2350          return UP_AUF; /* auth failed */
    2351        }
    2352        return authorise(old_auth_vector, credentials, overriden);
    2353      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    2354         code = set_object->scan_silent(new_object, strlen(new_object));
    2355         set_name = get_search_key(set_object, type, new_object);
    2356        if(strstr(set_name,":") == NULL ){/* if the name is _not_ hierarchical */
    2357          new_mntners = get_mntners(new_object);
    2358          new_auth_vector = get_auth_vector(new_mntners);
    2359          if(new_mntners != NULL && new_auth_vector == NULL){
    2360            /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    2361            return UP_AUF; /* auth failed */
    2362          }
    2363          return authorise(new_auth_vector, credentials, overriden);
    2364        }else{/* the name is hierarchical */
    2365          less_specific_object = get_less_specific_set(new_object, type);
    2366          if(less_specific_object != NULL){/* such an object exists */
    2367            temp_obj = new Object();
    2368            code = temp_obj->scan_silent(less_specific_object, strlen(less_specific_object));
    2369            less_specific_object_type = get_class_type(temp_obj);
    2370            delete(temp_obj);
    2371            if(strcmp(less_specific_object_type, "aut-num") == 0){/* if this is an aut-num object */
    2372              less_specific_mnt_lowers = get_mnt_lowers(less_specific_object);
    2373              less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    2374              if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    2375                /* then, the mntners in 'less_specific_auth_vector' do not exist. Problem. */
    2376               return UP_AUF; /* auth failed */
    2377              }
    2378              if(less_specific_auth_vector != NULL){
    2379                return authorise(less_specific_auth_vector, credentials, overriden);
    2380              }else{/* the less specific object doesn't contain any mnt-lower */
    2381                less_specific_mntners = get_mntners(less_specific_object);
    2382                less_specific_auth_vector = get_auth_vector(less_specific_mntners);
    2383                if(less_specific_mntners != NULL && less_specific_auth_vector == NULL){
    2384                  /* then, the mntners in 'less_specific_mntners' do not exist. Problem. */
    2385                  return UP_AUF; /* auth failed */
    2386                }
    2387                if(less_specific_auth_vector != NULL){/* less spec object has some mnt-by attribs,
    2388                                                         use them  */
    2389                    return authorise(less_specific_auth_vector, credentials, overriden);
    2390                }else{/* the less specific object doesn't contain any mnt-by either */
    2391                  if(overriden){
    2392                    return UP_AUTH_OK;
    2393                  }else{
    2394                    return UP_HOF; /* hierarchical authorisation failed */
    2395                  }
    2396                }
    2397              }
    2398            }else{ /* this is _not_ an aut-num object*/
    2399              less_specific_mntners = get_mntners(less_specific_object);
    2400              less_specific_auth_vector = get_auth_vector(less_specific_mntners);
    2401              if(less_specific_mntners != NULL && less_specific_auth_vector == NULL){
    2402                /* then, the mntners in 'less_specific_mntners' do not exist. Problem. */
    2403                return UP_AUF; /* auth failed */
    2404              }
    2405              if(less_specific_auth_vector != NULL ){/* the set obj has some mnt-by attribs */
    2406                return authorise(less_specific_auth_vector, credentials, overriden);
    2407              }else{
    2408                if(overriden){
    2409                  return UP_AUTH_OK;
    2410                }else{
    2411                  return UP_HOF; /* hierarchical authorisation failed */
    2412                }
    2413              }
    2414            }
    2415
    2416          }else{/* we don't have a less specific of this set object in the DB  */
    2417            return UP_HOF; /* hierarchical authorisation failed */
    2418          }
    2419        }
    2420      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    2421        old_mntners = get_mntners(old_object);
    2422        old_auth_vector = get_auth_vector(old_mntners);
    2423        if(old_mntners != NULL && old_auth_vector == NULL){
    2424          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    2425          return UP_AUF; /* auth failed */
    2426        }
    2427        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    2428          return authorise(old_auth_vector, credentials, overriden);
    2429        }else{
    2430          new_mntners = get_mntners(new_object);
    2431          new_auth_vector = get_auth_vector(new_mntners);
    2432          if(new_mntners != NULL && new_auth_vector == NULL){
    2433            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    2434            return UP_AUF; /* auth failed */
    2435          }
    2436          return authorise(new_auth_vector, credentials, overriden);
    2437        }
    2438      }else{ /* both are NULL, mustn't happen */
    2439          if(tracing){
    2440            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    2441          }
    2442          return UP_INT; /* internal error */
    2443      }
    2444
    2445
    2446
    2447
    2448
    2449    }else{ /* We exhausted all object classes. If we are here, then there is a problem */
    2450      cout << "check_auth: This type '" << type << "' is unknown" << endl;
    2451      return UP_NIY; /* not implemented yet */
    2452    }
    2453    return UP_AUF; /* if we come to this point, then auth failed */
    2454 }
    2455
    2456
    2457
    2458
    2459
    2460
    2461 /* Gets the old version of the given "arg" object, which is in char * format
    2462    and returns the old version again in char * format */
    2463
    2464 char * get_old_version(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2465
    2466     bool code = true;
    2467     char *type=NULL, *primary_search_key = NULL, *search_string = NULL;
    2468     Object *o;
    2469     o = new Object;
    2470     char *result = NULL, *origin = NULL;
    2471
    2472     error = 0;
    2473     code = o->scan_silent(arg,strlen(arg));
    2474     type = get_class_type(o);
    2475     primary_search_key = get_search_key(o, type, arg);
    2476     if(tracing) {
    2477       cout << "type=" << type << endl;
    2478       cout << "primary_search_key=" << primary_search_key << endl;
    2479     }
    2480     /* if the object is a pn ro a ro object, then get all pn/ro's with the
    2481        same NIC hdl */
    2482     if(strcmp(type,"person") == 0 || strcmp(type,"role") == 0){
    2483       /* prepare the search string */
    2484       search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2485                                           + strlen("person,role") + 2);
    2486       sprintf(search_string, "-x -R -r -Tperson,role %s", primary_search_key);
    2487     }else{
    2488       /* prepare the search string */
    2489       search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2490                                           + strlen(type) + 2);
    2491       sprintf(search_string, "-x -R -r -T%s %s",type, primary_search_key);
    2492     }
    2493     result = send_and_get(query_host, query_port, search_string);
    2494     if(tracing) {
    2495       cout << "TRACING: send_and_get has returned" << endl;
    2496       cout << "TRACING: send_and_get returned (with search '"<< search_string <<"'): " << endl
    2497            << result << endl;
    2498     }
    2499     /* XXX and here, we must filter the 'result' with NIC handle */
    2500
    2501     if(strcmp(type,"route") == 0){
    2502       if(tracing) {
    2503         printf("TRACING: This is a route\n");
    2504       }
    2505       /* if this is a route, then we must filter out the routes with different
    2506          origin attributes */
    2507       origin = get_search_key(o, "origin", arg);
    2508       if(tracing) {
    2509         printf("TRACING: Got origin of route: %s\n", origin);
    2510       }
    2511       result = filter_out_diff_origins(result, origin);
    2512       if(tracing) {
    2513         printf("TRACING: Filtered routes\n");
    2514       }
    2515     }
    2516
    2517     /* count the objects */
    2518     if(count_objects(result) == 0){
    2519       result = NULL; /* we don't have such an object */
    2520     }else if(count_objects(result) == 1){
    2521       result = take_object(result);
    2522       if(tracing) {
    2523       cout << "TRACING: Take_object returned ***\n" << result << "***" << endl;
    2524       }
    2525     }else{ /* we have more than one objects, error! */
    2526       error = UP_MOR;
    2527       return NULL;
    2528     }
    2529     return result;
    2530 }
    2531
    2532
    2533
    2534
    2535 /* Gets a credentials_struct whose 'from' field will be filled in and
    2536    the mail header. Finds the 'From:' line in the header and sets
    2537    the 'from' field to this line (all line, including the 'From:' string,
    2538    since some users have put regexps which match the whole line in their
    2539    'auth' attributes.) */
    2540 void process_mail_header(credentials_struct * credentials_ptr, char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2541   char * header = strdup(arg);
    2542   char * temp = (char *)malloc(strlen(header));
    2543   while(index(header, '\n') != NULL){
    2544     temp = strdup(header);
    2545     temp[index(temp, '\n') - temp] = '\0';
    2546     if(strstr(temp, "From:") == temp){
    2547       if(tracing) {
    2548         printf("TRACING: process_mail_header: Assigning %s\n", temp);
    2549       }
    2550       credentials_ptr->from = strdup(temp);
    2551       free(temp);
    2552       return;
    2553     }
    2554     header = header + (index(header, '\n') - header + 1);
    2555   }
    2556   free(temp);
    2557 }
    2558
    2559
    2560
    2561
    2562
    2563
    2564 void up_string_pack(char *dest, const char *source){
         /* [<][>][^][v][top][bottom][index][help] */
    2565
    2566   if(tracing) {
    2567     printf("TRACING: up_string_pack running\n");
    2568   }
    2569
    2570
    2571
    2572 /*----------------------------------------------------------------------*\
    2573
    2574 *  Function to rewrite a line of text with only one blankspace between  *
    2575 *  each word.
    2576 *
    2577
    2578 \*----------------------------------------------------------------------*/
    2579
    2580
    2581 /*
    2582  * This while loop continues until the NULL character is copied into
    2583  * the destination string.  If a tab character is copied into the
    2584  * destination string, it is replaced with a blank-space character.
    2585  *
    2586  * Multiple blank-space and/or tab characters are skipped in the source
    2587  * string until any other character is found.
    2588  */
    2589
    2590         while (1)
    2591                 {
    2592                 *dest = *source;
    2593
    2594                 if (*dest == '\t')
    2595                         (*dest = ' ');
    2596
    2597                 /* Exit if have copied the end of the string. */
    2598                 if (*dest == '\0')
    2599                         return;
    2600
    2601 /*
    2602  * If the source character was a blank-space or a tab, move to the next
    2603  * source character.  While the source character is a blank-space or a
    2604  * tab, move to the next character (i.e. ignore these characters).  When
    2605  * any other character is found in the source string, move to the next
    2606  * element of the destination string.
    2607  *
    2608  * Otherwise, simultaneously, move to the next elements of the destination
    2609  * and the source strings.
    2610  */
    2611
    2612
    2613
    2614                 if ( (*source == ' ') || (*source == '\t') )
    2615                         {
    2616                         ++source;
    2617                         while ( (*source == ' ') || (*source == '\t') )
    2618                                 {
    2619                                 ++source;
    2620                                 }
    2621
    2622                         ++dest;
    2623                         }
    2624                 else
    2625                         {
    2626                         ++dest;
    2627                         ++source;
    2628                         }
    2629                 }
    2630 }
    2631
    2632
    2633
    2634
    2635
    2636
    2637
    2638
    2639 /* strips lines beginning with "delete:" off  */
    2640 char * delete_delete_attrib(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2641
    2642     char ** temp = NULL;
    2643     char * string = NULL;
    2644     int i;
    2645
    2646     if(arg == NULL){
    2647        return NULL;
    2648     }
    2649
    2650     /* split the string into lines */
    2651     temp = g_strsplit (arg, "\n", 0);
    2652
    2653     for(i=0; temp[i] != NULL; i++){
    2654       /* if the line begins with "delete:", then do not copy it */
    2655       if(strstr(temp[i], "delete:") != temp[i]){
    2656         if(string == NULL){
    2657           string = strdup(temp[i]);
    2658         }else{
    2659           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 2);
    2660           string = strcat(string, "\n");
    2661           string = strcat(string, temp[i]);
    2662         }
    2663       }
    2664     }
    2665     g_strfreev(temp);
    2666     return string;
    2667 }
    2668
    2669
    2670
    2671
    2672
    2673
    2674 /* replaces the erase_str occurences with insert_str in str (which is a ptr to GString) */
    2675 char * UP_replace_strings(char * str, const char * erase_str, const char * insert_str){
         /* [<][>][^][v][top][bottom][index][help] */
    2676
    2677   GString * g_str;
    2678   int pos;
    2679   char * result_str;
    2680
    2681   /* erase_str mustn't be NULL */
    2682   assert(erase_str != NULL);
    2683
    2684   /* if insert str is NULL, make it empty string */
    2685   if(insert_str == NULL){
    2686     insert_str = strdup("");
    2687   }
    2688
    2689   g_str = g_string_new(str);
    2690
    2691   /* replace erase_str with insert_str */
    2692   while(strstr(g_str->str, erase_str) != NULL){
    2693     pos = strstr(g_str->str, erase_str) - g_str->str;
    2694     g_str = g_string_erase(g_str, pos, strlen(erase_str));
    2695     if(insert_str != NULL){
    2696       g_str = g_string_insert(g_str, pos, insert_str);
    2697     }
    2698   }
    2699
    2700
    2701   /* save the result string */
    2702   result_str = strdup(g_str->str);
    2703
    2704   /* free the GString structure (TRUE means 'also free the char string') */
    2705   g_string_free(g_str, TRUE);
    2706
    2707   return result_str;
    2708
    2709 }
    2710
    2711
    2712
    2713
    2714
    2715
    2716
    2717
    2718
    2719
    2720 /* replaces the erase_str occurences with insert_str in g_str (which is a ptr to GString) */
    2721 GString * UP_replace_GStrings(GString * g_str, const char * erase_str, const char * insert_str){
         /* [<][>][^][v][top][bottom][index][help] */
    2722
    2723   int pos;
    2724
    2725   if(insert_str == NULL){/* then don't do anything */
    2726     return g_str;
    2727   }
    2728
    2729   /* replace erase_str with insert_str */
    2730   while(strstr(g_str->str, erase_str) != NULL){
    2731     pos = strstr(g_str->str, erase_str) - g_str->str;
    2732     g_str = g_string_erase(g_str, pos, strlen(erase_str));
    2733     g_str = g_string_insert(g_str, pos, insert_str);
    2734   }
    2735   return g_str;
    2736
    2737 }
    2738
    2739
    2740
    2741
    2742
    2743
    2744
    2745
    2746 /* looks if two objects are identical or not.
    2747     Takes two objects as char *, and returns 1 if
    2748     they are identical, returns 0 if not.
    2749
    2750     Algorithm is very simple: All strings of tabs and
    2751     white spaces are collapsed into a single white space,
    2752     and then the strings are compared (strcmp) */
    2753 int identical(const char * old_version, const char * new_version){
         /* [<][>][^][v][top][bottom][index][help] */
    2754   char * arg1 = strdup(old_version);
    2755   char * arg2 = strdup(new_version);
    2756   int result = 0;
    2757   char *temp1, *temp2;
    2758   char *temp;
    2759
    2760
    2761   arg1 = g_strstrip(arg1);
    2762   arg2 = g_strstrip(arg2);
    2763
    2764   /* delete the 'delete:' attrib */
    2765   arg2 = delete_delete_attrib(arg2);
    2766
    2767   /* also delete 'override' attrib */
    2768   arg2 = delete_override(arg2);
    2769
    2770   /* convert tabs to white spaces */
    2771   arg1 = g_strdelimit(arg1, "\t", ' ');
    2772   arg2 = g_strdelimit(arg2, "\t", ' ');
    2773
    2774   temp1 = (char *)malloc(strlen(arg1) + 1);
    2775   temp2 = (char *)malloc(strlen(arg2) + 1);
    2776   up_string_pack(temp1, arg1);
    2777   up_string_pack(temp2, arg2);
    2778
    2779   /* if there are still \r's at the end of strings, remove them */
    2780   if((temp1[strlen(temp1) - 1]) == '\r'){
    2781     temp1[strlen(temp1) - 1] = '\0';
    2782   }
    2783   if((temp2[strlen(temp2) - 1]) == '\r'){
    2784     temp2[strlen(temp2) - 1] = '\0';
    2785   }
    2786
    2787   /* there may be white spaces at the end of the strings now, remove them */
    2788   if((temp1[strlen(temp1) - 1]) == ' '){
    2789     temp1[strlen(temp1) - 1] = '\0';
    2790   }
    2791   if((temp2[strlen(temp2) - 1]) == ' '){
    2792     temp2[strlen(temp2) - 1] = '\0';
    2793   }
    2794
    2795   /* remove the white spaces just before the EOLs (since this is not taken care of by
    2796      the up_string_pack func) */
    2797   temp = UP_replace_strings(temp1, " \n", "\n");
    2798   free(temp1);
    2799   temp1 = temp;
    2800
    2801   temp = UP_replace_strings(temp2, " \n", "\n");
    2802   free(temp2);
    2803   temp2 = temp;
    2804
    2805
    2806
    2807   result = strcmp(temp1, temp2);
    2808   if(tracing){
    2809     printf("TRACING: identical: the objects are:\n[%s]\n[%s]\n", temp1, temp2);
    2810     printf("TRACING: identical: the lengths are:\n[%i]\n[%i]\n", strlen(temp1), strlen(temp2));
    2811   }
    2812   free(arg1);
    2813   free(arg2);
    2814   free(temp1);
    2815   free(temp2);
    2816   if(result  == 0){
    2817     if(tracing) {
    2818       printf("TRACING: identical returning 1\n");
    2819     }
    2820     return 1;
    2821   }else{
    2822     if(tracing) {
    2823       printf("TRACING: identical returning 0\n");
    2824     }
    2825     return 0;
    2826   }
    2827 }
    2828
    2829
    2830
    2831
    2832
    2833
    2834 /* constructs an initials string from a given name (for NIC hdl generation) */
    2835 char * find_initials(const char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2836
    2837    char * temp, * temp2;
    2838    char * initials = NULL;
    2839    int len, i;
    2840    char ** vector;
    2841
    2842    temp = strdup(arg);
    2843    g_strstrip(temp);
    2844    temp2 = (char *)malloc(strlen(temp) + 1);
    2845    up_string_pack(temp2, temp);
    2846    vector = g_strsplit(temp2, " ", 0);
    2847    for(i = 0; vector[i] != NULL && i < 4; i++){
    2848      if((strlen(vector[i]) > 0 )&& isalpha(vector[i][0]) ){
    2849        if(initials == NULL){
    2850          initials = (char *)malloc(2);
    2851          initials[0] = vector[i][0]; initials[1] = '\0';
    2852        }else{
    2853          len = strlen(initials);
    2854          initials = (char *)realloc(initials, len + 2 );
    2855          initials[len] = vector[i][0];
    2856          initials[len + 1] = '\0';
    2857        }
    2858      }
    2859    }
    2860    free(temp);free(temp2);g_strfreev(vector);
    2861    return initials;
    2862 }
    2863
    2864
    2865
    2866
    2867
    2868 /*  Gets the letter combination to be used in the automatically
    2869     generated NIc handle. It the letter combination is specified
    2870     in the AUTO NIC handle, return that. If not, return NULL
    2871     (in which case the initials of the name must be used) */
    2872 char * get_combination_from_autonic(const char * autonic){
         /* [<][>][^][v][top][bottom][index][help] */
    2873
    2874   GString * temp;
    2875   char * str = NULL;
    2876
    2877   temp = g_string_new(autonic);
    2878   temp = g_string_up(temp);
    2879   temp = g_string_erase(temp, 0, strlen("AUTO-"));
    2880   /* delete all digits from the beginning of the string */
    2881   while(temp->len > 0 && ((temp->str)[0] >= '0' && (temp->str)[0] <= '9')){
    2882     temp = g_string_erase(temp, 0, 1);
    2883   }
    2884
    2885
    2886   if(temp->len < 2 ){
    2887     g_string_free(temp, TRUE);
    2888     return NULL;
    2889   }else{
    2890     str = temp->str;
    2891     g_string_free(temp, FALSE);
    2892     g_strup(str);
    2893     if(strlen(str) > 4){
    2894       str[4] = '\0';
    2895     }
    2896     return str;
    2897   }
    2898
    2899 }
    2900
    2901
    2902
    2903
    2904
    2905
    2906 /* Gets an object whose NIC hdl is AUTO and to be modified (to be sent to RIPupdate)
    2907    and  modifies the nic-hdl: attribute, returns the new object.
    2908    For example, "nic-hdl: AUTO-1" becomes "nic-hdl: HG*-RIPE . Also,
    2909    auto_nic is set to "AUTO-1"
    2910    auto_nic must be allocated enough memory before replace_AUTO_NIC_hdl called */
    2911 char * replace_AUTO_NIC_hdl(char * arg, char * auto_nic_hdl){
         /* [<][>][^][v][top][bottom][index][help] */
    2912
    2913   GString* temp_string;
    2914   char * to_be_returned = NULL;
    2915   char * person_role_name= NULL;
    2916   char * initials = NULL;
    2917   char ** temp = NULL;
    2918   int i, pos;
    2919   Object * o = new Object;
    2920
    2921   temp = g_strsplit(arg, "\n", 0);
    2922
    2923   for(i = 0; temp[i] != NULL; i++){
    2924     if(strstr(temp[i], "nic-hdl:") == temp[i]){/* if it starts with nic-hdl */
    2925       temp_string = g_string_new(temp[i]);
    2926       temp_string = g_string_down(temp_string);
    2927       if(strstr(temp_string->str, "auto-") != NULL){
    2928         auto_nic_hdl = strncpy(auto_nic_hdl, strstr(temp_string->str, "auto-"),
    2929             temp_string->len + temp_string->str - strstr(temp_string->str, "auto-") );
    2930         auto_nic_hdl[temp_string->len + temp_string->str - strstr(temp_string->str, "auto-")] = '\0';
    2931         g_strstrip(auto_nic_hdl);
    2932         if(tracing){
    2933           printf("TRACING: auto_nic is [%s]\n", auto_nic_hdl);
    2934         }
    2935         pos = strstr(temp_string->str, "auto-") - temp_string->str;
    2936         temp_string = g_string_erase(temp_string,
    2937             strstr(temp_string->str, "auto-") - temp_string->str, strlen(auto_nic_hdl)/*strlen("AUTO-")*/);
    2938         /* as the suffix to the AUTO nic handle we use the first updatable
    2939            source. Since currently we don't support multiple sources,
    2940            this is not a problem but when we support it, we must change this */
    2941         temp_string = g_string_insert(temp_string, pos, sources[0]);
    2942         temp_string = g_string_insert(temp_string, pos, "*-");
    2943         o->scan_silent(arg, strlen(arg));
    2944         person_role_name = get_attribute(o, get_class_type(o), arg);
    2945         delete(o);
    2946         /* if the letter combination is already specified, get it */
    2947         initials = get_combination_from_autonic(auto_nic_hdl);
    2948         /* if the letter combination is not in the AUTO nichdl, obtain it from the name */
    2949         if(initials == NULL){
    2950           initials = find_initials(person_role_name);
    2951         }
    2952         free(person_role_name);
    2953         temp_string = g_string_insert(temp_string, pos, initials);
    2954         free(initials);
    2955
    2956         if(to_be_returned == NULL){
    2957           to_be_returned = strdup(temp_string->str);
    2958           g_string_free(temp_string, TRUE);
    2959         }else{
    2960           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    2961           to_be_returned = strcat(to_be_returned, "\n");
    2962           to_be_returned = strcat(to_be_returned, temp_string->str);
    2963           g_string_free(temp_string, TRUE);
    2964         }
    2965       }else{
    2966         if(to_be_returned == NULL){
    2967           to_be_returned = strdup(temp[i]);
    2968         }else{
    2969           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2970           to_be_returned = strcat(to_be_returned, "\n");
    2971           to_be_returned = strcat(to_be_returned, temp[i]);
    2972         }
    2973       }
    2974     }else{/* if it doesn't begin with nic-hdl */
    2975         if(to_be_returned == NULL){
    2976           to_be_returned = strdup(temp[i]);
    2977         }else{
    2978           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2979           strcat(to_be_returned, "\n");
    2980           strcat(to_be_returned, temp[i]);
    2981         }
    2982
    2983     }
    2984
    2985   }
    2986   g_strfreev (temp);
    2987   return to_be_returned;
    2988 }
    2989
    2990
    2991
    2992
    2993
    2994
    2995
    2996 /* replaces the refs to AUTO NIC hdls with the assigned one */
    2997
    2998 char * replace_refs_to_AUTO_NIC_hdl(char * changed_obj, char * arg, GHashTable * auto_nic_hash){
         /* [<][>][^][v][top][bottom][index][help] */
    2999
    3000   char * auto_nic = NULL;
    3001   GString* temp_string;
    3002   char * to_be_returned = NULL, * tempstr = NULL;
    3003   char ** temp = NULL;
    3004   int i, pos;
    3005
    3006   if(tracing){
    3007     printf("TRACING: replace_refs_to_AUTO_NIC_hdl is running: changed_obj:[%s], arg:[%s]\n",
    3008               changed_obj ? changed_obj : "NULL", arg ? arg : "NULL");
    3009   }
    3010
    3011
    3012   temp = g_strsplit(arg, "\n", 0);
    3013
    3014   for(i = 0; temp[i] != NULL; i++){
    3015     if(   strstr(temp[i], "admin-c:") == temp[i]    /*    if it starts with admin-c */
    3016        || strstr(temp[i], "tech-c:" ) == temp[i]    /* or if it starts with tech-c */
    3017        || strstr(temp[i], "zone-c:" ) == temp[i]    /* or if it starts with zone-c */
    3018        || strstr(temp[i], "author:" ) == temp[i]){  /* or if it starts with author */
    3019       temp_string = g_string_new(temp[i]);
    3020       temp_string = g_string_down(temp_string);
    3021       if(strstr(temp_string->str, "auto-") != NULL){
    3022         auto_nic = (char *)malloc(temp_string->len + temp_string->str - strstr(temp_string->str, "auto-")  + 1);
    3023         auto_nic = strncpy(auto_nic, strstr(temp_string->str, "auto-"),
    3024             temp_string->len + temp_string->str - strstr(temp_string->str, "auto-") );
    3025         auto_nic[temp_string->str + temp_string->len - strstr(temp_string->str, "auto-")] = '\0';
    3026         g_strstrip(auto_nic);
    3027         if(tracing){
    3028           printf("TRACING: replace_refs_to_AUTO_NIC_hdl: auto_nic is [%s]\n", auto_nic);
    3029         }
    3030         pos = strstr(temp_string->str, "auto-") - temp_string->str;
    3031         temp_string = g_string_erase(temp_string,
    3032             strstr(temp_string->str, "auto-") - temp_string->str, strlen(auto_nic)/*strlen("AUTO-")*/);
    3033
    3034         /* if we have this AUTO NIC hdl in the hash, put it. */
    3035         if(g_hash_table_lookup(auto_nic_hash, auto_nic)){
    3036           temp_string = g_string_insert(temp_string, pos, (char *)g_hash_table_lookup(auto_nic_hash, auto_nic));
    3037         }else{/* else, return 0 immediately */
    3038           g_strfreev (temp);
    3039           return NULL;
    3040         }
    3041
    3042         if(to_be_returned == NULL){
    3043           to_be_returned = strdup(temp_string->str);
    3044           g_string_free(temp_string, TRUE);
    3045         }else{
    3046           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    3047           to_be_returned = strcat(to_be_returned, "\n");
    3048           to_be_returned = strcat(to_be_returned, temp_string->str);
    3049           g_string_free(temp_string, TRUE);
    3050         }
    3051       }else{
    3052         if(to_be_returned == NULL){
    3053           to_be_returned = strdup(temp[i]);
    3054         }else{
    3055           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    3056           to_be_returned = strcat(to_be_returned, "\n");
    3057           to_be_returned = strcat(to_be_returned, temp[i]);
    3058         }
    3059       }
    3060     }else{/* if it doesn't begin with ac,tc,ac or author */
    3061         if(to_be_returned == NULL){
    3062           to_be_returned = strdup(temp[i]);
    3063         }else{
    3064           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    3065           strcat(to_be_returned, "\n");
    3066           strcat(to_be_returned, temp[i]);
    3067         }
    3068
    3069     }
    3070
    3071   }
    3072   g_strfreev (temp);
    3073
    3074   /* now, if we don't have a '\n' at the end of the to_be_returned  string, we will
    3075      add one, since RAToolSet parser cannot deal with objects without a '\n' at the end */
    3076   if(to_be_returned[strlen(to_be_returned) - 1] != '\n'){
    3077     /* so, add a '\n' */
    3078     tempstr = (char *)malloc(strlen(to_be_returned) + 2);
    3079     sprintf(tempstr, "%s\n", to_be_returned);
    3080     free(to_be_returned);
    3081     to_be_returned = tempstr;
    3082   }
    3083
    3084   if(tracing){
    3085     printf("TRACING: replace_refs_to_AUTO_NIC_hdl is returning,\nto_be_returned=[%s]\n", to_be_returned);
    3086   }
    3087   return to_be_returned;
    3088 }
    3089
    3090
    3091
    3092
    3093 /* UP_put_assigned_NIC will replace the auto NIC handle of the object with its
    3094    assigned NIC handle */
    3095 char * UP_put_assigned_NIC(char * arg, const char * assigned_NIC){
         /* [<][>][^][v][top][bottom][index][help] */
    3096
    3097   Object * o = new Object();
    3098   char * object;
    3099   bool code;
    3100   GSList * attribute_list;
    3101   GSList * next;
    3102   external_syntax_struct *result;
    3103   int pos;
    3104   char * auto_nic = NULL;
    3105   char * temp = NULL;
    3106   GString* temp_string;
    3107
    3108
    3109
    3110   object = strdup(arg);
    3111   /* if the object does not have a '\n' at the end, add it. */
    3112   if(object[strlen(object) - 1] != '\n'){
    3113     object = (char *)realloc(object, strlen(object) + 2);
    3114     object = strcat(object, "\n");
    3115   }
    3116
    3117   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
    3118
    3119   /* initialize the struct */
    3120   result->result = 0;              /* we won't use this in this function in fact */
    3121   result->error_str = strdup("");  /* we won't use this in this function in fact */
    3122   result->warning_str = strdup("");/* we won't use this in this function in fact */
    3123
    3124   code = o->scan_silent(object, strlen(object));
    3125   attribute_list = up_get_attribute_list(o, object);
    3126
    3127
    3128   /* loop through the attributes */
    3129   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
    3130     /* is this a 'nic-hdl' attribute? */
    3131     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "nic-hdl") == 0){
    3132       /* then, we will replace the AUTO-NIC hdl in it with the assigned one  */
    3133       /* save the attribute value to a temp char *   */
    3134       temp = strdup((char *)(((attribute_struct *)(next->data))->content));
    3135       temp_string = g_string_new(temp);
    3136       temp_string = g_string_down(temp_string);
    3137       if(strstr(temp_string->str, "auto-") != NULL){
    3138         auto_nic = (char *)malloc(temp_string->len + temp_string->str - strstr(temp_string->str, "auto-")  + 1);
    3139         auto_nic = strncpy(auto_nic, strstr(temp_string->str, "auto-"),
    3140             temp_string->len + temp_string->str - strstr(temp_string->str, "auto-") );
    3141         auto_nic[temp_string->str + temp_string->len - strstr(temp_string->str, "auto-")] = '\0';
    3142         g_strstrip(auto_nic);
    3143         if(tracing){
    3144           printf("TRACING: UP_put_assigned_NIC: auto_nic is [%s]\n", auto_nic);
    3145         }
    3146         pos = strstr(temp_string->str, "auto-") - temp_string->str;
    3147         temp_string = g_string_erase(temp_string,
    3148             strstr(temp_string->str, "auto-") - temp_string->str, strlen(auto_nic)/*strlen("AUTO-")*/);
    3149
    3150         /* insert the assigned NIC handle */
    3151         temp_string = g_string_insert(temp_string, pos, assigned_NIC
    3152              /*(char *)g_hash_table_lookup(auto_nic_hash, auto_nic)*/);
    3153
    3154         /* and assign the new value of GList member */
    3155         ((attribute_struct *)(next->data))->content = temp_string->str;
    3156
    3157         //if(to_be_returned == NULL){
    3158         //  to_be_returned = strdup(temp_string->str);
    3159         //  g_string_free(temp_string, TRUE);
    3160         //}else{
    3161         //  to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    3162         //  to_be_returned = strcat(to_be_returned, "\n");
    3163         //  to_be_returned = strcat(to_be_returned, temp_string->str);
    3164         //  g_string_free(temp_string, TRUE);
    3165         //}
    3166       }
    3167     }
    3168   }
    3169   /* OK, now we must reconstruct the object as a char *   */
    3170   up_reconstruct_object(attribute_list, result);
    3171
    3172   /* free the o */
    3173   delete(o);
    3174
    3175   /* and return the reconstructed object */
    3176   return result->new_obj;
    3177 }
    3178
    3179
    3180
    3181
    3182
    3183 /* Takes an object in a char * , and returns 1 if this object has
    3184    an AUTO NIC handle. Otherwise, returns 0 */
    3185 int has_AUTO_NIC_hdl(const char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    3186
    3187   Object * o = new Object();
    3188   GSList * attributes = NULL;
    3189   bool code;
    3190
    3191   code = o->scan_silent(object, strlen(object));
    3192
    3193   if(code && !(o->isDeleted)){
    3194     attributes = get_attributes(o, "nic-hdl", object);
    3195     if(attributes != NULL){
    3196       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    3197         g_slist_free(attributes);
    3198         delete(o);
    3199         return 1;
    3200       }
    3201     }
    3202     /* if control reaches here, then we will return 0 */
    3203     g_slist_free(attributes);
    3204     delete(o);
    3205     return 0;
    3206   }else{/* it doesn't pass syntax check. So, it doesn't matter if
    3207            it contains refs to AUTO NIC hdls. */
    3208     delete(o);
    3209     return 0;
    3210   }
    3211
    3212 }
    3213
    3214
    3215 /* Takes an object in a char * , and returns 1 if this object contains
    3216    a reference to an AUTO NIC handle. Otherwise, returns 0 */
    3217 int has_ref_to_AUTO_nic_hdl(const char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    3218
    3219   Object * o = new Object();
    3220   GSList * attributes = NULL;
    3221   bool code;
    3222
    3223   code = o->scan_silent(object, strlen(object));
    3224
    3225   if(code && !(o->isDeleted)){
    3226     attributes = get_attributes(o, "admin-c", object);
    3227     if(attributes != NULL){
    3228       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    3229         g_slist_free(attributes);
    3230         delete(o);
    3231         return 1;
    3232       }
    3233     }
    3234     g_slist_free(attributes);
    3235     attributes = get_attributes(o, "tech-c", object);
    3236     if(attributes != NULL){
    3237       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    3238         g_slist_free(attributes);
    3239         delete(o);
    3240         return 1;
    3241       }
    3242     }
    3243
    3244     g_slist_free(attributes);
    3245     attributes = get_attributes(o, "zone-c", object);
    3246     if(attributes != NULL){
    3247       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    3248         g_slist_free(attributes);
    3249         delete(o);
    3250         return 1;
    3251       }
    3252     }
    3253     g_slist_free(attributes);
    3254     attributes = get_attributes(o, "author", object);
    3255     if(attributes != NULL){
    3256       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    3257         g_slist_free(attributes);
    3258         delete(o);
    3259         return 1;
    3260       }
    3261     }
    3262     /* if control reaches here, then we will return 0 */
    3263     delete(o);
    3264     return 0;
    3265   }else{/* it doesn't pass syntax check. So, it doesn't matter if
    3266            it contains refs to AUTO NIC hdls. */
    3267     delete(o);
    3268     return 0;
    3269   }
    3270
    3271 }
    3272
    3273
    3274
    3275
    3276
    3277
    3278
    3279
    3280
    3281 /* Gets the "From" line of the incoming mail message and finds out an
    3282    address to send the acknowledgement */
    3283 char * find_email_address(const char * from_line){
         /* [<][>][^][v][top][bottom][index][help] */
    3284   char * pos1 = NULL, * pos2 = NULL, * pos = NULL;
    3285   char * temp = NULL;
    3286   char * part1 = NULL, * part2 = NULL;
    3287
    3288   if(from_line == NULL){
    3289     return NULL;
    3290   }
    3291   if(strstr(from_line, "From:") != from_line){
    3292     temp = strdup(from_line);
    3293   }else{
    3294     temp = strdup(from_line + strlen("From:"));
    3295   }
    3296   g_strstrip(temp);
    3297   if(index(temp, '<')){/* then the line is something like '"John White" <john@inter.net>' */
    3298     pos1 = index(temp, '<');
    3299     pos2 = index(temp, '>');
    3300     temp = strncpy(temp, pos1 + 1, pos2 - pos1 -1);
    3301     temp[pos2 - pos1 - 1] = '\0';
    3302     if(tracing) {
    3303      printf("TRACING: find_email_address temp=[%s]\n", temp);
    3304     }
    3305
    3306   }
    3307
    3308
    3309
    3310
    3311   /* and now, we have to remove the parts in parantheses */
    3312   while(   index(temp, '(') != NULL && index(temp, ')') != NULL
    3313         && index(temp, '(') < index(temp, ')')){
    3314
    3315     part1 = strdup(temp);
    3316     /* terminate the string */
    3317     pos = index(part1, '(');
    3318     *pos = '\0';
    3319
    3320     part2 = strdup(index(temp, ')') + 1);
    3321     strcat(part1, part2);
    3322     free(temp);
    3323     temp = strdup(part1);
    3324     free(part1);
    3325     free(part2);
    3326
    3327   }
    3328
    3329   g_strstrip(temp);
    3330   return temp;
    3331
    3332 }
    3333
    3334
    3335
    3336
    3337
    3338
    3339 /* removes the '\n's and '\r's at the end of the arg, and returns it  */
    3340 char * UP_remove_EOLs(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    3341
    3342   while(strlen(arg) > 0 &&
    3343         (arg[strlen(arg) - 1] == '\n' ||
    3344          arg[strlen(arg) - 1] == '\r')){
    3345     arg[strlen(arg) - 1] = '\0';
    3346   }
    3347
    3348   return arg;
    3349 }
    3350
    3351
    3352
    3353
    3354
    3355
    3356
    3357
    3358
    3359
    3360 /* Duplicates the given arg, and replaces
    3361     $FROM,
    3362     $SUBJECT,
    3363     $MDATE,
    3364     $MSGID,
    3365     $CC,
    3366     $HUMAILBOX
    3367     $AUTOBOX
    3368     $FROMHOST
    3369
    3370     and $TIME & $DATE
    3371
    3372     strings with the corresponding variables.
    3373
    3374 */
    3375 char * UP_replace_globals(const char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    3376
    3377   GString * g_str;
    3378   int pos;
    3379   char * to_be_returned;
    3380   time_t cur_time;
    3381   char * temp, * time_str, * date_str;
    3382
    3383
    3384   /* get time */
    3385   cur_time = time(NULL);
    3386   temp = strdup(ctime(&cur_time));
    3387   /* temp is now something like "Fri Sep 13 00:00:00 1986\n\0", fields are const width */
    3388
    3389   time_str = (char *)malloc(9);
    3390   time_str = strncpy(time_str, temp + 11, 8);
    3391   time_str[8] = '\0';
    3392
    3393   date_str = (char *)malloc(16);
    3394   date_str = strncpy(date_str, temp, 11);
    3395   date_str[11] = '\0';
    3396   date_str = strncat(date_str, temp + 20, 4);
    3397
    3398
    3399   free(temp);
    3400
    3401   g_str = g_string_new(arg);
    3402
    3403   g_str = UP_replace_GStrings(g_str, "$TIME", time_str);
    3404
    3405   g_str = UP_replace_GStrings(g_str, "$DATE", date_str);
    3406
    3407   g_str = UP_replace_GStrings(g_str, "$SUBJECT", update_mail_subject);
    3408
    3409   g_str = UP_replace_GStrings(g_str, "$FROM", update_mail_sender);
    3410
    3411   g_str = UP_replace_GStrings(g_str, "$MDATE", update_mail_date);
    3412
    3413   g_str = UP_replace_GStrings(g_str, "$MSGID", update_mail_ID);
    3414
    3415   g_str = UP_replace_GStrings(g_str, "$CC", update_mail_cc);
    3416   if(update_mail_cc == NULL){
    3417     g_str = UP_replace_GStrings(g_str, "$CC", "");
    3418   }
    3419
    3420   g_str = UP_replace_GStrings(g_str, "$HUMAILBOX", humailbox);
    3421
    3422   g_str = UP_replace_GStrings(g_str, "$AUTOBOX", autobox);
    3423
    3424   g_str = UP_replace_GStrings(g_str, "$FROMHOST", netupdclientIP);
    3425
    3426   free(time_str);
    3427   free(date_str);
    3428
    3429   to_be_returned = strdup(g_str->str);
    3430   g_string_free(g_str, 1);
    3431   return to_be_returned;
    3432 }
    3433
    3434
    3435
    3436
    3437 /* Get the type of the object, which is represented as a char * */
    3438 char * get_class_type_char(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    3439   bool code;
    3440   Object * o;
    3441   char * type;
    3442   char * temp;
    3443
    3444   /* if there is no '\n' at the end of char * already, o->scan chokes. So, add it.
    3445    (no harm in having more than one) */
    3446   temp = (char *)malloc(strlen(object) + 2);
    3447   sprintf(temp, "%s\n", object);
    3448
    3449   if(tracing) {
    3450     printf("TRACING: get_class_type_char is running, object is \n[%s]\n", object);
    3451   }
    3452   o = new Object;
    3453   code = o->scan_silent(temp,strlen(temp));
    3454
    3455   type = get_class_type(o);
    3456
    3457   free(temp);
    3458   delete(o);
    3459   return type;
    3460
    3461 }
    3462
    3463
    3464
    3465
    3466
    3467 /* Adds the given file to the update log */
    3468 void UP_add_to_upd_log(const char * filename){
         /* [<][>][^][v][top][bottom][index][help] */
    3469
    3470   time_t now;
    3471   struct tm * tmstr;
    3472   time_t cur_time;
    3473   char * time_str;
    3474   char datestr[10];
    3475   char * updlogfile;
    3476   FILE * infile, * log_file;
    3477   char * buf;
    3478
    3479
    3480   /* We need to get the a date string to construct the updlog file name */
    3481   time(&now);
    3482   tmstr = localtime(&now);
    3483   strftime(datestr, 10, "%Y%m%d", tmstr);
    3484
    3485   /* now that we have the date string, we can construct updlog file name */
    3486   updlogfile = (char *)malloc(strlen(updlog) + strlen(datestr) + 2);
    3487   snprintf(updlogfile, strlen(updlog) + strlen(datestr) + 2,
    3488            "%s.%s", updlog, datestr);
    3489
    3490
    3491   if(( infile = fopen(filename, "r")) == NULL){
    3492     fprintf(stderr, "UP_add_to_upd_log: Can't open upd file, %s\n", filename);
    3493     return;
    3494   }
    3495
    3496   if(( log_file = fopen(updlogfile, "a")) == NULL){
    3497     fprintf(stderr, "UP_add_to_upd_log: Can't open upd log file, %s\n", log_file);
    3498     return;
    3499   }
    3500
    3501   /* get time */
    3502   cur_time = time(NULL);
    3503   time_str = strdup(ctime(&cur_time));
    3504   /* cut the '\n' at the end */
    3505   time_str[strlen(time_str) - 1] = '\0';
    3506
    3507   if(reading_from_mail){
    3508     fprintf(log_file, ">>> time: %s MAIL UPDATE <<<\n\n", time_str);
    3509   }else if(networkupdate){
    3510     fprintf(log_file, ">>> time: %s NETWORKUPDATE UPDATE <<<\n\n", time_str);
    3511   }else{
    3512     fprintf(log_file, ">>> time: %s UPDATE <<<\n\n", time_str);
    3513   }
    3514
    3515   free(time_str);
    3516
    3517   buf = (char *)malloc(1024);
    3518   while((buf=fgets(buf, 1023, infile)) > 0){
    3519     fprintf(log_file, "%s", buf);
    3520   }
    3521   free(buf);
    3522
    3523   fclose(infile);
    3524   fclose(log_file);
    3525
    3526 }
    3527
    3528
    3529
    3530 /* Logs the object to the update log */
    3531 void UP_log_networkupdate(const char * object, const char * host){
         /* [<][>][^][v][top][bottom][index][help] */
    3532
    3533   time_t now;
    3534   struct tm * tmstr;
    3535   time_t cur_time;
    3536   char * time_str;
    3537   char datestr[10];
    3538   char * updlogfile;
    3539   FILE * log_file;
    3540   char * buf;
    3541
    3542
    3543   /* We need to get the a date string to construct the updlog file name */
    3544   time(&now);
    3545   tmstr = localtime(&now);
    3546   strftime(datestr, 10, "%Y%m%d", tmstr);
    3547
    3548   /* now that we have the date string, we can construct updlog file name */
    3549   updlogfile = (char *)malloc(strlen(updlog) + strlen(datestr) + 2);
    3550   snprintf(updlogfile, strlen(updlog) + strlen(datestr) + 2,
    3551            "%s.%s", updlog, datestr);
    3552
    3553
    3554   if(( log_file = fopen(updlogfile, "a")) == NULL){
    3555     fprintf(stderr, "UP_add_to_upd_log: Can't open upd log file, %s\n", log_file);
    3556     return;
    3557   }
    3558
    3559   /* get time */
    3560   cur_time = time(NULL);
    3561   time_str = strdup(ctime(&cur_time));
    3562   /* cut the '\n' at the end */
    3563   time_str[strlen(time_str) - 1] = '\0';
    3564
    3565   fprintf(log_file, ">>> time: %s NETWORKUPDATE UPDATE (%s) <<<\n\n", time_str, host);
    3566
    3567   free(time_str);
    3568
    3569   fprintf(log_file, "%s\n", object);
    3570
    3571   fclose(log_file);
    3572
    3573
    3574 }

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