xref: /freebsd/sbin/ipf/libipf/printnat.c (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
1 /*	$FreeBSD$	*/
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)
16 static const char rcsid[] = "@(#)$Id$";
17 #endif
18 
19 
20 /*
21  * Print out a NAT rule
22  */
23 void
24 printnat(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