1 | /*************************************** 2 | $Revision: 1.18 $ 3 | 4 | Example code: A server for a client to connect to. 5 | 6 | Status: NOT REVUED, NOT TESTED 7 | 8 | Authors: Chris Ottrey, Joao Damas 9 | 10 | +html+ <DL COMPACT> 11 | +html+ <DT>Online References: 12 | +html+ <DD><UL> 13 | +html+ <LI>Based on <A HREF="http://iii.ripe.net/dbase/coding/new.code/progress/ottrey/code/java/src/DBServer.java">DBServer.java</A> 14 | +html+ </UL> 15 | +html+ </DL> 16 | 17 | ******************/ /****************** 18 | Modification History: 19 | ottrey (02/03/1999) Created. 20 | ottrey (08/03/1999) Modified. 21 | joao (22/06/1999) Modified. 22 | ******************/ /****************** 23 | Copyright (c) 1999 RIPE NCC 24 | 25 | All Rights Reserved 26 | 27 | Permission to use, copy, modify, and distribute this software and its 28 | documentation for any purpose and without fee is hereby granted, 29 | provided that the above copyright notice appear in all copies and that 30 | both that copyright notice and this permission notice appear in 31 | supporting documentation, and that the name of the author not be 32 | used in advertising or publicity pertaining to distribution of the 33 | software without specific, written prior permission. 34 | 35 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL 37 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 38 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 39 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 40 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41 | ***************************************/ 42 | #include <sys/socket.h> 43 | #include <netinet/in.h> 44 | 45 | #include <sys/wait.h> 46 | #include <ctype.h> 47 | 48 | #include "thread.h" 49 | #include "rxroutines.h" 50 | #include "socket.h" 51 | /* 52 | #include "objects.h" 53 | */ 54 | #include "constants.h" 55 | #include "mysql_driver.h" 56 | #include "access_control.h" 57 | 58 | #define RIPE_REG 17 59 | 60 | static void put_inet_sql(rx_tree_t *mytree) { 61 | SQ_row_t *row; 62 | int retrieved_objects=0; 63 | 64 | SQ_connection_t *con; 65 | SQ_result_set_t *result; 66 | 67 | char *str=NULL; 68 | int no_cols; 69 | int i, objnr=1; 70 | int brk=0; 71 | 72 | /* Make connection */ 73 | con = SQ_get_connection(CO_get_host(), CO_get_database_port(), CO_get_database(), CO_get_user(), CO_get_password()); 74 | 75 | result = SQ_execute_query(SQ_STORE, con, CO_get_in_query()); 76 | 77 | if (result == NULL) { 78 | fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); 79 | } 80 | else { 81 | printf("Initializing radix tree... go get a coffee.\n"); 82 | while ( (row = SQ_row_next(result)) != NULL ) { 83 | 84 | ip_range_t myrang; 85 | rx_dataleaf_t *leafptr; 86 | int in_id; 87 | int i; 88 | char *cpy; 89 | char *col[4]; 90 | 91 | memset(&myrang, 0, sizeof(ip_range_t)); 92 | myrang.begin.space = myrang.end.space = IP_V4; 93 | 94 | for(i=0; i<4; i++) { 95 | col[i] = SQ_get_column_string(result, row, i); 96 | if (col[i] == NULL) { 97 | die; 98 | } 99 | } 100 | 101 | // get the data: range and payload (id and netname) 102 | 103 | // begin of range 104 | if( col[1] == NULL || 105 | sscanf(col[1], "%u", &myrang.begin.words[0] ) < 1 ) { 106 | die; 107 | } 108 | 109 | // end of range 110 | 111 | if( col[2] == NULL || 112 | sscanf(col[2], "%u", &myrang.end.words[0] ) < 1 ) { 113 | die; 114 | } 115 | 116 | // fulltext id 117 | if( col[0] == NULL || sscanf(col[0], "%u", &in_id ) < 1 ) { 118 | die; 119 | } 120 | 121 | // netname 122 | if (col[3] == NULL) { 123 | /* XXX Dont die; */ 124 | col[3] = "NULL"; 125 | } 126 | 127 | /*** FILL IN ****************************************************/ 128 | 129 | if( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) 130 | != UT_OK) { 131 | die; 132 | } 133 | 134 | 135 | leafptr->data_key = in_id; 136 | 137 | // prepare output string for -K (inetnum: ip - ip \n) 138 | { 139 | char prstr[IP_RANGSTR_MAX]; 140 | 141 | if( IP_rang_b2a( &myrang, prstr, IP_RANGSTR_MAX) != IP_OK ) { 142 | die; // program error. 143 | } 144 | 145 | #define PAYLOAD_INETNUM_LENGTH strlen("inetnum:\t\n") 146 | 147 | leafptr->data_len = PAYLOAD_INETNUM_LENGTH + 1 + strlen(prstr); 148 | 149 | if( wr_calloc( (void **) & leafptr->data_ptr, leafptr->data_len, 1) 150 | != UT_OK) { 151 | die; 152 | } 153 | 154 | if( snprintf(leafptr->data_ptr, leafptr->data_len, 155 | "inetnum:\t%s\n", prstr ) 156 | > leafptr->data_len ) { 157 | // program error: the buffer is too short. 158 | die; 159 | } 160 | } 161 | 162 | /* 163 | leafptr->data_ptr = col[3]; 164 | leafptr->data_len = strlen(str)+1; 165 | */ 166 | 167 | if( RX_inum_node( RX_OPER_CRE, &myrang, mytree, leafptr ) != RX_OK ) { 168 | fprintf(stderr,"%d:\t%d\t%s\n", objnr, in_id, str); 169 | die; 170 | } 171 | 172 | /* 173 | printf("%d \t %s\n", in_id, str); 174 | */ 175 | 176 | /*** FREE ****************************************************/ 177 | 178 | for(i=0;i<4;i++) { 179 | free(col[i]); 180 | } 181 | objnr++; 182 | } 183 | } 184 | SQ_free_result(result); 185 | 186 | /* Close connection */ 187 | SQ_close_connection(con); 188 | 189 | } /* put_inet_sql() */ 190 | 191 | static void put_route_sql(rx_tree_t *mytree) { 192 | SQ_row_t *row; 193 | int retrieved_objects=0; 194 | 195 | SQ_connection_t *con; 196 | SQ_result_set_t *result; 197 | 198 | int objnr=1; 199 | int brk=0; 200 | 201 | char qry[1024]; 202 | 203 | /* Make connection */ 204 | con = SQ_get_connection(CO_get_host(), CO_get_database_port(), CO_get_database(), CO_get_user(), CO_get_password()); 205 | 206 | // compose the query 207 | 208 | result = SQ_execute_query(SQ_STORE, con, CO_get_rt_query()); 209 | 210 | if (result == NULL) { 211 | fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); 212 | } 213 | else { 214 | while ( (row = SQ_row_next(result)) != NULL ) { 215 | 216 | ip_prefix_t mypref; 217 | rx_dataleaf_t *leafptr; 218 | int rt_id; 219 | char *col[4]; 220 | int i; 221 | 222 | memset(&mypref, 0, sizeof(ip_prefix_t)); 223 | mypref.ip.space = IP_V4; 224 | 225 | for(i=0; i<4; i++) { 226 | col[i] = SQ_get_column_string(result, row, i); 227 | if (col[i] == NULL) { 228 | die; 229 | } 230 | } 231 | 232 | // get the data: prefix and payload (id and origin) 233 | 234 | // prefix ip 235 | if( sscanf(col[1], "%u", &mypref.ip.words[0] ) < 1 ) { 236 | die; 237 | } 238 | 239 | // prefix length 240 | if( sscanf(col[2], "%u", &mypref.bits ) < 1 ) { 241 | die; 242 | } 243 | 244 | // fulltext id 245 | if( sscanf(col[0], "%u", &rt_id ) < 1 ) { 246 | die; 247 | } 248 | 249 | /*** FILL IN ****************************************************/ 250 | 251 | // payload: goes into a dataleaf 252 | if( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) 253 | != UT_OK) { 254 | die; 255 | } 256 | 257 | leafptr->data_key = rt_id; 258 | 259 | // prepare output string for -K (route: prefix/len\norigin:col[3]) 260 | { 261 | char prstr[IP_PREFSTR_MAX]; 262 | 263 | if( IP_pref_b2a( &mypref, prstr, IP_PREFSTR_MAX) != IP_OK ) { 264 | die; // program error. 265 | } 266 | 267 | #define PAYLOAD_ROUTE_LENGTH strlen("route:\t/\norigin:\t\n") 268 | 269 | leafptr->data_len = PAYLOAD_ROUTE_LENGTH + 1 270 | + strlen(prstr) + strlen(col[3]); 271 | 272 | 273 | if( wr_calloc( (void **) & leafptr->data_ptr, leafptr->data_len, 1) 274 | != UT_OK) { 275 | die; 276 | } 277 | 278 | if( snprintf(leafptr->data_ptr, leafptr->data_len, 279 | "route:\t%s\norigin:\t%s\n", prstr, col[3] ) 280 | > leafptr->data_len ) { 281 | // program error: the buffer is too short. 282 | die; 283 | } 284 | } 285 | 286 | 287 | if( RX_bin_node( RX_OPER_CRE, &mypref, mytree, leafptr ) != RX_OK ) { 288 | fprintf(stderr,"%d:\t%d\t%s\n", objnr, rt_id, col[3]); 289 | die; 290 | } 291 | 292 | /*** FREE ****************************************************/ 293 | 294 | for(i=0;i<4;i++) { 295 | free(col[i]); 296 | } 297 | 298 | objnr++; 299 | } 300 | } 301 | SQ_free_result(result); 302 | 303 | /* Close connection */ 304 | SQ_close_connection(con); 305 | 306 | } /* put_route_sql() */ 307 | 308 | /* XXX void radix_init(char *database) { */ 309 | static void radix_init() { 310 | er_path_t erlogstr; 311 | rx_tree_t *mytree; 312 | 313 | if (RX_tree_cre(RIPE_REG, IP_V4, RX_FAM_IN, "0.0.0.0/0", RX_MEM_RAMONLY, RX_SUB_NONE, &mytree) != RX_OK) { 314 | puts("error!!!"); 315 | } 316 | else { 317 | 318 | put_inet_sql(mytree); 319 | RX_attach2forest(mytree); 320 | 321 | if (RX_tree_cre(RIPE_REG, IP_V4, RX_FAM_RT, "0.0.0.0/0", RX_MEM_RAMONLY, RX_SUB_NONE, &mytree) != RX_OK) { 322 | puts("error!!!"); 323 | } 324 | else { 325 | 326 | put_route_sql(mytree); 327 | RX_attach2forest(mytree); 328 | } 329 | } 330 | 331 | erlogstr.fdes = stderr; 332 | /* 333 | erlogstr.asp = ASP_RX_SRCH_DET | ASP_RX_STKBLD_DET ; 334 | */ 335 | erlogstr.asp = 0; /* No debugging info. */ 336 | erlogstr.sev = ER_SEV_W; 337 | erlogstr.mode = ER_M_SEVCHAR | ER_M_TEXTLONG; 338 | 339 | ER_setpath(& erlogstr); 340 | 341 | } /* radix_init() */ 342 | 343 | 344 | /* SV_start() */ 345 | /*++++++++++++++++++++++++++++++++++++++ 346 | 347 | Start the server. 348 | 349 | More: 350 | +html+ <PRE> 351 | Authors: 352 | ottrey 353 | joao 354 | +html+ </PRE> 355 | +html+ Starts up the server. 356 | +html+ <OL> 357 | +html+ <LI> Create sockets on the necessary ports (whois, config and mirror) 358 | +html+ <LI> Start new threads for each service. 359 | +html+ </OL> 360 | +html+ <A HREF=".DBrc">.properties</A> 361 | 362 | ++++++++++++++++++++++++++++++++++++++*/ 363 | void SV_start() { 364 | int status; 365 | int whois_sock,config_sock,mirror_sock; /* 7. */ 366 | uint32_t whois_addr,sock_addr,mirror_addr; 367 | int whois_port = -1; /* 6. */ 368 | int config_port = -1; /* 6. */ 369 | int mirror_port = -1; /* 6. */ 370 | 371 | /* Initialise the attributes. */ 372 | /* 373 | AT_init(); 374 | */ 375 | 376 | /* Initialise the objects. */ 377 | /* 378 | OB_init(); 379 | */ 380 | 381 | /* Initialise the access control list. */ 382 | AC_build(); 383 | AC_acc_load(); 384 | 385 | /* Initialise the radix tree before allowing any socket connections. */ 386 | radix_init(); 387 | 388 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 389 | /* Get port information for each service */ 390 | whois_port = SK_atoport(CO_get_whois_port(), "tcp"); 391 | printf("XXX whois_port=%d\n", whois_port); 392 | printf("XXX htons(whois_port)=%d\n", htons(whois_port)); 393 | if(whois_port == -1) { 394 | printf("Invalid service/port: %s\n", whois_port); 395 | exit(-1); 396 | } 397 | 398 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 399 | config_port = SK_atoport(CO_get_config_port(), "tcp"); 400 | printf("XXX config_port=%d\n", config_port); 401 | printf("XXX htons(config_port)=%d\n", htons(config_port)); 402 | if(config_port == -1) { 403 | printf("Invalid service/port: %s\n", config_port); 404 | exit(-1); 405 | } 406 | /* Commented out for now. Remove comment when enabling mirroring 407 | mirror_port = SK_atoport(CO_get_mirror_port(), "tcp"); 408 | if(mirror_port == -1) { 409 | printf("Invalid service/port: %s\n", mirror_port); 410 | exit(-1); 411 | } 412 | */ 413 | 414 | /* 6. Create a socket on the necessary ports/addresses and bind to them. */ 415 | /* whois socket */ 416 | whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY); 417 | /* Currently binds to INADDR_ANY. Will need to get specific address */ 418 | /* whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */ 419 | /* config interface socket */ 420 | config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY); 421 | /* nrt socket */ 422 | /* mirror_sock = SK_getsock(SOCK_STREAM,mirror_sock,mirror_addr); Remove comment when enabling mirroring */ 423 | 424 | /* Now.... accept() calls block until they get a connection 425 | so to listen on more than one port we need more 426 | than one thread */ 427 | 428 | /* Create master thread for whois threads */ 429 | TH_run(whois_sock, (void *)TH_do_whois); 430 | /* Create master thread for config threads */ 431 | TH_run(config_sock, (void *)TH_do_config); 432 | /* Create master thread for mirror threads */ 433 | /* Remove comment when enabling mirroring 434 | TH_run(mirror_sock, (void *)TH_do_mirror); 435 | */ 436 | 437 | /* XXX Is this needed? */ 438 | pthread_exit(&status); 439 | 440 | } /* SV_start() */