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