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