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