ipf_y.y revision 1448:768e2e711c1a
1%{
2/*
3 * Copyright (C) 2003 by Darren Reed.
4 *
5 * See the IPFILTER.LICENCE file for details on licencing.
6 *
7 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
8 * Use is subject to license terms.
9 */
10
11#pragma ident	"%Z%%M%	%I%	%E% SMI"
12
13#include "ipf.h"
14#include <netinet/ip_icmp.h>
15#include <sys/ioctl.h>
16#include <syslog.h>
17#ifdef IPFILTER_BPF
18# include <net/bpf.h>
19# include <pcap-int.h>
20# include <pcap.h>
21#endif
22#if SOLARIS2 >= 10
23#include "ip_pool.h"
24#include "ip_htable.h"
25#include "ipl.h"
26#else
27#include "netinet/ip_pool.h"
28#include "netinet/ip_htable.h"
29#include "netinet/ipl.h"
30#endif
31#include "ipf_l.h"
32
33#define	YYDEBUG	1
34#define	DOALL(x)	for (fr = frc; fr != NULL; fr = fr->fr_next) { x }
35#define	DOREM(x)	for (; fr != NULL; fr = fr->fr_next) { x }
36#if SOLARIS2 >= 10
37#define VNI	"vni"
38#define VNISTRLEN 3
39#endif
40
41#define OPTION_LOG		0x1
42#define OPTION_QUICK		0x2
43#define OPTION_DUP		0x4
44#define OPTION_PROUTE		0x8
45#define OPTION_ON		0x10
46#define OPTION_REPLYTO		0x20
47#define OPTION_FROUTE		0x40
48
49extern	void	yyerror __P((char *));
50extern	int	yyparse __P((void));
51extern	int	yylex __P((void));
52extern	int	yydebug;
53extern	FILE	*yyin;
54extern	int	yylineNum;
55
56static	void	newrule __P((void));
57static	void	setipftype __P((void));
58static	u_32_t	lookuphost __P((char *));
59static	void	dobpf __P((char *));
60static	void	resetaddr __P((void));
61static	struct	alist_s	*newalist __P((struct alist_s *));
62static	u_int	makehash __P((struct alist_s *));
63static	int	makepool __P((struct alist_s *));
64static	frentry_t *addrule __P((void));
65static	void	setsyslog __P((void));
66static	void	unsetsyslog __P((void));
67static	void	fillgroup __P((frentry_t *));
68
69frentry_t	*fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL;
70
71static	int		ifpflag = 0;
72static	int		nowith = 0;
73static	int		dynamic = -1;
74static	int		pooled = 0;
75static	int		hashed = 0;
76static	int		nrules = 0;
77static	int		newlist = 0;
78static	int		added = 0;
79static	int		ipffd = -1;
80static	int		*yycont = 0;
81static	int		ruleopts = 0;
82static	ioctlfunc_t	ipfioctl[IPL_LOGSIZE];
83static	addfunc_t	ipfaddfunc = NULL;
84static	wordtab_t	addrwords[4];
85static	wordtab_t	maskwords[5];
86static	wordtab_t	*savewords;
87static	int		set_ipv6_addr = 0;
88
89%}
90%union	{
91	char	*str;
92	u_32_t	num;
93	struct	in_addr	ipa;
94	frentry_t	fr;
95	frtuc_t	*frt;
96	struct	alist_s	*alist;
97	struct	{
98		u_short	p1;
99		u_short	p2;
100		int	pc;
101	} pc;
102	struct	{
103		union	i6addr	a;
104		union	i6addr	m;
105	} ipp;
106	union	i6addr	ip6;
107};
108
109%type	<num>	portnum facility priority icmpcode seclevel secname icmptype
110%type	<num>	opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr
111%type	<num>	portc porteq
112%type	<ipa>	hostname ipv4 ipv4mask
113%type	<ip6>	ipv6mask
114%type	<ipp>	addr ipaddr
115%type	<str>	servicename name interfacename
116%type	<pc>	portrange portcomp
117%type	<alist>	addrlist poollist
118
119%token	<num>	YY_NUMBER YY_HEX
120%token	<str>	YY_STR
121%token		YY_COMMENT
122%token		YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
123%token		YY_RANGE_OUT YY_RANGE_IN
124%token	<ip6>	YY_IPV6
125
126%token	IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL
127%token	IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST
128%token	IPFY_IN IPFY_OUT
129%token	IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA
130%token	IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO
131%token	IPFY_TOS IPFY_TTL IPFY_PROTO
132%token	IPFY_HEAD IPFY_GROUP
133%token	IPFY_AUTH IPFY_PREAUTH IPFY_DIVERT
134%token	IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK
135%token	IPFY_LOGTAG IPFY_TAG IPFY_SKIP
136%token	IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPF IPFY_POOL IPFY_HASH
137%token	IPFY_PPS
138%token	IPFY_ESP IPFY_AH
139%token	IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT
140%token	IPFY_TCPUDP IPFY_TCP IPFY_UDP
141%token	IPFY_FLAGS IPFY_MULTICAST
142%token	IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER
143%token	IPFY_PORT
144%token	IPFY_NOW
145%token	IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
146%token	IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG
147%token	IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR
148%token	IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
149%token	IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
150%token	IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
151%token	IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
152%token	IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA
153%token	IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS
154%token	IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP
155%token	IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2
156%token	IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3
157
158%token	IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS
159%token	IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING
160
161%token	IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH
162%token	IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST
163%token	IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP
164%token	IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD
165%token	IPFY_ICMPT_ROUTERSOL
166
167%token	IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR
168%token	IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK
169%token	IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO
170%token	IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE
171%token	IPFY_ICMPC_CUTPRE
172
173%token	IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH
174%token	IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON
175%token	IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3
176%token	IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7
177%token	IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT
178%token	IPFY_FAC_LFMT IPFY_FAC_CONSOLE
179
180%token	IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN
181%token	IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG
182%%
183file:	line
184	| assign
185	| file line
186	| file assign
187	;
188
189line:	xx rule		{ while ((fr = frtop) != NULL) {
190				frtop = fr->fr_next;
191				fr->fr_next = NULL;
192				(*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr);
193				fr->fr_next = frold;
194				frold = fr;
195			  }
196			  resetlexer();
197			}
198	| YY_COMMENT
199	;
200
201xx:	{ newrule(); }
202	;
203
204assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
205					  resetlexer();
206					  free($1);
207					  free($3);
208					}
209	;
210
211assigning:
212	'='				{ yyvarnext = 1; }
213	;
214
215rule:	inrule
216	| outrule
217	;
218
219inrule:
220	rulehead markin { ruleopts = 0; } inopts rulemain ruletail
221	;
222
223outrule:
224	rulehead markout { ruleopts = 0; } outopts rulemain ruletail
225	;
226
227rulehead:
228	collection action
229	| insert collection action
230	;
231
232markin:	IPFY_IN				{ fr->fr_flags |= FR_INQUE; }
233	;
234
235markout:
236	IPFY_OUT			{ fr->fr_flags |= FR_OUTQUE; }
237	;
238
239rulemain:
240	ipfrule
241	| bpfrule
242	;
243
244ipfrule:
245	tos ttl proto ip
246	;
247
248bpfrule:
249	IPFY_BPF '{' YY_STR '}' 	{ dobpf($3); free($3); }
250	;
251
252ruletail:
253	keep head group tag pps age new
254	;
255
256insert:
257	'@' YY_NUMBER			{ fr->fr_hits = (U_QUAD_T)$2; }
258	;
259
260collection:
261	| YY_NUMBER			{ fr->fr_collect = $1; }
262	;
263
264action:	block
265	| IPFY_PASS			{ fr->fr_flags |= FR_PASS; }
266	| IPFY_DIVERT YY_NUMBER		{ fr->fr_flags |= FR_DIVERT;
267					  fr->fr_arg = $2; }
268	| log
269	| IPFY_COUNT			{ fr->fr_flags |= FR_ACCOUNT; }
270	| auth
271	| IPFY_SKIP YY_NUMBER		{ fr->fr_flags |= FR_SKIP;
272					  fr->fr_arg = $2; }
273	| IPFY_CALL func
274	| IPFY_CALL IPFY_NOW func	{ fr->fr_flags |= FR_CALLNOW; }
275	;
276
277block:	blocked
278	| blocked blockreturn
279	;
280
281blocked:
282	IPFY_BLOCK			{ fr->fr_flags = FR_BLOCK; }
283	;
284blockreturn:
285	IPFY_RETICMP			{ fr->fr_flags |= FR_RETICMP; }
286	| IPFY_RETICMP returncode	{ fr->fr_flags |= FR_RETICMP; }
287	| IPFY_RETICMPASDST		{ fr->fr_flags |= FR_FAKEICMP; }
288	| IPFY_RETICMPASDST returncode	{ fr->fr_flags |= FR_FAKEICMP; }
289	| IPFY_RETRST			{ fr->fr_flags |= FR_RETRST; }
290	;
291
292log:	IPFY_LOG			{ fr->fr_flags |= FR_LOG; }
293	| IPFY_LOG logoptions		{ fr->fr_flags |= FR_LOG; }
294	;
295
296auth:	IPFY_AUTH			{ fr->fr_flags |= FR_AUTH; }
297	| IPFY_AUTH IPFY_RETRST		{ fr->fr_flags |= (FR_AUTH|FR_RETRST);}
298	| IPFY_PREAUTH			{ fr->fr_flags |= FR_PREAUTH; }
299	;
300
301func:	YY_STR '/' YY_NUMBER	{ fr->fr_func = nametokva($1,
302							  ipfioctl[IPL_LOGIPF]);
303				  fr->fr_arg = $3;
304				  free($1); }
305	;
306
307inopts:
308	| inopts inopt
309	;
310
311inopt:
312	logopt
313	{
314		if ( ruleopts & OPTION_LOG )
315			yyerror("Duplicate log option");
316		ruleopts |= OPTION_LOG;
317	}
318	| quick
319	{
320		if ( ruleopts & OPTION_QUICK )
321			yyerror("Duplicate quick option");
322		ruleopts |= OPTION_QUICK;
323	}
324	| on
325	{
326		if ( ruleopts & OPTION_ON )
327			yyerror("Duplicate on option");
328		ruleopts |= OPTION_ON;
329	}
330	| dup
331	{
332		if ( ruleopts & OPTION_DUP )
333			yyerror("Duplicate dup option");
334		ruleopts |= OPTION_DUP;
335	}
336	| froute
337	{
338		if ( ruleopts & OPTION_FROUTE )
339			yyerror("Duplicate froute option");
340		ruleopts |= OPTION_FROUTE;
341	}
342	| proute
343	{
344		if ( ruleopts & OPTION_PROUTE )
345			yyerror("Duplicate proute option");
346		ruleopts |= OPTION_PROUTE;
347	}
348	| replyto
349	{
350		if ( ruleopts & OPTION_REPLYTO )
351			yyerror("Duplicate replyto option");
352		ruleopts |= OPTION_REPLYTO;
353	}
354	;
355
356outopts:
357	| outopts outopt
358	;
359
360outopt:
361	logopt
362	{
363		if ( ruleopts & OPTION_LOG )
364			yyerror("Duplicate log option");
365		ruleopts |= OPTION_LOG;
366	}
367	| quick
368	{
369		if ( ruleopts & OPTION_QUICK )
370			yyerror("Duplicate quick option");
371		ruleopts |= OPTION_QUICK;
372	}
373	| on
374	{
375		if ( ruleopts & OPTION_ON )
376			yyerror("Duplicate on option");
377		ruleopts |= OPTION_ON;
378	}
379	| dup
380	{
381		if ( ruleopts & OPTION_DUP )
382			yyerror("Duplicate dup option");
383		ruleopts |= OPTION_DUP;
384	}
385	| proute
386	{
387		if ( ruleopts & OPTION_PROUTE )
388			yyerror("Duplicate proute option");
389		ruleopts |= OPTION_PROUTE;
390	}
391	| replyto
392	{
393		if ( ruleopts & OPTION_REPLYTO )
394			yyerror("Duplicate replyto option");
395		ruleopts |= OPTION_REPLYTO;
396	}
397	;
398
399tos:	| settos YY_NUMBER	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
400	| settos YY_HEX	{ DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) }
401	| settos lstart toslist lend
402	;
403
404settos:	IPFY_TOS			{ setipftype(); }
405	;
406
407toslist:
408	YY_NUMBER	{ DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
409	| YY_HEX	{ DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) }
410	| toslist lmore YY_NUMBER
411			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
412	| toslist lmore YY_HEX
413			{ DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) }
414	;
415
416ttl:	| setttl YY_NUMBER
417			{ DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
418	| setttl lstart ttllist lend
419	;
420
421lstart:	'('				{ newlist = 1; fr = frc; added = 0; }
422	;
423
424lend:	')'				{ nrules += added; }
425	;
426
427lmore:	lanother			{ if (newlist == 1) {
428						newlist = 0;
429					  }
430					  fr = addrule();
431					  if (yycont != NULL)
432					  	*yycont = 1;
433					}
434	;
435
436lanother:
437	| ','
438	;
439
440setttl:	IPFY_TTL			{ setipftype(); }
441	;
442
443ttllist:
444	YY_NUMBER	{ DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) }
445	| ttllist lmore YY_NUMBER
446			{ DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) }
447	;
448
449proto:	| protox protocol		{ yyresetdict(); }
450	;
451
452protox:	IPFY_PROTO			{ setipftype();
453					  fr = frc;
454					  yysetdict(NULL); }
455	;
456
457ip:	srcdst flags with icmp
458	;
459
460group:	| IPFY_GROUP YY_STR		{ DOALL(strncpy(fr->fr_group, $2, \
461							FR_GROUPLEN); \
462							fillgroup(fr););
463					  free($2); }
464	| IPFY_GROUP YY_NUMBER		{ DOALL(sprintf(fr->fr_group, "%d", \
465							$2); \
466							fillgroup(fr);) }
467	;
468
469head:	| IPFY_HEAD YY_STR		{ DOALL(strncpy(fr->fr_grhead, $2, \
470							FR_GROUPLEN););
471					  free($2); }
472	| IPFY_HEAD YY_NUMBER		{ DOALL(sprintf(fr->fr_grhead, "%d", \
473							$2);) }
474	;
475
476tag:	| IPFY_TAG YY_NUMBER		{ DOALL(fr->fr_logtag = $2;) }
477	| IPFY_TAG '(' taglist ')'
478
479taglist:
480	tagspec
481	| taglist ',' tagspec
482	;
483
484tagspec:
485	IPFY_NAT '=' YY_STR		{ DOALL(strncpy(fr->fr_nattag.ipt_tag,\
486						$3, 16););
487					  free($3); }
488	| IPFY_NAT '=' YY_NUMBER	{ DOALL(sprintf(fr->fr_nattag.ipt_tag,\
489						"%15d", $3);) }
490	| IPFY_LOG '=' YY_NUMBER	{ DOALL(fr->fr_logtag = $3;) }
491	;
492
493pps:	| IPFY_PPS YY_NUMBER		{ DOALL(fr->fr_pps = $2;) }
494	;
495
496new:	| savegroup file restoregroup
497	;
498
499savegroup:
500	'{'
501	;
502
503restoregroup:
504	'}'
505	;
506
507logopt:	log
508	;
509
510quick:
511	IPFY_QUICK			{ fr->fr_flags |= FR_QUICK; }
512	;
513
514on:	IPFY_ON onname
515	| IPFY_ON onname IPFY_INVIA vianame
516	| IPFY_ON onname IPFY_OUTVIA vianame
517	;
518
519onname:	interfacename
520		{
521#if SOLARIS2 >=10
522		char *cp;
523#endif
524		strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
525#if SOLARIS2 >= 10
526		if (strncmp(VNI, $1, VNISTRLEN) == 0) {
527			cp = $1 + VNISTRLEN;
528			cp += strspn(cp, "0123456789");
529			if (*cp == '\0' || *cp == ':') {
530				fprintf(stderr, "%d: Warning- %s specified. vni"
531				    " is a virtual interface, use a physical"
532				    " interface instead. See vni(7D)\n",
533				    yylineNum, $1);
534			}
535		}
536#endif
537		  free($1);
538		}
539	| interfacename ',' name
540		{
541#if SOLARIS2 >= 10
542		char *cp;
543#endif
544		strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0]));
545#if SOLARIS2 >= 10
546		if (strncmp(VNI, $1, VNISTRLEN) == 0) {
547			cp = $1 + VNISTRLEN;
548			cp += strspn(cp, "0123456789");
549			if (*cp == '\0' || *cp == ':') {
550				fprintf(stderr, "%d: Warning- %s specified. vni"
551				    " is a virtual interface, use a physical"
552				    " interface instead. See vni(7D)\n",
553				    yylineNum, $1);
554			}
555		}
556#endif
557		  free($1);
558		  strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1]));
559#if SOLARIS2 >= 10
560		if (strncmp(VNI, $3, VNISTRLEN) == 0) {
561			cp = $3 + VNISTRLEN;
562			cp += strspn(cp, "0123456789");
563			if (*cp == '\0' || *cp == ':') {
564				fprintf(stderr, "%d: Warning- %s specified. vni"
565				    " is a virtual interface, use a physical"
566				    " interface instead. See vni(7D)\n",
567				    yylineNum, $3);
568			}
569		}
570#endif
571		  free($3);
572		}
573	;
574
575vianame:
576	interfacename
577		{
578#if SOLARIS2 >= 10
579		char *cp;
580#endif
581		strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
582#if SOLARIS2 >= 10
583		if (strncmp(VNI, $1, VNISTRLEN) == 0) {
584			cp = $1 + VNISTRLEN;
585			cp += strspn(cp, "0123456789");
586			if (*cp == '\0' || *cp == ':') {
587				fprintf(stderr, "%d: Warning- %s specified. vni"
588				    " is a virtual interface, use a physical"
589				    " interface instead. See vni(7D)\n",
590				    yylineNum, $1);
591			}
592		}
593#endif
594		  free($1);
595		}
596	| interfacename ',' name
597		{
598#if SOLARIS2 >= 10
599		char *cp;
600#endif
601		strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2]));
602#if SOLARIS2 >= 10
603		if (strncmp(VNI, $1, VNISTRLEN) == 0) {
604			cp = $1 + VNISTRLEN;
605			cp += strspn(cp, "0123456789");
606			if (*cp == '\0' || *cp == ':') {
607				fprintf(stderr, "%d: Warning- %s specified. vni"
608				    " is a virtual interface, use a physical"
609				    " interface instead. See vni(7D)\n",
610				    yylineNum, $1);
611			}
612		}
613#endif
614		  free($1);
615		  strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3]));
616#if SOLARIS2 >= 10
617		if (strncmp(VNI, $3, VNISTRLEN) == 0) {
618			cp = $3 + VNISTRLEN;
619			cp += strspn(cp, "0123456789");
620			if (*cp == '\0' || *cp == ':') {
621				fprintf(stderr, "%d: Warning- %s specified. vni"
622				    " is a virtual interface, use a physical"
623				    " interface instead. See vni(7D)\n",
624				    yylineNum, $3);
625			}
626		}
627#endif
628		  free($3);
629		}
630	;
631
632dup:	IPFY_DUPTO name
633	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
634	  free($2);
635	}
636	| IPFY_DUPTO name ':' hostname
637	{ strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname));
638	  fr->fr_dif.fd_ip = $4;
639	  free($2);
640	}
641	;
642
643froute:	IPFY_FROUTE			{ fr->fr_flags |= FR_FASTROUTE; }
644	;
645
646proute:	IPFY_TO name
647	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
648	  free($2);
649	}
650	| IPFY_TO name ':' hostname
651	{ strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname));
652	  fr->fr_tif.fd_ip = $4;
653	  free($2);
654	}
655	;
656
657replyto:
658	IPFY_REPLY_TO name
659	{ strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
660	  free($2);
661	}
662	| IPFY_REPLY_TO name ':' hostname
663	{ strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname));
664	  fr->fr_rif.fd_ip = $4;
665	  free($2);
666	}
667	;
668
669logoptions:
670	logoption
671	| logoptions logoption
672	;
673
674logoption:
675	IPFY_BODY			{ fr->fr_flags |= FR_LOGBODY; }
676	| IPFY_FIRST			{ fr->fr_flags |= FR_LOGFIRST; }
677	| IPFY_ORBLOCK			{ fr->fr_flags |= FR_LOGORBLOCK; }
678	| level loglevel		{ unsetsyslog(); }
679	;
680
681returncode:
682	starticmpcode icmpcode ')'	{ fr->fr_icode = $2; yyresetdict(); }
683	;
684
685starticmpcode:
686	'('				{ yysetdict(icmpcodewords); }
687	;
688
689srcdst:	IPFY_ALL
690	| fromto
691	;
692
693protocol:
694	YY_NUMBER		{ DOREM(fr->fr_proto = $1; \
695					fr->fr_mproto = 0xff;) }
696	| YY_STR		{ if (!strcmp($1, "tcp-udp")) {
697					DOREM(fr->fr_flx |= FI_TCPUDP; \
698					      fr->fr_mflx |= FI_TCPUDP;)
699				  } else {
700					int p = getproto($1);
701					if (p == -1)
702						fprintf(stderr, "protocol unknown: %s, line %d\n", $1, yylineNum);
703					DOREM(fr->fr_proto = p; \
704						fr->fr_mproto = 0xff;)
705				  }
706				  free($1);
707				}
708	| YY_STR nextstring YY_STR
709				{ if (!strcmp($1, "tcp") &&
710				      !strcmp($3, "udp")) {
711					DOREM(fr->fr_flx |= FI_TCPUDP; \
712					      fr->fr_mflx |= FI_TCPUDP;)
713				  } else
714					YYERROR;
715				  free($1);
716				  free($3);
717				}
718	;
719
720nextstring:
721	'/'			{ yysetdict(NULL); }
722	;
723
724fromto:	from srcobject to dstobject	{ yyexpectaddr = 0; yycont = NULL; }
725	| to dstobject			{ yyexpectaddr = 0; yycont = NULL; }
726	| from srcobject		{ yyexpectaddr = 0; yycont = NULL; }
727	;
728
729from:	IPFY_FROM			{ setipftype();
730					  if (fr == NULL)
731						fr = frc;
732					  yyexpectaddr = 1;
733					  yycont = &yyexpectaddr;
734					  yysetdict(addrwords);
735					  resetaddr(); }
736	;
737
738to:	IPFY_TO				{ if (fr == NULL)
739						fr = frc;
740					  yyexpectaddr = 1;
741					  yycont = &yyexpectaddr;
742					  yysetdict(addrwords);
743					  resetaddr(); }
744	;
745
746with:	| andwith withlist
747	;
748
749andwith:
750	IPFY_WITH			{ nowith = 0; setipftype(); }
751	| IPFY_AND			{ nowith = 0; setipftype(); }
752	;
753
754flags:	| IPFY_FLAGS flagset
755		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
756	| IPFY_FLAGS flagset '/' flagset
757		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
758	| IPFY_FLAGS '/' flagset
759		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
760	| IPFY_FLAGS YY_NUMBER
761		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) }
762	| IPFY_FLAGS '/' YY_NUMBER
763		{ DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) }
764	| IPFY_FLAGS YY_NUMBER '/' YY_NUMBER
765		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
766	| IPFY_FLAGS flagset '/' YY_NUMBER
767		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
768	| IPFY_FLAGS YY_NUMBER '/' flagset
769		{ DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) }
770	;
771
772flagset:
773	YY_STR				{ $$ = tcpflags($1); free($1); }
774	| YY_HEX			{ $$ = $1; }
775	;
776
777srcobject:
778	srcaddr srcport
779	| '!' srcaddr srcport
780		{ DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
781	| fromport
782	;
783
784srcaddr:
785	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
786			bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
787			if (dynamic != -1) { \
788				fr->fr_satype = ifpflag; \
789				fr->fr_ipf->fri_sifpidx = dynamic; \
790			} else if (pooled || hashed) \
791				fr->fr_satype = FRI_LOOKUP;)
792		}
793	| lstart srcaddrlist lend
794	;
795
796srcaddrlist:
797	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \
798			bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \
799			if (dynamic != -1) { \
800				fr->fr_satype = ifpflag; \
801				fr->fr_ipf->fri_sifpidx = dynamic; \
802			} else if (pooled || hashed) \
803				fr->fr_satype = FRI_LOOKUP;)
804		}
805	| srcaddrlist lmore addr
806		{ DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \
807			bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \
808			if (dynamic != -1) { \
809				fr->fr_satype = ifpflag; \
810				fr->fr_ipf->fri_sifpidx = dynamic; \
811			} else if (pooled || hashed) \
812				fr->fr_satype = FRI_LOOKUP;)
813		}
814	;
815
816srcport:
817	| portcomp
818		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
819	| portrange
820		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
821			fr->fr_stop = $1.p2;) }
822	| porteq lstart srcportlist lend
823		{ yyresetdict(); }
824	;
825
826fromport:
827	portcomp
828		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) }
829	| portrange
830		{ DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \
831			fr->fr_stop = $1.p2;) }
832	| porteq lstart srcportlist lend
833		{ yyresetdict(); }
834	;
835
836srcportlist:
837	portnum		{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) }
838	| srcportlist lmore portnum
839			{ DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) }
840	;
841
842dstobject:
843	toport
844	| dstaddr dstport
845	| '!' dstaddr dstport
846			{ DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
847	;
848
849dstaddr:
850	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
851			bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
852			if (dynamic != -1) { \
853				fr->fr_datype = ifpflag; \
854				fr->fr_ipf->fri_difpidx = dynamic; \
855			  } else if (pooled || hashed) \
856				fr->fr_datype = FRI_LOOKUP;)
857		}
858	| lstart dstaddrlist lend
859	;
860
861dstaddrlist:
862	addr	{ DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \
863			bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \
864			if (dynamic != -1) { \
865				fr->fr_datype = ifpflag; \
866				fr->fr_ipf->fri_difpidx = dynamic; \
867			} else if (pooled || hashed) \
868				fr->fr_datype = FRI_LOOKUP;)
869		}
870	| dstaddrlist lmore addr
871		{ DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \
872			bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \
873			if (dynamic != -1) { \
874				fr->fr_datype = ifpflag; \
875				fr->fr_ipf->fri_difpidx = dynamic; \
876			} else if (pooled || hashed) \
877				fr->fr_datype = FRI_LOOKUP;)
878		}
879	;
880
881
882dstport:
883	| portcomp
884		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
885	| portrange
886		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
887			fr->fr_dtop = $1.p2;) }
888	| porteq lstart dstportlist lend
889		{ yyresetdict(); }
890	;
891
892toport:
893	portcomp
894		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) }
895	| portrange
896		{ DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \
897			fr->fr_dtop = $1.p2;) }
898	| porteq lstart dstportlist lend
899		{ yyresetdict(); }
900	;
901
902dstportlist:
903	portnum		{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) }
904	| dstportlist lmore portnum
905			{ DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) }
906	;
907
908addr:	pool '/' YY_NUMBER		{ pooled = 1;
909					  yyexpectaddr = 0;
910					  $$.a.iplookuptype = IPLT_POOL;
911					  $$.a.iplookupnum = $3; }
912	| pool '=' '(' poollist ')'	{ pooled = 1;
913					  yyexpectaddr = 0;
914					  $$.a.iplookuptype = IPLT_POOL;
915					  $$.a.iplookupnum = makepool($4); }
916	| hash '/' YY_NUMBER		{ hashed = 1;
917					  yyexpectaddr = 0;
918					  $$.a.iplookuptype = IPLT_HASH;
919					  $$.a.iplookupnum = $3; }
920	| hash '=' '(' addrlist ')'	{ hashed = 1;
921					  yyexpectaddr = 0;
922					  $$.a.iplookuptype = IPLT_HASH;
923					  $$.a.iplookupnum = makehash($4); }
924	| ipaddr			{ bcopy(&$1, &$$, sizeof($$));
925					  yyexpectaddr = 0; }
926	;
927
928ipaddr:	IPFY_ANY			{ bzero(&($$), sizeof($$));
929					  yyresetdict();
930					  yyexpectaddr = 0; }
931	| hostname			{ $$.a.in4 = $1;
932					  $$.m.in4_addr = 0xffffffff;
933					  yyexpectaddr = 0; }
934	| hostname			{ yyresetdict();
935					  $$.a.in4_addr = $1.s_addr; }
936		maskspace		{ yysetdict(maskwords); }
937		ipv4mask		{ $$.m.in4_addr = $5.s_addr;
938					  $$.a.in4_addr &= $5.s_addr;
939					  yyresetdict();
940					  yyexpectaddr = 0; }
941	| YY_IPV6			{ set_ipv6_addr = 1;
942					  bcopy(&$1, &$$.a, sizeof($$.a));
943					  fill6bits(128, (u_32_t *)&$$.m);
944					  yyresetdict();
945					  yyexpectaddr = 0; }
946	| YY_IPV6			{ set_ipv6_addr = 1;
947					  yyresetdict();
948					  bcopy(&$1, &$$.a, sizeof($$.a)); }
949		maskspace		{ yysetdict(maskwords); }
950		ipv6mask		{ bcopy(&$5, &$$.m, sizeof($$.m));
951					  yyresetdict();
952					  yyexpectaddr = 0; }
953	;
954
955maskspace:
956	'/'
957	| IPFY_MASK
958	;
959
960ipv4mask:
961	ipv4				{ $$ = $1; }
962	| YY_HEX			{ $$.s_addr = htonl($1); }
963	| YY_NUMBER			{ ntomask(4, $1, (u_32_t *)&$$); }
964	| IPFY_BROADCAST		{ if (ifpflag == FRI_DYNAMIC) {
965						$$.s_addr = 0;
966						ifpflag = FRI_BROADCAST;
967					  } else
968						YYERROR;
969					}
970	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
971						$$.s_addr = 0;
972						ifpflag = FRI_NETWORK;
973					  } else
974						YYERROR;
975					}
976	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
977						$$.s_addr = 0;
978						ifpflag = FRI_NETMASKED;
979					  } else
980						YYERROR;
981					}
982	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
983						$$.s_addr = 0;
984						ifpflag = FRI_PEERADDR;
985					  } else
986						YYERROR;
987					}
988	;
989
990ipv6mask:
991	YY_NUMBER			{ ntomask(6, $1, $$.i6); }
992	| IPFY_BROADCAST		{ if (ifpflag == FRI_DYNAMIC) {
993						bzero(&$$, sizeof($$));
994						ifpflag = FRI_BROADCAST;
995					  } else
996						YYERROR;
997					}
998	| IPFY_NETWORK			{ if (ifpflag == FRI_DYNAMIC) {
999						bzero(&$$, sizeof($$));
1000						ifpflag = FRI_BROADCAST;
1001					  } else
1002						YYERROR;
1003					}
1004	| IPFY_NETMASKED		{ if (ifpflag == FRI_DYNAMIC) {
1005						bzero(&$$, sizeof($$));
1006						ifpflag = FRI_BROADCAST;
1007					  } else
1008						YYERROR;
1009					}
1010	| IPFY_PEER			{ if (ifpflag == FRI_DYNAMIC) {
1011						bzero(&$$, sizeof($$));
1012						ifpflag = FRI_BROADCAST;
1013					  } else
1014						YYERROR;
1015					}
1016	;
1017
1018hostname:
1019	ipv4				{ $$ = $1; }
1020	| YY_NUMBER			{ $$.s_addr = $1; }
1021	| YY_HEX			{ $$.s_addr = $1; }
1022	| YY_STR			{ $$.s_addr = lookuphost($1);
1023					  free($1);
1024					  if ($$.s_addr == 0 &&
1025						ifpflag != FRI_DYNAMIC)
1026						yyerror("Unknown hostname");
1027					}
1028	;
1029
1030addrlist:
1031	ipaddr		{ $$ = newalist(NULL);
1032			  if (set_ipv6_addr)
1033				  $$->al_family = AF_INET6;
1034			  else
1035				  $$->al_family = AF_INET;
1036			  set_ipv6_addr = 0;
1037			  bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
1038			  bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
1039	| addrlist ',' ipaddr
1040			{ $$ = newalist($1);
1041			  if (set_ipv6_addr)
1042				  $$->al_family = AF_INET6;
1043			  else
1044				  $$->al_family = AF_INET;
1045			  set_ipv6_addr = 0;
1046			  bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
1047			  bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
1048	;
1049
1050pool:	IPFY_POOL	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1051	;
1052
1053hash:	IPFY_HASH	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1054	;
1055
1056poollist:
1057	ipaddr		{ $$ = newalist(NULL);
1058			  if (set_ipv6_addr)
1059				  $$->al_family = AF_INET6;
1060			  else
1061				  $$->al_family = AF_INET;
1062			  set_ipv6_addr = 0;
1063			  bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a));
1064			  bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); }
1065	| '!' ipaddr	{ $$ = newalist(NULL);
1066			  $$->al_not = 1;
1067			  if (set_ipv6_addr)
1068				  $$->al_family = AF_INET6;
1069			  else
1070				  $$->al_family = AF_INET;
1071			  set_ipv6_addr = 0;
1072			  bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a));
1073			  bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); }
1074	| poollist ',' ipaddr
1075			{ $$ = newalist($1);
1076			  if (set_ipv6_addr)
1077				  $$->al_family = AF_INET6;
1078			  else
1079				  $$->al_family = AF_INET;
1080			  set_ipv6_addr = 0;
1081			  bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a));
1082			  bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); }
1083	| poollist ',' '!' ipaddr
1084			{ $$ = newalist($1);
1085			  $$->al_not = 1;
1086			  if (set_ipv6_addr)
1087				  $$->al_family = AF_INET6;
1088			  else
1089				  $$->al_family = AF_INET;
1090			  set_ipv6_addr = 0;
1091			  bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a));
1092			  bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); }
1093	;
1094
1095port:	IPFY_PORT			{ yyexpectaddr = 0;
1096					  yycont = NULL;
1097					}
1098	;
1099
1100portc:	port compare			{ $$ = $2;
1101					  yysetdict(NULL); }
1102	| porteq			{ $$ = $1; }
1103	;
1104
1105porteq:	port '='			{ $$ = FR_EQUAL;
1106					  yysetdict(NULL); }
1107	;
1108
1109portr:	IPFY_PORT			{ yyexpectaddr = 0;
1110					  yycont = NULL;
1111					  yysetdict(NULL); }
1112	;
1113
1114portcomp:
1115	portc portnum			{ $$.pc = $1;
1116					  $$.p1 = $2;
1117					  yyresetdict(); }
1118	;
1119
1120portrange:
1121	portr portnum range portnum	{ $$.p1 = $2;
1122					  $$.pc = $3;
1123					  $$.p2 = $4;
1124					  yyresetdict(); }
1125	;
1126
1127icmp:	| itype icode
1128	;
1129
1130itype:	seticmptype icmptype
1131	{ DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00););
1132	  yyresetdict();
1133	}
1134	| seticmptype lstart typelist lend	{ yyresetdict(); }
1135	;
1136
1137seticmptype:
1138	IPFY_ICMPTYPE				{ setipftype();
1139						  yysetdict(icmptypewords); }
1140	;
1141
1142icode:	| seticmpcode icmpcode
1143	{ DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff););
1144	  yyresetdict();
1145	}
1146	| seticmpcode lstart codelist lend	{ yyresetdict(); }
1147	;
1148
1149seticmpcode:
1150	IPFY_ICMPCODE				{ yysetdict(icmpcodewords); }
1151	;
1152
1153typelist:
1154	icmptype
1155	{ DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) }
1156	| typelist lmore icmptype
1157	{ DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) }
1158	;
1159
1160codelist:
1161	icmpcode
1162	{ DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) }
1163	| codelist lmore icmpcode
1164	{ DOREM(fr->fr_icmp |= htons($3); fr->fr_icmpm |= htons(0xff);) }
1165	;
1166
1167age:	| IPFY_AGE YY_NUMBER		{ DOALL(fr->fr_age[0] = $2; \
1168						fr->fr_age[1] = $2;) }
1169	| IPFY_AGE YY_NUMBER '/' YY_NUMBER
1170					{ DOALL(fr->fr_age[0] = $2; \
1171						fr->fr_age[1] = $4;) }
1172	;
1173
1174keep:	| IPFY_KEEP keepstate
1175	| IPFY_KEEP keepfrag
1176	| IPFY_KEEP keepstate IPFY_KEEP keepfrag
1177	;
1178
1179keepstate:
1180	IPFY_STATE stateoptlist		{ DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
1181	;
1182
1183keepfrag:
1184	IPFY_FRAGS fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1185	;
1186
1187fragoptlist:
1188	| '(' fragopts ')'
1189	;
1190
1191fragopts:
1192	fragopt lanother fragopts
1193	| fragopt
1194	;
1195
1196fragopt:
1197	IPFY_STRICT			{ DOALL(fr->fr_flags |= FR_FRSTRICT;) }
1198	;
1199
1200stateoptlist:
1201	| '(' stateopts ')'
1202	;
1203
1204stateopts:
1205	stateopt lanother stateopts
1206	| stateopt
1207	;
1208
1209stateopt:
1210	IPFY_LIMIT YY_NUMBER	{ DOALL(fr->fr_statemax = $2;) }
1211	| IPFY_STRICT		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1212						YYERROR; \
1213					  } else \
1214						fr->fr_flags |= FR_STSTRICT;)
1215				}
1216	| IPFY_NEWISN		{ DOALL(if (fr->fr_proto != IPPROTO_TCP) { \
1217						YYERROR; \
1218					  } else \
1219						fr->fr_flags |= FR_NEWISN;)
1220				}
1221	| IPFY_NOICMPERR	{ DOALL(fr->fr_flags |= FR_NOICMPERR;) }
1222	;
1223
1224portnum:
1225	servicename			{ $$ = ntohs(getport(frc, $1));
1226					  if ($$ == -1)
1227						fprintf(stderr, "service unknown: %s, line %d\n", $1, yylineNum);
1228					  free($1);
1229					}
1230	| YY_NUMBER			{ $$ = $1; }
1231	;
1232
1233withlist:
1234	withopt
1235	| withlist withopt
1236	;
1237
1238withopt:
1239	opttype		{ DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) }
1240	| notwith opttype
1241			{ DOALL(fr->fr_mflx |= $2;) }
1242	| IPFY_OPT ipopts
1243	| notwith IPFY_OPT ipopts
1244	| startv6hdrs ipv6hdrs
1245	;
1246
1247startv6hdrs:
1248	IPF6_V6HDRS	{ if (use_inet6 == 0)
1249				yyerror("only available with IPv6");
1250			}
1251	;
1252
1253notwith:
1254	IPFY_NOT			{ nowith = 1; }
1255	| IPFY_NO			{ nowith = 1; }
1256	;
1257
1258opttype:
1259	IPFY_IPOPTS			{ $$ = FI_OPTIONS; }
1260	| IPFY_SHORT			{ $$ = FI_SHORT; }
1261	| IPFY_NAT			{ $$ = FI_NATED; }
1262	| IPFY_BAD			{ $$ = FI_BAD; }
1263	| IPFY_BADNAT			{ $$ = FI_BADNAT; }
1264	| IPFY_BADSRC			{ $$ = FI_BADSRC; }
1265	| IPFY_LOWTTL			{ $$ = FI_LOWTTL; }
1266	| IPFY_FRAG			{ $$ = FI_FRAG; }
1267	| IPFY_MBCAST			{ $$ = FI_MBCAST; }
1268	| IPFY_MULTICAST		{ $$ = FI_MULTICAST; }
1269	| IPFY_BROADCAST		{ $$ = FI_BROADCAST; }
1270	| IPFY_STATE			{ $$ = FI_STATE; }
1271	| IPFY_OOW			{ $$ = FI_OOW; }
1272	;
1273
1274ipopts:	optlist		{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1275				if (!nowith)
1276					fr->fr_ip.fi_optmsk |= $1;)
1277			}
1278	;
1279
1280optlist:
1281	opt				{ $$ |= $1; }
1282	| optlist ',' opt		{ $$ |= $1 | $3; }
1283	;
1284
1285ipv6hdrs:
1286	ipv6hdrlist	{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1287				if (!nowith)
1288					fr->fr_ip.fi_optmsk |= $1;)
1289			}
1290	;
1291
1292ipv6hdrlist:
1293	ipv6hdr				{ $$ |= $1; }
1294	| ipv6hdrlist ',' ipv6hdr	{ $$ |= $1 | $3; }
1295	;
1296
1297secname:
1298	seclevel			{ $$ |= $1; }
1299	| secname ',' seclevel		{ $$ |= $1 | $3; }
1300	;
1301
1302seclevel:
1303	IPFY_SEC_UNC			{ $$ = secbit(IPSO_CLASS_UNCL); }
1304	| IPFY_SEC_CONF			{ $$ = secbit(IPSO_CLASS_CONF); }
1305	| IPFY_SEC_RSV1			{ $$ = secbit(IPSO_CLASS_RES1); }
1306	| IPFY_SEC_RSV2			{ $$ = secbit(IPSO_CLASS_RES2); }
1307	| IPFY_SEC_RSV3			{ $$ = secbit(IPSO_CLASS_RES3); }
1308	| IPFY_SEC_RSV4			{ $$ = secbit(IPSO_CLASS_RES4); }
1309	| IPFY_SEC_SEC			{ $$ = secbit(IPSO_CLASS_SECR); }
1310	| IPFY_SEC_TS			{ $$ = secbit(IPSO_CLASS_TOPS); }
1311	;
1312
1313icmptype:
1314	YY_NUMBER			{ $$ = $1; }
1315	| IPFY_ICMPT_UNR		{ $$ = ICMP_UNREACH; }
1316	| IPFY_ICMPT_ECHO		{ $$ = ICMP_ECHO; }
1317	| IPFY_ICMPT_ECHOR		{ $$ = ICMP_ECHOREPLY; }
1318	| IPFY_ICMPT_SQUENCH		{ $$ = ICMP_SOURCEQUENCH; }
1319	| IPFY_ICMPT_REDIR		{ $$ = ICMP_REDIRECT; }
1320	| IPFY_ICMPT_TIMEX		{ $$ = ICMP_TIMXCEED; }
1321	| IPFY_ICMPT_PARAMP		{ $$ = ICMP_PARAMPROB; }
1322	| IPFY_ICMPT_TIMEST		{ $$ = ICMP_TSTAMP; }
1323	| IPFY_ICMPT_TIMESTREP		{ $$ = ICMP_TSTAMPREPLY; }
1324	| IPFY_ICMPT_INFOREQ		{ $$ = ICMP_IREQ; }
1325	| IPFY_ICMPT_INFOREP		{ $$ = ICMP_IREQREPLY; }
1326	| IPFY_ICMPT_MASKREQ		{ $$ = ICMP_MASKREQ; }
1327	| IPFY_ICMPT_MASKREP		{ $$ = ICMP_MASKREPLY; }
1328	| IPFY_ICMPT_ROUTERAD		{ $$ = ICMP_ROUTERADVERT; }
1329	| IPFY_ICMPT_ROUTERSOL		{ $$ = ICMP_ROUTERSOLICIT; }
1330	;
1331
1332icmpcode:
1333	YY_NUMBER			{ $$ = $1; }
1334	| IPFY_ICMPC_NETUNR		{ $$ = ICMP_UNREACH_NET; }
1335	| IPFY_ICMPC_HSTUNR		{ $$ = ICMP_UNREACH_HOST; }
1336	| IPFY_ICMPC_PROUNR		{ $$ = ICMP_UNREACH_PROTOCOL; }
1337	| IPFY_ICMPC_PORUNR		{ $$ = ICMP_UNREACH_PORT; }
1338	| IPFY_ICMPC_NEEDF		{ $$ = ICMP_UNREACH_NEEDFRAG; }
1339	| IPFY_ICMPC_SRCFAIL		{ $$ = ICMP_UNREACH_SRCFAIL; }
1340	| IPFY_ICMPC_NETUNK		{ $$ = ICMP_UNREACH_NET_UNKNOWN; }
1341	| IPFY_ICMPC_HSTUNK		{ $$ = ICMP_UNREACH_HOST_UNKNOWN; }
1342	| IPFY_ICMPC_ISOLATE		{ $$ = ICMP_UNREACH_ISOLATED; }
1343	| IPFY_ICMPC_NETPRO		{ $$ = ICMP_UNREACH_NET_PROHIB; }
1344	| IPFY_ICMPC_HSTPRO		{ $$ = ICMP_UNREACH_HOST_PROHIB; }
1345	| IPFY_ICMPC_NETTOS		{ $$ = ICMP_UNREACH_TOSNET; }
1346	| IPFY_ICMPC_HSTTOS		{ $$ = ICMP_UNREACH_TOSHOST; }
1347	| IPFY_ICMPC_FLTPRO		{ $$ = ICMP_UNREACH_ADMIN_PROHIBIT; }
1348	| IPFY_ICMPC_HSTPRE		{ $$ = 14; }
1349	| IPFY_ICMPC_CUTPRE		{ $$ = 15; }
1350	;
1351
1352opt:
1353	IPFY_IPOPT_NOP			{ $$ = getoptbyvalue(IPOPT_NOP); }
1354	| IPFY_IPOPT_RR			{ $$ = getoptbyvalue(IPOPT_RR); }
1355	| IPFY_IPOPT_ZSU		{ $$ = getoptbyvalue(IPOPT_ZSU); }
1356	| IPFY_IPOPT_MTUP		{ $$ = getoptbyvalue(IPOPT_MTUP); }
1357	| IPFY_IPOPT_MTUR		{ $$ = getoptbyvalue(IPOPT_MTUR); }
1358	| IPFY_IPOPT_ENCODE		{ $$ = getoptbyvalue(IPOPT_ENCODE); }
1359	| IPFY_IPOPT_TS			{ $$ = getoptbyvalue(IPOPT_TS); }
1360	| IPFY_IPOPT_TR			{ $$ = getoptbyvalue(IPOPT_TR); }
1361	| IPFY_IPOPT_SEC		{ $$ = getoptbyvalue(IPOPT_SECURITY); }
1362	| IPFY_IPOPT_LSRR		{ $$ = getoptbyvalue(IPOPT_LSRR); }
1363	| IPFY_IPOPT_ESEC		{ $$ = getoptbyvalue(IPOPT_E_SEC); }
1364	| IPFY_IPOPT_CIPSO		{ $$ = getoptbyvalue(IPOPT_CIPSO); }
1365	| IPFY_IPOPT_SATID		{ $$ = getoptbyvalue(IPOPT_SATID); }
1366	| IPFY_IPOPT_SSRR		{ $$ = getoptbyvalue(IPOPT_SSRR); }
1367	| IPFY_IPOPT_ADDEXT		{ $$ = getoptbyvalue(IPOPT_ADDEXT); }
1368	| IPFY_IPOPT_VISA		{ $$ = getoptbyvalue(IPOPT_VISA); }
1369	| IPFY_IPOPT_IMITD		{ $$ = getoptbyvalue(IPOPT_IMITD); }
1370	| IPFY_IPOPT_EIP		{ $$ = getoptbyvalue(IPOPT_EIP); }
1371	| IPFY_IPOPT_FINN		{ $$ = getoptbyvalue(IPOPT_FINN); }
1372	| IPFY_IPOPT_DPS		{ $$ = getoptbyvalue(IPOPT_DPS); }
1373	| IPFY_IPOPT_SDB		{ $$ = getoptbyvalue(IPOPT_SDB); }
1374	| IPFY_IPOPT_NSAPA		{ $$ = getoptbyvalue(IPOPT_NSAPA); }
1375	| IPFY_IPOPT_RTRALRT		{ $$ = getoptbyvalue(IPOPT_RTRALRT); }
1376	| IPFY_IPOPT_UMP		{ $$ = getoptbyvalue(IPOPT_UMP); }
1377	| IPFY_SECCLASS secname
1378			{ DOALL(fr->fr_mip.fi_secmsk |= $2;
1379				if (!nowith)
1380					fr->fr_ip.fi_secmsk |= $2;)
1381			  $$ = 0;
1382			}
1383	;
1384
1385ipv6hdr:
1386	IPFY_AH			{ $$ = getv6optbyvalue(IPPROTO_AH); }
1387	| IPFY_IPV6OPT_DSTOPTS	{ $$ = getv6optbyvalue(IPPROTO_DSTOPTS); }
1388	| IPFY_ESP		{ $$ = getv6optbyvalue(IPPROTO_ESP); }
1389	| IPFY_IPV6OPT_HOPOPTS	{ $$ = getv6optbyvalue(IPPROTO_HOPOPTS); }
1390	| IPFY_IPV6OPT_IPV6	{ $$ = getv6optbyvalue(IPPROTO_IPV6); }
1391	| IPFY_IPV6OPT_NONE	{ $$ = getv6optbyvalue(IPPROTO_NONE); }
1392	| IPFY_IPV6OPT_ROUTING	{ $$ = getv6optbyvalue(IPPROTO_ROUTING); }
1393	| IPFY_FRAG		{ $$ = getv6optbyvalue(IPPROTO_FRAGMENT); }
1394	;
1395
1396level:	IPFY_LEVEL			{ setsyslog(); }
1397	;
1398
1399loglevel:
1400	priority			{ fr->fr_loglevel = LOG_LOCAL0|$1; }
1401	| facility '.' priority		{ fr->fr_loglevel = $1 | $3; }
1402	;
1403
1404facility:
1405	IPFY_FAC_KERN			{ $$ = LOG_KERN; }
1406	| IPFY_FAC_USER			{ $$ = LOG_USER; }
1407	| IPFY_FAC_MAIL			{ $$ = LOG_MAIL; }
1408	| IPFY_FAC_DAEMON		{ $$ = LOG_DAEMON; }
1409	| IPFY_FAC_AUTH			{ $$ = LOG_AUTH; }
1410	| IPFY_FAC_SYSLOG		{ $$ = LOG_SYSLOG; }
1411	| IPFY_FAC_LPR			{ $$ = LOG_LPR; }
1412	| IPFY_FAC_NEWS			{ $$ = LOG_NEWS; }
1413	| IPFY_FAC_UUCP			{ $$ = LOG_UUCP; }
1414	| IPFY_FAC_CRON			{ $$ = LOG_CRON; }
1415	| IPFY_FAC_FTP			{ $$ = LOG_FTP; }
1416	| IPFY_FAC_AUTHPRIV		{ $$ = LOG_AUTHPRIV; }
1417	| IPFY_FAC_AUDIT		{ $$ = LOG_AUDIT; }
1418	| IPFY_FAC_LFMT			{ $$ = LOG_LFMT; }
1419	| IPFY_FAC_LOCAL0		{ $$ = LOG_LOCAL0; }
1420	| IPFY_FAC_LOCAL1		{ $$ = LOG_LOCAL1; }
1421	| IPFY_FAC_LOCAL2		{ $$ = LOG_LOCAL2; }
1422	| IPFY_FAC_LOCAL3		{ $$ = LOG_LOCAL3; }
1423	| IPFY_FAC_LOCAL4		{ $$ = LOG_LOCAL4; }
1424	| IPFY_FAC_LOCAL5		{ $$ = LOG_LOCAL5; }
1425	| IPFY_FAC_LOCAL6		{ $$ = LOG_LOCAL6; }
1426	| IPFY_FAC_LOCAL7		{ $$ = LOG_LOCAL7; }
1427	| IPFY_FAC_SECURITY		{ $$ = LOG_SECURITY; }
1428	;
1429
1430priority:
1431	IPFY_PRI_EMERG			{ $$ = LOG_EMERG; }
1432	| IPFY_PRI_ALERT		{ $$ = LOG_ALERT; }
1433	| IPFY_PRI_CRIT			{ $$ = LOG_CRIT; }
1434	| IPFY_PRI_ERR			{ $$ = LOG_ERR; }
1435	| IPFY_PRI_WARN			{ $$ = LOG_WARNING; }
1436	| IPFY_PRI_NOTICE		{ $$ = LOG_NOTICE; }
1437	| IPFY_PRI_INFO			{ $$ = LOG_INFO; }
1438	| IPFY_PRI_DEBUG		{ $$ = LOG_DEBUG; }
1439	;
1440
1441compare:
1442	'='				{ $$ = FR_EQUAL; }
1443	| YY_CMP_EQ			{ $$ = FR_EQUAL; }
1444	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
1445	| YY_CMP_LT			{ $$ = FR_LESST; }
1446	| YY_CMP_LE			{ $$ = FR_LESSTE; }
1447	| YY_CMP_GT			{ $$ = FR_GREATERT; }
1448	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
1449	;
1450
1451range:	YY_RANGE_IN			{ $$ = FR_INRANGE; }
1452	| YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
1453	| ':'				{ $$ = FR_INCRANGE; }
1454	;
1455
1456servicename:
1457	YY_STR				{ $$ = $1; }
1458	;
1459
1460interfacename:	YY_STR			{ $$ = $1; }
1461	| YY_STR ':' YY_NUMBER
1462		{ $$ = $1;
1463#if SOLARIS2 >= 10
1464		if (strncmp(VNI, $1, VNISTRLEN) != 0)
1465#endif
1466		  fprintf(stderr, "%d: Logical interface %s:%d unsupported, "
1467			"use the physical interface %s instead.\n",
1468			yylineNum, $1, $3, $1);
1469		}
1470	;
1471
1472name:	YY_STR				{ $$ = $1; }
1473	;
1474
1475ipv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
1476		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
1477			yyerror("Invalid octet string for IP address");
1478			return 0;
1479		  }
1480		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
1481		  $$.s_addr = htonl($$.s_addr);
1482		}
1483	;
1484%%
1485
1486
1487static	struct	wordtab ipfwords[] = {
1488	{ "addext",			IPFY_IPOPT_ADDEXT },
1489	{ "age",			IPFY_AGE },
1490	{ "ah",				IPFY_AH },
1491	{ "all",			IPFY_ALL },
1492	{ "and",			IPFY_AND },
1493	{ "auth",			IPFY_AUTH },
1494	{ "bad",			IPFY_BAD },
1495	{ "bad-nat",			IPFY_BADNAT },
1496	{ "bad-src",			IPFY_BADSRC },
1497	{ "bcast",			IPFY_BROADCAST },
1498	{ "block",			IPFY_BLOCK },
1499	{ "body",			IPFY_BODY },
1500	{ "bpf",			IPFY_BPF },
1501	{ "call",			IPFY_CALL },
1502	{ "cipso",			IPFY_IPOPT_CIPSO },
1503	{ "code",			IPFY_ICMPCODE },
1504	{ "confid",			IPFY_SEC_CONF },
1505	{ "count",			IPFY_COUNT },
1506	{ "divert",			IPFY_DIVERT },
1507	{ "dps",			IPFY_IPOPT_DPS },
1508	{ "dstopts",			IPFY_IPV6OPT_DSTOPTS },
1509	{ "dup-to",			IPFY_DUPTO },
1510	{ "e-sec",			IPFY_IPOPT_ESEC },
1511	{ "eip",			IPFY_IPOPT_EIP },
1512	{ "encode",			IPFY_IPOPT_ENCODE },
1513	{ "eq",				YY_CMP_EQ },
1514	{ "esp",			IPFY_ESP },
1515	{ "fastroute",			IPFY_FROUTE },
1516	{ "first",			IPFY_FIRST },
1517	{ "finn",			IPFY_IPOPT_FINN },
1518	{ "frag",			IPFY_FRAG },
1519	{ "flags",			IPFY_FLAGS },
1520	{ "frags",			IPFY_FRAGS },
1521	{ "from",			IPFY_FROM },
1522	{ "ge",				YY_CMP_GE },
1523	{ "group",			IPFY_GROUP },
1524	{ "gt",				YY_CMP_GT },
1525	{ "head",			IPFY_HEAD },
1526	{ "hopopts",			IPFY_IPV6OPT_HOPOPTS },
1527	{ "host-preced",		IPFY_ICMPC_HSTPRE },
1528	{ "host-prohib",		IPFY_ICMPC_HSTPRO },
1529	{ "host-tos",			IPFY_ICMPC_HSTTOS },
1530	{ "host-unk",			IPFY_ICMPC_HSTUNK },
1531	{ "host-unr",			IPFY_ICMPC_HSTUNR },
1532	{ "icmp",			IPFY_ICMP },
1533	{ "icmp-type",			IPFY_ICMPTYPE },
1534	{ "imitd",			IPFY_IPOPT_IMITD },
1535	{ "in",				IPFY_IN },
1536	{ "in-via",			IPFY_INVIA },
1537	{ "ipopt",			IPFY_IPOPTS },
1538	{ "ipopts",			IPFY_IPOPTS },
1539	{ "ipv6",			IPFY_IPV6OPT_IPV6 },
1540	{ "keep",			IPFY_KEEP },
1541	{ "le",				YY_CMP_LE },
1542	{ "level",			IPFY_LEVEL },
1543	{ "limit",			IPFY_LIMIT },
1544	{ "log",			IPFY_LOG },
1545	{ "lowttl",			IPFY_LOWTTL },
1546	{ "lsrr",			IPFY_IPOPT_LSRR },
1547	{ "lt",				YY_CMP_LT },
1548	{ "mask",			IPFY_MASK },
1549	{ "mbcast",			IPFY_MBCAST },
1550	{ "mtup",			IPFY_IPOPT_MTUP },
1551	{ "mtur",			IPFY_IPOPT_MTUR },
1552	{ "multicast",			IPFY_MULTICAST },
1553	{ "nat",			IPFY_NAT },
1554	{ "ne",				YY_CMP_NE },
1555	{ "net",			IPFY_NETWORK },
1556	{ "newisn",			IPFY_NEWISN },
1557	{ "no",				IPFY_NO },
1558	{ "no-icmp-err",		IPFY_NOICMPERR },
1559	{ "none",			IPFY_IPV6OPT_NONE },
1560	{ "nop",			IPFY_IPOPT_NOP },
1561	{ "now",			IPFY_NOW },
1562	{ "not",			IPFY_NOT },
1563	{ "nsapa",			IPFY_IPOPT_NSAPA },
1564	{ "oow",			IPFY_OOW },
1565	{ "on",				IPFY_ON },
1566	{ "opt",			IPFY_OPT },
1567	{ "or-block",			IPFY_ORBLOCK },
1568	{ "out",			IPFY_OUT },
1569	{ "out-via",			IPFY_OUTVIA },
1570	{ "pass",			IPFY_PASS },
1571	{ "port",			IPFY_PORT },
1572	{ "pps",			IPFY_PPS },
1573	{ "preauth",			IPFY_PREAUTH },
1574	{ "proto",			IPFY_PROTO },
1575	{ "quick",			IPFY_QUICK },
1576	{ "reply-to",			IPFY_REPLY_TO },
1577	{ "reserv-1",			IPFY_SEC_RSV1 },
1578	{ "reserv-2",			IPFY_SEC_RSV2 },
1579	{ "reserv-3",			IPFY_SEC_RSV3 },
1580	{ "reserv-4",			IPFY_SEC_RSV4 },
1581	{ "return-icmp",		IPFY_RETICMP },
1582	{ "return-icmp-as-dest",	IPFY_RETICMPASDST },
1583	{ "return-rst",			IPFY_RETRST },
1584	{ "routing",			IPFY_IPV6OPT_ROUTING },
1585	{ "rr",				IPFY_IPOPT_RR },
1586	{ "rtralrt",			IPFY_IPOPT_RTRALRT },
1587	{ "satid",			IPFY_IPOPT_SATID },
1588	{ "sdb",			IPFY_IPOPT_SDB },
1589	{ "sec",			IPFY_IPOPT_SEC },
1590	{ "sec-class",			IPFY_SECCLASS },
1591	{ "secret",			IPFY_SEC_SEC },
1592	{ "skip",			IPFY_SKIP },
1593	{ "short",			IPFY_SHORT },
1594	{ "ssrr",			IPFY_IPOPT_SSRR },
1595	{ "state",			IPFY_STATE },
1596	{ "strict",			IPFY_STRICT },
1597	{ "tag",			IPFY_TAG },
1598	{ "tcp",			IPFY_TCP },
1599	{ "tcp-udp",			IPFY_TCPUDP },
1600	{ "tos",			IPFY_TOS },
1601	{ "topsecret",			IPFY_SEC_TS },
1602	{ "to",				IPFY_TO },
1603	{ "tr",				IPFY_IPOPT_TR },
1604	{ "ts",				IPFY_IPOPT_TS },
1605	{ "ttl",			IPFY_TTL },
1606	{ "udp",			IPFY_UDP },
1607	{ "ump",			IPFY_IPOPT_UMP },
1608	{ "unclass",			IPFY_SEC_UNC },
1609	{ "v6hdrs",			IPF6_V6HDRS },
1610	{ "visa",			IPFY_IPOPT_VISA },
1611	{ "with",			IPFY_WITH },
1612	{ "zsu",			IPFY_IPOPT_ZSU },
1613	{ NULL,				0 }
1614};
1615
1616static	struct	wordtab	addrwords[4] = {
1617	{ "any",			IPFY_ANY },
1618	{ "hash",			IPFY_HASH },
1619	{ "pool",			IPFY_POOL },
1620	{ NULL,				0 }
1621};
1622
1623static	struct	wordtab	maskwords[5] = {
1624	{ "broadcast",			IPFY_BROADCAST },
1625	{ "netmasked",			IPFY_NETMASKED },
1626	{ "network",			IPFY_NETWORK },
1627	{ "peer",			IPFY_PEER },
1628	{ NULL,				0 }
1629};
1630
1631static	struct	wordtab icmptypewords[16] = {
1632	{ "echo",			IPFY_ICMPT_ECHO },
1633	{ "echorep",			IPFY_ICMPT_ECHOR },
1634	{ "inforeq",			IPFY_ICMPT_INFOREQ },
1635	{ "inforep",			IPFY_ICMPT_INFOREP },
1636	{ "maskrep",			IPFY_ICMPT_MASKREP },
1637	{ "maskreq",			IPFY_ICMPT_MASKREQ },
1638	{ "paramprob",			IPFY_ICMPT_PARAMP },
1639	{ "redir",			IPFY_ICMPT_REDIR },
1640	{ "unreach",			IPFY_ICMPT_UNR },
1641	{ "routerad",			IPFY_ICMPT_ROUTERAD },
1642	{ "routersol",			IPFY_ICMPT_ROUTERSOL },
1643	{ "squench",			IPFY_ICMPT_SQUENCH },
1644	{ "timest",			IPFY_ICMPT_TIMEST },
1645	{ "timestrep",			IPFY_ICMPT_TIMESTREP },
1646	{ "timex",			IPFY_ICMPT_TIMEX },
1647	{ NULL,				0 },
1648};
1649
1650static	struct	wordtab icmpcodewords[17] = {
1651	{ "cutoff-preced",		IPFY_ICMPC_CUTPRE },
1652	{ "filter-prohib",		IPFY_ICMPC_FLTPRO },
1653	{ "isolate",			IPFY_ICMPC_ISOLATE },
1654	{ "needfrag",			IPFY_ICMPC_NEEDF },
1655	{ "net-prohib",			IPFY_ICMPC_NETPRO },
1656	{ "net-tos",			IPFY_ICMPC_NETTOS },
1657	{ "host-preced",		IPFY_ICMPC_HSTPRE },
1658	{ "host-prohib",		IPFY_ICMPC_HSTPRO },
1659	{ "host-tos",			IPFY_ICMPC_HSTTOS },
1660	{ "host-unk",			IPFY_ICMPC_HSTUNK },
1661	{ "host-unr",			IPFY_ICMPC_HSTUNR },
1662	{ "net-unk",			IPFY_ICMPC_NETUNK },
1663	{ "net-unr",			IPFY_ICMPC_NETUNR },
1664	{ "port-unr",			IPFY_ICMPC_PORUNR },
1665	{ "proto-unr",			IPFY_ICMPC_PROUNR },
1666	{ "srcfail",			IPFY_ICMPC_SRCFAIL },
1667	{ NULL,				0 },
1668};
1669
1670static	struct	wordtab logwords[] = {
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	if (frn == NULL)
1786		yyerror("sorry, out of memory");
1787	for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next)
1788		;
1789	if (fr != NULL)
1790		fr->fr_next = frn;
1791	if (frtop == NULL)
1792		frtop = frn;
1793	fr = frn;
1794	frc = frn;
1795	fr->fr_loglevel = 0xffff;
1796	fr->fr_isc = (void *)-1;
1797	fr->fr_logtag = FR_NOLOGTAG;
1798	fr->fr_type = FR_T_NONE;
1799	if (use_inet6 != 0)
1800		fr->fr_v = 6;
1801	else
1802		fr->fr_v = 4;
1803
1804	nrules = 1;
1805}
1806
1807
1808static void setipftype()
1809{
1810	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1811		if (fr->fr_type == FR_T_NONE) {
1812			fr->fr_type = FR_T_IPF;
1813			fr->fr_data = (void *)calloc(sizeof(fripf_t), 1);
1814			if (fr->fr_data == NULL)
1815				yyerror("sorry, out of memory");
1816			fr->fr_dsize = sizeof(fripf_t);
1817			fr->fr_ip.fi_v = frc->fr_v;
1818			fr->fr_mip.fi_v = 0xf;
1819			fr->fr_ipf->fri_sifpidx = -1;
1820			fr->fr_ipf->fri_difpidx = -1;
1821		}
1822		if (fr->fr_type != FR_T_IPF) {
1823			fprintf(stderr, "IPF Type not set\n");
1824		}
1825	}
1826}
1827
1828
1829static frentry_t *addrule()
1830{
1831	frentry_t *f, *f1, *f2;
1832	int count;
1833
1834	for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next)
1835		;
1836
1837	count = nrules;
1838	if (count == 0) {
1839		f = (frentry_t *)calloc(sizeof(*f), 1);
1840		if (f == NULL)
1841			yyerror("sorry, out of memory");
1842		added++;
1843		f2->fr_next = f;
1844		bcopy(f2, f, sizeof(*f));
1845		if (f2->fr_caddr != NULL) {
1846			f->fr_caddr = malloc(f->fr_dsize);
1847			if (f->fr_caddr == NULL)
1848				yyerror("sorry, out of memory");
1849			bcopy(f2->fr_caddr, f->fr_caddr, f->fr_dsize);
1850		}
1851		f->fr_next = NULL;
1852		return f;
1853	}
1854	f = f2;
1855	for (f1 = frc; count > 0; count--, f1 = f1->fr_next) {
1856		f->fr_next = (frentry_t *)calloc(sizeof(*f), 1);
1857		if (f->fr_next == NULL)
1858			yyerror("sorry, out of memory");
1859		added++;
1860		f = f->fr_next;
1861		bcopy(f1, f, sizeof(*f));
1862		f->fr_next = NULL;
1863		if (f->fr_caddr != NULL) {
1864			f->fr_caddr = malloc(f->fr_dsize);
1865			if (f->fr_caddr == NULL)
1866				yyerror("sorry, out of memory");
1867			bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize);
1868		}
1869	}
1870
1871	return f2->fr_next;
1872}
1873
1874
1875static u_32_t lookuphost(name)
1876char *name;
1877{
1878	u_32_t addr;
1879	int i;
1880
1881	hashed = 0;
1882	pooled = 0;
1883	dynamic = -1;
1884
1885	for (i = 0; i < 4; i++) {
1886		if (strncmp(name, frc->fr_ifnames[i],
1887			    sizeof(frc->fr_ifnames[i])) == 0) {
1888			ifpflag = FRI_DYNAMIC;
1889			dynamic = i;
1890			return 0;
1891		}
1892	}
1893
1894	if (gethost(name, &addr) == -1) {
1895		return 0;
1896	}
1897	return addr;
1898}
1899
1900
1901static void dobpf(phrase)
1902char *phrase;
1903{
1904#ifdef IPFILTER_BPF
1905	struct bpf_program bpf;
1906	struct pcap *p;
1907	u_32_t l;
1908	char *s;
1909	int i;
1910
1911	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1912		if (fr->fr_type != FR_T_NONE) {
1913			fprintf(stderr, "cannoy mix IPF and BPF matching\n");
1914			return;
1915		}
1916		fr->fr_type = FR_T_IPF;
1917
1918		if (!strncmp(phrase, "\"0x", 2)) {
1919			phrase++;
1920			fr->fr_data = malloc(4);
1921			if (fr->fr_data == NULL)
1922				yyerror("sorry, out of memory");
1923
1924			for (i = 0, s = strtok(phrase, " \r\n\t"; s != NULL;
1925			     s = strtok(NULL, " \r\n\t"), i++) {
1926				fr->fr_data = realloc(fr->fr_data, (i + 1) * 4);
1927				if (fr->fr_data == NULL)
1928					yyerror("sorry, out of memory");
1929				l = (u_32_t)strtol(s, NULL, 0);
1930				((u_32_t *)fr->fr_data)[i] = l;
1931			}
1932			return;
1933		}
1934
1935		bzero((char *)&bpf, sizeof(bpf));
1936		p = pcap_open_dead(DLT_RAW, 1);
1937		if (!p) {
1938			fprintf(stderr, "pcap_open_dead failed\n");
1939			return;
1940		}
1941
1942		if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff) {
1943			pcap_perror(p, "ipf");
1944			pcap_close(p);
1945			fprintf(stderr, "pcap parsing failed\n");
1946			return;
1947		}
1948		pcap_close(p);
1949
1950		fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
1951		fr->fr_data = malloc(bpf.bf_len);
1952		if (fr->fr_data == NULL)
1953			yyerror("sorry, out of memory");
1954		bcopy((char *)bpf.bf_insns, fr->fr_data, bpf.bf_len);
1955		if (!bpf_validate(fr->fr_data, bpf.bf_len)) {
1956			fprintf(stderr, "BPF validation failed\n");
1957			return;
1958		}
1959	}
1960
1961	if (opts & OPT_DEBUG)
1962		bpf_dump(&bpf, 0);
1963#else
1964	fprintf(stderr, "BPF expressions for matching not supported\n");
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_family = a->al_family;
2007		n->ipn_mask.adf_family = a->al_family;
2008		(void *)bcopy((void *)&a->al_i6addr,
2009			      (void *)&n->ipn_addr.adf_addr,
2010			      sizeof(n->ipn_addr.adf_addr));
2011		(void *)bcopy((void *)&a->al_i6mask,
2012			      (void *)&n->ipn_mask.adf_addr,
2013			      sizeof(n->ipn_mask.adf_addr));
2014		n->ipn_info = a->al_not;
2015		if (a->al_next != NULL) {
2016			n->ipn_next = calloc(1, sizeof(*n));
2017			if (n->ipn_next == NULL)
2018				yyerror("sorry, out of memory");
2019			n = n->ipn_next;
2020		}
2021	}
2022
2023	bzero((char *)&pool, sizeof(pool));
2024	pool.ipo_unit = IPL_LOGIPF;
2025	pool.ipo_list = top;
2026	num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]);
2027
2028	while ((n = top) != NULL) {
2029		top = n->ipn_next;
2030		free(n);
2031	}
2032	return num;
2033}
2034
2035
2036static u_int makehash(list)
2037alist_t *list;
2038{
2039	iphtent_t *n, *top;
2040	iphtable_t iph;
2041	alist_t *a;
2042	int num;
2043
2044	if (list == NULL)
2045		return 0;
2046	top = calloc(1, sizeof(*top));
2047	if (top == NULL)
2048		return 0;
2049
2050	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2051		n->ipe_family = a->al_family;
2052		(void *)bcopy((void *)&a->al_i6addr,
2053			      (void *)&n->ipe_addr,
2054			      sizeof(n->ipe_addr));
2055		(void *)bcopy((void *)&a->al_i6mask,
2056			      (void *)&n->ipe_mask,
2057			      sizeof(n->ipe_mask));
2058		n->ipe_value = 0;
2059		if (a->al_next != NULL) {
2060			n->ipe_next = calloc(1, sizeof(*n));
2061			if (n->ipe_next == NULL)
2062				yyerror("sorry, out of memory");
2063			n = n->ipe_next;
2064		}
2065	}
2066
2067	bzero((char *)&iph, sizeof(iph));
2068	iph.iph_unit = IPL_LOGIPF;
2069	iph.iph_type = IPHASH_LOOKUP;
2070	*iph.iph_name = '\0';
2071
2072	if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0)
2073		sscanf(iph.iph_name, "%u", &num);
2074	else
2075		num = 0;
2076
2077	while ((n = top) != NULL) {
2078		top = n->ipe_next;
2079		free(n);
2080	}
2081	return num;
2082}
2083
2084
2085void ipf_addrule(fd, ioctlfunc, ptr)
2086int fd;
2087ioctlfunc_t ioctlfunc;
2088void *ptr;
2089{
2090	u_int add, del;
2091	frentry_t *fr;
2092	ipfobj_t obj;
2093
2094	fr = ptr;
2095	add = 0;
2096	del = 0;
2097
2098	bzero((char *)&obj, sizeof(obj));
2099	obj.ipfo_rev = IPFILTER_VERSION;
2100	obj.ipfo_size = sizeof(*fr);
2101	obj.ipfo_type = IPFOBJ_FRENTRY;
2102	obj.ipfo_ptr = ptr;
2103
2104	if ((opts & OPT_DONOTHING) != 0)
2105		fd = -1;
2106
2107	if (opts & OPT_ZERORULEST) {
2108		add = SIOCZRLST;
2109	} else if (opts & OPT_INACTIVE) {
2110		add = (u_int)fr->fr_hits ? SIOCINIFR :
2111					   SIOCADIFR;
2112		del = SIOCRMIFR;
2113	} else {
2114		add = (u_int)fr->fr_hits ? SIOCINAFR :
2115					   SIOCADAFR;
2116		del = SIOCRMAFR;
2117	}
2118
2119	if (fr && (opts & OPT_OUTQUE))
2120		fr->fr_flags |= FR_OUTQUE;
2121	if (fr->fr_hits)
2122		fr->fr_hits--;
2123	if (fr && (opts & OPT_VERBOSE))
2124		printfr(fr, ioctlfunc);
2125
2126	if (opts & OPT_DEBUG) {
2127		binprint(fr, sizeof(*fr));
2128		if (fr->fr_data != NULL)
2129			binprint(fr->fr_data, fr->fr_dsize);
2130	}
2131
2132	if ((opts & OPT_ZERORULEST) != 0) {
2133		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2134			if ((opts & OPT_DONOTHING) == 0) {
2135				fprintf(stderr, "%d:", yylineNum);
2136				perror("ioctl(SIOCZRLST)");
2137			}
2138		} else {
2139#ifdef	USE_QUAD_T
2140			printf("hits %qd bytes %qd ",
2141				(long long)fr->fr_hits,
2142				(long long)fr->fr_bytes);
2143#else
2144			printf("hits %ld bytes %ld ",
2145				fr->fr_hits, fr->fr_bytes);
2146#endif
2147			printfr(fr, ioctlfunc);
2148		}
2149	} else if ((opts & OPT_REMOVE) != 0) {
2150		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
2151			if ((opts & OPT_DONOTHING) == 0) {
2152				fprintf(stderr, "%d:", yylineNum);
2153				perror("ioctl(delete rule)");
2154			}
2155		}
2156	} else {
2157		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2158			if (!(opts & OPT_DONOTHING)) {
2159				fprintf(stderr, "%d:", yylineNum);
2160				fprintf(stderr,"ioctl(add/insert rule) failed: rule exists\n");
2161			}
2162		}
2163	}
2164}
2165
2166
2167static void setsyslog()
2168{
2169	savewords = yysettab(logwords);
2170	yybreakondot = 1;
2171}
2172
2173
2174static void unsetsyslog()
2175{
2176	yysettab(savewords);
2177	yybreakondot = 0;
2178}
2179
2180
2181static void fillgroup(fr)
2182frentry_t *fr;
2183{
2184	frentry_t *f;
2185	int i;
2186
2187	for (f = frold; f != NULL; f = f->fr_next)
2188		if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0)
2189			break;
2190	if (f == NULL)
2191		return;
2192
2193	/*
2194	 * Only copy down matching fields if the rules are of the same type
2195	 * and are of ipf type.
2196	 */
2197	if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF)
2198		return;
2199
2200	if (fr->fr_v == 0 && f->fr_v != 0)
2201		fr->fr_v = f->fr_v;
2202
2203	if (fr->fr_mproto == 0 && f->fr_mproto != 0)
2204		fr->fr_mproto = f->fr_mproto;
2205	if (fr->fr_proto == 0 && f->fr_proto != 0)
2206		fr->fr_proto = f->fr_proto;
2207
2208	if (fr->fr_proto == IPPROTO_TCP) {
2209		if (fr->fr_tcpfm == 0 && f->fr_tcpfm != 0)
2210			fr->fr_tcpfm = f->fr_tcpfm;
2211		if (fr->fr_tcpf == 0 && f->fr_tcpf != 0)
2212			fr->fr_tcpf = f->fr_tcpf;
2213	}
2214
2215	if (fr->fr_proto == IPPROTO_ICMP) {
2216		if (fr->fr_icmpm == 0 && f->fr_icmpm != 0)
2217			fr->fr_icmpm = f->fr_icmpm;
2218		if (fr->fr_icmp == 0 && f->fr_icmp != 0)
2219			fr->fr_icmp = f->fr_icmp;
2220	}
2221
2222	if (fr->fr_optbits == 0 && f->fr_optbits != 0)
2223		fr->fr_optbits = f->fr_optbits;
2224	if (fr->fr_optmask == 0 && f->fr_optmask != 0)
2225		fr->fr_optmask = f->fr_optmask;
2226	if (fr->fr_secbits == 0 && f->fr_secbits != 0)
2227		fr->fr_secbits = f->fr_secbits;
2228	if (fr->fr_secmask == 0 && f->fr_secmask != 0)
2229		fr->fr_secmask = f->fr_secmask;
2230	if (fr->fr_authbits == 0 && f->fr_authbits != 0)
2231		fr->fr_authbits = f->fr_authbits;
2232	if (fr->fr_authmask == 0 && f->fr_authmask != 0)
2233		fr->fr_authmask = f->fr_authmask;
2234
2235	for (i = 0; i < 3; i++) {
2236		if (*f->fr_ifnames[i] != '\0' && *fr->fr_ifnames[i] == '\0')
2237			strncpy(fr->fr_ifnames[i], f->fr_ifnames[i],
2238				sizeof(f->fr_ifnames[i]));
2239	}
2240}
2241