1    | /***************************************
2    |   $Revision: 1.12 $
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 <fcntl.h>
35   | #include <signal.h>
36   | #include "ud.h"
37   | #include "ud_int.h"
38   | #include "constants.h"
39   | #include "server.h"
40   | #include "protocol_mirror.h"
41   | 
42   | 
43   | /* Response time to swtching updates on and off */
44   | #define TIMEOUT 60 
45   | 
46   | 
47   | int get_current_serial()
48   | {
49   |  int fd;
50   |  char buff[64];
51   |  const char *filename;
52   |  
53   |  filename=CO_get_nrtm_cserialfile();
54   |  fd=open(filename, O_RDONLY, (mode_t)0);
55   |  if (fd < 0) { fprintf(stderr, "cannot open %s\n", filename); return(-1); }
56   |  read(fd, buff, sizeof(buff));
57   |  close(fd);
58   |  return(atoi(buff));
59   | }
60   | 
61   | int set_current_serial(int current_serial)
62   | {
63   | FILE *file;
64   | const char *filename;
65   | 
66   |  filename=CO_get_nrtm_cserialfile();
67   |  file=fopen(filename, "w+");
68   |  if (file==NULL) { fprintf(stderr, "cannot open %s\n", filename); return(-1); }
69   |  fprintf(file,"%d\n", current_serial);
70   |  fflush(file);
71   |  fclose(file);
72   |  return(current_serial);
73   | }
74   | 
75   | 
76   | /*************************************
77   | *
78   | *
79   | **************************************/
80   | 
81   | void UD_do_nrtm()
82   | {
83   | UD_stream_t ud_stream;
84   | struct _nrtm *nrtm;
85   | /*int dummy_allowed;*/
86   | int delay;
87   | int do_update=1;
88   | int do_server;
89   | const char *logfilename;
90   | FILE *file;
91   | int num_ok;
92   | int upto_last;
93   | int current_serial;
94   | 
95   |   nrtm=calloc(1, sizeof(struct _nrtm));
96   |   if(nrtm==NULL) {
97   | 	  printf("Cannot allocate memory\n");
98   | 	  die;
99   |   }	  
100  | /* get mode of operation: protected/unprotected (dummy) */
101  |   ud_stream.ud_mode=CO_get_update_mode();
102  | 
103  |   fprintf(stderr, "Mode of operation:\n");
104  |   if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n"); 
105  |    else fprintf(stderr, "* dummy not allowed\n");
106  |   if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
107  |    else fprintf(stderr, "* NRTM\n");
108  |   if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
109  |    else fprintf(stderr, "* running as a server\n");
110  |   
111  | /* get mirror server */
112  |   nrtm->server=CO_get_nrtm_host();
113  |   
114  | /* get mirror port */
115  |   nrtm->port = SK_atoport(CO_get_nrtm_port(), "tcp");
116  |   printf("XXX nrtm_port=%d\n", nrtm->port);
117  |   if(nrtm->port == -1) {
118  |     printf("Invalid service/port: %d\n", nrtm->port);
119  |     return;
120  |   }
121  |               
122  | /* get mirror version */
123  |   nrtm->version=CO_get_nrtm_version();
124  |   
125  | /* get error log facility */
126  |   logfilename=CO_get_nrtm_logfile();
127  |       
128  | /* Connect to the database */
129  |   fprintf(stderr, "D: Making SQL connection to %s@%s ...", CO_get_database(), CO_get_host());
130  | 
131  |   ud_stream.db_connection=SQ_get_connection2();
132  |    
133  |   if(! ud_stream.db_connection) {
134  |    fprintf(stderr, "D: ERROR: no SQL connection\n");
135  |     return;
136  |   }
137  |   	
138  |   fprintf(stderr, "OK\n");
139  | 
140  |       
141  |   
142  | /*  ud_stream.dummy_allowed=dummy_allowed;*/
143  |   ud_stream.num_skip=0;
144  |   ud_stream.load_pass=0;
145  |   ud_stream.nrtm=nrtm;
146  |   
147  |   upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/
148  | 
149  | /*+++ main cycle +++*/
150  | 
151  |  do {
152  |   do_update=CO_get_do_update();
153  |   if(do_update) {
154  |  
155  | 
156  |   /* get current serial */
157  |    current_serial=get_current_serial();
158  |    nrtm->current_serial=PM_get_current_serial(ud_stream.db_connection);
159  |    
160  |    if(nrtm->current_serial == -1) {
161  |      printf("Error obtaining current serial: %ld(%d)\n", nrtm->current_serial, current_serial);
162  |      return;
163  |    }
164  | 
165  |    fprintf(stderr, "current_serial:\t%ld(%d)\n", nrtm->current_serial, current_serial);
166  |    fprintf(stderr, "conecting to server...\n");
167  |       
168  |    
169  |     file = get_NRTM_stream(nrtm, upto_last);
170  |     fprintf(stderr, "OK\n");
171  |     printf("OK\n");
172  | 
173  | 
174  |     if (file==NULL) { 
175  |      fprintf(stderr, "Cannot open data stream. Trying...\n");
176  |      sleep(100);
177  |      continue;
178  |     }  
179  | 
180  | 
181  |    ud_stream.stream=file;
182  |    ud_stream.log.logfile = fopen(logfilename, "a+");
183  |    ud_stream.log.num_ok=0; 
184  |    ud_stream.log.num_failed=0;
185  |   
186  | 
187  |    fprintf(stderr, "starting processing stream\n");
188  | 
189  |    num_ok=UD_process_stream(&ud_stream);
190  |   
191  |   
192  |      /*Check for errors */
193  |    if(num_ok<0) {
194  | 	 fprintf(stderr, "processing stream failed\n");
195  | 	 do_server=0;
196  | 	 break;    
197  |    }	   
198  |    else fprintf(stderr, "processing stream finished\n"); 
199  |    
200  |   /* Now we can process serials in normal way (upto LAST)*/ 
201  |    if(num_ok==0) upto_last=1;
202  | 
203  | /* This is for test purposes, just to know if we are out of sync */
204  |    set_current_serial((int)(current_serial+num_ok));
205  |    fprintf(ud_stream.log.logfile, "forwarded to serial:\t%ld(%d)\n", (nrtm->current_serial+num_ok), current_serial+num_ok);
206  |    fclose(ud_stream.log.logfile);
207  |    fprintf(stderr, "forwarded to serial:\t%ld(%d)\n", (nrtm->current_serial+num_ok), current_serial+num_ok);
208  |    printf("Objects received: %d\n-----------\n", num_ok);
209  | 
210  |   /* get delay */
211  |    delay=CO_get_nrtm_delay();
212  |    SV_sleep(LOCK_SHTDOWN, delay);
213  |   }
214  |  else SV_sleep(LOCK_SHTDOWN, TIMEOUT); 
215  | 
216  |   do_server=CO_get_do_server();
217  |   
218  |  } while(do_server);  /* main cycle */
219  |    
220  |  if(nrtm) free(nrtm);
221  |  /* That's all. Close connection to the DB */ 
222  |  SQ_close_connection(ud_stream.db_connection);
223  |  fprintf(stderr, "NRTM stopped\n");  
224  | 
225  | } /* UD_do_nrtm() */
226  | 
227  | 
228  | 
229  | 
230  | /*************************************
231  | *
232  | *
233  | **************************************/
234  |   
235  | void UD_do_updates(void *arg)
236  | {
237  | int listening_socket = (int)arg;
238  | int connected_socket;
239  | UD_stream_t ud_stream;
240  | int do_update=1;
241  | int do_server;
242  | const char *logfilename;
243  | FILE *file, *file_ack;
244  | int num_ok;
245  | 
246  | 
247  | /* get mode of operation: protected/unprotected (dummy) */
248  |   ud_stream.ud_mode=CO_get_update_mode();
249  | 
250  |   fprintf(stderr, "Mode of operation:\n");
251  |   if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n"); 
252  |    else fprintf(stderr, "* dummy not allowed\n");
253  |   if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
254  |    else fprintf(stderr, "* NRTM\n");
255  |   if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
256  |    else fprintf(stderr, "* running as a server\n");
257  | 
258  |   
259  | 
260  | 
261  | /* get error log facility */
262  |   logfilename=CO_get_nrtm_logfile();
263  | 
264  | /* Connect to the database */
265  |   fprintf(stderr, "D: Making SQL connection to %s@%s ...", CO_get_database(), CO_get_host());
266  | 
267  |   ud_stream.db_connection=SQ_get_connection2();
268  |    
269  |   if(! ud_stream.db_connection) {
270  |    fprintf(stderr, "D: ERROR: no SQL connection\n");
271  |     return;
272  |   }
273  |   	
274  |   fprintf(stderr, "OK\n");
275  | 
276  |   ud_stream.num_skip=0;
277  |   ud_stream.load_pass=0;
278  |   ud_stream.nrtm=NULL;
279  |   
280  | /*+++ main cycle +++*/
281  | 
282  | do { /* be alive while do_server is 1. do_server is turned off by SIGINT */
283  |  
284  | /* accept connection */
285  |    connected_socket = SK_accept_connection(listening_socket);
286  |    if(connected_socket==-1) break;
287  |    
288  |    file=fdopen(connected_socket, "r");
289  |    file_ack=fdopen(connected_socket, "w");
290  | 
291  |  do_update=CO_get_do_update();
292  |  if(do_update) {
293  |  
294  |    fprintf(stderr, "Connection accepted...\n");
295  |    
296  |   if ((file==NULL) || (file_ack==NULL)) {
297  |     fprintf(stderr, "Cannot open data stream. Closing connction\n");
298  |     return; 
299  |   }
300  |   fprintf(stderr, "Connection accepted...\n");
301  | 
302  |   ud_stream.stream=file;
303  |   ud_stream.log.logfile = fopen(logfilename, "a+");
304  |   ud_stream.log.num_ok=0; 
305  |   ud_stream.log.num_failed=0;
306  |   
307  | 
308  |   fprintf(stderr, "starting processing object\n");
309  | 
310  |   num_ok=UD_process_stream(&ud_stream);
311  |   
312  |   fprintf(stderr, "processing object finished\n");  
313  | 
314  |   if(num_ok==1) {
315  |    fprintf(file_ack, "%%ERROR 0\n");
316  |    fprintf(stderr, "%%ERROR 0\n");
317  |   } 
318  |    else {
319  |       num_ok=(-1)*num_ok;
320  |       fprintf(file_ack, "%%ERROR %d\n",num_ok);
321  |       fprintf(stderr, "%%ERROR %d\n",num_ok);
322  |       fprintf(file_ack, "Transaction had the following problems:\n");
323  |       if(num_ok & ERROR_U_MEM) fprintf(file_ack, "Memory allocation error\n");
324  | /*      if(num_ok & ERROR_U_DBS) fprintf(file_ack, "Database (SQL) error\n");*/
325  | /*      if(num_ok & ERROR_U_OBJ) fprintf(file_ack, "Object (RF) error\n");*/
326  | /*      if(num_ok & ERROR_U_AUT) fprintf(file_ack, "Object authentication error\n");*/
327  |       if(num_ok & ERROR_U_BADOP) fprintf(file_ack, "Bad operation\n");
328  |       if(num_ok & ERROR_U_COP) fprintf(file_ack, "Conflicting operation\n");
329  |       if(num_ok & ERROR_U_NSUP) fprintf(file_ack, "Object of this type is not supported\n");
330  |       if(num_ok & ERROR_U_BUG) fprintf(file_ack, "Software bug - report to <ripe-dbm@ripe.net>\n");
331  |    }
332  |    if(ud_stream.error_script)fprintf(file_ack, "%s\n", ud_stream.error_script);
333  |    
334  |    if(ud_stream.error_script) free(ud_stream.error_script);
335  |    fclose(file_ack);   
336  |    fclose(file);
337  |    fclose(ud_stream.log.logfile);
338  |  
339  |  }  /* if do_update*/
340  | else { /* Otherwise print a message*/
341  |  fprintf(file_ack, "%%ERROR 1000\n%%Updates are suspended\n");
342  |  fclose(file_ack);
343  |  fclose(file);
344  | }
345  |   
346  |   do_server=CO_get_do_server();  
347  | 
348  | } while (do_server);  /* main cycle */
349  | 
350  |  /* That's all. Close connection to the DB */ 
351  |  SQ_close_connection(ud_stream.db_connection);
352  | 
353  |  fprintf(stderr, "server stopped\n");  
354  | 
355  | } /* UD_do_update() */
356  | 
357  | 
358  | 
359  |