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() */