1 | /*************************************** 2 | $Revision: 1.24 $ 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_lockw( &(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 | }