xref: /titanic_44/usr/src/cmd/ipf/tools/ipf_y.y (revision b7f45089ccbe01bab3d7c7377b49d80d2ae18a69)
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 
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 %%
182 file:	line
183 	| assign
184 	| file line
185 	| file assign
186 	;
187 
188 line:	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 
200 xx:	{ newrule(); }
201 	;
202 
203 assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
204 					  resetlexer();
205 					  free($1);
206 					  free($3);
207 					}
208 	;
209 
210 assigning:
211 	'='				{ yyvarnext = 1; }
212 	;
213 
214 rule:	inrule
215 	| outrule
216 	;
217 
218 inrule:
219 	rulehead markin { ruleopts = 0; } inopts rulemain ruletail
220 	;
221 
222 outrule:
223 	rulehead markout { ruleopts = 0; } outopts rulemain ruletail
224 	;
225 
226 rulehead:
227 	collection action
228 	| insert collection action
229 	;
230 
231 markin:	IPFY_IN				{ fr->fr_flags |= FR_INQUE; }
232 	;
233 
234 markout:
235 	IPFY_OUT			{ fr->fr_flags |= FR_OUTQUE; }
236 	;
237 
238 rulemain:
239 	ipfrule
240 	| bpfrule
241 	;
242 
243 ipfrule:
244 	tos ttl proto ip
245 	;
246 
247 bpfrule:
248 	IPFY_BPF '{' YY_STR '}' 	{ dobpf($3); free($3); }
249 	;
250 
251 ruletail:
252 	keep head group tag pps age new
253 	;
254 
255 insert:
256 	'@' YY_NUMBER			{ fr->fr_hits = (U_QUAD_T)$2; }
257 	;
258 
259 collection:
260 	| YY_NUMBER			{ fr->fr_collect = $1; }
261 	;
262 
263 action:	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 
276 block:	blocked
277 	| blocked blockreturn
278 	;
279 
280 blocked:
281 	IPFY_BLOCK			{ fr->fr_flags = FR_BLOCK; }
282 	;
283 blockreturn:
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 
291 log:	IPFY_LOG			{ fr->fr_flags |= FR_LOG; }
292 	| IPFY_LOG logoptions		{ fr->fr_flags |= FR_LOG; }
293 	;
294 
295 auth:	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 
300 func:	YY_STR '/' YY_NUMBER	{ fr->fr_func = nametokva($1,
301 							  ipfioctl[IPL_LOGIPF]);
302 				  fr->fr_arg = $3;
303 				  free($1); }
304 	;
305 
306 inopts:
307 	| inopts inopt
308 	;
309 
310 inopt:
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 
355 outopts:
356 	| outopts outopt
357 	;
358 
359 outopt:
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 
398 tos:	| 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 
403 settos:	IPFY_TOS			{ setipftype(); }
404 	;
405 
406 toslist:
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 
415 ttl:	| setttl YY_NUMBER
416 			{ DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) }
417 	| setttl lstart ttllist lend
418 	;
419 
420 lstart:	'('				{ newlist = 1; fr = frc; added = 0; }
421 	;
422 
423 lend:	')'				{ nrules += added; }
424 	;
425 
426 lmore:	lanother			{ if (newlist == 1) {
427 						newlist = 0;
428 					  }
429 					  fr = addrule();
430 					  if (yycont != NULL)
431 					  	*yycont = 1;
432 					}
433 	;
434 
435 lanother:
436 	| ','
437 	;
438 
439 setttl:	IPFY_TTL			{ setipftype(); }
440 	;
441 
442 ttllist:
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 
448 proto:	| protox protocol		{ yyresetdict(); }
449 	;
450 
451 protox:	IPFY_PROTO			{ setipftype();
452 					  fr = frc;
453 					  yysetdict(NULL); }
454 	;
455 
456 ip:	srcdst flags with icmp
457 	;
458 
459 group:	| 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 
468 head:	| 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 
475 tag:	| IPFY_TAG YY_NUMBER		{ DOALL(fr->fr_logtag = $2;) }
476 	| IPFY_TAG '(' taglist ')'
477 
478 taglist:
479 	tagspec
480 	| taglist ',' tagspec
481 	;
482 
483 tagspec:
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 
492 pps:	| IPFY_PPS YY_NUMBER		{ DOALL(fr->fr_pps = $2;) }
493 	;
494 
495 new:	| savegroup file restoregroup
496 	;
497 
498 savegroup:
499 	'{'
500 	;
501 
502 restoregroup:
503 	'}'
504 	;
505 
506 logopt:	log
507 	;
508 
509 quick:
510 	IPFY_QUICK			{ fr->fr_flags |= FR_QUICK; }
511 	;
512 
513 on:	IPFY_ON onname
514 	| IPFY_ON onname IPFY_INVIA vianame
515 	| IPFY_ON onname IPFY_OUTVIA vianame
516 	;
517 
518 onname:	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 
574 vianame:
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 
631 dup:	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 
642 froute:	IPFY_FROUTE			{ fr->fr_flags |= FR_FASTROUTE; }
643 	;
644 
645 proute:	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 
656 replyto:
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 
668 logoptions:
669 	logoption
670 	| logoptions logoption
671 	;
672 
673 logoption:
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 
680 returncode:
681 	starticmpcode icmpcode ')'	{ fr->fr_icode = $2; yyresetdict(); }
682 	;
683 
684 starticmpcode:
685 	'('				{ yysetdict(icmpcodewords); }
686 	;
687 
688 srcdst:	IPFY_ALL
689 	| fromto
690 	;
691 
692 protocol:
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 
719 nextstring:
720 	'/'			{ yysetdict(NULL); }
721 	;
722 
723 fromto:	from srcobject to dstobject	{ yyexpectaddr = 0; yycont = NULL; }
724 	| to dstobject			{ yyexpectaddr = 0; yycont = NULL; }
725 	| from srcobject		{ yyexpectaddr = 0; yycont = NULL; }
726 	;
727 
728 from:	IPFY_FROM			{ setipftype();
729 					  if (fr == NULL)
730 						fr = frc;
731 					  yyexpectaddr = 1;
732 					  yycont = &yyexpectaddr;
733 					  yysetdict(addrwords);
734 					  resetaddr(); }
735 	;
736 
737 to:	IPFY_TO				{ if (fr == NULL)
738 						fr = frc;
739 					  yyexpectaddr = 1;
740 					  yycont = &yyexpectaddr;
741 					  yysetdict(addrwords);
742 					  resetaddr(); }
743 	;
744 
745 with:	| andwith withlist
746 	;
747 
748 andwith:
749 	IPFY_WITH			{ nowith = 0; setipftype(); }
750 	| IPFY_AND			{ nowith = 0; setipftype(); }
751 	;
752 
753 flags:	| 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 
771 flagset:
772 	YY_STR				{ $$ = tcpflags($1); free($1); }
773 	| YY_HEX			{ $$ = $1; }
774 	;
775 
776 srcobject:
777 	srcaddr srcport
778 	| '!' srcaddr srcport
779 		{ DOALL(fr->fr_flags |= FR_NOTSRCIP;) }
780 	| fromport
781 	;
782 
783 srcaddr:
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 
795 srcaddrlist:
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 
815 srcport:
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 
825 fromport:
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 
835 srcportlist:
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 
841 dstobject:
842 	toport
843 	| dstaddr dstport
844 	| '!' dstaddr dstport
845 			{ DOALL(fr->fr_flags |= FR_NOTDSTIP;) }
846 	;
847 
848 dstaddr:
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 
860 dstaddrlist:
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 
881 dstport:
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 
891 toport:
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 
901 dstportlist:
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 
907 addr:	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 
927 ipaddr:	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 
952 maskspace:
953 	'/'
954 	| IPFY_MASK
955 	;
956 
957 ipv4mask:
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 
987 ipv6mask:
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 
1015 hostname:
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 
1027 addrlist:
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 
1037 pool:	IPFY_POOL	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1038 	;
1039 
1040 hash:	IPFY_HASH	{ yyexpectaddr = 0; yycont = NULL; yyresetdict(); }
1041 	;
1042 
1043 poollist:
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 
1062 port:	IPFY_PORT			{ yyexpectaddr = 0;
1063 					  yycont = NULL;
1064 					}
1065 	;
1066 
1067 portc:	port compare			{ $$ = $2;
1068 					  yysetdict(NULL); }
1069 	| porteq			{ $$ = $1; }
1070 	;
1071 
1072 porteq:	port '='			{ $$ = FR_EQUAL;
1073 					  yysetdict(NULL); }
1074 	;
1075 
1076 portr:	IPFY_PORT			{ yyexpectaddr = 0;
1077 					  yycont = NULL;
1078 					  yysetdict(NULL); }
1079 	;
1080 
1081 portcomp:
1082 	portc portnum			{ $$.pc = $1;
1083 					  $$.p1 = $2;
1084 					  yyresetdict(); }
1085 	;
1086 
1087 portrange:
1088 	portr portnum range portnum	{ $$.p1 = $2;
1089 					  $$.pc = $3;
1090 					  $$.p2 = $4;
1091 					  yyresetdict(); }
1092 	;
1093 
1094 icmp:	| itype icode
1095 	;
1096 
1097 itype:	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 
1104 seticmptype:
1105 	IPFY_ICMPTYPE				{ setipftype();
1106 						  yysetdict(icmptypewords); }
1107 	;
1108 
1109 icode:	| 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 
1116 seticmpcode:
1117 	IPFY_ICMPCODE				{ yysetdict(icmpcodewords); }
1118 	;
1119 
1120 typelist:
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 
1127 codelist:
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 
1134 age:	| 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 
1141 keep:	| IPFY_KEEP keepstate
1142 	| IPFY_KEEP keepfrag
1143 	| IPFY_KEEP keepstate IPFY_KEEP keepfrag
1144 	;
1145 
1146 keepstate:
1147 	IPFY_STATE stateoptlist		{ DOALL(fr->fr_flags |= FR_KEEPSTATE;)}
1148 	;
1149 
1150 keepfrag:
1151 	IPFY_FRAGS fragoptlist		{ DOALL(fr->fr_flags |= FR_KEEPFRAG;) }
1152 	;
1153 
1154 fragoptlist:
1155 	| '(' fragopts ')'
1156 	;
1157 
1158 fragopts:
1159 	fragopt lanother fragopts
1160 	| fragopt
1161 	;
1162 
1163 fragopt:
1164 	IPFY_STRICT			{ DOALL(fr->fr_flags |= FR_FRSTRICT;) }
1165 	;
1166 
1167 stateoptlist:
1168 	| '(' stateopts ')'
1169 	;
1170 
1171 stateopts:
1172 	stateopt lanother stateopts
1173 	| stateopt
1174 	;
1175 
1176 stateopt:
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 
1191 portnum:
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 
1200 withlist:
1201 	withopt
1202 	| withlist withopt
1203 	;
1204 
1205 withopt:
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 
1214 startv6hdrs:
1215 	IPF6_V6HDRS	{ if (use_inet6 == 0)
1216 				yyerror("only available with IPv6");
1217 			}
1218 	;
1219 
1220 notwith:
1221 	IPFY_NOT			{ nowith = 1; }
1222 	| IPFY_NO			{ nowith = 1; }
1223 	;
1224 
1225 opttype:
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 
1241 ipopts:	optlist		{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1242 				if (!nowith)
1243 					fr->fr_ip.fi_optmsk |= $1;)
1244 			}
1245 	;
1246 
1247 optlist:
1248 	opt				{ $$ |= $1; }
1249 	| optlist ',' opt		{ $$ |= $1 | $3; }
1250 	;
1251 
1252 ipv6hdrs:
1253 	ipv6hdrlist	{ DOALL(fr->fr_mip.fi_optmsk |= $1;
1254 				if (!nowith)
1255 					fr->fr_ip.fi_optmsk |= $1;)
1256 			}
1257 	;
1258 
1259 ipv6hdrlist:
1260 	ipv6hdr				{ $$ |= $1; }
1261 	| ipv6hdrlist ',' ipv6hdr	{ $$ |= $1 | $3; }
1262 	;
1263 
1264 secname:
1265 	seclevel			{ $$ |= $1; }
1266 	| secname ',' seclevel		{ $$ |= $1 | $3; }
1267 	;
1268 
1269 seclevel:
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 
1280 icmptype:
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 
1299 icmpcode:
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 
1319 opt:
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 
1352 ipv6hdr:
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 
1363 level:	IPFY_LEVEL			{ setsyslog(); }
1364 	;
1365 
1366 loglevel:
1367 	priority			{ fr->fr_loglevel = LOG_LOCAL0|$1; }
1368 	| facility '.' priority		{ fr->fr_loglevel = $1 | $3; }
1369 	;
1370 
1371 facility:
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 
1397 priority:
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 
1408 compare:
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 
1418 range:	YY_RANGE_IN			{ $$ = FR_INRANGE; }
1419 	| YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
1420 	| ':'				{ $$ = FR_INCRANGE; }
1421 	;
1422 
1423 servicename:
1424 	YY_STR				{ $$ = $1; }
1425 	;
1426 
1427 interfacename:	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 
1439 name:	YY_STR				{ $$ = $1; }
1440 	;
1441 
1442 ipv4:	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 
1454 static	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 
1583 static	struct	wordtab	addrwords[4] = {
1584 	{ "any",			IPFY_ANY },
1585 	{ "hash",			IPFY_HASH },
1586 	{ "pool",			IPFY_POOL },
1587 	{ NULL,				0 }
1588 };
1589 
1590 static	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 
1598 static	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 
1617 static	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 
1637 static	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 
1676 int ipf_parsefile(fd, addfunc, iocfuncs, filename)
1677 int fd;
1678 addfunc_t addfunc;
1679 ioctlfunc_t *iocfuncs;
1680 char *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 
1712 int ipf_parsesome(fd, addfunc, iocfuncs, fp)
1713 int fd;
1714 addfunc_t addfunc;
1715 ioctlfunc_t *iocfuncs;
1716 FILE *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 
1747 static 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 
1773 static 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 
1792 static 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 
1830 static u_32_t lookuphost(name)
1831 char *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 
1856 static void dobpf(phrase)
1857 char *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 
1918 static void resetaddr()
1919 {
1920 	hashed = 0;
1921 	pooled = 0;
1922 	dynamic = -1;
1923 }
1924 
1925 
1926 static alist_t *newalist(ptr)
1927 alist_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 
1940 static int makepool(list)
1941 alist_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 
1977 static u_int makehash(list)
1978 alist_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 
2019 void ipf_addrule(fd, ioctlfunc, ptr)
2020 int fd;
2021 ioctlfunc_t ioctlfunc;
2022 void *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 
2101 static void setsyslog()
2102 {
2103 	savewords = yysettab(logwords);
2104 	yybreakondot = 1;
2105 }
2106 
2107 
2108 static void unsetsyslog()
2109 {
2110 	yysettab(savewords);
2111 	yybreakondot = 0;
2112 }
2113 
2114 
2115 static void fillgroup(fr)
2116 frentry_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