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