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