modules/pm/protocol_mirror.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. parse_request
  2. PM_interact

   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)
     /* [<][>][^][v][top][bottom][index][help] */
  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) {
     /* [<][>][^][v][top][bottom][index][help] */
 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() */

/* [<][>][^][v][top][bottom][index][help] */