xref: /freebsd/sbin/ipf/libipf/printnat.c (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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(ipnat_t *np, int opts)
25 {
26 	struct protoent *pr;
27 	char *base;
28 	int family;
29 	int proto;
30 
31 	if (np->in_v[0] == 4)
32 		family = AF_INET;
33 #ifdef USE_INET6
34 	else if (np->in_v[0] == 6)
35 		family = AF_INET6;
36 #endif
37 	else
38 		family = AF_UNSPEC;
39 
40 	if (np->in_flags & IPN_NO)
41 		PRINTF("no ");
42 
43 	switch (np->in_redir)
44 	{
45 	case NAT_REDIRECT|NAT_ENCAP :
46 		PRINTF("encap in on");
47 		proto = np->in_pr[0];
48 		break;
49 	case NAT_MAP|NAT_ENCAP :
50 		PRINTF("encap out on");
51 		proto = np->in_pr[1];
52 		break;
53 	case NAT_REDIRECT|NAT_DIVERTUDP :
54 		PRINTF("divert in on");
55 		proto = np->in_pr[0];
56 		break;
57 	case NAT_MAP|NAT_DIVERTUDP :
58 		PRINTF("divert out on");
59 		proto = np->in_pr[1];
60 		break;
61 	case NAT_REDIRECT|NAT_REWRITE :
62 		PRINTF("rewrite in on");
63 		proto = np->in_pr[0];
64 		break;
65 	case NAT_MAP|NAT_REWRITE :
66 		PRINTF("rewrite out on");
67 		proto = np->in_pr[1];
68 		break;
69 	case NAT_REDIRECT :
70 		PRINTF("rdr");
71 		proto = np->in_pr[0];
72 		break;
73 	case NAT_MAP :
74 		PRINTF("map");
75 		proto = np->in_pr[1];
76 		break;
77 	case NAT_MAPBLK :
78 		PRINTF("map-block");
79 		proto = np->in_pr[1];
80 		break;
81 	case NAT_BIMAP :
82 		PRINTF("bimap");
83 		proto = np->in_pr[0];
84 		break;
85 	default :
86 		FPRINTF(stderr, "unknown value for in_redir: %#x\n",
87 			np->in_redir);
88 		proto = np->in_pr[0];
89 		break;
90 	}
91 
92 	pr = getprotobynumber(proto);
93 
94 	base = np->in_names;
95 	if (!strcmp(base + np->in_ifnames[0], "-"))
96 		PRINTF(" \"%s\"", base + np->in_ifnames[0]);
97 	else
98 		PRINTF(" %s", base + np->in_ifnames[0]);
99 	if ((np->in_ifnames[1] != -1) &&
100 	    (strcmp(base + np->in_ifnames[0], base + np->in_ifnames[1]) != 0)) {
101 		if (!strcmp(base + np->in_ifnames[1], "-"))
102 			PRINTF(",\"%s\"", base + np->in_ifnames[1]);
103 		else
104 			PRINTF(",%s", base + np->in_ifnames[1]);
105 	}
106 	putchar(' ');
107 
108 	if (family == AF_INET6)
109 		PRINTF("inet6 ");
110 
111 	if (np->in_redir & (NAT_REWRITE|NAT_ENCAP|NAT_DIVERTUDP)) {
112 		if ((proto != 0) || (np->in_flags & IPN_TCPUDP)) {
113 			PRINTF("proto ");
114 			printproto(pr, proto, np);
115 			putchar(' ');
116 		}
117 	}
118 
119 	if (np->in_flags & IPN_FILTER) {
120 		if (np->in_flags & IPN_NOTSRC)
121 			PRINTF("! ");
122 		PRINTF("from ");
123 		printnataddr(np->in_v[0], np->in_names, &np->in_osrc,
124 			     np->in_ifnames[0]);
125 		if (np->in_scmp)
126 			printportcmp(proto, &np->in_tuc.ftu_src);
127 
128 		if (np->in_flags & IPN_NOTDST)
129 			PRINTF(" !");
130 		PRINTF(" to ");
131 		printnataddr(np->in_v[0], np->in_names, &np->in_odst,
132 			     np->in_ifnames[0]);
133 		if (np->in_dcmp)
134 			printportcmp(proto, &np->in_tuc.ftu_dst);
135 	}
136 
137 	if (np->in_redir & (NAT_ENCAP|NAT_DIVERTUDP)) {
138 		PRINTF(" -> src ");
139 		printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
140 			     np->in_ifnames[0]);
141 		if ((np->in_redir & NAT_DIVERTUDP) != 0)
142 			PRINTF(",%u", np->in_spmin);
143 		PRINTF(" dst ");
144 		printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
145 			     np->in_ifnames[0]);
146 		if ((np->in_redir & NAT_DIVERTUDP) != 0)
147 			PRINTF(",%u udp", np->in_dpmin);
148 		if ((np->in_flags & IPN_PURGE) != 0)
149 			PRINTF(" purge");
150 		PRINTF(";\n");
151 
152 	} else if (np->in_redir & NAT_REWRITE) {
153 		PRINTF(" -> src ");
154 		if (np->in_nsrc.na_atype == FRI_LOOKUP &&
155 		    np->in_nsrc.na_type == IPLT_DSTLIST) {
156 			PRINTF("dstlist/");
157 			if (np->in_nsrc.na_subtype == 0)
158 				PRINTF("%d", np->in_nsrc.na_num);
159 			else
160 				PRINTF("%s", base + np->in_nsrc.na_num);
161 		} else {
162 			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
163 				     np->in_ifnames[0]);
164 		}
165 		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
166 		    (np->in_spmin != 0)) {
167 			if ((np->in_flags & IPN_FIXEDSPORT) != 0) {
168 				PRINTF(",port = %u", np->in_spmin);
169 			} else {
170 				PRINTF(",%u", np->in_spmin);
171 				if (np->in_spmax != np->in_spmin)
172 					PRINTF("-%u", np->in_spmax);
173 			}
174 		}
175 		PRINTF(" dst ");
176 		if (np->in_ndst.na_atype == FRI_LOOKUP &&
177 		    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