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