Source File modules/pm/pm_serials.c

    1    | /***************************************
    2    |   $Revision: 1.10 $
    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                              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   | #include <stdio.h>
    39   | #include "ud_int.h"
    40   | #include "protocol_mirror.h"
    41   |
    42   | void pm_get_source_info(GString *gbuff, ip_addr_t *client_address, char *source, ca_dbSource_t *source_hdl);
    43   |
    44   | /************************************************************
    45   | * PM_get_minmax_serial()                                    *
    46   | *                                                           *
    47   | * Returns the min or max serial number.                     *
    48   | *                                                           *
    49   | * Returns:                                                  *
    50   | *  min (max=0) or max (max=1) serial number                 *
    51   | *  -1 in case of an error                                   *
    52   | *                                                           *
    53   | * Note:                                                     *
    54   | *  min serial= MIN(serial_id)+1                             *
    55   | *  MIN(serial_id) represents legacy RIPE.CURRENSERIAL       *
    56   | *  of the snapshot                                          *
    57   | *                                                           *
    58   | *************************************************************/
    59   | long PM_get_minmax_serial(SQ_connection_t *sql_connection, int max)
    60   | {
    61   | char query[STR_M];
    62   | SQ_result_set_t *sql_result;
    63   | SQ_row_t *sql_row;
    64   | char *sql_str;
    65   | long current_serial;
    66   | char *minmax;
    67   | int sql_err;
    68   |
    69   | if(max==1)minmax="max"; else minmax="min";
    70   |
    71   |  sprintf(query, "SELECT %s(serial_id) FROM serials ", minmax);
    72   |
    73   | //fprintf(stderr, "D:<get_field_str>:query: %s\n", query);
    74   |  sql_err = SQ_execute_query(sql_connection, query, &sql_result);
    75   |
    76   |  if(sql_err) {
    77   |     ER_perror(FAC_PM, PM_NOSQLC,"%s[%s]", SQ_error(sql_connection), query);
    78   |     die;
    79   |  }
    80   |
    81   |
    82   |  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
    83   | 	sql_str = SQ_get_column_string(sql_result, sql_row, 0);
    84   |
    85   |      /* We must process all the rows of the result,*/
    86   |      /* otherwise we'll have them as part of the next qry */
    87   | 	while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
    88   | 	  ER_perror(FAC_PM, PM_NOSQLC,"duplicate PK [%s]", query);
    89   | 	  if(sql_str)free(sql_str); sql_str=NULL;
    90   | 	}
    91   |  }
    92   |  else sql_str=NULL;
    93   |
    94   |  if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
    95   |
    96   |  if(sql_str) {
    97   |   current_serial = atol(sql_str);
    98   |   if(max!=1)current_serial++;
    99   |   free(sql_str);
    100  |  }
    101  |  else current_serial=-1;
    102  |
    103  |  return(current_serial);
    104  |
    105  | }
    106  |
    107  | /************************************************************
    108  | * int atlast(long serial_number)
    109  | * -1 - sql error
    110  | *
    111  | ***********************************************************/
    112  |
    113  | static int atlast(SQ_connection_t *sql_connection, long serial_number)
    114  | {
    115  | char *sql_str;
    116  | char str_id[STR_S];
    117  | int atlast=-1;
    118  |
    119  |
    120  |   sprintf(str_id, "%ld", serial_number);
    121  |   sql_str= get_field_str(sql_connection, "atlast", "serials", "serial_id", str_id, NULL);
    122  |   if(sql_str) {
    123  |        	  atlast = atoi(sql_str);
    124  |        	  free(sql_str);
    125  |   }
    126  |
    127  |   return(atlast);
    128  |
    129  | }
    130  |
    131  |
    132  | /************************************************************
    133  | * int getop(long serial_number)
    134  | * -1 - sql error
    135  | *
    136  | * **********************************************************/
    137  |
    138  | static int getop(SQ_connection_t *sql_connection, long serial_number)
    139  | {
    140  | char *sql_str;
    141  | char str_id[STR_S];
    142  | int op=-1;
    143  |
    144  |
    145  |   sprintf(str_id, "%ld", serial_number);
    146  |   sql_str= get_field_str(sql_connection, "operation", "serials", "serial_id", str_id, NULL);
    147  |   if(sql_str) {
    148  |        	  op = atoi(sql_str);
    149  |        	  free(sql_str);
    150  |   }
    151  |
    152  |   return(op);
    153  |
    154  | }
    155  |
    156  |
    157  | /************************************************************
    158  | * char *PM_get_serial_object()                                 *
    159  | *                                                           *
    160  | * Returns text block corresponding to the requested serial  *
    161  | *                                                           *
    162  | * Returns:                                                  *
    163  | *  operation (ADD/DEL) and text object                      *
    164  | *  NULL in case of an error                                 *
    165  | *                                                           *
    166  | * Note:                                                     *
    167  | *  returned string should be freed by the caller            *
    168  | *                                                           *
    169  | *************************************************************/
    170  | char *PM_get_serial_object(SQ_connection_t *sql_connection, long serial_number, int *operation)
    171  | {
    172  | char *table;
    173  | SQ_result_set_t * sql_result;
    174  | SQ_row_t *sql_row;
    175  | char *sql_str;
    176  | char query[STR_M];
    177  | int sql_err;
    178  | int location;
    179  |
    180  |   switch(location=atlast(sql_connection, serial_number)){
    181  |
    182  |    case 0: table="history";
    183  |            break;
    184  |    case 1: table="last";
    185  |            break;
    186  |    case 2: table="failed_transaction";
    187  |            break;
    188  |    default: return(NULL);
    189  |
    190  |   }
    191  |
    192  |   if(location == 2)
    193  |      sprintf(query, "SELECT object FROM %s "
    194  |                     "WHERE serial_id=%ld ",
    195  | 		    table, serial_number);
    196  |   else
    197  |      sprintf(query, "SELECT %s.object FROM %s, serials "
    198  |                     "WHERE serials.serial_id=%ld "
    199  |                     "AND serials.object_id=%s.object_id "
    200  |                     "AND serials.sequence_id=%s.sequence_id ", table, table, serial_number, table, table);
    201  |
    202  |
    203  |  sql_err = SQ_execute_query(sql_connection, query, &sql_result);
    204  |
    205  |  if(sql_err) {
    206  |     ER_perror(FAC_PM, PM_NOSQLC,"%s[%s]", SQ_error(sql_connection), query);
    207  |     die;
    208  |  }
    209  |
    210  |
    211  |  if ((sql_row = SQ_row_next(sql_result)) != NULL) {
    212  | 	sql_str = SQ_get_column_string(sql_result, sql_row, 0);
    213  |
    214  |      /* We must process all the rows of the result,*/
    215  |      /* otherwise we'll have them as part of the next qry */
    216  | 	while ( (sql_row = SQ_row_next(sql_result)) != NULL) {
    217  | 	  ER_perror(FAC_PM, PM_NOSQLC,"duplicate PK [%s]", query);
    218  | 	  if(sql_str)free(sql_str); sql_str=NULL;
    219  | 	}
    220  |  }
    221  |  else sql_str=NULL;
    222  |
    223  |  if(sql_result){ SQ_free_result(sql_result); sql_result=NULL; }
    224  |
    225  |  *operation=getop(sql_connection, serial_number);
    226  |
    227  |  return(sql_str);
    228  |
    229  | }
    230  |
    231  | /************************************************************
    232  | * void pm_get_source_info()                                 *
    233  | *                                                           *
    234  | * Fills supplied buffer with information about the source   *
    235  | *                                                           *
    236  | * Returns text block corresponding to the requested source  *
    237  | * Format:                                                   *
    238  | * <source>:<can_mirror>:min_serial-max_serial               *
    239  | * source - name of the source (e.g. RIPE, RADB, etc.)       *
    240  | * can_mirror                                                *
    241  | *    'Y' if the client is allowed to mirror the source      *
    242  | *    'N' if not                                             *
    243  | *    'N' if there is no serials (then the range starts at 0)*
    244  | *                                                           *
    245  | *                                                           *
    246  | *************************************************************/
    247  | void pm_get_source_info(GString *gbuff, ip_addr_t *client_address, char *source, ca_dbSource_t *source_hdl)
    248  | {
    249  |
    250  | char *db_host = ca_get_srcdbmachine(source_hdl);
    251  | int   db_port = ca_get_srcdbport(source_hdl);
    252  | char *db_name = ca_get_srcdbname(source_hdl);
    253  | char *db_user = ca_get_srcdbuser(source_hdl);
    254  | char *db_passwd = ca_get_srcdbpassword(source_hdl);
    255  | int version = ca_get_srcnrtmprotocolvers(source_hdl);
    256  | SQ_connection_t *db_connection;
    257  | long min_serial, max_serial;
    258  | char can_mirror;
    259  |
    260  |       /* Connect to the database */
    261  |        db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
    262  |        min_serial=PM_get_oldest_serial(db_connection);
    263  |        max_serial=PM_get_current_serial(db_connection);
    264  |
    265  |        /* If it cannot be morrored at all - N, but range starts with 0 */
    266  |        /* If the client is allowed to mirror - Y         */
    267  |        /* Otherwise - N                                  */
    268  |        if(min_serial>max_serial) {
    269  | 	       can_mirror='N';
    270  | 	       min_serial=0;
    271  |        }
    272  |        else {
    273  | 	       if(AA_can_mirror(client_address, source )) can_mirror='Y';
    274  |                else can_mirror='N';
    275  |        }
    276  |        g_string_sprintfa(gbuff, "%s:%d:%c:%lu-%lu\n", source, version, can_mirror, min_serial, max_serial);
    277  |
    278  |        free(db_host);
    279  |        free(db_name);
    280  |        free(db_user);
    281  |        free(db_passwd);
    282  |        SQ_close_connection(db_connection);
    283  | }
    284  |
    285  | /************************************************************
    286  | * GString *PM_get_nrtm_sources()                            *
    287  | *                                                           *
    288  | * Fills supplied buffer with information about the sources  *
    289  | *                                                           *
    290  | *                                                           *
    291  | * Note:                                                     *
    292  | *  returned GString should be freed by the caller           *
    293  | *                                                           *
    294  | *************************************************************/
    295  | GString *PM_get_nrtm_sources(ip_addr_t *client_address, char *source)
    296  | {
    297  | GString *gbuff=g_string_sized_new(STR_L);
    298  | int nsource;
    299  | ca_dbSource_t *source_hdl;
    300  |
    301  |    if(source){
    302  |       source_hdl = ca_get_SourceHandleByName(source);
    303  |       if (source_hdl)pm_get_source_info(gbuff, client_address, source, source_hdl);
    304  |    } else
    305  |       for(nsource=0; (source_hdl = ca_get_SourceHandleByPosition(nsource))!=NULL ; nsource++){
    306  |        source=ca_get_srcname(source_hdl);
    307  |        pm_get_source_info(gbuff, client_address, source, source_hdl);
    308  |        free(source);
    309  |    }
    310  |
    311  |    g_string_sprintfa(gbuff, "\n\n");
    312  |    return(gbuff);
    313  | }