1 | /***************************************
2 | $Revision: 1.20 $
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, 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 | int 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 |
169 | dieif( vu == NULL /* loading query undefined */ );
170 |
171 | dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK );
172 |
173 | ER_inf_va(FAC_RP, ASP_RP_LOAD_DET, "loading using %s", vu);
174 | ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size before query = %x", sbrk(0));
175 |
176 | if ( SQ_execute_query(con, vu, &result) == -1 ) {
177 | fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con));
178 | die;
179 | }
180 | else {
181 | colcount = SQ_get_column_count(result);
182 |
183 | ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET,
184 | "size after query = %x; columns = %d", sbrk(0), colcount);
185 |
186 | /* LOCKED when created, so no need to acquire lock here */
187 |
188 | while ( (row = SQ_row_next(result)) != NULL
189 | && SQ_errno(con) == 0 ) {
190 |
191 | dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, space,
192 | colcount)) );
193 |
194 | if( ! NOERR(RP_pack_node_l(RX_OPER_CRE, &pack, mytree))) {
195 | fprintf(stderr,"%d:\t%ld\n", objnr, pack.key);
196 | die;
197 | }
198 |
199 | /* free allocated memory */
200 | if( pack.d.origin != NULL ) {
201 | wr_free(pack.d.origin);
202 | pack.d.origin = NULL;
203 | }
204 |
205 | objnr++;
206 |
207 | if( sizedebug ) {
208 | ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x",
209 | objnr, sbrk(0));
210 | }
211 |
212 | }
213 | /* XXX UNLOCK */
214 | TH_release_write_lock( &(mytree->rwlock) );
215 | }
216 |
217 | if( SQ_errno(con) == 0 ) {
218 | SQ_free_result(result);
219 | } else {
220 | die;
221 | }
222 |
223 | ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr,
224 | DF_get_attribute_code(attr) );
225 |
226 |
227 | return RP_OK;
228 | }
229 |
230 | er_ret_t
231 | RP_sql_load_reg(rp_regid_t reg_id)
232 | {
233 |
234 | er_ret_t err;
235 | SQ_connection_t *con;
236 | char *dbhost = ca_get_srcdbmachine(reg_id);
237 | char *dbname = ca_get_srcdbname(reg_id);
238 | char *dbuser = ca_get_srcdbuser(reg_id);
239 | char *dbpass = ca_get_srcdbpassword(reg_id);
240 | char *srcnam = ca_get_srcname(reg_id);
241 |
242 | con = SQ_get_connection( dbhost, ca_get_srcdbport(reg_id),
243 | dbname, dbuser, dbpass );
244 |
245 | dieif ( SQ_execute_query(con, "LOCK TABLES "
246 | "route READ, inetnum READ, inet6num READ, "
247 | "inaddr_arpa READ, domain READ, ip6int READ ",
248 | NULL) == -1 );
249 |
250 | do {
251 | if( !NOERR(err=RP_sql_load_attr_space( A_RT, IP_V4, reg_id, con))) {
252 | break;
253 | }
254 | if( !NOERR(err=RP_sql_load_attr_space( A_IN, IP_V4, reg_id, con))) {
255 | break;
256 | }
257 | if( !NOERR(err=RP_sql_load_attr_space( A_I6, IP_V6, reg_id, con))) {
258 | break;
259 | }
260 | if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V4, reg_id, con))) {
261 | break;
262 | }
263 | if( !NOERR(err=RP_sql_load_attr_space( A_DN, IP_V6, reg_id, con))) {
264 | break;
265 | }
266 | /* CONSTCOND */
267 | } while(0);
268 |
269 | dieif ( SQ_execute_query(con, "UNLOCK TABLES", NULL) == -1 );
270 |
271 | /* Close connection */
272 | SQ_close_connection(con);
273 |
274 | /* free junk */
275 | wr_free(dbhost);
276 | wr_free(dbname);
277 | wr_free(dbuser);
278 | wr_free(dbpass);
279 | wr_free(srcnam);
280 | return err;
281 | }
282 |
283 |
284 | /*
285 | load the tree from an ascii file (short attr names).
286 | mainly for testing...
287 | */
288 | er_ret_t
289 | RP_asc_load(char *filename, int maxobj, int operation,
290 | rp_regid_t reg_id)
291 | {
292 | er_ret_t err;
293 | FILE *fp;
294 | char buf[1024];
295 | char fulltext[65536];
296 | int objnr = 0;
297 | int len, oldlen=0;
298 | int ranlen;
299 | char rangstr[IP_RANGSTR_MAX];
300 | int parsed = 0;
301 | int eor; /* end of record */
302 |
303 |
304 | if( (fp = fopen(filename,"r")) == NULL ) {
305 | perror(filename);
306 | die;
307 | }
308 |
309 | do {
310 | fgets(buf, 128, fp);
311 |
312 | eor = ( strlen(buf) <= 1 || feof(fp) );
313 |
314 | if( strlen(buf) > 1 ) {
315 | len = strlen(buf);
316 | dieif( oldlen+len+1 > 65536 ); /* object too long */
317 | memcpy( fulltext+oldlen, buf, len);
318 | oldlen+=len;
319 |
320 | fulltext[oldlen]=0;
321 | }
322 |
323 | if( eor ) { /* end of object: put into the database. */
324 | parsed++;
325 |
326 | /* see if it was just some whitespace junk and nothing more */
327 | if( *fulltext==0 ) {
328 | continue; /* discard */
329 | }
330 |
331 | /* check if it's a radix object */
332 | do {
333 | char attrname[3];
334 | A_Type_t attrcode;
335 |
336 | if( fulltext[0] == '*' && fulltext[3] == ':' ) {
337 | strncpy(attrname, fulltext+1, 2);
338 | attrname[2]=0;
339 |
340 | if(strcmp(attrname, "XX") == 0 ) {
341 | /* object deleted */
342 | break;
343 | }
344 |
345 | if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) {
346 | fprintf(stderr,"discarding a non-object:\n%s\n", fulltext);
347 | break;
348 | }
349 |
350 | if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) {
351 | /* no interest to radix */
352 | break;
353 | }
354 |
355 | /* copy and translate the range */
356 | ranlen = index(fulltext+5,'\n')-fulltext-5;
357 | strncpy(rangstr, fulltext+5, ranlen);
358 | rangstr[ranlen]=0;
359 |
360 | if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id,
361 | fulltext, strlen(fulltext)+1, 0L )) ) {
362 | objnr++;
363 | }
364 | else {
365 | die; /* error putting into the radix tree */
366 | return err;
367 | }
368 |
369 | }
370 | /* CONSTCOND */
371 | } while(0);
372 |
373 | *fulltext=0;
374 | oldlen=0;
375 | }
376 | }
377 | while(!feof(fp) && objnr<maxobj);
378 |
379 | return RP_OK;
380 | }