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