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