Home | History | Annotate | Download | only in tools
      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