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