]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ipfilter/tools/ipmon_y.y
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ipfilter / tools / ipmon_y.y
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2012 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 #include <dlfcn.h>
17
18 #define YYDEBUG 1
19
20 extern  void    yyerror __P((char *));
21 extern  int     yyparse __P((void));
22 extern  int     yylex __P((void));
23 extern  int     yydebug;
24 extern  FILE    *yyin;
25 extern  int     yylineNum;
26 extern  int     ipmonopts;
27
28 typedef struct  opt_s   {
29         struct  opt_s   *o_next;
30         int             o_line;
31         int             o_type;
32         int             o_num;
33         char            *o_str;
34         struct in_addr  o_ip;
35         int             o_logfac;
36         int             o_logpri;
37 } opt_t;
38
39 static  void    build_action __P((opt_t *, ipmon_doing_t *));
40 static  opt_t   *new_opt __P((int));
41 static  void    free_action __P((ipmon_action_t *));
42 static  void    print_action __P((ipmon_action_t *));
43 static  int     find_doing __P((char *));
44 static  ipmon_doing_t *build_doing __P((char *, char *));
45 static  void    print_match __P((ipmon_action_t *));
46 static  int     install_saver __P((char *, char *));
47
48 static  ipmon_action_t  *alist = NULL;
49
50 ipmon_saver_int_t       *saverlist = NULL;
51 %}
52
53 %union  {
54         char    *str;
55         u_32_t  num;
56         struct in_addr  addr;
57         struct opt_s    *opt;
58         union   i6addr  ip6;
59         struct ipmon_doing_s    *ipmd;
60 }
61
62 %token  <num>   YY_NUMBER YY_HEX
63 %token  <str>   YY_STR
64 %token  <ip6>   YY_IPV6
65 %token  YY_COMMENT
66 %token  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
67 %token  YY_RANGE_OUT YY_RANGE_IN
68
69 %token  IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
70 %token  IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION
71 %token  IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
72 %token  IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
73 %token  IPM_DO IPM_DOING IPM_TYPE IPM_NAT
74 %token  IPM_STATE IPM_NATTAG IPM_IPF
75 %type   <addr> ipv4
76 %type   <opt> direction dstip dstport every group interface
77 %type   <opt> protocol result rule srcip srcport logtag matching
78 %type   <opt> matchopt nattag type
79 %type   <num> typeopt
80 %type   <ipmd> doopt doing
81
82 %%
83 file:   action
84         | file action
85         ;
86
87 action: line ';'
88         | assign ';'
89         | IPM_COMMENT
90         | YY_COMMENT
91         ;
92
93 line:   IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}'
94                                                 { build_action($3, $8);
95                                                   resetlexer();
96                                                 }
97         | IPM_LOADACTION YY_STR YY_STR  { if (install_saver($2, $3))
98                                                 yyerror("install saver");
99                                         }
100         ;
101
102 assign: YY_STR assigning YY_STR                 { set_variable($1, $3);
103                                                   resetlexer();
104                                                   free($1);
105                                                   free($3);
106                                                   yyvarnext = 0;
107                                                 }
108         ;
109
110 assigning:
111         '='                                     { yyvarnext = 1; }
112         ;
113
114 matching:
115         matchopt                                { $$ = $1; }
116         | matchopt ',' matching                 { $1->o_next = $3; $$ = $1; }
117         ;
118
119 matchopt:
120         direction                               { $$ = $1; }
121         | dstip                                 { $$ = $1; }
122         | dstport                               { $$ = $1; }
123         | every                                 { $$ = $1; }
124         | group                                 { $$ = $1; }
125         | interface                             { $$ = $1; }
126         | protocol                              { $$ = $1; }
127         | result                                { $$ = $1; }
128         | rule                                  { $$ = $1; }
129         | srcip                                 { $$ = $1; }
130         | srcport                               { $$ = $1; }
131         | logtag                                { $$ = $1; }
132         | nattag                                { $$ = $1; }
133         | type                                  { $$ = $1; }
134         ;
135
136 doing:
137         doopt                                   { $$ = $1; }
138         | doopt ',' doing                       { $1->ipmd_next = $3; $$ = $1; }
139         ;
140
141 doopt:
142         YY_STR                          { if (find_doing($1) != IPM_DOING)
143                                                 yyerror("unknown action");
144                                         }
145         '(' YY_STR ')'                  { $$ = build_doing($1, $4);
146                                           if ($$ == NULL)
147                                                 yyerror("action building");
148                                         }
149         | YY_STR                        { if (find_doing($1) == IPM_DOING)
150                                                 $$ = build_doing($1, NULL);
151                                         }
152         ;
153
154 direction:
155         IPM_DIRECTION '=' IPM_IN                { $$ = new_opt(IPM_DIRECTION);
156                                                   $$->o_num = IPM_IN; }
157         | IPM_DIRECTION '=' IPM_OUT             { $$ = new_opt(IPM_DIRECTION);
158                                                   $$->o_num = IPM_OUT; }
159         ;
160
161 dstip:  IPM_DSTIP '=' ipv4 '/' YY_NUMBER        { $$ = new_opt(IPM_DSTIP);
162                                                   $$->o_ip = $3;
163                                                   $$->o_num = $5; }
164         ;
165
166 dstport:
167         IPM_DSTPORT '=' YY_NUMBER               { $$ = new_opt(IPM_DSTPORT);
168                                                   $$->o_num = $3; }
169         | IPM_DSTPORT '=' YY_STR                { $$ = new_opt(IPM_DSTPORT);
170                                                   $$->o_str = $3; }
171         ;
172
173 every:  IPM_EVERY IPM_SECOND                    { $$ = new_opt(IPM_SECOND);
174                                                   $$->o_num = 1; }
175         | IPM_EVERY YY_NUMBER IPM_SECONDS       { $$ = new_opt(IPM_SECOND);
176                                                   $$->o_num = $2; }
177         | IPM_EVERY IPM_PACKET                  { $$ = new_opt(IPM_PACKET);
178                                                   $$->o_num = 1; }
179         | IPM_EVERY YY_NUMBER IPM_PACKETS       { $$ = new_opt(IPM_PACKET);
180                                                   $$->o_num = $2; }
181         ;
182
183 group:  IPM_GROUP '=' YY_NUMBER                 { $$ = new_opt(IPM_GROUP);
184                                                   $$->o_num = $3; }
185         | IPM_GROUP '=' YY_STR                  { $$ = new_opt(IPM_GROUP);
186                                                   $$->o_str = $3; }
187         ;
188
189 interface:
190         IPM_INTERFACE '=' YY_STR                { $$ = new_opt(IPM_INTERFACE);
191                                                   $$->o_str = $3; }
192         ;
193
194 logtag: IPM_LOGTAG '=' YY_NUMBER                { $$ = new_opt(IPM_LOGTAG);
195                                                   $$->o_num = $3; }
196         ;
197
198 nattag: IPM_NATTAG '=' YY_STR                   { $$ = new_opt(IPM_NATTAG);
199                                                   $$->o_str = $3; }
200         ;
201
202 protocol:
203         IPM_PROTOCOL '=' YY_NUMBER              { $$ = new_opt(IPM_PROTOCOL);
204                                                   $$->o_num = $3; }
205         | IPM_PROTOCOL '=' YY_STR               { $$ = new_opt(IPM_PROTOCOL);
206                                                   $$->o_num = getproto($3);
207                                                   free($3);
208                                                 }
209         ;
210
211 result: IPM_RESULT '=' YY_STR                   { $$ = new_opt(IPM_RESULT);
212                                                   $$->o_str = $3; }
213         ;
214
215 rule:   IPM_RULE '=' YY_NUMBER                  { $$ = new_opt(IPM_RULE);
216                                                   $$->o_num = YY_NUMBER; }
217         ;
218
219 srcip:  IPM_SRCIP '=' ipv4 '/' YY_NUMBER        { $$ = new_opt(IPM_SRCIP);
220                                                   $$->o_ip = $3;
221                                                   $$->o_num = $5; }
222         ;
223
224 srcport:
225         IPM_SRCPORT '=' YY_NUMBER               { $$ = new_opt(IPM_SRCPORT);
226                                                   $$->o_num = $3; }
227         | IPM_SRCPORT '=' YY_STR                { $$ = new_opt(IPM_SRCPORT);
228                                                   $$->o_str = $3; }
229         ;
230
231 type:   IPM_TYPE '=' typeopt                    { $$ = new_opt(IPM_TYPE);
232                                                   $$->o_num = $3; }
233         ;
234
235 typeopt:
236         IPM_IPF                                 { $$ = IPL_MAGIC; }
237         | IPM_NAT                               { $$ = IPL_MAGIC_NAT; }
238         | IPM_STATE                             { $$ = IPL_MAGIC_STATE; }
239         ;
240
241
242
243 ipv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
244                 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
245                         yyerror("Invalid octet string for IP address");
246                         return 0;
247                   }
248                   $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
249                   $$.s_addr = htonl($$.s_addr);
250                 }
251 %%
252 static  struct  wordtab yywords[] = {
253         { "body",       IPM_BODY },
254         { "direction",  IPM_DIRECTION },
255         { "do",         IPM_DO },
256         { "dstip",      IPM_DSTIP },
257         { "dstport",    IPM_DSTPORT },
258         { "every",      IPM_EVERY },
259         { "group",      IPM_GROUP },
260         { "in",         IPM_IN },
261         { "interface",  IPM_INTERFACE },
262         { "ipf",        IPM_IPF },
263         { "load_action",IPM_LOADACTION },
264         { "logtag",     IPM_LOGTAG },
265         { "match",      IPM_MATCH },
266         { "nat",        IPM_NAT },
267         { "nattag",     IPM_NATTAG },
268         { "no",         IPM_NO },
269         { "out",        IPM_OUT },
270         { "packet",     IPM_PACKET },
271         { "packets",    IPM_PACKETS },
272         { "protocol",   IPM_PROTOCOL },
273         { "result",     IPM_RESULT },
274         { "rule",       IPM_RULE },
275         { "second",     IPM_SECOND },
276         { "seconds",    IPM_SECONDS },
277         { "srcip",      IPM_SRCIP },
278         { "srcport",    IPM_SRCPORT },
279         { "state",      IPM_STATE },
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 *
305 new_opt(type)
306         int type;
307 {
308         opt_t *o;
309
310         o = (opt_t *)calloc(1, sizeof(*o));
311         o->o_type = type;
312         o->o_line = yylineNum;
313         o->o_logfac = -1;
314         o->o_logpri = -1;
315         return o;
316 }
317
318 static void
319 build_action(olist, todo)
320         opt_t *olist;
321         ipmon_doing_t *todo;
322 {
323         ipmon_action_t *a;
324         opt_t *o;
325         int i;
326
327         a = (ipmon_action_t *)calloc(1, sizeof(*a));
328         if (a == NULL)
329                 return;
330
331         while ((o = olist) != NULL) {
332                 /*
333                  * Check to see if the same comparator is being used more than
334                  * once per matching statement.
335                  */
336                 for (i = 0; macflags[i][0]; i++)
337                         if (macflags[i][0] == o->o_type)
338                                 break;
339                 if (macflags[i][1] & a->ac_mflag) {
340                         fprintf(stderr, "%s redfined on line %d\n",
341                                 yykeytostr(o->o_type), yylineNum);
342                         if (o->o_str != NULL)
343                                 free(o->o_str);
344                         olist = o->o_next;
345                         free(o);
346                         continue;
347                 }
348
349                 a->ac_mflag |= macflags[i][1];
350
351                 switch (o->o_type)
352                 {
353                 case IPM_DIRECTION :
354                         a->ac_direction = o->o_num;
355                         break;
356                 case IPM_DSTIP :
357                         a->ac_dip = o->o_ip.s_addr;
358                         a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
359                         break;
360                 case IPM_DSTPORT :
361                         a->ac_dport = htons(o->o_num);
362                         break;
363                 case IPM_INTERFACE :
364                         a->ac_iface = o->o_str;
365                         o->o_str = NULL;
366                         break;
367                 case IPM_GROUP :
368                         if (o->o_str != NULL)
369                                 strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
370                         else
371                                 sprintf(a->ac_group, "%d", o->o_num);
372                         break;
373                 case IPM_LOGTAG :
374                         a->ac_logtag = o->o_num;
375                         break;
376                 case IPM_NATTAG :
377                         strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
378                         break;
379                 case IPM_PACKET :
380                         a->ac_packet = o->o_num;
381                         break;
382                 case IPM_PROTOCOL :
383                         a->ac_proto = o->o_num;
384                         break;
385                 case IPM_RULE :
386                         a->ac_rule = o->o_num;
387                         break;
388                 case IPM_RESULT :
389                         if (!strcasecmp(o->o_str, "pass"))
390                                 a->ac_result = IPMR_PASS;
391                         else if (!strcasecmp(o->o_str, "block"))
392                                 a->ac_result = IPMR_BLOCK;
393                         else if (!strcasecmp(o->o_str, "nomatch"))
394                                 a->ac_result = IPMR_NOMATCH;
395                         else if (!strcasecmp(o->o_str, "log"))
396                                 a->ac_result = IPMR_LOG;
397                         break;
398                 case IPM_SECOND :
399                         a->ac_second = o->o_num;
400                         break;
401                 case IPM_SRCIP :
402                         a->ac_sip = o->o_ip.s_addr;
403                         a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
404                         break;
405                 case IPM_SRCPORT :
406                         a->ac_sport = htons(o->o_num);
407                         break;
408                 case IPM_TYPE :
409                         a->ac_type = o->o_num;
410                         break;
411                 case IPM_WITH :
412                         break;
413                 default :
414                         break;
415                 }
416
417                 olist = o->o_next;
418                 if (o->o_str != NULL)
419                         free(o->o_str);
420                 free(o);
421         }
422
423         a->ac_doing = todo;
424         a->ac_next = alist;
425         alist = a;
426
427         if (ipmonopts & IPMON_VERBOSE)
428                 print_action(a);
429 }
430
431
432 int
433 check_action(buf, log, opts, lvl)
434         char *buf, *log;
435         int opts, lvl;
436 {
437         ipmon_action_t *a;
438         struct timeval tv;
439         ipmon_doing_t *d;
440         ipmon_msg_t msg;
441         ipflog_t *ipf;
442         tcphdr_t *tcp;
443         iplog_t *ipl;
444         int matched;
445         u_long t1;
446         ip_t *ip;
447
448         matched = 0;
449         ipl = (iplog_t *)buf;
450         ipf = (ipflog_t *)(ipl +1);
451         ip = (ip_t *)(ipf + 1);
452         tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
453
454         msg.imm_data = ipl;
455         msg.imm_dsize = ipl->ipl_dsize;
456         msg.imm_when = ipl->ipl_time.tv_sec;
457         msg.imm_msg = log;
458         msg.imm_msglen = strlen(log);
459         msg.imm_loglevel = lvl;
460
461         for (a = alist; a != NULL; a = a->ac_next) {
462                 verbose(0, "== checking config rule\n");
463                 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
464                         if (a->ac_direction == IPM_IN) {
465                                 if ((ipf->fl_flags & FR_INQUE) == 0) {
466                                         verbose(8, "-- direction not in\n");
467                                         continue;
468                                 }
469                         } else if (a->ac_direction == IPM_OUT) {
470                                 if ((ipf->fl_flags & FR_OUTQUE) == 0) {
471                                         verbose(8, "-- direction not out\n");
472                                         continue;
473                                 }
474                         }
475                 }
476
477                 if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) {
478                         verbose(8, "-- type mismatch\n");
479                         continue;
480                 }
481
482                 if ((a->ac_mflag & IPMAC_EVERY) != 0) {
483                         gettimeofday(&tv, NULL);
484                         t1 = tv.tv_sec - a->ac_lastsec;
485                         if (tv.tv_usec <= a->ac_lastusec)
486                                 t1--;
487                         if (a->ac_second != 0) {
488                                 if (t1 < a->ac_second) {
489                                         verbose(8, "-- too soon\n");
490                                         continue;
491                                 }
492                                 a->ac_lastsec = tv.tv_sec;
493                                 a->ac_lastusec = tv.tv_usec;
494                         }
495
496                         if (a->ac_packet != 0) {
497                                 if (a->ac_pktcnt == 0)
498                                         a->ac_pktcnt++;
499                                 else if (a->ac_pktcnt == a->ac_packet) {
500                                         a->ac_pktcnt = 0;
501                                         verbose(8, "-- packet count\n");
502                                         continue;
503                                 } else {
504                                         a->ac_pktcnt++;
505                                         verbose(8, "-- packet count\n");
506                                         continue;
507                                 }
508                         }
509                 }
510
511                 if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
512                         if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) {
513                                 verbose(8, "-- dstip wrong\n");
514                                 continue;
515                         }
516                 }
517
518                 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
519                         if (ip->ip_p != IPPROTO_UDP &&
520                             ip->ip_p != IPPROTO_TCP) {
521                                 verbose(8, "-- not port protocol\n");
522                                 continue;
523                         }
524                         if (tcp->th_dport != a->ac_dport) {
525                                 verbose(8, "-- dport mismatch\n");
526                                 continue;
527                         }
528                 }
529
530                 if ((a->ac_mflag & IPMAC_GROUP) != 0) {
531                         if (strncmp(a->ac_group, ipf->fl_group,
532                                     FR_GROUPLEN) != 0) {
533                                 verbose(8, "-- group mismatch\n");
534                                 continue;
535                         }
536                 }
537
538                 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
539                         if (strcmp(a->ac_iface, ipf->fl_ifname)) {
540                                 verbose(8, "-- ifname mismatch\n");
541                                 continue;
542                         }
543                 }
544
545                 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
546                         if (a->ac_proto != ip->ip_p) {
547                                 verbose(8, "-- protocol mismatch\n");
548                                 continue;
549                         }
550                 }
551
552                 if ((a->ac_mflag & IPMAC_RESULT) != 0) {
553                         if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
554                                 if (a->ac_result != IPMR_NOMATCH) {
555                                         verbose(8, "-- ff-flags mismatch\n");
556                                         continue;
557                                 }
558                         } else if (FR_ISPASS(ipf->fl_flags)) {
559                                 if (a->ac_result != IPMR_PASS) {
560                                         verbose(8, "-- pass mismatch\n");
561                                         continue;
562                                 }
563                         } else if (FR_ISBLOCK(ipf->fl_flags)) {
564                                 if (a->ac_result != IPMR_BLOCK) {
565                                         verbose(8, "-- block mismatch\n");
566                                         continue;
567                                 }
568                         } else {        /* Log only */
569                                 if (a->ac_result != IPMR_LOG) {
570                                         verbose(8, "-- log mismatch\n");
571                                         continue;
572                                 }
573                         }
574                 }
575
576                 if ((a->ac_mflag & IPMAC_RULE) != 0) {
577                         if (a->ac_rule != ipf->fl_rule) {
578                                 verbose(8, "-- rule mismatch\n");
579                                 continue;
580                         }
581                 }
582
583                 if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
584                         if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) {
585                                 verbose(8, "-- srcip mismatch\n");
586                                 continue;
587                         }
588                 }
589
590                 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
591                         if (ip->ip_p != IPPROTO_UDP &&
592                             ip->ip_p != IPPROTO_TCP) {
593                                 verbose(8, "-- port protocol mismatch\n");
594                                 continue;
595                         }
596                         if (tcp->th_sport != a->ac_sport) {
597                                 verbose(8, "-- sport mismatch\n");
598                                 continue;
599                         }
600                 }
601
602                 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
603                         if (a->ac_logtag != ipf->fl_logtag) {
604                                 verbose(8, "-- logtag %d != %d\n",
605                                         a->ac_logtag, ipf->fl_logtag);
606                                 continue;
607                         }
608                 }
609
610                 if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
611                         if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
612                                     IPFTAG_LEN) != 0) {
613                                 verbose(8, "-- nattag mismatch\n");
614                                 continue;
615                         }
616                 }
617
618                 matched = 1;
619                 verbose(8, "++ matched\n");
620
621                 /*
622                  * It matched so now perform the saves
623                  */
624                 for (d = a->ac_doing; d != NULL; d = d->ipmd_next)
625                         (*d->ipmd_store)(d->ipmd_token, &msg);
626         }
627
628         return matched;
629 }
630
631
632 static void
633 free_action(a)
634         ipmon_action_t *a;
635 {
636         ipmon_doing_t *d;
637
638         while ((d = a->ac_doing) != NULL) {
639                 a->ac_doing = d->ipmd_next;
640                 (*d->ipmd_saver->ims_destroy)(d->ipmd_token);
641                 free(d);
642         }
643
644         if (a->ac_iface != NULL) {
645                 free(a->ac_iface);
646                 a->ac_iface = NULL;
647         }
648         a->ac_next = NULL;
649         free(a);
650 }
651
652
653 int
654 load_config(file)
655         char *file;
656 {
657         FILE *fp;
658         char *s;
659
660         unload_config();
661
662         s = getenv("YYDEBUG");
663         if (s != NULL)
664                 yydebug = atoi(s);
665         else
666                 yydebug = 0;
667
668         yylineNum = 1;
669
670         (void) yysettab(yywords);
671
672         fp = fopen(file, "r");
673         if (!fp) {
674                 perror("load_config:fopen:");
675                 return -1;
676         }
677         yyin = fp;
678         while (!feof(fp))
679                 yyparse();
680         fclose(fp);
681         return 0;
682 }
683
684
685 void
686 unload_config()
687 {
688         ipmon_saver_int_t *sav, **imsip;
689         ipmon_saver_t *is;
690         ipmon_action_t *a;
691
692         while ((a = alist) != NULL) {
693                 alist = a->ac_next;
694                 free_action(a);
695         }
696
697         /*
698          * Look for savers that have been added in dynamically from the
699          * configuration file.
700          */
701         for (imsip = &saverlist; (sav = *imsip) != NULL; ) {
702                 if (sav->imsi_handle == NULL)
703                         imsip = &sav->imsi_next;
704                 else {
705                         dlclose(sav->imsi_handle);
706
707                         *imsip = sav->imsi_next;
708                         is = sav->imsi_stor;
709                         free(sav);
710
711                         free(is->ims_name);
712                         free(is);
713                 }
714         }
715 }
716
717
718 void
719 dump_config()
720 {
721         ipmon_action_t *a;
722
723         for (a = alist; a != NULL; a = a->ac_next) {
724                 print_action(a);
725
726                 printf("#\n");
727         }
728 }
729
730
731 static void
732 print_action(a)
733         ipmon_action_t *a;
734 {
735         ipmon_doing_t *d;
736
737         printf("match { ");
738         print_match(a);
739         printf("; }\n");
740         printf("do {");
741         for (d = a->ac_doing; d != NULL; d = d->ipmd_next) {
742                 printf("%s", d->ipmd_saver->ims_name);
743                 if (d->ipmd_saver->ims_print != NULL) {
744                         printf("(\"");
745                         (*d->ipmd_saver->ims_print)(d->ipmd_token);
746                         printf("\")");
747                 }
748                 printf(";");
749         }
750         printf("};\n");
751 }
752
753
754 void *
755 add_doing(saver)
756         ipmon_saver_t *saver;
757 {
758         ipmon_saver_int_t *it;
759
760         if (find_doing(saver->ims_name) == IPM_DOING)
761                 return NULL;
762
763         it = calloc(1, sizeof(*it));
764         if (it == NULL)
765                 return NULL;
766         it->imsi_stor = saver;
767         it->imsi_next = saverlist;
768         saverlist = it;
769         return it;
770 }
771
772
773 static int
774 find_doing(string)
775         char *string;
776 {
777         ipmon_saver_int_t *it;
778
779         for (it = saverlist; it != NULL; it = it->imsi_next) {
780                 if (!strcmp(it->imsi_stor->ims_name, string))
781                         return IPM_DOING;
782         }
783         return 0;
784 }
785
786
787 static ipmon_doing_t *
788 build_doing(target, options)
789         char *target;
790         char *options;
791 {
792         ipmon_saver_int_t *it;
793         char *strarray[2];
794         ipmon_doing_t *d, *d1;
795         ipmon_action_t *a;
796         ipmon_saver_t *save;
797
798         d = calloc(1, sizeof(*d));
799         if (d == NULL)
800                 return NULL;
801
802         for (it = saverlist; it != NULL; it = it->imsi_next) {
803                 if (!strcmp(it->imsi_stor->ims_name, target))
804                         break;
805         }
806         if (it == NULL) {
807                 free(d);
808                 return NULL;
809         }
810
811         strarray[0] = options;
812         strarray[1] = NULL;
813
814         d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray);
815         if (d->ipmd_token == NULL) {
816                 free(d);
817                 return NULL;
818         }
819
820         save = it->imsi_stor;
821         d->ipmd_saver = save;
822         d->ipmd_store = it->imsi_stor->ims_store;
823
824         /*
825          * Look for duplicate do-things that need to be dup'd
826          */
827         for (a = alist; a != NULL; a = a->ac_next) {
828                 for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) {
829                         if (save != d1->ipmd_saver)
830                                 continue;
831                         if (save->ims_match == NULL || save->ims_dup == NULL)
832                                 continue;
833                         if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token))
834                                 continue;
835
836                         (*d->ipmd_saver->ims_destroy)(d->ipmd_token);
837                         d->ipmd_token = (*save->ims_dup)(d1->ipmd_token);
838                         break;
839                 }
840         }
841
842         return d;
843 }
844
845
846 static void
847 print_match(a)
848         ipmon_action_t *a;
849 {
850         char *coma = "";
851
852         if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
853                 printf("direction = ");
854                 if (a->ac_direction == IPM_IN)
855                         printf("in");
856                 else if (a->ac_direction == IPM_OUT)
857                         printf("out");
858                 coma = ", ";
859         }
860
861         if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
862                 printf("%sdstip = ", coma);
863                 printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk);
864                 coma = ", ";
865         }
866
867         if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
868                 printf("%sdstport = %hu", coma, ntohs(a->ac_dport));
869                 coma = ", ";
870         }
871
872         if ((a->ac_mflag & IPMAC_GROUP) != 0) {
873                 char group[FR_GROUPLEN+1];
874
875                 strncpy(group, a->ac_group, FR_GROUPLEN);
876                 group[FR_GROUPLEN] = '\0';
877                 printf("%sgroup = %s", coma, group);
878                 coma = ", ";
879         }
880
881         if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
882                 printf("%siface = %s", coma, a->ac_iface);
883                 coma = ", ";
884         }
885
886         if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
887                 printf("%slogtag = %u", coma, a->ac_logtag);
888                 coma = ", ";
889         }
890
891         if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
892                 char tag[17];
893
894                 strncpy(tag, a->ac_nattag, 16);
895                 tag[16] = '\0';
896                 printf("%snattag = %s", coma, tag);
897                 coma = ", ";
898         }
899
900         if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
901                 printf("%sprotocol = %u", coma, a->ac_proto);
902                 coma = ", ";
903         }
904
905         if ((a->ac_mflag & IPMAC_RESULT) != 0) {
906                 printf("%sresult = ", coma);
907                 switch (a->ac_result)
908                 {
909                 case IPMR_LOG :
910                         printf("log");
911                         break;
912                 case IPMR_PASS :
913                         printf("pass");
914                         break;
915                 case IPMR_BLOCK :
916                         printf("block");
917                         break;
918                 case IPMR_NOMATCH :
919                         printf("nomatch");
920                         break;
921                 }
922                 coma = ", ";
923         }
924
925         if ((a->ac_mflag & IPMAC_RULE) != 0) {
926                 printf("%srule = %u", coma, a->ac_rule);
927                 coma = ", ";
928         }
929
930         if ((a->ac_mflag & IPMAC_EVERY) != 0) {
931                 if (a->ac_packet > 1) {
932                         printf("%severy %d packets", coma, a->ac_packet);
933                         coma = ", ";
934                 } else if (a->ac_packet == 1) {
935                         printf("%severy packet", coma);
936                         coma = ", ";
937                 }
938                 if (a->ac_second > 1) {
939                         printf("%severy %d seconds", coma, a->ac_second);
940                         coma = ", ";
941                 } else if (a->ac_second == 1) {
942                         printf("%severy second", coma);
943                         coma = ", ";
944                 }
945         }
946
947         if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
948                 printf("%ssrcip = ", coma);
949                 printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk);
950                 coma = ", ";
951         }
952
953         if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
954                 printf("%ssrcport = %hu", coma, ntohs(a->ac_sport));
955                 coma = ", ";
956         }
957
958         if ((a->ac_mflag & IPMAC_TYPE) != 0) {
959                 printf("%stype = ", coma);
960                 switch (a->ac_type)
961                 {
962                 case IPL_LOGIPF :
963                         printf("ipf");
964                         break;
965                 case IPL_LOGSTATE :
966                         printf("state");
967                         break;
968                 case IPL_LOGNAT :
969                         printf("nat");
970                         break;
971                 }
972                 coma = ", ";
973         }
974
975         if ((a->ac_mflag & IPMAC_WITH) != 0) {
976                 printf("%swith ", coma);
977                 coma = ", ";
978         }
979 }
980
981
982 static int
983 install_saver(name, path)
984         char *name, *path;
985 {
986         ipmon_saver_int_t *isi;
987         ipmon_saver_t *is;
988         char nbuf[80];
989
990         if (find_doing(name) == IPM_DOING)
991                 return -1;
992
993         isi = calloc(1, sizeof(*isi));
994         if (isi == NULL)
995                 return -1;
996
997         is = calloc(1, sizeof(*is));
998         if (is == NULL)
999                 goto loaderror;
1000
1001         is->ims_name = name;
1002
1003 #ifdef RTLD_LAZY
1004         isi->imsi_handle = dlopen(path, RTLD_LAZY);
1005 #endif
1006 #ifdef DL_LAZY
1007         isi->imsi_handle = dlopen(path, DL_LAZY);
1008 #endif
1009
1010         if (isi->imsi_handle == NULL)
1011                 goto loaderror;
1012
1013         snprintf(nbuf, sizeof(nbuf), "%sdup", name);
1014         is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf);
1015
1016         snprintf(nbuf, sizeof(nbuf), "%sdestroy", name);
1017         is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf);
1018         if (is->ims_destroy == NULL)
1019                 goto loaderror;
1020
1021         snprintf(nbuf, sizeof(nbuf), "%smatch", name);
1022         is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf);
1023
1024         snprintf(nbuf, sizeof(nbuf), "%sparse", name);
1025         is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf);
1026         if (is->ims_parse == NULL)
1027                 goto loaderror;
1028
1029         snprintf(nbuf, sizeof(nbuf), "%sprint", name);
1030         is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf);
1031         if (is->ims_print == NULL)
1032                 goto loaderror;
1033
1034         snprintf(nbuf, sizeof(nbuf), "%sstore", name);
1035         is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf);
1036         if (is->ims_store == NULL)
1037                 goto loaderror;
1038
1039         isi->imsi_stor = is;
1040         isi->imsi_next = saverlist;
1041         saverlist = isi;
1042
1043         return 0;
1044
1045 loaderror:
1046         if (isi->imsi_handle != NULL)
1047                 dlclose(isi->imsi_handle);
1048         free(isi);
1049         if (is != NULL)
1050                 free(is);
1051         return -1;
1052 }