1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3170268Sdarrenr/*
4170268Sdarrenr * Copyright (C) 2001-2004 by Darren Reed.
5170268Sdarrenr *
6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7170268Sdarrenr */
8145510Sdarrenr%{
9145510Sdarrenr#include "ipf.h"
10145510Sdarrenr#include <syslog.h>
11145510Sdarrenr#undef	OPT_NAT
12145510Sdarrenr#undef	OPT_VERBOSE
13145510Sdarrenr#include "ipmon_l.h"
14145510Sdarrenr#include "ipmon.h"
15145510Sdarrenr
16145510Sdarrenr#define	YYDEBUG	1
17145510Sdarrenr
18145510Sdarrenrextern	void	yyerror __P((char *));
19145510Sdarrenrextern	int	yyparse __P((void));
20145510Sdarrenrextern	int	yylex __P((void));
21145510Sdarrenrextern	int	yydebug;
22145510Sdarrenrextern	FILE	*yyin;
23145510Sdarrenrextern	int	yylineNum;
24145510Sdarrenr
25145510Sdarrenrtypedef	struct	opt	{
26145510Sdarrenr	struct	opt	*o_next;
27145510Sdarrenr	int		o_line;
28145510Sdarrenr	int		o_type;
29145510Sdarrenr	int		o_num;
30145510Sdarrenr	char		*o_str;
31145510Sdarrenr	struct in_addr	o_ip;
32145510Sdarrenr} opt_t;
33145510Sdarrenr
34145510Sdarrenrstatic	void	build_action __P((struct opt *));
35145510Sdarrenrstatic	opt_t	*new_opt __P((int));
36145510Sdarrenrstatic	void	free_action __P((ipmon_action_t *));
37145510Sdarrenr
38145510Sdarrenrstatic	ipmon_action_t	*alist = NULL;
39145510Sdarrenr%}
40145510Sdarrenr
41145510Sdarrenr%union	{
42145510Sdarrenr	char	*str;
43145510Sdarrenr	u_32_t	num;
44145510Sdarrenr	struct in_addr	addr;
45145510Sdarrenr	struct opt	*opt;
46145510Sdarrenr	union	i6addr	ip6;
47145510Sdarrenr}
48145510Sdarrenr
49145510Sdarrenr%token	<num>	YY_NUMBER YY_HEX
50145510Sdarrenr%token	<str>	YY_STR
51145510Sdarrenr%token	<ip6>	YY_IPV6
52145510Sdarrenr%token	YY_COMMENT
53145510Sdarrenr%token	YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
54145510Sdarrenr%token	YY_RANGE_OUT YY_RANGE_IN
55145510Sdarrenr
56145510Sdarrenr%token	IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
57145510Sdarrenr%token	IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT
58145510Sdarrenr%token	IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
59145510Sdarrenr%token	IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
60145510Sdarrenr%token	IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT
61145510Sdarrenr%token	IPM_STATE IPM_NATTAG IPM_IPF
62145510Sdarrenr%type	<addr> ipv4
63145510Sdarrenr%type	<opt> direction dstip dstport every execute group interface
64145510Sdarrenr%type	<opt> protocol result rule srcip srcport logtag matching
65145510Sdarrenr%type	<opt> matchopt nattag type doopt doing save syslog nothing
66145510Sdarrenr%type	<num> saveopts saveopt typeopt
67145510Sdarrenr
68145510Sdarrenr%%
69145510Sdarrenrfile:	line
70145510Sdarrenr	| assign
71145510Sdarrenr	| file line
72145510Sdarrenr	| file assign
73145510Sdarrenr	;
74145510Sdarrenr
75145510Sdarrenrline:	IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';'
76145510Sdarrenr					{ build_action($3); resetlexer(); }
77145510Sdarrenr	| IPM_COMMENT
78145510Sdarrenr	| YY_COMMENT
79145510Sdarrenr	;
80145510Sdarrenr
81145510Sdarrenrassign:	YY_STR assigning YY_STR ';'		{ set_variable($1, $3);
82145510Sdarrenr						  resetlexer();
83145510Sdarrenr						  free($1);
84145510Sdarrenr						  free($3);
85170268Sdarrenr						  yyvarnext = 0;
86145510Sdarrenr						}
87145510Sdarrenr	;
88145510Sdarrenr
89145510Sdarrenrassigning:
90145510Sdarrenr	'='					{ yyvarnext = 1; }
91145510Sdarrenr	;
92145510Sdarrenr
93145510Sdarrenrmatching:
94145510Sdarrenr	matchopt				{ $$ = $1; }
95145510Sdarrenr	| matchopt ',' matching			{ $1->o_next = $3; $$ = $1; }
96145510Sdarrenr	;
97145510Sdarrenr
98145510Sdarrenrmatchopt:
99145510Sdarrenr	direction				{ $$ = $1; }
100145510Sdarrenr	| dstip					{ $$ = $1; }
101145510Sdarrenr	| dstport				{ $$ = $1; }
102145510Sdarrenr	| every					{ $$ = $1; }
103145510Sdarrenr	| group					{ $$ = $1; }
104145510Sdarrenr	| interface				{ $$ = $1; }
105145510Sdarrenr	| protocol				{ $$ = $1; }
106145510Sdarrenr	| result				{ $$ = $1; }
107145510Sdarrenr	| rule					{ $$ = $1; }
108145510Sdarrenr	| srcip					{ $$ = $1; }
109145510Sdarrenr	| srcport				{ $$ = $1; }
110145510Sdarrenr	| logtag				{ $$ = $1; }
111145510Sdarrenr	| nattag				{ $$ = $1; }
112145510Sdarrenr	| type					{ $$ = $1; }
113145510Sdarrenr	;
114145510Sdarrenr
115145510Sdarrenrdoing:
116145510Sdarrenr	doopt					{ $$ = $1; }
117145510Sdarrenr	| doopt ',' doing			{ $1->o_next = $3; $$ = $1; }
118145510Sdarrenr	;
119145510Sdarrenr
120145510Sdarrenrdoopt:
121145510Sdarrenr	execute					{ $$ = $1; }
122145510Sdarrenr	| save					{ $$ = $1; }
123145510Sdarrenr	| syslog				{ $$ = $1; }
124145510Sdarrenr	| nothing				{ $$ = $1; }
125145510Sdarrenr	;
126145510Sdarrenr
127145510Sdarrenrdirection:
128145510Sdarrenr	IPM_DIRECTION '=' IPM_IN		{ $$ = new_opt(IPM_DIRECTION);
129145510Sdarrenr						  $$->o_num = IPM_IN; }
130145510Sdarrenr	| IPM_DIRECTION '=' IPM_OUT		{ $$ = new_opt(IPM_DIRECTION);
131145510Sdarrenr						  $$->o_num = IPM_OUT; }
132145510Sdarrenr	;
133145510Sdarrenr
134145510Sdarrenrdstip:	IPM_DSTIP '=' ipv4 '/' YY_NUMBER	{ $$ = new_opt(IPM_DSTIP);
135145510Sdarrenr						  $$->o_ip = $3;
136145510Sdarrenr						  $$->o_num = $5; }
137145510Sdarrenr	;
138145510Sdarrenr
139145510Sdarrenrdstport:
140145510Sdarrenr	IPM_DSTPORT '=' YY_NUMBER		{ $$ = new_opt(IPM_DSTPORT);
141145510Sdarrenr						  $$->o_num = $3; }
142145510Sdarrenr	| IPM_DSTPORT '=' YY_STR		{ $$ = new_opt(IPM_DSTPORT);
143145510Sdarrenr						  $$->o_str = $3; }
144145510Sdarrenr	;
145145510Sdarrenr
146145510Sdarrenrevery:	IPM_EVERY IPM_SECOND			{ $$ = new_opt(IPM_SECOND);
147145510Sdarrenr						  $$->o_num = 1; }
148145510Sdarrenr	| IPM_EVERY YY_NUMBER IPM_SECONDS	{ $$ = new_opt(IPM_SECOND);
149145510Sdarrenr						  $$->o_num = $2; }
150145510Sdarrenr	| IPM_EVERY IPM_PACKET			{ $$ = new_opt(IPM_PACKET);
151145510Sdarrenr						  $$->o_num = 1; }
152145510Sdarrenr	| IPM_EVERY YY_NUMBER IPM_PACKETS	{ $$ = new_opt(IPM_PACKET);
153145510Sdarrenr						  $$->o_num = $2; }
154145510Sdarrenr	;
155145510Sdarrenr
156145510Sdarrenrgroup:	IPM_GROUP '=' YY_NUMBER			{ $$ = new_opt(IPM_GROUP);
157145510Sdarrenr						  $$->o_num = $3; }
158145510Sdarrenr	| IPM_GROUP '=' YY_STR			{ $$ = new_opt(IPM_GROUP);
159145510Sdarrenr						  $$->o_str = $3; }
160145510Sdarrenr	;
161145510Sdarrenr
162145510Sdarrenrinterface:
163145510Sdarrenr	IPM_INTERFACE '=' YY_STR		{ $$ = new_opt(IPM_INTERFACE);
164145510Sdarrenr						  $$->o_str = $3; }
165145510Sdarrenr	;
166145510Sdarrenr
167145510Sdarrenrlogtag:	IPM_LOGTAG '=' YY_NUMBER		{ $$ = new_opt(IPM_LOGTAG);
168145510Sdarrenr						  $$->o_num = $3; }
169145510Sdarrenr	;
170145510Sdarrenr
171145510Sdarrenrnattag:	IPM_NATTAG '=' YY_STR			{ $$ = new_opt(IPM_NATTAG);
172145510Sdarrenr						  $$->o_str = $3; }
173145510Sdarrenr	;
174145510Sdarrenr
175145510Sdarrenrprotocol:
176145510Sdarrenr	IPM_PROTOCOL '=' YY_NUMBER		{ $$ = new_opt(IPM_PROTOCOL);
177145510Sdarrenr						  $$->o_num = $3; }
178145510Sdarrenr	| IPM_PROTOCOL '=' YY_STR		{ $$ = new_opt(IPM_PROTOCOL);
179145510Sdarrenr						  $$->o_num = getproto($3);
180145510Sdarrenr						  free($3);
181145510Sdarrenr						}
182145510Sdarrenr	;
183145510Sdarrenr
184145510Sdarrenrresult:	IPM_RESULT '=' YY_STR			{ $$ = new_opt(IPM_RESULT);
185145510Sdarrenr						  $$->o_str = $3; }
186145510Sdarrenr	;
187145510Sdarrenr
188145510Sdarrenrrule:	IPM_RULE '=' YY_NUMBER			{ $$ = new_opt(IPM_RULE);
189145510Sdarrenr						  $$->o_num = YY_NUMBER; }
190145510Sdarrenr	;
191145510Sdarrenr
192145510Sdarrenrsrcip:	IPM_SRCIP '=' ipv4 '/' YY_NUMBER	{ $$ = new_opt(IPM_SRCIP);
193145510Sdarrenr						  $$->o_ip = $3;
194145510Sdarrenr						  $$->o_num = $5; }
195145510Sdarrenr	;
196145510Sdarrenr
197145510Sdarrenrsrcport:
198145510Sdarrenr	IPM_SRCPORT '=' YY_NUMBER		{ $$ = new_opt(IPM_SRCPORT);
199145510Sdarrenr						  $$->o_num = $3; }
200145510Sdarrenr	| IPM_SRCPORT '=' YY_STR		{ $$ = new_opt(IPM_SRCPORT);
201145510Sdarrenr						  $$->o_str = $3; }
202145510Sdarrenr	;
203145510Sdarrenr
204145510Sdarrenrtype:	IPM_TYPE '=' typeopt			{ $$ = new_opt(IPM_TYPE);
205145510Sdarrenr						  $$->o_num = $3; }
206145510Sdarrenr	;
207145510Sdarrenr
208145510Sdarrenrtypeopt:
209145510Sdarrenr	IPM_IPF					{ $$ = IPL_MAGIC; }
210145510Sdarrenr	| IPM_NAT				{ $$ = IPL_MAGIC_NAT; }
211145510Sdarrenr	| IPM_STATE				{ $$ = IPL_MAGIC_STATE; }
212145510Sdarrenr	;
213145510Sdarrenr
214145510Sdarrenrexecute:
215145510Sdarrenr	IPM_EXECUTE YY_STR			{ $$ = new_opt(IPM_EXECUTE);
216145510Sdarrenr						  $$->o_str = $2; }
217145510Sdarrenr	;
218145510Sdarrenr
219145510Sdarrenrsave:	IPM_SAVE saveopts YY_STR		{ $$ = new_opt(IPM_SAVE);
220145510Sdarrenr						  $$->o_num = $2;
221145510Sdarrenr						  $$->o_str = $3; }
222145510Sdarrenr	;
223145510Sdarrenr
224145510Sdarrenrsaveopts:					{ $$ = 0; }
225145510Sdarrenr	| saveopt				{ $$ = $1; }
226145510Sdarrenr	| saveopt ',' saveopts			{ $$ = $1 | $3; }
227145510Sdarrenr	;
228145510Sdarrenr
229145510Sdarrenrsaveopt:
230145510Sdarrenr	IPM_RAW					{ $$ = IPMDO_SAVERAW; }
231145510Sdarrenr	;
232145510Sdarrenr
233145510Sdarrenrsyslog:	IPM_SYSLOG				{ $$ = new_opt(IPM_SYSLOG); }
234145510Sdarrenr	;
235145510Sdarrenr
236145510Sdarrenrnothing:
237145510Sdarrenr	IPM_NOTHING				{ $$ = 0; }
238145510Sdarrenr	;
239145510Sdarrenr
240145510Sdarrenripv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
241145510Sdarrenr		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
242145510Sdarrenr			yyerror("Invalid octet string for IP address");
243145510Sdarrenr			return 0;
244145510Sdarrenr		  }
245145510Sdarrenr		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
246145510Sdarrenr		  $$.s_addr = htonl($$.s_addr);
247145510Sdarrenr		}
248145510Sdarrenr%%
249145510Sdarrenrstatic	struct	wordtab	yywords[] = {
250145510Sdarrenr	{ "body",	IPM_BODY },
251145510Sdarrenr	{ "direction",	IPM_DIRECTION },
252145510Sdarrenr	{ "do",		IPM_DO },
253145510Sdarrenr	{ "dstip",	IPM_DSTIP },
254145510Sdarrenr	{ "dstport",	IPM_DSTPORT },
255145510Sdarrenr	{ "every",	IPM_EVERY },
256145510Sdarrenr	{ "execute",	IPM_EXECUTE },
257145510Sdarrenr	{ "group",	IPM_GROUP },
258145510Sdarrenr	{ "in",		IPM_IN },
259145510Sdarrenr	{ "interface",	IPM_INTERFACE },
260145510Sdarrenr	{ "ipf",	IPM_IPF },
261145510Sdarrenr	{ "logtag",	IPM_LOGTAG },
262145510Sdarrenr	{ "match",	IPM_MATCH },
263145510Sdarrenr	{ "nat",	IPM_NAT },
264145510Sdarrenr	{ "nattag",	IPM_NATTAG },
265145510Sdarrenr	{ "no",		IPM_NO },
266145510Sdarrenr	{ "nothing",	IPM_NOTHING },
267145510Sdarrenr	{ "out",	IPM_OUT },
268145510Sdarrenr	{ "packet",	IPM_PACKET },
269145510Sdarrenr	{ "packets",	IPM_PACKETS },
270145510Sdarrenr	{ "protocol",	IPM_PROTOCOL },
271145510Sdarrenr	{ "result",	IPM_RESULT },
272145510Sdarrenr	{ "rule",	IPM_RULE },
273145510Sdarrenr	{ "save",	IPM_SAVE },
274145510Sdarrenr	{ "second",	IPM_SECOND },
275145510Sdarrenr	{ "seconds",	IPM_SECONDS },
276145510Sdarrenr	{ "srcip",	IPM_SRCIP },
277145510Sdarrenr	{ "srcport",	IPM_SRCPORT },
278145510Sdarrenr	{ "state",	IPM_STATE },
279145510Sdarrenr	{ "syslog",	IPM_SYSLOG },
280145510Sdarrenr	{ "with",	IPM_WITH },
281145510Sdarrenr	{ NULL,		0 }
282145510Sdarrenr};
283145510Sdarrenr
284145510Sdarrenrstatic int macflags[17][2] = {
285145510Sdarrenr	{ IPM_DIRECTION,	IPMAC_DIRECTION	},
286145510Sdarrenr	{ IPM_DSTIP,		IPMAC_DSTIP	},
287145510Sdarrenr	{ IPM_DSTPORT,		IPMAC_DSTPORT	},
288145510Sdarrenr	{ IPM_GROUP,		IPMAC_GROUP	},
289145510Sdarrenr	{ IPM_INTERFACE,	IPMAC_INTERFACE	},
290145510Sdarrenr	{ IPM_LOGTAG,		IPMAC_LOGTAG 	},
291145510Sdarrenr	{ IPM_NATTAG,		IPMAC_NATTAG 	},
292145510Sdarrenr	{ IPM_PACKET,		IPMAC_EVERY	},
293145510Sdarrenr	{ IPM_PROTOCOL,		IPMAC_PROTOCOL	},
294145510Sdarrenr	{ IPM_RESULT,		IPMAC_RESULT	},
295145510Sdarrenr	{ IPM_RULE,		IPMAC_RULE	},
296145510Sdarrenr	{ IPM_SECOND,		IPMAC_EVERY	},
297145510Sdarrenr	{ IPM_SRCIP,		IPMAC_SRCIP	},
298145510Sdarrenr	{ IPM_SRCPORT,		IPMAC_SRCPORT	},
299145510Sdarrenr	{ IPM_TYPE,		IPMAC_TYPE 	},
300145510Sdarrenr	{ IPM_WITH,		IPMAC_WITH 	},
301145510Sdarrenr	{ 0, 0 }
302145510Sdarrenr};
303145510Sdarrenr
304145510Sdarrenrstatic opt_t *new_opt(type)
305145510Sdarrenrint type;
306145510Sdarrenr{
307145510Sdarrenr	opt_t *o;
308145510Sdarrenr
309145510Sdarrenr	o = (opt_t *)malloc(sizeof(*o));
310145510Sdarrenr	o->o_type = type;
311145510Sdarrenr	o->o_line = yylineNum;
312145510Sdarrenr	o->o_num = 0;
313145510Sdarrenr	o->o_str = (char *)0;
314145510Sdarrenr	o->o_next = NULL;
315145510Sdarrenr	return o;
316145510Sdarrenr}
317145510Sdarrenr
318145510Sdarrenrstatic void build_action(olist)
319145510Sdarrenropt_t *olist;
320145510Sdarrenr{
321145510Sdarrenr	ipmon_action_t *a;
322145510Sdarrenr	opt_t *o;
323145510Sdarrenr	char c;
324145510Sdarrenr	int i;
325145510Sdarrenr
326145510Sdarrenr	a = (ipmon_action_t *)calloc(1, sizeof(*a));
327145510Sdarrenr	if (a == NULL)
328145510Sdarrenr		return;
329145510Sdarrenr	while ((o = olist) != NULL) {
330145510Sdarrenr		/*
331145510Sdarrenr		 * Check to see if the same comparator is being used more than
332145510Sdarrenr		 * once per matching statement.
333145510Sdarrenr		 */
334145510Sdarrenr		for (i = 0; macflags[i][0]; i++)
335145510Sdarrenr			if (macflags[i][0] == o->o_type)
336145510Sdarrenr				break;
337145510Sdarrenr		if (macflags[i][1] & a->ac_mflag) {
338145510Sdarrenr			fprintf(stderr, "%s redfined on line %d\n",
339145510Sdarrenr				yykeytostr(o->o_type), yylineNum);
340145510Sdarrenr			if (o->o_str != NULL)
341145510Sdarrenr				free(o->o_str);
342145510Sdarrenr			olist = o->o_next;
343145510Sdarrenr			free(o);
344145510Sdarrenr			continue;
345145510Sdarrenr		}
346145510Sdarrenr
347145510Sdarrenr		a->ac_mflag |= macflags[i][1];
348145510Sdarrenr
349145510Sdarrenr		switch (o->o_type)
350145510Sdarrenr		{
351145510Sdarrenr		case IPM_DIRECTION :
352145510Sdarrenr			a->ac_direction = o->o_num;
353145510Sdarrenr			break;
354145510Sdarrenr		case IPM_DSTIP :
355145510Sdarrenr			a->ac_dip = o->o_ip.s_addr;
356145510Sdarrenr			a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
357145510Sdarrenr			break;
358145510Sdarrenr		case IPM_DSTPORT :
359145510Sdarrenr			a->ac_dport = htons(o->o_num);
360145510Sdarrenr			break;
361145510Sdarrenr		case IPM_EXECUTE :
362145510Sdarrenr			a->ac_exec = o->o_str;
363145510Sdarrenr			c = *o->o_str;
364145510Sdarrenr			if (c== '"'|| c == '\'') {
365145510Sdarrenr				if (o->o_str[strlen(o->o_str) - 1] == c) {
366145510Sdarrenr					a->ac_run = strdup(o->o_str + 1);
367145510Sdarrenr					a->ac_run[strlen(a->ac_run) - 1] ='\0';
368145510Sdarrenr				} else
369145510Sdarrenr					a->ac_run = o->o_str;
370145510Sdarrenr			} else
371145510Sdarrenr				a->ac_run = o->o_str;
372145510Sdarrenr			o->o_str = NULL;
373145510Sdarrenr			break;
374145510Sdarrenr		case IPM_INTERFACE :
375145510Sdarrenr			a->ac_iface = o->o_str;
376145510Sdarrenr			o->o_str = NULL;
377145510Sdarrenr			break;
378145510Sdarrenr		case IPM_GROUP :
379145510Sdarrenr			if (o->o_str != NULL)
380145510Sdarrenr				strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
381145510Sdarrenr			else
382145510Sdarrenr				sprintf(a->ac_group, "%d", o->o_num);
383145510Sdarrenr			break;
384145510Sdarrenr		case IPM_LOGTAG :
385145510Sdarrenr			a->ac_logtag = o->o_num;
386145510Sdarrenr			break;
387145510Sdarrenr		case IPM_NATTAG :
388145510Sdarrenr			strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
389145510Sdarrenr			break;
390145510Sdarrenr		case IPM_PACKET :
391145510Sdarrenr			a->ac_packet = o->o_num;
392145510Sdarrenr			break;
393145510Sdarrenr		case IPM_PROTOCOL :
394145510Sdarrenr			a->ac_proto = o->o_num;
395145510Sdarrenr			break;
396145510Sdarrenr		case IPM_RULE :
397145510Sdarrenr			a->ac_rule = o->o_num;
398145510Sdarrenr			break;
399145510Sdarrenr		case IPM_RESULT :
400145510Sdarrenr			if (!strcasecmp(o->o_str, "pass"))
401145510Sdarrenr				a->ac_result = IPMR_PASS;
402145510Sdarrenr			else if (!strcasecmp(o->o_str, "block"))
403145510Sdarrenr				a->ac_result = IPMR_BLOCK;
404145510Sdarrenr			else if (!strcasecmp(o->o_str, "nomatch"))
405145510Sdarrenr				a->ac_result = IPMR_NOMATCH;
406145510Sdarrenr			else if (!strcasecmp(o->o_str, "log"))
407145510Sdarrenr				a->ac_result = IPMR_LOG;
408145510Sdarrenr			break;
409145510Sdarrenr		case IPM_SECOND :
410145510Sdarrenr			a->ac_second = o->o_num;
411145510Sdarrenr			break;
412145510Sdarrenr		case IPM_SRCIP :
413145510Sdarrenr			a->ac_sip = o->o_ip.s_addr;
414145510Sdarrenr			a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
415145510Sdarrenr			break;
416145510Sdarrenr		case IPM_SRCPORT :
417145510Sdarrenr			a->ac_sport = htons(o->o_num);
418145510Sdarrenr			break;
419145510Sdarrenr		case IPM_SAVE :
420145510Sdarrenr			if (a->ac_savefile != NULL) {
421145510Sdarrenr				fprintf(stderr, "%s redfined on line %d\n",
422145510Sdarrenr					yykeytostr(o->o_type), yylineNum);
423145510Sdarrenr				break;
424145510Sdarrenr			}
425145510Sdarrenr			a->ac_savefile = strdup(o->o_str);
426145510Sdarrenr			a->ac_savefp = fopen(o->o_str, "a");
427145510Sdarrenr			a->ac_dflag |= o->o_num & IPMDO_SAVERAW;
428145510Sdarrenr			break;
429145510Sdarrenr		case IPM_SYSLOG :
430145510Sdarrenr			if (a->ac_syslog != 0) {
431145510Sdarrenr				fprintf(stderr, "%s redfined on line %d\n",
432145510Sdarrenr					yykeytostr(o->o_type), yylineNum);
433145510Sdarrenr				break;
434145510Sdarrenr			}
435145510Sdarrenr			a->ac_syslog = 1;
436145510Sdarrenr			break;
437145510Sdarrenr		case IPM_TYPE :
438145510Sdarrenr			a->ac_type = o->o_num;
439145510Sdarrenr			break;
440145510Sdarrenr		case IPM_WITH :
441145510Sdarrenr			break;
442145510Sdarrenr		default :
443145510Sdarrenr			break;
444145510Sdarrenr		}
445145510Sdarrenr
446145510Sdarrenr		olist = o->o_next;
447145510Sdarrenr		if (o->o_str != NULL)
448145510Sdarrenr			free(o->o_str);
449145510Sdarrenr		free(o);
450145510Sdarrenr	}
451145510Sdarrenr	a->ac_next = alist;
452145510Sdarrenr	alist = a;
453145510Sdarrenr}
454145510Sdarrenr
455145510Sdarrenr
456145510Sdarrenrint check_action(buf, log, opts, lvl)
457145510Sdarrenrchar *buf, *log;
458145510Sdarrenrint opts, lvl;
459145510Sdarrenr{
460145510Sdarrenr	ipmon_action_t *a;
461145510Sdarrenr	struct timeval tv;
462145510Sdarrenr	ipflog_t *ipf;
463145510Sdarrenr	tcphdr_t *tcp;
464145510Sdarrenr	iplog_t *ipl;
465145510Sdarrenr	int matched;
466145510Sdarrenr	u_long t1;
467145510Sdarrenr	ip_t *ip;
468145510Sdarrenr
469145510Sdarrenr	matched = 0;
470145510Sdarrenr	ipl = (iplog_t *)buf;
471145510Sdarrenr	ipf = (ipflog_t *)(ipl +1);
472145510Sdarrenr	ip = (ip_t *)(ipf + 1);
473145510Sdarrenr	tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
474145510Sdarrenr
475145510Sdarrenr	for (a = alist; a != NULL; a = a->ac_next) {
476145510Sdarrenr		if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
477145510Sdarrenr			if (a->ac_direction == IPM_IN) {
478145510Sdarrenr				if ((ipf->fl_flags & FR_INQUE) == 0)
479145510Sdarrenr					continue;
480145510Sdarrenr			} else if (a->ac_direction == IPM_OUT) {
481145510Sdarrenr				if ((ipf->fl_flags & FR_OUTQUE) == 0)
482145510Sdarrenr					continue;
483145510Sdarrenr			}
484145510Sdarrenr		}
485145510Sdarrenr
486145510Sdarrenr		if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic))
487145510Sdarrenr			continue;
488145510Sdarrenr
489145510Sdarrenr		if ((a->ac_mflag & IPMAC_EVERY) != 0) {
490145510Sdarrenr			gettimeofday(&tv, NULL);
491145510Sdarrenr			t1 = tv.tv_sec - a->ac_lastsec;
492145510Sdarrenr			if (tv.tv_usec <= a->ac_lastusec)
493145510Sdarrenr				t1--;
494145510Sdarrenr			if (a->ac_second != 0) {
495145510Sdarrenr				if (t1 < a->ac_second)
496145510Sdarrenr					continue;
497145510Sdarrenr				a->ac_lastsec = tv.tv_sec;
498145510Sdarrenr				a->ac_lastusec = tv.tv_usec;
499145510Sdarrenr			}
500145510Sdarrenr
501145510Sdarrenr			if (a->ac_packet != 0) {
502145510Sdarrenr				if (a->ac_pktcnt == 0)
503145510Sdarrenr					a->ac_pktcnt++;
504145510Sdarrenr				else if (a->ac_pktcnt == a->ac_packet) {
505145510Sdarrenr					a->ac_pktcnt = 0;
506145510Sdarrenr					continue;
507145510Sdarrenr				} else {
508145510Sdarrenr					a->ac_pktcnt++;
509145510Sdarrenr					continue;
510145510Sdarrenr				}
511145510Sdarrenr			}
512145510Sdarrenr		}
513145510Sdarrenr
514145510Sdarrenr		if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
515145510Sdarrenr			if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip)
516145510Sdarrenr				continue;
517145510Sdarrenr		}
518145510Sdarrenr
519145510Sdarrenr		if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
520145510Sdarrenr			if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
521145510Sdarrenr				continue;
522145510Sdarrenr			if (tcp->th_dport != a->ac_dport)
523145510Sdarrenr				continue;
524145510Sdarrenr		}
525145510Sdarrenr
526145510Sdarrenr		if ((a->ac_mflag & IPMAC_GROUP) != 0) {
527145510Sdarrenr			if (strncmp(a->ac_group, ipf->fl_group,
528145510Sdarrenr				    FR_GROUPLEN) != 0)
529145510Sdarrenr				continue;
530145510Sdarrenr		}
531145510Sdarrenr
532145510Sdarrenr		if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
533145510Sdarrenr			if (strcmp(a->ac_iface, ipf->fl_ifname))
534145510Sdarrenr				continue;
535145510Sdarrenr		}
536145510Sdarrenr
537145510Sdarrenr		if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
538145510Sdarrenr			if (a->ac_proto != ip->ip_p)
539145510Sdarrenr				continue;
540145510Sdarrenr		}
541145510Sdarrenr
542145510Sdarrenr		if ((a->ac_mflag & IPMAC_RESULT) != 0) {
543145510Sdarrenr			if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
544145510Sdarrenr				if (a->ac_result != IPMR_NOMATCH)
545145510Sdarrenr					continue;
546145510Sdarrenr			} else if (FR_ISPASS(ipf->fl_flags)) {
547145510Sdarrenr				if (a->ac_result != IPMR_PASS)
548145510Sdarrenr					continue;
549145510Sdarrenr			} else if (FR_ISBLOCK(ipf->fl_flags)) {
550145510Sdarrenr				if (a->ac_result != IPMR_BLOCK)
551145510Sdarrenr					continue;
552145510Sdarrenr			} else {	/* Log only */
553145510Sdarrenr				if (a->ac_result != IPMR_LOG)
554145510Sdarrenr					continue;
555145510Sdarrenr			}
556145510Sdarrenr		}
557145510Sdarrenr
558145510Sdarrenr		if ((a->ac_mflag & IPMAC_RULE) != 0) {
559145510Sdarrenr			if (a->ac_rule != ipf->fl_rule)
560145510Sdarrenr				continue;
561145510Sdarrenr		}
562145510Sdarrenr
563145510Sdarrenr		if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
564145510Sdarrenr			if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip)
565145510Sdarrenr				continue;
566145510Sdarrenr		}
567145510Sdarrenr
568145510Sdarrenr		if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
569145510Sdarrenr			if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
570145510Sdarrenr				continue;
571145510Sdarrenr			if (tcp->th_sport != a->ac_sport)
572145510Sdarrenr				continue;
573145510Sdarrenr		}
574145510Sdarrenr
575145510Sdarrenr		if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
576145510Sdarrenr			if (a->ac_logtag != ipf->fl_logtag)
577145510Sdarrenr				continue;
578145510Sdarrenr		}
579145510Sdarrenr
580145510Sdarrenr		if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
581145510Sdarrenr			if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
582145510Sdarrenr				    IPFTAG_LEN) != 0)
583145510Sdarrenr				continue;
584145510Sdarrenr		}
585145510Sdarrenr
586145510Sdarrenr		matched = 1;
587145510Sdarrenr
588145510Sdarrenr		/*
589145510Sdarrenr		 * It matched so now execute the command
590145510Sdarrenr		 */
591145510Sdarrenr		if (a->ac_syslog != 0) {
592145510Sdarrenr			syslog(lvl, "%s", log);
593145510Sdarrenr		}
594145510Sdarrenr
595145510Sdarrenr		if (a->ac_savefp != NULL) {
596145510Sdarrenr			if (a->ac_dflag & IPMDO_SAVERAW)
597145510Sdarrenr				fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp);
598145510Sdarrenr			else
599145510Sdarrenr				fputs(log, a->ac_savefp);
600145510Sdarrenr		}
601145510Sdarrenr
602145510Sdarrenr		if (a->ac_exec != NULL) {
603145510Sdarrenr			switch (fork())
604145510Sdarrenr			{
605145510Sdarrenr			case 0 :
606145510Sdarrenr			{
607145510Sdarrenr				FILE *pi;
608145510Sdarrenr
609145510Sdarrenr				pi = popen(a->ac_run, "w");
610145510Sdarrenr				if (pi != NULL) {
611145510Sdarrenr					fprintf(pi, "%s\n", log);
612145510Sdarrenr					if ((opts & OPT_HEXHDR) != 0) {
613145510Sdarrenr						dumphex(pi, 0, buf,
614145510Sdarrenr							sizeof(*ipl) +
615145510Sdarrenr							sizeof(*ipf));
616145510Sdarrenr					}
617145510Sdarrenr					if ((opts & OPT_HEXBODY) != 0) {
618145510Sdarrenr						dumphex(pi, 0, (char *)ip,
619145510Sdarrenr							ipf->fl_hlen +
620145510Sdarrenr							ipf->fl_plen);
621145510Sdarrenr					}
622145510Sdarrenr					pclose(pi);
623145510Sdarrenr				}
624145510Sdarrenr				exit(1);
625145510Sdarrenr			}
626145510Sdarrenr			case -1 :
627145510Sdarrenr				break;
628145510Sdarrenr			default :
629145510Sdarrenr				break;
630145510Sdarrenr			}
631145510Sdarrenr		}
632145510Sdarrenr	}
633145510Sdarrenr
634145510Sdarrenr	return matched;
635145510Sdarrenr}
636145510Sdarrenr
637145510Sdarrenr
638145510Sdarrenrstatic void free_action(a)
639145510Sdarrenripmon_action_t *a;
640145510Sdarrenr{
641145510Sdarrenr	if (a->ac_savefile != NULL) {
642145510Sdarrenr		free(a->ac_savefile);
643145510Sdarrenr		a->ac_savefile = NULL;
644145510Sdarrenr	}
645145510Sdarrenr	if (a->ac_savefp != NULL) {
646145510Sdarrenr		fclose(a->ac_savefp);
647145510Sdarrenr		a->ac_savefp = NULL;
648145510Sdarrenr	}
649145510Sdarrenr	if (a->ac_exec != NULL) {
650145510Sdarrenr		free(a->ac_exec);
651145510Sdarrenr		if (a->ac_run == a->ac_exec)
652145510Sdarrenr			a->ac_run = NULL;
653145510Sdarrenr		a->ac_exec = NULL;
654145510Sdarrenr	}
655145510Sdarrenr	if (a->ac_run != NULL) {
656145510Sdarrenr		free(a->ac_run);
657145510Sdarrenr		a->ac_run = NULL;
658145510Sdarrenr	}
659145510Sdarrenr	if (a->ac_iface != NULL) {
660145510Sdarrenr		free(a->ac_iface);
661145510Sdarrenr		a->ac_iface = NULL;
662145510Sdarrenr	}
663145510Sdarrenr	a->ac_next = NULL;
664145510Sdarrenr	free(a);
665145510Sdarrenr}
666145510Sdarrenr
667145510Sdarrenr
668145510Sdarrenrint load_config(file)
669145510Sdarrenrchar *file;
670145510Sdarrenr{
671145510Sdarrenr	ipmon_action_t *a;
672145510Sdarrenr	FILE *fp;
673145510Sdarrenr	char *s;
674145510Sdarrenr
675145510Sdarrenr	s = getenv("YYDEBUG");
676145510Sdarrenr	if (s != NULL)
677145510Sdarrenr		yydebug = atoi(s);
678145510Sdarrenr	else
679145510Sdarrenr		yydebug = 0;
680145510Sdarrenr
681145510Sdarrenr	while ((a = alist) != NULL) {
682145510Sdarrenr		alist = a->ac_next;
683145510Sdarrenr		free_action(a);
684145510Sdarrenr	}
685145510Sdarrenr
686145510Sdarrenr	yylineNum = 1;
687145510Sdarrenr
688145510Sdarrenr	(void) yysettab(yywords);
689145510Sdarrenr
690145510Sdarrenr	fp = fopen(file, "r");
691145510Sdarrenr	if (!fp) {
692145510Sdarrenr		perror("load_config:fopen:");
693145510Sdarrenr		return -1;
694145510Sdarrenr	}
695145510Sdarrenr	yyin = fp;
696145510Sdarrenr	while (!feof(fp))
697145510Sdarrenr		yyparse();
698145510Sdarrenr	fclose(fp);
699145510Sdarrenr	return 0;
700145510Sdarrenr}
701