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).  Whois protocol.
   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) 1999                              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 "socket.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   
 166 
 167   char *hostaddress=NULL;
 168 //  acl_st acl_rip,   acl_eip;
 169   
 170   sk_conn_st condat;
 171   nrtm_q_t nrtm_q;
 172   long current_serial;
 173   long oldest_serial;
 174   
 175   char *object;
 176   int operation;
 177   
 178   
 179   const char *db_host;
 180   int  db_port;
 181   const char *db_name;
 182   const char *db_user;
 183   const char *db_pswd;
 184 
 185   GString *gbuff;
 186   
 187   SQ_connection_t *sql_connection;     
 188 
 189   /* make a record for thread accounting */
 190   TA_add(sock, "nrtm_srv");
 191 
 192   
 193   /* Get the IP of the client */
 194   hostaddress = SK_getpeername(sock);
 195   fprintf(stderr,"SK address: %s\n", hostaddress);
 196   
 197   /* initialise the connection structure */
 198   memset( &condat, 0, sizeof(sk_conn_st));
 199   /* initialise the nrtm structure */
 200   memset( &nrtm_q, 0, sizeof(nrtm_q_t));
 201   /* set the connection data: both rIP and eIP to real IP */
 202   condat.sock = sock;
 203   condat.ip = hostaddress;
 204   SK_getpeerip(sock, &(condat.rIP));
 205   memcpy( &(condat.eIP), &(condat.rIP), sizeof(ip_addr_t));
 206 
 207 
 208   /* Read input */
 209   read_result = SK_cd_gets(&(condat), input, MAX_INPUT_SIZE);
 210     
 211   /* read_result < 0 is an error and connection should be closed */
 212   if (read_result < 0 ) {
 213       /* log the fact, rtc was set */
 214 //not yet, SK_... returns arb number      return; 
 215   }
 216 
 217     
 218   parse_result = parse_request(input, &nrtm_q);
 219 
 220   
 221   if (parse_result < 0 ) {
 222 /*      fprintf(stderr, "Garbage received: %s\n", input);*/
 223       ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] -- Garbage received: %s", hostaddress, input);
 224       /* log the fact and exit */
 225       /* Free the hostaddress */
 226       sprintf(buff, "\n%%ERROR:1: Syntax error\n\n");
 227       SK_cd_puts(&condat, buff);
 228       SK_cd_close(&(condat));
 229       free(hostaddress);
 230       free(nrtm_q.source);
 231       return;
 232   }
 233   
 234   ER_dbg_va(FAC_PM, ASP_PM_INPUT,"[%s] -- input: [%s]", hostaddress, input); 
 235     
 236   if (parse_result == 1 ) {
 237           
 238      fprintf(stderr, "-q sources\n"); 
 239      gbuff=PM_get_nrtm_sources(&(condat.rIP), nrtm_q.source);
 240      SK_cd_puts(&condat, gbuff->str);
 241      /* Free allocated memory  */
 242      g_string_free(gbuff, TRUE);
 243      free(hostaddress);
 244      free(nrtm_q.source);
 245      SK_cd_close(&(condat));
 246      return;
 247   }
 248  
 249   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);
 250    
 251   source_hdl = ca_get_SourceHandleByName(nrtm_q.source); 
 252   if (source_hdl == NULL){
 253  /*    fprintf(stderr, "%%ERROR:4: Unknown source %s\n", nrtm_q.source); */
 254      ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] --  Unknown source %s", hostaddress, nrtm_q.source);
 255      sprintf(buff, "\n%%ERROR:4: Unknown source\n\n");
 256      SK_cd_puts(&condat, buff);
 257      free(hostaddress);
 258      free(nrtm_q.source);
 259      SK_cd_close(&(condat));
 260      return;
 261   }
 262          
 263   /* check if the client is authorized to mirror */
 264   SK_getpeerip(sock, &address);
 265   if(!AA_can_mirror(&address, nrtm_q.source)){
 266 /*     fprintf(stderr, "%%ERROR:3: You are not authorized to mirror the database\n");*/
 267      ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] --  Not authorized to mirror the database", hostaddress);
 268      sprintf(buff, "\n%%ERROR:3: You are not authorized to mirror the database\n\n");
 269      SK_cd_puts(&condat, buff);
 270      free(hostaddress);
 271      free(nrtm_q.source);
 272      SK_cd_close(&(condat));
 273      return;
 274   }
 275 
 276       
 277     
 278   /* get database */
 279 /*  db_name=CO_get_database(); */
 280   db_name = ca_get_srcdbname(source_hdl);
 281       
 282   /* get database host*/
 283 /*  db_host=CO_get_host();*/
 284   db_host = ca_get_srcdbmachine(source_hdl);      
 285   /* get database port*/
 286 /*  db_port=CO_get_database_port();*/
 287   db_port = ca_get_srcdbport(source_hdl);        
 288   /* get database user*/
 289 /*  db_user=CO_get_user(); */
 290   db_user = ca_get_srcdbuser(source_hdl);          
 291   /* get database password*/
 292 /*  db_pswd=CO_get_password(); */
 293   db_pswd = ca_get_srcdbpassword(source_hdl);
 294   
 295 /*  fprintf(stderr, "D: Making SQL connection to %s@%s ...", db_name, db_host);*/
 296   sql_connection = SQ_get_connection(db_host, db_port,db_name, db_user, db_pswd);
 297   if(!sql_connection) {
 298 /*      fprintf(stderr, "E: ERROR: no SQL connection\n");*/
 299       ER_perror(FAC_PM, PM_NOSQLC," database='%s' [%d] %s",db_name, SQ_errno(sql_connection), SQ_error(sql_connection));
 300       return;
 301   }
 302 /*  fprintf(stderr, "OK\n"); */
 303    ER_dbg_va(FAC_PM, ASP_PM_INPUT,"[%s] --  Made SQL connection to %s@%s", hostaddress, db_name, db_host); 
 304 
 305   /* free copies of the variables */
 306   free(db_host);
 307   free(db_name);
 308   free(db_user);
 309   free(db_pswd);
 310                                                         
 311   current_serial=PM_get_current_serial(sql_connection);
 312   oldest_serial=PM_get_oldest_serial(sql_connection);
 313     
 314   if((current_serial==-1) || (oldest_serial==-1)) {
 315 /*      fprintf(stderr, "E: ERROR: cannot get serial #\n");*/
 316       ER_perror(FAC_PM, PM_NOSERN," database='%s' [%d] %s",db_name, SQ_errno(sql_connection), SQ_error(sql_connection));
 317       /* Free the hostaddress */
 318       SK_cd_close(&(condat));
 319       /* close the connection to SQL server */
 320       SQ_close_connection(sql_connection); 
 321       free(hostaddress);
 322       free(nrtm_q.source);
 323       return;
 324   }
 325   
 326   /* zero indicates that LAST keyword has been used */    
 327   if(nrtm_q.last==0)nrtm_q.last=current_serial;
 328   
 329     
 330   if((nrtm_q.first>nrtm_q.last) || (nrtm_q.first<oldest_serial) || (nrtm_q.last>current_serial) ||
 331      (nrtm_q.first<=0) || (nrtm_q.last<=0) ) 
 332   {
 333      /* if(nrtm_q.first<oldest_serial) nrtm_q.last=oldest_serial-1;
 334       if(nrtm_q.last>current_serial) nrtm_q.first=current_serial+1; */
 335 /*      fprintf(stderr, "E: ERROR: invalid range: %ld-%ld\n",  nrtm_q.first, nrtm_q.last);*/
 336       ER_dbg_va(FAC_PM, ASP_PM_ERESP,"[%s] --  Invalid range: %ld-%ld", hostaddress, nrtm_q.first, nrtm_q.last);
 337       /* write error message back to the client */
 338 /*      sprintf(buff, "%%ERROR:2: Invalid range: serial(s) %ld-%ld don't exist\n", nrtm_q.first, nrtm_q.last); */
 339       sprintf(buff, "\n%%ERROR:2: Invalid range: Not within %ld-%ld\n\n", oldest_serial, current_serial);
 340       SK_cd_puts(&condat, buff);
 341       SK_cd_close(&(condat));
 342       
 343       /* close the connection to SQL server */
 344       SQ_close_connection(sql_connection); 
 345 
 346       /* Free the hostaddress */
 347       free(hostaddress);
 348       free(nrtm_q.source);
 349       return;
 350   }
 351   
 352   current_serial=nrtm_q.first;
 353   /* print banner */
 354   
 355   sprintf(buff, "%%START Version:%d %s %ld-%ld\n", nrtm_q.version, nrtm_q.source, nrtm_q.first, nrtm_q.last);
 356   SK_cd_puts(&condat, buff);
 357 
 358   /* make a record for thread accounting */
 359   TA_setactivity(buff);
 360   
 361 /* now start feeding client with data */    
 362   do {    
 363 
 364     object=PM_get_serial_object(sql_connection, current_serial, &operation);
 365     if (operation == OP_ADD) SK_cd_puts(&condat, "\nADD\n\n");
 366     else SK_cd_puts(&condat, "\nDEL\n\n");
 367     
 368     SK_cd_puts(&condat, object);
 369       
 370     free(object);
 371     current_serial++;
 372 
 373 
 374   } /* do */
 375    while((current_serial<=nrtm_q.last) && (condat.rtc == 0));
 376 
 377   
 378   sprintf(buff, "\n%%END %s\n\n", nrtm_q.source);
 379   SK_cd_puts(&condat, buff);
 380 
 381   ER_inf_va(FAC_PM, ASP_PM_INPUT,"[%s] -- <%s:%ld-%ld (%ld)> ", 
 382            hostaddress, nrtm_q.source, nrtm_q.first, nrtm_q.last, nrtm_q.last-nrtm_q.first+1); 
 383 
 384   /* make a record for thread accounting */
 385   TA_delete();
 386 
 387   SK_cd_close(&(condat));
 388 
 389   /* close the connection to SQL server */
 390   SQ_close_connection(sql_connection); 
 391   /* Free the hostaddress */
 392   free(hostaddress);
 393   free(nrtm_q.source);
 394 
 395   
 396   
 397 } /* PM_interact() */

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