Source File modules/pm/protocol_mirror.c

    1    | /***************************************
    2    |
    3    |   Protocol mirror module (pw).
    4    |
    5    |   Status: NOT REVUED, NOT TESTED
    6    |
    7    |   ******************/ /******************
    8    |   Filename            : protocol_mirror.c
    9    |   Author              : andrei
    10   |   OSs Tested          : Solaris
    11   |   ******************/ /******************
    12   |   Copyright (c) 2000                              RIPE NCC
    13   |
    14   |   All Rights Reserved
    15   |
    16   |   Permission to use, copy, modify, and distribute this software and its
    17   |   documentation for any purpose and without fee is hereby granted,
    18   |   provided that the above copyright notice appear in all copies and that
    19   |   both that copyright notice and this permission notice appear in
    20   |   supporting documentation, and that the name of the author not be
    21   |   used in advertising or publicity pertaining to distribution of the
    22   |   software without specific, written prior permission.
    23   |
    24   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    25   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    26   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    27   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    28   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    29   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    30   |   ***************************************/
    31   | #include <stdio.h>
    32   | #include <glib.h>
    33   |
    34   | #include "protocol_mirror.h"
    35   | #include "mysql_driver.h"
    36   | #include "constants.h"
    37   |
    38   | //#include "access_control.h"
    39   | #include "sk.h"
    40   | #include "stubs.h"
    41   | #include "ud.h"
    42   | #include "ta.h"
    43   |
    44   | #include "ca_configFns.h"
    45   | #include "ca_dictSyms.h"
    46   | #include "ca_macros.h"
    47   | #include "ca_srcAttribs.h"
    48   |
    49   | #include "erroutines.h"
    50   |
    51   | #define MIN_ARG_LENGTH  6
    52   | #define NRTM_DELIM "-:"
    53   | /*
    54   | * parses input and fills nrtm_q_t structure
    55   | *
    56   | * Returns:
    57   | *  -1 in case of garbage
    58   | *  0  in case of valid -g
    59   | *  1  in case of -q sources
    60   | *
    61   | */
    62   | static int parse_request(char *input, nrtm_q_t *nrtm_q)
    63   | {
    64   |  char *ptr=input;
    65   |  char *token;
    66   |  char **tokens;
    67   |  char **tokens2;
    68   |  int res=0;
    69   |
    70   | // return(-1);
    71   |
    72   |  if(strlen(input)<MIN_ARG_LENGTH) return(-1);
    73   |  g_strchug(input);
    74   |  res=strncmp(input, "-g", 2);
    75   |  if(res!=0) {
    76   | 	 /* may be this is -q source query */
    77   | 	 res=strncmp(input, "-q", 2);
    78   | 	 if(res!=0)return(-1);
    79   | 	 ptr+=2;
    80   | 	 g_strchug(ptr);
    81   | 	 res=strncmp(ptr, "sources", 7);
    82   | 	 if(res!=0)return(-1);
    83   | 	 ptr+=7;
    84   | 	 g_strchug(ptr);
    85   | 	 token=ptr;
    86   | 	 if ((*token=='\0') || (*token=='\n'))nrtm_q->source=NULL;
    87   | 	 else {
    88   | 	   ptr=index(token, ' ');
    89   | 	   if (ptr) nrtm_q->source=g_strndup(token, (ptr-token));
    90   | 	   else {
    91   | 	    ptr=index(token, 13); /* search for ctrl-M - telnet loves this */
    92   | 	     if (ptr) nrtm_q->source=g_strndup(token, (ptr-token));
    93   | 	       else {
    94   |                   ptr=index(token, '\n');
    95   | 		   if (ptr) nrtm_q->source=g_strndup(token, (ptr-token));
    96   | 	            else
    97   | 		       nrtm_q->source=g_strdup(token);
    98   | 	       }
    99   |            }
    100  | 	 }
    101  | 	 return(1);
    102  |  }
    103  |
    104  |  /* this is -q query */
    105  |  ptr+=2;
    106  |
    107  |
    108  |  g_strchug(ptr);
    109  |  g_strdelimit(ptr, NRTM_DELIM, ':');
    110  |  tokens=g_strsplit(ptr, ":", 4);
    111  |  if(tokens==NULL) return(-1);
    112  |
    113  |  if(tokens[0]) {
    114  |     /* first token is source name */
    115  |     nrtm_q->source=g_strdup(tokens[0]);
    116  |     if(tokens[1]) {
    117  |       /* second token is version number */
    118  |       nrtm_q->version=atoi(tokens[1]);
    119  |       if(tokens[2]) {
    120  | 	/* this is first serial */
    121  |         nrtm_q->first=atol(tokens[2]);
    122  | 	if (nrtm_q->first>0) {
    123  |           if(tokens[3]) {
    124  |             /* this is last serial */
    125  |               nrtm_q->last=atol(tokens[3]);
    126  | 	      if (nrtm_q->last==0)
    127  | 	       if (strncasecmp(tokens[3], "LAST", 4)!=0) res=-1;
    128  |           } else res=-1;
    129  | 	} else res=-1;
    130  |       } else res=-1;
    131  |     } else res=-1;
    132  |  } else res=-1;
    133  |  g_strfreev(tokens);
    134  |
    135  | return(res);
    136  | }
    137  |
    138  |
    139  | /* PM_interact() */
    140  | /*++++++++++++++++++++++++++++++++++++++
    141  |   Interact with the client.
    142  |
    143  |   int sock Socket that client is connected to.
    144  |
    145  |   More:
    146  |   +html+ <PRE>
    147  |   Authors:
    148  |         ottrey
    149  |         andrei
    150  |
    151  |   +html+ </PRE><DL COMPACT>
    152  |   +html+ <DT>Online References:
    153  |   +html+ <DD><UL>
    154  |   +html+ </UL></DL>
    155  |
    156  |   ++++++++++++++++++++++++++++++++++++++*/
    157  | void PM_interact(int sock) {
    158  |   char input[MAX_INPUT_SIZE];
    159  |   char buff[STR_L];
    160  |   ca_dbSource_t *source_hdl;
    161  |   int read_result;
    162  |   int parse_result;
    163  |   ip_addr_t address;
    164  |
    165  |   char *hostaddress=NULL;
    166  |   sk_conn_st condat;
    167  |   nrtm_q_t nrtm_q;
    168  |   long current_serial;
    169  |   long oldest_serial;
    170  |
    171  |   char *object;
    172  |   int operation;
    173  |
    174  |
    175  |   char *db_host;
    176  |   int  db_port;
    177  |   char *db_name;
    178  |   char *db_user;
    179  |   char *db_pswd;
    180  |
    181  |   GString *gbuff;
    182  |
    183  |   SQ_connection_t *sql_connection;
    184  |
    185  |   /* make a record for thread accounting */
    186  |   TA_add(sock, "nrtm_srv");
    187  |
    188  |
    189  |   /* Get the IP of the client */
    190  |   hostaddress = SK_getpeername(sock);
    191  |
    192  |   /* initialise the connection structure */
    193  |   memset( &condat, 0, sizeof(sk_conn_st));
    194  |   /* initialise the nrtm structure */
    195  |   memset( &nrtm_q, 0, sizeof(nrtm_q_t));
    196  |   /* set the connection data: both rIP and eIP to real IP */
    197  |   condat.sock = sock;
    198  |   condat.ip = hostaddress;
    199  |   SK_getpeerip(sock, &(condat.rIP));
    200  |   memcpy( &(condat.eIP), &(condat.rIP), sizeof(ip_addr_t));
    201  |
    202  |
    203  |   /* Read input */
    204  |   read_result = SK_cd_gets(&(condat), input, MAX_INPUT_SIZE);
    205  |
    206  |   /* read_result < 0 is an error and connection should be closed */
    207  |   if (read_result < 0 ) {
    208  |       /* log the fact, rtc was set */
    209  |   }
    210  |
    211  |
    212  |   parse_result = parse_request(input, &nrtm_q);
    213  |
    214  |
    215  |   if (parse_result < 0 ) {
    216  |       ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] -- Garbage received: %s", hostaddress, input);
    217  |       /* log the fact and exit */
    218  |       /* Free the hostaddress */
    219  |       sprintf(buff, "\n%%ERROR:1: Syntax error\n\n");
    220  |       SK_cd_puts(&condat, buff);
    221  |       SK_cd_close(&(condat));
    222  |       free(hostaddress);
    223  |       free(nrtm_q.source);
    224  |       return;
    225  |   }
    226  |
    227  |   ER_dbg_va(FAC_PM, ASP_PM_INPUT,"[%s] -- input: [%s]", hostaddress, input);
    228  |
    229  |   if (parse_result == 1 ) {
    230  |
    231  |      gbuff=PM_get_nrtm_sources(&(condat.rIP), nrtm_q.source);
    232  |      SK_cd_puts(&condat, gbuff->str);
    233  |      /* Free allocated memory  */
    234  |      g_string_free(gbuff, TRUE);
    235  |      free(hostaddress);
    236  |      free(nrtm_q.source);
    237  |      SK_cd_close(&(condat));
    238  |      return;
    239  |   }
    240  |
    241  |   ER_dbg_va(FAC_PM, ASP_PM_INPUT,"[%s] -- input parsed: %s:%d:%ld-%ld", hostaddress, nrtm_q.source, nrtm_q.version, nrtm_q.first, nrtm_q.last);
    242  |
    243  |   source_hdl = ca_get_SourceHandleByName(nrtm_q.source);
    244  |   if (source_hdl == NULL){
    245  |      ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] --  Unknown source %s", hostaddress, nrtm_q.source);
    246  |      sprintf(buff, "\n%%ERROR:4: Unknown source\n\n");
    247  |      SK_cd_puts(&condat, buff);
    248  |      free(hostaddress);
    249  |      free(nrtm_q.source);
    250  |      SK_cd_close(&(condat));
    251  |      return;
    252  |   }
    253  |
    254  |   /* check if the client is authorized to mirror */
    255  |   SK_getpeerip(sock, &address);
    256  |   if(!AA_can_mirror(&address, nrtm_q.source)){
    257  |      ER_inf_va(FAC_PM, ASP_PM_ERESP,"[%s] --  Not authorized to mirror the source %s", hostaddress, nrtm_q.source);
    258  |      sprintf(buff, "\n%%ERROR:3: You are not authorized to mirror the database\n\n");
    259  |      SK_cd_puts(&condat, buff);
    260  |      free(hostaddress);
    261  |      free(nrtm_q.source);
    262  |      SK_cd_close(&(condat));
    263  |      return;
    264  |   }
    265  |
    266  |
    267  |
    268  |   /* get database */
    269  |   db_name = ca_get_srcdbname(source_hdl);
    270  |   /* get database host*/
    271  |   db_host = ca_get_srcdbmachine(source_hdl);
    272  |   /* get database port*/
    273  |   db_port = ca_get_srcdbport(source_hdl);
    274  |   /* get database user*/
    275  |   db_user = ca_get_srcdbuser(source_hdl);
    276  |   /* get database password*/
    277  |   db_pswd = ca_get_srcdbpassword(source_hdl);
    278  |
    279  |   sql_connection = SQ_get_connection(db_host, db_port,db_name, db_user, db_pswd);
    280  |   if(!sql_connection) {
    281  |       ER_perror(FAC_PM, PM_NOSQLC," database='%s' [%d] %s",db_name, SQ_errno(sql_connection), SQ_error(sql_connection));
    282  |       return;
    283  |   }
    284  |   ER_dbg_va(FAC_PM, ASP_PM_INPUT,"[%s] --  Made SQL connection to %s@%s", hostaddress, db_name, db_host);
    285  |
    286  |   /* free copies of the variables */
    287  |   free(db_host);
    288  |   free(db_name);
    289  |   free(db_user);
    290  |   free(db_pswd);
    291  |
    292  |   current_serial=PM_get_current_serial(sql_connection);
    293  |   oldest_serial=PM_get_oldest_serial(sql_connection);
    294  |
    295  |   if((current_serial==-1) || (oldest_serial==-1)) {
    296  |       ER_perror(FAC_PM, PM_NOSERN," database='%s' [%d] %s",db_name, SQ_errno(sql_connection), SQ_error(sql_connection));
    297  |       /* Free the hostaddress */
    298  |       SK_cd_close(&(condat));
    299  |       /* close the connection to SQL server */
    300  |       SQ_close_connection(sql_connection);
    301  |       free(hostaddress);
    302  |       free(nrtm_q.source);
    303  |       return;
    304  |   }
    305  |
    306  |   /* zero indicates that LAST keyword has been used */
    307  |   if(nrtm_q.last==0)nrtm_q.last=current_serial;
    308  |
    309  |
    310  |   if((nrtm_q.first>nrtm_q.last) || (nrtm_q.first<oldest_serial) || (nrtm_q.last>current_serial) ||
    311  |      (nrtm_q.first<=0) || (nrtm_q.last<=0) )
    312  |   {
    313  |       ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] --  Invalid range: %ld-%ld", hostaddress, nrtm_q.first, nrtm_q.last);
    314  |       /* write error message back to the client */
    315  |       sprintf(buff, "\n%%ERROR:2: Invalid range: Not within %ld-%ld\n\n", oldest_serial, current_serial);
    316  |       SK_cd_puts(&condat, buff);
    317  |       SK_cd_close(&(condat));
    318  |
    319  |       /* close the connection to SQL server */
    320  |       SQ_close_connection(sql_connection);
    321  |
    322  |       /* Free the hostaddress */
    323  |       free(hostaddress);
    324  |       free(nrtm_q.source);
    325  |       return;
    326  |   }
    327  |
    328  |   current_serial=nrtm_q.first;
    329  |
    330  |   /* print banner */
    331  |   {
    332  |   /* get the header string */
    333  |   char *resp_header = ca_get_pw_resp_header;
    334  | /*  sprintf(buff, "\n%% Rights restricted by copyright. See http://www.ripe.net/ripencc/pub-services/db/copyright.html\n\n"); */
    335  |   SK_cd_puts(&condat, resp_header);
    336  |   free(resp_header);
    337  |   SK_cd_puts(&condat, "\n");
    338  |   }
    339  |
    340  |   sprintf(buff, "%%START Version: %d %s %ld-%ld\n", nrtm_q.version, nrtm_q.source, nrtm_q.first, nrtm_q.last);
    341  |   SK_cd_puts(&condat, buff);
    342  |
    343  |   /* make a record for thread accounting */
    344  |   TA_setactivity(buff);
    345  |
    346  | /* now start feeding client with data */
    347  |   do {
    348  |
    349  |     object=PM_get_serial_object(sql_connection, current_serial, &operation);
    350  |     if (operation == OP_ADD) SK_cd_puts(&condat, "\nADD\n\n");
    351  |     else SK_cd_puts(&condat, "\nDEL\n\n");
    352  |
    353  |     SK_cd_puts(&condat, object);
    354  |
    355  |     free(object);
    356  |     current_serial++;
    357  |
    358  |
    359  |   } /* do while there are more serials, connection was not reset and XXX do_server is on*/
    360  |    while((current_serial<=nrtm_q.last) && (condat.rtc == 0));
    361  |
    362  |
    363  |   sprintf(buff, "\n%%END %s\n\n", nrtm_q.source);
    364  |   SK_cd_puts(&condat, buff);
    365  |
    366  |   ER_inf_va(FAC_PM, ASP_PM_INPUT,"[%s] -- <%s:%ld-%ld (%ld)> ",
    367  |            hostaddress, nrtm_q.source, nrtm_q.first, nrtm_q.last, nrtm_q.last-nrtm_q.first+1);
    368  |
    369  |   /* make a record for thread accounting */
    370  |   TA_delete();
    371  |
    372  |   SK_cd_close(&(condat));
    373  |
    374  |   /* close the connection to SQL server */
    375  |   SQ_close_connection(sql_connection);
    376  |   /* Free the hostaddress */
    377  |   free(hostaddress);
    378  |   free(nrtm_q.source);
    379  |
    380  |
    381  |
    382  | } /* PM_interact() */