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