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() */