## 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] */