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