Source File modules/ud/ud_core.c

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