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