printnat.c revision 272987
1/*	$FreeBSD: stable/10/contrib/ipfilter/lib/printnat.c 272987 2014-10-12 16:51:02Z 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_atype == FRI_LOOKUP &&
157		    np->in_nsrc.na_type == IPLT_DSTLIST) {
158			PRINTF("dstlist/");
159			if (np->in_nsrc.na_subtype == 0)
160				PRINTF("%d", np->in_nsrc.na_num);
161			else
162				PRINTF("%s", base + np->in_nsrc.na_num);
163		} else {
164			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
165				     np->in_ifnames[0]);
166		}
167		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
168		    (np->in_spmin != 0)) {
169			if ((np->in_flags & IPN_FIXEDSPORT) != 0) {
170				PRINTF(",port = %u", np->in_spmin);
171			} else {
172				PRINTF(",%u", np->in_spmin);
173				if (np->in_spmax != np->in_spmin)
174					PRINTF("-%u", np->in_spmax);
175			}
176		}
177		PRINTF(" dst ");
178		if (np->in_ndst.na_atype == FRI_LOOKUP &&
179		    np->in_ndst.na_type == IPLT_DSTLIST) {
180			PRINTF("dstlist/");
181			if (np->in_ndst.na_subtype == 0)
182				PRINTF("%d", np->in_nsrc.na_num);
183			else
184				PRINTF("%s", base + np->in_ndst.na_num);
185		} else {
186			printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
187				     np->in_ifnames[0]);
188		}
189		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
190		    (np->in_dpmin != 0)) {
191			if ((np->in_flags & IPN_FIXEDDPORT) != 0) {
192				PRINTF(",port = %u", np->in_dpmin);
193			} else {
194				PRINTF(",%u", np->in_dpmin);
195				if (np->in_dpmax != np->in_dpmin)
196					PRINTF("-%u", np->in_dpmax);
197			}
198		}
199		if ((np->in_flags & IPN_PURGE) != 0)
200			PRINTF(" purge");
201		PRINTF(";\n");
202
203	} else if (np->in_redir == NAT_REDIRECT) {
204		if (!(np->in_flags & IPN_FILTER)) {
205			printnataddr(np->in_v[0], np->in_names, &np->in_odst,
206				     np->in_ifnames[0]);
207			if (np->in_flags & IPN_TCPUDP) {
208				PRINTF(" port %d", np->in_odport);
209				if (np->in_odport != np->in_dtop)
210					PRINTF("-%d", np->in_dtop);
211			}
212		}
213		if (np->in_flags & IPN_NO) {
214			putchar(' ');
215			printproto(pr, proto, np);
216			PRINTF(";\n");
217			return;
218		}
219		PRINTF(" -> ");
220		printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
221			     np->in_ifnames[0]);
222		if (np->in_flags & IPN_TCPUDP) {
223			if ((np->in_flags & IPN_FIXEDDPORT) != 0)
224				PRINTF(" port = %d", np->in_dpmin);
225			else {
226				PRINTF(" port %d", np->in_dpmin);
227				if (np->in_dpmin != np->in_dpmax)
228					PRINTF("-%d", np->in_dpmax);
229			}
230		}
231		putchar(' ');
232		printproto(pr, proto, np);
233		if (np->in_flags & IPN_ROUNDR)
234			PRINTF(" round-robin");
235		if (np->in_flags & IPN_FRAG)
236			PRINTF(" frag");
237		if (np->in_age[0] != 0 || np->in_age[1] != 0) {
238			PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]);
239		}
240		if (np->in_flags & IPN_STICKY)
241			PRINTF(" sticky");
242		if (np->in_mssclamp != 0)
243			PRINTF(" mssclamp %d", np->in_mssclamp);
244		if (np->in_plabel != -1)
245			PRINTF(" proxy %s", np->in_names + np->in_plabel);
246		if (np->in_tag.ipt_tag[0] != '\0')
247			PRINTF(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag);
248		if ((np->in_flags & IPN_PURGE) != 0)
249			PRINTF(" purge");
250		PRINTF("\n");
251		if (opts & OPT_DEBUG)
252			PRINTF("\tpmax %u\n", np->in_dpmax);
253
254	} else {
255		int protoprinted = 0;
256
257		if (!(np->in_flags & IPN_FILTER)) {
258			printnataddr(np->in_v[0], np->in_names, &np->in_osrc,
259				     np->in_ifnames[0]);
260		}
261		if (np->in_flags & IPN_NO) {
262			putchar(' ');
263			printproto(pr, proto, np);
264			PRINTF(";\n");
265			return;
266		}
267		PRINTF(" -> ");
268		if (np->in_flags & IPN_SIPRANGE) {
269			PRINTF("range ");
270			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
271				     np->in_ifnames[0]);
272		} else {
273			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
274				     np->in_ifnames[0]);
275		}
276		if (np->in_plabel != -1) {
277			PRINTF(" proxy port ");
278			if (np->in_odport != 0) {
279				char *s;
280
281				s = portname(proto, np->in_odport);
282				if (s != NULL)
283					fputs(s, stdout);
284				else
285					fputs("???", stdout);
286			}
287			PRINTF(" %s/", np->in_names + np->in_plabel);
288			printproto(pr, proto, NULL);
289			protoprinted = 1;
290		} else if (np->in_redir == NAT_MAPBLK) {
291			if ((np->in_spmin == 0) &&
292			    (np->in_flags & IPN_AUTOPORTMAP))
293				PRINTF(" ports auto");
294			else
295				PRINTF(" ports %d", np->in_spmin);
296			if (opts & OPT_DEBUG)
297				PRINTF("\n\tip modulous %d", np->in_spmax);
298
299		} else if (np->in_spmin || np->in_spmax) {
300			if (np->in_flags & IPN_ICMPQUERY) {
301				PRINTF(" icmpidmap ");
302			} else {
303				PRINTF(" portmap ");
304			}
305			printproto(pr, proto, np);
306			protoprinted = 1;
307			if (np->in_flags & IPN_AUTOPORTMAP) {
308				PRINTF(" auto");
309				if (opts & OPT_DEBUG)
310					PRINTF(" [%d:%d %d %d]",
311					       np->in_spmin, np->in_spmax,
312					       np->in_ippip, np->in_ppip);
313			} else {
314				PRINTF(" %d:%d", np->in_spmin, np->in_spmax);
315			}
316			if (np->in_flags & IPN_SEQUENTIAL)
317				PRINTF(" sequential");
318		}
319
320		if (np->in_flags & IPN_FRAG)
321			PRINTF(" frag");
322		if (np->in_age[0] != 0 || np->in_age[1] != 0) {
323			PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]);
324		}
325		if (np->in_mssclamp != 0)
326			PRINTF(" mssclamp %d", np->in_mssclamp);
327		if (np->in_tag.ipt_tag[0] != '\0')
328			PRINTF(" tag %s", np->in_tag.ipt_tag);
329		if (!protoprinted && (np->in_flags & IPN_TCPUDP || proto)) {
330			putchar(' ');
331			printproto(pr, proto, np);
332		}
333		if ((np->in_flags & IPN_PURGE) != 0)
334			PRINTF(" purge");
335		PRINTF("\n");
336		if (opts & OPT_DEBUG) {
337			PRINTF("\tnextip ");
338			printip(family, &np->in_snip);
339			PRINTF(" pnext %d\n", np->in_spnext);
340		}
341	}
342
343	if (opts & OPT_DEBUG) {
344		PRINTF("\tspace %lu use %u hits %lu flags %#x proto %d/%d",
345			np->in_space, np->in_use, np->in_hits,
346			np->in_flags, np->in_pr[0], np->in_pr[1]);
347		PRINTF(" hv %u/%u\n", np->in_hv[0], np->in_hv[1]);
348		PRINTF("\tifp[0] %p ifp[1] %p apr %p\n",
349			np->in_ifps[0], np->in_ifps[1], np->in_apr);
350		PRINTF("\ttqehead %p/%p comment %p\n",
351			np->in_tqehead[0], np->in_tqehead[1], np->in_comment);
352	}
353}
354