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 |