xref: /titanic_41/usr/src/cmd/ipf/tools/ipf_y.y (revision 0adc16190e36914964740716575460dda750de39)
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 
49 extern	void	yyerror __P((char *));
50 extern	int	yyparse __P((void));
51 extern	int	yylex __P((void));
52 extern	int	yydebug;
53 extern	FILE	*yyin;
54 extern	int	yylineNum;
55 
56 static	void	newrule __P((void));
57 static	void	setipftype __P((void));
58 static	u_32_t	lookuphost __P((char *));
59 static	void	dobpf __P((char *));
60 static	void	resetaddr __P((void));
61 static	struct	alist_s	*newalist __P((struct alist_s *));
62 static	u_int	makehash __P((struct alist_s *));
63 static	int	makepool __P((struct alist_s *));
64 static	frentry_t *addrule __P((void));
65 static	void	setsyslog __P((void));
66 static	void	unsetsyslog __P((void));
67 static	void	fillgroup __P((frentry_t *));
68 
69 frentry_t	*fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL;
70 
71 static	int		ifpflag = 0;
72 static	int		nowith = 0;
73 static	int		dynamic = -1;
74 static	int		pooled = 0;
75 static	int		hashed = 0;
76 static	int		nrules = 0;
77 static	int		newlist = 0;
78 static	int		added = 0;
79 static	int		ipffd = -1;
80 static	int		*yycont = 0;
81 static	int		ruleopts = 0;
82 static	ioctlfunc_t	ipfioctl[IPL_LOGSIZE];
83 static	addfunc_t	ipfaddfunc = NULL;
84 static	wordtab_t	addrwords[4];
85 static	wordtab_t	maskwords[5];
86 static	wordtab_t	*savewords;
87 static	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 %%
183 file:	line
184 	| assign
185 	| file line
186 	| file assign
187 	;
188 
189 line:	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 
201 xx:	{ newrule(); }
202 	;
203 
204 assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
205 					  resetlexer();
206 					  free($1);
207 					  free($3);
208 					}
209 	;
210 
211 assigning:
212 	'='				{ yyvarnext = 1; }
213 	;
214 
215 rule:	inrule
216 	| outrule
217 	;
218 
219 inrule:
220 	rulehead markin { ruleopts = 0; } inopts rulemain ruletail
221 	;
222 
223 outrule:
224 	rulehead markout { ruleopts = 0; } outopts rulemain ruletail
225 	;
226 
227 rulehead:
228 	collection action
229 	| insert collection action
230 	;
231 
232 markin:	IPFY_IN				{ fr->fr_flags |= FR_INQUE; }
233 	;
234 
235 markout:
236 	IPFY_OUT			{ fr->fr_flags |= FR_OUTQUE; }
237 	;
238 
239 rulemain:
240 	ipfrule
241 	| bpfrule
242 	;
243 
244 ipfrule:
245 	tos ttl proto ip
246 	;
247 
248 bpfrule:
249 	IPFY_BPF '{' YY_STR '}' 	{ dobpf($3); free($3); }
250 	;
251 
252 ruletail:
253 	keep head group tag pps age new
254 	;
255 
256 insert:
257 	'@' YY_NUMBER			{ fr->fr_hits = (U_QUAD_T)$2; }
258 	;
259 
260 collection:
261 	| YY_NUMBER			{ fr->fr_collect = $1; }
262 	;
263 
264 action:	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 
277 block:	blocked
278 	| blocked blockreturn
279 	;
280 
281 blocked:
282 	IPFY_BLOCK			{ fr->fr_flags = FR_BLOCK; }
283 	;
284 blockreturn:
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 
292 log:	IPFY_LOG			{ fr->fr_flags |= FR_LOG; }
293 	| IPFY_LOG logoptions		{ fr->fr_flags |= FR_LOG; }
294 	;
295 
296 auth:	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 
301 func:	YY_STR '/' YY_NUMBER	{ fr->fr_func = nametokva($1,
302 							  ipfioctl[IPL_LOGIPF]);
303 				  fr->fr_arg = $3;
304 				  free($1); }
305 	;
306 
307 inopts:
308 	| inopts inopt
309 	;
310 
311 inopt:
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 
356 outopts:
357 	| outopts outopt
358 	;
359 
360 outopt:
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 
399 tos:	| 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 
404 settos:	IPFY_TOS			{ setipftype(); }
405 	;
406 
407 toslist:
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 
416 ttl:	| setttl YY_NUMBER
417 			{ DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
418 	| setttl lstart ttllist lend
419 	;
420 
421 lstart:	'('				{ newlist = 1; fr = frc; added = 0; }
422 	;
423 
424 lend:	')'				{ nrules += added; }
425 	;
426 
427 lmore:	lanother			{ if (newlist == 1) {
428 						newlist = 0;
429 					  }
430 					  fr = addrule();
431 					  if (yycont != NULL)
432 					  	*yycont = 1;
433 					}
434 	;
435 
436 lanother:
437 	| ','
438 	;
439 
440 setttl:	IPFY_TTL			{ setipftype(); }
441 	;
442 
443 ttllist:
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 
449 proto:	| protox protocol		{ yyresetdict(); }
450 	;
451 
452 protox:	IPFY_PROTO			{ setipftype();
453 					  fr = frc;
454 					  yysetdict(NULL); }
455 	;
456 
457 ip:	srcdst flags with icmp
458 	;
459 
460 group:	| 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 
469 head:	| 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 
476 tag:	| IPFY_TAG YY_NUMBER		{ DOALL(fr->fr_logtag = $2;) }
477 	| IPFY_TAG '(' taglist ')'
478 
479 taglist:
480 	tagspec
481 	| taglist ',' tagspec
482 	;
483 
484 tagspec:
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 
493 pps:	| IPFY_PPS YY_NUMBER		{ DOALL(fr->fr_pps = $2;) }
494 	;
495 
496 new:	| savegroup file restoregroup
497 	;
498 
499 savegroup:
500 	'{'
501 	;
502 
503 restoregroup:
504 	'}'
505 	;
506 
507 logopt:	log
508 	;
509 
510 quick:
511 	IPFY_QUICK			{ fr->fr_flags |= FR_QUICK; }
512 	;
513 
514 on:	IPFY_ON onname
515 	| IPFY_ON onname IPFY_INVIA vianame
516 	| IPFY_ON onname IPFY_OUTVIA vianame
517 	;
518 
519 onname:	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 
575 vianame:
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 
632 dup:	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 
643 froute:	IPFY_FROUTE			{ fr->fr_flags |= FR_FASTROUTE; }
644 	;
645 
646 proute:	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 
657 replyto:
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 
669 logoptions:
670 	logoption
671 	| logoptions logoption
672 	;
673 
674 logoption:
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 
681 returncode:
682 	starticmpcode icmpcode ')'	{ fr->fr_icode = $2; yyresetdict(); }
683 	;
684 
685 starticmpcode:
686 	'('				{ yysetdict(icmpcodewords); }
687 	;
688 
689 srcdst:	IPFY_ALL
690 	| fromto
691 	;
692 
693 protocol:
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 
720 nextstring:
721 	'/'			{ yysetdict(NULL); }
722 	;
723 
724 fromto:	from srcobject to dstobject	{ yyexpectaddr = 0; yycont = NULL; }
725 	| to dstobject			{ yyexpectaddr = 0; yycont = NULL; }
726 	| from srcobject		{ yyexpectaddr = 0; yycont = NULL; }
727 	;
728 
729 from:	IPFY_FROM			{ setipftype();
730 					  if (fr == NULL)
731 						fr = frc;
732 					  yyexpectaddr = 1;
733 					  yycont = &yyexpectaddr;
734 					  yysetdict(addrwords);
735 					  resetaddr(); }
736 	;
737 
738 to:	IPFY_TO				{ if (fr == NULL)
739 						fr = frc;
740 					  yyexpectaddr = 1;
741 					  yycont = &yyexpectaddr;
742 					  yysetdict(addrwords);
743 					  resetaddr(); }
744 	;
745 
746 with:	| andwith withlist
747 	;
748 
749 andwith:
750 	IPFY_WITH			{ nowith = 0; setipftype(); }
751 	| IPFY_AND			{ nowith = 0; setipftype(); }
752 	;
753 
754 flags:	| 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 
772 flagset:
773 	YY_STR				{ $$ = tcpflags($1); free($1); }
774 	| YY_HEX			{ $$ = $1; }
775 	;
776 
777 srcobject:
778 	srcaddr srcport
779 	| '!' srcaddr srcport
780 		{ DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
781 	| fromport
782 	;
783 
784 srcaddr:
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 
796 srcaddrlist:
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 
816 srcport:
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 
826 fromport:
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 
836 srcportlist:
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 
842 dstobject:
843 	toport
844 	| dstaddr dstport
845 	| '!' dstaddr dstport
846 			{ DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
847 	;
848 
849 dstaddr:
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 
861 dstaddrlist:
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 
882 dstport:
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 
892 toport:
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 
902 dstportlist:
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 
908 addr:	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 
928 ipaddr:	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 
955 maskspace:
956 	'/'
957 	| IPFY_MASK
958 	;
959 
960 ipv4mask:
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 
990 ipv6mask:
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 
1018 hostname:
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 
1030 addrlist:
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 
1050 pool:	IPFY_POOL	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1051 	;
1052 
1053 hash:	IPFY_HASH	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1054 	;
1055 
1056 poollist:
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 
1095 port:	IPFY_PORT			{ yyexpectaddr = 0;
1096 					  yycont = NULL;
1097 					}
1098 	;
1099 
1100 portc:	port compare			{ $$ = $2;
1101 					  yysetdict(NULL); }
1102 	| porteq			{ $$ = $1; }
1103 	;
1104 
1105 porteq:	port '='			{ $$ = FR_EQUAL;
1106 					  yysetdict(NULL); }
1107 	;
1108 
1109 portr:	IPFY_PORT			{ yyexpectaddr = 0;
1110 					  yycont = NULL;
1111 					  yysetdict(NULL); }
1112 	;
1113 
1114 portcomp:
1115 	portc portnum			{ $$.pc = $1;
1116 					  $$.p1 = $2;
1117 					  yyresetdict(); }
1118 	;
1119 
1120 portrange:
1121 	portr portnum range portnum	{ $$.p1 = $2;
1122 					  $$.pc = $3;
1123 					  $$.p2 = $4;
1124 					  yyresetdict(); }
1125 	;
1126 
1127 icmp:	| itype icode
1128 	;
1129 
1130 itype:	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 
1137 seticmptype:
1138 	IPFY_ICMPTYPE				{ setipftype();
1139 						  yysetdict(icmptypewords); }
1140 	;
1141 
1142 icode:	| 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 
1149 seticmpcode:
1150 	IPFY_ICMPCODE				{ yysetdict(icmpcodewords); }
1151 	;
1152 
1153 typelist:
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 
1160 codelist:
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 
1167 age:	| 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 
1174 keep:	| IPFY_KEEP keepstate
1175 	| IPFY_KEEP keepfrag
1176 	| IPFY_KEEP keepstate IPFY_KEEP keepfrag
1177 	;
1178 
1179 keepstate:
1180 	IPFY_STATE stateoptlist		{ DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
1181 	;
1182 
1183 keepfrag:
1184 	IPFY_FRAGS fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1185 	;
1186 
1187 fragoptlist:
1188 	| '(' fragopts ')'
1189 	;
1190 
1191 fragopts:
1192 	fragopt lanother fragopts
1193 	| fragopt
1194 	;
1195 
1196 fragopt:
1197 	IPFY_STRICT			{ DOALL(fr->fr_flags |= FR_FRSTRICT;) }
1198 	;
1199 
1200 stateoptlist:
1201 	| '(' stateopts ')'
1202 	;
1203 
1204 stateopts:
1205 	stateopt lanother stateopts
1206 	| stateopt
1207 	;
1208 
1209 stateopt:
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 
1224 portnum:
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 
1233 withlist:
1234 	withopt
1235 	| withlist withopt
1236 	;
1237 
1238 withopt:
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 
1247 startv6hdrs:
1248 	IPF6_V6HDRS	{ if (use_inet6 == 0)
1249 				yyerror("only available with IPv6");
1250 			}
1251 	;
1252 
1253 notwith:
1254 	IPFY_NOT			{ nowith = 1; }
1255 	| IPFY_NO			{ nowith = 1; }
1256 	;
1257 
1258 opttype:
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 
1274 ipopts:	optlist		{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1275 				if (!nowith)
1276 					fr->fr_ip.fi_optmsk |= $1;)
1277 			}
1278 	;
1279 
1280 optlist:
1281 	opt				{ $$ |= $1; }
1282 	| optlist ',' opt		{ $$ |= $1 | $3; }
1283 	;
1284 
1285 ipv6hdrs:
1286 	ipv6hdrlist	{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1287 				if (!nowith)
1288 					fr->fr_ip.fi_optmsk |= $1;)
1289 			}
1290 	;
1291 
1292 ipv6hdrlist:
1293 	ipv6hdr				{ $$ |= $1; }
1294 	| ipv6hdrlist ',' ipv6hdr	{ $$ |= $1 | $3; }
1295 	;
1296 
1297 secname:
1298 	seclevel			{ $$ |= $1; }
1299 	| secname ',' seclevel		{ $$ |= $1 | $3; }
1300 	;
1301 
1302 seclevel:
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 
1313 icmptype:
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 
1332 icmpcode:
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 
1352 opt:
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 
1385 ipv6hdr:
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 
1396 level:	IPFY_LEVEL			{ setsyslog(); }
1397 	;
1398 
1399 loglevel:
1400 	priority			{ fr->fr_loglevel = LOG_LOCAL0|$1; }
1401 	| facility '.' priority		{ fr->fr_loglevel = $1 | $3; }
1402 	;
1403 
1404 facility:
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 
1430 priority:
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 
1441 compare:
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 
1451 range:	YY_RANGE_IN			{ $$ = FR_INRANGE; }
1452 	| YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
1453 	| ':'				{ $$ = FR_INCRANGE; }
1454 	;
1455 
1456 servicename:
1457 	YY_STR				{ $$ = $1; }
1458 	;
1459 
1460 interfacename:	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 
1472 name:	YY_STR				{ $$ = $1; }
1473 	;
1474 
1475 ipv4:	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 
1487 static	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 
1616 static	struct	wordtab	addrwords[4] = {
1617 	{ "any",			IPFY_ANY },
1618 	{ "hash",			IPFY_HASH },
1619 	{ "pool",			IPFY_POOL },
1620 	{ NULL,				0 }
1621 };
1622 
1623 static	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 
1631 static	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 
1650 static	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 
1670 static	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 
1709 int ipf_parsefile(fd, addfunc, iocfuncs, filename)
1710 int fd;
1711 addfunc_t addfunc;
1712 ioctlfunc_t *iocfuncs;
1713 char *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 
1745 int ipf_parsesome(fd, addfunc, iocfuncs, fp)
1746 int fd;
1747 addfunc_t addfunc;
1748 ioctlfunc_t *iocfuncs;
1749 FILE *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 
1780 static void newrule()
1781 {
1782 	frentry_t *frn;
1783 
1784 	frn = (frentry_t *)calloc(1, sizeof(frentry_t));
1785 	for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next)
1786 		;
1787 	if (fr != NULL)
1788 		fr->fr_next = frn;
1789 	if (frtop == NULL)
1790 		frtop = frn;
1791 	fr = frn;
1792 	frc = frn;
1793 	fr->fr_loglevel = 0xffff;
1794 	fr->fr_isc = (void *)-1;
1795 	fr->fr_logtag = FR_NOLOGTAG;
1796 	fr->fr_type = FR_T_NONE;
1797 	if (use_inet6 != 0)
1798 		fr->fr_v = 6;
1799 	else
1800 		fr->fr_v = 4;
1801 
1802 	nrules = 1;
1803 }
1804 
1805 
1806 static void setipftype()
1807 {
1808 	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1809 		if (fr->fr_type == FR_T_NONE) {
1810 			fr->fr_type = FR_T_IPF;
1811 			fr->fr_data = (void *)calloc(sizeof(fripf_t), 1);
1812 			fr->fr_dsize = sizeof(fripf_t);
1813 			fr->fr_ip.fi_v = frc->fr_v;
1814 			fr->fr_mip.fi_v = 0xf;
1815 			fr->fr_ipf->fri_sifpidx = -1;
1816 			fr->fr_ipf->fri_difpidx = -1;
1817 		}
1818 		if (fr->fr_type != FR_T_IPF) {
1819 			fprintf(stderr, "IPF Type not set\n");
1820 		}
1821 	}
1822 }
1823 
1824 
1825 static frentry_t *addrule()
1826 {
1827 	frentry_t *f, *f1, *f2;
1828 	int count;
1829 
1830 	for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next)
1831 		;
1832 
1833 	count = nrules;
1834 	if (count == 0) {
1835 		f = (frentry_t *)calloc(sizeof(*f), 1);
1836 		added++;
1837 		f2->fr_next = f;
1838 		bcopy(f2, f, sizeof(*f));
1839 		if (f2->fr_caddr != NULL) {
1840 			f->fr_caddr = malloc(f->fr_dsize);
1841 			bcopy(f2->fr_caddr, f->fr_caddr, f->fr_dsize);
1842 		}
1843 		f->fr_next = NULL;
1844 		return f;
1845 	}
1846 	f = f2;
1847 	for (f1 = frc; count > 0; count--, f1 = f1->fr_next) {
1848 		f->fr_next = (frentry_t *)calloc(sizeof(*f), 1);
1849 		added++;
1850 		f = f->fr_next;
1851 		bcopy(f1, f, sizeof(*f));
1852 		f->fr_next = NULL;
1853 		if (f->fr_caddr != NULL) {
1854 			f->fr_caddr = malloc(f->fr_dsize);
1855 			bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize);
1856 		}
1857 	}
1858 
1859 	return f2->fr_next;
1860 }
1861 
1862 
1863 static u_32_t lookuphost(name)
1864 char *name;
1865 {
1866 	u_32_t addr;
1867 	int i;
1868 
1869 	hashed = 0;
1870 	pooled = 0;
1871 	dynamic = -1;
1872 
1873 	for (i = 0; i < 4; i++) {
1874 		if (strncmp(name, frc->fr_ifnames[i],
1875 			    sizeof(frc->fr_ifnames[i])) == 0) {
1876 			ifpflag = FRI_DYNAMIC;
1877 			dynamic = i;
1878 			return 0;
1879 		}
1880 	}
1881 
1882 	if (gethost(name, &addr) == -1) {
1883 		return 0;
1884 	}
1885 	return addr;
1886 }
1887 
1888 
1889 static void dobpf(phrase)
1890 char *phrase;
1891 {
1892 #ifdef IPFILTER_BPF
1893 	struct bpf_program bpf;
1894 	struct pcap *p;
1895 	u_32_t l;
1896 	char *s;
1897 	int i;
1898 
1899 	for (fr = frc; fr != NULL; fr = fr->fr_next) {
1900 		if (fr->fr_type != FR_T_NONE) {
1901 			fprintf(stderr, "cannoy mix IPF and BPF matching\n");
1902 			return;
1903 		}
1904 		fr->fr_type = FR_T_IPF;
1905 
1906 		if (!strncmp(phrase, "\"0x", 2)) {
1907 			phrase++;
1908 			fr->fr_data = malloc(4);
1909 
1910 			for (i = 0, s = strtok(phrase, " \r\n\t"; s != NULL;
1911 			     s = strtok(NULL, " \r\n\t"), i++) {
1912 				fr->fr_data = realloc(fr->fr_data, (i + 1) * 4);
1913 				l = (u_32_t)strtol(s, NULL, 0);
1914 				((u_32_t *)fr->fr_data)[i] = l;
1915 			}
1916 			return;
1917 		}
1918 
1919 		bzero((char *)&bpf, sizeof(bpf));
1920 		p = pcap_open_dead(DLT_RAW, 1);
1921 		if (!p) {
1922 			fprintf(stderr, "pcap_open_dead failed\n");
1923 			return;
1924 		}
1925 
1926 		if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff) {
1927 			pcap_perror(p, "ipf");
1928 			pcap_close(p);
1929 			fprintf(stderr, "pcap parsing failed\n");
1930 			return;
1931 		}
1932 		pcap_close(p);
1933 
1934 		fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn);
1935 		fr->fr_data = malloc(bpf.bf_len);
1936 		bcopy((char *)bpf.bf_insns, fr->fr_data, bpf.bf_len);
1937 		if (!bpf_validate(fr->fr_data, bpf.bf_len)) {
1938 			fprintf(stderr, "BPF validation failed\n");
1939 			return;
1940 		}
1941 	}
1942 
1943 	if (opts & OPT_DEBUG)
1944 		bpf_dump(&bpf, 0);
1945 #else
1946 	fprintf(stderr, "BPF expressions for matching not supported\n");
1947 #endif
1948 }
1949 
1950 
1951 static void resetaddr()
1952 {
1953 	hashed = 0;
1954 	pooled = 0;
1955 	dynamic = -1;
1956 }
1957 
1958 
1959 static alist_t *newalist(ptr)
1960 alist_t *ptr;
1961 {
1962 	alist_t *al;
1963 
1964 	al = malloc(sizeof(*al));
1965 	if (al == NULL)
1966 		return NULL;
1967 	al->al_not = 0;
1968 	al->al_next = ptr;
1969 	return al;
1970 }
1971 
1972 
1973 static int makepool(list)
1974 alist_t *list;
1975 {
1976 	ip_pool_node_t *n, *top;
1977 	ip_pool_t pool;
1978 	alist_t *a;
1979 	int num;
1980 
1981 	if (list == NULL)
1982 		return 0;
1983 	top = calloc(1, sizeof(*top));
1984 	if (top == NULL)
1985 		return 0;
1986 
1987 	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
1988 		n->ipn_addr.adf_family = a->al_family;
1989 		n->ipn_mask.adf_family = a->al_family;
1990 		(void *)bcopy((void *)&a->al_i6addr,
1991 			      (void *)&n->ipn_addr.adf_addr,
1992 			      sizeof(n->ipn_addr.adf_addr));
1993 		(void *)bcopy((void *)&a->al_i6mask,
1994 			      (void *)&n->ipn_mask.adf_addr,
1995 			      sizeof(n->ipn_mask.adf_addr));
1996 		n->ipn_info = a->al_not;
1997 		if (a->al_next != NULL) {
1998 			n->ipn_next = calloc(1, sizeof(*n));
1999 			n = n->ipn_next;
2000 		}
2001 	}
2002 
2003 	bzero((char *)&pool, sizeof(pool));
2004 	pool.ipo_unit = IPL_LOGIPF;
2005 	pool.ipo_list = top;
2006 	num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]);
2007 
2008 	while ((n = top) != NULL) {
2009 		top = n->ipn_next;
2010 		free(n);
2011 	}
2012 	return num;
2013 }
2014 
2015 
2016 static u_int makehash(list)
2017 alist_t *list;
2018 {
2019 	iphtent_t *n, *top;
2020 	iphtable_t iph;
2021 	alist_t *a;
2022 	int num;
2023 
2024 	if (list == NULL)
2025 		return 0;
2026 	top = calloc(1, sizeof(*top));
2027 	if (top == NULL)
2028 		return 0;
2029 
2030 	for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) {
2031 		n->ipe_family = a->al_family;
2032 		(void *)bcopy((void *)&a->al_i6addr,
2033 			      (void *)&n->ipe_addr,
2034 			      sizeof(n->ipe_addr));
2035 		(void *)bcopy((void *)&a->al_i6mask,
2036 			      (void *)&n->ipe_mask,
2037 			      sizeof(n->ipe_mask));
2038 		n->ipe_value = 0;
2039 		if (a->al_next != NULL) {
2040 			n->ipe_next = calloc(1, sizeof(*n));
2041 			n = n->ipe_next;
2042 		}
2043 	}
2044 
2045 	bzero((char *)&iph, sizeof(iph));
2046 	iph.iph_unit = IPL_LOGIPF;
2047 	iph.iph_type = IPHASH_LOOKUP;
2048 	*iph.iph_name = '\0';
2049 
2050 	if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0)
2051 		sscanf(iph.iph_name, "%u", &num);
2052 	else
2053 		num = 0;
2054 
2055 	while ((n = top) != NULL) {
2056 		top = n->ipe_next;
2057 		free(n);
2058 	}
2059 	return num;
2060 }
2061 
2062 
2063 void ipf_addrule(fd, ioctlfunc, ptr)
2064 int fd;
2065 ioctlfunc_t ioctlfunc;
2066 void *ptr;
2067 {
2068 	u_int add, del;
2069 	frentry_t *fr;
2070 	ipfobj_t obj;
2071 
2072 	fr = ptr;
2073 	add = 0;
2074 	del = 0;
2075 
2076 	bzero((char *)&obj, sizeof(obj));
2077 	obj.ipfo_rev = IPFILTER_VERSION;
2078 	obj.ipfo_size = sizeof(*fr);
2079 	obj.ipfo_type = IPFOBJ_FRENTRY;
2080 	obj.ipfo_ptr = ptr;
2081 
2082 	if ((opts & OPT_DONOTHING) != 0)
2083 		fd = -1;
2084 
2085 	if (opts & OPT_ZERORULEST) {
2086 		add = SIOCZRLST;
2087 	} else if (opts & OPT_INACTIVE) {
2088 		add = (u_int)fr->fr_hits ? SIOCINIFR :
2089 					   SIOCADIFR;
2090 		del = SIOCRMIFR;
2091 	} else {
2092 		add = (u_int)fr->fr_hits ? SIOCINAFR :
2093 					   SIOCADAFR;
2094 		del = SIOCRMAFR;
2095 	}
2096 
2097 	if (fr && (opts & OPT_OUTQUE))
2098 		fr->fr_flags |= FR_OUTQUE;
2099 	if (fr->fr_hits)
2100 		fr->fr_hits--;
2101 	if (fr && (opts & OPT_VERBOSE))
2102 		printfr(fr, ioctlfunc);
2103 
2104 	if (opts & OPT_DEBUG) {
2105 		binprint(fr, sizeof(*fr));
2106 		if (fr->fr_data != NULL)
2107 			binprint(fr->fr_data, fr->fr_dsize);
2108 	}
2109 
2110 	if ((opts & OPT_ZERORULEST) != 0) {
2111 		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2112 			if ((opts & OPT_DONOTHING) == 0) {
2113 				fprintf(stderr, "%d:", yylineNum);
2114 				perror("ioctl(SIOCZRLST)");
2115 			}
2116 		} else {
2117 #ifdef	USE_QUAD_T
2118 			printf("hits %qd bytes %qd ",
2119 				(long long)fr->fr_hits,
2120 				(long long)fr->fr_bytes);
2121 #else
2122 			printf("hits %ld bytes %ld ",
2123 				fr->fr_hits, fr->fr_bytes);
2124 #endif
2125 			printfr(fr, ioctlfunc);
2126 		}
2127 	} else if ((opts & OPT_REMOVE) != 0) {
2128 		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
2129 			if ((opts & OPT_DONOTHING) == 0) {
2130 				fprintf(stderr, "%d:", yylineNum);
2131 				perror("ioctl(delete rule)");
2132 			}
2133 		}
2134 	} else {
2135 		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
2136 			if (!(opts & OPT_DONOTHING)) {
2137 				fprintf(stderr, "%d:", yylineNum);
2138 				fprintf(stderr,"ioctl(add/insert rule) failed: rule exists\n");
2139 			}
2140 		}
2141 	}
2142 }
2143 
2144 
2145 static void setsyslog()
2146 {
2147 	savewords = yysettab(logwords);
2148 	yybreakondot = 1;
2149 }
2150 
2151 
2152 static void unsetsyslog()
2153 {
2154 	yysettab(savewords);
2155 	yybreakondot = 0;
2156 }
2157 
2158 
2159 static void fillgroup(fr)
2160 frentry_t *fr;
2161 {
2162 	frentry_t *f;
2163 	int i;
2164 
2165 	for (f = frold; f != NULL; f = f->fr_next)
2166 		if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0)
2167 			break;
2168 	if (f == NULL)
2169 		return;
2170 
2171 	/*
2172 	 * Only copy down matching fields if the rules are of the same type
2173 	 * and are of ipf type.
2174 	 */
2175 	if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF)
2176 		return;
2177 
2178 	if (fr->fr_v == 0 && f->fr_v != 0)
2179 		fr->fr_v = f->fr_v;
2180 
2181 	if (fr->fr_mproto == 0 && f->fr_mproto != 0)
2182 		fr->fr_mproto = f->fr_mproto;
2183 	if (fr->fr_proto == 0 && f->fr_proto != 0)
2184 		fr->fr_proto = f->fr_proto;
2185 
2186 	if (fr->fr_proto == IPPROTO_TCP) {
2187 		if (fr->fr_tcpfm == 0 && f->fr_tcpfm != 0)
2188 			fr->fr_tcpfm = f->fr_tcpfm;
2189 		if (fr->fr_tcpf == 0 && f->fr_tcpf != 0)
2190 			fr->fr_tcpf = f->fr_tcpf;
2191 	}
2192 
2193 	if (fr->fr_proto == IPPROTO_ICMP) {
2194 		if (fr->fr_icmpm == 0 && f->fr_icmpm != 0)
2195 			fr->fr_icmpm = f->fr_icmpm;
2196 		if (fr->fr_icmp == 0 && f->fr_icmp != 0)
2197 			fr->fr_icmp = f->fr_icmp;
2198 	}
2199 
2200 	if (fr->fr_optbits == 0 && f->fr_optbits != 0)
2201 		fr->fr_optbits = f->fr_optbits;
2202 	if (fr->fr_optmask == 0 && f->fr_optmask != 0)
2203 		fr->fr_optmask = f->fr_optmask;
2204 	if (fr->fr_secbits == 0 && f->fr_secbits != 0)
2205 		fr->fr_secbits = f->fr_secbits;
2206 	if (fr->fr_secmask == 0 && f->fr_secmask != 0)
2207 		fr->fr_secmask = f->fr_secmask;
2208 	if (fr->fr_authbits == 0 && f->fr_authbits != 0)
2209 		fr->fr_authbits = f->fr_authbits;
2210 	if (fr->fr_authmask == 0 && f->fr_authmask != 0)
2211 		fr->fr_authmask = f->fr_authmask;
2212 
2213 	for (i = 0; i < 3; i++) {
2214 		if (*f->fr_ifnames[i] != '\0' && *fr->fr_ifnames[i] == '\0')
2215 			strncpy(fr->fr_ifnames[i], f->fr_ifnames[i],
2216 				sizeof(f->fr_ifnames[i]));
2217 	}
2218 }
2219