xref: /freebsd/sbin/ipf/ipnat/ipnat_y.y (revision 2a63c3be158216222d89a073dcbd6a72ee4aab5a)
141edb306SCy Schubert 
241edb306SCy Schubert /*
341edb306SCy Schubert  * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert  *
541edb306SCy Schubert  * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert  */
741edb306SCy Schubert %{
841edb306SCy Schubert #include <stdio.h>
941edb306SCy Schubert #include <unistd.h>
1041edb306SCy Schubert #include <string.h>
1141edb306SCy Schubert #include <fcntl.h>
1241edb306SCy Schubert #include <errno.h>
1341edb306SCy Schubert #if !defined(__SVR4) && !defined(__GNUC__)
1441edb306SCy Schubert #include <strings.h>
1541edb306SCy Schubert #endif
1641edb306SCy Schubert #include <sys/types.h>
1741edb306SCy Schubert #include <sys/param.h>
1841edb306SCy Schubert #include <sys/file.h>
1941edb306SCy Schubert #include <stdlib.h>
2041edb306SCy Schubert #include <stddef.h>
2141edb306SCy Schubert #include <sys/socket.h>
2241edb306SCy Schubert #include <sys/ioctl.h>
2341edb306SCy Schubert #include <netinet/in.h>
2441edb306SCy Schubert #include <netinet/in_systm.h>
2541edb306SCy Schubert #include <sys/time.h>
2641edb306SCy Schubert #include <syslog.h>
2741edb306SCy Schubert #include <net/if.h>
2841edb306SCy Schubert #include <netdb.h>
2941edb306SCy Schubert #include <arpa/nameser.h>
3041edb306SCy Schubert #include <resolv.h>
3141edb306SCy Schubert #include "ipf.h"
3241edb306SCy Schubert #include "netinet/ipl.h"
3341edb306SCy Schubert #include "ipnat_l.h"
3441edb306SCy Schubert 
3541edb306SCy Schubert #define	YYDEBUG	1
3641edb306SCy Schubert 
3741edb306SCy Schubert extern	void	yyerror(char *);
3841edb306SCy Schubert extern	int	yyparse(void);
3941edb306SCy Schubert extern	int	yylex(void);
4041edb306SCy Schubert extern	int	yydebug;
4141edb306SCy Schubert extern	FILE	*yyin;
4241edb306SCy Schubert extern	int	yylineNum;
4341edb306SCy Schubert 
4441edb306SCy Schubert static	ipnat_t		*nattop = NULL;
4541edb306SCy Schubert static	ipnat_t		*nat = NULL;
4641edb306SCy Schubert static	int		natfd = -1;
4741edb306SCy Schubert static	ioctlfunc_t	natioctlfunc = NULL;
4841edb306SCy Schubert static	addfunc_t	nataddfunc = NULL;
4941edb306SCy Schubert static	int		suggest_port = 0;
5041edb306SCy Schubert static	proxyrule_t	*prules = NULL;
5141edb306SCy Schubert static	int		parser_error = 0;
5241edb306SCy Schubert 
5341edb306SCy Schubert static	void	newnatrule(void);
5441edb306SCy Schubert static	void	setnatproto(int);
5541edb306SCy Schubert static	void	setmapifnames(void);
5641edb306SCy Schubert static	void	setrdrifnames(void);
5741edb306SCy Schubert static	void	proxy_setconfig(int);
5841edb306SCy Schubert static	void	proxy_unsetconfig(void);
5941edb306SCy Schubert static	namelist_t *proxy_dns_add_pass(char *, char *);
6041edb306SCy Schubert static	namelist_t *proxy_dns_add_block(char *, char *);
6141edb306SCy Schubert static	void	proxy_addconfig(char *, int, char *, namelist_t *);
6241edb306SCy Schubert static	void	proxy_loadconfig(int, ioctlfunc_t, char *, int,
6341edb306SCy Schubert 				      char *, namelist_t *);
6441edb306SCy Schubert static	void	proxy_loadrules(int, ioctlfunc_t, proxyrule_t *);
6541edb306SCy Schubert static	void	setmapifnames(void);
6641edb306SCy Schubert static	void	setrdrifnames(void);
6741edb306SCy Schubert static	void	setifname(ipnat_t **, int, char *);
6841edb306SCy Schubert static	int	addname(ipnat_t **, char *);
6941edb306SCy Schubert %}
7041edb306SCy Schubert %union	{
7141edb306SCy Schubert 	char	*str;
7241edb306SCy Schubert 	u_32_t	num;
7341edb306SCy Schubert 	struct {
7441edb306SCy Schubert 		i6addr_t	a;
7541edb306SCy Schubert 		int		f;
7641edb306SCy Schubert 	} ipa;
7741edb306SCy Schubert 	frentry_t	fr;
7841edb306SCy Schubert 	frtuc_t	*frt;
7941edb306SCy Schubert 	u_short	port;
8041edb306SCy Schubert 	struct	{
8141edb306SCy Schubert 		int	p1;
8241edb306SCy Schubert 		int	p2;
8341edb306SCy Schubert 		int	pc;
8441edb306SCy Schubert 	} pc;
8541edb306SCy Schubert 	struct	{
8641edb306SCy Schubert 		i6addr_t	a;
8741edb306SCy Schubert 		i6addr_t	m;
8841edb306SCy Schubert 		int	t;		/* Address type */
8941edb306SCy Schubert 		int	u;
9041edb306SCy Schubert 		int	f;		/* Family */
9141edb306SCy Schubert 		int	v;		/* IP version */
9241edb306SCy Schubert 		int	s;		/* 0 = number, 1 = text */
9341edb306SCy Schubert 		int	n;		/* number */
9441edb306SCy Schubert 	} ipp;
9541edb306SCy Schubert 	union	i6addr	ip6;
9641edb306SCy Schubert 	namelist_t	*names;
9741edb306SCy Schubert };
9841edb306SCy Schubert 
9941edb306SCy Schubert %token  <num>   YY_NUMBER YY_HEX
10041edb306SCy Schubert %token  <str>   YY_STR
10141edb306SCy Schubert %token	  YY_COMMENT
10241edb306SCy Schubert %token	  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
10341edb306SCy Schubert %token	  YY_RANGE_OUT YY_RANGE_IN
10441edb306SCy Schubert %token  <ip6>   YY_IPV6
10541edb306SCy Schubert 
10641edb306SCy Schubert %token	IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
10741edb306SCy Schubert %token	IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
10841edb306SCy Schubert %token	IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
10941edb306SCy Schubert %token	IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
11041edb306SCy Schubert %token	IPNY_TLATE IPNY_POOL IPNY_HASH IPNY_NO IPNY_REWRITE IPNY_PROTO
11141edb306SCy Schubert %token	IPNY_ON IPNY_SRC IPNY_DST IPNY_IN IPNY_OUT IPNY_DIVERT
11241edb306SCy Schubert %token	IPNY_CONFIG IPNY_ALLOW IPNY_DENY IPNY_DNS IPNY_INET IPNY_INET6
11341edb306SCy Schubert %token	IPNY_SEQUENTIAL IPNY_DSTLIST IPNY_PURGE
11441edb306SCy Schubert %type	<port> portspec
11541edb306SCy Schubert %type	<num> hexnumber compare range proto
11641edb306SCy Schubert %type	<num> saddr daddr sobject dobject mapfrom rdrfrom dip
11741edb306SCy Schubert %type	<ipa> hostname ipv4 ipaddr
11841edb306SCy Schubert %type	<ipp> addr rhsaddr rhdaddr erhdaddr
11941edb306SCy Schubert %type	<pc> portstuff portpair comaports srcports dstports
12041edb306SCy Schubert %type	<names> dnslines dnsline
12141edb306SCy Schubert %%
12241edb306SCy Schubert file:	line
12341edb306SCy Schubert 	| assign
12441edb306SCy Schubert 	| file line
12541edb306SCy Schubert 	| file assign
12641edb306SCy Schubert 	| file pconf ';'
12741edb306SCy Schubert 	;
12841edb306SCy Schubert 
12941edb306SCy Schubert line:	xx rule		{ int err;
13041edb306SCy Schubert 			  while ((nat = nattop) != NULL) {
13141edb306SCy Schubert 				if (nat->in_v[0] == 0)
13241edb306SCy Schubert 					nat->in_v[0] = 4;
13341edb306SCy Schubert 				if (nat->in_v[1] == 0)
13441edb306SCy Schubert 					nat->in_v[1] = nat->in_v[0];
13541edb306SCy Schubert 				nattop = nat->in_next;
13641edb306SCy Schubert 				err = (*nataddfunc)(natfd, natioctlfunc, nat);
13741edb306SCy Schubert 				free(nat);
13841edb306SCy Schubert 				if (err != 0) {
13941edb306SCy Schubert 					parser_error = err;
14041edb306SCy Schubert 					break;
14141edb306SCy Schubert 				}
14241edb306SCy Schubert 			  }
14341edb306SCy Schubert 			  if (parser_error == 0 && prules != NULL) {
14441edb306SCy Schubert 				proxy_loadrules(natfd, natioctlfunc, prules);
14541edb306SCy Schubert 				prules = NULL;
14641edb306SCy Schubert 			  }
14741edb306SCy Schubert 			  resetlexer();
14841edb306SCy Schubert 			}
14941edb306SCy Schubert 	| YY_COMMENT
15041edb306SCy Schubert 	;
15141edb306SCy Schubert 
15241edb306SCy Schubert assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
15341edb306SCy Schubert 					  resetlexer();
15441edb306SCy Schubert 					  free($1);
15541edb306SCy Schubert 					  free($3);
15641edb306SCy Schubert 					  yyvarnext = 0;
15741edb306SCy Schubert 					}
15841edb306SCy Schubert 	;
15941edb306SCy Schubert 
16041edb306SCy Schubert assigning:
16141edb306SCy Schubert 	'='				{ yyvarnext = 1; }
16241edb306SCy Schubert 	;
16341edb306SCy Schubert 
16441edb306SCy Schubert xx:					{ newnatrule(); }
16541edb306SCy Schubert 	;
16641edb306SCy Schubert 
16741edb306SCy Schubert rule:	map eol
16841edb306SCy Schubert 	| mapblock eol
16941edb306SCy Schubert 	| redir eol
17041edb306SCy Schubert 	| rewrite ';'
17141edb306SCy Schubert 	| divert ';'
17241edb306SCy Schubert 	;
17341edb306SCy Schubert 
17441edb306SCy Schubert no:	IPNY_NO				{ nat->in_flags |= IPN_NO; }
17541edb306SCy Schubert 	;
17641edb306SCy Schubert 
17741edb306SCy Schubert eol:	| ';'
17841edb306SCy Schubert 	;
17941edb306SCy Schubert 
18041edb306SCy Schubert map:	mapit ifnames addr tlate rhsaddr proxy mapoptions
18141edb306SCy Schubert 				{ if ($3.f != 0 && $3.f != $5.f && $5.f != 0)
18241edb306SCy Schubert 					yyerror("3.address family mismatch");
18341edb306SCy Schubert 				  if (nat->in_v[0] == 0 && $5.v != 0)
18441edb306SCy Schubert 					nat->in_v[0] = $5.v;
18541edb306SCy Schubert 				  else if (nat->in_v[0] == 0 && $3.v != 0)
18641edb306SCy Schubert 					nat->in_v[0] = $3.v;
18741edb306SCy Schubert 				  if (nat->in_v[1] == 0 && $5.v != 0)
18841edb306SCy Schubert 					nat->in_v[1] = $5.v;
18941edb306SCy Schubert 				  else if (nat->in_v[1] == 0 && $3.v != 0)
19041edb306SCy Schubert 					nat->in_v[1] = $3.v;
19141edb306SCy Schubert 				  nat->in_osrcatype = $3.t;
19241edb306SCy Schubert 				  bcopy(&$3.a, &nat->in_osrc.na_addr[0],
19341edb306SCy Schubert 					sizeof($3.a));
19441edb306SCy Schubert 				  bcopy(&$3.m, &nat->in_osrc.na_addr[1],
19541edb306SCy Schubert 					sizeof($3.a));
19641edb306SCy Schubert 				  nat->in_nsrcatype = $5.t;
19741edb306SCy Schubert 				  nat->in_nsrcafunc = $5.u;
19841edb306SCy Schubert 				  bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
19941edb306SCy Schubert 					sizeof($5.a));
20041edb306SCy Schubert 				  bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
20141edb306SCy Schubert 					sizeof($5.a));
20241edb306SCy Schubert 
20341edb306SCy Schubert 				  setmapifnames();
20441edb306SCy Schubert 				}
20541edb306SCy Schubert 	| mapit ifnames addr tlate rhsaddr mapport mapoptions
20641edb306SCy Schubert 				{ if ($3.f != $5.f && $3.f != 0 && $5.f != 0)
20741edb306SCy Schubert 					yyerror("4.address family mismatch");
20841edb306SCy Schubert 				  if (nat->in_v[1] == 0 && $5.v != 0)
20941edb306SCy Schubert 					nat->in_v[1] = $5.v;
21041edb306SCy Schubert 				  else if (nat->in_v[0] == 0 && $3.v != 0)
21141edb306SCy Schubert 					nat->in_v[0] = $3.v;
21241edb306SCy Schubert 				  if (nat->in_v[0] == 0 && $5.v != 0)
21341edb306SCy Schubert 					nat->in_v[0] = $5.v;
21441edb306SCy Schubert 				  else if (nat->in_v[1] == 0 && $3.v != 0)
21541edb306SCy Schubert 					nat->in_v[1] = $3.v;
21641edb306SCy Schubert 				  nat->in_osrcatype = $3.t;
21741edb306SCy Schubert 				  bcopy(&$3.a, &nat->in_osrc.na_addr[0],
21841edb306SCy Schubert 					sizeof($3.a));
21941edb306SCy Schubert 				  bcopy(&$3.m, &nat->in_osrc.na_addr[1],
22041edb306SCy Schubert 					sizeof($3.a));
22141edb306SCy Schubert 				  nat->in_nsrcatype = $5.t;
22241edb306SCy Schubert 				  nat->in_nsrcafunc = $5.u;
22341edb306SCy Schubert 				  bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
22441edb306SCy Schubert 					sizeof($5.a));
22541edb306SCy Schubert 				  bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
22641edb306SCy Schubert 					sizeof($5.a));
22741edb306SCy Schubert 
22841edb306SCy Schubert 				  setmapifnames();
22941edb306SCy Schubert 				}
23041edb306SCy Schubert 	| no mapit ifnames addr setproto ';'
23141edb306SCy Schubert 				{ if (nat->in_v[0] == 0)
23241edb306SCy Schubert 					nat->in_v[0] = $4.v;
23341edb306SCy Schubert 				  nat->in_osrcatype = $4.t;
23441edb306SCy Schubert 				  bcopy(&$4.a, &nat->in_osrc.na_addr[0],
23541edb306SCy Schubert 					sizeof($4.a));
23641edb306SCy Schubert 				  bcopy(&$4.m, &nat->in_osrc.na_addr[1],
23741edb306SCy Schubert 					sizeof($4.a));
23841edb306SCy Schubert 
23941edb306SCy Schubert 				  setmapifnames();
24041edb306SCy Schubert 				}
24141edb306SCy Schubert 	| mapit ifnames mapfrom tlate rhsaddr proxy mapoptions
24241edb306SCy Schubert 				{ if ($3 != 0 && $5.f != 0 && $3 != $5.f)
24341edb306SCy Schubert 					yyerror("5.address family mismatch");
24441edb306SCy Schubert 				  if (nat->in_v[0] == 0 && $5.v != 0)
24541edb306SCy Schubert 					nat->in_v[0] = $5.v;
24641edb306SCy Schubert 				  else if (nat->in_v[0] == 0 && $3 != 0)
24741edb306SCy Schubert 					nat->in_v[0] = ftov($3);
24841edb306SCy Schubert 				  if (nat->in_v[1] == 0 && $5.v != 0)
24941edb306SCy Schubert 					nat->in_v[1] = $5.v;
25041edb306SCy Schubert 				  else if (nat->in_v[1] == 0 && $3 != 0)
25141edb306SCy Schubert 					nat->in_v[1] = ftov($3);
25241edb306SCy Schubert 				  nat->in_nsrcatype = $5.t;
25341edb306SCy Schubert 				  nat->in_nsrcafunc = $5.u;
25441edb306SCy Schubert 				  bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
25541edb306SCy Schubert 					sizeof($5.a));
25641edb306SCy Schubert 				  bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
25741edb306SCy Schubert 					sizeof($5.a));
25841edb306SCy Schubert 
25941edb306SCy Schubert 				  setmapifnames();
26041edb306SCy Schubert 				}
26141edb306SCy Schubert 	| no mapit ifnames mapfrom setproto ';'
26241edb306SCy Schubert 				{ nat->in_v[0] = ftov($4);
26341edb306SCy Schubert 				  setmapifnames();
26441edb306SCy Schubert 				}
26541edb306SCy Schubert 	| mapit ifnames mapfrom tlate rhsaddr mapport mapoptions
26641edb306SCy Schubert 				{ if ($3 != 0 && $5.f != 0 && $3 != $5.f)
26741edb306SCy Schubert 					yyerror("6.address family mismatch");
26841edb306SCy Schubert 				  if (nat->in_v[0] == 0 && $5.v != 0)
26941edb306SCy Schubert 					nat->in_v[0] = $5.v;
27041edb306SCy Schubert 				  else if (nat->in_v[0] == 0 && $3 != 0)
27141edb306SCy Schubert 					nat->in_v[0] = ftov($3);
27241edb306SCy Schubert 				  if (nat->in_v[1] == 0 && $5.v != 0)
27341edb306SCy Schubert 					nat->in_v[1] = $5.v;
27441edb306SCy Schubert 				  else if (nat->in_v[1] == 0 && $3 != 0)
27541edb306SCy Schubert 					nat->in_v[1] = ftov($3);
27641edb306SCy Schubert 				  nat->in_nsrcatype = $5.t;
27741edb306SCy Schubert 				  nat->in_nsrcafunc = $5.u;
27841edb306SCy Schubert 				  bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
27941edb306SCy Schubert 					sizeof($5.a));
28041edb306SCy Schubert 				  bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
28141edb306SCy Schubert 					sizeof($5.a));
28241edb306SCy Schubert 
28341edb306SCy Schubert 				  setmapifnames();
28441edb306SCy Schubert 				}
28541edb306SCy Schubert 	;
28641edb306SCy Schubert 
28741edb306SCy Schubert mapblock:
28841edb306SCy Schubert 	mapblockit ifnames addr tlate addr ports mapoptions
28941edb306SCy Schubert 				{ if ($3.f != 0 && $5.f != 0 && $3.f != $5.f)
29041edb306SCy Schubert 					yyerror("7.address family mismatch");
29141edb306SCy Schubert 				  if (nat->in_v[0] == 0 && $5.v != 0)
29241edb306SCy Schubert 					nat->in_v[0] = $5.v;
29341edb306SCy Schubert 				  else if (nat->in_v[0] == 0 && $3.v != 0)
29441edb306SCy Schubert 					nat->in_v[0] = $3.v;
29541edb306SCy Schubert 				  if (nat->in_v[1] == 0 && $5.v != 0)
29641edb306SCy Schubert 					nat->in_v[1] = $5.v;
29741edb306SCy Schubert 				  else if (nat->in_v[1] == 0 && $3.v != 0)
29841edb306SCy Schubert 					nat->in_v[1] = $3.v;
29941edb306SCy Schubert 				  nat->in_osrcatype = $3.t;
30041edb306SCy Schubert 				  bcopy(&$3.a, &nat->in_osrc.na_addr[0],
30141edb306SCy Schubert 					sizeof($3.a));
30241edb306SCy Schubert 				  bcopy(&$3.m, &nat->in_osrc.na_addr[1],
30341edb306SCy Schubert 					sizeof($3.a));
30441edb306SCy Schubert 				  nat->in_nsrcatype = $5.t;
30541edb306SCy Schubert 				  nat->in_nsrcafunc = $5.u;
30641edb306SCy Schubert 				  bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
30741edb306SCy Schubert 					sizeof($5.a));
30841edb306SCy Schubert 				  bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
30941edb306SCy Schubert 					sizeof($5.a));
31041edb306SCy Schubert 
31141edb306SCy Schubert 				  setmapifnames();
31241edb306SCy Schubert 				}
31341edb306SCy Schubert 	| no mapblockit ifnames { yyexpectaddr = 1; } addr setproto ';'
31441edb306SCy Schubert 				{ if (nat->in_v[0] == 0)
31541edb306SCy Schubert 					nat->in_v[0] = $5.v;
31641edb306SCy Schubert 				  if (nat->in_v[1] == 0)
31741edb306SCy Schubert 					nat->in_v[1] = $5.v;
31841edb306SCy Schubert 				  nat->in_osrcatype = $5.t;
31941edb306SCy Schubert 				  bcopy(&$5.a, &nat->in_osrc.na_addr[0],
32041edb306SCy Schubert 					sizeof($5.a));
32141edb306SCy Schubert 				  bcopy(&$5.m, &nat->in_osrc.na_addr[1],
32241edb306SCy Schubert 					sizeof($5.a));
32341edb306SCy Schubert 
32441edb306SCy Schubert 				  setmapifnames();
32541edb306SCy Schubert 				}
32641edb306SCy Schubert 	;
32741edb306SCy Schubert 
32841edb306SCy Schubert redir:	rdrit ifnames addr dport tlate dip nport setproto rdroptions
32941edb306SCy Schubert 				{ if ($6 != 0 && $3.f != 0 && $6 != $3.f)
33041edb306SCy Schubert 					yyerror("21.address family mismatch");
33141edb306SCy Schubert 				  if (nat->in_v[0] == 0) {
33241edb306SCy Schubert 					if ($3.v != AF_UNSPEC)
33341edb306SCy Schubert 						nat->in_v[0] = ftov($3.f);
33441edb306SCy Schubert 					  else
33541edb306SCy Schubert 						nat->in_v[0] = ftov($6);
33641edb306SCy Schubert 				  }
33741edb306SCy Schubert 				  nat->in_odstatype = $3.t;
33841edb306SCy Schubert 				  bcopy(&$3.a, &nat->in_odst.na_addr[0],
33941edb306SCy Schubert 					sizeof($3.a));
34041edb306SCy Schubert 				  bcopy(&$3.m, &nat->in_odst.na_addr[1],
34141edb306SCy Schubert 					sizeof($3.a));
34241edb306SCy Schubert 
34341edb306SCy Schubert 				  setrdrifnames();
34441edb306SCy Schubert 				}
34541edb306SCy Schubert 	| no rdrit ifnames addr dport setproto ';'
34641edb306SCy Schubert 				{ if (nat->in_v[0] == 0)
34741edb306SCy Schubert 					nat->in_v[0] = ftov($4.f);
34841edb306SCy Schubert 				  nat->in_odstatype = $4.t;
34941edb306SCy Schubert 				  bcopy(&$4.a, &nat->in_odst.na_addr[0],
35041edb306SCy Schubert 					sizeof($4.a));
35141edb306SCy Schubert 				  bcopy(&$4.m, &nat->in_odst.na_addr[1],
35241edb306SCy Schubert 					sizeof($4.a));
35341edb306SCy Schubert 
35441edb306SCy Schubert 				  setrdrifnames();
35541edb306SCy Schubert 				}
35641edb306SCy Schubert 	| rdrit ifnames rdrfrom tlate dip nport setproto rdroptions
35741edb306SCy Schubert 				{ if ($5 != 0 && $3 != 0 && $5 != $3)
35841edb306SCy Schubert 					yyerror("20.address family mismatch");
35941edb306SCy Schubert 				  if (nat->in_v[0] == 0) {
36041edb306SCy Schubert 					  if ($3 != AF_UNSPEC)
36141edb306SCy Schubert 						nat->in_v[0] = ftov($3);
36241edb306SCy Schubert 					  else
36341edb306SCy Schubert 						nat->in_v[0] = ftov($5);
36441edb306SCy Schubert 				  }
36541edb306SCy Schubert 				  setrdrifnames();
36641edb306SCy Schubert 				}
36741edb306SCy Schubert 	| no rdrit ifnames rdrfrom setproto ';'
36841edb306SCy Schubert 				{ nat->in_v[0] = ftov($4);
36941edb306SCy Schubert 
37041edb306SCy Schubert 				  setrdrifnames();
37141edb306SCy Schubert 				}
37241edb306SCy Schubert 	;
37341edb306SCy Schubert 
37441edb306SCy Schubert rewrite:
37541edb306SCy Schubert 	IPNY_REWRITE oninout rwrproto mapfrom tlate newdst newopts
37641edb306SCy Schubert 				{ if (nat->in_v[0] == 0)
37741edb306SCy Schubert 					nat->in_v[0] = ftov($4);
37841edb306SCy Schubert 				  if (nat->in_redir & NAT_MAP)
37941edb306SCy Schubert 					setmapifnames();
38041edb306SCy Schubert 				  else
38141edb306SCy Schubert 					setrdrifnames();
38241edb306SCy Schubert 				  nat->in_redir |= NAT_REWRITE;
38341edb306SCy Schubert 				}
38441edb306SCy Schubert 	;
38541edb306SCy Schubert 
38641edb306SCy Schubert divert:	IPNY_DIVERT oninout rwrproto mapfrom tlate divdst newopts
38741edb306SCy Schubert 				{ if (nat->in_v[0] == 0)
38841edb306SCy Schubert 					nat->in_v[0] = ftov($4);
38941edb306SCy Schubert 				  if (nat->in_redir & NAT_MAP) {
39041edb306SCy Schubert 					setmapifnames();
39141edb306SCy Schubert 					nat->in_pr[0] = IPPROTO_UDP;
39241edb306SCy Schubert 				  } else {
39341edb306SCy Schubert 					setrdrifnames();
39441edb306SCy Schubert 					nat->in_pr[1] = IPPROTO_UDP;
39541edb306SCy Schubert 				  }
39641edb306SCy Schubert 				  nat->in_flags &= ~IPN_TCP;
39741edb306SCy Schubert 				}
39841edb306SCy Schubert 	;
39941edb306SCy Schubert 
40041edb306SCy Schubert tlate:	IPNY_TLATE		{ yyexpectaddr = 1; }
40141edb306SCy Schubert 	;
40241edb306SCy Schubert 
40341edb306SCy Schubert pconf:	IPNY_PROXY		{ yysetdict(proxies); }
40441edb306SCy Schubert 	IPNY_DNS '/' proto IPNY_CONFIG YY_STR '{'
40541edb306SCy Schubert 				{ proxy_setconfig(IPNY_DNS); }
40641edb306SCy Schubert 	dnslines ';' '}'
40741edb306SCy Schubert 				{ proxy_addconfig("dns", $5, $7, $10);
40841edb306SCy Schubert 				  proxy_unsetconfig();
40941edb306SCy Schubert 				}
41041edb306SCy Schubert 	;
41141edb306SCy Schubert 
41241edb306SCy Schubert dnslines:
41341edb306SCy Schubert 	dnsline 		{ $$ = $1; }
41441edb306SCy Schubert 	| dnslines ';' dnsline	{ $$ = $1; $1->na_next = $3; }
41541edb306SCy Schubert 	;
41641edb306SCy Schubert 
41741edb306SCy Schubert dnsline:
41841edb306SCy Schubert 	IPNY_ALLOW YY_STR	{ $$ = proxy_dns_add_pass(NULL, $2); }
41941edb306SCy Schubert 	| IPNY_DENY YY_STR	{ $$ = proxy_dns_add_block(NULL, $2); }
42041edb306SCy Schubert 	| IPNY_ALLOW '.' YY_STR	{ $$ = proxy_dns_add_pass(".", $3); }
42141edb306SCy Schubert 	| IPNY_DENY '.' YY_STR	{ $$ = proxy_dns_add_block(".", $3); }
42241edb306SCy Schubert 	;
42341edb306SCy Schubert 
42441edb306SCy Schubert oninout:
42541edb306SCy Schubert 	inout IPNY_ON ifnames	{ ; }
42641edb306SCy Schubert 	;
42741edb306SCy Schubert 
42841edb306SCy Schubert inout:	IPNY_IN			{ nat->in_redir = NAT_REDIRECT; }
42941edb306SCy Schubert 	| IPNY_OUT		{ nat->in_redir = NAT_MAP; }
43041edb306SCy Schubert 	;
43141edb306SCy Schubert 
43241edb306SCy Schubert rwrproto:
43341edb306SCy Schubert 	| IPNY_PROTO setproto
43441edb306SCy Schubert 	;
43541edb306SCy Schubert 
43641edb306SCy Schubert newdst:	src rhsaddr srcports dst erhdaddr dstports
43741edb306SCy Schubert 				{ nat->in_nsrc.na_addr[0] = $2.a;
43841edb306SCy Schubert 				  nat->in_nsrc.na_addr[1] = $2.m;
43941edb306SCy Schubert 				  nat->in_nsrc.na_atype = $2.t;
44041edb306SCy Schubert 				  if ($2.t == FRI_LOOKUP) {
44141edb306SCy Schubert 					nat->in_nsrc.na_type = $2.u;
44241edb306SCy Schubert 					nat->in_nsrc.na_subtype = $2.s;
44341edb306SCy Schubert 					nat->in_nsrc.na_num = $2.n;
44441edb306SCy Schubert 				  }
44541edb306SCy Schubert 				  nat->in_nsports[0] = $3.p1;
44641edb306SCy Schubert 				  nat->in_nsports[1] = $3.p2;
44741edb306SCy Schubert 				  nat->in_ndst.na_addr[0] = $5.a;
44841edb306SCy Schubert 				  nat->in_ndst.na_addr[1] = $5.m;
44941edb306SCy Schubert 				  nat->in_ndst.na_atype = $5.t;
45041edb306SCy Schubert 				  if ($5.t == FRI_LOOKUP) {
45141edb306SCy Schubert 					nat->in_ndst.na_type = $5.u;
45241edb306SCy Schubert 					nat->in_ndst.na_subtype = $5.s;
45341edb306SCy Schubert 					nat->in_ndst.na_num = $5.n;
45441edb306SCy Schubert 				  }
45541edb306SCy Schubert 				  nat->in_ndports[0] = $6.p1;
45641edb306SCy Schubert 				  nat->in_ndports[1] = $6.p2;
45741edb306SCy Schubert 				}
45841edb306SCy Schubert 	;
45941edb306SCy Schubert 
46041edb306SCy Schubert divdst:	src addr ',' portspec dst addr ',' portspec IPNY_UDP
46141edb306SCy Schubert 				{ nat->in_nsrc.na_addr[0] = $2.a;
46241edb306SCy Schubert 				  if ($2.m.in4.s_addr != 0xffffffff)
46341edb306SCy Schubert 					yyerror("divert must have /32 dest");
46441edb306SCy Schubert 				  nat->in_nsrc.na_addr[1] = $2.m;
46541edb306SCy Schubert 				  nat->in_nsports[0] = $4;
46641edb306SCy Schubert 				  nat->in_nsports[1] = $4;
46741edb306SCy Schubert 
46841edb306SCy Schubert 				  nat->in_ndst.na_addr[0] = $6.a;
46941edb306SCy Schubert 				  nat->in_ndst.na_addr[1] = $6.m;
47041edb306SCy Schubert 				  if ($6.m.in4.s_addr != 0xffffffff)
47141edb306SCy Schubert 					yyerror("divert must have /32 dest");
47241edb306SCy Schubert 				  nat->in_ndports[0] = $8;
47341edb306SCy Schubert 				  nat->in_ndports[1] = $8;
47441edb306SCy Schubert 
47541edb306SCy Schubert 				  nat->in_redir |= NAT_DIVERTUDP;
47641edb306SCy Schubert 				}
47741edb306SCy Schubert 	;
47841edb306SCy Schubert 
47941edb306SCy Schubert src:	IPNY_SRC		{ yyexpectaddr = 1; }
48041edb306SCy Schubert 	;
48141edb306SCy Schubert 
48241edb306SCy Schubert dst:	IPNY_DST		{ yyexpectaddr = 1; }
48341edb306SCy Schubert 	;
48441edb306SCy Schubert 
48541edb306SCy Schubert srcports:
48641edb306SCy Schubert 	comaports		{ $$.p1 = $1.p1;
48741edb306SCy Schubert 				  $$.p2 = $1.p2;
48841edb306SCy Schubert 				}
48941edb306SCy Schubert 	| IPNY_PORT '=' portspec
49041edb306SCy Schubert 				{ $$.p1 = $3;
49141edb306SCy Schubert 				  $$.p2 = $3;
49241edb306SCy Schubert 				  nat->in_flags |= IPN_FIXEDSPORT;
49341edb306SCy Schubert 				}
49441edb306SCy Schubert 	;
49541edb306SCy Schubert 
49641edb306SCy Schubert dstports:
49741edb306SCy Schubert 	comaports		{ $$.p1 = $1.p1;
49841edb306SCy Schubert 				  $$.p2 = $1.p2;
49941edb306SCy Schubert 				}
50041edb306SCy Schubert 	| IPNY_PORT '=' portspec
50141edb306SCy Schubert 				{ $$.p1 = $3;
50241edb306SCy Schubert 				  $$.p2 = $3;
50341edb306SCy Schubert 				  nat->in_flags |= IPN_FIXEDDPORT;
50441edb306SCy Schubert 				}
50541edb306SCy Schubert 	;
50641edb306SCy Schubert 
50741edb306SCy Schubert comaports:
50841edb306SCy Schubert 				{ $$.p1 = 0;
50941edb306SCy Schubert 				  $$.p2 = 0;
51041edb306SCy Schubert 				}
51141edb306SCy Schubert 	| ','			{ if (!(nat->in_flags & IPN_TCPUDP))
51241edb306SCy Schubert 					yyerror("must be TCP/UDP for ports");
51341edb306SCy Schubert 				}
51441edb306SCy Schubert 	portpair		{ $$.p1 = $3.p1;
51541edb306SCy Schubert 				  $$.p2 = $3.p2;
51641edb306SCy Schubert 				}
51741edb306SCy Schubert 	;
51841edb306SCy Schubert 
51941edb306SCy Schubert proxy:	| IPNY_PROXY port portspec YY_STR '/' proto
52041edb306SCy Schubert 			{ int pos;
52141edb306SCy Schubert 			  pos = addname(&nat, $4);
52241edb306SCy Schubert 			  nat->in_plabel = pos;
52341edb306SCy Schubert 			  if (nat->in_dcmp == 0) {
52441edb306SCy Schubert 				nat->in_odport = $3;
52541edb306SCy Schubert 			  } else if ($3 != nat->in_odport) {
52641edb306SCy Schubert 				yyerror("proxy port numbers not consistant");
52741edb306SCy Schubert 			  }
52841edb306SCy Schubert 			  nat->in_ndport = $3;
52941edb306SCy Schubert 			  setnatproto($6);
53041edb306SCy Schubert 			  free($4);
53141edb306SCy Schubert 			}
53241edb306SCy Schubert 	| IPNY_PROXY port YY_STR YY_STR '/' proto
53341edb306SCy Schubert 			{ int pnum, pos;
53441edb306SCy Schubert 			  pos = addname(&nat, $4);
53541edb306SCy Schubert 			  nat->in_plabel = pos;
53641edb306SCy Schubert 			  pnum = getportproto($3, $6);
53741edb306SCy Schubert 			  if (pnum == -1)
53841edb306SCy Schubert 				yyerror("invalid port number");
53941edb306SCy Schubert 			  nat->in_odport = ntohs(pnum);
54041edb306SCy Schubert 			  nat->in_ndport = ntohs(pnum);
54141edb306SCy Schubert 			  setnatproto($6);
54241edb306SCy Schubert 			  free($3);
54341edb306SCy Schubert 			  free($4);
54441edb306SCy Schubert 			}
54541edb306SCy Schubert 	| IPNY_PROXY port portspec YY_STR '/' proto IPNY_CONFIG YY_STR
54641edb306SCy Schubert 			{ int pos;
54741edb306SCy Schubert 			  pos = addname(&nat, $4);
54841edb306SCy Schubert 			  nat->in_plabel = pos;
54941edb306SCy Schubert 			  if (nat->in_dcmp == 0) {
55041edb306SCy Schubert 				nat->in_odport = $3;
55141edb306SCy Schubert 			  } else if ($3 != nat->in_odport) {
55241edb306SCy Schubert 				yyerror("proxy port numbers not consistant");
55341edb306SCy Schubert 			  }
55441edb306SCy Schubert 			  nat->in_ndport = $3;
55541edb306SCy Schubert 			  setnatproto($6);
55641edb306SCy Schubert 			  nat->in_pconfig = addname(&nat, $8);
55741edb306SCy Schubert 			  free($4);
55841edb306SCy Schubert 			  free($8);
55941edb306SCy Schubert 			}
56041edb306SCy Schubert 	| IPNY_PROXY port YY_STR YY_STR '/' proto IPNY_CONFIG YY_STR
56141edb306SCy Schubert 			{ int pnum, pos;
56241edb306SCy Schubert 			  pos = addname(&nat, $4);
56341edb306SCy Schubert 			  nat->in_plabel = pos;
56441edb306SCy Schubert 			  pnum = getportproto($3, $6);
56541edb306SCy Schubert 			  if (pnum == -1)
56641edb306SCy Schubert 				yyerror("invalid port number");
56741edb306SCy Schubert 			  nat->in_odport = ntohs(pnum);
56841edb306SCy Schubert 			  nat->in_ndport = ntohs(pnum);
56941edb306SCy Schubert 			  setnatproto($6);
57041edb306SCy Schubert 			  pos = addname(&nat, $8);
57141edb306SCy Schubert 			  nat->in_pconfig = pos;
57241edb306SCy Schubert 			  free($3);
57341edb306SCy Schubert 			  free($4);
57441edb306SCy Schubert 			  free($8);
57541edb306SCy Schubert 			}
57641edb306SCy Schubert 	;
57741edb306SCy Schubert setproto:
57841edb306SCy Schubert 	| proto				{ if (nat->in_pr[0] != 0 ||
57941edb306SCy Schubert 					      nat->in_pr[1] != 0 ||
58041edb306SCy Schubert 					      nat->in_flags & IPN_TCPUDP)
58141edb306SCy Schubert 						yyerror("protocol set twice");
58241edb306SCy Schubert 					  setnatproto($1);
58341edb306SCy Schubert 					}
58441edb306SCy Schubert 	| IPNY_TCPUDP			{ if (nat->in_pr[0] != 0 ||
58541edb306SCy Schubert 					      nat->in_pr[1] != 0 ||
58641edb306SCy Schubert 					      nat->in_flags & IPN_TCPUDP)
58741edb306SCy Schubert 						yyerror("protocol set twice");
58841edb306SCy Schubert 					  nat->in_flags |= IPN_TCPUDP;
58941edb306SCy Schubert 					  nat->in_pr[0] = 0;
59041edb306SCy Schubert 					  nat->in_pr[1] = 0;
59141edb306SCy Schubert 					}
59241edb306SCy Schubert 	| IPNY_TCP '/' IPNY_UDP		{ if (nat->in_pr[0] != 0 ||
59341edb306SCy Schubert 					      nat->in_pr[1] != 0 ||
59441edb306SCy Schubert 					      nat->in_flags & IPN_TCPUDP)
59541edb306SCy Schubert 						yyerror("protocol set twice");
59641edb306SCy Schubert 					  nat->in_flags |= IPN_TCPUDP;
59741edb306SCy Schubert 					  nat->in_pr[0] = 0;
59841edb306SCy Schubert 					  nat->in_pr[1] = 0;
59941edb306SCy Schubert 					}
60041edb306SCy Schubert 	;
60141edb306SCy Schubert 
60241edb306SCy Schubert rhsaddr:
60341edb306SCy Schubert 	addr				{ $$ = $1;
60441edb306SCy Schubert 					  yyexpectaddr = 0;
60541edb306SCy Schubert 					}
60641edb306SCy Schubert 	| hostname '-' { yyexpectaddr = 1; } hostname
60741edb306SCy Schubert 					{ $$.t = FRI_RANGE;
60841edb306SCy Schubert 					  if ($1.f != $4.f)
60941edb306SCy Schubert 						yyerror("8.address family "
61041edb306SCy Schubert 							"mismatch");
61141edb306SCy Schubert 					  $$.f = $1.f;
61241edb306SCy Schubert 					  $$.v = ftov($1.f);
61341edb306SCy Schubert 					  $$.a = $1.a;
61441edb306SCy Schubert 					  $$.m = $4.a;
61541edb306SCy Schubert 					  nat->in_flags |= IPN_SIPRANGE;
61641edb306SCy Schubert 					  yyexpectaddr = 0;
61741edb306SCy Schubert 					}
61841edb306SCy Schubert 	| IPNY_RANGE hostname '-' { yyexpectaddr = 1; } hostname
61941edb306SCy Schubert 					{ $$.t = FRI_RANGE;
62041edb306SCy Schubert 					  if ($2.f != $5.f)
62141edb306SCy Schubert 						yyerror("9.address family "
62241edb306SCy Schubert 							"mismatch");
62341edb306SCy Schubert 					  $$.f = $2.f;
62441edb306SCy Schubert 					  $$.v = ftov($2.f);
62541edb306SCy Schubert 					  $$.a = $2.a;
62641edb306SCy Schubert 					  $$.m = $5.a;
62741edb306SCy Schubert 					  nat->in_flags |= IPN_SIPRANGE;
62841edb306SCy Schubert 					  yyexpectaddr = 0;
62941edb306SCy Schubert 					}
63041edb306SCy Schubert 	;
63141edb306SCy Schubert 
63241edb306SCy Schubert dip:
63341edb306SCy Schubert 	hostname ',' { yyexpectaddr = 1; } hostname
63441edb306SCy Schubert 				{ nat->in_flags |= IPN_SPLIT;
63541edb306SCy Schubert 				  if ($1.f != $4.f)
63641edb306SCy Schubert 					yyerror("10.address family "
63741edb306SCy Schubert 						"mismatch");
63841edb306SCy Schubert 				  $$ = $1.f;
63941edb306SCy Schubert 				  nat->in_ndstip6 = $1.a;
64041edb306SCy Schubert 				  nat->in_ndstmsk6 = $4.a;
64141edb306SCy Schubert 				  nat->in_ndstatype = FRI_SPLIT;
64241edb306SCy Schubert 				  yyexpectaddr = 0;
64341edb306SCy Schubert 				}
64441edb306SCy Schubert 	| rhdaddr		{ int bits;
64541edb306SCy Schubert 				  nat->in_ndstip6 = $1.a;
64641edb306SCy Schubert 				  nat->in_ndstmsk6 = $1.m;
64741edb306SCy Schubert 				  nat->in_ndst.na_atype = $1.t;
64841edb306SCy Schubert 				  yyexpectaddr = 0;
64941edb306SCy Schubert 				  if ($1.f == AF_INET)
65041edb306SCy Schubert 					bits = count4bits($1.m.in4.s_addr);
65141edb306SCy Schubert 				  else
65241edb306SCy Schubert 					bits = count6bits($1.m.i6);
65341edb306SCy Schubert 				  if (($1.f == AF_INET) && (bits != 0) &&
65441edb306SCy Schubert 				      (bits != 32)) {
65541edb306SCy Schubert 					yyerror("dest ip bitmask not /32");
65641edb306SCy Schubert 				  } else if (($1.f == AF_INET6) &&
65741edb306SCy Schubert 					     (bits != 0) && (bits != 128)) {
65841edb306SCy Schubert 					yyerror("dest ip bitmask not /128");
65941edb306SCy Schubert 				  }
66041edb306SCy Schubert 				  $$ = $1.f;
66141edb306SCy Schubert 				}
66241edb306SCy Schubert 	;
66341edb306SCy Schubert 
66441edb306SCy Schubert rhdaddr:
66541edb306SCy Schubert 	addr				{ $$ = $1;
66641edb306SCy Schubert 					  yyexpectaddr = 0;
66741edb306SCy Schubert 					}
66841edb306SCy Schubert 	| hostname '-' hostname		{ bzero(&$$, sizeof($$));
66941edb306SCy Schubert 					  $$.t = FRI_RANGE;
67041edb306SCy Schubert 					  if ($1.f != 0 && $3.f != 0 &&
67141edb306SCy Schubert 					      $1.f != $3.f)
67241edb306SCy Schubert 						yyerror("11.address family "
67341edb306SCy Schubert 							"mismatch");
67441edb306SCy Schubert 					  $$.a = $1.a;
67541edb306SCy Schubert 					  $$.m = $3.a;
67641edb306SCy Schubert 					  nat->in_flags |= IPN_DIPRANGE;
67741edb306SCy Schubert 					  yyexpectaddr = 0;
67841edb306SCy Schubert 					}
67941edb306SCy Schubert 	| IPNY_RANGE hostname '-' hostname
68041edb306SCy Schubert 					{ bzero(&$$, sizeof($$));
68141edb306SCy Schubert 					  $$.t = FRI_RANGE;
68241edb306SCy Schubert 					  if ($2.f != 0 && $4.f != 0 &&
68341edb306SCy Schubert 					      $2.f != $4.f)
68441edb306SCy Schubert 						yyerror("12.address family "
68541edb306SCy Schubert 							"mismatch");
68641edb306SCy Schubert 					  $$.a = $2.a;
68741edb306SCy Schubert 					  $$.m = $4.a;
68841edb306SCy Schubert 					  nat->in_flags |= IPN_DIPRANGE;
68941edb306SCy Schubert 					  yyexpectaddr = 0;
69041edb306SCy Schubert 					}
69141edb306SCy Schubert 	;
69241edb306SCy Schubert 
69341edb306SCy Schubert erhdaddr:
69441edb306SCy Schubert 	rhdaddr				{ $$ = $1; }
69541edb306SCy Schubert 	| IPNY_DSTLIST '/' YY_NUMBER	{ $$.t = FRI_LOOKUP;
69641edb306SCy Schubert 					  $$.u = IPLT_DSTLIST;
69741edb306SCy Schubert 					  $$.s = 0;
69841edb306SCy Schubert 					  $$.n = $3;
69941edb306SCy Schubert 					}
70041edb306SCy Schubert 	| IPNY_DSTLIST '/' YY_STR	{ $$.t = FRI_LOOKUP;
70141edb306SCy Schubert 					  $$.u = IPLT_DSTLIST;
70241edb306SCy Schubert 					  $$.s = 1;
70341edb306SCy Schubert 					  $$.n = addname(&nat, $3);
70441edb306SCy Schubert 					}
70541edb306SCy Schubert 	;
70641edb306SCy Schubert 
70741edb306SCy Schubert port:	IPNY_PORT			{ suggest_port = 1; }
70841edb306SCy Schubert 	;
70941edb306SCy Schubert 
71041edb306SCy Schubert portspec:
71141edb306SCy Schubert 	YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
71241edb306SCy Schubert 						yyerror("invalid port number");
71341edb306SCy Schubert 					  else
71441edb306SCy Schubert 						$$ = $1;
71541edb306SCy Schubert 					}
71641edb306SCy Schubert 	| YY_STR			{ if (getport(NULL, $1,
71741edb306SCy Schubert 						      &($$), NULL) == -1)
71841edb306SCy Schubert 						yyerror("invalid port number");
71941edb306SCy Schubert 					  $$ = ntohs($$);
72041edb306SCy Schubert 					}
72141edb306SCy Schubert 	;
72241edb306SCy Schubert 
72341edb306SCy Schubert portpair:
72441edb306SCy Schubert 	portspec			{ $$.p1 = $1; $$.p2 = $1; }
72541edb306SCy Schubert 	| portspec '-' portspec		{ $$.p1 = $1; $$.p2 = $3; }
72641edb306SCy Schubert 	| portspec ':' portspec		{ $$.p1 = $1; $$.p2 = $3; }
72741edb306SCy Schubert 	;
72841edb306SCy Schubert 
72941edb306SCy Schubert dport:	| port portpair			{ nat->in_odport = $2.p1;
73041edb306SCy Schubert 					  if ($2.p2 == 0)
73141edb306SCy Schubert 						nat->in_dtop = $2.p1;
73241edb306SCy Schubert 					  else
73341edb306SCy Schubert 						nat->in_dtop = $2.p2;
73441edb306SCy Schubert 					}
73541edb306SCy Schubert 	;
73641edb306SCy Schubert 
73741edb306SCy Schubert nport:	| port portpair			{ nat->in_dpmin = $2.p1;
73841edb306SCy Schubert 					  nat->in_dpnext = $2.p1;
73941edb306SCy Schubert 					  nat->in_dpmax = $2.p2;
74041edb306SCy Schubert 					  nat->in_ndport = $2.p1;
74141edb306SCy Schubert 					  if (nat->in_dtop == 0)
74241edb306SCy Schubert 						nat->in_dtop = $2.p2;
74341edb306SCy Schubert 					}
74441edb306SCy Schubert 	| port '=' portspec		{ nat->in_dpmin = $3;
74541edb306SCy Schubert 					  nat->in_dpnext = $3;
74641edb306SCy Schubert 					  nat->in_ndport = $3;
74741edb306SCy Schubert 					  if (nat->in_dtop == 0)
74841edb306SCy Schubert 						nat->in_dtop = nat->in_odport;
74941edb306SCy Schubert 					  nat->in_flags |= IPN_FIXEDDPORT;
75041edb306SCy Schubert 					}
75141edb306SCy Schubert 	;
75241edb306SCy Schubert 
75341edb306SCy Schubert ports:	| IPNY_PORTS YY_NUMBER		{ nat->in_spmin = $2; }
75441edb306SCy Schubert 	| IPNY_PORTS IPNY_AUTO		{ nat->in_flags |= IPN_AUTOPORTMAP; }
75541edb306SCy Schubert 	;
75641edb306SCy Schubert 
75741edb306SCy Schubert mapit:	IPNY_MAP			{ nat->in_redir = NAT_MAP; }
75841edb306SCy Schubert 	| IPNY_BIMAP			{ nat->in_redir = NAT_BIMAP; }
75941edb306SCy Schubert 	;
76041edb306SCy Schubert 
76141edb306SCy Schubert rdrit:	IPNY_RDR			{ nat->in_redir = NAT_REDIRECT; }
76241edb306SCy Schubert 	;
76341edb306SCy Schubert 
76441edb306SCy Schubert mapblockit:
76541edb306SCy Schubert 	IPNY_MAPBLOCK			{ nat->in_redir = NAT_MAPBLK; }
76641edb306SCy Schubert 	;
76741edb306SCy Schubert 
76841edb306SCy Schubert mapfrom:
76941edb306SCy Schubert 	from sobject to dobject		{ if ($2 != 0 && $4 != 0 && $2 != $4)
77041edb306SCy Schubert 						yyerror("13.address family "
77141edb306SCy Schubert 							"mismatch");
77241edb306SCy Schubert 					  $$ = $2;
77341edb306SCy Schubert 					}
77441edb306SCy Schubert 	| from sobject '!' to dobject
77541edb306SCy Schubert 					{ if ($2 != 0 && $5 != 0 && $2 != $5)
77641edb306SCy Schubert 						yyerror("14.address family "
77741edb306SCy Schubert 							"mismatch");
77841edb306SCy Schubert 					  nat->in_flags |= IPN_NOTDST;
77941edb306SCy Schubert 					  $$ = $2;
78041edb306SCy Schubert 					}
78141edb306SCy Schubert 	| from sobject to '!' dobject
78241edb306SCy Schubert 					{ if ($2 != 0 && $5 != 0 && $2 != $5)
78341edb306SCy Schubert 						yyerror("15.address family "
78441edb306SCy Schubert 							"mismatch");
78541edb306SCy Schubert 					  nat->in_flags |= IPN_NOTDST;
78641edb306SCy Schubert 					  $$ = $2;
78741edb306SCy Schubert 					}
78841edb306SCy Schubert 	;
78941edb306SCy Schubert 
79041edb306SCy Schubert rdrfrom:
79141edb306SCy Schubert 	from sobject to dobject		{ if ($2 != 0 && $4 != 0 && $2 != $4)
79241edb306SCy Schubert 						yyerror("16.address family "
79341edb306SCy Schubert 							"mismatch");
79441edb306SCy Schubert 					  $$ = $2;
79541edb306SCy Schubert 					}
79641edb306SCy Schubert 	| '!' from sobject to dobject
79741edb306SCy Schubert 					{ if ($3 != 0 && $5 != 0 && $3 != $5)
79841edb306SCy Schubert 						yyerror("17.address family "
79941edb306SCy Schubert 							"mismatch");
80041edb306SCy Schubert 					  nat->in_flags |= IPN_NOTSRC;
80141edb306SCy Schubert 					  $$ = $3;
80241edb306SCy Schubert 					}
80341edb306SCy Schubert 	| from '!' sobject to dobject
80441edb306SCy Schubert 					{ if ($3 != 0 && $5 != 0 && $3 != $5)
80541edb306SCy Schubert 						yyerror("18.address family "
80641edb306SCy Schubert 							"mismatch");
80741edb306SCy Schubert 					  nat->in_flags |= IPN_NOTSRC;
80841edb306SCy Schubert 					  $$ = $3;
80941edb306SCy Schubert 					}
81041edb306SCy Schubert 	;
81141edb306SCy Schubert 
81241edb306SCy Schubert from:	IPNY_FROM			{ nat->in_flags |= IPN_FILTER;
81341edb306SCy Schubert 					  yyexpectaddr = 1;
81441edb306SCy Schubert 					}
81541edb306SCy Schubert 	;
81641edb306SCy Schubert 
81741edb306SCy Schubert to:	IPNY_TO				{ yyexpectaddr = 1; }
81841edb306SCy Schubert 	;
81941edb306SCy Schubert 
82041edb306SCy Schubert ifnames:
82141edb306SCy Schubert 	ifname family			{ yyexpectaddr = 1; }
82241edb306SCy Schubert 	| ifname ',' otherifname family	{ yyexpectaddr = 1; }
82341edb306SCy Schubert 	;
82441edb306SCy Schubert 
82541edb306SCy Schubert ifname:	YY_STR				{ setifname(&nat, 0, $1);
82641edb306SCy Schubert 					  free($1);
82741edb306SCy Schubert 					}
82841edb306SCy Schubert 	;
82941edb306SCy Schubert 
83041edb306SCy Schubert family:	| IPNY_INET			{ nat->in_v[0] = 4; nat->in_v[1] = 4; }
83141edb306SCy Schubert 	| IPNY_INET6			{ nat->in_v[0] = 6; nat->in_v[1] = 6; }
83241edb306SCy Schubert 	;
83341edb306SCy Schubert 
83441edb306SCy Schubert otherifname:
83541edb306SCy Schubert 	YY_STR				{ setifname(&nat, 1, $1);
83641edb306SCy Schubert 					  free($1);
83741edb306SCy Schubert 					}
83841edb306SCy Schubert 	;
83941edb306SCy Schubert 
84041edb306SCy Schubert mapport:
84141edb306SCy Schubert 	IPNY_PORTMAP tcpudp portpair sequential
84241edb306SCy Schubert 					{ nat->in_spmin = $3.p1;
84341edb306SCy Schubert 					  nat->in_spmax = $3.p2;
84441edb306SCy Schubert 					}
84541edb306SCy Schubert 	| IPNY_PORTMAP portpair tcpudp sequential
84641edb306SCy Schubert 					{ nat->in_spmin = $2.p1;
84741edb306SCy Schubert 					  nat->in_spmax = $2.p2;
84841edb306SCy Schubert 					}
84941edb306SCy Schubert 	| IPNY_PORTMAP tcpudp IPNY_AUTO sequential
85041edb306SCy Schubert 					{ nat->in_flags |= IPN_AUTOPORTMAP;
85141edb306SCy Schubert 					  nat->in_spmin = 1024;
85241edb306SCy Schubert 					  nat->in_spmax = 65535;
85341edb306SCy Schubert 					}
85441edb306SCy Schubert 	| IPNY_ICMPIDMAP YY_STR portpair sequential
85541edb306SCy Schubert 			{ if (strcmp($2, "icmp") != 0 &&
85641edb306SCy Schubert 			      strcmp($2, "ipv6-icmp") != 0) {
85741edb306SCy Schubert 				yyerror("icmpidmap not followed by icmp");
85841edb306SCy Schubert 			  }
85941edb306SCy Schubert 			  free($2);
86041edb306SCy Schubert 			  if ($3.p1 < 0 || $3.p1 > 65535)
86141edb306SCy Schubert 				yyerror("invalid 1st ICMP Id number");
86241edb306SCy Schubert 			  if ($3.p2 < 0 || $3.p2 > 65535)
86341edb306SCy Schubert 				yyerror("invalid 2nd ICMP Id number");
86441edb306SCy Schubert 			  if (strcmp($2, "ipv6-icmp") == 0) {
86541edb306SCy Schubert 				nat->in_pr[0] = IPPROTO_ICMPV6;
86641edb306SCy Schubert 				nat->in_pr[1] = IPPROTO_ICMPV6;
86741edb306SCy Schubert 			  } else {
86841edb306SCy Schubert 				nat->in_pr[0] = IPPROTO_ICMP;
86941edb306SCy Schubert 				nat->in_pr[1] = IPPROTO_ICMP;
87041edb306SCy Schubert 			  }
87141edb306SCy Schubert 			  nat->in_flags = IPN_ICMPQUERY;
87241edb306SCy Schubert 			  nat->in_spmin = $3.p1;
87341edb306SCy Schubert 			  nat->in_spmax = $3.p2;
87441edb306SCy Schubert 			}
87541edb306SCy Schubert 	;
87641edb306SCy Schubert 
87741edb306SCy Schubert sobject:
87841edb306SCy Schubert 	saddr				{ $$ = $1; }
87941edb306SCy Schubert 	| saddr port portstuff		{ nat->in_osport = $3.p1;
88041edb306SCy Schubert 					  nat->in_stop = $3.p2;
88141edb306SCy Schubert 					  nat->in_scmp = $3.pc;
88241edb306SCy Schubert 					  $$ = $1;
88341edb306SCy Schubert 					}
88441edb306SCy Schubert 	;
88541edb306SCy Schubert 
88641edb306SCy Schubert saddr:	addr				{ nat->in_osrcatype = $1.t;
88741edb306SCy Schubert 					  bcopy(&$1.a,
88841edb306SCy Schubert 						&nat->in_osrc.na_addr[0],
88941edb306SCy Schubert 						sizeof($1.a));
89041edb306SCy Schubert 					  bcopy(&$1.m,
89141edb306SCy Schubert 						&nat->in_osrc.na_addr[1],
89241edb306SCy Schubert 						sizeof($1.m));
89341edb306SCy Schubert 					  $$ = $1.f;
89441edb306SCy Schubert 					}
89541edb306SCy Schubert 	;
89641edb306SCy Schubert 
89741edb306SCy Schubert dobject:
89841edb306SCy Schubert 	daddr				{ $$ = $1; }
89941edb306SCy Schubert 	| daddr port portstuff		{ nat->in_odport = $3.p1;
90041edb306SCy Schubert 					  nat->in_dtop = $3.p2;
90141edb306SCy Schubert 					  nat->in_dcmp = $3.pc;
90241edb306SCy Schubert 					  $$ = $1;
90341edb306SCy Schubert 					}
90441edb306SCy Schubert 	;
90541edb306SCy Schubert 
90641edb306SCy Schubert daddr:	addr				{ nat->in_odstatype = $1.t;
90741edb306SCy Schubert 					  bcopy(&$1.a,
90841edb306SCy Schubert 						&nat->in_odst.na_addr[0],
90941edb306SCy Schubert 						sizeof($1.a));
91041edb306SCy Schubert 					  bcopy(&$1.m,
91141edb306SCy Schubert 						&nat->in_odst.na_addr[1],
91241edb306SCy Schubert 						sizeof($1.m));
91341edb306SCy Schubert 					  $$ = $1.f;
91441edb306SCy Schubert 					}
91541edb306SCy Schubert 	;
91641edb306SCy Schubert 
91741edb306SCy Schubert addr:	IPNY_ANY			{ yyexpectaddr = 0;
91841edb306SCy Schubert 					  bzero(&$$, sizeof($$));
91941edb306SCy Schubert 					  $$.t = FRI_NORMAL;
92041edb306SCy Schubert 					}
92141edb306SCy Schubert 	| hostname			{ bzero(&$$, sizeof($$));
92241edb306SCy Schubert 					  $$.a = $1.a;
92341edb306SCy Schubert 					  $$.t = FRI_NORMAL;
92441edb306SCy Schubert 					  $$.v = ftov($1.f);
92541edb306SCy Schubert 					  $$.f = $1.f;
92641edb306SCy Schubert 					  if ($$.f == AF_INET) {
92741edb306SCy Schubert 						  $$.m.in4.s_addr = 0xffffffff;
92841edb306SCy Schubert 					  } else if ($$.f == AF_INET6) {
92941edb306SCy Schubert 						  $$.m.i6[0] = 0xffffffff;
93041edb306SCy Schubert 						  $$.m.i6[1] = 0xffffffff;
93141edb306SCy Schubert 						  $$.m.i6[2] = 0xffffffff;
93241edb306SCy Schubert 						  $$.m.i6[3] = 0xffffffff;
93341edb306SCy Schubert 					  }
93441edb306SCy Schubert 					  yyexpectaddr = 0;
93541edb306SCy Schubert 					}
93641edb306SCy Schubert 	| hostname slash YY_NUMBER
93741edb306SCy Schubert 					{ bzero(&$$, sizeof($$));
93841edb306SCy Schubert 					  $$.a = $1.a;
93941edb306SCy Schubert 					  $$.f = $1.f;
94041edb306SCy Schubert 					  $$.v = ftov($1.f);
94141edb306SCy Schubert 					  $$.t = FRI_NORMAL;
94241edb306SCy Schubert 					  ntomask($$.f, $3, (u_32_t *)&$$.m);
94341edb306SCy Schubert 					  $$.a.i6[0] &= $$.m.i6[0];
94441edb306SCy Schubert 					  $$.a.i6[1] &= $$.m.i6[1];
94541edb306SCy Schubert 					  $$.a.i6[2] &= $$.m.i6[2];
94641edb306SCy Schubert 					  $$.a.i6[3] &= $$.m.i6[3];
94741edb306SCy Schubert 					  yyexpectaddr = 0;
94841edb306SCy Schubert 					}
94941edb306SCy Schubert 	| hostname slash ipaddr		{ bzero(&$$, sizeof($$));
95041edb306SCy Schubert 					  if ($1.f != $3.f) {
95141edb306SCy Schubert 						yyerror("1.address family "
95241edb306SCy Schubert 							"mismatch");
95341edb306SCy Schubert 					  }
95441edb306SCy Schubert 					  $$.a = $1.a;
95541edb306SCy Schubert 					  $$.m = $3.a;
95641edb306SCy Schubert 					  $$.t = FRI_NORMAL;
95741edb306SCy Schubert 					  $$.a.i6[0] &= $$.m.i6[0];
95841edb306SCy Schubert 					  $$.a.i6[1] &= $$.m.i6[1];
95941edb306SCy Schubert 					  $$.a.i6[2] &= $$.m.i6[2];
96041edb306SCy Schubert 					  $$.a.i6[3] &= $$.m.i6[3];
96141edb306SCy Schubert 					  $$.f = $1.f;
96241edb306SCy Schubert 					  $$.v = ftov($1.f);
96341edb306SCy Schubert 					  yyexpectaddr = 0;
96441edb306SCy Schubert 					}
96541edb306SCy Schubert 	| hostname slash hexnumber	{ bzero(&$$, sizeof($$));
96641edb306SCy Schubert 					  $$.a = $1.a;
96741edb306SCy Schubert 					  $$.m.in4.s_addr = htonl($3);
96841edb306SCy Schubert 					  $$.t = FRI_NORMAL;
96941edb306SCy Schubert 					  $$.a.in4.s_addr &= $$.m.in4.s_addr;
97041edb306SCy Schubert 					  $$.f = $1.f;
97141edb306SCy Schubert 					  $$.v = ftov($1.f);
97241edb306SCy Schubert 					  if ($$.f == AF_INET6)
97341edb306SCy Schubert 						yyerror("incorrect inet6 mask");
97441edb306SCy Schubert 					}
97541edb306SCy Schubert 	| hostname mask ipaddr		{ bzero(&$$, sizeof($$));
97641edb306SCy Schubert 					  if ($1.f != $3.f) {
97741edb306SCy Schubert 						yyerror("2.address family "
97841edb306SCy Schubert 							"mismatch");
97941edb306SCy Schubert 					  }
98041edb306SCy Schubert 					  $$.a = $1.a;
98141edb306SCy Schubert 					  $$.m = $3.a;
98241edb306SCy Schubert 					  $$.t = FRI_NORMAL;
98341edb306SCy Schubert 					  $$.a.i6[0] &= $$.m.i6[0];
98441edb306SCy Schubert 					  $$.a.i6[1] &= $$.m.i6[1];
98541edb306SCy Schubert 					  $$.a.i6[2] &= $$.m.i6[2];
98641edb306SCy Schubert 					  $$.a.i6[3] &= $$.m.i6[3];
98741edb306SCy Schubert 					  $$.f = $1.f;
98841edb306SCy Schubert 					  $$.v = ftov($1.f);
98941edb306SCy Schubert 					  yyexpectaddr = 0;
99041edb306SCy Schubert 					}
99141edb306SCy Schubert 	| hostname mask hexnumber	{ bzero(&$$, sizeof($$));
99241edb306SCy Schubert 					  $$.a = $1.a;
99341edb306SCy Schubert 					  $$.m.in4.s_addr = htonl($3);
99441edb306SCy Schubert 					  $$.t = FRI_NORMAL;
99541edb306SCy Schubert 					  $$.a.in4.s_addr &= $$.m.in4.s_addr;
99641edb306SCy Schubert 					  $$.f = AF_INET;
99741edb306SCy Schubert 					  $$.v = 4;
99841edb306SCy Schubert 					}
99941edb306SCy Schubert 	| pool slash YY_NUMBER		{ bzero(&$$, sizeof($$));
100041edb306SCy Schubert 					  $$.a.iplookupnum = $3;
100141edb306SCy Schubert 					  $$.a.iplookuptype = IPLT_POOL;
100241edb306SCy Schubert 					  $$.a.iplookupsubtype = 0;
100341edb306SCy Schubert 					  $$.t = FRI_LOOKUP;
100441edb306SCy Schubert 					}
100541edb306SCy Schubert 	| pool slash YY_STR		{ bzero(&$$, sizeof($$));
100641edb306SCy Schubert 					  $$.a.iplookupname = addname(&nat,$3);
100741edb306SCy Schubert 					  $$.a.iplookuptype = IPLT_POOL;
100841edb306SCy Schubert 					  $$.a.iplookupsubtype = 1;
100941edb306SCy Schubert 					  $$.t = FRI_LOOKUP;
101041edb306SCy Schubert 					}
101141edb306SCy Schubert 	| hash slash YY_NUMBER		{ bzero(&$$, sizeof($$));
101241edb306SCy Schubert 					  $$.a.iplookupnum = $3;
101341edb306SCy Schubert 					  $$.a.iplookuptype = IPLT_HASH;
101441edb306SCy Schubert 					  $$.a.iplookupsubtype = 0;
101541edb306SCy Schubert 					  $$.t = FRI_LOOKUP;
101641edb306SCy Schubert 					}
101741edb306SCy Schubert 	| hash slash YY_STR		{ bzero(&$$, sizeof($$));
101841edb306SCy Schubert 					  $$.a.iplookupname = addname(&nat,$3);
101941edb306SCy Schubert 					  $$.a.iplookuptype = IPLT_HASH;
102041edb306SCy Schubert 					  $$.a.iplookupsubtype = 1;
102141edb306SCy Schubert 					  $$.t = FRI_LOOKUP;
102241edb306SCy Schubert 					}
102341edb306SCy Schubert 	;
102441edb306SCy Schubert 
102541edb306SCy Schubert slash:	'/'				{ yyexpectaddr = 0; }
102641edb306SCy Schubert 	;
102741edb306SCy Schubert 
102841edb306SCy Schubert mask:	IPNY_MASK			{ yyexpectaddr = 0; }
102941edb306SCy Schubert 	;
103041edb306SCy Schubert 
103141edb306SCy Schubert pool:	IPNY_POOL			{ if (!(nat->in_flags & IPN_FILTER)) {
103241edb306SCy Schubert 						yyerror("Can only use pool with from/to rules\n");
103341edb306SCy Schubert 					  }
103441edb306SCy Schubert 					  yyexpectaddr = 0;
103541edb306SCy Schubert 					  yyresetdict();
103641edb306SCy Schubert 					}
103741edb306SCy Schubert 	;
103841edb306SCy Schubert 
103941edb306SCy Schubert hash:	IPNY_HASH			{ if (!(nat->in_flags & IPN_FILTER)) {
104041edb306SCy Schubert 						yyerror("Can only use hash with from/to rules\n");
104141edb306SCy Schubert 					  }
104241edb306SCy Schubert 					  yyexpectaddr = 0;
104341edb306SCy Schubert 					  yyresetdict();
104441edb306SCy Schubert 					}
104541edb306SCy Schubert 	;
104641edb306SCy Schubert 
104741edb306SCy Schubert portstuff:
104841edb306SCy Schubert 	compare portspec		{ $$.pc = $1; $$.p1 = $2; $$.p2 = 0; }
104941edb306SCy Schubert 	| portspec range portspec	{ $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
105041edb306SCy Schubert 	;
105141edb306SCy Schubert 
105241edb306SCy Schubert mapoptions:
105341edb306SCy Schubert 	rr frag age mssclamp nattag setproto purge
105441edb306SCy Schubert 	;
105541edb306SCy Schubert 
105641edb306SCy Schubert rdroptions:
105741edb306SCy Schubert 	rr frag age sticky mssclamp rdrproxy nattag purge
105841edb306SCy Schubert 	;
105941edb306SCy Schubert 
106041edb306SCy Schubert nattag:	| IPNY_TAG YY_STR		{ strncpy(nat->in_tag.ipt_tag, $2,
106141edb306SCy Schubert 						  sizeof(nat->in_tag.ipt_tag));
106241edb306SCy Schubert 					}
106341edb306SCy Schubert rr:	| IPNY_ROUNDROBIN		{ nat->in_flags |= IPN_ROUNDR; }
106441edb306SCy Schubert 	;
106541edb306SCy Schubert 
106641edb306SCy Schubert frag:	| IPNY_FRAG			{ nat->in_flags |= IPN_FRAG; }
106741edb306SCy Schubert 	;
106841edb306SCy Schubert 
106941edb306SCy Schubert age:	| IPNY_AGE YY_NUMBER			{ nat->in_age[0] = $2;
107041edb306SCy Schubert 						  nat->in_age[1] = $2; }
107141edb306SCy Schubert 	| IPNY_AGE YY_NUMBER '/' YY_NUMBER	{ nat->in_age[0] = $2;
107241edb306SCy Schubert 						  nat->in_age[1] = $4; }
107341edb306SCy Schubert 	;
107441edb306SCy Schubert 
107541edb306SCy Schubert sticky: | IPNY_STICKY			{ if (!(nat->in_flags & IPN_ROUNDR) &&
107641edb306SCy Schubert 					      !(nat->in_flags & IPN_SPLIT)) {
107741edb306SCy Schubert 						FPRINTF(stderr,
107841edb306SCy Schubert 		"'sticky' for use with round-robin/IP splitting only\n");
107941edb306SCy Schubert 					  } else
108041edb306SCy Schubert 						nat->in_flags |= IPN_STICKY;
108141edb306SCy Schubert 					}
108241edb306SCy Schubert 	;
108341edb306SCy Schubert 
108441edb306SCy Schubert mssclamp:
108541edb306SCy Schubert 	| IPNY_MSSCLAMP YY_NUMBER		{ nat->in_mssclamp = $2; }
108641edb306SCy Schubert 	;
108741edb306SCy Schubert 
108841edb306SCy Schubert tcpudp:	IPNY_TCP			{ setnatproto(IPPROTO_TCP); }
108941edb306SCy Schubert 	| IPNY_UDP			{ setnatproto(IPPROTO_UDP); }
109041edb306SCy Schubert 	| IPNY_TCPUDP			{ nat->in_flags |= IPN_TCPUDP;
109141edb306SCy Schubert 					  nat->in_pr[0] = 0;
109241edb306SCy Schubert 					  nat->in_pr[1] = 0;
109341edb306SCy Schubert 					}
109441edb306SCy Schubert 	| IPNY_TCP '/' IPNY_UDP		{ nat->in_flags |= IPN_TCPUDP;
109541edb306SCy Schubert 					  nat->in_pr[0] = 0;
109641edb306SCy Schubert 					  nat->in_pr[1] = 0;
109741edb306SCy Schubert 					}
109841edb306SCy Schubert 	;
109941edb306SCy Schubert 
110041edb306SCy Schubert sequential:
110141edb306SCy Schubert 	| IPNY_SEQUENTIAL		{ nat->in_flags |= IPN_SEQUENTIAL; }
110241edb306SCy Schubert 	;
110341edb306SCy Schubert 
110441edb306SCy Schubert purge:
110541edb306SCy Schubert 	| IPNY_PURGE			{ nat->in_flags |= IPN_PURGE; }
110641edb306SCy Schubert 	;
110741edb306SCy Schubert 
110841edb306SCy Schubert rdrproxy:
110941edb306SCy Schubert 	IPNY_PROXY YY_STR
111041edb306SCy Schubert 					{ int pos;
111141edb306SCy Schubert 					  pos = addname(&nat, $2);
111241edb306SCy Schubert 					  nat->in_plabel = pos;
111341edb306SCy Schubert 					  nat->in_odport = nat->in_dpnext;
111441edb306SCy Schubert 					  nat->in_dtop = nat->in_odport;
111541edb306SCy Schubert 					  free($2);
111641edb306SCy Schubert 					}
111741edb306SCy Schubert 	| proxy			{ if (nat->in_plabel != -1) {
111841edb306SCy Schubert 					nat->in_ndport = nat->in_odport;
111941edb306SCy Schubert 					nat->in_dpmin = nat->in_odport;
112041edb306SCy Schubert 					nat->in_dpmax = nat->in_dpmin;
112141edb306SCy Schubert 					nat->in_dtop = nat->in_dpmin;
112241edb306SCy Schubert 					nat->in_dpnext = nat->in_dpmin;
112341edb306SCy Schubert 				  }
112441edb306SCy Schubert 				}
112541edb306SCy Schubert 	;
112641edb306SCy Schubert 
112741edb306SCy Schubert newopts:
112841edb306SCy Schubert 	| IPNY_PURGE			{ nat->in_flags |= IPN_PURGE; }
112941edb306SCy Schubert 	;
113041edb306SCy Schubert 
113141edb306SCy Schubert proto:	YY_NUMBER			{ $$ = $1;
113241edb306SCy Schubert 					  if ($$ != IPPROTO_TCP &&
113341edb306SCy Schubert 					      $$ != IPPROTO_UDP)
113441edb306SCy Schubert 						suggest_port = 0;
113541edb306SCy Schubert 					}
113641edb306SCy Schubert 	| IPNY_TCP			{ $$ = IPPROTO_TCP; }
113741edb306SCy Schubert 	| IPNY_UDP			{ $$ = IPPROTO_UDP; }
113841edb306SCy Schubert 	| YY_STR			{ $$ = getproto($1);
113941edb306SCy Schubert 					  free($1);
114041edb306SCy Schubert 					  if ($$ == -1)
114141edb306SCy Schubert 						yyerror("unknown protocol");
114241edb306SCy Schubert 					  if ($$ != IPPROTO_TCP &&
114341edb306SCy Schubert 					      $$ != IPPROTO_UDP)
114441edb306SCy Schubert 						suggest_port = 0;
114541edb306SCy Schubert 					}
114641edb306SCy Schubert 	;
114741edb306SCy Schubert 
114841edb306SCy Schubert hexnumber:
114941edb306SCy Schubert 	YY_HEX				{ $$ = $1; }
115041edb306SCy Schubert 	;
115141edb306SCy Schubert 
115241edb306SCy Schubert hostname:
115341edb306SCy Schubert 	YY_STR				{ i6addr_t addr;
115441edb306SCy Schubert 					  int family;
115541edb306SCy Schubert 
115641edb306SCy Schubert #ifdef USE_INET6
115741edb306SCy Schubert 					  if (nat->in_v[0] == 6)
115841edb306SCy Schubert 						family = AF_INET6;
115941edb306SCy Schubert 					  else
116041edb306SCy Schubert #endif
116141edb306SCy Schubert 						family = AF_INET;
116241edb306SCy Schubert 					  memset(&($$), 0, sizeof($$));
116341edb306SCy Schubert 					  memset(&addr, 0, sizeof(addr));
116441edb306SCy Schubert 					  $$.f = family;
116541edb306SCy Schubert 					  if (gethost(family, $1,
116641edb306SCy Schubert 						      &addr) == 0) {
116741edb306SCy Schubert 						$$.a = addr;
116841edb306SCy Schubert 					  } else {
116941edb306SCy Schubert 						FPRINTF(stderr,
117041edb306SCy Schubert 							"Unknown host '%s'\n",
117141edb306SCy Schubert 							$1);
117241edb306SCy Schubert 					  }
117341edb306SCy Schubert 					  free($1);
117441edb306SCy Schubert 					}
117541edb306SCy Schubert 	| YY_NUMBER			{ memset(&($$), 0, sizeof($$));
117641edb306SCy Schubert 					  $$.a.in4.s_addr = htonl($1);
117741edb306SCy Schubert 					  if ($$.a.in4.s_addr != 0)
117841edb306SCy Schubert 						$$.f = AF_INET;
117941edb306SCy Schubert 					}
118041edb306SCy Schubert 	| ipv4				{ $$ = $1; }
118141edb306SCy Schubert 	| YY_IPV6			{ memset(&($$), 0, sizeof($$));
118241edb306SCy Schubert 					  $$.a = $1;
118341edb306SCy Schubert 					  $$.f = AF_INET6;
118441edb306SCy Schubert 					}
118541edb306SCy Schubert 	| YY_NUMBER YY_IPV6		{ memset(&($$), 0, sizeof($$));
118641edb306SCy Schubert 					  $$.a = $2;
118741edb306SCy Schubert 					  $$.f = AF_INET6;
118841edb306SCy Schubert 					}
118941edb306SCy Schubert 	;
119041edb306SCy Schubert 
119141edb306SCy Schubert compare:
119241edb306SCy Schubert 	'='				{ $$ = FR_EQUAL; }
119341edb306SCy Schubert 	| YY_CMP_EQ			{ $$ = FR_EQUAL; }
119441edb306SCy Schubert 	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
119541edb306SCy Schubert 	| YY_CMP_LT			{ $$ = FR_LESST; }
119641edb306SCy Schubert 	| YY_CMP_LE			{ $$ = FR_LESSTE; }
119741edb306SCy Schubert 	| YY_CMP_GT			{ $$ = FR_GREATERT; }
119841edb306SCy Schubert 	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
119941edb306SCy Schubert 
120041edb306SCy Schubert range:
120141edb306SCy Schubert 	YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
120241edb306SCy Schubert 	| YY_RANGE_IN			{ $$ = FR_INRANGE; }
120341edb306SCy Schubert 	| ':'				{ $$ = FR_INCRANGE; }
120441edb306SCy Schubert 	;
120541edb306SCy Schubert 
120641edb306SCy Schubert ipaddr:	ipv4				{ $$ = $1; }
120741edb306SCy Schubert 	| YY_IPV6			{ $$.a = $1;
120841edb306SCy Schubert 					  $$.f = AF_INET6;
120941edb306SCy Schubert 					}
121041edb306SCy Schubert 	;
121141edb306SCy Schubert 
121241edb306SCy Schubert ipv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
121341edb306SCy Schubert 		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
121441edb306SCy Schubert 			yyerror("Invalid octet string for IP address");
1215*2582ae57SCy Schubert 			return(0);
121641edb306SCy Schubert 		  }
121741edb306SCy Schubert 		  bzero((char *)&$$, sizeof($$));
121841edb306SCy Schubert 		  $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
121941edb306SCy Schubert 		  $$.a.in4.s_addr = htonl($$.a.in4.s_addr);
122041edb306SCy Schubert 		  $$.f = AF_INET;
122141edb306SCy Schubert 		}
122241edb306SCy Schubert 	;
122341edb306SCy Schubert 
122441edb306SCy Schubert %%
122541edb306SCy Schubert 
122641edb306SCy Schubert 
122741edb306SCy Schubert static	wordtab_t	proxies[] = {
122841edb306SCy Schubert 	{ "dns",	IPNY_DNS }
122941edb306SCy Schubert };
123041edb306SCy Schubert 
123141edb306SCy Schubert static	wordtab_t	dnswords[] = {
123241edb306SCy Schubert 	{ "allow",	IPNY_ALLOW },
123341edb306SCy Schubert 	{ "block",	IPNY_DENY },
123441edb306SCy Schubert 	{ "deny",	IPNY_DENY },
123541edb306SCy Schubert 	{ "drop",	IPNY_DENY },
123641edb306SCy Schubert 	{ "pass",	IPNY_ALLOW },
123741edb306SCy Schubert 
123841edb306SCy Schubert };
123941edb306SCy Schubert 
124041edb306SCy Schubert static	wordtab_t	yywords[] = {
124141edb306SCy Schubert 	{ "age",	IPNY_AGE },
124241edb306SCy Schubert 	{ "any",	IPNY_ANY },
124341edb306SCy Schubert 	{ "auto",	IPNY_AUTO },
124441edb306SCy Schubert 	{ "bimap",	IPNY_BIMAP },
124541edb306SCy Schubert 	{ "config",	IPNY_CONFIG },
124641edb306SCy Schubert 	{ "divert",	IPNY_DIVERT },
124741edb306SCy Schubert 	{ "dst",	IPNY_DST },
124841edb306SCy Schubert 	{ "dstlist",	IPNY_DSTLIST },
124941edb306SCy Schubert 	{ "frag",	IPNY_FRAG },
125041edb306SCy Schubert 	{ "from",	IPNY_FROM },
125141edb306SCy Schubert 	{ "hash",	IPNY_HASH },
125241edb306SCy Schubert 	{ "icmpidmap",	IPNY_ICMPIDMAP },
125341edb306SCy Schubert 	{ "in",		IPNY_IN },
125441edb306SCy Schubert 	{ "inet",	IPNY_INET },
125541edb306SCy Schubert 	{ "inet6",	IPNY_INET6 },
125641edb306SCy Schubert 	{ "mask",	IPNY_MASK },
125741edb306SCy Schubert 	{ "map",	IPNY_MAP },
125841edb306SCy Schubert 	{ "map-block",	IPNY_MAPBLOCK },
125941edb306SCy Schubert 	{ "mssclamp",	IPNY_MSSCLAMP },
126041edb306SCy Schubert 	{ "netmask",	IPNY_MASK },
126141edb306SCy Schubert 	{ "no",		IPNY_NO },
126241edb306SCy Schubert 	{ "on",		IPNY_ON },
126341edb306SCy Schubert 	{ "out",	IPNY_OUT },
126441edb306SCy Schubert 	{ "pool",	IPNY_POOL },
126541edb306SCy Schubert 	{ "port",	IPNY_PORT },
126641edb306SCy Schubert 	{ "portmap",	IPNY_PORTMAP },
126741edb306SCy Schubert 	{ "ports",	IPNY_PORTS },
126841edb306SCy Schubert 	{ "proto",	IPNY_PROTO },
126941edb306SCy Schubert 	{ "proxy",	IPNY_PROXY },
127041edb306SCy Schubert 	{ "purge",	IPNY_PURGE },
127141edb306SCy Schubert 	{ "range",	IPNY_RANGE },
127241edb306SCy Schubert 	{ "rewrite",	IPNY_REWRITE },
127341edb306SCy Schubert 	{ "rdr",	IPNY_RDR },
127441edb306SCy Schubert 	{ "round-robin",IPNY_ROUNDROBIN },
127541edb306SCy Schubert 	{ "sequential",	IPNY_SEQUENTIAL },
127641edb306SCy Schubert 	{ "src",	IPNY_SRC },
127741edb306SCy Schubert 	{ "sticky",	IPNY_STICKY },
127841edb306SCy Schubert 	{ "tag",	IPNY_TAG },
127941edb306SCy Schubert 	{ "tcp",	IPNY_TCP },
128041edb306SCy Schubert 	{ "tcpudp",	IPNY_TCPUDP },
128141edb306SCy Schubert 	{ "to",		IPNY_TO },
128241edb306SCy Schubert 	{ "udp",	IPNY_UDP },
128341edb306SCy Schubert 	{ "-",		'-' },
128441edb306SCy Schubert 	{ "->",		IPNY_TLATE },
128541edb306SCy Schubert 	{ "eq",		YY_CMP_EQ },
128641edb306SCy Schubert 	{ "ne",		YY_CMP_NE },
128741edb306SCy Schubert 	{ "lt",		YY_CMP_LT },
128841edb306SCy Schubert 	{ "gt",		YY_CMP_GT },
128941edb306SCy Schubert 	{ "le",		YY_CMP_LE },
129041edb306SCy Schubert 	{ "ge",		YY_CMP_GE },
129141edb306SCy Schubert 	{ NULL,		0 }
129241edb306SCy Schubert };
129341edb306SCy Schubert 
129441edb306SCy Schubert 
129541edb306SCy Schubert int
ipnat_parsefile(int fd,addfunc_t addfunc,ioctlfunc_t ioctlfunc,char * filename)1296efeb8bffSCy Schubert ipnat_parsefile(int fd, addfunc_t addfunc, ioctlfunc_t ioctlfunc,
1297efeb8bffSCy Schubert 	char *filename)
129841edb306SCy Schubert {
129941edb306SCy Schubert 	FILE *fp = NULL;
130041edb306SCy Schubert 	int rval;
130141edb306SCy Schubert 	char *s;
130241edb306SCy Schubert 
130341edb306SCy Schubert 	yylineNum = 1;
130441edb306SCy Schubert 
130541edb306SCy Schubert 	(void) yysettab(yywords);
130641edb306SCy Schubert 
130741edb306SCy Schubert 	s = getenv("YYDEBUG");
130841edb306SCy Schubert 	if (s)
130941edb306SCy Schubert 		yydebug = atoi(s);
131041edb306SCy Schubert 	else
131141edb306SCy Schubert 		yydebug = 0;
131241edb306SCy Schubert 
131341edb306SCy Schubert 	if (strcmp(filename, "-")) {
131441edb306SCy Schubert 		fp = fopen(filename, "r");
131541edb306SCy Schubert 		if (!fp) {
131641edb306SCy Schubert 			FPRINTF(stderr, "fopen(%s) failed: %s\n", filename,
131741edb306SCy Schubert 				STRERROR(errno));
1318*2582ae57SCy Schubert 			return(-1);
131941edb306SCy Schubert 		}
132041edb306SCy Schubert 	} else
132141edb306SCy Schubert 		fp = stdin;
132241edb306SCy Schubert 
132341edb306SCy Schubert 	while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0)
132441edb306SCy Schubert 		;
132541edb306SCy Schubert 	if (fp != NULL)
132641edb306SCy Schubert 		fclose(fp);
132741edb306SCy Schubert 	if (rval == -1)
132841edb306SCy Schubert 		rval = 0;
132941edb306SCy Schubert 	else if (rval != 0)
133041edb306SCy Schubert 		rval = 1;
1331*2582ae57SCy Schubert 	return(rval);
133241edb306SCy Schubert }
133341edb306SCy Schubert 
133441edb306SCy Schubert 
133541edb306SCy Schubert int
ipnat_parsesome(int fd,addfunc_t addfunc,ioctlfunc_t ioctlfunc,FILE * fp)1336efeb8bffSCy Schubert ipnat_parsesome(int fd, addfunc_t addfunc, ioctlfunc_t ioctlfunc,
1337efeb8bffSCy Schubert 	FILE *fp)
133841edb306SCy Schubert {
133941edb306SCy Schubert 	char *s;
134041edb306SCy Schubert 	int i;
134141edb306SCy Schubert 
134241edb306SCy Schubert 	natfd = fd;
134341edb306SCy Schubert 	parser_error = 0;
134441edb306SCy Schubert 	nataddfunc = addfunc;
134541edb306SCy Schubert 	natioctlfunc = ioctlfunc;
134641edb306SCy Schubert 
134741edb306SCy Schubert 	if (feof(fp))
1348*2582ae57SCy Schubert 		return(-1);
134941edb306SCy Schubert 	i = fgetc(fp);
135041edb306SCy Schubert 	if (i == EOF)
1351*2582ae57SCy Schubert 		return(-1);
135241edb306SCy Schubert 	if (ungetc(i, fp) == EOF)
1353*2582ae57SCy Schubert 		return(-1);
135441edb306SCy Schubert 	if (feof(fp))
1355*2582ae57SCy Schubert 		return(-1);
135641edb306SCy Schubert 	s = getenv("YYDEBUG");
135741edb306SCy Schubert 	if (s)
135841edb306SCy Schubert 		yydebug = atoi(s);
135941edb306SCy Schubert 	else
136041edb306SCy Schubert 		yydebug = 0;
136141edb306SCy Schubert 
136241edb306SCy Schubert 	yyin = fp;
136341edb306SCy Schubert 	yyparse();
1364*2582ae57SCy Schubert 	return(parser_error);
136541edb306SCy Schubert }
136641edb306SCy Schubert 
136741edb306SCy Schubert 
136841edb306SCy Schubert static void
newnatrule(void)1369efeb8bffSCy Schubert newnatrule(void)
137041edb306SCy Schubert {
137141edb306SCy Schubert 	ipnat_t *n;
137241edb306SCy Schubert 
137341edb306SCy Schubert 	n = calloc(1, sizeof(*n));
137441edb306SCy Schubert 	if (n == NULL)
137541edb306SCy Schubert 		return;
137641edb306SCy Schubert 
137741edb306SCy Schubert 	if (nat == NULL) {
137841edb306SCy Schubert 		nattop = nat = n;
137941edb306SCy Schubert 		n->in_pnext = &nattop;
138041edb306SCy Schubert 	} else {
138141edb306SCy Schubert 		nat->in_next = n;
138241edb306SCy Schubert 		n->in_pnext = &nat->in_next;
138341edb306SCy Schubert 		nat = n;
138441edb306SCy Schubert 	}
138541edb306SCy Schubert 
138641edb306SCy Schubert 	n->in_flineno = yylineNum;
138741edb306SCy Schubert 	n->in_ifnames[0] = -1;
138841edb306SCy Schubert 	n->in_ifnames[1] = -1;
138941edb306SCy Schubert 	n->in_plabel = -1;
139041edb306SCy Schubert 	n->in_pconfig = -1;
139141edb306SCy Schubert 	n->in_size = sizeof(*n);
139241edb306SCy Schubert 
139341edb306SCy Schubert 	suggest_port = 0;
139441edb306SCy Schubert }
139541edb306SCy Schubert 
139641edb306SCy Schubert 
139741edb306SCy Schubert static void
setnatproto(int p)1398efeb8bffSCy Schubert setnatproto(int p)
139941edb306SCy Schubert {
140041edb306SCy Schubert 	nat->in_pr[0] = p;
140141edb306SCy Schubert 	nat->in_pr[1] = p;
140241edb306SCy Schubert 
140341edb306SCy Schubert 	switch (p)
140441edb306SCy Schubert 	{
140541edb306SCy Schubert 	case IPPROTO_TCP :
140641edb306SCy Schubert 		nat->in_flags |= IPN_TCP;
140741edb306SCy Schubert 		nat->in_flags &= ~IPN_UDP;
140841edb306SCy Schubert 		break;
140941edb306SCy Schubert 	case IPPROTO_UDP :
141041edb306SCy Schubert 		nat->in_flags |= IPN_UDP;
141141edb306SCy Schubert 		nat->in_flags &= ~IPN_TCP;
141241edb306SCy Schubert 		break;
141341edb306SCy Schubert #ifdef USE_INET6
141441edb306SCy Schubert 	case IPPROTO_ICMPV6 :
141541edb306SCy Schubert #endif
141641edb306SCy Schubert 	case IPPROTO_ICMP :
141741edb306SCy Schubert 		nat->in_flags &= ~IPN_TCPUDP;
141841edb306SCy Schubert 		if (!(nat->in_flags & IPN_ICMPQUERY) &&
141941edb306SCy Schubert 		    !(nat->in_redir & NAT_DIVERTUDP)) {
142041edb306SCy Schubert 			nat->in_dcmp = 0;
142141edb306SCy Schubert 			nat->in_scmp = 0;
142241edb306SCy Schubert 			nat->in_dpmin = 0;
142341edb306SCy Schubert 			nat->in_dpmax = 0;
142441edb306SCy Schubert 			nat->in_dpnext = 0;
142541edb306SCy Schubert 			nat->in_spmin = 0;
142641edb306SCy Schubert 			nat->in_spmax = 0;
142741edb306SCy Schubert 			nat->in_spnext = 0;
142841edb306SCy Schubert 		}
142941edb306SCy Schubert 		break;
143041edb306SCy Schubert 	default :
143141edb306SCy Schubert 		if ((nat->in_redir & NAT_MAPBLK) == 0) {
143241edb306SCy Schubert 			nat->in_flags &= ~IPN_TCPUDP;
143341edb306SCy Schubert 			nat->in_dcmp = 0;
143441edb306SCy Schubert 			nat->in_scmp = 0;
143541edb306SCy Schubert 			nat->in_dpmin = 0;
143641edb306SCy Schubert 			nat->in_dpmax = 0;
143741edb306SCy Schubert 			nat->in_dpnext = 0;
143841edb306SCy Schubert 			nat->in_spmin = 0;
143941edb306SCy Schubert 			nat->in_spmax = 0;
144041edb306SCy Schubert 			nat->in_spnext = 0;
144141edb306SCy Schubert 		}
144241edb306SCy Schubert 		break;
144341edb306SCy Schubert 	}
144441edb306SCy Schubert 
144541edb306SCy Schubert 	if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) {
144641edb306SCy Schubert 		nat->in_stop = 0;
144741edb306SCy Schubert 		nat->in_dtop = 0;
144841edb306SCy Schubert 		nat->in_osport = 0;
144941edb306SCy Schubert 		nat->in_odport = 0;
145041edb306SCy Schubert 		nat->in_stop = 0;
145141edb306SCy Schubert 		nat->in_osport = 0;
145241edb306SCy Schubert 		nat->in_dtop = 0;
145341edb306SCy Schubert 		nat->in_odport = 0;
145441edb306SCy Schubert 	}
145541edb306SCy Schubert 	if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
145641edb306SCy Schubert 		nat->in_flags &= ~IPN_FIXEDDPORT;
145741edb306SCy Schubert }
145841edb306SCy Schubert 
145941edb306SCy Schubert 
146041edb306SCy Schubert int
ipnat_addrule(int fd,ioctlfunc_t ioctlfunc,void * ptr)1461efeb8bffSCy Schubert ipnat_addrule(int fd, ioctlfunc_t ioctlfunc, void *ptr)
146241edb306SCy Schubert {
146341edb306SCy Schubert 	ioctlcmd_t add, del;
146441edb306SCy Schubert 	ipfobj_t obj;
146541edb306SCy Schubert 	ipnat_t *ipn;
146641edb306SCy Schubert 
146741edb306SCy Schubert 	ipn = ptr;
146841edb306SCy Schubert 	bzero((char *)&obj, sizeof(obj));
146941edb306SCy Schubert 	obj.ipfo_rev = IPFILTER_VERSION;
147041edb306SCy Schubert 	obj.ipfo_size = ipn->in_size;
147141edb306SCy Schubert 	obj.ipfo_type = IPFOBJ_IPNAT;
147241edb306SCy Schubert 	obj.ipfo_ptr = ptr;
147341edb306SCy Schubert 
147441edb306SCy Schubert 	if ((opts & OPT_DONOTHING) != 0)
147541edb306SCy Schubert 		fd = -1;
147641edb306SCy Schubert 
147741edb306SCy Schubert 	if (opts & OPT_ZERORULEST) {
147841edb306SCy Schubert 		add = SIOCZRLST;
147941edb306SCy Schubert 		del = 0;
148041edb306SCy Schubert 	} else if (opts & OPT_PURGE) {
148141edb306SCy Schubert 		add = 0;
148241edb306SCy Schubert 		del = SIOCPURGENAT;
148341edb306SCy Schubert 	} else {
148441edb306SCy Schubert 		add = SIOCADNAT;
148541edb306SCy Schubert 		del = SIOCRMNAT;
148641edb306SCy Schubert 	}
148741edb306SCy Schubert 
148841edb306SCy Schubert 	if ((opts & OPT_VERBOSE) != 0)
148941edb306SCy Schubert 		printnat(ipn, opts);
149041edb306SCy Schubert 
149141edb306SCy Schubert 	if (opts & OPT_DEBUG)
149241edb306SCy Schubert 		binprint(ipn, ipn->in_size);
149341edb306SCy Schubert 
149441edb306SCy Schubert 	if ((opts & OPT_ZERORULEST) != 0) {
149541edb306SCy Schubert 		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
149641edb306SCy Schubert 			if ((opts & OPT_DONOTHING) == 0) {
149741edb306SCy Schubert 				char msg[80];
149841edb306SCy Schubert 
149941edb306SCy Schubert 				snprintf(msg, sizeof(msg), "%d:ioctl(zero nat rule)",
150041edb306SCy Schubert 					ipn->in_flineno);
1501*2582ae57SCy Schubert 				return(ipf_perror_fd(fd, ioctlfunc, msg));
150241edb306SCy Schubert 			}
150341edb306SCy Schubert 		} else {
150441edb306SCy Schubert 			PRINTF("hits %lu ", ipn->in_hits);
150541edb306SCy Schubert #ifdef USE_QUAD_T
150641edb306SCy Schubert 			PRINTF("bytes %"PRIu64" ",
150741edb306SCy Schubert 			       ipn->in_bytes[0] + ipn->in_bytes[1]);
150841edb306SCy Schubert #else
150941edb306SCy Schubert 			PRINTF("bytes %lu ",
151041edb306SCy Schubert 			       ipn->in_bytes[0] + ipn->in_bytes[1]);
151141edb306SCy Schubert #endif
151241edb306SCy Schubert 			printnat(ipn, opts);
151341edb306SCy Schubert 		}
151441edb306SCy Schubert 	} else if ((opts & OPT_REMOVE) != 0) {
151541edb306SCy Schubert 		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
151641edb306SCy Schubert 			if ((opts & OPT_DONOTHING) == 0) {
151741edb306SCy Schubert 				char msg[80];
151841edb306SCy Schubert 
151941edb306SCy Schubert 				snprintf(msg, sizeof(msg), "%d:ioctl(delete nat rule)",
152041edb306SCy Schubert 					ipn->in_flineno);
1521*2582ae57SCy Schubert 				return(ipf_perror_fd(fd, ioctlfunc, msg));
152241edb306SCy Schubert 			}
152341edb306SCy Schubert 		}
152441edb306SCy Schubert 	} else {
152541edb306SCy Schubert 		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
152641edb306SCy Schubert 			if ((opts & OPT_DONOTHING) == 0) {
152741edb306SCy Schubert 				char msg[80];
152841edb306SCy Schubert 
152941edb306SCy Schubert 				snprintf(msg, sizeof(msg), "%d:ioctl(add/insert nat rule)",
153041edb306SCy Schubert 					ipn->in_flineno);
153141edb306SCy Schubert 				if (errno == EEXIST) {
153241edb306SCy Schubert 					int strlen_msg = strlen(msg);
153341edb306SCy Schubert 					snprintf(msg + strlen_msg, sizeof(msg) -strlen_msg, "(line %d)",
153441edb306SCy Schubert 						ipn->in_flineno);
153541edb306SCy Schubert 				}
1536*2582ae57SCy Schubert 				return(ipf_perror_fd(fd, ioctlfunc, msg));
153741edb306SCy Schubert 			}
153841edb306SCy Schubert 		}
153941edb306SCy Schubert 	}
1540*2582ae57SCy Schubert 	return(0);
154141edb306SCy Schubert }
154241edb306SCy Schubert 
154341edb306SCy Schubert 
154441edb306SCy Schubert static void
setmapifnames()154541edb306SCy Schubert setmapifnames()
154641edb306SCy Schubert {
154741edb306SCy Schubert 	if (nat->in_ifnames[1] == -1)
154841edb306SCy Schubert 		nat->in_ifnames[1] = nat->in_ifnames[0];
154941edb306SCy Schubert 
155041edb306SCy Schubert 	if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0)
155141edb306SCy Schubert 		nat->in_flags |= IPN_TCPUDP;
155241edb306SCy Schubert 
155341edb306SCy Schubert 	if ((nat->in_flags & IPN_TCPUDP) == 0)
155441edb306SCy Schubert 		setnatproto(nat->in_pr[1]);
155541edb306SCy Schubert 
155641edb306SCy Schubert 	if (((nat->in_redir & NAT_MAPBLK) != 0) ||
155741edb306SCy Schubert 	      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
155841edb306SCy Schubert 		nat_setgroupmap(nat);
155941edb306SCy Schubert }
156041edb306SCy Schubert 
156141edb306SCy Schubert 
156241edb306SCy Schubert static void
setrdrifnames(void)1563efeb8bffSCy Schubert setrdrifnames(void)
156441edb306SCy Schubert {
156541edb306SCy Schubert 	if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0)
156641edb306SCy Schubert 		nat->in_flags |= IPN_TCPUDP;
156741edb306SCy Schubert 
156841edb306SCy Schubert 	if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) &&
156941edb306SCy Schubert 	    (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0))
157041edb306SCy Schubert 		setnatproto(IPPROTO_TCP);
157141edb306SCy Schubert 
157241edb306SCy Schubert 	if (nat->in_ifnames[1] == -1)
157341edb306SCy Schubert 		nat->in_ifnames[1] = nat->in_ifnames[0];
157441edb306SCy Schubert }
157541edb306SCy Schubert 
157641edb306SCy Schubert 
157741edb306SCy Schubert static void
proxy_setconfig(int proxy)1578efeb8bffSCy Schubert proxy_setconfig(int proxy)
157941edb306SCy Schubert {
158041edb306SCy Schubert 	if (proxy == IPNY_DNS) {
158141edb306SCy Schubert 		yysetfixeddict(dnswords);
158241edb306SCy Schubert 	}
158341edb306SCy Schubert }
158441edb306SCy Schubert 
158541edb306SCy Schubert 
158641edb306SCy Schubert static void
proxy_unsetconfig(void)1587efeb8bffSCy Schubert proxy_unsetconfig(void)
158841edb306SCy Schubert {
158941edb306SCy Schubert 	yyresetdict();
159041edb306SCy Schubert }
159141edb306SCy Schubert 
159241edb306SCy Schubert 
159341edb306SCy Schubert static namelist_t *
proxy_dns_add_pass(char * prefix,char * name)1594efeb8bffSCy Schubert proxy_dns_add_pass(char *prefix, char *name)
159541edb306SCy Schubert {
159641edb306SCy Schubert 	namelist_t *n;
159741edb306SCy Schubert 
159841edb306SCy Schubert 	n = calloc(1, sizeof(*n));
159941edb306SCy Schubert 	if (n != NULL) {
160041edb306SCy Schubert 		if (prefix == NULL || *prefix == '\0') {
160141edb306SCy Schubert 			n->na_name = strdup(name);
160241edb306SCy Schubert 		} else {
160341edb306SCy Schubert 			n->na_name = malloc(strlen(name) + strlen(prefix) + 1);
160441edb306SCy Schubert 			strcpy(n->na_name, prefix);
160541edb306SCy Schubert 			strcat(n->na_name, name);
160641edb306SCy Schubert 		}
160741edb306SCy Schubert 	}
1608*2582ae57SCy Schubert 	return(n);
160941edb306SCy Schubert }
161041edb306SCy Schubert 
161141edb306SCy Schubert 
161241edb306SCy Schubert static namelist_t *
proxy_dns_add_block(char * prefix,char * name)1613efeb8bffSCy Schubert proxy_dns_add_block(char *prefix, char *name)
161441edb306SCy Schubert {
161541edb306SCy Schubert 	namelist_t *n;
161641edb306SCy Schubert 
161741edb306SCy Schubert 	n = calloc(1, sizeof(*n));
161841edb306SCy Schubert 	if (n != NULL) {
161941edb306SCy Schubert 		if (prefix == NULL || *prefix == '\0') {
162041edb306SCy Schubert 			n->na_name = strdup(name);
162141edb306SCy Schubert 		} else {
162241edb306SCy Schubert 			n->na_name = malloc(strlen(name) + strlen(prefix) + 1);
162341edb306SCy Schubert 			strcpy(n->na_name, prefix);
162441edb306SCy Schubert 			strcat(n->na_name, name);
162541edb306SCy Schubert 		}
162641edb306SCy Schubert 		n->na_value = 1;
162741edb306SCy Schubert 	}
1628*2582ae57SCy Schubert 	return(n);
162941edb306SCy Schubert }
163041edb306SCy Schubert 
163141edb306SCy Schubert 
163241edb306SCy Schubert static void
proxy_addconfig(char * proxy,int proto,char * conf,namelist_t * list)1633efeb8bffSCy Schubert proxy_addconfig(char *proxy, int proto, char *conf, namelist_t *list)
163441edb306SCy Schubert {
163541edb306SCy Schubert 	proxyrule_t *pr;
163641edb306SCy Schubert 
163741edb306SCy Schubert 	pr = calloc(1, sizeof(*pr));
163841edb306SCy Schubert 	if (pr != NULL) {
163941edb306SCy Schubert 		pr->pr_proto = proto;
164041edb306SCy Schubert 		pr->pr_proxy = proxy;
164141edb306SCy Schubert 		pr->pr_conf = conf;
164241edb306SCy Schubert 		pr->pr_names = list;
164341edb306SCy Schubert 		pr->pr_next = prules;
164441edb306SCy Schubert 		prules = pr;
164541edb306SCy Schubert 	}
164641edb306SCy Schubert }
164741edb306SCy Schubert 
164841edb306SCy Schubert 
164941edb306SCy Schubert static void
proxy_loadrules(int fd,ioctlfunc_t ioctlfunc,proxyrule_t * rules)1650efeb8bffSCy Schubert proxy_loadrules(int fd, ioctlfunc_t ioctlfunc, proxyrule_t *rules)
165141edb306SCy Schubert {
165241edb306SCy Schubert 	proxyrule_t *pr;
165341edb306SCy Schubert 
165441edb306SCy Schubert 	while ((pr = rules) != NULL) {
165541edb306SCy Schubert 		proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto,
165641edb306SCy Schubert 				 pr->pr_conf, pr->pr_names);
165741edb306SCy Schubert 		rules = pr->pr_next;
165841edb306SCy Schubert 		free(pr->pr_conf);
165941edb306SCy Schubert 		free(pr);
166041edb306SCy Schubert 	}
166141edb306SCy Schubert }
166241edb306SCy Schubert 
166341edb306SCy Schubert 
166441edb306SCy Schubert static void
proxy_loadconfig(int fd,ioctlfunc_t ioctlfunc,char * proxy,int proto,char * conf,namelist_t * list)1665efeb8bffSCy Schubert proxy_loadconfig(int fd, ioctlfunc_t ioctlfunc, char *proxy, int proto,
1666efeb8bffSCy Schubert 	char *conf, namelist_t *list)
166741edb306SCy Schubert {
166841edb306SCy Schubert 	namelist_t *na;
166941edb306SCy Schubert 	ipfobj_t obj;
167041edb306SCy Schubert 	ap_ctl_t pcmd;
167141edb306SCy Schubert 
167241edb306SCy Schubert 	obj.ipfo_rev = IPFILTER_VERSION;
167341edb306SCy Schubert 	obj.ipfo_type = IPFOBJ_PROXYCTL;
167441edb306SCy Schubert 	obj.ipfo_size = sizeof(pcmd);
167541edb306SCy Schubert 	obj.ipfo_ptr = &pcmd;
167641edb306SCy Schubert 
167741edb306SCy Schubert 	while ((na = list) != NULL) {
167841edb306SCy Schubert 		if ((opts & OPT_REMOVE) != 0)
167941edb306SCy Schubert 			pcmd.apc_cmd = APC_CMD_DEL;
168041edb306SCy Schubert 		else
168141edb306SCy Schubert 			pcmd.apc_cmd = APC_CMD_ADD;
168241edb306SCy Schubert 		pcmd.apc_dsize = strlen(na->na_name) + 1;
168341edb306SCy Schubert 		pcmd.apc_data = na->na_name;
168441edb306SCy Schubert 		pcmd.apc_arg = na->na_value;
168541edb306SCy Schubert 		pcmd.apc_p = proto;
168641edb306SCy Schubert 
168741edb306SCy Schubert 		strncpy(pcmd.apc_label, proxy, APR_LABELLEN);
168841edb306SCy Schubert 		pcmd.apc_label[APR_LABELLEN - 1] = '\0';
168941edb306SCy Schubert 
169041edb306SCy Schubert 		strncpy(pcmd.apc_config, conf, APR_LABELLEN);
169141edb306SCy Schubert 		pcmd.apc_config[APR_LABELLEN - 1] = '\0';
169241edb306SCy Schubert 
169341edb306SCy Schubert 		if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) {
169441edb306SCy Schubert                         if ((opts & OPT_DONOTHING) == 0) {
169541edb306SCy Schubert                                 char msg[80];
169641edb306SCy Schubert 
169741edb306SCy Schubert                                 snprintf(msg, sizeof(msg), "%d:ioctl(add/remove proxy rule)",
169841edb306SCy Schubert 					yylineNum);
169941edb306SCy Schubert                                 ipf_perror_fd(fd, ioctlfunc, msg);
170041edb306SCy Schubert 				return;
170141edb306SCy Schubert                         }
170241edb306SCy Schubert 		}
170341edb306SCy Schubert 
170441edb306SCy Schubert 		list = na->na_next;
170541edb306SCy Schubert 		free(na->na_name);
170641edb306SCy Schubert 		free(na);
170741edb306SCy Schubert 	}
170841edb306SCy Schubert }
170941edb306SCy Schubert 
171041edb306SCy Schubert 
171141edb306SCy Schubert static void
setifname(ipnat_t ** np,int idx,char * name)1712efeb8bffSCy Schubert setifname(ipnat_t **np, int idx, char *name)
171341edb306SCy Schubert {
171441edb306SCy Schubert 	int pos;
171541edb306SCy Schubert 
171641edb306SCy Schubert 	pos = addname(np, name);
171741edb306SCy Schubert 	if (pos == -1)
171841edb306SCy Schubert 		return;
171941edb306SCy Schubert 	(*np)->in_ifnames[idx] = pos;
172041edb306SCy Schubert }
172141edb306SCy Schubert 
172241edb306SCy Schubert 
172341edb306SCy Schubert static int
addname(ipnat_t ** np,char * name)1724efeb8bffSCy Schubert addname(ipnat_t **np, char *name)
172541edb306SCy Schubert {
172641edb306SCy Schubert 	ipnat_t *n;
172741edb306SCy Schubert 	int nlen;
172841edb306SCy Schubert 	int pos;
172941edb306SCy Schubert 
173041edb306SCy Schubert 	nlen = strlen(name) + 1;
173141edb306SCy Schubert 	n = realloc(*np, (*np)->in_size + nlen);
173241edb306SCy Schubert 	if (*np == nattop)
173341edb306SCy Schubert 		nattop = n;
173441edb306SCy Schubert 	*np = n;
173541edb306SCy Schubert 	if (n == NULL)
1736*2582ae57SCy Schubert 		return(-1);
173741edb306SCy Schubert 	if (n->in_pnext != NULL)
173841edb306SCy Schubert 		*n->in_pnext = n;
173941edb306SCy Schubert 	n->in_size += nlen;
174041edb306SCy Schubert 	pos = n->in_namelen;
174141edb306SCy Schubert 	n->in_namelen += nlen;
174241edb306SCy Schubert 	strcpy(n->in_names + pos, name);
174341edb306SCy Schubert 	n->in_names[n->in_namelen] = '\0';
1744*2582ae57SCy Schubert 	return(pos);
174541edb306SCy Schubert }
1746