modules/ud/ud_main.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. get_NRTM_fd
  2. UD_do_nrtm
  3. 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 

/* [<][>][^][v][top][bottom][index][help] */