xref: /onnv-gate/usr/src/cmd/ipf/tools/ipnat_y.y (revision 7259:eb414b676b9b)
10Sstevel@tonic-gate %{
2570Syx160601 /*
37176Syx160601  * Copyright (C) 2001-2008 by Darren Reed.
4570Syx160601  *
5570Syx160601  * See the IPFILTER.LICENCE file for details on licencing.
6570Syx160601  *
77176Syx160601  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
8570Syx160601  * Use is subject to license terms.
9570Syx160601  */
102609Sjojemann 
112609Sjojemann #pragma ident	"%Z%%M%	%I%	%E% SMI"
12570Syx160601 
130Sstevel@tonic-gate #ifdef  __FreeBSD__
140Sstevel@tonic-gate # ifndef __FreeBSD_cc_version
150Sstevel@tonic-gate #  include <osreldate.h>
160Sstevel@tonic-gate # else
170Sstevel@tonic-gate #  if __FreeBSD_cc_version < 430000
180Sstevel@tonic-gate #   include <osreldate.h>
190Sstevel@tonic-gate #  endif
200Sstevel@tonic-gate # endif
210Sstevel@tonic-gate #endif
220Sstevel@tonic-gate #include <stdio.h>
230Sstevel@tonic-gate #include <unistd.h>
240Sstevel@tonic-gate #include <string.h>
250Sstevel@tonic-gate #include <fcntl.h>
260Sstevel@tonic-gate #include <errno.h>
270Sstevel@tonic-gate #if !defined(__SVR4) && !defined(__GNUC__)
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #endif
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <sys/file.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <stddef.h>
350Sstevel@tonic-gate #include <sys/socket.h>
360Sstevel@tonic-gate #include <sys/ioctl.h>
370Sstevel@tonic-gate #include <netinet/in.h>
380Sstevel@tonic-gate #include <netinet/in_systm.h>
390Sstevel@tonic-gate #include <sys/time.h>
400Sstevel@tonic-gate #include <syslog.h>
410Sstevel@tonic-gate #include <net/if.h>
420Sstevel@tonic-gate #if __FreeBSD_version >= 300000
430Sstevel@tonic-gate # include <net/if_var.h>
440Sstevel@tonic-gate #endif
450Sstevel@tonic-gate #include <netdb.h>
460Sstevel@tonic-gate #include <arpa/nameser.h>
470Sstevel@tonic-gate #include <resolv.h>
480Sstevel@tonic-gate #include "ipf.h"
490Sstevel@tonic-gate #include "netinet/ipl.h"
500Sstevel@tonic-gate #include "ipnat_l.h"
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #define	YYDEBUG	1
530Sstevel@tonic-gate 
540Sstevel@tonic-gate extern	void	yyerror __P((char *));
550Sstevel@tonic-gate extern	int	yyparse __P((void));
560Sstevel@tonic-gate extern	int	yylex __P((void));
570Sstevel@tonic-gate extern	int	yydebug;
580Sstevel@tonic-gate extern	FILE	*yyin;
590Sstevel@tonic-gate extern	int	yylineNum;
600Sstevel@tonic-gate 
610Sstevel@tonic-gate static	ipnat_t		*nattop = NULL;
620Sstevel@tonic-gate static	ipnat_t		*nat = NULL;
630Sstevel@tonic-gate static	int		natfd = -1;
640Sstevel@tonic-gate static	ioctlfunc_t	natioctlfunc = NULL;
650Sstevel@tonic-gate static	addfunc_t	nataddfunc = NULL;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate static	void	newnatrule __P((void));
680Sstevel@tonic-gate static	void	setnatproto __P((int));
690Sstevel@tonic-gate 
700Sstevel@tonic-gate %}
710Sstevel@tonic-gate %union	{
720Sstevel@tonic-gate 	char	*str;
730Sstevel@tonic-gate 	u_32_t	num;
747176Syx160601 	struct	{
757176Syx160601 		i6addr_t	a;
767176Syx160601 		int		v;
777176Syx160601 	} ipa;
780Sstevel@tonic-gate 	frentry_t	fr;
790Sstevel@tonic-gate 	frtuc_t	*frt;
802393Syz155240 	u_short	port;
810Sstevel@tonic-gate 	struct	{
820Sstevel@tonic-gate 		u_short	p1;
830Sstevel@tonic-gate 		u_short	p2;
840Sstevel@tonic-gate 		int	pc;
850Sstevel@tonic-gate 	} pc;
860Sstevel@tonic-gate 	struct	{
877176Syx160601 		i6addr_t	a;
887176Syx160601 		i6addr_t	m;
897176Syx160601 		int	v;
900Sstevel@tonic-gate 	} ipp;
910Sstevel@tonic-gate 	union	i6addr	ip6;
920Sstevel@tonic-gate };
930Sstevel@tonic-gate 
940Sstevel@tonic-gate %token  <num>   YY_NUMBER YY_HEX
950Sstevel@tonic-gate %token  <str>   YY_STR
960Sstevel@tonic-gate %token	  YY_COMMENT
970Sstevel@tonic-gate %token	  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
980Sstevel@tonic-gate %token	  YY_RANGE_OUT YY_RANGE_IN
990Sstevel@tonic-gate %token  <ip6>   YY_IPV6
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate %token	IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
1020Sstevel@tonic-gate %token	IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
1030Sstevel@tonic-gate %token	IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
1040Sstevel@tonic-gate %token	IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
105*7259Sdr146992 %token	IPNY_TLATE IPNY_SEQUENTIAL
1062393Syz155240 %type	<port> portspec
1072393Syz155240 %type	<num> hexnumber compare range proto
1087176Syx160601 %type	<num> saddr daddr sobject dobject mapfrom rdrfrom dip
1097176Syx160601 %type	<ipa> hostname ipv4 ipaddr
1107176Syx160601 %type	<ipp> addr rhaddr
1110Sstevel@tonic-gate %type	<pc> portstuff
1120Sstevel@tonic-gate %%
1130Sstevel@tonic-gate file:	line
1140Sstevel@tonic-gate 	| assign
1150Sstevel@tonic-gate 	| file line
1160Sstevel@tonic-gate 	| file assign
1170Sstevel@tonic-gate 	;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate line:	xx rule		{ while ((nat = nattop) != NULL) {
1207176Syx160601 				if (nat->in_v == 0)
1217176Syx160601 					nat->in_v = 4;
1220Sstevel@tonic-gate 				nattop = nat->in_next;
1230Sstevel@tonic-gate 				(*nataddfunc)(natfd, natioctlfunc, nat);
1240Sstevel@tonic-gate 				free(nat);
1250Sstevel@tonic-gate 			  }
1260Sstevel@tonic-gate 			  resetlexer();
1270Sstevel@tonic-gate 			}
1280Sstevel@tonic-gate 	| YY_COMMENT
1290Sstevel@tonic-gate 	;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
1320Sstevel@tonic-gate 					  resetlexer();
1330Sstevel@tonic-gate 					  free($1);
1340Sstevel@tonic-gate 					  free($3);
1350Sstevel@tonic-gate 					}
1360Sstevel@tonic-gate 	;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate assigning:
1390Sstevel@tonic-gate 	'='				{ yyvarnext = 1; }
1400Sstevel@tonic-gate 	;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate xx:					{ newnatrule(); }
1430Sstevel@tonic-gate 	;
1440Sstevel@tonic-gate 
1452393Syz155240 rule:	map eol
1462393Syz155240 	| mapblock eol
1472393Syz155240 	| redir eol
1482393Syz155240 	;
1492393Syz155240 
1502393Syz155240 eol:	| ';'
1510Sstevel@tonic-gate 	;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate map:	mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
1547176Syx160601 				{ if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
1557176Syx160601 					yyerror("1.address family mismatch");
1567176Syx160601 				  bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
1577176Syx160601 				  bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
1587176Syx160601 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
1597176Syx160601 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1600Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
1610Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
1620Sstevel@tonic-gate 						nat->in_ifnames[0],
1630Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
1640Sstevel@tonic-gate 				  if ((nat->in_flags & IPN_TCPUDP) == 0)
1650Sstevel@tonic-gate 					setnatproto(nat->in_p);
1660Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1670Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
1680Sstevel@tonic-gate 					nat_setgroupmap(nat);
1690Sstevel@tonic-gate 				}
1700Sstevel@tonic-gate 	| mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
1717176Syx160601 				{ if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
1727176Syx160601 					yyerror("2.address family mismatch");
1737176Syx160601 				  bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
1747176Syx160601 				  bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
1757176Syx160601 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
1767176Syx160601 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1770Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
1780Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
1790Sstevel@tonic-gate 						nat->in_ifnames[0],
1800Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
1812393Syz155240 				  if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
1822393Syz155240 					setnatproto(nat->in_p);
1832393Syz155240 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1842393Syz155240 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
1852393Syz155240 					nat_setgroupmap(nat);
1862393Syz155240 				}
1872393Syz155240 	| mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
1887176Syx160601 				{ if ($3 != 0 && $3 != $5.v && $5.v != 0)
1897176Syx160601 					yyerror("3.address family mismatch");
1907176Syx160601 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
1917176Syx160601 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1922393Syz155240 				  if (nat->in_ifnames[1][0] == '\0')
1932393Syz155240 					strncpy(nat->in_ifnames[1],
1942393Syz155240 						nat->in_ifnames[0],
1952393Syz155240 						sizeof(nat->in_ifnames[0]));
1960Sstevel@tonic-gate 				  if ((nat->in_flags & IPN_TCPUDP) == 0)
1970Sstevel@tonic-gate 					setnatproto(nat->in_p);
1980Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1990Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2000Sstevel@tonic-gate 					nat_setgroupmap(nat);
2010Sstevel@tonic-gate 				}
2022393Syz155240 	| mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
2037176Syx160601 				{ if ($3 != 0 && $3 != $5.v && $5.v != 0)
2047176Syx160601 					yyerror("4.address family mismatch");
2057176Syx160601 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
2067176Syx160601 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
2070Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2080Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2090Sstevel@tonic-gate 						nat->in_ifnames[0],
2100Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2112393Syz155240 				  if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
2120Sstevel@tonic-gate 					setnatproto(nat->in_p);
2130Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
2140Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2150Sstevel@tonic-gate 					nat_setgroupmap(nat);
2160Sstevel@tonic-gate 				}
2170Sstevel@tonic-gate 	;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate mapblock:
2200Sstevel@tonic-gate 	mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
2217176Syx160601 				{ if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
2227176Syx160601 					yyerror("5.address family mismatch");
2237176Syx160601 				  bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
2247176Syx160601 				  bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
2257176Syx160601 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
2267176Syx160601 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
2270Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2280Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2290Sstevel@tonic-gate 						nat->in_ifnames[0],
2300Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2310Sstevel@tonic-gate 				  if ((nat->in_flags & IPN_TCPUDP) == 0)
2320Sstevel@tonic-gate 					setnatproto(nat->in_p);
2330Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
2340Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2350Sstevel@tonic-gate 					nat_setgroupmap(nat);
2360Sstevel@tonic-gate 				}
2370Sstevel@tonic-gate 	;
2380Sstevel@tonic-gate 
2392393Syz155240 redir:	rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
2407176Syx160601 				{ if ($6 != 0 && $3.v != 0 && $6 != $3.v)
2417176Syx160601 					yyerror("6.address family mismatch");
2427176Syx160601 				  bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
2437176Syx160601 				  bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
2440Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2450Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2460Sstevel@tonic-gate 						nat->in_ifnames[0],
2470Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2480Sstevel@tonic-gate 				  if ((nat->in_p == 0) &&
2490Sstevel@tonic-gate 				      ((nat->in_flags & IPN_TCPUDP) == 0) &&
2500Sstevel@tonic-gate 				      (nat->in_pmin != 0 ||
2510Sstevel@tonic-gate 				       nat->in_pmax != 0 ||
2520Sstevel@tonic-gate 				       nat->in_pnext != 0))
2530Sstevel@tonic-gate 						setnatproto(IPPROTO_TCP);
2540Sstevel@tonic-gate 				}
2552393Syz155240 	| rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
2567176Syx160601 				{ if ($5 != 0 && $3 != 0 && $5 != $3)
2577176Syx160601 					yyerror("7.address family mismatch");
2582393Syz155240 				  if ((nat->in_p == 0) &&
2590Sstevel@tonic-gate 				      ((nat->in_flags & IPN_TCPUDP) == 0) &&
2600Sstevel@tonic-gate 				      (nat->in_pmin != 0 ||
2610Sstevel@tonic-gate 				       nat->in_pmax != 0 ||
2620Sstevel@tonic-gate 				       nat->in_pnext != 0))
2630Sstevel@tonic-gate 					setnatproto(IPPROTO_TCP);
2640Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2650Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2660Sstevel@tonic-gate 						nat->in_ifnames[0],
2670Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2680Sstevel@tonic-gate 				}
2692393Syz155240 	| rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
2707176Syx160601 				{ if ($5 != 0 && $3.v != 0 && $5 != $3.v)
2717176Syx160601 					yyerror("8.address family mismatch");
2727176Syx160601 				  bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
2737176Syx160601 				  bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
2740Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2750Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2760Sstevel@tonic-gate 						nat->in_ifnames[0],
2770Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2780Sstevel@tonic-gate 				}
2790Sstevel@tonic-gate 	;
2800Sstevel@tonic-gate 
2812393Syz155240 proxy:	| IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto
2820Sstevel@tonic-gate 			{ strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
2830Sstevel@tonic-gate 			  if (nat->in_dcmp == 0) {
2840Sstevel@tonic-gate 				nat->in_dport = htons($3);
2850Sstevel@tonic-gate 			  } else if ($3 != nat->in_dport) {
2860Sstevel@tonic-gate 				yyerror("proxy port numbers not consistant");
2870Sstevel@tonic-gate 			  }
2880Sstevel@tonic-gate 			  setnatproto($6);
2890Sstevel@tonic-gate 			  free($4);
2900Sstevel@tonic-gate 			}
2910Sstevel@tonic-gate 	| IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto
2922393Syz155240 			{ int pnum;
2932393Syz155240 			  strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
2942393Syz155240 			  pnum = getportproto($3, $6);
2952393Syz155240 			  if (pnum == -1)
2962393Syz155240 				yyerror("invalid port number");
2972393Syz155240 			  nat->in_dport = pnum;
2980Sstevel@tonic-gate 			  setnatproto($6);
2990Sstevel@tonic-gate 			  free($3);
3000Sstevel@tonic-gate 			  free($4);
3010Sstevel@tonic-gate 			}
3020Sstevel@tonic-gate 	;
3030Sstevel@tonic-gate 
3042393Syz155240 setproto:
3052393Syz155240 	| proto				{ if (nat->in_p != 0 ||
3062393Syz155240 					      nat->in_flags & IPN_TCPUDP)
3072393Syz155240 						yyerror("protocol set twice");
3082393Syz155240 					  setnatproto($1);
3092393Syz155240 					}
3102393Syz155240 	| IPNY_TCPUDP			{ if (nat->in_p != 0 ||
3112393Syz155240 					      nat->in_flags & IPN_TCPUDP)
3122393Syz155240 						yyerror("protocol set twice");
3132393Syz155240 					  nat->in_flags |= IPN_TCPUDP;
3142393Syz155240 					  nat->in_p = 0;
3152393Syz155240 					}
3162393Syz155240 	| IPNY_TCP '/' IPNY_UDP		{ if (nat->in_p != 0 ||
3172393Syz155240 					      nat->in_flags & IPN_TCPUDP)
3182393Syz155240 						yyerror("protocol set twice");
3192393Syz155240 					  nat->in_flags |= IPN_TCPUDP;
3202393Syz155240 					  nat->in_p = 0;
3210Sstevel@tonic-gate 					}
3220Sstevel@tonic-gate 	;
3230Sstevel@tonic-gate 
3247176Syx160601 rhaddr:	addr				{ $$.a = $1.a;
3257176Syx160601 					  $$.m = $1.m;
3267176Syx160601 					  $$.v = $1.v;
3277176Syx160601 					  if ($$.v == 0)
3287176Syx160601 						$$.v = nat->in_v;
3297176Syx160601 					  yyexpectaddr = 0; }
3307176Syx160601 	| IPNY_RANGE hostname '-' hostname
3317176Syx160601 					{ if ($2.v != 0 && $4.v != 0 && $4.v != $2.v)
3327176Syx160601 						yyerror("9.address family "
3337176Syx160601 							"mismatch");
3347176Syx160601 					  $$.v = $2.v;
3357176Syx160601 					  $$.a = $2.a;
3367176Syx160601 					  $$.m = $4.a;
3377176Syx160601 					  nat->in_flags |= IPN_IPRANGE;
3387176Syx160601 					  yyexpectaddr = 0; }
3392393Syz155240 	;
3402393Syz155240 
3410Sstevel@tonic-gate dip:
3427176Syx160601 	hostname			{ bcopy(&$1.a, &nat->in_in[0],
3437176Syx160601 						sizeof($1.a));
3447176Syx160601 					  if ($1.v == 0)
3457176Syx160601 						$1.v = nat->in_v;
3467176Syx160601 					  if ($1.v == 4) {
3477176Syx160601 						nat->in_inmsk = 0xffffffff;
3487176Syx160601 					  } else {
3497176Syx160601 						nat->in_in[1].i6[0] = 0xffffffff;
3507176Syx160601 						nat->in_in[1].i6[1] = 0xffffffff;
3517176Syx160601 						nat->in_in[1].i6[2] = 0xffffffff;
3527176Syx160601 						nat->in_in[1].i6[3] = 0xffffffff;
3537176Syx160601 					  }
3547176Syx160601 					  $$ = $1.v;
3557176Syx160601 					}
3567176Syx160601 	| hostname '/' YY_NUMBER        { if ($1.v == 0)
3577176Syx160601 						$1.v = nat->in_v;
3587176Syx160601 					  if ($1.v == 4 &&
3597176Syx160601 					      ($1.a.in4.s_addr != 0 ||
3607176Syx160601 					      ($3 != 0 && $3 != 32)))
3617176Syx160601 						yyerror("Invalid mask for dip");
3627176Syx160601 					  else if ($1.v == 6 &&
3637176Syx160601 					      ($1.a.in4.s_addr != 0 ||
3647176Syx160601 					      ($3 != 0 && $3 != 128)))
3652873Sjojemann 						yyerror("Invalid mask for dip");
3667176Syx160601 					  else if ($1.v == 0 ) {
3677176Syx160601 						if ($1.a.in4.s_addr == 0 &&
3687176Syx160601 						    ($3 == 32 || $3 == 0))
3697176Syx160601 							$1.v = 4;
3707176Syx160601 						else if ($3 == 128)
3717176Syx160601 							$1.v = 6;
3727176Syx160601 					  }
3737176Syx160601 					  bcopy(&$1.a, &nat->in_in[0],
3747176Syx160601 						sizeof($1.a));
3757176Syx160601 					  ntomask($1.v, $3,
3767176Syx160601 						(u_32_t *)&nat->in_in[1]);
3777176Syx160601 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[0];
3787176Syx160601 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[1];
3797176Syx160601 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[2];
3807176Syx160601 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[3];
3817176Syx160601 					  nat->in_v = $1.v;
3827176Syx160601 					  $$ = $1.v;
3837176Syx160601 					}
3847176Syx160601 	| hostname ',' { yyexpectaddr = 1; } hostname
3857176Syx160601 					{ if ($1.v != $4.v)
3867176Syx160601 						yyerror("10.address family "
3877176Syx160601 							"mismatch");
3887176Syx160601 					  $$ = $1.v;
3897176Syx160601 					  nat->in_flags |= IPN_SPLIT;
3907176Syx160601 					  bcopy(&$1.a, &nat->in_in[0],
3917176Syx160601 						sizeof($1.a));
3927176Syx160601 					  bcopy(&$4.a, &nat->in_in[1],
3937176Syx160601 						sizeof($4.a));
3947176Syx160601 					  yyexpectaddr = 0; }
3950Sstevel@tonic-gate 	;
3960Sstevel@tonic-gate 
3972393Syz155240 portspec:
3982393Syz155240 	YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
3992393Syz155240 						yyerror("invalid port number");
4002393Syz155240 					  else
4012393Syz155240 						$$ = $1;
4022393Syz155240 					}
4032393Syz155240 	| YY_STR			{ if (getport(NULL, $1, &($$)) == -1)
4042393Syz155240 						yyerror("invalid port number");
4052393Syz155240 					  $$ = ntohs($$);
4062393Syz155240 					}
4072393Syz155240 	;
4082393Syz155240 
4092393Syz155240 dport:	| IPNY_PORT portspec			{ nat->in_pmin = htons($2);
4100Sstevel@tonic-gate 						  nat->in_pmax = htons($2); }
4112393Syz155240 	| IPNY_PORT portspec '-' portspec	{ nat->in_pmin = htons($2);
4122393Syz155240 						  nat->in_pmax = htons($4); }
4132393Syz155240 	| IPNY_PORT portspec ':' portspec	{ nat->in_pmin = htons($2);
4140Sstevel@tonic-gate 						  nat->in_pmax = htons($4); }
4150Sstevel@tonic-gate 	;
4160Sstevel@tonic-gate 
4172393Syz155240 nport:	IPNY_PORT portspec		{ nat->in_pnext = htons($2); }
4182393Syz155240 	| IPNY_PORT '=' portspec	{ nat->in_pnext = htons($3);
4192393Syz155240 					  nat->in_flags |= IPN_FIXEDDPORT;
4202393Syz155240 					}
4210Sstevel@tonic-gate 	;
4220Sstevel@tonic-gate 
4232393Syz155240 ports:	| IPNY_PORTS YY_NUMBER		{ nat->in_pmin = $2; }
4240Sstevel@tonic-gate 	| IPNY_PORTS IPNY_AUTO		{ nat->in_flags |= IPN_AUTOPORTMAP; }
4250Sstevel@tonic-gate 	;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate mapit:	IPNY_MAP			{ nat->in_redir = NAT_MAP; }
4280Sstevel@tonic-gate 	| IPNY_BIMAP			{ nat->in_redir = NAT_BIMAP; }
4290Sstevel@tonic-gate 	;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate rdrit:	IPNY_RDR			{ nat->in_redir = NAT_REDIRECT; }
4320Sstevel@tonic-gate 	;
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate mapblockit:
4350Sstevel@tonic-gate 	IPNY_MAPBLOCK			{ nat->in_redir = NAT_MAPBLK; }
4360Sstevel@tonic-gate 	;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate mapfrom:
4397176Syx160601 	from sobject IPNY_TO dobject	{ if ($2 != 0 && $4 != 0 && $2 != $4)
4407176Syx160601 						yyerror("11.address family "
4417176Syx160601 							"mismatch");
4427176Syx160601 					  $$ = $2;
4437176Syx160601 					}
4440Sstevel@tonic-gate 	| from sobject '!' IPNY_TO dobject
4457176Syx160601 					{ if ($2 != 0 && $5 != 0 && $2 != $5)
4467176Syx160601 						yyerror("12.address family "
4477176Syx160601 							"mismatch");
4487176Syx160601 					  nat->in_flags |= IPN_NOTDST;
4497176Syx160601 					  $$ = $2;
4507176Syx160601 					}
4510Sstevel@tonic-gate 	;
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate rdrfrom:
4547176Syx160601 	from sobject IPNY_TO dobject	{ if ($2 != 0 && $4 != 0 && $2 != $4)
4557176Syx160601 						yyerror("13.address family "
4567176Syx160601 							"mismatch");
4577176Syx160601 					  $$ = $2;
4587176Syx160601 					}
4590Sstevel@tonic-gate 	| '!' from sobject IPNY_TO dobject
4607176Syx160601 					{ if ($3 != 0 && $5 != 0 && $3 != $5)
4617176Syx160601 						yyerror("14.address family "
4627176Syx160601 							"mismatch");
4637176Syx160601 					  nat->in_flags |= IPN_NOTSRC;
4647176Syx160601 					  $$ = $3;
4657176Syx160601 					}
4660Sstevel@tonic-gate 	;
4670Sstevel@tonic-gate 
4687176Syx160601 from:	IPNY_FROM			{ nat->in_flags |= IPN_FILTER;
4697176Syx160601 					  yyexpectaddr = 1; }
4700Sstevel@tonic-gate 	;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate ifnames:
4737176Syx160601 	ifname				{ yyexpectaddr = 1; }
4747176Syx160601 	| ifname ',' otherifname	{ yyexpectaddr = 1; }
4750Sstevel@tonic-gate 	;
4760Sstevel@tonic-gate 
4772393Syz155240 ifname:	YY_STR			{ strncpy(nat->in_ifnames[0], $1,
4782393Syz155240 					  sizeof(nat->in_ifnames[0]));
4792393Syz155240 				  nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
4802393Syz155240 				  free($1);
4812393Syz155240 				}
4820Sstevel@tonic-gate 	;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate otherifname:
4852393Syz155240 	YY_STR			{ strncpy(nat->in_ifnames[1], $1,
4862393Syz155240 					  sizeof(nat->in_ifnames[1]));
4872393Syz155240 				  nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0';
4882393Syz155240 				  free($1);
4892393Syz155240 				}
4900Sstevel@tonic-gate 	;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate mapport:
493*7259Sdr146992 	IPNY_PORTMAP tcpudp portspec ':' portspec randport
4942393Syz155240 			{ nat->in_pmin = htons($3);
4952393Syz155240 			  nat->in_pmax = htons($5);
4962393Syz155240 			}
497*7259Sdr146992 	| IPNY_PORTMAP tcpudp IPNY_AUTO randport
4982393Syz155240 			{ nat->in_flags |= IPN_AUTOPORTMAP;
4992393Syz155240 			  nat->in_pmin = htons(1024);
5002393Syz155240 			  nat->in_pmax = htons(65535);
5012393Syz155240 			}
5022393Syz155240 	| IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER
5032393Syz155240 			{ if (strcmp($2, "icmp") != 0) {
5042393Syz155240 				yyerror("icmpidmap not followed by icmp");
5052393Syz155240 			  }
5062393Syz155240 			  free($2);
5072393Syz155240 			  if ($3 < 0 || $3 > 65535)
5082393Syz155240 				yyerror("invalid ICMP Id number");
5092393Syz155240 			  if ($5 < 0 || $5 > 65535)
5102393Syz155240 				yyerror("invalid ICMP Id number");
5112393Syz155240 			  nat->in_flags = IPN_ICMPQUERY;
5122393Syz155240 			  nat->in_pmin = htons($3);
5132393Syz155240 			  nat->in_pmax = htons($5);
5142393Syz155240 			}
5150Sstevel@tonic-gate 	;
5160Sstevel@tonic-gate 
517*7259Sdr146992 randport:
518*7259Sdr146992 	| IPNY_SEQUENTIAL	{ nat->in_flags |= IPN_SEQUENTIAL; }
519*7259Sdr146992 	;
520*7259Sdr146992 
5210Sstevel@tonic-gate sobject:
5227176Syx160601 	saddr				{ $$ = $1; }
5230Sstevel@tonic-gate 	| saddr IPNY_PORT portstuff	{ nat->in_sport = $3.p1;
5240Sstevel@tonic-gate 					  nat->in_stop = $3.p2;
5257176Syx160601 					  nat->in_scmp = $3.pc;
5267176Syx160601 					  $$ = $1;
5277176Syx160601 					}
5280Sstevel@tonic-gate 	;
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate saddr:	addr				{ if (nat->in_redir == NAT_REDIRECT) {
5317176Syx160601 						bcopy(&$1.a, &nat->in_src[0],
5327176Syx160601 							sizeof($1.a));
5337176Syx160601 						bcopy(&$1.m, &nat->in_src[1],
5347176Syx160601 							sizeof($1.a));
5350Sstevel@tonic-gate 					  } else {
5367176Syx160601 						bcopy(&$1.a, &nat->in_in[0],
5377176Syx160601 							sizeof($1.a));
5387176Syx160601 						bcopy(&$1.m, &nat->in_in[1],
5397176Syx160601 							sizeof($1.a));
5400Sstevel@tonic-gate 					  }
5417176Syx160601 					  $$ = $1.v;
5420Sstevel@tonic-gate 					}
5430Sstevel@tonic-gate 	;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate dobject:
5467176Syx160601 	daddr				{ $$ = $1; }
5470Sstevel@tonic-gate 	| daddr IPNY_PORT portstuff	{ nat->in_dport = $3.p1;
5480Sstevel@tonic-gate 					  nat->in_dtop = $3.p2;
5490Sstevel@tonic-gate 					  nat->in_dcmp = $3.pc;
5500Sstevel@tonic-gate 					  if (nat->in_redir == NAT_REDIRECT)
5510Sstevel@tonic-gate 						nat->in_pmin = htons($3.p1);
5520Sstevel@tonic-gate 					}
5530Sstevel@tonic-gate 	;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate daddr:	addr				{ if (nat->in_redir == NAT_REDIRECT) {
5567176Syx160601 						bcopy(&$1.a, &nat->in_out[0],
5577176Syx160601 							sizeof($1.a));
5587176Syx160601 						bcopy(&$1.m, &nat->in_out[1],
5597176Syx160601 							sizeof($1.a));
5600Sstevel@tonic-gate 					  } else {
5617176Syx160601 						bcopy(&$1.a, &nat->in_src[0],
5627176Syx160601 							sizeof($1.a));
5637176Syx160601 						bcopy(&$1.m, &nat->in_src[1],
5647176Syx160601 							sizeof($1.a));
5650Sstevel@tonic-gate 					  }
5667176Syx160601 					  $$ = $1.v;
5670Sstevel@tonic-gate 					}
5680Sstevel@tonic-gate 	;
5690Sstevel@tonic-gate 
5707176Syx160601 addr:	IPNY_ANY			{ yyexpectaddr = 0;
5717176Syx160601 					  bzero(&$$.a, sizeof($$.a));
5727176Syx160601 					  bzero(&$$.m, sizeof($$.a));
5737176Syx160601 					  $$.v = nat->in_v;
5747176Syx160601 					}
5757176Syx160601 	| hostname			{ $$.a = $1.a;
5767176Syx160601 					  $$.v = $1.v;
5777176Syx160601 					  if ($$.v == 4) {
5787176Syx160601 						$$.m.in4.s_addr = 0xffffffff;
5797176Syx160601 					  } else {
5807176Syx160601 						$$.m.i6[0] = 0xffffffff;
5817176Syx160601 						$$.m.i6[1] = 0xffffffff;
5827176Syx160601 						$$.m.i6[2] = 0xffffffff;
5837176Syx160601 						$$.m.i6[3] = 0xffffffff;
5847176Syx160601 					  }
5857176Syx160601 					  yyexpectaddr = 0;
5867176Syx160601 					}
5877176Syx160601 	| hostname '/' YY_NUMBER	{ $$.a = $1.a;
5887176Syx160601 					  if ($1.v == 0) {
5897176Syx160601 						if ($1.a.in4.s_addr != 0)
5907176Syx160601 							yyerror("invalid addr");
5917176Syx160601 						if ($3 == 0 || $3 == 32)
5927176Syx160601 							$1.v = 4;
5937176Syx160601 						else if ($3 == 128)
5947176Syx160601 							$1.v = 6;
5957176Syx160601 						else
5967176Syx160601 							yyerror("invalid mask");
5977176Syx160601 						nat->in_v = $1.v;
5987176Syx160601 					  }
5997176Syx160601 					  ntomask($1.v, $3, (u_32_t *)&$$.m);
6007176Syx160601 					  $$.a.i6[0] &= $$.m.i6[0];
6017176Syx160601 					  $$.a.i6[1] &= $$.m.i6[1];
6027176Syx160601 					  $$.a.i6[2] &= $$.m.i6[2];
6037176Syx160601 					  $$.a.i6[3] &= $$.m.i6[3];
6047176Syx160601 					  $$.v = $1.v;
6057176Syx160601 					  yyexpectaddr = 0;
6067176Syx160601 					}
6077176Syx160601 	| hostname '/' ipaddr		{ if ($1.v != $3.v) {
6087176Syx160601 						yyerror("1.address family "
6097176Syx160601 							"mismatch");
6107176Syx160601 					  }
6117176Syx160601 					  $$.a = $1.a;
6127176Syx160601 					  $$.m = $3.a;
6137176Syx160601 					  $$.a.i6[0] &= $$.m.i6[0];
6147176Syx160601 					  $$.a.i6[1] &= $$.m.i6[1];
6157176Syx160601 					  $$.a.i6[2] &= $$.m.i6[2];
6167176Syx160601 					  $$.a.i6[3] &= $$.m.i6[3];
6177176Syx160601 					  $$.v = $1.v;
6187176Syx160601 					  yyexpectaddr = 0;
6197176Syx160601 					}
6207176Syx160601 	| hostname '/' hexnumber	{ $$.a = $1.a;
6217176Syx160601 					  $$.m.in4.s_addr = htonl($3);
6227176Syx160601 					  $$.a.in4.s_addr &= $$.m.in4.s_addr;
6237176Syx160601 					  $$.v = 4;
6247176Syx160601 					}
6257176Syx160601 	| hostname IPNY_MASK ipaddr	{ if ($1.v != $3.v) {
6267176Syx160601 						yyerror("2.address family "
6277176Syx160601 							"mismatch");
6287176Syx160601 					  }
6297176Syx160601 					  $$.a = $1.a;
6307176Syx160601 					  $$.m = $3.a;
6317176Syx160601 					  $$.a.i6[0] &= $$.m.i6[0];
6327176Syx160601 					  $$.a.i6[1] &= $$.m.i6[1];
6337176Syx160601 					  $$.a.i6[2] &= $$.m.i6[2];
6347176Syx160601 					  $$.a.i6[3] &= $$.m.i6[3];
6357176Syx160601 					  $$.v = $1.v;
6367176Syx160601 					  yyexpectaddr = 0;
6377176Syx160601 					}
6387176Syx160601 	| hostname IPNY_MASK hexnumber	{ $$.a = $1.a;
6397176Syx160601 					  $$.m.in4.s_addr = htonl($3);
6407176Syx160601 					  $$.a.in4.s_addr &= $$.m.in4.s_addr;
6417176Syx160601 					  $$.v = 4;
6427176Syx160601 					}
6430Sstevel@tonic-gate 	;
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate portstuff:
6462393Syz155240 	compare portspec		{ $$.pc = $1; $$.p1 = $2; }
6472873Sjojemann 	| portspec range portspec	{ $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
6480Sstevel@tonic-gate 	;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate mapoptions:
6512393Syz155240 	rr frag age mssclamp nattag setproto
6520Sstevel@tonic-gate 	;
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate rdroptions:
6550Sstevel@tonic-gate 	rr frag age sticky mssclamp rdrproxy nattag
6560Sstevel@tonic-gate 	;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate nattag:	| IPNY_TAG YY_STR		{ strncpy(nat->in_tag.ipt_tag, $2,
6590Sstevel@tonic-gate 						  sizeof(nat->in_tag.ipt_tag));
6600Sstevel@tonic-gate 					}
661*7259Sdr146992 
6620Sstevel@tonic-gate rr:	| IPNY_ROUNDROBIN		{ nat->in_flags |= IPN_ROUNDR; }
6630Sstevel@tonic-gate 	;
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate frag:	| IPNY_FRAG			{ nat->in_flags |= IPN_FRAG; }
6660Sstevel@tonic-gate 	;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate age:	| IPNY_AGE YY_NUMBER			{ nat->in_age[0] = $2;
6690Sstevel@tonic-gate 						  nat->in_age[1] = $2; }
6700Sstevel@tonic-gate 	| IPNY_AGE YY_NUMBER '/' YY_NUMBER	{ nat->in_age[0] = $2;
6710Sstevel@tonic-gate 						  nat->in_age[1] = $4; }
6720Sstevel@tonic-gate 	;
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate sticky:	| IPNY_STICKY			{ if (!(nat->in_flags & IPN_ROUNDR) &&
6750Sstevel@tonic-gate 					      !(nat->in_flags & IPN_SPLIT)) {
6760Sstevel@tonic-gate 						fprintf(stderr,
6770Sstevel@tonic-gate 		"'sticky' for use with round-robin/IP splitting only\n");
6780Sstevel@tonic-gate 					  } else
6790Sstevel@tonic-gate 						nat->in_flags |= IPN_STICKY;
6800Sstevel@tonic-gate 					}
6810Sstevel@tonic-gate 	;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate mssclamp:
6840Sstevel@tonic-gate 	| IPNY_MSSCLAMP YY_NUMBER		{ nat->in_mssclamp = $2; }
6850Sstevel@tonic-gate 	;
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate tcpudp:	| IPNY_TCP			{ setnatproto(IPPROTO_TCP); }
6880Sstevel@tonic-gate 	| IPNY_UDP			{ setnatproto(IPPROTO_UDP); }
6890Sstevel@tonic-gate 	| IPNY_TCPUDP			{ nat->in_flags |= IPN_TCPUDP;
6900Sstevel@tonic-gate 					  nat->in_p = 0;
6910Sstevel@tonic-gate 					}
6920Sstevel@tonic-gate 	| IPNY_TCP '/' IPNY_UDP		{ nat->in_flags |= IPN_TCPUDP;
6930Sstevel@tonic-gate 					  nat->in_p = 0;
6940Sstevel@tonic-gate 					}
6950Sstevel@tonic-gate 	;
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate rdrproxy:
6982393Syz155240 	IPNY_PROXY YY_STR
6990Sstevel@tonic-gate 					{ strncpy(nat->in_plabel, $2,
7000Sstevel@tonic-gate 						  sizeof(nat->in_plabel));
7010Sstevel@tonic-gate 					  nat->in_dport = nat->in_pnext;
7022393Syz155240 					  nat->in_dport = htons(nat->in_dport);
7030Sstevel@tonic-gate 					  free($2);
7040Sstevel@tonic-gate 					}
7050Sstevel@tonic-gate 	| proxy				{ if (nat->in_plabel[0] != '\0') {
7060Sstevel@tonic-gate 						  nat->in_pmin = nat->in_dport;
7070Sstevel@tonic-gate 						  nat->in_pmax = nat->in_pmin;
7080Sstevel@tonic-gate 						  nat->in_pnext = nat->in_pmin;
7090Sstevel@tonic-gate 					  }
7100Sstevel@tonic-gate 					}
7110Sstevel@tonic-gate 	;
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate proto:	YY_NUMBER			{ $$ = $1; }
7140Sstevel@tonic-gate 	| IPNY_TCP			{ $$ = IPPROTO_TCP; }
7150Sstevel@tonic-gate 	| IPNY_UDP			{ $$ = IPPROTO_UDP; }
7160Sstevel@tonic-gate 	| YY_STR			{ $$ = getproto($1); free($1); }
7170Sstevel@tonic-gate 	;
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate hexnumber:
7200Sstevel@tonic-gate 	YY_HEX				{ $$ = $1; }
7210Sstevel@tonic-gate 	;
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate hostname:
7247176Syx160601 	YY_STR				{ i6addr_t addr;
7257176Syx160601 					  if (gethost($1, &addr, 0) == 0) {
7267176Syx160601 						$$.a = addr;
7277176Syx160601 						$$.v = 4;
7287176Syx160601 					  } else
7297176Syx160601 					  if (gethost($1, &addr, 1) == 0) {
7307176Syx160601 						$$.a = addr;
7317176Syx160601 						$$.v = 6;
7327176Syx160601 					  } else {
7332609Sjojemann 						yyerror("Unknown hostname");
7347176Syx160601 					  }
7357176Syx160601 					  if ($$.v != 0)
7367176Syx160601 						nat->in_v = $$.v;
7377176Syx160601 					  free($1);
7380Sstevel@tonic-gate 					}
7397176Syx160601 	| YY_NUMBER			{ bzero(&$$.a, sizeof($$.a));
7407176Syx160601 					  $$.a.in4.s_addr = htonl($1);
7417176Syx160601 					  if ($$.a.in4.s_addr != 0)
7427176Syx160601 						$$.v = 4;
7437176Syx160601 					  else
7447176Syx160601 						$$.v = nat->in_v;
7457176Syx160601 					  if ($$.v != 0)
7467176Syx160601 						nat->in_v = $$.v;
7477176Syx160601 					}
7487176Syx160601 	| ipv4				{ $$ = $1;
7497176Syx160601 					  nat->in_v = 4;
7507176Syx160601 					}
7517176Syx160601 	| YY_IPV6			{ $$.a = $1;
7527176Syx160601 					  $$.v = 6;
7537176Syx160601 					  nat->in_v = 6;
7547176Syx160601 					}
7557176Syx160601 	| YY_NUMBER YY_IPV6		{ $$.a = $2;
7567176Syx160601 					  $$.v = 6;
7577176Syx160601 					}
7580Sstevel@tonic-gate 	;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate compare:
7610Sstevel@tonic-gate 	'='				{ $$ = FR_EQUAL; }
7620Sstevel@tonic-gate 	| YY_CMP_EQ			{ $$ = FR_EQUAL; }
7630Sstevel@tonic-gate 	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
7640Sstevel@tonic-gate 	| YY_CMP_LT			{ $$ = FR_LESST; }
7650Sstevel@tonic-gate 	| YY_CMP_LE			{ $$ = FR_LESSTE; }
7660Sstevel@tonic-gate 	| YY_CMP_GT			{ $$ = FR_GREATERT; }
7670Sstevel@tonic-gate 	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate range:
7700Sstevel@tonic-gate 	YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
7710Sstevel@tonic-gate 	| YY_RANGE_IN			{ $$ = FR_INRANGE; }
7720Sstevel@tonic-gate 	;
7730Sstevel@tonic-gate 
7747176Syx160601 ipaddr:	ipv4				{ $$ = $1; }
7757176Syx160601 	| YY_IPV6			{ $$.a = $1;
7767176Syx160601 					  $$.v = 6;
7777176Syx160601 					}
7787176Syx160601 	;
7797176Syx160601 
7800Sstevel@tonic-gate ipv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
7810Sstevel@tonic-gate 		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
7820Sstevel@tonic-gate 			yyerror("Invalid octet string for IP address");
7830Sstevel@tonic-gate 			return 0;
7840Sstevel@tonic-gate 		  }
7857176Syx160601 		  $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
7867176Syx160601 		  $$.a.in4.s_addr = htonl($$.a.in4.s_addr);
7877176Syx160601 		  $$.v = 4;
7880Sstevel@tonic-gate 		}
7890Sstevel@tonic-gate 	;
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate %%
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate static	wordtab_t	yywords[] = {
7950Sstevel@tonic-gate 	{ "age",	IPNY_AGE },
7960Sstevel@tonic-gate 	{ "any",	IPNY_ANY },
7970Sstevel@tonic-gate 	{ "auto",	IPNY_AUTO },
7980Sstevel@tonic-gate 	{ "bimap",	IPNY_BIMAP },
7990Sstevel@tonic-gate 	{ "frag",	IPNY_FRAG },
8000Sstevel@tonic-gate 	{ "from",	IPNY_FROM },
8010Sstevel@tonic-gate 	{ "icmpidmap",	IPNY_ICMPIDMAP },
8020Sstevel@tonic-gate 	{ "mask",	IPNY_MASK },
8030Sstevel@tonic-gate 	{ "map",	IPNY_MAP },
8040Sstevel@tonic-gate 	{ "map-block",	IPNY_MAPBLOCK },
8050Sstevel@tonic-gate 	{ "mssclamp",	IPNY_MSSCLAMP },
8062393Syz155240 	{ "netmask",	IPNY_MASK },
8070Sstevel@tonic-gate 	{ "port",	IPNY_PORT },
8080Sstevel@tonic-gate 	{ "portmap",	IPNY_PORTMAP },
8090Sstevel@tonic-gate 	{ "ports",	IPNY_PORTS },
8100Sstevel@tonic-gate 	{ "proxy",	IPNY_PROXY },
8110Sstevel@tonic-gate 	{ "range",	IPNY_RANGE },
8120Sstevel@tonic-gate 	{ "rdr",	IPNY_RDR },
8130Sstevel@tonic-gate 	{ "round-robin",IPNY_ROUNDROBIN },
814*7259Sdr146992 	{ "sequential",	IPNY_SEQUENTIAL },
8150Sstevel@tonic-gate 	{ "sticky",	IPNY_STICKY },
8160Sstevel@tonic-gate 	{ "tag",	IPNY_TAG },
8170Sstevel@tonic-gate 	{ "tcp",	IPNY_TCP },
8182393Syz155240 	{ "tcpudp",	IPNY_TCPUDP },
8190Sstevel@tonic-gate 	{ "to",		IPNY_TO },
8200Sstevel@tonic-gate 	{ "udp",	IPNY_UDP },
8210Sstevel@tonic-gate 	{ "-",		'-' },
8220Sstevel@tonic-gate 	{ "->",		IPNY_TLATE },
8230Sstevel@tonic-gate 	{ "eq",		YY_CMP_EQ },
8240Sstevel@tonic-gate 	{ "ne",		YY_CMP_NE },
8250Sstevel@tonic-gate 	{ "lt",		YY_CMP_LT },
8260Sstevel@tonic-gate 	{ "gt",		YY_CMP_GT },
8270Sstevel@tonic-gate 	{ "le",		YY_CMP_LE },
8280Sstevel@tonic-gate 	{ "ge",		YY_CMP_GE },
8290Sstevel@tonic-gate 	{ NULL,		0 }
8300Sstevel@tonic-gate };
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate 
ipnat_parsefile(fd,addfunc,ioctlfunc,filename)8330Sstevel@tonic-gate int ipnat_parsefile(fd, addfunc, ioctlfunc, filename)
8340Sstevel@tonic-gate int fd;
8350Sstevel@tonic-gate addfunc_t addfunc;
8360Sstevel@tonic-gate ioctlfunc_t ioctlfunc;
8370Sstevel@tonic-gate char *filename;
8380Sstevel@tonic-gate {
8390Sstevel@tonic-gate 	FILE *fp = NULL;
8400Sstevel@tonic-gate 	char *s;
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	(void) yysettab(yywords);
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	s = getenv("YYDEBUG");
8450Sstevel@tonic-gate 	if (s)
8460Sstevel@tonic-gate 		yydebug = atoi(s);
8470Sstevel@tonic-gate 	else
8480Sstevel@tonic-gate 		yydebug = 0;
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	if (strcmp(filename, "-")) {
8510Sstevel@tonic-gate 		fp = fopen(filename, "r");
8520Sstevel@tonic-gate 		if (!fp) {
8530Sstevel@tonic-gate 			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
8540Sstevel@tonic-gate 				STRERROR(errno));
8550Sstevel@tonic-gate 			return -1;
8560Sstevel@tonic-gate 		}
8570Sstevel@tonic-gate 	} else
8580Sstevel@tonic-gate 		fp = stdin;
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1)
8610Sstevel@tonic-gate 		;
8620Sstevel@tonic-gate 	if (fp != NULL)
8630Sstevel@tonic-gate 		fclose(fp);
8640Sstevel@tonic-gate 	return 0;
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate 
ipnat_parsesome(fd,addfunc,ioctlfunc,fp)8680Sstevel@tonic-gate int ipnat_parsesome(fd, addfunc, ioctlfunc, fp)
8690Sstevel@tonic-gate int fd;
8700Sstevel@tonic-gate addfunc_t addfunc;
8710Sstevel@tonic-gate ioctlfunc_t ioctlfunc;
8720Sstevel@tonic-gate FILE *fp;
8730Sstevel@tonic-gate {
8740Sstevel@tonic-gate 	char *s;
8750Sstevel@tonic-gate 	int i;
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	yylineNum = 1;
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	natfd = fd;
8800Sstevel@tonic-gate 	nataddfunc = addfunc;
8810Sstevel@tonic-gate 	natioctlfunc = ioctlfunc;
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate 	if (feof(fp))
8840Sstevel@tonic-gate 		return 0;
8850Sstevel@tonic-gate 	i = fgetc(fp);
8860Sstevel@tonic-gate 	if (i == EOF)
8870Sstevel@tonic-gate 		return 0;
8880Sstevel@tonic-gate 	if (ungetc(i, fp) == EOF)
8890Sstevel@tonic-gate 		return 0;
8900Sstevel@tonic-gate 	if (feof(fp))
8910Sstevel@tonic-gate 		return 0;
8920Sstevel@tonic-gate 	s = getenv("YYDEBUG");
8930Sstevel@tonic-gate 	if (s)
8940Sstevel@tonic-gate 		yydebug = atoi(s);
8950Sstevel@tonic-gate 	else
8960Sstevel@tonic-gate 		yydebug = 0;
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 	yyin = fp;
8990Sstevel@tonic-gate 	yyparse();
9000Sstevel@tonic-gate 	return 1;
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 
newnatrule()9040Sstevel@tonic-gate static void newnatrule()
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate 	ipnat_t *n;
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	n = calloc(1, sizeof(*n));
9090Sstevel@tonic-gate 	if (n == NULL)
9100Sstevel@tonic-gate 		return;
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	if (nat == NULL)
9130Sstevel@tonic-gate 		nattop = nat = n;
9140Sstevel@tonic-gate 	else {
9150Sstevel@tonic-gate 		nat->in_next = n;
9160Sstevel@tonic-gate 		nat = n;
9170Sstevel@tonic-gate 	}
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 
setnatproto(p)9210Sstevel@tonic-gate static void setnatproto(p)
9220Sstevel@tonic-gate int p;
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate 	nat->in_p = p;
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	switch (p)
9270Sstevel@tonic-gate 	{
9280Sstevel@tonic-gate 	case IPPROTO_TCP :
9290Sstevel@tonic-gate 		nat->in_flags |= IPN_TCP;
9300Sstevel@tonic-gate 		nat->in_flags &= ~IPN_UDP;
9310Sstevel@tonic-gate 		break;
9320Sstevel@tonic-gate 	case IPPROTO_UDP :
9330Sstevel@tonic-gate 		nat->in_flags |= IPN_UDP;
9340Sstevel@tonic-gate 		nat->in_flags &= ~IPN_TCP;
9350Sstevel@tonic-gate 		break;
9362393Syz155240 	case IPPROTO_ICMP :
9372393Syz155240 		nat->in_flags &= ~IPN_TCPUDP;
9382393Syz155240 		if (!(nat->in_flags & IPN_ICMPQUERY)) {
9392393Syz155240 			nat->in_dcmp = 0;
9402393Syz155240 			nat->in_scmp = 0;
9412393Syz155240 			nat->in_pmin = 0;
9422393Syz155240 			nat->in_pmax = 0;
9432393Syz155240 			nat->in_pnext = 0;
9442393Syz155240 		}
9452393Syz155240 		break;
9460Sstevel@tonic-gate 	default :
9470Sstevel@tonic-gate 		if ((nat->in_redir & NAT_MAPBLK) == 0) {
9482393Syz155240 			/* Only reset dcmp/scmp in case dport/sport not set */
9492393Syz155240 			if (0 == nat->in_tuc.ftu_dport)
9502393Syz155240 				nat->in_dcmp = 0;
9512393Syz155240 			if (0 == nat->in_tuc.ftu_sport)
9522393Syz155240 				nat->in_scmp = 0;
9530Sstevel@tonic-gate 			nat->in_pmin = 0;
9540Sstevel@tonic-gate 			nat->in_pmax = 0;
9550Sstevel@tonic-gate 			nat->in_pnext = 0;
9560Sstevel@tonic-gate 			nat->in_flags &= ~IPN_TCPUDP;
9570Sstevel@tonic-gate 		}
9580Sstevel@tonic-gate 		break;
9590Sstevel@tonic-gate 	}
9602393Syz155240 
9612393Syz155240 	if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
9622393Syz155240 		nat->in_flags &= ~IPN_FIXEDDPORT;
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 
ipnat_addrule(fd,ioctlfunc,ptr)9660Sstevel@tonic-gate void ipnat_addrule(fd, ioctlfunc, ptr)
9670Sstevel@tonic-gate int fd;
9680Sstevel@tonic-gate ioctlfunc_t ioctlfunc;
9690Sstevel@tonic-gate void *ptr;
9700Sstevel@tonic-gate {
9712393Syz155240 	ioctlcmd_t add, del;
9720Sstevel@tonic-gate 	ipfobj_t obj;
9730Sstevel@tonic-gate 	ipnat_t *ipn;
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 	ipn = ptr;
9760Sstevel@tonic-gate 	bzero((char *)&obj, sizeof(obj));
9770Sstevel@tonic-gate 	obj.ipfo_rev = IPFILTER_VERSION;
9780Sstevel@tonic-gate 	obj.ipfo_size = sizeof(ipnat_t);
9790Sstevel@tonic-gate 	obj.ipfo_type = IPFOBJ_IPNAT;
9800Sstevel@tonic-gate 	obj.ipfo_ptr = ptr;
9810Sstevel@tonic-gate 	add = 0;
9820Sstevel@tonic-gate 	del = 0;
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 	if ((opts & OPT_DONOTHING) != 0)
9850Sstevel@tonic-gate 		fd = -1;
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 	if (opts & OPT_ZERORULEST) {
9880Sstevel@tonic-gate 		add = SIOCZRLST;
9890Sstevel@tonic-gate 	} else if (opts & OPT_INACTIVE) {
9900Sstevel@tonic-gate 		add = SIOCADNAT;
9910Sstevel@tonic-gate 		del = SIOCRMNAT;
9920Sstevel@tonic-gate 	} else {
9930Sstevel@tonic-gate 		add = SIOCADNAT;
9940Sstevel@tonic-gate 		del = SIOCRMNAT;
9950Sstevel@tonic-gate 	}
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	if (ipn && (opts & OPT_VERBOSE))
9980Sstevel@tonic-gate 		printnat(ipn, opts);
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 	if (opts & OPT_DEBUG)
10010Sstevel@tonic-gate 		binprint(ipn, sizeof(*ipn));
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 	if ((opts & OPT_ZERORULEST) != 0) {
10040Sstevel@tonic-gate 		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
10050Sstevel@tonic-gate 			if ((opts & OPT_DONOTHING) == 0) {
10060Sstevel@tonic-gate 				fprintf(stderr, "%d:", yylineNum);
10070Sstevel@tonic-gate 				perror("ioctl(SIOCZRLST)");
10080Sstevel@tonic-gate 			}
10090Sstevel@tonic-gate 		} else {
10100Sstevel@tonic-gate #ifdef	USE_QUAD_T
10110Sstevel@tonic-gate /*
10120Sstevel@tonic-gate 			printf("hits %qd bytes %qd ",
10130Sstevel@tonic-gate 				(long long)fr->fr_hits,
10140Sstevel@tonic-gate 				(long long)fr->fr_bytes);
10150Sstevel@tonic-gate */
10160Sstevel@tonic-gate #else
10170Sstevel@tonic-gate /*
10180Sstevel@tonic-gate 			printf("hits %ld bytes %ld ",
10190Sstevel@tonic-gate 				fr->fr_hits, fr->fr_bytes);
10200Sstevel@tonic-gate */
10210Sstevel@tonic-gate #endif
10220Sstevel@tonic-gate 			printnat(ipn, opts);
10230Sstevel@tonic-gate 		}
10240Sstevel@tonic-gate 	} else if ((opts & OPT_REMOVE) != 0) {
10250Sstevel@tonic-gate 		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
10260Sstevel@tonic-gate 			if ((opts & OPT_DONOTHING) == 0) {
10270Sstevel@tonic-gate 				fprintf(stderr, "%d:", yylineNum);
10280Sstevel@tonic-gate 				perror("ioctl(delete nat rule)");
10290Sstevel@tonic-gate 			}
10300Sstevel@tonic-gate 		}
10310Sstevel@tonic-gate 	} else {
10320Sstevel@tonic-gate 		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
10330Sstevel@tonic-gate 			if ((opts & OPT_DONOTHING) == 0) {
10340Sstevel@tonic-gate 				fprintf(stderr, "%d:", yylineNum);
10350Sstevel@tonic-gate 				perror("ioctl(add/insert nat rule)");
10360Sstevel@tonic-gate 			}
10370Sstevel@tonic-gate 		}
10380Sstevel@tonic-gate 	}
10390Sstevel@tonic-gate }
10402609Sjojemann 
1041