modules/ud/ud_main.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- get_NRTM_fd
- UD_do_nrtm
- UD_do_updates
1 /***************************************
2 $Revision: 1.34 $
3
4 Wrapper for NRTM client
5
6 Status: NOT REVUED, NOT TESTED
7
8 Author(s): Andrei Robachevsky
9
10 ******************/ /******************
11 Modification History:
12 andrei (17/01/2000) Created.
13 ******************/ /******************
14 Copyright (c) 2000 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 /*#include <stream.h>*/
40
41
42 #include "ud.h"
43 #include "ud_int.h"
44
45 #include "constants.h"
46
47 #include "er_macro.h"
48 #include "er_paths.h"
49
50 #include "server.h"
51 #include "protocol_mirror.h"
52 #include "ta.h"
53
54 #include "iproutines.h"
55 #include "aa.h"
56
57 /* here we store sockets for update threads */
58 /* they are from SV module */
59 extern int SV_update_sock[];
60
61 /* Response time to swtching updates on and off */
62 #define TIMEOUT 60
63
64 /* timeout between successive attempts to establish connection with server */
65 #define PM_CONNECTION_TIMEOUT 10
66
67 /* Maximum number of objects(serials) we can consume at a time */
68 #define SBUNCH 1000
69
70 /* Timeout in seconds when reading (writing) from DBupdate */
71 #define STREAM_TIMEOUT 120
72
73 /************************************************************
74 * int get_NRTM_fd() *
75 * *
76 * Gets the NRTM stream *
77 * *
78 * First tries to request the serials from the NRTM server *
79 * If the name of the server appears to be not a network name*
80 * it tries to open the file with this name *
81 * *
82 * nrtm - pointer to _nrtm structure *
83 * upto_last - if==1 then requests to download serials using *
84 * LAST keyword *
85 * *
86 * Returns: *
87 * A file descriptor for a data stream *
88 * -1 - error *
89 * *
90 ************************************************************/
91 int get_NRTM_fd(struct _nrtm *nrtm, int upto_last, char *source)
/* [<][>][^][v][top][bottom][index][help] */
92 {
93 int sockfd;
94 struct hostent *hptr;
95 struct sockaddr_in serv_addr;
96 struct in_addr *paddr;
97 char line_buff[STR_XXL];
98 int fd;
99 int ret;
100 struct hostent result;
101 int error;
102 int network;
103
104
105 /* fprintf(stderr, "Making connection to NRTM server ...\n");*/
106 if ((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1){
107 ER_perror(FAC_UD, UD_FS, "cannot create socket");
108 return(-1);
109 }
110 #ifdef __linux__
111 if(gethostbyname_r(nrtm->server, &result, line_buff, sizeof(line_buff), &hptr, &error)<0) hptr=NULL;
112 #else/* default is Solaris implementation */
113 hptr=gethostbyname_r(nrtm->server, &result, line_buff, sizeof(line_buff), &error);
114 #endif
115
116 /* Check if it is a network stream or a file */
117 if (hptr) { /* this is a network stream*/
118 paddr=(struct in_addr *)hptr->h_addr;
119 bzero(&serv_addr, sizeof(serv_addr));
120 serv_addr.sin_family=AF_INET;
121 serv_addr.sin_port=nrtm->port;
122 memcpy(&serv_addr.sin_addr, paddr, sizeof(struct in_addr));
123 /* fprintf(stderr,"Trying %s port %d\n", inet_ntoa(serv_addr.sin_addr), nrtm->port);*/
124 if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))==-1) {
125 ER_perror(FAC_UD, UD_FS, "cannot connect");
126 close(sockfd);
127 return(-1);
128 }
129 /* fprintf(stderr, "Sending Invitation\n"); */
130
131 /* Request all available serials (upto LAST), or SBUNCH of them */
132 if(upto_last==1)
133 sprintf(line_buff, "-g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1);
134 else if(upto_last==-1) /* persistent mirroring */
135 sprintf(line_buff, "-k -g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1);
136 else
137 sprintf(line_buff, "-g %s:%d:%ld-%ld\n", source, nrtm->version, nrtm->current_serial+1, nrtm->current_serial+SBUNCH);
138 ret=SK_write(sockfd, line_buff, strlen(line_buff), NULL, NULL );
139 if(ret != 1) {
140 ER_perror(FAC_UD, UD_FS, "cannot write");
141 close(sockfd);
142 return(-1);
143 }
144 fd=sockfd;
145 network=1;
146 /* fprintf(stderr, "Returning stream pointer\n"); */
147 }
148 else { /* this is a file stream*/
149 network=0;
150 close(sockfd);
151 /* fprintf(stderr, "Trying file ...\n");*/
152 if((fd=open(nrtm->server, O_RDONLY, 0666))==-1) {
153 ER_perror(FAC_UD, UD_FS, "cannot open");
154 return(-1);
155 }
156 }
157 return(fd);
158 }
159
160
161
162 /************************************************************
163 * void UD_do_nrtm() *
164 * *
165 * Processes NRTM stream *
166 * *
167 * It cycles requesting objects from the NRTM server, *
168 * processing them and then sleeping a specified amount of *
169 * time. *
170 * *
171 * It starts by requesting SBUNCH number of serials and does *
172 * so untill no serials are received (actually a warning *
173 * is received saying that the requested range is invalid) *
174 * This approach avoids excessive load on the NRTM server *
175 * *
176 * After that it requests serials using LAST keyward keeping *
177 * almost in sync with the server *
178 * *
179 ************************************************************/
180
181 void UD_do_nrtm(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
182 {
183 int source = (int)arg;
184 UD_stream_t ud_stream;
185 struct _nrtm *nrtm;
186 int nrtm_delay;
187 int do_update=1;
188 int do_server;
189 int nrtm_fd;
190 int num_ok;
191 int upto_last;
192 char ta_activity[STR_M];
193 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
194 char *db_host, *db_name, *db_user, *db_passwd;
195 int db_port;
196 /* get source we are going to mirror */
197 char *source_name = ca_get_srcname(source_hdl);
198
199 { /* set up the lohgging path */
200 int res;
201 char *er_ud_def = ca_get_er_ud_def; /* something like 'RIPUPDLOG basename' */
202 char er_def[256];
203 char *erret = NULL;
204
205 sprintf(er_def, "%s %s", er_ud_def, source_name);
206 fprintf(stderr, "[%s]\n", er_def);
207 if( (res = ER_macro_spec(er_def, &erret)) != 0 ) {
208 fputs(erret, stderr);
209 die;
210 /* or some other error handling */
211 }
212 free(erret); /* the response is allocated and must be freed */
213 free(er_ud_def);
214 }
215
216 nrtm=calloc(1, sizeof(struct _nrtm));
217 if(nrtm==NULL) {
218 ER_perror(FAC_UD, UD_MEM, "cannot allocate memory");
219 die;
220 }
221 /* get mode of operation: protected/unprotected (dummy) */
222 memset(&ud_stream, 0, sizeof(ud_stream));
223 ud_stream.source_hdl=source_hdl;
224 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
225 nrtm_delay=ca_get_srcnrtmdelay(source_hdl);
226 /* Zero delay means persistent connection */
227 if (nrtm_delay==0) ud_stream.ud_mode |= B_PERSIST_MIRR;
228
229 fprintf(stderr, "Mode of operation:\n");
230 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
231 else fprintf(stderr, "* dummy not allowed\n");
232
233 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
234 else if(IS_NRTM_CLNT(ud_stream.ud_mode)) {
235
236 if(IS_PERSIST_MIRR(ud_stream.ud_mode))fprintf(stderr, "* NRTM: persistent conection\n");
237 else fprintf(stderr, "* NRTM\n");
238 }
239 else fprintf(stderr, "* STATIC\n");
240
241 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
242 else fprintf(stderr, "* running as a server\n");
243
244 if(IS_NO_NHR(ud_stream.ud_mode))fprintf(stderr, "* NHR is not maintained\n");
245 else fprintf(stderr, "* NHR is maintained\n");
246
247
248 /* get mirror server */
249 nrtm->server=ca_get_srcnrtmhost(source_hdl);
250
251
252 /* get mirror port */
253 nrtm->port = htons(ca_get_srcnrtmport(source_hdl));
254 printf("XXX nrtm_port=%d\n", ntohs(nrtm->port));
255
256 /* get mirror version */
257 nrtm->version=ca_get_srcnrtmprotocolvers(source_hdl);
258
259
260 /* get error log facility */
261 /* logfilename=ca_get_srcnrtmlog(source_hdl); */
262
263 db_host = ca_get_srcdbmachine(source_hdl);
264 db_port = ca_get_srcdbport(source_hdl);
265 db_name = ca_get_srcdbname(source_hdl);
266 db_user = ca_get_srcdbuser(source_hdl);
267 db_passwd = ca_get_srcdbpassword(source_hdl);
268
269 /* Connect to the database */
270 ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s making SQL connection to %s@%s ...", UD_TAG, db_name, db_host);
271 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
272
273
274 if(! ud_stream.db_connection) {
275 ER_perror(FAC_UD, UD_SQL, "no connection to SQL server");
276 die;
277 }
278
279 ud_stream.num_skip=0;
280 ud_stream.load_pass=0;
281 ud_stream.nrtm=nrtm;
282
283 if(IS_PERSIST_MIRR(ud_stream.ud_mode))upto_last=-1; /* the faster the better */
284 else upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/
285
286 /*+++ main cycle +++*/
287
288 do {
289 do_update=CO_get_do_update();
290 if(do_update) {
291
292 /* Check connection to the database and try to reconnect */
293 if(SQ_ping(ud_stream.db_connection)) {
294 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connection to SQL server timed out - reistablishing", UD_TAG);
295 }
296
297 /* get current serial */
298 nrtm->current_serial=PM_get_current_serial(ud_stream.db_connection);
299
300 if(nrtm->current_serial == -1) {
301 ER_perror(FAC_UD, UD_SQL, "cannot obtain current serial: %ld", nrtm->current_serial);
302 die;
303 }
304
305 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connecting to NRTM server [%s:%d] (current serial=%ld)",
306 UD_TAG, nrtm->server, ntohs(nrtm->port), nrtm->current_serial);
307
308 /* Get file descriptor of the data stream (RPSL format, use mirror reflector to convert if needed)*/
309 nrtm_fd=get_NRTM_fd(nrtm, upto_last, source_name);
310 if (nrtm_fd==-1) {
311 ER_inf_va(FAC_UD, ASP_UD_OBJ, "%s Cannot open data stream. Trying...", UD_TAG);
312 SV_sleep(PM_CONNECTION_TIMEOUT);
313 continue;
314 }
315
316
317 /* make a record for thread accounting */
318 TA_add(nrtm_fd, "nrtm_clnt");
319 sprintf(ta_activity,"[%s]%ld->", source_name, nrtm->current_serial);
320 TA_setactivity(ta_activity);
321
322
323 ud_stream.condat.sock = nrtm_fd;
324 ud_stream.log.num_ok=0;
325 ud_stream.log.num_failed=0;
326
327
328 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s starting processing stream", UD_TAG);
329
330 /***************** process stream ****************/
331
332 num_ok=UD_process_stream(&ud_stream);
333
334 /***************** process stream ****************/
335
336 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s processing stream finished", UD_TAG);
337
338 /* close the socket of the NRTM stream */
339 close(ud_stream.condat.sock);
340
341
342
343 ER_inf_va(FAC_UD, ASP_UD_OBJ, "%s forwarded to serial:%ld", UD_TAG, (nrtm->current_serial+num_ok));
344
345 /* set activity for thread record */
346 sprintf(ta_activity,"[%s]->%ld", source_name, (nrtm->current_serial+num_ok));
347 TA_setactivity(ta_activity);
348
349 /* if we are NOT in persistent mode */
350 if(!IS_PERSIST_MIRR(ud_stream.ud_mode)) {
351 /* Now we can process serials in normal way (upto LAST)*/
352 if(num_ok==0) upto_last=1;
353 /* get delay */
354 nrtm_delay=ca_get_srcnrtmdelay(source_hdl);
355 } else
356 /* we need to delay the next attempt not to have a birst of requests */
357 nrtm_delay=TIMEOUT;
358 /* sleep the delay seconds or untill the shutdown requested */
359 SV_sleep(nrtm_delay);
360
361 } /* if do_updates */
362 else SV_sleep(TIMEOUT);
363
364
365 TA_delete();
366
367 } while((do_server=CO_get_do_server())); /* main cycle */
368
369 /* fclose(ud_stream.log.logfile);*/
370 free(source_name);
371 /* free data associated with nrtm structure */
372 if(nrtm) {
373 free(nrtm->server);
374 free(nrtm);
375 }
376
377 /* That's all. Close connection to the DB */
378 SQ_close_connection(ud_stream.db_connection);
379 free(db_host);
380 free(db_name);
381 free(db_user);
382 free(db_passwd);
383
384 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s NRTM client stopped", UD_TAG);
385 } /* UD_do_nrtm() */
386
387 /************************************************************
388 * void UD_do_updates() *
389 * *
390 * Processes updates *
391 * *
392 * It cycles accepting connections and processing them *
393 * (interactive server). This assures that there is only *
394 * one write thread per database/source. *
395 * *
396 ************************************************************/
397
398 void UD_do_updates(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
399 {
400 int source = (int)arg;
401 int listening_socket = SV_update_sock[source];
402 int connected_socket;
403 UD_stream_t ud_stream;
404 int do_update=1;
405 int num_ok;
406 ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source);
407 char *db_host, *db_name, *db_user, *db_passwd;
408 int db_port;
409 ip_addr_t address;
410 char *source_name;
411
412 source_name = ca_get_srcname(source_hdl);
413
414 { /* set up the lohgging path */
415 /* get source we are going to update */
416 int res;
417 char *er_ud_def = ca_get_er_ud_def; /* something like 'RIPUPDLOG basename' */
418 char er_def[256];
419 char *erret = NULL;
420
421
422 sprintf(er_def, "%s %s", er_ud_def, source_name);
423 if( (res = ER_macro_spec(er_def, &erret)) != 0 ) {
424 fputs(erret, stderr);
425 die;
426 /* or some other error handling */
427 }
428 free(erret); /* the response is allocated and must be freed */
429 free(er_ud_def);
430 }
431
432 /* get mode of operation: protected/unprotected (dummy) */
433 memset(&ud_stream, 0, sizeof(ud_stream));
434 ud_stream.source_hdl=source_hdl;
435 ud_stream.ud_mode=ca_get_srcmode(source_hdl);
436
437 fprintf(stderr, "Mode of operation:\n");
438 if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
439 else fprintf(stderr, "* dummy not allowed\n");
440 if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
441 else fprintf(stderr, "* NRTM\n");
442 if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
443 else fprintf(stderr, "* running as a server\n");
444
445
446 /* get the database */
447 db_host = ca_get_srcdbmachine(source_hdl);
448 db_port = ca_get_srcdbport(source_hdl);
449 db_name = ca_get_srcdbname(source_hdl);
450 db_user = ca_get_srcdbuser(source_hdl);
451 db_passwd = ca_get_srcdbpassword(source_hdl);
452
453 /* Connect to the database */
454 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s making SQL connection to %s@%s ...", UD_TAG, db_name, db_host);
455 ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
456
457 if(! ud_stream.db_connection) {
458 ER_perror(FAC_UD, UD_SQL, "no connection to SQL server\n");
459 die;
460 }
461
462
463 ud_stream.condat.rd_timeout.tv_sec=STREAM_TIMEOUT;
464 ud_stream.num_skip=0;
465 ud_stream.load_pass=0;
466 ud_stream.nrtm=NULL;
467
468 /*+++ main cycle +++*/
469
470 do { /* be alive while do_server is 1. do_server is turned off by SIGINT */
471
472 /* make a record for thread accounting */
473 TA_add(listening_socket, "update");
474 TA_setactivity("waiting");
475
476 /* accept connection */
477 connected_socket = SK_accept_connection(listening_socket);
478 if(connected_socket==-1) continue;
479
480 /* check if the client is authorised to update */
481 SK_getpeerip(connected_socket, &address);
482 if(!AA_can_ripupdate(&address, source_name)){
483 char *hostaddress;
484 sk_conn_st condat;
485 char buff[STR_L];
486
487 memset( &condat, 0, sizeof(sk_conn_st));
488 condat.wr_timeout.tv_sec=STREAM_TIMEOUT;
489 condat.sock = connected_socket;
490 SK_getpeerip(connected_socket, &(condat.rIP));
491 memcpy( &(condat.eIP), &(condat.rIP), sizeof(ip_addr_t));
492 hostaddress = SK_getpeername(connected_socket);
493 condat.ip = hostaddress;
494
495 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%s] -- Not authorized to update the source %s", hostaddress, source_name);
496 sprintf(buff, "\n%%ERROR:406: not authorized to update the database\n\n\n");
497 SK_cd_puts(&condat, buff);
498 SK_cd_close(&(condat));
499
500 free(hostaddress);
501 /* start the next loop */
502 continue;
503 }
504
505 /* make a record for thread accounting */
506 TA_delete(); /* Delete 'waiting' record */
507 TA_add(connected_socket, "update");
508
509
510 ud_stream.condat.sock = connected_socket;
511 ud_stream.condat.rtc = 0;
512
513
514 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s Connection accepted...", UD_TAG);
515
516 ud_stream.log.num_ok=0;
517 ud_stream.log.num_failed=0;
518
519
520 while((do_update=CO_get_do_update())!=1) {
521 TA_setactivity("suspended");
522 /* if shutdown was requested - break */
523 if(SV_sleep(3*TIME_SLICE)) break;
524 }
525
526 if(do_update) {
527 /* Check connection to the database and try to reconnect*/
528 if(SQ_ping(ud_stream.db_connection)) {
529 ER_perror(FAC_UD, UD_SQL, "%s", SQ_error(ud_stream.db_connection));
530 die;
531 }
532
533 ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s starting processing object", UD_TAG);
534
535 /***************** process stream ****************/
536
537 num_ok=UD_process_stream(&ud_stream);
538
539 /***************** process stream ****************/
540
541 ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s processing object finished", UD_TAG);
542
543 /* close the socket of the NRTM stream */
544 close(ud_stream.condat.sock);
545
546 } /* if do_update*/
547
548
549 TA_delete();
550
551 } while (CO_get_do_server()); /* main cycle */
552
553 /* fclose(ud_stream.log.logfile); */
554 /* That's all. Close connection to the DB */
555 SQ_close_connection(ud_stream.db_connection);
556 free(db_host);
557 free(db_name);
558 free(db_user);
559 free(db_passwd);
560 free(source_name);
561
562
563 ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s update server stopped", UD_TAG);
564 } /* UD_do_update() */
565
566
567
568