1 | /*************************************** 2 | $Revision: 1.15 $ 3 | 4 | 5 | Sql module (sq). This is a mysql implementation of an sql module. 6 | 7 | Status: NOT REVUED, NOT TESTED 8 | 9 | Note: this code has been heavily coupled to MySQL, and may need to be changed 10 | (to improve performance) if a new RDBMS is used. 11 | 12 | ******************/ /****************** 13 | Filename : query_instructions.c 14 | Author : ottrey@ripe.net 15 | OSs Tested : Solaris 16 | Problems : Moderately linked to MySQL. Not sure which inverse 17 | attributes each option has. Would like to modify this 18 | after re-designing the objects module. 19 | Comments : Not sure about the different keytypes. 20 | ******************/ /****************** 21 | Copyright (c) 1999 RIPE NCC 22 | 23 | All Rights Reserved 24 | 25 | Permission to use, copy, modify, and distribute this software and its 26 | documentation for any purpose and without fee is hereby granted, 27 | provided that the above copyright notice appear in all copies and that 28 | both that copyright notice and this permission notice appear in 29 | supporting documentation, and that the name of the author not be 30 | used in advertising or publicity pertaining to distribution of the 31 | software without specific, written prior permission. 32 | 33 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 34 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 35 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 36 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 37 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 38 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 39 | ***************************************/ 40 | #include <stdio.h> 41 | #include "which_keytypes.h" 42 | #include "query_instructions.h" 43 | #include "mysql_driver.h" 44 | #include "attributes.h" 45 | #include "rxroutines.h" 46 | #include "stubs.h" 47 | #include "constants.h" 48 | 49 | /*+ String sizes +*/ 50 | #define STR_S 63 51 | #define STR_M 255 52 | #define STR_L 1023 53 | #define STR_XL 4095 54 | #define STR_XXL 16383 55 | 56 | 57 | /*+ Definition of SQL query to be made +*/ 58 | struct _Instruction { 59 | WK_Type keytype; 60 | const char *sql_primary_query; 61 | const char *sql_inverse_query; 62 | }; 63 | 64 | /*+ SQL query to be made for each keytype: +*/ 65 | static struct _Instruction Instructions[] = { 66 | { WK_NAME, Q_PRI_NAME, Q_INV_NAME }, /* A name */ 67 | { WK_NICHDL, Q_PRI_NICHDL, Q_INV_NICHDL }, /* NICHDL */ 68 | { WK_EMAIL, Q_PRI_EMAIL, Q_INV_EMAIL }, /* RFC822 e-mail address */ 69 | { WK_MAINT, Q_PRI_MAINT, Q_INV_MAINT }, /* Maintainer name */ 70 | { WK_KEYCERT, Q_PRI_KEYCERT, Q_INV_KEYCERT }, /* PGPKEY (see i-d for syntax) */ 71 | { WK_IPRANGE, Q_PRI_IPRANGE, Q_INV_IPRANGE }, /* IP range (*) needs modification */ 72 | { WK_IP6RANGE, Q_PRI_IP6RANGE, Q_INV_IP6RANGE }, /* IPv6 range (*) needs modification */ 73 | { WK_NETNAME, Q_PRI_NETNAME, Q_INV_NETNAME }, /* Network name */ 74 | { WK_ASNUM, Q_PRI_ASNUM, Q_INV_ASNUM }, /* AS number */ 75 | { WK_ASSETNAME, Q_PRI_ASSETNAME, Q_INV_ASSETNAME }, /* AS set name */ 76 | { WK_ROUTESETNAME, Q_PRI_ROUTESETNAME, Q_INV_ROUTESETNAME }, /* Route set name */ 77 | { WK_DOMNAME, Q_PRI_DOMNAME, Q_INV_DOMNAME }, /* Domain name */ 78 | { WK_HOSTNAME, Q_PRI_HOSTNAME, Q_INV_HOSTNAME }, /* Host name */ 79 | { WK_LIMERICKNAME, Q_PRI_LIMERICKNAME, Q_INV_LIMERICKNAME }, /* Limerick name */ 80 | NULL 81 | }; 82 | 83 | 84 | /* log_inst_print() */ 85 | /*++++++++++++++++++++++++++++++++++++++ 86 | Log the instruction. 87 | 88 | char *str instruction to be logged. 89 | 90 | More: 91 | +html+ <PRE> 92 | Authors: 93 | ottrey 94 | +html+ </PRE><DL COMPACT> 95 | +html+ <DT>Online References: 96 | +html+ <DD><UL> 97 | +html+ </UL></DL> 98 | 99 | ++++++++++++++++++++++++++++++++++++++*/ 100 | static void log_inst_print(char *str) { 101 | FILE *logf; 102 | 103 | if (CO_get_instr_logging() == 1) { 104 | if (strcmp(CO_get_instr_logfile(), "stdout") == 0) { 105 | printf("%s", str); 106 | } 107 | else { 108 | logf = fopen(CO_get_instr_logfile(), "a"); 109 | fprintf(logf, "%s", str); 110 | fclose(logf); 111 | } 112 | } 113 | 114 | } /* log_inst_print() */ 115 | 116 | /* create_name_query() */ 117 | /*++++++++++++++++++++++++++++++++++++++ 118 | Create an sql query for the names table. 119 | 120 | char *query_str 121 | 122 | const char *sql_query 123 | 124 | const char *keys 125 | 126 | More: 127 | +html+ <PRE> 128 | Authors: 129 | ottrey 130 | +html+ </PRE><DL COMPACT> 131 | +html+ <DT>Online References: 132 | +html+ <DD><UL> 133 | +html+ </UL></DL> 134 | 135 | ++++++++++++++++++++++++++++++++++++++*/ 136 | static void create_name_query(char *query_str, const char *sql_query, const char *keys) { 137 | int i; 138 | char *word; 139 | char from_clause_atom[STR_XL]; 140 | char from_clause[STR_XXL]; 141 | char where_clause_atom[STR_XL]; 142 | char where_clause[STR_XXL]; 143 | char *keys_tmp; 144 | 145 | strcpy(from_clause, ""); 146 | strcpy(where_clause, ""); 147 | 148 | keys_tmp = (char *)calloc(1, strlen(keys)+1); 149 | strcpy(keys_tmp, keys); 150 | 151 | word = (char *)strtok(keys_tmp, " "); 152 | 153 | sprintf(from_clause_atom, "names N%.2d", 0); 154 | sprintf(where_clause_atom, "N%.2d.name='%s'", 0, word); 155 | 156 | strcat(from_clause, from_clause_atom); 157 | strcat(where_clause, where_clause_atom); 158 | 159 | for (i=1; (word=(char *)strtok(NULL, " ")) != NULL; i++) { 160 | sprintf(from_clause_atom, ", names N%.2d", i); 161 | sprintf(where_clause_atom, " AND N%.2d.name='%s' AND N00.pe_ro_id = N%.2d.pe_ro_id", i, word, i); 162 | 163 | strcat(from_clause, from_clause_atom); 164 | strcat(where_clause, where_clause_atom); 165 | 166 | strcpy(from_clause_atom, ""); 167 | strcpy(where_clause_atom, ""); 168 | } 169 | 170 | sprintf(query_str, sql_query, from_clause, where_clause); 171 | 172 | /* XXX Free here */ 173 | /* 174 | free(keys_tmp); 175 | */ 176 | 177 | } /* create_name_query() */ 178 | 179 | /* create_query() */ 180 | /*++++++++++++++++++++++++++++++++++++++ 181 | Create an sql query from the query_command and the matching keytype and the 182 | selected inverse attributes. 183 | Note this clears the first inv_attribute it sees, so is called sequentially 184 | until there are no inv_attributes left. 185 | 186 | WK_Type keytype The matching keytype. 187 | 188 | const Query_command *qc The query command. 189 | 190 | mask_t *inv_attrs_bitmap The selected inverse attributes. 191 | 192 | More: 193 | +html+ <PRE> 194 | Authors: 195 | ottrey 196 | +html+ </PRE><DL COMPACT> 197 | +html+ <DT>Online References: 198 | +html+ <DD><UL> 199 | +html+ </UL></DL> 200 | 201 | ++++++++++++++++++++++++++++++++++++++*/ 202 | static char *create_query(WK_Type keytype, const Query_command *qc, mask_t *inv_attrs_bitmap) { 203 | char query_str_buf[STR_XXL]; 204 | char query_str_buf_stage1[STR_XXL]; 205 | char query_str_buf_filter[STR_XXL]; 206 | char *query_str; 207 | const char *sql_query; 208 | char *str; 209 | int inverse_query; 210 | 211 | if ( MA_bitcount(*inv_attrs_bitmap) == 0 ) { 212 | sql_query = Instructions[keytype].sql_primary_query; 213 | inverse_query = 0; 214 | } 215 | else { 216 | sql_query = Instructions[keytype].sql_inverse_query; 217 | inverse_query = 1; 218 | } 219 | 220 | strcpy(query_str_buf, ""); 221 | strcpy(query_str_buf_stage1, ""); 222 | 223 | switch ( keytype ) { 224 | case WK_NAME: 225 | if (sql_query != NULL) { 226 | if ( inverse_query == 0 ) { 227 | create_name_query(query_str_buf, sql_query, qc->keys); 228 | /* XXX There is no way to filter -Tpn WK_NAME in the current schema design. */ 229 | } 230 | else { 231 | /* Inverse name query */ 232 | if ( MA_isset(*inv_attrs_bitmap, A_AC) == 1 ) { 233 | MA_set(inv_attrs_bitmap, A_AC, 0); 234 | sprintf(query_str_buf_stage1, sql_query, "admin_c", "admin_c", "admin_c"); 235 | create_name_query(query_str_buf, query_str_buf_stage1, qc->keys); 236 | } 237 | else if ( MA_isset(*inv_attrs_bitmap, A_TC) == 1 ) { 238 | MA_set(inv_attrs_bitmap, A_TC, 0); 239 | sprintf(query_str_buf_stage1, sql_query, "tech_c", "tech_c", "tech_c"); 240 | create_name_query(query_str_buf, query_str_buf_stage1, qc->keys); 241 | } 242 | else if ( MA_isset(*inv_attrs_bitmap, A_ZC) == 1 ) { 243 | MA_set(inv_attrs_bitmap, A_ZC, 0); 244 | sprintf(query_str_buf_stage1, sql_query, "zone_c", "zone_c", "zone_c"); 245 | create_name_query(query_str_buf, query_str_buf_stage1, qc->keys); 246 | } 247 | else { 248 | MA_clear(inv_attrs_bitmap); 249 | } 250 | } 251 | } 252 | else { 253 | MA_clear(inv_attrs_bitmap); 254 | } 255 | 256 | break; 257 | 258 | case WK_NICHDL: 259 | if (sql_query != NULL) { 260 | if ( inverse_query == 0 ) { 261 | sprintf(query_str_buf, sql_query, qc->keys); 262 | if ( (MA_isset(qc->object_type_bitmap, A_PN) == 1) 263 | && (MA_isset(qc->object_type_bitmap, A_RO) == 0) ) { 264 | strcat(query_str_buf, " AND is_person = 1"); 265 | } 266 | else if ( (MA_isset(qc->object_type_bitmap, A_RO) == 1) 267 | && (MA_isset(qc->object_type_bitmap, A_PN) == 0) ) { 268 | strcat(query_str_buf, " AND is_person = 0"); 269 | } 270 | } 271 | else { 272 | /* Inverse NICHDL query */ 273 | if ( MA_isset(*inv_attrs_bitmap, A_AC) == 1 ) { 274 | MA_set(inv_attrs_bitmap, A_AC, 0); 275 | sprintf(query_str_buf, sql_query, "admin_c", "admin_c", qc->keys, "admin_c"); 276 | } 277 | else if ( MA_isset(*inv_attrs_bitmap, A_TC) == 1 ) { 278 | MA_set(inv_attrs_bitmap, A_TC, 0); 279 | sprintf(query_str_buf, sql_query, "tech_c", "tech_c", qc->keys, "tech_c"); 280 | } 281 | else if ( MA_isset(*inv_attrs_bitmap, A_ZC) == 1 ) { 282 | MA_set(inv_attrs_bitmap, A_ZC, 0); 283 | sprintf(query_str_buf, sql_query, "zone_c", "zone_c", qc->keys, "zone_c"); 284 | } 285 | else { 286 | MA_clear(inv_attrs_bitmap); 287 | } 288 | if ( (MA_isset(qc->object_type_bitmap, A_PN) == 1) 289 | && (MA_isset(qc->object_type_bitmap, A_RO) == 0) ) { 290 | /* XXX This is backwards. */ 291 | strcat(query_str_buf, " AND is_person = 0"); 292 | } 293 | else if ( (MA_isset(qc->object_type_bitmap, A_RO) == 1) 294 | && (MA_isset(qc->object_type_bitmap, A_PN) == 0) ) { 295 | /* XXX This is backwards. */ 296 | strcat(query_str_buf, " AND is_person = 1"); 297 | } 298 | } 299 | } 300 | else { 301 | MA_clear(inv_attrs_bitmap); 302 | } 303 | break; 304 | 305 | case WK_EMAIL: 306 | if (sql_query != NULL) { 307 | if ( inverse_query == 0 ) { 308 | sprintf(query_str_buf, sql_query, qc->keys); 309 | } 310 | else { 311 | /* Inverse EMAIL query */ 312 | if ( MA_isset(*inv_attrs_bitmap, A_NY) == 1 ) { 313 | MA_set(inv_attrs_bitmap, A_NY, 0); 314 | sprintf(query_str_buf, sql_query, qc->keys); 315 | } 316 | else { 317 | MA_clear(inv_attrs_bitmap); 318 | } 319 | } 320 | } 321 | else { 322 | MA_clear(inv_attrs_bitmap); 323 | } 324 | break; 325 | 326 | case WK_MAINT: 327 | if (sql_query != NULL) { 328 | if ( inverse_query == 0 ) { 329 | sprintf(query_str_buf, sql_query, qc->keys); 330 | } 331 | else { 332 | /* Inverse MAINT query */ 333 | if ( MA_isset(*inv_attrs_bitmap, A_MB) == 1 ) { 334 | MA_set(inv_attrs_bitmap, A_MB, 0); 335 | sprintf(query_str_buf, sql_query, qc->keys); 336 | } 337 | else { 338 | MA_clear(inv_attrs_bitmap); 339 | } 340 | } 341 | } 342 | else { 343 | MA_clear(inv_attrs_bitmap); 344 | } 345 | break; 346 | 347 | case WK_ASNUM: 348 | if (sql_query != NULL) { 349 | if ( inverse_query == 0 ) { 350 | sprintf(query_str_buf, sql_query, qc->keys); 351 | } 352 | else { 353 | /* Inverse ASNUM query */ 354 | if ( MA_isset(*inv_attrs_bitmap, A_OR) == 1 ) { 355 | MA_set(inv_attrs_bitmap, A_OR, 0); 356 | sprintf(query_str_buf, sql_query, qc->keys); 357 | } 358 | else { 359 | MA_clear(inv_attrs_bitmap); 360 | } 361 | } 362 | } 363 | else { 364 | MA_clear(inv_attrs_bitmap); 365 | } 366 | break; 367 | 368 | case WK_DOMNAME: 369 | if (sql_query != NULL) { 370 | if ( inverse_query == 0 ) { 371 | sprintf(query_str_buf, sql_query, qc->keys); 372 | } 373 | else { 374 | /* Inverse DOMNAME query */ 375 | if ( MA_isset(*inv_attrs_bitmap, A_SD) == 1 ) { 376 | MA_set(inv_attrs_bitmap, A_OR, 0); 377 | sprintf(query_str_buf, sql_query, qc->keys); 378 | } 379 | else { 380 | MA_clear(inv_attrs_bitmap); 381 | } 382 | } 383 | } 384 | else { 385 | MA_clear(inv_attrs_bitmap); 386 | } 387 | break; 388 | 389 | default: 390 | if (sql_query != NULL) { 391 | if ( inverse_query == 0 ) { 392 | sprintf(query_str_buf, sql_query, qc->keys); 393 | } 394 | else { 395 | /* No Inverse query */ 396 | MA_clear(inv_attrs_bitmap); 397 | } 398 | 399 | } 400 | else { 401 | MA_clear(inv_attrs_bitmap); 402 | } 403 | } /* switch() */ 404 | 405 | if (strcmp(query_str_buf, "") == 0) { 406 | query_str = NULL; 407 | } 408 | else { 409 | query_str = (char *)calloc(1, strlen(query_str_buf)+1); 410 | strcpy(query_str, query_str_buf); 411 | } 412 | 413 | return query_str; 414 | } /* create_query() */ 415 | 416 | /* write_results() */ 417 | /*++++++++++++++++++++++++++++++++++++++ 418 | Write the results to the client socket. 419 | 420 | SQ_result_set_t *result The result set returned from the sql query. 421 | 422 | int sock The socket that the client is connected to. 423 | 424 | XXX NB. this is very dependendant on what rows are returned in the result!!! 425 | 426 | More: 427 | +html+ <PRE> 428 | Authors: 429 | ottrey 430 | +html+ </PRE><DL COMPACT> 431 | +html+ <DT>Online References: 432 | +html+ <DD><UL> 433 | +html+ </UL></DL> 434 | 435 | ++++++++++++++++++++++++++++++++++++++*/ 436 | static int write_results(SQ_result_set_t *result, int sock) { 437 | SQ_row_t *row; 438 | char *str; 439 | char log_str[STR_L]; 440 | int retrieved_objects=0; 441 | 442 | /* Get all the results - one at a time */ 443 | if (result != NULL) { 444 | while ( (row = SQ_row_next(result)) != NULL) { 445 | str = SQ_get_column_string(row, 0); 446 | if (str != NULL) { 447 | strcpy(log_str, ""); 448 | sprintf(log_str, "Retrieved serial id = %d\n", atoi(str)); 449 | log_inst_print(log_str); 450 | } 451 | free(str); 452 | 453 | str = SQ_get_column_string(row, 2); 454 | if (str != NULL) { 455 | SK_puts(sock, str); 456 | SK_puts(sock, "\n"); 457 | retrieved_objects++; 458 | } 459 | free(str); 460 | } 461 | } 462 | 463 | return retrieved_objects; 464 | } /* write_results() */ 465 | 466 | 467 | /* write_objects() */ 468 | /*++++++++++++++++++++++++++++++++++++++ 469 | This is linked into MySQL by the fact that MySQL doesn't have sub selects 470 | (yet). The queries are done in two stages. Make some temporary tables and 471 | insert into them. Then use them in the next select. 472 | 473 | SQ_connection_t *sql_connection The connection to the database. 474 | 475 | char *id_table The id of the temporary table (This is a result of the hacky 476 | way we've tried to get MySQL to do sub-selects.) 477 | 478 | unsigned int recursive A recursive query. 479 | 480 | unsigned int sock The client socket. 481 | 482 | More: 483 | +html+ <PRE> 484 | Authors: 485 | ottrey 486 | +html+ </PRE><DL COMPACT> 487 | ++++++++++++++++++++++++++++++++++++++*/ 488 | static void write_objects(SQ_connection_t *sql_connection, char *id_table, unsigned int recursive, unsigned int sock) { 489 | /* XXX This should really return a linked list of the objects */ 490 | 491 | SQ_result_set_t *result; 492 | int retrieved_objects=0; 493 | 494 | char sql_command[STR_XL]; 495 | char log_str[STR_L]; 496 | 497 | strcpy(sql_command, ""); 498 | /* XXX These may and should change a lot. */ 499 | sprintf(sql_command, Q_OBJECTS, id_table, id_table); 500 | result = SQ_execute_query(sql_connection, sql_command); 501 | 502 | retrieved_objects += write_results(result, sock); 503 | 504 | SQ_free_result(result); 505 | 506 | /* Now for recursive queries */ 507 | if (recursive == 1) { 508 | strcpy(sql_command, ""); 509 | sprintf(sql_command, Q_REC, id_table, "admin_c", id_table, id_table); 510 | SQ_execute_query(sql_connection, sql_command); 511 | 512 | strcpy(sql_command, ""); 513 | sprintf(sql_command, Q_REC, id_table, "tech_c", id_table, id_table); 514 | SQ_execute_query(sql_connection, sql_command); 515 | 516 | strcpy(sql_command, ""); 517 | sprintf(sql_command, Q_REC, id_table, "zone_c", id_table, id_table); 518 | SQ_execute_query(sql_connection, sql_command); 519 | 520 | /* XXX These may and should change a lot. */ 521 | strcpy(sql_command, ""); 522 | sprintf(sql_command, Q_REC_OBJECTS, id_table, id_table, id_table); 523 | result = SQ_execute_query(sql_connection, sql_command); 524 | 525 | retrieved_objects += write_results(result, sock); 526 | 527 | SQ_free_result(result); 528 | 529 | /* Now drop the IDS recursive table */ 530 | strcpy(sql_command, ""); 531 | sprintf(sql_command, "DROP TABLE %s_R", id_table); 532 | SQ_execute_query(sql_connection, sql_command); 533 | } 534 | 535 | /* If nothing is retreived default to return the 0th object - I.e "not found" */ 536 | if (retrieved_objects == 0) { 537 | result = SQ_execute_query(sql_connection, Q_NO_OBJECTS); 538 | write_results(result, sock); 539 | 540 | SQ_free_result(result); 541 | } 542 | 543 | /* Now drop the IDS table */ 544 | strcpy(sql_command, ""); 545 | sprintf(sql_command, "DROP TABLE %s", id_table); 546 | SQ_execute_query(sql_connection, sql_command); 547 | 548 | strcpy(log_str, ""); 549 | sprintf(log_str, "%d object(s) retrieved\n\n", retrieved_objects); 550 | log_inst_print(log_str); 551 | 552 | if (CO_get_accounting() == 1) { 553 | /* XXX - later man. 554 | account(retrieved_objects); 555 | */ 556 | printf("account(retrieved_objects);\n"); 557 | } 558 | 559 | } /* write_objects() */ 560 | 561 | /* insert_radix_serials() */ 562 | /*++++++++++++++++++++++++++++++++++++++ 563 | Insert the radix serial numbers into a temporary table in the database. 564 | 565 | mask_t bitmap The bitmap of attribute to be converted. 566 | 567 | SQ_connection_t *sql_connection The connection to the database. 568 | 569 | char *id_table The id of the temporary table (This is a result of the hacky 570 | way we've tried to get MySQL to do sub-selects.) 571 | 572 | GList *datlist The list of data from the radix tree. 573 | 574 | XXX Hmmmmm this isn't really a good place to free things... infact it's quite nasty. :-( 575 | 576 | More: 577 | +html+ <PRE> 578 | Authors: 579 | ottrey 580 | +html+ </PRE><DL COMPACT> 581 | +html+ <DT>Online References: 582 | +html+ <DD><UL> 583 | <LI><A HREF="http://www.gtk.org/rdp/glib/glib-doubly-linked-lists.html">Glist</A> 584 | +html+ </UL></DL> 585 | 586 | ++++++++++++++++++++++++++++++++++++++*/ 587 | static void insert_radix_serials(SQ_connection_t *sql_connection, char *id_table, GList *datlist) { 588 | GList *qitem; 589 | char sql_command[STR_XL]; 590 | int serial; 591 | int i; 592 | 593 | /* 594 | TODO -- marek --- TODO 595 | for( qitem = g_list_last(datlist); qitem != NULL; qitem = g_list_previous(qitem)) { 596 | */ 597 | for( qitem = g_list_first(datlist); qitem != NULL; qitem = g_list_next(qitem)) { 598 | rx_datcpy_t *datcpy = qitem->data; 599 | 600 | serial = datcpy->leafcpy.data_key; 601 | 602 | strcpy(sql_command, ""); 603 | sprintf(sql_command, "INSERT INTO %s values (%d)\n", id_table, serial); 604 | SQ_execute_query(sql_connection, sql_command); 605 | 606 | /* XXX AAAARGH why here?!?! */ 607 | wr_free(datcpy->leafcpy.data_ptr); 608 | } 609 | 610 | /* XXX Possible memory leak here. -fix above?? */ 611 | g_list_foreach(datlist, rx_free_list_element, NULL); 612 | g_list_free(datlist); 613 | 614 | } /* insert_radix_serials() */ 615 | 616 | /* map_qc2rx() */ 617 | /*++++++++++++++++++++++++++++++++++++++ 618 | The mapping between a query_command and a radix query. 619 | 620 | Query_instruction *qi The Query Instruction to be created from the mapping 621 | of the query command. 622 | 623 | const Query_command *qc The query command to be mapped. 624 | 625 | More: 626 | +html+ <PRE> 627 | Authors: 628 | ottrey 629 | +html+ </PRE><DL COMPACT> 630 | +html+ <DT>Online References: 631 | +html+ <DD><UL> 632 | +html+ </UL></DL> 633 | 634 | ++++++++++++++++++++++++++++++++++++++*/ 635 | static int map_qc2rx(Query_instruction *qi, const Query_command *qc) { 636 | int result=1; 637 | 638 | qi->rx_keys = qc->keys; 639 | 640 | if ( (qc->L == 0) && (qc->M == 0) && (qc->l == 0) && (qc->m == 0) ) { 641 | qi->rx_srch_mode = RX_SRCH_EXLESS; 642 | qi->rx_par_a = 0; 643 | } 644 | else if ( (qc->L == 1) && (qc->M == 0) && (qc->l == 0) && (qc->m == 0) ) { 645 | qi->rx_srch_mode = RX_SRCH_LESS; 646 | qi->rx_par_a = RX_ALL_DEPTHS; 647 | } 648 | else if ( (qc->L == 0) && (qc->M == 1) && (qc->l == 0) && (qc->m == 0) ) { 649 | qi->rx_srch_mode = RX_SRCH_MORE; 650 | qi->rx_par_a = RX_ALL_DEPTHS; 651 | } 652 | else if ( (qc->L == 0) && (qc->M == 0) && (qc->l == 1) && (qc->m == 0) ) { 653 | qi->rx_srch_mode = RX_SRCH_LESS; 654 | qi->rx_par_a = 1; 655 | } 656 | else if ( (qc->L == 0) && (qc->M == 0) && (qc->l == 0) && (qc->m == 1) ) { 657 | qi->rx_srch_mode = RX_SRCH_MORE; 658 | qi->rx_par_a = 1; 659 | } 660 | else { 661 | result = -1; 662 | } 663 | 664 | return result; 665 | 666 | } /* map_qc2rx() */ 667 | 668 | 669 | /* QI_execute() */ 670 | /*++++++++++++++++++++++++++++++++++++++ 671 | Execute the query instructions. This is called by a g_list_foreach 672 | function, so each of the sources in the "database source" list can be passed 673 | into this function. 674 | 675 | void *database_voidptr Pointer to the database. 676 | 677 | void *qis_voidptr Pointer to the query_instructions. 678 | 679 | More: 680 | +html+ <PRE> 681 | Authors: 682 | ottrey 683 | +html+ </PRE><DL COMPACT> 684 | +html+ <DT>Online References: 685 | +html+ <DD><UL> 686 | <LI><A 687 | HREF="http://www.gtk.org/rdp/glib/glib-singly-linked-lists.html#G-SLIST-FOREACH">g_list_foreach</A> 688 | +html+ </UL></DL> 689 | 690 | ++++++++++++++++++++++++++++++++++++++*/ 691 | void QI_execute(void *database_voidptr, void *qis_voidptr) { 692 | char *database = (char *)database_voidptr; 693 | Query_instructions *qis = (Query_instructions *)qis_voidptr; 694 | Query_instruction **ins=NULL; 695 | char id_table[STR_S]; 696 | char sql_command[STR_XL]; 697 | GList *datlist=NULL; 698 | int i; 699 | 700 | char log_str[STR_L]; 701 | 702 | SQ_connection_t *sql_connection=NULL; 703 | 704 | sql_connection = SQ_get_connection(CO_get_host(), CO_get_database_port(), database, CO_get_user(), CO_get_password() ); 705 | 706 | if (sql_connection == NULL) { 707 | SK_puts(qis->sock, "% WARNING: Failed to make connection to "); 708 | SK_puts(qis->sock, database); 709 | SK_puts(qis->sock, " database mirror.\n\n"); 710 | } 711 | else { 712 | strcpy(sql_command, ""); 713 | 714 | /* XXX This is a really bad thing to do. It should'nt _have_ to be called here. 715 | But unfortunately it does. -- Sigh. */ 716 | sprintf(id_table, "ID_%d", mysql_thread_id(sql_connection) ); 717 | 718 | strcpy(sql_command, ""); 719 | sprintf(sql_command, "CREATE TABLE %s ( id int ) TYPE=HEAP", id_table); 720 | SQ_execute_query(sql_connection, sql_command); 721 | 722 | if (qis->recursive == 1) { 723 | strcpy(sql_command, ""); 724 | sprintf(sql_command, "CREATE TABLE %s_R ( id int ) TYPE=HEAP", id_table); 725 | SQ_execute_query(sql_connection, sql_command); 726 | } 727 | 728 | ins = qis->instruction; 729 | for (i=0; ins[i] != NULL; i++) { 730 | switch ( (ins[i])->search_type ) { 731 | case QI_SQL: 732 | if ( (ins[i])->query_str != NULL ) { 733 | strcpy(sql_command, ""); 734 | sprintf(sql_command, "INSERT INTO %s %s\n", id_table, (ins[i])->query_str); 735 | SQ_execute_query(sql_connection, sql_command); 736 | } 737 | break; 738 | 739 | /* XXX I don't like this bit much. This is one of the bits that needs re-designing. */ 740 | #define RIPE_REG 17 741 | case QI_RADIX: 742 | datlist = NULL; 743 | printf("searching 'in'\n"); 744 | if ( RX_asc_search((ins[i])->rx_srch_mode, (ins[i])->rx_par_a, 0, (ins[i])->rx_keys, RIPE_REG, IP_V4, RX_FAM_IN, &datlist, RX_ANS_ALL) == RX_OK ) { 745 | insert_radix_serials(sql_connection, id_table, datlist); 746 | } 747 | else { 748 | /* Skip query */ 749 | strcpy(log_str, ""); 750 | sprintf(log_str, "rx: /* Skip in query */\n"); 751 | log_inst_print(log_str); 752 | } 753 | datlist = NULL; 754 | printf("searching 'rt'\n"); 755 | if ( RX_asc_search((ins[i])->rx_srch_mode, (ins[i])->rx_par_a, 0, (ins[i])->rx_keys, RIPE_REG, IP_V4, RX_FAM_RT, &datlist, RX_ANS_ALL) == RX_OK ) {; 756 | insert_radix_serials(sql_connection, id_table, datlist); 757 | } 758 | else { 759 | /* Skip query */ 760 | strcpy(log_str, ""); 761 | sprintf(log_str, "rx: /* Skip rt query */\n"); 762 | log_inst_print(log_str); 763 | } 764 | break; 765 | 766 | case QI_RADIX_IN: 767 | datlist = NULL; 768 | printf("searching 'in'\n"); 769 | if ( RX_asc_search((ins[i])->rx_srch_mode, (ins[i])->rx_par_a, 0, (ins[i])->rx_keys, RIPE_REG, IP_V4, RX_FAM_IN, &datlist, RX_ANS_ALL) == RX_OK ) { 770 | insert_radix_serials(sql_connection, id_table, datlist); 771 | } 772 | else { 773 | /* Skip query */ 774 | strcpy(log_str, ""); 775 | sprintf(log_str, "rx: /* Skip in query */\n"); 776 | log_inst_print(log_str); 777 | } 778 | break; 779 | 780 | case QI_RADIX_RT: 781 | datlist = NULL; 782 | printf("searching 'rt'\n"); 783 | if ( RX_asc_search((ins[i])->rx_srch_mode, (ins[i])->rx_par_a, 0, (ins[i])->rx_keys, RIPE_REG, IP_V4, RX_FAM_RT, &datlist, RX_ANS_ALL) == RX_OK ) {; 784 | insert_radix_serials(sql_connection, id_table, datlist); 785 | } 786 | else { 787 | /* Skip query */ 788 | strcpy(log_str, ""); 789 | sprintf(log_str, "rx: /* Skip rt query */\n"); 790 | log_inst_print(log_str); 791 | } 792 | break; 793 | 794 | default: 795 | strcpy(log_str, ""); 796 | sprintf(log_str, "ERROR: bad search_type\n"); 797 | log_inst_print(log_str); 798 | } /* switch */ 799 | } 800 | write_objects(sql_connection, id_table, qis->recursive, qis->sock); 801 | } 802 | 803 | SQ_close_connection(sql_connection); 804 | 805 | } /* QI_execute() */ 806 | 807 | /* instruction_free() */ 808 | /*++++++++++++++++++++++++++++++++++++++ 809 | Free the instruction. 810 | 811 | Query_instruction *qi query_instruction to be freed. 812 | 813 | More: 814 | +html+ <PRE> 815 | Authors: 816 | ottrey 817 | +html+ </PRE><DL COMPACT> 818 | +html+ <DT>Online References: 819 | +html+ <DD><UL> 820 | +html+ </UL></DL> 821 | 822 | ++++++++++++++++++++++++++++++++++++++*/ 823 | static void instruction_free(Query_instruction *qi) { 824 | if (qi != NULL) { 825 | if (qi->query_str != NULL) { 826 | free(qi->query_str); 827 | } 828 | free(qi); 829 | } 830 | } /* instruction_free() */ 831 | 832 | /* QI_free() */ 833 | /*++++++++++++++++++++++++++++++++++++++ 834 | Free the query_instructions. 835 | 836 | Query_instructions *qis Query_instructions to be freed. 837 | 838 | XXX This isn't working too well at the moment. 839 | 840 | More: 841 | +html+ <PRE> 842 | Authors: 843 | ottrey 844 | +html+ </PRE><DL COMPACT> 845 | +html+ <DT>Online References: 846 | +html+ <DD><UL> 847 | +html+ </UL></DL> 848 | 849 | ++++++++++++++++++++++++++++++++++++++*/ 850 | void QI_free(Query_instructions *qis) { 851 | /* XXX huh!?H? 852 | int i; 853 | 854 | for (i=0; qis[i] != NULL; i++) { 855 | instruction_free(*qis[i]); 856 | } 857 | */ 858 | if (qis != NULL) { 859 | free(qis); 860 | } 861 | 862 | } /* QI_free() */ 863 | 864 | /* QI_new() */ 865 | /*++++++++++++++++++++++++++++++++++++++ 866 | Create a new set of query_instructions. 867 | 868 | mask_t bitmap The bitmap of attribute to be converted. 869 | 870 | const Query_command *qc The query_command that the instructions are created 871 | from. 872 | 873 | unsigned int sock The client socket. 874 | 875 | More: 876 | +html+ <PRE> 877 | Authors: 878 | ottrey 879 | +html+ </PRE><DL COMPACT> 880 | +html+ <DT>Online References: 881 | +html+ <DD><UL> 882 | +html+ </UL></DL> 883 | 884 | ++++++++++++++++++++++++++++++++++++++*/ 885 | Query_instructions *QI_new(const Query_command *qc, unsigned int sock) { 886 | Query_instructions *qis=NULL; 887 | Query_instruction *qi=NULL; 888 | int i_no=0,j; 889 | WK_Type keytype; 890 | char *query_str; 891 | mask_t inv_attrs_bitmap; 892 | mask_t wk_search_rx_bitmap, wk_search_sq_bitmap; 893 | 894 | char log_str[STR_L]; 895 | 896 | wk_search_rx_bitmap = MA_new(WK_SEARCH_MASK_RX); 897 | wk_search_sq_bitmap = MA_new(WK_SEARCH_MASK_SQ); 898 | 899 | qis = (Query_instructions *)calloc(1, sizeof(Query_instructions)); 900 | qis->sock = sock; 901 | qis->recursive = qc->recursive; 902 | 903 | for (keytype=0; keytype < WK_END; keytype++) { 904 | /* XXX This bit is really bad; and needs work - needs redesigning. */ 905 | /* if that keytype is one of the objects in the -T list. (NB. "NULL" implies all by default) */ 906 | switch (keytype) { 907 | case WK_NAME: 908 | case WK_NICHDL: 909 | if ( (MA_isset(qc->object_type_bitmap, A_PN) != 1) 910 | && (MA_isset(qc->object_type_bitmap, A_RO) != 1) ) { 911 | continue; 912 | } 913 | break; 914 | 915 | case WK_EMAIL: 916 | /* XXX Hmmmm I don't know. Search it anyway. */ 917 | ; 918 | break; 919 | 920 | case WK_MAINT: 921 | if (MA_isset(qc->object_type_bitmap, A_MT) != 1) { 922 | continue; 923 | } 924 | break; 925 | 926 | case WK_KEYCERT: 927 | if (MA_isset(qc->object_type_bitmap, A_KC) != 1) { 928 | continue; 929 | } 930 | break; 931 | 932 | case WK_IPRANGE: 933 | /* XXX Hmmmm I don't know. Search it anyway. */ 934 | ; 935 | break; 936 | 937 | case WK_IP6RANGE: 938 | /* XXX Hmmmm I don't know. Search it anyway. */ 939 | ; 940 | break; 941 | 942 | case WK_NETNAME: 943 | /* XXX Hmmmm I don't know. Search it anyway. */ 944 | ; 945 | break; 946 | 947 | case WK_ASNUM: 948 | /* XXX Hmmmm I don't know. Search it anyway. */ 949 | ; 950 | break; 951 | 952 | case WK_ASSETNAME: 953 | /* XXX Hmmmm I don't know. Search it anyway. */ 954 | ; 955 | break; 956 | 957 | case WK_ROUTESETNAME: 958 | /* XXX Hmmmm I don't know. Search it anyway. */ 959 | ; 960 | break; 961 | 962 | case WK_DOMNAME: 963 | if (MA_isset(qc->object_type_bitmap, A_DN) != 1) { 964 | continue; 965 | } 966 | break; 967 | 968 | case WK_HOSTNAME: 969 | /* XXX Hmmmm I don't know. Search it anyway. */ 970 | ; 971 | break; 972 | 973 | case WK_LIMERICKNAME: 974 | if (MA_isset(qc->object_type_bitmap, A_LI) != 1) { 975 | continue; 976 | } 977 | break; 978 | 979 | default: 980 | printf("Error: bad keytype encountered in QI_new()\n"); 981 | } 982 | 983 | /* If matched the keytype */ 984 | if ( MA_isset(qc->keytypes_bitmap, keytype) == 1) { 985 | qi = (Query_instruction *)calloc(1, sizeof(Query_instruction)); 986 | /* SQL Query */ 987 | if ( MA_isset(wk_search_sq_bitmap, keytype) == 1 ) { 988 | qi->search_type = QI_SQL; 989 | 990 | inv_attrs_bitmap = qc->inv_attrs_bitmap; 991 | j=0; 992 | do { 993 | query_str = create_query(keytype, qc, &inv_attrs_bitmap); 994 | if (query_str != NULL) { 995 | qi->query_str = query_str; 996 | qis->instruction[i_no++] = qi; 997 | } 998 | j++; 999 | if (j> 7) { 1000 | strcpy(log_str, ""); 1001 | sprintf(log_str, "ERROR Too many loops .. bailing\n"); 1002 | log_inst_print(log_str); 1003 | break; 1004 | } 1005 | } while (MA_bitcount(inv_attrs_bitmap)); 1006 | } 1007 | /* Radix Query */ 1008 | else if ( MA_isset(wk_search_rx_bitmap, keytype) == 1 ) { 1009 | if ( MA_isset(qc->object_type_bitmap, A_IN) == 1 ) { 1010 | qi->search_type = QI_RADIX_IN; 1011 | } 1012 | if ( MA_isset(qc->object_type_bitmap, A_RT) == 1 ) { 1013 | qi->search_type = QI_RADIX_RT; 1014 | } 1015 | if ( ( MA_isset(qc->object_type_bitmap, A_IN) == 1 ) 1016 | && ( MA_isset(qc->object_type_bitmap, A_RT) == 1 ) ) { 1017 | qi->search_type = QI_RADIX; 1018 | } 1019 | if (map_qc2rx(qi, qc) == 1) { 1020 | /* Add the query_instruction to the array */ 1021 | qis->instruction[i_no++] = qi; 1022 | } 1023 | else { 1024 | strcpy(log_str, ""); 1025 | sprintf(log_str, "ERROR in qc2rx mapping: bad combination of flags\n"); 1026 | log_inst_print(log_str); 1027 | } 1028 | } 1029 | else { 1030 | strcpy(log_str, ""); 1031 | sprintf(log_str, "ERROR: bad search_type\n"); 1032 | log_inst_print(log_str); 1033 | } 1034 | } 1035 | } 1036 | qis->instruction[i_no++] = NULL; 1037 | 1038 | return qis; 1039 | 1040 | } /* QI_new() */