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