## 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] */