1    | /***************************************
2    |   $Revision: 1.15 $
3    | 
4    |   Radix payload (rp) - user level functions for storing data in radix trees
5    | 
6    |   rp_load = loading the radix trees with data on startup
7    | 
8    |   Status: NOT REVIEWED, TESTED
9    |   
10   |   Design and implementation by: Marek Bukowy
11   |   
12   |   ******************/ /******************
13   |   Copyright (c) 1999                              RIPE NCC
14   |  
15   |   All Rights Reserved
16   |   
17   |   Permission to use, copy, modify, and distribute this software and its
18   |   documentation for any purpose and without fee is hereby granted,
19   |   provided that the above copyright notice appear in all copies and that
20   |   both that copyright notice and this permission notice appear in
21   |   supporting documentation, and that the name of the author not be
22   |   used in advertising or publicity pertaining to distribution of the
23   |   software without specific, written prior permission.
24   |   
25   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
26   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
27   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
28   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31   |   ***************************************/
32   | #include <rp.h>
33   | #include <mysql_driver.h>
34   | #include <constants.h>
35   | 
36   | #include "ca_configFns.h"
37   | #include "ca_dictSyms.h"
38   | #include "ca_macros.h"
39   | #include "ca_srcAttribs.h"
40   | 
41   | static
42   | er_ret_t
43   | make_sql2pack(SQ_result_set_t *result, SQ_row_t *row, 
44   | 	      rp_upd_pack_t *pack, rp_attr_t  attr, int colcount)
45   | {
46   |   er_ret_t   conv = RP_OK;
47   |   rp_uni_t   *uniptr = &(pack->uni);
48   |   char       *idptr; /* initially set to the 0'th column */
49   |   char       *col[4];
50   |   int        i;
51   | 
52   |   dieif(colcount>4); /* size of the col array */
53   | 
54   |   for(i=0; i<colcount; i++) {
55   |     col[i] = SQ_get_column_string_nocopy(result, row, i);
56   |     if (col[i] == NULL) {
57   |       die;
58   |     }
59   |   }
60   | 
61   |   idptr = col[0];
62   | 
63   |   pack->type = attr;
64   |   pack->d.origin = NULL;
65   |   switch( attr ) {
66   |   case A_IN:
67   |     /*
68   |       read 0-2 from inetnum
69   |       0 - objectid
70   |       1 - begin   
71   |       2 - end     
72   |     */
73   |     uniptr->space = IP_V4;
74   |     conv = IP_rang_f2b_v4( &(uniptr->u.in), col[1], col[2] );
75   |     break;
76   |   case A_RT:
77   |     /*
78   |       read 0-3 from route
79   |       0 - objectid 
80   |       1 - prefix    
81   |       2 - prefix_length   
82   |       3 - origin
83   |     */
84   |     uniptr->space = IP_V4;
85   |     if( NOERR(conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] ))) {
86   |       dieif(wr_malloc( (void **) &(pack->d.origin), strlen(col[3])+1)
87   | 	    != UT_OK);
88   | 
89   |       strcpy(pack->d.origin, col[3]);
90   |     }
91   |     break;
92   |   case A_DN:
93   |     /*
94   |       read 0-3 from inaddr
95   |       0 - objectid 
96   |       1 - prefix
97   |       2 - prefix_length   
98   |       3 - domain
99   |     */
100  |     conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] );
101  |     uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
102  |     dieif(wr_malloc( (void **) &(pack->d.domain), strlen(col[3])+1)
103  | 	    != UT_OK);
104  | 
105  |     strcpy(pack->d.domain, col[3]);
106  |     break;
107  |   case A_I6: 
108  |     /*
109  |       read 0-3 from inaddr
110  |       0 - objectid 
111  |       1 - msb
112  |       2 - lsb
113  |       3 - prefix_length 
114  |     */
115  |     conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3]);
116  |     uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
117  |     break;
118  |   default:
119  |     /*    die; / * shouldn't have got here */
120  |     conv = IP_INVARG;
121  |   }
122  |   
123  |   if( sscanf(idptr, "%lu", &(pack->key) ) < 1 ) {
124  |     conv = IP_INVARG;
125  |   }
126  |   
127  | 
128  |   for(i=0; i<colcount; i++) {
129  |     /*    wr_free(col[i]);*/ ;
130  |   }
131  |   
132  |   return conv;
133  | }
134  | 
135  | er_ret_t
136  | RP_sql_load_attr_space( int maxobj, int operation, 
137  | 			char *qry,
138  | 			rp_attr_t attr, ip_space_t space, 
139  | 			rp_regid_t reg_id, SQ_connection_t *con
140  | 			)
141  | {
142  |   SQ_row_t *row;
143  |   SQ_result_set_t *result;
144  |   int objnr=0;
145  |   rx_tree_t   *mytree;
146  |   rp_upd_pack_t pack;
147  |   int colcount;
148  |   int sizedebug = ER_is_traced(FAC_RP, ASP_RP_LOAD_DET);
149  | 
150  |   dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK );
151  |  
152  |   
153  |   ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loading %s", qry);
154  |   
155  |   ER_dbg_va(FAC_RP, ASP_RP_LOAD_GEN, "size before query = %x", sbrk(0));
156  |   
157  |   if ( SQ_execute_query(con, qry, &result) == -1 ) {
158  |     fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
159  |     die;
160  |   }
161  |   else { 
162  |     colcount = SQ_get_column_count(result);
163  |     
164  |     ER_dbg_va(FAC_RP, ASP_RP_LOAD_GEN, 
165  | 	      "size after query = %x; columns = %d", sbrk(0), colcount);
166  |     
167  |     /* XXX LOCKED when created */
168  |     /*TH_acquire_write_lock( &(mytree->rwlock) );*/
169  |     
170  |     while ( (row = SQ_row_next(result)) != NULL 
171  | 	    && SQ_errno(con) == 0
172  | 	    && objnr<=maxobj) {
173  |       
174  |       dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, colcount)) );
175  |       
176  |       if( ! NOERR(RP_pack_node_l(operation, &pack, mytree))) {
177  | 	fprintf(stderr,"%d:\t%ld\n", objnr, pack.key);
178  | 	die;
179  |       }
180  |       
181  |       /* free allocated memory */
182  |       if( pack.d.origin != NULL ) {
183  | 	wr_free(pack.d.origin);
184  | 	pack.d.origin == NULL;
185  |       }
186  |       
187  |       
188  |       
189  |       objnr++;
190  |       
191  |       if( sizedebug ) {
192  | 	ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x", 
193  | 		  objnr, sbrk(0));
194  |       }
195  |       
196  |     }
197  |     /* XXX UNLOCK */
198  |     TH_release_write_lock( &(mytree->rwlock) );
199  |   }
200  | 
201  |   if( SQ_errno(con) == 0 ) {
202  |       SQ_free_result(result);
203  |   } else {
204  |       die;
205  |   }
206  | 
207  |   ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr,
208  | 	    DF_get_attribute_code(attr) );
209  |  
210  |   
211  |   return RP_OK;
212  | }
213  | 
214  | er_ret_t
215  | RP_sql_load_reg(rp_regid_t reg_id) 
216  | {
217  |   unsigned maxline = 999999999;
218  |   er_ret_t err;
219  |   SQ_connection_t *con;
220  |   char *dbhost = ca_get_srcdbmachine(reg_id);
221  |   char *dbname = ca_get_srcdbname(reg_id);
222  |   char *dbuser = ca_get_srcdbuser(reg_id);
223  |   char *dbpass = ca_get_srcdbpassword(reg_id);
224  |   char *srcnam = ca_get_srcname(reg_id);
225  | 
226  | 
227  |   /* Make connection */
228  |   /*
229  |   con = SQ_get_connection(HOST, DATABASE_PORT, DATABASE, USER, PASSWD);
230  |   */
231  | 
232  | 
233  |   con = SQ_get_connection( dbhost, ca_get_srcdbport(reg_id),
234  | 				      dbname, dbuser, dbpass );
235  | #if 0
236  |   con = SQ_get_connection(CO_get_host(), 
237  | 			  CO_get_database_port(), 
238  | 			  CO_get_database(), /* XXX for this regid */
239  | 			  CO_get_user(), 
240  | 			  CO_get_password());
241  | #endif
242  | 
243  |   dieif ( SQ_execute_query(con, "LOCK TABLES    " 
244  |      "route READ, inetnum READ, inet6num READ, inaddr_arpa READ, domain READ ",
245  | 			   NULL) == -1 );
246  | 
247  |   do {
248  |    
249  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
250  |  "SELECT  object_id,prefix,prefix_length,origin   FROM route ",
251  | 					  A_RT, IP_V4, reg_id, con))) {
252  |       break;
253  |     }
254  |     
255  | #if 0
256  |     {
257  |       er_path_t erlogstr;
258  |       
259  |       erlogstr.fdes = stderr;
260  |       erlogstr.asp  = 0xffff0000;
261  |       erlogstr.fac  = FAC_RP; /* FAC_QI; */
262  |       erlogstr.sev  = ER_SEV_I;
263  |       erlogstr.mode = ER_M_SEVCHAR | ER_M_FACSYMB | ER_M_TEXTLONG;
264  |       
265  |       ER_setpath(& erlogstr);  
266  |       
267  |       wr_log_set(0);
268  |     }
269  | #endif
270  |  
271  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
272  | "SELECT  object_id,begin_in,end_in       FROM inetnum ",
273  | 					  A_IN, IP_V4, reg_id, con))) {
274  |       break;
275  |     }
276  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
277  | 					 
278  | "SELECT object_id,i6_msb,i6_lsb,prefix_length FROM inet6num",
279  | 
280  | 					  A_I6, IP_V6, reg_id, con))) {
281  |       break;
282  |     }
283  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
284  | 
285  | "SELECT domain.object_id,prefix,prefix_length,domain FROM inaddr_arpa,domain WHERE domain.object_id = inaddr_arpa.object_id",
286  | 					  
287  | 					  A_DN, IP_V4, reg_id, con))) {
288  |       break;
289  |     }
290  | 
291  |     /* CONSTCOND */
292  |   }while(0);
293  | 
294  |   dieif ( SQ_execute_query(con, "UNLOCK TABLES    ", NULL) == -1 );
295  | 
296  |   /* Close connection */
297  |   SQ_close_connection(con);
298  | 
299  |   /* free junk */
300  |   wr_free(dbhost);
301  |   wr_free(dbname);
302  |   wr_free(dbuser);
303  |   wr_free(dbpass);
304  |   wr_free(srcnam);
305  |   return err;
306  | }
307  | 
308  | 
309  | er_ret_t
310  | RP_asc_load(char *filename, int maxobj, int operation, 
311  | 	    rp_regid_t reg_id)
312  | {
313  |   er_ret_t err;
314  |   FILE *fp;
315  |   char buf[1024];
316  |   char fulltext[65536];
317  |   int objnr = 0;
318  |   int len, oldlen=0;
319  |   int ranlen;
320  |   char rangstr[IP_RANGSTR_MAX];
321  |   int parsed = 0;
322  |   int eor; /* end of record */
323  | 
324  |   
325  |   if( (fp = fopen(filename,"r")) == NULL ) {
326  |     perror(filename);
327  |     die; 
328  |   }
329  |  
330  |   do {
331  |     fgets(buf, 128, fp);
332  | 
333  |     eor = ( strlen(buf) <= 1 || feof(fp) );
334  |       
335  |     if( strlen(buf) > 1 ) {
336  |       len = strlen(buf);
337  |       dieif( oldlen+len+1 > 65536 ); /* object too long */
338  |       memcpy( fulltext+oldlen, buf, len);
339  |       oldlen+=len;
340  |       
341  |       fulltext[oldlen]=0;
342  |     }
343  |     
344  |     if( eor ) {              /* end of object: put into the database. */
345  |       parsed++;
346  |       
347  |       /* see if it was just some whitespace junk and nothing more */
348  |       if( *fulltext==0 ) {
349  | 	continue;  /* discard */
350  |       }
351  | 
352  |       /* check if it's a radix object */
353  |       do {
354  | 	char attrname[3];
355  | 	A_Type_t attrcode;
356  | 	
357  | 	if( fulltext[0] == '*' &&  fulltext[3] == ':' ) {
358  | 	  strncpy(attrname, fulltext+1, 2);
359  | 	  attrname[2]=0;
360  | 	  
361  | 	  if(strcmp(attrname, "XX") == 0 ) {
362  | 	    /* object deleted */
363  | 	    break;
364  | 	  }
365  | 	  
366  | 	  if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
367  | 	    fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
368  | 	    break;
369  | 	  }
370  | 	  
371  | 	  if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
372  | 	    /* no interest to radix */
373  | 	    break;
374  | 	  }
375  | 	
376  | 	  /* copy and translate the range */
377  | 	  ranlen = index(fulltext+5,'\n')-fulltext-5;
378  | 	  strncpy(rangstr, fulltext+5, ranlen);
379  | 	  rangstr[ranlen]=0;
380  | 	       
381  | 	  if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,  
382  | 				    fulltext, strlen(fulltext)+1, 0L )) ) {
383  | 	    objnr++;
384  | 	  }
385  | 	  else {
386  | 	    die; /* error putting into the radix tree */
387  | 	    return err;
388  | 	  }
389  | 	  
390  | 	}
391  | 	/* CONSTCOND */
392  |       } while(0);
393  |       
394  |       *fulltext=0;
395  |       oldlen=0;
396  |     }
397  |   }
398  |   while(!feof(fp) && objnr<maxobj);  
399  | 
400  |   return RP_OK;
401  | }