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