ipf_y.y revision 172776
1158115Sume/*	$FreeBSD: head/contrib/ipfilter/tools/ipf_y.y 172776 2007-10-18 21:52:14Z darrenr $	*/
2158115Sume
3158115Sume/*
4158115Sume * Copyright (C) 2001-2006 by Darren Reed.
5158115Sume *
6158115Sume * See the IPFILTER.LICENCE file for details on licencing.
7158115Sume */
8158115Sume%{
9158115Sume#include "ipf.h"
10158115Sume#include <sys/ioctl.h>
11158115Sume#include <syslog.h>
12158115Sume#ifdef IPFILTER_BPF
13158115Sume# include "pcap-bpf.h"
14158115Sume# define _NET_BPF_H_
15158115Sume# include <pcap.h>
16158115Sume#endif
17158115Sume#include "netinet/ip_pool.h"
18158115Sume#include "netinet/ip_htable.h"
19158115Sume#include "netinet/ipl.h"
20158115Sume#include "ipf_l.h"
21158115Sume
22158115Sume#define	YYDEBUG	1
23158115Sume#define	DOALL(x)	for (fr = frc; fr != NULL; fr = fr->fr_next) { x }
24158115Sume#define	DOREM(x)	for (; fr != NULL; fr = fr->fr_next) { x }
25158115Sume
26158115Sumeextern	void	yyerror __P((char *));
27158115Sumeextern	int	yyparse __P((void));
28158115Sumeextern	int	yylex __P((void));
29158115Sumeextern	int	yydebug;
30158115Sumeextern	FILE	*yyin;
31194089Sdesextern	int	yylineNum;
32194089Sdes
33158115Sumestatic	void	newrule __P((void));
34194089Sdesstatic	void	setipftype __P((void));
35158115Sumestatic	u_32_t	lookuphost __P((char *));
36194089Sdesstatic	void	dobpf __P((int, char *));
37158115Sumestatic	void	resetaddr __P((void));
38158115Sumestatic	struct	alist_s	*newalist __P((struct alist_s *));
39158115Sumestatic	u_int	makehash __P((struct alist_s *));
40158115Sumestatic	int	makepool __P((struct alist_s *));
41158115Sumestatic	frentry_t *addrule __P((void));
42158115Sumestatic	void	setsyslog __P((void));
43158115Sumestatic	void	unsetsyslog __P((void));
44158115Sumestatic	void	fillgroup __P((frentry_t *));
45158115Sume
46158115Sumefrentry_t	*fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL;
47158115Sume
48158115Sumestatic	int		ifpflag = 0;
49158115Sumestatic	int		nowith = 0;
50158115Sumestatic	int		dynamic = -1;
51158115Sumestatic	int		pooled = 0;
52158115Sumestatic	int		hashed = 0;
53158115Sumestatic	int		nrules = 0;
54158115Sumestatic	int		newlist = 0;
55158115Sumestatic	int		added = 0;
56158115Sumestatic	int		ipffd = -1;
57158115Sumestatic	int		*yycont = 0;
58158115Sumestatic	ioctlfunc_t	ipfioctl[IPL_LOGSIZE];
59158115Sumestatic	addfunc_t	ipfaddfunc = NULL;
60158115Sumestatic	struct	wordtab ipfwords[95];
61158115Sumestatic	struct	wordtab	addrwords[4];
62194087Sdesstatic	struct	wordtab	maskwords[5];
63158115Sumestatic	struct	wordtab icmpcodewords[17];
64158115Sumestatic	struct	wordtab icmptypewords[16];
65158115Sumestatic	struct	wordtab ipv4optwords[25];
66158115Sumestatic	struct	wordtab ipv4secwords[9];
67158115Sumestatic	struct	wordtab ipv6optwords[9];
68158115Sumestatic	struct	wordtab logwords[33];
69158115Sume
70158115Sume%}
71158115Sume%union	{
72158115Sume	char	*str;
73158115Sume	u_32_t	num;
74158115Sume	struct	in_addr	ipa;
75158115Sume	frentry_t	fr;
76158115Sume	frtuc_t	*frt;
77158115Sume	struct	alist_s	*alist;
78158115Sume	u_short	port;
79158115Sume	struct	{
80158115Sume		u_short	p1;
81158115Sume		u_short	p2;
82158115Sume		int	pc;
83158115Sume	} pc;
84194087Sdes	struct	{
85158115Sume		union	i6addr	a;
86158115Sume		union	i6addr	m;
87158115Sume	} ipp;
88158115Sume	union	i6addr	ip6;
89194104Sdes	struct	{
90194104Sdes		char	*if1;
91158115Sume		char	*if2;
92158115Sume	} ifs;
93158115Sume};
94158115Sume
95158115Sume%type	<port>	portnum
96158115Sume%type	<num>	facility priority icmpcode seclevel secname icmptype
97158115Sume%type	<num>	opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr
98158115Sume%type	<num>	portc porteq
99158115Sume%type	<ipa>	hostname ipv4 ipv4mask ipv4_16 ipv4_24
100158115Sume%type	<ip6>	ipv6mask
101158115Sume%type	<ipp>	addr ipaddr
102158115Sume%type	<str>	servicename name interfacename
103158115Sume%type	<pc>	portrange portcomp
104158115Sume%type	<alist>	addrlist poollist
105158115Sume%type	<ifs>	onname
106158115Sume
107158115Sume%token	<num>	YY_NUMBER YY_HEX
108158115Sume%token	<str>	YY_STR
109158115Sume%token		YY_COMMENT
110158115Sume%token		YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
111158115Sume%token		YY_RANGE_OUT YY_RANGE_IN
112158115Sume%token	<ip6>	YY_IPV6
113158115Sume
114158115Sume%token	IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL IPFY_NOMATCH
115158115Sume%token	IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST
116158115Sume%token	IPFY_IN IPFY_OUT
117158115Sume%token	IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA
118158115Sume%token	IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO
119158115Sume%token	IPFY_TOS IPFY_TTL IPFY_PROTO
120158115Sume%token	IPFY_HEAD IPFY_GROUP
121158115Sume%token	IPFY_AUTH IPFY_PREAUTH
122158115Sume%token	IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK
123158115Sume%token	IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP
124158115Sume%token	IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH
125158115Sume%token	IPFY_PPS
126158115Sume%token	IPFY_ESP IPFY_AH
127158115Sume%token	IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT
128158115Sume%token	IPFY_TCPUDP IPFY_TCP IPFY_UDP
129158115Sume%token	IPFY_FLAGS IPFY_MULTICAST
130158115Sume%token	IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER
131158115Sume%token	IPFY_PORT
132158115Sume%token	IPFY_NOW
133158115Sume%token	IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
134158115Sume%token	IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG
135158115Sume%token	IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR
136158115Sume%token	IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
137158115Sume%token	IPFY_SYNC IPFY_FRAGBODY
138158115Sume%token	IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
139158115Sume%token	IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
140158115Sume%token	IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
141158115Sume%token	IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA
142158115Sume%token	IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS
143158115Sume%token	IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP
144158115Sume%token	IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2
145158115Sume%token	IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3
146158115Sume
147158115Sume%token	IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS
148158115Sume%token	IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING
149158115Sume%token	IPFY_IPV6OPT_MOBILITY IPFY_IPV6OPT_ESP IPFY_IPV6OPT_FRAG
150158115Sume
151158115Sume%token	IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH
152158115Sume%token	IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST
153158115Sume%token	IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP
154158115Sume%token	IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD
155158115Sume%token	IPFY_ICMPT_ROUTERSOL
156158115Sume
157158115Sume%token	IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR
158158115Sume%token	IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK
159158115Sume%token	IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO
160158115Sume%token	IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE
161158115Sume%token	IPFY_ICMPC_CUTPRE
162158115Sume
163158115Sume%token	IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH
164158115Sume%token	IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON
165158115Sume%token	IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3
166158115Sume%token	IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7
167158115Sume%token	IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT
168158115Sume%token	IPFY_FAC_LFMT IPFY_FAC_CONSOLE
169158115Sume
170158115Sume%token	IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN
171158115Sume%token	IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG
172158115Sume%%
173158115Sumefile:	line
174158115Sume	| assign
175158115Sume	| file line
176158115Sume	| file assign
177158115Sume	;
178158115Sume
179158115Sumeline:	rule		{ while ((fr = frtop) != NULL) {
180158115Sume				frtop = fr->fr_next;
181158115Sume				fr->fr_next = NULL;
182158115Sume				(*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr);
183158115Sume				fr->fr_next = frold;
184158115Sume				frold = fr;
185158115Sume			  }
186158115Sume			  resetlexer();
187158115Sume			}
188158115Sume	| YY_COMMENT
189158115Sume	;
190158115Sume
191158115Sumexx:					{ newrule(); }
192158115Sume	;
193158115Sume
194158115Sumeassign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
195158115Sume					  resetlexer();
196158115Sume					  free($1);
197158115Sume					  free($3);
198158115Sume					  yyvarnext = 0;
199194104Sdes					}
200194104Sdes	;
201158115Sume
202158115Sumeassigning:
203158115Sume	'='				{ yyvarnext = 1; }
204158115Sume	;
205158115Sume
206158115Sumerule:	inrule eol
207158115Sume	| outrule eol
208158115Sume	;
209158115Sume
210158115Sumeeol:	| ';'
211158115Sume	;
212158115Sume
213158115Sumeinrule:
214158115Sume	rulehead markin inopts rulemain ruletail intag ruletail2
215158115Sume	;
216158115Sume
217158115Sumeoutrule:
218158115Sume	rulehead markout outopts rulemain ruletail outtag ruletail2
219158115Sume	;
220158115Sume
221158115Sumerulehead:
222158115Sume	xx collection action
223158115Sume	| xx insert collection action
224158115Sume	;
225158115Sume
226158115Sumemarkin:	IPFY_IN				{ fr->fr_flags |= FR_INQUE; }
227158115Sume	;
228158115Sume
229158115Sumemarkout:
230158115Sume	IPFY_OUT			{ fr->fr_flags |= FR_OUTQUE; }
231158115Sume	;
232158115Sume
233158115Sumerulemain:
234158115Sume	ipfrule
235158115Sume	| bpfrule
236158115Sume	;
237158115Sume
238158115Sumeipfrule:
239158115Sume	tos ttl proto ip
240158115Sume	;
241158115Sume
242158115Sumebpfrule:
243158115Sume	IPFY_BPFV4 '{' YY_STR '}' 	{ dobpf(4, $3); free($3); }
244158115Sume	| IPFY_BPFV6 '{' YY_STR '}' 	{ dobpf(6, $3); free($3); }
245158115Sume	;
246158115Sume
247158115Sumeruletail:
248158115Sume	with keep head group
249158115Sume	;
250158115Sume
251158115Sumeruletail2:
252158115Sume	pps age new
253158115Sume	;
254158115Sume
255194087Sdesintag:	settagin matchtagin
256158115Sume	;
257158115Sume
258158115Sumeouttag:	settagout matchtagout
259158115Sume	;
260158115Sume
261158115Sumeinsert:
262158115Sume	'@' YY_NUMBER			{ fr->fr_hits = (U_QUAD_T)$2 + 1; }
263158115Sume	;
264158115Sume
265158115Sumecollection:
266158115Sume	| YY_NUMBER			{ fr->fr_collect = $1; }
267158115Sume	;
268158115Sume
269158115Sumeaction:	block
270158115Sume	| IPFY_PASS			{ fr->fr_flags |= FR_PASS; }
271158115Sume	| IPFY_NOMATCH			{ fr->fr_flags |= FR_NOMATCH; }
272158115Sume	| log
273158115Sume	| IPFY_COUNT			{ fr->fr_flags |= FR_ACCOUNT; }
274158115Sume	| auth
275158115Sume	| IPFY_SKIP YY_NUMBER		{ fr->fr_flags |= FR_SKIP;
276158115Sume					  fr->fr_arg = $2; }
277158115Sume	| IPFY_CALL func
278158115Sume	| IPFY_CALL IPFY_NOW func	{ fr->fr_flags |= FR_CALLNOW; }
279158115Sume	;
280158115Sume
281158115Sumeblock:	blocked
282158115Sume	| blocked blockreturn
283158115Sume	;
284158115Sume
285158115Sumeblocked:
286158115Sume	IPFY_BLOCK			{ fr->fr_flags = FR_BLOCK; }
287158115Sume	;
288158115Sumeblockreturn:
289158115Sume	IPFY_RETICMP			{ fr->fr_flags |= FR_RETICMP; }
290158115Sume	| IPFY_RETICMP returncode	{ fr->fr_flags |= FR_RETICMP; }
291158115Sume	| IPFY_RETICMPASDST		{ fr->fr_flags |= FR_FAKEICMP; }
292158115Sume	| IPFY_RETICMPASDST returncode	{ fr->fr_flags |= FR_FAKEICMP; }
293158115Sume	| IPFY_RETRST			{ fr->fr_flags |= FR_RETRST; }
294158115Sume	;
295158115Sume
296158115Sumelog:	IPFY_LOG			{ fr->fr_flags |= FR_LOG; }
297158115Sume	| IPFY_LOG logoptions		{ fr->fr_flags |= FR_LOG; }
298158115Sume	;
299158115Sume
300194087Sdesauth:	IPFY_AUTH			{ fr->fr_flags |= FR_AUTH; }
301158115Sume	| IPFY_AUTH blockreturn		{ fr->fr_flags |= FR_AUTH;}
302158115Sume	| IPFY_PREAUTH			{ fr->fr_flags |= FR_PREAUTH; }
303158115Sume	;
304158115Sume
305158115Sumefunc:	YY_STR '/' YY_NUMBER	{ fr->fr_func = nametokva($1,
306158115Sume							  ipfioctl[IPL_LOGIPF]);
307158115Sume				  fr->fr_arg = $3;
308158115Sume				  free($1); }
309158115Sume	;
310158115Sume
311158115Sumeinopts:
312158115Sume	| inopts inopt
313158115Sume	;
314158115Sume
315158115Sumeinopt:
316158115Sume	logopt
317158115Sume	| quick
318158115Sume	| on
319158115Sume	| dup
320158115Sume	| froute
321158115Sume	| proute
322158115Sume	| replyto
323158115Sume	;
324158115Sume
325158115Sumeoutopts:
326158115Sume	| outopts outopt
327158115Sume	;
328158115Sume
329158115Sumeoutopt:
330158115Sume	logopt
331158115Sume	| quick
332158115Sume	| on
333158115Sume	| dup
334158115Sume	| proute
335158115Sume	| replyto
336158115Sume	;
337158115Sume
338158115Sumetos:	| settos YY_NUMBER	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
339194104Sdes	| settos YY_HEX	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
340194104Sdes	| settos lstart toslist lend
341158115Sume	;
342158115Sume
343158115Sumesettos:	IPFY_TOS			{ setipftype(); }
344158115Sume	;
345158115Sume
346158115Sumetoslist:
347158115Sume	YY_NUMBER	{ DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
348158115Sume	| YY_HEX	{ DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
349158115Sume	| toslist lmore YY_NUMBER
350158115Sume			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
351158115Sume	| toslist lmore YY_HEX
352158115Sume			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
353158115Sume	;
354158115Sume
355158115Sumettl:	| setttl YY_NUMBER
356158115Sume			{ DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
357158115Sume	| setttl lstart ttllist lend
358158115Sume	;
359158115Sume
360158115Sumelstart:	'('				{ newlist = 1; fr = frc; added = 0; }
361158115Sume	;
362158115Sume
363158115Sumelend:	')'				{ nrules += added; }
364158115Sume	;
365158115Sume
366158115Sumelmore:	lanother			{ if (newlist == 1) {
367158115Sume						newlist = 0;
368158115Sume					  }
369158115Sume					  fr = addrule();
370158115Sume					  if (yycont != NULL)
371158115Sume						*yycont = 1;
372158115Sume					}
373158115Sume	;
374158115Sume
375158115Sumelanother:
376158115Sume	| ','
377158115Sume	;
378158115Sume
379158115Sumesetttl:	IPFY_TTL			{ setipftype(); }
380158115Sume	;
381158115Sume
382158115Sumettllist:
383158115Sume	YY_NUMBER	{ DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) }
384158115Sume	| ttllist lmore YY_NUMBER
385158115Sume			{ DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) }
386158115Sume	;
387158115Sume
388158115Sumeproto:	| protox protocol		{ yyresetdict(); }
389158115Sume	;
390158115Sume
391158115Sumeprotox:	IPFY_PROTO			{ setipftype();
392158115Sume					  fr = frc;
393158115Sume					  yysetdict(NULL); }
394158115Sume	;
395158115Sume
396158115Sumeip:	srcdst flags icmp
397158115Sume	;
398158115Sume
399158115Sumegroup:	| IPFY_GROUP YY_STR		{ DOALL(strncpy(fr->fr_group, $2, \
400158115Sume							FR_GROUPLEN); \
401158115Sume							fillgroup(fr););
402158115Sume					  free($2); }
403158115Sume	| IPFY_GROUP YY_NUMBER		{ DOALL(sprintf(fr->fr_group, "%d", \
404158115Sume							$2); \
405158115Sume							fillgroup(fr);) }
406158115Sume	;
407158115Sume
408158115Sumehead:	| IPFY_HEAD YY_STR		{ DOALL(strncpy(fr->fr_grhead, $2, \
409158115Sume							FR_GROUPLEN););
410158115Sume					  free($2); }
411158115Sume	| IPFY_HEAD YY_NUMBER		{ DOALL(sprintf(fr->fr_grhead, "%d", \
412158115Sume							$2);) }
413158115Sume	;
414158115Sume
415158115Sumesettagin:
416158115Sume	| IPFY_SETTAG '(' taginlist ')'
417158115Sume	;
418158115Sume
419158115Sumetaginlist:
420158115Sume	taginspec
421158115Sume	| taginlist ',' taginspec
422158115Sume	;
423158115Sume
424158115Sumetaginspec:
425158115Sume	logtag
426158115Sume	;
427158115Sume
428158115Sumenattag:	IPFY_NAT '=' YY_STR		{ DOALL(strncpy(fr->fr_nattag.ipt_tag,\
429158115Sume						$3, IPFTAG_LEN););
430158115Sume					  free($3); }
431158115Sume	| IPFY_NAT '=' YY_NUMBER	{ DOALL(sprintf(fr->fr_nattag.ipt_tag,\
432158115Sume						"%d", $3 & 0xffffffff);) }
433158115Sume	;
434158115Sume
435158115Sumelogtag:	IPFY_LOG '=' YY_NUMBER		{ DOALL(fr->fr_logtag = $3;) }
436158115Sume	;
437158115Sume
438158115Sumesettagout:
439158115Sume	| IPFY_SETTAG '(' tagoutlist ')'
440158115Sume	;
441158115Sume
442158115Sumetagoutlist:
443158115Sume	tagoutspec
444158115Sume	| tagoutlist ',' tagoutspec
445158115Sume	;
446158115Sume
447158115Sumetagoutspec:
448158115Sume	logtag
449158115Sume	| nattag
450158115Sume	;
451158115Sume
452158115Sumematchtagin:
453158115Sume	| IPFY_MATCHTAG '(' tagoutlist ')'
454158115Sume	;
455158115Sume
456158115Sumematchtagout:
457158115Sume	| IPFY_MATCHTAG '(' taginlist ')'
458158115Sume	;
459158115Sume
460158115Sumepps:	| IPFY_PPS YY_NUMBER		{ DOALL(fr->fr_pps = $2;) }
461158115Sume	;
462158115Sume
463158115Sumenew:	| savegroup file restoregroup
464158115Sume	;
465158115Sume
466158115Sumesavegroup:
467158115Sume	'{'
468158115Sume	;
469158115Sume
470158115Sumerestoregroup:
471158115Sume	'}'
472158115Sume	;
473158115Sume
474158115Sumelogopt:	log
475158115Sume	;
476158115Sume
477158115Sumequick:
478158115Sume	IPFY_QUICK			{ fr->fr_flags |= FR_QUICK; }
479158115Sume	;
480158115Sume
481158115Sumeon:	IPFY_ON onname
482158115Sume	| IPFY_ON lstart onlist lend
483158115Sume	| IPFY_ON onname IPFY_INVIA vianame
484158115Sume	| IPFY_ON onname IPFY_OUTVIA vianame
485158115Sume	;
486158115Sume
487158115Sumeonlist:	onname			{ DOREM(strncpy(fr->fr_ifnames[0], $1.if1, \
488158115Sume					sizeof(fr->fr_ifnames[0])); 	   \
489158115Sume					if ($1.if2 != NULL) {		   \
490158115Sume						strncpy(fr->fr_ifnames[1], \
491158115Sume							$1.if2,		   \
492158115Sume						sizeof(fr->fr_ifnames[1]));\
493158115Sume					}				   \
494158115Sume					) }
495158115Sume	| onlist lmore onname	{ DOREM(strncpy(fr->fr_ifnames[0], $3.if1, \
496158115Sume					sizeof(fr->fr_ifnames[0])); 	   \
497158115Sume					if ($3.if2 != NULL) {		   \
498158115Sume						strncpy(fr->fr_ifnames[1], \
499158115Sume							$3.if2,		   \
500158115Sume						sizeof(fr->fr_ifnames[1]));\
501158115Sume					}				   \
502158115Sume					) }
503158115Sume	;
504158115Sume
505158115Sumeonname:	interfacename
506158115Sume		{ strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
507158115Sume		  $$.if1 = fr->fr_ifnames[0];
508158115Sume		  $$.if2 = NULL;
509158115Sume		  free($1);
510158115Sume		}
511158115Sume	| interfacename ',' interfacename
512158115Sume		{ strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
513158115Sume		  $$.if1 = fr->fr_ifnames[0];
514158115Sume		  free($1);
515158115Sume		  strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1]));
516158115Sume		  $$.if1 = fr->fr_ifnames[1];
517158115Sume		  free($3);
518158115Sume		}
519158115Sume	;
520158115Sume
521158115Sumevianame:
522158115Sume	name
523158115Sume		{ strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
524158115Sume		  free($1);
525158115Sume		}
526158115Sume	| name ',' name
527158115Sume		{ strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
528158115Sume		  free($1);
529158115Sume		  strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3]));
530158115Sume		  free($3);
531158115Sume		}
532158115Sume	;
533158115Sume
534158115Sumedup:	IPFY_DUPTO name
535158115Sume	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
536158115Sume	  free($2);
537194087Sdes	}
538158115Sume	| IPFY_DUPTO name duptoseparator hostname
539158115Sume	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
540158115Sume	  fr->fr_dif.fd_ip = $4;
541158115Sume	  yyexpectaddr = 0;
542158115Sume	  free($2);
543194104Sdes	}
544194104Sdes	| IPFY_DUPTO name duptoseparator YY_IPV6
545158115Sume	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
546158115Sume	  bcopy(&$4, &fr->fr_dif.fd_ip6, sizeof(fr->fr_dif.fd_ip6));
547158115Sume	  yyexpectaddr = 0;
548158115Sume	  free($2);
549158115Sume	}
550158115Sume	;
551158115Sume
552158115Sumeduptoseparator:
553158115Sume	':'	{ yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); }
554158115Sume	;
555158115Sume
556158115Sumefroute:	IPFY_FROUTE			{ fr->fr_flags |= FR_FASTROUTE; }
557158115Sume	;
558158115Sume
559158115Sumeproute:	routeto name
560158115Sume	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
561158115Sume	  free($2);
562158115Sume	}
563158115Sume	| routeto name duptoseparator hostname
564158115Sume	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
565158115Sume	  fr->fr_tif.fd_ip = $4;
566158115Sume	  yyexpectaddr = 0;
567158115Sume	  free($2);
568158115Sume	}
569158115Sume	| routeto name duptoseparator YY_IPV6
570158115Sume	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
571158115Sume	  bcopy(&$4, &fr->fr_tif.fd_ip6, sizeof(fr->fr_tif.fd_ip6));
572158115Sume	  yyexpectaddr = 0;
573158115Sume	  free($2);
574158115Sume	}
575158115Sume	;
576158115Sume
577158115Sumerouteto:
578158115Sume	IPFY_TO
579158115Sume	| IPFY_ROUTETO
580158115Sume	;
581158115Sume
582158115Sumereplyto:
583158115Sume	IPFY_REPLY_TO name
584158115Sume	{ strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
585158115Sume	  free($2);
586158115Sume	}
587158115Sume	| IPFY_REPLY_TO name duptoseparator hostname
588158115Sume	{ strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
589158115Sume	  fr->fr_rif.fd_ip = $4;
590158115Sume	  free($2);
591	}
592	;
593
594logoptions:
595	logoption
596	| logoptions logoption
597	;
598
599logoption:
600	IPFY_BODY			{ fr->fr_flags |= FR_LOGBODY; }
601	| IPFY_FIRST			{ fr->fr_flags |= FR_LOGFIRST; }
602	| IPFY_ORBLOCK			{ fr->fr_flags |= FR_LOGORBLOCK; }
603	| level loglevel		{ unsetsyslog(); }
604	;
605
606returncode:
607	starticmpcode icmpcode ')'	{ fr->fr_icode = $2; yyresetdict(); }
608	;
609
610starticmpcode:
611	'('				{ yysetdict(icmpcodewords); }
612	;
613
614srcdst:	| IPFY_ALL
615	| fromto
616	;
617
618protocol:
619	YY_NUMBER		{ DOREM(fr->fr_proto = $1; \
620					fr->fr_mproto = 0xff;) }
621	| YY_STR		{ if (!strcmp($1, "tcp-udp")) {
622					DOREM(fr->fr_flx |= FI_TCPUDP; \
623					      fr->fr_mflx |= FI_TCPUDP;)
624				  } else {
625					int p = getproto($1);
626					if (p == -1)
627						yyerror("protocol unknown");
628					DOREM(fr->fr_proto = p; \
629						fr->fr_mproto = 0xff;)
630				  }
631				  free($1);
632					}
633	| YY_STR nextstring YY_STR
634				{ if (!strcmp($1, "tcp") &&
635				      !strcmp($3, "udp")) {
636					DOREM(fr->fr_flx |= FI_TCPUDP; \
637					      fr->fr_mflx |= FI_TCPUDP;)
638				  } else
639					YYERROR;
640				  free($1);
641				  free($3);
642				}
643	;
644
645nextstring:
646	'/'			{ yysetdict(NULL); }
647	;
648
649fromto:	from srcobject to dstobject	{ yyexpectaddr = 0; yycont = NULL; }
650	| to dstobject			{ yyexpectaddr = 0; yycont = NULL; }
651	| from srcobject		{ yyexpectaddr = 0; yycont = NULL; }
652	;
653
654from:	IPFY_FROM			{ setipftype();
655					  if (fr == NULL)
656						fr = frc;
657					  yyexpectaddr = 1;
658					  if (yydebug)
659						printf("set yyexpectaddr\n");
660					  yycont = &yyexpectaddr;
661					  yysetdict(addrwords);
662					  resetaddr(); }
663	;
664
665to:	IPFY_TO				{ if (fr == NULL)
666						fr = frc;
667					  yyexpectaddr = 1;
668					  if (yydebug)
669						printf("set yyexpectaddr\n");
670					  yycont = &yyexpectaddr;
671					  yysetdict(addrwords);
672					  resetaddr(); }
673	;
674
675with:	| andwith withlist
676	;
677
678andwith:
679	IPFY_WITH			{ nowith = 0; setipftype(); }
680	| IPFY_AND			{ nowith = 0; setipftype(); }
681	;
682
683flags:	| startflags flagset
684		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
685	| startflags flagset '/' flagset
686		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
687	| startflags '/' flagset
688		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
689	| startflags YY_NUMBER
690		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
691	| startflags '/' YY_NUMBER
692		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
693	| startflags YY_NUMBER '/' YY_NUMBER
694		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
695	| startflags flagset '/' YY_NUMBER
696		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
697	| startflags YY_NUMBER '/' flagset
698		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
699	;
700
701startflags:
702	IPFY_FLAGS	{ if (frc->fr_type != FR_T_IPF)
703				yyerror("flags with non-ipf type rule");
704			  if (frc->fr_proto != IPPROTO_TCP)
705				yyerror("flags with non-TCP rule");
706			}
707	;
708
709flagset:
710	YY_STR				{ $$ = tcpflags($1); free($1); }
711	| YY_HEX			{ $$ = $1; }
712	;
713
714srcobject:
715	{ yyresetdict(); } fromport
716	| srcaddr srcport
717	| '!' srcaddr srcport
718		{ DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
719	;
720
721srcaddr:
722	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
723			bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
724			if (dynamic != -1) { \
725				fr->fr_satype = ifpflag; \
726				fr->fr_ipf->fri_sifpidx = dynamic; \
727			} else if (pooled || hashed) \
728				fr->fr_satype = FRI_LOOKUP;)
729		}
730	| lstart srcaddrlist lend
731	;
732
733srcaddrlist:
734	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
735			bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
736			if (dynamic != -1) { \
737				fr->fr_satype = ifpflag; \
738				fr->fr_ipf->fri_sifpidx = dynamic; \
739			} else if (pooled || hashed) \
740				fr->fr_satype = FRI_LOOKUP;)
741		}
742	| srcaddrlist lmore addr
743		{ DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \
744			bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \
745			if (dynamic != -1) { \
746				fr->fr_satype = ifpflag; \
747				fr->fr_ipf->fri_sifpidx = dynamic; \
748			} else if (pooled || hashed) \
749				fr->fr_satype = FRI_LOOKUP;)
750		}
751	;
752
753srcport:
754	| portcomp
755		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
756	| portrange
757		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
758			fr->fr_stop = $1.p2;) }
759	| porteq lstart srcportlist lend
760		{ yyresetdict(); }
761	;
762
763fromport:
764	portcomp
765		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
766	| portrange
767		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
768			fr->fr_stop = $1.p2;) }
769	| porteq lstart srcportlist lend
770		{ yyresetdict(); }
771	;
772
773srcportlist:
774	portnum		{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) }
775	| portnum ':' portnum
776			{ DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \
777				fr->fr_stop = $3;) }
778	| portnum YY_RANGE_IN portnum
779			{ DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \
780				fr->fr_stop = $3;) }
781	| srcportlist lmore portnum
782			{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) }
783	| srcportlist lmore portnum ':' portnum
784			{ DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $3; \
785				fr->fr_stop = $5;) }
786	| srcportlist lmore portnum YY_RANGE_IN portnum
787			{ DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $3; \
788				fr->fr_stop = $5;) }
789	;
790
791dstobject:
792	{ yyresetdict(); } toport
793	| dstaddr dstport
794	| '!' dstaddr dstport
795			{ DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
796	;
797
798dstaddr:
799	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
800			bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
801			if (dynamic != -1) { \
802				fr->fr_datype = ifpflag; \
803				fr->fr_ipf->fri_difpidx = dynamic; \
804			  } else if (pooled || hashed) \
805				fr->fr_datype = FRI_LOOKUP;)
806		}
807	| lstart dstaddrlist lend
808	;
809
810dstaddrlist:
811	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
812			bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
813			if (dynamic != -1) { \
814				fr->fr_datype = ifpflag; \
815				fr->fr_ipf->fri_difpidx = dynamic; \
816			} else if (pooled || hashed) \
817				fr->fr_datype = FRI_LOOKUP;)
818		}
819	| dstaddrlist lmore addr
820		{ DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \
821			bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \
822			if (dynamic != -1) { \
823				fr->fr_datype = ifpflag; \
824				fr->fr_ipf->fri_difpidx = dynamic; \
825			} else if (pooled || hashed) \
826				fr->fr_datype = FRI_LOOKUP;)
827		}
828	;
829
830
831dstport:
832	| portcomp
833		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
834	| portrange
835		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
836			fr->fr_dtop = $1.p2;) }
837	| porteq lstart dstportlist lend
838		{ yyresetdict(); }
839	;
840
841toport:
842	portcomp
843		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
844	| portrange
845		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
846			fr->fr_dtop = $1.p2;) }
847	| porteq lstart dstportlist lend
848		{ yyresetdict(); }
849	;
850
851dstportlist:
852	portnum		{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) }
853	| portnum ':' portnum
854			{ DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \
855				fr->fr_dtop = $3;) }
856	| portnum YY_RANGE_IN portnum
857			{ DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \
858				fr->fr_dtop = $3;) }
859	| dstportlist lmore portnum
860			{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) }
861	| dstportlist lmore portnum ':' portnum
862			{ DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $3; \
863				fr->fr_dtop = $5;) }
864	| dstportlist lmore portnum YY_RANGE_IN portnum
865			{ DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $3; \
866				fr->fr_dtop = $5;) }
867	;
868
869addr:	pool '/' YY_NUMBER		{ pooled = 1;
870					  $$.a.iplookuptype = IPLT_POOL;
871					  $$.a.iplookupsubtype = 0;
872					  $$.a.iplookupnum = $3; }
873	| pool '/' YY_STR		{ pooled = 1;
874					  $$.a.iplookuptype = IPLT_POOL;
875					  $$.a.iplookupsubtype = 1;
876					  strncpy($$.a.iplookupname, $3,
877						  sizeof($$.a.iplookupname));
878					}
879	| pool '=' '(' poollist ')'	{ pooled = 1;
880					  $$.a.iplookuptype = IPLT_POOL;
881					  $$.a.iplookupsubtype = 0;
882					  $$.a.iplookupnum = makepool($4); }
883	| hash '/' YY_NUMBER		{ hashed = 1;
884					  $$.a.iplookuptype = IPLT_HASH;
885					  $$.a.iplookupsubtype = 0;
886					  $$.a.iplookupnum = $3; }
887	| hash '/' YY_STR		{ pooled = 1;
888					  $$.a.iplookuptype = IPLT_HASH;
889					  $$.a.iplookupsubtype = 1;
890					  strncpy($$.a.iplookupname, $3,
891						  sizeof($$.a.iplookupname));
892					}
893	| hash '=' '(' addrlist ')'	{ hashed = 1;
894					  $$.a.iplookuptype = IPLT_HASH;
895					  $$.a.iplookupsubtype = 0;
896					  $$.a.iplookupnum = makehash($4); }
897	| ipaddr			{ bcopy(&$1, &$$, sizeof($$));
898					  yyexpectaddr = 0; }
899	;
900
901ipaddr:	IPFY_ANY			{ bzero(&($$), sizeof($$));
902					  yyresetdict();
903					  yyexpectaddr = 0; }
904	| hostname			{ $$.a.in4 = $1;
905					  $$.m.in4_addr = 0xffffffff;
906					  yyexpectaddr = 0; }
907	| hostname			{ yyresetdict();
908					  $$.a.in4_addr = $1.s_addr; }
909		maskspace		{ yysetdict(maskwords); }
910		ipv4mask		{ $$.m.in4_addr = $5.s_addr;
911					  $$.a.in4_addr &= $5.s_addr;
912					  yyresetdict();
913					  yyexpectaddr = 0; }
914	| YY_IPV6			{ bcopy(&$1, &$$.a, sizeof($$.a));
915					  fill6bits(128, (u_32_t *)&$$.m);
916					  yyresetdict();
917					  yyexpectaddr = 0; }
918	| YY_IPV6			{ yyresetdict();
919					  bcopy(&$1, &$$.a, sizeof($$.a)); }
920		maskspace		{ yysetdict(maskwords); }
921		ipv6mask		{ bcopy(&$5, &$$.m, sizeof($$.m));
922					  yyresetdict();
923					  yyexpectaddr = 0; }
924	;
925maskspace:
926	'/'
927	| IPFY_MASK
928	;
929
930ipv4mask:
931	ipv4				{ $$ = $1; }
932	| YY_HEX			{ $$.s_addr = htonl($1); }
933	| YY_NUMBER			{ ntomask(4, $1, (u_32_t *)&$$); }
934	| IPFY_BROADCAST		{ if (ifpflag == FRI_DYNAMIC) {
935						$$.s_addr = 0;
936						ifpflag = FRI_BROADCAST;
937					  } else
938						YYERROR;
939					}
940	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
941						$$.s_addr = 0;
942						ifpflag = FRI_NETWORK;
943					  } else
944						YYERROR;
945					}
946	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
947						$$.s_addr = 0;
948						ifpflag = FRI_NETMASKED;
949					  } else
950						YYERROR;
951					}
952	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
953						$$.s_addr = 0;
954						ifpflag = FRI_PEERADDR;
955					  } else
956						YYERROR;
957					}
958	;
959
960ipv6mask:
961	YY_NUMBER			{ ntomask(6, $1, $$.i6); }
962	| IPFY_BROADCAST		{ if (ifpflag == FRI_DYNAMIC) {
963						bzero(&$$, sizeof($$));
964						ifpflag = FRI_BROADCAST;
965					  } else
966						YYERROR;
967					}
968	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
969						bzero(&$$, sizeof($$));
970						ifpflag = FRI_BROADCAST;
971					  } else
972						YYERROR;
973					}
974	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
975						bzero(&$$, sizeof($$));
976						ifpflag = FRI_BROADCAST;
977					  } else
978						YYERROR;
979					}
980	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
981						bzero(&$$, sizeof($$));
982						ifpflag = FRI_BROADCAST;
983					  } else
984						YYERROR;
985					}
986	;
987
988hostname:
989	ipv4				{ $$ = $1; }
990	| YY_NUMBER			{ $$.s_addr = $1; }
991	| YY_HEX			{ $$.s_addr = $1; }
992	| YY_STR			{ $$.s_addr = lookuphost($1);
993					  free($1);
994					}
995	;
996
997addrlist:
998	ipaddr		{ $$ = newalist(NULL);
999			  bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
1000			  bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
1001	| addrlist ',' ipaddr
1002			{ $$ = newalist($1);
1003			  bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
1004			  bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
1005	;
1006
1007pool:	IPFY_POOL	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1008	;
1009
1010hash:	IPFY_HASH	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1011	;
1012
1013poollist:
1014	ipaddr		{ $$ = newalist(NULL);
1015			  bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
1016			  bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
1017	| '!' ipaddr	{ $$ = newalist(NULL);
1018			  $$->al_not = 1;
1019			  bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a));
1020			  bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); }
1021	| poollist ',' ipaddr
1022			{ $$ = newalist($1);
1023			  bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
1024			  bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
1025	| poollist ',' '!' ipaddr
1026			{ $$ = newalist($1);
1027			  $$->al_not = 1;
1028			  bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a));
1029			  bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); }
1030	;
1031
1032port:	IPFY_PORT			{ yyexpectaddr = 0;
1033					  yycont = NULL;
1034					}
1035	;
1036
1037portc:	port compare			{ $$ = $2;
1038					  yysetdict(NULL); }
1039	| porteq			{ $$ = $1; }
1040	;
1041
1042porteq:	port '='			{ $$ = FR_EQUAL;
1043					  yysetdict(NULL); }
1044	;
1045
1046portr:	IPFY_PORT			{ yyexpectaddr = 0;
1047					  yycont = NULL;
1048					  yysetdict(NULL); }
1049	;
1050
1051portcomp:
1052	portc portnum			{ $$.pc = $1;
1053					  $$.p1 = $2;
1054					  yyresetdict(); }
1055	;
1056
1057portrange:
1058	portr portnum range portnum	{ $$.p1 = $2;
1059					  $$.pc = $3;
1060					  $$.p2 = $4;
1061					  yyresetdict(); }
1062	;
1063
1064icmp:	| itype icode
1065	;
1066
1067itype:	seticmptype icmptype
1068	{ DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00););
1069	  yyresetdict();
1070	}
1071	| seticmptype lstart typelist lend	{ yyresetdict(); }
1072	;
1073
1074seticmptype:
1075	IPFY_ICMPTYPE				{ setipftype();
1076						  yysetdict(icmptypewords); }
1077	;
1078
1079icode:	| seticmpcode icmpcode
1080	{ DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff););
1081	  yyresetdict();
1082	}
1083	| seticmpcode lstart codelist lend	{ yyresetdict(); }
1084	;
1085
1086seticmpcode:
1087	IPFY_ICMPCODE				{ yysetdict(icmpcodewords); }
1088	;
1089
1090typelist:
1091	icmptype
1092	{ DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) }
1093	| typelist lmore icmptype
1094	{ DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) }
1095	;
1096
1097codelist:
1098	icmpcode
1099	{ DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) }
1100	| codelist lmore icmpcode
1101	{ DOREM(fr->fr_icmp &= htons(0xff00); fr->fr_icmp |= htons($3); \
1102		fr->fr_icmpm |= htons(0xff);) }
1103	;
1104
1105age:	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1106						fr->fr_age[1] = $2;) }
1107	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1108					{ DOALL(fr->fr_age[0] = $2; \
1109						fr->fr_age[1] = $4;) }
1110	;
1111
1112keep:	| IPFY_KEEP keepstate keep
1113	| IPFY_KEEP keepfrag keep
1114	;
1115
1116keepstate:
1117	IPFY_STATE stateoptlist		{ DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
1118	;
1119
1120keepfrag:
1121	IPFY_FRAGS fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1122	| IPFY_FRAG fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1123	;
1124
1125fragoptlist:
1126	| '(' fragopts ')'
1127	;
1128
1129fragopts:
1130	fragopt lanother fragopts
1131	| fragopt
1132	;
1133
1134fragopt:
1135	IPFY_STRICT			{ DOALL(fr->fr_flags |= FR_FRSTRICT;) }
1136	;
1137
1138stateoptlist:
1139	| '(' stateopts ')'
1140	;
1141
1142stateopts:
1143	stateopt lanother stateopts
1144	| stateopt
1145	;
1146
1147stateopt:
1148	IPFY_LIMIT YY_NUMBER	{ DOALL(fr->fr_statemax = $2;) }
1149	| IPFY_STRICT		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1150						YYERROR; \
1151					  } else \
1152						fr->fr_flags |= FR_STSTRICT;)
1153				}
1154	| IPFY_NEWISN		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1155						YYERROR; \
1156					  } else \
1157						fr->fr_flags |= FR_NEWISN;)
1158				}
1159	| IPFY_NOICMPERR	{ DOALL(fr->fr_flags |= FR_NOICMPERR;) }
1160
1161	| IPFY_SYNC		{ DOALL(fr->fr_flags |= FR_STATESYNC;) }
1162	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1163						fr->fr_age[1] = $2;) }
1164	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1165					{ DOALL(fr->fr_age[0] = $2; \
1166						fr->fr_age[1] = $4;) }
1167	;
1168
1169portnum:
1170	servicename			{ if (getport(frc, $1, &($$)) == -1)
1171						yyerror("service unknown");
1172					  $$ = ntohs($$);
1173					  free($1);
1174					}
1175	| YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
1176						yyerror("invalid port number");
1177					  else
1178						$$ = $1;
1179					}
1180	;
1181
1182withlist:
1183	withopt				{ nowith = 0; }
1184	| withlist withopt		{ nowith = 0; }
1185	| withlist ',' withopt		{ nowith = 0; }
1186	;
1187
1188withopt:
1189	opttype		{ DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) }
1190	| notwith opttype		{ DOALL(fr->fr_mflx |= $2;) }
1191	| ipopt ipopts			{ yyresetdict(); }
1192	| notwith ipopt ipopts		{ yyresetdict(); }
1193	| startv6hdrs ipv6hdrs		{ yyresetdict(); }
1194	;
1195
1196ipopt:	IPFY_OPT			{ yysetdict(ipv4optwords); }
1197	;
1198
1199startv6hdrs:
1200	IPF6_V6HDRS	{ if (use_inet6 == 0)
1201				yyerror("only available with IPv6");
1202			  yysetdict(ipv6optwords);
1203			}
1204	;
1205
1206notwith:
1207	IPFY_NOT			{ nowith = 1; }
1208	| IPFY_NO			{ nowith = 1; }
1209	;
1210
1211opttype:
1212	IPFY_IPOPTS			{ $$ = FI_OPTIONS; }
1213	| IPFY_SHORT			{ $$ = FI_SHORT; }
1214	| IPFY_NAT			{ $$ = FI_NATED; }
1215	| IPFY_BAD			{ $$ = FI_BAD; }
1216	| IPFY_BADNAT			{ $$ = FI_BADNAT; }
1217	| IPFY_BADSRC			{ $$ = FI_BADSRC; }
1218	| IPFY_LOWTTL			{ $$ = FI_LOWTTL; }
1219	| IPFY_FRAG			{ $$ = FI_FRAG; }
1220	| IPFY_FRAGBODY			{ $$ = FI_FRAGBODY; }
1221	| IPFY_FRAGS			{ $$ = FI_FRAG; }
1222	| IPFY_MBCAST			{ $$ = FI_MBCAST; }
1223	| IPFY_MULTICAST		{ $$ = FI_MULTICAST; }
1224	| IPFY_BROADCAST		{ $$ = FI_BROADCAST; }
1225	| IPFY_STATE			{ $$ = FI_STATE; }
1226	| IPFY_OOW			{ $$ = FI_OOW; }
1227	;
1228
1229ipopts:	optlist		{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1230				if (!nowith)
1231					fr->fr_ip.fi_optmsk |= $1;)
1232			}
1233	;
1234
1235optlist:
1236	opt				{ $$ |= $1; }
1237	| optlist ',' opt		{ $$ |= $1 | $3; }
1238	;
1239
1240ipv6hdrs:
1241	ipv6hdrlist	{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1242				if (!nowith)
1243					fr->fr_ip.fi_optmsk |= $1;)
1244			}
1245	;
1246
1247ipv6hdrlist:
1248	ipv6hdr				{ $$ |= $1; }
1249	| ipv6hdrlist ',' ipv6hdr	{ $$ |= $1 | $3; }
1250	;
1251
1252secname:
1253	seclevel			{ $$ |= $1; }
1254	| secname ',' seclevel		{ $$ |= $1 | $3; }
1255	;
1256
1257seclevel:
1258	IPFY_SEC_UNC			{ $$ = secbit(IPSO_CLASS_UNCL); }
1259	| IPFY_SEC_CONF			{ $$ = secbit(IPSO_CLASS_CONF); }
1260	| IPFY_SEC_RSV1			{ $$ = secbit(IPSO_CLASS_RES1); }
1261	| IPFY_SEC_RSV2			{ $$ = secbit(IPSO_CLASS_RES2); }
1262	| IPFY_SEC_RSV3			{ $$ = secbit(IPSO_CLASS_RES3); }
1263	| IPFY_SEC_RSV4			{ $$ = secbit(IPSO_CLASS_RES4); }
1264	| IPFY_SEC_SEC			{ $$ = secbit(IPSO_CLASS_SECR); }
1265	| IPFY_SEC_TS			{ $$ = secbit(IPSO_CLASS_TOPS); }
1266	;
1267
1268icmptype:
1269	YY_NUMBER			{ $$ = $1; }
1270	| IPFY_ICMPT_UNR		{ $$ = ICMP_UNREACH; }
1271	| IPFY_ICMPT_ECHO		{ $$ = ICMP_ECHO; }
1272	| IPFY_ICMPT_ECHOR		{ $$ = ICMP_ECHOREPLY; }
1273	| IPFY_ICMPT_SQUENCH		{ $$ = ICMP_SOURCEQUENCH; }
1274	| IPFY_ICMPT_REDIR		{ $$ = ICMP_REDIRECT; }
1275	| IPFY_ICMPT_TIMEX		{ $$ = ICMP_TIMXCEED; }
1276	| IPFY_ICMPT_PARAMP		{ $$ = ICMP_PARAMPROB; }
1277	| IPFY_ICMPT_TIMEST		{ $$ = ICMP_TSTAMP; }
1278	| IPFY_ICMPT_TIMESTREP		{ $$ = ICMP_TSTAMPREPLY; }
1279	| IPFY_ICMPT_INFOREQ		{ $$ = ICMP_IREQ; }
1280	| IPFY_ICMPT_INFOREP		{ $$ = ICMP_IREQREPLY; }
1281	| IPFY_ICMPT_MASKREQ		{ $$ = ICMP_MASKREQ; }
1282	| IPFY_ICMPT_MASKREP		{ $$ = ICMP_MASKREPLY; }
1283	| IPFY_ICMPT_ROUTERAD		{ $$ = ICMP_ROUTERADVERT; }
1284	| IPFY_ICMPT_ROUTERSOL		{ $$ = ICMP_ROUTERSOLICIT; }
1285	;
1286
1287icmpcode:
1288	YY_NUMBER			{ $$ = $1; }
1289	| IPFY_ICMPC_NETUNR		{ $$ = ICMP_UNREACH_NET; }
1290	| IPFY_ICMPC_HSTUNR		{ $$ = ICMP_UNREACH_HOST; }
1291	| IPFY_ICMPC_PROUNR		{ $$ = ICMP_UNREACH_PROTOCOL; }
1292	| IPFY_ICMPC_PORUNR		{ $$ = ICMP_UNREACH_PORT; }
1293	| IPFY_ICMPC_NEEDF		{ $$ = ICMP_UNREACH_NEEDFRAG; }
1294	| IPFY_ICMPC_SRCFAIL		{ $$ = ICMP_UNREACH_SRCFAIL; }
1295	| IPFY_ICMPC_NETUNK		{ $$ = ICMP_UNREACH_NET_UNKNOWN; }
1296	| IPFY_ICMPC_HSTUNK		{ $$ = ICMP_UNREACH_HOST_UNKNOWN; }
1297	| IPFY_ICMPC_ISOLATE		{ $$ = ICMP_UNREACH_ISOLATED; }
1298	| IPFY_ICMPC_NETPRO		{ $$ = ICMP_UNREACH_NET_PROHIB; }
1299	| IPFY_ICMPC_HSTPRO		{ $$ = ICMP_UNREACH_HOST_PROHIB; }
1300	| IPFY_ICMPC_NETTOS		{ $$ = ICMP_UNREACH_TOSNET; }
1301	| IPFY_ICMPC_HSTTOS		{ $$ = ICMP_UNREACH_TOSHOST; }
1302	| IPFY_ICMPC_FLTPRO		{ $$ = ICMP_UNREACH_ADMIN_PROHIBIT; }
1303	| IPFY_ICMPC_HSTPRE		{ $$ = 14; }
1304	| IPFY_ICMPC_CUTPRE		{ $$ = 15; }
1305	;
1306
1307opt:
1308	IPFY_IPOPT_NOP			{ $$ = getoptbyvalue(IPOPT_NOP); }
1309	| IPFY_IPOPT_RR			{ $$ = getoptbyvalue(IPOPT_RR); }
1310	| IPFY_IPOPT_ZSU		{ $$ = getoptbyvalue(IPOPT_ZSU); }
1311	| IPFY_IPOPT_MTUP		{ $$ = getoptbyvalue(IPOPT_MTUP); }
1312	| IPFY_IPOPT_MTUR		{ $$ = getoptbyvalue(IPOPT_MTUR); }
1313	| IPFY_IPOPT_ENCODE		{ $$ = getoptbyvalue(IPOPT_ENCODE); }
1314	| IPFY_IPOPT_TS			{ $$ = getoptbyvalue(IPOPT_TS); }
1315	| IPFY_IPOPT_TR			{ $$ = getoptbyvalue(IPOPT_TR); }
1316	| IPFY_IPOPT_SEC		{ $$ = getoptbyvalue(IPOPT_SECURITY); }
1317	| IPFY_IPOPT_LSRR		{ $$ = getoptbyvalue(IPOPT_LSRR); }
1318	| IPFY_IPOPT_ESEC		{ $$ = getoptbyvalue(IPOPT_E_SEC); }
1319	| IPFY_IPOPT_CIPSO		{ $$ = getoptbyvalue(IPOPT_CIPSO); }
1320	| IPFY_IPOPT_SATID		{ $$ = getoptbyvalue(IPOPT_SATID); }
1321	| IPFY_IPOPT_SSRR		{ $$ = getoptbyvalue(IPOPT_SSRR); }
1322	| IPFY_IPOPT_ADDEXT		{ $$ = getoptbyvalue(IPOPT_ADDEXT); }
1323	| IPFY_IPOPT_VISA		{ $$ = getoptbyvalue(IPOPT_VISA); }
1324	| IPFY_IPOPT_IMITD		{ $$ = getoptbyvalue(IPOPT_IMITD); }
1325	| IPFY_IPOPT_EIP		{ $$ = getoptbyvalue(IPOPT_EIP); }
1326	| IPFY_IPOPT_FINN		{ $$ = getoptbyvalue(IPOPT_FINN); }
1327	| IPFY_IPOPT_DPS		{ $$ = getoptbyvalue(IPOPT_DPS); }
1328	| IPFY_IPOPT_SDB		{ $$ = getoptbyvalue(IPOPT_SDB); }
1329	| IPFY_IPOPT_NSAPA		{ $$ = getoptbyvalue(IPOPT_NSAPA); }
1330	| IPFY_IPOPT_RTRALRT		{ $$ = getoptbyvalue(IPOPT_RTRALRT); }
1331	| IPFY_IPOPT_UMP		{ $$ = getoptbyvalue(IPOPT_UMP); }
1332	| setsecclass secname
1333			{ DOALL(fr->fr_mip.fi_secmsk |= $2;
1334				if (!nowith)
1335					fr->fr_ip.fi_secmsk |= $2;)
1336			  $$ = 0;
1337			  yyresetdict();
1338			}
1339	;
1340
1341setsecclass:
1342	IPFY_SECCLASS	{ yysetdict(ipv4secwords); }
1343	;
1344
1345ipv6hdr:
1346	IPFY_AH			{ $$ = getv6optbyvalue(IPPROTO_AH); }
1347	| IPFY_IPV6OPT_DSTOPTS	{ $$ = getv6optbyvalue(IPPROTO_DSTOPTS); }
1348	| IPFY_IPV6OPT_ESP	{ $$ = getv6optbyvalue(IPPROTO_ESP); }
1349	| IPFY_IPV6OPT_HOPOPTS	{ $$ = getv6optbyvalue(IPPROTO_HOPOPTS); }
1350	| IPFY_IPV6OPT_IPV6	{ $$ = getv6optbyvalue(IPPROTO_IPV6); }
1351	| IPFY_IPV6OPT_NONE	{ $$ = getv6optbyvalue(IPPROTO_NONE); }
1352	| IPFY_IPV6OPT_ROUTING	{ $$ = getv6optbyvalue(IPPROTO_ROUTING); }
1353	| IPFY_IPV6OPT_FRAG	{ $$ = getv6optbyvalue(IPPROTO_FRAGMENT); }
1354	| IPFY_IPV6OPT_MOBILITY	{ $$ = getv6optbyvalue(IPPROTO_MOBILITY); }
1355	;
1356
1357level:	IPFY_LEVEL			{ setsyslog(); }
1358	;
1359
1360loglevel:
1361	priority			{ fr->fr_loglevel = LOG_LOCAL0|$1; }
1362	| facility '.' priority		{ fr->fr_loglevel = $1 | $3; }
1363	;
1364
1365facility:
1366	IPFY_FAC_KERN			{ $$ = LOG_KERN; }
1367	| IPFY_FAC_USER			{ $$ = LOG_USER; }
1368	| IPFY_FAC_MAIL			{ $$ = LOG_MAIL; }
1369	| IPFY_FAC_DAEMON		{ $$ = LOG_DAEMON; }
1370	| IPFY_FAC_AUTH			{ $$ = LOG_AUTH; }
1371	| IPFY_FAC_SYSLOG		{ $$ = LOG_SYSLOG; }
1372	| IPFY_FAC_LPR			{ $$ = LOG_LPR; }
1373	| IPFY_FAC_NEWS			{ $$ = LOG_NEWS; }
1374	| IPFY_FAC_UUCP			{ $$ = LOG_UUCP; }
1375	| IPFY_FAC_CRON			{ $$ = LOG_CRON; }
1376	| IPFY_FAC_FTP			{ $$ = LOG_FTP; }
1377	| IPFY_FAC_AUTHPRIV		{ $$ = LOG_AUTHPRIV; }
1378	| IPFY_FAC_AUDIT		{ $$ = LOG_AUDIT; }
1379	| IPFY_FAC_LFMT			{ $$ = LOG_LFMT; }
1380	| IPFY_FAC_LOCAL0		{ $$ = LOG_LOCAL0; }
1381	| IPFY_FAC_LOCAL1		{ $$ = LOG_LOCAL1; }
1382	| IPFY_FAC_LOCAL2		{ $$ = LOG_LOCAL2; }
1383	| IPFY_FAC_LOCAL3		{ $$ = LOG_LOCAL3; }
1384	| IPFY_FAC_LOCAL4		{ $$ = LOG_LOCAL4; }
1385	| IPFY_FAC_LOCAL5		{ $$ = LOG_LOCAL5; }
1386	| IPFY_FAC_LOCAL6		{ $$ = LOG_LOCAL6; }
1387	| IPFY_FAC_LOCAL7		{ $$ = LOG_LOCAL7; }
1388	| IPFY_FAC_SECURITY		{ $$ = LOG_SECURITY; }
1389	;
1390
1391priority:
1392	IPFY_PRI_EMERG			{ $$ = LOG_EMERG; }
1393	| IPFY_PRI_ALERT		{ $$ = LOG_ALERT; }
1394	| IPFY_PRI_CRIT			{ $$ = LOG_CRIT; }
1395	| IPFY_PRI_ERR			{ $$ = LOG_ERR; }
1396	| IPFY_PRI_WARN			{ $$ = LOG_WARNING; }
1397	| IPFY_PRI_NOTICE		{ $$ = LOG_NOTICE; }
1398	| IPFY_PRI_INFO			{ $$ = LOG_INFO; }
1399	| IPFY_PRI_DEBUG		{ $$ = LOG_DEBUG; }
1400	;
1401
1402compare:
1403	YY_CMP_EQ			{ $$ = FR_EQUAL; }
1404	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
1405	| YY_CMP_LT			{ $$ = FR_LESST; }
1406	| YY_CMP_LE			{ $$ = FR_LESSTE; }
1407	| YY_CMP_GT			{ $$ = FR_GREATERT; }
1408	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
1409	;
1410
1411range:	YY_RANGE_IN			{ $$ = FR_INRANGE; }
1412	| YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
1413	| ':'				{ $$ = FR_INCRANGE; }
1414	;
1415
1416servicename:
1417	YY_STR				{ $$ = $1; }
1418	;
1419
1420interfacename:	name				{ $$ = $1; }
1421	| name ':' YY_NUMBER
1422		{ $$ = $1;
1423		  fprintf(stderr, "%d: Logical interface %s:%d unsupported, "
1424			  "use the physical interface %s instead.\n",
1425			  yylineNum, $1, $3, $1);
1426		}
1427	;
1428
1429name:	YY_STR				{ $$ = $1; }
1430	| '-'				{ $$ = strdup("-"); }
1431	;
1432
1433ipv4_16:
1434	YY_NUMBER '.' YY_NUMBER
1435		{ if ($1 > 255 || $3 > 255) {
1436			yyerror("Invalid octet string for IP address");
1437			return 0;
1438		  }
1439		  $$.s_addr = ($1 << 24) | ($3 << 16);
1440		  $$.s_addr = htonl($$.s_addr);
1441		}
1442	;
1443
1444ipv4_24:
1445	ipv4_16 '.' YY_NUMBER
1446		{ if ($3 > 255) {
1447			yyerror("Invalid octet string for IP address");
1448			return 0;
1449		  }
1450		  $$.s_addr |= htonl($3 << 8);
1451		}
1452	;
1453
1454ipv4:	ipv4_24 '.' YY_NUMBER
1455		{ if ($3 > 255) {
1456			yyerror("Invalid octet string for IP address");
1457			return 0;
1458		  }
1459		  $$.s_addr |= htonl($3);
1460		}
1461	| ipv4_24
1462	| ipv4_16
1463	;
1464
1465%%
1466
1467
1468static	struct	wordtab ipfwords[95] = {
1469	{ "age",			IPFY_AGE },
1470	{ "ah",				IPFY_AH },
1471	{ "all",			IPFY_ALL },
1472	{ "and",			IPFY_AND },
1473	{ "auth",			IPFY_AUTH },
1474	{ "bad",			IPFY_BAD },
1475	{ "bad-nat",			IPFY_BADNAT },
1476	{ "bad-src",			IPFY_BADSRC },
1477	{ "bcast",			IPFY_BROADCAST },
1478	{ "block",			IPFY_BLOCK },
1479	{ "body",			IPFY_BODY },
1480	{ "bpf-v4",			IPFY_BPFV4 },
1481#ifdef USE_INET6
1482	{ "bpf-v6",			IPFY_BPFV6 },
1483#endif
1484	{ "call",			IPFY_CALL },
1485	{ "code",			IPFY_ICMPCODE },
1486	{ "count",			IPFY_COUNT },
1487	{ "dup-to",			IPFY_DUPTO },
1488	{ "eq",				YY_CMP_EQ },
1489	{ "esp",			IPFY_ESP },
1490	{ "fastroute",			IPFY_FROUTE },
1491	{ "first",			IPFY_FIRST },
1492	{ "flags",			IPFY_FLAGS },
1493	{ "frag",			IPFY_FRAG },
1494	{ "frag-body",			IPFY_FRAGBODY },
1495	{ "frags",			IPFY_FRAGS },
1496	{ "from",			IPFY_FROM },
1497	{ "ge",				YY_CMP_GE },
1498	{ "group",			IPFY_GROUP },
1499	{ "gt",				YY_CMP_GT },
1500	{ "head",			IPFY_HEAD },
1501	{ "icmp",			IPFY_ICMP },
1502	{ "icmp-type",			IPFY_ICMPTYPE },
1503	{ "in",				IPFY_IN },
1504	{ "in-via",			IPFY_INVIA },
1505	{ "ipopt",			IPFY_IPOPTS },
1506	{ "ipopts",			IPFY_IPOPTS },
1507	{ "keep",			IPFY_KEEP },
1508	{ "le",				YY_CMP_LE },
1509	{ "level",			IPFY_LEVEL },
1510	{ "limit",			IPFY_LIMIT },
1511	{ "log",			IPFY_LOG },
1512	{ "lowttl",			IPFY_LOWTTL },
1513	{ "lt",				YY_CMP_LT },
1514	{ "mask",			IPFY_MASK },
1515	{ "match-tag",			IPFY_MATCHTAG },
1516	{ "mbcast",			IPFY_MBCAST },
1517	{ "mcast",			IPFY_MULTICAST },
1518	{ "multicast",			IPFY_MULTICAST },
1519	{ "nat",			IPFY_NAT },
1520	{ "ne",				YY_CMP_NE },
1521	{ "net",			IPFY_NETWORK },
1522	{ "newisn",			IPFY_NEWISN },
1523	{ "no",				IPFY_NO },
1524	{ "no-icmp-err",		IPFY_NOICMPERR },
1525	{ "nomatch",			IPFY_NOMATCH },
1526	{ "now",			IPFY_NOW },
1527	{ "not",			IPFY_NOT },
1528	{ "oow",			IPFY_OOW },
1529	{ "on",				IPFY_ON },
1530	{ "opt",			IPFY_OPT },
1531	{ "or-block",			IPFY_ORBLOCK },
1532	{ "out",			IPFY_OUT },
1533	{ "out-via",			IPFY_OUTVIA },
1534	{ "pass",			IPFY_PASS },
1535	{ "port",			IPFY_PORT },
1536	{ "pps",			IPFY_PPS },
1537	{ "preauth",			IPFY_PREAUTH },
1538	{ "proto",			IPFY_PROTO },
1539	{ "quick",			IPFY_QUICK },
1540	{ "reply-to",			IPFY_REPLY_TO },
1541	{ "return-icmp",		IPFY_RETICMP },
1542	{ "return-icmp-as-dest",	IPFY_RETICMPASDST },
1543	{ "return-rst",			IPFY_RETRST },
1544	{ "route-to",			IPFY_ROUTETO },
1545	{ "sec-class",			IPFY_SECCLASS },
1546	{ "set-tag",			IPFY_SETTAG },
1547	{ "skip",			IPFY_SKIP },
1548	{ "short",			IPFY_SHORT },
1549	{ "state",			IPFY_STATE },
1550	{ "state-age",			IPFY_AGE },
1551	{ "strict",			IPFY_STRICT },
1552	{ "sync",			IPFY_SYNC },
1553	{ "tcp",			IPFY_TCP },
1554	{ "tcp-udp",			IPFY_TCPUDP },
1555	{ "tos",			IPFY_TOS },
1556	{ "to",				IPFY_TO },
1557	{ "ttl",			IPFY_TTL },
1558	{ "udp",			IPFY_UDP },
1559	{ "v6hdrs",			IPF6_V6HDRS },
1560	{ "with",			IPFY_WITH },
1561	{ NULL,				0 }
1562};
1563
1564static	struct	wordtab	addrwords[4] = {
1565	{ "any",			IPFY_ANY },
1566	{ "hash",			IPFY_HASH },
1567	{ "pool",			IPFY_POOL },
1568	{ NULL,				0 }
1569};
1570
1571static	struct	wordtab	maskwords[5] = {
1572	{ "broadcast",			IPFY_BROADCAST },
1573	{ "netmasked",			IPFY_NETMASKED },
1574	{ "network",			IPFY_NETWORK },
1575	{ "peer",			IPFY_PEER },
1576	{ NULL,				0 }
1577};
1578
1579static	struct	wordtab icmptypewords[16] = {
1580	{ "echo",			IPFY_ICMPT_ECHO },
1581	{ "echorep",			IPFY_ICMPT_ECHOR },
1582	{ "inforeq",			IPFY_ICMPT_INFOREQ },
1583	{ "inforep",			IPFY_ICMPT_INFOREP },
1584	{ "maskrep",			IPFY_ICMPT_MASKREP },
1585	{ "maskreq",			IPFY_ICMPT_MASKREQ },
1586	{ "paramprob",			IPFY_ICMPT_PARAMP },
1587	{ "redir",			IPFY_ICMPT_REDIR },
1588	{ "unreach",			IPFY_ICMPT_UNR },
1589	{ "routerad",			IPFY_ICMPT_ROUTERAD },
1590	{ "routersol",			IPFY_ICMPT_ROUTERSOL },
1591	{ "squench",			IPFY_ICMPT_SQUENCH },
1592	{ "timest",			IPFY_ICMPT_TIMEST },
1593	{ "timestrep",			IPFY_ICMPT_TIMESTREP },
1594	{ "timex",			IPFY_ICMPT_TIMEX },
1595	{ NULL,				0 },
1596};
1597
1598static	struct	wordtab icmpcodewords[17] = {
1599	{ "cutoff-preced",		IPFY_ICMPC_CUTPRE },
1600	{ "filter-prohib",		IPFY_ICMPC_FLTPRO },
1601	{ "isolate",			IPFY_ICMPC_ISOLATE },
1602	{ "needfrag",			IPFY_ICMPC_NEEDF },
1603	{ "net-prohib",			IPFY_ICMPC_NETPRO },
1604	{ "net-tos",			IPFY_ICMPC_NETTOS },
1605	{ "host-preced",		IPFY_ICMPC_HSTPRE },
1606	{ "host-prohib",		IPFY_ICMPC_HSTPRO },
1607	{ "host-tos",			IPFY_ICMPC_HSTTOS },
1608	{ "host-unk",			IPFY_ICMPC_HSTUNK },
1609	{ "host-unr",			IPFY_ICMPC_HSTUNR },
1610	{ "net-unk",			IPFY_ICMPC_NETUNK },
1611	{ "net-unr",			IPFY_ICMPC_NETUNR },
1612	{ "port-unr",			IPFY_ICMPC_PORUNR },
1613	{ "proto-unr",			IPFY_ICMPC_PROUNR },
1614	{ "srcfail",			IPFY_ICMPC_SRCFAIL },
1615	{ NULL,				0 },
1616};
1617
1618static	struct	wordtab ipv4optwords[25] = {
1619	{ "addext",			IPFY_IPOPT_ADDEXT },
1620	{ "cipso",			IPFY_IPOPT_CIPSO },
1621	{ "dps",			IPFY_IPOPT_DPS },
1622	{ "e-sec",			IPFY_IPOPT_ESEC },
1623	{ "eip",			IPFY_IPOPT_EIP },
1624	{ "encode",			IPFY_IPOPT_ENCODE },
1625	{ "finn",			IPFY_IPOPT_FINN },
1626	{ "imitd",			IPFY_IPOPT_IMITD },
1627	{ "lsrr",			IPFY_IPOPT_LSRR },
1628	{ "mtup",			IPFY_IPOPT_MTUP },
1629	{ "mtur",			IPFY_IPOPT_MTUR },
1630	{ "nop",			IPFY_IPOPT_NOP },
1631	{ "nsapa",			IPFY_IPOPT_NSAPA },
1632	{ "rr",				IPFY_IPOPT_RR },
1633	{ "rtralrt",			IPFY_IPOPT_RTRALRT },
1634	{ "satid",			IPFY_IPOPT_SATID },
1635	{ "sdb",			IPFY_IPOPT_SDB },
1636	{ "sec",			IPFY_IPOPT_SEC },
1637	{ "ssrr",			IPFY_IPOPT_SSRR },
1638	{ "tr",				IPFY_IPOPT_TR },
1639	{ "ts",				IPFY_IPOPT_TS },
1640	{ "ump",			IPFY_IPOPT_UMP },
1641	{ "visa",			IPFY_IPOPT_VISA },
1642	{ "zsu",			IPFY_IPOPT_ZSU },
1643	{ NULL,				0 },
1644};
1645
1646static	struct	wordtab ipv4secwords[9] = {
1647	{ "confid",			IPFY_SEC_CONF },
1648	{ "reserv-1",			IPFY_SEC_RSV1 },
1649	{ "reserv-2",			IPFY_SEC_RSV2 },
1650	{ "reserv-3",			IPFY_SEC_RSV3 },
1651	{ "reserv-4",			IPFY_SEC_RSV4 },
1652	{ "secret",			IPFY_SEC_SEC },
1653	{ "topsecret",			IPFY_SEC_TS },
1654	{ "unclass",			IPFY_SEC_UNC },
1655	{ NULL,				0 },
1656};
1657
1658static	struct	wordtab ipv6optwords[9] = {
1659	{ "dstopts",			IPFY_IPV6OPT_DSTOPTS },
1660	{ "esp",			IPFY_IPV6OPT_ESP },
1661	{ "frag",			IPFY_IPV6OPT_FRAG },
1662	{ "hopopts",			IPFY_IPV6OPT_HOPOPTS },
1663	{ "ipv6",			IPFY_IPV6OPT_IPV6 },
1664	{ "mobility",			IPFY_IPV6OPT_MOBILITY },
1665	{ "none",			IPFY_IPV6OPT_NONE },
1666	{ "routing",			IPFY_IPV6OPT_ROUTING },
1667	{ NULL,				0 },
1668};
1669
1670static	struct	wordtab logwords[33] = {
1671	{ "kern",			IPFY_FAC_KERN },
1672	{ "user",			IPFY_FAC_USER },
1673	{ "mail",			IPFY_FAC_MAIL },
1674	{ "daemon",			IPFY_FAC_DAEMON },
1675	{ "auth",			IPFY_FAC_AUTH },
1676	{ "syslog",			IPFY_FAC_SYSLOG },
1677	{ "lpr",			IPFY_FAC_LPR },
1678	{ "news",			IPFY_FAC_NEWS },
1679	{ "uucp",			IPFY_FAC_UUCP },
1680	{ "cron",			IPFY_FAC_CRON },
1681	{ "ftp",			IPFY_FAC_FTP },
1682	{ "authpriv",			IPFY_FAC_AUTHPRIV },
1683	{ "audit",			IPFY_FAC_AUDIT },
1684	{ "logalert",			IPFY_FAC_LFMT },
1685	{ "console",			IPFY_FAC_CONSOLE },
1686	{ "security",			IPFY_FAC_SECURITY },
1687	{ "local0",			IPFY_FAC_LOCAL0 },
1688	{ "local1",			IPFY_FAC_LOCAL1 },
1689	{ "local2",			IPFY_FAC_LOCAL2 },
1690	{ "local3",			IPFY_FAC_LOCAL3 },
1691	{ "local4",			IPFY_FAC_LOCAL4 },
1692	{ "local5",			IPFY_FAC_LOCAL5 },
1693	{ "local6",			IPFY_FAC_LOCAL6 },
1694	{ "local7",			IPFY_FAC_LOCAL7 },
1695	{ "emerg",			IPFY_PRI_EMERG },
1696	{ "alert",			IPFY_PRI_ALERT },
1697	{ "crit",			IPFY_PRI_CRIT },
1698	{ "err",			IPFY_PRI_ERR },
1699	{ "warn",			IPFY_PRI_WARN },
1700	{ "notice",			IPFY_PRI_NOTICE },
1701	{ "info",			IPFY_PRI_INFO },
1702	{ "debug",			IPFY_PRI_DEBUG },
1703	{ NULL,				0 },
1704};
1705
1706
1707
1708
1709int ipf_parsefile(fd, addfunc, iocfuncs, filename)
1710int fd;
1711addfunc_t addfunc;
1712ioctlfunc_t *iocfuncs;
1713char *filename;
1714{
1715	FILE *fp = NULL;
1716	char *s;
1717
1718	yylineNum = 1;
1719	yysettab(ipfwords);
1720
1721	s = getenv("YYDEBUG");
1722	if (s != NULL)
1723		yydebug = atoi(s);
1724	else
1725		yydebug = 0;
1726
1727	if (strcmp(filename, "-")) {
1728		fp = fopen(filename, "r");
1729		if (fp == NULL) {
1730			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
1731				STRERROR(errno));
1732			return -1;
1733		}
1734	} else
1735		fp = stdin;
1736
1737	while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1)
1738		;
1739	if (fp != NULL)
1740		fclose(fp);
1741	return 0;
1742}
1743
1744
1745int ipf_parsesome(fd, addfunc, iocfuncs, fp)
1746int fd;
1747addfunc_t addfunc;
1748ioctlfunc_t *iocfuncs;
1749FILE *fp;
1750{
1751	char *s;
1752	int i;
1753
1754	ipffd = fd;
1755	for (i = 0; i <= IPL_LOGMAX; i++)
1756		ipfioctl[i] = iocfuncs[i];
1757	ipfaddfunc = addfunc;
1758
1759	if (feof(fp))
1760		return 0;
1761	i = fgetc(fp);
1762	if (i == EOF)
1763		return 0;
1764	if (ungetc(i, fp) == 0)
1765		return 0;
1766	if (feof(fp))
1767		return 0;
1768	s = getenv("YYDEBUG");
1769	if (s != NULL)
1770		yydebug = atoi(s);
1771	else
1772		yydebug = 0;
1773
1774	yyin = fp;
1775	yyparse();
1776	return 1;
1777}
1778
1779
1780static void newrule()
1781{
1782	frentry_t *frn;
1783
1784	frn = (frentry_t *)calloc(1, sizeof(frentry_t));
1785	for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next)
1786		;
1787	if (fr != NULL)
1788		fr->fr_next = frn;
1789	if (frtop == NULL)
1790		frtop = frn;
1791	fr = frn;
1792	frc = frn;
1793	fr->fr_loglevel = 0xffff;
1794	fr->fr_isc = (void *)-1;
1795	fr->fr_logtag = FR_NOLOGTAG;
1796	fr->fr_type = FR_T_NONE;
1797	if (use_inet6 != 0)
1798		fr->fr_v = 6;
1799	else
1800		fr->fr_v = 4;
1801
1802	nrules = 1;
1803}
1804
1805
1806static void setipftype()
1807{
1808	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1809		if (fr->fr_type == FR_T_NONE) {
1810			fr->fr_type = FR_T_IPF;
1811			fr->fr_data = (void *)calloc(sizeof(fripf_t), 1);
1812			fr->fr_dsize = sizeof(fripf_t);
1813			fr->fr_ip.fi_v = frc->fr_v;
1814			fr->fr_mip.fi_v = 0xf;
1815			fr->fr_ipf->fri_sifpidx = -1;
1816			fr->fr_ipf->fri_difpidx = -1;
1817		}
1818		if (fr->fr_type != FR_T_IPF) {
1819			fprintf(stderr, "IPF Type not set\n");
1820		}
1821	}
1822}
1823
1824
1825static frentry_t *addrule()
1826{
1827	frentry_t *f, *f1, *f2;
1828	int count;
1829
1830	for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next)
1831		;
1832
1833	count = nrules;
1834	f = f2;
1835	for (f1 = frc; count > 0; count--, f1 = f1->fr_next) {
1836		f->fr_next = (frentry_t *)calloc(sizeof(*f), 1);
1837		added++;
1838		f = f->fr_next;
1839		bcopy(f1, f, sizeof(*f));
1840		f->fr_next = NULL;
1841		if (f->fr_caddr != NULL) {
1842			f->fr_caddr = malloc(f->fr_dsize);
1843			bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize);
1844		}
1845	}
1846
1847	return f2->fr_next;
1848}
1849
1850
1851static u_32_t lookuphost(name)
1852char *name;
1853{
1854	u_32_t addr;
1855	int i;
1856
1857	hashed = 0;
1858	pooled = 0;
1859	dynamic = -1;
1860
1861	for (i = 0; i < 4; i++) {
1862		if (strncmp(name, frc->fr_ifnames[i],
1863			    sizeof(frc->fr_ifnames[i])) == 0) {
1864			ifpflag = FRI_DYNAMIC;
1865			dynamic = i;
1866			return 0;
1867		}
1868	}
1869
1870	if (gethost(name, &addr) == -1) {
1871		fprintf(stderr, "unknown name \"%s\"\n", name);
1872		return 0;
1873	}
1874	return addr;
1875}
1876
1877
1878static void dobpf(v, phrase)
1879int v;
1880char *phrase;
1881{
1882#ifdef IPFILTER_BPF
1883	struct bpf_program bpf;
1884	struct pcap *p;
1885#endif
1886	fakebpf_t *fb;
1887	u_32_t l;
1888	char *s;
1889	int i;
1890
1891	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1892		if (fr->fr_type != FR_T_NONE) {
1893			fprintf(stderr, "cannot mix IPF and BPF matching\n");
1894			return;
1895		}
1896		fr->fr_v = v;
1897		fr->fr_type = FR_T_BPFOPC;
1898
1899		if (!strncmp(phrase, "0x", 2)) {
1900			fb = malloc(sizeof(fakebpf_t));
1901
1902			for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL;
1903			     s = strtok(NULL, " \r\n\t"), i++) {
1904				fb = realloc(fb, (i / 4 + 1) * sizeof(*fb));
1905				l = (u_32_t)strtol(s, NULL, 0);
1906				switch (i & 3)
1907				{
1908				case 0 :
1909					fb[i / 4].fb_c = l & 0xffff;
1910					break;
1911				case 1 :
1912					fb[i / 4].fb_t = l & 0xff;
1913					break;
1914				case 2 :
1915					fb[i / 4].fb_f = l & 0xff;
1916					break;
1917				case 3 :
1918					fb[i / 4].fb_k = l;
1919					break;
1920				}
1921			}
1922			if ((i & 3) != 0) {
1923				fprintf(stderr,
1924					"Odd number of bytes in BPF code\n");
1925				exit(1);
1926			}
1927			i--;
1928			fr->fr_dsize = (i / 4 + 1) * sizeof(*fb);
1929			fr->fr_data = fb;
1930			return;
1931		}
1932
1933#ifdef IPFILTER_BPF
1934		bzero((char *)&bpf, sizeof(bpf));
1935		p = pcap_open_dead(DLT_RAW, 1);
1936		if (!p) {
1937			fprintf(stderr, "pcap_open_dead failed\n");
1938			return;
1939		}
1940
1941		if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) {
1942			pcap_perror(p, "ipf");
1943			pcap_close(p);
1944			fprintf(stderr, "pcap parsing failed (%s)\n", phrase);
1945			return;
1946		}
1947		pcap_close(p);
1948
1949		fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
1950		fr->fr_data = malloc(fr->fr_dsize);
1951		bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize);
1952		if (!bpf_validate(fr->fr_data, bpf.bf_len)) {
1953			fprintf(stderr, "BPF validation failed\n");
1954			return;
1955		}
1956#endif
1957	}
1958
1959#ifdef IPFILTER_BPF
1960	if (opts & OPT_DEBUG)
1961		bpf_dump(&bpf, 0);
1962#else
1963	fprintf(stderr, "BPF filter expressions not supported\n");
1964	exit(1);
1965#endif
1966}
1967
1968
1969static void resetaddr()
1970{
1971	hashed = 0;
1972	pooled = 0;
1973	dynamic = -1;
1974}
1975
1976
1977static alist_t *newalist(ptr)
1978alist_t *ptr;
1979{
1980	alist_t *al;
1981
1982	al = malloc(sizeof(*al));
1983	if (al == NULL)
1984		return NULL;
1985	al->al_not = 0;
1986	al->al_next = ptr;
1987	return al;
1988}
1989
1990
1991static int makepool(list)
1992alist_t *list;
1993{
1994	ip_pool_node_t *n, *top;
1995	ip_pool_t pool;
1996	alist_t *a;
1997	int num;
1998
1999	if (list == NULL)
2000		return 0;
2001	top = calloc(1, sizeof(*top));
2002	if (top == NULL)
2003		return 0;
2004
2005	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2006		n->ipn_addr.adf_addr.in4.s_addr = a->al_1;
2007		n->ipn_mask.adf_addr.in4.s_addr = a->al_2;
2008		n->ipn_info = a->al_not;
2009		if (a->al_next != NULL) {
2010			n->ipn_next = calloc(1, sizeof(*n));
2011			n = n->ipn_next;
2012		}
2013	}
2014
2015	bzero((char *)&pool, sizeof(pool));
2016	pool.ipo_unit = IPL_LOGIPF;
2017	pool.ipo_list = top;
2018	num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]);
2019
2020	while ((n = top) != NULL) {
2021		top = n->ipn_next;
2022		free(n);
2023	}
2024	return num;
2025}
2026
2027
2028static u_int makehash(list)
2029alist_t *list;
2030{
2031	iphtent_t *n, *top;
2032	iphtable_t iph;
2033	alist_t *a;
2034	int num;
2035
2036	if (list == NULL)
2037		return 0;
2038	top = calloc(1, sizeof(*top));
2039	if (top == NULL)
2040		return 0;
2041
2042	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2043		n->ipe_addr.in4_addr = a->al_1;
2044		n->ipe_mask.in4_addr = a->al_2;
2045		n->ipe_value = 0;
2046		if (a->al_next != NULL) {
2047			n->ipe_next = calloc(1, sizeof(*n));
2048			n = n->ipe_next;
2049		}
2050	}
2051
2052	bzero((char *)&iph, sizeof(iph));
2053	iph.iph_unit = IPL_LOGIPF;
2054	iph.iph_type = IPHASH_LOOKUP;
2055	*iph.iph_name = '\0';
2056
2057	if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0)
2058		sscanf(iph.iph_name, "%u", &num);
2059	else
2060		num = 0;
2061
2062	while ((n = top) != NULL) {
2063		top = n->ipe_next;
2064		free(n);
2065	}
2066	return num;
2067}
2068
2069
2070void ipf_addrule(fd, ioctlfunc, ptr)
2071int fd;
2072ioctlfunc_t ioctlfunc;
2073void *ptr;
2074{
2075	ioctlcmd_t add, del;
2076	frentry_t *fr;
2077	ipfobj_t obj;
2078
2079	if (ptr == NULL)
2080		return;
2081
2082	fr = ptr;
2083	add = 0;
2084	del = 0;
2085
2086	bzero((char *)&obj, sizeof(obj));
2087	obj.ipfo_rev = IPFILTER_VERSION;
2088	obj.ipfo_size = sizeof(*fr);
2089	obj.ipfo_type = IPFOBJ_FRENTRY;
2090	obj.ipfo_ptr = ptr;
2091
2092	if ((opts & OPT_DONOTHING) != 0)
2093		fd = -1;
2094
2095	if (opts & OPT_ZERORULEST) {
2096		add = SIOCZRLST;
2097	} else if (opts & OPT_INACTIVE) {
2098		add = (u_int)fr->fr_hits ? SIOCINIFR :
2099					   SIOCADIFR;
2100		del = SIOCRMIFR;
2101	} else {
2102		add = (u_int)fr->fr_hits ? SIOCINAFR :
2103					   SIOCADAFR;
2104		del = SIOCRMAFR;
2105	}
2106
2107	if ((opts & OPT_OUTQUE) != 0)
2108		fr->fr_flags |= FR_OUTQUE;
2109	if (fr->fr_hits)
2110		fr->fr_hits--;
2111	if ((opts & OPT_VERBOSE) != 0)
2112		printfr(fr, ioctlfunc);
2113
2114	if ((opts & OPT_DEBUG) != 0) {
2115		binprint(fr, sizeof(*fr));
2116		if (fr->fr_data != NULL)
2117			binprint(fr->fr_data, fr->fr_dsize);
2118	}
2119
2120	if ((opts & OPT_ZERORULEST) != 0) {
2121		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2122			if ((opts & OPT_DONOTHING) == 0) {
2123				fprintf(stderr, "%d:", yylineNum);
2124				perror("ioctl(SIOCZRLST)");
2125			}
2126		} else {
2127#ifdef	USE_QUAD_T
2128			printf("hits %qd bytes %qd ",
2129				(long long)fr->fr_hits,
2130				(long long)fr->fr_bytes);
2131#else
2132			printf("hits %ld bytes %ld ",
2133				fr->fr_hits, fr->fr_bytes);
2134#endif
2135			printfr(fr, ioctlfunc);
2136		}
2137	} else if ((opts & OPT_REMOVE) != 0) {
2138		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
2139			if ((opts & OPT_DONOTHING) != 0) {
2140				fprintf(stderr, "%d:", yylineNum);
2141				perror("ioctl(delete rule)");
2142			}
2143		}
2144	} else {
2145		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2146			if (!(opts & OPT_DONOTHING)) {
2147				fprintf(stderr, "%d:", yylineNum);
2148				perror("ioctl(add/insert rule)");
2149			}
2150		}
2151	}
2152}
2153
2154static void setsyslog()
2155{
2156	yysetdict(logwords);
2157	yybreakondot = 1;
2158}
2159
2160
2161static void unsetsyslog()
2162{
2163	yyresetdict();
2164	yybreakondot = 0;
2165}
2166
2167
2168static void fillgroup(fr)
2169frentry_t *fr;
2170{
2171	frentry_t *f;
2172
2173	for (f = frold; f != NULL; f = f->fr_next)
2174		if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0)
2175			break;
2176	if (f == NULL)
2177		return;
2178
2179	/*
2180	 * Only copy down matching fields if the rules are of the same type
2181	 * and are of ipf type.   The only fields that are copied are those
2182	 * that impact the rule parsing itself, eg. need for knowing what the
2183	 * protocol should be for rules with port comparisons in them.
2184	 */
2185	if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF)
2186		return;
2187
2188	if (fr->fr_v == 0 && f->fr_v != 0)
2189		fr->fr_v = f->fr_v;
2190
2191	if (fr->fr_mproto == 0 && f->fr_mproto != 0)
2192		fr->fr_mproto = f->fr_mproto;
2193	if (fr->fr_proto == 0 && f->fr_proto != 0)
2194		fr->fr_proto = f->fr_proto;
2195
2196	if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) &&
2197	    ((f->fr_flx & FI_TCPUDP) != 0))
2198		fr->fr_flx |= FI_TCPUDP;
2199}
2200