ipnat_y.y revision 170268
1145519Sdarrenr/*	$FreeBSD: head/contrib/ipfilter/tools/ipnat_y.y 170268 2007-06-04 02:54:36Z darrenr $	*/
2145510Sdarrenr
3170268Sdarrenr/*
4170268Sdarrenr * Copyright (C) 2001-2006 by Darren Reed.
5170268Sdarrenr *
6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7170268Sdarrenr */
8145510Sdarrenr%{
9145510Sdarrenr#ifdef  __FreeBSD__
10145510Sdarrenr# ifndef __FreeBSD_cc_version
11145510Sdarrenr#  include <osreldate.h>
12145510Sdarrenr# else
13145510Sdarrenr#  if __FreeBSD_cc_version < 430000
14145510Sdarrenr#   include <osreldate.h>
15145510Sdarrenr#  endif
16145510Sdarrenr# endif
17145510Sdarrenr#endif
18145510Sdarrenr#include <stdio.h>
19145510Sdarrenr#include <unistd.h>
20145510Sdarrenr#include <string.h>
21145510Sdarrenr#include <fcntl.h>
22145510Sdarrenr#include <errno.h>
23145510Sdarrenr#if !defined(__SVR4) && !defined(__GNUC__)
24145510Sdarrenr#include <strings.h>
25145510Sdarrenr#endif
26145510Sdarrenr#include <sys/types.h>
27145510Sdarrenr#include <sys/param.h>
28145510Sdarrenr#include <sys/file.h>
29145510Sdarrenr#include <stdlib.h>
30145510Sdarrenr#include <stddef.h>
31145510Sdarrenr#include <sys/socket.h>
32145510Sdarrenr#include <sys/ioctl.h>
33145510Sdarrenr#include <netinet/in.h>
34145510Sdarrenr#include <netinet/in_systm.h>
35145510Sdarrenr#include <sys/time.h>
36145510Sdarrenr#include <syslog.h>
37145510Sdarrenr#include <net/if.h>
38145510Sdarrenr#if __FreeBSD_version >= 300000
39145510Sdarrenr# include <net/if_var.h>
40145510Sdarrenr#endif
41145510Sdarrenr#include <netdb.h>
42145510Sdarrenr#include <arpa/nameser.h>
43145510Sdarrenr#include <resolv.h>
44145510Sdarrenr#include "ipf.h"
45145510Sdarrenr#include "netinet/ipl.h"
46145510Sdarrenr#include "ipnat_l.h"
47145510Sdarrenr
48145510Sdarrenr#define	YYDEBUG	1
49145510Sdarrenr
50145510Sdarrenrextern	void	yyerror __P((char *));
51145510Sdarrenrextern	int	yyparse __P((void));
52145510Sdarrenrextern	int	yylex __P((void));
53145510Sdarrenrextern	int	yydebug;
54145510Sdarrenrextern	FILE	*yyin;
55145510Sdarrenrextern	int	yylineNum;
56145510Sdarrenr
57145510Sdarrenrstatic	ipnat_t		*nattop = NULL;
58145510Sdarrenrstatic	ipnat_t		*nat = NULL;
59145510Sdarrenrstatic	int		natfd = -1;
60145510Sdarrenrstatic	ioctlfunc_t	natioctlfunc = NULL;
61145510Sdarrenrstatic	addfunc_t	nataddfunc = NULL;
62161357Sguidostatic	int		suggest_port = 0;
63145510Sdarrenr
64145510Sdarrenrstatic	void	newnatrule __P((void));
65145510Sdarrenrstatic	void	setnatproto __P((int));
66145510Sdarrenr
67145510Sdarrenr%}
68145510Sdarrenr%union	{
69145510Sdarrenr	char	*str;
70145510Sdarrenr	u_32_t	num;
71145510Sdarrenr	struct	in_addr	ipa;
72145510Sdarrenr	frentry_t	fr;
73145510Sdarrenr	frtuc_t	*frt;
74145510Sdarrenr	u_short	port;
75145510Sdarrenr	struct	{
76145510Sdarrenr		u_short	p1;
77145510Sdarrenr		u_short	p2;
78145510Sdarrenr		int	pc;
79145510Sdarrenr	} pc;
80145510Sdarrenr	struct	{
81145510Sdarrenr		struct	in_addr	a;
82145510Sdarrenr		struct	in_addr	m;
83145510Sdarrenr	} ipp;
84145510Sdarrenr	union	i6addr	ip6;
85145510Sdarrenr};
86145510Sdarrenr
87145510Sdarrenr%token  <num>   YY_NUMBER YY_HEX
88145510Sdarrenr%token  <str>   YY_STR
89145510Sdarrenr%token	  YY_COMMENT
90145510Sdarrenr%token	  YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
91145510Sdarrenr%token	  YY_RANGE_OUT YY_RANGE_IN
92145510Sdarrenr%token  <ip6>   YY_IPV6
93145510Sdarrenr
94145510Sdarrenr%token	IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
95145510Sdarrenr%token	IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
96145510Sdarrenr%token	IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
97145510Sdarrenr%token	IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
98145510Sdarrenr%token	IPNY_TLATE
99145510Sdarrenr%type	<port> portspec
100145510Sdarrenr%type	<num> hexnumber compare range proto
101145510Sdarrenr%type	<ipa> hostname ipv4
102145510Sdarrenr%type	<ipp> addr nummask rhaddr
103145510Sdarrenr%type	<pc> portstuff
104145510Sdarrenr%%
105145510Sdarrenrfile:	line
106145510Sdarrenr	| assign
107145510Sdarrenr	| file line
108145510Sdarrenr	| file assign
109145510Sdarrenr	;
110145510Sdarrenr
111145510Sdarrenrline:	xx rule		{ while ((nat = nattop) != NULL) {
112145510Sdarrenr				nattop = nat->in_next;
113145510Sdarrenr				(*nataddfunc)(natfd, natioctlfunc, nat);
114145510Sdarrenr				free(nat);
115145510Sdarrenr			  }
116145510Sdarrenr			  resetlexer();
117145510Sdarrenr			}
118145510Sdarrenr	| YY_COMMENT
119145510Sdarrenr	;
120145510Sdarrenr
121145510Sdarrenrassign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
122145510Sdarrenr					  resetlexer();
123145510Sdarrenr					  free($1);
124145510Sdarrenr					  free($3);
125170268Sdarrenr					  yyvarnext = 0;
126145510Sdarrenr					}
127145510Sdarrenr	;
128145510Sdarrenr
129145510Sdarrenrassigning:
130145510Sdarrenr	'='				{ yyvarnext = 1; }
131145510Sdarrenr	;
132145510Sdarrenr
133145510Sdarrenrxx:					{ newnatrule(); }
134145510Sdarrenr	;
135145510Sdarrenr
136145510Sdarrenrrule:	map eol
137145510Sdarrenr	| mapblock eol
138145510Sdarrenr	| redir eol
139145510Sdarrenr	;
140145510Sdarrenr
141145510Sdarrenreol:	| ';'
142145510Sdarrenr	;
143145510Sdarrenr
144145510Sdarrenrmap:	mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
145145510Sdarrenr				{ nat->in_v = 4;
146145510Sdarrenr				  nat->in_inip = $3.a.s_addr;
147145510Sdarrenr				  nat->in_inmsk = $3.m.s_addr;
148145510Sdarrenr				  nat->in_outip = $5.a.s_addr;
149145510Sdarrenr				  nat->in_outmsk = $5.m.s_addr;
150145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
151145510Sdarrenr					strncpy(nat->in_ifnames[1],
152145510Sdarrenr						nat->in_ifnames[0],
153145510Sdarrenr						sizeof(nat->in_ifnames[0]));
154145510Sdarrenr				  if ((nat->in_flags & IPN_TCPUDP) == 0)
155145510Sdarrenr					setnatproto(nat->in_p);
156145510Sdarrenr				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
157145510Sdarrenr				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
158145510Sdarrenr					nat_setgroupmap(nat);
159145510Sdarrenr				}
160145510Sdarrenr	| mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
161145510Sdarrenr				{ nat->in_v = 4;
162145510Sdarrenr				  nat->in_inip = $3.a.s_addr;
163145510Sdarrenr				  nat->in_inmsk = $3.m.s_addr;
164145510Sdarrenr				  nat->in_outip = $5.a.s_addr;
165145510Sdarrenr				  nat->in_outmsk = $5.m.s_addr;
166145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
167145510Sdarrenr					strncpy(nat->in_ifnames[1],
168145510Sdarrenr						nat->in_ifnames[0],
169145510Sdarrenr						sizeof(nat->in_ifnames[0]));
170145510Sdarrenr				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
171145510Sdarrenr				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
172145510Sdarrenr					nat_setgroupmap(nat);
173145510Sdarrenr				}
174145510Sdarrenr	| mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
175145510Sdarrenr				{ nat->in_v = 4;
176145510Sdarrenr				  nat->in_outip = $5.a.s_addr;
177145510Sdarrenr				  nat->in_outmsk = $5.m.s_addr;
178145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
179145510Sdarrenr					strncpy(nat->in_ifnames[1],
180145510Sdarrenr						nat->in_ifnames[0],
181145510Sdarrenr						sizeof(nat->in_ifnames[0]));
182161357Sguido				  if ((suggest_port == 1) &&
183161357Sguido				      (nat->in_flags & IPN_TCPUDP) == 0)
184161357Sguido					nat->in_flags |= IPN_TCPUDP;
185145510Sdarrenr				  if ((nat->in_flags & IPN_TCPUDP) == 0)
186145510Sdarrenr					setnatproto(nat->in_p);
187145510Sdarrenr				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
188145510Sdarrenr				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
189145510Sdarrenr					nat_setgroupmap(nat);
190145510Sdarrenr				}
191145510Sdarrenr	| mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
192145510Sdarrenr				{ nat->in_v = 4;
193145510Sdarrenr				  nat->in_outip = $5.a.s_addr;
194145510Sdarrenr				  nat->in_outmsk = $5.m.s_addr;
195145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
196145510Sdarrenr					strncpy(nat->in_ifnames[1],
197145510Sdarrenr						nat->in_ifnames[0],
198145510Sdarrenr						sizeof(nat->in_ifnames[0]));
199161357Sguido				  if ((suggest_port == 1) &&
200161357Sguido				      (nat->in_flags & IPN_TCPUDP) == 0)
201161357Sguido					nat->in_flags |= IPN_TCPUDP;
202145510Sdarrenr				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
203145510Sdarrenr				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
204145510Sdarrenr					nat_setgroupmap(nat);
205145510Sdarrenr				}
206145510Sdarrenr	;
207145510Sdarrenr
208145510Sdarrenrmapblock:
209145510Sdarrenr	mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
210145510Sdarrenr				{ nat->in_v = 4;
211145510Sdarrenr				  nat->in_inip = $3.a.s_addr;
212145510Sdarrenr				  nat->in_inmsk = $3.m.s_addr;
213145510Sdarrenr				  nat->in_outip = $5.a.s_addr;
214145510Sdarrenr				  nat->in_outmsk = $5.m.s_addr;
215145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
216145510Sdarrenr					strncpy(nat->in_ifnames[1],
217145510Sdarrenr						nat->in_ifnames[0],
218145510Sdarrenr						sizeof(nat->in_ifnames[0]));
219145510Sdarrenr				  if ((nat->in_flags & IPN_TCPUDP) == 0)
220145510Sdarrenr					setnatproto(nat->in_p);
221145510Sdarrenr				  if (((nat->in_redir & NAT_MAPBLK) != 0) ||
222145510Sdarrenr				      ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
223145510Sdarrenr					nat_setgroupmap(nat);
224145510Sdarrenr				}
225145510Sdarrenr	;
226145510Sdarrenr
227145510Sdarrenrredir:	rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
228145510Sdarrenr				{ nat->in_v = 4;
229145510Sdarrenr				  nat->in_outip = $3.a.s_addr;
230145510Sdarrenr				  nat->in_outmsk = $3.m.s_addr;
231145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
232145510Sdarrenr					strncpy(nat->in_ifnames[1],
233145510Sdarrenr						nat->in_ifnames[0],
234145510Sdarrenr						sizeof(nat->in_ifnames[0]));
235145510Sdarrenr				  if ((nat->in_p == 0) &&
236145510Sdarrenr				      ((nat->in_flags & IPN_TCPUDP) == 0) &&
237145510Sdarrenr				      (nat->in_pmin != 0 ||
238145510Sdarrenr				       nat->in_pmax != 0 ||
239145510Sdarrenr				       nat->in_pnext != 0))
240161357Sguido					setnatproto(IPPROTO_TCP);
241145510Sdarrenr				}
242145510Sdarrenr	| rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
243145510Sdarrenr				{ nat->in_v = 4;
244145510Sdarrenr				  if ((nat->in_p == 0) &&
245145510Sdarrenr				      ((nat->in_flags & IPN_TCPUDP) == 0) &&
246145510Sdarrenr				      (nat->in_pmin != 0 ||
247145510Sdarrenr				       nat->in_pmax != 0 ||
248145510Sdarrenr				       nat->in_pnext != 0))
249145510Sdarrenr					setnatproto(IPPROTO_TCP);
250161357Sguido				  if ((suggest_port == 1) &&
251161357Sguido				      (nat->in_flags & IPN_TCPUDP) == 0)
252161357Sguido					nat->in_flags |= IPN_TCPUDP;
253145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
254145510Sdarrenr					strncpy(nat->in_ifnames[1],
255145510Sdarrenr						nat->in_ifnames[0],
256145510Sdarrenr						sizeof(nat->in_ifnames[0]));
257145510Sdarrenr				}
258145510Sdarrenr	| rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
259145510Sdarrenr				{ nat->in_v = 4;
260145510Sdarrenr				  nat->in_outip = $3.a.s_addr;
261145510Sdarrenr				  nat->in_outmsk = $3.m.s_addr;
262145510Sdarrenr				  if (nat->in_ifnames[1][0] == '\0')
263145510Sdarrenr					strncpy(nat->in_ifnames[1],
264145510Sdarrenr						nat->in_ifnames[0],
265145510Sdarrenr						sizeof(nat->in_ifnames[0]));
266145510Sdarrenr				}
267161357Sguido	| rdrit ifnames rdrfrom IPNY_TLATE dip setproto rdroptions
268161357Sguido				{ nat->in_v = 4;
269161357Sguido				  if ((suggest_port == 1) &&
270161357Sguido				      (nat->in_flags & IPN_TCPUDP) == 0)
271161357Sguido					nat->in_flags |= IPN_TCPUDP;
272161357Sguido				  if (nat->in_ifnames[1][0] == '\0')
273161357Sguido					strncpy(nat->in_ifnames[1],
274161357Sguido						nat->in_ifnames[0],
275161357Sguido						sizeof(nat->in_ifnames[0]));
276161357Sguido				}
277145510Sdarrenr	;
278145510Sdarrenr
279161357Sguidoproxy:	| IPNY_PROXY port portspec YY_STR '/' proto
280145510Sdarrenr			{ strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
281145510Sdarrenr			  if (nat->in_dcmp == 0) {
282145510Sdarrenr				nat->in_dport = htons($3);
283145510Sdarrenr			  } else if ($3 != nat->in_dport) {
284145510Sdarrenr				yyerror("proxy port numbers not consistant");
285145510Sdarrenr			  }
286145510Sdarrenr			  setnatproto($6);
287145510Sdarrenr			  free($4);
288145510Sdarrenr			}
289161357Sguido	| IPNY_PROXY port YY_STR YY_STR '/' proto
290145510Sdarrenr			{ int pnum;
291145510Sdarrenr			  strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
292145510Sdarrenr			  pnum = getportproto($3, $6);
293145510Sdarrenr			  if (pnum == -1)
294145510Sdarrenr				yyerror("invalid port number");
295145510Sdarrenr			  nat->in_dport = pnum;
296145510Sdarrenr			  setnatproto($6);
297145510Sdarrenr			  free($3);
298145510Sdarrenr			  free($4);
299145510Sdarrenr			}
300145510Sdarrenr	;
301145510Sdarrenr
302145510Sdarrenrsetproto:
303145510Sdarrenr	| proto				{ if (nat->in_p != 0 ||
304145510Sdarrenr					      nat->in_flags & IPN_TCPUDP)
305145510Sdarrenr						yyerror("protocol set twice");
306145510Sdarrenr					  setnatproto($1);
307145510Sdarrenr					}
308145510Sdarrenr	| IPNY_TCPUDP			{ if (nat->in_p != 0 ||
309145510Sdarrenr					      nat->in_flags & IPN_TCPUDP)
310145510Sdarrenr						yyerror("protocol set twice");
311145510Sdarrenr					  nat->in_flags |= IPN_TCPUDP;
312145510Sdarrenr					  nat->in_p = 0;
313145510Sdarrenr					}
314145510Sdarrenr	| IPNY_TCP '/' IPNY_UDP		{ if (nat->in_p != 0 ||
315145510Sdarrenr					      nat->in_flags & IPN_TCPUDP)
316145510Sdarrenr						yyerror("protocol set twice");
317145510Sdarrenr					  nat->in_flags |= IPN_TCPUDP;
318145510Sdarrenr					  nat->in_p = 0;
319145510Sdarrenr					}
320145510Sdarrenr	;
321145510Sdarrenr
322145510Sdarrenrrhaddr:	addr				{ $$.a = $1.a; $$.m = $1.m; }
323145510Sdarrenr	| IPNY_RANGE ipv4 '-' ipv4
324145510Sdarrenr					{ $$.a = $2; $$.m = $4;
325145510Sdarrenr					  nat->in_flags |= IPN_IPRANGE; }
326145510Sdarrenr	;
327145510Sdarrenr
328145510Sdarrenrdip:
329145510Sdarrenr	hostname			{ nat->in_inip = $1.s_addr;
330145510Sdarrenr					  nat->in_inmsk = 0xffffffff; }
331153881Sguido	| hostname '/' YY_NUMBER	{ if ($3 != 0 || $1.s_addr != 0)
332153881Sguido						yyerror("Only 0/0 supported");
333153881Sguido					  nat->in_inip = 0;
334153881Sguido					  nat->in_inmsk = 0;
335153881Sguido					}
336145510Sdarrenr	| hostname ',' hostname		{ nat->in_flags |= IPN_SPLIT;
337145510Sdarrenr					  nat->in_inip = $1.s_addr;
338145510Sdarrenr					  nat->in_inmsk = $3.s_addr; }
339145510Sdarrenr	;
340145510Sdarrenr
341161357Sguidoport:	IPNY_PORT			{ suggest_port = 1; }
342161357Sguido	;
343161357Sguido
344145510Sdarrenrportspec:
345145510Sdarrenr	YY_NUMBER			{ if ($1 > 65535)	/* Unsigned */
346145510Sdarrenr						yyerror("invalid port number");
347145510Sdarrenr					  else
348145510Sdarrenr						$$ = $1;
349145510Sdarrenr					}
350145510Sdarrenr	| YY_STR			{ if (getport(NULL, $1, &($$)) == -1)
351145510Sdarrenr						yyerror("invalid port number");
352145510Sdarrenr					  $$ = ntohs($$);
353145510Sdarrenr					}
354145510Sdarrenr	;
355145510Sdarrenr
356161357Sguidodport:	| port portspec			{ nat->in_pmin = htons($2);
357170268Sdarrenr					  nat->in_pmax = htons($2); }
358161357Sguido	| port portspec '-' portspec	{ nat->in_pmin = htons($2);
359170268Sdarrenr					  nat->in_pmax = htons($4); }
360161357Sguido	| port portspec ':' portspec	{ nat->in_pmin = htons($2);
361170268Sdarrenr					  nat->in_pmax = htons($4); }
362145510Sdarrenr	;
363145510Sdarrenr
364161357Sguidonport:	port portspec			{ nat->in_pnext = htons($2); }
365161357Sguido	| port '=' portspec		{ nat->in_pnext = htons($3);
366145510Sdarrenr					  nat->in_flags |= IPN_FIXEDDPORT;
367145510Sdarrenr					}
368145510Sdarrenr	;
369145510Sdarrenr
370145510Sdarrenrports:	| IPNY_PORTS YY_NUMBER		{ nat->in_pmin = $2; }
371145510Sdarrenr	| IPNY_PORTS IPNY_AUTO		{ nat->in_flags |= IPN_AUTOPORTMAP; }
372145510Sdarrenr	;
373145510Sdarrenr
374145510Sdarrenrmapit:	IPNY_MAP			{ nat->in_redir = NAT_MAP; }
375145510Sdarrenr	| IPNY_BIMAP			{ nat->in_redir = NAT_BIMAP; }
376145510Sdarrenr	;
377145510Sdarrenr
378145510Sdarrenrrdrit:	IPNY_RDR			{ nat->in_redir = NAT_REDIRECT; }
379145510Sdarrenr	;
380145510Sdarrenr
381145510Sdarrenrmapblockit:
382145510Sdarrenr	IPNY_MAPBLOCK			{ nat->in_redir = NAT_MAPBLK; }
383145510Sdarrenr	;
384145510Sdarrenr
385145510Sdarrenrmapfrom:
386145510Sdarrenr	from sobject IPNY_TO dobject
387145510Sdarrenr	| from sobject '!' IPNY_TO dobject
388145510Sdarrenr					{ nat->in_flags |= IPN_NOTDST; }
389161357Sguido	| from sobject IPNY_TO '!' dobject
390161357Sguido					{ nat->in_flags |= IPN_NOTDST; }
391145510Sdarrenr	;
392145510Sdarrenr
393145510Sdarrenrrdrfrom:
394145510Sdarrenr	from sobject IPNY_TO dobject
395145510Sdarrenr	| '!' from sobject IPNY_TO dobject
396145510Sdarrenr					{ nat->in_flags |= IPN_NOTSRC; }
397161357Sguido	| from '!' sobject IPNY_TO dobject
398161357Sguido					{ nat->in_flags |= IPN_NOTSRC; }
399145510Sdarrenr	;
400145510Sdarrenr
401145510Sdarrenrfrom:	IPNY_FROM			{ nat->in_flags |= IPN_FILTER; }
402145510Sdarrenr	;
403145510Sdarrenr
404145510Sdarrenrifnames:
405145510Sdarrenr	ifname
406145510Sdarrenr	| ifname ',' otherifname
407145510Sdarrenr	;
408145510Sdarrenr
409145510Sdarrenrifname:	YY_STR			{ strncpy(nat->in_ifnames[0], $1,
410145510Sdarrenr					  sizeof(nat->in_ifnames[0]));
411145510Sdarrenr				  nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
412145510Sdarrenr				  free($1);
413145510Sdarrenr				}
414145510Sdarrenr	;
415145510Sdarrenr
416145510Sdarrenrotherifname:
417145510Sdarrenr	YY_STR			{ strncpy(nat->in_ifnames[1], $1,
418145510Sdarrenr					  sizeof(nat->in_ifnames[1]));
419145510Sdarrenr				  nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0';
420145510Sdarrenr				  free($1);
421145510Sdarrenr				}
422145510Sdarrenr	;
423145510Sdarrenr
424145510Sdarrenrmapport:
425145510Sdarrenr	IPNY_PORTMAP tcpudp portspec ':' portspec
426145510Sdarrenr			{ nat->in_pmin = htons($3);
427145510Sdarrenr			  nat->in_pmax = htons($5);
428145510Sdarrenr			}
429145510Sdarrenr	| IPNY_PORTMAP tcpudp IPNY_AUTO
430145510Sdarrenr			{ nat->in_flags |= IPN_AUTOPORTMAP;
431145510Sdarrenr			  nat->in_pmin = htons(1024);
432145510Sdarrenr			  nat->in_pmax = htons(65535);
433145510Sdarrenr			}
434145510Sdarrenr	| IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER
435145510Sdarrenr			{ if (strcmp($2, "icmp") != 0) {
436145510Sdarrenr				yyerror("icmpidmap not followed by icmp");
437145510Sdarrenr			  }
438145510Sdarrenr			  free($2);
439145510Sdarrenr			  if ($3 < 0 || $3 > 65535)
440145510Sdarrenr				yyerror("invalid ICMP Id number");
441145510Sdarrenr			  if ($5 < 0 || $5 > 65535)
442145510Sdarrenr				yyerror("invalid ICMP Id number");
443145510Sdarrenr			  nat->in_flags = IPN_ICMPQUERY;
444145510Sdarrenr			  nat->in_pmin = htons($3);
445145510Sdarrenr			  nat->in_pmax = htons($5);
446145510Sdarrenr			}
447145510Sdarrenr	;
448145510Sdarrenr
449145510Sdarrenrsobject:
450145510Sdarrenr	saddr
451161357Sguido	| saddr port portstuff	{ nat->in_sport = $3.p1;
452145510Sdarrenr					  nat->in_stop = $3.p2;
453145510Sdarrenr					  nat->in_scmp = $3.pc; }
454145510Sdarrenr	;
455145510Sdarrenr
456145510Sdarrenrsaddr:	addr				{ if (nat->in_redir == NAT_REDIRECT) {
457145510Sdarrenr						nat->in_srcip = $1.a.s_addr;
458145510Sdarrenr						nat->in_srcmsk = $1.m.s_addr;
459145510Sdarrenr					  } else {
460145510Sdarrenr						nat->in_inip = $1.a.s_addr;
461145510Sdarrenr						nat->in_inmsk = $1.m.s_addr;
462145510Sdarrenr					  }
463145510Sdarrenr					}
464145510Sdarrenr	;
465145510Sdarrenr
466145510Sdarrenrdobject:
467145510Sdarrenr	daddr
468161357Sguido	| daddr port portstuff	{ nat->in_dport = $3.p1;
469145510Sdarrenr					  nat->in_dtop = $3.p2;
470145510Sdarrenr					  nat->in_dcmp = $3.pc;
471145510Sdarrenr					  if (nat->in_redir == NAT_REDIRECT)
472145510Sdarrenr						nat->in_pmin = htons($3.p1);
473145510Sdarrenr					}
474145510Sdarrenr	;
475145510Sdarrenr
476145510Sdarrenrdaddr:	addr				{ if (nat->in_redir == NAT_REDIRECT) {
477145510Sdarrenr						nat->in_outip = $1.a.s_addr;
478145510Sdarrenr						nat->in_outmsk = $1.m.s_addr;
479145510Sdarrenr					  } else {
480145510Sdarrenr						nat->in_srcip = $1.a.s_addr;
481145510Sdarrenr						nat->in_srcmsk = $1.m.s_addr;
482145510Sdarrenr					  }
483145510Sdarrenr					}
484145510Sdarrenr	;
485145510Sdarrenr
486145510Sdarrenraddr:	IPNY_ANY			{ $$.a.s_addr = 0; $$.m.s_addr = 0; }
487145510Sdarrenr	| nummask			{ $$.a = $1.a; $$.m = $1.m;
488145510Sdarrenr					  $$.a.s_addr &= $$.m.s_addr; }
489145510Sdarrenr	| hostname '/' ipv4		{ $$.a = $1; $$.m = $3;
490145510Sdarrenr					  $$.a.s_addr &= $$.m.s_addr; }
491153881Sguido	| hostname '/' hexnumber	{ $$.a = $1; $$.m.s_addr = htonl($3);
492145510Sdarrenr					  $$.a.s_addr &= $$.m.s_addr; }
493145510Sdarrenr	| hostname IPNY_MASK ipv4	{ $$.a = $1; $$.m = $3;
494145510Sdarrenr					  $$.a.s_addr &= $$.m.s_addr; }
495153881Sguido	| hostname IPNY_MASK hexnumber	{ $$.a = $1; $$.m.s_addr = htonl($3);
496145510Sdarrenr					  $$.a.s_addr &= $$.m.s_addr; }
497145510Sdarrenr	;
498145510Sdarrenr
499145510Sdarrenrnummask:
500145510Sdarrenr	hostname			{ $$.a = $1;
501145510Sdarrenr					  $$.m.s_addr = 0xffffffff; }
502145510Sdarrenr	| hostname '/' YY_NUMBER	{ $$.a = $1;
503145510Sdarrenr					  ntomask(4, $3, &$$.m.s_addr); }
504145510Sdarrenr	;
505145510Sdarrenr
506145510Sdarrenrportstuff:
507145510Sdarrenr	compare portspec		{ $$.pc = $1; $$.p1 = $2; }
508153881Sguido	| portspec range portspec	{ $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
509145510Sdarrenr	;
510145510Sdarrenr
511145510Sdarrenrmapoptions:
512145510Sdarrenr	rr frag age mssclamp nattag setproto
513145510Sdarrenr	;
514145510Sdarrenr
515145510Sdarrenrrdroptions:
516145510Sdarrenr	rr frag age sticky mssclamp rdrproxy nattag
517145510Sdarrenr	;
518145510Sdarrenr
519145510Sdarrenrnattag:	| IPNY_TAG YY_STR		{ strncpy(nat->in_tag.ipt_tag, $2,
520145510Sdarrenr						  sizeof(nat->in_tag.ipt_tag));
521145510Sdarrenr					}
522145510Sdarrenrrr:	| IPNY_ROUNDROBIN		{ nat->in_flags |= IPN_ROUNDR; }
523145510Sdarrenr	;
524145510Sdarrenr
525145510Sdarrenrfrag:	| IPNY_FRAG			{ nat->in_flags |= IPN_FRAG; }
526145510Sdarrenr	;
527145510Sdarrenr
528145510Sdarrenrage:	| IPNY_AGE YY_NUMBER			{ nat->in_age[0] = $2;
529145510Sdarrenr						  nat->in_age[1] = $2; }
530145510Sdarrenr	| IPNY_AGE YY_NUMBER '/' YY_NUMBER	{ nat->in_age[0] = $2;
531145510Sdarrenr						  nat->in_age[1] = $4; }
532145510Sdarrenr	;
533145510Sdarrenr
534145510Sdarrenrsticky:	| IPNY_STICKY			{ if (!(nat->in_flags & IPN_ROUNDR) &&
535145510Sdarrenr					      !(nat->in_flags & IPN_SPLIT)) {
536145510Sdarrenr						fprintf(stderr,
537145510Sdarrenr		"'sticky' for use with round-robin/IP splitting only\n");
538145510Sdarrenr					  } else
539145510Sdarrenr						nat->in_flags |= IPN_STICKY;
540145510Sdarrenr					}
541145510Sdarrenr	;
542145510Sdarrenr
543145510Sdarrenrmssclamp:
544145510Sdarrenr	| IPNY_MSSCLAMP YY_NUMBER		{ nat->in_mssclamp = $2; }
545145510Sdarrenr	;
546145510Sdarrenr
547145510Sdarrenrtcpudp:	| IPNY_TCP			{ setnatproto(IPPROTO_TCP); }
548145510Sdarrenr	| IPNY_UDP			{ setnatproto(IPPROTO_UDP); }
549145510Sdarrenr	| IPNY_TCPUDP			{ nat->in_flags |= IPN_TCPUDP;
550145510Sdarrenr					  nat->in_p = 0;
551145510Sdarrenr					}
552145510Sdarrenr	| IPNY_TCP '/' IPNY_UDP		{ nat->in_flags |= IPN_TCPUDP;
553145510Sdarrenr					  nat->in_p = 0;
554145510Sdarrenr					}
555145510Sdarrenr	;
556145510Sdarrenr
557145510Sdarrenrrdrproxy:
558145510Sdarrenr	IPNY_PROXY YY_STR
559145510Sdarrenr					{ strncpy(nat->in_plabel, $2,
560145510Sdarrenr						  sizeof(nat->in_plabel));
561145510Sdarrenr					  nat->in_dport = nat->in_pnext;
562145510Sdarrenr					  nat->in_dport = htons(nat->in_dport);
563145510Sdarrenr					  free($2);
564145510Sdarrenr					}
565145510Sdarrenr	| proxy				{ if (nat->in_plabel[0] != '\0') {
566145510Sdarrenr						  nat->in_pmin = nat->in_dport;
567145510Sdarrenr						  nat->in_pmax = nat->in_pmin;
568145510Sdarrenr						  nat->in_pnext = nat->in_pmin;
569145510Sdarrenr					  }
570145510Sdarrenr					}
571145510Sdarrenr	;
572145510Sdarrenr
573161357Sguidoproto:	YY_NUMBER			{ $$ = $1;
574161357Sguido					  if ($$ != IPPROTO_TCP &&
575161357Sguido					      $$ != IPPROTO_UDP)
576161357Sguido						suggest_port = 0;
577161357Sguido					}
578145510Sdarrenr	| IPNY_TCP			{ $$ = IPPROTO_TCP; }
579145510Sdarrenr	| IPNY_UDP			{ $$ = IPPROTO_UDP; }
580161357Sguido	| YY_STR			{ $$ = getproto($1); free($1);
581161357Sguido					  if ($$ != IPPROTO_TCP &&
582161357Sguido					      $$ != IPPROTO_UDP)
583161357Sguido						suggest_port = 0;
584161357Sguido					}
585145510Sdarrenr	;
586145510Sdarrenr
587145510Sdarrenrhexnumber:
588145510Sdarrenr	YY_HEX				{ $$ = $1; }
589145510Sdarrenr	;
590145510Sdarrenr
591145510Sdarrenrhostname:
592145510Sdarrenr	YY_STR				{ if (gethost($1, &$$.s_addr) == -1)
593145510Sdarrenr						fprintf(stderr,
594145510Sdarrenr							"Unknown host '%s'\n",
595145510Sdarrenr							$1);
596145510Sdarrenr					  free($1);
597145510Sdarrenr					}
598145510Sdarrenr	| YY_NUMBER			{ $$.s_addr = htonl($1); }
599145510Sdarrenr	| ipv4				{ $$.s_addr = $1.s_addr; }
600145510Sdarrenr	;
601145510Sdarrenr
602145510Sdarrenrcompare:
603145510Sdarrenr	'='				{ $$ = FR_EQUAL; }
604145510Sdarrenr	| YY_CMP_EQ			{ $$ = FR_EQUAL; }
605145510Sdarrenr	| YY_CMP_NE			{ $$ = FR_NEQUAL; }
606145510Sdarrenr	| YY_CMP_LT			{ $$ = FR_LESST; }
607145510Sdarrenr	| YY_CMP_LE			{ $$ = FR_LESSTE; }
608145510Sdarrenr	| YY_CMP_GT			{ $$ = FR_GREATERT; }
609145510Sdarrenr	| YY_CMP_GE			{ $$ = FR_GREATERTE; }
610145510Sdarrenr
611145510Sdarrenrrange:
612145510Sdarrenr	YY_RANGE_OUT			{ $$ = FR_OUTRANGE; }
613145510Sdarrenr	| YY_RANGE_IN			{ $$ = FR_INRANGE; }
614145510Sdarrenr	;
615145510Sdarrenr
616145510Sdarrenripv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
617145510Sdarrenr		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
618145510Sdarrenr			yyerror("Invalid octet string for IP address");
619145510Sdarrenr			return 0;
620145510Sdarrenr		  }
621145510Sdarrenr		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
622145510Sdarrenr		  $$.s_addr = htonl($$.s_addr);
623145510Sdarrenr		}
624145510Sdarrenr	;
625145510Sdarrenr
626145510Sdarrenr%%
627145510Sdarrenr
628145510Sdarrenr
629145510Sdarrenrstatic	wordtab_t	yywords[] = {
630145510Sdarrenr	{ "age",	IPNY_AGE },
631145510Sdarrenr	{ "any",	IPNY_ANY },
632145510Sdarrenr	{ "auto",	IPNY_AUTO },
633145510Sdarrenr	{ "bimap",	IPNY_BIMAP },
634145510Sdarrenr	{ "frag",	IPNY_FRAG },
635145510Sdarrenr	{ "from",	IPNY_FROM },
636145510Sdarrenr	{ "icmpidmap",	IPNY_ICMPIDMAP },
637145510Sdarrenr	{ "mask",	IPNY_MASK },
638145510Sdarrenr	{ "map",	IPNY_MAP },
639145510Sdarrenr	{ "map-block",	IPNY_MAPBLOCK },
640145510Sdarrenr	{ "mssclamp",	IPNY_MSSCLAMP },
641145510Sdarrenr	{ "netmask",	IPNY_MASK },
642145510Sdarrenr	{ "port",	IPNY_PORT },
643145510Sdarrenr	{ "portmap",	IPNY_PORTMAP },
644145510Sdarrenr	{ "ports",	IPNY_PORTS },
645145510Sdarrenr	{ "proxy",	IPNY_PROXY },
646145510Sdarrenr	{ "range",	IPNY_RANGE },
647145510Sdarrenr	{ "rdr",	IPNY_RDR },
648145510Sdarrenr	{ "round-robin",IPNY_ROUNDROBIN },
649145510Sdarrenr	{ "sticky",	IPNY_STICKY },
650145510Sdarrenr	{ "tag",	IPNY_TAG },
651145510Sdarrenr	{ "tcp",	IPNY_TCP },
652145510Sdarrenr	{ "tcpudp",	IPNY_TCPUDP },
653145510Sdarrenr	{ "to",		IPNY_TO },
654145510Sdarrenr	{ "udp",	IPNY_UDP },
655145510Sdarrenr	{ "-",		'-' },
656145510Sdarrenr	{ "->",		IPNY_TLATE },
657145510Sdarrenr	{ "eq",		YY_CMP_EQ },
658145510Sdarrenr	{ "ne",		YY_CMP_NE },
659145510Sdarrenr	{ "lt",		YY_CMP_LT },
660145510Sdarrenr	{ "gt",		YY_CMP_GT },
661145510Sdarrenr	{ "le",		YY_CMP_LE },
662145510Sdarrenr	{ "ge",		YY_CMP_GE },
663145510Sdarrenr	{ NULL,		0 }
664145510Sdarrenr};
665145510Sdarrenr
666145510Sdarrenr
667145510Sdarrenrint ipnat_parsefile(fd, addfunc, ioctlfunc, filename)
668145510Sdarrenrint fd;
669145510Sdarrenraddfunc_t addfunc;
670145510Sdarrenrioctlfunc_t ioctlfunc;
671145510Sdarrenrchar *filename;
672145510Sdarrenr{
673145510Sdarrenr	FILE *fp = NULL;
674145510Sdarrenr	char *s;
675145510Sdarrenr
676145510Sdarrenr	(void) yysettab(yywords);
677145510Sdarrenr
678145510Sdarrenr	s = getenv("YYDEBUG");
679145510Sdarrenr	if (s)
680145510Sdarrenr		yydebug = atoi(s);
681145510Sdarrenr	else
682145510Sdarrenr		yydebug = 0;
683145510Sdarrenr
684145510Sdarrenr	if (strcmp(filename, "-")) {
685145510Sdarrenr		fp = fopen(filename, "r");
686145510Sdarrenr		if (!fp) {
687145510Sdarrenr			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
688145510Sdarrenr				STRERROR(errno));
689145510Sdarrenr			return -1;
690145510Sdarrenr		}
691145510Sdarrenr	} else
692145510Sdarrenr		fp = stdin;
693145510Sdarrenr
694145510Sdarrenr	while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1)
695145510Sdarrenr		;
696145510Sdarrenr	if (fp != NULL)
697145510Sdarrenr		fclose(fp);
698145510Sdarrenr	return 0;
699145510Sdarrenr}
700145510Sdarrenr
701145510Sdarrenr
702145510Sdarrenrint ipnat_parsesome(fd, addfunc, ioctlfunc, fp)
703145510Sdarrenrint fd;
704145510Sdarrenraddfunc_t addfunc;
705145510Sdarrenrioctlfunc_t ioctlfunc;
706145510SdarrenrFILE *fp;
707145510Sdarrenr{
708145510Sdarrenr	char *s;
709145510Sdarrenr	int i;
710145510Sdarrenr
711145510Sdarrenr	yylineNum = 1;
712145510Sdarrenr
713145510Sdarrenr	natfd = fd;
714145510Sdarrenr	nataddfunc = addfunc;
715145510Sdarrenr	natioctlfunc = ioctlfunc;
716145510Sdarrenr
717145510Sdarrenr	if (feof(fp))
718145510Sdarrenr		return 0;
719145510Sdarrenr	i = fgetc(fp);
720145510Sdarrenr	if (i == EOF)
721145510Sdarrenr		return 0;
722145510Sdarrenr	if (ungetc(i, fp) == EOF)
723145510Sdarrenr		return 0;
724145510Sdarrenr	if (feof(fp))
725145510Sdarrenr		return 0;
726145510Sdarrenr	s = getenv("YYDEBUG");
727145510Sdarrenr	if (s)
728145510Sdarrenr		yydebug = atoi(s);
729145510Sdarrenr	else
730145510Sdarrenr		yydebug = 0;
731145510Sdarrenr
732145510Sdarrenr	yyin = fp;
733145510Sdarrenr	yyparse();
734145510Sdarrenr	return 1;
735145510Sdarrenr}
736145510Sdarrenr
737145510Sdarrenr
738145510Sdarrenrstatic void newnatrule()
739145510Sdarrenr{
740145510Sdarrenr	ipnat_t *n;
741145510Sdarrenr
742145510Sdarrenr	n = calloc(1, sizeof(*n));
743145510Sdarrenr	if (n == NULL)
744145510Sdarrenr		return;
745145510Sdarrenr
746145510Sdarrenr	if (nat == NULL)
747145510Sdarrenr		nattop = nat = n;
748145510Sdarrenr	else {
749145510Sdarrenr		nat->in_next = n;
750145510Sdarrenr		nat = n;
751145510Sdarrenr	}
752161357Sguido
753161357Sguido	suggest_port = 0;
754145510Sdarrenr}
755145510Sdarrenr
756145510Sdarrenr
757145510Sdarrenrstatic void setnatproto(p)
758145510Sdarrenrint p;
759145510Sdarrenr{
760145510Sdarrenr	nat->in_p = p;
761145510Sdarrenr
762145510Sdarrenr	switch (p)
763145510Sdarrenr	{
764145510Sdarrenr	case IPPROTO_TCP :
765145510Sdarrenr		nat->in_flags |= IPN_TCP;
766145510Sdarrenr		nat->in_flags &= ~IPN_UDP;
767145510Sdarrenr		break;
768145510Sdarrenr	case IPPROTO_UDP :
769145510Sdarrenr		nat->in_flags |= IPN_UDP;
770145510Sdarrenr		nat->in_flags &= ~IPN_TCP;
771145510Sdarrenr		break;
772145510Sdarrenr	case IPPROTO_ICMP :
773145510Sdarrenr		nat->in_flags &= ~IPN_TCPUDP;
774145510Sdarrenr		if (!(nat->in_flags & IPN_ICMPQUERY)) {
775145510Sdarrenr			nat->in_dcmp = 0;
776145510Sdarrenr			nat->in_scmp = 0;
777145510Sdarrenr			nat->in_pmin = 0;
778145510Sdarrenr			nat->in_pmax = 0;
779145510Sdarrenr			nat->in_pnext = 0;
780145510Sdarrenr		}
781145510Sdarrenr		break;
782145510Sdarrenr	default :
783145510Sdarrenr		if ((nat->in_redir & NAT_MAPBLK) == 0) {
784145510Sdarrenr			nat->in_flags &= ~IPN_TCPUDP;
785145510Sdarrenr			nat->in_dcmp = 0;
786145510Sdarrenr			nat->in_scmp = 0;
787145510Sdarrenr			nat->in_pmin = 0;
788145510Sdarrenr			nat->in_pmax = 0;
789145510Sdarrenr			nat->in_pnext = 0;
790145510Sdarrenr		}
791145510Sdarrenr		break;
792145510Sdarrenr	}
793145510Sdarrenr
794145510Sdarrenr	if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
795145510Sdarrenr		nat->in_flags &= ~IPN_FIXEDDPORT;
796145510Sdarrenr}
797145510Sdarrenr
798145510Sdarrenr
799145510Sdarrenrvoid ipnat_addrule(fd, ioctlfunc, ptr)
800145510Sdarrenrint fd;
801145510Sdarrenrioctlfunc_t ioctlfunc;
802145510Sdarrenrvoid *ptr;
803145510Sdarrenr{
804145510Sdarrenr	ioctlcmd_t add, del;
805145510Sdarrenr	ipfobj_t obj;
806145510Sdarrenr	ipnat_t *ipn;
807145510Sdarrenr
808145510Sdarrenr	ipn = ptr;
809145510Sdarrenr	bzero((char *)&obj, sizeof(obj));
810145510Sdarrenr	obj.ipfo_rev = IPFILTER_VERSION;
811145510Sdarrenr	obj.ipfo_size = sizeof(ipnat_t);
812145510Sdarrenr	obj.ipfo_type = IPFOBJ_IPNAT;
813145510Sdarrenr	obj.ipfo_ptr = ptr;
814145510Sdarrenr	add = 0;
815145510Sdarrenr	del = 0;
816145510Sdarrenr
817145510Sdarrenr	if ((opts & OPT_DONOTHING) != 0)
818145510Sdarrenr		fd = -1;
819145510Sdarrenr
820145510Sdarrenr	if (opts & OPT_ZERORULEST) {
821145510Sdarrenr		add = SIOCZRLST;
822145510Sdarrenr	} else if (opts & OPT_INACTIVE) {
823145510Sdarrenr		add = SIOCADNAT;
824145510Sdarrenr		del = SIOCRMNAT;
825145510Sdarrenr	} else {
826145510Sdarrenr		add = SIOCADNAT;
827145510Sdarrenr		del = SIOCRMNAT;
828145510Sdarrenr	}
829145510Sdarrenr
830161357Sguido	if ((opts & OPT_VERBOSE) != 0)
831145510Sdarrenr		printnat(ipn, opts);
832145510Sdarrenr
833145510Sdarrenr	if (opts & OPT_DEBUG)
834145510Sdarrenr		binprint(ipn, sizeof(*ipn));
835145510Sdarrenr
836145510Sdarrenr	if ((opts & OPT_ZERORULEST) != 0) {
837145510Sdarrenr		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
838145510Sdarrenr			if ((opts & OPT_DONOTHING) == 0) {
839145510Sdarrenr				fprintf(stderr, "%d:", yylineNum);
840145510Sdarrenr				perror("ioctl(SIOCZRLST)");
841145510Sdarrenr			}
842145510Sdarrenr		} else {
843145510Sdarrenr#ifdef	USE_QUAD_T
844145510Sdarrenr/*
845145510Sdarrenr			printf("hits %qd bytes %qd ",
846145510Sdarrenr				(long long)fr->fr_hits,
847145510Sdarrenr				(long long)fr->fr_bytes);
848145510Sdarrenr*/
849145510Sdarrenr#else
850145510Sdarrenr/*
851145510Sdarrenr			printf("hits %ld bytes %ld ",
852145510Sdarrenr				fr->fr_hits, fr->fr_bytes);
853145510Sdarrenr*/
854145510Sdarrenr#endif
855145510Sdarrenr			printnat(ipn, opts);
856145510Sdarrenr		}
857145510Sdarrenr	} else if ((opts & OPT_REMOVE) != 0) {
858145510Sdarrenr		if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
859145510Sdarrenr			if ((opts & OPT_DONOTHING) == 0) {
860145510Sdarrenr				fprintf(stderr, "%d:", yylineNum);
861145510Sdarrenr				perror("ioctl(delete nat rule)");
862145510Sdarrenr			}
863145510Sdarrenr		}
864145510Sdarrenr	} else {
865145510Sdarrenr		if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
866145510Sdarrenr			if ((opts & OPT_DONOTHING) == 0) {
867145510Sdarrenr				fprintf(stderr, "%d:", yylineNum);
868145510Sdarrenr				perror("ioctl(add/insert nat rule)");
869145510Sdarrenr			}
870145510Sdarrenr		}
871145510Sdarrenr	}
872145510Sdarrenr}
873