Source File modules/sv/server.c

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