1 | /*************************************** 2 | $Revision: 1.15 $ 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, int colcount) 45 | { 46 | er_ret_t conv = RP_OK; 47 | rp_uni_t *uniptr = &(pack->uni); 48 | char *idptr; /* initially set to the 0'th column */ 49 | char *col[4]; 50 | int i; 51 | 52 | dieif(colcount>4); /* size of the col array */ 53 | 54 | for(i=0; i<colcount; i++) { 55 | col[i] = SQ_get_column_string_nocopy(result, row, i); 56 | if (col[i] == NULL) { 57 | die; 58 | } 59 | } 60 | 61 | idptr = col[0]; 62 | 63 | pack->type = attr; 64 | pack->d.origin = NULL; 65 | switch( attr ) { 66 | case A_IN: 67 | /* 68 | read 0-2 from inetnum 69 | 0 - objectid 70 | 1 - begin 71 | 2 - end 72 | */ 73 | uniptr->space = IP_V4; 74 | conv = IP_rang_f2b_v4( &(uniptr->u.in), col[1], col[2] ); 75 | break; 76 | case A_RT: 77 | /* 78 | read 0-3 from route 79 | 0 - objectid 80 | 1 - prefix 81 | 2 - prefix_length 82 | 3 - origin 83 | */ 84 | uniptr->space = IP_V4; 85 | if( NOERR(conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] ))) { 86 | dieif(wr_malloc( (void **) &(pack->d.origin), strlen(col[3])+1) 87 | != UT_OK); 88 | 89 | strcpy(pack->d.origin, col[3]); 90 | } 91 | break; 92 | case A_DN: 93 | /* 94 | read 0-3 from inaddr 95 | 0 - objectid 96 | 1 - prefix 97 | 2 - prefix_length 98 | 3 - domain 99 | */ 100 | conv = IP_pref_f2b_v4( &(uniptr->u.rt), col[1], col[2] ); 101 | uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) ); 102 | dieif(wr_malloc( (void **) &(pack->d.domain), strlen(col[3])+1) 103 | != UT_OK); 104 | 105 | strcpy(pack->d.domain, col[3]); 106 | break; 107 | case A_I6: 108 | /* 109 | read 0-3 from inaddr 110 | 0 - objectid 111 | 1 - msb 112 | 2 - lsb 113 | 3 - prefix_length 114 | */ 115 | conv = IP_pref_f2b_v6( &(uniptr->u.rt), col[1], col[2], col[3]); 116 | uniptr->space = IP_pref_b2_space( &(uniptr->u.rt) ); 117 | break; 118 | default: 119 | /* die; / * shouldn't have got here */ 120 | conv = IP_INVARG; 121 | } 122 | 123 | if( sscanf(idptr, "%lu", &(pack->key) ) < 1 ) { 124 | conv = IP_INVARG; 125 | } 126 | 127 | 128 | for(i=0; i<colcount; i++) { 129 | /* wr_free(col[i]);*/ ; 130 | } 131 | 132 | return conv; 133 | } 134 | 135 | er_ret_t 136 | RP_sql_load_attr_space( int maxobj, int operation, 137 | char *qry, 138 | rp_attr_t attr, ip_space_t space, 139 | rp_regid_t reg_id, SQ_connection_t *con 140 | ) 141 | { 142 | SQ_row_t *row; 143 | SQ_result_set_t *result; 144 | int objnr=0; 145 | rx_tree_t *mytree; 146 | rp_upd_pack_t pack; 147 | int colcount; 148 | int sizedebug = ER_is_traced(FAC_RP, ASP_RP_LOAD_DET); 149 | 150 | dieif( RP_tree_get ( &mytree, reg_id, space, attr ) != RP_OK ); 151 | 152 | 153 | ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loading %s", qry); 154 | 155 | ER_dbg_va(FAC_RP, ASP_RP_LOAD_GEN, "size before query = %x", sbrk(0)); 156 | 157 | if ( SQ_execute_query(con, qry, &result) == -1 ) { 158 | fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); 159 | die; 160 | } 161 | else { 162 | colcount = SQ_get_column_count(result); 163 | 164 | ER_dbg_va(FAC_RP, ASP_RP_LOAD_GEN, 165 | "size after query = %x; columns = %d", sbrk(0), colcount); 166 | 167 | /* XXX LOCKED when created */ 168 | /*TH_acquire_write_lock( &(mytree->rwlock) );*/ 169 | 170 | while ( (row = SQ_row_next(result)) != NULL 171 | && SQ_errno(con) == 0 172 | && objnr<=maxobj) { 173 | 174 | dieif( ! NOERR(make_sql2pack(result, row, &pack, attr, colcount)) ); 175 | 176 | if( ! NOERR(RP_pack_node_l(operation, &pack, mytree))) { 177 | fprintf(stderr,"%d:\t%ld\n", objnr, pack.key); 178 | die; 179 | } 180 | 181 | /* free allocated memory */ 182 | if( pack.d.origin != NULL ) { 183 | wr_free(pack.d.origin); 184 | pack.d.origin == NULL; 185 | } 186 | 187 | 188 | 189 | objnr++; 190 | 191 | if( sizedebug ) { 192 | ER_dbg_va(FAC_RP, ASP_RP_LOAD_DET, "size after object %d = %x", 193 | objnr, sbrk(0)); 194 | } 195 | 196 | } 197 | /* XXX UNLOCK */ 198 | TH_release_write_lock( &(mytree->rwlock) ); 199 | } 200 | 201 | if( SQ_errno(con) == 0 ) { 202 | SQ_free_result(result); 203 | } else { 204 | die; 205 | } 206 | 207 | ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN, "loaded %d objects into %s", objnr, 208 | DF_get_attribute_code(attr) ); 209 | 210 | 211 | return RP_OK; 212 | } 213 | 214 | er_ret_t 215 | RP_sql_load_reg(rp_regid_t reg_id) 216 | { 217 | unsigned maxline = 999999999; 218 | er_ret_t err; 219 | SQ_connection_t *con; 220 | char *dbhost = ca_get_srcdbmachine(reg_id); 221 | char *dbname = ca_get_srcdbname(reg_id); 222 | char *dbuser = ca_get_srcdbuser(reg_id); 223 | char *dbpass = ca_get_srcdbpassword(reg_id); 224 | char *srcnam = ca_get_srcname(reg_id); 225 | 226 | 227 | /* Make connection */ 228 | /* 229 | con = SQ_get_connection(HOST, DATABASE_PORT, DATABASE, USER, PASSWD); 230 | */ 231 | 232 | 233 | con = SQ_get_connection( dbhost, ca_get_srcdbport(reg_id), 234 | dbname, dbuser, dbpass ); 235 | #if 0 236 | con = SQ_get_connection(CO_get_host(), 237 | CO_get_database_port(), 238 | CO_get_database(), /* XXX for this regid */ 239 | CO_get_user(), 240 | CO_get_password()); 241 | #endif 242 | 243 | dieif ( SQ_execute_query(con, "LOCK TABLES " 244 | "route READ, inetnum READ, inet6num READ, inaddr_arpa READ, domain READ ", 245 | NULL) == -1 ); 246 | 247 | do { 248 | 249 | if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 250 | "SELECT object_id,prefix,prefix_length,origin FROM route ", 251 | A_RT, IP_V4, reg_id, con))) { 252 | break; 253 | } 254 | 255 | #if 0 256 | { 257 | er_path_t erlogstr; 258 | 259 | erlogstr.fdes = stderr; 260 | erlogstr.asp = 0xffff0000; 261 | erlogstr.fac = FAC_RP; /* FAC_QI; */ 262 | erlogstr.sev = ER_SEV_I; 263 | erlogstr.mode = ER_M_SEVCHAR | ER_M_FACSYMB | ER_M_TEXTLONG; 264 | 265 | ER_setpath(& erlogstr); 266 | 267 | wr_log_set(0); 268 | } 269 | #endif 270 | 271 | if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 272 | "SELECT object_id,begin_in,end_in FROM inetnum ", 273 | A_IN, IP_V4, reg_id, con))) { 274 | break; 275 | } 276 | if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 277 | 278 | "SELECT object_id,i6_msb,i6_lsb,prefix_length FROM inet6num", 279 | 280 | A_I6, IP_V6, reg_id, con))) { 281 | break; 282 | } 283 | if( !NOERR(err=RP_sql_load_attr_space(maxline, RX_OPER_CRE, 284 | 285 | "SELECT domain.object_id,prefix,prefix_length,domain FROM inaddr_arpa,domain WHERE domain.object_id = inaddr_arpa.object_id", 286 | 287 | A_DN, IP_V4, reg_id, con))) { 288 | break; 289 | } 290 | 291 | /* CONSTCOND */ 292 | }while(0); 293 | 294 | dieif ( SQ_execute_query(con, "UNLOCK TABLES ", NULL) == -1 ); 295 | 296 | /* Close connection */ 297 | SQ_close_connection(con); 298 | 299 | /* free junk */ 300 | wr_free(dbhost); 301 | wr_free(dbname); 302 | wr_free(dbuser); 303 | wr_free(dbpass); 304 | wr_free(srcnam); 305 | return err; 306 | } 307 | 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 | int len, oldlen=0; 319 | int ranlen; 320 | char rangstr[IP_RANGSTR_MAX]; 321 | int parsed = 0; 322 | int eor; /* end of record */ 323 | 324 | 325 | if( (fp = fopen(filename,"r")) == NULL ) { 326 | perror(filename); 327 | die; 328 | } 329 | 330 | do { 331 | fgets(buf, 128, fp); 332 | 333 | eor = ( strlen(buf) <= 1 || feof(fp) ); 334 | 335 | if( strlen(buf) > 1 ) { 336 | len = strlen(buf); 337 | dieif( oldlen+len+1 > 65536 ); /* object too long */ 338 | memcpy( fulltext+oldlen, buf, len); 339 | oldlen+=len; 340 | 341 | fulltext[oldlen]=0; 342 | } 343 | 344 | if( eor ) { /* end of object: put into the database. */ 345 | parsed++; 346 | 347 | /* see if it was just some whitespace junk and nothing more */ 348 | if( *fulltext==0 ) { 349 | continue; /* discard */ 350 | } 351 | 352 | /* check if it's a radix object */ 353 | do { 354 | char attrname[3]; 355 | A_Type_t attrcode; 356 | 357 | if( fulltext[0] == '*' && fulltext[3] == ':' ) { 358 | strncpy(attrname, fulltext+1, 2); 359 | attrname[2]=0; 360 | 361 | if(strcmp(attrname, "XX") == 0 ) { 362 | /* object deleted */ 363 | break; 364 | } 365 | 366 | if( (attrcode = DF_attribute_code2type( attrname )) == -1 ) { 367 | fprintf(stderr,"discarding a non-object:\n%s\n", fulltext); 368 | break; 369 | } 370 | 371 | if( DF_attrcode_has_radix_lookup(attrcode) == 0 ) { 372 | /* no interest to radix */ 373 | break; 374 | } 375 | 376 | /* copy and translate the range */ 377 | ranlen = index(fulltext+5,'\n')-fulltext-5; 378 | strncpy(rangstr, fulltext+5, ranlen); 379 | rangstr[ranlen]=0; 380 | 381 | if( NOERR(err=RP_asc_node(operation, rangstr, attrcode, reg_id, 382 | fulltext, strlen(fulltext)+1, 0L )) ) { 383 | objnr++; 384 | } 385 | else { 386 | die; /* error putting into the radix tree */ 387 | return err; 388 | } 389 | 390 | } 391 | /* CONSTCOND */ 392 | } while(0); 393 | 394 | *fulltext=0; 395 | oldlen=0; 396 | } 397 | } 398 | while(!feof(fp) && objnr<maxobj); 399 | 400 | return RP_OK; 401 | }