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