Source File pm/pm_serials.c

    1    | /***************************************
    2    |   $Revision: 1.16 $
    3    |
    4    |   Near real-time mirror server module (pm).  NRTM  protocol.
    5    |
    6    |   Status: NOT REVUED, NOT TESTED
    7    |
    8    |   +html+ <DL COMPACT>
    9    |   +html+ <DT>Online References:
    10   |   +html+ <DD><UL>
    11   |   +html+ </UL>
    12   |   +html+ </DL>
    13   |   +html+ <PRE>
    14   |   Author:
    15   |       andrei
    16   |   +html+ </PRE>
    17   |
    18   |   ******************/ /******************
    19   |   Copyright (c) 2000,2001,2002                    RIPE NCC
    20   |
    21   |   All Rights Reserved
    22   |
    23   |   Permission to use, copy, modify, and distribute this software and its
    24   |   documentation for any purpose and without fee is hereby granted,
    25   |   provided that the above copyright notice appear in all copies and that
    26   |   both that copyright notice and this permission notice appear in
    27   |   supporting documentation, and that the name of the author not be
    28   |   used in advertising or publicity pertaining to distribution of the
    29   |   software without specific, written prior permission.
    30   |
    31   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    32   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    33   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    34   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    35   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    36   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    37   |   ***************************************/
    38   |
    39   | #include "rip.h"
    40   |
    41   | #include <stdio.h>
    42   |
    43   | void pm_get_source_info(GString *gbuff, ip_addr_t *client_address, char *source, ca_dbSource_t *source_hdl);
    44   |
    45   | /************************************************************
    46   | * PM_get_minmax_serial()                                    *
    47   | *                                                           *
    48   | * Returns the min or max serial number.                     *
    49   | *                                                           *
    50   | * Returns:                                                  *
    51   | *  min (max=0) or max (max=1) serial number                 *
    52   | *  -1 in case of an error                                   *
    53   | *                                                           *
    54   | * Note:                                                     *
    55   | *  min serial= MIN(serial_id)+1                             *
    56   | *  MIN(serial_id) represents legacy RIPE.CURRENSERIAL       *
    57   | *  of the snapshot                                          *
    58   | *                                                           *
    59   | *************************************************************/
    60   | long PM_get_minmax_serial(SQ_connection_t *sql_connection, int max)
    61   | {
    62   | char query[STR_M];
    63   | SQ_result_set_t *sql_result;
    64   | SQ_row_t *sql_row;
    65   | char *sql_str;
    66   | long current_serial;
    67   | char *minmax;
    68   | int sql_err;
    69   |
    70   | if(max==1)minmax="max"; else minmax="min";
    71   |
    72   |     /* get the lock to ensure that queries are not stopped */
    73   |     /* which means access to the database is allowed */
    74   |     PW_record_query_start();
    75   |
    76   |  sprintf(query, "SELECT %s(serial_id) FROM serials ", minmax);
    77   |
    78   | //fprintf(stderr, "D:<get_field_str>:query: %s\n", query);
    79   |  sql_err = SQ_execute_query(sql_connection, query, &sql_result);
    80   |
    81   |  if(sql_err) {
    82   |     ER_perror(FAC_PM, PM_NOSQLC,"%s[%s]", SQ_error(sql_connection), query);
    83   |     die;
    84   |  }
    85   |
    86   |
    87   |  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
    88   | 	sql_str = SQ_get_column_string(sql_result, sql_row, 0);
    89   |
    90   |      /* We must process all the rows of the result,*/
    91   |      /* otherwise we'll have them as part of the next qry */
    92   | 	while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
    93   | 	  ER_perror(FAC_PM, PM_NOSQLC,"duplicate PK [%s]", query);
    94   | 	  if(sql_str) UT_free(sql_str); sql_str=NULL;
    95   | 	}
    96   |  }
    97   |  else sql_str=NULL;
    98   |
    99   |  if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
    100  |
    101  |  if(sql_str) {
    102  |   current_serial = atol(sql_str);
    103  |   if(max!=1)current_serial++;
    104  |   UT_free(sql_str);
    105  |  }
    106  |  else current_serial=-1;
    107  |
    108  |     /* release the lock */
    109  |     PW_record_query_end();
    110  |
    111  |
    112  |  return(current_serial);
    113  |
    114  | }
    115  |
    116  | /************************************************************
    117  | * int atlast(long serial_number)
    118  | * -1 - sql error
    119  | *
    120  | ***********************************************************/
    121  |
    122  | static int atlast(SQ_connection_t *sql_connection, long serial_number)
    123  | {
    124  | char *sql_str;
    125  | char str_id[STR_S];
    126  | int atlast=-1;
    127  |
    128  |   sprintf(str_id, "%ld", serial_number);
    129  |   sql_str= get_field_str(sql_connection, "atlast", "serials", "serial_id", str_id, NULL);
    130  |   if(sql_str) {
    131  |        	  atlast = atoi(sql_str);
    132  |        	  UT_free(sql_str);
    133  |   }
    134  |
    135  |   return(atlast);
    136  |
    137  | }
    138  |
    139  |
    140  | /************************************************************
    141  | * int getop(long serial_number)
    142  | * -1 - sql error
    143  | *
    144  | * **********************************************************/
    145  |
    146  | static int getop(SQ_connection_t *sql_connection, long serial_number)
    147  | {
    148  | char *sql_str;
    149  | char str_id[STR_S];
    150  | int op=-1;
    151  |
    152  |   sprintf(str_id, "%ld", serial_number);
    153  |   sql_str= get_field_str(sql_connection, "operation", "serials", "serial_id", str_id, NULL);
    154  |   if(sql_str) {
    155  |        	  op = atoi(sql_str);
    156  |        	  UT_free(sql_str);
    157  |   }
    158  |
    159  |   return(op);
    160  |
    161  | }
    162  |
    163  |
    164  | /************************************************************
    165  | * char *PM_get_serial_object()                                 *
    166  | *                                                           *
    167  | * Returns text block corresponding to the requested serial  *
    168  | *                                                           *
    169  | * Returns:                                                  *
    170  | *  operation (ADD/DEL) and text object                      *
    171  | *  NULL in case of an error                                 *
    172  | *                                                           *
    173  | * Note:                                                     *
    174  | *  returned string should be freed by the caller            *
    175  | *                                                           *
    176  | *************************************************************/
    177  | char *PM_get_serial_object(SQ_connection_t *sql_connection, long serial_number, int *operation)
    178  | {
    179  | char *table;
    180  | SQ_result_set_t * sql_result;
    181  | SQ_row_t *sql_row;
    182  | char *sql_str;
    183  | char query[STR_M];
    184  | int sql_err;
    185  | int location;
    186  |
    187  |     /* get the lock to ensure that queries are not stopped */
    188  |     /* which means access to the database is allowed */
    189  |     PW_record_query_start();
    190  |
    191  |   switch(location=atlast(sql_connection, serial_number)){
    192  |
    193  |    case 0: table="history";
    194  |            break;
    195  |    case 1: table="last";
    196  |            break;
    197  |    case 2: table="failed_transaction";
    198  |            break;
    199  |    default: return(NULL);
    200  |
    201  |   }
    202  |
    203  |   if(location == 2)
    204  |      sprintf(query, "SELECT object FROM %s "
    205  |                     "WHERE serial_id=%ld ",
    206  | 		    table, serial_number);
    207  |   else
    208  |      sprintf(query, "SELECT %s.object FROM %s, serials "
    209  |                     "WHERE serials.serial_id=%ld "
    210  |                     "AND serials.object_id=%s.object_id "
    211  |                     "AND serials.sequence_id=%s.sequence_id ", table, table, serial_number, table, table);
    212  |
    213  |
    214  |  sql_err = SQ_execute_query(sql_connection, query, &sql_result);
    215  |
    216  |  if(sql_err) {
    217  |     ER_perror(FAC_PM, PM_NOSQLC,"%s[%s]", SQ_error(sql_connection), query);
    218  |     die;
    219  |  }
    220  |
    221  |
    222  |  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
    223  | 	sql_str = SQ_get_column_string(sql_result, sql_row, 0);
    224  |
    225  |      /* We must process all the rows of the result,*/
    226  |      /* otherwise we'll have them as part of the next qry */
    227  | 	while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
    228  | 	  ER_perror(FAC_PM, PM_NOSQLC,"duplicate PK [%s]", query);
    229  | 	  if(sql_str) UT_free(sql_str); sql_str=NULL;
    230  | 	}
    231  |  }
    232  |  else sql_str=NULL;
    233  |
    234  |  if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
    235  |
    236  |  *operation=getop(sql_connection, serial_number);
    237  |
    238  |     /* release the lock */
    239  |     PW_record_query_end();
    240  |
    241  |  return(sql_str);
    242  |
    243  | }
    244  |
    245  | /************************************************************
    246  | * void pm_get_source_info()                                 *
    247  | *                                                           *
    248  | * Fills supplied buffer with information about the source   *
    249  | *                                                           *
    250  | * Returns text block corresponding to the requested source  *
    251  | * Format:                                                   *
    252  | * <source>:<can_mirror>:min_serial-max_serial               *
    253  | * source - name of the source (e.g. RIPE, RADB, etc.)       *
    254  | * can_mirror                                                *
    255  | *    'Y' if the client is allowed to mirror the source      *
    256  | *    'N' if not                                             *
    257  | *    'N' if there is no serials (then the range starts at 0)*
    258  | *                                                           *
    259  | *                                                           *
    260  | *************************************************************/
    261  | void pm_get_source_info(GString *gbuff, ip_addr_t *client_address, char *source, ca_dbSource_t *source_hdl)
    262  | {
    263  |
    264  | char *db_host = ca_get_srcdbmachine(source_hdl);
    265  | int   db_port = ca_get_srcdbport(source_hdl);
    266  | char *db_name = ca_get_srcdbname(source_hdl);
    267  | char *db_user = ca_get_srcdbuser(source_hdl);
    268  | char *db_passwd = ca_get_srcdbpassword(source_hdl);
    269  | int version = ca_get_srcnrtmprotocolvers(source_hdl);
    270  | SQ_connection_t *db_connection;
    271  | long min_serial, max_serial;
    272  | char can_mirror;
    273  |
    274  |       /* Connect to the database */
    275  |        db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
    276  |        min_serial=PM_get_oldest_serial(db_connection);
    277  |        max_serial=PM_get_current_serial(db_connection) - SAFE_BACKLOG;
    278  |
    279  |        /* If it cannot be morrored at all - N, but range starts with 0 */
    280  |        /* If the client is allowed to mirror - Y         */
    281  |        /* Otherwise - N                                  */
    282  |        if(min_serial>max_serial) {
    283  | 	       can_mirror='N';
    284  | 	       min_serial=0;
    285  |        }
    286  |        else {
    287  | 	       if(AA_can_mirror(client_address, source )) can_mirror='Y';
    288  |                else can_mirror='N';
    289  |        }
    290  |        g_string_sprintfa(gbuff, "%s:%d:%c:%lu-%lu\n", source, version, can_mirror, min_serial, max_serial);
    291  |
    292  |        UT_free(db_host);
    293  |        UT_free(db_name);
    294  |        UT_free(db_user);
    295  |        UT_free(db_passwd);
    296  |        SQ_close_connection(db_connection);
    297  | }
    298  |
    299  | /************************************************************
    300  | * GString *PM_get_nrtm_sources()                            *
    301  | *                                                           *
    302  | * Fills supplied buffer with information about the sources  *
    303  | *                                                           *
    304  | *                                                           *
    305  | * Note:                                                     *
    306  | *  returned GString should be freed by the caller           *
    307  | *                                                           *
    308  | *************************************************************/
    309  | GString *PM_get_nrtm_sources(ip_addr_t *client_address, char *source)
    310  | {
    311  | GString *gbuff=g_string_sized_new(STR_L);
    312  | int nsource;
    313  | ca_dbSource_t *source_hdl;
    314  |
    315  |    if(source){
    316  |       source_hdl = ca_get_SourceHandleByName(source);
    317  |       if (source_hdl)pm_get_source_info(gbuff, client_address, source, source_hdl);
    318  |    } else
    319  |       for(nsource=0; (source_hdl = ca_get_SourceHandleByPosition(nsource))!=NULL ; nsource++){
    320  |        source=ca_get_srcname(source_hdl);
    321  |        pm_get_source_info(gbuff, client_address, source, source_hdl);
    322  |        UT_free(source);
    323  |    }
    324  |    /* one extra line, another one will be put bt PW or PM */
    325  |    g_string_sprintfa(gbuff, "\n");
    326  |    return(gbuff);
    327  | }