printnat.c revision 256281
1/*	$FreeBSD: stable/10/contrib/ipfilter/lib/printnat.c 255332 2013-09-06 23:11:19Z cy $	*/
2
3/*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 *
8 * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
9 */
10
11#include "ipf.h"
12#include "kmem.h"
13
14
15#if !defined(lint)
16static const char rcsid[] = "@(#)$Id$";
17#endif
18
19
20/*
21 * Print out a NAT rule
22 */
23void
24printnat(np, opts)
25	ipnat_t *np;
26	int opts;
27{
28	struct protoent *pr;
29	char *base;
30	int family;
31	int proto;
32
33	if (np->in_v[0] == 4)
34		family = AF_INET;
35#ifdef USE_INET6
36	else if (np->in_v[0] == 6)
37		family = AF_INET6;
38#endif
39	else
40		family = AF_UNSPEC;
41
42	if (np->in_flags & IPN_NO)
43		PRINTF("no ");
44
45	switch (np->in_redir)
46	{
47	case NAT_REDIRECT|NAT_ENCAP :
48		PRINTF("encap in on");
49		proto = np->in_pr[0];
50		break;
51	case NAT_MAP|NAT_ENCAP :
52		PRINTF("encap out on");
53		proto = np->in_pr[1];
54		break;
55	case NAT_REDIRECT|NAT_DIVERTUDP :
56		PRINTF("divert in on");
57		proto = np->in_pr[0];
58		break;
59	case NAT_MAP|NAT_DIVERTUDP :
60		PRINTF("divert out on");
61		proto = np->in_pr[1];
62		break;
63	case NAT_REDIRECT|NAT_REWRITE :
64		PRINTF("rewrite in on");
65		proto = np->in_pr[0];
66		break;
67	case NAT_MAP|NAT_REWRITE :
68		PRINTF("rewrite out on");
69		proto = np->in_pr[1];
70		break;
71	case NAT_REDIRECT :
72		PRINTF("rdr");
73		proto = np->in_pr[0];
74		break;
75	case NAT_MAP :
76		PRINTF("map");
77		proto = np->in_pr[1];
78		break;
79	case NAT_MAPBLK :
80		PRINTF("map-block");
81		proto = np->in_pr[1];
82		break;
83	case NAT_BIMAP :
84		PRINTF("bimap");
85		proto = np->in_pr[0];
86		break;
87	default :
88		FPRINTF(stderr, "unknown value for in_redir: %#x\n",
89			np->in_redir);
90		proto = np->in_pr[0];
91		break;
92	}
93
94	pr = getprotobynumber(proto);
95
96	base = np->in_names;
97	if (!strcmp(base + np->in_ifnames[0], "-"))
98		PRINTF(" \"%s\"", base + np->in_ifnames[0]);
99	else
100		PRINTF(" %s", base + np->in_ifnames[0]);
101	if ((np->in_ifnames[1] != -1) &&
102	    (strcmp(base + np->in_ifnames[0], base + np->in_ifnames[1]) != 0)) {
103		if (!strcmp(base + np->in_ifnames[1], "-"))
104			PRINTF(",\"%s\"", base + np->in_ifnames[1]);
105		else
106			PRINTF(",%s", base + np->in_ifnames[1]);
107	}
108	putchar(' ');
109
110	if (family == AF_INET6)
111		PRINTF("inet6 ");
112
113	if (np->in_redir & (NAT_REWRITE|NAT_ENCAP|NAT_DIVERTUDP)) {
114		if ((proto != 0) || (np->in_flags & IPN_TCPUDP)) {
115			PRINTF("proto ");
116			printproto(pr, proto, np);
117			putchar(' ');
118		}
119	}
120
121	if (np->in_flags & IPN_FILTER) {
122		if (np->in_flags & IPN_NOTSRC)
123			PRINTF("! ");
124		PRINTF("from ");
125		printnataddr(np->in_v[0], np->in_names, &np->in_osrc,
126			     np->in_ifnames[0]);
127		if (np->in_scmp)
128			printportcmp(proto, &np->in_tuc.ftu_src);
129
130		if (np->in_flags & IPN_NOTDST)
131			PRINTF(" !");
132		PRINTF(" to ");
133		printnataddr(np->in_v[0], np->in_names, &np->in_odst,
134			     np->in_ifnames[0]);
135		if (np->in_dcmp)
136			printportcmp(proto, &np->in_tuc.ftu_dst);
137	}
138
139	if (np->in_redir & (NAT_ENCAP|NAT_DIVERTUDP)) {
140		PRINTF(" -> src ");
141		printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
142			     np->in_ifnames[0]);
143		if ((np->in_redir & NAT_DIVERTUDP) != 0)
144			PRINTF(",%u", np->in_spmin);
145		PRINTF(" dst ");
146		printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
147			     np->in_ifnames[0]);
148		if ((np->in_redir & NAT_DIVERTUDP) != 0)
149			PRINTF(",%u udp", np->in_dpmin);
150		if ((np->in_flags & IPN_PURGE) != 0)
151			PRINTF(" purge");
152		PRINTF(";\n");
153
154	} else if (np->in_redir & NAT_REWRITE) {
155		PRINTF(" -> src ");
156		if (np->in_nsrc.na_type == IPLT_DSTLIST) {
157			PRINTF("dstlist/");
158			if (np->in_nsrc.na_subtype == 0)
159				PRINTF("%d", np->in_nsrc.na_num);
160			else
161				PRINTF("%s", base + np->in_nsrc.na_num);
162		} else {
163			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
164				     np->in_ifnames[0]);
165		}
166		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
167		    (np->in_spmin != 0)) {
168			if ((np->in_flags & IPN_FIXEDSPORT) != 0) {
169				PRINTF(",port = %u", np->in_spmin);
170			} else {
171				PRINTF(",%u", np->in_spmin);
172				if (np->in_spmax != np->in_spmin)
173					PRINTF("-%u", np->in_spmax);
174			}
175		}
176		PRINTF(" dst ");
177		if (np->in_ndst.na_type == IPLT_DSTLIST) {
178			PRINTF("dstlist/");
179			if (np->in_ndst.na_subtype == 0)
180				PRINTF("%d", np->in_nsrc.na_num);
181			else
182				PRINTF("%s", base + np->in_ndst.na_num);
183		} else {
184			printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
185				     np->in_ifnames[0]);
186		}
187		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
188		    (np->in_dpmin != 0)) {
189			if ((np->in_flags & IPN_FIXEDDPORT) != 0) {
190				PRINTF(",port = %u", np->in_dpmin);
191			} else {
192				PRINTF(",%u", np->in_dpmin);
193				if (np->in_dpmax != np->in_dpmin)
194					PRINTF("-%u", np->in_dpmax);
195			}
196		}
197		if ((np->in_flags & IPN_PURGE) != 0)
198			PRINTF(" purge");
199		PRINTF(";\n");
200
201	} else if (np->in_redir == NAT_REDIRECT) {
202		if (!(np->in_flags & IPN_FILTER)) {
203			printnataddr(np->in_v[0], np->in_names, &np->in_odst,
204				     np->in_ifnames[0]);
205			if (np->in_flags & IPN_TCPUDP) {
206				PRINTF(" port %d", np->in_odport);
207				if (np->in_odport != np->in_dtop)
208					PRINTF("-%d", np->in_dtop);
209			}
210		}
211		if (np->in_flags & IPN_NO) {
212			putchar(' ');
213			printproto(pr, proto, np);
214			PRINTF(";\n");
215			return;
216		}
217		PRINTF(" -> ");
218		printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
219			     np->in_ifnames[0]);
220		if (np->in_flags & IPN_TCPUDP) {
221			if ((np->in_flags & IPN_FIXEDDPORT) != 0)
222				PRINTF(" port = %d", np->in_dpmin);
223			else {
224				PRINTF(" port %d", np->in_dpmin);
225				if (np->in_dpmin != np->in_dpmax)
226					PRINTF("-%d", np->in_dpmax);
227			}
228		}
229		putchar(' ');
230		printproto(pr, proto, np);
231		if (np->in_flags & IPN_ROUNDR)
232			PRINTF(" round-robin");
233		if (np->in_flags & IPN_FRAG)
234			PRINTF(" frag");
235		if (np->in_age[0] != 0 || np->in_age[1] != 0) {
236			PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]);
237		}
238		if (np->in_flags & IPN_STICKY)
239			PRINTF(" sticky");
240		if (np->in_mssclamp != 0)
241			PRINTF(" mssclamp %d", np->in_mssclamp);
242		if (np->in_plabel != -1)
243			PRINTF(" proxy %s", np->in_names + np->in_plabel);
244		if (np->in_tag.ipt_tag[0] != '\0')
245			PRINTF(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag);
246		if ((np->in_flags & IPN_PURGE) != 0)
247			PRINTF(" purge");
248		PRINTF("\n");
249		if (opts & OPT_DEBUG)
250			PRINTF("\tpmax %u\n", np->in_dpmax);
251
252	} else {
253		int protoprinted = 0;
254
255		if (!(np->in_flags & IPN_FILTER)) {
256			printnataddr(np->in_v[0], np->in_names, &np->in_osrc,
257				     np->in_ifnames[0]);
258		}
259		if (np->in_flags & IPN_NO) {
260			putchar(' ');
261			printproto(pr, proto, np);
262			PRINTF(";\n");
263			return;
264		}
265		PRINTF(" -> ");
266		if (np->in_flags & IPN_SIPRANGE) {
267			PRINTF("range ");
268			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
269				     np->in_ifnames[0]);
270		} else {
271			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
272				     np->in_ifnames[0]);
273		}
274		if (np->in_plabel != -1) {
275			PRINTF(" proxy port ");
276			if (np->in_odport != 0) {
277				char *s;
278
279				s = portname(proto, np->in_odport);
280				if (s != NULL)
281					fputs(s, stdout);
282				else
283					fputs("???", stdout);
284			}
285			PRINTF(" %s/", np->in_names + np->in_plabel);
286			printproto(pr, proto, NULL);
287			protoprinted = 1;
288		} else if (np->in_redir == NAT_MAPBLK) {
289			if ((np->in_spmin == 0) &&
290			    (np->in_flags & IPN_AUTOPORTMAP))
291				PRINTF(" ports auto");
292			else
293				PRINTF(" ports %d", np->in_spmin);
294			if (opts & OPT_DEBUG)
295				PRINTF("\n\tip modulous %d", np->in_spmax);
296
297		} else if (np->in_spmin || np->in_spmax) {
298			if (np->in_flags & IPN_ICMPQUERY) {
299				PRINTF(" icmpidmap ");
300			} else {
301				PRINTF(" portmap ");
302			}
303			printproto(pr, proto, np);
304			protoprinted = 1;
305			if (np->in_flags & IPN_AUTOPORTMAP) {
306				PRINTF(" auto");
307				if (opts & OPT_DEBUG)
308					PRINTF(" [%d:%d %d %d]",
309					       np->in_spmin, np->in_spmax,
310					       np->in_ippip, np->in_ppip);
311			} else {
312				PRINTF(" %d:%d", np->in_spmin, np->in_spmax);
313			}
314			if (np->in_flags & IPN_SEQUENTIAL)
315				PRINTF(" sequential");
316		}
317
318		if (np->in_flags & IPN_FRAG)
319			PRINTF(" frag");
320		if (np->in_age[0] != 0 || np->in_age[1] != 0) {
321			PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]);
322		}
323		if (np->in_mssclamp != 0)
324			PRINTF(" mssclamp %d", np->in_mssclamp);
325		if (np->in_tag.ipt_tag[0] != '\0')
326			PRINTF(" tag %s", np->in_tag.ipt_tag);
327		if (!protoprinted && (np->in_flags & IPN_TCPUDP || proto)) {
328			putchar(' ');
329			printproto(pr, proto, np);
330		}
331		if ((np->in_flags & IPN_PURGE) != 0)
332			PRINTF(" purge");
333		PRINTF("\n");
334		if (opts & OPT_DEBUG) {
335			PRINTF("\tnextip ");
336			printip(family, &np->in_snip);
337			PRINTF(" pnext %d\n", np->in_spnext);
338		}
339	}
340
341	if (opts & OPT_DEBUG) {
342		PRINTF("\tspace %lu use %u hits %lu flags %#x proto %d/%d",
343			np->in_space, np->in_use, np->in_hits,
344			np->in_flags, np->in_pr[0], np->in_pr[1]);
345		PRINTF(" hv %u/%u\n", np->in_hv[0], np->in_hv[1]);
346		PRINTF("\tifp[0] %p ifp[1] %p apr %p\n",
347			np->in_ifps[0], np->in_ifps[1], np->in_apr);
348		PRINTF("\ttqehead %p/%p comment %p\n",
349			np->in_tqehead[0], np->in_tqehead[1], np->in_comment);
350	}
351}
352