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(char *);
21 extern int yyparse(void);
22 extern int yylex(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(opt_t *, ipmon_doing_t *);
40 static opt_t *new_opt(int);
41 static void free_action(ipmon_action_t *);
42 static void print_action(ipmon_action_t *);
43 static int find_doing(char *);
44 static ipmon_doing_t *build_doing(char *, char *);
45 static void print_match(ipmon_action_t *);
46 static int install_saver(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(int type)305 new_opt(int type)
306 {
307 opt_t *o;
308
309 o = (opt_t *)calloc(1, sizeof(*o));
310 o->o_type = type;
311 o->o_line = yylineNum;
312 o->o_logfac = -1;
313 o->o_logpri = -1;
314 return(o);
315 }
316
317 static void
build_action(opt_t * olist,ipmon_doing_t * todo)318 build_action(opt_t *olist, ipmon_doing_t *todo)
319 {
320 ipmon_action_t *a;
321 opt_t *o;
322 int i;
323
324 a = (ipmon_action_t *)calloc(1, sizeof(*a));
325 if (a == NULL)
326 return;
327
328 while ((o = olist) != NULL) {
329 /*
330 * Check to see if the same comparator is being used more than
331 * once per matching statement.
332 */
333 for (i = 0; macflags[i][0]; i++)
334 if (macflags[i][0] == o->o_type)
335 break;
336 if (macflags[i][1] & a->ac_mflag) {
337 fprintf(stderr, "%s redfined on line %d\n",
338 yykeytostr(o->o_type), yylineNum);
339 if (o->o_str != NULL)
340 free(o->o_str);
341 olist = o->o_next;
342 free(o);
343 continue;
344 }
345
346 a->ac_mflag |= macflags[i][1];
347
348 switch (o->o_type)
349 {
350 case IPM_DIRECTION :
351 a->ac_direction = o->o_num;
352 break;
353 case IPM_DSTIP :
354 a->ac_dip = o->o_ip.s_addr;
355 a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
356 break;
357 case IPM_DSTPORT :
358 a->ac_dport = htons(o->o_num);
359 break;
360 case IPM_INTERFACE :
361 a->ac_iface = o->o_str;
362 o->o_str = NULL;
363 break;
364 case IPM_GROUP :
365 if (o->o_str != NULL)
366 strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
367 else
368 sprintf(a->ac_group, "%d", o->o_num);
369 break;
370 case IPM_LOGTAG :
371 a->ac_logtag = o->o_num;
372 break;
373 case IPM_NATTAG :
374 strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
375 break;
376 case IPM_PACKET :
377 a->ac_packet = o->o_num;
378 break;
379 case IPM_PROTOCOL :
380 a->ac_proto = o->o_num;
381 break;
382 case IPM_RULE :
383 a->ac_rule = o->o_num;
384 break;
385 case IPM_RESULT :
386 if (!strcasecmp(o->o_str, "pass"))
387 a->ac_result = IPMR_PASS;
388 else if (!strcasecmp(o->o_str, "block"))
389 a->ac_result = IPMR_BLOCK;
390 else if (!strcasecmp(o->o_str, "nomatch"))
391 a->ac_result = IPMR_NOMATCH;
392 else if (!strcasecmp(o->o_str, "log"))
393 a->ac_result = IPMR_LOG;
394 break;
395 case IPM_SECOND :
396 a->ac_second = o->o_num;
397 break;
398 case IPM_SRCIP :
399 a->ac_sip = o->o_ip.s_addr;
400 a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
401 break;
402 case IPM_SRCPORT :
403 a->ac_sport = htons(o->o_num);
404 break;
405 case IPM_TYPE :
406 a->ac_type = o->o_num;
407 break;
408 case IPM_WITH :
409 break;
410 default :
411 break;
412 }
413
414 olist = o->o_next;
415 if (o->o_str != NULL)
416 free(o->o_str);
417 free(o);
418 }
419
420 a->ac_doing = todo;
421 a->ac_next = alist;
422 alist = a;
423
424 if (ipmonopts & IPMON_VERBOSE)
425 print_action(a);
426 }
427
428
429 int
check_action(char * buf,char * log,int opts,int lvl)430 check_action(char *buf, char *log, int opts, int lvl)
431 {
432 ipmon_action_t *a;
433 struct timeval tv;
434 ipmon_doing_t *d;
435 ipmon_msg_t msg;
436 ipflog_t *ipf;
437 tcphdr_t *tcp;
438 iplog_t *ipl;
439 int matched;
440 u_long t1;
441 ip_t *ip;
442
443 matched = 0;
444 ipl = (iplog_t *)buf;
445 ipf = (ipflog_t *)(ipl +1);
446 ip = (ip_t *)(ipf + 1);
447 tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
448
449 msg.imm_data = ipl;
450 msg.imm_dsize = ipl->ipl_dsize;
451 msg.imm_when = ipl->ipl_time.tv_sec;
452 msg.imm_msg = log;
453 msg.imm_msglen = strlen(log);
454 msg.imm_loglevel = lvl;
455
456 for (a = alist; a != NULL; a = a->ac_next) {
457 verbose(0, "== checking config rule\n");
458 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
459 if (a->ac_direction == IPM_IN) {
460 if ((ipf->fl_flags & FR_INQUE) == 0) {
461 verbose(8, "-- direction not in\n");
462 continue;
463 }
464 } else if (a->ac_direction == IPM_OUT) {
465 if ((ipf->fl_flags & FR_OUTQUE) == 0) {
466 verbose(8, "-- direction not out\n");
467 continue;
468 }
469 }
470 }
471
472 if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) {
473 verbose(8, "-- type mismatch\n");
474 continue;
475 }
476
477 if ((a->ac_mflag & IPMAC_EVERY) != 0) {
478 gettimeofday(&tv, NULL);
479 t1 = tv.tv_sec - a->ac_lastsec;
480 if (tv.tv_usec <= a->ac_lastusec)
481 t1--;
482 if (a->ac_second != 0) {
483 if (t1 < a->ac_second) {
484 verbose(8, "-- too soon\n");
485 continue;
486 }
487 a->ac_lastsec = tv.tv_sec;
488 a->ac_lastusec = tv.tv_usec;
489 }
490
491 if (a->ac_packet != 0) {
492 if (a->ac_pktcnt == 0)
493 a->ac_pktcnt++;
494 else if (a->ac_pktcnt == a->ac_packet) {
495 a->ac_pktcnt = 0;
496 verbose(8, "-- packet count\n");
497 continue;
498 } else {
499 a->ac_pktcnt++;
500 verbose(8, "-- packet count\n");
501 continue;
502 }
503 }
504 }
505
506 if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
507 if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) {
508 verbose(8, "-- dstip wrong\n");
509 continue;
510 }
511 }
512
513 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
514 if (ip->ip_p != IPPROTO_UDP &&
515 ip->ip_p != IPPROTO_TCP) {
516 verbose(8, "-- not port protocol\n");
517 continue;
518 }
519 if (tcp->th_dport != a->ac_dport) {
520 verbose(8, "-- dport mismatch\n");
521 continue;
522 }
523 }
524
525 if ((a->ac_mflag & IPMAC_GROUP) != 0) {
526 if (strncmp(a->ac_group, ipf->fl_group,
527 FR_GROUPLEN) != 0) {
528 verbose(8, "-- group mismatch\n");
529 continue;
530 }
531 }
532
533 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
534 if (strcmp(a->ac_iface, ipf->fl_ifname)) {
535 verbose(8, "-- ifname mismatch\n");
536 continue;
537 }
538 }
539
540 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
541 if (a->ac_proto != ip->ip_p) {
542 verbose(8, "-- protocol mismatch\n");
543 continue;
544 }
545 }
546
547 if ((a->ac_mflag & IPMAC_RESULT) != 0) {
548 if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
549 if (a->ac_result != IPMR_NOMATCH) {
550 verbose(8, "-- ff-flags mismatch\n");
551 continue;
552 }
553 } else if (FR_ISPASS(ipf->fl_flags)) {
554 if (a->ac_result != IPMR_PASS) {
555 verbose(8, "-- pass mismatch\n");
556 continue;
557 }
558 } else if (FR_ISBLOCK(ipf->fl_flags)) {
559 if (a->ac_result != IPMR_BLOCK) {
560 verbose(8, "-- block mismatch\n");
561 continue;
562 }
563 } else { /* Log only */
564 if (a->ac_result != IPMR_LOG) {
565 verbose(8, "-- log mismatch\n");
566 continue;
567 }
568 }
569 }
570
571 if ((a->ac_mflag & IPMAC_RULE) != 0) {
572 if (a->ac_rule != ipf->fl_rule) {
573 verbose(8, "-- rule mismatch\n");
574 continue;
575 }
576 }
577
578 if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
579 if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) {
580 verbose(8, "-- srcip mismatch\n");
581 continue;
582 }
583 }
584
585 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
586 if (ip->ip_p != IPPROTO_UDP &&
587 ip->ip_p != IPPROTO_TCP) {
588 verbose(8, "-- port protocol mismatch\n");
589 continue;
590 }
591 if (tcp->th_sport != a->ac_sport) {
592 verbose(8, "-- sport mismatch\n");
593 continue;
594 }
595 }
596
597 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
598 if (a->ac_logtag != ipf->fl_logtag) {
599 verbose(8, "-- logtag %d != %d\n",
600 a->ac_logtag, ipf->fl_logtag);
601 continue;
602 }
603 }
604
605 if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
606 if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
607 IPFTAG_LEN) != 0) {
608 verbose(8, "-- nattag mismatch\n");
609 continue;
610 }
611 }
612
613 matched = 1;
614 verbose(8, "++ matched\n");
615
616 /*
617 * It matched so now perform the saves
618 */
619 for (d = a->ac_doing; d != NULL; d = d->ipmd_next)
620 (*d->ipmd_store)(d->ipmd_token, &msg);
621 }
622
623 return(matched);
624 }
625
626
627 static void
free_action(ipmon_action_t * a)628 free_action(ipmon_action_t *a)
629 {
630 ipmon_doing_t *d;
631
632 while ((d = a->ac_doing) != NULL) {
633 a->ac_doing = d->ipmd_next;
634 (*d->ipmd_saver->ims_destroy)(d->ipmd_token);
635 free(d);
636 }
637
638 if (a->ac_iface != NULL) {
639 free(a->ac_iface);
640 a->ac_iface = NULL;
641 }
642 a->ac_next = NULL;
643 free(a);
644 }
645
646
647 int
load_config(char * file)648 load_config(char *file)
649 {
650 FILE *fp;
651 char *s;
652
653 unload_config();
654
655 s = getenv("YYDEBUG");
656 if (s != NULL)
657 yydebug = atoi(s);
658 else
659 yydebug = 0;
660
661 yylineNum = 1;
662
663 (void) yysettab(yywords);
664
665 fp = fopen(file, "r");
666 if (!fp) {
667 perror("load_config:fopen:");
668 return(-1);
669 }
670 yyin = fp;
671 while (!feof(fp))
672 yyparse();
673 fclose(fp);
674 return(0);
675 }
676
677
678 void
unload_config(void)679 unload_config(void)
680 {
681 ipmon_saver_int_t *sav, **imsip;
682 ipmon_saver_t *is;
683 ipmon_action_t *a;
684
685 while ((a = alist) != NULL) {
686 alist = a->ac_next;
687 free_action(a);
688 }
689
690 /*
691 * Look for savers that have been added in dynamically from the
692 * configuration file.
693 */
694 for (imsip = &saverlist; (sav = *imsip) != NULL; ) {
695 if (sav->imsi_handle == NULL)
696 imsip = &sav->imsi_next;
697 else {
698 dlclose(sav->imsi_handle);
699
700 *imsip = sav->imsi_next;
701 is = sav->imsi_stor;
702 free(sav);
703
704 free(is->ims_name);
705 free(is);
706 }
707 }
708 }
709
710
711 void
dump_config(void)712 dump_config(void)
713 {
714 ipmon_action_t *a;
715
716 for (a = alist; a != NULL; a = a->ac_next) {
717 print_action(a);
718
719 printf("#\n");
720 }
721 }
722
723
724 static void
print_action(ipmon_action_t * a)725 print_action(ipmon_action_t *a)
726 {
727 ipmon_doing_t *d;
728
729 printf("match { ");
730 print_match(a);
731 printf("; }\n");
732 printf("do {");
733 for (d = a->ac_doing; d != NULL; d = d->ipmd_next) {
734 printf("%s", d->ipmd_saver->ims_name);
735 if (d->ipmd_saver->ims_print != NULL) {
736 printf("(\"");
737 (*d->ipmd_saver->ims_print)(d->ipmd_token);
738 printf("\")");
739 }
740 printf(";");
741 }
742 printf("};\n");
743 }
744
745
746 void *
add_doing(ipmon_saver_t * saver)747 add_doing(ipmon_saver_t *saver)
748 {
749 ipmon_saver_int_t *it;
750
751 if (find_doing(saver->ims_name) == IPM_DOING)
752 return(NULL);
753
754 it = calloc(1, sizeof(*it));
755 if (it == NULL)
756 return(NULL);
757 it->imsi_stor = saver;
758 it->imsi_next = saverlist;
759 saverlist = it;
760 return(it);
761 }
762
763
764 static int
find_doing(char * string)765 find_doing(char *string)
766 {
767 ipmon_saver_int_t *it;
768
769 for (it = saverlist; it != NULL; it = it->imsi_next) {
770 if (!strcmp(it->imsi_stor->ims_name, string))
771 return(IPM_DOING);
772 }
773 return(0);
774 }
775
776
777 static ipmon_doing_t *
build_doing(char * target,char * options)778 build_doing(char *target, char *options)
779 {
780 ipmon_saver_int_t *it;
781 char *strarray[2];
782 ipmon_doing_t *d, *d1;
783 ipmon_action_t *a;
784 ipmon_saver_t *save;
785
786 d = calloc(1, sizeof(*d));
787 if (d == NULL)
788 return(NULL);
789
790 for (it = saverlist; it != NULL; it = it->imsi_next) {
791 if (!strcmp(it->imsi_stor->ims_name, target))
792 break;
793 }
794 if (it == NULL) {
795 free(d);
796 return(NULL);
797 }
798
799 strarray[0] = options;
800 strarray[1] = NULL;
801
802 d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray);
803 if (d->ipmd_token == NULL) {
804 free(d);
805 return(NULL);
806 }
807
808 save = it->imsi_stor;
809 d->ipmd_saver = save;
810 d->ipmd_store = it->imsi_stor->ims_store;
811
812 /*
813 * Look for duplicate do-things that need to be dup'd
814 */
815 for (a = alist; a != NULL; a = a->ac_next) {
816 for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) {
817 if (save != d1->ipmd_saver)
818 continue;
819 if (save->ims_match == NULL || save->ims_dup == NULL)
820 continue;
821 if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token))
822 continue;
823
824 (*d->ipmd_saver->ims_destroy)(d->ipmd_token);
825 d->ipmd_token = (*save->ims_dup)(d1->ipmd_token);
826 break;
827 }
828 }
829
830 return(d);
831 }
832
833
834 static void
print_match(ipmon_action_t * a)835 print_match(ipmon_action_t *a)
836 {
837 char *coma = "";
838
839 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
840 printf("direction = ");
841 if (a->ac_direction == IPM_IN)
842 printf("in");
843 else if (a->ac_direction == IPM_OUT)
844 printf("out");
845 coma = ", ";
846 }
847
848 if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
849 printf("%sdstip = ", coma);
850 printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk);
851 coma = ", ";
852 }
853
854 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
855 printf("%sdstport = %hu", coma, ntohs(a->ac_dport));
856 coma = ", ";
857 }
858
859 if ((a->ac_mflag & IPMAC_GROUP) != 0) {
860 char group[FR_GROUPLEN+1];
861
862 strncpy(group, a->ac_group, FR_GROUPLEN);
863 group[FR_GROUPLEN] = '\0';
864 printf("%sgroup = %s", coma, group);
865 coma = ", ";
866 }
867
868 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
869 printf("%siface = %s", coma, a->ac_iface);
870 coma = ", ";
871 }
872
873 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
874 printf("%slogtag = %u", coma, a->ac_logtag);
875 coma = ", ";
876 }
877
878 if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
879 char tag[17];
880
881 strncpy(tag, a->ac_nattag, 16);
882 tag[16] = '\0';
883 printf("%snattag = %s", coma, tag);
884 coma = ", ";
885 }
886
887 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
888 printf("%sprotocol = %u", coma, a->ac_proto);
889 coma = ", ";
890 }
891
892 if ((a->ac_mflag & IPMAC_RESULT) != 0) {
893 printf("%sresult = ", coma);
894 switch (a->ac_result)
895 {
896 case IPMR_LOG :
897 printf("log");
898 break;
899 case IPMR_PASS :
900 printf("pass");
901 break;
902 case IPMR_BLOCK :
903 printf("block");
904 break;
905 case IPMR_NOMATCH :
906 printf("nomatch");
907 break;
908 }
909 coma = ", ";
910 }
911
912 if ((a->ac_mflag & IPMAC_RULE) != 0) {
913 printf("%srule = %u", coma, a->ac_rule);
914 coma = ", ";
915 }
916
917 if ((a->ac_mflag & IPMAC_EVERY) != 0) {
918 if (a->ac_packet > 1) {
919 printf("%severy %d packets", coma, a->ac_packet);
920 coma = ", ";
921 } else if (a->ac_packet == 1) {
922 printf("%severy packet", coma);
923 coma = ", ";
924 }
925 if (a->ac_second > 1) {
926 printf("%severy %d seconds", coma, a->ac_second);
927 coma = ", ";
928 } else if (a->ac_second == 1) {
929 printf("%severy second", coma);
930 coma = ", ";
931 }
932 }
933
934 if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
935 printf("%ssrcip = ", coma);
936 printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk);
937 coma = ", ";
938 }
939
940 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
941 printf("%ssrcport = %hu", coma, ntohs(a->ac_sport));
942 coma = ", ";
943 }
944
945 if ((a->ac_mflag & IPMAC_TYPE) != 0) {
946 printf("%stype = ", coma);
947 switch (a->ac_type)
948 {
949 case IPL_LOGIPF :
950 printf("ipf");
951 break;
952 case IPL_LOGSTATE :
953 printf("state");
954 break;
955 case IPL_LOGNAT :
956 printf("nat");
957 break;
958 }
959 coma = ", ";
960 }
961
962 if ((a->ac_mflag & IPMAC_WITH) != 0) {
963 printf("%swith ", coma);
964 coma = ", ";
965 }
966 }
967
968
969 static int
install_saver(char * name,char * path)970 install_saver(char *name, char *path)
971 {
972 ipmon_saver_int_t *isi;
973 ipmon_saver_t *is;
974 char nbuf[80];
975
976 if (find_doing(name) == IPM_DOING)
977 return(-1);
978
979 isi = calloc(1, sizeof(*isi));
980 if (isi == NULL)
981 return(-1);
982
983 is = calloc(1, sizeof(*is));
984 if (is == NULL)
985 goto loaderror;
986
987 is->ims_name = name;
988
989 #ifdef RTLD_LAZY
990 isi->imsi_handle = dlopen(path, RTLD_LAZY);
991 #endif
992 #ifdef DL_LAZY
993 isi->imsi_handle = dlopen(path, DL_LAZY);
994 #endif
995
996 if (isi->imsi_handle == NULL)
997 goto loaderror;
998
999 snprintf(nbuf, sizeof(nbuf), "%sdup", name);
1000 is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf);
1001
1002 snprintf(nbuf, sizeof(nbuf), "%sdestroy", name);
1003 is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf);
1004 if (is->ims_destroy == NULL)
1005 goto loaderror;
1006
1007 snprintf(nbuf, sizeof(nbuf), "%smatch", name);
1008 is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf);
1009
1010 snprintf(nbuf, sizeof(nbuf), "%sparse", name);
1011 is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf);
1012 if (is->ims_parse == NULL)
1013 goto loaderror;
1014
1015 snprintf(nbuf, sizeof(nbuf), "%sprint", name);
1016 is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf);
1017 if (is->ims_print == NULL)
1018 goto loaderror;
1019
1020 snprintf(nbuf, sizeof(nbuf), "%sstore", name);
1021 is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf);
1022 if (is->ims_store == NULL)
1023 goto loaderror;
1024
1025 isi->imsi_stor = is;
1026 isi->imsi_next = saverlist;
1027 saverlist = isi;
1028
1029 return(0);
1030
1031 loaderror:
1032 if (isi->imsi_handle != NULL)
1033 dlclose(isi->imsi_handle);
1034 free(isi);
1035 if (is != NULL)
1036 free(is);
1037 return(-1);
1038 }
1039