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 | }