1145519Sdarrenr/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ipf_y.y 369245 2021-02-09 13:47:46Z git2svn $	*/
2145510Sdarrenr
3170268Sdarrenr/*
4255332Scy * Copyright (C) 2012 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>
12317314Scy#include <err.h>
13145510Sdarrenr#ifdef IPFILTER_BPF
14145510Sdarrenr# include <pcap.h>
15145510Sdarrenr#endif
16145510Sdarrenr#include "netinet/ip_pool.h"
17145510Sdarrenr#include "netinet/ip_htable.h"
18145510Sdarrenr#include "netinet/ipl.h"
19145510Sdarrenr#include "ipf_l.h"
20145510Sdarrenr
21145510Sdarrenr#define	YYDEBUG	1
22145510Sdarrenr#define	DOALL(x)	for (fr = frc; fr != NULL; fr = fr->fr_next) { x }
23145510Sdarrenr#define	DOREM(x)	for (; fr != NULL; fr = fr->fr_next) { x }
24145510Sdarrenr
25369245Sgit2svnextern	void	yyerror(char *);
26369245Sgit2svnextern	int	yyparse(void);
27369245Sgit2svnextern	int	yylex(void);
28145510Sdarrenrextern	int	yydebug;
29145510Sdarrenrextern	FILE	*yyin;
30145510Sdarrenrextern	int	yylineNum;
31145510Sdarrenr
32369245Sgit2svnstatic	int	addname(frentry_t **, char *);
33369245Sgit2svnstatic	frentry_t *addrule(void);
34369245Sgit2svnstatic frentry_t *allocfr(void);
35369245Sgit2svnstatic	void	build_dstaddr_af(frentry_t *, void *);
36369245Sgit2svnstatic	void	build_srcaddr_af(frentry_t *, void *);
37369245Sgit2svnstatic	void	dobpf(int, char *);
38369245Sgit2svnstatic	void	doipfexpr(char *);
39369245Sgit2svnstatic	void	do_tuneint(char *, int);
40369245Sgit2svnstatic	void	do_tunestr(char *, char *);
41369245Sgit2svnstatic	void	fillgroup(frentry_t *);
42369245Sgit2svnstatic	int	lookuphost(char *, i6addr_t *);
43369245Sgit2svnstatic	u_int	makehash(struct alist_s *);
44369245Sgit2svnstatic	int	makepool(struct alist_s *);
45369245Sgit2svnstatic	struct	alist_s	*newalist(struct alist_s *);
46369245Sgit2svnstatic	void	newrule(void);
47369245Sgit2svnstatic	void	resetaddr(void);
48369245Sgit2svnstatic	void	setgroup(frentry_t **, char *);
49369245Sgit2svnstatic	void	setgrhead(frentry_t **, char *);
50369245Sgit2svnstatic	void	seticmphead(frentry_t **, char *);
51369245Sgit2svnstatic	void	setifname(frentry_t **, int, char *);
52369245Sgit2svnstatic	void	setipftype(void);
53369245Sgit2svnstatic	void	setsyslog(void);
54369245Sgit2svnstatic	void	unsetsyslog(void);
55145510Sdarrenr
56145510Sdarrenrfrentry_t	*fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL;
57145510Sdarrenr
58145510Sdarrenrstatic	int		ifpflag = 0;
59145510Sdarrenrstatic	int		nowith = 0;
60145510Sdarrenrstatic	int		dynamic = -1;
61145510Sdarrenrstatic	int		pooled = 0;
62145510Sdarrenrstatic	int		hashed = 0;
63145510Sdarrenrstatic	int		nrules = 0;
64145510Sdarrenrstatic	int		newlist = 0;
65145510Sdarrenrstatic	int		added = 0;
66145510Sdarrenrstatic	int		ipffd = -1;
67255332Scystatic	int		*yycont = NULL;
68255332Scystatic	ioctlfunc_t	ipfioctls[IPL_LOGSIZE];
69145510Sdarrenrstatic	addfunc_t	ipfaddfunc = NULL;
70145510Sdarrenr
71145510Sdarrenr%}
72145510Sdarrenr%union	{
73145510Sdarrenr	char	*str;
74145510Sdarrenr	u_32_t	num;
75145510Sdarrenr	frentry_t	fr;
76145510Sdarrenr	frtuc_t	*frt;
77145510Sdarrenr	struct	alist_s	*alist;
78145510Sdarrenr	u_short	port;
79255332Scy	struct	in_addr	ip4;
80145510Sdarrenr	struct	{
81145510Sdarrenr		u_short	p1;
82145510Sdarrenr		u_short	p2;
83145510Sdarrenr		int	pc;
84145510Sdarrenr	} pc;
85255332Scy	struct ipp_s {
86255332Scy		int		type;
87255332Scy		int		ifpos;
88255332Scy		int		f;
89255332Scy		int		v;
90255332Scy		int		lif;
91145510Sdarrenr		union	i6addr	a;
92145510Sdarrenr		union	i6addr	m;
93255332Scy		char		*name;
94145510Sdarrenr	} ipp;
95161357Sguido	struct	{
96255332Scy		i6addr_t	adr;
97255332Scy		int		f;
98255332Scy	} adr;
99255332Scy	i6addr_t	ip6;
100255332Scy	struct	{
101161357Sguido		char	*if1;
102161357Sguido		char	*if2;
103161357Sguido	} ifs;
104255332Scy	char	gname[FR_GROUPLEN];
105145510Sdarrenr};
106145510Sdarrenr
107145510Sdarrenr%type	<port>	portnum
108145510Sdarrenr%type	<num>	facility priority icmpcode seclevel secname icmptype
109145510Sdarrenr%type	<num>	opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr
110255332Scy%type	<num>	portc porteq ipmask maskopts
111255332Scy%type	<ip4>	ipv4 ipv4_16 ipv4_24
112255332Scy%type	<adr>	hostname
113145510Sdarrenr%type	<ipp>	addr ipaddr
114255332Scy%type	<str>	servicename name interfacename groupname
115145510Sdarrenr%type	<pc>	portrange portcomp
116145510Sdarrenr%type	<alist>	addrlist poollist
117161357Sguido%type	<ifs>	onname
118145510Sdarrenr
119145510Sdarrenr%token	<num>	YY_NUMBER YY_HEX
120145510Sdarrenr%token	<str>	YY_STR
121145510Sdarrenr%token		YY_COMMENT
122145510Sdarrenr%token		YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
123145510Sdarrenr%token		YY_RANGE_OUT YY_RANGE_IN
124145510Sdarrenr%token	<ip6>	YY_IPV6
125145510Sdarrenr
126255332Scy%token	IPFY_SET
127161357Sguido%token	IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL IPFY_NOMATCH
128145510Sdarrenr%token	IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST
129145510Sdarrenr%token	IPFY_IN IPFY_OUT
130145510Sdarrenr%token	IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA
131145510Sdarrenr%token	IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO
132255332Scy%token	IPFY_TOS IPFY_TTL IPFY_PROTO IPFY_INET IPFY_INET6
133145510Sdarrenr%token	IPFY_HEAD IPFY_GROUP
134145510Sdarrenr%token	IPFY_AUTH IPFY_PREAUTH
135255332Scy%token	IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK IPFY_L5AS
136255332Scy%token	IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP IPFY_DECAPS
137145510Sdarrenr%token	IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH
138255332Scy%token	IPFY_IPFEXPR IPFY_PPS IPFY_FAMILY IPFY_DSTLIST
139145510Sdarrenr%token	IPFY_ESP IPFY_AH
140145510Sdarrenr%token	IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT
141145510Sdarrenr%token	IPFY_TCPUDP IPFY_TCP IPFY_UDP
142145510Sdarrenr%token	IPFY_FLAGS IPFY_MULTICAST
143145510Sdarrenr%token	IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER
144255332Scy%token	IPFY_RPC IPFY_PORT
145255332Scy%token	IPFY_NOW IPFY_COMMENT IPFY_RULETTL
146145510Sdarrenr%token	IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
147145510Sdarrenr%token	IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG
148145510Sdarrenr%token	IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR
149145510Sdarrenr%token	IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
150255332Scy%token	IPFY_SYNC IPFY_FRAGBODY IPFY_ICMPHEAD IPFY_NOLOG IPFY_LOOSE
151255332Scy%token	IPFY_MAX_SRCS IPFY_MAX_PER_SRC
152145510Sdarrenr%token	IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
153145510Sdarrenr%token	IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
154145510Sdarrenr%token	IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
155145510Sdarrenr%token	IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA
156145510Sdarrenr%token	IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS
157145510Sdarrenr%token	IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP
158145510Sdarrenr%token	IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2
159255332Scy%token	IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 IPFY_DOI
160145510Sdarrenr
161255332Scy%token	IPFY_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS
162255332Scy%token	IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING IPFY_V6HDR
163153881Sguido%token	IPFY_IPV6OPT_MOBILITY IPFY_IPV6OPT_ESP IPFY_IPV6OPT_FRAG
164145510Sdarrenr
165145510Sdarrenr%token	IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH
166145510Sdarrenr%token	IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST
167145510Sdarrenr%token	IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP
168145510Sdarrenr%token	IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD
169145510Sdarrenr%token	IPFY_ICMPT_ROUTERSOL
170145510Sdarrenr
171145510Sdarrenr%token	IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR
172145510Sdarrenr%token	IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK
173145510Sdarrenr%token	IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO
174145510Sdarrenr%token	IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE
175145510Sdarrenr%token	IPFY_ICMPC_CUTPRE
176145510Sdarrenr
177145510Sdarrenr%token	IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH
178145510Sdarrenr%token	IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON
179145510Sdarrenr%token	IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3
180145510Sdarrenr%token	IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7
181145510Sdarrenr%token	IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT
182145510Sdarrenr%token	IPFY_FAC_LFMT IPFY_FAC_CONSOLE
183145510Sdarrenr
184145510Sdarrenr%token	IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN
185145510Sdarrenr%token	IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG
186145510Sdarrenr%%
187255332Scyfile:	settings rules
188255332Scy	| rules
189255332Scy	;
190255332Scy
191255332Scysettings:
192255332Scy	YY_COMMENT
193255332Scy	| setting
194255332Scy	| settings setting
195255332Scy	;
196255332Scy
197255332Scyrules:	line
198145510Sdarrenr	| assign
199255332Scy	| rules line
200255332Scy	| rules assign
201145510Sdarrenr	;
202145510Sdarrenr
203255332Scysetting:
204255332Scy	IPFY_SET YY_STR YY_NUMBER ';'	{ do_tuneint($2, $3); }
205255332Scy	| IPFY_SET YY_STR YY_HEX ';'	{ do_tuneint($2, $3); }
206255332Scy	| IPFY_SET YY_STR YY_STR ';'	{ do_tunestr($2, $3); }
207255332Scy	;
208255332Scy
209170268Sdarrenrline:	rule		{ while ((fr = frtop) != NULL) {
210145510Sdarrenr				frtop = fr->fr_next;
211145510Sdarrenr				fr->fr_next = NULL;
212255332Scy				if ((fr->fr_type == FR_T_IPF) &&
213255332Scy				    (fr->fr_ip.fi_v == 0))
214255332Scy					fr->fr_mip.fi_v = 0;
215255332Scy				/* XXX validate ? */
216255332Scy				(*ipfaddfunc)(ipffd, ipfioctls[IPL_LOGIPF], fr);
217145510Sdarrenr				fr->fr_next = frold;
218145510Sdarrenr				frold = fr;
219145510Sdarrenr			  }
220145510Sdarrenr			  resetlexer();
221145510Sdarrenr			}
222145510Sdarrenr	| YY_COMMENT
223145510Sdarrenr	;
224145510Sdarrenr
225161357Sguidoxx:					{ newrule(); }
226145510Sdarrenr	;
227145510Sdarrenr
228145510Sdarrenrassign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
229145510Sdarrenr					  resetlexer();
230145510Sdarrenr					  free($1);
231145510Sdarrenr					  free($3);
232170268Sdarrenr					  yyvarnext = 0;
233145510Sdarrenr					}
234145510Sdarrenr	;
235145510Sdarrenr
236145510Sdarrenrassigning:
237145510Sdarrenr	'='				{ yyvarnext = 1; }
238145510Sdarrenr	;
239145510Sdarrenr
240145510Sdarrenrrule:	inrule eol
241145510Sdarrenr	| outrule eol
242145510Sdarrenr	;
243145510Sdarrenr
244145510Sdarrenreol:	| ';'
245145510Sdarrenr	;
246145510Sdarrenr
247145510Sdarrenrinrule:
248145510Sdarrenr	rulehead markin inopts rulemain ruletail intag ruletail2
249145510Sdarrenr	;
250145510Sdarrenr
251145510Sdarrenroutrule:
252145510Sdarrenr	rulehead markout outopts rulemain ruletail outtag ruletail2
253145510Sdarrenr	;
254145510Sdarrenr
255145510Sdarrenrrulehead:
256170268Sdarrenr	xx collection action
257170268Sdarrenr	| xx insert collection action
258145510Sdarrenr	;
259145510Sdarrenr
260145510Sdarrenrmarkin:	IPFY_IN				{ fr->fr_flags |= FR_INQUE; }
261145510Sdarrenr	;
262145510Sdarrenr
263145510Sdarrenrmarkout:
264145510Sdarrenr	IPFY_OUT			{ fr->fr_flags |= FR_OUTQUE; }
265145510Sdarrenr	;
266145510Sdarrenr
267145510Sdarrenrrulemain:
268145510Sdarrenr	ipfrule
269145510Sdarrenr	| bpfrule
270255332Scy	| exprrule
271145510Sdarrenr	;
272145510Sdarrenr
273145510Sdarrenripfrule:
274255332Scy	family tos ttl proto ip
275145510Sdarrenr	;
276145510Sdarrenr
277255332Scyfamily:	| IPFY_FAMILY IPFY_INET		{ if (use_inet6 == 1) {
278255332Scy						YYERROR;
279255332Scy					  } else {
280255332Scy						frc->fr_family = AF_INET;
281255332Scy					  }
282255332Scy					}
283255332Scy	| IPFY_INET			{ if (use_inet6 == 1) {
284255332Scy						YYERROR;
285255332Scy					  } else {
286255332Scy						frc->fr_family = AF_INET;
287255332Scy					  }
288255332Scy					}
289255332Scy	| IPFY_FAMILY IPFY_INET6	{ if (use_inet6 == -1) {
290255332Scy						YYERROR;
291255332Scy					  } else {
292255332Scy						frc->fr_family = AF_INET6;
293255332Scy					  }
294255332Scy					}
295255332Scy	| IPFY_INET6			{ if (use_inet6 == -1) {
296255332Scy						YYERROR;
297255332Scy					  } else {
298255332Scy						frc->fr_family = AF_INET6;
299255332Scy					  }
300255332Scy					}
301255332Scy	;
302255332Scy
303145510Sdarrenrbpfrule:
304145510Sdarrenr	IPFY_BPFV4 '{' YY_STR '}' 	{ dobpf(4, $3); free($3); }
305145510Sdarrenr	| IPFY_BPFV6 '{' YY_STR '}' 	{ dobpf(6, $3); free($3); }
306145510Sdarrenr	;
307145510Sdarrenr
308255332Scyexprrule:
309255332Scy	IPFY_IPFEXPR '{' YY_STR '}'	{ doipfexpr($3); }
310255332Scy	;
311255332Scy
312145510Sdarrenrruletail:
313145510Sdarrenr	with keep head group
314145510Sdarrenr	;
315145510Sdarrenr
316145510Sdarrenrruletail2:
317255332Scy	pps age new rulettl comment
318145510Sdarrenr	;
319145510Sdarrenr
320145510Sdarrenrintag:	settagin matchtagin
321145510Sdarrenr	;
322145510Sdarrenr
323145510Sdarrenrouttag:	settagout matchtagout
324145510Sdarrenr	;
325145510Sdarrenr
326145510Sdarrenrinsert:
327145510Sdarrenr	'@' YY_NUMBER			{ fr->fr_hits = (U_QUAD_T)$2 + 1; }
328145510Sdarrenr	;
329145510Sdarrenr
330145510Sdarrenrcollection:
331145510Sdarrenr	| YY_NUMBER			{ fr->fr_collect = $1; }
332145510Sdarrenr	;
333145510Sdarrenr
334145510Sdarrenraction:	block
335145510Sdarrenr	| IPFY_PASS			{ fr->fr_flags |= FR_PASS; }
336161357Sguido	| IPFY_NOMATCH			{ fr->fr_flags |= FR_NOMATCH; }
337145510Sdarrenr	| log
338145510Sdarrenr	| IPFY_COUNT			{ fr->fr_flags |= FR_ACCOUNT; }
339255332Scy	| decaps			{ fr->fr_flags |= FR_DECAPSULATE; }
340145510Sdarrenr	| auth
341145510Sdarrenr	| IPFY_SKIP YY_NUMBER		{ fr->fr_flags |= FR_SKIP;
342145510Sdarrenr					  fr->fr_arg = $2; }
343145510Sdarrenr	| IPFY_CALL func
344145510Sdarrenr	| IPFY_CALL IPFY_NOW func	{ fr->fr_flags |= FR_CALLNOW; }
345145510Sdarrenr	;
346145510Sdarrenr
347145510Sdarrenrblock:	blocked
348145510Sdarrenr	| blocked blockreturn
349145510Sdarrenr	;
350145510Sdarrenr
351145510Sdarrenrblocked:
352145510Sdarrenr	IPFY_BLOCK			{ fr->fr_flags = FR_BLOCK; }
353145510Sdarrenr	;
354145510Sdarrenrblockreturn:
355145510Sdarrenr	IPFY_RETICMP			{ fr->fr_flags |= FR_RETICMP; }
356145510Sdarrenr	| IPFY_RETICMP returncode	{ fr->fr_flags |= FR_RETICMP; }
357145510Sdarrenr	| IPFY_RETICMPASDST		{ fr->fr_flags |= FR_FAKEICMP; }
358145510Sdarrenr	| IPFY_RETICMPASDST returncode	{ fr->fr_flags |= FR_FAKEICMP; }
359145510Sdarrenr	| IPFY_RETRST			{ fr->fr_flags |= FR_RETRST; }
360145510Sdarrenr	;
361145510Sdarrenr
362255332Scydecaps:	IPFY_DECAPS
363255332Scy	| IPFY_DECAPS IPFY_L5AS '(' YY_STR ')'
364255332Scy					{ fr->fr_icode = atoi($4); }
365255332Scy	;
366255332Scy
367145510Sdarrenrlog:	IPFY_LOG			{ fr->fr_flags |= FR_LOG; }
368145510Sdarrenr	| IPFY_LOG logoptions		{ fr->fr_flags |= FR_LOG; }
369145510Sdarrenr	;
370145510Sdarrenr
371145510Sdarrenrauth:	IPFY_AUTH			{ fr->fr_flags |= FR_AUTH; }
372161357Sguido	| IPFY_AUTH blockreturn		{ fr->fr_flags |= FR_AUTH;}
373145510Sdarrenr	| IPFY_PREAUTH			{ fr->fr_flags |= FR_PREAUTH; }
374145510Sdarrenr	;
375145510Sdarrenr
376255332Scyfunc:	YY_STR '/' YY_NUMBER
377255332Scy			{ fr->fr_func = nametokva($1, ipfioctls[IPL_LOGIPF]);
378255332Scy			  fr->fr_arg = $3;
379255332Scy			  free($1);
380255332Scy			}
381145510Sdarrenr	;
382145510Sdarrenr
383145510Sdarrenrinopts:
384145510Sdarrenr	| inopts inopt
385145510Sdarrenr	;
386145510Sdarrenr
387145510Sdarrenrinopt:
388145510Sdarrenr	logopt
389145510Sdarrenr	| quick
390145510Sdarrenr	| on
391145510Sdarrenr	| dup
392145510Sdarrenr	| froute
393145510Sdarrenr	| proute
394145510Sdarrenr	| replyto
395145510Sdarrenr	;
396145510Sdarrenr
397145510Sdarrenroutopts:
398145510Sdarrenr	| outopts outopt
399145510Sdarrenr	;
400145510Sdarrenr
401145510Sdarrenroutopt:
402145510Sdarrenr	logopt
403145510Sdarrenr	| quick
404145510Sdarrenr	| on
405145510Sdarrenr	| dup
406145510Sdarrenr	| proute
407255332Scy	| froute
408145510Sdarrenr	| replyto
409145510Sdarrenr	;
410145510Sdarrenr
411145510Sdarrenrtos:	| settos YY_NUMBER	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
412145510Sdarrenr	| settos YY_HEX	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
413145510Sdarrenr	| settos lstart toslist lend
414145510Sdarrenr	;
415145510Sdarrenr
416145510Sdarrenrsettos:	IPFY_TOS			{ setipftype(); }
417145510Sdarrenr	;
418145510Sdarrenr
419145510Sdarrenrtoslist:
420145510Sdarrenr	YY_NUMBER	{ DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
421145510Sdarrenr	| YY_HEX	{ DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
422145510Sdarrenr	| toslist lmore YY_NUMBER
423145510Sdarrenr			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
424255332Scy	| toslist lmore YY_HEX
425145510Sdarrenr			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
426145510Sdarrenr	;
427145510Sdarrenr
428145510Sdarrenrttl:	| setttl YY_NUMBER
429145510Sdarrenr			{ DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
430145510Sdarrenr	| setttl lstart ttllist lend
431145510Sdarrenr	;
432145510Sdarrenr
433255332Scylstart:	'{'				{ newlist = 1; fr = frc; added = 0; }
434145510Sdarrenr	;
435145510Sdarrenr
436255332Scylend:	'}'				{ nrules += added; }
437145510Sdarrenr	;
438145510Sdarrenr
439145510Sdarrenrlmore:	lanother			{ if (newlist == 1) {
440145510Sdarrenr						newlist = 0;
441145510Sdarrenr					  }
442145510Sdarrenr					  fr = addrule();
443145510Sdarrenr					  if (yycont != NULL)
444145510Sdarrenr						*yycont = 1;
445145510Sdarrenr					}
446145510Sdarrenr	;
447145510Sdarrenr
448145510Sdarrenrlanother:
449145510Sdarrenr	| ','
450145510Sdarrenr	;
451145510Sdarrenr
452145510Sdarrenrsetttl:	IPFY_TTL			{ setipftype(); }
453145510Sdarrenr	;
454145510Sdarrenr
455145510Sdarrenrttllist:
456145510Sdarrenr	YY_NUMBER	{ DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) }
457145510Sdarrenr	| ttllist lmore YY_NUMBER
458145510Sdarrenr			{ DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) }
459145510Sdarrenr	;
460145510Sdarrenr
461145510Sdarrenrproto:	| protox protocol		{ yyresetdict(); }
462145510Sdarrenr	;
463145510Sdarrenr
464145510Sdarrenrprotox:	IPFY_PROTO			{ setipftype();
465145510Sdarrenr					  fr = frc;
466145510Sdarrenr					  yysetdict(NULL); }
467145510Sdarrenr	;
468145510Sdarrenr
469145510Sdarrenrip:	srcdst flags icmp
470145510Sdarrenr	;
471145510Sdarrenr
472255332Scygroup:	| IPFY_GROUP groupname		{ DOALL(setgroup(&fr, $2); \
473255332Scy						fillgroup(fr););
474255332Scy					  free($2);
475255332Scy					}
476145510Sdarrenr	;
477145510Sdarrenr
478255332Scyhead:	| IPFY_HEAD groupname		{ DOALL(setgrhead(&fr, $2););
479255332Scy					  free($2);
480255332Scy					}
481145510Sdarrenr	;
482145510Sdarrenr
483255332Scygroupname:
484255332Scy	YY_STR				{ $$ = $1;
485255332Scy					  if (strlen($$) >= FR_GROUPLEN)
486255332Scy						$$[FR_GROUPLEN - 1] = '\0';
487255332Scy					}
488255332Scy	| YY_NUMBER			{ $$ = malloc(16);
489255332Scy					  sprintf($$, "%d", $1);
490255332Scy					}
491255332Scy	;
492255332Scy
493145510Sdarrenrsettagin:
494145510Sdarrenr	| IPFY_SETTAG '(' taginlist ')'
495145510Sdarrenr	;
496145510Sdarrenr
497145510Sdarrenrtaginlist:
498145510Sdarrenr	taginspec
499145510Sdarrenr	| taginlist ',' taginspec
500145510Sdarrenr	;
501145510Sdarrenr
502145510Sdarrenrtaginspec:
503145510Sdarrenr	logtag
504145510Sdarrenr	;
505145510Sdarrenr
506145510Sdarrenrnattag:	IPFY_NAT '=' YY_STR		{ DOALL(strncpy(fr->fr_nattag.ipt_tag,\
507145510Sdarrenr						$3, IPFTAG_LEN););
508145510Sdarrenr					  free($3); }
509145510Sdarrenr	| IPFY_NAT '=' YY_NUMBER	{ DOALL(sprintf(fr->fr_nattag.ipt_tag,\
510145510Sdarrenr						"%d", $3 & 0xffffffff);) }
511145510Sdarrenr	;
512145510Sdarrenr
513145510Sdarrenrlogtag:	IPFY_LOG '=' YY_NUMBER		{ DOALL(fr->fr_logtag = $3;) }
514145510Sdarrenr	;
515145510Sdarrenr
516145510Sdarrenrsettagout:
517145510Sdarrenr	| IPFY_SETTAG '(' tagoutlist ')'
518145510Sdarrenr	;
519145510Sdarrenr
520145510Sdarrenrtagoutlist:
521145510Sdarrenr	tagoutspec
522145510Sdarrenr	| tagoutlist ',' tagoutspec
523145510Sdarrenr	;
524145510Sdarrenr
525145510Sdarrenrtagoutspec:
526145510Sdarrenr	logtag
527145510Sdarrenr	| nattag
528145510Sdarrenr	;
529145510Sdarrenr
530145510Sdarrenrmatchtagin:
531145510Sdarrenr	| IPFY_MATCHTAG '(' tagoutlist ')'
532145510Sdarrenr	;
533145510Sdarrenr
534145510Sdarrenrmatchtagout:
535145510Sdarrenr	| IPFY_MATCHTAG '(' taginlist ')'
536145510Sdarrenr	;
537145510Sdarrenr
538145510Sdarrenrpps:	| IPFY_PPS YY_NUMBER		{ DOALL(fr->fr_pps = $2;) }
539145510Sdarrenr	;
540145510Sdarrenr
541145510Sdarrenrnew:	| savegroup file restoregroup
542145510Sdarrenr	;
543145510Sdarrenr
544255332Scyrulettl:
545255332Scy	| IPFY_RULETTL YY_NUMBER	{ DOALL(fr->fr_die = $2;) }
546255332Scy	;
547255332Scy
548255332Scycomment:
549255332Scy	| IPFY_COMMENT YY_STR		{ DOALL(fr->fr_comment = addname(&fr, \
550255332Scy						$2);) }
551255332Scy	;
552255332Scy
553145510Sdarrenrsavegroup:
554145510Sdarrenr	'{'
555145510Sdarrenr	;
556145510Sdarrenr
557145510Sdarrenrrestoregroup:
558145510Sdarrenr	'}'
559145510Sdarrenr	;
560145510Sdarrenr
561145510Sdarrenrlogopt:	log
562145510Sdarrenr	;
563145510Sdarrenr
564255332Scyquick:	IPFY_QUICK				{ fr->fr_flags |= FR_QUICK; }
565145510Sdarrenr	;
566145510Sdarrenr
567255332Scyon:	IPFY_ON onname				{ setifname(&fr, 0, $2.if1);
568255332Scy						  free($2.if1);
569255332Scy						  if ($2.if2 != NULL) {
570255332Scy							setifname(&fr, 1,
571255332Scy								  $2.if2);
572255332Scy							free($2.if2);
573255332Scy						  }
574255332Scy						}
575161357Sguido	| IPFY_ON lstart onlist lend
576255332Scy	| IPFY_ON onname IPFY_INVIA vianame	{ setifname(&fr, 0, $2.if1);
577255332Scy						  free($2.if1);
578255332Scy						  if ($2.if2 != NULL) {
579255332Scy							setifname(&fr, 1,
580255332Scy								  $2.if2);
581255332Scy							free($2.if2);
582255332Scy						  }
583255332Scy						}
584255332Scy	| IPFY_ON onname IPFY_OUTVIA vianame	{ setifname(&fr, 0, $2.if1);
585255332Scy						  free($2.if1);
586255332Scy						  if ($2.if2 != NULL) {
587255332Scy							setifname(&fr, 1,
588255332Scy								  $2.if2);
589255332Scy							free($2.if2);
590255332Scy						  }
591255332Scy						}
592145510Sdarrenr	;
593145510Sdarrenr
594255332Scyonlist:	onname			{ DOREM(setifname(&fr, 0, $1.if1);	   \
595255332Scy					if ($1.if2 != NULL)		   \
596255332Scy						setifname(&fr, 1, $1.if2); \
597255332Scy					)
598255332Scy				  free($1.if1);
599255332Scy				  if ($1.if2 != NULL)
600255332Scy					free($1.if2);
601255332Scy				}
602255332Scy	| onlist lmore onname	{ DOREM(setifname(&fr, 0, $3.if1);	   \
603255332Scy					if ($3.if2 != NULL)		   \
604255332Scy						setifname(&fr, 1, $3.if2); \
605255332Scy					)
606255332Scy				  free($3.if1);
607255332Scy				  if ($3.if2 != NULL)
608255332Scy					free($3.if2);
609255332Scy				}
610161357Sguido	;
611161357Sguido
612255332Scyonname:	interfacename		{ $$.if1 = $1;
613255332Scy				  $$.if2 = NULL;
614255332Scy				}
615145510Sdarrenr	| interfacename ',' interfacename
616255332Scy				{ $$.if1 = $1;
617255332Scy				  $$.if2 = $3;
618255332Scy				}
619145510Sdarrenr	;
620145510Sdarrenr
621145510Sdarrenrvianame:
622255332Scy	name			{ setifname(&fr, 2, $1);
623255332Scy				  free($1);
624255332Scy				}
625255332Scy	| name ',' name		{ setifname(&fr, 2, $1);
626255332Scy				  free($1);
627255332Scy				  setifname(&fr, 3, $3);
628255332Scy				  free($3);
629255332Scy				}
630145510Sdarrenr	;
631145510Sdarrenr
632145510Sdarrenrdup:	IPFY_DUPTO name
633255332Scy	{ int idx = addname(&fr, $2);
634255332Scy	  fr->fr_dif.fd_name = idx;
635145510Sdarrenr	  free($2);
636145510Sdarrenr	}
637255332Scy	| IPFY_DUPTO IPFY_DSTLIST '/' name
638255332Scy	{ int idx = addname(&fr, $4);
639255332Scy	  fr->fr_dif.fd_name = idx;
640255332Scy	  fr->fr_dif.fd_type = FRD_DSTLIST;
641255332Scy	  free($4);
642255332Scy	}
643145510Sdarrenr	| IPFY_DUPTO name duptoseparator hostname
644255332Scy	{ int idx = addname(&fr, $2);
645255332Scy	  fr->fr_dif.fd_name = idx;
646255332Scy	  fr->fr_dif.fd_ptr = (void *)-1;
647255332Scy	  fr->fr_dif.fd_ip6 = $4.adr;
648255332Scy	  if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC)
649255332Scy		fr->fr_family = $4.f;
650145510Sdarrenr	  yyexpectaddr = 0;
651145510Sdarrenr	  free($2);
652145510Sdarrenr	}
653145510Sdarrenr	;
654145510Sdarrenr
655145510Sdarrenrduptoseparator:
656145510Sdarrenr	':'	{ yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); }
657145510Sdarrenr	;
658145510Sdarrenr
659145510Sdarrenrfroute:	IPFY_FROUTE			{ fr->fr_flags |= FR_FASTROUTE; }
660145510Sdarrenr	;
661145510Sdarrenr
662145510Sdarrenrproute:	routeto name
663255332Scy	{ int idx = addname(&fr, $2);
664255332Scy	  fr->fr_tif.fd_name = idx;
665145510Sdarrenr	  free($2);
666145510Sdarrenr	}
667255332Scy	| routeto IPFY_DSTLIST '/' name
668255332Scy	{ int idx = addname(&fr, $4);
669255332Scy	  fr->fr_tif.fd_name = idx;
670255332Scy	  fr->fr_tif.fd_type = FRD_DSTLIST;
671255332Scy	  free($4);
672255332Scy	}
673145510Sdarrenr	| routeto name duptoseparator hostname
674255332Scy	{ int idx = addname(&fr, $2);
675255332Scy	  fr->fr_tif.fd_name = idx;
676255332Scy	  fr->fr_tif.fd_ptr = (void *)-1;
677255332Scy	  fr->fr_tif.fd_ip6 = $4.adr;
678255332Scy	  if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC)
679255332Scy		fr->fr_family = $4.f;
680145510Sdarrenr	  yyexpectaddr = 0;
681145510Sdarrenr	  free($2);
682145510Sdarrenr	}
683145510Sdarrenr	;
684145510Sdarrenr
685145510Sdarrenrrouteto:
686145510Sdarrenr	IPFY_TO
687145510Sdarrenr	| IPFY_ROUTETO
688145510Sdarrenr	;
689145510Sdarrenr
690145510Sdarrenrreplyto:
691145510Sdarrenr	IPFY_REPLY_TO name
692255332Scy	{ int idx = addname(&fr, $2);
693255332Scy	  fr->fr_rif.fd_name = idx;
694145510Sdarrenr	  free($2);
695145510Sdarrenr	}
696255332Scy	| IPFY_REPLY_TO IPFY_DSTLIST '/' name
697255332Scy	{ fr->fr_rif.fd_name = addname(&fr, $4);
698255332Scy	  fr->fr_rif.fd_type = FRD_DSTLIST;
699255332Scy	  free($4);
700255332Scy	}
701145510Sdarrenr	| IPFY_REPLY_TO name duptoseparator hostname
702255332Scy	{ int idx = addname(&fr, $2);
703255332Scy	  fr->fr_rif.fd_name = idx;
704255332Scy	  fr->fr_rif.fd_ptr = (void *)-1;
705255332Scy	  fr->fr_rif.fd_ip6 = $4.adr;
706255332Scy	  if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC)
707255332Scy		fr->fr_family = $4.f;
708145510Sdarrenr	  free($2);
709145510Sdarrenr	}
710145510Sdarrenr	;
711145510Sdarrenr
712145510Sdarrenrlogoptions:
713145510Sdarrenr	logoption
714145510Sdarrenr	| logoptions logoption
715145510Sdarrenr	;
716145510Sdarrenr
717145510Sdarrenrlogoption:
718145510Sdarrenr	IPFY_BODY			{ fr->fr_flags |= FR_LOGBODY; }
719145510Sdarrenr	| IPFY_FIRST			{ fr->fr_flags |= FR_LOGFIRST; }
720145510Sdarrenr	| IPFY_ORBLOCK			{ fr->fr_flags |= FR_LOGORBLOCK; }
721145510Sdarrenr	| level loglevel		{ unsetsyslog(); }
722145510Sdarrenr	;
723145510Sdarrenr
724145510Sdarrenrreturncode:
725145510Sdarrenr	starticmpcode icmpcode ')'	{ fr->fr_icode = $2; yyresetdict(); }
726145510Sdarrenr	;
727145510Sdarrenr
728145510Sdarrenrstarticmpcode:
729145510Sdarrenr	'('				{ yysetdict(icmpcodewords); }
730145510Sdarrenr	;
731145510Sdarrenr
732145510Sdarrenrsrcdst:	| IPFY_ALL
733145510Sdarrenr	| fromto
734145510Sdarrenr	;
735145510Sdarrenr
736145510Sdarrenrprotocol:
737255332Scy	YY_NUMBER		{ DOALL(fr->fr_proto = $1; \
738255332Scy					fr->fr_mproto = 0xff;)
739255332Scy				}
740145510Sdarrenr	| YY_STR		{ if (!strcmp($1, "tcp-udp")) {
741255332Scy					DOALL(fr->fr_flx |= FI_TCPUDP; \
742145510Sdarrenr					      fr->fr_mflx |= FI_TCPUDP;)
743145510Sdarrenr				  } else {
744145510Sdarrenr					int p = getproto($1);
745145510Sdarrenr					if (p == -1)
746145510Sdarrenr						yyerror("protocol unknown");
747255332Scy					DOALL(fr->fr_proto = p; \
748145510Sdarrenr						fr->fr_mproto = 0xff;)
749145510Sdarrenr				  }
750145510Sdarrenr				  free($1);
751255332Scy				}
752145510Sdarrenr	| YY_STR nextstring YY_STR
753145510Sdarrenr				{ if (!strcmp($1, "tcp") &&
754145510Sdarrenr				      !strcmp($3, "udp")) {
755145510Sdarrenr					DOREM(fr->fr_flx |= FI_TCPUDP; \
756145510Sdarrenr					      fr->fr_mflx |= FI_TCPUDP;)
757255332Scy				  } else {
758145510Sdarrenr					YYERROR;
759255332Scy				  }
760145510Sdarrenr				  free($1);
761145510Sdarrenr				  free($3);
762145510Sdarrenr				}
763145510Sdarrenr	;
764145510Sdarrenr
765145510Sdarrenrnextstring:
766145510Sdarrenr	'/'			{ yysetdict(NULL); }
767145510Sdarrenr	;
768145510Sdarrenr
769145510Sdarrenrfromto:	from srcobject to dstobject	{ yyexpectaddr = 0; yycont = NULL; }
770145510Sdarrenr	| to dstobject			{ yyexpectaddr = 0; yycont = NULL; }
771145510Sdarrenr	| from srcobject		{ yyexpectaddr = 0; yycont = NULL; }
772145510Sdarrenr	;
773145510Sdarrenr
774145510Sdarrenrfrom:	IPFY_FROM			{ setipftype();
775145510Sdarrenr					  if (fr == NULL)
776145510Sdarrenr						fr = frc;
777145510Sdarrenr					  yyexpectaddr = 1;
778145510Sdarrenr					  if (yydebug)
779145510Sdarrenr						printf("set yyexpectaddr\n");
780145510Sdarrenr					  yycont = &yyexpectaddr;
781145510Sdarrenr					  yysetdict(addrwords);
782145510Sdarrenr					  resetaddr(); }
783145510Sdarrenr	;
784145510Sdarrenr
785145510Sdarrenrto:	IPFY_TO				{ if (fr == NULL)
786145510Sdarrenr						fr = frc;
787145510Sdarrenr					  yyexpectaddr = 1;
788145510Sdarrenr					  if (yydebug)
789145510Sdarrenr						printf("set yyexpectaddr\n");
790145510Sdarrenr					  yycont = &yyexpectaddr;
791145510Sdarrenr					  yysetdict(addrwords);
792255332Scy					  resetaddr();
793255332Scy					}
794145510Sdarrenr	;
795145510Sdarrenr
796145510Sdarrenrwith:	| andwith withlist
797145510Sdarrenr	;
798145510Sdarrenr
799145510Sdarrenrandwith:
800145510Sdarrenr	IPFY_WITH			{ nowith = 0; setipftype(); }
801145510Sdarrenr	| IPFY_AND			{ nowith = 0; setipftype(); }
802145510Sdarrenr	;
803145510Sdarrenr
804255332Scyflags:	| startflags flagset
805145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
806145510Sdarrenr	| startflags flagset '/' flagset
807145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
808145510Sdarrenr	| startflags '/' flagset
809145510Sdarrenr		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
810145510Sdarrenr	| startflags YY_NUMBER
811145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
812145510Sdarrenr	| startflags '/' YY_NUMBER
813145510Sdarrenr		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
814145510Sdarrenr	| startflags YY_NUMBER '/' YY_NUMBER
815145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
816145510Sdarrenr	| startflags flagset '/' YY_NUMBER
817145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
818145510Sdarrenr	| startflags YY_NUMBER '/' flagset
819145510Sdarrenr		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
820145510Sdarrenr	;
821145510Sdarrenr
822145510Sdarrenrstartflags:
823145510Sdarrenr	IPFY_FLAGS	{ if (frc->fr_type != FR_T_IPF)
824145510Sdarrenr				yyerror("flags with non-ipf type rule");
825145510Sdarrenr			  if (frc->fr_proto != IPPROTO_TCP)
826145510Sdarrenr				yyerror("flags with non-TCP rule");
827145510Sdarrenr			}
828145510Sdarrenr	;
829145510Sdarrenr
830145510Sdarrenrflagset:
831145510Sdarrenr	YY_STR				{ $$ = tcpflags($1); free($1); }
832145510Sdarrenr	| YY_HEX			{ $$ = $1; }
833145510Sdarrenr	;
834145510Sdarrenr
835145510Sdarrenrsrcobject:
836145510Sdarrenr	{ yyresetdict(); } fromport
837145510Sdarrenr	| srcaddr srcport
838145510Sdarrenr	| '!' srcaddr srcport
839145510Sdarrenr		{ DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
840145510Sdarrenr	;
841145510Sdarrenr
842145510Sdarrenrsrcaddr:
843255332Scy	addr	{ build_srcaddr_af(fr, &$1); }
844145510Sdarrenr	| lstart srcaddrlist lend
845145510Sdarrenr	;
846145510Sdarrenr
847145510Sdarrenrsrcaddrlist:
848255332Scy	addr	{ build_srcaddr_af(fr, &$1); }
849145510Sdarrenr	| srcaddrlist lmore addr
850255332Scy		{ build_srcaddr_af(fr, &$3); }
851145510Sdarrenr	;
852145510Sdarrenr
853145510Sdarrenrsrcport:
854145510Sdarrenr	| portcomp
855145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
856145510Sdarrenr	| portrange
857145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
858145510Sdarrenr			fr->fr_stop = $1.p2;) }
859145510Sdarrenr	| porteq lstart srcportlist lend
860145510Sdarrenr		{ yyresetdict(); }
861145510Sdarrenr	;
862145510Sdarrenr
863145510Sdarrenrfromport:
864145510Sdarrenr	portcomp
865145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
866145510Sdarrenr	| portrange
867145510Sdarrenr		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
868145510Sdarrenr			fr->fr_stop = $1.p2;) }
869145510Sdarrenr	| porteq lstart srcportlist lend
870145510Sdarrenr		{ yyresetdict(); }
871145510Sdarrenr	;
872145510Sdarrenr
873145510Sdarrenrsrcportlist:
874145510Sdarrenr	portnum		{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) }
875255332Scy	| portnum ':' portnum
876172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \
877172776Sdarrenr				fr->fr_stop = $3;) }
878255332Scy	| portnum YY_RANGE_IN portnum
879172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \
880172776Sdarrenr				fr->fr_stop = $3;) }
881145510Sdarrenr	| srcportlist lmore portnum
882145510Sdarrenr			{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) }
883172776Sdarrenr	| srcportlist lmore portnum ':' portnum
884172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $3; \
885172776Sdarrenr				fr->fr_stop = $5;) }
886172776Sdarrenr	| srcportlist lmore portnum YY_RANGE_IN portnum
887172776Sdarrenr			{ DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $3; \
888172776Sdarrenr				fr->fr_stop = $5;) }
889145510Sdarrenr	;
890145510Sdarrenr
891145510Sdarrenrdstobject:
892145510Sdarrenr	{ yyresetdict(); } toport
893145510Sdarrenr	| dstaddr dstport
894145510Sdarrenr	| '!' dstaddr dstport
895145510Sdarrenr			{ DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
896145510Sdarrenr	;
897145510Sdarrenr
898145510Sdarrenrdstaddr:
899255332Scy	addr	{ if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) &&
900255332Scy		      ($1.f != frc->fr_family))
901255332Scy			yyerror("1.src/dst address family mismatch");
902255332Scy		  build_dstaddr_af(fr, &$1);
903145510Sdarrenr		}
904145510Sdarrenr	| lstart dstaddrlist lend
905145510Sdarrenr	;
906145510Sdarrenr
907145510Sdarrenrdstaddrlist:
908255332Scy	addr	{ if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) &&
909255332Scy		      ($1.f != frc->fr_family))
910255332Scy			yyerror("2.src/dst address family mismatch");
911255332Scy		  build_dstaddr_af(fr, &$1);
912145510Sdarrenr		}
913145510Sdarrenr	| dstaddrlist lmore addr
914255332Scy		{ if (($3.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) &&
915255332Scy		      ($3.f != frc->fr_family))
916255332Scy			yyerror("3.src/dst address family mismatch");
917255332Scy		  build_dstaddr_af(fr, &$3);
918145510Sdarrenr		}
919145510Sdarrenr	;
920145510Sdarrenr
921145510Sdarrenr
922145510Sdarrenrdstport:
923145510Sdarrenr	| portcomp
924145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
925145510Sdarrenr	| portrange
926145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
927145510Sdarrenr			fr->fr_dtop = $1.p2;) }
928145510Sdarrenr	| porteq lstart dstportlist lend
929145510Sdarrenr		{ yyresetdict(); }
930145510Sdarrenr	;
931145510Sdarrenr
932145510Sdarrenrtoport:
933145510Sdarrenr	portcomp
934145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
935145510Sdarrenr	| portrange
936145510Sdarrenr		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
937145510Sdarrenr			fr->fr_dtop = $1.p2;) }
938145510Sdarrenr	| porteq lstart dstportlist lend
939145510Sdarrenr		{ yyresetdict(); }
940145510Sdarrenr	;
941145510Sdarrenr
942145510Sdarrenrdstportlist:
943145510Sdarrenr	portnum		{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) }
944255332Scy	| portnum ':' portnum
945172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \
946172776Sdarrenr				fr->fr_dtop = $3;) }
947255332Scy	| portnum YY_RANGE_IN portnum
948172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \
949172776Sdarrenr				fr->fr_dtop = $3;) }
950145510Sdarrenr	| dstportlist lmore portnum
951145510Sdarrenr			{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) }
952172776Sdarrenr	| dstportlist lmore portnum ':' portnum
953172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $3; \
954172776Sdarrenr				fr->fr_dtop = $5;) }
955172776Sdarrenr	| dstportlist lmore portnum YY_RANGE_IN portnum
956172776Sdarrenr			{ DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $3; \
957172776Sdarrenr				fr->fr_dtop = $5;) }
958145510Sdarrenr	;
959145510Sdarrenr
960145510Sdarrenraddr:	pool '/' YY_NUMBER		{ pooled = 1;
961255332Scy					  yyexpectaddr = 0;
962255332Scy					  $$.type = FRI_LOOKUP;
963255332Scy					  $$.v = 0;
964255332Scy					  $$.ifpos = -1;
965255332Scy					  $$.f = AF_UNSPEC;
966145510Sdarrenr					  $$.a.iplookuptype = IPLT_POOL;
967170268Sdarrenr					  $$.a.iplookupsubtype = 0;
968145510Sdarrenr					  $$.a.iplookupnum = $3; }
969170268Sdarrenr	| pool '/' YY_STR		{ pooled = 1;
970255332Scy					  $$.ifpos = -1;
971255332Scy					  $$.f = AF_UNSPEC;
972255332Scy					  $$.type = FRI_LOOKUP;
973170268Sdarrenr					  $$.a.iplookuptype = IPLT_POOL;
974170268Sdarrenr					  $$.a.iplookupsubtype = 1;
975255332Scy					  $$.a.iplookupname = addname(&fr, $3);
976170268Sdarrenr					}
977255332Scy	| pool '=' '('			{ yyexpectaddr = 1;
978255332Scy					  pooled = 1;
979255332Scy					}
980255332Scy			poollist ')'	{ yyexpectaddr = 0;
981255332Scy					  $$.v = 0;
982255332Scy					  $$.ifpos = -1;
983255332Scy					  $$.f = AF_UNSPEC;
984255332Scy					  $$.type = FRI_LOOKUP;
985145510Sdarrenr					  $$.a.iplookuptype = IPLT_POOL;
986170268Sdarrenr					  $$.a.iplookupsubtype = 0;
987255332Scy					  $$.a.iplookupnum = makepool($5);
988255332Scy					}
989145510Sdarrenr	| hash '/' YY_NUMBER		{ hashed = 1;
990255332Scy					  yyexpectaddr = 0;
991255332Scy					  $$.v = 0;
992255332Scy					  $$.ifpos = -1;
993255332Scy					  $$.f = AF_UNSPEC;
994255332Scy					  $$.type = FRI_LOOKUP;
995145510Sdarrenr					  $$.a.iplookuptype = IPLT_HASH;
996170268Sdarrenr					  $$.a.iplookupsubtype = 0;
997255332Scy					  $$.a.iplookupnum = $3;
998255332Scy					}
999255332Scy	| hash '/' YY_STR		{ hashed = 1;
1000255332Scy					  $$.type = FRI_LOOKUP;
1001255332Scy					  $$.v = 0;
1002255332Scy					  $$.ifpos = -1;
1003255332Scy					  $$.f = AF_UNSPEC;
1004170268Sdarrenr					  $$.a.iplookuptype = IPLT_HASH;
1005170268Sdarrenr					  $$.a.iplookupsubtype = 1;
1006255332Scy					  $$.a.iplookupname = addname(&fr, $3);
1007170268Sdarrenr					}
1008255332Scy	| hash '=' '(' 			{ hashed = 1;
1009255332Scy					  yyexpectaddr = 1;
1010255332Scy					}
1011255332Scy			addrlist ')'	{ yyexpectaddr = 0;
1012255332Scy					  $$.v = 0;
1013255332Scy					  $$.ifpos = -1;
1014255332Scy					  $$.f = AF_UNSPEC;
1015255332Scy					  $$.type = FRI_LOOKUP;
1016145510Sdarrenr					  $$.a.iplookuptype = IPLT_HASH;
1017170268Sdarrenr					  $$.a.iplookupsubtype = 0;
1018255332Scy					  $$.a.iplookupnum = makehash($5);
1019255332Scy					}
1020255332Scy	| ipaddr			{ $$ = $1;
1021145510Sdarrenr					  yyexpectaddr = 0; }
1022145510Sdarrenr	;
1023145510Sdarrenr
1024271974Scyipaddr:	IPFY_ANY			{ memset(&($$), 0, sizeof($$));
1025255332Scy					  $$.type = FRI_NORMAL;
1026255332Scy					  $$.ifpos = -1;
1027255332Scy					  yyexpectaddr = 0;
1028255332Scy					}
1029271974Scy	| hostname			{ memset(&($$), 0, sizeof($$));
1030271974Scy					  $$.a = $1.adr;
1031255332Scy					  $$.f = $1.f;
1032255332Scy					  if ($1.f == AF_INET6)
1033255332Scy						  fill6bits(128, $$.m.i6);
1034255332Scy					  else if ($1.f == AF_INET)
1035255332Scy						  fill6bits(32, $$.m.i6);
1036255332Scy					  $$.v = ftov($1.f);
1037255332Scy					  $$.ifpos = dynamic;
1038255332Scy					  $$.type = FRI_NORMAL;
1039255332Scy					}
1040255332Scy	| hostname			{ yyresetdict(); }
1041255332Scy		maskspace		{ yysetdict(maskwords);
1042255332Scy					  yyexpectaddr = 2; }
1043271974Scy		ipmask			{ memset(&($$), 0, sizeof($$));
1044271974Scy					  ntomask($1.f, $5, $$.m.i6);
1045255332Scy					  $$.a = $1.adr;
1046255332Scy					  $$.a.i6[0] &= $$.m.i6[0];
1047255332Scy					  $$.a.i6[1] &= $$.m.i6[1];
1048255332Scy					  $$.a.i6[2] &= $$.m.i6[2];
1049255332Scy					  $$.a.i6[3] &= $$.m.i6[3];
1050255332Scy					  $$.f = $1.f;
1051255332Scy					  $$.v = ftov($1.f);
1052255332Scy					  $$.type = ifpflag;
1053255332Scy					  $$.ifpos = dynamic;
1054255332Scy					  if (ifpflag != 0 && $$.v == 0) {
1055255332Scy						if (frc->fr_family == AF_INET6){
1056255332Scy							$$.v = 6;
1057255332Scy							$$.f = AF_INET6;
1058255332Scy						} else {
1059255332Scy							$$.v = 4;
1060255332Scy							$$.f = AF_INET;
1061255332Scy						}
1062255332Scy					  }
1063145510Sdarrenr					  yyresetdict();
1064255332Scy					  yyexpectaddr = 0;
1065255332Scy					}
1066271974Scy	| '(' YY_STR ')'		{ memset(&($$), 0, sizeof($$));
1067271974Scy					  $$.type = FRI_DYNAMIC;
1068255332Scy					  ifpflag = FRI_DYNAMIC;
1069255332Scy					  $$.ifpos = addname(&fr, $2);
1070255332Scy					  $$.lif = 0;
1071255332Scy					}
1072255332Scy	| '(' YY_STR ')' '/'
1073255332Scy	  { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); }
1074255332Scy	  maskopts
1075271974Scy					{ memset(&($$), 0, sizeof($$));
1076271974Scy					  $$.type = ifpflag;
1077255332Scy					  $$.ifpos = addname(&fr, $2);
1078255332Scy					  $$.lif = 0;
1079255332Scy					  if (frc->fr_family == AF_UNSPEC)
1080255332Scy						frc->fr_family = AF_INET;
1081255332Scy					  if (ifpflag == FRI_DYNAMIC) {
1082255332Scy						ntomask(frc->fr_family,
1083255332Scy							$6, $$.m.i6);
1084255332Scy					  }
1085145510Sdarrenr					  yyresetdict();
1086255332Scy					  yyexpectaddr = 0;
1087255332Scy					}
1088255332Scy	| '(' YY_STR ':' YY_NUMBER ')' '/'
1089255332Scy	  { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); }
1090255332Scy	  maskopts
1091271974Scy					{ memset(&($$), 0, sizeof($$));
1092271974Scy					  $$.type = ifpflag;
1093255332Scy					  $$.ifpos = addname(&fr, $2);
1094255332Scy					  $$.lif = $4;
1095255332Scy					  if (frc->fr_family == AF_UNSPEC)
1096255332Scy						frc->fr_family = AF_INET;
1097255332Scy					  if (ifpflag == FRI_DYNAMIC) {
1098255332Scy						ntomask(frc->fr_family,
1099255332Scy							$8, $$.m.i6);
1100255332Scy					  }
1101145510Sdarrenr					  yyresetdict();
1102255332Scy					  yyexpectaddr = 0;
1103255332Scy					}
1104145510Sdarrenr	;
1105255332Scy
1106145510Sdarrenrmaskspace:
1107145510Sdarrenr	'/'
1108145510Sdarrenr	| IPFY_MASK
1109145510Sdarrenr	;
1110145510Sdarrenr
1111255332Scyipmask:	ipv4				{ $$ = count4bits($1.s_addr); }
1112255332Scy	| YY_HEX			{ $$ = count4bits(htonl($1)); }
1113255332Scy	| YY_NUMBER			{ $$ = $1; }
1114255332Scy	| YY_IPV6			{ $$ = count6bits($1.i6); }
1115255332Scy	| maskopts			{ $$ = $1; }
1116255332Scy	;
1117255332Scy
1118255332Scymaskopts:
1119255332Scy	IPFY_BROADCAST			{ if (ifpflag == FRI_DYNAMIC) {
1120145510Sdarrenr						ifpflag = FRI_BROADCAST;
1121255332Scy					  } else {
1122145510Sdarrenr						YYERROR;
1123255332Scy					  }
1124255332Scy					  $$ = 0;
1125145510Sdarrenr					}
1126145510Sdarrenr	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
1127145510Sdarrenr						ifpflag = FRI_NETWORK;
1128255332Scy					  } else {
1129145510Sdarrenr						YYERROR;
1130255332Scy					  }
1131255332Scy					  $$ = 0;
1132145510Sdarrenr					}
1133145510Sdarrenr	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
1134145510Sdarrenr						ifpflag = FRI_NETMASKED;
1135255332Scy					  } else {
1136145510Sdarrenr						YYERROR;
1137255332Scy					  }
1138255332Scy					  $$ = 0;
1139145510Sdarrenr					}
1140145510Sdarrenr	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
1141145510Sdarrenr						ifpflag = FRI_PEERADDR;
1142255332Scy					  } else {
1143145510Sdarrenr						YYERROR;
1144255332Scy					  }
1145255332Scy					  $$ = 0;
1146145510Sdarrenr					}
1147255332Scy	| YY_NUMBER			{ $$ = $1; }
1148145510Sdarrenr	;
1149145510Sdarrenr
1150255332Scyhostname:
1151271974Scy	ipv4				{ memset(&($$), 0, sizeof($$));
1152271974Scy					  $$.adr.in4 = $1;
1153255332Scy					  if (frc->fr_family == AF_INET6)
1154145510Sdarrenr						YYERROR;
1155255332Scy					  $$.f = AF_INET;
1156255332Scy					  yyexpectaddr = 2;
1157145510Sdarrenr					}
1158271974Scy	| YY_NUMBER			{ memset(&($$), 0, sizeof($$));
1159271974Scy					  if (frc->fr_family == AF_INET6)
1160145510Sdarrenr						YYERROR;
1161255332Scy					  $$.adr.in4_addr = $1;
1162255332Scy					  $$.f = AF_INET;
1163255332Scy					  yyexpectaddr = 2;
1164145510Sdarrenr					}
1165271974Scy	| YY_HEX			{ memset(&($$), 0, sizeof($$));
1166271974Scy					  if (frc->fr_family == AF_INET6)
1167145510Sdarrenr						YYERROR;
1168255332Scy					  $$.adr.in4_addr = $1;
1169255332Scy					  $$.f = AF_INET;
1170255332Scy					  yyexpectaddr = 2;
1171145510Sdarrenr					}
1172271974Scy	| YY_STR			{ memset(&($$), 0, sizeof($$));
1173271974Scy					  if (lookuphost($1, &$$.adr) == 0)
1174255332Scy						  $$.f = AF_INET;
1175255332Scy					  free($1);
1176255332Scy					  yyexpectaddr = 2;
1177255332Scy					}
1178271974Scy	| YY_IPV6			{ memset(&($$), 0, sizeof($$));
1179271974Scy					  if (frc->fr_family == AF_INET)
1180145510Sdarrenr						YYERROR;
1181255332Scy					  $$.adr = $1;
1182255332Scy					  $$.f = AF_INET6;
1183255332Scy					  yyexpectaddr = 2;
1184145510Sdarrenr					}
1185145510Sdarrenr	;
1186145510Sdarrenr
1187145510Sdarrenraddrlist:
1188145510Sdarrenr	ipaddr		{ $$ = newalist(NULL);
1189255332Scy			  $$->al_family = $1.f;
1190255332Scy			  $$->al_i6addr = $1.a;
1191255332Scy			  $$->al_i6mask = $1.m;
1192255332Scy			}
1193255332Scy	| ipaddr ',' { yyexpectaddr = 1; } addrlist
1194255332Scy			{ $$ = newalist($4);
1195255332Scy			  $$->al_family = $1.f;
1196255332Scy			  $$->al_i6addr = $1.a;
1197255332Scy			  $$->al_i6mask = $1.m;
1198255332Scy			}
1199145510Sdarrenr	;
1200145510Sdarrenr
1201145510Sdarrenrpool:	IPFY_POOL	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1202145510Sdarrenr	;
1203145510Sdarrenr
1204145510Sdarrenrhash:	IPFY_HASH	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1205145510Sdarrenr	;
1206145510Sdarrenr
1207145510Sdarrenrpoollist:
1208145510Sdarrenr	ipaddr		{ $$ = newalist(NULL);
1209255332Scy			  $$->al_family = $1.f;
1210255332Scy			  $$->al_i6addr = $1.a;
1211255332Scy			  $$->al_i6mask = $1.m;
1212255332Scy			}
1213145510Sdarrenr	| '!' ipaddr	{ $$ = newalist(NULL);
1214145510Sdarrenr			  $$->al_not = 1;
1215255332Scy			  $$->al_family = $2.f;
1216255332Scy			  $$->al_i6addr = $2.a;
1217255332Scy			  $$->al_i6mask = $2.m;
1218255332Scy			}
1219145510Sdarrenr	| poollist ',' ipaddr
1220145510Sdarrenr			{ $$ = newalist($1);
1221255332Scy			  $$->al_family = $3.f;
1222255332Scy			  $$->al_i6addr = $3.a;
1223255332Scy			  $$->al_i6mask = $3.m;
1224255332Scy			}
1225145510Sdarrenr	| poollist ',' '!' ipaddr
1226145510Sdarrenr			{ $$ = newalist($1);
1227145510Sdarrenr			  $$->al_not = 1;
1228255332Scy			  $$->al_family = $4.f;
1229255332Scy			  $$->al_i6addr = $4.a;
1230255332Scy			  $$->al_i6mask = $4.m;
1231255332Scy			}
1232145510Sdarrenr	;
1233145510Sdarrenr
1234145510Sdarrenrport:	IPFY_PORT			{ yyexpectaddr = 0;
1235145510Sdarrenr					  yycont = NULL;
1236255332Scy					  if (frc->fr_proto != 0 &&
1237255332Scy					      frc->fr_proto != IPPROTO_UDP &&
1238255332Scy					      frc->fr_proto != IPPROTO_TCP)
1239255332Scy						yyerror("port use incorrect");
1240145510Sdarrenr					}
1241145510Sdarrenr	;
1242145510Sdarrenr
1243145510Sdarrenrportc:	port compare			{ $$ = $2;
1244255332Scy					  yysetdict(NULL);
1245255332Scy					}
1246145510Sdarrenr	| porteq			{ $$ = $1; }
1247145510Sdarrenr	;
1248145510Sdarrenr
1249145510Sdarrenrporteq:	port '='			{ $$ = FR_EQUAL;
1250255332Scy					  yysetdict(NULL);
1251255332Scy					}
1252145510Sdarrenr	;
1253145510Sdarrenr
1254145510Sdarrenrportr:	IPFY_PORT			{ yyexpectaddr = 0;
1255145510Sdarrenr					  yycont = NULL;
1256255332Scy					  yysetdict(NULL);
1257255332Scy					}
1258145510Sdarrenr	;
1259145510Sdarrenr
1260145510Sdarrenrportcomp:
1261145510Sdarrenr	portc portnum			{ $$.pc = $1;
1262145510Sdarrenr					  $$.p1 = $2;
1263255332Scy					  yyresetdict();
1264255332Scy					}
1265145510Sdarrenr	;
1266145510Sdarrenr
1267145510Sdarrenrportrange:
1268145510Sdarrenr	portr portnum range portnum	{ $$.p1 = $2;
1269145510Sdarrenr					  $$.pc = $3;
1270145510Sdarrenr					  $$.p2 = $4;
1271255332Scy					  yyresetdict();
1272255332Scy					}
1273145510Sdarrenr	;
1274145510Sdarrenr
1275145510Sdarrenricmp:	| itype icode
1276145510Sdarrenr	;
1277145510Sdarrenr
1278145510Sdarrenritype:	seticmptype icmptype
1279145510Sdarrenr	{ DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00););
1280145510Sdarrenr	  yyresetdict();
1281145510Sdarrenr	}
1282145510Sdarrenr	| seticmptype lstart typelist lend	{ yyresetdict(); }
1283145510Sdarrenr	;
1284145510Sdarrenr
1285145510Sdarrenrseticmptype:
1286255332Scy	IPFY_ICMPTYPE		{ if (frc->fr_family == AF_UNSPEC)
1287255332Scy					frc->fr_family = AF_INET;
1288255332Scy				  if (frc->fr_family == AF_INET &&
1289255332Scy				      frc->fr_type == FR_T_IPF &&
1290255332Scy				      frc->fr_proto != IPPROTO_ICMP) {
1291255332Scy					yyerror("proto not icmp");
1292255332Scy				  }
1293255332Scy				  if (frc->fr_family == AF_INET6 &&
1294255332Scy				      frc->fr_type == FR_T_IPF &&
1295255332Scy				      frc->fr_proto != IPPROTO_ICMPV6) {
1296255332Scy					yyerror("proto not ipv6-icmp");
1297255332Scy				  }
1298255332Scy				  setipftype();
1299255332Scy				  DOALL(if (fr->fr_family == AF_INET) { \
1300255332Scy						fr->fr_ip.fi_v = 4; \
1301255332Scy						fr->fr_mip.fi_v = 0xf; \
1302255332Scy					}
1303255332Scy					if (fr->fr_family == AF_INET6) { \
1304255332Scy						fr->fr_ip.fi_v = 6; \
1305255332Scy						fr->fr_mip.fi_v = 0xf; \
1306255332Scy					}
1307255332Scy				  )
1308255332Scy				  yysetdict(NULL);
1309255332Scy				}
1310145510Sdarrenr	;
1311145510Sdarrenr
1312145510Sdarrenricode:	| seticmpcode icmpcode
1313145510Sdarrenr	{ DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff););
1314145510Sdarrenr	  yyresetdict();
1315145510Sdarrenr	}
1316145510Sdarrenr	| seticmpcode lstart codelist lend	{ yyresetdict(); }
1317145510Sdarrenr	;
1318145510Sdarrenr
1319145510Sdarrenrseticmpcode:
1320145510Sdarrenr	IPFY_ICMPCODE				{ yysetdict(icmpcodewords); }
1321145510Sdarrenr	;
1322145510Sdarrenr
1323145510Sdarrenrtypelist:
1324145510Sdarrenr	icmptype
1325145510Sdarrenr	{ DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) }
1326145510Sdarrenr	| typelist lmore icmptype
1327145510Sdarrenr	{ DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) }
1328145510Sdarrenr	;
1329145510Sdarrenr
1330145510Sdarrenrcodelist:
1331145510Sdarrenr	icmpcode
1332145510Sdarrenr	{ DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) }
1333145510Sdarrenr	| codelist lmore icmpcode
1334161357Sguido	{ DOREM(fr->fr_icmp &= htons(0xff00); fr->fr_icmp |= htons($3); \
1335161357Sguido		fr->fr_icmpm |= htons(0xff);) }
1336145510Sdarrenr	;
1337145510Sdarrenr
1338145510Sdarrenrage:	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1339145510Sdarrenr						fr->fr_age[1] = $2;) }
1340145510Sdarrenr	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1341145510Sdarrenr					{ DOALL(fr->fr_age[0] = $2; \
1342145510Sdarrenr						fr->fr_age[1] = $4;) }
1343145510Sdarrenr	;
1344145510Sdarrenr
1345145510Sdarrenrkeep:	| IPFY_KEEP keepstate keep
1346145510Sdarrenr	| IPFY_KEEP keepfrag keep
1347145510Sdarrenr	;
1348145510Sdarrenr
1349145510Sdarrenrkeepstate:
1350145510Sdarrenr	IPFY_STATE stateoptlist		{ DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
1351145510Sdarrenr	;
1352145510Sdarrenr
1353145510Sdarrenrkeepfrag:
1354145510Sdarrenr	IPFY_FRAGS fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1355145510Sdarrenr	| IPFY_FRAG fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1356145510Sdarrenr	;
1357145510Sdarrenr
1358145510Sdarrenrfragoptlist:
1359145510Sdarrenr	| '(' fragopts ')'
1360145510Sdarrenr	;
1361145510Sdarrenr
1362145510Sdarrenrfragopts:
1363145510Sdarrenr	fragopt lanother fragopts
1364145510Sdarrenr	| fragopt
1365145510Sdarrenr	;
1366145510Sdarrenr
1367145510Sdarrenrfragopt:
1368145510Sdarrenr	IPFY_STRICT			{ DOALL(fr->fr_flags |= FR_FRSTRICT;) }
1369145510Sdarrenr	;
1370145510Sdarrenr
1371145510Sdarrenrstateoptlist:
1372145510Sdarrenr	| '(' stateopts ')'
1373145510Sdarrenr	;
1374145510Sdarrenr
1375145510Sdarrenrstateopts:
1376145510Sdarrenr	stateopt lanother stateopts
1377145510Sdarrenr	| stateopt
1378145510Sdarrenr	;
1379145510Sdarrenr
1380145510Sdarrenrstateopt:
1381145510Sdarrenr	IPFY_LIMIT YY_NUMBER	{ DOALL(fr->fr_statemax = $2;) }
1382145510Sdarrenr	| IPFY_STRICT		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1383145510Sdarrenr						YYERROR; \
1384255332Scy					} else if (fr->fr_flags & FR_STLOOSE) {\
1385255332Scy						YYERROR; \
1386255332Scy					} else \
1387145510Sdarrenr						fr->fr_flags |= FR_STSTRICT;)
1388145510Sdarrenr				}
1389255332Scy	| IPFY_LOOSE		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1390255332Scy						YYERROR; \
1391255332Scy					} else if (fr->fr_flags & FR_STSTRICT){\
1392255332Scy						YYERROR; \
1393255332Scy					} else \
1394255332Scy						fr->fr_flags |= FR_STLOOSE;)
1395255332Scy				}
1396145510Sdarrenr	| IPFY_NEWISN		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1397145510Sdarrenr						YYERROR; \
1398145510Sdarrenr					  } else \
1399145510Sdarrenr						fr->fr_flags |= FR_NEWISN;)
1400145510Sdarrenr				}
1401145510Sdarrenr	| IPFY_NOICMPERR	{ DOALL(fr->fr_flags |= FR_NOICMPERR;) }
1402145510Sdarrenr
1403145510Sdarrenr	| IPFY_SYNC		{ DOALL(fr->fr_flags |= FR_STATESYNC;) }
1404161357Sguido	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1405161357Sguido						fr->fr_age[1] = $2;) }
1406161357Sguido	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1407161357Sguido					{ DOALL(fr->fr_age[0] = $2; \
1408161357Sguido						fr->fr_age[1] = $4;) }
1409255332Scy	| IPFY_ICMPHEAD groupname
1410255332Scy				{ DOALL(seticmphead(&fr, $2);)
1411255332Scy				  free($2);
1412255332Scy				}
1413255332Scy	| IPFY_NOLOG
1414255332Scy				{ DOALL(fr->fr_nostatelog = 1;) }
1415255332Scy	| IPFY_RPC
1416255332Scy				{ DOALL(fr->fr_rpc = 1;) }
1417255332Scy	| IPFY_RPC IPFY_IN YY_STR
1418255332Scy				{ DOALL(fr->fr_rpc = 1;) }
1419255332Scy	| IPFY_MAX_SRCS YY_NUMBER
1420255332Scy				{ DOALL(fr->fr_srctrack.ht_max_nodes = $2;) }
1421255332Scy	| IPFY_MAX_PER_SRC YY_NUMBER
1422255332Scy				{ DOALL(fr->fr_srctrack.ht_max_per_node = $2; \
1423255332Scy					fr->fr_srctrack.ht_netmask = \
1424255332Scy					fr->fr_family == AF_INET ? 32: 128;)
1425255332Scy				}
1426255332Scy	| IPFY_MAX_PER_SRC YY_NUMBER '/' YY_NUMBER
1427255332Scy				{ DOALL(fr->fr_srctrack.ht_max_per_node = $2; \
1428255332Scy					fr->fr_srctrack.ht_netmask = $4;)
1429255332Scy				}
1430145510Sdarrenr	;
1431145510Sdarrenr
1432145510Sdarrenrportnum:
1433255332Scy	servicename			{ if (getport(frc, $1,
1434255332Scy						      &($$), NULL) == -1)
1435145510Sdarrenr						yyerror("service unknown");
1436145510Sdarrenr					  $$ = ntohs($$);
1437145510Sdarrenr					  free($1);
1438145510Sdarrenr					}
1439145510Sdarrenr	| YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
1440145510Sdarrenr						yyerror("invalid port number");
1441145510Sdarrenr					  else
1442145510Sdarrenr						$$ = $1;
1443145510Sdarrenr					}
1444145510Sdarrenr	;
1445145510Sdarrenr
1446145510Sdarrenrwithlist:
1447153881Sguido	withopt				{ nowith = 0; }
1448153881Sguido	| withlist withopt		{ nowith = 0; }
1449153881Sguido	| withlist ',' withopt		{ nowith = 0; }
1450145510Sdarrenr	;
1451145510Sdarrenr
1452145510Sdarrenrwithopt:
1453145510Sdarrenr	opttype		{ DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) }
1454153881Sguido	| notwith opttype		{ DOALL(fr->fr_mflx |= $2;) }
1455145510Sdarrenr	| ipopt ipopts			{ yyresetdict(); }
1456145510Sdarrenr	| notwith ipopt ipopts		{ yyresetdict(); }
1457255332Scy	| startv6hdr ipv6hdrs		{ yyresetdict(); }
1458145510Sdarrenr	;
1459145510Sdarrenr
1460145510Sdarrenripopt:	IPFY_OPT			{ yysetdict(ipv4optwords); }
1461145510Sdarrenr	;
1462145510Sdarrenr
1463255332Scystartv6hdr:
1464255332Scy	IPFY_V6HDR	{ if (frc->fr_family != AF_INET6)
1465145510Sdarrenr				yyerror("only available with IPv6");
1466145510Sdarrenr			  yysetdict(ipv6optwords);
1467145510Sdarrenr			}
1468145510Sdarrenr	;
1469145510Sdarrenr
1470145510Sdarrenrnotwith:
1471145510Sdarrenr	IPFY_NOT			{ nowith = 1; }
1472145510Sdarrenr	| IPFY_NO			{ nowith = 1; }
1473145510Sdarrenr	;
1474145510Sdarrenr
1475145510Sdarrenropttype:
1476145510Sdarrenr	IPFY_IPOPTS			{ $$ = FI_OPTIONS; }
1477145510Sdarrenr	| IPFY_SHORT			{ $$ = FI_SHORT; }
1478145510Sdarrenr	| IPFY_NAT			{ $$ = FI_NATED; }
1479145510Sdarrenr	| IPFY_BAD			{ $$ = FI_BAD; }
1480145510Sdarrenr	| IPFY_BADNAT			{ $$ = FI_BADNAT; }
1481145510Sdarrenr	| IPFY_BADSRC			{ $$ = FI_BADSRC; }
1482145510Sdarrenr	| IPFY_LOWTTL			{ $$ = FI_LOWTTL; }
1483145510Sdarrenr	| IPFY_FRAG			{ $$ = FI_FRAG; }
1484145510Sdarrenr	| IPFY_FRAGBODY			{ $$ = FI_FRAGBODY; }
1485145510Sdarrenr	| IPFY_FRAGS			{ $$ = FI_FRAG; }
1486145510Sdarrenr	| IPFY_MBCAST			{ $$ = FI_MBCAST; }
1487145510Sdarrenr	| IPFY_MULTICAST		{ $$ = FI_MULTICAST; }
1488145510Sdarrenr	| IPFY_BROADCAST		{ $$ = FI_BROADCAST; }
1489145510Sdarrenr	| IPFY_STATE			{ $$ = FI_STATE; }
1490145510Sdarrenr	| IPFY_OOW			{ $$ = FI_OOW; }
1491255332Scy	| IPFY_AH			{ $$ = FI_AH; }
1492255332Scy	| IPFY_V6HDRS			{ $$ = FI_V6EXTHDR; }
1493145510Sdarrenr	;
1494145510Sdarrenr
1495145510Sdarrenripopts:	optlist		{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1496255332Scy				if (fr->fr_family == AF_UNSPEC) {
1497255332Scy					fr->fr_family = AF_INET;
1498255332Scy					fr->fr_ip.fi_v = 4;
1499255332Scy					fr->fr_mip.fi_v = 0xf;
1500255332Scy				} else if (fr->fr_family != AF_INET) {
1501255332Scy					YYERROR;
1502255332Scy				}
1503145510Sdarrenr				if (!nowith)
1504145510Sdarrenr					fr->fr_ip.fi_optmsk |= $1;)
1505145510Sdarrenr			}
1506145510Sdarrenr	;
1507145510Sdarrenr
1508145510Sdarrenroptlist:
1509145510Sdarrenr	opt				{ $$ |= $1; }
1510145510Sdarrenr	| optlist ',' opt		{ $$ |= $1 | $3; }
1511145510Sdarrenr	;
1512145510Sdarrenr
1513145510Sdarrenripv6hdrs:
1514145510Sdarrenr	ipv6hdrlist	{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1515145510Sdarrenr				if (!nowith)
1516145510Sdarrenr					fr->fr_ip.fi_optmsk |= $1;)
1517145510Sdarrenr			}
1518145510Sdarrenr	;
1519145510Sdarrenr
1520145510Sdarrenripv6hdrlist:
1521145510Sdarrenr	ipv6hdr				{ $$ |= $1; }
1522145510Sdarrenr	| ipv6hdrlist ',' ipv6hdr	{ $$ |= $1 | $3; }
1523145510Sdarrenr	;
1524145510Sdarrenr
1525145510Sdarrenrsecname:
1526145510Sdarrenr	seclevel			{ $$ |= $1; }
1527145510Sdarrenr	| secname ',' seclevel		{ $$ |= $1 | $3; }
1528145510Sdarrenr	;
1529145510Sdarrenr
1530145510Sdarrenrseclevel:
1531145510Sdarrenr	IPFY_SEC_UNC			{ $$ = secbit(IPSO_CLASS_UNCL); }
1532145510Sdarrenr	| IPFY_SEC_CONF			{ $$ = secbit(IPSO_CLASS_CONF); }
1533145510Sdarrenr	| IPFY_SEC_RSV1			{ $$ = secbit(IPSO_CLASS_RES1); }
1534145510Sdarrenr	| IPFY_SEC_RSV2			{ $$ = secbit(IPSO_CLASS_RES2); }
1535145510Sdarrenr	| IPFY_SEC_RSV3			{ $$ = secbit(IPSO_CLASS_RES3); }
1536145510Sdarrenr	| IPFY_SEC_RSV4			{ $$ = secbit(IPSO_CLASS_RES4); }
1537145510Sdarrenr	| IPFY_SEC_SEC			{ $$ = secbit(IPSO_CLASS_SECR); }
1538145510Sdarrenr	| IPFY_SEC_TS			{ $$ = secbit(IPSO_CLASS_TOPS); }
1539145510Sdarrenr	;
1540145510Sdarrenr
1541145510Sdarrenricmptype:
1542255332Scy	YY_NUMBER		{ $$ = $1; }
1543255332Scy	| YY_STR		{ $$ = geticmptype(frc->fr_family, $1);
1544255332Scy				  if ($$ == -1)
1545255332Scy					yyerror("unrecognised icmp type");
1546255332Scy				}
1547145510Sdarrenr	;
1548145510Sdarrenr
1549145510Sdarrenricmpcode:
1550145510Sdarrenr	YY_NUMBER			{ $$ = $1; }
1551145510Sdarrenr	| IPFY_ICMPC_NETUNR		{ $$ = ICMP_UNREACH_NET; }
1552145510Sdarrenr	| IPFY_ICMPC_HSTUNR		{ $$ = ICMP_UNREACH_HOST; }
1553145510Sdarrenr	| IPFY_ICMPC_PROUNR		{ $$ = ICMP_UNREACH_PROTOCOL; }
1554145510Sdarrenr	| IPFY_ICMPC_PORUNR		{ $$ = ICMP_UNREACH_PORT; }
1555145510Sdarrenr	| IPFY_ICMPC_NEEDF		{ $$ = ICMP_UNREACH_NEEDFRAG; }
1556145510Sdarrenr	| IPFY_ICMPC_SRCFAIL		{ $$ = ICMP_UNREACH_SRCFAIL; }
1557145510Sdarrenr	| IPFY_ICMPC_NETUNK		{ $$ = ICMP_UNREACH_NET_UNKNOWN; }
1558145510Sdarrenr	| IPFY_ICMPC_HSTUNK		{ $$ = ICMP_UNREACH_HOST_UNKNOWN; }
1559145510Sdarrenr	| IPFY_ICMPC_ISOLATE		{ $$ = ICMP_UNREACH_ISOLATED; }
1560145510Sdarrenr	| IPFY_ICMPC_NETPRO		{ $$ = ICMP_UNREACH_NET_PROHIB; }
1561145510Sdarrenr	| IPFY_ICMPC_HSTPRO		{ $$ = ICMP_UNREACH_HOST_PROHIB; }
1562145510Sdarrenr	| IPFY_ICMPC_NETTOS		{ $$ = ICMP_UNREACH_TOSNET; }
1563145510Sdarrenr	| IPFY_ICMPC_HSTTOS		{ $$ = ICMP_UNREACH_TOSHOST; }
1564145510Sdarrenr	| IPFY_ICMPC_FLTPRO		{ $$ = ICMP_UNREACH_ADMIN_PROHIBIT; }
1565145510Sdarrenr	| IPFY_ICMPC_HSTPRE		{ $$ = 14; }
1566145510Sdarrenr	| IPFY_ICMPC_CUTPRE		{ $$ = 15; }
1567145510Sdarrenr	;
1568145510Sdarrenr
1569145510Sdarrenropt:
1570145510Sdarrenr	IPFY_IPOPT_NOP			{ $$ = getoptbyvalue(IPOPT_NOP); }
1571145510Sdarrenr	| IPFY_IPOPT_RR			{ $$ = getoptbyvalue(IPOPT_RR); }
1572145510Sdarrenr	| IPFY_IPOPT_ZSU		{ $$ = getoptbyvalue(IPOPT_ZSU); }
1573145510Sdarrenr	| IPFY_IPOPT_MTUP		{ $$ = getoptbyvalue(IPOPT_MTUP); }
1574145510Sdarrenr	| IPFY_IPOPT_MTUR		{ $$ = getoptbyvalue(IPOPT_MTUR); }
1575145510Sdarrenr	| IPFY_IPOPT_ENCODE		{ $$ = getoptbyvalue(IPOPT_ENCODE); }
1576145510Sdarrenr	| IPFY_IPOPT_TS			{ $$ = getoptbyvalue(IPOPT_TS); }
1577145510Sdarrenr	| IPFY_IPOPT_TR			{ $$ = getoptbyvalue(IPOPT_TR); }
1578145510Sdarrenr	| IPFY_IPOPT_SEC		{ $$ = getoptbyvalue(IPOPT_SECURITY); }
1579145510Sdarrenr	| IPFY_IPOPT_LSRR		{ $$ = getoptbyvalue(IPOPT_LSRR); }
1580145510Sdarrenr	| IPFY_IPOPT_ESEC		{ $$ = getoptbyvalue(IPOPT_E_SEC); }
1581255332Scy	| IPFY_IPOPT_CIPSO 		{ $$ = getoptbyvalue(IPOPT_CIPSO); }
1582255332Scy	| IPFY_IPOPT_CIPSO doi		{ $$ = getoptbyvalue(IPOPT_CIPSO); }
1583145510Sdarrenr	| IPFY_IPOPT_SATID		{ $$ = getoptbyvalue(IPOPT_SATID); }
1584145510Sdarrenr	| IPFY_IPOPT_SSRR		{ $$ = getoptbyvalue(IPOPT_SSRR); }
1585145510Sdarrenr	| IPFY_IPOPT_ADDEXT		{ $$ = getoptbyvalue(IPOPT_ADDEXT); }
1586145510Sdarrenr	| IPFY_IPOPT_VISA		{ $$ = getoptbyvalue(IPOPT_VISA); }
1587145510Sdarrenr	| IPFY_IPOPT_IMITD		{ $$ = getoptbyvalue(IPOPT_IMITD); }
1588145510Sdarrenr	| IPFY_IPOPT_EIP		{ $$ = getoptbyvalue(IPOPT_EIP); }
1589145510Sdarrenr	| IPFY_IPOPT_FINN		{ $$ = getoptbyvalue(IPOPT_FINN); }
1590145510Sdarrenr	| IPFY_IPOPT_DPS		{ $$ = getoptbyvalue(IPOPT_DPS); }
1591145510Sdarrenr	| IPFY_IPOPT_SDB		{ $$ = getoptbyvalue(IPOPT_SDB); }
1592145510Sdarrenr	| IPFY_IPOPT_NSAPA		{ $$ = getoptbyvalue(IPOPT_NSAPA); }
1593145510Sdarrenr	| IPFY_IPOPT_RTRALRT		{ $$ = getoptbyvalue(IPOPT_RTRALRT); }
1594145510Sdarrenr	| IPFY_IPOPT_UMP		{ $$ = getoptbyvalue(IPOPT_UMP); }
1595145510Sdarrenr	| setsecclass secname
1596145510Sdarrenr			{ DOALL(fr->fr_mip.fi_secmsk |= $2;
1597255332Scy				if (fr->fr_family == AF_UNSPEC) {
1598255332Scy					fr->fr_family = AF_INET;
1599255332Scy					fr->fr_ip.fi_v = 4;
1600255332Scy					fr->fr_mip.fi_v = 0xf;
1601255332Scy				} else if (fr->fr_family != AF_INET) {
1602255332Scy					YYERROR;
1603255332Scy				}
1604145510Sdarrenr				if (!nowith)
1605145510Sdarrenr					fr->fr_ip.fi_secmsk |= $2;)
1606145510Sdarrenr			  $$ = 0;
1607145510Sdarrenr			  yyresetdict();
1608145510Sdarrenr			}
1609145510Sdarrenr	;
1610145510Sdarrenr
1611145510Sdarrenrsetsecclass:
1612255332Scy	IPFY_SECCLASS			{ yysetdict(ipv4secwords); }
1613145510Sdarrenr	;
1614145510Sdarrenr
1615255332Scydoi:	IPFY_DOI YY_NUMBER		{ DOALL(fr->fr_doimask = 0xffffffff; \
1616255332Scy						if (!nowith) \
1617255332Scy							fr->fr_doi = $2;) }
1618255332Scy	| IPFY_DOI YY_HEX		{ DOALL(fr->fr_doimask = 0xffffffff; \
1619255332Scy						if (!nowith) \
1620255332Scy							fr->fr_doi = $2;) }
1621255332Scy	;
1622255332Scy
1623145510Sdarrenripv6hdr:
1624145510Sdarrenr	IPFY_AH			{ $$ = getv6optbyvalue(IPPROTO_AH); }
1625145510Sdarrenr	| IPFY_IPV6OPT_DSTOPTS	{ $$ = getv6optbyvalue(IPPROTO_DSTOPTS); }
1626153881Sguido	| IPFY_IPV6OPT_ESP	{ $$ = getv6optbyvalue(IPPROTO_ESP); }
1627145510Sdarrenr	| IPFY_IPV6OPT_HOPOPTS	{ $$ = getv6optbyvalue(IPPROTO_HOPOPTS); }
1628145510Sdarrenr	| IPFY_IPV6OPT_IPV6	{ $$ = getv6optbyvalue(IPPROTO_IPV6); }
1629145510Sdarrenr	| IPFY_IPV6OPT_NONE	{ $$ = getv6optbyvalue(IPPROTO_NONE); }
1630145510Sdarrenr	| IPFY_IPV6OPT_ROUTING	{ $$ = getv6optbyvalue(IPPROTO_ROUTING); }
1631153881Sguido	| IPFY_IPV6OPT_FRAG	{ $$ = getv6optbyvalue(IPPROTO_FRAGMENT); }
1632153881Sguido	| IPFY_IPV6OPT_MOBILITY	{ $$ = getv6optbyvalue(IPPROTO_MOBILITY); }
1633145510Sdarrenr	;
1634145510Sdarrenr
1635145510Sdarrenrlevel:	IPFY_LEVEL			{ setsyslog(); }
1636145510Sdarrenr	;
1637145510Sdarrenr
1638145510Sdarrenrloglevel:
1639145510Sdarrenr	priority			{ fr->fr_loglevel = LOG_LOCAL0|$1; }
1640145510Sdarrenr	| facility '.' priority		{ fr->fr_loglevel = $1 | $3; }
1641145510Sdarrenr	;
1642145510Sdarrenr
1643145510Sdarrenrfacility:
1644145510Sdarrenr	IPFY_FAC_KERN			{ $$ = LOG_KERN; }
1645145510Sdarrenr	| IPFY_FAC_USER			{ $$ = LOG_USER; }
1646145510Sdarrenr	| IPFY_FAC_MAIL			{ $$ = LOG_MAIL; }
1647145510Sdarrenr	| IPFY_FAC_DAEMON		{ $$ = LOG_DAEMON; }
1648145510Sdarrenr	| IPFY_FAC_AUTH			{ $$ = LOG_AUTH; }
1649145510Sdarrenr	| IPFY_FAC_SYSLOG		{ $$ = LOG_SYSLOG; }
1650145510Sdarrenr	| IPFY_FAC_LPR			{ $$ = LOG_LPR; }
1651145510Sdarrenr	| IPFY_FAC_NEWS			{ $$ = LOG_NEWS; }
1652145510Sdarrenr	| IPFY_FAC_UUCP			{ $$ = LOG_UUCP; }
1653145510Sdarrenr	| IPFY_FAC_CRON			{ $$ = LOG_CRON; }
1654145510Sdarrenr	| IPFY_FAC_FTP			{ $$ = LOG_FTP; }
1655145510Sdarrenr	| IPFY_FAC_AUTHPRIV		{ $$ = LOG_AUTHPRIV; }
1656145510Sdarrenr	| IPFY_FAC_AUDIT		{ $$ = LOG_AUDIT; }
1657145510Sdarrenr	| IPFY_FAC_LFMT			{ $$ = LOG_LFMT; }
1658145510Sdarrenr	| IPFY_FAC_LOCAL0		{ $$ = LOG_LOCAL0; }
1659145510Sdarrenr	| IPFY_FAC_LOCAL1		{ $$ = LOG_LOCAL1; }
1660145510Sdarrenr	| IPFY_FAC_LOCAL2		{ $$ = LOG_LOCAL2; }
1661145510Sdarrenr	| IPFY_FAC_LOCAL3		{ $$ = LOG_LOCAL3; }
1662145510Sdarrenr	| IPFY_FAC_LOCAL4		{ $$ = LOG_LOCAL4; }
1663145510Sdarrenr	| IPFY_FAC_LOCAL5		{ $$ = LOG_LOCAL5; }
1664145510Sdarrenr	| IPFY_FAC_LOCAL6		{ $$ = LOG_LOCAL6; }
1665145510Sdarrenr	| IPFY_FAC_LOCAL7		{ $$ = LOG_LOCAL7; }
1666145510Sdarrenr	| IPFY_FAC_SECURITY		{ $$ = LOG_SECURITY; }
1667145510Sdarrenr	;
1668145510Sdarrenr
1669145510Sdarrenrpriority:
1670145510Sdarrenr	IPFY_PRI_EMERG			{ $$ = LOG_EMERG; }
1671145510Sdarrenr	| IPFY_PRI_ALERT		{ $$ = LOG_ALERT; }
1672145510Sdarrenr	| IPFY_PRI_CRIT			{ $$ = LOG_CRIT; }
1673145510Sdarrenr	| IPFY_PRI_ERR			{ $$ = LOG_ERR; }
1674145510Sdarrenr	| IPFY_PRI_WARN			{ $$ = LOG_WARNING; }
1675145510Sdarrenr	| IPFY_PRI_NOTICE		{ $$ = LOG_NOTICE; }
1676145510Sdarrenr	| IPFY_PRI_INFO			{ $$ = LOG_INFO; }
1677145510Sdarrenr	| IPFY_PRI_DEBUG		{ $$ = LOG_DEBUG; }
1678145510Sdarrenr	;
1679145510Sdarrenr
1680145510Sdarrenrcompare:
1681145510Sdarrenr	YY_CMP_EQ			{ $$ = FR_EQUAL; }
1682145510Sdarrenr	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
1683145510Sdarrenr	| YY_CMP_LT			{ $$ = FR_LESST; }
1684145510Sdarrenr	| YY_CMP_LE			{ $$ = FR_LESSTE; }
1685145510Sdarrenr	| YY_CMP_GT			{ $$ = FR_GREATERT; }
1686145510Sdarrenr	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
1687145510Sdarrenr	;
1688145510Sdarrenr
1689145510Sdarrenrrange:	YY_RANGE_IN			{ $$ = FR_INRANGE; }
1690145510Sdarrenr	| YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
1691145510Sdarrenr	| ':'				{ $$ = FR_INCRANGE; }
1692145510Sdarrenr	;
1693145510Sdarrenr
1694145510Sdarrenrservicename:
1695145510Sdarrenr	YY_STR				{ $$ = $1; }
1696145510Sdarrenr	;
1697145510Sdarrenr
1698170268Sdarrenrinterfacename:	name				{ $$ = $1; }
1699170268Sdarrenr	| name ':' YY_NUMBER
1700145510Sdarrenr		{ $$ = $1;
1701145510Sdarrenr		  fprintf(stderr, "%d: Logical interface %s:%d unsupported, "
1702145510Sdarrenr			  "use the physical interface %s instead.\n",
1703145510Sdarrenr			  yylineNum, $1, $3, $1);
1704145510Sdarrenr		}
1705145510Sdarrenr	;
1706145510Sdarrenr
1707145510Sdarrenrname:	YY_STR				{ $$ = $1; }
1708170268Sdarrenr	| '-'				{ $$ = strdup("-"); }
1709145510Sdarrenr	;
1710145510Sdarrenr
1711145510Sdarrenripv4_16:
1712145510Sdarrenr	YY_NUMBER '.' YY_NUMBER
1713145510Sdarrenr		{ if ($1 > 255 || $3 > 255) {
1714145510Sdarrenr			yyerror("Invalid octet string for IP address");
1715145510Sdarrenr			return 0;
1716145510Sdarrenr		  }
1717145510Sdarrenr		  $$.s_addr = ($1 << 24) | ($3 << 16);
1718145510Sdarrenr		  $$.s_addr = htonl($$.s_addr);
1719145510Sdarrenr		}
1720145510Sdarrenr	;
1721145510Sdarrenr
1722145510Sdarrenripv4_24:
1723145510Sdarrenr	ipv4_16 '.' YY_NUMBER
1724145510Sdarrenr		{ if ($3 > 255) {
1725145510Sdarrenr			yyerror("Invalid octet string for IP address");
1726145510Sdarrenr			return 0;
1727145510Sdarrenr		  }
1728145510Sdarrenr		  $$.s_addr |= htonl($3 << 8);
1729145510Sdarrenr		}
1730145510Sdarrenr	;
1731145510Sdarrenr
1732145510Sdarrenripv4:	ipv4_24 '.' YY_NUMBER
1733145510Sdarrenr		{ if ($3 > 255) {
1734145510Sdarrenr			yyerror("Invalid octet string for IP address");
1735145510Sdarrenr			return 0;
1736145510Sdarrenr		  }
1737145510Sdarrenr		  $$.s_addr |= htonl($3);
1738145510Sdarrenr		}
1739145510Sdarrenr	| ipv4_24
1740145510Sdarrenr	| ipv4_16
1741145510Sdarrenr	;
1742145510Sdarrenr
1743145510Sdarrenr%%
1744145510Sdarrenr
1745145510Sdarrenr
1746255332Scystatic	struct	wordtab ipfwords[] = {
1747145510Sdarrenr	{ "age",			IPFY_AGE },
1748145510Sdarrenr	{ "ah",				IPFY_AH },
1749145510Sdarrenr	{ "all",			IPFY_ALL },
1750145510Sdarrenr	{ "and",			IPFY_AND },
1751145510Sdarrenr	{ "auth",			IPFY_AUTH },
1752145510Sdarrenr	{ "bad",			IPFY_BAD },
1753145510Sdarrenr	{ "bad-nat",			IPFY_BADNAT },
1754145510Sdarrenr	{ "bad-src",			IPFY_BADSRC },
1755145510Sdarrenr	{ "bcast",			IPFY_BROADCAST },
1756145510Sdarrenr	{ "block",			IPFY_BLOCK },
1757145510Sdarrenr	{ "body",			IPFY_BODY },
1758145510Sdarrenr	{ "bpf-v4",			IPFY_BPFV4 },
1759145510Sdarrenr#ifdef USE_INET6
1760145510Sdarrenr	{ "bpf-v6",			IPFY_BPFV6 },
1761145510Sdarrenr#endif
1762145510Sdarrenr	{ "call",			IPFY_CALL },
1763145510Sdarrenr	{ "code",			IPFY_ICMPCODE },
1764255332Scy	{ "comment",			IPFY_COMMENT },
1765145510Sdarrenr	{ "count",			IPFY_COUNT },
1766255332Scy	{ "decapsulate",		IPFY_DECAPS },
1767255332Scy	{ "dstlist",			IPFY_DSTLIST },
1768255332Scy	{ "doi",			IPFY_DOI },
1769145510Sdarrenr	{ "dup-to",			IPFY_DUPTO },
1770145510Sdarrenr	{ "eq",				YY_CMP_EQ },
1771145510Sdarrenr	{ "esp",			IPFY_ESP },
1772255332Scy	{ "exp",			IPFY_IPFEXPR },
1773255332Scy	{ "family",			IPFY_FAMILY },
1774145510Sdarrenr	{ "fastroute",			IPFY_FROUTE },
1775145510Sdarrenr	{ "first",			IPFY_FIRST },
1776145510Sdarrenr	{ "flags",			IPFY_FLAGS },
1777145510Sdarrenr	{ "frag",			IPFY_FRAG },
1778145510Sdarrenr	{ "frag-body",			IPFY_FRAGBODY },
1779145510Sdarrenr	{ "frags",			IPFY_FRAGS },
1780145510Sdarrenr	{ "from",			IPFY_FROM },
1781145510Sdarrenr	{ "ge",				YY_CMP_GE },
1782145510Sdarrenr	{ "group",			IPFY_GROUP },
1783145510Sdarrenr	{ "gt",				YY_CMP_GT },
1784145510Sdarrenr	{ "head",			IPFY_HEAD },
1785145510Sdarrenr	{ "icmp",			IPFY_ICMP },
1786255332Scy	{ "icmp-head",			IPFY_ICMPHEAD },
1787145510Sdarrenr	{ "icmp-type",			IPFY_ICMPTYPE },
1788145510Sdarrenr	{ "in",				IPFY_IN },
1789145510Sdarrenr	{ "in-via",			IPFY_INVIA },
1790255332Scy	{ "inet",			IPFY_INET },
1791255332Scy	{ "inet6",			IPFY_INET6 },
1792145510Sdarrenr	{ "ipopt",			IPFY_IPOPTS },
1793145510Sdarrenr	{ "ipopts",			IPFY_IPOPTS },
1794145510Sdarrenr	{ "keep",			IPFY_KEEP },
1795255332Scy	{ "l5-as",			IPFY_L5AS },
1796145510Sdarrenr	{ "le",				YY_CMP_LE },
1797145510Sdarrenr	{ "level",			IPFY_LEVEL },
1798145510Sdarrenr	{ "limit",			IPFY_LIMIT },
1799145510Sdarrenr	{ "log",			IPFY_LOG },
1800255332Scy	{ "loose",			IPFY_LOOSE },
1801145510Sdarrenr	{ "lowttl",			IPFY_LOWTTL },
1802145510Sdarrenr	{ "lt",				YY_CMP_LT },
1803145510Sdarrenr	{ "mask",			IPFY_MASK },
1804145510Sdarrenr	{ "match-tag",			IPFY_MATCHTAG },
1805255332Scy	{ "max-per-src",		IPFY_MAX_PER_SRC },
1806255332Scy	{ "max-srcs",			IPFY_MAX_SRCS },
1807145510Sdarrenr	{ "mbcast",			IPFY_MBCAST },
1808153881Sguido	{ "mcast",			IPFY_MULTICAST },
1809145510Sdarrenr	{ "multicast",			IPFY_MULTICAST },
1810145510Sdarrenr	{ "nat",			IPFY_NAT },
1811145510Sdarrenr	{ "ne",				YY_CMP_NE },
1812145510Sdarrenr	{ "net",			IPFY_NETWORK },
1813145510Sdarrenr	{ "newisn",			IPFY_NEWISN },
1814145510Sdarrenr	{ "no",				IPFY_NO },
1815145510Sdarrenr	{ "no-icmp-err",		IPFY_NOICMPERR },
1816255332Scy	{ "nolog",			IPFY_NOLOG },
1817161357Sguido	{ "nomatch",			IPFY_NOMATCH },
1818145510Sdarrenr	{ "now",			IPFY_NOW },
1819145510Sdarrenr	{ "not",			IPFY_NOT },
1820145510Sdarrenr	{ "oow",			IPFY_OOW },
1821145510Sdarrenr	{ "on",				IPFY_ON },
1822145510Sdarrenr	{ "opt",			IPFY_OPT },
1823145510Sdarrenr	{ "or-block",			IPFY_ORBLOCK },
1824145510Sdarrenr	{ "out",			IPFY_OUT },
1825145510Sdarrenr	{ "out-via",			IPFY_OUTVIA },
1826145510Sdarrenr	{ "pass",			IPFY_PASS },
1827145510Sdarrenr	{ "port",			IPFY_PORT },
1828145510Sdarrenr	{ "pps",			IPFY_PPS },
1829145510Sdarrenr	{ "preauth",			IPFY_PREAUTH },
1830145510Sdarrenr	{ "proto",			IPFY_PROTO },
1831145510Sdarrenr	{ "quick",			IPFY_QUICK },
1832145510Sdarrenr	{ "reply-to",			IPFY_REPLY_TO },
1833145510Sdarrenr	{ "return-icmp",		IPFY_RETICMP },
1834145510Sdarrenr	{ "return-icmp-as-dest",	IPFY_RETICMPASDST },
1835145510Sdarrenr	{ "return-rst",			IPFY_RETRST },
1836145510Sdarrenr	{ "route-to",			IPFY_ROUTETO },
1837255332Scy	{ "rule-ttl",			IPFY_RULETTL },
1838255332Scy	{ "rpc",			IPFY_RPC },
1839145510Sdarrenr	{ "sec-class",			IPFY_SECCLASS },
1840255332Scy	{ "set",			IPFY_SET },
1841145510Sdarrenr	{ "set-tag",			IPFY_SETTAG },
1842145510Sdarrenr	{ "skip",			IPFY_SKIP },
1843145510Sdarrenr	{ "short",			IPFY_SHORT },
1844145510Sdarrenr	{ "state",			IPFY_STATE },
1845145510Sdarrenr	{ "state-age",			IPFY_AGE },
1846145510Sdarrenr	{ "strict",			IPFY_STRICT },
1847145510Sdarrenr	{ "sync",			IPFY_SYNC },
1848145510Sdarrenr	{ "tcp",			IPFY_TCP },
1849145510Sdarrenr	{ "tcp-udp",			IPFY_TCPUDP },
1850145510Sdarrenr	{ "tos",			IPFY_TOS },
1851145510Sdarrenr	{ "to",				IPFY_TO },
1852145510Sdarrenr	{ "ttl",			IPFY_TTL },
1853145510Sdarrenr	{ "udp",			IPFY_UDP },
1854255332Scy	{ "v6hdr",			IPFY_V6HDR },
1855255332Scy	{ "v6hdrs",			IPFY_V6HDRS },
1856145510Sdarrenr	{ "with",			IPFY_WITH },
1857145510Sdarrenr	{ NULL,				0 }
1858145510Sdarrenr};
1859145510Sdarrenr
1860255332Scystatic	struct	wordtab	addrwords[] = {
1861145510Sdarrenr	{ "any",			IPFY_ANY },
1862145510Sdarrenr	{ "hash",			IPFY_HASH },
1863145510Sdarrenr	{ "pool",			IPFY_POOL },
1864145510Sdarrenr	{ NULL,				0 }
1865145510Sdarrenr};
1866145510Sdarrenr
1867255332Scystatic	struct	wordtab	maskwords[] = {
1868145510Sdarrenr	{ "broadcast",			IPFY_BROADCAST },
1869145510Sdarrenr	{ "netmasked",			IPFY_NETMASKED },
1870145510Sdarrenr	{ "network",			IPFY_NETWORK },
1871145510Sdarrenr	{ "peer",			IPFY_PEER },
1872145510Sdarrenr	{ NULL,				0 }
1873145510Sdarrenr};
1874145510Sdarrenr
1875255332Scystatic	struct	wordtab icmpcodewords[] = {
1876145510Sdarrenr	{ "cutoff-preced",		IPFY_ICMPC_CUTPRE },
1877145510Sdarrenr	{ "filter-prohib",		IPFY_ICMPC_FLTPRO },
1878145510Sdarrenr	{ "isolate",			IPFY_ICMPC_ISOLATE },
1879145510Sdarrenr	{ "needfrag",			IPFY_ICMPC_NEEDF },
1880145510Sdarrenr	{ "net-prohib",			IPFY_ICMPC_NETPRO },
1881145510Sdarrenr	{ "net-tos",			IPFY_ICMPC_NETTOS },
1882145510Sdarrenr	{ "host-preced",		IPFY_ICMPC_HSTPRE },
1883145510Sdarrenr	{ "host-prohib",		IPFY_ICMPC_HSTPRO },
1884145510Sdarrenr	{ "host-tos",			IPFY_ICMPC_HSTTOS },
1885145510Sdarrenr	{ "host-unk",			IPFY_ICMPC_HSTUNK },
1886145510Sdarrenr	{ "host-unr",			IPFY_ICMPC_HSTUNR },
1887145510Sdarrenr	{ "net-unk",			IPFY_ICMPC_NETUNK },
1888145510Sdarrenr	{ "net-unr",			IPFY_ICMPC_NETUNR },
1889145510Sdarrenr	{ "port-unr",			IPFY_ICMPC_PORUNR },
1890145510Sdarrenr	{ "proto-unr",			IPFY_ICMPC_PROUNR },
1891145510Sdarrenr	{ "srcfail",			IPFY_ICMPC_SRCFAIL },
1892145510Sdarrenr	{ NULL,				0 },
1893145510Sdarrenr};
1894145510Sdarrenr
1895255332Scystatic	struct	wordtab ipv4optwords[] = {
1896145510Sdarrenr	{ "addext",			IPFY_IPOPT_ADDEXT },
1897145510Sdarrenr	{ "cipso",			IPFY_IPOPT_CIPSO },
1898145510Sdarrenr	{ "dps",			IPFY_IPOPT_DPS },
1899145510Sdarrenr	{ "e-sec",			IPFY_IPOPT_ESEC },
1900145510Sdarrenr	{ "eip",			IPFY_IPOPT_EIP },
1901145510Sdarrenr	{ "encode",			IPFY_IPOPT_ENCODE },
1902145510Sdarrenr	{ "finn",			IPFY_IPOPT_FINN },
1903145510Sdarrenr	{ "imitd",			IPFY_IPOPT_IMITD },
1904145510Sdarrenr	{ "lsrr",			IPFY_IPOPT_LSRR },
1905145510Sdarrenr	{ "mtup",			IPFY_IPOPT_MTUP },
1906145510Sdarrenr	{ "mtur",			IPFY_IPOPT_MTUR },
1907145510Sdarrenr	{ "nop",			IPFY_IPOPT_NOP },
1908145510Sdarrenr	{ "nsapa",			IPFY_IPOPT_NSAPA },
1909145510Sdarrenr	{ "rr",				IPFY_IPOPT_RR },
1910145510Sdarrenr	{ "rtralrt",			IPFY_IPOPT_RTRALRT },
1911145510Sdarrenr	{ "satid",			IPFY_IPOPT_SATID },
1912145510Sdarrenr	{ "sdb",			IPFY_IPOPT_SDB },
1913145510Sdarrenr	{ "sec",			IPFY_IPOPT_SEC },
1914145510Sdarrenr	{ "ssrr",			IPFY_IPOPT_SSRR },
1915145510Sdarrenr	{ "tr",				IPFY_IPOPT_TR },
1916145510Sdarrenr	{ "ts",				IPFY_IPOPT_TS },
1917145510Sdarrenr	{ "ump",			IPFY_IPOPT_UMP },
1918145510Sdarrenr	{ "visa",			IPFY_IPOPT_VISA },
1919145510Sdarrenr	{ "zsu",			IPFY_IPOPT_ZSU },
1920145510Sdarrenr	{ NULL,				0 },
1921145510Sdarrenr};
1922145510Sdarrenr
1923255332Scystatic	struct	wordtab ipv4secwords[] = {
1924145510Sdarrenr	{ "confid",			IPFY_SEC_CONF },
1925145510Sdarrenr	{ "reserv-1",			IPFY_SEC_RSV1 },
1926145510Sdarrenr	{ "reserv-2",			IPFY_SEC_RSV2 },
1927145510Sdarrenr	{ "reserv-3",			IPFY_SEC_RSV3 },
1928145510Sdarrenr	{ "reserv-4",			IPFY_SEC_RSV4 },
1929145510Sdarrenr	{ "secret",			IPFY_SEC_SEC },
1930145510Sdarrenr	{ "topsecret",			IPFY_SEC_TS },
1931145510Sdarrenr	{ "unclass",			IPFY_SEC_UNC },
1932145510Sdarrenr	{ NULL,				0 },
1933145510Sdarrenr};
1934145510Sdarrenr
1935255332Scystatic	struct	wordtab ipv6optwords[] = {
1936145510Sdarrenr	{ "dstopts",			IPFY_IPV6OPT_DSTOPTS },
1937153881Sguido	{ "esp",			IPFY_IPV6OPT_ESP },
1938153881Sguido	{ "frag",			IPFY_IPV6OPT_FRAG },
1939145510Sdarrenr	{ "hopopts",			IPFY_IPV6OPT_HOPOPTS },
1940145510Sdarrenr	{ "ipv6",			IPFY_IPV6OPT_IPV6 },
1941153881Sguido	{ "mobility",			IPFY_IPV6OPT_MOBILITY },
1942145510Sdarrenr	{ "none",			IPFY_IPV6OPT_NONE },
1943145510Sdarrenr	{ "routing",			IPFY_IPV6OPT_ROUTING },
1944145510Sdarrenr	{ NULL,				0 },
1945145510Sdarrenr};
1946145510Sdarrenr
1947255332Scystatic	struct	wordtab logwords[] = {
1948145510Sdarrenr	{ "kern",			IPFY_FAC_KERN },
1949145510Sdarrenr	{ "user",			IPFY_FAC_USER },
1950145510Sdarrenr	{ "mail",			IPFY_FAC_MAIL },
1951145510Sdarrenr	{ "daemon",			IPFY_FAC_DAEMON },
1952145510Sdarrenr	{ "auth",			IPFY_FAC_AUTH },
1953145510Sdarrenr	{ "syslog",			IPFY_FAC_SYSLOG },
1954145510Sdarrenr	{ "lpr",			IPFY_FAC_LPR },
1955145510Sdarrenr	{ "news",			IPFY_FAC_NEWS },
1956145510Sdarrenr	{ "uucp",			IPFY_FAC_UUCP },
1957145510Sdarrenr	{ "cron",			IPFY_FAC_CRON },
1958145510Sdarrenr	{ "ftp",			IPFY_FAC_FTP },
1959145510Sdarrenr	{ "authpriv",			IPFY_FAC_AUTHPRIV },
1960145510Sdarrenr	{ "audit",			IPFY_FAC_AUDIT },
1961145510Sdarrenr	{ "logalert",			IPFY_FAC_LFMT },
1962145510Sdarrenr	{ "console",			IPFY_FAC_CONSOLE },
1963145510Sdarrenr	{ "security",			IPFY_FAC_SECURITY },
1964145510Sdarrenr	{ "local0",			IPFY_FAC_LOCAL0 },
1965145510Sdarrenr	{ "local1",			IPFY_FAC_LOCAL1 },
1966145510Sdarrenr	{ "local2",			IPFY_FAC_LOCAL2 },
1967145510Sdarrenr	{ "local3",			IPFY_FAC_LOCAL3 },
1968145510Sdarrenr	{ "local4",			IPFY_FAC_LOCAL4 },
1969145510Sdarrenr	{ "local5",			IPFY_FAC_LOCAL5 },
1970145510Sdarrenr	{ "local6",			IPFY_FAC_LOCAL6 },
1971145510Sdarrenr	{ "local7",			IPFY_FAC_LOCAL7 },
1972145510Sdarrenr	{ "emerg",			IPFY_PRI_EMERG },
1973145510Sdarrenr	{ "alert",			IPFY_PRI_ALERT },
1974145510Sdarrenr	{ "crit",			IPFY_PRI_CRIT },
1975145510Sdarrenr	{ "err",			IPFY_PRI_ERR },
1976145510Sdarrenr	{ "warn",			IPFY_PRI_WARN },
1977145510Sdarrenr	{ "notice",			IPFY_PRI_NOTICE },
1978145510Sdarrenr	{ "info",			IPFY_PRI_INFO },
1979145510Sdarrenr	{ "debug",			IPFY_PRI_DEBUG },
1980145510Sdarrenr	{ NULL,				0 },
1981145510Sdarrenr};
1982145510Sdarrenr
1983145510Sdarrenr
1984145510Sdarrenr
1985145510Sdarrenr
1986145510Sdarrenrint ipf_parsefile(fd, addfunc, iocfuncs, filename)
1987145510Sdarrenrint fd;
1988145510Sdarrenraddfunc_t addfunc;
1989145510Sdarrenrioctlfunc_t *iocfuncs;
1990145510Sdarrenrchar *filename;
1991145510Sdarrenr{
1992145510Sdarrenr	FILE *fp = NULL;
1993145510Sdarrenr	char *s;
1994145510Sdarrenr
1995145510Sdarrenr	yylineNum = 1;
1996145510Sdarrenr	yysettab(ipfwords);
1997145510Sdarrenr
1998145510Sdarrenr	s = getenv("YYDEBUG");
1999145510Sdarrenr	if (s != NULL)
2000145510Sdarrenr		yydebug = atoi(s);
2001145510Sdarrenr	else
2002145510Sdarrenr		yydebug = 0;
2003145510Sdarrenr
2004145510Sdarrenr	if (strcmp(filename, "-")) {
2005145510Sdarrenr		fp = fopen(filename, "r");
2006145510Sdarrenr		if (fp == NULL) {
2007145510Sdarrenr			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
2008145510Sdarrenr				STRERROR(errno));
2009145510Sdarrenr			return -1;
2010145510Sdarrenr		}
2011145510Sdarrenr	} else
2012145510Sdarrenr		fp = stdin;
2013145510Sdarrenr
2014145510Sdarrenr	while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1)
2015145510Sdarrenr		;
2016145510Sdarrenr	if (fp != NULL)
2017145510Sdarrenr		fclose(fp);
2018145510Sdarrenr	return 0;
2019145510Sdarrenr}
2020145510Sdarrenr
2021145510Sdarrenr
2022145510Sdarrenrint ipf_parsesome(fd, addfunc, iocfuncs, fp)
2023145510Sdarrenrint fd;
2024145510Sdarrenraddfunc_t addfunc;
2025145510Sdarrenrioctlfunc_t *iocfuncs;
2026145510SdarrenrFILE *fp;
2027145510Sdarrenr{
2028145510Sdarrenr	char *s;
2029145510Sdarrenr	int i;
2030145510Sdarrenr
2031145510Sdarrenr	ipffd = fd;
2032145510Sdarrenr	for (i = 0; i <= IPL_LOGMAX; i++)
2033255332Scy		ipfioctls[i] = iocfuncs[i];
2034145510Sdarrenr	ipfaddfunc = addfunc;
2035145510Sdarrenr
2036145510Sdarrenr	if (feof(fp))
2037145510Sdarrenr		return 0;
2038145510Sdarrenr	i = fgetc(fp);
2039145510Sdarrenr	if (i == EOF)
2040145510Sdarrenr		return 0;
2041145510Sdarrenr	if (ungetc(i, fp) == 0)
2042145510Sdarrenr		return 0;
2043145510Sdarrenr	if (feof(fp))
2044145510Sdarrenr		return 0;
2045145510Sdarrenr	s = getenv("YYDEBUG");
2046145510Sdarrenr	if (s != NULL)
2047145510Sdarrenr		yydebug = atoi(s);
2048145510Sdarrenr	else
2049145510Sdarrenr		yydebug = 0;
2050145510Sdarrenr
2051145510Sdarrenr	yyin = fp;
2052145510Sdarrenr	yyparse();
2053145510Sdarrenr	return 1;
2054145510Sdarrenr}
2055145510Sdarrenr
2056145510Sdarrenr
2057145510Sdarrenrstatic void newrule()
2058145510Sdarrenr{
2059145510Sdarrenr	frentry_t *frn;
2060145510Sdarrenr
2061255332Scy	frn = allocfr();
2062145510Sdarrenr	for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next)
2063145510Sdarrenr		;
2064255332Scy	if (fr != NULL) {
2065145510Sdarrenr		fr->fr_next = frn;
2066255332Scy		frn->fr_pnext = &fr->fr_next;
2067255332Scy	}
2068255332Scy	if (frtop == NULL) {
2069145510Sdarrenr		frtop = frn;
2070255332Scy		frn->fr_pnext = &frtop;
2071255332Scy	}
2072145510Sdarrenr	fr = frn;
2073145510Sdarrenr	frc = frn;
2074145510Sdarrenr	fr->fr_loglevel = 0xffff;
2075145510Sdarrenr	fr->fr_isc = (void *)-1;
2076145510Sdarrenr	fr->fr_logtag = FR_NOLOGTAG;
2077145510Sdarrenr	fr->fr_type = FR_T_NONE;
2078255332Scy	fr->fr_flineno = yylineNum;
2079145510Sdarrenr
2080255332Scy	if (use_inet6 == 1)
2081255332Scy		fr->fr_family = AF_INET6;
2082255332Scy	else if (use_inet6 == -1)
2083255332Scy		fr->fr_family = AF_INET;
2084255332Scy
2085145510Sdarrenr	nrules = 1;
2086145510Sdarrenr}
2087145510Sdarrenr
2088145510Sdarrenr
2089145510Sdarrenrstatic void setipftype()
2090145510Sdarrenr{
2091145510Sdarrenr	for (fr = frc; fr != NULL; fr = fr->fr_next) {
2092145510Sdarrenr		if (fr->fr_type == FR_T_NONE) {
2093145510Sdarrenr			fr->fr_type = FR_T_IPF;
2094145510Sdarrenr			fr->fr_data = (void *)calloc(sizeof(fripf_t), 1);
2095145510Sdarrenr			fr->fr_dsize = sizeof(fripf_t);
2096255332Scy			fr->fr_family = frc->fr_family;
2097255332Scy			if (fr->fr_family == AF_INET) {
2098255332Scy				fr->fr_ip.fi_v = 4;
2099255332Scy			}
2100255332Scy			else if (fr->fr_family == AF_INET6) {
2101255332Scy				fr->fr_ip.fi_v = 6;
2102255332Scy			}
2103145510Sdarrenr			fr->fr_mip.fi_v = 0xf;
2104145510Sdarrenr			fr->fr_ipf->fri_sifpidx = -1;
2105145510Sdarrenr			fr->fr_ipf->fri_difpidx = -1;
2106145510Sdarrenr		}
2107145510Sdarrenr		if (fr->fr_type != FR_T_IPF) {
2108145510Sdarrenr			fprintf(stderr, "IPF Type not set\n");
2109145510Sdarrenr		}
2110145510Sdarrenr	}
2111145510Sdarrenr}
2112145510Sdarrenr
2113145510Sdarrenr
2114145510Sdarrenrstatic frentry_t *addrule()
2115145510Sdarrenr{
2116145510Sdarrenr	frentry_t *f, *f1, *f2;
2117145510Sdarrenr	int count;
2118145510Sdarrenr
2119145510Sdarrenr	for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next)
2120145510Sdarrenr		;
2121145510Sdarrenr
2122145510Sdarrenr	count = nrules;
2123145510Sdarrenr	f = f2;
2124145510Sdarrenr	for (f1 = frc; count > 0; count--, f1 = f1->fr_next) {
2125255332Scy		f->fr_next = allocfr();
2126255332Scy		if (f->fr_next == NULL)
2127255332Scy			return NULL;
2128255332Scy		f->fr_next->fr_pnext = &f->fr_next;
2129145510Sdarrenr		added++;
2130145510Sdarrenr		f = f->fr_next;
2131255332Scy		*f = *f1;
2132145510Sdarrenr		f->fr_next = NULL;
2133145510Sdarrenr		if (f->fr_caddr != NULL) {
2134145510Sdarrenr			f->fr_caddr = malloc(f->fr_dsize);
2135145510Sdarrenr			bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize);
2136145510Sdarrenr		}
2137145510Sdarrenr	}
2138145510Sdarrenr
2139145510Sdarrenr	return f2->fr_next;
2140145510Sdarrenr}
2141145510Sdarrenr
2142145510Sdarrenr
2143255332Scystatic int
2144255332Scylookuphost(name, addrp)
2145255332Scy	char *name;
2146255332Scy	i6addr_t *addrp;
2147145510Sdarrenr{
2148145510Sdarrenr	int i;
2149145510Sdarrenr
2150145510Sdarrenr	hashed = 0;
2151145510Sdarrenr	pooled = 0;
2152145510Sdarrenr	dynamic = -1;
2153145510Sdarrenr
2154145510Sdarrenr	for (i = 0; i < 4; i++) {
2155255332Scy		if (fr->fr_ifnames[i] == -1)
2156255332Scy			continue;
2157255332Scy		if (strcmp(name, fr->fr_names + fr->fr_ifnames[i]) == 0) {
2158145510Sdarrenr			ifpflag = FRI_DYNAMIC;
2159255332Scy			dynamic = addname(&fr, name);
2160255332Scy			return 1;
2161145510Sdarrenr		}
2162145510Sdarrenr	}
2163145510Sdarrenr
2164255332Scy	if (gethost(AF_INET, name, addrp) == -1) {
2165145510Sdarrenr		fprintf(stderr, "unknown name \"%s\"\n", name);
2166255332Scy		return -1;
2167145510Sdarrenr	}
2168255332Scy	return 0;
2169145510Sdarrenr}
2170145510Sdarrenr
2171145510Sdarrenr
2172145510Sdarrenrstatic void dobpf(v, phrase)
2173145510Sdarrenrint v;
2174145510Sdarrenrchar *phrase;
2175145510Sdarrenr{
2176145510Sdarrenr#ifdef IPFILTER_BPF
2177145510Sdarrenr	struct bpf_program bpf;
2178145510Sdarrenr	struct pcap *p;
2179145510Sdarrenr#endif
2180145510Sdarrenr	fakebpf_t *fb;
2181145510Sdarrenr	u_32_t l;
2182145510Sdarrenr	char *s;
2183145510Sdarrenr	int i;
2184145510Sdarrenr
2185145510Sdarrenr	for (fr = frc; fr != NULL; fr = fr->fr_next) {
2186145510Sdarrenr		if (fr->fr_type != FR_T_NONE) {
2187145510Sdarrenr			fprintf(stderr, "cannot mix IPF and BPF matching\n");
2188145510Sdarrenr			return;
2189145510Sdarrenr		}
2190255332Scy		fr->fr_family = vtof(v);
2191145510Sdarrenr		fr->fr_type = FR_T_BPFOPC;
2192145510Sdarrenr
2193153881Sguido		if (!strncmp(phrase, "0x", 2)) {
2194145510Sdarrenr			fb = malloc(sizeof(fakebpf_t));
2195145510Sdarrenr
2196145510Sdarrenr			for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL;
2197145510Sdarrenr			     s = strtok(NULL, " \r\n\t"), i++) {
2198319175Scy				fb = reallocarray(fb, i / 4 + 1, sizeof(*fb));
2199317314Scy				if (fb == NULL) {
2200317314Scy					warnx("memory allocation error at %d in %s in %s", __LINE__, __FUNCTION__, __FILE__);
2201317314Scy					abort();
2202317314Scy				}
2203145510Sdarrenr				l = (u_32_t)strtol(s, NULL, 0);
2204145510Sdarrenr				switch (i & 3)
2205145510Sdarrenr				{
2206145510Sdarrenr				case 0 :
2207145510Sdarrenr					fb[i / 4].fb_c = l & 0xffff;
2208145510Sdarrenr					break;
2209145510Sdarrenr				case 1 :
2210145510Sdarrenr					fb[i / 4].fb_t = l & 0xff;
2211145510Sdarrenr					break;
2212145510Sdarrenr				case 2 :
2213145510Sdarrenr					fb[i / 4].fb_f = l & 0xff;
2214145510Sdarrenr					break;
2215145510Sdarrenr				case 3 :
2216145510Sdarrenr					fb[i / 4].fb_k = l;
2217145510Sdarrenr					break;
2218145510Sdarrenr				}
2219145510Sdarrenr			}
2220145510Sdarrenr			if ((i & 3) != 0) {
2221145510Sdarrenr				fprintf(stderr,
2222145510Sdarrenr					"Odd number of bytes in BPF code\n");
2223145510Sdarrenr				exit(1);
2224145510Sdarrenr			}
2225145510Sdarrenr			i--;
2226145510Sdarrenr			fr->fr_dsize = (i / 4 + 1) * sizeof(*fb);
2227145510Sdarrenr			fr->fr_data = fb;
2228145510Sdarrenr			return;
2229145510Sdarrenr		}
2230145510Sdarrenr
2231145510Sdarrenr#ifdef IPFILTER_BPF
2232145510Sdarrenr		bzero((char *)&bpf, sizeof(bpf));
2233145510Sdarrenr		p = pcap_open_dead(DLT_RAW, 1);
2234145510Sdarrenr		if (!p) {
2235145510Sdarrenr			fprintf(stderr, "pcap_open_dead failed\n");
2236145510Sdarrenr			return;
2237145510Sdarrenr		}
2238145510Sdarrenr
2239145510Sdarrenr		if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) {
2240145510Sdarrenr			pcap_perror(p, "ipf");
2241145510Sdarrenr			pcap_close(p);
2242145510Sdarrenr			fprintf(stderr, "pcap parsing failed (%s)\n", phrase);
2243145510Sdarrenr			return;
2244145510Sdarrenr		}
2245145510Sdarrenr		pcap_close(p);
2246145510Sdarrenr
2247145510Sdarrenr		fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
2248145510Sdarrenr		fr->fr_data = malloc(fr->fr_dsize);
2249145510Sdarrenr		bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize);
2250145510Sdarrenr		if (!bpf_validate(fr->fr_data, bpf.bf_len)) {
2251145510Sdarrenr			fprintf(stderr, "BPF validation failed\n");
2252145510Sdarrenr			return;
2253145510Sdarrenr		}
2254145510Sdarrenr#endif
2255145510Sdarrenr	}
2256145510Sdarrenr
2257145510Sdarrenr#ifdef IPFILTER_BPF
2258145510Sdarrenr	if (opts & OPT_DEBUG)
2259145510Sdarrenr		bpf_dump(&bpf, 0);
2260145510Sdarrenr#else
2261145510Sdarrenr	fprintf(stderr, "BPF filter expressions not supported\n");
2262145510Sdarrenr	exit(1);
2263145510Sdarrenr#endif
2264145510Sdarrenr}
2265145510Sdarrenr
2266145510Sdarrenr
2267145510Sdarrenrstatic void resetaddr()
2268145510Sdarrenr{
2269145510Sdarrenr	hashed = 0;
2270145510Sdarrenr	pooled = 0;
2271145510Sdarrenr	dynamic = -1;
2272145510Sdarrenr}
2273145510Sdarrenr
2274145510Sdarrenr
2275145510Sdarrenrstatic alist_t *newalist(ptr)
2276145510Sdarrenralist_t *ptr;
2277145510Sdarrenr{
2278145510Sdarrenr	alist_t *al;
2279145510Sdarrenr
2280145510Sdarrenr	al = malloc(sizeof(*al));
2281145510Sdarrenr	if (al == NULL)
2282145510Sdarrenr		return NULL;
2283145510Sdarrenr	al->al_not = 0;
2284145510Sdarrenr	al->al_next = ptr;
2285145510Sdarrenr	return al;
2286145510Sdarrenr}
2287145510Sdarrenr
2288145510Sdarrenr
2289255332Scystatic int
2290255332Scymakepool(list)
2291255332Scy	alist_t *list;
2292145510Sdarrenr{
2293145510Sdarrenr	ip_pool_node_t *n, *top;
2294145510Sdarrenr	ip_pool_t pool;
2295145510Sdarrenr	alist_t *a;
2296145510Sdarrenr	int num;
2297145510Sdarrenr
2298145510Sdarrenr	if (list == NULL)
2299145510Sdarrenr		return 0;
2300145510Sdarrenr	top = calloc(1, sizeof(*top));
2301145510Sdarrenr	if (top == NULL)
2302145510Sdarrenr		return 0;
2303255332Scy
2304145510Sdarrenr	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2305255332Scy		if (use_inet6 == 1) {
2306255332Scy#ifdef AF_INET6
2307255332Scy			n->ipn_addr.adf_family = AF_INET6;
2308255332Scy			n->ipn_addr.adf_addr = a->al_i6addr;
2309255332Scy			n->ipn_addr.adf_len = offsetof(addrfamily_t,
2310255332Scy						       adf_addr) + 16;
2311255332Scy			n->ipn_mask.adf_family = AF_INET6;
2312255332Scy			n->ipn_mask.adf_addr = a->al_i6mask;
2313255332Scy			n->ipn_mask.adf_len = offsetof(addrfamily_t,
2314255332Scy						       adf_addr) + 16;
2315255332Scy
2316255332Scy#endif
2317255332Scy		} else {
2318255332Scy			n->ipn_addr.adf_family = AF_INET;
2319255332Scy			n->ipn_addr.adf_addr.in4.s_addr = a->al_1;
2320255332Scy			n->ipn_addr.adf_len = offsetof(addrfamily_t,
2321255332Scy						       adf_addr) + 4;
2322255332Scy			n->ipn_mask.adf_family = AF_INET;
2323255332Scy			n->ipn_mask.adf_addr.in4.s_addr = a->al_2;
2324255332Scy			n->ipn_mask.adf_len = offsetof(addrfamily_t,
2325255332Scy						       adf_addr) + 4;
2326255332Scy		}
2327145510Sdarrenr		n->ipn_info = a->al_not;
2328145510Sdarrenr		if (a->al_next != NULL) {
2329145510Sdarrenr			n->ipn_next = calloc(1, sizeof(*n));
2330145510Sdarrenr			n = n->ipn_next;
2331145510Sdarrenr		}
2332145510Sdarrenr	}
2333145510Sdarrenr
2334145510Sdarrenr	bzero((char *)&pool, sizeof(pool));
2335145510Sdarrenr	pool.ipo_unit = IPL_LOGIPF;
2336145510Sdarrenr	pool.ipo_list = top;
2337255332Scy	num = load_pool(&pool, ipfioctls[IPL_LOGLOOKUP]);
2338145510Sdarrenr
2339145510Sdarrenr	while ((n = top) != NULL) {
2340145510Sdarrenr		top = n->ipn_next;
2341145510Sdarrenr		free(n);
2342145510Sdarrenr	}
2343145510Sdarrenr	return num;
2344145510Sdarrenr}
2345145510Sdarrenr
2346145510Sdarrenr
2347145510Sdarrenrstatic u_int makehash(list)
2348145510Sdarrenralist_t *list;
2349145510Sdarrenr{
2350145510Sdarrenr	iphtent_t *n, *top;
2351145510Sdarrenr	iphtable_t iph;
2352145510Sdarrenr	alist_t *a;
2353145510Sdarrenr	int num;
2354145510Sdarrenr
2355145510Sdarrenr	if (list == NULL)
2356145510Sdarrenr		return 0;
2357145510Sdarrenr	top = calloc(1, sizeof(*top));
2358145510Sdarrenr	if (top == NULL)
2359145510Sdarrenr		return 0;
2360255332Scy
2361145510Sdarrenr	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2362255332Scy		if (a->al_family == AF_INET6) {
2363255332Scy			n->ipe_family = AF_INET6;
2364255332Scy			n->ipe_addr = a->al_i6addr;
2365255332Scy			n->ipe_mask = a->al_i6mask;
2366255332Scy		} else {
2367255332Scy			n->ipe_family = AF_INET;
2368255332Scy			n->ipe_addr.in4_addr = a->al_1;
2369255332Scy			n->ipe_mask.in4_addr = a->al_2;
2370255332Scy		}
2371145510Sdarrenr		n->ipe_value = 0;
2372145510Sdarrenr		if (a->al_next != NULL) {
2373145510Sdarrenr			n->ipe_next = calloc(1, sizeof(*n));
2374145510Sdarrenr			n = n->ipe_next;
2375145510Sdarrenr		}
2376145510Sdarrenr	}
2377145510Sdarrenr
2378145510Sdarrenr	bzero((char *)&iph, sizeof(iph));
2379145510Sdarrenr	iph.iph_unit = IPL_LOGIPF;
2380145510Sdarrenr	iph.iph_type = IPHASH_LOOKUP;
2381145510Sdarrenr	*iph.iph_name = '\0';
2382145510Sdarrenr
2383255332Scy	if (load_hash(&iph, top, ipfioctls[IPL_LOGLOOKUP]) == 0)
2384145510Sdarrenr		sscanf(iph.iph_name, "%u", &num);
2385145510Sdarrenr	else
2386145510Sdarrenr		num = 0;
2387145510Sdarrenr
2388145510Sdarrenr	while ((n = top) != NULL) {
2389145510Sdarrenr		top = n->ipe_next;
2390145510Sdarrenr		free(n);
2391145510Sdarrenr	}
2392145510Sdarrenr	return num;
2393145510Sdarrenr}
2394145510Sdarrenr
2395145510Sdarrenr
2396255332Scyint ipf_addrule(fd, ioctlfunc, ptr)
2397145510Sdarrenrint fd;
2398145510Sdarrenrioctlfunc_t ioctlfunc;
2399145510Sdarrenrvoid *ptr;
2400145510Sdarrenr{
2401145510Sdarrenr	ioctlcmd_t add, del;
2402145510Sdarrenr	frentry_t *fr;
2403145510Sdarrenr	ipfobj_t obj;
2404145510Sdarrenr
2405170268Sdarrenr	if (ptr == NULL)
2406255332Scy		return 0;
2407170268Sdarrenr
2408145510Sdarrenr	fr = ptr;
2409145510Sdarrenr	add = 0;
2410145510Sdarrenr	del = 0;
2411145510Sdarrenr
2412145510Sdarrenr	bzero((char *)&obj, sizeof(obj));
2413145510Sdarrenr	obj.ipfo_rev = IPFILTER_VERSION;
2414255332Scy	obj.ipfo_size = fr->fr_size;
2415145510Sdarrenr	obj.ipfo_type = IPFOBJ_FRENTRY;
2416145510Sdarrenr	obj.ipfo_ptr = ptr;
2417145510Sdarrenr
2418145510Sdarrenr	if ((opts & OPT_DONOTHING) != 0)
2419145510Sdarrenr		fd = -1;
2420145510Sdarrenr
2421145510Sdarrenr	if (opts & OPT_ZERORULEST) {
2422145510Sdarrenr		add = SIOCZRLST;
2423145510Sdarrenr	} else if (opts & OPT_INACTIVE) {
2424145510Sdarrenr		add = (u_int)fr->fr_hits ? SIOCINIFR :
2425145510Sdarrenr					   SIOCADIFR;
2426145510Sdarrenr		del = SIOCRMIFR;
2427145510Sdarrenr	} else {
2428145510Sdarrenr		add = (u_int)fr->fr_hits ? SIOCINAFR :
2429145510Sdarrenr					   SIOCADAFR;
2430145510Sdarrenr		del = SIOCRMAFR;
2431145510Sdarrenr	}
2432145510Sdarrenr
2433161357Sguido	if ((opts & OPT_OUTQUE) != 0)
2434145510Sdarrenr		fr->fr_flags |= FR_OUTQUE;
2435145510Sdarrenr	if (fr->fr_hits)
2436145510Sdarrenr		fr->fr_hits--;
2437170268Sdarrenr	if ((opts & OPT_VERBOSE) != 0)
2438145510Sdarrenr		printfr(fr, ioctlfunc);
2439145510Sdarrenr
2440170268Sdarrenr	if ((opts & OPT_DEBUG) != 0) {
2441145510Sdarrenr		binprint(fr, sizeof(*fr));
2442145510Sdarrenr		if (fr->fr_data != NULL)
2443145510Sdarrenr			binprint(fr->fr_data, fr->fr_dsize);
2444145510Sdarrenr	}
2445145510Sdarrenr
2446145510Sdarrenr	if ((opts & OPT_ZERORULEST) != 0) {
2447145510Sdarrenr		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2448145510Sdarrenr			if ((opts & OPT_DONOTHING) == 0) {
2449255332Scy				char msg[80];
2450255332Scy
2451255332Scy				sprintf(msg, "%d:ioctl(zero rule)",
2452255332Scy					fr->fr_flineno);
2453255332Scy				return ipf_perror_fd(fd, ioctlfunc, msg);
2454145510Sdarrenr			}
2455145510Sdarrenr		} else {
2456145510Sdarrenr#ifdef	USE_QUAD_T
2457145510Sdarrenr			printf("hits %qd bytes %qd ",
2458145510Sdarrenr				(long long)fr->fr_hits,
2459145510Sdarrenr				(long long)fr->fr_bytes);
2460145510Sdarrenr#else
2461145510Sdarrenr			printf("hits %ld bytes %ld ",
2462145510Sdarrenr				fr->fr_hits, fr->fr_bytes);
2463145510Sdarrenr#endif
2464145510Sdarrenr			printfr(fr, ioctlfunc);
2465145510Sdarrenr		}
2466145510Sdarrenr	} else if ((opts & OPT_REMOVE) != 0) {
2467145510Sdarrenr		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
2468255332Scy			if ((opts & OPT_DONOTHING) == 0) {
2469255332Scy				char msg[80];
2470255332Scy
2471255332Scy				sprintf(msg, "%d:ioctl(delete rule)",
2472255332Scy					fr->fr_flineno);
2473255332Scy				return ipf_perror_fd(fd, ioctlfunc, msg);
2474145510Sdarrenr			}
2475145510Sdarrenr		}
2476145510Sdarrenr	} else {
2477145510Sdarrenr		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2478255332Scy			if ((opts & OPT_DONOTHING) == 0) {
2479255332Scy				char msg[80];
2480255332Scy
2481255332Scy				sprintf(msg, "%d:ioctl(add/insert rule)",
2482255332Scy					fr->fr_flineno);
2483255332Scy				return ipf_perror_fd(fd, ioctlfunc, msg);
2484145510Sdarrenr			}
2485145510Sdarrenr		}
2486145510Sdarrenr	}
2487255332Scy	return 0;
2488145510Sdarrenr}
2489145510Sdarrenr
2490145510Sdarrenrstatic void setsyslog()
2491145510Sdarrenr{
2492145510Sdarrenr	yysetdict(logwords);
2493145510Sdarrenr	yybreakondot = 1;
2494145510Sdarrenr}
2495145510Sdarrenr
2496145510Sdarrenr
2497145510Sdarrenrstatic void unsetsyslog()
2498145510Sdarrenr{
2499145510Sdarrenr	yyresetdict();
2500145510Sdarrenr	yybreakondot = 0;
2501145510Sdarrenr}
2502145510Sdarrenr
2503145510Sdarrenr
2504145510Sdarrenrstatic void fillgroup(fr)
2505145510Sdarrenrfrentry_t *fr;
2506145510Sdarrenr{
2507145510Sdarrenr	frentry_t *f;
2508145510Sdarrenr
2509255332Scy	for (f = frold; f != NULL; f = f->fr_next) {
2510255332Scy		if (f->fr_grhead == -1 && fr->fr_group == -1)
2511145510Sdarrenr			break;
2512255332Scy		if (f->fr_grhead == -1 || fr->fr_group == -1)
2513255332Scy			continue;
2514255332Scy		if (strcmp(f->fr_names + f->fr_grhead,
2515255332Scy			   fr->fr_names + fr->fr_group) == 0)
2516255332Scy			break;
2517255332Scy	}
2518255332Scy
2519145510Sdarrenr	if (f == NULL)
2520145510Sdarrenr		return;
2521145510Sdarrenr
2522145510Sdarrenr	/*
2523145510Sdarrenr	 * Only copy down matching fields if the rules are of the same type
2524145510Sdarrenr	 * and are of ipf type.   The only fields that are copied are those
2525145510Sdarrenr	 * that impact the rule parsing itself, eg. need for knowing what the
2526145510Sdarrenr	 * protocol should be for rules with port comparisons in them.
2527145510Sdarrenr	 */
2528145510Sdarrenr	if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF)
2529145510Sdarrenr		return;
2530145510Sdarrenr
2531255332Scy	if (fr->fr_family == 0 && f->fr_family != 0)
2532255332Scy		fr->fr_family = f->fr_family;
2533145510Sdarrenr
2534145510Sdarrenr	if (fr->fr_mproto == 0 && f->fr_mproto != 0)
2535145510Sdarrenr		fr->fr_mproto = f->fr_mproto;
2536145510Sdarrenr	if (fr->fr_proto == 0 && f->fr_proto != 0)
2537145510Sdarrenr		fr->fr_proto = f->fr_proto;
2538145510Sdarrenr
2539145510Sdarrenr	if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) &&
2540255332Scy	    ((f->fr_flx & FI_TCPUDP) != 0)) {
2541145510Sdarrenr		fr->fr_flx |= FI_TCPUDP;
2542255332Scy		fr->fr_mflx |= FI_TCPUDP;
2543255332Scy	}
2544145510Sdarrenr}
2545255332Scy
2546255332Scy
2547255332Scystatic void doipfexpr(line)
2548255332Scychar *line;
2549255332Scy{
2550255332Scy	int *array;
2551255332Scy	char *error;
2552255332Scy
2553255332Scy	array = parseipfexpr(line, &error);
2554255332Scy	if (array == NULL) {
2555255332Scy		fprintf(stderr, "%s:", error);
2556255332Scy		yyerror("error parsing ipf matching expression");
2557255332Scy		return;
2558255332Scy	}
2559255332Scy
2560255332Scy	fr->fr_type = FR_T_IPFEXPR;
2561255332Scy	fr->fr_data = array;
2562255332Scy	fr->fr_dsize = array[0] * sizeof(*array);
2563255332Scy}
2564255332Scy
2565255332Scy
2566255332Scystatic void do_tuneint(varname, value)
2567255332Scychar *varname;
2568255332Scyint value;
2569255332Scy{
2570255332Scy	char buffer[80];
2571255332Scy
2572255332Scy	strncpy(buffer, varname, 60);
2573255332Scy	buffer[59] = '\0';
2574255332Scy	strcat(buffer, "=");
2575255332Scy	sprintf(buffer, "%u", value);
2576255332Scy	ipf_dotuning(ipffd, buffer, ioctl);
2577255332Scy}
2578255332Scy
2579255332Scy
2580255332Scystatic void do_tunestr(varname, value)
2581255332Scychar *varname, *value;
2582255332Scy{
2583255332Scy
2584255332Scy	if (!strcasecmp(value, "true")) {
2585255332Scy		do_tuneint(varname, 1);
2586255332Scy	} else if (!strcasecmp(value, "false")) {
2587255332Scy		do_tuneint(varname, 0);
2588255332Scy	} else {
2589255332Scy		yyerror("did not find true/false where expected");
2590255332Scy	}
2591255332Scy}
2592255332Scy
2593255332Scy
2594255332Scystatic void setifname(frp, idx, name)
2595255332Scyfrentry_t **frp;
2596255332Scyint idx;
2597255332Scychar *name;
2598255332Scy{
2599255332Scy	int pos;
2600255332Scy
2601255332Scy	pos = addname(frp, name);
2602255332Scy	if (pos == -1)
2603255332Scy		return;
2604255332Scy	(*frp)->fr_ifnames[idx] = pos;
2605255332Scy}
2606255332Scy
2607255332Scy
2608255332Scystatic int addname(frp, name)
2609255332Scyfrentry_t **frp;
2610255332Scychar *name;
2611255332Scy{
2612255332Scy	frentry_t *f;
2613255332Scy	int nlen;
2614255332Scy	int pos;
2615255332Scy
2616255332Scy	nlen = strlen(name) + 1;
2617255332Scy	f = realloc(*frp, (*frp)->fr_size + nlen);
2618255332Scy	if (*frp == frc)
2619255332Scy		frc = f;
2620255332Scy	*frp = f;
2621255332Scy	if (f == NULL)
2622255332Scy		return -1;
2623255332Scy	if (f->fr_pnext != NULL)
2624255332Scy		*f->fr_pnext = f;
2625255332Scy	f->fr_size += nlen;
2626255332Scy	pos = f->fr_namelen;
2627255332Scy	f->fr_namelen += nlen;
2628255332Scy	strcpy(f->fr_names + pos, name);
2629255332Scy	f->fr_names[f->fr_namelen] = '\0';
2630255332Scy	return pos;
2631255332Scy}
2632255332Scy
2633255332Scy
2634255332Scystatic frentry_t *allocfr()
2635255332Scy{
2636255332Scy	frentry_t *fr;
2637255332Scy
2638255332Scy	fr = calloc(1, sizeof(*fr));
2639255332Scy	if (fr != NULL) {
2640255332Scy		fr->fr_size = sizeof(*fr);
2641255332Scy		fr->fr_comment = -1;
2642255332Scy		fr->fr_group = -1;
2643255332Scy		fr->fr_grhead = -1;
2644255332Scy		fr->fr_icmphead = -1;
2645255332Scy		fr->fr_ifnames[0] = -1;
2646255332Scy		fr->fr_ifnames[1] = -1;
2647255332Scy		fr->fr_ifnames[2] = -1;
2648255332Scy		fr->fr_ifnames[3] = -1;
2649255332Scy		fr->fr_tif.fd_name = -1;
2650255332Scy		fr->fr_rif.fd_name = -1;
2651255332Scy		fr->fr_dif.fd_name = -1;
2652255332Scy	}
2653255332Scy	return fr;
2654255332Scy}
2655255332Scy
2656255332Scy
2657255332Scystatic void setgroup(frp, name)
2658255332Scyfrentry_t **frp;
2659255332Scychar *name;
2660255332Scy{
2661255332Scy	int pos;
2662255332Scy
2663255332Scy	pos = addname(frp, name);
2664255332Scy	if (pos == -1)
2665255332Scy		return;
2666255332Scy	(*frp)->fr_group = pos;
2667255332Scy}
2668255332Scy
2669255332Scy
2670255332Scystatic void setgrhead(frp, name)
2671255332Scyfrentry_t **frp;
2672255332Scychar *name;
2673255332Scy{
2674255332Scy	int pos;
2675255332Scy
2676255332Scy	pos = addname(frp, name);
2677255332Scy	if (pos == -1)
2678255332Scy		return;
2679255332Scy	(*frp)->fr_grhead = pos;
2680255332Scy}
2681255332Scy
2682255332Scy
2683255332Scystatic void seticmphead(frp, name)
2684255332Scyfrentry_t **frp;
2685255332Scychar *name;
2686255332Scy{
2687255332Scy	int pos;
2688255332Scy
2689255332Scy	pos = addname(frp, name);
2690255332Scy	if (pos == -1)
2691255332Scy		return;
2692255332Scy	(*frp)->fr_icmphead = pos;
2693255332Scy}
2694255332Scy
2695255332Scy
2696255332Scystatic void
2697255332Scybuild_dstaddr_af(fp, ptr)
2698255332Scy	frentry_t *fp;
2699255332Scy	void *ptr;
2700255332Scy{
2701255332Scy	struct ipp_s *ipp = ptr;
2702255332Scy	frentry_t *f = fp;
2703255332Scy
2704255332Scy	if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) {
2705255332Scy		ipp->f = f->fr_family;
2706255332Scy		ipp->v = f->fr_ip.fi_v;
2707255332Scy	}
2708255332Scy	if (ipp->f == AF_INET)
2709255332Scy		ipp->v = 4;
2710255332Scy	else if (ipp->f == AF_INET6)
2711255332Scy		ipp->v = 6;
2712255332Scy
2713255332Scy	for (; f != NULL; f = f->fr_next) {
2714255332Scy		f->fr_ip.fi_dst = ipp->a;
2715255332Scy		f->fr_mip.fi_dst = ipp->m;
2716255332Scy		f->fr_family = ipp->f;
2717255332Scy		f->fr_ip.fi_v = ipp->v;
2718255332Scy		f->fr_mip.fi_v = 0xf;
2719255332Scy		f->fr_datype = ipp->type;
2720255332Scy		if (ipp->ifpos != -1)
2721255332Scy			f->fr_ipf->fri_difpidx = ipp->ifpos;
2722255332Scy	}
2723255332Scy	fr = NULL;
2724255332Scy}
2725255332Scy
2726255332Scy
2727255332Scystatic void
2728255332Scybuild_srcaddr_af(fp, ptr)
2729255332Scy	frentry_t *fp;
2730255332Scy	void *ptr;
2731255332Scy{
2732255332Scy	struct ipp_s *ipp = ptr;
2733255332Scy	frentry_t *f = fp;
2734255332Scy
2735255332Scy	if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) {
2736255332Scy		ipp->f = f->fr_family;
2737255332Scy		ipp->v = f->fr_ip.fi_v;
2738255332Scy	}
2739255332Scy	if (ipp->f == AF_INET)
2740255332Scy		ipp->v = 4;
2741255332Scy	else if (ipp->f == AF_INET6)
2742255332Scy		ipp->v = 6;
2743255332Scy
2744255332Scy	for (; f != NULL; f = f->fr_next) {
2745255332Scy		f->fr_ip.fi_src = ipp->a;
2746255332Scy		f->fr_mip.fi_src = ipp->m;
2747255332Scy		f->fr_family = ipp->f;
2748255332Scy		f->fr_ip.fi_v = ipp->v;
2749255332Scy		f->fr_mip.fi_v = 0xf;
2750255332Scy		f->fr_satype = ipp->type;
2751255332Scy		f->fr_ipf->fri_sifpidx = ipp->ifpos;
2752255332Scy	}
2753255332Scy	fr = NULL;
2754255332Scy}
2755