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