1 /*        $NetBSD: ipmon_y.y,v 1.2 2012/10/21 22:57:48 christos Exp $ */
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 *
new_opt(type)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
build_action(olist,todo)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
check_action(buf,log,opts,lvl)433 check_action(buf, log, opts, lvl)
434           const 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 = (char *)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
free_action(a)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
load_config(file)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
unload_config()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
dump_config()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
print_action(a)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 *
add_doing(saver)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
find_doing(string)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 *
build_doing(target,options)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
print_match(a)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
install_saver(name,path)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 }
1053