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 |