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() */