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