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  |