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