1 | /*************************************** 2 | $Revision: 1.9 $ 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,2001,2002 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 | #include "rip.h" 34 | 35 | 36 | /*++++++++++++++++++++++++++++++++++++++ 37 | finds path by identifier 38 | 39 | er_path_t * 40 | er_find_path_byname returns the pointer to it if found or NULL if not found 41 | 42 | char *key path identifier 43 | 44 | ++++++++++++++++++++++++++++++++++++++*/ 45 | static 46 | er_path_t * 47 | er_find_path_byname(char *key) 48 | { 49 | GList *pitem; 50 | er_path_t *pathptr; 51 | 52 | /* foreach path */ 53 | for( pitem = g_list_first(er_pathlist); 54 | pitem != NULL; 55 | pitem = g_list_next(pitem)) { 56 | 57 | pathptr = (er_path_t *)pitem->data; 58 | 59 | if( strcmp(pathptr->name, key) == 0 ) { 60 | return pathptr; 61 | } 62 | } 63 | 64 | return NULL; 65 | } 66 | 67 | 68 | /*++++++++++++++++++++++++++++++++++++++ 69 | 70 | Updates the array of currently active aspects. Must be used after any change 71 | of filters/paths. 72 | 73 | The "asp" array describes the "OR" of all filters' aspects. This is to allow 74 | fast dropping of messages that would be dropped anyway 75 | 76 | This function clears the array and regenerates it by going through 77 | all filters and setting appropriate bits of aspects per facility. 78 | 79 | ++++++++++++++++++++++++++++++++++++++*/ 80 | void 81 | er_upd_asparray(void) 82 | { 83 | GList *pitem, *fitem; 84 | er_fac_code_t f; 85 | 86 | /* clear */ 87 | for(f=0; f<FAC_LAST; f++) { 88 | er_asparray[f] = 0; 89 | } 90 | 91 | /* foreach path */ 92 | for( pitem = g_list_first(er_pathlist); 93 | pitem != NULL; 94 | pitem = g_list_next(pitem)) { 95 | 96 | er_path_t *pathptr = (er_path_t *)pitem->data; 97 | 98 | /* active paths only */ 99 | if( pathptr->active ) { 100 | 101 | /* foreach filter on that path */ 102 | for( fitem = g_list_first(pathptr->filters); 103 | fitem != NULL; 104 | fitem = g_list_next(fitem)) { 105 | 106 | er_filter_t *filtptr = (er_filter_t *) fitem->data; 107 | 108 | /* foreach facility in that filter */ 109 | for(f=0; f<FAC_LAST; f++) { 110 | if( MA_isset( filtptr->fac_mask, f ) ) { 111 | er_asparray[f] |= filtptr->asp_mask; 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | 119 | 120 | /*++++++++++++++++++++++++++++++++++++++ 121 | 122 | Adds a filter to the filter chain for the given path. 123 | 124 | er_ret_t 125 | er_add_filter always returns ER_OK. 126 | 127 | er_path_t *pathptr pointer to path 128 | 129 | er_filter_t *filter pointer to the filter 130 | ++++++++++++++++++++++++++++++++++++++*/ 131 | er_ret_t 132 | er_add_filter( er_path_t *pathptr, er_filter_t *filter ) 133 | { 134 | er_filter_t *ft = UT_malloc(sizeof(er_filter_t)); 135 | 136 | memcpy(ft, filter, sizeof(er_filter_t)); 137 | pathptr->filters = g_list_append(pathptr->filters, ft); 138 | 139 | return ER_OK; 140 | } 141 | 142 | 143 | /*++++++++++++++++++++++++++++++++++++++ 144 | 145 | Finds a path by identifier and adds a list of filters to the filter 146 | chain for that path. 147 | 148 | er_ret_t 149 | er_attach_filter_chain returns ER_INVKEY if the path cannot be found 150 | or ER_OK on success. 151 | 152 | char *key path identifier 153 | 154 | GList *filterlist list of filters 155 | ++++++++++++++++++++++++++++++++++++++*/ 156 | er_ret_t 157 | er_attach_filter_chain( char *key, GList *filterlist ) 158 | { 159 | er_path_t *pathptr; 160 | er_ret_t err; 161 | 162 | if( (pathptr=er_find_path_byname(key)) == NULL ) { 163 | return ER_INVKEY; 164 | } 165 | else { 166 | GList *fitem; 167 | for( fitem = g_list_first(filterlist); 168 | fitem != NULL; 169 | fitem = g_list_next(fitem)) { 170 | 171 | er_filter_t *filtptr = (er_filter_t *) fitem->data; 172 | 173 | if( !NOERR(err=er_add_filter( pathptr, filtptr)) ) { 174 | return err; 175 | } 176 | } 177 | } 178 | 179 | er_upd_asparray(); 180 | 181 | return ER_OK; 182 | } 183 | 184 | 185 | /*++++++++++++++++++++++++++++++++++++++ 186 | 187 | basic sanity checks for a path definition. Currently only checking 188 | if a specified socket exists. 189 | 190 | int 191 | er_path_safeguard Returns 0 on success, -1 on failure 192 | 193 | er_path_t *path new path structure 194 | ++++++++++++++++++++++++++++++++++++++*/ 195 | static 196 | int 197 | er_path_safeguard(er_path_t *path) 198 | { 199 | 200 | switch ( path->type ) { 201 | 202 | case ER_PATH_SOCK: /* the socket must exist */ 203 | { 204 | char *n = SK_getpeername(path->descr.sock.fd); 205 | if( n == NULL ) { 206 | return -1; 207 | } 208 | else { 209 | UT_free(n); 210 | } 211 | } 212 | break; 213 | default: 214 | break; 215 | } 216 | 217 | return 0; 218 | } 219 | 220 | 221 | /*++++++++++++++++++++++++++++++++++++++ 222 | 223 | Registers a path in the chain of paths. 224 | 225 | er_ret_t 226 | er_register_path returns ER_DUPENT if a path with that identifier 227 | already exists, returns ER_INSANE if the sanity check 228 | is not passed, or ER_OK on success. 229 | 230 | er_path_t *path new path structure 231 | 232 | char *key path identifier 233 | ++++++++++++++++++++++++++++++++++++++*/ 234 | er_ret_t 235 | er_register_path( er_path_t *path, char *key ) 236 | { 237 | er_path_t *ft; 238 | er_path_t *pathptr; 239 | 240 | if( (pathptr=er_find_path_byname(key)) != NULL ) { 241 | return ER_DUPENT; /* duplicate !!! */ 242 | } 243 | if( er_path_safeguard(path) < 0 ) { 244 | return ER_INSANE; 245 | } 246 | 247 | ft = UT_calloc(sizeof(er_path_t),1); 248 | memcpy(ft, path, sizeof(er_path_t)); 249 | strncpy(ft->name, key, 31); 250 | er_pathlist = g_list_append(er_pathlist, ft); 251 | 252 | er_upd_asparray(); 253 | 254 | return ER_OK; 255 | } 256 | 257 | 258 | /*++++++++++++++++++++++++++++++++++++++ 259 | 260 | Finds the path by identified and replaces its definition without touching 261 | the filters 262 | 263 | er_ret_t 264 | er_modify_path returns ER_INVKEY if the path cannot be found 265 | or ER_OK on success. 266 | 267 | er_path_t *newpath new path structure 268 | 269 | char *key path identifier 270 | ++++++++++++++++++++++++++++++++++++++*/ 271 | er_ret_t 272 | er_modify_path( er_path_t *newpath, char *key ) 273 | { 274 | er_path_t *pathptr; 275 | 276 | if( (pathptr=er_find_path_byname(key)) == NULL ) { 277 | return ER_INVKEY; 278 | } 279 | else { 280 | /* name stays the same */ 281 | pathptr->active = newpath->active; 282 | pathptr->format = newpath->format; 283 | pathptr->mutex = newpath->mutex; 284 | pathptr->type = newpath->type; 285 | pathptr->descr = newpath->descr; 286 | /* filters stay the same */ 287 | 288 | er_upd_asparray(); 289 | 290 | return ER_OK; 291 | } 292 | } 293 | 294 | 295 | /*++++++++++++++++++++++++++++++++++++++ 296 | 297 | Deletes a filter from the list of filters of the path specified by 298 | identifier. The filter is specified by its position in the list, 299 | starting with 0. 300 | 301 | er_ret_t 302 | er_delete_filter returns ER_INVKEY if the path or filter cannot be found 303 | 304 | char *key path identifier 305 | 306 | unsigned filterid filter position 307 | ++++++++++++++++++++++++++++++++++++++*/ 308 | er_ret_t 309 | er_delete_filter( char *key, unsigned filterid ) 310 | { 311 | er_path_t *pathptr; 312 | er_filter_t *filtptr; 313 | 314 | if( (pathptr=er_find_path_byname(key)) == NULL ) { 315 | return ER_INVKEY; 316 | } 317 | else { 318 | int numfilters = g_list_length(pathptr->filters); 319 | 320 | if( filterid >= numfilters ) { 321 | return ER_INVKEY; 322 | } 323 | 324 | filtptr = g_list_nth_data(pathptr->filters, (unsigned) filterid); 325 | /* free filter structure */ 326 | UT_free(filtptr); 327 | /* remove filter link from list */ 328 | pathptr->filters = g_list_remove(pathptr->filters, filtptr); 329 | /* update arrays */ 330 | er_upd_asparray(); 331 | 332 | return ER_OK; 333 | } 334 | } 335 | 336 | 337 | /*++++++++++++++++++++++++++++++++++++++ 338 | 339 | Adds an argument to a dynamically build argv array of arguments for 340 | a path of EXEC type. 341 | 342 | er_path_t *pathptr path structure 343 | 344 | char *arg new argument 345 | ++++++++++++++++++++++++++++++++++++++*/ 346 | void 347 | er_add_exec_arg(er_path_t *pathptr, char *arg) 348 | { 349 | int len = 0; 350 | char **argv = pathptr->descr.exec.argv; 351 | char **newargv; 352 | 353 | if( argv != NULL ) { 354 | while( argv[len] != NULL ) { 355 | len++; 356 | } 357 | } 358 | 359 | newargv = UT_calloc( sizeof(char **) * (len+2), 1 ); 360 | if( len > 0 ) { 361 | memcpy( newargv, argv, sizeof(char **) * len); 362 | } 363 | newargv[len] = UT_strdup(arg); 364 | 365 | pathptr->descr.exec.argv = newargv; 366 | 367 | if( argv != NULL ) { 368 | UT_free(argv); 369 | } 370 | } 371 | 372 | 373 | 374 | /*++++++++++++++++++++++++++++++++++++++ 375 | 376 | free dynamic elements of the path structure 377 | 378 | er_path_t *pathptr path structure 379 | 380 | ++++++++++++++++++++++++++++++++++++++*/ 381 | void er_free_dynadescr( er_path_t *pathptr ) 382 | { 383 | if(pathptr->type == ER_PATH_EXEC ) { 384 | char **argv = pathptr->descr.exec.argv; 385 | int len=0; 386 | 387 | if( argv != NULL ) { 388 | while( argv[len] != NULL ) { 389 | UT_free( argv[len] ); 390 | len++; 391 | } 392 | } 393 | if( argv != NULL ) { 394 | UT_free(argv); 395 | } 396 | } 397 | } 398 | 399 | 400 | 401 | /*++++++++++++++++++++++++++++++++++++++ 402 | 403 | finds and removes a path identified by identifier 404 | 405 | er_ret_t 406 | er_delete_path ER_OK on success, ER_INVKEY if path not found 407 | 408 | char *key path identifier 409 | ++++++++++++++++++++++++++++++++++++++*/ 410 | er_ret_t 411 | er_delete_path(char *key ) 412 | { 413 | er_path_t *pathptr; 414 | 415 | if( (pathptr=er_find_path_byname(key)) == NULL ) { 416 | return ER_INVKEY; 417 | } 418 | else { 419 | /* remove filters */ 420 | wr_clear_list( &(pathptr->filters) ); 421 | /* delete dynamic elements */ 422 | er_free_dynadescr( pathptr ); 423 | /* free path structure */ 424 | UT_free(pathptr); 425 | /* remove path link from list */ 426 | er_pathlist = g_list_remove(er_pathlist, pathptr); 427 | 428 | /* update arrays */ 429 | er_upd_asparray(); 430 | 431 | return ER_OK; 432 | } 433 | } 434 |