Source File modules/er/er_paths.c

    1    | /***************************************
    2    |   $Revision: 1.3 $
    3    |
    4    |   Error reporting (er) er_paths.c - parser callback functions for path
    5    |                                     & filter creation/modification/deletion
    6    |
    7    |   Status: NOT REVUED, PARTLY TESTED
    8    |
    9    |   Design and implementation by: Marek Bukowy
    10   |
    11   |   ******************/ /******************
    12   |   Copyright (c) 1999,2000                             RIPE NCC
    13   |
    14   |   All Rights Reserved
    15   |
    16   |   Permission to use, copy, modify, and distribute this software and its
    17   |   documentation for any purpose and without fee is hereby granted,
    18   |   provided that the above copyright notice appear in all copies and that
    19   |   both that copyright notice and this permission notice appear in
    20   |   supporting documentation, and that the name of the author not be
    21   |   used in advertising or publicity pertaining to distribution of the
    22   |   software without specific, written prior permission.
    23   |
    24   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    25   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    26   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    27   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    28   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    29   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    30   |   ***************************************/
    31   |
    32   |
    33   |
    34   | #include "erroutines.h"
    35   | #include "memwrap.h"
    36   |
    37   |
    38   | /* find path by name, returns the pointer to it if found or NULL. */
    39   | static
    40   | er_path_t *
    41   | er_find_path_byname(char *key)
    42   | {
    43   |   GList *pitem;
    44   |   er_path_t *pathptr;
    45   |
    46   |   /* foreach path */
    47   |   for( pitem = g_list_first(er_pathlist);
    48   |        pitem != NULL;
    49   |        pitem = g_list_next(pitem)) {
    50   |
    51   |     pathptr = (er_path_t *)pitem->data;
    52   |
    53   |     if( strcmp(pathptr->name, key) == 0 ) {
    54   |       return pathptr;
    55   |     }
    56   |   }
    57   |
    58   |   return NULL;
    59   | }
    60   |
    61   | /* the "asp" array describes the "OR" of all filters' aspects. This is to allow
    62   |    fast dropping of messages that would be dropped anyway
    63   |
    64   |    when invoked, clears the array and then goes through all filters
    65   |    setting appropriate bits of aspects per facility
    66   | */
    67   | void
    68   | er_upd_asparray(void)
    69   | {
    70   |   GList *pitem, *fitem;
    71   |   er_fac_code_t f;
    72   |
    73   |   /* clear */
    74   |   for(f=0; f<FAC_LAST; f++) {
    75   |     er_asparray[f] = 0;
    76   |   }
    77   |
    78   |   /* foreach path */
    79   |   for( pitem = g_list_first(er_pathlist);
    80   |        pitem != NULL;
    81   |        pitem = g_list_next(pitem)) {
    82   |
    83   |     er_path_t *pathptr = (er_path_t *)pitem->data;
    84   |
    85   |     /* active paths only */
    86   |     if( pathptr->active ) {
    87   |
    88   |       /* foreach filter on that path */
    89   |       for( fitem = g_list_first(pathptr->filters);
    90   | 	   fitem != NULL;
    91   | 	   fitem = g_list_next(fitem)) {
    92   |
    93   | 	er_filter_t *filtptr = (er_filter_t *) fitem->data;
    94   |
    95   | 	/* foreach facility in that filter */
    96   | 	for(f=0; f<FAC_LAST; f++) {
    97   | 	  if( MA_isset( filtptr->fac_mask, f ) ) {
    98   | 	    er_asparray[f] |= filtptr->asp_mask;
    99   | 	  }
    100  | 	}
    101  |       }
    102  |     }
    103  |   }
    104  | }
    105  |
    106  |
    107  |
    108  | er_ret_t
    109  | er_add_filter( er_path_t *pathptr, er_filter_t *filter )
    110  | {
    111  |   er_filter_t *ft = malloc(sizeof(er_filter_t));
    112  |
    113  |   memcpy(ft, filter, sizeof(er_filter_t));
    114  |   pathptr->filters =  g_list_append(pathptr->filters, ft);
    115  |
    116  |   return ER_OK;
    117  | }
    118  |
    119  |
    120  | er_ret_t
    121  | er_attach_filter_chain( char *key, GList *filterlist )
    122  | {
    123  |   er_path_t *pathptr;
    124  |   er_ret_t err;
    125  |
    126  |   if( (pathptr=er_find_path_byname(key)) == NULL ) {
    127  |      return ER_INVKEY;
    128  |   }
    129  |   else {
    130  |     GList  *fitem;
    131  |     for( fitem = g_list_first(filterlist);
    132  | 	 fitem != NULL;
    133  | 	 fitem = g_list_next(fitem)) {
    134  |
    135  |       er_filter_t *filtptr = (er_filter_t *) fitem->data;
    136  |
    137  |       if( !NOERR(err=er_add_filter( pathptr, filtptr)) ) {
    138  | 	return err;
    139  |       }
    140  |     }
    141  |   }
    142  |
    143  |   return ER_OK;
    144  | }
    145  |
    146  |
    147  | er_ret_t
    148  | er_register_path(  er_path_t *path, char *key )
    149  | {
    150  |   er_path_t *ft;
    151  |   er_path_t *pathptr;
    152  |
    153  |   if( (pathptr=er_find_path_byname(key)) != NULL ) {
    154  |     return ER_DUPENT; /* duplicate !!! */
    155  |   }
    156  |
    157  |   ft = calloc(sizeof(er_path_t),1);
    158  |   memcpy(ft, path, sizeof(er_path_t));
    159  |   strncpy(ft->name, key, 31);
    160  |   er_pathlist = g_list_append(er_pathlist, ft);
    161  |
    162  |   er_upd_asparray();
    163  |
    164  |   return ER_OK;
    165  | }
    166  |
    167  | /* find the path by name and replace its definition without touching
    168  |    the filters
    169  | */
    170  | er_ret_t
    171  | er_modify_path(  er_path_t *newpath, char *key )
    172  | {
    173  |   er_path_t *pathptr;
    174  |
    175  |   if( (pathptr=er_find_path_byname(key)) == NULL ) {
    176  |      return ER_INVKEY;
    177  |   }
    178  |   else {
    179  |     /* name stays the same */
    180  |     pathptr->active = newpath->active;
    181  |     pathptr->format = newpath->format;
    182  |     pathptr->mutex  = newpath->mutex;
    183  |     pathptr->type   = newpath->type;
    184  |     pathptr->descr  = newpath->descr;
    185  |     /* filters stay the same */
    186  |
    187  |     er_upd_asparray();
    188  |
    189  |     return ER_OK;
    190  |   }
    191  | }
    192  |
    193  | er_ret_t
    194  | er_delete_filter( char *key, unsigned int filterid )
    195  | {
    196  |   er_path_t *pathptr;
    197  |   er_filter_t *filtptr;
    198  |
    199  |   if( (pathptr=er_find_path_byname(key)) == NULL ) {
    200  |      return ER_INVKEY;
    201  |   }
    202  |   else {
    203  |     int numfilters = g_list_length(pathptr->filters);
    204  |
    205  |     if( filterid >= numfilters ) {
    206  |       return ER_INVKEY;
    207  |     }
    208  |
    209  |     filtptr = g_list_nth_data(pathptr->filters, filterid);
    210  |     /* free filter structure */
    211  |     free(filtptr);
    212  |     /* remove filter link from list */
    213  |     pathptr->filters = g_list_remove(pathptr->filters, filtptr);
    214  |     /* update arrays */
    215  |     er_upd_asparray();
    216  |
    217  |     return ER_OK;
    218  |   }
    219  | }
    220  |
    221  |
    222  | void
    223  | er_add_exec_arg(er_path_t *pathptr, char *arg)
    224  | {
    225  |   int len = 0;
    226  |   char **argv = pathptr->descr.exec.argv;
    227  |   char **newargv;
    228  |
    229  |   if( argv != NULL ) {
    230  |     while( argv[len] != NULL ) {
    231  |       len++;
    232  |     }
    233  |   }
    234  |
    235  |   newargv = calloc( sizeof(char **) * (len+2), 1 );
    236  |   if( len > 0 ) {
    237  |     memcpy( newargv, argv, sizeof(char **) * len);
    238  |   }
    239  |   newargv[len] = strdup(arg);
    240  |
    241  |   pathptr->descr.exec.argv = newargv;
    242  |
    243  |   if( argv != NULL ) {
    244  |     free(argv);
    245  |   }
    246  | }
    247  |
    248  | /* free dynamic elements of the path description */
    249  | void er_free_dynadescr( er_path_t *pathptr )
    250  | {
    251  |   char **argv = pathptr->descr.exec.argv;
    252  |   int len=0;
    253  |
    254  |   if( argv != NULL ) {
    255  |     while( argv[len] != NULL ) {
    256  |       free( argv[len] );
    257  |       len++;
    258  |     }
    259  |   }
    260  |
    261  |   if( argv != NULL ) {
    262  |     free(argv);
    263  |   }
    264  | }
    265  |
    266  |
    267  | /* finds and removes a path identified by the key (name).
    268  |    Also removes all associated filters.
    269  |
    270  |    returns:
    271  |    ER_OK on success
    272  |
    273  | */
    274  | er_ret_t
    275  | er_delete_path(char *key )
    276  | {
    277  |   er_path_t *pathptr;
    278  |
    279  |   if( (pathptr=er_find_path_byname(key)) == NULL ) {
    280  |      return ER_INVKEY;
    281  |   }
    282  |   else {
    283  |     /* remove filters */
    284  |     wr_clear_list( &(pathptr->filters) );
    285  |     /* delete dynamic elements */
    286  |     er_free_dynadescr( pathptr );
    287  |     /* free path structure */
    288  |     free(pathptr);
    289  |     /* remove path link from list */
    290  |     er_pathlist = g_list_remove(er_pathlist, pathptr);
    291  |
    292  |     /* update arrays */
    293  |     er_upd_asparray();
    294  |
    295  |     return ER_OK;
    296  |   }
    297  | }
    298  |
    299  |
    300  | /************************************************************/
    301  | static
    302  | void er_print_format(int format, GString *g_reply )
    303  | {
    304  |   int i;
    305  |
    306  |   for(i=0;  er_formarr[i].n != NULL; i++) {
    307  |     if( format & er_formarr[i].v ) {
    308  |       g_string_sprintfa(g_reply, "%s|",er_formarr[i].n);
    309  |     }
    310  |   }
    311  |   /* cut the last "|" */
    312  |   g_string_truncate(g_reply, strlen(g_reply->str)-1);
    313  | }
    314  |
    315  |
    316  | static
    317  | void er_print_one_path_descr(er_path_t *pathptr, GString *g_reply )
    318  | {
    319  |   er_path_descr_t *d = &(pathptr->descr);
    320  |
    321  |   switch(pathptr->type) {
    322  |   case  ER_PATH_NAME:
    323  |     g_string_sprintfa(g_reply, "NAME %s%s", d->name.filename,
    324  | 		      d->name.date ? " DATE" : ""
    325  | 		      );
    326  |     break;
    327  |   case  ER_PATH_SOCK:
    328  |     g_string_sprintfa(g_reply, "SOCK %d", d->sock.fd );
    329  |
    330  |     break;
    331  |
    332  |   case  ER_PATH_EXEC:
    333  |     g_string_sprintfa(g_reply, "EXEC ");
    334  |     if( d->exec.usepath ) {
    335  |       g_string_sprintfa(g_reply, "PATH ");
    336  |     }
    337  |     {
    338  |       char **argv = d->exec.argv;
    339  |       int len=0;
    340  |
    341  |       if( argv != NULL ) {
    342  | 	while( argv[len] != NULL ) {
    343  | 	  g_string_sprintfa(g_reply, "%s ", argv[len]);
    344  | 	  len++;
    345  | 	}
    346  |       }
    347  |     }
    348  |     break;
    349  |
    350  |   default:
    351  |     /* XXX other path descriptions missing */
    352  |     break;
    353  |   }
    354  | }
    355  |
    356  | static
    357  | void er_print_aspmask(mask_t facmask, unsigned aspmask, GString *g_reply)
    358  | {
    359  |   int i = 31;
    360  |
    361  |   while(i >= 0) {
    362  |     if( aspmask & (1<<i) ) {
    363  |       er_getaspsym(facmask, 1<<i, g_reply);
    364  |       g_string_append(g_reply, "|");
    365  |     }
    366  |
    367  |     i--;
    368  |   }
    369  |   /* cut the last "|" */
    370  |   g_string_truncate(g_reply, strlen(g_reply->str)-1);
    371  | }
    372  |
    373  | static
    374  | void er_print_facmask(mask_t facmask, GString *g_reply)
    375  | {
    376  |   int i = FAC_NONE;
    377  |
    378  |   while( ++i != FAC_LAST ) {
    379  |     if( MA_isset(facmask, er_fac_err[i].code) ) {
    380  |       g_string_sprintfa(g_reply, "%s|", er_fac_err[i].name);
    381  |     }
    382  |   }
    383  |   /* cut the last "|" */
    384  |   g_string_truncate(g_reply, strlen(g_reply->str)-1);
    385  |
    386  | }
    387  |
    388  | static
    389  | void er_print_one_filter(er_filter_t *filtptr, GString *g_reply )
    390  | {
    391  |   g_string_sprintfa(g_reply, "( FAC ");
    392  |   er_print_facmask( filtptr->fac_mask, g_reply);
    393  |
    394  |   if( filtptr->asp_mask != 0 ) {
    395  |     g_string_sprintfa(g_reply, "  ASP ");
    396  |     er_print_aspmask(  filtptr->fac_mask, filtptr->asp_mask, g_reply);
    397  |   }
    398  |
    399  |   g_string_sprintfa(g_reply, "  SEV %s-%s ",
    400  | 		    er_getsevsym( filtptr->sev_min, ER_M_SEVCHAR),
    401  | 		    er_getsevsym( filtptr->sev_max, ER_M_SEVCHAR)
    402  | 		    );
    403  |   if( filtptr->thr_id != 0 ) {
    404  |     g_string_sprintfa(g_reply, "   THR %u ", filtptr->thr_id);
    405  |   }
    406  |   g_string_sprintfa(g_reply, " )" );
    407  | }
    408  |
    409  | static
    410  | void er_print_one_path(er_path_t *pathptr, GString *g_reply )
    411  | {
    412  |   GList   *qitem;
    413  |   int f=1;
    414  |
    415  |   g_string_sprintfa(g_reply,"%s { ", pathptr->name );
    416  |   g_string_sprintfa(g_reply," FORMAT ");
    417  |   er_print_format(pathptr->format, g_reply );
    418  |   g_string_sprintfa(g_reply,"  ");
    419  |
    420  |   er_print_one_path_descr(pathptr, g_reply);
    421  |   g_string_sprintfa(g_reply," }\n");
    422  |
    423  |   for(qitem = g_list_first(pathptr->filters);
    424  |       qitem != NULL;
    425  |       qitem = g_list_next(qitem)) {
    426  |     er_filter_t *filtptr = (er_filter_t *) qitem -> data;
    427  |
    428  |     g_string_sprintfa(g_reply,"\t");
    429  |     er_print_one_filter(filtptr, g_reply) ;
    430  |     g_string_sprintfa(g_reply,"\n");
    431  |     f++;
    432  |   }
    433  |
    434  | }
    435  |
    436  | void er_print_paths(char **retbuf)
    437  | {
    438  |   GList   *qitem;
    439  |   GString *g_reply = g_string_sized_new(2048); /* initial size */
    440  |
    441  |   for( qitem = g_list_first(er_pathlist);
    442  |        qitem != NULL;
    443  |        qitem = g_list_next(qitem)) {
    444  |     er_path_t *pathptr = qitem -> data;
    445  |
    446  |     /*   g_string_sprintfa(g_reply, "path type %d (%s) with %d filters\n",
    447  | 	   pathptr->type, er_pathtypes[pathptr->type],
    448  | 	   g_list_length(pathptr->filters));
    449  |     */
    450  |     er_print_one_path(pathptr, g_reply);
    451  |
    452  |   }
    453  |
    454  |   *retbuf = g_reply->str;
    455  |
    456  |   /* we must duplicate the string allocated by glib - it can be freed
    457  |      only by glib internal free function :-( */
    458  |   g_string_free( g_reply, /* CONSTCOND */ FALSE);
    459  | }