## 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. send_object_db
6. get_type
7. get_search_key
8. send_and_get
9. count_objects
10. strip_lines
11. take_objects
12. take_object
13. get_as_block
14. get_aut_num_object
15. get_less_specific_domain
16. get_less_specific_set
17. get_less_specific
18. get_less_spec_inetnum
19. get_exact_match_inetnum
20. get_exact_match_routes
21. get_less_spec_routes
22. get_mntners
23. get_attributes
24. get_attribute
25. strstr_in_list
26. get_auths
27. get_mnt_lowers
28. get_mnt_routes
29. get_mnt_routes_from_list
30. get_mnt_lowers_from_list
31. get_override
32. check_override
33. add_to_auth_vector
34. get_auth_vector
35. filter_out_diff_origins
36. check_auth
37. get_old_version
38. process_mail_header
39. stringPack
40. delete_delete_attrib
41. identical
42. find_initials
43. replace_AUTO_NIC_hdl
44. replace_refs_to_AUTO_NIC_hdl
45. has_AUTO_NIC_hdl
46. has_ref_to_AUTO_nic_hdl
47. add_to_ack
48. add_to_ack_string
49. process_object
50. find_to_address

       1 /***************************************
       2   $Revision: 1.18 $
       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 "dbupdate.h"
      35
      36 int error = 0; // a global variable to store the errors
      37 char * error_msg = NULL; // a global variable to store the error messages
      38 extern int tracing;
      39
      40 /* authorise function takes the auth_vector, credentials struct, and 'overriden'
      41    variable. If overriden == 1, then it immediately returns UP_AUTH_OK
      42    (because this means that the update contained a valid override attribute).
      43    Else, it goes through the auth_vector and when it finds a an "auth:"
      44    attribute which passes, then it returns UP_AUTH_OK. Otherwise, it returns
      45    UP_AUF (authorisation failed) */
      46
      47 int authorise(GSList * auth_vector, credentials_struct credentials, int overriden){
         /* [<][>][^][v][top][bottom][index][help] */
      48
      49   int result = 0;
      50
      51   if(tracing){
      52     printf("TRACING: authorise started with override: %i\n", overriden);
      53   }
      54
      55   /* If 'overriden' variable is 1, then return UP_AUTH_OK immediately */
      56   if(overriden == 1){
      57     return UP_AUTH_OK;
      58   }
      59   else{
      60     result = AU_authorise(auth_vector, credentials);
      61     if(tracing){
      62       printf("TRACING: authorise: AU_authorise returned %i\n", result);
      63     }
      64     if(result > 0){
      65       return UP_AUTH_OK;
      66     }
      67     else{
      68       return UP_AUF; /* authorisation failed */
      69     }
      70   }
      71 }
      72
      73 /* concatanates the string at the end of error_msg */
      74 void error_msg_cat(const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
      75
      76   if(string == NULL){
      77     return;
      78   }
      79   if(error_msg == NULL){
      80     error_msg = strdup(string);
      81   }else{
      82     error_msg = (char *)realloc(error_msg, strlen(error_msg) + strlen(string) + 2);
      83     error_msg = strcat(error_msg, "\n");
      84     error_msg = strcat(error_msg, string);
      85   }
      86 }
      87
      88
      89 /* interprets the result string coming from RIPupd
      90    It is called by send_object_db.
      91    It returns the error no returned from RIPupd.  */
      92
      93 int interpret_ripdb_result(const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
      94    char * error_no = NULL;
      95    char ** temp = NULL, ** temp2 = NULL;
      96    int i;
      97    int err = 0;
      98
      99   /* if the string is NULL or empty, then return error */
     100   if(string == NULL || strlen(string) == 0){
     101     error = UP_INT; /* internal error, RIPupd should return something */
     102     error_msg_cat("Internal error. RIPupd didn't return anything.");
     103     return 0;
     104   }
     105
     106   /* split the string into lines */
     107   temp = g_strsplit(string , "\n", 0);
     108   for(i = 0; temp[i] != NULL; i++){
     109     if(i == 0){/* this line must contain "%ERROR " string in the beginning */
     110       temp2 = g_strsplit(temp[0], " ", 0);
     111       error_no = strdup(temp2[1]);
     112       g_strfreev(temp2);
     113       err = atoi(error_no);
     114       printf("TRACING: interpret_ripdb_result: error_no is [%s]\n", error_no);
     115     }else if(error_no != NULL && strcmp(error_no, "0") != 0){
     116       error_msg_cat(temp[i]);
     117     }
     118   }
     119   g_strfreev(temp);
     120   //if(error_no != NULL && error_msg != NULL){
     121   //  printf("TRACING: interpret_ripdb_result: Error: [%s][%s]\n", error_no, error_msg);
     122   //}
     123   if(error_no != NULL){
     124     free(error_no);
     125   }
     126   return err; /* 0 means no error in this context */
     127 }
     128
     129
     130
     131 /* Gets assigned NIC hdl from the string that is returned from
     132    RIPupdate */
     133 void get_assigned_nic(char * nic_hdl, const char * string){
         /* [<][>][^][v][top][bottom][index][help] */
     134    char * error_no = NULL;
     135    char ** temp = NULL, ** temp2 = NULL;
     136    int i;
     137    //char * to_be_returned = NULL;
     138
     139   /* if the string is NULL or empty, then return error */
     140   if(string == NULL || strlen(string) == 0){
     141     error = UP_INT; /* internal error, RIPupd should return something */
     142     error_msg_cat("Internal error. RIPupd didn't return anything.");
     143     return;
     144   }
     145
     146   /* split the string into lines */
     147   temp = g_strsplit(string , "\n", 0);
     148   for(i = 0; temp[i] != NULL; i++){
     149     if(i == 0){/* this line must contain "%ERROR " string in the beginning */
     150       temp2 = g_strsplit(temp[0], " ", 0);
     151       error_no = strdup(temp2[1]);
     152       g_strfreev(temp2);
     153       printf("TRACING: get_assigned_nic: error_no is [%s]\n", error_no);
     154     }else if(error_no != NULL && strcmp(error_no, "0") != 0){
     155       error_msg_cat(temp[i]);
     156     }else if(error_no != NULL && strcmp(error_no, "0") == 0 && i == 1){/* look for assigned NIC hdl */
     157       printf("error_no != NULL && strcmp(error_no, \"0\") == 0 && i == 1\n");
     158       /* in the second line RIPupdate returns for example "I[65][EK3-RIPE]" We
     159          need to extract EK3-RIPE part */
     160       //to_be_returned = (char *)malloc(128); /* 128 should be enough for a NIC hdl */
     161       nic_hdl = strncpy(nic_hdl, rindex(temp[i],'[') + 1 ,
     162                                  rindex(temp[i],']') - rindex(temp[i],'[') - 1);
     163       nic_hdl[rindex(temp[i],']') - rindex(temp[i],'[') - 1] = '\0';
     164       if(nic_hdl != NULL){
     165         printf("DEBUG: get_assigned_nic will return [%s]\n", nic_hdl);
     166       }
     167       g_strfreev(temp);
     168       //return to_be_returned;
     169       return;
     170     }
     171   }
     172   g_strfreev(temp);
     173   if(error_no != NULL && error_msg != NULL){
     174     printf("TRACING: interpret_ripdb_result: Error: [%s][%s]\n", error_no, error_msg);
     175   }
     176   return;
     177 }
     178
     179
     180
     181 /* sends the object to the database. char * operation is either 'ADD' ,'DEL' or 'UPD'
     182    assigned_NIC is filled in if this is a person/role creation with AUTO nic hdl
     183    assigned_NIC must be allocated enough memory before send_object_db is called
     184
     185    If the called do not expect a NIC hdl back, then assigned_NIC can be given NULL
     186    */
     187 int send_object_db(char * arg, char * assigned_NIC, char * operation){
         /* [<][>][^][v][top][bottom][index][help] */
     188
     189         int sockfd, numbytes;
     190         char buf[MAXDATASIZE];
     191         struct hostent *he;
     192         struct sockaddr_in their_addr; /* connector's address information */
     193         char *result_string = NULL;
     194         char *to_be_returned = NULL;
     195         int err = 0;
     196
     197
     198         if ((he=gethostbyname(UPDATE_HOST)) == NULL) {  /* get the host info */
     199             perror("gethostbyname");
     200             exit(1);
     201         }
     202
     203         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     204             perror("socket");
     205             exit(1);
     206         }
     207
     208         their_addr.sin_family = AF_INET;      /* host byte order */
     209         their_addr.sin_port = htons(UPDATE_PORT);    /* short, network byte order */
     210         their_addr.sin_addr = *((struct in_addr *)he->h_addr);
     211         bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
     212
     213
     214         if (connect(sockfd, (struct sockaddr *)&their_addr,
     215                                               sizeof(struct sockaddr)) == -1) {
     216             perror("connect");
     217             exit(1);
     218         }
     219
     220         if (send(sockfd, operation , strlen(operation), 0) == -1)
     221             perror("send");
     222         if (send(sockfd, "\n\n" , strlen("\n\n"), 0) == -1)
     223             perror("send");
     224         if (send(sockfd, arg , strlen(arg), 0) == -1)
     225             perror("send");
     226         if (send(sockfd, "\n\n",2,0)  == -1)
     227             perror("send");
     228
     229
     230         while ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) != 0) {
     231             buf[numbytes] = '\0';
     232             printf("%s",buf);
     233             if(result_string == NULL){
     234               result_string = strdup(buf);
     235             }else{
     236               result_string = (char *)realloc(result_string,
     237                                  strlen(result_string) + strlen(buf) + 1);
     238               result_string = strcat(result_string, buf);
     239             }
     240         }
     241
     242         err = interpret_ripdb_result(result_string);
     243         if(assigned_NIC != NULL){ /* if the caller of the function expected to get a NIC handle */
     244           get_assigned_nic(assigned_NIC, result_string);
     245         }
     246         close(sockfd);
     247         return err; /* 0 means no error in this context */
     248 }
     249
     250
     251
     252
     253
     254
     255 /* takes a pre-parsed object, and returns its type */
     256 char * get_type(Object *arg){
         /* [<][>][^][v][top][bottom][index][help] */
     257
     258     char * be_returned = NULL;
     259     if(arg == NULL) return NULL;
     260     be_returned = strdup(arg->type->getName());
     261     return g_strstrip(be_returned);
     262 }
     263
     264
     265
     266
     267
     268
     269 /* takes an object (pre-parsed) and returns its first attrib if it is not
     270    a person, and returns the nic-hdl if it is a person object */
     271 char * get_search_key(Object *arg, char * type, const char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     272
     273
     274     Attr *attr;
     275     char *primary_key = NULL, *value = NULL;
     276
     277     if(arg == NULL) return NULL;
     278
     279     for(attr = arg->attrs.head(); attr; attr = arg->attrs.next(attr)){
     280        value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     281        strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     282            attr->len - strlen(attr->type->name()) -2 );
     283            value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     284        //cout << "value: #" << value << "#" << endl;
     285        if(strcmp(attr->type->name(),type) == 0 &&
     286               strcmp(type,"person") != 0){
     287          primary_key = strdup(value);
     288        }
     289        if(strcmp(attr->type->name(),"nic-hdl") == 0 &&
     290             strcmp(type,"person") == 0){
     291          primary_key = strdup(value);
     292        }
     293     }
     294     if(primary_key != NULL){
     295       return g_strstrip(primary_key);
     296     }else{
     297       return NULL;
     298     }
     299 }
     300
     301
     302
     303
     304 /* sends char * arg to the specified host's specified port, and
     305    returns the reply as a string. This is used to query the
     306    whois host. Probably we must use WC (whois client) module here,
     307    but it must be extented */
     308 char * send_and_get(char * host, int port, char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     309
     310         int sockfd, numbytes;
     311         char * result = NULL;
     312         char buf[MAXDATASIZE];
     313         struct hostent *he;
     314         struct sockaddr_in their_addr; /* connector's address information */
     315
     316         if(tracing) {
     317           printf("TRACING: send_and_get: arg : [%s]; port: [%i]; host: [%s]\n", arg, port, host);
     318         }
     319
     320         if ((he=gethostbyname(host)) == NULL) {  /* get the host info */
     321             perror("gethostbyname");
     322             exit(1);
     323         }
     324
     325         if(tracing) {
     326           printf("TRACING: send_and_get: called gethostbyname\n");
     327         }
     328
     329         if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
     330             perror("socket");
     331             exit(1);
     332         }
     333
     334         if(tracing) {
     335           printf("TRACING: send_and_get: called socket\n");
     336         }
     337
     338
     339         their_addr.sin_family = AF_INET;      /* host byte order */
     340         their_addr.sin_port = htons(port);    /* short, network byte order */
     341         their_addr.sin_addr = *((struct in_addr *)he->h_addr);
     342         bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
     343
     344         if (connect(sockfd, (struct sockaddr *)&their_addr,
     345                                               sizeof(struct sockaddr)) == -1) {
     346             perror("connect");
     347             exit(1);
     348         }
     349         if (send(sockfd, arg , strlen(arg), 0) == -1)
     350                perror("send");
     351         if (send(sockfd, "\n",1,0)  == -1)
     352                perror("send");
     353
     354
     355         while ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) != 0) {
     356             buf[numbytes] = '\0';
     357             if(result == NULL){
     358               result = strdup(buf);
     359             }else{
     360               result = (char *)realloc(result, strlen(result) + strlen(buf));
     361               result = strcat(result, buf);
     362             }
     363         }
     364
     365         close(sockfd);
     366         return result;
     367
     368
     369 }
     370
     371 /* counts the number of objects in a string */
     372 int count_objects(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     373     int count = 0;
     374     char *pos = NULL;
     375     char *temp = NULL;
     376
     377     if(tracing) {
     378       printf("TRACING: count_objects running\n");
     379     }
     380
     381     if(arg != NULL){
     382       temp = strdup(arg);
     383     }else{
     384       return 0;
     385     }
     386
     387     if(isalpha(arg[0])){
     388       count++;
     389     }else if(arg[0] == '\n' && isalpha(arg[1])){
     390       count++;
     391     }
     392     while(pos = strstr(temp,"\n\n")){
     393       pos[0] = 'a'; /* something non-EOL so that it won't be caught in the next loop */
     394       if(isalpha(pos[2])){
     395         count++;
     396       }
     397     }
     398     if(tracing) {
     399       cout << "TRACING: count_objects returning " << count << endl;
     400     }
     401     return count;
     402 }
     403
     404
     405 /* strips lines beginning with '%' off  */
     406 char * strip_lines(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     407
     408     char ** temp = NULL;
     409     char * string = NULL;
     410     int i;
     411
     412     if(arg == NULL){
     413        return NULL;
     414     }
     415
     416     /* split the string into lines */
     417     temp = g_strsplit (arg, "\n", 0);
     418
     419     for(i=0; temp[i] != NULL; i++){
     420       if(temp[i][0] != '%'){
     421         if(string == NULL){
     422           string = strdup(temp[i]);
     423         }else{
     424           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 1);
     425           string = strcat(string, "\n");
     426           string = strcat(string, temp[i]);
     427         }
     428       }
     429     }
     430     return string;
     431 }
     432
     433 /* Separates the objects in the given char * arg using "\n\n" as
     434    separator. Returns a linked list whose data consist of separated
     435    objects as  char *  */
     436
     437 GSList * take_objects(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     438     char ** objects=NULL;
     439     char ** temp = NULL;
     440     GSList * tobereturned = NULL;
     441     int i;
     442
     443     arg = strip_lines(arg);
     444
     445     objects =  g_strsplit(arg, "\n\n", 1000);
     446     temp = objects;
     447     for(i=0; temp[i] != NULL; i++){
     448       /* stripe off the trailing and leading white spaces-eols*/
     449       g_strstrip(temp[i]);
     450       if(strlen(temp[i]) > 0){/* if not an empty string */
     451         tobereturned = g_slist_append(tobereturned, temp[i]);
     452       }
     453     }
     454     return tobereturned;
     455 }
     456
     457
     458
     459
     460
     461 /* takes the first object in the given char *, using empty lines as
     462    separator */
     463 char * take_object(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
     464     char * object = NULL, * pos = NULL;
     465     char * temp = strdup(arg);
     466
     467     if(isalpha(temp[0])){
     468       if(strstr(temp,"\n\n") == NULL){
     469         return temp;
     470       }else{
     471         pos = strstr(temp,"\n\n");
     472         pos[0] = '\0';
     473         return temp;
     474       }
     475     }else if(temp[0] == '\n' && isalpha(temp[1])){
     476       if(strstr(temp,"\n\n") == NULL){
     477         return (char *)temp[1];
     478       }else{
     479         pos = strstr(temp,"\n\n");
     480         pos[0] = '\0';
     481         return (char *)temp[1];
     482       }
     483     }else{
     484       temp = strstr(temp,"\n\n");
     485       temp = temp + 2;
     486       if(strstr(temp,"\n\n") == NULL){
     487         return temp;
     488       }else{
     489         pos = strstr(temp,"\n\n");
     490         pos[0] = '\0';
     491         return temp;
     492       }
     493     }
     494 }
     495
     496
     497
     498
     499
     500 /* Takes an autnum_object, and returns the as-block containing this aut-num */
     501 char * get_as_block(char *autnum_object){
         /* [<][>][^][v][top][bottom][index][help] */
     502   bool code;
     503   char * search_key = NULL, * query_string = NULL;
     504   char * result = NULL;
     505   Object * o = new Object();
     506
     507   code = o->scan(autnum_object, strlen(autnum_object));
     508   search_key = get_search_key(o,"aut-num",autnum_object);
     509
     510   query_string = (char *)malloc(strlen("-Tas-block -r ")+strlen(search_key)+1);
     511   sprintf(query_string, "-Tas-block -r %s",search_key);
     512   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     513   if(count_objects(result) == 0){
     514     cout << "No such as-block" << endl;
     515     return NULL;
     516   }else if(count_objects(result) > 1){
     517     cout << "More than one as-block returned" << endl;
     518     return NULL;
     519   }else{ /* count_objects(result) == 1 */
     520     return take_object(result);
     521   }
     522
     523 }
     524
     525
     526 /* Takes a route_object, and returns the aut-num mentioned in origin
     527    attribute of this route */
     528 char * get_aut_num_object(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     529   bool code;
     530   char * search_key = NULL, * query_string = NULL;
     531   char * result = NULL;
     532   Object * o = new Object();
     533
     534   code = o->scan(route_object, strlen(route_object));
     535   search_key = get_search_key(o,"origin",route_object);
     536
     537   query_string = (char *)malloc(strlen("-Tas-block -r ")+strlen(search_key)+1);
     538   sprintf(query_string, "-Taut-num -r %s",search_key);
     539   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     540   if(count_objects(result) == 0){
     541     cout << "No such aut-num" << endl;
     542     return NULL;
     543   }else if(count_objects(result) > 1){
     544     cout << "More than one aut-num returned" << endl;
     545     return NULL;
     546   }else{ /* count_objects(result) == 1 */
     547     return take_object(result);
     548   }
     549
     550 }
     551
     552
     553
     554
     555 /* Takes a domain_object, and returns the less specific domain of it */
     556 char * get_less_specific_domain(char *domain_object){
         /* [<][>][^][v][top][bottom][index][help] */
     557   bool code;
     558   char * search_key = NULL, * query_string = NULL;
     559   char * result = NULL, * domain = NULL;
     560   Object * o = new Object();
     561   int i,j, length;
     562   char * temp = NULL;
     563   char ** splitted;
     564
     565   code = o->scan(domain_object, strlen(domain_object));
     566   domain = get_search_key(o,"domain",domain_object);
     567
     568   /* split the domain from its dots ('50' is the max # of pieces, this number is just arbitrary) */
     569   splitted =   g_strsplit((char *)strdup(domain), ".", 50);
     570
     571   for(i=1; splitted[i] != NULL; i++){
     572     /* in the following for loop, we will construct the 'less spec' domains
     573        to be looked up in the DB */
     574     for(j=i; splitted[j] !=NULL; j++){
     575       length = 0;
     576       if(temp!=NULL){
     577         length = strlen(temp);
     578       }
     579       temp = (char *)realloc(temp, length + strlen(splitted[j]) + 2);
     580       if(j==i){
     581         temp = (char *)strdup(splitted[j]);
     582       }else{
     583         sprintf(temp, "%s.%s", temp, splitted[j]);
     584       }
     585     }
     586     query_string = (char *)malloc(strlen("-Tdomain -r -R ")+strlen(temp)+1);
     587     sprintf(query_string, "-Tdomain -r -R %s", temp);
     588     result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     589     if(count_objects(result) == 0){
     590     }else if(count_objects(result) > 1){
     591       if(tracing){
     592         cout << "TRACING: get_less_specific_domain: More than one domains returned" << endl;
     593       }
     594       return NULL; /* error condition */
     595     }else{ /* count_objects(result) == 1 */
     596       return take_object(result);
     597     }
     598
     599   }
     600   /* release the memory allocated to **splitted */
     601   for(i=0; splitted[i] != NULL; i++){
     602     free(splitted[i]);
     603   }
     604   /* so, we couldn't  find any 'less specific' domain */
     605   return NULL;
     606 }
     607
     608
     609
     610
     611
     612 /* Takes a hierarchical set_object, and returns the less specific set or auth-num of it
     613    by striping down the object's name ( eg, for as35:rs-trial:rs-myset,
     614    as35:rs-trial is tried ) */
     615 char * get_less_specific_set(char *set_object, char *type){
         /* [<][>][^][v][top][bottom][index][help] */
     616   bool code;
     617   char * search_key = NULL, * query_string = NULL;
     618   char * result = NULL;
     619   Object * o = new Object();
     620   int i;
     621
     622   code = o->scan(set_object, strlen(set_object));
     623   search_key = get_search_key(o, type, set_object);
     624   delete(o);
     625
     626   for(i = strlen(search_key) -1; i > -1; i--){
     627     if(search_key[i] == ':'){
     628       search_key[i] = '\0'; /* truncate the string */
     629       break;
     630     }
     631     if(i == 0){/* if we've reached the beginning of the string
     632                 (this means there wasn't any ';' in the string) */
     633       free(search_key);
     634       search_key = NULL;
     635     }
     636   }
     637   if( search_key == NULL || strlen(search_key) == 0){/* this mustn't happen in fact, since
     638                                                         we make sure that the name of the
     639                                                         set_object contains a ':' in a proper place */
     640     return NULL;
     641   }
     642
     643
     644   query_string = (char *)malloc(strlen("-Taut-num,as-set,rtr-set,peering-set,filter-set -r ")+strlen(search_key)+1);
     645   sprintf(query_string, "-Taut-num,as-set,rtr-set,peering-set,filter-set -r  %s", search_key);
     646   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     647   if(count_objects(result) == 0){
     648     cout << "No such object"  << endl;
     649     return NULL;
     650   }else if(count_objects(result) > 1){
     651     cout << "More than one objects returned" << endl;
     652     return NULL;
     653   }else{ // count_objects(result) == 1
     654     return take_object(result);
     655   }
     656
     657 }
     658
     659
     660
     661
     662
     663
     664
     665 /* Takes an inetnum or inet6num object and returnes one less specific of it */
     666 char * get_less_specific(char *inetnum_object, char *type){
         /* [<][>][^][v][top][bottom][index][help] */
     667   bool code;
     668   char * search_key = NULL, * query_string = NULL;
     669   char * result = NULL;
     670   Object * o = new Object();
     671
     672   code = o->scan(inetnum_object, strlen(inetnum_object));
     673   search_key = get_search_key(o, type, inetnum_object);
     674
     675   query_string = (char *)malloc(strlen("-Tinet6num -r -l ") + strlen(search_key) + 1);
     676   sprintf(query_string, "-T%s -r -l %s",type, search_key);
     677   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     678   if(count_objects(result) == 0){
     679     cout << "No such " << type << endl;
     680     return NULL;
     681   }else if(count_objects(result) > 1){
     682     cout << "More than one " << type << " returned" << endl;
     683     return NULL;
     684   }else{ /* count_objects(result) == 1 */
     685     return take_object(result);
     686   }
     687
     688 }
     689
     690
     691
     692 /* Takes a route object and returnes one less specific inetnum */
     693 char * get_less_spec_inetnum(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     694   bool code;
     695   char * search_key = NULL, * query_string = NULL;
     696   char * result = NULL;
     697   Object * o = new Object();
     698
     699   code = o->scan(route_object, strlen(route_object));
     700   search_key = get_search_key(o, "route", route_object);
     701
     702   query_string = (char *)malloc(strlen("-Tinetnum -r -l ") + strlen(search_key) + 1);
     703   sprintf(query_string, "-Tinetnum -r -l %s", search_key);
     704   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     705   if(count_objects(result) == 0){
     706     cout << "No such inetnum" << endl;
     707     return NULL;
     708   }else if(count_objects(result) > 1){
     709     cout << "More than one inetnums returned" << endl;
     710     return NULL;
     711   }else{ /* count_objects(result) == 1 */
     712     return take_object(result);
     713   }
     714
     715 }
     716
     717
     718 /* Takes a route object and returnes exact match inetnum */
     719 char * get_exact_match_inetnum(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     720   bool code;
     721   char * search_key = NULL, * query_string = NULL;
     722   char * result = NULL;
     723   Object * o = new Object();
     724
     725   code = o->scan(route_object, strlen(route_object));
     726   search_key = get_search_key(o, "route", route_object);
     727
     728   query_string = (char *)malloc(strlen("-Tinetnum -r -x ") + strlen(search_key) + 1);
     729   sprintf(query_string, "-Tinetnum -r -x %s", search_key);
     730   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     731   if(count_objects(result) == 0){
     732     cout << "No such inetnum" << endl;
     733     return NULL;
     734   }else if(count_objects(result) > 1){
     735     cout << "More than one inetnums returned" << endl;
     736     return NULL;
     737   }else{ /* count_objects(result) == 1 */
     738     return take_object(result);
     739   }
     740
     741 }
     742
     743
     744
     745 /* Takes a route object and returnes exact matches of this route */
     746 GSList * get_exact_match_routes(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     747   bool code;
     748   char * search_key = NULL, * query_string = NULL;
     749   char * result = NULL;
     750   Object * o = new Object();
     751
     752   code = o->scan(route_object, strlen(route_object));
     753   search_key = get_search_key(o, "route", route_object);
     754
     755   query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(search_key) + 1);
     756   sprintf(query_string, "-Troute -r -x %s", search_key);
     757   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     758   if(count_objects(result) == 0){
     759     cout << "get_exact_match_routes: No such route" << endl;
     760     return NULL;
     761   }else{ /* count_objects(result) == 1 */
     762     return take_objects(result);
     763   }
     764
     765 }
     766
     767
     768
     769 /* Takes a route object and returns (immediate) less specifics of this route */
     770 GSList * get_less_spec_routes(char *route_object){
         /* [<][>][^][v][top][bottom][index][help] */
     771   bool code;
     772   char * search_key = NULL, * query_string = NULL;
     773   char * result = NULL;
     774   Object * o = new Object();
     775
     776   code = o->scan(route_object, strlen(route_object));
     777   search_key = get_search_key(o, "route", route_object);
     778
     779   query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(search_key) + 1);
     780   sprintf(query_string, "-Troute -r -l %s", search_key);
     781   result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
     782   if(count_objects(result) == 0){
     783     cout << "get_less_spec_routes: No such route" << endl;
     784     return NULL;
     785   }else{ /* count_objects(result) == 1 */
     786     return take_objects(result);
     787   }
     788
     789 }
     790
     791
     792
     793 /* Gets an object as a string and returns its 'mnt-by' attributes as a
     794    GSList (linked list)   */
     795
     796 GSList *get_mntners(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
     797   bool code;
     798   Object * o;
     799   Attr *attr;
     800   char *value  = NULL;
     801   GSList *list_of_mntners = NULL;
     802
     803   if(tracing) {
     804     printf("TRACING: get_mntners is running\n");
     805   }
     806   o = new Object;
     807   code = o->scan(object,strlen(object));
     808
     809   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     810     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     811     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
     812         attr->len - strlen(attr->type->name()) -2 );
     813     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     814     //cout << "value: #" << value << "#" << endl;
     815     if(strcmp(attr->type->name(),"mnt-by") == 0){
     816       if(tracing) {
     817         cout << "TRACING: get_mntners: adding " << g_strstrip(value) << endl;
     818       }
     819       list_of_mntners = g_slist_append(list_of_mntners, strdup(g_strstrip(value)));
     820     }
     821     free(value);
     822   }
     823
     824
     825   return list_of_mntners;
     826 }
     827
     828
     829 /* Gets a preparsed object, its text and an attribute name. Returns a list of
     830    attribute values */
     831 GSList *get_attributes(Object * o, const char * attrib, const char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     832
     833   char * value = NULL;
     834   Attr *attr;
     835   GSList *list_of_attributes = NULL;
     836
     837   //if(tracing) {
     838   //  printf("TRACING: get_attributes is running\n");
     839   //}
     840
     841   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     842     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     843     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     844         attr->len - strlen(attr->type->name()) -2 );
     845     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     846     if(strcmp(attr->type->name(), attrib) == 0){
     847       if(tracing) {
     848         cout << "TRACING: get_attributes: adding " << g_strstrip(value) << endl;
     849       }
     850       list_of_attributes = g_slist_append(list_of_attributes, strdup(g_strstrip(value)));
     851     }
     852     //free(value);
     853   }
     854
     855   //if(tracing) {
     856   //  printf("TRACING: get_attributes is returning\n");
     857   //}
     858
     859   return list_of_attributes;
     860 }
     861
     862
     863 /* Gets a preparsed object, an attribute name. Returns the value of first occurence
     864    of this attribute */
     865 char *get_attribute(Object * o, const char * attrib, char * text){
         /* [<][>][^][v][top][bottom][index][help] */
     866
     867   char * value = NULL;
     868   Attr *attr;
     869
     870   if(tracing) {
     871     printf("TRACING: get_attributes is running\n");
     872   }
     873
     874   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     875     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     876     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
     877         attr->len - strlen(attr->type->name()) -2 );
     878     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     879     if(strcmp(attr->type->name(), attrib) == 0){
     880       if(tracing) {
     881         cout << "TRACING: get_attribute: will return " << value << endl;
     882       }
     883       return value;
     884     }else{
     885       free(value);
     886     }
     887   }
     888
     889   if(tracing) {
     890     printf("TRACING: get_attribute is returning\n");
     891   }
     892
     893   return NULL;
     894 }
     895
     896
     897
     898 /* Gets a GSList of strings and returns 1 if one of them starts with substr, 0 otherwise */
     899 int strstr_in_list(GSList * list, const char * substr){
         /* [<][>][^][v][top][bottom][index][help] */
     900
     901  GSList * next = NULL;
     902  char * word;
     903
     904   if(tracing) {
     905     printf("TRACING: strstr_in_list is running\n");
     906   }
     907
     908  for( next = list; next != NULL ; next = g_slist_next(next) ){
     909    word = strdup((char *)next->data);
     910    g_strup(word);
     911    if(strstr(word, substr) == word){
     912      free(word);
     913      return 1;
     914    }
     915    free(word);
     916  }
     917  /* none of them matched, so return 0 */
     918  return 0;
     919 }
     920
     921
     922
     923
     924
     925 /* Gets a (maintainer) object as a string and returns its 'auth' attributes
     926    as a GSList (linked list) */
     927
     928 GSList *get_auths(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
     929   bool code;
     930   Object * o;
     931   Attr *attr;
     932   char *value  = NULL;
     933   GSList *list_of_auths = NULL;
     934
     935   if(tracing){
     936     printf("TRACING: get_auths is running\n");
     937   }
     938   o = new Object;
     939   code = o->scan(object,strlen(object));
     940
     941   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     942     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     943     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
     944         attr->len - strlen(attr->type->name()) -2 );
     945     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     946     //cout << "value: #" << value << "#" << endl;
     947     if(strcmp(attr->type->name(),"auth") == 0){
     948       if(tracing) {
     949         cout << "TRACING: get_auths: adding " << g_strstrip(value) << endl;
     950       }
     951       list_of_auths = g_slist_append(list_of_auths, strdup(g_strstrip(value)));
     952       if(tracing) {
     953         cout << "TRACING: get_auths: # of nodes in list_of_auths is now " << g_slist_length(list_of_auths) << endl;
     954       }
     955     }
     956   }
     957
     958   if(tracing) {
     959     cout << "TRACING: get_auths: returning (with " << g_slist_length(list_of_auths) << " nodes)" << endl;
     960   }
     961   return list_of_auths;
     962 }
     963
     964
     965
     966
     967
     968 /* Gets an object as a string an returns its mnt_lower attributes as a
     969    GSList (linked list) */
     970
     971 GSList *get_mnt_lowers(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
     972   bool code;
     973   Object * o;
     974   Attr *attr;
     975   char *value  = NULL;
     976   GSList *list_of_mnt_lowers = NULL;
     977
     978
     979   if(tracing) {
     980     printf("TRACING: get_mnt_lowers is running\n");
     981   }
     982   o = new Object;
     983   code = o->scan(object,strlen(object));
     984
     985   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
     986     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
     987     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
     988         attr->len - strlen(attr->type->name()) -2 );
     989     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
     990     //cout << "value: #" << value << "#" << endl;
     991     if(strcmp(attr->type->name(),"mnt-lower") == 0){
     992       if(tracing) {
     993         cout << "TRACING: get_mnt_lowers: adding " << g_strstrip(value) << endl;
     994       }
     995       list_of_mnt_lowers = g_slist_append(list_of_mnt_lowers, strdup(g_strstrip(value)));
     996     }
     997   }
     998
     999
    1000   return list_of_mnt_lowers;
    1001 }
    1002
    1003
    1004 /* Gets an object as a string an returns its mnt_routes attributes as a
    1005    GSList (linked list) */
    1006
    1007 GSList *get_mnt_routes(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1008   bool code;
    1009   Object * o;
    1010   Attr *attr;
    1011   char *value  = NULL;
    1012   GSList *list_of_mnt_routes = NULL;
    1013
    1014   if(tracing) {
    1015   cout << "TRACING: get_mnt_routes is running" << endl;
    1016   }
    1017   o = new Object;
    1018   code = o->scan(object,strlen(object));
    1019
    1020   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1021     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1022     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1023         attr->len - strlen(attr->type->name()) -2 );
    1024     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1025     //cout << "value: #" << value << "#" << endl;
    1026     if(strcmp(attr->type->name(),"mnt-routes") == 0){
    1027       if(tracing) {
    1028         cout << "TRACING: get_mnt_routes: adding " << g_strstrip(value) << endl;
    1029       }
    1030       list_of_mnt_routes = g_slist_append(list_of_mnt_routes, strdup(g_strstrip(value)));
    1031     }
    1032   }
    1033
    1034   return list_of_mnt_routes;
    1035 }
    1036
    1037
    1038 /* Gets a linked list of objects and returns the mnt_routes attribs of
    1039    them in a linked list */
    1040 GSList *get_mnt_routes_from_list(GSList * objects){
         /* [<][>][^][v][top][bottom][index][help] */
    1041   GSList *next = NULL;
    1042   GSList *list_of_mnt_routes = NULL;
    1043
    1044   for( next = objects; next != NULL ; next = g_slist_next(next) ){
    1045     list_of_mnt_routes = g_slist_concat(list_of_mnt_routes, get_mnt_routes((char *)next->data));
    1046   }
    1047
    1048   return list_of_mnt_routes;
    1049 }
    1050
    1051
    1052
    1053 /* Gets a linked list of objects and returns the mnt_routes attribs of
    1054    them in a linked list */
    1055 GSList *get_mnt_lowers_from_list(GSList * objects){
         /* [<][>][^][v][top][bottom][index][help] */
    1056   GSList *next = NULL;
    1057   GSList *list_of_mnt_lowers = NULL;
    1058
    1059   for( next = objects; next != NULL ; next = g_slist_next(next) ){
    1060     list_of_mnt_lowers = g_slist_concat(list_of_mnt_lowers, get_mnt_lowers((char *)next->data));
    1061   }
    1062
    1063   return list_of_mnt_lowers;
    1064 }
    1065
    1066
    1067
    1068 /* retrieves the override password from the 'override' attribute
    1069    of the object. If none, it returns NULL   */
    1070 char *get_override(char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    1071   bool code;
    1072   Object * o;
    1073   Attr *attr;
    1074   char *value  = NULL;
    1075
    1076   if(tracing){
    1077     printf("TRACING: get_override is running\n");
    1078   }
    1079   o = new Object;
    1080   code = o->scan(object,strlen(object));
    1081
    1082   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    1083     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
    1084     strncpy(value, (char *)(object+attr->offset) + strlen(attr->type->name())+1,
    1085         attr->len - strlen(attr->type->name()) -2 );
    1086     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
    1087     //cout << "value: #" << value << "#" << endl;
    1088     if(strcmp(attr->type->name(),"override") == 0){
    1089       if(tracing) {
    1090         cout << "TRACING: get_override: returning " << g_strstrip(value) << endl;
    1091       }
    1092       return  strdup(g_strstrip(value));
    1093     }
    1094   }
    1095   /* there was no 'override' attrib, so return NULL */
    1096   return NULL;
    1097 }
    1098
    1099
    1100
    1101
    1102
    1103
    1104 /* checks override string (password)
    1105    returns OVR_OK if it is correct password */
    1106 int check_override(char * string){
         /* [<][>][^][v][top][bottom][index][help] */
    1107    char ** temp;
    1108    int i;
    1109    char * crypted_password = strdup(CRYPTEDPASSWD);
    1110    if(string == NULL) {
    1111      if(tracing) {
    1112        printf("TRACING: check_override is returning FAILED\n");
    1113      }
    1114      return UP_OVF; /* override attempt failed */
    1115    }else{
    1116     /* split the string */
    1117      temp = g_strsplit (string, " ", 0);
    1118
    1119      for(i=0; temp[i] != NULL; i++){
    1120        if(strlen(temp[i]) != 0){
    1121          printf("%s\n", temp[i]);
    1122          if(strcmp(AU_crypt(temp[i], crypted_password), crypted_password) == 0){
    1123            g_strfreev(temp);
    1124            if(tracing) {
    1125              printf("TRACING: check_override is returning OK\n", string);
    1126            }
    1127            return OVR_OK;
    1128          }
    1129        }
    1130      }
    1131
    1132      g_strfreev(temp);
    1133      /* we couldn't find a word matching the override password */
    1134           return UP_OVF; /* override attempt failed */
    1135    }
    1136 }
    1137
    1138
    1139
    1140
    1141
    1142
    1143
    1144 /* takes a GSList of struct auth_struct and a GSList of auths, and a mntner name,
    1145    add new elements to GSList of struct auth_struct and  returns the new
    1146    GSList of struct auth_struct  */
    1147
    1148 GSList * add_to_auth_vector(GSList * list_of_auth_struct, GSList * auths, char * mntner_name){
         /* [<][>][^][v][top][bottom][index][help] */
    1149    //GSList * to_be_returned = NULL;
    1150    GSList * next;
    1151    char * auth_attrib = NULL;
    1152    char * auth_attrib_uppercase = NULL, * argument = NULL;
    1153    //struct auth_struct * temp = NULL;
    1154    auth_struct * temp = NULL;
    1155    int index = 1;
    1156
    1157    for(next = auths; next != NULL; next = g_slist_next(next)){
    1158      auth_attrib = strdup((char *)next->data);
    1159      auth_attrib = g_strstrip(auth_attrib);
    1160      if(tracing) {
    1161        cout << "TRACING: add_to_auth_vector: " << auth_attrib << endl;
    1162      }
    1163      /* Take the auth attribute and convert it into uppercase for comparisons */
    1164      auth_attrib_uppercase = strdup(auth_attrib);
    1165      g_strup(auth_attrib_uppercase);
    1166
    1167      if(strstr(auth_attrib_uppercase,"CRYPT-PW") == auth_attrib_uppercase){
    1168        /* take the argument of the auth attribute */
    1169        argument = strdup(auth_attrib + strlen("CRYPT-PW"));
    1170        g_strstrip(argument);
    1171        if(tracing) {
    1172          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1173        }
    1174        //temp = (struct auth_struct *)malloc(sizeof(auth_struct));
    1175        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1176        temp->type = AU_CRYPT_PW;
    1177        temp->auth = argument;
    1178        temp->mntner_name = mntner_name;
    1179        temp->index = index++;
    1180        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1181      }else if(strstr(auth_attrib_uppercase,"MAIL-FROM") == auth_attrib_uppercase){
    1182        /* take the argument of the auth attribute */
    1183        argument = strdup(auth_attrib + strlen("MAIL-FROM"));
    1184        g_strstrip(argument);
    1185        if(tracing) {
    1186          cout << "TRACING: add_to_auth_vector: adding new argument: " << argument << endl;
    1187        }
    1188        //temp = (struct auth_struct *)malloc(sizeof(auth_struct));
    1189        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1190        temp->type = AU_MAIL_FROM;
    1191        temp->auth = argument;
    1192        temp->mntner_name = mntner_name;
    1193        temp->index = index++;
    1194        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1195      }else if(strstr(auth_attrib_uppercase,"NONE") == auth_attrib_uppercase){
    1196        /* take the argument of the auth attribute */
    1197        //argument = strdup(auth_attrib + strlen("NONE"));
    1198        //g_strstrip(argument);
    1199        //cout << "DEBUG: add_to_auth_vector: adding new argument: " << argument << endl;
    1200        //temp = (struct auth_struct *)malloc(sizeof(auth_struct));
    1201        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1202        temp->type = AU_NONE;
    1203        temp->auth = NULL;
    1204        temp->mntner_name = mntner_name;
    1205        temp->index = index++;
    1206        list_of_auth_struct = g_slist_append(list_of_auth_struct, temp);
    1207     }else if(strstr(auth_attrib_uppercase,"PGP-") == auth_attrib_uppercase){
    1208        //temp = (struct auth_struct *)malloc(sizeof(auth_struct));
    1209        temp = (auth_struct *)malloc(sizeof(auth_struct));
    1210        temp->type = AU_PGP;
    1211        temp->mntner_name = mntner_name;
    1212        temp->index = index++;
    1213        /* temp->pgp_struct must be assigned, not yet implemented */
    1214        cout << "Not implemented totally (PGP)" << endl;
    1215      }else{
    1216        cout << "DEBUG: Error: invalid auth attrib: " << auth_attrib << endl;
    1217        return NULL;
    1218      }
    1219    }
    1220    free(auth_attrib_uppercase);
    1221    free(auth_attrib);
    1222    return list_of_auth_struct;
    1223
    1224 }
    1225
    1226
    1227
    1228
    1229
    1230
    1231
    1232
    1233
    1234
    1235 /* constructs the authorisation vector, which is a GSList of
    1236    struct auth_struct */
    1237
    1238 GSList * get_auth_vector(GSList * mntners){
         /* [<][>][^][v][top][bottom][index][help] */
    1239   GSList * list_of_auths = NULL;
    1240   GSList * next = NULL;
    1241   GSList * to_be_returned = NULL;
    1242   char * query_string = NULL, * result = NULL, * object = NULL;
    1243   GSList * temp;
    1244
    1245   for( next = mntners; next != NULL ; next = g_slist_next(next) ){
    1246     if(tracing) {
    1247       cout << "=====" << endl << "Got a mntner" << endl;
    1248       cout << (char *)next->data << endl;
    1249     }
    1250     query_string = (char *)malloc(strlen("-Tmntner -r ")+strlen((char *)next->data)+1);
    1251     sprintf(query_string, "-Tmntner -r %s",(char *)next->data);
    1252     result = send_and_get(QUERY_HOST, QUERY_PORT, query_string);
    1253     if(count_objects(result) == 0){
    1254       //if(tracing) {
    1255       //  cout << "No such maintainer, exiting" << endl;
    1256       //}
    1257       //exit(1);
    1258       /* no such maintainer */
    1259       return NULL;
    1260     }else if(count_objects(result) > 1){
    1261       if(tracing) {
    1262         cout << "More than one objects returned" << endl;
    1263       }
    1264     }else{ /* count_objects(result) == 1 */
    1265       object = take_object(result);
    1266       if(tracing) {
    1267         printf("TRACING: get_auth_vector: Calling get_auths(char *)\n");
    1268       }
    1269       temp = get_auths(object);
    1270       if(tracing) {
    1271         cout << "TRACING: get_auth_vector: get_auths(char *) returned (with " << g_slist_length(temp) << " nodes)" << endl;
    1272       }
    1273       list_of_auths = g_slist_concat(list_of_auths, temp);
    1274       if(tracing) {
    1275         cout << "TRACING: get_auth_vector: list_of_auths has now " <<  g_slist_length(list_of_auths) << " nodes" << endl;
    1276       }
    1277       /* add this to the auth_vector. ( next->data is the name of the maintainer  ) */
    1278       if(tracing) {
    1279        cout << "TRACING: get_auth_vector: to_be_returned has now " <<  g_slist_length(to_be_returned) << " nodes" << endl;
    1280       }
    1281       to_be_returned = add_to_auth_vector(to_be_returned, list_of_auths, (char *)next->data);
    1282     }
    1283   }
    1284
    1285   if(tracing) {
    1286     printf("TRACING: get_auth_vector: to_be_returned has %i nodes\n", g_slist_length(to_be_returned));
    1287   }
    1288   return to_be_returned;
    1289 }
    1290
    1291
    1292 /* gets one or more route objects filters out the ones which don't have the same
    1293    origin as 'char * origin' argument */
    1294 char * filter_out_diff_origins(char * objects, char * origin){
         /* [<][>][^][v][top][bottom][index][help] */
    1295   GSList * object_list = NULL, * next =NULL;
    1296   char * objects_to_be_returned = NULL;
    1297   bool code;
    1298   char * key = NULL;
    1299   Object * o = new Object();
    1300
    1301
    1302   if(tracing) {
    1303     printf("TRACING: filter_out_diff_origins\n");
    1304   }
    1305
    1306   /* strip the lines beginning with '%' off */
    1307   objects = strip_lines(objects);
    1308
    1309   /* separate the objects, store them in a linked list */
    1310   object_list = take_objects(objects);
    1311
    1312   for(next = object_list; next != NULL; next = g_slist_next(next)){
    1313     code = o->scan((char *)next->data, strlen((char *)next->data));
    1314     key = get_search_key(o, "origin", (char *)next->data);
    1315     if(key != NULL && strcasecmp(g_strstrip(origin), key) == 0){
    1316       if(objects_to_be_returned == NULL){
    1317         objects_to_be_returned = strdup((char *)next->data);
    1318       }else{
    1319         objects_to_be_returned = (char *)realloc(objects_to_be_returned,
    1320                       strlen(objects_to_be_returned) + strlen((char *)next->data) + 2);
    1321         objects_to_be_returned = strcat(objects_to_be_returned, "\n");
    1322         objects_to_be_returned = strcat(objects_to_be_returned, (char *)next->data);
    1323       }
    1324     }
    1325   }
    1326
    1327   delete(o);
    1328   if(tracing) {
    1329     if(objects_to_be_returned != NULL){
    1330       printf("TRACING: filter_out_diff_origins: returning:\n%s\n", objects_to_be_returned? "(NULL)":objects_to_be_returned);
    1331     }else {
    1332       printf("TRACING: filter_out_diff_origins: returning NULL\n");
    1333
    1334     }
    1335   }
    1336   return objects_to_be_returned;
    1337
    1338 }
    1339
    1340
    1341
    1342
    1343 /* Check authorisation
    1344    Applies authorisation rules according to the object type
    1345
    1346    Arguments:
    1347       char *new_object: the new object,
    1348       char *old_object: the old object, as found in the database,
    1349       char *type: type of the object
    1350       credentials_struct credentials: a struct which
    1351         contains credentials of the update, such as 'From:' field of
    1352         the e-mail header and passwords in the update   */
    1353
    1354 int check_auth(char *new_object, char *old_object, char *type, credentials_struct credentials){
         /* [<][>][^][v][top][bottom][index][help] */
    1355
    1356    GSList *old_mntners = NULL, *new_mntners = NULL;
    1357    GSList *old_auths = NULL, *new_auths = NULL;
    1358    GSList *as_block_mnt_lowers = NULL;
    1359    GSList *old_auth_vector = NULL, *new_auth_vector = NULL, *as_block_auth_vector = NULL;
    1360    GSList *less_specific_auth_vector = NULL, *less_specific_mnt_lowers = NULL;
    1361    GSList *less_specific_mntners = NULL;
    1362    GSList *aut_num_maintainers = NULL;
    1363    GSList *aut_num_auth_vector = NULL;
    1364    GSList *exact_match_routes = NULL;
    1365    GSList *exact_match_routes_maintainers = NULL;
    1366    GSList *exact_match_routes_auth_vector = NULL;
    1367    GSList *less_spec_routes = NULL;
    1368    GSList *less_spec_routes_mntners = NULL;
    1369    GSList *less_spec_routes_auth_vector = NULL;
    1370    GSList *exact_match_inetnum_mnt_routes = NULL;
    1371    GSList *exact_match_inetnum_auth_vector = NULL;
    1372    GSList *less_spec_inetnum_mntners = NULL;
    1373    GSList *less_spec_inetnum_auth_vector = NULL;
    1374    GSList *exact_match_intenum_auth_vector = NULL;
    1375    GSList *exact_match_auth_vector = NULL;
    1376
    1377    char *as_block_object = NULL, *less_specific_object = NULL;
    1378    char *less_specific_domain = NULL;
    1379    char *less_spec_inetnum = NULL;
    1380    char *exact_match_inetnum = NULL;
    1381    char *less_specific_object_type = NULL;
    1382    char *override_string = NULL;
    1383    char *set_name = NULL;
    1384    char * aut_num_object = NULL;
    1385    Object *set_object = new Object();
    1386    Object *temp_obj;
    1387    bool code;
    1388    bool aut_num_auth_OK = false;
    1389
    1390    int overriden = 0;
    1391
    1392    /* first check if it is overriden or not. if overriden, check the override
    1393       password. If it is correct, continue, setting "overriden" to 1. If not,
    1394       immediately exit returning ERR_UP_OVF                                   */
    1395    override_string = get_override((new_object == NULL) ? old_object : new_object );
    1396    if(override_string == NULL){
    1397      overriden = 0;
    1398    }else if(check_override(override_string) == OVR_OK){
    1399      overriden = 1; /* authorisation is overriden */
    1400    }else if(check_override(override_string) == UP_OVS){
    1401      return UP_OVS; /* override syntax error --it must have at least two words */
    1402    }else{
    1403      return UP_OVF; /* override failed! */
    1404    }
    1405
    1406
    1407    /*
    1408     *  Handle the "person", "role", "limerick", "inet-rtr" types
    1409     */
    1410    if(strcmp(type,"person")   == 0 || strcmp(type,"role")     == 0 ||
    1411       strcmp(type,"limerick") == 0 || strcmp(type,"inet-rtr") == 0 ){
    1412      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1413        old_mntners = get_mntners(old_object);
    1414        old_auth_vector = get_auth_vector(old_mntners);
    1415        return authorise(old_auth_vector, credentials, overriden);
    1416      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1417        new_mntners = get_mntners(new_object);
    1418        new_auth_vector = get_auth_vector(new_mntners);
    1419        if(new_mntners != NULL && new_auth_vector == NULL){
    1420          /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1421          return UP_AUF; /* auth failed */
    1422        }
    1423        /*printf("DEBUG: check_auth: new_auth_vector has %i, new_mntners has %i nodes\n",
    1424               g_slist_length(new_auth_vector) ,g_slist_length(new_mntners));*/
    1425        return authorise(new_auth_vector, credentials, overriden);
    1426      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1427        old_mntners = get_mntners(old_object);
    1428        old_auth_vector = get_auth_vector(old_mntners);
    1429        if(old_mntners != NULL && old_auth_vector == NULL){
    1430          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1431          return UP_AUF; /* auth failed */
    1432        }
    1433        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1434          return authorise(old_auth_vector, credentials, overriden);
    1435        }else{
    1436          new_mntners = get_mntners(new_object);
    1437          new_auth_vector = get_auth_vector(new_mntners);
    1438          if(new_mntners != NULL && new_auth_vector == NULL){
    1439            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1440            return UP_AUF; /* auth failed */
    1441          }
    1442          return authorise(new_auth_vector, credentials, overriden);
    1443        }
    1444      }else{ // both are NULL, mustn't happen
    1445          cout << "DEBUG: check_auth: internal error: Both pointers are NULL" << endl;
    1446          return UP_INT; /* internal error */
    1447      }
    1448    }
    1449
    1450    /*
    1451     *  Handle the "auth-num" type
    1452     */
    1453    else if(strcmp(type,"aut-num")  == 0 ){
    1454      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1455        old_mntners = get_mntners(old_object);
    1456        old_auth_vector = get_auth_vector(old_mntners);
    1457        if(old_mntners != NULL && old_auth_vector == NULL){
    1458          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1459          return UP_AUF; /* auth failed */
    1460        }
    1461        return authorise(old_auth_vector, credentials, overriden);
    1462      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1463        as_block_object = get_as_block(new_object);
    1464        if(as_block_object == NULL ){
    1465          return UP_ABN; /* As-block does not exist */
    1466          }else{
    1467            as_block_mnt_lowers = get_mnt_lowers(as_block_object);
    1468            as_block_auth_vector = get_auth_vector(as_block_mnt_lowers);
    1469            if(as_block_mnt_lowers != NULL && as_block_auth_vector == NULL){
    1470              /* then, the mntners in 'as_block_mnt_lowers' do not exist. Problem. */
    1471              return UP_AUF; /* auth failed */
    1472            }
    1473          if(authorise(as_block_auth_vector, credentials, overriden) == UP_AUTH_OK ){
    1474            new_mntners = get_mntners(new_object);
    1475            new_auth_vector = get_auth_vector(new_mntners);
    1476            if(new_mntners != NULL && new_auth_vector == NULL){
    1477              /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1478              return UP_AUF; /* auth failed */
    1479            }
    1480            return authorise(new_auth_vector, credentials, overriden);
    1481          }else{
    1482            return UP_HOF; /* hierarchical auth failed */
    1483          }
    1484        }
    1485      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1486        old_mntners = get_mntners(old_object);
    1487        old_auth_vector = get_auth_vector(old_mntners);
    1488        if(old_mntners != NULL && old_auth_vector == NULL){
    1489          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1490          return UP_AUF; /* auth failed */
    1491        }
    1492        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1493          return authorise(old_auth_vector, credentials, overriden);
    1494        }else{
    1495          new_mntners = get_mntners(new_object);
    1496          new_auth_vector = get_auth_vector(new_mntners);
    1497          if(new_mntners != NULL && new_auth_vector == NULL){
    1498            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1499            return UP_AUF; /* auth failed */
    1500          }
    1501          return authorise(new_auth_vector, credentials, overriden);
    1502        }
    1503      }else{ /* both are NULL, mustn't happen */
    1504          if(tracing) {
    1505            cout << "TRACING: check_auth: internal error: Both pointers are NULL" << endl;
    1506          }
    1507          return UP_INT; /* internal error */
    1508      }
    1509    }
    1510
    1511    /*
    1512     *  Handle the "mntner/as-block" types
    1513     */
    1514    else if(strcmp(type,"mntner")  == 0 || strcmp(type,"as-block")  == 0 ){
    1515      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1516        old_mntners = get_mntners(old_object);
    1517        old_auth_vector = get_auth_vector(old_mntners);
    1518        if(old_mntners != NULL && old_auth_vector == NULL){
    1519          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1520          return UP_AUF; /* auth failed */
    1521        }
    1522        return authorise(old_auth_vector, credentials, overriden);
    1523      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1524        if(overriden){
    1525          return UP_AUTH_OK;
    1526        }else{/* If not overriden, and if not coming from ripe-dbm, must be forwarded to ripe-dbm */
    1527          if(tracing) {
    1528            cout << "DEBUG: check_auth: '" << type << "' creation requested" << endl;
    1529          }
    1530          return UP_AUF; /* authorisation failed */
    1531        }
    1532      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1533        old_mntners = get_mntners(old_object);
    1534        old_auth_vector = get_auth_vector(old_mntners);
    1535        if(old_mntners != NULL && old_auth_vector == NULL){
    1536          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1537          return UP_AUF; /* auth failed */
    1538        }
    1539        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1540          return authorise(old_auth_vector, credentials, overriden);
    1541        }else{
    1542          new_mntners = get_mntners(new_object);
    1543          new_auth_vector = get_auth_vector(new_mntners);
    1544          if(new_mntners != NULL && new_auth_vector == NULL){
    1545            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1546            return UP_AUF; /* auth failed */
    1547          }
    1548          return authorise(new_auth_vector, credentials, overriden);
    1549        }
    1550      }else{ // both are NULL, mustn't happen
    1551          cout << "DEBUG: check_auth: internal error: Both pointers are NULL" << endl;
    1552          return UP_INT; /* internal error */
    1553      }
    1554    }
    1555
    1556    /*
    1557     *  Handle the "inetnum/inet6num" types
    1558     */
    1559    else if(strcmp(type,"inetnum")  == 0 || strcmp(type,"inet6num")  == 0 ){
    1560      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1561        old_mntners = get_mntners(old_object);
    1562        old_auth_vector = get_auth_vector(old_mntners);
    1563        if(old_mntners != NULL && old_auth_vector == NULL){
    1564          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1565          return UP_AUF; /* auth failed */
    1566        }
    1567        return authorise(old_auth_vector, credentials, overriden);
    1568      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1569        less_specific_object = get_less_specific(new_object, type);
    1570        if(less_specific_object == NULL){
    1571          if(overriden){
    1572            return UP_AUTH_OK;
    1573          }else{
    1574            return UP_HOF; /* hierarchical authorisation failed */
    1575          }
    1576        }else{ /* if we got an inet(6)num object */
    1577          less_specific_mnt_lowers = get_mnt_lowers(less_specific_object);
    1578          less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    1579          if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    1580            /* then, the mntners in 'less_specific_mnt_lowers' do not exist. Problem. */
    1581            return UP_AUF; /* auth failed */
    1582          }
    1583          if(authorise(less_specific_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1584            new_mntners = get_mntners(new_object);
    1585            new_auth_vector = get_auth_vector(new_mntners);
    1586            if(new_mntners != NULL && new_auth_vector == NULL){
    1587              /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1588              return UP_AUF; /* auth failed */
    1589            }
    1590            return authorise(new_auth_vector, credentials, overriden);
    1591          }else{
    1592            return UP_HOF; /* hierarchical authorisation failed */
    1593          }
    1594        }
    1595      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1596        old_mntners = get_mntners(old_object);
    1597        old_auth_vector = get_auth_vector(old_mntners);
    1598        if(old_mntners != NULL && old_auth_vector == NULL){
    1599          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1600          return UP_AUF; /* auth failed */
    1601        }
    1602        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1603          return authorise(old_auth_vector, credentials, overriden);
    1604        }else{
    1605          new_mntners = get_mntners(new_object);
    1606          new_auth_vector = get_auth_vector(new_mntners);
    1607          if(new_mntners != NULL && new_auth_vector == NULL){
    1608            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1609            return UP_AUF; /* auth failed */
    1610          }
    1611          return authorise(new_auth_vector, credentials, overriden);
    1612        }
    1613      }else{ /* both are NULL, mustn't happen */
    1614          cout << "DEBUG: check_auth: internal error: Both pointers are NULL" << endl;
    1615          return UP_INT; /* internal error */
    1616      }
    1617    }
    1618
    1619
    1620
    1621    /*
    1622     *  Handle the "domain" type
    1623     */
    1624    else if(strcmp(type,"domain")  == 0){
    1625      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1626        old_mntners = get_mntners(old_object);
    1627        old_auth_vector = get_auth_vector(old_mntners);
    1628        if(old_mntners != NULL && old_auth_vector == NULL){
    1629          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1630          return UP_AUF; /* auth failed */
    1631        }
    1632        return authorise(old_auth_vector, credentials, overriden);
    1633      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1634        /* now, we have to find a 'less specific domain object' for this.
    1635           If there is no less specific object, then creation is possible
    1636           only with overriding. */
    1637       less_specific_domain = get_less_specific_domain(new_object);
    1638       if(less_specific_domain == NULL){
    1639         if(overriden){/* we didn't get a 'less specific' domain object */
    1640            return UP_AUTH_OK;
    1641          }else{
    1642            return UP_HOF; /* hierarchical authorisation failed */
    1643          }
    1644       }else{ /* we get a 'less specific' domain object */
    1645          less_specific_mnt_lowers = get_mnt_lowers(less_specific_domain);
    1646          less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    1647          if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    1648            /* then, the mntners in 'less_specific_mnt_lowers' do not exist. Problem. */
    1649            return UP_AUF; /* auth failed */
    1650          }
    1651          if(authorise(less_specific_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1652            new_mntners = get_mntners(new_object);
    1653            new_auth_vector = get_auth_vector(new_mntners);
    1654            if(new_mntners != NULL && new_auth_vector == NULL){
    1655              /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1656              return UP_AUF; /* auth failed */
    1657            }
    1658            return authorise(new_auth_vector, credentials, overriden);
    1659          }else{
    1660            return UP_HOF; /* hierarchical authorisation failed */
    1661          }
    1662
    1663       }
    1664      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1665        old_mntners = get_mntners(old_object);
    1666        old_auth_vector = get_auth_vector(old_mntners);
    1667        if(old_mntners != NULL && old_auth_vector == NULL){
    1668          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1669          return UP_AUF; /* auth failed */
    1670        }
    1671        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1672          return authorise(old_auth_vector, credentials, overriden);
    1673        }else{
    1674          new_mntners = get_mntners(new_object);
    1675          new_auth_vector = get_auth_vector(new_mntners);
    1676          if(new_mntners != NULL && new_auth_vector == NULL){
    1677            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1678            return UP_AUF; /* auth failed */
    1679          }
    1680          return authorise(new_auth_vector, credentials, overriden);
    1681        }
    1682      }else{ /* both are NULL, mustn't happen */
    1683          cout << "DEBUG: check_auth: internal error: Both pointers are NULL" << endl;
    1684          return UP_INT; /* internal error */
    1685      }
    1686    }
    1687
    1688
    1689    /*
    1690     *  Handle the "route" type
    1691     */
    1692    else if(strcmp(type,"route")  == 0){
    1693      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1694        old_mntners = get_mntners(old_object);
    1695        old_auth_vector = get_auth_vector(old_mntners);
    1696        if(old_mntners != NULL && old_auth_vector == NULL){
    1697          /* then, the mntners in 'old_mntners' do not exist. Problem. */
    1698          return UP_AUF; /* auth failed */
    1699        }
    1700        return authorise(old_auth_vector, credentials, overriden);
    1701      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1702        /* first we have to find the aut-num object mentioned in the
    1703           origin attribute */
    1704
    1705        aut_num_object = get_aut_num_object(new_object);
    1706        if(aut_num_object == NULL){
    1707          if(overriden){
    1708            return UP_AUTH_OK;
    1709          }else{
    1710            return UP_HOF; /* hierarchical authorisation failed */
    1711          }
    1712        }else{/* there is a corresponding aut-num in the db */
    1713          printf("DEBUG: check_auth: will try to authorise the route using aut-num\n");
    1714          aut_num_maintainers = get_mnt_routes(aut_num_object);
    1715          if(aut_num_maintainers != NULL){
    1716            aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    1717            if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1718              aut_num_auth_OK = true;
    1719            }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    1720              return UP_HOF;
    1721            }
    1722          }else{/* aut_num_maintainers is NULL */
    1723             aut_num_maintainers = get_mnt_lowers(aut_num_object);
    1724             if(aut_num_maintainers != NULL){
    1725               aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    1726               if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1727                 aut_num_auth_OK = TRUE;
    1728               }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    1729                 return UP_HOF; /* hierarchical authorisation failed */
    1730               }
    1731             }else{/* aut_num_maintainers is NULL */
    1732               aut_num_maintainers = get_mntners(aut_num_object);
    1733               if(aut_num_maintainers != NULL){
    1734                 aut_num_auth_vector = get_auth_vector(aut_num_maintainers);
    1735                 if(authorise(aut_num_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1736                   aut_num_auth_OK = TRUE;
    1737                 }else{/* authorise(aut_num_auth_vector, credentials, overriden) != UP_AUTH_OK */
    1738                   return UP_HOF; /* hierarchical authorisation failed */
    1739                 }
    1740               }else{/* aut_num_maintainers is NULL */
    1741                 aut_num_auth_OK = TRUE;
    1742               }
    1743
    1744             }
    1745          }
    1746          if(aut_num_auth_OK){
    1747            /* now, we have to find an exact match for this route object.
    1748               If there is no exact match object, then we will go on to find
    1749               less specific. */
    1750            exact_match_routes = get_exact_match_routes(new_object);
    1751            if(exact_match_routes != NULL){
    1752              exact_match_routes_maintainers = get_mnt_routes_from_list(exact_match_routes);
    1753              exact_match_routes_auth_vector = get_auth_vector(exact_match_routes_maintainers);
    1754              if(exact_match_routes_maintainers != NULL && exact_match_routes_auth_vector == NULL){
    1755                /* then, the mntners in 'exact_match_routes_maintainers' do not exist. Problem. */
    1756                return UP_AUF; /* auth failed */
    1757               }
    1758              if(authorise(exact_match_routes_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1759                /* then, check mnt_bys of the route itself */
    1760                new_mntners = get_mntners(new_object);
    1761                new_auth_vector = get_auth_vector(new_mntners);
    1762                if(new_mntners != NULL && new_auth_vector == NULL){
    1763                  /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1764                  return UP_AUF; /* auth failed */
    1765                }
    1766                return authorise(new_auth_vector, credentials, overriden);
    1767              }else{/*authorise(exact_match_routes_auth_vector, credentials, overriden) != UP_AUTH_OK*/
    1768                return UP_HOF; /* hierarchical authorisation failed */
    1769              }
    1770            }else{ /* exact_match_routes == NULL */
    1771              /* then we have to look for less specific route objs */
    1772              less_spec_routes = get_less_spec_routes(new_object);
    1773              if(less_spec_routes != NULL){
    1774                less_spec_routes_mntners = get_mnt_routes_from_list(less_spec_routes);
    1775                less_spec_routes_mntners = g_slist_concat(less_spec_routes_mntners,
    1776                                              get_mnt_lowers_from_list(less_spec_routes));
    1777                less_spec_routes_auth_vector = get_auth_vector(less_spec_routes_mntners);
    1778                if(less_spec_routes_mntners != NULL && less_spec_routes_auth_vector == NULL){
    1779                  /* then, the mntners in 'less_spec_routes_mntners' do not exist. Problem. */
    1780                  return UP_AUF; /* auth failed */
    1781                }
    1782                if(authorise(less_spec_routes_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1783                  /* then, check mnt_bys of the route itself */
    1784                  new_mntners = get_mntners(new_object);
    1785                  new_auth_vector = get_auth_vector(new_mntners);
    1786                  if(new_mntners != NULL && new_auth_vector == NULL){
    1787                    /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1788                    return UP_AUF; /* auth failed */
    1789                  }
    1790                  return authorise(new_auth_vector, credentials, overriden);
    1791                }else{/*authorise(less_spec_routes_auth_vector, credentials, overriden) != UP_AUTH_OK*/
    1792                  return UP_HOF; /* hierarchical authorisation failed */
    1793                }
    1794             }else{/* less_spec_routes == NULL */
    1795                /* so, we have to get the exact match inetnum */
    1796                exact_match_inetnum = get_exact_match_inetnum(new_object);
    1797                if(exact_match_inetnum != NULL){
    1798                  exact_match_inetnum_mnt_routes = get_mnt_routes(exact_match_inetnum);
    1799                  exact_match_inetnum_auth_vector = get_auth_vector(exact_match_inetnum_mnt_routes);
    1800                  if(exact_match_inetnum_mnt_routes != NULL && exact_match_inetnum_auth_vector == NULL){
    1801                    /* then, the mntners in 'exact_match_inetnum_mnt_routes' do not exist. Problem. */
    1802                    return UP_AUF; /* auth failed */
    1803                  }
    1804                  if(authorise(exact_match_intenum_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1805                    /* then, check mnt_bys of the route itself */
    1806                    new_mntners = get_mntners(new_object);
    1807                    new_auth_vector = get_auth_vector(new_mntners);
    1808                    if(new_mntners != NULL && new_auth_vector == NULL){
    1809                      /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1810                      return UP_AUF; /* auth failed */
    1811                    }
    1812                    return authorise(new_auth_vector, credentials, overriden);
    1813                  }else{
    1814                    return UP_HOF; /* hierarchical authorisation failed */
    1815                  }
    1816                }else{/* exact_match_inetnum == NULL */
    1817                  /* then, we will try to find less spec inetnums */
    1818                  less_spec_inetnum = get_less_spec_inetnum(new_object);
    1819                  if(less_spec_inetnum != NULL){
    1820                    less_spec_inetnum_mntners = get_mnt_routes(less_spec_inetnum);
    1821                    less_spec_inetnum_mntners = g_slist_concat(less_spec_inetnum_mntners,
    1822                                   get_mnt_lowers(less_spec_inetnum));
    1823                    less_spec_inetnum_auth_vector = get_auth_vector(less_spec_inetnum_mntners);
    1824                    if(less_spec_inetnum_mntners != NULL && less_spec_inetnum_auth_vector == NULL){
    1825                      /* then, the mntners in 'less_spec_inetnum_mntners' do not exist. Problem. */
    1826                      return UP_AUF; /* auth failed */
    1827                    }
    1828                    if(authorise(exact_match_auth_vector, credentials, overriden) == UP_AUTH_OK){
    1829                      /* then, check mnt_bys of the route itself */
    1830                      new_mntners = get_mntners(new_object);
    1831                      new_auth_vector = get_auth_vector(new_mntners);
    1832                      if(new_mntners != NULL && new_auth_vector == NULL){
    1833                        /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1834                        return UP_AUF; /* auth failed */
    1835                      }
    1836                      return authorise(new_auth_vector, credentials, overriden);
    1837                    }else{/* authorise(exact_match_auth_vector, credentials, overriden) != UP_AUTH_OK */
    1838                      return UP_HOF; /* hierarchical authorisation failed */
    1839                    }
    1840                  }else{/* less_spec_inetnum == NULL */
    1841                    /* now that we couldn't find any route or inetnum object
    1842                       to be used in authentication. So, only if the auth is
    1843                       overriden the object will be created. */
    1844                    if(overriden){
    1845                      return UP_AUTH_OK;
    1846                    }else{
    1847                      return UP_HOF; /* hierarchical authorisation failed */
    1848                    }
    1849                  }
    1850                }
    1851              }
    1852            }
    1853          }else{/* ! aut_num_auth_OK */
    1854            return UP_HOF; /* hierarchical auth failed */
    1855          }
    1856
    1857        }
    1858
    1859      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1860        old_mntners = get_mntners(old_object);
    1861        old_auth_vector = get_auth_vector(old_mntners);
    1862        if(old_mntners != NULL && old_auth_vector == NULL){
    1863          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    1864          return UP_AUF; /* auth failed */
    1865        }
    1866        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1867          return authorise(old_auth_vector, credentials, overriden);
    1868        }else{
    1869          new_mntners = get_mntners(new_object);
    1870          new_auth_vector = get_auth_vector(new_mntners);
    1871          if(new_mntners != NULL && new_auth_vector == NULL){
    1872            /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1873            return UP_AUF; /* auth failed */
    1874          }
    1875          return authorise(new_auth_vector, credentials, overriden);
    1876        }
    1877      }else{ /* both are NULL, mustn't happen */
    1878          cout << "DEBUG: check_auth: internal error: Both pointers are NULL" << endl;
    1879          return UP_INT; /* internal error */
    1880      }
    1881    }
    1882
    1883
    1884    /*
    1885     *  Handle the set objects ("as-set","rtr-set", "peering-set", "route-set" and "filter-set" types
    1886     */
    1887    else if(strcmp(type,"as-set")       == 0 || strcmp(type,"rtr-set")     == 0 ||
    1888            strcmp(type,"peering-set")  == 0 || strcmp(type,"filter-set")  == 0 ||
    1889            strcmp(type,"route-set")    == 0 ){
    1890      if( new_object == NULL && old_object != NULL ){ /* the object is to be deleted */
    1891        old_mntners = get_mntners(old_object);
    1892        old_auth_vector = get_auth_vector(old_mntners);
    1893        if(old_mntners != NULL && old_auth_vector == NULL){
    1894          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    1895          return UP_AUF; /* auth failed */
    1896        }
    1897        return authorise(old_auth_vector, credentials, overriden);
    1898      }else if( new_object != NULL && old_object == NULL ){ /* the object is to be created */
    1899         code = set_object->scan(new_object, strlen(new_object));
    1900         set_name = get_search_key(set_object, type, new_object);
    1901        if(strstr(set_name,":") == NULL ){/* if the name is _not_ hierarchical */
    1902          new_mntners = get_mntners(new_object);
    1903          new_auth_vector = get_auth_vector(new_mntners);
    1904          if(new_mntners != NULL && new_auth_vector == NULL){
    1905            /* then, the mntners in 'new_auth_vector' do not exist. Problem. */
    1906            return UP_AUF; /* auth failed */
    1907          }
    1908          return authorise(new_auth_vector, credentials, overriden);
    1909        }else{/* the name is hierarchical */
    1910          less_specific_object = get_less_specific_set(new_object, type);
    1911          if(less_specific_object != NULL){/* such an object exists */
    1912            temp_obj = new Object();
    1913            code = temp_obj->scan(less_specific_object, strlen(less_specific_object));
    1914            less_specific_object_type = get_type(temp_obj);
    1915            delete(temp_obj);
    1916            if(strcmp(less_specific_object_type, "aut-num") == 0){/* if this is an aut-num object */
    1917              less_specific_mnt_lowers = get_mnt_lowers(less_specific_object);
    1918              less_specific_auth_vector = get_auth_vector(less_specific_mnt_lowers);
    1919              if(less_specific_mnt_lowers != NULL && less_specific_auth_vector == NULL){
    1920                /* then, the mntners in 'less_specific_auth_vector' do not exist. Problem. */
    1921               return UP_AUF; /* auth failed */
    1922              }
    1923              if(less_specific_auth_vector != NULL){
    1924                return authorise(less_specific_auth_vector, credentials, overriden);
    1925              }else{/* the less specific object doesn't contain any mnt-lower */
    1926                less_specific_mntners = get_mntners(less_specific_object);
    1927                less_specific_auth_vector = get_auth_vector(less_specific_mntners);
    1928                if(less_specific_mntners != NULL && less_specific_auth_vector == NULL){
    1929                  /* then, the mntners in 'less_specific_mntners' do not exist. Problem. */
    1930                  return UP_AUF; /* auth failed */
    1931                }
    1932                if(less_specific_auth_vector != NULL){/* less spec object has some mnt-by attribs,
    1933                                                         use them  */
    1934                    return authorise(less_specific_auth_vector, credentials, overriden);
    1935                }else{/* the less specific object doesn't contain any mnt-by either */
    1936                  if(overriden){
    1937                    return UP_AUTH_OK;
    1938                  }else{
    1939                    return UP_HOF; /* hierarchical authorisation failed */
    1940                  }
    1941                }
    1942              }
    1943            }else{ /* this is _not_ an aut-num object*/
    1944              less_specific_mntners = get_mntners(less_specific_object);
    1945              less_specific_auth_vector = get_auth_vector(less_specific_mntners);
    1946              if(less_specific_mntners != NULL && less_specific_auth_vector == NULL){
    1947                /* then, the mntners in 'less_specific_mntners' do not exist. Problem. */
    1948                return UP_AUF; /* auth failed */
    1949              }
    1950              if(less_specific_auth_vector != NULL ){/* the set obj has some mnt-by attribs */
    1951                return authorise(less_specific_auth_vector, credentials, overriden);
    1952              }else{
    1953                if(overriden){
    1954                  return UP_AUTH_OK;
    1955                }else{
    1956                  return UP_HOF; /* hierarchical authorisation failed */
    1957                }
    1958              }
    1959            }
    1960
    1961          }else{/* we don't have a less specific of this set object in the DB  */
    1962            return UP_HOF; /* hierarchical authorisation failed */
    1963          }
    1964        }
    1965      }else if( new_object != NULL && old_object != NULL ){ /* this is an update */
    1966        old_mntners = get_mntners(old_object);
    1967        old_auth_vector = get_auth_vector(old_mntners);
    1968        if(old_mntners != NULL && old_auth_vector == NULL){
    1969          /* then, the mntners in 'old_auth_vector' do not exist. Problem. */
    1970          return UP_AUF; /* auth failed */
    1971        }
    1972        if(old_auth_vector){ /* if we have mntners in the old object, use them */
    1973          return authorise(old_auth_vector, credentials, overriden);
    1974        }else{
    1975          new_mntners = get_mntners(new_object);
    1976          new_auth_vector = get_auth_vector(new_mntners);
    1977          if(new_mntners != NULL && new_auth_vector == NULL){
    1978            /* then, the mntners in 'new_mntners' do not exist. Problem. */
    1979            return UP_AUF; /* auth failed */
    1980          }
    1981          return authorise(new_auth_vector, credentials, overriden);
    1982        }
    1983      }else{ /* both are NULL, mustn't happen */
    1984          cout << "DEBUG: check_auth: internal error: Both pointers are NULL" << endl;
    1985          return UP_INT; /* internal error */
    1986      }
    1987
    1988
    1989
    1990
    1991
    1992    }else{ /* We exhausted all object classes. If we are here, then there is a problem */
    1993      cout << "check_auth: This type '" << type << "' is unknown" << endl;
    1994      return UP_NIY; /* not implemented yet */
    1995    }
    1996    return UP_AUF; /* if we come to this point, then auth failed */
    1997 }
    1998
    1999
    2000
    2001
    2002
    2003
    2004 /* Gets the old version of the given "arg" object, which is in char * format
    2005    and returns the old version again in char * format */
    2006
    2007 char * get_old_version(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2008
    2009     bool code = true;
    2010     char *type=NULL, *primary_search_key = NULL, *search_string = NULL;
    2011     Object *o;
    2012     o = new Object;
    2013     char *result = NULL, *origin = NULL;
    2014
    2015     error = 0;
    2016     code = o->scan(arg,strlen(arg));
    2017     type = get_type(o);
    2018     primary_search_key = get_search_key(o, type, arg);
    2019     if(tracing) {
    2020       cout << "type=" << type << endl;
    2021       cout << "primary_search_key=" << primary_search_key << endl;
    2022     }
    2023     /* prepare the search string */
    2024     //search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2025     //                                      + strlen(type) + 1);
    2026     /* if the object is a pn ro a ro object, then get all pn/ro's with the
    2027        same NIC hdl */
    2028     if(strcmp(type,"person") == 0 || strcmp(type,"role") == 0){
    2029       /* prepare the search string */
    2030       search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2031                                           + strlen("person,role") + 1);
    2032       sprintf(search_string, "-x -R -r -Tperson,role %s", primary_search_key);
    2033     }else{
    2034       /* prepare the search string */
    2035       search_string = (char *)malloc(strlen(primary_search_key) + strlen("-x -R -r -T")
    2036                                           + strlen(type) + 1);
    2037       sprintf(search_string, "-x -R -r -T%s %s",type, primary_search_key);
    2038     }
    2039     result = send_and_get(QUERY_HOST, QUERY_PORT, search_string);
    2040     if(tracing) {
    2041       cout << "TRACING: send_and_get has returned" << endl;
    2042       cout << "TRACING: send_and_get returned (with search '"<< search_string <<"'): " << endl
    2043            << result << endl;
    2044     }
    2045     /* Attention: here we must also check these:
    2046          for ro/pn objects: The name must also the same. When the NIC hdl is the
    2047                same but names are different, we must somehow return an error.
    2048                Also, when we search for a person, we must also look for role objects
    2049                (and vice versa) since the RIPupdate does not distinguish between
    2050                role & person objects. We have to check it here.
    2051          for rt objects: We also have to check the identicalness of origin
    2052                attributes.
    2053
    2054           These are not yet implemented.
    2055                */
    2056
    2057     if(strcmp(type,"route") == 0){
    2058       if(tracing) {
    2059         printf("TRACING: This is a route\n");
    2060       }
    2061       /* if this is a route, then we must filter out the routes with different
    2062          origin attributes */
    2063       origin = get_search_key(o, "origin", arg);
    2064       if(tracing) {
    2065         printf("TRACING: Got origin of route: %s\n", origin);
    2066       }
    2067       result = filter_out_diff_origins(result, origin);
    2068       if(tracing) {
    2069         printf("TRACING: Filtered routes\n");
    2070       }
    2071     }
    2072     // count the objects
    2073     if(count_objects(result) == 0){
    2074       result = NULL; /* we don't have such an object */
    2075     }else if(count_objects(result) == 1){
    2076       result = take_object(result);
    2077       if(tracing) {
    2078       cout << "TRACING: Take_object returned ***\n" << result << "***" << endl;
    2079       }
    2080     }else{ /* we have more than one objects, error! */
    2081       error = UP_MOR;
    2082       return NULL;
    2083     }
    2084     return result;
    2085 }
    2086
    2087
    2088
    2089
    2090 /* Gets a credentials_struct whose 'from' field will be filled in and
    2091    the mail header. Finds the 'From:' line in the header and sets
    2092    the 'from' field to this line (all line, including the 'From:' string,
    2093    since some users have put regexps which match the whole line in their
    2094    'auth' attributes.) */
    2095 void process_mail_header(credentials_struct * credentials_ptr, char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2096   char * header = strdup(arg);
    2097   char * temp = (char *)malloc(strlen(header));
    2098   while(index(header, '\n') != NULL){
    2099     temp = strdup(header);
    2100     temp[index(temp, '\n') - temp] = '\0';
    2101     if(strstr(temp, "From:") == temp){
    2102       if(tracing) {
    2103         printf("TRACING: process_mail_header: Assigning %s\n", temp);
    2104       }
    2105       credentials_ptr->from = strdup(temp);
    2106       free(temp);
    2107       return;
    2108     }
    2109     header = header + (index(header, '\n') - header + 1);
    2110   }
    2111   free(temp);
    2112 }
    2113
    2114
    2115
    2116
    2117
    2118
    2119 void stringPack(char *dest, const char *source)
         /* [<][>][^][v][top][bottom][index][help] */
    2120 {
    2121
    2122   if(tracing) {
    2123     printf("TRACING: stringPack running\n");
    2124   }
    2125
    2126
    2127
    2128 /*----------------------------------------------------------------------*\
    2129
    2130 *  Function to rewrite a line of text with only one blankspace between  *
    2131 *  each word.
    2132 *
    2133
    2134 \*----------------------------------------------------------------------*/
    2135
    2136
    2137 /*
    2138  * This while loop continues until the NULL character is copied into
    2139  * the destination string.  If a tab character is copied into the
    2140  * destination string, it is replaced with a blank-space character.
    2141  *
    2142  * Multiple blank-space and/or tab characters are skipped in the source
    2143  * string until any other character is found.
    2144  */
    2145
    2146         while (1)
    2147                 {
    2148                 *dest = *source;
    2149
    2150                 if (*dest == '\t')
    2151                         (*dest = ' ');
    2152
    2153                 /* Exit if have copied the end of the string. */
    2154                 if (*dest == '\0')
    2155                         return;
    2156
    2157 /*
    2158  * If the source character was a blank-space or a tab, move to the next
    2159  * source character.  While the source character is a blank-space or a
    2160  * tab, move to the next character (i.e. ignore these characters).  When
    2161  * any other character is found in the source string, move to the next
    2162  * element of the destination string.
    2163  *
    2164  * Otherwise, simultaneously, move to the next elements of the destination
    2165  * and the source strings.
    2166  */
    2167
    2168
    2169
    2170                 if ( (*source == ' ') || (*source == '\t') )
    2171                         {
    2172                         ++source;
    2173                         while ( (*source == ' ') || (*source == '\t') )
    2174                                 {
    2175                                 ++source;
    2176                                 }
    2177
    2178                         ++dest;
    2179                         }
    2180                 else
    2181                         {
    2182                         ++dest;
    2183                         ++source;
    2184                         }
    2185                 }
    2186 }
    2187
    2188 /* strips lines beginning with "delete:" off  */
    2189 char * delete_delete_attrib(char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2190
    2191     char ** temp = NULL;
    2192     char * string = NULL;
    2193     int i;
    2194
    2195     if(arg == NULL){
    2196        return NULL;
    2197     }
    2198
    2199     /* split the string into lines */
    2200     temp = g_strsplit (arg, "\n", 0);
    2201
    2202     for(i=0; temp[i] != NULL; i++){
    2203       if(strstr(temp[i], "delete:") != temp[0]){
    2204         //printf("DEBUG: temp[i] = %s\n", temp[i]);
    2205         if(string == NULL){
    2206           string = strdup(temp[i]);
    2207         }else{
    2208           string = (char *)realloc(string, strlen(string) + strlen(temp[i]) + 1);
    2209           string = strcat(string, "\n");
    2210           string = strcat(string, temp[i]);
    2211         }
    2212       }
    2213     }
    2214     g_strfreev(temp);
    2215     return string;
    2216 }
    2217
    2218
    2219
    2220 int identical(const char * old_version, const char * new_version){
         /* [<][>][^][v][top][bottom][index][help] */
    2221   char * arg1 = strdup(old_version);
    2222   char * arg2 = strdup(new_version);
    2223   int result = 0;
    2224   char *temp1, *temp2;
    2225
    2226
    2227   arg1 = g_strstrip(arg1);
    2228   arg2 = g_strstrip(arg2);
    2229
    2230   /* delete the 'delete:' attrib */
    2231   arg1 = delete_delete_attrib(arg2);
    2232   /* convert tabs to white spaces */
    2233   arg1 = g_strdelimit(arg1, "\t", ' ');
    2234   arg2 = g_strdelimit(arg2, "\t", ' ');
    2235
    2236   temp1 = (char *)malloc(strlen(arg1));
    2237   temp2 = (char *)malloc(strlen(arg2));
    2238   stringPack(temp1, arg1);
    2239   stringPack(temp2, arg2);
    2240
    2241   result = strcmp(temp1, temp2);
    2242   //printf("TRACING: identical: the objects are:\n[%s]\n[%s]\n", temp1, temp2);
    2243   free(arg1);
    2244   free(arg2);
    2245   free(temp1);
    2246   free(temp2);
    2247   if(result  == 0){
    2248     if(tracing) {
    2249       printf("TRACING: identical returning 1\n");
    2250     }
    2251     return 1;
    2252   }else{
    2253     if(tracing) {
    2254       printf("TRACING: identical returning 0\n");
    2255     }
    2256     return 0;
    2257   }
    2258 }
    2259
    2260
    2261
    2262
    2263
    2264
    2265 /* constructs an initials string from a given name (for NIC hdl generation) */
    2266 char * find_initials(const char * arg){
         /* [<][>][^][v][top][bottom][index][help] */
    2267
    2268    char * temp, * temp2;
    2269    char * initials = NULL;
    2270    int len, i;
    2271    char ** vector;
    2272
    2273    temp = strdup(arg);
    2274    g_strstrip(temp);
    2275    temp2 = (char *)malloc(strlen(temp) + 1);
    2276    stringPack(temp2, temp);
    2277    vector = g_strsplit(temp2, " ", 0);
    2278    for(i = 0; vector[i] != NULL && i < 4; i++){
    2279      //printf("%i\n",i);
    2280      if(strlen(vector[i]) > 0){
    2281        if(initials == NULL){
    2282          initials = (char *)malloc(2);
    2283          initials[0] = vector[i][0]; initials[1] = '\0';
    2284        }else{
    2285          len = strlen(initials);
    2286          initials = (char *)realloc(initials, len + 2 );
    2287          initials[len] = vector[i][0];
    2288          initials[len + 1] = '\0';
    2289        }
    2290      }
    2291    }
    2292    free(temp);free(temp2);g_strfreev(vector);
    2293    return initials;
    2294 }
    2295
    2296
    2297
    2298
    2299
    2300
    2301
    2302 /* Gets an object whose NIC hdl is AUTO and to be modified (to be sent to RIPupdate)
    2303    and  modifies the nic-hdl: attribute, returns the new object.
    2304    For example, "nic-hdl: AUTO-1" becomes "nic-hdl: HG*-RIPE . Also,
    2305    auto_nic is set to "AUTO-1"
    2306    auto_nic must be allocated enough memory before replace_AUTO_NIC_hdl called */
    2307
    2308 char * replace_AUTO_NIC_hdl(char * arg, char * auto_nic_hdl){
         /* [<][>][^][v][top][bottom][index][help] */
    2309
    2310   GString* temp_string;
    2311   char * to_be_returned = NULL;
    2312   char * person_role_name= NULL;
    2313   char * initials = NULL;
    2314   char ** temp = NULL;
    2315   int i, pos;
    2316   Object * o = new Object;
    2317
    2318   temp = g_strsplit(arg, "\n", 0);
    2319
    2320   for(i = 0; temp[i] != NULL; i++){
    2321     //printf("Line: %s\n", temp[i]);
    2322     if(strstr(temp[i], "nic-hdl:") == temp[i]){/* if it starts with nic-hdl */
    2323       temp_string = g_string_new(temp[i]);
    2324       if(strstr(temp_string->str, "AUTO-") != NULL){
    2325         auto_nic_hdl = strncpy(auto_nic_hdl, strstr(temp_string->str, "AUTO-"),
    2326             temp_string->len + temp_string->str - strstr(temp_string->str, "AUTO-") );
    2327         auto_nic_hdl[temp_string->len + temp_string->str - strstr(temp_string->str, "AUTO-")] = '\0';
    2328         g_strstrip(auto_nic_hdl);
    2329         printf("DEBUG: auto_nic is [%s]\n", auto_nic_hdl);
    2330         pos = strstr(temp_string->str, "AUTO-") - temp_string->str;
    2331         temp_string = g_string_erase(temp_string,
    2332             strstr(temp_string->str, "AUTO-") - temp_string->str, strlen(auto_nic_hdl)/*strlen("AUTO-")*/);
    2333
    2334         temp_string = g_string_insert(temp_string, pos, UPDATE_SOURCE);
    2335         temp_string = g_string_insert(temp_string, pos, "*-");
    2336         o->scan(arg, strlen(arg));
    2337         person_role_name = get_attribute(o, get_type(o), arg);
    2338         delete(o);
    2339         initials = find_initials(person_role_name);
    2340         free(person_role_name);
    2341         temp_string = g_string_insert(temp_string, pos, initials);
    2342         free(initials);
    2343
    2344         if(to_be_returned == NULL){
    2345           to_be_returned = strdup(temp_string->str);
    2346           g_string_free(temp_string, TRUE);
    2347         }else{
    2348           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    2349           to_be_returned = strcat(to_be_returned, "\n");
    2350           to_be_returned = strcat(to_be_returned, temp_string->str);
    2351           g_string_free(temp_string, TRUE);
    2352         }
    2353       }else{
    2354         if(to_be_returned == NULL){
    2355           to_be_returned = strdup(temp[i]);
    2356         }else{
    2357           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2358           to_be_returned = strcat(to_be_returned, "\n");
    2359           to_be_returned = strcat(to_be_returned, temp[i]);
    2360         }
    2361       }
    2362     }else{/* if it doesn't begin with nic-hdl */
    2363         if(to_be_returned == NULL){
    2364           to_be_returned = strdup(temp[i]);
    2365         }else{
    2366           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2367           strcat(to_be_returned, "\n");
    2368           strcat(to_be_returned, temp[i]);
    2369         }
    2370
    2371     }
    2372
    2373   }
    2374   g_strfreev (temp);
    2375   return to_be_returned;
    2376 }
    2377
    2378
    2379
    2380 /* replaces the refs to AUTO NIC hdls with the assigned one */
    2381
    2382 char * replace_refs_to_AUTO_NIC_hdl(char * changed_obj, char * arg, GHashTable * auto_nic_hash){
         /* [<][>][^][v][top][bottom][index][help] */
    2383
    2384   char * auto_nic = NULL;
    2385   GString* temp_string;
    2386   char * to_be_returned = NULL;
    2387   char ** temp = NULL;
    2388   int i, pos;
    2389
    2390   //printf("DEBUG: replace_first_ref_to_AUTO_NIC_hdl is running\n");
    2391
    2392   temp = g_strsplit(arg, "\n", 0);
    2393
    2394   for(i = 0; temp[i] != NULL; i++){
    2395     //printf("Line: %s\n", temp[i]);
    2396     if(   strstr(temp[i], "admin-c:") == temp[i]    /*    if it starts with admin-c */
    2397        || strstr(temp[i], "tech-c:" ) == temp[i]    /* or if it starts with tech-c */
    2398        || strstr(temp[i], "zone-c:" ) == temp[i]    /* or if it starts with zone-c */
    2399        || strstr(temp[i], "author:" ) == temp[i]){  /* or if it starts with author */
    2400       temp_string = g_string_new(temp[i]);
    2401       if(strstr(temp_string->str, "AUTO-") != NULL){
    2402         auto_nic = (char *)malloc(temp_string->len + temp_string->str - strstr(temp_string->str, "AUTO-")  + 1);
    2403         auto_nic = strncpy(auto_nic, strstr(temp_string->str, "AUTO-"),
    2404             temp_string->len + temp_string->str - strstr(temp_string->str, "AUTO-") );
    2405         auto_nic[temp_string->str + temp_string->len - strstr(temp_string->str, "AUTO-")] = '\0';
    2406         g_strstrip(auto_nic);
    2407         printf("DEBUG: auto_nic is [%s]\n", auto_nic);
    2408         pos = strstr(temp_string->str, "AUTO-") - temp_string->str;
    2409         temp_string = g_string_erase(temp_string,
    2410             strstr(temp_string->str, "AUTO-") - temp_string->str, strlen(auto_nic)/*strlen("AUTO-")*/);
    2411
    2412         //temp_string = g_string_insert(temp_string, pos, UPDATE_SOURCE);
    2413         //temp_string = g_string_insert(temp_string, pos, "*-");
    2414         /* if we have this AUTO NIC hdl in the hash, put it. */
    2415         if(g_hash_table_lookup(auto_nic_hash, auto_nic)){
    2416           temp_string = g_string_insert(temp_string, pos, (char *)g_hash_table_lookup(auto_nic_hash, auto_nic));
    2417         }else{/* else, return 0 immediately */
    2418           g_strfreev (temp);
    2419           return NULL;
    2420         }
    2421
    2422         if(to_be_returned == NULL){
    2423           to_be_returned = strdup(temp_string->str);
    2424           g_string_free(temp_string, TRUE);
    2425         }else{
    2426           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + temp_string->len + 2);
    2427           to_be_returned = strcat(to_be_returned, "\n");
    2428           to_be_returned = strcat(to_be_returned, temp_string->str);
    2429           g_string_free(temp_string, TRUE);
    2430         }
    2431       }else{
    2432         if(to_be_returned == NULL){
    2433           to_be_returned = strdup(temp[i]);
    2434         }else{
    2435           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2436           to_be_returned = strcat(to_be_returned, "\n");
    2437           to_be_returned = strcat(to_be_returned, temp[i]);
    2438         }
    2439       }
    2440     }else{/* if it doesn't begin with ac,tc,ac or author */
    2441         if(to_be_returned == NULL){
    2442           to_be_returned = strdup(temp[i]);
    2443         }else{
    2444           to_be_returned = (char *)realloc(to_be_returned, strlen(to_be_returned) + strlen(temp[i]) + 2);
    2445           strcat(to_be_returned, "\n");
    2446           strcat(to_be_returned, temp[i]);
    2447         }
    2448
    2449     }
    2450
    2451   }
    2452   g_strfreev (temp);
    2453   //free(arg);
    2454   //changed_obj = strdup(to_be_returned);
    2455   //free(to_be_returned);
    2456   printf("DEBUG: replace_first_ref_to_AUTO_NIC_hdl is returning,\nto_be_returned=[%s]\n", to_be_returned);
    2457   return to_be_returned;
    2458 }
    2459
    2460
    2461
    2462
    2463
    2464
    2465
    2466
    2467 /* Takes an object in a char * , and returns 1 if this object has
    2468    an AUTO NIC handle. Otherwise, returns 0 */
    2469 int has_AUTO_NIC_hdl(const char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    2470
    2471   Object * o = new Object();
    2472   GSList * attributes = NULL;
    2473   bool code;
    2474
    2475   code = o->scan(object, strlen(object));
    2476
    2477   if(code && !(o->isDeleted)){
    2478     attributes = get_attributes(o, "nic-hdl", object);
    2479     if(attributes != NULL){
    2480       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2481         g_slist_free(attributes);
    2482         delete(o);
    2483         return 1;
    2484       }
    2485     }
    2486     /* if control reaches here, then we will return 0 */
    2487     g_slist_free(attributes);
    2488     delete(o);
    2489     return 0;
    2490   }else{/* it doesn't pass syntax check. So, it doesn't matter if
    2491            it contains refs to AUTO NIC hdls. */
    2492     delete(o);
    2493     return 0;
    2494   }
    2495
    2496 }
    2497
    2498
    2499 /* Takes an object in a char * , and returns 1 if this object contains
    2500    a reference to an AUTO NIC handle. Otherwise, returns 0 */
    2501 int has_ref_to_AUTO_nic_hdl(const char * object){
         /* [<][>][^][v][top][bottom][index][help] */
    2502
    2503   Object * o = new Object();
    2504   GSList * attributes = NULL;
    2505   bool code;
    2506
    2507   code = o->scan(object, strlen(object));
    2508
    2509   if(code && !(o->isDeleted)){
    2510     attributes = get_attributes(o, "admin-c", object);
    2511     if(attributes != NULL){
    2512       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2513         g_slist_free(attributes);
    2514         delete(o);
    2515         return 1;
    2516       }
    2517     }
    2518     g_slist_free(attributes);
    2519     attributes = get_attributes(o, "tech-c", object);
    2520     if(attributes != NULL){
    2521       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2522         g_slist_free(attributes);
    2523         delete(o);
    2524         return 1;
    2525       }
    2526     }
    2527
    2528     g_slist_free(attributes);
    2529     attributes = get_attributes(o, "zone-c", object);
    2530     if(attributes != NULL){
    2531       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2532         g_slist_free(attributes);
    2533         delete(o);
    2534         return 1;
    2535       }
    2536     }
    2537     g_slist_free(attributes);
    2538     attributes = get_attributes(o, "author", object);
    2539     if(attributes != NULL){
    2540       if(strstr_in_list(attributes, "AUTO-") == 1){/* if it contains a ref to AUTO nic */
    2541         g_slist_free(attributes);
    2542         delete(o);
    2543         return 1;
    2544       }
    2545     }
    2546     /* if control reaches here, then we will return 0 */
    2547     delete(o);
    2548     return 0;
    2549   }else{/* it doesn't pass syntax check. So, it doesn't matter if
    2550            it contains refs to AUTO NIC hdls. */
    2551     delete(o);
    2552     return 0;
    2553   }
    2554
    2555 }
    2556
    2557
    2558 /*  */
    2559 void add_to_ack(const char * msg, const char * file_name){
         /* [<][>][^][v][top][bottom][index][help] */
    2560
    2561    FILE * ack_file;
    2562
    2563    if((ack_file = fopen(file_name, "a")) == NULL){
    2564      perror("Couldn't open ack file");
    2565      return;
    2566    }
    2567    fprintf(ack_file, "%s\n", msg);
    2568    fclose(ack_file);
    2569 }
    2570
    2571 /*  */
    2572 void add_to_ack_string(const string msg, const char * file_name){
         /* [<][>][^][v][top][bottom][index][help] */
    2573
    2574    ofstream ack_file(file_name, ios::app);
    2575
    2576    if(!ack_file){
    2577      cerr << "Couldn't open ack file" << endl;
    2578      return;
    2579    }
    2580    ack_file << msg << endl;
    2581    ack_file.close();
    2582 }
    2583
    2584
    2585 /* Checks the object's syntax, retrives the old version of it from the db,
    2586    and checks auth2. If everything is OK, then sends it to RIPdb, where referential
    2587    integrity is checked, and the object is really committed to the db.
    2588
    2589      Arguments:
    2590         char * arg: The object,
    2591         credentials_struct credentials: The struct containing the credentials, such as
    2592           'From:' field of the e-mail update,
    2593         GHashTable * NIC_hdl_hash: A hash containing
    2594         char * ack_file_name:  The file name, to be used to store ACK message
    2595 */
    2596
    2597 int process_object(char * arg, credentials_struct credentials, GHashTable * NIC_hdl_hash, char * ack_file_name){
         /* [<][>][^][v][top][bottom][index][help] */
    2598     bool code = true;
    2599     Object *o;
    2600     char * old_version = NULL;
    2601     o = new Object;
    2602     int result = 0;
    2603     int result_from_RIPupd = 0;
    2604     char * auto_nic = NULL;
    2605     char * changed_obj = NULL;
    2606     char * obj_with_AUTO_NIC_hdl;
    2607     char * assigned_NIC;
    2608
    2609     char * value = NULL;/* these two are for */
    2610     Attr * attr;        /* ack messages only */
    2611
    2612     if(has_ref_to_AUTO_nic_hdl(arg)){/* if this object has refs to AUTO NIC hdls*/
    2613        /* then first replace AUTO NIC hdls with assigned NIC hdls (in NIC_hdl_hash) */
    2614        if((arg = replace_refs_to_AUTO_NIC_hdl(changed_obj, arg, NIC_hdl_hash)) == NULL){
    2615          return UP_ANE; /* AUTO NIC hdl error */
    2616        };
    2617     }
    2618
    2619     code = o->scan(arg,strlen(arg));
    2620     if(code){
    2621       /* is the object to be deleted? */
    2622       if(o->isDeleted){
    2623         printf("This object is to be deleted\n");
    2624         old_version = get_old_version(arg);
    2625         if(old_version == NULL){ // the object doesn't exist in the db!
    2626           add_to_ack("\nDeletion Failed: Object doesn't exist", ack_file_name);
    2627           add_to_ack(o->type->getName(), ack_file_name);
    2628           add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2629           return UP_NSO; /* no such object */
    2630         }else {/* the object is in the db */
    2631           if(identical(old_version, arg)){/* if the old & new versions are identical */
    2632             result = check_auth(NULL, old_version, o->type->getName(), credentials);
    2633             if(result == UP_AUTH_OK){
    2634               if(tracing) {
    2635                 printf("TRACING: Will send the obj to be deleted\n");
    2636               }
    2637               result_from_RIPupd = send_object_db(arg, NULL, "DEL");
    2638               if(result_from_RIPupd == 0){
    2639                 add_to_ack("\nDeletion succeeded", ack_file_name);
    2640                 add_to_ack(o->type->getName(), ack_file_name);
    2641                 add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2642               }else{
    2643                 add_to_ack("\nDeletion failed: Referential intergrity failure", ack_file_name);
    2644                 add_to_ack(o->type->getName(), ack_file_name);
    2645                 add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2646               }
    2647               result_from_RIPupd = 0;
    2648             }else{ /* auth failed */
    2649               if(tracing) {
    2650                 printf("TRACING: Auth failed\n");
    2651               }
    2652               if(error_msg != NULL){
    2653                   cout << error_msg << endl;
    2654               }
    2655               add_to_ack("\nDeletion failed: Auth failed", ack_file_name);
    2656               add_to_ack(o->type->getName(), ack_file_name);
    2657               add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2658               return UP_AUF; /* Auth failed */
    2659             }
    2660           }else{/* the new & old versions do not match */
    2661             add_to_ack("Deletion failed: new & old versions do not match", ack_file_name);
    2662             return UP_NOM; /* new & old versions do not match */
    2663           }
    2664         }
    2665       }else {/* the object is _not_ to be deleted */
    2666         if(has_AUTO_NIC_hdl(arg)){/* it the object has an AUTO NIC hdl */
    2667           /* then its nic-hdl attribute must be modified so that RIPupdate
    2668              would understand that it must assign a NIC handle to it */
    2669           /* but first check the auth */
    2670           result = check_auth(arg, NULL, o->type->getName(), credentials);
    2671           if(result == UP_AUTH_OK){
    2672             if(tracing) {
    2673                 printf("TRACING: Will send the obj to be created with AUTO NIC hdl\n");
    2674             }
    2675             auto_nic = (char *)malloc(1024); /* should be enough for a NIC hdl */
    2676             obj_with_AUTO_NIC_hdl = replace_AUTO_NIC_hdl(arg, auto_nic);
    2677             if(tracing) {
    2678               printf("TRACING:  Called replace_AUTO_NIC_hdl, get [%s]\n", obj_with_AUTO_NIC_hdl);
    2679               printf("TRACING: Will send the obj to be added\n");
    2680             }
    2681             assigned_NIC = (char *)malloc(128); /* this should be enough for a NIC hdl */
    2682             result_from_RIPupd = send_object_db(obj_with_AUTO_NIC_hdl, assigned_NIC, "ADD");
    2683             if(result_from_RIPupd == 0){
    2684               add_to_ack("\nCreation succeeded", ack_file_name);
    2685               add_to_ack(o->type->getName(), ack_file_name);
    2686               add_to_ack(assigned_NIC, ack_file_name);
    2687             }else{
    2688               add_to_ack("\nCreation failed: Referential integrity failure", ack_file_name);
    2689               add_to_ack(o->type->getName(), ack_file_name);
    2690               add_to_ack(arg, ack_file_name);
    2691             }
    2692             result_from_RIPupd = 0;
    2693             if(tracing && assigned_NIC != NULL) {
    2694               printf("TRACING: send_object_db returned [%s] as assigned NIC hdl\n", assigned_NIC);
    2695             }
    2696             if(assigned_NIC != NULL){
    2697               printf("DEBUG: auto_nic=[%s], assigned_NIC=[%s]\n", auto_nic, assigned_NIC);
    2698               g_hash_table_insert(NIC_hdl_hash, auto_nic, assigned_NIC);
    2699               printf("DEBUG: NIC_hdl_hash has %i pairs\n",g_hash_table_size(NIC_hdl_hash));
    2700             }
    2701
    2702           }else{
    2703             // auth failed !
    2704             if(tracing) {
    2705               printf("TRACING: Auth failed\n");
    2706             }
    2707             if(error_msg != NULL){
    2708               cout << error_msg << endl;
    2709             }
    2710             ER_perror(0, result, "");
    2711             add_to_ack("\nCreation failed: Auth failed", ack_file_name);
    2712             add_to_ack(o->type->getName(), ack_file_name);
    2713             add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2714             return UP_AUF; /* Auth failed */
    2715           }
    2716         }
    2717         else{
    2718           old_version = get_old_version(arg);
    2719           if(old_version != NULL){/* so, this is an update operation */
    2720             result = check_auth(arg, old_version, o->type->getName(), credentials);
    2721             if(result == UP_AUTH_OK){
    2722               if(tracing) {
    2723                 printf("TRACING: Will send the obj to be updated\n");
    2724               }
    2725               result_from_RIPupd = send_object_db(arg, NULL, "UPD");
    2726               if(result_from_RIPupd == 0){
    2727                 add_to_ack("\nUpdate succeeded", ack_file_name);
    2728                 add_to_ack(o->type->getName(), ack_file_name);
    2729                 add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2730               }else{
    2731                 add_to_ack("\nUpdate failed: Referential integrity failure", ack_file_name);
    2732                 add_to_ack(o->type->getName(), ack_file_name);
    2733                 add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2734               }
    2735               result_from_RIPupd = 0;
    2736             }else{
    2737               // auth failed !
    2738               if(tracing) {
    2739                 printf("TRACING: Auth failed\n");
    2740               }
    2741               if(error_msg != NULL){
    2742                 cout << error_msg << endl;
    2743               }
    2744               add_to_ack("\nUpdate failed: Auth failed", ack_file_name);
    2745               add_to_ack(o->type->getName(), ack_file_name);
    2746               add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2747               return UP_AUF; /* Auth failed */
    2748             }
    2749           }else { /* old_version  == NULL, so, creation */
    2750             result = check_auth(arg, NULL, o->type->getName(), credentials);
    2751             if(result == UP_AUTH_OK){
    2752               if(tracing) {
    2753                 printf("TRACING: Will send the obj to be added\n");
    2754               }
    2755               result_from_RIPupd = send_object_db(arg, NULL, "ADD");
    2756               if(result_from_RIPupd == 0){
    2757                 add_to_ack("\nCreation succeeded", ack_file_name);
    2758                 add_to_ack(o->type->getName(), ack_file_name);
    2759                 add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2760               }else{
    2761                 add_to_ack("\nCreation failed: Referential integrity failure", ack_file_name);
    2762                 add_to_ack(o->type->getName(), ack_file_name);
    2763                 add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2764               }
    2765               result_from_RIPupd = 0;
    2766             }else{
    2767               // auth failed !
    2768               if(tracing) {
    2769                 printf("TRACING: Auth failed\n");
    2770               }
    2771               if(error_msg != NULL){
    2772                 cout << error_msg << endl;
    2773               }
    2774               ER_perror(0, result, "");
    2775               add_to_ack("\nCreation failed: Auth failed", ack_file_name);
    2776               add_to_ack(o->type->getName(), ack_file_name);
    2777               add_to_ack(get_search_key(o, o->type->getName(), arg), ack_file_name);
    2778               return UP_AUF; /* Auth failed */
    2779             }
    2780           }
    2781         }
    2782       }
    2783     }else{// even if obj doesn't parse properly, it may be a legacy object
    2784           // which the user wants to delete...
    2785        printf("DEBUG: Object didn't parse\n");
    2786        add_to_ack("\nFailed: Syntax error in object", ack_file_name);
    2787        add_to_ack(arg, ack_file_name);
    2788        //for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
    2789        //  value = (char*)malloc((*attr).len );
    2790        //  strncpy(value, (char *)(arg+attr->offset) ,
    2791        //    attr->len - 1);
    2792        //  value[attr->len - 1] = '\0';
    2793        //  add_to_ack(value, ack_file_name);
    2794        //  if(!attr->errors.empty()){
    2795        //    add_to_ack_string(attr->errors, ack_file_name);
    2796        //  }
    2797        //  free(value);
    2798        // }
    2799        // if(o->has_error){
    2800        //   add_to_ack_string(o->errors, ack_file_name);
    2801        // }
    2802
    2803        return UP_NIY; /* Not implemented yet */
    2804     }
    2805 }
    2806
    2807
    2808
    2809
    2810 /* Gets the "From" line of the incoming mail message and finds out an
    2811    address to send the acknowledgement */
    2812 char * find_to_address(const char * from_line){
         /* [<][>][^][v][top][bottom][index][help] */
    2813   char * pos1 = NULL, * pos2 = NULL;
    2814   char * temp = NULL;
    2815
    2816   if(from_line == NULL){
    2817     return NULL;
    2818   }
    2819   if(strstr(from_line, "From:") != from_line){/* there is a problem, the line must start with
    2820                                                  "From:" */
    2821     fprintf(stderr, "The line doesn't start with 'From:'\n");
    2822     return NULL;
    2823   }
    2824   temp = strdup(from_line + strlen("From:"));
    2825   g_strstrip(temp);
    2826   if(index(temp, '<')){/* then the line is something like '"John White" <john@inter.net>' */
    2827     pos1 = index(temp, '<');
    2828     pos2 = index(temp, '>');
    2829     temp = strncpy(temp, pos1 + 1, pos2 - pos1 -1);
    2830     temp[pos2 - pos1 - 1] = '\0';
    2831     printf("DEBUG: find_to_address\n");
    2832     printf("DEBUG: find_to_address temp=[%s]\n", temp);
    2833     return temp;
    2834   }else{/* the line contains only the address, then */
    2835    return temp;
    2836   }
    2837 }
    2838

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