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