1 | /***************************************
2 | $Revision: 1.16 $
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 | }