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