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] */