1 | /*************************************** 2 | $Revision: 1.11 $ 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 | #include "objects.h" 52 | #include "constants.h" 53 | #include "mysql_driver.h" 54 | 55 | #define RIPE_REG 17 56 | 57 | static void put_inet_sql(rx_tree_t *mytree, char *database ) { 58 | SQ_row_t *row; 59 | int retrieved_objects=0; 60 | 61 | SQ_connection_t *con; 62 | SQ_result_set_t *result; 63 | 64 | char *str=NULL; 65 | int no_cols; 66 | int i, objnr=1; 67 | int brk=0; 68 | 69 | /* Make connection */ 70 | con = SQ_get_connection(CO_get_host(), CO_get_database_port(), database, CO_get_user(), CO_get_password()); 71 | 72 | result = SQ_execute_query(con, CO_get_in_query()); 73 | 74 | if (result == NULL) { 75 | fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); 76 | } 77 | else { 78 | printf("Initializing radix tree... go get a coffee.\n"); 79 | while ( (row = SQ_row_next(result)) != NULL ) { 80 | 81 | ip_range_t myrang; 82 | rx_dataleaf_t *leafptr; 83 | int in_id; 84 | char *cpy; 85 | 86 | memset(&myrang, 0, sizeof(ip_range_t)); 87 | myrang.begin.space = myrang.end.space = IP_V4; 88 | 89 | 90 | // get the data: range and payload (id and netname) 91 | 92 | // begin of range 93 | 94 | str = SQ_get_column_string(row, 1); 95 | if (str == NULL) { 96 | die; 97 | } 98 | 99 | if( sscanf(str, "%u", &myrang.begin.words[0] ) < 1 ) { 100 | die; 101 | } 102 | free(str); 103 | 104 | // end of range 105 | 106 | str = SQ_get_column_string(row, 2); 107 | if (str == NULL) { 108 | die; 109 | } 110 | 111 | if( sscanf(str, "%u", &myrang.end.words[0] ) < 1 ) { 112 | die; 113 | } 114 | free(str); 115 | 116 | if( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) 117 | != UT_OK) { 118 | die; 119 | } 120 | 121 | // fulltext id 122 | 123 | str = SQ_get_column_string(row, 0); 124 | if (str == NULL) { 125 | die; 126 | } 127 | 128 | if( sscanf(str, "%u", &in_id ) < 1 ) { 129 | die; 130 | } 131 | free(str); 132 | 133 | leafptr->data_key = in_id; 134 | 135 | // netname - already allocated in SQ_get_column_string, 136 | // just save the pointer 137 | 138 | str = SQ_get_column_string(row, 3); 139 | if (str == NULL) { 140 | /* XXX Dont die; */ 141 | str = "NULL"; 142 | } 143 | 144 | 145 | leafptr->data_ptr = str; 146 | /* 147 | leafptr->data_len = strlen(str)+1; 148 | */ 149 | 150 | if( RX_inum_node( RX_OPER_CRE, &myrang, mytree, leafptr ) != RX_OK ) { 151 | fprintf(stderr,"%d:\t%d\t%s\n", objnr, in_id, str); 152 | die; 153 | } 154 | 155 | /* 156 | printf("%d \t %s\n", in_id, str); 157 | */ 158 | 159 | objnr++; 160 | } 161 | } 162 | SQ_free_result(result); 163 | 164 | /* Close connection */ 165 | SQ_close_connection(con); 166 | 167 | } /* put_inet_sql() */ 168 | 169 | static void put_route_sql(rx_tree_t *mytree, char *database ) { 170 | SQ_row_t *row; 171 | int retrieved_objects=0; 172 | 173 | SQ_connection_t *con; 174 | SQ_result_set_t *result; 175 | 176 | int objnr=1; 177 | int brk=0; 178 | 179 | char qry[1024]; 180 | 181 | /* Make connection */ 182 | con = SQ_get_connection(CO_get_host(), CO_get_database_port(), database, CO_get_user(), CO_get_password()); 183 | 184 | // compose the query 185 | 186 | result = SQ_execute_query(con, CO_get_rt_query()); 187 | 188 | if (result == NULL) { 189 | fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); 190 | } 191 | else { 192 | while ( (row = SQ_row_next(result)) != NULL ) { 193 | 194 | ip_prefix_t mypref; 195 | rx_dataleaf_t *leafptr; 196 | int rt_id; 197 | char *col[4]; 198 | int i; 199 | 200 | memset(&mypref, 0, sizeof(ip_prefix_t)); 201 | mypref.ip.space = IP_V4; 202 | 203 | for(i=0; i<4; i++) { 204 | col[i] = SQ_get_column_string( row, i); 205 | if (col[i] == NULL) { 206 | die; 207 | } 208 | } 209 | 210 | // get the data: prefix and payload (id and origin) 211 | 212 | // prefix ip 213 | if( sscanf(col[1], "%u", &mypref.ip.words[0] ) < 1 ) { 214 | die; 215 | } 216 | free(col[1]); 217 | 218 | // prefix length 219 | if( sscanf(col[2], "%u", &mypref.bits ) < 1 ) { 220 | die; 221 | } 222 | free(col[2]); 223 | 224 | // payload: goes into a dataleaf 225 | if( wr_calloc( (void **)& leafptr, sizeof(rx_dataleaf_t), 1) 226 | != UT_OK) { 227 | die; 228 | } 229 | 230 | // fulltext id 231 | if( sscanf(col[0], "%u", &rt_id ) < 1 ) { 232 | die; 233 | } 234 | free(col[0]); 235 | leafptr->data_key = rt_id; 236 | 237 | // origin - already allocated in SQ_get_column_string, 238 | // just save the pointer 239 | leafptr->data_ptr = col[3]; 240 | leafptr->data_len = strlen(col[3])+1; 241 | 242 | if( RX_bin_node( RX_OPER_CRE, &mypref, mytree, leafptr ) != RX_OK ) { 243 | fprintf(stderr,"%d:\t%d\t%s\n", objnr, rt_id, col[3]); 244 | die; 245 | } 246 | 247 | objnr++; 248 | } 249 | } 250 | SQ_free_result(result); 251 | 252 | /* Close connection */ 253 | SQ_close_connection(con); 254 | 255 | } /* put_route_sql() */ 256 | 257 | /* XXX void radix_init(char *database) { */ 258 | static void radix_init() { 259 | er_path_t erlogstr; 260 | rx_tree_t *mytree; 261 | 262 | if (RX_space_cre(RIPE_REG, IP_V4, RX_FAM_IN, "0.0.0.0/0", RX_MEM_RAMONLY, RX_SUB_NONE) != RX_OK) { 263 | puts("error!!!"); 264 | } 265 | else { 266 | if( RX_get_tree( &mytree, RIPE_REG, IP_V4, RX_FAM_IN) != RX_OK ) { 267 | die; 268 | } 269 | 270 | put_inet_sql(mytree, "RIPE"); 271 | 272 | if (RX_space_cre(RIPE_REG, IP_V4, RX_FAM_RT, "0.0.0.0/0", RX_MEM_RAMONLY, RX_SUB_NONE) != RX_OK) { 273 | puts("error!!!"); 274 | } 275 | else { 276 | if( RX_get_tree( &mytree, RIPE_REG, IP_V4, RX_FAM_RT) != RX_OK ) { 277 | die; 278 | } 279 | put_route_sql(mytree, "RIPE"); 280 | } 281 | } 282 | 283 | erlogstr.fdes = stderr; 284 | erlogstr.asp = 0; 285 | erlogstr.sev = ER_SEV_W; 286 | erlogstr.mode = ER_M_SEVCHAR | ER_M_TEXTLONG; 287 | 288 | ER_setpath(& erlogstr); 289 | 290 | } /* radix_init() */ 291 | 292 | 293 | /* SV_start() */ 294 | /*++++++++++++++++++++++++++++++++++++++ 295 | 296 | Start the server. 297 | 298 | More: 299 | +html+ <PRE> 300 | Authors: 301 | ottrey 302 | joao 303 | +html+ </PRE> 304 | +html+ Starts up the server. 305 | +html+ <OL> 306 | +html+ <LI> Create sockets on the necessary ports (whois, config and mirror) 307 | +html+ <LI> Start new threads for each service. 308 | +html+ </OL> 309 | +html+ <A HREF=".DBrc">.properties</A> 310 | 311 | ++++++++++++++++++++++++++++++++++++++*/ 312 | void SV_start() { 313 | int status; 314 | int whois_sock,config_sock,mirror_sock; /* 7. */ 315 | uint32_t whois_addr,sock_addr,mirror_addr; 316 | int whois_port = -1; /* 6. */ 317 | int config_port = -1; /* 6. */ 318 | int mirror_port = -1; /* 6. */ 319 | 320 | /* Initialize the radix tree before allowing any socket connections. */ 321 | radix_init(); 322 | 323 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 324 | /* Get port information for each service */ 325 | whois_port = SK_atoport(CO_get_whois_port(), "tcp"); 326 | printf("XXX whois_port=%d\n", whois_port); 327 | if(whois_port == -1) { 328 | printf("Invalid service/port: %s\n", whois_port); 329 | exit(-1); 330 | } 331 | 332 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 333 | config_port = SK_atoport(CO_get_config_port(), "tcp"); 334 | printf("XXX config_port=%d\n", config_port); 335 | if(config_port == -1) { 336 | printf("Invalid service/port: %s\n", config_port); 337 | exit(-1); 338 | } 339 | /* Commented out for now. Remove comment when enabling mirroring 340 | mirror_port = SK_atoport(CO_get_mirror_port(), "tcp"); 341 | if(mirror_port == -1) { 342 | printf("Invalid service/port: %s\n", mirror_port); 343 | exit(-1); 344 | } 345 | */ 346 | 347 | /* 6. Create a socket on the necessary ports/addresses and bind to them. */ 348 | /* whois socket */ 349 | whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY); 350 | /* Currently binds to INADDR_ANY. Will need to get specific address */ 351 | /* whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */ 352 | /* config interface socket */ 353 | config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY); 354 | /* nrt socket */ 355 | /* mirror_sock = SK_getsock(SOCK_STREAM,mirror_sock,mirror_addr); Remove comment when enabling mirroring */ 356 | 357 | /* Now.... accept() calls block until they get a connection 358 | so to listen on more than one port we need more 359 | than one thread */ 360 | 361 | /* Initialise the objects. */ 362 | OB_init(); 363 | 364 | /* Create master thread for whois threads */ 365 | TH_run(whois_sock, (void *)TH_do_whois); 366 | /* Create master thread for config threads */ 367 | TH_run(config_sock, (void *)TH_do_config); 368 | /* Create master thread for mirror threads */ 369 | /* Remove comment when enabling mirroring 370 | TH_run(mirror_sock, (void *)TH_do_mirror); 371 | */ 372 | 373 | /* XXX Is this needed? */ 374 | pthread_exit(&status); 375 | 376 | } /* SV_start() */