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