]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ipfilter/tools/ipmon_y.y
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ipfilter / tools / ipmon_y.y
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2001-2004 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  */
8 %{
9 #include "ipf.h"
10 #include <syslog.h>
11 #undef  OPT_NAT
12 #undef  OPT_VERBOSE
13 #include "ipmon_l.h"
14 #include "ipmon.h"
15
16 #define YYDEBUG 1
17
18 extern  void    yyerror __P((char *));
19 extern  int     yyparse __P((void));
20 extern  int     yylex __P((void));
21 extern  int     yydebug;
22 extern  FILE    *yyin;
23 extern  int     yylineNum;
24
25 typedef struct  opt     {
26         struct  opt     *o_next;
27         int             o_line;
28         int             o_type;
29         int             o_num;
30         char            *o_str;
31         struct in_addr  o_ip;
32 } opt_t;
33
34 static  void    build_action __P((struct opt *));
35 static  opt_t   *new_opt __P((int));
36 static  void    free_action __P((ipmon_action_t *));
37
38 static  ipmon_action_t  *alist = NULL;
39 %}
40
41 %union  {
42         char    *str;
43         u_32_t  num;
44         struct in_addr  addr;
45         struct opt      *opt;
46         union   i6addr  ip6;
47 }
48
49 %token  <num>   YY_NUMBER YY_HEX
50 %token  <str>   YY_STR
51 %token  <ip6>   YY_IPV6
52 %token  YY_COMMENT 
53 %token  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
54 %token  YY_RANGE_OUT YY_RANGE_IN
55
56 %token  IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
57 %token  IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT
58 %token  IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
59 %token  IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
60 %token  IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT
61 %token  IPM_STATE IPM_NATTAG IPM_IPF
62 %type   <addr> ipv4
63 %type   <opt> direction dstip dstport every execute group interface
64 %type   <opt> protocol result rule srcip srcport logtag matching
65 %type   <opt> matchopt nattag type doopt doing save syslog nothing
66 %type   <num> saveopts saveopt typeopt
67
68 %%
69 file:   line
70         | assign
71         | file line
72         | file assign
73         ;
74
75 line:   IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';'
76                                         { build_action($3); resetlexer(); }
77         | IPM_COMMENT
78         | YY_COMMENT
79         ;
80
81 assign: YY_STR assigning YY_STR ';'             { set_variable($1, $3);
82                                                   resetlexer();
83                                                   free($1);
84                                                   free($3);
85                                                   yyvarnext = 0;
86                                                 } 
87         ;
88
89 assigning:
90         '='                                     { yyvarnext = 1; }
91         ;
92
93 matching:
94         matchopt                                { $$ = $1; }
95         | matchopt ',' matching                 { $1->o_next = $3; $$ = $1; }
96         ;
97
98 matchopt:
99         direction                               { $$ = $1; }
100         | dstip                                 { $$ = $1; }
101         | dstport                               { $$ = $1; }
102         | every                                 { $$ = $1; }
103         | group                                 { $$ = $1; }
104         | interface                             { $$ = $1; }
105         | protocol                              { $$ = $1; }
106         | result                                { $$ = $1; }
107         | rule                                  { $$ = $1; }
108         | srcip                                 { $$ = $1; }
109         | srcport                               { $$ = $1; }
110         | logtag                                { $$ = $1; }
111         | nattag                                { $$ = $1; }
112         | type                                  { $$ = $1; }
113         ;
114
115 doing:
116         doopt                                   { $$ = $1; }
117         | doopt ',' doing                       { $1->o_next = $3; $$ = $1; }
118         ;
119
120 doopt:
121         execute                                 { $$ = $1; }
122         | save                                  { $$ = $1; }
123         | syslog                                { $$ = $1; }
124         | nothing                               { $$ = $1; }
125         ;
126
127 direction:
128         IPM_DIRECTION '=' IPM_IN                { $$ = new_opt(IPM_DIRECTION);
129                                                   $$->o_num = IPM_IN; }
130         | IPM_DIRECTION '=' IPM_OUT             { $$ = new_opt(IPM_DIRECTION);
131                                                   $$->o_num = IPM_OUT; }
132         ;
133
134 dstip:  IPM_DSTIP '=' ipv4 '/' YY_NUMBER        { $$ = new_opt(IPM_DSTIP);
135                                                   $$->o_ip = $3;
136                                                   $$->o_num = $5; }
137         ;
138
139 dstport:
140         IPM_DSTPORT '=' YY_NUMBER               { $$ = new_opt(IPM_DSTPORT);
141                                                   $$->o_num = $3; }
142         | IPM_DSTPORT '=' YY_STR                { $$ = new_opt(IPM_DSTPORT);
143                                                   $$->o_str = $3; }
144         ;
145
146 every:  IPM_EVERY IPM_SECOND                    { $$ = new_opt(IPM_SECOND);
147                                                   $$->o_num = 1; }
148         | IPM_EVERY YY_NUMBER IPM_SECONDS       { $$ = new_opt(IPM_SECOND);
149                                                   $$->o_num = $2; }
150         | IPM_EVERY IPM_PACKET                  { $$ = new_opt(IPM_PACKET);
151                                                   $$->o_num = 1; }
152         | IPM_EVERY YY_NUMBER IPM_PACKETS       { $$ = new_opt(IPM_PACKET);
153                                                   $$->o_num = $2; }
154         ;
155
156 group:  IPM_GROUP '=' YY_NUMBER                 { $$ = new_opt(IPM_GROUP);
157                                                   $$->o_num = $3; }
158         | IPM_GROUP '=' YY_STR                  { $$ = new_opt(IPM_GROUP);
159                                                   $$->o_str = $3; }
160         ;
161
162 interface:
163         IPM_INTERFACE '=' YY_STR                { $$ = new_opt(IPM_INTERFACE);
164                                                   $$->o_str = $3; }
165         ;
166
167 logtag: IPM_LOGTAG '=' YY_NUMBER                { $$ = new_opt(IPM_LOGTAG);
168                                                   $$->o_num = $3; }
169         ;
170
171 nattag: IPM_NATTAG '=' YY_STR                   { $$ = new_opt(IPM_NATTAG);
172                                                   $$->o_str = $3; }
173         ;
174
175 protocol:
176         IPM_PROTOCOL '=' YY_NUMBER              { $$ = new_opt(IPM_PROTOCOL);
177                                                   $$->o_num = $3; }
178         | IPM_PROTOCOL '=' YY_STR               { $$ = new_opt(IPM_PROTOCOL);
179                                                   $$->o_num = getproto($3);
180                                                   free($3);
181                                                 }
182         ;
183
184 result: IPM_RESULT '=' YY_STR                   { $$ = new_opt(IPM_RESULT);
185                                                   $$->o_str = $3; }
186         ;
187
188 rule:   IPM_RULE '=' YY_NUMBER                  { $$ = new_opt(IPM_RULE);
189                                                   $$->o_num = YY_NUMBER; }
190         ;
191
192 srcip:  IPM_SRCIP '=' ipv4 '/' YY_NUMBER        { $$ = new_opt(IPM_SRCIP);
193                                                   $$->o_ip = $3;
194                                                   $$->o_num = $5; }
195         ;
196
197 srcport:
198         IPM_SRCPORT '=' YY_NUMBER               { $$ = new_opt(IPM_SRCPORT);
199                                                   $$->o_num = $3; }
200         | IPM_SRCPORT '=' YY_STR                { $$ = new_opt(IPM_SRCPORT);
201                                                   $$->o_str = $3; }
202         ;
203
204 type:   IPM_TYPE '=' typeopt                    { $$ = new_opt(IPM_TYPE);
205                                                   $$->o_num = $3; }
206         ;
207
208 typeopt:
209         IPM_IPF                                 { $$ = IPL_MAGIC; }
210         | IPM_NAT                               { $$ = IPL_MAGIC_NAT; }
211         | IPM_STATE                             { $$ = IPL_MAGIC_STATE; }
212         ;
213
214 execute:
215         IPM_EXECUTE YY_STR                      { $$ = new_opt(IPM_EXECUTE);
216                                                   $$->o_str = $2; }
217         ;
218
219 save:   IPM_SAVE saveopts YY_STR                { $$ = new_opt(IPM_SAVE);
220                                                   $$->o_num = $2;
221                                                   $$->o_str = $3; }
222         ;
223
224 saveopts:                                       { $$ = 0; }
225         | saveopt                               { $$ = $1; }
226         | saveopt ',' saveopts                  { $$ = $1 | $3; }
227         ;
228
229 saveopt:
230         IPM_RAW                                 { $$ = IPMDO_SAVERAW; }
231         ;
232
233 syslog: IPM_SYSLOG                              { $$ = new_opt(IPM_SYSLOG); }
234         ;
235
236 nothing:
237         IPM_NOTHING                             { $$ = 0; }
238         ;
239
240 ipv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
241                 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
242                         yyerror("Invalid octet string for IP address");
243                         return 0;
244                   }
245                   $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
246                   $$.s_addr = htonl($$.s_addr);
247                 }
248 %%
249 static  struct  wordtab yywords[] = {
250         { "body",       IPM_BODY },
251         { "direction",  IPM_DIRECTION },
252         { "do",         IPM_DO },
253         { "dstip",      IPM_DSTIP },
254         { "dstport",    IPM_DSTPORT },
255         { "every",      IPM_EVERY },
256         { "execute",    IPM_EXECUTE },
257         { "group",      IPM_GROUP },
258         { "in",         IPM_IN },
259         { "interface",  IPM_INTERFACE },
260         { "ipf",        IPM_IPF },
261         { "logtag",     IPM_LOGTAG },
262         { "match",      IPM_MATCH },
263         { "nat",        IPM_NAT },
264         { "nattag",     IPM_NATTAG },
265         { "no",         IPM_NO },
266         { "nothing",    IPM_NOTHING },
267         { "out",        IPM_OUT },
268         { "packet",     IPM_PACKET },
269         { "packets",    IPM_PACKETS },
270         { "protocol",   IPM_PROTOCOL },
271         { "result",     IPM_RESULT },
272         { "rule",       IPM_RULE },
273         { "save",       IPM_SAVE },
274         { "second",     IPM_SECOND },
275         { "seconds",    IPM_SECONDS },
276         { "srcip",      IPM_SRCIP },
277         { "srcport",    IPM_SRCPORT },
278         { "state",      IPM_STATE },
279         { "syslog",     IPM_SYSLOG },
280         { "with",       IPM_WITH },
281         { NULL,         0 }
282 };
283
284 static int macflags[17][2] = {
285         { IPM_DIRECTION,        IPMAC_DIRECTION },
286         { IPM_DSTIP,            IPMAC_DSTIP     },
287         { IPM_DSTPORT,          IPMAC_DSTPORT   },
288         { IPM_GROUP,            IPMAC_GROUP     },
289         { IPM_INTERFACE,        IPMAC_INTERFACE },
290         { IPM_LOGTAG,           IPMAC_LOGTAG    },
291         { IPM_NATTAG,           IPMAC_NATTAG    },
292         { IPM_PACKET,           IPMAC_EVERY     },
293         { IPM_PROTOCOL,         IPMAC_PROTOCOL  },
294         { IPM_RESULT,           IPMAC_RESULT    },
295         { IPM_RULE,             IPMAC_RULE      },
296         { IPM_SECOND,           IPMAC_EVERY     },
297         { IPM_SRCIP,            IPMAC_SRCIP     },
298         { IPM_SRCPORT,          IPMAC_SRCPORT   },
299         { IPM_TYPE,             IPMAC_TYPE      },
300         { IPM_WITH,             IPMAC_WITH      },
301         { 0, 0 }
302 };
303
304 static opt_t *new_opt(type)
305 int type;
306 {
307         opt_t *o;
308
309         o = (opt_t *)malloc(sizeof(*o));
310         o->o_type = type;
311         o->o_line = yylineNum;
312         o->o_num = 0;
313         o->o_str = (char *)0;
314         o->o_next = NULL;
315         return o;
316 }
317
318 static void build_action(olist)
319 opt_t *olist;
320 {
321         ipmon_action_t *a;
322         opt_t *o;
323         char c;
324         int i;
325
326         a = (ipmon_action_t *)calloc(1, sizeof(*a));
327         if (a == NULL)
328                 return;
329         while ((o = olist) != NULL) {
330                 /*
331                  * Check to see if the same comparator is being used more than
332                  * once per matching statement.
333                  */
334                 for (i = 0; macflags[i][0]; i++)
335                         if (macflags[i][0] == o->o_type)
336                                 break;
337                 if (macflags[i][1] & a->ac_mflag) {
338                         fprintf(stderr, "%s redfined on line %d\n",
339                                 yykeytostr(o->o_type), yylineNum);
340                         if (o->o_str != NULL)
341                                 free(o->o_str);
342                         olist = o->o_next;
343                         free(o);
344                         continue;
345                 }
346
347                 a->ac_mflag |= macflags[i][1];
348
349                 switch (o->o_type)
350                 {
351                 case IPM_DIRECTION :
352                         a->ac_direction = o->o_num;
353                         break;
354                 case IPM_DSTIP :
355                         a->ac_dip = o->o_ip.s_addr;
356                         a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
357                         break;
358                 case IPM_DSTPORT :
359                         a->ac_dport = htons(o->o_num);
360                         break;
361                 case IPM_EXECUTE :
362                         a->ac_exec = o->o_str;
363                         c = *o->o_str;
364                         if (c== '"'|| c == '\'') {
365                                 if (o->o_str[strlen(o->o_str) - 1] == c) {
366                                         a->ac_run = strdup(o->o_str + 1);
367                                         a->ac_run[strlen(a->ac_run) - 1] ='\0';
368                                 } else
369                                         a->ac_run = o->o_str;
370                         } else
371                                 a->ac_run = o->o_str;
372                         o->o_str = NULL;
373                         break;
374                 case IPM_INTERFACE :
375                         a->ac_iface = o->o_str;
376                         o->o_str = NULL;
377                         break;
378                 case IPM_GROUP : 
379                         if (o->o_str != NULL)
380                                 strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
381                         else
382                                 sprintf(a->ac_group, "%d", o->o_num);
383                         break;
384                 case IPM_LOGTAG :
385                         a->ac_logtag = o->o_num;
386                         break;
387                 case IPM_NATTAG :
388                         strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
389                         break;
390                 case IPM_PACKET :
391                         a->ac_packet = o->o_num;
392                         break;
393                 case IPM_PROTOCOL :
394                         a->ac_proto = o->o_num;
395                         break;
396                 case IPM_RULE :
397                         a->ac_rule = o->o_num;
398                         break;
399                 case IPM_RESULT :
400                         if (!strcasecmp(o->o_str, "pass"))
401                                 a->ac_result = IPMR_PASS;
402                         else if (!strcasecmp(o->o_str, "block"))
403                                 a->ac_result = IPMR_BLOCK;
404                         else if (!strcasecmp(o->o_str, "nomatch"))
405                                 a->ac_result = IPMR_NOMATCH;
406                         else if (!strcasecmp(o->o_str, "log"))
407                                 a->ac_result = IPMR_LOG;
408                         break;
409                 case IPM_SECOND :
410                         a->ac_second = o->o_num;
411                         break;
412                 case IPM_SRCIP :
413                         a->ac_sip = o->o_ip.s_addr;
414                         a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
415                         break;
416                 case IPM_SRCPORT :
417                         a->ac_sport = htons(o->o_num);
418                         break;
419                 case IPM_SAVE :
420                         if (a->ac_savefile != NULL) {
421                                 fprintf(stderr, "%s redfined on line %d\n",
422                                         yykeytostr(o->o_type), yylineNum);
423                                 break;
424                         }
425                         a->ac_savefile = strdup(o->o_str);
426                         a->ac_savefp = fopen(o->o_str, "a");
427                         a->ac_dflag |= o->o_num & IPMDO_SAVERAW;
428                         break;
429                 case IPM_SYSLOG :
430                         if (a->ac_syslog != 0) {
431                                 fprintf(stderr, "%s redfined on line %d\n",
432                                         yykeytostr(o->o_type), yylineNum);
433                                 break;
434                         }
435                         a->ac_syslog = 1;
436                         break;
437                 case IPM_TYPE :
438                         a->ac_type = o->o_num;
439                         break;
440                 case IPM_WITH :
441                         break;
442                 default :
443                         break;
444                 }
445
446                 olist = o->o_next;
447                 if (o->o_str != NULL)
448                         free(o->o_str);
449                 free(o);
450         }
451         a->ac_next = alist;
452         alist = a;
453 }
454
455
456 int check_action(buf, log, opts, lvl)
457 char *buf, *log;
458 int opts, lvl;
459 {
460         ipmon_action_t *a;
461         struct timeval tv;
462         ipflog_t *ipf;
463         tcphdr_t *tcp;
464         iplog_t *ipl;
465         int matched;
466         u_long t1;
467         ip_t *ip;
468
469         matched = 0;
470         ipl = (iplog_t *)buf;
471         ipf = (ipflog_t *)(ipl +1);
472         ip = (ip_t *)(ipf + 1);
473         tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
474
475         for (a = alist; a != NULL; a = a->ac_next) {
476                 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
477                         if (a->ac_direction == IPM_IN) {
478                                 if ((ipf->fl_flags & FR_INQUE) == 0)
479                                         continue;
480                         } else if (a->ac_direction == IPM_OUT) {
481                                 if ((ipf->fl_flags & FR_OUTQUE) == 0)
482                                         continue;
483                         }
484                 }
485
486                 if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic))
487                         continue;
488
489                 if ((a->ac_mflag & IPMAC_EVERY) != 0) {
490                         gettimeofday(&tv, NULL);
491                         t1 = tv.tv_sec - a->ac_lastsec;
492                         if (tv.tv_usec <= a->ac_lastusec)
493                                 t1--;
494                         if (a->ac_second != 0) {
495                                 if (t1 < a->ac_second)
496                                         continue;
497                                 a->ac_lastsec = tv.tv_sec;
498                                 a->ac_lastusec = tv.tv_usec;
499                         }
500
501                         if (a->ac_packet != 0) {
502                                 if (a->ac_pktcnt == 0)
503                                         a->ac_pktcnt++;
504                                 else if (a->ac_pktcnt == a->ac_packet) {
505                                         a->ac_pktcnt = 0;
506                                         continue;
507                                 } else {
508                                         a->ac_pktcnt++;
509                                         continue;
510                                 }
511                         }
512                 }
513
514                 if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
515                         if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip)
516                                 continue;
517                 }
518
519                 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
520                         if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
521                                 continue;
522                         if (tcp->th_dport != a->ac_dport)
523                                 continue;
524                 }
525
526                 if ((a->ac_mflag & IPMAC_GROUP) != 0) {
527                         if (strncmp(a->ac_group, ipf->fl_group,
528                                     FR_GROUPLEN) != 0)
529                                 continue;
530                 }
531
532                 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
533                         if (strcmp(a->ac_iface, ipf->fl_ifname))
534                                 continue;
535                 }
536
537                 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
538                         if (a->ac_proto != ip->ip_p)
539                                 continue;
540                 }
541
542                 if ((a->ac_mflag & IPMAC_RESULT) != 0) {
543                         if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
544                                 if (a->ac_result != IPMR_NOMATCH)
545                                         continue;
546                         } else if (FR_ISPASS(ipf->fl_flags)) {
547                                 if (a->ac_result != IPMR_PASS)
548                                         continue;
549                         } else if (FR_ISBLOCK(ipf->fl_flags)) {
550                                 if (a->ac_result != IPMR_BLOCK)
551                                         continue;
552                         } else {        /* Log only */
553                                 if (a->ac_result != IPMR_LOG)
554                                         continue;
555                         }
556                 }
557
558                 if ((a->ac_mflag & IPMAC_RULE) != 0) {
559                         if (a->ac_rule != ipf->fl_rule)
560                                 continue;
561                 }
562
563                 if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
564                         if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip)
565                                 continue;
566                 }
567
568                 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
569                         if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
570                                 continue;
571                         if (tcp->th_sport != a->ac_sport)
572                                 continue;
573                 }
574
575                 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
576                         if (a->ac_logtag != ipf->fl_logtag)
577                                 continue;
578                 }
579
580                 if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
581                         if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
582                                     IPFTAG_LEN) != 0)
583                                 continue;
584                 }
585
586                 matched = 1;
587
588                 /*
589                  * It matched so now execute the command
590                  */
591                 if (a->ac_syslog != 0) {
592                         syslog(lvl, "%s", log);
593                 }
594
595                 if (a->ac_savefp != NULL) {
596                         if (a->ac_dflag & IPMDO_SAVERAW)
597                                 fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp);
598                         else
599                                 fputs(log, a->ac_savefp);
600                 }
601
602                 if (a->ac_exec != NULL) {
603                         switch (fork())
604                         {
605                         case 0 :
606                         {
607                                 FILE *pi;
608
609                                 pi = popen(a->ac_run, "w");
610                                 if (pi != NULL) {
611                                         fprintf(pi, "%s\n", log);
612                                         if ((opts & OPT_HEXHDR) != 0) {
613                                                 dumphex(pi, 0, buf,
614                                                         sizeof(*ipl) +
615                                                         sizeof(*ipf));
616                                         }
617                                         if ((opts & OPT_HEXBODY) != 0) {
618                                                 dumphex(pi, 0, (char *)ip,
619                                                         ipf->fl_hlen +
620                                                         ipf->fl_plen);
621                                         }
622                                         pclose(pi);
623                                 }
624                                 exit(1);
625                         }
626                         case -1 :
627                                 break;
628                         default :
629                                 break;
630                         }
631                 }
632         }
633
634         return matched;
635 }
636
637
638 static void free_action(a)
639 ipmon_action_t *a;
640 {
641         if (a->ac_savefile != NULL) {
642                 free(a->ac_savefile);
643                 a->ac_savefile = NULL;
644         }
645         if (a->ac_savefp != NULL) {
646                 fclose(a->ac_savefp);
647                 a->ac_savefp = NULL;
648         }
649         if (a->ac_exec != NULL) {
650                 free(a->ac_exec);
651                 if (a->ac_run == a->ac_exec)
652                         a->ac_run = NULL;
653                 a->ac_exec = NULL;
654         }
655         if (a->ac_run != NULL) {
656                 free(a->ac_run);
657                 a->ac_run = NULL;
658         }
659         if (a->ac_iface != NULL) {
660                 free(a->ac_iface);
661                 a->ac_iface = NULL;
662         }
663         a->ac_next = NULL;
664         free(a);
665 }
666
667
668 int load_config(file)
669 char *file;
670 {
671         ipmon_action_t *a;
672         FILE *fp;
673         char *s;
674
675         s = getenv("YYDEBUG");
676         if (s != NULL)
677                 yydebug = atoi(s);
678         else
679                 yydebug = 0;
680
681         while ((a = alist) != NULL) {
682                 alist = a->ac_next;
683                 free_action(a);
684         }
685
686         yylineNum = 1;
687
688         (void) yysettab(yywords);
689
690         fp = fopen(file, "r");
691         if (!fp) {
692                 perror("load_config:fopen:");
693                 return -1;
694         }
695         yyin = fp;
696         while (!feof(fp))
697                 yyparse();
698         fclose(fp);
699         return 0;
700 }