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 | }