xref: /freebsd/sbin/ipf/ipmon/ipmon_y.y (revision 2a63c3be158216222d89a073dcbd6a72ee4aab5a)
141edb306SCy Schubert 
241edb306SCy Schubert /*
341edb306SCy Schubert  * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert  *
541edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert  */
741edb306SCy Schubert %{
841edb306SCy Schubert #include "ipf.h"
941edb306SCy Schubert #include <syslog.h>
1041edb306SCy Schubert #undef	OPT_NAT
1141edb306SCy Schubert #undef	OPT_VERBOSE
1241edb306SCy Schubert #include "ipmon_l.h"
1341edb306SCy Schubert #include "ipmon.h"
1441edb306SCy Schubert 
1541edb306SCy Schubert #include <dlfcn.h>
1641edb306SCy Schubert 
1741edb306SCy Schubert #define	YYDEBUG	1
1841edb306SCy Schubert 
1941edb306SCy Schubert extern	void	yyerror(char *);
2041edb306SCy Schubert extern	int	yyparse(void);
2141edb306SCy Schubert extern	int	yylex(void);
2241edb306SCy Schubert extern	int	yydebug;
2341edb306SCy Schubert extern	FILE	*yyin;
2441edb306SCy Schubert extern	int	yylineNum;
2541edb306SCy Schubert extern	int	ipmonopts;
2641edb306SCy Schubert 
2741edb306SCy Schubert typedef	struct	opt_s	{
2841edb306SCy Schubert 	struct	opt_s	*o_next;
2941edb306SCy Schubert 	int		o_line;
3041edb306SCy Schubert 	int		o_type;
3141edb306SCy Schubert 	int		o_num;
3241edb306SCy Schubert 	char		*o_str;
3341edb306SCy Schubert 	struct in_addr	o_ip;
3441edb306SCy Schubert 	int		o_logfac;
3541edb306SCy Schubert 	int		o_logpri;
3641edb306SCy Schubert } opt_t;
3741edb306SCy Schubert 
3841edb306SCy Schubert static	void	build_action(opt_t *, ipmon_doing_t *);
3941edb306SCy Schubert static	opt_t	*new_opt(int);
4041edb306SCy Schubert static	void	free_action(ipmon_action_t *);
4141edb306SCy Schubert static	void	print_action(ipmon_action_t *);
4241edb306SCy Schubert static	int	find_doing(char *);
4341edb306SCy Schubert static	ipmon_doing_t *build_doing(char *, char *);
4441edb306SCy Schubert static	void	print_match(ipmon_action_t *);
4541edb306SCy Schubert static	int	install_saver(char *, char *);
4641edb306SCy Schubert 
4741edb306SCy Schubert static	ipmon_action_t	*alist = NULL;
4841edb306SCy Schubert 
4941edb306SCy Schubert ipmon_saver_int_t	*saverlist = NULL;
5041edb306SCy Schubert %}
5141edb306SCy Schubert 
5241edb306SCy Schubert %union	{
5341edb306SCy Schubert 	char	*str;
5441edb306SCy Schubert 	u_32_t	num;
5541edb306SCy Schubert 	struct in_addr	addr;
5641edb306SCy Schubert 	struct opt_s	*opt;
5741edb306SCy Schubert 	union	i6addr	ip6;
5841edb306SCy Schubert 	struct ipmon_doing_s	*ipmd;
5941edb306SCy Schubert }
6041edb306SCy Schubert 
6141edb306SCy Schubert %token	<num>	YY_NUMBER YY_HEX
6241edb306SCy Schubert %token	<str>	YY_STR
6341edb306SCy Schubert %token	<ip6>	YY_IPV6
6441edb306SCy Schubert %token	YY_COMMENT
6541edb306SCy Schubert %token	YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
6641edb306SCy Schubert %token	YY_RANGE_OUT YY_RANGE_IN
6741edb306SCy Schubert 
6841edb306SCy Schubert %token	IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
6941edb306SCy Schubert %token	IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION
7041edb306SCy Schubert %token	IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
7141edb306SCy Schubert %token	IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
7241edb306SCy Schubert %token	IPM_DO IPM_DOING IPM_TYPE IPM_NAT
7341edb306SCy Schubert %token	IPM_STATE IPM_NATTAG IPM_IPF
7441edb306SCy Schubert %type	<addr> ipv4
7541edb306SCy Schubert %type	<opt> direction dstip dstport every group interface
7641edb306SCy Schubert %type	<opt> protocol result rule srcip srcport logtag matching
7741edb306SCy Schubert %type	<opt> matchopt nattag type
7841edb306SCy Schubert %type	<num> typeopt
7941edb306SCy Schubert %type	<ipmd> doopt doing
8041edb306SCy Schubert 
8141edb306SCy Schubert %%
8241edb306SCy Schubert file:	action
8341edb306SCy Schubert 	| file action
8441edb306SCy Schubert 	;
8541edb306SCy Schubert 
8641edb306SCy Schubert action:	line ';'
8741edb306SCy Schubert 	| assign ';'
8841edb306SCy Schubert 	| IPM_COMMENT
8941edb306SCy Schubert 	| YY_COMMENT
9041edb306SCy Schubert 	;
9141edb306SCy Schubert 
9241edb306SCy Schubert line:	IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}'
9341edb306SCy Schubert 						{ build_action($3, $8);
9441edb306SCy Schubert 						  resetlexer();
9541edb306SCy Schubert 						}
9641edb306SCy Schubert 	| IPM_LOADACTION YY_STR YY_STR 	{ if (install_saver($2, $3))
9741edb306SCy Schubert 						yyerror("install saver");
9841edb306SCy Schubert 					}
9941edb306SCy Schubert 	;
10041edb306SCy Schubert 
10141edb306SCy Schubert assign:	YY_STR assigning YY_STR 		{ set_variable($1, $3);
10241edb306SCy Schubert 						  resetlexer();
10341edb306SCy Schubert 						  free($1);
10441edb306SCy Schubert 						  free($3);
10541edb306SCy Schubert 						  yyvarnext = 0;
10641edb306SCy Schubert 						}
10741edb306SCy Schubert 	;
10841edb306SCy Schubert 
10941edb306SCy Schubert assigning:
11041edb306SCy Schubert 	'='					{ yyvarnext = 1; }
11141edb306SCy Schubert 	;
11241edb306SCy Schubert 
11341edb306SCy Schubert matching:
11441edb306SCy Schubert 	matchopt				{ $$ = $1; }
11541edb306SCy Schubert 	| matchopt ',' matching			{ $1->o_next = $3; $$ = $1; }
11641edb306SCy Schubert 	;
11741edb306SCy Schubert 
11841edb306SCy Schubert matchopt:
11941edb306SCy Schubert 	direction				{ $$ = $1; }
12041edb306SCy Schubert 	| dstip					{ $$ = $1; }
12141edb306SCy Schubert 	| dstport				{ $$ = $1; }
12241edb306SCy Schubert 	| every					{ $$ = $1; }
12341edb306SCy Schubert 	| group					{ $$ = $1; }
12441edb306SCy Schubert 	| interface				{ $$ = $1; }
12541edb306SCy Schubert 	| protocol				{ $$ = $1; }
12641edb306SCy Schubert 	| result				{ $$ = $1; }
12741edb306SCy Schubert 	| rule					{ $$ = $1; }
12841edb306SCy Schubert 	| srcip					{ $$ = $1; }
12941edb306SCy Schubert 	| srcport				{ $$ = $1; }
13041edb306SCy Schubert 	| logtag				{ $$ = $1; }
13141edb306SCy Schubert 	| nattag				{ $$ = $1; }
13241edb306SCy Schubert 	| type					{ $$ = $1; }
13341edb306SCy Schubert 	;
13441edb306SCy Schubert 
13541edb306SCy Schubert doing:
13641edb306SCy Schubert 	doopt					{ $$ = $1; }
13741edb306SCy Schubert 	| doopt ',' doing			{ $1->ipmd_next = $3; $$ = $1; }
13841edb306SCy Schubert 	;
13941edb306SCy Schubert 
14041edb306SCy Schubert doopt:
14141edb306SCy Schubert 	YY_STR				{ if (find_doing($1) != IPM_DOING)
14241edb306SCy Schubert 						yyerror("unknown action");
14341edb306SCy Schubert 					}
14441edb306SCy Schubert 	'(' YY_STR ')'			{ $$ = build_doing($1, $4);
14541edb306SCy Schubert 					  if ($$ == NULL)
14641edb306SCy Schubert 						yyerror("action building");
14741edb306SCy Schubert 					}
14841edb306SCy Schubert 	| YY_STR			{ if (find_doing($1) == IPM_DOING)
14941edb306SCy Schubert 						$$ = build_doing($1, NULL);
15041edb306SCy Schubert 					}
15141edb306SCy Schubert 	;
15241edb306SCy Schubert 
15341edb306SCy Schubert direction:
15441edb306SCy Schubert 	IPM_DIRECTION '=' IPM_IN		{ $$ = new_opt(IPM_DIRECTION);
15541edb306SCy Schubert 						  $$->o_num = IPM_IN; }
15641edb306SCy Schubert 	| IPM_DIRECTION '=' IPM_OUT		{ $$ = new_opt(IPM_DIRECTION);
15741edb306SCy Schubert 						  $$->o_num = IPM_OUT; }
15841edb306SCy Schubert 	;
15941edb306SCy Schubert 
16041edb306SCy Schubert dstip:	IPM_DSTIP '=' ipv4 '/' YY_NUMBER	{ $$ = new_opt(IPM_DSTIP);
16141edb306SCy Schubert 						  $$->o_ip = $3;
16241edb306SCy Schubert 						  $$->o_num = $5; }
16341edb306SCy Schubert 	;
16441edb306SCy Schubert 
16541edb306SCy Schubert dstport:
16641edb306SCy Schubert 	IPM_DSTPORT '=' YY_NUMBER		{ $$ = new_opt(IPM_DSTPORT);
16741edb306SCy Schubert 						  $$->o_num = $3; }
16841edb306SCy Schubert 	| IPM_DSTPORT '=' YY_STR		{ $$ = new_opt(IPM_DSTPORT);
16941edb306SCy Schubert 						  $$->o_str = $3; }
17041edb306SCy Schubert 	;
17141edb306SCy Schubert 
17241edb306SCy Schubert every:	IPM_EVERY IPM_SECOND			{ $$ = new_opt(IPM_SECOND);
17341edb306SCy Schubert 						  $$->o_num = 1; }
17441edb306SCy Schubert 	| IPM_EVERY YY_NUMBER IPM_SECONDS	{ $$ = new_opt(IPM_SECOND);
17541edb306SCy Schubert 						  $$->o_num = $2; }
17641edb306SCy Schubert 	| IPM_EVERY IPM_PACKET			{ $$ = new_opt(IPM_PACKET);
17741edb306SCy Schubert 						  $$->o_num = 1; }
17841edb306SCy Schubert 	| IPM_EVERY YY_NUMBER IPM_PACKETS	{ $$ = new_opt(IPM_PACKET);
17941edb306SCy Schubert 						  $$->o_num = $2; }
18041edb306SCy Schubert 	;
18141edb306SCy Schubert 
18241edb306SCy Schubert group:	IPM_GROUP '=' YY_NUMBER			{ $$ = new_opt(IPM_GROUP);
18341edb306SCy Schubert 						  $$->o_num = $3; }
18441edb306SCy Schubert 	| IPM_GROUP '=' YY_STR			{ $$ = new_opt(IPM_GROUP);
18541edb306SCy Schubert 						  $$->o_str = $3; }
18641edb306SCy Schubert 	;
18741edb306SCy Schubert 
18841edb306SCy Schubert interface:
18941edb306SCy Schubert 	IPM_INTERFACE '=' YY_STR		{ $$ = new_opt(IPM_INTERFACE);
19041edb306SCy Schubert 						  $$->o_str = $3; }
19141edb306SCy Schubert 	;
19241edb306SCy Schubert 
19341edb306SCy Schubert logtag:	IPM_LOGTAG '=' YY_NUMBER		{ $$ = new_opt(IPM_LOGTAG);
19441edb306SCy Schubert 						  $$->o_num = $3; }
19541edb306SCy Schubert 	;
19641edb306SCy Schubert 
19741edb306SCy Schubert nattag:	IPM_NATTAG '=' YY_STR			{ $$ = new_opt(IPM_NATTAG);
19841edb306SCy Schubert 						  $$->o_str = $3; }
19941edb306SCy Schubert 	;
20041edb306SCy Schubert 
20141edb306SCy Schubert protocol:
20241edb306SCy Schubert 	IPM_PROTOCOL '=' YY_NUMBER		{ $$ = new_opt(IPM_PROTOCOL);
20341edb306SCy Schubert 						  $$->o_num = $3; }
20441edb306SCy Schubert 	| IPM_PROTOCOL '=' YY_STR		{ $$ = new_opt(IPM_PROTOCOL);
20541edb306SCy Schubert 						  $$->o_num = getproto($3);
20641edb306SCy Schubert 						  free($3);
20741edb306SCy Schubert 						}
20841edb306SCy Schubert 	;
20941edb306SCy Schubert 
21041edb306SCy Schubert result:	IPM_RESULT '=' YY_STR			{ $$ = new_opt(IPM_RESULT);
21141edb306SCy Schubert 						  $$->o_str = $3; }
21241edb306SCy Schubert 	;
21341edb306SCy Schubert 
21441edb306SCy Schubert rule:	IPM_RULE '=' YY_NUMBER			{ $$ = new_opt(IPM_RULE);
21541edb306SCy Schubert 						  $$->o_num = YY_NUMBER; }
21641edb306SCy Schubert 	;
21741edb306SCy Schubert 
21841edb306SCy Schubert srcip:	IPM_SRCIP '=' ipv4 '/' YY_NUMBER	{ $$ = new_opt(IPM_SRCIP);
21941edb306SCy Schubert 						  $$->o_ip = $3;
22041edb306SCy Schubert 						  $$->o_num = $5; }
22141edb306SCy Schubert 	;
22241edb306SCy Schubert 
22341edb306SCy Schubert srcport:
22441edb306SCy Schubert 	IPM_SRCPORT '=' YY_NUMBER		{ $$ = new_opt(IPM_SRCPORT);
22541edb306SCy Schubert 						  $$->o_num = $3; }
22641edb306SCy Schubert 	| IPM_SRCPORT '=' YY_STR		{ $$ = new_opt(IPM_SRCPORT);
22741edb306SCy Schubert 						  $$->o_str = $3; }
22841edb306SCy Schubert 	;
22941edb306SCy Schubert 
23041edb306SCy Schubert type:	IPM_TYPE '=' typeopt			{ $$ = new_opt(IPM_TYPE);
23141edb306SCy Schubert 						  $$->o_num = $3; }
23241edb306SCy Schubert 	;
23341edb306SCy Schubert 
23441edb306SCy Schubert typeopt:
23541edb306SCy Schubert 	IPM_IPF					{ $$ = IPL_MAGIC; }
23641edb306SCy Schubert 	| IPM_NAT				{ $$ = IPL_MAGIC_NAT; }
23741edb306SCy Schubert 	| IPM_STATE				{ $$ = IPL_MAGIC_STATE; }
23841edb306SCy Schubert 	;
23941edb306SCy Schubert 
24041edb306SCy Schubert 
24141edb306SCy Schubert 
24241edb306SCy Schubert ipv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
24341edb306SCy Schubert 		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
24441edb306SCy Schubert 			yyerror("Invalid octet string for IP address");
245*2582ae57SCy Schubert 			return(0);
24641edb306SCy Schubert 		  }
24741edb306SCy Schubert 		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
24841edb306SCy Schubert 		  $$.s_addr = htonl($$.s_addr);
24941edb306SCy Schubert 		}
25041edb306SCy Schubert %%
25141edb306SCy Schubert static	struct	wordtab	yywords[] = {
25241edb306SCy Schubert 	{ "body",	IPM_BODY },
25341edb306SCy Schubert 	{ "direction",	IPM_DIRECTION },
25441edb306SCy Schubert 	{ "do",		IPM_DO },
25541edb306SCy Schubert 	{ "dstip",	IPM_DSTIP },
25641edb306SCy Schubert 	{ "dstport",	IPM_DSTPORT },
25741edb306SCy Schubert 	{ "every",	IPM_EVERY },
25841edb306SCy Schubert 	{ "group",	IPM_GROUP },
25941edb306SCy Schubert 	{ "in",		IPM_IN },
26041edb306SCy Schubert 	{ "interface",	IPM_INTERFACE },
26141edb306SCy Schubert 	{ "ipf",	IPM_IPF },
26241edb306SCy Schubert 	{ "load_action",IPM_LOADACTION },
26341edb306SCy Schubert 	{ "logtag",	IPM_LOGTAG },
26441edb306SCy Schubert 	{ "match",	IPM_MATCH },
26541edb306SCy Schubert 	{ "nat",	IPM_NAT },
26641edb306SCy Schubert 	{ "nattag",	IPM_NATTAG },
26741edb306SCy Schubert 	{ "no",		IPM_NO },
26841edb306SCy Schubert 	{ "out",	IPM_OUT },
26941edb306SCy Schubert 	{ "packet",	IPM_PACKET },
27041edb306SCy Schubert 	{ "packets",	IPM_PACKETS },
27141edb306SCy Schubert 	{ "protocol",	IPM_PROTOCOL },
27241edb306SCy Schubert 	{ "result",	IPM_RESULT },
27341edb306SCy Schubert 	{ "rule",	IPM_RULE },
27441edb306SCy Schubert 	{ "second",	IPM_SECOND },
27541edb306SCy Schubert 	{ "seconds",	IPM_SECONDS },
27641edb306SCy Schubert 	{ "srcip",	IPM_SRCIP },
27741edb306SCy Schubert 	{ "srcport",	IPM_SRCPORT },
27841edb306SCy Schubert 	{ "state",	IPM_STATE },
27941edb306SCy Schubert 	{ "with",	IPM_WITH },
28041edb306SCy Schubert 	{ NULL,		0 }
28141edb306SCy Schubert };
28241edb306SCy Schubert 
28341edb306SCy Schubert static int macflags[17][2] = {
28441edb306SCy Schubert 	{ IPM_DIRECTION,	IPMAC_DIRECTION	},
28541edb306SCy Schubert 	{ IPM_DSTIP,		IPMAC_DSTIP	},
28641edb306SCy Schubert 	{ IPM_DSTPORT,		IPMAC_DSTPORT	},
28741edb306SCy Schubert 	{ IPM_GROUP,		IPMAC_GROUP	},
28841edb306SCy Schubert 	{ IPM_INTERFACE,	IPMAC_INTERFACE	},
28941edb306SCy Schubert 	{ IPM_LOGTAG,		IPMAC_LOGTAG 	},
29041edb306SCy Schubert 	{ IPM_NATTAG,		IPMAC_NATTAG 	},
29141edb306SCy Schubert 	{ IPM_PACKET,		IPMAC_EVERY	},
29241edb306SCy Schubert 	{ IPM_PROTOCOL,		IPMAC_PROTOCOL	},
29341edb306SCy Schubert 	{ IPM_RESULT,		IPMAC_RESULT	},
29441edb306SCy Schubert 	{ IPM_RULE,		IPMAC_RULE	},
29541edb306SCy Schubert 	{ IPM_SECOND,		IPMAC_EVERY	},
29641edb306SCy Schubert 	{ IPM_SRCIP,		IPMAC_SRCIP	},
29741edb306SCy Schubert 	{ IPM_SRCPORT,		IPMAC_SRCPORT	},
29841edb306SCy Schubert 	{ IPM_TYPE,		IPMAC_TYPE 	},
29941edb306SCy Schubert 	{ IPM_WITH,		IPMAC_WITH 	},
30041edb306SCy Schubert 	{ 0, 0 }
30141edb306SCy Schubert };
30241edb306SCy Schubert 
30341edb306SCy Schubert static opt_t *
new_opt(int type)304efeb8bffSCy Schubert new_opt(int type)
30541edb306SCy Schubert {
30641edb306SCy Schubert 	opt_t *o;
30741edb306SCy Schubert 
30841edb306SCy Schubert 	o = (opt_t *)calloc(1, sizeof(*o));
30941edb306SCy Schubert 	o->o_type = type;
31041edb306SCy Schubert 	o->o_line = yylineNum;
31141edb306SCy Schubert 	o->o_logfac = -1;
31241edb306SCy Schubert 	o->o_logpri = -1;
313*2582ae57SCy Schubert 	return(o);
31441edb306SCy Schubert }
31541edb306SCy Schubert 
31641edb306SCy Schubert static void
build_action(opt_t * olist,ipmon_doing_t * todo)317efeb8bffSCy Schubert build_action(opt_t *olist, ipmon_doing_t *todo)
31841edb306SCy Schubert {
31941edb306SCy Schubert 	ipmon_action_t *a;
32041edb306SCy Schubert 	opt_t *o;
32141edb306SCy Schubert 	int i;
32241edb306SCy Schubert 
32341edb306SCy Schubert 	a = (ipmon_action_t *)calloc(1, sizeof(*a));
32441edb306SCy Schubert 	if (a == NULL)
32541edb306SCy Schubert 		return;
32641edb306SCy Schubert 
32741edb306SCy Schubert 	while ((o = olist) != NULL) {
32841edb306SCy Schubert 		/*
32941edb306SCy Schubert 		 * Check to see if the same comparator is being used more than
33041edb306SCy Schubert 		 * once per matching statement.
33141edb306SCy Schubert 		 */
33241edb306SCy Schubert 		for (i = 0; macflags[i][0]; i++)
33341edb306SCy Schubert 			if (macflags[i][0] == o->o_type)
33441edb306SCy Schubert 				break;
33541edb306SCy Schubert 		if (macflags[i][1] & a->ac_mflag) {
33641edb306SCy Schubert 			fprintf(stderr, "%s redfined on line %d\n",
33741edb306SCy Schubert 				yykeytostr(o->o_type), yylineNum);
33841edb306SCy Schubert 			if (o->o_str != NULL)
33941edb306SCy Schubert 				free(o->o_str);
34041edb306SCy Schubert 			olist = o->o_next;
34141edb306SCy Schubert 			free(o);
34241edb306SCy Schubert 			continue;
34341edb306SCy Schubert 		}
34441edb306SCy Schubert 
34541edb306SCy Schubert 		a->ac_mflag |= macflags[i][1];
34641edb306SCy Schubert 
34741edb306SCy Schubert 		switch (o->o_type)
34841edb306SCy Schubert 		{
34941edb306SCy Schubert 		case IPM_DIRECTION :
35041edb306SCy Schubert 			a->ac_direction = o->o_num;
35141edb306SCy Schubert 			break;
35241edb306SCy Schubert 		case IPM_DSTIP :
35341edb306SCy Schubert 			a->ac_dip = o->o_ip.s_addr;
35441edb306SCy Schubert 			a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
35541edb306SCy Schubert 			break;
35641edb306SCy Schubert 		case IPM_DSTPORT :
35741edb306SCy Schubert 			a->ac_dport = htons(o->o_num);
35841edb306SCy Schubert 			break;
35941edb306SCy Schubert 		case IPM_INTERFACE :
36041edb306SCy Schubert 			a->ac_iface = o->o_str;
36141edb306SCy Schubert 			o->o_str = NULL;
36241edb306SCy Schubert 			break;
36341edb306SCy Schubert 		case IPM_GROUP :
36441edb306SCy Schubert 			if (o->o_str != NULL)
36541edb306SCy Schubert 				strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
36641edb306SCy Schubert 			else
367d740faa3SCy Schubert 				sprintf(a->ac_group, "%d", o->o_num);
36841edb306SCy Schubert 			break;
36941edb306SCy Schubert 		case IPM_LOGTAG :
37041edb306SCy Schubert 			a->ac_logtag = o->o_num;
37141edb306SCy Schubert 			break;
37241edb306SCy Schubert 		case IPM_NATTAG :
37341edb306SCy Schubert 			strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
37441edb306SCy Schubert 			break;
37541edb306SCy Schubert 		case IPM_PACKET :
37641edb306SCy Schubert 			a->ac_packet = o->o_num;
37741edb306SCy Schubert 			break;
37841edb306SCy Schubert 		case IPM_PROTOCOL :
37941edb306SCy Schubert 			a->ac_proto = o->o_num;
38041edb306SCy Schubert 			break;
38141edb306SCy Schubert 		case IPM_RULE :
38241edb306SCy Schubert 			a->ac_rule = o->o_num;
38341edb306SCy Schubert 			break;
38441edb306SCy Schubert 		case IPM_RESULT :
38541edb306SCy Schubert 			if (!strcasecmp(o->o_str, "pass"))
38641edb306SCy Schubert 				a->ac_result = IPMR_PASS;
38741edb306SCy Schubert 			else if (!strcasecmp(o->o_str, "block"))
38841edb306SCy Schubert 				a->ac_result = IPMR_BLOCK;
38941edb306SCy Schubert 			else if (!strcasecmp(o->o_str, "nomatch"))
39041edb306SCy Schubert 				a->ac_result = IPMR_NOMATCH;
39141edb306SCy Schubert 			else if (!strcasecmp(o->o_str, "log"))
39241edb306SCy Schubert 				a->ac_result = IPMR_LOG;
39341edb306SCy Schubert 			break;
39441edb306SCy Schubert 		case IPM_SECOND :
39541edb306SCy Schubert 			a->ac_second = o->o_num;
39641edb306SCy Schubert 			break;
39741edb306SCy Schubert 		case IPM_SRCIP :
39841edb306SCy Schubert 			a->ac_sip = o->o_ip.s_addr;
39941edb306SCy Schubert 			a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
40041edb306SCy Schubert 			break;
40141edb306SCy Schubert 		case IPM_SRCPORT :
40241edb306SCy Schubert 			a->ac_sport = htons(o->o_num);
40341edb306SCy Schubert 			break;
40441edb306SCy Schubert 		case IPM_TYPE :
40541edb306SCy Schubert 			a->ac_type = o->o_num;
40641edb306SCy Schubert 			break;
40741edb306SCy Schubert 		case IPM_WITH :
40841edb306SCy Schubert 			break;
40941edb306SCy Schubert 		default :
41041edb306SCy Schubert 			break;
41141edb306SCy Schubert 		}
41241edb306SCy Schubert 
41341edb306SCy Schubert 		olist = o->o_next;
41441edb306SCy Schubert 		if (o->o_str != NULL)
41541edb306SCy Schubert 			free(o->o_str);
41641edb306SCy Schubert 		free(o);
41741edb306SCy Schubert 	}
41841edb306SCy Schubert 
41941edb306SCy Schubert 	a->ac_doing = todo;
42041edb306SCy Schubert 	a->ac_next = alist;
42141edb306SCy Schubert 	alist = a;
42241edb306SCy Schubert 
42341edb306SCy Schubert 	if (ipmonopts & IPMON_VERBOSE)
42441edb306SCy Schubert 		print_action(a);
42541edb306SCy Schubert }
42641edb306SCy Schubert 
42741edb306SCy Schubert 
42841edb306SCy Schubert int
check_action(char * buf,char * log,int opts,int lvl)429efeb8bffSCy Schubert check_action(char *buf, char *log, int opts, int lvl)
43041edb306SCy Schubert {
43141edb306SCy Schubert 	ipmon_action_t *a;
43241edb306SCy Schubert 	struct timeval tv;
43341edb306SCy Schubert 	ipmon_doing_t *d;
43441edb306SCy Schubert 	ipmon_msg_t msg;
43541edb306SCy Schubert 	ipflog_t *ipf;
43641edb306SCy Schubert 	tcphdr_t *tcp;
43741edb306SCy Schubert 	iplog_t *ipl;
43841edb306SCy Schubert 	int matched;
43941edb306SCy Schubert 	u_long t1;
44041edb306SCy Schubert 	ip_t *ip;
44141edb306SCy Schubert 
44241edb306SCy Schubert 	matched = 0;
44341edb306SCy Schubert 	ipl = (iplog_t *)buf;
44441edb306SCy Schubert 	ipf = (ipflog_t *)(ipl +1);
44541edb306SCy Schubert 	ip = (ip_t *)(ipf + 1);
44641edb306SCy Schubert 	tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
44741edb306SCy Schubert 
44841edb306SCy Schubert 	msg.imm_data = ipl;
44941edb306SCy Schubert 	msg.imm_dsize = ipl->ipl_dsize;
45041edb306SCy Schubert 	msg.imm_when = ipl->ipl_time.tv_sec;
45141edb306SCy Schubert 	msg.imm_msg = log;
45241edb306SCy Schubert 	msg.imm_msglen = strlen(log);
45341edb306SCy Schubert 	msg.imm_loglevel = lvl;
45441edb306SCy Schubert 
45541edb306SCy Schubert 	for (a = alist; a != NULL; a = a->ac_next) {
45641edb306SCy Schubert 		verbose(0, "== checking config rule\n");
45741edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
45841edb306SCy Schubert 			if (a->ac_direction == IPM_IN) {
45941edb306SCy Schubert 				if ((ipf->fl_flags & FR_INQUE) == 0) {
46041edb306SCy Schubert 					verbose(8, "-- direction not in\n");
46141edb306SCy Schubert 					continue;
46241edb306SCy Schubert 				}
46341edb306SCy Schubert 			} else if (a->ac_direction == IPM_OUT) {
46441edb306SCy Schubert 				if ((ipf->fl_flags & FR_OUTQUE) == 0) {
46541edb306SCy Schubert 					verbose(8, "-- direction not out\n");
46641edb306SCy Schubert 					continue;
46741edb306SCy Schubert 				}
46841edb306SCy Schubert 			}
46941edb306SCy Schubert 		}
47041edb306SCy Schubert 
47141edb306SCy Schubert 		if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) {
47241edb306SCy Schubert 			verbose(8, "-- type mismatch\n");
47341edb306SCy Schubert 			continue;
47441edb306SCy Schubert 		}
47541edb306SCy Schubert 
47641edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_EVERY) != 0) {
47741edb306SCy Schubert 			gettimeofday(&tv, NULL);
47841edb306SCy Schubert 			t1 = tv.tv_sec - a->ac_lastsec;
47941edb306SCy Schubert 			if (tv.tv_usec <= a->ac_lastusec)
48041edb306SCy Schubert 				t1--;
48141edb306SCy Schubert 			if (a->ac_second != 0) {
48241edb306SCy Schubert 				if (t1 < a->ac_second) {
48341edb306SCy Schubert 					verbose(8, "-- too soon\n");
48441edb306SCy Schubert 					continue;
48541edb306SCy Schubert 				}
48641edb306SCy Schubert 				a->ac_lastsec = tv.tv_sec;
48741edb306SCy Schubert 				a->ac_lastusec = tv.tv_usec;
48841edb306SCy Schubert 			}
48941edb306SCy Schubert 
49041edb306SCy Schubert 			if (a->ac_packet != 0) {
49141edb306SCy Schubert 				if (a->ac_pktcnt == 0)
49241edb306SCy Schubert 					a->ac_pktcnt++;
49341edb306SCy Schubert 				else if (a->ac_pktcnt == a->ac_packet) {
49441edb306SCy Schubert 					a->ac_pktcnt = 0;
49541edb306SCy Schubert 					verbose(8, "-- packet count\n");
49641edb306SCy Schubert 					continue;
49741edb306SCy Schubert 				} else {
49841edb306SCy Schubert 					a->ac_pktcnt++;
49941edb306SCy Schubert 					verbose(8, "-- packet count\n");
50041edb306SCy Schubert 					continue;
50141edb306SCy Schubert 				}
50241edb306SCy Schubert 			}
50341edb306SCy Schubert 		}
50441edb306SCy Schubert 
50541edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
50641edb306SCy Schubert 			if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) {
50741edb306SCy Schubert 				verbose(8, "-- dstip wrong\n");
50841edb306SCy Schubert 				continue;
50941edb306SCy Schubert 			}
51041edb306SCy Schubert 		}
51141edb306SCy Schubert 
51241edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
51341edb306SCy Schubert 			if (ip->ip_p != IPPROTO_UDP &&
51441edb306SCy Schubert 			    ip->ip_p != IPPROTO_TCP) {
51541edb306SCy Schubert 				verbose(8, "-- not port protocol\n");
51641edb306SCy Schubert 				continue;
51741edb306SCy Schubert 			}
51841edb306SCy Schubert 			if (tcp->th_dport != a->ac_dport) {
51941edb306SCy Schubert 				verbose(8, "-- dport mismatch\n");
52041edb306SCy Schubert 				continue;
52141edb306SCy Schubert 			}
52241edb306SCy Schubert 		}
52341edb306SCy Schubert 
52441edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_GROUP) != 0) {
52541edb306SCy Schubert 			if (strncmp(a->ac_group, ipf->fl_group,
52641edb306SCy Schubert 				    FR_GROUPLEN) != 0) {
52741edb306SCy Schubert 				verbose(8, "-- group mismatch\n");
52841edb306SCy Schubert 				continue;
52941edb306SCy Schubert 			}
53041edb306SCy Schubert 		}
53141edb306SCy Schubert 
53241edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
53341edb306SCy Schubert 			if (strcmp(a->ac_iface, ipf->fl_ifname)) {
53441edb306SCy Schubert 				verbose(8, "-- ifname mismatch\n");
53541edb306SCy Schubert 				continue;
53641edb306SCy Schubert 			}
53741edb306SCy Schubert 		}
53841edb306SCy Schubert 
53941edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
54041edb306SCy Schubert 			if (a->ac_proto != ip->ip_p) {
54141edb306SCy Schubert 				verbose(8, "-- protocol mismatch\n");
54241edb306SCy Schubert 				continue;
54341edb306SCy Schubert 			}
54441edb306SCy Schubert 		}
54541edb306SCy Schubert 
54641edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_RESULT) != 0) {
54741edb306SCy Schubert 			if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
54841edb306SCy Schubert 				if (a->ac_result != IPMR_NOMATCH) {
54941edb306SCy Schubert 					verbose(8, "-- ff-flags mismatch\n");
55041edb306SCy Schubert 					continue;
55141edb306SCy Schubert 				}
55241edb306SCy Schubert 			} else if (FR_ISPASS(ipf->fl_flags)) {
55341edb306SCy Schubert 				if (a->ac_result != IPMR_PASS) {
55441edb306SCy Schubert 					verbose(8, "-- pass mismatch\n");
55541edb306SCy Schubert 					continue;
55641edb306SCy Schubert 				}
55741edb306SCy Schubert 			} else if (FR_ISBLOCK(ipf->fl_flags)) {
55841edb306SCy Schubert 				if (a->ac_result != IPMR_BLOCK) {
55941edb306SCy Schubert 					verbose(8, "-- block mismatch\n");
56041edb306SCy Schubert 					continue;
56141edb306SCy Schubert 				}
56241edb306SCy Schubert 			} else {	/* Log only */
56341edb306SCy Schubert 				if (a->ac_result != IPMR_LOG) {
56441edb306SCy Schubert 					verbose(8, "-- log mismatch\n");
56541edb306SCy Schubert 					continue;
56641edb306SCy Schubert 				}
56741edb306SCy Schubert 			}
56841edb306SCy Schubert 		}
56941edb306SCy Schubert 
57041edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_RULE) != 0) {
57141edb306SCy Schubert 			if (a->ac_rule != ipf->fl_rule) {
57241edb306SCy Schubert 				verbose(8, "-- rule mismatch\n");
57341edb306SCy Schubert 				continue;
57441edb306SCy Schubert 			}
57541edb306SCy Schubert 		}
57641edb306SCy Schubert 
57741edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
57841edb306SCy Schubert 			if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) {
57941edb306SCy Schubert 				verbose(8, "-- srcip mismatch\n");
58041edb306SCy Schubert 				continue;
58141edb306SCy Schubert 			}
58241edb306SCy Schubert 		}
58341edb306SCy Schubert 
58441edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
58541edb306SCy Schubert 			if (ip->ip_p != IPPROTO_UDP &&
58641edb306SCy Schubert 			    ip->ip_p != IPPROTO_TCP) {
58741edb306SCy Schubert 				verbose(8, "-- port protocol mismatch\n");
58841edb306SCy Schubert 				continue;
58941edb306SCy Schubert 			}
59041edb306SCy Schubert 			if (tcp->th_sport != a->ac_sport) {
59141edb306SCy Schubert 				verbose(8, "-- sport mismatch\n");
59241edb306SCy Schubert 				continue;
59341edb306SCy Schubert 			}
59441edb306SCy Schubert 		}
59541edb306SCy Schubert 
59641edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
59741edb306SCy Schubert 			if (a->ac_logtag != ipf->fl_logtag) {
59841edb306SCy Schubert 				verbose(8, "-- logtag %d != %d\n",
59941edb306SCy Schubert 					a->ac_logtag, ipf->fl_logtag);
60041edb306SCy Schubert 				continue;
60141edb306SCy Schubert 			}
60241edb306SCy Schubert 		}
60341edb306SCy Schubert 
60441edb306SCy Schubert 		if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
60541edb306SCy Schubert 			if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
60641edb306SCy Schubert 				    IPFTAG_LEN) != 0) {
60741edb306SCy Schubert 				verbose(8, "-- nattag mismatch\n");
60841edb306SCy Schubert 				continue;
60941edb306SCy Schubert 			}
61041edb306SCy Schubert 		}
61141edb306SCy Schubert 
61241edb306SCy Schubert 		matched = 1;
61341edb306SCy Schubert 		verbose(8, "++ matched\n");
61441edb306SCy Schubert 
61541edb306SCy Schubert 		/*
61641edb306SCy Schubert 		 * It matched so now perform the saves
61741edb306SCy Schubert 		 */
61841edb306SCy Schubert 		for (d = a->ac_doing; d != NULL; d = d->ipmd_next)
61941edb306SCy Schubert 			(*d->ipmd_store)(d->ipmd_token, &msg);
62041edb306SCy Schubert 	}
62141edb306SCy Schubert 
622*2582ae57SCy Schubert 	return(matched);
62341edb306SCy Schubert }
62441edb306SCy Schubert 
62541edb306SCy Schubert 
62641edb306SCy Schubert static void
free_action(ipmon_action_t * a)627efeb8bffSCy Schubert free_action(ipmon_action_t *a)
62841edb306SCy Schubert {
62941edb306SCy Schubert 	ipmon_doing_t *d;
63041edb306SCy Schubert 
63141edb306SCy Schubert 	while ((d = a->ac_doing) != NULL) {
63241edb306SCy Schubert 		a->ac_doing = d->ipmd_next;
63341edb306SCy Schubert 		(*d->ipmd_saver->ims_destroy)(d->ipmd_token);
63441edb306SCy Schubert 		free(d);
63541edb306SCy Schubert 	}
63641edb306SCy Schubert 
63741edb306SCy Schubert 	if (a->ac_iface != NULL) {
63841edb306SCy Schubert 		free(a->ac_iface);
63941edb306SCy Schubert 		a->ac_iface = NULL;
64041edb306SCy Schubert 	}
64141edb306SCy Schubert 	a->ac_next = NULL;
64241edb306SCy Schubert 	free(a);
64341edb306SCy Schubert }
64441edb306SCy Schubert 
64541edb306SCy Schubert 
64641edb306SCy Schubert int
load_config(char * file)647efeb8bffSCy Schubert load_config(char *file)
64841edb306SCy Schubert {
64941edb306SCy Schubert 	FILE *fp;
65041edb306SCy Schubert 	char *s;
65141edb306SCy Schubert 
65241edb306SCy Schubert 	unload_config();
65341edb306SCy Schubert 
65441edb306SCy Schubert 	s = getenv("YYDEBUG");
65541edb306SCy Schubert 	if (s != NULL)
65641edb306SCy Schubert 		yydebug = atoi(s);
65741edb306SCy Schubert 	else
65841edb306SCy Schubert 		yydebug = 0;
65941edb306SCy Schubert 
66041edb306SCy Schubert 	yylineNum = 1;
66141edb306SCy Schubert 
66241edb306SCy Schubert 	(void) yysettab(yywords);
66341edb306SCy Schubert 
66441edb306SCy Schubert 	fp = fopen(file, "r");
66541edb306SCy Schubert 	if (!fp) {
66641edb306SCy Schubert 		perror("load_config:fopen:");
667*2582ae57SCy Schubert 		return(-1);
66841edb306SCy Schubert 	}
66941edb306SCy Schubert 	yyin = fp;
67041edb306SCy Schubert 	while (!feof(fp))
67141edb306SCy Schubert 		yyparse();
67241edb306SCy Schubert 	fclose(fp);
673*2582ae57SCy Schubert 	return(0);
67441edb306SCy Schubert }
67541edb306SCy Schubert 
67641edb306SCy Schubert 
67741edb306SCy Schubert void
unload_config(void)678efeb8bffSCy Schubert unload_config(void)
67941edb306SCy Schubert {
68041edb306SCy Schubert 	ipmon_saver_int_t *sav, **imsip;
68141edb306SCy Schubert 	ipmon_saver_t *is;
68241edb306SCy Schubert 	ipmon_action_t *a;
68341edb306SCy Schubert 
68441edb306SCy Schubert 	while ((a = alist) != NULL) {
68541edb306SCy Schubert 		alist = a->ac_next;
68641edb306SCy Schubert 		free_action(a);
68741edb306SCy Schubert 	}
68841edb306SCy Schubert 
68941edb306SCy Schubert 	/*
69041edb306SCy Schubert 	 * Look for savers that have been added in dynamically from the
69141edb306SCy Schubert 	 * configuration file.
69241edb306SCy Schubert 	 */
69341edb306SCy Schubert 	for (imsip = &saverlist; (sav = *imsip) != NULL; ) {
69441edb306SCy Schubert 		if (sav->imsi_handle == NULL)
69541edb306SCy Schubert 			imsip = &sav->imsi_next;
69641edb306SCy Schubert 		else {
69741edb306SCy Schubert 			dlclose(sav->imsi_handle);
69841edb306SCy Schubert 
69941edb306SCy Schubert 			*imsip = sav->imsi_next;
70041edb306SCy Schubert 			is = sav->imsi_stor;
70141edb306SCy Schubert 			free(sav);
70241edb306SCy Schubert 
70341edb306SCy Schubert 			free(is->ims_name);
70441edb306SCy Schubert 			free(is);
70541edb306SCy Schubert 		}
70641edb306SCy Schubert 	}
70741edb306SCy Schubert }
70841edb306SCy Schubert 
70941edb306SCy Schubert 
71041edb306SCy Schubert void
dump_config(void)711efeb8bffSCy Schubert dump_config(void)
71241edb306SCy Schubert {
71341edb306SCy Schubert 	ipmon_action_t *a;
71441edb306SCy Schubert 
71541edb306SCy Schubert 	for (a = alist; a != NULL; a = a->ac_next) {
71641edb306SCy Schubert 		print_action(a);
71741edb306SCy Schubert 
71841edb306SCy Schubert 		printf("#\n");
71941edb306SCy Schubert 	}
72041edb306SCy Schubert }
72141edb306SCy Schubert 
72241edb306SCy Schubert 
72341edb306SCy Schubert static void
print_action(ipmon_action_t * a)724efeb8bffSCy Schubert print_action(ipmon_action_t *a)
72541edb306SCy Schubert {
72641edb306SCy Schubert 	ipmon_doing_t *d;
72741edb306SCy Schubert 
72841edb306SCy Schubert 	printf("match { ");
72941edb306SCy Schubert 	print_match(a);
73041edb306SCy Schubert 	printf("; }\n");
73141edb306SCy Schubert 	printf("do {");
73241edb306SCy Schubert 	for (d = a->ac_doing; d != NULL; d = d->ipmd_next) {
73341edb306SCy Schubert 		printf("%s", d->ipmd_saver->ims_name);
73441edb306SCy Schubert 		if (d->ipmd_saver->ims_print != NULL) {
73541edb306SCy Schubert 			printf("(\"");
73641edb306SCy Schubert 			(*d->ipmd_saver->ims_print)(d->ipmd_token);
73741edb306SCy Schubert 			printf("\")");
73841edb306SCy Schubert 		}
73941edb306SCy Schubert 		printf(";");
74041edb306SCy Schubert 	}
74141edb306SCy Schubert 	printf("};\n");
74241edb306SCy Schubert }
74341edb306SCy Schubert 
74441edb306SCy Schubert 
74541edb306SCy Schubert void *
add_doing(ipmon_saver_t * saver)746efeb8bffSCy Schubert add_doing(ipmon_saver_t *saver)
74741edb306SCy Schubert {
74841edb306SCy Schubert 	ipmon_saver_int_t *it;
74941edb306SCy Schubert 
75041edb306SCy Schubert 	if (find_doing(saver->ims_name) == IPM_DOING)
751*2582ae57SCy Schubert 		return(NULL);
75241edb306SCy Schubert 
75341edb306SCy Schubert 	it = calloc(1, sizeof(*it));
75441edb306SCy Schubert 	if (it == NULL)
755*2582ae57SCy Schubert 		return(NULL);
75641edb306SCy Schubert 	it->imsi_stor = saver;
75741edb306SCy Schubert 	it->imsi_next = saverlist;
75841edb306SCy Schubert 	saverlist = it;
759*2582ae57SCy Schubert 	return(it);
76041edb306SCy Schubert }
76141edb306SCy Schubert 
76241edb306SCy Schubert 
76341edb306SCy Schubert static int
find_doing(char * string)764efeb8bffSCy Schubert find_doing(char *string)
76541edb306SCy Schubert {
76641edb306SCy Schubert 	ipmon_saver_int_t *it;
76741edb306SCy Schubert 
76841edb306SCy Schubert 	for (it = saverlist; it != NULL; it = it->imsi_next) {
76941edb306SCy Schubert 		if (!strcmp(it->imsi_stor->ims_name, string))
770*2582ae57SCy Schubert 			return(IPM_DOING);
77141edb306SCy Schubert 	}
772*2582ae57SCy Schubert 	return(0);
77341edb306SCy Schubert }
77441edb306SCy Schubert 
77541edb306SCy Schubert 
77641edb306SCy Schubert static ipmon_doing_t *
build_doing(char * target,char * options)777efeb8bffSCy Schubert build_doing(char *target, char *options)
77841edb306SCy Schubert {
77941edb306SCy Schubert 	ipmon_saver_int_t *it;
78041edb306SCy Schubert 	char *strarray[2];
78141edb306SCy Schubert 	ipmon_doing_t *d, *d1;
78241edb306SCy Schubert 	ipmon_action_t *a;
78341edb306SCy Schubert 	ipmon_saver_t *save;
78441edb306SCy Schubert 
78541edb306SCy Schubert 	d = calloc(1, sizeof(*d));
78641edb306SCy Schubert 	if (d == NULL)
787*2582ae57SCy Schubert 		return(NULL);
78841edb306SCy Schubert 
78941edb306SCy Schubert 	for (it = saverlist; it != NULL; it = it->imsi_next) {
79041edb306SCy Schubert 		if (!strcmp(it->imsi_stor->ims_name, target))
79141edb306SCy Schubert 			break;
79241edb306SCy Schubert 	}
79341edb306SCy Schubert 	if (it == NULL) {
79441edb306SCy Schubert 		free(d);
795*2582ae57SCy Schubert 		return(NULL);
79641edb306SCy Schubert 	}
79741edb306SCy Schubert 
79841edb306SCy Schubert 	strarray[0] = options;
79941edb306SCy Schubert 	strarray[1] = NULL;
80041edb306SCy Schubert 
80141edb306SCy Schubert 	d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray);
80241edb306SCy Schubert 	if (d->ipmd_token == NULL) {
80341edb306SCy Schubert 		free(d);
804*2582ae57SCy Schubert 		return(NULL);
80541edb306SCy Schubert 	}
80641edb306SCy Schubert 
80741edb306SCy Schubert 	save = it->imsi_stor;
80841edb306SCy Schubert 	d->ipmd_saver = save;
80941edb306SCy Schubert 	d->ipmd_store = it->imsi_stor->ims_store;
81041edb306SCy Schubert 
81141edb306SCy Schubert 	/*
81241edb306SCy Schubert 	 * Look for duplicate do-things that need to be dup'd
81341edb306SCy Schubert 	 */
81441edb306SCy Schubert 	for (a = alist; a != NULL; a = a->ac_next) {
81541edb306SCy Schubert 		for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) {
81641edb306SCy Schubert 			if (save != d1->ipmd_saver)
81741edb306SCy Schubert 				continue;
81841edb306SCy Schubert 			if (save->ims_match == NULL || save->ims_dup == NULL)
81941edb306SCy Schubert 				continue;
82041edb306SCy Schubert 			if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token))
82141edb306SCy Schubert 				continue;
82241edb306SCy Schubert 
82341edb306SCy Schubert 			(*d->ipmd_saver->ims_destroy)(d->ipmd_token);
82441edb306SCy Schubert 			d->ipmd_token = (*save->ims_dup)(d1->ipmd_token);
82541edb306SCy Schubert 			break;
82641edb306SCy Schubert 		}
82741edb306SCy Schubert 	}
82841edb306SCy Schubert 
829*2582ae57SCy Schubert 	return(d);
83041edb306SCy Schubert }
83141edb306SCy Schubert 
83241edb306SCy Schubert 
83341edb306SCy Schubert static void
print_match(ipmon_action_t * a)834efeb8bffSCy Schubert print_match(ipmon_action_t *a)
83541edb306SCy Schubert {
83641edb306SCy Schubert 	char *coma = "";
83741edb306SCy Schubert 
83841edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
83941edb306SCy Schubert 		printf("direction = ");
84041edb306SCy Schubert 		if (a->ac_direction == IPM_IN)
84141edb306SCy Schubert 			printf("in");
84241edb306SCy Schubert 		else if (a->ac_direction == IPM_OUT)
84341edb306SCy Schubert 			printf("out");
84441edb306SCy Schubert 		coma = ", ";
84541edb306SCy Schubert 	}
84641edb306SCy Schubert 
84741edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
84841edb306SCy Schubert 		printf("%sdstip = ", coma);
84941edb306SCy Schubert 		printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk);
85041edb306SCy Schubert 		coma = ", ";
85141edb306SCy Schubert 	}
85241edb306SCy Schubert 
85341edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
85441edb306SCy Schubert 		printf("%sdstport = %hu", coma, ntohs(a->ac_dport));
85541edb306SCy Schubert 		coma = ", ";
85641edb306SCy Schubert 	}
85741edb306SCy Schubert 
85841edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_GROUP) != 0) {
85941edb306SCy Schubert 		char group[FR_GROUPLEN+1];
86041edb306SCy Schubert 
86141edb306SCy Schubert 		strncpy(group, a->ac_group, FR_GROUPLEN);
86241edb306SCy Schubert 		group[FR_GROUPLEN] = '\0';
86341edb306SCy Schubert 		printf("%sgroup = %s", coma, group);
86441edb306SCy Schubert 		coma = ", ";
86541edb306SCy Schubert 	}
86641edb306SCy Schubert 
86741edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
86841edb306SCy Schubert 		printf("%siface = %s", coma, a->ac_iface);
86941edb306SCy Schubert 		coma = ", ";
87041edb306SCy Schubert 	}
87141edb306SCy Schubert 
87241edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
87341edb306SCy Schubert 		printf("%slogtag = %u", coma, a->ac_logtag);
87441edb306SCy Schubert 		coma = ", ";
87541edb306SCy Schubert 	}
87641edb306SCy Schubert 
87741edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
87841edb306SCy Schubert 		char tag[17];
87941edb306SCy Schubert 
88041edb306SCy Schubert 		strncpy(tag, a->ac_nattag, 16);
88141edb306SCy Schubert 		tag[16] = '\0';
88241edb306SCy Schubert 		printf("%snattag = %s", coma, tag);
88341edb306SCy Schubert 		coma = ", ";
88441edb306SCy Schubert 	}
88541edb306SCy Schubert 
88641edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
88741edb306SCy Schubert 		printf("%sprotocol = %u", coma, a->ac_proto);
88841edb306SCy Schubert 		coma = ", ";
88941edb306SCy Schubert 	}
89041edb306SCy Schubert 
89141edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_RESULT) != 0) {
89241edb306SCy Schubert 		printf("%sresult = ", coma);
89341edb306SCy Schubert 		switch (a->ac_result)
89441edb306SCy Schubert 		{
89541edb306SCy Schubert 		case IPMR_LOG :
89641edb306SCy Schubert 			printf("log");
89741edb306SCy Schubert 			break;
89841edb306SCy Schubert 		case IPMR_PASS :
89941edb306SCy Schubert 			printf("pass");
90041edb306SCy Schubert 			break;
90141edb306SCy Schubert 		case IPMR_BLOCK :
90241edb306SCy Schubert 			printf("block");
90341edb306SCy Schubert 			break;
90441edb306SCy Schubert 		case IPMR_NOMATCH :
90541edb306SCy Schubert 			printf("nomatch");
90641edb306SCy Schubert 			break;
90741edb306SCy Schubert 		}
90841edb306SCy Schubert 		coma = ", ";
90941edb306SCy Schubert 	}
91041edb306SCy Schubert 
91141edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_RULE) != 0) {
91241edb306SCy Schubert 		printf("%srule = %u", coma, a->ac_rule);
91341edb306SCy Schubert 		coma = ", ";
91441edb306SCy Schubert 	}
91541edb306SCy Schubert 
91641edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_EVERY) != 0) {
91741edb306SCy Schubert 		if (a->ac_packet > 1) {
91841edb306SCy Schubert 			printf("%severy %d packets", coma, a->ac_packet);
91941edb306SCy Schubert 			coma = ", ";
92041edb306SCy Schubert 		} else if (a->ac_packet == 1) {
92141edb306SCy Schubert 			printf("%severy packet", coma);
92241edb306SCy Schubert 			coma = ", ";
92341edb306SCy Schubert 		}
92441edb306SCy Schubert 		if (a->ac_second > 1) {
92541edb306SCy Schubert 			printf("%severy %d seconds", coma, a->ac_second);
92641edb306SCy Schubert 			coma = ", ";
92741edb306SCy Schubert 		} else if (a->ac_second == 1) {
92841edb306SCy Schubert 			printf("%severy second", coma);
92941edb306SCy Schubert 			coma = ", ";
93041edb306SCy Schubert 		}
93141edb306SCy Schubert 	}
93241edb306SCy Schubert 
93341edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
93441edb306SCy Schubert 		printf("%ssrcip = ", coma);
93541edb306SCy Schubert 		printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk);
93641edb306SCy Schubert 		coma = ", ";
93741edb306SCy Schubert 	}
93841edb306SCy Schubert 
93941edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
94041edb306SCy Schubert 		printf("%ssrcport = %hu", coma, ntohs(a->ac_sport));
94141edb306SCy Schubert 		coma = ", ";
94241edb306SCy Schubert 	}
94341edb306SCy Schubert 
94441edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_TYPE) != 0) {
94541edb306SCy Schubert 		printf("%stype = ", coma);
94641edb306SCy Schubert 		switch (a->ac_type)
94741edb306SCy Schubert 		{
94841edb306SCy Schubert 		case IPL_LOGIPF :
94941edb306SCy Schubert 			printf("ipf");
95041edb306SCy Schubert 			break;
95141edb306SCy Schubert 		case IPL_LOGSTATE :
95241edb306SCy Schubert 			printf("state");
95341edb306SCy Schubert 			break;
95441edb306SCy Schubert 		case IPL_LOGNAT :
95541edb306SCy Schubert 			printf("nat");
95641edb306SCy Schubert 			break;
95741edb306SCy Schubert 		}
95841edb306SCy Schubert 		coma = ", ";
95941edb306SCy Schubert 	}
96041edb306SCy Schubert 
96141edb306SCy Schubert 	if ((a->ac_mflag & IPMAC_WITH) != 0) {
96241edb306SCy Schubert 		printf("%swith ", coma);
96341edb306SCy Schubert 		coma = ", ";
96441edb306SCy Schubert 	}
96541edb306SCy Schubert }
96641edb306SCy Schubert 
96741edb306SCy Schubert 
96841edb306SCy Schubert static int
install_saver(char * name,char * path)969efeb8bffSCy Schubert install_saver(char *name, char *path)
97041edb306SCy Schubert {
97141edb306SCy Schubert 	ipmon_saver_int_t *isi;
97241edb306SCy Schubert 	ipmon_saver_t *is;
97341edb306SCy Schubert 	char nbuf[80];
97441edb306SCy Schubert 
97541edb306SCy Schubert 	if (find_doing(name) == IPM_DOING)
976*2582ae57SCy Schubert 		return(-1);
97741edb306SCy Schubert 
97841edb306SCy Schubert 	isi = calloc(1, sizeof(*isi));
97941edb306SCy Schubert 	if (isi == NULL)
980*2582ae57SCy Schubert 		return(-1);
98141edb306SCy Schubert 
98241edb306SCy Schubert 	is = calloc(1, sizeof(*is));
98341edb306SCy Schubert 	if (is == NULL)
98441edb306SCy Schubert 		goto loaderror;
98541edb306SCy Schubert 
98641edb306SCy Schubert 	is->ims_name = name;
98741edb306SCy Schubert 
98841edb306SCy Schubert #ifdef RTLD_LAZY
98941edb306SCy Schubert 	isi->imsi_handle = dlopen(path, RTLD_LAZY);
99041edb306SCy Schubert #endif
99141edb306SCy Schubert #ifdef DL_LAZY
99241edb306SCy Schubert 	isi->imsi_handle = dlopen(path, DL_LAZY);
99341edb306SCy Schubert #endif
99441edb306SCy Schubert 
99541edb306SCy Schubert 	if (isi->imsi_handle == NULL)
99641edb306SCy Schubert 		goto loaderror;
99741edb306SCy Schubert 
99841edb306SCy Schubert 	snprintf(nbuf, sizeof(nbuf), "%sdup", name);
99941edb306SCy Schubert 	is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf);
100041edb306SCy Schubert 
100141edb306SCy Schubert 	snprintf(nbuf, sizeof(nbuf), "%sdestroy", name);
100241edb306SCy Schubert 	is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf);
100341edb306SCy Schubert 	if (is->ims_destroy == NULL)
100441edb306SCy Schubert 		goto loaderror;
100541edb306SCy Schubert 
100641edb306SCy Schubert 	snprintf(nbuf, sizeof(nbuf), "%smatch", name);
100741edb306SCy Schubert 	is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf);
100841edb306SCy Schubert 
100941edb306SCy Schubert 	snprintf(nbuf, sizeof(nbuf), "%sparse", name);
101041edb306SCy Schubert 	is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf);
101141edb306SCy Schubert 	if (is->ims_parse == NULL)
101241edb306SCy Schubert 		goto loaderror;
101341edb306SCy Schubert 
101441edb306SCy Schubert 	snprintf(nbuf, sizeof(nbuf), "%sprint", name);
101541edb306SCy Schubert 	is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf);
101641edb306SCy Schubert 	if (is->ims_print == NULL)
101741edb306SCy Schubert 		goto loaderror;
101841edb306SCy Schubert 
101941edb306SCy Schubert 	snprintf(nbuf, sizeof(nbuf), "%sstore", name);
102041edb306SCy Schubert 	is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf);
102141edb306SCy Schubert 	if (is->ims_store == NULL)
102241edb306SCy Schubert 		goto loaderror;
102341edb306SCy Schubert 
102441edb306SCy Schubert 	isi->imsi_stor = is;
102541edb306SCy Schubert 	isi->imsi_next = saverlist;
102641edb306SCy Schubert 	saverlist = isi;
102741edb306SCy Schubert 
1028*2582ae57SCy Schubert 	return(0);
102941edb306SCy Schubert 
103041edb306SCy Schubert loaderror:
103141edb306SCy Schubert 	if (isi->imsi_handle != NULL)
103241edb306SCy Schubert 		dlclose(isi->imsi_handle);
103341edb306SCy Schubert 	free(isi);
103441edb306SCy Schubert 	if (is != NULL)
103541edb306SCy Schubert 		free(is);
1036*2582ae57SCy Schubert 	return(-1);
103741edb306SCy Schubert }
1038