## modules/ud/ud_core.c

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

## FUNCTIONS

This source file includes following functions.

1. s_split
2. s_splitn
3. convert_if
4. convert_rf
5. convert_as
6. convert_as_range
7. convert_time
8. get_set_name
9. get_object_id
10. get_qresult_str
11. get_field_str
12. get_sequence_id
13. get_ref_id
14. isdummy
15. isnichandle
16. process_reverse_domain
17. insert_reverse_domain
18. update_reverse_domain
19. auth_member_of
20. create_dummy
21. update_attr
22. each_attribute_process
23. each_primary_key_select
24. perform_create
25. perform_update
26. object_process

       1 /***************************************
       2   $Revision: 1.18 $
       3
       4   Core functions for update lower layer
       5
       6   Status: NOT REVUED, NOT TESTED
       7
       8  Author(s):       Chris Ottrey, Andrei Robachevsky
       9
      10   ******************/ /******************
      11   Modification History:
      12         andrei (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 #include "ud.h"
      34 #include "ud_int.h"
      35
      36 static int perform_update(Transaction_t *tr);
      37
      38 static int perform_create(Transaction_t *tr);
      39
      40 static void each_primary_key_select(void *element_data, void *result_ptr);
      41
      42 static void each_attribute_process(void *element_data, void *tr_ptr);
      43
      44 static void update_attr(Attribute_t *attr, Transaction_t *tr);
      45
      46 static int create_dummy(Attribute_t *attr, Transaction_t *tr);
      47
      48 static int auth_member_of(Attribute_t *attr, Transaction_t *tr);
      49
      50 /***************************************************
      51 * char *s_split(char *line)                        *
      52 *                                                  *
      53 * Consequently returns words of the 'line'         *
      54 * When there are no words it returns NULL          *
      55 * You need to retreive all words !                 *
      56 *                                                  *
      57 * NB This function damages 'line' replacing        *
      58 * whitespace with '\0'                             *
      59 * *************************************************/
      60 static char *s_split(char *line)
         /* [<][>][^][v][top][bottom][index][help] */
      61 {
      62 static char *delim;
      63 static char *token=NULL;
      64
      65  if(token==NULL)token=line;
      66  else token=delim;
      67
      68  if(token==NULL)return(token);
      69  while(isspace((int)*token))token++;
      70  delim=token;
      71
      72  while(!isspace((int)*delim)) {
      73         if((*delim)=='\0'){
      74                 if(delim==token)token=NULL;
      75                 delim=NULL; return(token);
      76         }
      77         delim++;
      78  }
      79  *delim='\0'; delim++;
      80  return(token);
      81
      82 }
      83
      84 /* The same as s_split() but returns nwords words */
      85 /*  and the rest of the line                      */
      86 static char *s_splitn(char *line, int nwords)
         /* [<][>][^][v][top][bottom][index][help] */
      87 {
      88 static char *delim;
      89 static char *token=NULL;
      90 static int w=0;
      91
      92
      93  if(token==NULL)token=line;
      94  else token=delim;
      95
      96  w++; if(w>nwords){ w=0; delim=token; token=NULL; return(delim); }
      97
      98  if(token==NULL)return(token);
      99  while(isspace((int)*token))token++;
     100  delim=token;
     101
     102  while(!isspace((int)*delim)) {
     103         if((*delim)=='\0'){
     104                 if(delim==token)token=NULL;
     105                 delim=NULL; return(token);
     106         }
     107         delim++;
     108  }
     109  *delim='\0'; delim++;
     110  return(token);
     111
     112
     113 }
     114
     115 /**********************************************************
     116 * Attribute expansion/conversion functions                *
     117 ***********************************************************/
     118 /* Convert ifaddr attribute into numbers */
     119 er_ret_t convert_if(char *avalue, unsigned int *pif_address)
         /* [<][>][^][v][top][bottom][index][help] */
     120 {
     121 char *delim;
     122 ip_addr_t ip_addr;
     123 er_ret_t ret;
     124
     125   if ((delim=index(avalue, ' '))!=NULL) *delim='\0';
     126   ret=IP_addr_a2v4(avalue, &ip_addr,  pif_address );
     127   return(ret);
     128 }
     129
     130
     131 /* Convert refer attribute. Free host after use ! */
     132 char *convert_rf(char *avalue, int *type, int *port)
         /* [<][>][^][v][top][bottom][index][help] */
     133 {
     134 char *delim, *token;
     135 char buff[STR_M];
     136 char *host;
     137
     138   host=NULL;
     139   strcpy(buff, avalue);
     140   g_strchug(buff);
     141   delim=index(buff, ' ');
     142   *delim='\0';
     143   delim++;
     144
     145 /* convert the type      */
     146   if(strcmp(buff, S_RIPE)==0)*type=RF_RIPE;
     147    else if(strcmp(buff, S_INTERNIC)==0)*type=RF_INTERNIC;
     148     else if(strcmp(buff, S_SIMPLE)==0)*type=RF_SIMPLE;
     149      else if(strcmp(buff, S_CLIENTADDERSS)==0)*type=RF_CLIENTADDRESS;
     150
     151   token=delim;
     152   g_strchug(token);
     153   delim=index(token, ' ');
     154   if(delim){
     155    *delim='\0';
     156    delim++;
     157   }
     158 /* convert the hostname      */
     159   host = g_strdup(token);
     160
     161 /* convert port number      */
     162   if(delim){
     163     token=delim;
     164     *port = atoi(token);
     165     if (*port==0) *port=RF_DEF_PORT; /* default port number*/
     166   } else *port=RF_DEF_PORT;
     167   return(host);
     168 }
     169
     170
     171 /* Convert AS# into integer */
     172 static int convert_as(char *as)
         /* [<][>][^][v][top][bottom][index][help] */
     173 {
     174 char *ptr;
     175  ptr=as; ptr++; ptr++;
     176  return(atoi(ptr));
     177 }
     178
     179 /* Convert AS range (AS4321 - AS5672) into numbers */
     180 int convert_as_range(const char *as_range, int *begin, int *end)
         /* [<][>][^][v][top][bottom][index][help] */
     181 {
     182 char buf[STR_M];
     183   strcpy(buf, as_range); /*save it*/
     184   *begin=convert_as(s_split(buf));
     185   s_split(buf); /* should be '-'*/
     186   *end=convert_as(s_split(buf));
     187   while(s_split(buf));
     188   return(0);
     189 }
     190
     191 /* Convert time in ASCII format (19991224) into time_t unix time */
     192 time_t convert_time(char *asc_time)
         /* [<][>][^][v][top][bottom][index][help] */
     193 {
     194 struct tm tm;
     195 char buf[STR_S];
     196 char *ptr;
     197
     198
     199   bzero(&tm, sizeof(tm));
     200
     201   strncpy(buf, asc_time, 4); ptr=buf+4; *ptr='\0';
     202   tm.tm_year = atoi(buf) - 1900;
     203
     204   strncpy(buf, (asc_time+4), 2); ptr=buf+2; *ptr='\0';
     205   tm.tm_mon = atoi(buf) - 1;
     206
     207   strncpy(buf, (asc_time+6), 2); ptr=buf+2; *ptr='\0';
     208   tm.tm_mday = atoi(buf);
     209
     210   return(mktime(&tm));
     211
     212 }
     213
     214
     215 /************************************************************
     216 *  char *get_set_name()                                     *
     217 *                                                           *
     218 * Returns set name for the specified object class           *
     219 *                                                           *
     220 * **********************************************************/
     221 static char *get_set_name(C_Type_t class_type)
         /* [<][>][^][v][top][bottom][index][help] */
     222 {
     223  switch(class_type){
     224   case C_RT:   return("route_set");
     225   case C_AN:   return("as_set");
     226   default:     return(NULL);
     227  }
     228 }
     229
     230
     231 /************************************************************
     232 * long get_object_id()                                      *
     233 * Queries the database for an object.                       *
     234 * For constructing a query uses each_primary_key_select()   *
     235 *                                                           *
     236 * Returns:                                                  *
     237 * >0 - object exists, returns object_id                     *
     238 * 0  - object does not exist                                *
     239 * -1 - error (f.e. more than one object with the same PK)   *
     240 * Error code is stored in tr->error                         *
     241 *                                                           *
     242 * **********************************************************/
     243 long get_object_id(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     244 {
     245 Object_t *obj=tr->object;
     246 SQ_result_set_t *sql_result;
     247 SQ_row_t *sql_row;
     248 char *sql_str;
     249 GString *query;
     250 long object_id=0;
     251 int sql_err;
     252
     253  if ((query = g_string_sized_new(STR_XL)) == NULL){
     254   fprintf(stderr, "E: cannot allocate gstring\n");
     255   tr->succeeded=0;
     256   tr->error |= ERROR_U_MEM;
     257   return(-1);
     258  }
     259
     260 /* compose query */
     261  g_string_sprintf(query, "SELECT object_id FROM %s WHERE",DF_get_class_sql_table(obj->type));
     262  /* add all primary keys */
     263  g_slist_foreach(obj->attributes, each_primary_key_select, query);
     264  /* truncate the last ' AND '*/
     265  g_string_truncate(query, (query->len) - 4);
     266
     267 /* execute query */
     268  sql_err=SQ_execute_query(tr->sql_connection, query->str, &sql_result);
     269  g_string_free(query, TRUE);
     270
     271 /* in case of an error copy error code and return */
     272  if(sql_err) {
     273    fprintf(stderr,"ERROR: %s\n", SQ_error(tr->sql_connection));
     274    tr->succeeded=0;
     275    tr->error |= ERROR_U_DBS;
     276    return(-1);
     277  }
     278
     279 /* Fetch the row */
     280  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
     281 /* Object exists */
     282 #define OBJECT_ID 0
     283    sql_str = SQ_get_column_string(sql_result, sql_row, OBJECT_ID);
     284    if (sql_str != NULL) {
     285      object_id = atol(sql_str);
     286      free(sql_str);
     287    }
     288
     289 /* We must process all the rows of the result */
     290 /* otherwise we'll have them as part of the next qry */
     291    while ( (sql_row = SQ_row_next(sql_result)) != NULL) object_id=-1;
     292  } else
     293       object_id=0;  /* object does not exist*/
     294
     295  SQ_free_result(sql_result);
     296  return(object_id);
     297 }
     298
     299
     300 /************************************************************
     301 * get_qresult_str()                                         *
     302 *                                                           *
     303 * Returns string containing query result                    *
     304 *                                                           *
     305 *                                                           *
     306 * Returns:                                                  *
     307 *  String containing the result.Needs to be freed after use *
     308 *  NULL in case of an error                                 *
     309 *  - SQL error                                              *
     310 *  - if query returns more than one string (row)            *
     311 *                                                           *
     312 *************************************************************/
     313 char *get_qresult_str(SQ_connection_t *sql_connection, char *query)
         /* [<][>][^][v][top][bottom][index][help] */
     314 {
     315 SQ_result_set_t *sql_result;
     316 SQ_row_t *sql_row;
     317 char *sql_str;
     318 int sql_err;
     319
     320
     321 /*fprintf(stderr, "D:<get_field_str>:query: %s\n", query);*/
     322  sql_err=SQ_execute_query(sql_connection, query, &sql_result);
     323
     324  if(sql_err) {
     325     fprintf(stderr,"ERROR: %s\n", SQ_error(sql_connection));
     326     die;
     327  }
     328
     329
     330  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
     331         sql_str = SQ_get_column_string(sql_result, sql_row, 0);
     332
     333      /* We must process all the rows of the result,*/
     334      /* otherwise we'll have them as part of the next qry */
     335         while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
     336           fprintf(stderr, "E:<get_field_str> error : Dupl PK[%s]\n", query);
     337           if(sql_str)free(sql_str); sql_str=NULL;
     338         }
     339  }
     340  else sql_str=NULL;
     341
     342  SQ_free_result(sql_result);
     343  return(sql_str);
     344 }
     345
     346
     347
     348 /************************************************************
     349 * get_field_str()                                           *
     350 *                                                           *
     351 * Returns string containing the field.                      *
     352 *  field - field name to be retrieved                       *
     353 *  ref_tbl_name - name of the table containing the field    *
     354 *  ref_name - reference name                                *
     355 *  attr_value - reference value                             *
     356 *  condition - additional condition ( f.e. 'AND dummy=0'    *
     357 *                                                           *
     358 * Returns:                                                  *
     359 *  String containing the field. Needs to be freed after use *
     360 *  NULL in case of an error                                 *
     361 *                                                           *
     362 *************************************************************/
     363 char *get_field_str(SQ_connection_t *sql_connection, char *field,
         /* [<][>][^][v][top][bottom][index][help] */
     364                            char *ref_tbl_name, char *ref_name,
     365                            char * attr_value, char *condition)
     366 {
     367 static char query[STR_L];
     368
     369  sprintf(query, "SELECT %s FROM %s "
     370                 "WHERE %s='%s' ",
     371                 field, ref_tbl_name, ref_name, attr_value);
     372  if (condition)strcat(query, condition);
     373
     374  return( get_qresult_str(sql_connection, query));
     375
     376 }
     377
     378 /************************************************************
     379 * long get_sequence_id(Transaction_t *tr)
     380 * >0 - success
     381 * -1 - sql error
     382 *
     383 * **********************************************************/
     384
     385 long get_sequence_id(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     386 {
     387 char *sql_str;
     388 char str_id[STR_M];
     389 long sequence_id=-1;
     390
     391
     392   sprintf(str_id, "%ld", tr->object_id);
     393   sql_str= get_field_str(tr->sql_connection, "sequence_id", "last", "object_id", str_id, NULL);
     394   if(sql_str) {
     395           sequence_id = atol(sql_str);
     396 /*                fprintf(stderr, "D: Retrieved set serial id = %ld\n", sequence_id);*/
     397           free(sql_str);
     398   }
     399
     400   return(sequence_id);
     401
     402 }
     403
     404
     405 /************************************************************
     406 * long get_ref_id(char *ref_tbl_name, char *ref_name, char * attr_value)
     407 * >0 - success
     408 * -1 - sql error
     409 *
     410 * **********************************************************/
     411
     412 static long get_ref_id(Transaction_t *tr, char *ref_tbl_name, char *ref_name, char * attr_value, char *condition)
         /* [<][>][^][v][top][bottom][index][help] */
     413 {
     414 char *sql_str;
     415 long ref_id=-1;
     416
     417 /*fprintf(stderr, "D:<get_ref_id>: entering...\n");*/
     418
     419         sql_str= get_field_str(tr->sql_connection, "object_id", ref_tbl_name, ref_name, attr_value, condition);
     420         if(sql_str) {
     421                  ref_id = atol(sql_str);
     422 /*               fprintf(stderr, "D: Retrieved set serial id = %ld\n", ref_id);*/
     423                  free(sql_str);
     424         }
     425         return(ref_id);
     426 }
     427
     428
     429 /************************************************************
     430 * int isdummy()
     431 *
     432 * Returns 1 if the object in question is a dummy,
     433 * otherwise returns 0.
     434 *
     435 * In case of error:
     436 * -1 - sql error or object does not exist
     437 *
     438 ***********************************************************/
     439
     440 int isdummy(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     441 {
     442 char *sql_str;
     443 char str_id[STR_M];
     444 int object_type=-1;
     445
     446   sprintf(str_id, "%ld", tr->object_id);
     447   sql_str= get_field_str(tr->sql_connection, "object_type", "last", "object_id", str_id, NULL);
     448   if(sql_str) {
     449           object_type = atoi(sql_str);
     450           free(sql_str);
     451   }
     452
     453   if (object_type==-1) return(-1);
     454   if (object_type==DUMMY_TYPE) return(1);
     455   else return(0);
     456
     457 }
     458
     459 static int isnichandle(char *name)
         /* [<][>][^][v][top][bottom][index][help] */
     460 {
     461  return(MA_isset(WK_new(name), WK_NIC_HDL));
     462 }
     463
     464
     465 /************************************************************
     466 * process_reverse_domain()                                  *
     467 *                                                           *
     468 * Tries to insert additional data for reverse domains       *
     469 * This data includes prefix and perfix length for reverse   *
     470 * delegation block. It is stored in inaddr_arpa table for   *
     471 * IPv4 and ip6int table for IPv6 address spaces             *
     472 *                                                           *
     473 * Returns:                                                  *
     474 * 0  success                                                *
     475 * -1 sql error                                              *
     476 *                                                           *
     477 *************************************************************/
     478
     479 static int process_reverse_domain(Transaction_t *tr,
         /* [<][>][^][v][top][bottom][index][help] */
     480                                   ip_prefix_t *prefptr,
     481                                   int op)
     482 {
     483   unsigned prefix, prefix_length; /* ipv4 */
     484   ip_v6word_t high, low;          /* ipv6 */
     485   char query[STR_L];
     486   int num;
     487   int sql_err;
     488
     489
     490   if( IP_pref_b2_space(prefptr) == IP_V4 ) {  /* ipv4 */
     491     if(op==0) { /* insert record */
     492       IP_revd_b2v4(prefptr, &prefix, &prefix_length);
     493       sprintf(query, "INSERT INTO inaddr_arpa SET thread_id=%d, object_id=%ld, prefix=%u, prefix_length=%d ",
     494               tr->thread_ins, tr->object_id, prefix, prefix_length);
     495     }
     496     else {
     497       /* update record */
     498       sprintf(query, "UPDATE inaddr_arpa SET thread_id=%d WHERE object_id=%ld ",
     499               tr->thread_upd, tr->object_id);
     500     }
     501   }
     502   else { /* ipv6 */
     503     if(op==0) { /* insert record */
     504       IP_revd_b2v6(prefptr, &high, &low, &prefix_length);
     505       sprintf(query, "INSERT INTO ip6int SET thread_id=%d, object_id=%ld, high=%llu, low=%llu, prefix_length=%d ",
     506               tr->thread_ins, tr->object_id, high, low, prefix_length);
     507     }
     508     else {
     509       /* update record */
     510       sprintf(query, "UPDATE ip6int SET thread_id=%d WHERE object_id=%ld ",
     511               tr->thread_upd, tr->object_id);
     512     }
     513   }
     514
     515   sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
     516   num = mysql_affected_rows(tr->sql_connection);
     517
     518   /* Check for errors */
     519   if (sql_err) {
     520    fprintf(stderr, "E: insert inaddr:%s[%s]\n", SQ_error(tr->sql_connection), query);
     521    return(-1);
     522   }
     523   /* If nothing was affected then WHERE clause returned nothing - DB error */
     524   if(num == 0) {
     525    fprintf(stderr, "E: insert inaddr:no effect [%s]\n", query);
     526    return(-1);
     527   }
     528   return(0);
     529 }
     530
     531 #define insert_reverse_domain(tr, pr) process_reverse_domain(tr, pr, 0)
         /* [<][>][^][v][top][bottom][index][help] */
     532 #define update_reverse_domain(tr, pr) process_reverse_domain(tr, pr, 1)
         /* [<][>][^][v][top][bottom][index][help] */
     533
     534
     535 /************************************************************
     536 * auth_member_of()                                          *
     537 *                                                           *
     538 * Function that checks the authorization for membership     *
     539 * (i.e. if the object is authorized to be a memeber by      *
     540 * mbrs-by-ref attribute of the set is refers by member-of   *
     541 * attribute).                                               *
     542 * First checks if 'mbrs-by-ref: ANY'                        *
     543 * If not then checks that maintner referenced by            *
     544 * mbrs-by-ref attribute of the set is the one in mnt-by.    *
     545 *                                                           *
     546 * Returns:                                                  *
     547 * 0  success                                                *
     548 * 1  not allowed                                            *
     549 * -1 SQL error                                              *
     550 *                                                           *
     551 *************************************************************/
     552 static int auth_member_of(Attribute_t *attr, Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     553 {
     554 GString *query;
     555 /* SQ_result_set_t *sql_result; */
     556 /* SQ_row_t *sql_row; */
     557 char *set_name;
     558 char *qresult;
     559 int error;
     560 /* char *sq_error; */
     561 /* int sql_err; */
     562
     563
     564  error=0;
     565
     566 /* Check if set has mbrs_by_ref==ANY
     567    In such case mbrs_by_ref.mnt_id==0
     568 */
     569
     570  if ((query = g_string_sized_new(STR_XL)) == NULL){
     571   tr->succeeded=0;
     572   tr->error |= ERROR_U_MEM;
     573   fprintf(stderr, "E: cannot allocate gstring\n");
     574   return(-1);
     575  }
     576
     577  set_name = get_set_name(tr->class_type);
     578 /* fprintf(stderr, "D:<auth_member_of>: Got set name: %s\n", set_name); */
     579
     580 /* Check if the set protects itself with mbrs-by-ref attribute */
     581    g_string_sprintf(query,"SELECT COUNT(*) FROM mbrs_by_ref, %s "
     582                           "WHERE mbrs_by_ref.object_id=%s.object_id "
     583                           "AND %s.%s='%s' ",
     584                           set_name, set_name, set_name, set_name, attr->value);
     585
     586    qresult = get_qresult_str(tr->sql_connection, query->str);
     587    /* should be '0' if there is no mbrs-by-ref attribute */
     588    if (strcmp(qresult, "0")==0){
     589            /* there is no mbrs-by-ref attribute - so we cannot go ahead */
     590            fprintf(stderr, "E:<auth_member_of> : Membership is not autorized[%s]\n",query->str);
     591            g_string_free(query, TRUE);
     592            return(1);
     593    }
     594    else free(qresult);
     595
     596 /* Check if membership is protected by the keyword "ANY" */
     597 /* There is a dummy mntmer object in the database corresponding to "ANY" */
     598 /* Its object_id==0 */
     599 /* EXAMPLE:
     600
     601    SELECT route_set.object_id
     602    FROM   mbrs_by_ref, route_set
     603    WHERE  mbrs_by_ref.object_id=route_set.object_id
     604    AND    route_set.route_set=<setname>
     605    AND    mbrs_by_ref.mnt_id=0
     606 */
     607     g_string_sprintf(query,"SELECT %s.object_id FROM mbrs_by_ref, %s "
     608                            "WHERE mbrs_by_ref.object_id=%s.object_id "
     609                            "AND %s.%s='%s' AND mbrs_by_ref.mnt_id=0 ",
     610                            set_name, set_name, set_name, set_name, set_name, attr->value);
     611 /* fprintf(stderr, "D:<auth_member_of>: query: %s\n", query->str);*/
     612
     613     qresult = get_qresult_str(tr->sql_connection, query->str);
     614   /* if such record exists - go ahead */
     615     if(qresult) {
     616         free(qresult);
     617         g_string_free(query, TRUE);
     618         return(0);
     619     }
     620
     621 /* Now check if our mnt_by belongs to mbrs_by_ref list of the set */
     622 /* we search only mnt_by.thread_id!=0 to check against new/updated mnt-by attribute */
     623     g_string_sprintf(query, "SELECT mbrs_by_ref.object_id FROM route_set, mbrs_by_ref, mnt_by "
     624                             "WHERE mbrs_by_ref.mnt_id=mnt_by.mnt_id "
     625                             "AND mnt_by.object_id=%ld "
     626                             "AND %s.object_id=mbrs_by_ref.object_id "
     627                             "AND %s.%s='%s' "
     628                             "AND mnt_by.thread_id!=0 ",
     629                             tr->object_id, set_name, set_name, set_name, attr->value);
     630
     631 /*  fprintf(stderr, "D:<auth_member_of>: query: %s\n", query->str);                                             */
     632
     633     qresult = get_qresult_str(tr->sql_connection, query->str);
     634     /* If our mntner is listed (non-empty result)  membership is authorized */
     635     if (qresult) {
     636          free(qresult);g_string_free(query, TRUE);
     637          return(0);
     638     } else {
     639          fprintf(stderr, "E:<auth_member_of> : Membership is not autorized[%s]\n", query->str);
     640          g_string_free(query, TRUE);
     641          return(1);
     642     }
     643  }/* auth_member_of()  */
     644
     645
     646 /************************************************************
     647 * create_dummy()                                            *
     648 *                                                           *
     649 * Function that creates a dummy object (that is one that    *
     650 * is referenced from an object but does not                 *
     651 * exist in the database).                                   *
     652 * Dummy object exists only in relevant main and 'last'      *
     653 * tables. Its creation is controlled by tr->dummy_allowed.  *
     654 * Queries for the dummies are defined in Dummy[] array.     *
     655 *                                                           *
     656 * Returns:                                                  *
     657 * 0  success                                                *
     658 * 1  no rf integrity and dummy not allowed
     659 * -1 SQL error                                              *
     660 *                                                           *
     661 *************************************************************/
     662 static int create_dummy(Attribute_t *attr, Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     663 {
     664 /*SQ_result_set_t *sql_result;*/
     665 const char *query_fmt;
     666 long dummy_id;
     667 char query[STR_L];
     668 int result=0;
     669 char *set_name;
     670 char *p_name;
     671 int query_type;
     672 long timestamp;
     673 char str_id[STR_M];
     674 gchar *attr_value=NULL;
     675 int sql_err;
     676
     677
     678 /*  query_fmt = Dummy[attr->type].qry; */
     679   query_fmt = DF_get_dummy_query(attr->type);
     680   if (strcmp(query_fmt, "") == 0) {
     681      fprintf(stderr, "E:<create_dummy>: empty query string\n");
     682      return(1);
     683   }
     684
     685   /* We allow creating dummy sets in any mode */
     686   /* For others attributes return if we are in protected mode */
     687   if ((attr->type!=A_MO) &&  (tr->dummy != 1)) return(1);
     688
     689   /* Insert dummy in the last table */
     690   sprintf(str_id, "%ld", tr->object_id);
     691   timestamp=time(NULL);
     692   sprintf(query, "INSERT INTO last SET thread_id=%d, timestamp=%ld, object_type=%d, object='DUMMY for %s'",
     693                   tr->thread_ins, timestamp, DUMMY_TYPE, str_id);
     694 /* fprintf(stderr, "D: making dummy entry in the last table\n %s\n", query);*/
     695   sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
     696 /*  num = mysql_affected_rows(tr->sql_connection);*/
     697
     698   /* Check for errors */
     699   if (sql_err) {
     700    fprintf(stderr, "E: dummy->last:[%s]\n", query);
     701    return(-1);
     702   }
     703
     704   /* insert dummy in the main table */
     705   dummy_id=mysql_insert_id(tr->sql_connection);
     706   /* Record dummy's object_id, it'll be needed in commit/rollback */
     707   tr->dummy_id[tr->ndummy]=dummy_id; tr->ndummy++;
     708
     709   /* compose the query */
     710 /*  query_type=Dummy[attr->type].qtype; */
     711   query_type=DF_get_dummy_query_type(attr->type);
     712   switch (query_type) {
     713
     714          /* person_role */
     715          case UD_AX_PR:
     716               sprintf(query, query_fmt, tr->thread_ins, dummy_id, attr->value, DUMMY_TYPE);
     717               break;
     718
     719          /* maintner */
     720          case UD_AX_MT:
     721               sprintf(query, query_fmt, tr->thread_ins, dummy_id, attr->value, DUMMY_TYPE);
     722               break;
     723
     724          /* as_set, route_set */
     725          case UD_AX_MO:
     726               set_name = get_set_name(tr->class_type);
     727               sprintf(query, query_fmt, set_name, tr->thread_ins, dummy_id, set_name, attr->value);
     728               break;
     729
     730          default:
     731               fprintf(stderr, "E: query not defined for this type of attribute[%d]\n", attr->type);
     732               return(-1);
     733               break;
     734   }
     735
     736   /*fprintf(stderr, "D: query: %s\n", query);*/
     737   sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
     738  /* num = mysql_affected_rows(tr->sql_connection); */
     739   /*fprintf(stderr, "D: query: %d rows affected\n", num);*/
     740   if (sql_err) {
     741    fprintf(stderr, "E: dummy->main:%s[%s]\n", SQ_error(tr->sql_connection), query);
     742    return(-1);
     743   }
     744
     745   /* for legacy person/role reference (without nic-handle) create records in names table */
     746   if( (query_type == UD_AX_PR) && (!isnichandle (attr->value)) ){
     747    /* parse the names */
     748     /*fprintf(stderr,"adding names for dummy\n");*/
     749     query_fmt = DF_get_insert_query(A_PN);
     750     attr_value = g_strdup(attr->value);
     751     while((p_name=s_split(attr_value))){
     752                 sprintf(query, query_fmt, tr->thread_ins, dummy_id, DUMMY_TYPE, p_name);
     753 /*              fprintf(stderr, "D: query: %s\n", query);*/
     754                 sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
     755 /*              num = mysql_affected_rows(tr->sql_connection); */
     756                 if (sql_err)
     757                  if(SQ_errno(tr->sql_connection) != ER_DUP_ENTRY) {
     758                   fprintf(stderr, "E: insert dummy names:%s[%s]\n", SQ_error(tr->sql_connection), query);
     759                   result=-1;
     760                  }
     761 /*              if (num==0) {
     762                   fprintf(stderr, "E: insert dummy names:%s[%s]\n", "", query);
     763                   result=-1;
     764                 } */
     765     }
     766     free(attr_value);
     767   }
     768  return(result);
     769 }
     770
     771 /************************************************************
     772 * update_attr()                                             *
     773 *                                                           *
     774 * Function that updates an attribute if it already exists.  *
     775 * Called from each_attribute_proces() function if it        *
     776 * cannot insert the row.                                    *
     777 * Queries for the attributes are defined in Update[] array. *
     778 *                                                           *
     779 * Returns: Nothing. Error code is stored in tr->error.      *
     780 *                                                           *
     781 *************************************************************/
     782 static void update_attr(Attribute_t *attr, Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
     783 {
     784 /*SQ_result_set_t * sql_result;*/
     785 int num;
     786 const char *query_fmt;
     787 /*GString *query;*/
     788 char *set_name;
     789 unsigned int if_address;
     790 char * rf_host;
     791 int rf_port, rf_type;
     792 char *a_value;
     793 /*int dupl;*/
     794 int sq_info[3];
     795 char * condition;
     796 char *sq_error;
     797 char query[STR_XL];
     798 ip_prefix_t dn_pref;
     799 int sql_err;
     800
     801 /* It may be needed to update second attribute stored in the main table, like inetnum, filter-set, etc. */
     802  if((tr->load_pass!=0)&&(DF_get_update_query_type(attr->type)!=UD_MA_U2)) return;
     803
     804 /*      fprintf(stderr, "D: updating attribute...\n");*/
     805
     806    /* Do some additional processing for reverse domains */
     807    /* XXX Later we will implement this under UD_MA_DN case */
     808    if ((attr->type == A_DN) && (IP_revd_e2b(&dn_pref, attr->value)==IP_OK)) {
     809      if(update_reverse_domain(tr, &dn_pref) !=0 ){
     810        tr->error|=ERROR_U_DBS;
     811        tr->succeeded=0;
     812        g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,
     813                          ERROR_U_DBS, attr->type, attr->value, SQ_error(tr->sql_connection));
     814      }
     815    }
     816
     817 /*   query_fmt = Update[attr->type].qry; */
     818    query_fmt =  DF_get_update_query(attr->type);
     819
     820    if (strcmp(query_fmt, "") == 0) return;
     821
     822    switch (DF_get_update_query_type(attr->type)) {
     823          case UD_MAIN_: sprintf(query, query_fmt, tr->thread_upd, tr->object_id);
     824                         break;
     825          case UD_MA_PR:
     826                         sprintf(query, query_fmt, tr->thread_upd, tr->class_type, tr->object_id);
     827                         break;
     828          case UD_MA_U2: /* save the new value of the attribute for commit*/
     829                   /* this is necessary for filter(filter-set), netname (inet?num), */
     830                   /* local-as(inet-rtr) attributes, as they are another field in the record */
     831                         if((tr->load_pass != 0)){
     832                       /* for fast loader we need to update the field as we have no commit */
     833                           sprintf(query, query_fmt, DF_get_class_sql_table(tr->class_type), 0, attr->value, tr->object_id);
     834                         }
     835                         else {
     836                          tr->save=g_strdup(attr->value);
     837 /*                       fprintf(stderr, "D:<e_a_p> attribute saved: %s\n", tr->save);*/
     838                          return;
     839                         }
     840                         break;
     841          case UD_AX_PR:
     842                         /* This is for non-conformant admin-c, etc.*/
     843                         a_value=attr->value;
     844                         if(strlen(attr->value)>MAX_NIC_HDL)*(attr->value + MAX_NIC_HDL)='\0';
     845
     846                         if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
     847                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
     848                                 get_ref_id(tr, "person_role", "nic_hdl", attr->value, condition));
     849                         break;
     850          case UD_AX_MT:
     851                         if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
     852                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
     853                                 get_ref_id(tr, "mntner", "mntner", attr->value, condition));
     854                         break;
     855          case UD_AX_MO:
     856                         set_name = get_set_name(tr->class_type);
     857 /*                    fprintf(stderr, "D: retrieved set name: %s\n", set_name);*/
     858                         if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
     859                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
     860                                         get_ref_id(tr, set_name, set_name, attr->value, condition));
     861                         break;
     862          case UD_AX_MR:
     863                         if ((strcmp(attr->value, "ANY")==0) || (strcmp(attr->value, "any")==0) || (strcmp(attr->value, "Any")==0))
     864                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
     865                                 get_ref_id(tr, "mntner", "mntner", "ANY",NULL));
     866                         else {
     867                          if (tr->dummy!=1)condition="AND dummy=0 "; else condition=NULL;
     868                          sprintf(query, query_fmt, tr->thread_upd, tr->object_id,
     869                                 get_ref_id(tr, "mntner", "mntner", attr->value, condition));
     870                         }
     871                         break;
     872          case UD_LEAF_:
     873                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, attr->value);
     874                         break;
     875          case UD_LF_IF:
     876                 /* Convert ascii ip -> numeric one */
     877                         convert_if(attr->value, &if_address);
     878                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, if_address);
     879                         break;
     880          case UD_LF_RF:
     881                         rf_host=convert_rf(attr->value, &rf_type, &rf_port);
     882                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, rf_type, rf_host, rf_port);
     883                         if(rf_host)free(rf_host);
     884                         break;
     885          case UD_LF_AY:
     886                         sprintf(query, query_fmt, tr->thread_upd, tr->object_id, convert_time(attr->value));
     887                         break;
     888            default:
     889                 fprintf(stderr, "E:<e_a_u> query not defined for this type of attribute:[%d]\n", attr->type);
     890                         tr->error|=ERROR_U_BUG;
     891                         tr->succeeded=0;
     892                         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:no update qry\n" ,ERROR_U_BUG, attr->type, attr->value);
     893                         break;
     894         }
     895 /* fprintf(stderr, "D: update: [%s]", query); */
     896
     897    /* Execute the query */
     898     sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
     899     if(sql_err) { /* an error occured*/
     900      /* Error - copy the error condition and return */
     901         sq_error=SQ_error(tr->sql_connection);
     902         fprintf(stderr, "E:<each_attribute_create> %s:[%s]\n", sq_error, query);
     903         tr->error|=ERROR_U_DBS;
     904         tr->succeeded=0;
     905         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,ERROR_U_DBS, attr->type, attr->value, sq_error);
     906         return;
     907     }
     908     else {
     909      /* Query OK */
     910       num = mysql_affected_rows(tr->sql_connection);
     911       if(num == 0) { /* check for duplicates*/
     912         SQ_get_info(tr->sql_connection, sq_info); /* UPDATE ... SET*/
     913         if ((sq_info[SQL_DUPLICATES]==0) && (sq_info[SQL_MATCHES]==0)) {
     914         /* Condition with zero duplicates and matches may occur when the object is a dummy */
     915         /* and we are running in protected mode ( dummies are not allowed, tr->dummy==0). */
     916         /* In such case we will append "AND dummy=0" to the query, which won't */
     917         /* return a match if the object in question is a dummy */
     918           fprintf(stderr, "E: Dummy prevents update: [%s]\n", query);
     919           tr->error|=ERROR_U_OBJ;
     920           tr->succeeded=0;
     921           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy update\n" ,ERROR_U_OBJ, attr->type, attr->value);
     922         } /* else duplicate entry - silently drop it  */
     923       }
     924       /* For member_of attribute we need to check membership claim in protected mode */
     925       if ((attr->type == A_MO) && (tr->dummy!=1)){
     926 /*      fprintf(stderr, "D:<e_a_p>: need to auth membership\n");*/
     927           if(auth_member_of(attr, tr)!=0){
     928           tr->error|=ERROR_U_AUT;
     929           tr->succeeded=0;
     930           fprintf(stderr, "E:<each_attribute_create>: membership not allowed\n");
     931           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:membership not allowed\n" ,ERROR_U_AUT, attr->type, attr->value);
     932         }
     933       }
     934     }
     935 return;
     936 }/*  update_attr()  */
     937
     938
     939 /************************************************************
     940 * each_attribute_proces()                                   *
     941 *                                                           *
     942 * Main function that processes object attributes one by one.*
     943 * Called from g_slist_foreach() function.                   *
     944 * First it tries to insert an attribute.                    *
     945 * If an error it assumes that attribute is already in       *
     946 * a table and calls update_attr() to update it.             *
     947 * Queries for the attributes are defined in Insert[] array. *
     948 *                                                           *
     949 * Returns: Nothing. Error code is stored in tr->error.      *
     950 *                                                           *
     951 *************************************************************/
     952 static void each_attribute_process(void *element_data, void *tr_ptr)
         /* [<][>][^][v][top][bottom][index][help] */
     953 {
     954 /*SQ_result_set_t * sql_result;*/
     955 int num;
     956 const char *query_fmt;
     957 int query_type;
     958 int do_query;
     959 Attribute_t *attr = element_data;
     960 Transaction_t *tr = (Transaction_t *)tr_ptr;
     961 unsigned int prefix, prefix_length, if_address;
     962 unsigned int begin_in, end_in;
     963 ip_v6word_t  high, low;
     964
     965 int begin_as, end_as;
     966 char query[STR_XL];
     967 char * set_name;
     968 char * rf_host; /* needs to be deleted after use*/
     969 int rf_type, rf_port;
     970 char *a_value;
     971 int sq_info[3];
     972 char *mu_mntner, *mu_prefix;
     973 int dummy_err;
     974 char *sq_error;
     975 ip_prefix_t dn_pref;
     976 int sql_err;
     977 int res;
     978
     979 /* In this structure we keep data for the radix tree */
     980 static rp_upd_pack_t data_pack;
     981
     982 /* we still want to continue to collect all possible errors*/
     983 /*  if(tr->succeeded == 0) return; // no sense to continue*/
     984
     985  /* To switch off querying for some types of attributes */
     986   do_query=1;
     987
     988  /* Determine the query type */
     989 /*  query_type=Insert[attr->type].qtype; */
     990   query_type=DF_get_insert_query_type(attr->type);
     991
     992 /* For loadind pass #1 we need to process only main tables */
     993   if(tr->load_pass==1){
     994         switch(query_type) {
     995          case UD_MAIN_:
     996          case UD_MA_U2:
     997          case UD_MA_PR:
     998          case UD_MA_RT:
     999          case UD_MA_IN:
    1000          case UD_MA_I6:
    1001          case UD_MA_OR:
    1002          case UD_MA_AK:
    1003                         break;
    1004          default:       return; /* return for other than MAIN tables*/
    1005         }
    1006   }
    1007
    1008     query_fmt = DF_get_insert_query(attr->type);
    1009
    1010 /* return if no query is defined for this attribute */
    1011   if (strcmp(query_fmt, "") == 0) return;
    1012
    1013  /* compose the query depending on the attribute */
    1014   switch (query_type) {
    1015    case UD_MAIN_: /* for MAIN tables */
    1016                 if (ACT_UPDATE(tr->action)) do_query=0;
    1017                 else
    1018                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, attr->value);
    1019                 break;
    1020    case UD_MA_OR: /* for the origin attribute */
    1021                 if (ACT_UPDATE(tr->action)) do_query=0;
    1022                 else {
    1023                   sprintf(query, query_fmt, tr->thread_ins, attr->value, tr->object_id);
    1024                  /* if(attr->type == A_OR) { */
    1025                   RP_pack_set_orig(attr->type, &data_pack, attr->value);
    1026                   tr->packptr = &data_pack; /* just in case*/
    1027                  /* }   */
    1028                 }
    1029                 break;
    1030    case UD_MA_PR: /* for person_role table*/
    1031                 if (ACT_UPDATE(tr->action)) do_query=0;
    1032                 else
    1033                  sprintf(query, query_fmt, tr->thread_ins, tr->class_type, tr->object_id,  attr->value);
    1034
    1035                 /* check if we need to update NHR */
    1036                 if (ACT_UPD_NHR(tr->action)) {
    1037                  /* Check if we can allocate it */
    1038                   res = NH_check(tr->nh, tr->sql_connection);
    1039                   if(res == -1) { /* we cannot allocate this NIC handle (DB error) */
    1040                      tr->succeeded=0;
    1041                      tr->error |= ERROR_U_DBS;
    1042                      g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:cannot allocate nic-handle\n", ERROR_U_DBS, attr->type, attr->value);
    1043                      return;
    1044                   }
    1045                   else
    1046                   if(res == 0) { /* we cannot allocate this NIC handle (full space or ID in use) */
    1047                     tr->succeeded=0;
    1048                     tr->error |= ERROR_U_OBJ;
    1049                     g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:nic-handle already in use\n", ERROR_U_OBJ, attr->type, attr->value);
    1050                     return;
    1051                   }
    1052                 }
    1053                 break;
    1054    case UD_MA_RT: /* for route table*/
    1055                 if (ACT_UPDATE(tr->action)) do_query=0;
    1056                 else {
    1057
    1058                   RP_pack_set_pref4(attr->type, attr->value, &data_pack, &prefix, &prefix_length);
    1059                   /*fprintf(stderr, "D: route: %u/%u\n", prefix, prefix_length);                */
    1060                   sprintf(query, query_fmt, tr->thread_ins,
    1061                           tr->object_id, prefix, prefix_length);
    1062                   /* save stuff for radix update*/
    1063                   tr->packptr = &data_pack;
    1064                 }
    1065                 break;
    1066    case UD_MA_IN: /* for inetnum table*/
    1067                 if (ACT_UPDATE(tr->action)) do_query=0;
    1068                 else {
    1069                   RP_pack_set_rang(attr->type, attr->value, &data_pack, &begin_in, &end_in);
    1070                   /* XXX error handling ? */
    1071                   sprintf(query, query_fmt, tr->thread_ins, tr->object_id, begin_in, end_in);
    1072                   tr->packptr = &data_pack;
    1073                 }
    1074                 break;
    1075    case UD_MA_I6: /* for inet6num table*/
    1076                 if (ACT_UPDATE(tr->action)) do_query=0;
    1077                 else {
    1078                   RP_pack_set_pref6(attr->type, attr->value, &data_pack, &high, &low, &prefix_length);
    1079                   /* XXX error handling ? */
    1080                   sprintf(query, query_fmt, tr->thread_ins, tr->object_id, high, low, prefix_length);
    1081                   tr->packptr = &data_pack;
    1082                 }
    1083                 break;
    1084    case UD_MA_U2: /* This is actually an update - go to update_attr - this is more natural */
    1085                  do_query=0;
    1086                 break;
    1087    case UD_MA_AK: /* for as_block table*/
    1088                 if (ACT_UPDATE(tr->action)) do_query=0;
    1089                 else {
    1090                   convert_as_range(attr->value, &begin_as, &end_as);
    1091                   sprintf(query, query_fmt, tr->thread_ins, tr->object_id, begin_as, end_as);
    1092                 }
    1093                 break;
    1094    case UD_AUX__: /* for AUX tables*/
    1095                 if((attr->type==A_AC) || (attr->type==A_TC) || (attr->type==A_ZC))
    1096                  if(strlen(attr->value)>MAX_NIC_HDL)*(attr->value + MAX_NIC_HDL)='\0';
    1097
    1098                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
    1099                 if(tr->dummy!=1)strcat(query, " AND dummy=0 ");
    1100                 break;
    1101    case UD_AX_MO: /* for member_of table*/
    1102                 set_name = get_set_name(tr->class_type);
    1103 /*              fprintf(stderr, "D: retrieved set name: %s\n", set_name);*/
    1104                 sprintf(query, query_fmt, tr->thread_ins,
    1105                  tr->object_id, set_name, tr->class_type, set_name, set_name, set_name, attr->value);
    1106                 break;
    1107    case UD_AX_MR: /* for mbrs_by_ref table*/
    1108                 if ((strcmp(attr->value, "ANY")==0) || (strcmp(attr->value, "any")==0) || (strcmp(attr->value, "Any")==0))
    1109                  sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, "ANY");
    1110                 else
    1111                  sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
    1112                 break;
    1113    case UD_AX_MU: /* for mnt_routes table*/
    1114                 a_value=g_strdup(attr->value);
    1115                 mu_mntner=s_splitn(a_value, 1);
    1116                 mu_prefix=s_splitn(a_value, 1);
    1117                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, mu_prefix, tr->class_type, mu_mntner);
    1118                 free(a_value);
    1119                 if(tr->dummy!=1)strcat(query, " AND dummy=0 ");
    1120                 break;
    1121    case UD_LEAF_: /* for LEAF tables*/
    1122                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, attr->value);
    1123                 break;
    1124    case UD_LF_OT: /* for LEAF tables containing object_type field*/
    1125                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
    1126                 break;
    1127    case UD_LF_AT: /* check PGPKEY. If yes - check the existence of key-cert.*/
    1128                 if(tr->dummy!=1){
    1129                  if(strncmp("PGPKEY", attr->value, 6)==0) {
    1130                    if(get_ref_id(tr, "key_cert", "key_cert", attr->value, NULL)<=0) {
    1131                     fprintf(stderr, "E:<e_a_p>: No key-cert object.\n");
    1132                     tr->error|=ERROR_U_OBJ;
    1133                     tr->succeeded=0;
    1134                     g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:no key-cert object\n" ,ERROR_U_OBJ, attr->type, attr->value);
    1135                     return;
    1136                    }
    1137                  }
    1138                 }
    1139                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, tr->class_type, attr->value);
    1140                 break;
    1141    case UD_LF_IF: /* for ifaddr tables*/
    1142                 /* Convert ascii ip -> numeric one*/
    1143                 convert_if(attr->value, &if_address);
    1144                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, if_address);
    1145                 break;
    1146    case UD_LF_RF: /* for refer table*/
    1147                 rf_host=convert_rf(attr->value, &rf_type, &rf_port);
    1148                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, rf_type, rf_host, rf_port);
    1149                 if(rf_host)free(rf_host);
    1150                 break;
    1151    case UD_LF_AY: /* for auth_override table*/
    1152                 sprintf(query, query_fmt, tr->thread_ins, tr->object_id, convert_time(attr->value));
    1153                 break;
    1154         default:
    1155                 fprintf(stderr, "E: query not defined for this type of attribute\n");
    1156                 tr->succeeded=0;
    1157                 tr->error |= ERROR_U_BUG;
    1158                 g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:query not defined for the attribute\n" ,ERROR_U_BUG, attr->type, attr->value);
    1159                 return;
    1160                 break;
    1161   }
    1162
    1163 /* fprintf(stderr, "D: insert: [%s]", query); */
    1164
    1165
    1166  /* Make the query. For primary keys go straight to updates if we are updating the object */
    1167   if(do_query){
    1168    sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
    1169   }
    1170   else {
    1171    update_attr(attr, tr);
    1172    return;
    1173   }
    1174
    1175 /*  fprintf(stderr, "D: query: %d rows affected\n", num);*/
    1176   if (sql_err)  {
    1177   /* we received an error */
    1178    if(SQ_errno(tr->sql_connection) == ER_DUP_ENTRY){ /* Only error "Duplicate entry" may be considered*/
    1179         if (ACT_UPDATE(tr->action)) { /* In update mode this is common (so actually not an error)*/
    1180                 update_attr(attr, tr);
    1181                 return;
    1182         }
    1183      /* Otherwise this is a duplicate attribute, just ignore it */
    1184      /* In the future if we are more stringent, checks may be added here */
    1185    }
    1186    else { /* Other errors reveal a database/server problem*/
    1187         sq_error=SQ_error(tr->sql_connection);
    1188         tr->error|=ERROR_U_DBS;
    1189         tr->succeeded=0;
    1190         fprintf(stderr, "E:<each_attribute_create>: %s: [%s]\n", sq_error, query);
    1191         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,ERROR_U_DBS, attr->type, attr->value, sq_error);
    1192    }
    1193   } /* if error occured */
    1194   else {
    1195  /* If the query was successful */
    1196    num = mysql_affected_rows(tr->sql_connection);
    1197    if(num>0){ /* this is OK*/
    1198  /* Do some additional processing for member_of attribute  */
    1199         if ((attr->type == A_MO) && (tr->dummy!=1)){
    1200 /*              fprintf(stderr, "D:<e_a_p>: need to auth membership\n");*/
    1201                 if(auth_member_of(attr, tr)!=0){
    1202                  tr->error|=ERROR_U_AUT;
    1203                  tr->succeeded=0;
    1204                  fprintf(stderr, "E:<each_attribute_create>: membership not allowed\n");
    1205                  g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:membership not allowed\n" ,ERROR_U_AUT, attr->type, attr->value);
    1206                 }
    1207         }
    1208         else
    1209           /* Do some additional processing for reverse zones domains */
    1210           if ((attr->type == A_DN)
    1211               && IP_revd_e2b(&dn_pref, attr->value)==IP_OK ) {
    1212
    1213             if(insert_reverse_domain(tr, &dn_pref) != 0 ) {
    1214                 tr->error|=ERROR_U_DBS;
    1215                 tr->succeeded=0;
    1216                 g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,
    1217                                   ERROR_U_DBS, attr->type, attr->value,
    1218                                   SQ_error(tr->sql_connection));
    1219             }
    1220             else {
    1221               /* save data for the radix tree update */
    1222               RP_pack_set_revd(attr->type, attr->value, &data_pack);
    1223               tr->packptr = &data_pack;
    1224             }
    1225           }
    1226         return;
    1227    }
    1228    if(num == 0) {
    1229 /* this could be an empty update or a null select */
    1230         SQ_get_info(tr->sql_connection, sq_info);
    1231         if (sq_info[SQL_DUPLICATES]>0) {
    1232                 if (sq_info[SQL_DUPLICATES]>1) {
    1233                         fprintf(stderr, "E: Update: Too many duplicates for query: [%s]\n", query);
    1234                         tr->error|=ERROR_U_DBS;
    1235                         tr->succeeded=0;
    1236                         g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:duplicates\n" ,ERROR_U_DBS, attr->type, attr->value);
    1237                         return;
    1238                 }
    1239                 update_attr(attr, tr);
    1240         }
    1241         else {
    1242
    1243                 /* try to create dummy and repeat original query*/
    1244
    1245 /*              fprintf(stderr, "W: no ref. integrity. Trying to create dummy...");*/
    1246
    1247                 dummy_err = create_dummy(attr, tr);
    1248                 if (dummy_err == 0) {
    1249 /*                      fprintf(stderr, "D: ... dummy OK\n");*/
    1250                         g_string_sprintfa(tr->error_script,"W[%d][%d:%s]:dummy created\n" ,0, attr->type, attr->value);
    1251 /*                      fprintf(stderr, "D: repeating query: %s\n", query);*/
    1252                         sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
    1253                         num = mysql_affected_rows(tr->sql_connection);
    1254                         if (sql_err) {
    1255                           sq_error=SQ_error(tr->sql_connection);
    1256                           fprintf(stderr, "E: re-insert query:%s[%s]\n", sq_error, query);
    1257                           tr->error|=ERROR_U_DBS;
    1258                           tr->succeeded=0;
    1259                           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:%s\n" ,
    1260                                             ERROR_U_DBS, attr->type, attr->value, sq_error);
    1261                         }
    1262                         if (num==0) {
    1263                           fprintf(stderr, "E: re-insert query:%s[%s]\n", "", query);
    1264                           tr->error|=ERROR_U_DBS;
    1265                           tr->succeeded=0;
    1266                           fprintf(stderr, "E: re-insert query: [%s]\n", query);
    1267                           g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:re-insert qry\n" ,
    1268                                             ERROR_U_DBS, attr->type, attr->value);
    1269                         }
    1270                 }
    1271                 else
    1272                  if(dummy_err == 1) {
    1273                    tr->error |= ERROR_U_OBJ;
    1274                    tr->succeeded=0;
    1275                    g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy not allowed\n" ,ERROR_U_OBJ, attr->type, attr->value);
    1276                  }
    1277                  else {
    1278                    tr->error|=ERROR_U_DBS;
    1279                    tr->succeeded=0;
    1280                    fprintf(stderr, "E:<each_attribute_create>: dummy not created\n");
    1281                    g_string_sprintfa(tr->error_script,"E[%d][%d:%s]:dummy not created\n" ,ERROR_U_DBS, attr->type, attr->value);
    1282                 }
    1283         }  /* RI*/
    1284    }/* if num == 0*/
    1285   } /* if the query was successful */
    1286
    1287   return;
    1288 } /* each_attribute_process() */
    1289
    1290
    1291
    1292 /************************************************************
    1293 * each_primary_key_select()                                 *
    1294 *                                                           *
    1295 * Function that forms a query for an object (w prinary keys)*
    1296 * Called from g_slist_foreach() function.                   *
    1297 * Primary keys are defined in Select[] array.               *
    1298 *                                                           *
    1299 * Returns: Nothing.                                         *
    1300 *                                                           *
    1301 *************************************************************/
    1302 static void each_primary_key_select(void *element_data, void *result_ptr)
         /* [<][>][^][v][top][bottom][index][help] */
    1303 {
    1304 Attribute_t *attr = element_data;
    1305 GString *result = (GString *)result_ptr;
    1306 const char *query_fmt;
    1307 unsigned int prefix, prefix_length;
    1308 unsigned int begin_in, end_in;
    1309 int begin_as, end_as;
    1310 ip_prefix_t prefstr;
    1311 ip_range_t  rangstr;
    1312 ip_v6word_t i6_msb, i6_lsb;
    1313
    1314 /*  query_fmt = Select[attr->type].qry; */
    1315    query_fmt = DF_get_select_query(attr->type);
    1316
    1317 /* fprintf(stderr, "D: qry fmt: %s\n", query_fmt);*/
    1318
    1319   if (strcmp(query_fmt, "") != 0) {
    1320     switch (DF_get_select_query_type(attr->type)) {
    1321      case UD_MAIN_:
    1322                 g_string_sprintfa(result, query_fmt, attr->value);
    1323                 break;
    1324      case UD_MA_RT:
    1325                 IP_pref_a2v4(attr->value, &prefstr, &prefix, &prefix_length);
    1326                 g_string_sprintfa(result, query_fmt, prefix, prefix_length);
    1327                 break;
    1328      case UD_MA_IN:
    1329                 IP_rang_a2v4(attr->value, &rangstr, &begin_in, &end_in);
    1330                 g_string_sprintfa(result, query_fmt, begin_in, end_in);
    1331                 break;
    1332      case UD_MA_I6:
    1333                 IP_pref_a2v6(attr->value, &prefstr, &i6_msb, &i6_lsb, &prefix_length);
    1334                 g_string_sprintfa(result, query_fmt, i6_msb, i6_lsb, prefix_length);
    1335                 break;
    1336      case UD_MA_AK:
    1337                 convert_as_range(attr->value, &begin_as, &end_as);
    1338                 g_string_sprintfa(result, query_fmt, begin_as, end_as);
    1339                 break;
    1340      default:
    1341 fprintf(stderr, "E:<e_p_k_s>: query not defined for this type of attribute:[%d]\n", attr->type);
    1342                 die;
    1343
    1344         break;
    1345     }
    1346 /* fprintf(stderr, "D: each_primary_key_select(): %s\n",result->str); */
    1347   }
    1348 }
    1349
    1350 /************************************************************
    1351 * perform_create(const Object_t *obj, Transaction_t *tr)    *
    1352 *                                                           *
    1353 * Procedure for creating a new object.                      *
    1354 * First inserts object into 'last' table and gets object_id.*
    1355 * Then processes all attributes.                            *
    1356 *                                                           *
    1357 * Returns: tr->succeeded: >0 success, 0 - error             *
    1358 * Error code is stored in tr->error.                        *
    1359 *                                                           *
    1360 *************************************************************/
    1361 static int perform_create(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
    1362 {
    1363  Object_t *obj=tr->object;
    1364 /* SQ_result_set_t *sql_result;*/
    1365  char *str;
    1366  static char query[STR_XXXL];
    1367  long timestamp;
    1368  int sql_err;
    1369
    1370       str = (obj->object)->str;
    1371       timestamp=time(NULL);
    1372       tr->sequence_id=1; /* we start with 1*/
    1373       sprintf(query, "INSERT INTO last SET thread_id=0, timestamp=%ld, sequence_id=1, object_type=%d, object='%s' ",
    1374                       timestamp, tr->class_type, str);
    1375
    1376       sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
    1377
    1378      /* Check for affected rows. One row should be affected . */
    1379 /*      num = mysql_affected_rows(tr->sql_connection); */
    1380       if (sql_err) {
    1381         tr->error|=ERROR_U_DBS;
    1382         tr->succeeded=0;
    1383         fprintf(stderr, "E ERROR!<perform_create>: INSERT last failed:%s\n", SQ_error(tr->sql_connection));
    1384         g_string_sprintfa(tr->error_script,"E[%d][:]:%s\n" ,ERROR_U_DBS, SQ_error(tr->sql_connection));
    1385       }
    1386       else {
    1387       /* Get generated (autoincrement) object_id */
    1388         tr->object_id=mysql_insert_id(tr->sql_connection);
    1389         g_slist_foreach(obj->attributes, each_attribute_process, tr);
    1390       }
    1391     return(tr->succeeded);
    1392 } /* perform_create() */
    1393
    1394 /************************************************************
    1395 * perform_update(Transaction_t *tr)                         *
    1396 *                                                           *
    1397 * Procedure for updating (existing) object.                 *
    1398 * First processes all attributes.                           *
    1399 * Then saves previous object in 'history' and updates       *
    1400 * 'last' table.                                             *
    1401 *                                                           *
    1402 * Returns: tr->succeeded: >0 success, 0 - error             *
    1403 * Error code is stored in tr->error.                        *
    1404 *                                                           *
    1405 *************************************************************/
    1406 static int perform_update(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
    1407 {
    1408 Object_t *obj=tr->object;
    1409 /*SQ_result_set_t * sql_result;*/
    1410 char *str;
    1411 static char query[STR_XXXL];
    1412 int num;
    1413 long sequence_id;
    1414 long timestamp;
    1415 char *sq_error;
    1416 int sql_err;
    1417
    1418   /* process each attribute one by one */
    1419   g_slist_foreach(obj->attributes, each_attribute_process, tr);
    1420
    1421   /* If we've already failed or this is fast load - just return */
    1422   if((tr->succeeded == 0) || (tr->load_pass != 0)) return(tr->succeeded);
    1423
    1424     /* No return: thread_id=0 */
    1425     /* Do it only if previous transactions finished well */
    1426
    1427     /* copy object to the history table */
    1428 /*fprintf(stderr, "INSERT history\n");    */
    1429     sprintf(query,"INSERT history "
    1430                   "SELECT 0, object_id, sequence_id, timestamp, object_type, object "
    1431                   "FROM last "
    1432                   "WHERE object_id=%ld ", tr->object_id);
    1433
    1434     sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
    1435
    1436    /* Check for affected rows. One row should be affected . */
    1437     num = mysql_affected_rows(tr->sql_connection);
    1438     if (num < 1) {
    1439          tr->error|=ERROR_U_DBS;
    1440          tr->succeeded=0;
    1441          if (sql_err) {
    1442           sq_error=SQ_error(tr->sql_connection);
    1443           fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]%s\n", num, query, sq_error);
    1444           g_string_sprintfa(tr->error_script,"E[%d][:]:INSERT history failed:%s\n" ,ERROR_U_DBS, sq_error);
    1445          }
    1446          else {
    1447           fprintf(stderr, "E ERROR!<perform_update>: INSERT history failed:[%d][%s]\n", num, query);
    1448           g_string_sprintfa(tr->error_script,"E[%d][:]:INSERT history failed\n" ,ERROR_U_DBS);
    1449         /* This is to check that this is really could happen */
    1450           die;
    1451          }
    1452          return(tr->succeeded);
    1453     }
    1454
    1455     /* get sequence number */
    1456
    1457     sequence_id = get_sequence_id(tr);
    1458     if(sequence_id==-1) {
    1459       fprintf(stderr, "E ERROR!<perform_update> cannot get sequence_id\n");
    1460       tr->error|=ERROR_U_DBS;
    1461       tr->succeeded=0;
    1462       g_string_sprintfa(tr->error_script,"E[%d][:]:cannot get seq ID\n" ,ERROR_U_DBS);
    1463       return(tr->succeeded);
    1464     }
    1465     else tr->sequence_id=sequence_id; /* save it for rollback*/
    1466
    1467
    1468     /* Insert new version into the last */
    1469
    1470     /* Put a timestamp */
    1471     str = (obj->object)->str;
    1472     timestamp=time(NULL);
    1473     tr->sequence_id++;
    1474
    1475 /*fprintf(stderr, "UPDATE last\n");       */
    1476     /* If we are here - it's almost commit. Otherwise this row will not be updated at all. */
    1477     sprintf(query, "UPDATE last "
    1478                    "SET thread_id=0, sequence_id=%ld, timestamp=%ld, object_type=%d, object='%s' "
    1479                    "WHERE object_id=%ld ",
    1480                    tr->sequence_id, timestamp, tr->class_type, str, tr->object_id);
    1481
    1482     sql_err = SQ_execute_query(tr->sql_connection, query, (SQ_result_set_t **)NULL);
    1483
    1484     /* Check for affected rows. One row should be affected */
    1485     num = mysql_affected_rows(tr->sql_connection);
    1486     if (num < 1) {
    1487          tr->error|=ERROR_U_DBS;
    1488          tr->succeeded=0;
    1489          if(sql_err) {
    1490           fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]%s\n", num, query, SQ_error(tr->sql_connection));
    1491           g_string_sprintfa(tr->error_script,"E[%d][:]:UPDATE last failed:%s\n" ,ERROR_U_DBS,SQ_error(tr->sql_connection));
    1492          }
    1493          else {
    1494           fprintf(stderr, "E ERROR!<perform_update>: UPDATE last failed: [%d][%s]\n", num, query);
    1495           g_string_sprintfa(tr->error_script,"E[%d][:]:UPDATE last failed\n" ,ERROR_U_DBS);
    1496           /* This is to check that this is really could happen */
    1497           die;
    1498          }
    1499          return(tr->succeeded);
    1500     }
    1501  return(tr->succeeded);
    1502 } /* perform_update() */
    1503
    1504
    1505
    1506
    1507 /************************************************************
    1508 * int object_process(Transaction_t *tr)                     *
    1509 *                                                           *
    1510 * This is the interface between core and upper layer        *
    1511 * All it gets is Transaction *tr, which contains all        *
    1512 * necessary information, including the object in its        *
    1513 * internal representation.                                  *
    1514 *                                                           *
    1515 * Returns: tr->succeeded: >0 success, 0 - error             *
    1516 * Error code is stored in tr->error.                        *
    1517 *                                                           *
    1518 *************************************************************/
    1519 int object_process(Transaction_t *tr)
         /* [<][>][^][v][top][bottom][index][help] */
    1520 {
    1521 int res;
    1522 char nic[MAX_NH_LENGTH];
    1523
    1524    if(ACT_DELETE(tr->action)){
    1525                 fprintf(stderr, "D: Action: Delete...");
    1526                 delete(tr);
    1527                 /* Commit nic-handle deletion to the repository */
    1528                 if(tr->succeeded && ((tr->class_type==C_PN) || (tr->class_type==C_RO)) && tr->nh ){
    1529                  res = NH_free(tr->nh, tr->sql_connection);
    1530                  if(res == -1) {
    1531                   tr->succeeded=0;
    1532                   tr->error |= ERROR_U_DBS;
    1533                   g_string_sprintfa(tr->error_script,"E[%d][]:cannot delete nic-handle\n", ERROR_U_DBS);
    1534                   return(tr->succeeded);
    1535                  }
    1536                  else if(res == 0) {
    1537                   tr->succeeded=0;
    1538                   tr->error |= ERROR_U_OBJ;
    1539                   g_string_sprintfa(tr->error_script,"E[%d][]:nic-handle not found\n", ERROR_U_OBJ);
    1540                   return(tr->succeeded);
    1541                  }
    1542                 }
    1543                 return(tr->succeeded); /*commit is not needed*/
    1544     }
    1545     else if(ACT_UPDATE(tr->action)){
    1546                 fprintf(stderr, "D: Action: Update...");
    1547                 perform_update(tr);
    1548                 /* Commit nic-handle allocation (if any) to the repository if we are replacing dummy*/
    1549                 if(ACT_UPD_NHR(tr->action) && tr->succeeded && ((tr->class_type==C_PN) || (tr->class_type==C_RO)) && tr->nh ){
    1550                  /* convert nh to DB nIC handle before registration */
    1551                  /* because there nh will bee freed */
    1552                  NH_convert(nic, tr->nh);
    1553                  res = NH_register(tr->nh, tr->sql_connection);
    1554                  if(res == -1) {
    1555                   tr->succeeded=0;
    1556                   tr->error |= ERROR_U_DBS;
    1557                   g_string_sprintfa(tr->error_script,"E[%d][]:cannot allocate nic-handle\n", ERROR_U_DBS);
    1558                  }
    1559                  else if(res == 0) {
    1560                   tr->succeeded=0;
    1561                   tr->error |= ERROR_U_OBJ;
    1562                   g_string_sprintfa(tr->error_script,"E[%d][]:nic-handle already in use\n", ERROR_U_OBJ);
    1563                  }
    1564                  else { /* copy the NH to the report to return to DBupdate */
    1565                  /* Convert nh to the database format */
    1566                   g_string_sprintfa(tr->error_script,"I[%d][%s]\n", A_NH, nic);
    1567                  }
    1568                 }
    1569     }
    1570     else if(ACT_CREATE(tr->action)){
    1571                 fprintf(stderr, "D: Action: Create...");
    1572                 perform_create(tr);
    1573                 /* Commit nic-handle allocation (if any) to the repository */
    1574                 if(tr->succeeded && ((tr->class_type==C_PN) || (tr->class_type==C_RO)) && tr->nh ){
    1575                  /* convert nh to DB nIC handle before registration */
    1576                  /* because there nh will bee freed */
    1577                  NH_convert(nic, tr->nh);
    1578                  res = NH_register(tr->nh, tr->sql_connection);
    1579                  if(res == -1) {
    1580                   tr->succeeded=0;
    1581                   tr->error |= ERROR_U_DBS;
    1582                   g_string_sprintfa(tr->error_script,"E[%d][]:cannot allocate nic-handle\n", ERROR_U_DBS);
    1583                  }
    1584                  else if(res == 0) {
    1585                   tr->succeeded=0;
    1586                   tr->error |= ERROR_U_OBJ;
    1587                   g_string_sprintfa(tr->error_script,"E[%d][]:nic-handle already in use\n", ERROR_U_OBJ);
    1588                  }
    1589                  else { /* copy the NH to the report to return to DBupdate */
    1590                   g_string_sprintfa(tr->error_script,"I[%d][%s]\n", A_NH, nic);
    1591                  }
    1592                 }
    1593
    1594      }
    1595      else {
    1596                 fprintf(stderr, "D: Action: Unknown...");
    1597                 tr->succeeded=0;
    1598                 tr->error|=ERROR_U_BADOP;
    1599                 return(tr->succeeded);
    1600      }
    1601
    1602    if(tr->load_pass == 0) { /* not for fast loader*/
    1603       if (tr->succeeded == 1) {
    1604 /*fprintf(stderr, "D: Commit transaction...\n");      */
    1605         commit(tr);
    1606       }
    1607       else {
    1608 /*fprintf(stderr, "D: Roll back transaction...\n");      */
    1609         rollback(tr);
    1610       }
    1611     }
    1612  return(tr->succeeded);
    1613 } /* object_process() */
    1614

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