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