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   | 
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 nrtm_q->source=g_strdup(token);
91   | 	 }
92   | 	 return(1);
93   |  }
94   | 
95   |  /* this is -q query */
96   |  ptr+=2;
97   |  
98   |  
99   |  g_strchug(ptr);
100  |  g_strdelimit(ptr, NRTM_DELIM, ':');
101  |  tokens=g_strsplit(ptr, ":", 4);
102  |  if(tokens==NULL) return(-1);
103  |  
104  |  if(tokens[0]) {
105  |     /* first token is source name */	 
106  |     nrtm_q->source=g_strdup(tokens[0]);
107  |     if(tokens[1]) {
108  |       /* second token is version number */
109  |       nrtm_q->version=atoi(tokens[1]);
110  |       if(tokens[2]) {
111  | 	/* this is first serial */      
112  |         nrtm_q->first=atol(tokens[2]);
113  |           if(tokens[3]) {
114  |             /* this is last serial */
115  |               nrtm_q->last=atol(tokens[3]);
116  |           } else res=-1;  
117  |       } else res=-1; 
118  |     } else res=-1;  
119  |  } else res=-1;   
120  |  g_strfreev(tokens);
121  |  
122  | return(res);
123  | }
124  | 
125  | 
126  | /* PM_interact() */
127  | /*++++++++++++++++++++++++++++++++++++++
128  |   Interact with the client.
129  | 
130  |   int sock Socket that client is connected to.
131  | 
132  |   More:
133  |   +html+ <PRE>
134  |   Authors:
135  |         ottrey
136  |         andrei
137  | 
138  |   +html+ </PRE><DL COMPACT>
139  |   +html+ <DT>Online References:
140  |   +html+ <DD><UL>
141  |   +html+ </UL></DL>
142  | 
143  |   ++++++++++++++++++++++++++++++++++++++*/
144  | void PM_interact(int sock) {
145  |   char input[MAX_INPUT_SIZE];
146  |   ca_dbSource_t *source_hdl;
147  |   int read_result;
148  |   int parse_result;
149  |   ip_addr_t address;
150  | 
151  |   
152  | 
153  |   char *hostaddress=NULL;
154  | //  acl_st acl_rip,   acl_eip;
155  |   
156  |   sk_conn_st condat;
157  |   nrtm_q_t nrtm_q;
158  |   long current_serial;
159  |   long oldest_serial;
160  |   
161  |   char *object;
162  |   int operation;
163  |   char buff[STR_S];
164  |   
165  |   const char *db_host;
166  |   int  db_port;
167  |   const char *db_name;
168  |   const char *db_user;
169  |   const char *db_pswd;
170  | 
171  |   GString *gbuff;
172  |   
173  |   SQ_connection_t *sql_connection;     
174  | 
175  |   /* make a record for thread accounting */
176  |   TA_add(sock, "nrtm_srv");
177  | 
178  |   
179  |   /* Get the IP of the client */
180  |   hostaddress = SK_getpeername(sock);
181  |   printf("SK address: %s\n", hostaddress);
182  |   
183  |   /* initialise the connection structure */
184  |   memset( &condat, 0, sizeof(sk_conn_st));
185  |   /* set the connection data: both rIP and eIP to real IP */
186  |   condat.sock = sock;
187  |   condat.ip = hostaddress;
188  |   SK_getpeerip(sock, &(condat.rIP));
189  |   memcpy( &(condat.eIP), &(condat.rIP), sizeof(ip_addr_t));
190  | 
191  | 
192  |   /* Read input */
193  |   read_result = SK_cd_gets(&(condat), input, MAX_INPUT_SIZE);
194  |     
195  |   /* read_result < 0 is an error and connection should be closed */
196  |   if (read_result < 0 ) {
197  |       /* log the fact, rtc was set */
198  | //not yet, SK_... returns arb number      return; 
199  |   }
200  |     
201  |   parse_result = parse_request(input, &nrtm_q);
202  |   if (parse_result < 0 ) {
203  |       fprintf(stderr, "Garbage received: %s\n", input);
204  |       /* log the fact and exit */
205  |       /* Free the hostaddress */
206  |       SK_cd_close(&(condat));
207  |       free(hostaddress);
208  |       free(nrtm_q.source);
209  |       return;
210  |   }
211  |   if (parse_result == 1 ) {
212  | 	  
213  |      fprintf(stderr, "-q sources\n"); 
214  |      gbuff=PM_get_nrtm_sources(&(condat.rIP), nrtm_q.source);
215  |      SK_cd_puts(&condat, gbuff->str);
216  |      /* Free allocated memory  */
217  |      g_string_free(gbuff, TRUE);
218  |      free(hostaddress);
219  |      free(nrtm_q.source);
220  |      SK_cd_close(&(condat));
221  |      return;
222  |   }
223  |      
224  |   source_hdl = ca_get_SourceHandleByName(nrtm_q.source); 
225  |   if (source_hdl == NULL){
226  |      sprintf(buff, "\n%%ERROR 6: Unknown source\n\n");
227  |      SK_cd_puts(&condat, buff);
228  |      free(hostaddress);
229  |      free(nrtm_q.source);
230  |      SK_cd_close(&(condat));
231  |      return;
232  |   }
233  | 	 
234  |   /* check if the client is authorized to mirror */
235  |   SK_getpeerip(sock, &address);
236  |   if(!AA_can_mirror(&address, nrtm_q.source)){
237  |      sprintf(buff, "\n%%ERROR 5: You are not authorized to mirror the database\n\n");
238  |      SK_cd_puts(&condat, buff);
239  |      free(hostaddress);
240  |      free(nrtm_q.source);
241  |      SK_cd_close(&(condat));
242  |      return;
243  |   }
244  | 
245  |       
246  |     
247  |   /* get database */
248  | /*  db_name=CO_get_database(); */
249  |   db_name = ca_get_srcdbname(source_hdl);
250  |       
251  |   /* get database host*/
252  | /*  db_host=CO_get_host();*/
253  |   db_host = ca_get_srcdbmachine(source_hdl);      
254  |   /* get database port*/
255  | /*  db_port=CO_get_database_port();*/
256  |   db_port = ca_get_srcdbport(source_hdl);        
257  |   /* get database user*/
258  | /*  db_user=CO_get_user(); */
259  |   db_user = ca_get_srcdbuser(source_hdl);          
260  |   /* get database password*/
261  | /*  db_pswd=CO_get_password(); */
262  |   db_pswd = ca_get_srcdbpassword(source_hdl);
263  |   
264  |   fprintf(stderr, "D: Making SQL connection to %s@%s ...", db_name, db_host);
265  |   sql_connection = SQ_get_connection(db_host, db_port,db_name, db_user, db_pswd);
266  |   if(!sql_connection) {
267  |       fprintf(stderr, "E: ERROR: no SQL connection\n");
268  |       return;
269  |   }
270  |   fprintf(stderr, "OK\n");
271  | 
272  |   /* free copies of the variables */
273  |   free(db_host);
274  |   free(db_name);
275  |   free(db_user);
276  |   free(db_pswd);
277  |                                                         
278  |   current_serial=PM_get_current_serial(sql_connection);
279  |   oldest_serial=PM_get_oldest_serial(sql_connection);
280  |     
281  |   if((current_serial==-1) || (oldest_serial==-1)) {
282  |       fprintf(stderr, "E: ERROR: cannot get serial #\n");
283  |       /* Free the hostaddress */
284  |       SK_cd_close(&(condat));
285  |       free(hostaddress);
286  |       free(nrtm_q.source);
287  |       return;
288  |   }
289  |   
290  |   /* zero indicates that LAST keyword has been used */    
291  |   if(nrtm_q.last==0)nrtm_q.last=current_serial;
292  |   
293  |     
294  |   if((nrtm_q.first>nrtm_q.last) || (nrtm_q.first<oldest_serial) || (nrtm_q.last>current_serial)) {
295  |       if(nrtm_q.first<oldest_serial) nrtm_q.last=oldest_serial-1;
296  |       if(nrtm_q.last>current_serial) nrtm_q.first=current_serial+1;
297  |       fprintf(stderr, "E: ERROR: invalid range\n");
298  |       /* write error message back to the client */
299  | /*      sprintf(buff, "%%ERROR:4: Invalid range: serial(s) %ld-%ld don't exist\n", nrtm_q.first, nrtm_q.last); */
300  |       sprintf(buff, "\n%%ERROR:4: Invalid range: Not within %ld-%ld\n\n", oldest_serial, current_serial);
301  |       SK_cd_puts(&condat, buff);
302  |       SK_cd_close(&(condat));
303  | 
304  |       /* Free the hostaddress */
305  |       free(hostaddress);
306  |       free(nrtm_q.source);
307  |       return;
308  |   }
309  |   
310  |   current_serial=nrtm_q.first;
311  |   /* print banner */
312  |   
313  |   sprintf(buff, "%%START Version:%d %s %ld-%ld\n", nrtm_q.version, nrtm_q.source, nrtm_q.first, nrtm_q.last);
314  |   SK_cd_puts(&condat, buff);
315  | 
316  |   /* make a record for thread accounting */
317  |   TA_setactivity(buff);
318  |   
319  | /* now start feeding client with data */    
320  |   do {    
321  | 
322  |     object=PM_get_serial_object(sql_connection, current_serial, &operation);
323  |     if (operation == OP_ADD) SK_cd_puts(&condat, "\nADD\n\n");
324  |     else SK_cd_puts(&condat, "\nDEL\n\n");
325  |     
326  |     SK_cd_puts(&condat, object);
327  |       
328  |     free(object);
329  |     current_serial++;
330  | 
331  | 
332  |   } /* do */
333  |    while((current_serial<=nrtm_q.last) && (condat.rtc == 0));
334  | 
335  |   
336  |   sprintf(buff, "\n%%END %s\n\n", nrtm_q.source);
337  |   SK_cd_puts(&condat, buff);
338  | 
339  |   /* make a record for thread accounting */
340  |   TA_delete();
341  |   
342  |   SK_cd_close(&(condat));
343  |   /* Free the hostaddress */
344  |   free(hostaddress);
345  |   free(nrtm_q.source);
346  | 
347  |   
348  |   
349  | } /* PM_interact() */