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 |