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