modules/pm/protocol_mirror.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- parse_request
- 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() */