1/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ipmon_y.y 369245 2021-02-09 13:47:46Z git2svn $	*/
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
20extern	void	yyerror(char *);
21extern	int	yyparse(void);
22extern	int	yylex(void);
23extern	int	yydebug;
24extern	FILE	*yyin;
25extern	int	yylineNum;
26extern	int	ipmonopts;
27
28typedef	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
39static	void	build_action(opt_t *, ipmon_doing_t *);
40static	opt_t	*new_opt(int);
41static	void	free_action(ipmon_action_t *);
42static	void	print_action(ipmon_action_t *);
43static	int	find_doing(char *);
44static	ipmon_doing_t *build_doing(char *, char *);
45static	void	print_match(ipmon_action_t *);
46static	int	install_saver(char *, char *);
47
48static	ipmon_action_t	*alist = NULL;
49
50ipmon_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%%
83file:	action
84	| file action
85	;
86
87action:	line ';'
88	| assign ';'
89	| IPM_COMMENT
90	| YY_COMMENT
91	;
92
93line:	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
102assign:	YY_STR assigning YY_STR 		{ set_variable($1, $3);
103						  resetlexer();
104						  free($1);
105						  free($3);
106						  yyvarnext = 0;
107						}
108	;
109
110assigning:
111	'='					{ yyvarnext = 1; }
112	;
113
114matching:
115	matchopt				{ $$ = $1; }
116	| matchopt ',' matching			{ $1->o_next = $3; $$ = $1; }
117	;
118
119matchopt:
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
136doing:
137	doopt					{ $$ = $1; }
138	| doopt ',' doing			{ $1->ipmd_next = $3; $$ = $1; }
139	;
140
141doopt:
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
154direction:
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
161dstip:	IPM_DSTIP '=' ipv4 '/' YY_NUMBER	{ $$ = new_opt(IPM_DSTIP);
162						  $$->o_ip = $3;
163						  $$->o_num = $5; }
164	;
165
166dstport:
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
173every:	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
183group:	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
189interface:
190	IPM_INTERFACE '=' YY_STR		{ $$ = new_opt(IPM_INTERFACE);
191						  $$->o_str = $3; }
192	;
193
194logtag:	IPM_LOGTAG '=' YY_NUMBER		{ $$ = new_opt(IPM_LOGTAG);
195						  $$->o_num = $3; }
196	;
197
198nattag:	IPM_NATTAG '=' YY_STR			{ $$ = new_opt(IPM_NATTAG);
199						  $$->o_str = $3; }
200	;
201
202protocol:
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
211result:	IPM_RESULT '=' YY_STR			{ $$ = new_opt(IPM_RESULT);
212						  $$->o_str = $3; }
213	;
214
215rule:	IPM_RULE '=' YY_NUMBER			{ $$ = new_opt(IPM_RULE);
216						  $$->o_num = YY_NUMBER; }
217	;
218
219srcip:	IPM_SRCIP '=' ipv4 '/' YY_NUMBER	{ $$ = new_opt(IPM_SRCIP);
220						  $$->o_ip = $3;
221						  $$->o_num = $5; }
222	;
223
224srcport:
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
231type:	IPM_TYPE '=' typeopt			{ $$ = new_opt(IPM_TYPE);
232						  $$->o_num = $3; }
233	;
234
235typeopt:
236	IPM_IPF					{ $$ = IPL_MAGIC; }
237	| IPM_NAT				{ $$ = IPL_MAGIC_NAT; }
238	| IPM_STATE				{ $$ = IPL_MAGIC_STATE; }
239	;
240
241
242
243ipv4:   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%%
252static	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
284static 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
304static opt_t *
305new_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
318static void
319build_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
432int
433check_action(buf, log, opts, lvl)
434	char *buf, *log;
435	int opts, lvl;
436{
437	ipmon_action_t *a;
438	struct timeval tv;
439	ipmon_doing_t *d;
440	ipmon_msg_t msg;
441	ipflog_t *ipf;
442	tcphdr_t *tcp;
443	iplog_t *ipl;
444	int matched;
445	u_long t1;
446	ip_t *ip;
447
448	matched = 0;
449	ipl = (iplog_t *)buf;
450	ipf = (ipflog_t *)(ipl +1);
451	ip = (ip_t *)(ipf + 1);
452	tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
453
454	msg.imm_data = ipl;
455	msg.imm_dsize = ipl->ipl_dsize;
456	msg.imm_when = ipl->ipl_time.tv_sec;
457	msg.imm_msg = log;
458	msg.imm_msglen = strlen(log);
459	msg.imm_loglevel = lvl;
460
461	for (a = alist; a != NULL; a = a->ac_next) {
462		verbose(0, "== checking config rule\n");
463		if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
464			if (a->ac_direction == IPM_IN) {
465				if ((ipf->fl_flags & FR_INQUE) == 0) {
466					verbose(8, "-- direction not in\n");
467					continue;
468				}
469			} else if (a->ac_direction == IPM_OUT) {
470				if ((ipf->fl_flags & FR_OUTQUE) == 0) {
471					verbose(8, "-- direction not out\n");
472					continue;
473				}
474			}
475		}
476
477		if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) {
478			verbose(8, "-- type mismatch\n");
479			continue;
480		}
481
482		if ((a->ac_mflag & IPMAC_EVERY) != 0) {
483			gettimeofday(&tv, NULL);
484			t1 = tv.tv_sec - a->ac_lastsec;
485			if (tv.tv_usec <= a->ac_lastusec)
486				t1--;
487			if (a->ac_second != 0) {
488				if (t1 < a->ac_second) {
489					verbose(8, "-- too soon\n");
490					continue;
491				}
492				a->ac_lastsec = tv.tv_sec;
493				a->ac_lastusec = tv.tv_usec;
494			}
495
496			if (a->ac_packet != 0) {
497				if (a->ac_pktcnt == 0)
498					a->ac_pktcnt++;
499				else if (a->ac_pktcnt == a->ac_packet) {
500					a->ac_pktcnt = 0;
501					verbose(8, "-- packet count\n");
502					continue;
503				} else {
504					a->ac_pktcnt++;
505					verbose(8, "-- packet count\n");
506					continue;
507				}
508			}
509		}
510
511		if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
512			if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) {
513				verbose(8, "-- dstip wrong\n");
514				continue;
515			}
516		}
517
518		if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
519			if (ip->ip_p != IPPROTO_UDP &&
520			    ip->ip_p != IPPROTO_TCP) {
521				verbose(8, "-- not port protocol\n");
522				continue;
523			}
524			if (tcp->th_dport != a->ac_dport) {
525				verbose(8, "-- dport mismatch\n");
526				continue;
527			}
528		}
529
530		if ((a->ac_mflag & IPMAC_GROUP) != 0) {
531			if (strncmp(a->ac_group, ipf->fl_group,
532				    FR_GROUPLEN) != 0) {
533				verbose(8, "-- group mismatch\n");
534				continue;
535			}
536		}
537
538		if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
539			if (strcmp(a->ac_iface, ipf->fl_ifname)) {
540				verbose(8, "-- ifname mismatch\n");
541				continue;
542			}
543		}
544
545		if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
546			if (a->ac_proto != ip->ip_p) {
547				verbose(8, "-- protocol mismatch\n");
548				continue;
549			}
550		}
551
552		if ((a->ac_mflag & IPMAC_RESULT) != 0) {
553			if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
554				if (a->ac_result != IPMR_NOMATCH) {
555					verbose(8, "-- ff-flags mismatch\n");
556					continue;
557				}
558			} else if (FR_ISPASS(ipf->fl_flags)) {
559				if (a->ac_result != IPMR_PASS) {
560					verbose(8, "-- pass mismatch\n");
561					continue;
562				}
563			} else if (FR_ISBLOCK(ipf->fl_flags)) {
564				if (a->ac_result != IPMR_BLOCK) {
565					verbose(8, "-- block mismatch\n");
566					continue;
567				}
568			} else {	/* Log only */
569				if (a->ac_result != IPMR_LOG) {
570					verbose(8, "-- log mismatch\n");
571					continue;
572				}
573			}
574		}
575
576		if ((a->ac_mflag & IPMAC_RULE) != 0) {
577			if (a->ac_rule != ipf->fl_rule) {
578				verbose(8, "-- rule mismatch\n");
579				continue;
580			}
581		}
582
583		if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
584			if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) {
585				verbose(8, "-- srcip mismatch\n");
586				continue;
587			}
588		}
589
590		if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
591			if (ip->ip_p != IPPROTO_UDP &&
592			    ip->ip_p != IPPROTO_TCP) {
593				verbose(8, "-- port protocol mismatch\n");
594				continue;
595			}
596			if (tcp->th_sport != a->ac_sport) {
597				verbose(8, "-- sport mismatch\n");
598				continue;
599			}
600		}
601
602		if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
603			if (a->ac_logtag != ipf->fl_logtag) {
604				verbose(8, "-- logtag %d != %d\n",
605					a->ac_logtag, ipf->fl_logtag);
606				continue;
607			}
608		}
609
610		if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
611			if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
612				    IPFTAG_LEN) != 0) {
613				verbose(8, "-- nattag mismatch\n");
614				continue;
615			}
616		}
617
618		matched = 1;
619		verbose(8, "++ matched\n");
620
621		/*
622		 * It matched so now perform the saves
623		 */
624		for (d = a->ac_doing; d != NULL; d = d->ipmd_next)
625			(*d->ipmd_store)(d->ipmd_token, &msg);
626	}
627
628	return matched;
629}
630
631
632static void
633free_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
653int
654load_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
685void
686unload_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
718void
719dump_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
731static void
732print_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
754void *
755add_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
773static int
774find_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
787static ipmon_doing_t *
788build_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
846static void
847print_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
982static int
983install_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
1045loaderror:
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