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