1    | /***************************************
2    |   $Revision: 1.14 $
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   | static
37   | er_ret_t
38   | make_sql2pack(SQ_result_set_t *result, SQ_row_t *row, 
39   | 	      rp_upd_pack_t *pack, rp_attr_t  attr, int colcount)
40   | {
41   |   er_ret_t   conv = RP_OK;
42   |   rp_uni_t   *uniptr = &(pack->uni);
43   |   char       *idptr; /* initially set to the 0'th column */
44   |   char       *col[4];
45   |   int        i;
46   | 
47   |   dieif(colcount>4); /* size of the col array */
48   | 
49   |   for(i=0; i<colcount; i++) {
50   |     col[i] = SQ_get_column_string_nocopy(result, row, i);
51   |     if (col[i] == NULL) {
52   |       die;
53   |     }
54   |   }
55   | 
56   |   idptr = col[0];
57   | 
58   |   pack->type = attr;
59   |   pack->d.origin = NULL;
60   |   switch( attr ) {
61   |   case A_IN:
62   |     /*
63   |       read 0-2 from inetnum
64   |       0 - objectid
65   |       1 - begin   
66   |       2 - end     
67   |     */
68   |     uniptr->space = IP_V4;
69   |     conv = IP_rang_f2b_v4( &(uniptr->u.in), col[1], col[2] );
70   |     break;
71   |   case A_RT:
72   |     /*
73   |       read 0-3 from route
74   |       0 - objectid 
75   |       1 - prefix    
76   |       2 - prefix_length   
77   |       3 - origin
78   |     */
79   |     uniptr->space = IP_V4;
80   |     if( NOERR(conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] ))) {
81   |       dieif(wr_malloc( (void **) &(pack->d.origin), strlen(col[3])+1)
82   | 	    != UT_OK);
83   | 
84   |       strcpy(pack->d.origin, col[3]);
85   |     }
86   |     break;
87   |   case A_DN:
88   |     /*
89   |       read 0-3 from inaddr
90   |       0 - objectid 
91   |       1 - prefix
92   |       2 - prefix_length   
93   |       3 - domain
94   |     */
95   |     conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] );
96   |     uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
97   |     dieif(wr_malloc( (void **) &(pack->d.domain), strlen(col[3])+1)
98   | 	    != UT_OK);
99   | 
100  |     strcpy(pack->d.domain, col[3]);
101  |     break;
102  |   case A_I6: 
103  |     /*
104  |       read 0-3 from inaddr
105  |       0 - objectid 
106  |       1 - msb
107  |       2 - lsb
108  |       3 - prefix_length 
109  |     */
110  |     conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3]);
111  |     uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) );
112  |     break;
113  |   default:
114  |     /*    die; / * shouldn't have got here */
115  |     conv = IP_INVARG;
116  |   }
117  |   
118  |   if( sscanf(idptr, "%lu", &(pack->key) ) < 1 ) {
119  |     conv = IP_INVARG;
120  |   }
121  |   
122  | 
123  |   for(i=0; i<colcount; i++) {
124  |     /*    wr_free(col[i]);*/ ;
125  |   }
126  |   
127  |   return conv;
128  | }
129  | 
130  | er_ret_t
131  | RP_sql_load_attr_space( int maxobj, int operation, 
132  | 			char *qry,
133  | 			rp_attr_t attr, ip_space_t space, 
134  | 			rp_regid_t reg_id, SQ_connection_t *con
135  | 			)
136  | {
137  |   SQ_row_t *row;
138  |   SQ_result_set_t *result;
139  |   int objnr=0;
140  |   rx_tree_t   *mytree;
141  |   rp_upd_pack_t pack;
142  |   int colcount;
143  |   int sizedebug = ER_is_traced(FAC_RP, ASP_RP_LOAD_DET);
144  | 
145  |   dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK );
146  |  
147  |   
148  |   ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loading %s", qry);
149  |   
150  |   ER_dbg_va(FAC_RP, ASP_RP_LOAD_GEN, "size before query = %x", sbrk(0));
151  |   
152  |   if ( SQ_execute_query(con, qry, &result) == -1 ) {
153  |     fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
154  |     die;
155  |   }
156  |   else { 
157  |     colcount = SQ_get_column_count(result);
158  |     
159  |     ER_dbg_va(FAC_RP, ASP_RP_LOAD_GEN, 
160  | 	      "size after query = %x; columns = %d", sbrk(0), colcount);
161  |     
162  |     /* XXX LOCKED when created */
163  |     /*TH_acquire_write_lock( &(mytree->rwlock) );*/
164  |     
165  |     while ( (row = SQ_row_next(result)) != NULL 
166  | 	    && SQ_errno(con) == 0
167  | 	    && objnr<=maxobj) {
168  |       
169  |       dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, colcount)) );
170  |       
171  |       if( ! NOERR(RP_pack_node_l(operation, &pack, mytree))) {
172  | 	fprintf(stderr,"%d:\t%ld\n", objnr, pack.key);
173  | 	die;
174  |       }
175  |       
176  |       objnr++;
177  |       
178  |       if( sizedebug ) {
179  | 	ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x", 
180  | 		  objnr, sbrk(0));
181  |       }
182  |       
183  |     }
184  |     /* XXX UNLOCK */
185  |     TH_release_write_lock( &(mytree->rwlock) );
186  |   }
187  | 
188  |   if( SQ_errno(con) == 0 ) {
189  |       SQ_free_result(result);
190  |   } else {
191  |       die;
192  |   }
193  | 
194  |   ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr,
195  | 	    DF_get_attribute_code(attr) );
196  |  
197  |   
198  |   return RP_OK;
199  | }
200  | 
201  | er_ret_t
202  | RP_sql_load_reg(rp_regid_t reg_id) 
203  | {
204  |   unsigned maxline = 999999999;
205  |   er_ret_t err;
206  |   SQ_connection_t *con;
207  | 
208  |   /* Make connection */
209  |   /*
210  |   con = SQ_get_connection(HOST, DATABASE_PORT, DATABASE, USER, PASSWD);
211  |   */
212  | 
213  |   con = SQ_get_connection(CO_get_host(), 
214  | 			  CO_get_database_port(), 
215  | 			  CO_get_database(), /* XXX for this regid */
216  | 			  CO_get_user(), 
217  | 			  CO_get_password());
218  | 
219  |   dieif ( SQ_execute_query(con, "LOCK TABLES    " 
220  |      "route READ, inetnum READ, inet6num READ, inaddr_arpa READ, domain READ ",
221  | 			   NULL) == -1 );
222  | 
223  |   do {
224  |    
225  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
226  |  "SELECT  object_id,prefix,prefix_length,origin   FROM route ",
227  | 					  A_RT, IP_V4, reg_id, con))) {
228  |       break;
229  |     }
230  |     
231  | #if 0
232  |     {
233  |       er_path_t erlogstr;
234  |       
235  |       erlogstr.fdes = stderr;
236  |       erlogstr.asp  = 0xffff0000;
237  |       erlogstr.fac  = FAC_RP; /* FAC_QI; */
238  |       erlogstr.sev  = ER_SEV_I;
239  |       erlogstr.mode = ER_M_SEVCHAR | ER_M_FACSYMB | ER_M_TEXTLONG;
240  |       
241  |       ER_setpath(& erlogstr);  
242  |       
243  |       wr_log_set(0);
244  |     }
245  | #endif
246  |  
247  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
248  | "SELECT  object_id,begin_in,end_in       FROM inetnum ",
249  | 					  A_IN, IP_V4, reg_id, con))) {
250  |       break;
251  |     }
252  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
253  | 					 
254  | "SELECT object_id,i6_msb,i6_lsb,prefix_length FROM inet6num",
255  | 
256  | 					  A_I6, IP_V6, reg_id, con))) {
257  |       break;
258  |     }
259  |     if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 
260  | 
261  | "SELECT domain.object_id,prefix,prefix_length,domain FROM inaddr_arpa,domain WHERE domain.object_id = inaddr_arpa.object_id",
262  | 					  
263  | 					  A_DN, IP_V4, reg_id, con))) {
264  |       break;
265  |     }
266  | 
267  |     /* CONSTCOND */
268  |   }while(0);
269  | 
270  |   dieif ( SQ_execute_query(con, "UNLOCK TABLES    ", NULL) == -1 );
271  | 
272  |   /* Close connection */
273  |   SQ_close_connection(con);
274  | 
275  |   return err;
276  | }
277  | 
278  | 
279  | er_ret_t
280  | RP_asc_load(char *filename, int maxobj, int operation, 
281  | 	    rp_regid_t reg_id)
282  | {
283  |   er_ret_t err;
284  |   FILE *fp;
285  |   char buf[1024];
286  |   char fulltext[65536];
287  |   int objnr = 0;
288  |   int len, oldlen=0;
289  |   int ranlen;
290  |   char rangstr[IP_RANGSTR_MAX];
291  |   int parsed = 0;
292  |   int eor; /* end of record */
293  | 
294  |   
295  |   if( (fp = fopen(filename,"r")) == NULL ) {
296  |     perror(filename);
297  |     die; 
298  |   }
299  |  
300  |   do {
301  |     fgets(buf, 128, fp);
302  | 
303  |     eor = ( strlen(buf) <= 1 || feof(fp) );
304  |       
305  |     if( strlen(buf) > 1 ) {
306  |       len = strlen(buf);
307  |       dieif( oldlen+len+1 > 65536 ); /* object too long */
308  |       memcpy( fulltext+oldlen, buf, len);
309  |       oldlen+=len;
310  |       
311  |       fulltext[oldlen]=0;
312  |     }
313  |     
314  |     if( eor ) {              /* end of object: put into the database. */
315  |       parsed++;
316  |       
317  |       /* see if it was just some whitespace junk and nothing more */
318  |       if( *fulltext==0 ) {
319  | 	continue;  /* discard */
320  |       }
321  | 
322  |       /* check if it's a radix object */
323  |       do {
324  | 	char attrname[3];
325  | 	A_Type_t attrcode;
326  | 	
327  | 	if( fulltext[0] == '*' &&  fulltext[3] == ':' ) {
328  | 	  strncpy(attrname, fulltext+1, 2);
329  | 	  attrname[2]=0;
330  | 	  
331  | 	  if(strcmp(attrname, "XX") == 0 ) {
332  | 	    /* object deleted */
333  | 	    break;
334  | 	  }
335  | 	  
336  | 	  if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
337  | 	    fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
338  | 	    break;
339  | 	  }
340  | 	  
341  | 	  if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
342  | 	    /* no interest to radix */
343  | 	    break;
344  | 	  }
345  | 	
346  | 	  /* copy and translate the range */
347  | 	  ranlen = index(fulltext+5,'\n')-fulltext-5;
348  | 	  strncpy(rangstr, fulltext+5, ranlen);
349  | 	  rangstr[ranlen]=0;
350  | 	       
351  | 	  if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,  
352  | 				    fulltext, strlen(fulltext)+1, 0L )) ) {
353  | 	    objnr++;
354  | 	  }
355  | 	  else {
356  | 	    die; /* error putting into the radix tree */
357  | 	    return err;
358  | 	  }
359  | 	  
360  | 	}
361  | 	/* CONSTCOND */
362  |       } while(0);
363  |       
364  |       *fulltext=0;
365  |       oldlen=0;
366  |     }
367  |   }
368  |   while(!feof(fp) && objnr<maxobj);  
369  | 
370  |   return RP_OK;
371  | }