1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3170268Sdarrenr/*
4170268Sdarrenr * Copyright (C) 2001-2006 by Darren Reed.
5170268Sdarrenr *
6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7170268Sdarrenr */
8145510Sdarrenr%{
9145510Sdarrenr#include "ipf.h"
10145510Sdarrenr#include <sys/ioctl.h>
11145510Sdarrenr#include <syslog.h>
12145510Sdarrenr#ifdef IPFILTER_BPF
13145510Sdarrenr# include <pcap.h>
14145510Sdarrenr#endif
15145510Sdarrenr#include "netinet/ip_pool.h"
16145510Sdarrenr#include "netinet/ip_htable.h"
17145510Sdarrenr#include "netinet/ipl.h"
18145510Sdarrenr#include "ipf_l.h"
19145510Sdarrenr
20145510Sdarrenr#define	YYDEBUG	1
21145510Sdarrenr#define	DOALL(x)	for (fr = frc; fr != NULL; fr = fr->fr_next) { x }
22145510Sdarrenr#define	DOREM(x)	for (; fr != NULL; fr = fr->fr_next) { x }
23145510Sdarrenr
24145510Sdarrenrextern	void	yyerror __P((char *));
25145510Sdarrenrextern	int	yyparse __P((void));
26145510Sdarrenrextern	int	yylex __P((void));
27145510Sdarrenrextern	int	yydebug;
28145510Sdarrenrextern	FILE	*yyin;
29145510Sdarrenrextern	int	yylineNum;
30145510Sdarrenr
31145510Sdarrenrstatic	void	newrule __P((void));
32145510Sdarrenrstatic	void	setipftype __P((void));
33145510Sdarrenrstatic	u_32_t	lookuphost __P((char *));
34145510Sdarrenrstatic	void	dobpf __P((int, char *));
35145510Sdarrenrstatic	void	resetaddr __P((void));
36145510Sdarrenrstatic	struct	alist_s	*newalist __P((struct alist_s *));
37145510Sdarrenrstatic	u_int	makehash __P((struct alist_s *));
38145510Sdarrenrstatic	int	makepool __P((struct alist_s *));
39145510Sdarrenrstatic	frentry_t *addrule __P((void));
40145510Sdarrenrstatic	void	setsyslog __P((void));
41145510Sdarrenrstatic	void	unsetsyslog __P((void));
42145510Sdarrenrstatic	void	fillgroup __P((frentry_t *));
43145510Sdarrenr
44145510Sdarrenrfrentry_t	*fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL;
45145510Sdarrenr
46145510Sdarrenrstatic	int		ifpflag = 0;
47145510Sdarrenrstatic	int		nowith = 0;
48145510Sdarrenrstatic	int		dynamic = -1;
49145510Sdarrenrstatic	int		pooled = 0;
50145510Sdarrenrstatic	int		hashed = 0;
51145510Sdarrenrstatic	int		nrules = 0;
52145510Sdarrenrstatic	int		newlist = 0;
53145510Sdarrenrstatic	int		added = 0;
54145510Sdarrenrstatic	int		ipffd = -1;
55145510Sdarrenrstatic	int		*yycont = 0;
56145510Sdarrenrstatic	ioctlfunc_t	ipfioctl[IPL_LOGSIZE];
57145510Sdarrenrstatic	addfunc_t	ipfaddfunc = NULL;
58145510Sdarrenrstatic	struct	wordtab ipfwords[95];
59145510Sdarrenrstatic	struct	wordtab	addrwords[4];
60145510Sdarrenrstatic	struct	wordtab	maskwords[5];
61145510Sdarrenrstatic	struct	wordtab icmpcodewords[17];
62145510Sdarrenrstatic	struct	wordtab icmptypewords[16];
63145510Sdarrenrstatic	struct	wordtab ipv4optwords[25];
64145510Sdarrenrstatic	struct	wordtab ipv4secwords[9];
65153881Sguidostatic	struct	wordtab ipv6optwords[9];
66145510Sdarrenrstatic	struct	wordtab logwords[33];
67145510Sdarrenr
68145510Sdarrenr%}
69145510Sdarrenr%union	{
70145510Sdarrenr	char	*str;
71145510Sdarrenr	u_32_t	num;
72145510Sdarrenr	struct	in_addr	ipa;
73145510Sdarrenr	frentry_t	fr;
74145510Sdarrenr	frtuc_t	*frt;
75145510Sdarrenr	struct	alist_s	*alist;
76145510Sdarrenr	u_short	port;
77145510Sdarrenr	struct	{
78145510Sdarrenr		u_short	p1;
79145510Sdarrenr		u_short	p2;
80145510Sdarrenr		int	pc;
81145510Sdarrenr	} pc;
82145510Sdarrenr	struct	{
83145510Sdarrenr		union	i6addr	a;
84145510Sdarrenr		union	i6addr	m;
85145510Sdarrenr	} ipp;
86145510Sdarrenr	union	i6addr	ip6;
87161357Sguido	struct	{
88161357Sguido		char	*if1;
89161357Sguido		char	*if2;
90161357Sguido	} ifs;
91145510Sdarrenr};
92145510Sdarrenr
93145510Sdarrenr%type	<port>	portnum
94145510Sdarrenr%type	<num>	facility priority icmpcode seclevel secname icmptype
95145510Sdarrenr%type	<num>	opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr
96145510Sdarrenr%type	<num>	portc porteq
97145510Sdarrenr%type	<ipa>	hostname ipv4 ipv4mask ipv4_16 ipv4_24
98145510Sdarrenr%type	<ip6>	ipv6mask
99145510Sdarrenr%type	<ipp>	addr ipaddr
100145510Sdarrenr%type	<str>	servicename name interfacename
101145510Sdarrenr%type	<pc>	portrange portcomp
102145510Sdarrenr%type	<alist>	addrlist poollist
103161357Sguido%type	<ifs>	onname
104145510Sdarrenr
105145510Sdarrenr%token	<num>	YY_NUMBER YY_HEX
106145510Sdarrenr%token	<str>	YY_STR
107145510Sdarrenr%token		YY_COMMENT
108145510Sdarrenr%token		YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
109145510Sdarrenr%token		YY_RANGE_OUT YY_RANGE_IN
110145510Sdarrenr%token	<ip6>	YY_IPV6
111145510Sdarrenr
112161357Sguido%token	IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL IPFY_NOMATCH
113145510Sdarrenr%token	IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST
114145510Sdarrenr%token	IPFY_IN IPFY_OUT
115145510Sdarrenr%token	IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA
116145510Sdarrenr%token	IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO
117145510Sdarrenr%token	IPFY_TOS IPFY_TTL IPFY_PROTO
118145510Sdarrenr%token	IPFY_HEAD IPFY_GROUP
119145510Sdarrenr%token	IPFY_AUTH IPFY_PREAUTH
120145510Sdarrenr%token	IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK
121145510Sdarrenr%token	IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP
122145510Sdarrenr%token	IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH
123145510Sdarrenr%token	IPFY_PPS
124145510Sdarrenr%token	IPFY_ESP IPFY_AH
125145510Sdarrenr%token	IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT
126145510Sdarrenr%token	IPFY_TCPUDP IPFY_TCP IPFY_UDP
127145510Sdarrenr%token	IPFY_FLAGS IPFY_MULTICAST
128145510Sdarrenr%token	IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER
129145510Sdarrenr%token	IPFY_PORT
130145510Sdarrenr%token	IPFY_NOW
131145510Sdarrenr%token	IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
132145510Sdarrenr%token	IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG
133145510Sdarrenr%token	IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR
134145510Sdarrenr%token	IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
135145510Sdarrenr%token	IPFY_SYNC IPFY_FRAGBODY
136145510Sdarrenr%token	IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
137145510Sdarrenr%token	IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
138145510Sdarrenr%token	IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
139145510Sdarrenr%token	IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA
140145510Sdarrenr%token	IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS
141145510Sdarrenr%token	IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP
142145510Sdarrenr%token	IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2
143145510Sdarrenr%token	IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3
144145510Sdarrenr
145145510Sdarrenr%token	IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS
146145510Sdarrenr%token	IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING
147153881Sguido%token	IPFY_IPV6OPT_MOBILITY IPFY_IPV6OPT_ESP IPFY_IPV6OPT_FRAG
148145510Sdarrenr
149145510Sdarrenr%token	IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH
150145510Sdarrenr%token	IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST
151145510Sdarrenr%token	IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP
152145510Sdarrenr%token	IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD
153145510Sdarrenr%token	IPFY_ICMPT_ROUTERSOL
154145510Sdarrenr
155145510Sdarrenr%token	IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR
156145510Sdarrenr%token	IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK
157145510Sdarrenr%token	IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO
158145510Sdarrenr%token	IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE
159145510Sdarrenr%token	IPFY_ICMPC_CUTPRE
160145510Sdarrenr
161145510Sdarrenr%token	IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH
162145510Sdarrenr%token	IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON
163145510Sdarrenr%token	IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3
164145510Sdarrenr%token	IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7
165145510Sdarrenr%token	IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT
166145510Sdarrenr%token	IPFY_FAC_LFMT IPFY_FAC_CONSOLE
167145510Sdarrenr
168145510Sdarrenr%token	IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN
169145510Sdarrenr%token	IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG
170145510Sdarrenr%%
171145510Sdarrenrfile:	line
172145510Sdarrenr	| assign
173145510Sdarrenr	| file line
174145510Sdarrenr	| file assign
175145510Sdarrenr	;
176145510Sdarrenr
177170268Sdarrenrline:	rule		{ while ((fr = frtop) != NULL) {
178145510Sdarrenr				frtop = fr->fr_next;
179145510Sdarrenr				fr->fr_next = NULL;
180145510Sdarrenr				(*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr);
181145510Sdarrenr				fr->fr_next = frold;
182145510Sdarrenr				frold = fr;
183145510Sdarrenr			  }
184145510Sdarrenr			  resetlexer();
185145510Sdarrenr			}
186145510Sdarrenr	| YY_COMMENT
187145510Sdarrenr	;
188145510Sdarrenr
189161357Sguidoxx:					{ newrule(); }
190145510Sdarrenr	;
191145510Sdarrenr
192145510Sdarrenrassign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
193145510Sdarrenr					  resetlexer();
194145510Sdarrenr					  free($1);
195145510Sdarrenr					  free($3);
196170268Sdarrenr					  yyvarnext = 0;
197145510Sdarrenr					}
198145510Sdarrenr	;
199145510Sdarrenr
200145510Sdarrenrassigning:
201145510Sdarrenr	'='				{ yyvarnext = 1; }
202145510Sdarrenr	;
203145510Sdarrenr
204145510Sdarrenrrule:	inrule eol
205145510Sdarrenr	| outrule eol
206145510Sdarrenr	;
207145510Sdarrenr
208145510Sdarrenreol:	| ';'
209145510Sdarrenr	;
210145510Sdarrenr
211145510Sdarrenrinrule:
212145510Sdarrenr	rulehead markin inopts rulemain ruletail intag ruletail2
213145510Sdarrenr	;
214145510Sdarrenr
215145510Sdarrenroutrule:
216145510Sdarrenr	rulehead markout outopts rulemain ruletail outtag ruletail2
217145510Sdarrenr	;
218145510Sdarrenr
219145510Sdarrenrrulehead:
220170268Sdarrenr	xx collection action
221170268Sdarrenr	| xx insert collection action
222145510Sdarrenr	;
223145510Sdarrenr
224145510Sdarrenrmarkin:	IPFY_IN				{ fr->fr_flags |= FR_INQUE; }
225145510Sdarrenr	;
226145510Sdarrenr
227145510Sdarrenrmarkout:
228145510Sdarrenr	IPFY_OUT			{ fr->fr_flags |= FR_OUTQUE; }
229145510Sdarrenr	;
230145510Sdarrenr
231145510Sdarrenrrulemain:
232145510Sdarrenr	ipfrule
233145510Sdarrenr	| bpfrule
234145510Sdarrenr	;
235145510Sdarrenr
236145510Sdarrenripfrule:
237145510Sdarrenr	tos ttl proto ip
238145510Sdarrenr	;
239145510Sdarrenr
240145510Sdarrenrbpfrule:
241145510Sdarrenr	IPFY_BPFV4 '{' YY_STR '}' 	{ dobpf(4, $3); free($3); }
242145510Sdarrenr	| IPFY_BPFV6 '{' YY_STR '}' 	{ dobpf(6, $3); free($3); }
243145510Sdarrenr	;
244145510Sdarrenr
245145510Sdarrenrruletail:
246145510Sdarrenr	with keep head group
247145510Sdarrenr	;
248145510Sdarrenr
249145510Sdarrenrruletail2:
250145510Sdarrenr	pps age new
251145510Sdarrenr	;
252145510Sdarrenr
253145510Sdarrenrintag:	settagin matchtagin
254145510Sdarrenr	;
255145510Sdarrenr
256145510Sdarrenrouttag:	settagout matchtagout
257145510Sdarrenr	;
258145510Sdarrenr
259145510Sdarrenrinsert:
260145510Sdarrenr	'@' YY_NUMBER			{ fr->fr_hits = (U_QUAD_T)$2 + 1; }
261145510Sdarrenr	;
262145510Sdarrenr
263145510Sdarrenrcollection:
264145510Sdarrenr	| YY_NUMBER			{ fr->fr_collect = $1; }
265145510Sdarrenr	;
266145510Sdarrenr
267145510Sdarrenraction:	block
268145510Sdarrenr	| IPFY_PASS			{ fr->fr_flags |= FR_PASS; }
269161357Sguido	| IPFY_NOMATCH			{ fr->fr_flags |= FR_NOMATCH; }
270145510Sdarrenr	| log
271145510Sdarrenr	| IPFY_COUNT			{ fr->fr_flags |= FR_ACCOUNT; }
272145510Sdarrenr	| auth
273145510Sdarrenr	| IPFY_SKIP YY_NUMBER		{ fr->fr_flags |= FR_SKIP;
274145510Sdarrenr					  fr->fr_arg = $2; }
275145510Sdarrenr	| IPFY_CALL func
276145510Sdarrenr	| IPFY_CALL IPFY_NOW func	{ fr->fr_flags |= FR_CALLNOW; }
277145510Sdarrenr	;
278145510Sdarrenr
279145510Sdarrenrblock:	blocked
280145510Sdarrenr	| blocked blockreturn
281145510Sdarrenr	;
282145510Sdarrenr
283145510Sdarrenrblocked:
284145510Sdarrenr	IPFY_BLOCK			{ fr->fr_flags = FR_BLOCK; }
285145510Sdarrenr	;
286145510Sdarrenrblockreturn:
287145510Sdarrenr	IPFY_RETICMP			{ fr->fr_flags |= FR_RETICMP; }
288145510Sdarrenr	| IPFY_RETICMP returncode	{ fr->fr_flags |= FR_RETICMP; }
289145510Sdarrenr	| IPFY_RETICMPASDST		{ fr->fr_flags |= FR_FAKEICMP; }
290145510Sdarrenr	| IPFY_RETICMPASDST returncode	{ fr->fr_flags |= FR_FAKEICMP; }
291145510Sdarrenr	| IPFY_RETRST			{ fr->fr_flags |= FR_RETRST; }
292145510Sdarrenr	;
293145510Sdarrenr
294145510Sdarrenrlog:	IPFY_LOG			{ fr->fr_flags |= FR_LOG; }
295145510Sdarrenr	| IPFY_LOG logoptions		{ fr->fr_flags |= FR_LOG; }
296145510Sdarrenr	;
297145510Sdarrenr
298145510Sdarrenrauth:	IPFY_AUTH			{ fr->fr_flags |= FR_AUTH; }
299161357Sguido	| IPFY_AUTH blockreturn		{ fr->fr_flags |= FR_AUTH;}
300145510Sdarrenr	| IPFY_PREAUTH			{ fr->fr_flags |= FR_PREAUTH; }
301145510Sdarrenr	;
302145510Sdarrenr
303145510Sdarrenrfunc:	YY_STR '/' YY_NUMBER	{ fr->fr_func = nametokva($1,
304145510Sdarrenr							  ipfioctl[IPL_LOGIPF]);
305145510Sdarrenr				  fr->fr_arg = $3;
306145510Sdarrenr				  free($1); }
307145510Sdarrenr	;
308145510Sdarrenr
309145510Sdarrenrinopts:
310145510Sdarrenr	| inopts inopt
311145510Sdarrenr	;
312145510Sdarrenr
313145510Sdarrenrinopt:
314145510Sdarrenr	logopt
315145510Sdarrenr	| quick
316145510Sdarrenr	| on
317145510Sdarrenr	| dup
318145510Sdarrenr	| froute
319145510Sdarrenr	| proute
320145510Sdarrenr	| replyto
321145510Sdarrenr	;
322145510Sdarrenr
323145510Sdarrenroutopts:
324145510Sdarrenr	| outopts outopt
325145510Sdarrenr	;
326145510Sdarrenr
327145510Sdarrenroutopt:
328145510Sdarrenr	logopt
329145510Sdarrenr	| quick
330145510Sdarrenr	| on
331145510Sdarrenr	| dup
332145510Sdarrenr	| proute
333145510Sdarrenr	| replyto
334145510Sdarrenr	;
335145510Sdarrenr
336145510Sdarrenrtos:	| settos YY_NUMBER	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
337145510Sdarrenr	| settos YY_HEX	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
338145510Sdarrenr	| settos lstart toslist lend
339145510Sdarrenr	;
340145510Sdarrenr
341145510Sdarrenrsettos:	IPFY_TOS			{ setipftype(); }
342145510Sdarrenr	;
343145510Sdarrenr
344145510Sdarrenrtoslist:
345145510Sdarrenr	YY_NUMBER	{ DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
346145510Sdarrenr	| YY_HEX	{ DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
347145510Sdarrenr	| toslist lmore YY_NUMBER
348145510Sdarrenr			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
349145510Sdarrenr	| toslist lmore YY_HEX
350145510Sdarrenr			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
351145510Sdarrenr	;
352145510Sdarrenr
353145510Sdarrenrttl:	| setttl YY_NUMBER
354145510Sdarrenr			{ DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
355145510Sdarrenr	| setttl lstart ttllist lend
356145510Sdarrenr	;
357145510Sdarrenr
358145510Sdarrenrlstart:	'('				{ newlist = 1; fr = frc; added = 0; }
359145510Sdarrenr	;
360145510Sdarrenr
361145510Sdarrenrlend:	')'				{ nrules += added; }
362145510Sdarrenr	;
363145510Sdarrenr
364145510Sdarrenrlmore:	lanother			{ if (newlist == 1) {
365145510Sdarrenr						newlist = 0;
366145510Sdarrenr					  }
367145510Sdarrenr					  fr = addrule();
368145510Sdarrenr					  if (yycont != NULL)
369145510Sdarrenr						*yycont = 1;
370145510Sdarrenr					}
371145510Sdarrenr	;
372145510Sdarrenr
373145510Sdarrenrlanother:
374145510Sdarrenr	| ','
375145510Sdarrenr	;
376145510Sdarrenr
377145510Sdarrenrsetttl:	IPFY_TTL			{ setipftype(); }
378145510Sdarrenr	;
379145510Sdarrenr
380145510Sdarrenrttllist:
381145510Sdarrenr	YY_NUMBER	{ DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) }
382145510Sdarrenr	| ttllist lmore YY_NUMBER
383145510Sdarrenr			{ DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) }
384145510Sdarrenr	;
385145510Sdarrenr
386145510Sdarrenrproto:	| protox protocol		{ yyresetdict(); }
387145510Sdarrenr	;
388145510Sdarrenr
389145510Sdarrenrprotox:	IPFY_PROTO			{ setipftype();
390145510Sdarrenr					  fr = frc;
391145510Sdarrenr					  yysetdict(NULL); }
392145510Sdarrenr	;
393145510Sdarrenr
394145510Sdarrenrip:	srcdst flags icmp
395145510Sdarrenr	;
396145510Sdarrenr
397145510Sdarrenrgroup:	| IPFY_GROUP YY_STR		{ DOALL(strncpy(fr->fr_group, $2, \
398145510Sdarrenr							FR_GROUPLEN); \
399145510Sdarrenr							fillgroup(fr););
400145510Sdarrenr					  free($2); }
401145510Sdarrenr	| IPFY_GROUP YY_NUMBER		{ DOALL(sprintf(fr->fr_group, "%d", \
402145510Sdarrenr							$2); \
403145510Sdarrenr							fillgroup(fr);) }
404145510Sdarrenr	;
405145510Sdarrenr
406145510Sdarrenrhead:	| IPFY_HEAD YY_STR		{ DOALL(strncpy(fr->fr_grhead, $2, \
407145510Sdarrenr							FR_GROUPLEN););
408145510Sdarrenr					  free($2); }
409145510Sdarrenr	| IPFY_HEAD YY_NUMBER		{ DOALL(sprintf(fr->fr_grhead, "%d", \
410145510Sdarrenr							$2);) }
411145510Sdarrenr	;
412145510Sdarrenr
413145510Sdarrenrsettagin:
414145510Sdarrenr	| IPFY_SETTAG '(' taginlist ')'
415145510Sdarrenr	;
416145510Sdarrenr
417145510Sdarrenrtaginlist:
418145510Sdarrenr	taginspec
419145510Sdarrenr	| taginlist ',' taginspec
420145510Sdarrenr	;
421145510Sdarrenr
422145510Sdarrenrtaginspec:
423145510Sdarrenr	logtag
424145510Sdarrenr	;
425145510Sdarrenr
426145510Sdarrenrnattag:	IPFY_NAT '=' YY_STR		{ DOALL(strncpy(fr->fr_nattag.ipt_tag,\
427145510Sdarrenr						$3, IPFTAG_LEN););
428145510Sdarrenr					  free($3); }
429145510Sdarrenr	| IPFY_NAT '=' YY_NUMBER	{ DOALL(sprintf(fr->fr_nattag.ipt_tag,\
430145510Sdarrenr						"%d", $3 & 0xffffffff);) }
431145510Sdarrenr	;
432145510Sdarrenr
433145510Sdarrenrlogtag:	IPFY_LOG '=' YY_NUMBER		{ DOALL(fr->fr_logtag = $3;) }
434145510Sdarrenr	;
435145510Sdarrenr
436145510Sdarrenrsettagout:
437145510Sdarrenr	| IPFY_SETTAG '(' tagoutlist ')'
438145510Sdarrenr	;
439145510Sdarrenr
440145510Sdarrenrtagoutlist:
441145510Sdarrenr	tagoutspec
442145510Sdarrenr	| tagoutlist ',' tagoutspec
443145510Sdarrenr	;
444145510Sdarrenr
445145510Sdarrenrtagoutspec:
446145510Sdarrenr	logtag
447145510Sdarrenr	| nattag
448145510Sdarrenr	;
449145510Sdarrenr
450145510Sdarrenrmatchtagin:
451145510Sdarrenr	| IPFY_MATCHTAG '(' tagoutlist ')'
452145510Sdarrenr	;
453145510Sdarrenr
454145510Sdarrenrmatchtagout:
455145510Sdarrenr	| IPFY_MATCHTAG '(' taginlist ')'
456145510Sdarrenr	;
457145510Sdarrenr
458145510Sdarrenrpps:	| IPFY_PPS YY_NUMBER		{ DOALL(fr->fr_pps = $2;) }
459145510Sdarrenr	;
460145510Sdarrenr
461145510Sdarrenrnew:	| savegroup file restoregroup
462145510Sdarrenr	;
463145510Sdarrenr
464145510Sdarrenrsavegroup:
465145510Sdarrenr	'{'
466145510Sdarrenr	;
467145510Sdarrenr
468145510Sdarrenrrestoregroup:
469145510Sdarrenr	'}'
470145510Sdarrenr	;
471145510Sdarrenr
472145510Sdarrenrlogopt:	log
473145510Sdarrenr	;
474145510Sdarrenr
475145510Sdarrenrquick:
476145510Sdarrenr	IPFY_QUICK			{ fr->fr_flags |= FR_QUICK; }
477145510Sdarrenr	;
478145510Sdarrenr
479145510Sdarrenron:	IPFY_ON onname
480161357Sguido	| IPFY_ON lstart onlist lend
481145510Sdarrenr	| IPFY_ON onname IPFY_INVIA vianame
482145510Sdarrenr	| IPFY_ON onname IPFY_OUTVIA vianame
483145510Sdarrenr	;
484145510Sdarrenr
485161357Sguidoonlist:	onname			{ DOREM(strncpy(fr->fr_ifnames[0], $1.if1, \
486161357Sguido					sizeof(fr->fr_ifnames[0])); 	   \
487161357Sguido					if ($1.if2 != NULL) {		   \
488161357Sguido						strncpy(fr->fr_ifnames[1], \
489161357Sguido							$1.if2,		   \
490161357Sguido						sizeof(fr->fr_ifnames[1]));\
491161357Sguido					}				   \
492161357Sguido					) }
493161357Sguido	| onlist lmore onname	{ DOREM(strncpy(fr->fr_ifnames[0], $3.if1, \
494161357Sguido					sizeof(fr->fr_ifnames[0])); 	   \
495161357Sguido					if ($3.if2 != NULL) {		   \
496161357Sguido						strncpy(fr->fr_ifnames[1], \
497161357Sguido							$3.if2,		   \
498161357Sguido						sizeof(fr->fr_ifnames[1]));\
499161357Sguido					}				   \
500161357Sguido					) }
501161357Sguido	;
502161357Sguido
503145510Sdarrenronname:	interfacename
504145510Sdarrenr		{ strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
505161357Sguido		  $$.if1 = fr->fr_ifnames[0];
506161357Sguido		  $$.if2 = NULL;
507145510Sdarrenr		  free($1);
508145510Sdarrenr		}
509145510Sdarrenr	| interfacename ',' interfacename
510145510Sdarrenr		{ strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
511161357Sguido		  $$.if1 = fr->fr_ifnames[0];
512145510Sdarrenr		  free($1);
513145510Sdarrenr		  strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1]));
514161357Sguido		  $$.if1 = fr->fr_ifnames[1];
515145510Sdarrenr		  free($3);
516145510Sdarrenr		}
517145510Sdarrenr	;
518145510Sdarrenr
519145510Sdarrenrvianame:
520145510Sdarrenr	name
521145510Sdarrenr		{ strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
522145510Sdarrenr		  free($1);
523145510Sdarrenr		}
524145510Sdarrenr	| name ',' name
525145510Sdarrenr		{ strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
526145510Sdarrenr		  free($1);
527145510Sdarrenr		  strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3]));
528145510Sdarrenr		  free($3);
529145510Sdarrenr		}
530145510Sdarrenr	;
531145510Sdarrenr
532145510Sdarrenrdup:	IPFY_DUPTO name
533145510Sdarrenr	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
534145510Sdarrenr	  free($2);
535145510Sdarrenr	}
536145510Sdarrenr	| IPFY_DUPTO name duptoseparator hostname
537145510Sdarrenr	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
538145510Sdarrenr	  fr->fr_dif.fd_ip = $4;
539145510Sdarrenr	  yyexpectaddr = 0;
540145510Sdarrenr	  free($2);
541145510Sdarrenr	}
542145510Sdarrenr	| IPFY_DUPTO name duptoseparator YY_IPV6
543145510Sdarrenr	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
544145510Sdarrenr	  bcopy(&$4, &fr->fr_dif.fd_ip6, sizeof(fr->fr_dif.fd_ip6));
545145510Sdarrenr	  yyexpectaddr = 0;
546145510Sdarrenr	  free($2);
547145510Sdarrenr	}
548145510Sdarrenr	;
549145510Sdarrenr
550145510Sdarrenrduptoseparator:
551145510Sdarrenr	':'	{ yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); }
552145510Sdarrenr	;
553145510Sdarrenr
554145510Sdarrenrfroute:	IPFY_FROUTE			{ fr->fr_flags |= FR_FASTROUTE; }
555145510Sdarrenr	;
556145510Sdarrenr
557145510Sdarrenrproute:	routeto name
558145510Sdarrenr	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
559145510Sdarrenr	  free($2);
560145510Sdarrenr	}
561145510Sdarrenr	| routeto name duptoseparator hostname
562145510Sdarrenr	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
563145510Sdarrenr	  fr->fr_tif.fd_ip = $4;
564145510Sdarrenr	  yyexpectaddr = 0;
565145510Sdarrenr	  free($2);
566145510Sdarrenr	}
567145510Sdarrenr	| routeto name duptoseparator YY_IPV6
568145510Sdarrenr	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
569145510Sdarrenr	  bcopy(&$4, &fr->fr_tif.fd_ip6, sizeof(fr->fr_tif.fd_ip6));
570145510Sdarrenr	  yyexpectaddr = 0;
571145510Sdarrenr	  free($2);
572145510Sdarrenr	}
573145510Sdarrenr	;
574145510Sdarrenr
575145510Sdarrenrrouteto:
576145510Sdarrenr	IPFY_TO
577145510Sdarrenr	| IPFY_ROUTETO
578145510Sdarrenr	;
579145510Sdarrenr
580145510Sdarrenrreplyto:
581145510Sdarrenr	IPFY_REPLY_TO name
582145510Sdarrenr	{ strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
583145510Sdarrenr	  free($2);
584145510Sdarrenr	}
585145510Sdarrenr	| IPFY_REPLY_TO name duptoseparator hostname
586145510Sdarrenr	{ strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
587145510Sdarrenr	  fr->fr_rif.fd_ip = $4;
588145510Sdarrenr	  free($2);
589145510Sdarrenr	}
590145510Sdarrenr	;
591145510Sdarrenr
592145510Sdarrenrlogoptions:
593145510Sdarrenr	logoption
594145510Sdarrenr	| logoptions logoption
595145510Sdarrenr	;
596145510Sdarrenr
597145510Sdarrenrlogoption:
598145510Sdarrenr	IPFY_BODY			{ fr->fr_flags |= FR_LOGBODY; }
599145510Sdarrenr	| IPFY_FIRST			{ fr->fr_flags |= FR_LOGFIRST; }
600145510Sdarrenr	| IPFY_ORBLOCK			{ fr->fr_flags |= FR_LOGORBLOCK; }
601145510Sdarrenr	| level loglevel		{ unsetsyslog(); }
602145510Sdarrenr	;
603145510Sdarrenr
604145510Sdarrenrreturncode:
605145510Sdarrenr	starticmpcode icmpcode ')'	{ fr->fr_icode = $2; yyresetdict(); }
606145510Sdarrenr	;
607145510Sdarrenr
608145510Sdarrenrstarticmpcode:
609145510Sdarrenr	'('				{ yysetdict(icmpcodewords); }
610145510Sdarrenr	;
611145510Sdarrenr
612145510Sdarrenrsrcdst:	| IPFY_ALL
613145510Sdarrenr	| fromto
614145510Sdarrenr	;
615145510Sdarrenr
616145510Sdarrenrprotocol:
617145510Sdarrenr	YY_NUMBER		{ DOREM(fr->fr_proto = $1; \
618145510Sdarrenr					fr->fr_mproto = 0xff;) }
619145510Sdarrenr	| YY_STR		{ if (!strcmp($1, "tcp-udp")) {
620145510Sdarrenr					DOREM(fr->fr_flx |= FI_TCPUDP; \
621145510Sdarrenr					      fr->fr_mflx |= FI_TCPUDP;)
622145510Sdarrenr				  } else {
623145510Sdarrenr					int p = getproto($1);
624145510Sdarrenr					if (p == -1)
625145510Sdarrenr						yyerror("protocol unknown");
626145510Sdarrenr					DOREM(fr->fr_proto = p; \
627145510Sdarrenr						fr->fr_mproto = 0xff;)
628145510Sdarrenr				  }
629145510Sdarrenr				  free($1);
630145510Sdarrenr					}
631145510Sdarrenr	| YY_STR nextstring YY_STR
632145510Sdarrenr				{ if (!strcmp($1, "tcp") &&
633145510Sdarrenr				      !strcmp($3, "udp")) {
634145510Sdarrenr					DOREM(fr->fr_flx |= FI_TCPUDP; \
635145510Sdarrenr					      fr->fr_mflx |= FI_TCPUDP;)
636145510Sdarrenr				  } else
637145510Sdarrenr					YYERROR;
638145510Sdarrenr				  free($1);
639145510Sdarrenr				  free($3);
640145510Sdarrenr				}
641145510Sdarrenr	;
642145510Sdarrenr
643145510Sdarrenrnextstring:
644145510Sdarrenr	'/'			{ yysetdict(NULL); }
645145510Sdarrenr	;
646145510Sdarrenr
647145510Sdarrenrfromto:	from srcobject to dstobject	{ yyexpectaddr = 0; yycont = NULL; }
648145510Sdarrenr	| to dstobject			{ yyexpectaddr = 0; yycont = NULL; }
649145510Sdarrenr	| from srcobject		{ yyexpectaddr = 0; yycont = NULL; }
650145510Sdarrenr	;
651145510Sdarrenr
652145510Sdarrenrfrom:	IPFY_FROM			{ setipftype();
653145510Sdarrenr					  if (fr == NULL)
654145510Sdarrenr						fr = frc;
655145510Sdarrenr					  yyexpectaddr = 1;
656145510Sdarrenr					  if (yydebug)
657145510Sdarrenr						printf("set yyexpectaddr\n");
658145510Sdarrenr					  yycont = &yyexpectaddr;
659145510Sdarrenr					  yysetdict(addrwords);
660145510Sdarrenr					  resetaddr(); }
661145510Sdarrenr	;
662145510Sdarrenr
663145510Sdarrenrto:	IPFY_TO				{ if (fr == NULL)
664145510Sdarrenr						fr = frc;
665145510Sdarrenr					  yyexpectaddr = 1;
666145510Sdarrenr					  if (yydebug)
667145510Sdarrenr						printf("set yyexpectaddr\n");
668145510Sdarrenr					  yycont = &yyexpectaddr;
669145510Sdarrenr					  yysetdict(addrwords);
670145510Sdarrenr					  resetaddr(); }
671145510Sdarrenr	;
672145510Sdarrenr
673145510Sdarrenrwith:	| andwith withlist
674145510Sdarrenr	;
675145510Sdarrenr
676145510Sdarrenrandwith:
677145510Sdarrenr	IPFY_WITH			{ nowith = 0; setipftype(); }
678145510Sdarrenr	| IPFY_AND			{ nowith = 0; setipftype(); }
679145510Sdarrenr	;
680145510Sdarrenr
681145510Sdarrenrflags:	| startflags flagset
682145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
683145510Sdarrenr	| startflags flagset '/' flagset
684145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
685145510Sdarrenr	| startflags '/' flagset
686145510Sdarrenr		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
687145510Sdarrenr	| startflags YY_NUMBER
688145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
689145510Sdarrenr	| startflags '/' YY_NUMBER
690145510Sdarrenr		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
691145510Sdarrenr	| startflags YY_NUMBER '/' YY_NUMBER
692145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
693145510Sdarrenr	| startflags flagset '/' YY_NUMBER
694145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
695145510Sdarrenr	| startflags YY_NUMBER '/' flagset
696145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
697145510Sdarrenr	;
698145510Sdarrenr
699145510Sdarrenrstartflags:
700145510Sdarrenr	IPFY_FLAGS	{ if (frc->fr_type != FR_T_IPF)
701145510Sdarrenr				yyerror("flags with non-ipf type rule");
702145510Sdarrenr			  if (frc->fr_proto != IPPROTO_TCP)
703145510Sdarrenr				yyerror("flags with non-TCP rule");
704145510Sdarrenr			}
705145510Sdarrenr	;
706145510Sdarrenr
707145510Sdarrenrflagset:
708145510Sdarrenr	YY_STR				{ $$ = tcpflags($1); free($1); }
709145510Sdarrenr	| YY_HEX			{ $$ = $1; }
710145510Sdarrenr	;
711145510Sdarrenr
712145510Sdarrenrsrcobject:
713145510Sdarrenr	{ yyresetdict(); } fromport
714145510Sdarrenr	| srcaddr srcport
715145510Sdarrenr	| '!' srcaddr srcport
716145510Sdarrenr		{ DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
717145510Sdarrenr	;
718145510Sdarrenr
719145510Sdarrenrsrcaddr:
720145510Sdarrenr	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
721145510Sdarrenr			bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
722145510Sdarrenr			if (dynamic != -1) { \
723145510Sdarrenr				fr->fr_satype = ifpflag; \
724145510Sdarrenr				fr->fr_ipf->fri_sifpidx = dynamic; \
725145510Sdarrenr			} else if (pooled || hashed) \
726145510Sdarrenr				fr->fr_satype = FRI_LOOKUP;)
727145510Sdarrenr		}
728145510Sdarrenr	| lstart srcaddrlist lend
729145510Sdarrenr	;
730145510Sdarrenr
731145510Sdarrenrsrcaddrlist:
732145510Sdarrenr	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
733145510Sdarrenr			bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
734145510Sdarrenr			if (dynamic != -1) { \
735145510Sdarrenr				fr->fr_satype = ifpflag; \
736145510Sdarrenr				fr->fr_ipf->fri_sifpidx = dynamic; \
737145510Sdarrenr			} else if (pooled || hashed) \
738145510Sdarrenr				fr->fr_satype = FRI_LOOKUP;)
739145510Sdarrenr		}
740145510Sdarrenr	| srcaddrlist lmore addr
741145510Sdarrenr		{ DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \
742145510Sdarrenr			bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \
743145510Sdarrenr			if (dynamic != -1) { \
744145510Sdarrenr				fr->fr_satype = ifpflag; \
745145510Sdarrenr				fr->fr_ipf->fri_sifpidx = dynamic; \
746145510Sdarrenr			} else if (pooled || hashed) \
747145510Sdarrenr				fr->fr_satype = FRI_LOOKUP;)
748145510Sdarrenr		}
749145510Sdarrenr	;
750145510Sdarrenr
751145510Sdarrenrsrcport:
752145510Sdarrenr	| portcomp
753145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
754145510Sdarrenr	| portrange
755145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
756145510Sdarrenr			fr->fr_stop = $1.p2;) }
757145510Sdarrenr	| porteq lstart srcportlist lend
758145510Sdarrenr		{ yyresetdict(); }
759145510Sdarrenr	;
760145510Sdarrenr
761145510Sdarrenrfromport:
762145510Sdarrenr	portcomp
763145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
764145510Sdarrenr	| portrange
765145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
766145510Sdarrenr			fr->fr_stop = $1.p2;) }
767145510Sdarrenr	| porteq lstart srcportlist lend
768145510Sdarrenr		{ yyresetdict(); }
769145510Sdarrenr	;
770145510Sdarrenr
771145510Sdarrenrsrcportlist:
772145510Sdarrenr	portnum		{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) }
773172776Sdarrenr	| portnum ':' portnum
774172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \
775172776Sdarrenr				fr->fr_stop = $3;) }
776172776Sdarrenr	| portnum YY_RANGE_IN portnum
777172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \
778172776Sdarrenr				fr->fr_stop = $3;) }
779145510Sdarrenr	| srcportlist lmore portnum
780145510Sdarrenr			{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) }
781172776Sdarrenr	| srcportlist lmore portnum ':' portnum
782172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $3; \
783172776Sdarrenr				fr->fr_stop = $5;) }
784172776Sdarrenr	| srcportlist lmore portnum YY_RANGE_IN portnum
785172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $3; \
786172776Sdarrenr				fr->fr_stop = $5;) }
787145510Sdarrenr	;
788145510Sdarrenr
789145510Sdarrenrdstobject:
790145510Sdarrenr	{ yyresetdict(); } toport
791145510Sdarrenr	| dstaddr dstport
792145510Sdarrenr	| '!' dstaddr dstport
793145510Sdarrenr			{ DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
794145510Sdarrenr	;
795145510Sdarrenr
796145510Sdarrenrdstaddr:
797145510Sdarrenr	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
798145510Sdarrenr			bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
799145510Sdarrenr			if (dynamic != -1) { \
800145510Sdarrenr				fr->fr_datype = ifpflag; \
801145510Sdarrenr				fr->fr_ipf->fri_difpidx = dynamic; \
802145510Sdarrenr			  } else if (pooled || hashed) \
803145510Sdarrenr				fr->fr_datype = FRI_LOOKUP;)
804145510Sdarrenr		}
805145510Sdarrenr	| lstart dstaddrlist lend
806145510Sdarrenr	;
807145510Sdarrenr
808145510Sdarrenrdstaddrlist:
809145510Sdarrenr	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
810145510Sdarrenr			bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
811145510Sdarrenr			if (dynamic != -1) { \
812145510Sdarrenr				fr->fr_datype = ifpflag; \
813145510Sdarrenr				fr->fr_ipf->fri_difpidx = dynamic; \
814145510Sdarrenr			} else if (pooled || hashed) \
815145510Sdarrenr				fr->fr_datype = FRI_LOOKUP;)
816145510Sdarrenr		}
817145510Sdarrenr	| dstaddrlist lmore addr
818145510Sdarrenr		{ DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \
819145510Sdarrenr			bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \
820145510Sdarrenr			if (dynamic != -1) { \
821145510Sdarrenr				fr->fr_datype = ifpflag; \
822145510Sdarrenr				fr->fr_ipf->fri_difpidx = dynamic; \
823145510Sdarrenr			} else if (pooled || hashed) \
824145510Sdarrenr				fr->fr_datype = FRI_LOOKUP;)
825145510Sdarrenr		}
826145510Sdarrenr	;
827145510Sdarrenr
828145510Sdarrenr
829145510Sdarrenrdstport:
830145510Sdarrenr	| portcomp
831145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
832145510Sdarrenr	| portrange
833145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
834145510Sdarrenr			fr->fr_dtop = $1.p2;) }
835145510Sdarrenr	| porteq lstart dstportlist lend
836145510Sdarrenr		{ yyresetdict(); }
837145510Sdarrenr	;
838145510Sdarrenr
839145510Sdarrenrtoport:
840145510Sdarrenr	portcomp
841145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
842145510Sdarrenr	| portrange
843145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
844145510Sdarrenr			fr->fr_dtop = $1.p2;) }
845145510Sdarrenr	| porteq lstart dstportlist lend
846145510Sdarrenr		{ yyresetdict(); }
847145510Sdarrenr	;
848145510Sdarrenr
849145510Sdarrenrdstportlist:
850145510Sdarrenr	portnum		{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) }
851172776Sdarrenr	| portnum ':' portnum
852172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \
853172776Sdarrenr				fr->fr_dtop = $3;) }
854172776Sdarrenr	| portnum YY_RANGE_IN portnum
855172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \
856172776Sdarrenr				fr->fr_dtop = $3;) }
857145510Sdarrenr	| dstportlist lmore portnum
858145510Sdarrenr			{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) }
859172776Sdarrenr	| dstportlist lmore portnum ':' portnum
860172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $3; \
861172776Sdarrenr				fr->fr_dtop = $5;) }
862172776Sdarrenr	| dstportlist lmore portnum YY_RANGE_IN portnum
863172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $3; \
864172776Sdarrenr				fr->fr_dtop = $5;) }
865145510Sdarrenr	;
866145510Sdarrenr
867145510Sdarrenraddr:	pool '/' YY_NUMBER		{ pooled = 1;
868145510Sdarrenr					  $$.a.iplookuptype = IPLT_POOL;
869170268Sdarrenr					  $$.a.iplookupsubtype = 0;
870145510Sdarrenr					  $$.a.iplookupnum = $3; }
871170268Sdarrenr	| pool '/' YY_STR		{ pooled = 1;
872170268Sdarrenr					  $$.a.iplookuptype = IPLT_POOL;
873170268Sdarrenr					  $$.a.iplookupsubtype = 1;
874170268Sdarrenr					  strncpy($$.a.iplookupname, $3,
875170268Sdarrenr						  sizeof($$.a.iplookupname));
876170268Sdarrenr					}
877145510Sdarrenr	| pool '=' '(' poollist ')'	{ pooled = 1;
878145510Sdarrenr					  $$.a.iplookuptype = IPLT_POOL;
879170268Sdarrenr					  $$.a.iplookupsubtype = 0;
880145510Sdarrenr					  $$.a.iplookupnum = makepool($4); }
881145510Sdarrenr	| hash '/' YY_NUMBER		{ hashed = 1;
882145510Sdarrenr					  $$.a.iplookuptype = IPLT_HASH;
883170268Sdarrenr					  $$.a.iplookupsubtype = 0;
884145510Sdarrenr					  $$.a.iplookupnum = $3; }
885170268Sdarrenr	| hash '/' YY_STR		{ pooled = 1;
886170268Sdarrenr					  $$.a.iplookuptype = IPLT_HASH;
887170268Sdarrenr					  $$.a.iplookupsubtype = 1;
888170268Sdarrenr					  strncpy($$.a.iplookupname, $3,
889170268Sdarrenr						  sizeof($$.a.iplookupname));
890170268Sdarrenr					}
891145510Sdarrenr	| hash '=' '(' addrlist ')'	{ hashed = 1;
892145510Sdarrenr					  $$.a.iplookuptype = IPLT_HASH;
893170268Sdarrenr					  $$.a.iplookupsubtype = 0;
894145510Sdarrenr					  $$.a.iplookupnum = makehash($4); }
895145510Sdarrenr	| ipaddr			{ bcopy(&$1, &$$, sizeof($$));
896145510Sdarrenr					  yyexpectaddr = 0; }
897145510Sdarrenr	;
898145510Sdarrenr
899145510Sdarrenripaddr:	IPFY_ANY			{ bzero(&($$), sizeof($$));
900145510Sdarrenr					  yyresetdict();
901145510Sdarrenr					  yyexpectaddr = 0; }
902145510Sdarrenr	| hostname			{ $$.a.in4 = $1;
903145510Sdarrenr					  $$.m.in4_addr = 0xffffffff;
904145510Sdarrenr					  yyexpectaddr = 0; }
905145510Sdarrenr	| hostname			{ yyresetdict();
906145510Sdarrenr					  $$.a.in4_addr = $1.s_addr; }
907145510Sdarrenr		maskspace		{ yysetdict(maskwords); }
908145510Sdarrenr		ipv4mask		{ $$.m.in4_addr = $5.s_addr;
909145510Sdarrenr					  $$.a.in4_addr &= $5.s_addr;
910145510Sdarrenr					  yyresetdict();
911145510Sdarrenr					  yyexpectaddr = 0; }
912145510Sdarrenr	| YY_IPV6			{ bcopy(&$1, &$$.a, sizeof($$.a));
913145510Sdarrenr					  fill6bits(128, (u_32_t *)&$$.m);
914145510Sdarrenr					  yyresetdict();
915145510Sdarrenr					  yyexpectaddr = 0; }
916145510Sdarrenr	| YY_IPV6			{ yyresetdict();
917145510Sdarrenr					  bcopy(&$1, &$$.a, sizeof($$.a)); }
918145510Sdarrenr		maskspace		{ yysetdict(maskwords); }
919145510Sdarrenr		ipv6mask		{ bcopy(&$5, &$$.m, sizeof($$.m));
920145510Sdarrenr					  yyresetdict();
921145510Sdarrenr					  yyexpectaddr = 0; }
922145510Sdarrenr	;
923145510Sdarrenrmaskspace:
924145510Sdarrenr	'/'
925145510Sdarrenr	| IPFY_MASK
926145510Sdarrenr	;
927145510Sdarrenr
928145510Sdarrenripv4mask:
929145510Sdarrenr	ipv4				{ $$ = $1; }
930145510Sdarrenr	| YY_HEX			{ $$.s_addr = htonl($1); }
931145510Sdarrenr	| YY_NUMBER			{ ntomask(4, $1, (u_32_t *)&$$); }
932145510Sdarrenr	| IPFY_BROADCAST		{ if (ifpflag == FRI_DYNAMIC) {
933145510Sdarrenr						$$.s_addr = 0;
934145510Sdarrenr						ifpflag = FRI_BROADCAST;
935145510Sdarrenr					  } else
936145510Sdarrenr						YYERROR;
937145510Sdarrenr					}
938145510Sdarrenr	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
939145510Sdarrenr						$$.s_addr = 0;
940145510Sdarrenr						ifpflag = FRI_NETWORK;
941145510Sdarrenr					  } else
942145510Sdarrenr						YYERROR;
943145510Sdarrenr					}
944145510Sdarrenr	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
945145510Sdarrenr						$$.s_addr = 0;
946145510Sdarrenr						ifpflag = FRI_NETMASKED;
947145510Sdarrenr					  } else
948145510Sdarrenr						YYERROR;
949145510Sdarrenr					}
950145510Sdarrenr	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
951145510Sdarrenr						$$.s_addr = 0;
952145510Sdarrenr						ifpflag = FRI_PEERADDR;
953145510Sdarrenr					  } else
954145510Sdarrenr						YYERROR;
955145510Sdarrenr					}
956145510Sdarrenr	;
957145510Sdarrenr
958145510Sdarrenripv6mask:
959145510Sdarrenr	YY_NUMBER			{ ntomask(6, $1, $$.i6); }
960145510Sdarrenr	| IPFY_BROADCAST		{ if (ifpflag == FRI_DYNAMIC) {
961145510Sdarrenr						bzero(&$$, sizeof($$));
962145510Sdarrenr						ifpflag = FRI_BROADCAST;
963145510Sdarrenr					  } else
964145510Sdarrenr						YYERROR;
965145510Sdarrenr					}
966145510Sdarrenr	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
967145510Sdarrenr						bzero(&$$, sizeof($$));
968145510Sdarrenr						ifpflag = FRI_BROADCAST;
969145510Sdarrenr					  } else
970145510Sdarrenr						YYERROR;
971145510Sdarrenr					}
972145510Sdarrenr	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
973145510Sdarrenr						bzero(&$$, sizeof($$));
974145510Sdarrenr						ifpflag = FRI_BROADCAST;
975145510Sdarrenr					  } else
976145510Sdarrenr						YYERROR;
977145510Sdarrenr					}
978145510Sdarrenr	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
979145510Sdarrenr						bzero(&$$, sizeof($$));
980145510Sdarrenr						ifpflag = FRI_BROADCAST;
981145510Sdarrenr					  } else
982145510Sdarrenr						YYERROR;
983145510Sdarrenr					}
984145510Sdarrenr	;
985145510Sdarrenr
986145510Sdarrenrhostname:
987145510Sdarrenr	ipv4				{ $$ = $1; }
988145510Sdarrenr	| YY_NUMBER			{ $$.s_addr = $1; }
989145510Sdarrenr	| YY_HEX			{ $$.s_addr = $1; }
990145510Sdarrenr	| YY_STR			{ $$.s_addr = lookuphost($1);
991145510Sdarrenr					  free($1);
992145510Sdarrenr					}
993145510Sdarrenr	;
994145510Sdarrenr
995145510Sdarrenraddrlist:
996145510Sdarrenr	ipaddr		{ $$ = newalist(NULL);
997145510Sdarrenr			  bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
998145510Sdarrenr			  bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
999145510Sdarrenr	| addrlist ',' ipaddr
1000145510Sdarrenr			{ $$ = newalist($1);
1001145510Sdarrenr			  bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
1002145510Sdarrenr			  bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
1003145510Sdarrenr	;
1004145510Sdarrenr
1005145510Sdarrenrpool:	IPFY_POOL	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1006145510Sdarrenr	;
1007145510Sdarrenr
1008145510Sdarrenrhash:	IPFY_HASH	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1009145510Sdarrenr	;
1010145510Sdarrenr
1011145510Sdarrenrpoollist:
1012145510Sdarrenr	ipaddr		{ $$ = newalist(NULL);
1013145510Sdarrenr			  bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
1014145510Sdarrenr			  bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
1015145510Sdarrenr	| '!' ipaddr	{ $$ = newalist(NULL);
1016145510Sdarrenr			  $$->al_not = 1;
1017145510Sdarrenr			  bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a));
1018145510Sdarrenr			  bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); }
1019145510Sdarrenr	| poollist ',' ipaddr
1020145510Sdarrenr			{ $$ = newalist($1);
1021145510Sdarrenr			  bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
1022145510Sdarrenr			  bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
1023145510Sdarrenr	| poollist ',' '!' ipaddr
1024145510Sdarrenr			{ $$ = newalist($1);
1025145510Sdarrenr			  $$->al_not = 1;
1026145510Sdarrenr			  bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a));
1027145510Sdarrenr			  bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); }
1028145510Sdarrenr	;
1029145510Sdarrenr
1030145510Sdarrenrport:	IPFY_PORT			{ yyexpectaddr = 0;
1031145510Sdarrenr					  yycont = NULL;
1032145510Sdarrenr					}
1033145510Sdarrenr	;
1034145510Sdarrenr
1035145510Sdarrenrportc:	port compare			{ $$ = $2;
1036145510Sdarrenr					  yysetdict(NULL); }
1037145510Sdarrenr	| porteq			{ $$ = $1; }
1038145510Sdarrenr	;
1039145510Sdarrenr
1040145510Sdarrenrporteq:	port '='			{ $$ = FR_EQUAL;
1041145510Sdarrenr					  yysetdict(NULL); }
1042145510Sdarrenr	;
1043145510Sdarrenr
1044145510Sdarrenrportr:	IPFY_PORT			{ yyexpectaddr = 0;
1045145510Sdarrenr					  yycont = NULL;
1046145510Sdarrenr					  yysetdict(NULL); }
1047145510Sdarrenr	;
1048145510Sdarrenr
1049145510Sdarrenrportcomp:
1050145510Sdarrenr	portc portnum			{ $$.pc = $1;
1051145510Sdarrenr					  $$.p1 = $2;
1052145510Sdarrenr					  yyresetdict(); }
1053145510Sdarrenr	;
1054145510Sdarrenr
1055145510Sdarrenrportrange:
1056145510Sdarrenr	portr portnum range portnum	{ $$.p1 = $2;
1057145510Sdarrenr					  $$.pc = $3;
1058145510Sdarrenr					  $$.p2 = $4;
1059145510Sdarrenr					  yyresetdict(); }
1060145510Sdarrenr	;
1061145510Sdarrenr
1062145510Sdarrenricmp:	| itype icode
1063145510Sdarrenr	;
1064145510Sdarrenr
1065145510Sdarrenritype:	seticmptype icmptype
1066145510Sdarrenr	{ DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00););
1067145510Sdarrenr	  yyresetdict();
1068145510Sdarrenr	}
1069145510Sdarrenr	| seticmptype lstart typelist lend	{ yyresetdict(); }
1070145510Sdarrenr	;
1071145510Sdarrenr
1072145510Sdarrenrseticmptype:
1073145510Sdarrenr	IPFY_ICMPTYPE				{ setipftype();
1074145510Sdarrenr						  yysetdict(icmptypewords); }
1075145510Sdarrenr	;
1076145510Sdarrenr
1077145510Sdarrenricode:	| seticmpcode icmpcode
1078145510Sdarrenr	{ DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff););
1079145510Sdarrenr	  yyresetdict();
1080145510Sdarrenr	}
1081145510Sdarrenr	| seticmpcode lstart codelist lend	{ yyresetdict(); }
1082145510Sdarrenr	;
1083145510Sdarrenr
1084145510Sdarrenrseticmpcode:
1085145510Sdarrenr	IPFY_ICMPCODE				{ yysetdict(icmpcodewords); }
1086145510Sdarrenr	;
1087145510Sdarrenr
1088145510Sdarrenrtypelist:
1089145510Sdarrenr	icmptype
1090145510Sdarrenr	{ DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) }
1091145510Sdarrenr	| typelist lmore icmptype
1092145510Sdarrenr	{ DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) }
1093145510Sdarrenr	;
1094145510Sdarrenr
1095145510Sdarrenrcodelist:
1096145510Sdarrenr	icmpcode
1097145510Sdarrenr	{ DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) }
1098145510Sdarrenr	| codelist lmore icmpcode
1099161357Sguido	{ DOREM(fr->fr_icmp &= htons(0xff00); fr->fr_icmp |= htons($3); \
1100161357Sguido		fr->fr_icmpm |= htons(0xff);) }
1101145510Sdarrenr	;
1102145510Sdarrenr
1103145510Sdarrenrage:	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1104145510Sdarrenr						fr->fr_age[1] = $2;) }
1105145510Sdarrenr	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1106145510Sdarrenr					{ DOALL(fr->fr_age[0] = $2; \
1107145510Sdarrenr						fr->fr_age[1] = $4;) }
1108145510Sdarrenr	;
1109145510Sdarrenr
1110145510Sdarrenrkeep:	| IPFY_KEEP keepstate keep
1111145510Sdarrenr	| IPFY_KEEP keepfrag keep
1112145510Sdarrenr	;
1113145510Sdarrenr
1114145510Sdarrenrkeepstate:
1115145510Sdarrenr	IPFY_STATE stateoptlist		{ DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
1116145510Sdarrenr	;
1117145510Sdarrenr
1118145510Sdarrenrkeepfrag:
1119145510Sdarrenr	IPFY_FRAGS fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1120145510Sdarrenr	| IPFY_FRAG fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1121145510Sdarrenr	;
1122145510Sdarrenr
1123145510Sdarrenrfragoptlist:
1124145510Sdarrenr	| '(' fragopts ')'
1125145510Sdarrenr	;
1126145510Sdarrenr
1127145510Sdarrenrfragopts:
1128145510Sdarrenr	fragopt lanother fragopts
1129145510Sdarrenr	| fragopt
1130145510Sdarrenr	;
1131145510Sdarrenr
1132145510Sdarrenrfragopt:
1133145510Sdarrenr	IPFY_STRICT			{ DOALL(fr->fr_flags |= FR_FRSTRICT;) }
1134145510Sdarrenr	;
1135145510Sdarrenr
1136145510Sdarrenrstateoptlist:
1137145510Sdarrenr	| '(' stateopts ')'
1138145510Sdarrenr	;
1139145510Sdarrenr
1140145510Sdarrenrstateopts:
1141145510Sdarrenr	stateopt lanother stateopts
1142145510Sdarrenr	| stateopt
1143145510Sdarrenr	;
1144145510Sdarrenr
1145145510Sdarrenrstateopt:
1146145510Sdarrenr	IPFY_LIMIT YY_NUMBER	{ DOALL(fr->fr_statemax = $2;) }
1147145510Sdarrenr	| IPFY_STRICT		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1148145510Sdarrenr						YYERROR; \
1149145510Sdarrenr					  } else \
1150145510Sdarrenr						fr->fr_flags |= FR_STSTRICT;)
1151145510Sdarrenr				}
1152145510Sdarrenr	| IPFY_NEWISN		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1153145510Sdarrenr						YYERROR; \
1154145510Sdarrenr					  } else \
1155145510Sdarrenr						fr->fr_flags |= FR_NEWISN;)
1156145510Sdarrenr				}
1157145510Sdarrenr	| IPFY_NOICMPERR	{ DOALL(fr->fr_flags |= FR_NOICMPERR;) }
1158145510Sdarrenr
1159145510Sdarrenr	| IPFY_SYNC		{ DOALL(fr->fr_flags |= FR_STATESYNC;) }
1160161357Sguido	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1161161357Sguido						fr->fr_age[1] = $2;) }
1162161357Sguido	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1163161357Sguido					{ DOALL(fr->fr_age[0] = $2; \
1164161357Sguido						fr->fr_age[1] = $4;) }
1165145510Sdarrenr	;
1166145510Sdarrenr
1167145510Sdarrenrportnum:
1168145510Sdarrenr	servicename			{ if (getport(frc, $1, &($$)) == -1)
1169145510Sdarrenr						yyerror("service unknown");
1170145510Sdarrenr					  $$ = ntohs($$);
1171145510Sdarrenr					  free($1);
1172145510Sdarrenr					}
1173145510Sdarrenr	| YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
1174145510Sdarrenr						yyerror("invalid port number");
1175145510Sdarrenr					  else
1176145510Sdarrenr						$$ = $1;
1177145510Sdarrenr					}
1178145510Sdarrenr	;
1179145510Sdarrenr
1180145510Sdarrenrwithlist:
1181153881Sguido	withopt				{ nowith = 0; }
1182153881Sguido	| withlist withopt		{ nowith = 0; }
1183153881Sguido	| withlist ',' withopt		{ nowith = 0; }
1184145510Sdarrenr	;
1185145510Sdarrenr
1186145510Sdarrenrwithopt:
1187145510Sdarrenr	opttype		{ DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) }
1188153881Sguido	| notwith opttype		{ DOALL(fr->fr_mflx |= $2;) }
1189145510Sdarrenr	| ipopt ipopts			{ yyresetdict(); }
1190145510Sdarrenr	| notwith ipopt ipopts		{ yyresetdict(); }
1191145510Sdarrenr	| startv6hdrs ipv6hdrs		{ yyresetdict(); }
1192145510Sdarrenr	;
1193145510Sdarrenr
1194145510Sdarrenripopt:	IPFY_OPT			{ yysetdict(ipv4optwords); }
1195145510Sdarrenr	;
1196145510Sdarrenr
1197145510Sdarrenrstartv6hdrs:
1198145510Sdarrenr	IPF6_V6HDRS	{ if (use_inet6 == 0)
1199145510Sdarrenr				yyerror("only available with IPv6");
1200145510Sdarrenr			  yysetdict(ipv6optwords);
1201145510Sdarrenr			}
1202145510Sdarrenr	;
1203145510Sdarrenr
1204145510Sdarrenrnotwith:
1205145510Sdarrenr	IPFY_NOT			{ nowith = 1; }
1206145510Sdarrenr	| IPFY_NO			{ nowith = 1; }
1207145510Sdarrenr	;
1208145510Sdarrenr
1209145510Sdarrenropttype:
1210145510Sdarrenr	IPFY_IPOPTS			{ $$ = FI_OPTIONS; }
1211145510Sdarrenr	| IPFY_SHORT			{ $$ = FI_SHORT; }
1212145510Sdarrenr	| IPFY_NAT			{ $$ = FI_NATED; }
1213145510Sdarrenr	| IPFY_BAD			{ $$ = FI_BAD; }
1214145510Sdarrenr	| IPFY_BADNAT			{ $$ = FI_BADNAT; }
1215145510Sdarrenr	| IPFY_BADSRC			{ $$ = FI_BADSRC; }
1216145510Sdarrenr	| IPFY_LOWTTL			{ $$ = FI_LOWTTL; }
1217145510Sdarrenr	| IPFY_FRAG			{ $$ = FI_FRAG; }
1218145510Sdarrenr	| IPFY_FRAGBODY			{ $$ = FI_FRAGBODY; }
1219145510Sdarrenr	| IPFY_FRAGS			{ $$ = FI_FRAG; }
1220145510Sdarrenr	| IPFY_MBCAST			{ $$ = FI_MBCAST; }
1221145510Sdarrenr	| IPFY_MULTICAST		{ $$ = FI_MULTICAST; }
1222145510Sdarrenr	| IPFY_BROADCAST		{ $$ = FI_BROADCAST; }
1223145510Sdarrenr	| IPFY_STATE			{ $$ = FI_STATE; }
1224145510Sdarrenr	| IPFY_OOW			{ $$ = FI_OOW; }
1225145510Sdarrenr	;
1226145510Sdarrenr
1227145510Sdarrenripopts:	optlist		{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1228145510Sdarrenr				if (!nowith)
1229145510Sdarrenr					fr->fr_ip.fi_optmsk |= $1;)
1230145510Sdarrenr			}
1231145510Sdarrenr	;
1232145510Sdarrenr
1233145510Sdarrenroptlist:
1234145510Sdarrenr	opt				{ $$ |= $1; }
1235145510Sdarrenr	| optlist ',' opt		{ $$ |= $1 | $3; }
1236145510Sdarrenr	;
1237145510Sdarrenr
1238145510Sdarrenripv6hdrs:
1239145510Sdarrenr	ipv6hdrlist	{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1240145510Sdarrenr				if (!nowith)
1241145510Sdarrenr					fr->fr_ip.fi_optmsk |= $1;)
1242145510Sdarrenr			}
1243145510Sdarrenr	;
1244145510Sdarrenr
1245145510Sdarrenripv6hdrlist:
1246145510Sdarrenr	ipv6hdr				{ $$ |= $1; }
1247145510Sdarrenr	| ipv6hdrlist ',' ipv6hdr	{ $$ |= $1 | $3; }
1248145510Sdarrenr	;
1249145510Sdarrenr
1250145510Sdarrenrsecname:
1251145510Sdarrenr	seclevel			{ $$ |= $1; }
1252145510Sdarrenr	| secname ',' seclevel		{ $$ |= $1 | $3; }
1253145510Sdarrenr	;
1254145510Sdarrenr
1255145510Sdarrenrseclevel:
1256145510Sdarrenr	IPFY_SEC_UNC			{ $$ = secbit(IPSO_CLASS_UNCL); }
1257145510Sdarrenr	| IPFY_SEC_CONF			{ $$ = secbit(IPSO_CLASS_CONF); }
1258145510Sdarrenr	| IPFY_SEC_RSV1			{ $$ = secbit(IPSO_CLASS_RES1); }
1259145510Sdarrenr	| IPFY_SEC_RSV2			{ $$ = secbit(IPSO_CLASS_RES2); }
1260145510Sdarrenr	| IPFY_SEC_RSV3			{ $$ = secbit(IPSO_CLASS_RES3); }
1261145510Sdarrenr	| IPFY_SEC_RSV4			{ $$ = secbit(IPSO_CLASS_RES4); }
1262145510Sdarrenr	| IPFY_SEC_SEC			{ $$ = secbit(IPSO_CLASS_SECR); }
1263145510Sdarrenr	| IPFY_SEC_TS			{ $$ = secbit(IPSO_CLASS_TOPS); }
1264145510Sdarrenr	;
1265145510Sdarrenr
1266145510Sdarrenricmptype:
1267145510Sdarrenr	YY_NUMBER			{ $$ = $1; }
1268145510Sdarrenr	| IPFY_ICMPT_UNR		{ $$ = ICMP_UNREACH; }
1269145510Sdarrenr	| IPFY_ICMPT_ECHO		{ $$ = ICMP_ECHO; }
1270145510Sdarrenr	| IPFY_ICMPT_ECHOR		{ $$ = ICMP_ECHOREPLY; }
1271145510Sdarrenr	| IPFY_ICMPT_SQUENCH		{ $$ = ICMP_SOURCEQUENCH; }
1272145510Sdarrenr	| IPFY_ICMPT_REDIR		{ $$ = ICMP_REDIRECT; }
1273145510Sdarrenr	| IPFY_ICMPT_TIMEX		{ $$ = ICMP_TIMXCEED; }
1274145510Sdarrenr	| IPFY_ICMPT_PARAMP		{ $$ = ICMP_PARAMPROB; }
1275145510Sdarrenr	| IPFY_ICMPT_TIMEST		{ $$ = ICMP_TSTAMP; }
1276145510Sdarrenr	| IPFY_ICMPT_TIMESTREP		{ $$ = ICMP_TSTAMPREPLY; }
1277145510Sdarrenr	| IPFY_ICMPT_INFOREQ		{ $$ = ICMP_IREQ; }
1278145510Sdarrenr	| IPFY_ICMPT_INFOREP		{ $$ = ICMP_IREQREPLY; }
1279145510Sdarrenr	| IPFY_ICMPT_MASKREQ		{ $$ = ICMP_MASKREQ; }
1280145510Sdarrenr	| IPFY_ICMPT_MASKREP		{ $$ = ICMP_MASKREPLY; }
1281145510Sdarrenr	| IPFY_ICMPT_ROUTERAD		{ $$ = ICMP_ROUTERADVERT; }
1282145510Sdarrenr	| IPFY_ICMPT_ROUTERSOL		{ $$ = ICMP_ROUTERSOLICIT; }
1283145510Sdarrenr	;
1284145510Sdarrenr
1285145510Sdarrenricmpcode:
1286145510Sdarrenr	YY_NUMBER			{ $$ = $1; }
1287145510Sdarrenr	| IPFY_ICMPC_NETUNR		{ $$ = ICMP_UNREACH_NET; }
1288145510Sdarrenr	| IPFY_ICMPC_HSTUNR		{ $$ = ICMP_UNREACH_HOST; }
1289145510Sdarrenr	| IPFY_ICMPC_PROUNR		{ $$ = ICMP_UNREACH_PROTOCOL; }
1290145510Sdarrenr	| IPFY_ICMPC_PORUNR		{ $$ = ICMP_UNREACH_PORT; }
1291145510Sdarrenr	| IPFY_ICMPC_NEEDF		{ $$ = ICMP_UNREACH_NEEDFRAG; }
1292145510Sdarrenr	| IPFY_ICMPC_SRCFAIL		{ $$ = ICMP_UNREACH_SRCFAIL; }
1293145510Sdarrenr	| IPFY_ICMPC_NETUNK		{ $$ = ICMP_UNREACH_NET_UNKNOWN; }
1294145510Sdarrenr	| IPFY_ICMPC_HSTUNK		{ $$ = ICMP_UNREACH_HOST_UNKNOWN; }
1295145510Sdarrenr	| IPFY_ICMPC_ISOLATE		{ $$ = ICMP_UNREACH_ISOLATED; }
1296145510Sdarrenr	| IPFY_ICMPC_NETPRO		{ $$ = ICMP_UNREACH_NET_PROHIB; }
1297145510Sdarrenr	| IPFY_ICMPC_HSTPRO		{ $$ = ICMP_UNREACH_HOST_PROHIB; }
1298145510Sdarrenr	| IPFY_ICMPC_NETTOS		{ $$ = ICMP_UNREACH_TOSNET; }
1299145510Sdarrenr	| IPFY_ICMPC_HSTTOS		{ $$ = ICMP_UNREACH_TOSHOST; }
1300145510Sdarrenr	| IPFY_ICMPC_FLTPRO		{ $$ = ICMP_UNREACH_ADMIN_PROHIBIT; }
1301145510Sdarrenr	| IPFY_ICMPC_HSTPRE		{ $$ = 14; }
1302145510Sdarrenr	| IPFY_ICMPC_CUTPRE		{ $$ = 15; }
1303145510Sdarrenr	;
1304145510Sdarrenr
1305145510Sdarrenropt:
1306145510Sdarrenr	IPFY_IPOPT_NOP			{ $$ = getoptbyvalue(IPOPT_NOP); }
1307145510Sdarrenr	| IPFY_IPOPT_RR			{ $$ = getoptbyvalue(IPOPT_RR); }
1308145510Sdarrenr	| IPFY_IPOPT_ZSU		{ $$ = getoptbyvalue(IPOPT_ZSU); }
1309145510Sdarrenr	| IPFY_IPOPT_MTUP		{ $$ = getoptbyvalue(IPOPT_MTUP); }
1310145510Sdarrenr	| IPFY_IPOPT_MTUR		{ $$ = getoptbyvalue(IPOPT_MTUR); }
1311145510Sdarrenr	| IPFY_IPOPT_ENCODE		{ $$ = getoptbyvalue(IPOPT_ENCODE); }
1312145510Sdarrenr	| IPFY_IPOPT_TS			{ $$ = getoptbyvalue(IPOPT_TS); }
1313145510Sdarrenr	| IPFY_IPOPT_TR			{ $$ = getoptbyvalue(IPOPT_TR); }
1314145510Sdarrenr	| IPFY_IPOPT_SEC		{ $$ = getoptbyvalue(IPOPT_SECURITY); }
1315145510Sdarrenr	| IPFY_IPOPT_LSRR		{ $$ = getoptbyvalue(IPOPT_LSRR); }
1316145510Sdarrenr	| IPFY_IPOPT_ESEC		{ $$ = getoptbyvalue(IPOPT_E_SEC); }
1317145510Sdarrenr	| IPFY_IPOPT_CIPSO		{ $$ = getoptbyvalue(IPOPT_CIPSO); }
1318145510Sdarrenr	| IPFY_IPOPT_SATID		{ $$ = getoptbyvalue(IPOPT_SATID); }
1319145510Sdarrenr	| IPFY_IPOPT_SSRR		{ $$ = getoptbyvalue(IPOPT_SSRR); }
1320145510Sdarrenr	| IPFY_IPOPT_ADDEXT		{ $$ = getoptbyvalue(IPOPT_ADDEXT); }
1321145510Sdarrenr	| IPFY_IPOPT_VISA		{ $$ = getoptbyvalue(IPOPT_VISA); }
1322145510Sdarrenr	| IPFY_IPOPT_IMITD		{ $$ = getoptbyvalue(IPOPT_IMITD); }
1323145510Sdarrenr	| IPFY_IPOPT_EIP		{ $$ = getoptbyvalue(IPOPT_EIP); }
1324145510Sdarrenr	| IPFY_IPOPT_FINN		{ $$ = getoptbyvalue(IPOPT_FINN); }
1325145510Sdarrenr	| IPFY_IPOPT_DPS		{ $$ = getoptbyvalue(IPOPT_DPS); }
1326145510Sdarrenr	| IPFY_IPOPT_SDB		{ $$ = getoptbyvalue(IPOPT_SDB); }
1327145510Sdarrenr	| IPFY_IPOPT_NSAPA		{ $$ = getoptbyvalue(IPOPT_NSAPA); }
1328145510Sdarrenr	| IPFY_IPOPT_RTRALRT		{ $$ = getoptbyvalue(IPOPT_RTRALRT); }
1329145510Sdarrenr	| IPFY_IPOPT_UMP		{ $$ = getoptbyvalue(IPOPT_UMP); }
1330145510Sdarrenr	| setsecclass secname
1331145510Sdarrenr			{ DOALL(fr->fr_mip.fi_secmsk |= $2;
1332145510Sdarrenr				if (!nowith)
1333145510Sdarrenr					fr->fr_ip.fi_secmsk |= $2;)
1334145510Sdarrenr			  $$ = 0;
1335145510Sdarrenr			  yyresetdict();
1336145510Sdarrenr			}
1337145510Sdarrenr	;
1338145510Sdarrenr
1339145510Sdarrenrsetsecclass:
1340145510Sdarrenr	IPFY_SECCLASS	{ yysetdict(ipv4secwords); }
1341145510Sdarrenr	;
1342145510Sdarrenr
1343145510Sdarrenripv6hdr:
1344145510Sdarrenr	IPFY_AH			{ $$ = getv6optbyvalue(IPPROTO_AH); }
1345145510Sdarrenr	| IPFY_IPV6OPT_DSTOPTS	{ $$ = getv6optbyvalue(IPPROTO_DSTOPTS); }
1346153881Sguido	| IPFY_IPV6OPT_ESP	{ $$ = getv6optbyvalue(IPPROTO_ESP); }
1347145510Sdarrenr	| IPFY_IPV6OPT_HOPOPTS	{ $$ = getv6optbyvalue(IPPROTO_HOPOPTS); }
1348145510Sdarrenr	| IPFY_IPV6OPT_IPV6	{ $$ = getv6optbyvalue(IPPROTO_IPV6); }
1349145510Sdarrenr	| IPFY_IPV6OPT_NONE	{ $$ = getv6optbyvalue(IPPROTO_NONE); }
1350145510Sdarrenr	| IPFY_IPV6OPT_ROUTING	{ $$ = getv6optbyvalue(IPPROTO_ROUTING); }
1351153881Sguido	| IPFY_IPV6OPT_FRAG	{ $$ = getv6optbyvalue(IPPROTO_FRAGMENT); }
1352153881Sguido	| IPFY_IPV6OPT_MOBILITY	{ $$ = getv6optbyvalue(IPPROTO_MOBILITY); }
1353145510Sdarrenr	;
1354145510Sdarrenr
1355145510Sdarrenrlevel:	IPFY_LEVEL			{ setsyslog(); }
1356145510Sdarrenr	;
1357145510Sdarrenr
1358145510Sdarrenrloglevel:
1359145510Sdarrenr	priority			{ fr->fr_loglevel = LOG_LOCAL0|$1; }
1360145510Sdarrenr	| facility '.' priority		{ fr->fr_loglevel = $1 | $3; }
1361145510Sdarrenr	;
1362145510Sdarrenr
1363145510Sdarrenrfacility:
1364145510Sdarrenr	IPFY_FAC_KERN			{ $$ = LOG_KERN; }
1365145510Sdarrenr	| IPFY_FAC_USER			{ $$ = LOG_USER; }
1366145510Sdarrenr	| IPFY_FAC_MAIL			{ $$ = LOG_MAIL; }
1367145510Sdarrenr	| IPFY_FAC_DAEMON		{ $$ = LOG_DAEMON; }
1368145510Sdarrenr	| IPFY_FAC_AUTH			{ $$ = LOG_AUTH; }
1369145510Sdarrenr	| IPFY_FAC_SYSLOG		{ $$ = LOG_SYSLOG; }
1370145510Sdarrenr	| IPFY_FAC_LPR			{ $$ = LOG_LPR; }
1371145510Sdarrenr	| IPFY_FAC_NEWS			{ $$ = LOG_NEWS; }
1372145510Sdarrenr	| IPFY_FAC_UUCP			{ $$ = LOG_UUCP; }
1373145510Sdarrenr	| IPFY_FAC_CRON			{ $$ = LOG_CRON; }
1374145510Sdarrenr	| IPFY_FAC_FTP			{ $$ = LOG_FTP; }
1375145510Sdarrenr	| IPFY_FAC_AUTHPRIV		{ $$ = LOG_AUTHPRIV; }
1376145510Sdarrenr	| IPFY_FAC_AUDIT		{ $$ = LOG_AUDIT; }
1377145510Sdarrenr	| IPFY_FAC_LFMT			{ $$ = LOG_LFMT; }
1378145510Sdarrenr	| IPFY_FAC_LOCAL0		{ $$ = LOG_LOCAL0; }
1379145510Sdarrenr	| IPFY_FAC_LOCAL1		{ $$ = LOG_LOCAL1; }
1380145510Sdarrenr	| IPFY_FAC_LOCAL2		{ $$ = LOG_LOCAL2; }
1381145510Sdarrenr	| IPFY_FAC_LOCAL3		{ $$ = LOG_LOCAL3; }
1382145510Sdarrenr	| IPFY_FAC_LOCAL4		{ $$ = LOG_LOCAL4; }
1383145510Sdarrenr	| IPFY_FAC_LOCAL5		{ $$ = LOG_LOCAL5; }
1384145510Sdarrenr	| IPFY_FAC_LOCAL6		{ $$ = LOG_LOCAL6; }
1385145510Sdarrenr	| IPFY_FAC_LOCAL7		{ $$ = LOG_LOCAL7; }
1386145510Sdarrenr	| IPFY_FAC_SECURITY		{ $$ = LOG_SECURITY; }
1387145510Sdarrenr	;
1388145510Sdarrenr
1389145510Sdarrenrpriority:
1390145510Sdarrenr	IPFY_PRI_EMERG			{ $$ = LOG_EMERG; }
1391145510Sdarrenr	| IPFY_PRI_ALERT		{ $$ = LOG_ALERT; }
1392145510Sdarrenr	| IPFY_PRI_CRIT			{ $$ = LOG_CRIT; }
1393145510Sdarrenr	| IPFY_PRI_ERR			{ $$ = LOG_ERR; }
1394145510Sdarrenr	| IPFY_PRI_WARN			{ $$ = LOG_WARNING; }
1395145510Sdarrenr	| IPFY_PRI_NOTICE		{ $$ = LOG_NOTICE; }
1396145510Sdarrenr	| IPFY_PRI_INFO			{ $$ = LOG_INFO; }
1397145510Sdarrenr	| IPFY_PRI_DEBUG		{ $$ = LOG_DEBUG; }
1398145510Sdarrenr	;
1399145510Sdarrenr
1400145510Sdarrenrcompare:
1401145510Sdarrenr	YY_CMP_EQ			{ $$ = FR_EQUAL; }
1402145510Sdarrenr	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
1403145510Sdarrenr	| YY_CMP_LT			{ $$ = FR_LESST; }
1404145510Sdarrenr	| YY_CMP_LE			{ $$ = FR_LESSTE; }
1405145510Sdarrenr	| YY_CMP_GT			{ $$ = FR_GREATERT; }
1406145510Sdarrenr	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
1407145510Sdarrenr	;
1408145510Sdarrenr
1409145510Sdarrenrrange:	YY_RANGE_IN			{ $$ = FR_INRANGE; }
1410145510Sdarrenr	| YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
1411145510Sdarrenr	| ':'				{ $$ = FR_INCRANGE; }
1412145510Sdarrenr	;
1413145510Sdarrenr
1414145510Sdarrenrservicename:
1415145510Sdarrenr	YY_STR				{ $$ = $1; }
1416145510Sdarrenr	;
1417145510Sdarrenr
1418170268Sdarrenrinterfacename:	name				{ $$ = $1; }
1419170268Sdarrenr	| name ':' YY_NUMBER
1420145510Sdarrenr		{ $$ = $1;
1421145510Sdarrenr		  fprintf(stderr, "%d: Logical interface %s:%d unsupported, "
1422145510Sdarrenr			  "use the physical interface %s instead.\n",
1423145510Sdarrenr			  yylineNum, $1, $3, $1);
1424145510Sdarrenr		}
1425145510Sdarrenr	;
1426145510Sdarrenr
1427145510Sdarrenrname:	YY_STR				{ $$ = $1; }
1428170268Sdarrenr	| '-'				{ $$ = strdup("-"); }
1429145510Sdarrenr	;
1430145510Sdarrenr
1431145510Sdarrenripv4_16:
1432145510Sdarrenr	YY_NUMBER '.' YY_NUMBER
1433145510Sdarrenr		{ if ($1 > 255 || $3 > 255) {
1434145510Sdarrenr			yyerror("Invalid octet string for IP address");
1435145510Sdarrenr			return 0;
1436145510Sdarrenr		  }
1437145510Sdarrenr		  $$.s_addr = ($1 << 24) | ($3 << 16);
1438145510Sdarrenr		  $$.s_addr = htonl($$.s_addr);
1439145510Sdarrenr		}
1440145510Sdarrenr	;
1441145510Sdarrenr
1442145510Sdarrenripv4_24:
1443145510Sdarrenr	ipv4_16 '.' YY_NUMBER
1444145510Sdarrenr		{ if ($3 > 255) {
1445145510Sdarrenr			yyerror("Invalid octet string for IP address");
1446145510Sdarrenr			return 0;
1447145510Sdarrenr		  }
1448145510Sdarrenr		  $$.s_addr |= htonl($3 << 8);
1449145510Sdarrenr		}
1450145510Sdarrenr	;
1451145510Sdarrenr
1452145510Sdarrenripv4:	ipv4_24 '.' YY_NUMBER
1453145510Sdarrenr		{ if ($3 > 255) {
1454145510Sdarrenr			yyerror("Invalid octet string for IP address");
1455145510Sdarrenr			return 0;
1456145510Sdarrenr		  }
1457145510Sdarrenr		  $$.s_addr |= htonl($3);
1458145510Sdarrenr		}
1459145510Sdarrenr	| ipv4_24
1460145510Sdarrenr	| ipv4_16
1461145510Sdarrenr	;
1462145510Sdarrenr
1463145510Sdarrenr%%
1464145510Sdarrenr
1465145510Sdarrenr
1466145510Sdarrenrstatic	struct	wordtab ipfwords[95] = {
1467145510Sdarrenr	{ "age",			IPFY_AGE },
1468145510Sdarrenr	{ "ah",				IPFY_AH },
1469145510Sdarrenr	{ "all",			IPFY_ALL },
1470145510Sdarrenr	{ "and",			IPFY_AND },
1471145510Sdarrenr	{ "auth",			IPFY_AUTH },
1472145510Sdarrenr	{ "bad",			IPFY_BAD },
1473145510Sdarrenr	{ "bad-nat",			IPFY_BADNAT },
1474145510Sdarrenr	{ "bad-src",			IPFY_BADSRC },
1475145510Sdarrenr	{ "bcast",			IPFY_BROADCAST },
1476145510Sdarrenr	{ "block",			IPFY_BLOCK },
1477145510Sdarrenr	{ "body",			IPFY_BODY },
1478145510Sdarrenr	{ "bpf-v4",			IPFY_BPFV4 },
1479145510Sdarrenr#ifdef USE_INET6
1480145510Sdarrenr	{ "bpf-v6",			IPFY_BPFV6 },
1481145510Sdarrenr#endif
1482145510Sdarrenr	{ "call",			IPFY_CALL },
1483145510Sdarrenr	{ "code",			IPFY_ICMPCODE },
1484145510Sdarrenr	{ "count",			IPFY_COUNT },
1485145510Sdarrenr	{ "dup-to",			IPFY_DUPTO },
1486145510Sdarrenr	{ "eq",				YY_CMP_EQ },
1487145510Sdarrenr	{ "esp",			IPFY_ESP },
1488145510Sdarrenr	{ "fastroute",			IPFY_FROUTE },
1489145510Sdarrenr	{ "first",			IPFY_FIRST },
1490145510Sdarrenr	{ "flags",			IPFY_FLAGS },
1491145510Sdarrenr	{ "frag",			IPFY_FRAG },
1492145510Sdarrenr	{ "frag-body",			IPFY_FRAGBODY },
1493145510Sdarrenr	{ "frags",			IPFY_FRAGS },
1494145510Sdarrenr	{ "from",			IPFY_FROM },
1495145510Sdarrenr	{ "ge",				YY_CMP_GE },
1496145510Sdarrenr	{ "group",			IPFY_GROUP },
1497145510Sdarrenr	{ "gt",				YY_CMP_GT },
1498145510Sdarrenr	{ "head",			IPFY_HEAD },
1499145510Sdarrenr	{ "icmp",			IPFY_ICMP },
1500145510Sdarrenr	{ "icmp-type",			IPFY_ICMPTYPE },
1501145510Sdarrenr	{ "in",				IPFY_IN },
1502145510Sdarrenr	{ "in-via",			IPFY_INVIA },
1503145510Sdarrenr	{ "ipopt",			IPFY_IPOPTS },
1504145510Sdarrenr	{ "ipopts",			IPFY_IPOPTS },
1505145510Sdarrenr	{ "keep",			IPFY_KEEP },
1506145510Sdarrenr	{ "le",				YY_CMP_LE },
1507145510Sdarrenr	{ "level",			IPFY_LEVEL },
1508145510Sdarrenr	{ "limit",			IPFY_LIMIT },
1509145510Sdarrenr	{ "log",			IPFY_LOG },
1510145510Sdarrenr	{ "lowttl",			IPFY_LOWTTL },
1511145510Sdarrenr	{ "lt",				YY_CMP_LT },
1512145510Sdarrenr	{ "mask",			IPFY_MASK },
1513145510Sdarrenr	{ "match-tag",			IPFY_MATCHTAG },
1514145510Sdarrenr	{ "mbcast",			IPFY_MBCAST },
1515153881Sguido	{ "mcast",			IPFY_MULTICAST },
1516145510Sdarrenr	{ "multicast",			IPFY_MULTICAST },
1517145510Sdarrenr	{ "nat",			IPFY_NAT },
1518145510Sdarrenr	{ "ne",				YY_CMP_NE },
1519145510Sdarrenr	{ "net",			IPFY_NETWORK },
1520145510Sdarrenr	{ "newisn",			IPFY_NEWISN },
1521145510Sdarrenr	{ "no",				IPFY_NO },
1522145510Sdarrenr	{ "no-icmp-err",		IPFY_NOICMPERR },
1523161357Sguido	{ "nomatch",			IPFY_NOMATCH },
1524145510Sdarrenr	{ "now",			IPFY_NOW },
1525145510Sdarrenr	{ "not",			IPFY_NOT },
1526145510Sdarrenr	{ "oow",			IPFY_OOW },
1527145510Sdarrenr	{ "on",				IPFY_ON },
1528145510Sdarrenr	{ "opt",			IPFY_OPT },
1529145510Sdarrenr	{ "or-block",			IPFY_ORBLOCK },
1530145510Sdarrenr	{ "out",			IPFY_OUT },
1531145510Sdarrenr	{ "out-via",			IPFY_OUTVIA },
1532145510Sdarrenr	{ "pass",			IPFY_PASS },
1533145510Sdarrenr	{ "port",			IPFY_PORT },
1534145510Sdarrenr	{ "pps",			IPFY_PPS },
1535145510Sdarrenr	{ "preauth",			IPFY_PREAUTH },
1536145510Sdarrenr	{ "proto",			IPFY_PROTO },
1537145510Sdarrenr	{ "quick",			IPFY_QUICK },
1538145510Sdarrenr	{ "reply-to",			IPFY_REPLY_TO },
1539145510Sdarrenr	{ "return-icmp",		IPFY_RETICMP },
1540145510Sdarrenr	{ "return-icmp-as-dest",	IPFY_RETICMPASDST },
1541145510Sdarrenr	{ "return-rst",			IPFY_RETRST },
1542145510Sdarrenr	{ "route-to",			IPFY_ROUTETO },
1543145510Sdarrenr	{ "sec-class",			IPFY_SECCLASS },
1544145510Sdarrenr	{ "set-tag",			IPFY_SETTAG },
1545145510Sdarrenr	{ "skip",			IPFY_SKIP },
1546145510Sdarrenr	{ "short",			IPFY_SHORT },
1547145510Sdarrenr	{ "state",			IPFY_STATE },
1548145510Sdarrenr	{ "state-age",			IPFY_AGE },
1549145510Sdarrenr	{ "strict",			IPFY_STRICT },
1550145510Sdarrenr	{ "sync",			IPFY_SYNC },
1551145510Sdarrenr	{ "tcp",			IPFY_TCP },
1552145510Sdarrenr	{ "tcp-udp",			IPFY_TCPUDP },
1553145510Sdarrenr	{ "tos",			IPFY_TOS },
1554145510Sdarrenr	{ "to",				IPFY_TO },
1555145510Sdarrenr	{ "ttl",			IPFY_TTL },
1556145510Sdarrenr	{ "udp",			IPFY_UDP },
1557145510Sdarrenr	{ "v6hdrs",			IPF6_V6HDRS },
1558145510Sdarrenr	{ "with",			IPFY_WITH },
1559145510Sdarrenr	{ NULL,				0 }
1560145510Sdarrenr};
1561145510Sdarrenr
1562145510Sdarrenrstatic	struct	wordtab	addrwords[4] = {
1563145510Sdarrenr	{ "any",			IPFY_ANY },
1564145510Sdarrenr	{ "hash",			IPFY_HASH },
1565145510Sdarrenr	{ "pool",			IPFY_POOL },
1566145510Sdarrenr	{ NULL,				0 }
1567145510Sdarrenr};
1568145510Sdarrenr
1569145510Sdarrenrstatic	struct	wordtab	maskwords[5] = {
1570145510Sdarrenr	{ "broadcast",			IPFY_BROADCAST },
1571145510Sdarrenr	{ "netmasked",			IPFY_NETMASKED },
1572145510Sdarrenr	{ "network",			IPFY_NETWORK },
1573145510Sdarrenr	{ "peer",			IPFY_PEER },
1574145510Sdarrenr	{ NULL,				0 }
1575145510Sdarrenr};
1576145510Sdarrenr
1577145510Sdarrenrstatic	struct	wordtab icmptypewords[16] = {
1578145510Sdarrenr	{ "echo",			IPFY_ICMPT_ECHO },
1579145510Sdarrenr	{ "echorep",			IPFY_ICMPT_ECHOR },
1580145510Sdarrenr	{ "inforeq",			IPFY_ICMPT_INFOREQ },
1581145510Sdarrenr	{ "inforep",			IPFY_ICMPT_INFOREP },
1582145510Sdarrenr	{ "maskrep",			IPFY_ICMPT_MASKREP },
1583145510Sdarrenr	{ "maskreq",			IPFY_ICMPT_MASKREQ },
1584145510Sdarrenr	{ "paramprob",			IPFY_ICMPT_PARAMP },
1585145510Sdarrenr	{ "redir",			IPFY_ICMPT_REDIR },
1586145510Sdarrenr	{ "unreach",			IPFY_ICMPT_UNR },
1587145510Sdarrenr	{ "routerad",			IPFY_ICMPT_ROUTERAD },
1588145510Sdarrenr	{ "routersol",			IPFY_ICMPT_ROUTERSOL },
1589145510Sdarrenr	{ "squench",			IPFY_ICMPT_SQUENCH },
1590145510Sdarrenr	{ "timest",			IPFY_ICMPT_TIMEST },
1591145510Sdarrenr	{ "timestrep",			IPFY_ICMPT_TIMESTREP },
1592145510Sdarrenr	{ "timex",			IPFY_ICMPT_TIMEX },
1593145510Sdarrenr	{ NULL,				0 },
1594145510Sdarrenr};
1595145510Sdarrenr
1596145510Sdarrenrstatic	struct	wordtab icmpcodewords[17] = {
1597145510Sdarrenr	{ "cutoff-preced",		IPFY_ICMPC_CUTPRE },
1598145510Sdarrenr	{ "filter-prohib",		IPFY_ICMPC_FLTPRO },
1599145510Sdarrenr	{ "isolate",			IPFY_ICMPC_ISOLATE },
1600145510Sdarrenr	{ "needfrag",			IPFY_ICMPC_NEEDF },
1601145510Sdarrenr	{ "net-prohib",			IPFY_ICMPC_NETPRO },
1602145510Sdarrenr	{ "net-tos",			IPFY_ICMPC_NETTOS },
1603145510Sdarrenr	{ "host-preced",		IPFY_ICMPC_HSTPRE },
1604145510Sdarrenr	{ "host-prohib",		IPFY_ICMPC_HSTPRO },
1605145510Sdarrenr	{ "host-tos",			IPFY_ICMPC_HSTTOS },
1606145510Sdarrenr	{ "host-unk",			IPFY_ICMPC_HSTUNK },
1607145510Sdarrenr	{ "host-unr",			IPFY_ICMPC_HSTUNR },
1608145510Sdarrenr	{ "net-unk",			IPFY_ICMPC_NETUNK },
1609145510Sdarrenr	{ "net-unr",			IPFY_ICMPC_NETUNR },
1610145510Sdarrenr	{ "port-unr",			IPFY_ICMPC_PORUNR },
1611145510Sdarrenr	{ "proto-unr",			IPFY_ICMPC_PROUNR },
1612145510Sdarrenr	{ "srcfail",			IPFY_ICMPC_SRCFAIL },
1613145510Sdarrenr	{ NULL,				0 },
1614145510Sdarrenr};
1615145510Sdarrenr
1616145510Sdarrenrstatic	struct	wordtab ipv4optwords[25] = {
1617145510Sdarrenr	{ "addext",			IPFY_IPOPT_ADDEXT },
1618145510Sdarrenr	{ "cipso",			IPFY_IPOPT_CIPSO },
1619145510Sdarrenr	{ "dps",			IPFY_IPOPT_DPS },
1620145510Sdarrenr	{ "e-sec",			IPFY_IPOPT_ESEC },
1621145510Sdarrenr	{ "eip",			IPFY_IPOPT_EIP },
1622145510Sdarrenr	{ "encode",			IPFY_IPOPT_ENCODE },
1623145510Sdarrenr	{ "finn",			IPFY_IPOPT_FINN },
1624145510Sdarrenr	{ "imitd",			IPFY_IPOPT_IMITD },
1625145510Sdarrenr	{ "lsrr",			IPFY_IPOPT_LSRR },
1626145510Sdarrenr	{ "mtup",			IPFY_IPOPT_MTUP },
1627145510Sdarrenr	{ "mtur",			IPFY_IPOPT_MTUR },
1628145510Sdarrenr	{ "nop",			IPFY_IPOPT_NOP },
1629145510Sdarrenr	{ "nsapa",			IPFY_IPOPT_NSAPA },
1630145510Sdarrenr	{ "rr",				IPFY_IPOPT_RR },
1631145510Sdarrenr	{ "rtralrt",			IPFY_IPOPT_RTRALRT },
1632145510Sdarrenr	{ "satid",			IPFY_IPOPT_SATID },
1633145510Sdarrenr	{ "sdb",			IPFY_IPOPT_SDB },
1634145510Sdarrenr	{ "sec",			IPFY_IPOPT_SEC },
1635145510Sdarrenr	{ "ssrr",			IPFY_IPOPT_SSRR },
1636145510Sdarrenr	{ "tr",				IPFY_IPOPT_TR },
1637145510Sdarrenr	{ "ts",				IPFY_IPOPT_TS },
1638145510Sdarrenr	{ "ump",			IPFY_IPOPT_UMP },
1639145510Sdarrenr	{ "visa",			IPFY_IPOPT_VISA },
1640145510Sdarrenr	{ "zsu",			IPFY_IPOPT_ZSU },
1641145510Sdarrenr	{ NULL,				0 },
1642145510Sdarrenr};
1643145510Sdarrenr
1644145510Sdarrenrstatic	struct	wordtab ipv4secwords[9] = {
1645145510Sdarrenr	{ "confid",			IPFY_SEC_CONF },
1646145510Sdarrenr	{ "reserv-1",			IPFY_SEC_RSV1 },
1647145510Sdarrenr	{ "reserv-2",			IPFY_SEC_RSV2 },
1648145510Sdarrenr	{ "reserv-3",			IPFY_SEC_RSV3 },
1649145510Sdarrenr	{ "reserv-4",			IPFY_SEC_RSV4 },
1650145510Sdarrenr	{ "secret",			IPFY_SEC_SEC },
1651145510Sdarrenr	{ "topsecret",			IPFY_SEC_TS },
1652145510Sdarrenr	{ "unclass",			IPFY_SEC_UNC },
1653145510Sdarrenr	{ NULL,				0 },
1654145510Sdarrenr};
1655145510Sdarrenr
1656153881Sguidostatic	struct	wordtab ipv6optwords[9] = {
1657145510Sdarrenr	{ "dstopts",			IPFY_IPV6OPT_DSTOPTS },
1658153881Sguido	{ "esp",			IPFY_IPV6OPT_ESP },
1659153881Sguido	{ "frag",			IPFY_IPV6OPT_FRAG },
1660145510Sdarrenr	{ "hopopts",			IPFY_IPV6OPT_HOPOPTS },
1661145510Sdarrenr	{ "ipv6",			IPFY_IPV6OPT_IPV6 },
1662153881Sguido	{ "mobility",			IPFY_IPV6OPT_MOBILITY },
1663145510Sdarrenr	{ "none",			IPFY_IPV6OPT_NONE },
1664145510Sdarrenr	{ "routing",			IPFY_IPV6OPT_ROUTING },
1665145510Sdarrenr	{ NULL,				0 },
1666145510Sdarrenr};
1667145510Sdarrenr
1668145510Sdarrenrstatic	struct	wordtab logwords[33] = {
1669145510Sdarrenr	{ "kern",			IPFY_FAC_KERN },
1670145510Sdarrenr	{ "user",			IPFY_FAC_USER },
1671145510Sdarrenr	{ "mail",			IPFY_FAC_MAIL },
1672145510Sdarrenr	{ "daemon",			IPFY_FAC_DAEMON },
1673145510Sdarrenr	{ "auth",			IPFY_FAC_AUTH },
1674145510Sdarrenr	{ "syslog",			IPFY_FAC_SYSLOG },
1675145510Sdarrenr	{ "lpr",			IPFY_FAC_LPR },
1676145510Sdarrenr	{ "news",			IPFY_FAC_NEWS },
1677145510Sdarrenr	{ "uucp",			IPFY_FAC_UUCP },
1678145510Sdarrenr	{ "cron",			IPFY_FAC_CRON },
1679145510Sdarrenr	{ "ftp",			IPFY_FAC_FTP },
1680145510Sdarrenr	{ "authpriv",			IPFY_FAC_AUTHPRIV },
1681145510Sdarrenr	{ "audit",			IPFY_FAC_AUDIT },
1682145510Sdarrenr	{ "logalert",			IPFY_FAC_LFMT },
1683145510Sdarrenr	{ "console",			IPFY_FAC_CONSOLE },
1684145510Sdarrenr	{ "security",			IPFY_FAC_SECURITY },
1685145510Sdarrenr	{ "local0",			IPFY_FAC_LOCAL0 },
1686145510Sdarrenr	{ "local1",			IPFY_FAC_LOCAL1 },
1687145510Sdarrenr	{ "local2",			IPFY_FAC_LOCAL2 },
1688145510Sdarrenr	{ "local3",			IPFY_FAC_LOCAL3 },
1689145510Sdarrenr	{ "local4",			IPFY_FAC_LOCAL4 },
1690145510Sdarrenr	{ "local5",			IPFY_FAC_LOCAL5 },
1691145510Sdarrenr	{ "local6",			IPFY_FAC_LOCAL6 },
1692145510Sdarrenr	{ "local7",			IPFY_FAC_LOCAL7 },
1693145510Sdarrenr	{ "emerg",			IPFY_PRI_EMERG },
1694145510Sdarrenr	{ "alert",			IPFY_PRI_ALERT },
1695145510Sdarrenr	{ "crit",			IPFY_PRI_CRIT },
1696145510Sdarrenr	{ "err",			IPFY_PRI_ERR },
1697145510Sdarrenr	{ "warn",			IPFY_PRI_WARN },
1698145510Sdarrenr	{ "notice",			IPFY_PRI_NOTICE },
1699145510Sdarrenr	{ "info",			IPFY_PRI_INFO },
1700145510Sdarrenr	{ "debug",			IPFY_PRI_DEBUG },
1701145510Sdarrenr	{ NULL,				0 },
1702145510Sdarrenr};
1703145510Sdarrenr
1704145510Sdarrenr
1705145510Sdarrenr
1706145510Sdarrenr
1707145510Sdarrenrint ipf_parsefile(fd, addfunc, iocfuncs, filename)
1708145510Sdarrenrint fd;
1709145510Sdarrenraddfunc_t addfunc;
1710145510Sdarrenrioctlfunc_t *iocfuncs;
1711145510Sdarrenrchar *filename;
1712145510Sdarrenr{
1713145510Sdarrenr	FILE *fp = NULL;
1714145510Sdarrenr	char *s;
1715145510Sdarrenr
1716145510Sdarrenr	yylineNum = 1;
1717145510Sdarrenr	yysettab(ipfwords);
1718145510Sdarrenr
1719145510Sdarrenr	s = getenv("YYDEBUG");
1720145510Sdarrenr	if (s != NULL)
1721145510Sdarrenr		yydebug = atoi(s);
1722145510Sdarrenr	else
1723145510Sdarrenr		yydebug = 0;
1724145510Sdarrenr
1725145510Sdarrenr	if (strcmp(filename, "-")) {
1726145510Sdarrenr		fp = fopen(filename, "r");
1727145510Sdarrenr		if (fp == NULL) {
1728145510Sdarrenr			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
1729145510Sdarrenr				STRERROR(errno));
1730145510Sdarrenr			return -1;
1731145510Sdarrenr		}
1732145510Sdarrenr	} else
1733145510Sdarrenr		fp = stdin;
1734145510Sdarrenr
1735145510Sdarrenr	while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1)
1736145510Sdarrenr		;
1737145510Sdarrenr	if (fp != NULL)
1738145510Sdarrenr		fclose(fp);
1739145510Sdarrenr	return 0;
1740145510Sdarrenr}
1741145510Sdarrenr
1742145510Sdarrenr
1743145510Sdarrenrint ipf_parsesome(fd, addfunc, iocfuncs, fp)
1744145510Sdarrenrint fd;
1745145510Sdarrenraddfunc_t addfunc;
1746145510Sdarrenrioctlfunc_t *iocfuncs;
1747145510SdarrenrFILE *fp;
1748145510Sdarrenr{
1749145510Sdarrenr	char *s;
1750145510Sdarrenr	int i;
1751145510Sdarrenr
1752145510Sdarrenr	ipffd = fd;
1753145510Sdarrenr	for (i = 0; i <= IPL_LOGMAX; i++)
1754145510Sdarrenr		ipfioctl[i] = iocfuncs[i];
1755145510Sdarrenr	ipfaddfunc = addfunc;
1756145510Sdarrenr
1757145510Sdarrenr	if (feof(fp))
1758145510Sdarrenr		return 0;
1759145510Sdarrenr	i = fgetc(fp);
1760145510Sdarrenr	if (i == EOF)
1761145510Sdarrenr		return 0;
1762145510Sdarrenr	if (ungetc(i, fp) == 0)
1763145510Sdarrenr		return 0;
1764145510Sdarrenr	if (feof(fp))
1765145510Sdarrenr		return 0;
1766145510Sdarrenr	s = getenv("YYDEBUG");
1767145510Sdarrenr	if (s != NULL)
1768145510Sdarrenr		yydebug = atoi(s);
1769145510Sdarrenr	else
1770145510Sdarrenr		yydebug = 0;
1771145510Sdarrenr
1772145510Sdarrenr	yyin = fp;
1773145510Sdarrenr	yyparse();
1774145510Sdarrenr	return 1;
1775145510Sdarrenr}
1776145510Sdarrenr
1777145510Sdarrenr
1778145510Sdarrenrstatic void newrule()
1779145510Sdarrenr{
1780145510Sdarrenr	frentry_t *frn;
1781145510Sdarrenr
1782145510Sdarrenr	frn = (frentry_t *)calloc(1, sizeof(frentry_t));
1783145510Sdarrenr	for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next)
1784145510Sdarrenr		;
1785145510Sdarrenr	if (fr != NULL)
1786145510Sdarrenr		fr->fr_next = frn;
1787145510Sdarrenr	if (frtop == NULL)
1788145510Sdarrenr		frtop = frn;
1789145510Sdarrenr	fr = frn;
1790145510Sdarrenr	frc = frn;
1791145510Sdarrenr	fr->fr_loglevel = 0xffff;
1792145510Sdarrenr	fr->fr_isc = (void *)-1;
1793145510Sdarrenr	fr->fr_logtag = FR_NOLOGTAG;
1794145510Sdarrenr	fr->fr_type = FR_T_NONE;
1795145510Sdarrenr	if (use_inet6 != 0)
1796145510Sdarrenr		fr->fr_v = 6;
1797145510Sdarrenr	else
1798145510Sdarrenr		fr->fr_v = 4;
1799145510Sdarrenr
1800145510Sdarrenr	nrules = 1;
1801145510Sdarrenr}
1802145510Sdarrenr
1803145510Sdarrenr
1804145510Sdarrenrstatic void setipftype()
1805145510Sdarrenr{
1806145510Sdarrenr	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1807145510Sdarrenr		if (fr->fr_type == FR_T_NONE) {
1808145510Sdarrenr			fr->fr_type = FR_T_IPF;
1809145510Sdarrenr			fr->fr_data = (void *)calloc(sizeof(fripf_t), 1);
1810145510Sdarrenr			fr->fr_dsize = sizeof(fripf_t);
1811145510Sdarrenr			fr->fr_ip.fi_v = frc->fr_v;
1812145510Sdarrenr			fr->fr_mip.fi_v = 0xf;
1813145510Sdarrenr			fr->fr_ipf->fri_sifpidx = -1;
1814145510Sdarrenr			fr->fr_ipf->fri_difpidx = -1;
1815145510Sdarrenr		}
1816145510Sdarrenr		if (fr->fr_type != FR_T_IPF) {
1817145510Sdarrenr			fprintf(stderr, "IPF Type not set\n");
1818145510Sdarrenr		}
1819145510Sdarrenr	}
1820145510Sdarrenr}
1821145510Sdarrenr
1822145510Sdarrenr
1823145510Sdarrenrstatic frentry_t *addrule()
1824145510Sdarrenr{
1825145510Sdarrenr	frentry_t *f, *f1, *f2;
1826145510Sdarrenr	int count;
1827145510Sdarrenr
1828145510Sdarrenr	for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next)
1829145510Sdarrenr		;
1830145510Sdarrenr
1831145510Sdarrenr	count = nrules;
1832145510Sdarrenr	f = f2;
1833145510Sdarrenr	for (f1 = frc; count > 0; count--, f1 = f1->fr_next) {
1834145510Sdarrenr		f->fr_next = (frentry_t *)calloc(sizeof(*f), 1);
1835145510Sdarrenr		added++;
1836145510Sdarrenr		f = f->fr_next;
1837145510Sdarrenr		bcopy(f1, f, sizeof(*f));
1838145510Sdarrenr		f->fr_next = NULL;
1839145510Sdarrenr		if (f->fr_caddr != NULL) {
1840145510Sdarrenr			f->fr_caddr = malloc(f->fr_dsize);
1841145510Sdarrenr			bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize);
1842145510Sdarrenr		}
1843145510Sdarrenr	}
1844145510Sdarrenr
1845145510Sdarrenr	return f2->fr_next;
1846145510Sdarrenr}
1847145510Sdarrenr
1848145510Sdarrenr
1849145510Sdarrenrstatic u_32_t lookuphost(name)
1850145510Sdarrenrchar *name;
1851145510Sdarrenr{
1852145510Sdarrenr	u_32_t addr;
1853145510Sdarrenr	int i;
1854145510Sdarrenr
1855145510Sdarrenr	hashed = 0;
1856145510Sdarrenr	pooled = 0;
1857145510Sdarrenr	dynamic = -1;
1858145510Sdarrenr
1859145510Sdarrenr	for (i = 0; i < 4; i++) {
1860145510Sdarrenr		if (strncmp(name, frc->fr_ifnames[i],
1861145510Sdarrenr			    sizeof(frc->fr_ifnames[i])) == 0) {
1862145510Sdarrenr			ifpflag = FRI_DYNAMIC;
1863145510Sdarrenr			dynamic = i;
1864145510Sdarrenr			return 0;
1865145510Sdarrenr		}
1866145510Sdarrenr	}
1867145510Sdarrenr
1868145510Sdarrenr	if (gethost(name, &addr) == -1) {
1869145510Sdarrenr		fprintf(stderr, "unknown name \"%s\"\n", name);
1870145510Sdarrenr		return 0;
1871145510Sdarrenr	}
1872145510Sdarrenr	return addr;
1873145510Sdarrenr}
1874145510Sdarrenr
1875145510Sdarrenr
1876145510Sdarrenrstatic void dobpf(v, phrase)
1877145510Sdarrenrint v;
1878145510Sdarrenrchar *phrase;
1879145510Sdarrenr{
1880145510Sdarrenr#ifdef IPFILTER_BPF
1881145510Sdarrenr	struct bpf_program bpf;
1882145510Sdarrenr	struct pcap *p;
1883145510Sdarrenr#endif
1884145510Sdarrenr	fakebpf_t *fb;
1885145510Sdarrenr	u_32_t l;
1886145510Sdarrenr	char *s;
1887145510Sdarrenr	int i;
1888145510Sdarrenr
1889145510Sdarrenr	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1890145510Sdarrenr		if (fr->fr_type != FR_T_NONE) {
1891145510Sdarrenr			fprintf(stderr, "cannot mix IPF and BPF matching\n");
1892145510Sdarrenr			return;
1893145510Sdarrenr		}
1894145510Sdarrenr		fr->fr_v = v;
1895145510Sdarrenr		fr->fr_type = FR_T_BPFOPC;
1896145510Sdarrenr
1897153881Sguido		if (!strncmp(phrase, "0x", 2)) {
1898145510Sdarrenr			fb = malloc(sizeof(fakebpf_t));
1899145510Sdarrenr
1900145510Sdarrenr			for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL;
1901145510Sdarrenr			     s = strtok(NULL, " \r\n\t"), i++) {
1902145510Sdarrenr				fb = realloc(fb, (i / 4 + 1) * sizeof(*fb));
1903145510Sdarrenr				l = (u_32_t)strtol(s, NULL, 0);
1904145510Sdarrenr				switch (i & 3)
1905145510Sdarrenr				{
1906145510Sdarrenr				case 0 :
1907145510Sdarrenr					fb[i / 4].fb_c = l & 0xffff;
1908145510Sdarrenr					break;
1909145510Sdarrenr				case 1 :
1910145510Sdarrenr					fb[i / 4].fb_t = l & 0xff;
1911145510Sdarrenr					break;
1912145510Sdarrenr				case 2 :
1913145510Sdarrenr					fb[i / 4].fb_f = l & 0xff;
1914145510Sdarrenr					break;
1915145510Sdarrenr				case 3 :
1916145510Sdarrenr					fb[i / 4].fb_k = l;
1917145510Sdarrenr					break;
1918145510Sdarrenr				}
1919145510Sdarrenr			}
1920145510Sdarrenr			if ((i & 3) != 0) {
1921145510Sdarrenr				fprintf(stderr,
1922145510Sdarrenr					"Odd number of bytes in BPF code\n");
1923145510Sdarrenr				exit(1);
1924145510Sdarrenr			}
1925145510Sdarrenr			i--;
1926145510Sdarrenr			fr->fr_dsize = (i / 4 + 1) * sizeof(*fb);
1927145510Sdarrenr			fr->fr_data = fb;
1928145510Sdarrenr			return;
1929145510Sdarrenr		}
1930145510Sdarrenr
1931145510Sdarrenr#ifdef IPFILTER_BPF
1932145510Sdarrenr		bzero((char *)&bpf, sizeof(bpf));
1933145510Sdarrenr		p = pcap_open_dead(DLT_RAW, 1);
1934145510Sdarrenr		if (!p) {
1935145510Sdarrenr			fprintf(stderr, "pcap_open_dead failed\n");
1936145510Sdarrenr			return;
1937145510Sdarrenr		}
1938145510Sdarrenr
1939145510Sdarrenr		if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) {
1940145510Sdarrenr			pcap_perror(p, "ipf");
1941145510Sdarrenr			pcap_close(p);
1942145510Sdarrenr			fprintf(stderr, "pcap parsing failed (%s)\n", phrase);
1943145510Sdarrenr			return;
1944145510Sdarrenr		}
1945145510Sdarrenr		pcap_close(p);
1946145510Sdarrenr
1947145510Sdarrenr		fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
1948145510Sdarrenr		fr->fr_data = malloc(fr->fr_dsize);
1949145510Sdarrenr		bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize);
1950145510Sdarrenr		if (!bpf_validate(fr->fr_data, bpf.bf_len)) {
1951145510Sdarrenr			fprintf(stderr, "BPF validation failed\n");
1952145510Sdarrenr			return;
1953145510Sdarrenr		}
1954145510Sdarrenr#endif
1955145510Sdarrenr	}
1956145510Sdarrenr
1957145510Sdarrenr#ifdef IPFILTER_BPF
1958145510Sdarrenr	if (opts & OPT_DEBUG)
1959145510Sdarrenr		bpf_dump(&bpf, 0);
1960145510Sdarrenr#else
1961145510Sdarrenr	fprintf(stderr, "BPF filter expressions not supported\n");
1962145510Sdarrenr	exit(1);
1963145510Sdarrenr#endif
1964145510Sdarrenr}
1965145510Sdarrenr
1966145510Sdarrenr
1967145510Sdarrenrstatic void resetaddr()
1968145510Sdarrenr{
1969145510Sdarrenr	hashed = 0;
1970145510Sdarrenr	pooled = 0;
1971145510Sdarrenr	dynamic = -1;
1972145510Sdarrenr}
1973145510Sdarrenr
1974145510Sdarrenr
1975145510Sdarrenrstatic alist_t *newalist(ptr)
1976145510Sdarrenralist_t *ptr;
1977145510Sdarrenr{
1978145510Sdarrenr	alist_t *al;
1979145510Sdarrenr
1980145510Sdarrenr	al = malloc(sizeof(*al));
1981145510Sdarrenr	if (al == NULL)
1982145510Sdarrenr		return NULL;
1983145510Sdarrenr	al->al_not = 0;
1984145510Sdarrenr	al->al_next = ptr;
1985145510Sdarrenr	return al;
1986145510Sdarrenr}
1987145510Sdarrenr
1988145510Sdarrenr
1989145510Sdarrenrstatic int makepool(list)
1990145510Sdarrenralist_t *list;
1991145510Sdarrenr{
1992145510Sdarrenr	ip_pool_node_t *n, *top;
1993145510Sdarrenr	ip_pool_t pool;
1994145510Sdarrenr	alist_t *a;
1995145510Sdarrenr	int num;
1996145510Sdarrenr
1997145510Sdarrenr	if (list == NULL)
1998145510Sdarrenr		return 0;
1999145510Sdarrenr	top = calloc(1, sizeof(*top));
2000145510Sdarrenr	if (top == NULL)
2001145510Sdarrenr		return 0;
2002145510Sdarrenr
2003145510Sdarrenr	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2004145510Sdarrenr		n->ipn_addr.adf_addr.in4.s_addr = a->al_1;
2005145510Sdarrenr		n->ipn_mask.adf_addr.in4.s_addr = a->al_2;
2006145510Sdarrenr		n->ipn_info = a->al_not;
2007145510Sdarrenr		if (a->al_next != NULL) {
2008145510Sdarrenr			n->ipn_next = calloc(1, sizeof(*n));
2009145510Sdarrenr			n = n->ipn_next;
2010145510Sdarrenr		}
2011145510Sdarrenr	}
2012145510Sdarrenr
2013145510Sdarrenr	bzero((char *)&pool, sizeof(pool));
2014145510Sdarrenr	pool.ipo_unit = IPL_LOGIPF;
2015145510Sdarrenr	pool.ipo_list = top;
2016145510Sdarrenr	num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]);
2017145510Sdarrenr
2018145510Sdarrenr	while ((n = top) != NULL) {
2019145510Sdarrenr		top = n->ipn_next;
2020145510Sdarrenr		free(n);
2021145510Sdarrenr	}
2022145510Sdarrenr	return num;
2023145510Sdarrenr}
2024145510Sdarrenr
2025145510Sdarrenr
2026145510Sdarrenrstatic u_int makehash(list)
2027145510Sdarrenralist_t *list;
2028145510Sdarrenr{
2029145510Sdarrenr	iphtent_t *n, *top;
2030145510Sdarrenr	iphtable_t iph;
2031145510Sdarrenr	alist_t *a;
2032145510Sdarrenr	int num;
2033145510Sdarrenr
2034145510Sdarrenr	if (list == NULL)
2035145510Sdarrenr		return 0;
2036145510Sdarrenr	top = calloc(1, sizeof(*top));
2037145510Sdarrenr	if (top == NULL)
2038145510Sdarrenr		return 0;
2039145510Sdarrenr
2040145510Sdarrenr	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2041145510Sdarrenr		n->ipe_addr.in4_addr = a->al_1;
2042145510Sdarrenr		n->ipe_mask.in4_addr = a->al_2;
2043145510Sdarrenr		n->ipe_value = 0;
2044145510Sdarrenr		if (a->al_next != NULL) {
2045145510Sdarrenr			n->ipe_next = calloc(1, sizeof(*n));
2046145510Sdarrenr			n = n->ipe_next;
2047145510Sdarrenr		}
2048145510Sdarrenr	}
2049145510Sdarrenr
2050145510Sdarrenr	bzero((char *)&iph, sizeof(iph));
2051145510Sdarrenr	iph.iph_unit = IPL_LOGIPF;
2052145510Sdarrenr	iph.iph_type = IPHASH_LOOKUP;
2053145510Sdarrenr	*iph.iph_name = '\0';
2054145510Sdarrenr
2055145510Sdarrenr	if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0)
2056145510Sdarrenr		sscanf(iph.iph_name, "%u", &num);
2057145510Sdarrenr	else
2058145510Sdarrenr		num = 0;
2059145510Sdarrenr
2060145510Sdarrenr	while ((n = top) != NULL) {
2061145510Sdarrenr		top = n->ipe_next;
2062145510Sdarrenr		free(n);
2063145510Sdarrenr	}
2064145510Sdarrenr	return num;
2065145510Sdarrenr}
2066145510Sdarrenr
2067145510Sdarrenr
2068145510Sdarrenrvoid ipf_addrule(fd, ioctlfunc, ptr)
2069145510Sdarrenrint fd;
2070145510Sdarrenrioctlfunc_t ioctlfunc;
2071145510Sdarrenrvoid *ptr;
2072145510Sdarrenr{
2073145510Sdarrenr	ioctlcmd_t add, del;
2074145510Sdarrenr	frentry_t *fr;
2075145510Sdarrenr	ipfobj_t obj;
2076145510Sdarrenr
2077170268Sdarrenr	if (ptr == NULL)
2078170268Sdarrenr		return;
2079170268Sdarrenr
2080145510Sdarrenr	fr = ptr;
2081145510Sdarrenr	add = 0;
2082145510Sdarrenr	del = 0;
2083145510Sdarrenr
2084145510Sdarrenr	bzero((char *)&obj, sizeof(obj));
2085145510Sdarrenr	obj.ipfo_rev = IPFILTER_VERSION;
2086145510Sdarrenr	obj.ipfo_size = sizeof(*fr);
2087145510Sdarrenr	obj.ipfo_type = IPFOBJ_FRENTRY;
2088145510Sdarrenr	obj.ipfo_ptr = ptr;
2089145510Sdarrenr
2090145510Sdarrenr	if ((opts & OPT_DONOTHING) != 0)
2091145510Sdarrenr		fd = -1;
2092145510Sdarrenr
2093145510Sdarrenr	if (opts & OPT_ZERORULEST) {
2094145510Sdarrenr		add = SIOCZRLST;
2095145510Sdarrenr	} else if (opts & OPT_INACTIVE) {
2096145510Sdarrenr		add = (u_int)fr->fr_hits ? SIOCINIFR :
2097145510Sdarrenr					   SIOCADIFR;
2098145510Sdarrenr		del = SIOCRMIFR;
2099145510Sdarrenr	} else {
2100145510Sdarrenr		add = (u_int)fr->fr_hits ? SIOCINAFR :
2101145510Sdarrenr					   SIOCADAFR;
2102145510Sdarrenr		del = SIOCRMAFR;
2103145510Sdarrenr	}
2104145510Sdarrenr
2105161357Sguido	if ((opts & OPT_OUTQUE) != 0)
2106145510Sdarrenr		fr->fr_flags |= FR_OUTQUE;
2107145510Sdarrenr	if (fr->fr_hits)
2108145510Sdarrenr		fr->fr_hits--;
2109170268Sdarrenr	if ((opts & OPT_VERBOSE) != 0)
2110145510Sdarrenr		printfr(fr, ioctlfunc);
2111145510Sdarrenr
2112170268Sdarrenr	if ((opts & OPT_DEBUG) != 0) {
2113145510Sdarrenr		binprint(fr, sizeof(*fr));
2114145510Sdarrenr		if (fr->fr_data != NULL)
2115145510Sdarrenr			binprint(fr->fr_data, fr->fr_dsize);
2116145510Sdarrenr	}
2117145510Sdarrenr
2118145510Sdarrenr	if ((opts & OPT_ZERORULEST) != 0) {
2119145510Sdarrenr		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2120145510Sdarrenr			if ((opts & OPT_DONOTHING) == 0) {
2121145510Sdarrenr				fprintf(stderr, "%d:", yylineNum);
2122145510Sdarrenr				perror("ioctl(SIOCZRLST)");
2123145510Sdarrenr			}
2124145510Sdarrenr		} else {
2125145510Sdarrenr#ifdef	USE_QUAD_T
2126145510Sdarrenr			printf("hits %qd bytes %qd ",
2127145510Sdarrenr				(long long)fr->fr_hits,
2128145510Sdarrenr				(long long)fr->fr_bytes);
2129145510Sdarrenr#else
2130145510Sdarrenr			printf("hits %ld bytes %ld ",
2131145510Sdarrenr				fr->fr_hits, fr->fr_bytes);
2132145510Sdarrenr#endif
2133145510Sdarrenr			printfr(fr, ioctlfunc);
2134145510Sdarrenr		}
2135145510Sdarrenr	} else if ((opts & OPT_REMOVE) != 0) {
2136145510Sdarrenr		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
2137145510Sdarrenr			if ((opts & OPT_DONOTHING) != 0) {
2138145510Sdarrenr				fprintf(stderr, "%d:", yylineNum);
2139145510Sdarrenr				perror("ioctl(delete rule)");
2140145510Sdarrenr			}
2141145510Sdarrenr		}
2142145510Sdarrenr	} else {
2143145510Sdarrenr		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2144145510Sdarrenr			if (!(opts & OPT_DONOTHING)) {
2145145510Sdarrenr				fprintf(stderr, "%d:", yylineNum);
2146145510Sdarrenr				perror("ioctl(add/insert rule)");
2147145510Sdarrenr			}
2148145510Sdarrenr		}
2149145510Sdarrenr	}
2150145510Sdarrenr}
2151145510Sdarrenr
2152145510Sdarrenrstatic void setsyslog()
2153145510Sdarrenr{
2154145510Sdarrenr	yysetdict(logwords);
2155145510Sdarrenr	yybreakondot = 1;
2156145510Sdarrenr}
2157145510Sdarrenr
2158145510Sdarrenr
2159145510Sdarrenrstatic void unsetsyslog()
2160145510Sdarrenr{
2161145510Sdarrenr	yyresetdict();
2162145510Sdarrenr	yybreakondot = 0;
2163145510Sdarrenr}
2164145510Sdarrenr
2165145510Sdarrenr
2166145510Sdarrenrstatic void fillgroup(fr)
2167145510Sdarrenrfrentry_t *fr;
2168145510Sdarrenr{
2169145510Sdarrenr	frentry_t *f;
2170145510Sdarrenr
2171145510Sdarrenr	for (f = frold; f != NULL; f = f->fr_next)
2172145510Sdarrenr		if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0)
2173145510Sdarrenr			break;
2174145510Sdarrenr	if (f == NULL)
2175145510Sdarrenr		return;
2176145510Sdarrenr
2177145510Sdarrenr	/*
2178145510Sdarrenr	 * Only copy down matching fields if the rules are of the same type
2179145510Sdarrenr	 * and are of ipf type.   The only fields that are copied are those
2180145510Sdarrenr	 * that impact the rule parsing itself, eg. need for knowing what the
2181145510Sdarrenr	 * protocol should be for rules with port comparisons in them.
2182145510Sdarrenr	 */
2183145510Sdarrenr	if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF)
2184145510Sdarrenr		return;
2185145510Sdarrenr
2186145510Sdarrenr	if (fr->fr_v == 0 && f->fr_v != 0)
2187145510Sdarrenr		fr->fr_v = f->fr_v;
2188145510Sdarrenr
2189145510Sdarrenr	if (fr->fr_mproto == 0 && f->fr_mproto != 0)
2190145510Sdarrenr		fr->fr_mproto = f->fr_mproto;
2191145510Sdarrenr	if (fr->fr_proto == 0 && f->fr_proto != 0)
2192145510Sdarrenr		fr->fr_proto = f->fr_proto;
2193145510Sdarrenr
2194145510Sdarrenr	if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) &&
2195145510Sdarrenr	    ((f->fr_flx & FI_TCPUDP) != 0))
2196145510Sdarrenr		fr->fr_flx |= FI_TCPUDP;
2197145510Sdarrenr}
2198