xref: /illumos-gate/usr/src/cmd/ipf/tools/ipnat_y.y (revision ab073b32)
17c478bd9Sstevel@tonic-gate %{
26aed92a9Syx /*
3d6c23f6fSyx  * Copyright (C) 2001-2008 by Darren Reed.
46aed92a9Syx  *
56aed92a9Syx  * See the IPFILTER.LICENCE file for details on licencing.
66aed92a9Syx  *
7d6c23f6fSyx  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
86aed92a9Syx  * Use is subject to license terms.
96aed92a9Syx  */
109b4c7145Sjojemann 
119b4c7145Sjojemann #pragma ident	"%Z%%M%	%I%	%E% SMI"
126aed92a9Syx 
137c478bd9Sstevel@tonic-gate #ifdef  __FreeBSD__
147c478bd9Sstevel@tonic-gate # ifndef __FreeBSD_cc_version
157c478bd9Sstevel@tonic-gate #  include <osreldate.h>
167c478bd9Sstevel@tonic-gate # else
177c478bd9Sstevel@tonic-gate #  if __FreeBSD_cc_version < 430000
187c478bd9Sstevel@tonic-gate #   include <osreldate.h>
197c478bd9Sstevel@tonic-gate #  endif
207c478bd9Sstevel@tonic-gate # endif
217c478bd9Sstevel@tonic-gate #endif
227c478bd9Sstevel@tonic-gate #include <stdio.h>
237c478bd9Sstevel@tonic-gate #include <unistd.h>
247c478bd9Sstevel@tonic-gate #include <string.h>
257c478bd9Sstevel@tonic-gate #include <fcntl.h>
267c478bd9Sstevel@tonic-gate #include <errno.h>
277c478bd9Sstevel@tonic-gate #if !defined(__SVR4) && !defined(__GNUC__)
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #endif
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/file.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <stddef.h>
357c478bd9Sstevel@tonic-gate #include <sys/socket.h>
367c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
377c478bd9Sstevel@tonic-gate #include <netinet/in.h>
387c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
397c478bd9Sstevel@tonic-gate #include <sys/time.h>
407c478bd9Sstevel@tonic-gate #include <syslog.h>
417c478bd9Sstevel@tonic-gate #include <net/if.h>
427c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 300000
437c478bd9Sstevel@tonic-gate # include <net/if_var.h>
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate #include <netdb.h>
467c478bd9Sstevel@tonic-gate #include <arpa/nameser.h>
477c478bd9Sstevel@tonic-gate #include <resolv.h>
487c478bd9Sstevel@tonic-gate #include "ipf.h"
497c478bd9Sstevel@tonic-gate #include "netinet/ipl.h"
507c478bd9Sstevel@tonic-gate #include "ipnat_l.h"
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	YYDEBUG	1
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate extern	void	yyerror __P((char *));
557c478bd9Sstevel@tonic-gate extern	int	yyparse __P((void));
567c478bd9Sstevel@tonic-gate extern	int	yylex __P((void));
577c478bd9Sstevel@tonic-gate extern	int	yydebug;
587c478bd9Sstevel@tonic-gate extern	FILE	*yyin;
597c478bd9Sstevel@tonic-gate extern	int	yylineNum;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static	ipnat_t		*nattop = NULL;
627c478bd9Sstevel@tonic-gate static	ipnat_t		*nat = NULL;
637c478bd9Sstevel@tonic-gate static	int		natfd = -1;
647c478bd9Sstevel@tonic-gate static	ioctlfunc_t	natioctlfunc = NULL;
657c478bd9Sstevel@tonic-gate static	addfunc_t	nataddfunc = NULL;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate static	void	newnatrule __P((void));
687c478bd9Sstevel@tonic-gate static	void	setnatproto __P((int));
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate %}
717c478bd9Sstevel@tonic-gate %union	{
727c478bd9Sstevel@tonic-gate 	char	*str;
737c478bd9Sstevel@tonic-gate 	u_32_t	num;
74d6c23f6fSyx 	struct	{
75d6c23f6fSyx 		i6addr_t	a;
76d6c23f6fSyx 		int		v;
77d6c23f6fSyx 	} ipa;
787c478bd9Sstevel@tonic-gate 	frentry_t	fr;
797c478bd9Sstevel@tonic-gate 	frtuc_t	*frt;
80ab25eeb5Syz 	u_short	port;
817c478bd9Sstevel@tonic-gate 	struct	{
827c478bd9Sstevel@tonic-gate 		u_short	p1;
837c478bd9Sstevel@tonic-gate 		u_short	p2;
847c478bd9Sstevel@tonic-gate 		int	pc;
857c478bd9Sstevel@tonic-gate 	} pc;
867c478bd9Sstevel@tonic-gate 	struct	{
87d6c23f6fSyx 		i6addr_t	a;
88d6c23f6fSyx 		i6addr_t	m;
89d6c23f6fSyx 		int	v;
907c478bd9Sstevel@tonic-gate 	} ipp;
917c478bd9Sstevel@tonic-gate 	union	i6addr	ip6;
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate %token  <num>   YY_NUMBER YY_HEX
957c478bd9Sstevel@tonic-gate %token  <str>   YY_STR
967c478bd9Sstevel@tonic-gate %token	  YY_COMMENT
977c478bd9Sstevel@tonic-gate %token	  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
987c478bd9Sstevel@tonic-gate %token	  YY_RANGE_OUT YY_RANGE_IN
997c478bd9Sstevel@tonic-gate %token  <ip6>   YY_IPV6
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate %token	IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
1027c478bd9Sstevel@tonic-gate %token	IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
1037c478bd9Sstevel@tonic-gate %token	IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
1047c478bd9Sstevel@tonic-gate %token	IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
105*ab073b32Sdr %token	IPNY_TLATE IPNY_SEQUENTIAL
106ab25eeb5Syz %type	<port> portspec
107ab25eeb5Syz %type	<num> hexnumber compare range proto
108d6c23f6fSyx %type	<num> saddr daddr sobject dobject mapfrom rdrfrom dip
109d6c23f6fSyx %type	<ipa> hostname ipv4 ipaddr
110d6c23f6fSyx %type	<ipp> addr rhaddr
1117c478bd9Sstevel@tonic-gate %type	<pc> portstuff
1127c478bd9Sstevel@tonic-gate %%
1137c478bd9Sstevel@tonic-gate file:	line
1147c478bd9Sstevel@tonic-gate 	| assign
1157c478bd9Sstevel@tonic-gate 	| file line
1167c478bd9Sstevel@tonic-gate 	| file assign
1177c478bd9Sstevel@tonic-gate 	;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate line:	xx rule		{ while ((nat = nattop) != NULL) {
120d6c23f6fSyx 				if (nat->in_v == 0)
121d6c23f6fSyx 					nat->in_v = 4;
1227c478bd9Sstevel@tonic-gate 				nattop = nat->in_next;
1237c478bd9Sstevel@tonic-gate 				(*nataddfunc)(natfd, natioctlfunc, nat);
1247c478bd9Sstevel@tonic-gate 				free(nat);
1257c478bd9Sstevel@tonic-gate 			  }
1267c478bd9Sstevel@tonic-gate 			  resetlexer();
1277c478bd9Sstevel@tonic-gate 			}
1287c478bd9Sstevel@tonic-gate 	| YY_COMMENT
1297c478bd9Sstevel@tonic-gate 	;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
1327c478bd9Sstevel@tonic-gate 					  resetlexer();
1337c478bd9Sstevel@tonic-gate 					  free($1);
1347c478bd9Sstevel@tonic-gate 					  free($3);
1357c478bd9Sstevel@tonic-gate 					}
1367c478bd9Sstevel@tonic-gate 	;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate assigning:
1397c478bd9Sstevel@tonic-gate 	'='				{ yyvarnext = 1; }
1407c478bd9Sstevel@tonic-gate 	;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate xx:					{ newnatrule(); }
1437c478bd9Sstevel@tonic-gate 	;
1447c478bd9Sstevel@tonic-gate 
145ab25eeb5Syz rule:	map eol
146ab25eeb5Syz 	| mapblock eol
147ab25eeb5Syz 	| redir eol
148ab25eeb5Syz 	;
149ab25eeb5Syz 
150ab25eeb5Syz eol:	| ';'
1517c478bd9Sstevel@tonic-gate 	;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate map:	mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
154d6c23f6fSyx 				{ if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
155d6c23f6fSyx 					yyerror("1.address family mismatch");
156d6c23f6fSyx 				  bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
157d6c23f6fSyx 				  bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
158d6c23f6fSyx 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
159d6c23f6fSyx 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1607c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
1617c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
1627c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
1637c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
1647c478bd9Sstevel@tonic-gate 				  if ((nat->in_flags & IPN_TCPUDP) == 0)
1657c478bd9Sstevel@tonic-gate 					setnatproto(nat->in_p);
1667c478bd9Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1677c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
1687c478bd9Sstevel@tonic-gate 					nat_setgroupmap(nat);
1697c478bd9Sstevel@tonic-gate 				}
1707c478bd9Sstevel@tonic-gate 	| mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
171d6c23f6fSyx 				{ if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
172d6c23f6fSyx 					yyerror("2.address family mismatch");
173d6c23f6fSyx 				  bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
174d6c23f6fSyx 				  bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
175d6c23f6fSyx 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
176d6c23f6fSyx 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1777c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
1787c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
1797c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
1807c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
181ab25eeb5Syz 				  if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
1827c478bd9Sstevel@tonic-gate 					setnatproto(nat->in_p);
1837c478bd9Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1847c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
1857c478bd9Sstevel@tonic-gate 					nat_setgroupmap(nat);
1867c478bd9Sstevel@tonic-gate 				}
1877c478bd9Sstevel@tonic-gate 	| mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
188d6c23f6fSyx 				{ if ($3 != 0 && $3 != $5.v && $5.v != 0)
189d6c23f6fSyx 					yyerror("3.address family mismatch");
190d6c23f6fSyx 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
191d6c23f6fSyx 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1927c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
1937c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
1947c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
1957c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
1967c478bd9Sstevel@tonic-gate 				  if ((nat->in_flags & IPN_TCPUDP) == 0)
1977c478bd9Sstevel@tonic-gate 					setnatproto(nat->in_p);
1987c478bd9Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1997c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2007c478bd9Sstevel@tonic-gate 					nat_setgroupmap(nat);
2017c478bd9Sstevel@tonic-gate 				}
2027c478bd9Sstevel@tonic-gate 	| mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
203d6c23f6fSyx 				{ if ($3 != 0 && $3 != $5.v && $5.v != 0)
204d6c23f6fSyx 					yyerror("4.address family mismatch");
205d6c23f6fSyx 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
206d6c23f6fSyx 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
2077c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2087c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2097c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
2107c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
211ab25eeb5Syz 				  if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
2127c478bd9Sstevel@tonic-gate 					setnatproto(nat->in_p);
2137c478bd9Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
2147c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2157c478bd9Sstevel@tonic-gate 					nat_setgroupmap(nat);
2167c478bd9Sstevel@tonic-gate 				}
2177c478bd9Sstevel@tonic-gate 	;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate mapblock:
2207c478bd9Sstevel@tonic-gate 	mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
221d6c23f6fSyx 				{ if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
222d6c23f6fSyx 					yyerror("5.address family mismatch");
223d6c23f6fSyx 				  bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
224d6c23f6fSyx 				  bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
225d6c23f6fSyx 				  bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
226d6c23f6fSyx 				  bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
2277c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2287c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2297c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
2307c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2317c478bd9Sstevel@tonic-gate 				  if ((nat->in_flags & IPN_TCPUDP) == 0)
2327c478bd9Sstevel@tonic-gate 					setnatproto(nat->in_p);
2337c478bd9Sstevel@tonic-gate 				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
2347c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2357c478bd9Sstevel@tonic-gate 					nat_setgroupmap(nat);
2367c478bd9Sstevel@tonic-gate 				}
2377c478bd9Sstevel@tonic-gate 	;
2387c478bd9Sstevel@tonic-gate 
239ab25eeb5Syz redir:	rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
240d6c23f6fSyx 				{ if ($6 != 0 && $3.v != 0 && $6 != $3.v)
241d6c23f6fSyx 					yyerror("6.address family mismatch");
242d6c23f6fSyx 				  bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
243d6c23f6fSyx 				  bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
2447c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2457c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2467c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
2477c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2487c478bd9Sstevel@tonic-gate 				  if ((nat->in_p == 0) &&
2497c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_TCPUDP) == 0) &&
2507c478bd9Sstevel@tonic-gate 				      (nat->in_pmin != 0 ||
2517c478bd9Sstevel@tonic-gate 				       nat->in_pmax != 0 ||
2527c478bd9Sstevel@tonic-gate 				       nat->in_pnext != 0))
2537c478bd9Sstevel@tonic-gate 						setnatproto(IPPROTO_TCP);
2547c478bd9Sstevel@tonic-gate 				}
255ab25eeb5Syz 	| rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
256d6c23f6fSyx 				{ if ($5 != 0 && $3 != 0 && $5 != $3)
257d6c23f6fSyx 					yyerror("7.address family mismatch");
258ab25eeb5Syz 				  if ((nat->in_p == 0) &&
2597c478bd9Sstevel@tonic-gate 				      ((nat->in_flags & IPN_TCPUDP) == 0) &&
2607c478bd9Sstevel@tonic-gate 				      (nat->in_pmin != 0 ||
2617c478bd9Sstevel@tonic-gate 				       nat->in_pmax != 0 ||
2627c478bd9Sstevel@tonic-gate 				       nat->in_pnext != 0))
2637c478bd9Sstevel@tonic-gate 					setnatproto(IPPROTO_TCP);
2647c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2657c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2667c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
2677c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2687c478bd9Sstevel@tonic-gate 				}
269ab25eeb5Syz 	| rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
270d6c23f6fSyx 				{ if ($5 != 0 && $3.v != 0 && $5 != $3.v)
271d6c23f6fSyx 					yyerror("8.address family mismatch");
272d6c23f6fSyx 				  bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
273d6c23f6fSyx 				  bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
2747c478bd9Sstevel@tonic-gate 				  if (nat->in_ifnames[1][0] == '\0')
2757c478bd9Sstevel@tonic-gate 					strncpy(nat->in_ifnames[1],
2767c478bd9Sstevel@tonic-gate 						nat->in_ifnames[0],
2777c478bd9Sstevel@tonic-gate 						sizeof(nat->in_ifnames[0]));
2787c478bd9Sstevel@tonic-gate 				}
2797c478bd9Sstevel@tonic-gate 	;
2807c478bd9Sstevel@tonic-gate 
281ab25eeb5Syz proxy:	| IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto
2827c478bd9Sstevel@tonic-gate 			{ strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
2837c478bd9Sstevel@tonic-gate 			  if (nat->in_dcmp == 0) {
2847c478bd9Sstevel@tonic-gate 				nat->in_dport = htons($3);
2857c478bd9Sstevel@tonic-gate 			  } else if ($3 != nat->in_dport) {
2867c478bd9Sstevel@tonic-gate 				yyerror("proxy port numbers not consistant");
2877c478bd9Sstevel@tonic-gate 			  }
2887c478bd9Sstevel@tonic-gate 			  setnatproto($6);
2897c478bd9Sstevel@tonic-gate 			  free($4);
2907c478bd9Sstevel@tonic-gate 			}
2917c478bd9Sstevel@tonic-gate 	| IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto
292ab25eeb5Syz 			{ int pnum;
293ab25eeb5Syz 			  strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
294ab25eeb5Syz 			  pnum = getportproto($3, $6);
295ab25eeb5Syz 			  if (pnum == -1)
296ab25eeb5Syz 				yyerror("invalid port number");
297ab25eeb5Syz 			  nat->in_dport = pnum;
2987c478bd9Sstevel@tonic-gate 			  setnatproto($6);
2997c478bd9Sstevel@tonic-gate 			  free($3);
3007c478bd9Sstevel@tonic-gate 			  free($4);
3017c478bd9Sstevel@tonic-gate 			}
3027c478bd9Sstevel@tonic-gate 	;
3037c478bd9Sstevel@tonic-gate 
304ab25eeb5Syz setproto:
305ab25eeb5Syz 	| proto				{ if (nat->in_p != 0 ||
306ab25eeb5Syz 					      nat->in_flags & IPN_TCPUDP)
307ab25eeb5Syz 						yyerror("protocol set twice");
308ab25eeb5Syz 					  setnatproto($1);
309ab25eeb5Syz 					}
310ab25eeb5Syz 	| IPNY_TCPUDP			{ if (nat->in_p != 0 ||
311ab25eeb5Syz 					      nat->in_flags & IPN_TCPUDP)
312ab25eeb5Syz 						yyerror("protocol set twice");
313ab25eeb5Syz 					  nat->in_flags |= IPN_TCPUDP;
314ab25eeb5Syz 					  nat->in_p = 0;
315ab25eeb5Syz 					}
316ab25eeb5Syz 	| IPNY_TCP '/' IPNY_UDP		{ if (nat->in_p != 0 ||
317ab25eeb5Syz 					      nat->in_flags & IPN_TCPUDP)
318ab25eeb5Syz 						yyerror("protocol set twice");
319ab25eeb5Syz 					  nat->in_flags |= IPN_TCPUDP;
320ab25eeb5Syz 					  nat->in_p = 0;
3217c478bd9Sstevel@tonic-gate 					}
3227c478bd9Sstevel@tonic-gate 	;
3237c478bd9Sstevel@tonic-gate 
324d6c23f6fSyx rhaddr:	addr				{ $$.a = $1.a;
325d6c23f6fSyx 					  $$.m = $1.m;
326d6c23f6fSyx 					  $$.v = $1.v;
327d6c23f6fSyx 					  if ($$.v == 0)
328d6c23f6fSyx 						$$.v = nat->in_v;
329d6c23f6fSyx 					  yyexpectaddr = 0; }
330d6c23f6fSyx 	| IPNY_RANGE hostname '-' hostname
331d6c23f6fSyx 					{ if ($2.v != 0 && $4.v != 0 && $4.v != $2.v)
332d6c23f6fSyx 						yyerror("9.address family "
333d6c23f6fSyx 							"mismatch");
334d6c23f6fSyx 					  $$.v = $2.v;
335d6c23f6fSyx 					  $$.a = $2.a;
336d6c23f6fSyx 					  $$.m = $4.a;
337d6c23f6fSyx 					  nat->in_flags |= IPN_IPRANGE;
338d6c23f6fSyx 					  yyexpectaddr = 0; }
339ab25eeb5Syz 	;
340ab25eeb5Syz 
3417c478bd9Sstevel@tonic-gate dip:
342d6c23f6fSyx 	hostname			{ bcopy(&$1.a, &nat->in_in[0],
343d6c23f6fSyx 						sizeof($1.a));
344d6c23f6fSyx 					  if ($1.v == 0)
345d6c23f6fSyx 						$1.v = nat->in_v;
346d6c23f6fSyx 					  if ($1.v == 4) {
347d6c23f6fSyx 						nat->in_inmsk = 0xffffffff;
348d6c23f6fSyx 					  } else {
349d6c23f6fSyx 						nat->in_in[1].i6[0] = 0xffffffff;
350d6c23f6fSyx 						nat->in_in[1].i6[1] = 0xffffffff;
351d6c23f6fSyx 						nat->in_in[1].i6[2] = 0xffffffff;
352d6c23f6fSyx 						nat->in_in[1].i6[3] = 0xffffffff;
353d6c23f6fSyx 					  }
354d6c23f6fSyx 					  $$ = $1.v;
355d6c23f6fSyx 					}
356d6c23f6fSyx 	| hostname '/' YY_NUMBER        { if ($1.v == 0)
357d6c23f6fSyx 						$1.v = nat->in_v;
358d6c23f6fSyx 					  if ($1.v == 4 &&
359d6c23f6fSyx 					      ($1.a.in4.s_addr != 0 ||
360d6c23f6fSyx 					      ($3 != 0 && $3 != 32)))
361d6c23f6fSyx 						yyerror("Invalid mask for dip");
362d6c23f6fSyx 					  else if ($1.v == 6 &&
363d6c23f6fSyx 					      ($1.a.in4.s_addr != 0 ||
364d6c23f6fSyx 					      ($3 != 0 && $3 != 128)))
365ef292b7fSjojemann 						yyerror("Invalid mask for dip");
366d6c23f6fSyx 					  else if ($1.v == 0 ) {
367d6c23f6fSyx 						if ($1.a.in4.s_addr == 0 &&
368d6c23f6fSyx 						    ($3 == 32 || $3 == 0))
369d6c23f6fSyx 							$1.v = 4;
370d6c23f6fSyx 						else if ($3 == 128)
371d6c23f6fSyx 							$1.v = 6;
372d6c23f6fSyx 					  }
373d6c23f6fSyx 					  bcopy(&$1.a, &nat->in_in[0],
374d6c23f6fSyx 						sizeof($1.a));
375d6c23f6fSyx 					  ntomask($1.v, $3,
376d6c23f6fSyx 						(u_32_t *)&nat->in_in[1]);
377d6c23f6fSyx 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[0];
378d6c23f6fSyx 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[1];
379d6c23f6fSyx 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[2];
380d6c23f6fSyx 					  nat->in_in[0].i6[0] &= nat->in_in[1].i6[3];
381d6c23f6fSyx 					  nat->in_v = $1.v;
382d6c23f6fSyx 					  $$ = $1.v;
383d6c23f6fSyx 					}
384d6c23f6fSyx 	| hostname ',' { yyexpectaddr = 1; } hostname
385d6c23f6fSyx 					{ if ($1.v != $4.v)
386d6c23f6fSyx 						yyerror("10.address family "
387d6c23f6fSyx 							"mismatch");
388d6c23f6fSyx 					  $$ = $1.v;
389d6c23f6fSyx 					  nat->in_flags |= IPN_SPLIT;
390d6c23f6fSyx 					  bcopy(&$1.a, &nat->in_in[0],
391d6c23f6fSyx 						sizeof($1.a));
392d6c23f6fSyx 					  bcopy(&$4.a, &nat->in_in[1],
393d6c23f6fSyx 						sizeof($4.a));
394d6c23f6fSyx 					  yyexpectaddr = 0; }
3957c478bd9Sstevel@tonic-gate 	;
3967c478bd9Sstevel@tonic-gate 
397ab25eeb5Syz portspec:
398ab25eeb5Syz 	YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
399ab25eeb5Syz 						yyerror("invalid port number");
400ab25eeb5Syz 					  else
401ab25eeb5Syz 						$$ = $1;
402ab25eeb5Syz 					}
403ab25eeb5Syz 	| YY_STR			{ if (getport(NULL, $1, &($$)) == -1)
404ab25eeb5Syz 						yyerror("invalid port number");
405ab25eeb5Syz 					  $$ = ntohs($$);
406ab25eeb5Syz 					}
407ab25eeb5Syz 	;
408ab25eeb5Syz 
409ab25eeb5Syz dport:	| IPNY_PORT portspec			{ nat->in_pmin = htons($2);
4107c478bd9Sstevel@tonic-gate 						  nat->in_pmax = htons($2); }
411ab25eeb5Syz 	| IPNY_PORT portspec '-' portspec	{ nat->in_pmin = htons($2);
412ab25eeb5Syz 						  nat->in_pmax = htons($4); }
413ab25eeb5Syz 	| IPNY_PORT portspec ':' portspec	{ nat->in_pmin = htons($2);
4147c478bd9Sstevel@tonic-gate 						  nat->in_pmax = htons($4); }
4157c478bd9Sstevel@tonic-gate 	;
4167c478bd9Sstevel@tonic-gate 
417ab25eeb5Syz nport:	IPNY_PORT portspec		{ nat->in_pnext = htons($2); }
418ab25eeb5Syz 	| IPNY_PORT '=' portspec	{ nat->in_pnext = htons($3);
419ab25eeb5Syz 					  nat->in_flags |= IPN_FIXEDDPORT;
420ab25eeb5Syz 					}
4217c478bd9Sstevel@tonic-gate 	;
4227c478bd9Sstevel@tonic-gate 
423ab25eeb5Syz ports:	| IPNY_PORTS YY_NUMBER		{ nat->in_pmin = $2; }
4247c478bd9Sstevel@tonic-gate 	| IPNY_PORTS IPNY_AUTO		{ nat->in_flags |= IPN_AUTOPORTMAP; }
4257c478bd9Sstevel@tonic-gate 	;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate mapit:	IPNY_MAP			{ nat->in_redir = NAT_MAP; }
4287c478bd9Sstevel@tonic-gate 	| IPNY_BIMAP			{ nat->in_redir = NAT_BIMAP; }
4297c478bd9Sstevel@tonic-gate 	;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate rdrit:	IPNY_RDR			{ nat->in_redir = NAT_REDIRECT; }
4327c478bd9Sstevel@tonic-gate 	;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate mapblockit:
4357c478bd9Sstevel@tonic-gate 	IPNY_MAPBLOCK			{ nat->in_redir = NAT_MAPBLK; }
4367c478bd9Sstevel@tonic-gate 	;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate mapfrom:
439d6c23f6fSyx 	from sobject IPNY_TO dobject	{ if ($2 != 0 && $4 != 0 && $2 != $4)
440d6c23f6fSyx 						yyerror("11.address family "
441d6c23f6fSyx 							"mismatch");
442d6c23f6fSyx 					  $$ = $2;
443d6c23f6fSyx 					}
4447c478bd9Sstevel@tonic-gate 	| from sobject '!' IPNY_TO dobject
445d6c23f6fSyx 					{ if ($2 != 0 && $5 != 0 && $2 != $5)
446d6c23f6fSyx 						yyerror("12.address family "
447d6c23f6fSyx 							"mismatch");
448d6c23f6fSyx 					  nat->in_flags |= IPN_NOTDST;
449d6c23f6fSyx 					  $$ = $2;
450d6c23f6fSyx 					}
4517c478bd9Sstevel@tonic-gate 	;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate rdrfrom:
454d6c23f6fSyx 	from sobject IPNY_TO dobject	{ if ($2 != 0 && $4 != 0 && $2 != $4)
455d6c23f6fSyx 						yyerror("13.address family "
456d6c23f6fSyx 							"mismatch");
457d6c23f6fSyx 					  $$ = $2;
458d6c23f6fSyx 					}
4597c478bd9Sstevel@tonic-gate 	| '!' from sobject IPNY_TO dobject
460d6c23f6fSyx 					{ if ($3 != 0 && $5 != 0 && $3 != $5)
461d6c23f6fSyx 						yyerror("14.address family "
462d6c23f6fSyx 							"mismatch");
463d6c23f6fSyx 					  nat->in_flags |= IPN_NOTSRC;
464d6c23f6fSyx 					  $$ = $3;
465d6c23f6fSyx 					}
4667c478bd9Sstevel@tonic-gate 	;
4677c478bd9Sstevel@tonic-gate 
468d6c23f6fSyx from:	IPNY_FROM			{ nat->in_flags |= IPN_FILTER;
469d6c23f6fSyx 					  yyexpectaddr = 1; }
4707c478bd9Sstevel@tonic-gate 	;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate ifnames:
473d6c23f6fSyx 	ifname				{ yyexpectaddr = 1; }
474d6c23f6fSyx 	| ifname ',' otherifname	{ yyexpectaddr = 1; }
4757c478bd9Sstevel@tonic-gate 	;
4767c478bd9Sstevel@tonic-gate 
477