xref: /netbsd-src/external/bsd/ipf/dist/lib/printnat.c (revision b757af438b42b93f8c6571f026d8b8ef3eaf5fc9)
1 /*	$NetBSD: printnat.c,v 1.1.1.1 2012/03/23 21:20:10 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2009 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 proto;
31 
32 	if (np->in_flags & IPN_NO)
33 		PRINTF("no ");
34 
35 	switch (np->in_redir)
36 	{
37 	case NAT_REDIRECT|NAT_ENCAP :
38 		PRINTF("encap in on");
39 		proto = np->in_pr[0];
40 		break;
41 	case NAT_MAP|NAT_ENCAP :
42 		PRINTF("encap out on");
43 		proto = np->in_pr[1];
44 		break;
45 	case NAT_REDIRECT|NAT_DIVERTUDP :
46 		PRINTF("divert in on");
47 		proto = np->in_pr[0];
48 		break;
49 	case NAT_MAP|NAT_DIVERTUDP :
50 		PRINTF("divert out on");
51 		proto = np->in_pr[1];
52 		break;
53 	case NAT_REDIRECT|NAT_REWRITE :
54 		PRINTF("rewrite in on");
55 		proto = np->in_pr[0];
56 		break;
57 	case NAT_MAP|NAT_REWRITE :
58 		PRINTF("rewrite out on");
59 		proto = np->in_pr[1];
60 		break;
61 	case NAT_REDIRECT :
62 		PRINTF("rdr");
63 		proto = np->in_pr[0];
64 		break;
65 	case NAT_MAP :
66 		PRINTF("map");
67 		proto = np->in_pr[1];
68 		break;
69 	case NAT_MAPBLK :
70 		PRINTF("map-block");
71 		proto = np->in_pr[1];
72 		break;
73 	case NAT_BIMAP :
74 		PRINTF("bimap");
75 		proto = np->in_pr[0];
76 		break;
77 	default :
78 		FPRINTF(stderr, "unknown value for in_redir: %#x\n",
79 			np->in_redir);
80 		proto = np->in_pr[0];
81 		break;
82 	}
83 
84 	pr = getprotobynumber(proto);
85 
86 	base = np->in_names;
87 	if (!strcmp(base + np->in_ifnames[0], "-"))
88 		PRINTF(" \"%s\"", base + np->in_ifnames[0]);
89 	else
90 		PRINTF(" %s", base + np->in_ifnames[0]);
91 	if ((np->in_ifnames[1] != -1) &&
92 	    (strcmp(base + np->in_ifnames[0], base + np->in_ifnames[1]) != 0)) {
93 		if (!strcmp(base + np->in_ifnames[1], "-"))
94 			PRINTF(",\"%s\"", base + np->in_ifnames[1]);
95 		else
96 			PRINTF(",%s", base + np->in_ifnames[1]);
97 	}
98 	putchar(' ');
99 
100 	if (np->in_redir & (NAT_REWRITE|NAT_ENCAP|NAT_DIVERTUDP)) {
101 		if ((proto != 0) || (np->in_flags & IPN_TCPUDP)) {
102 			PRINTF("proto ");
103 			printproto(pr, proto, np);
104 			putchar(' ');
105 		}
106 	}
107 
108 	if (np->in_flags & IPN_FILTER) {
109 		if (np->in_flags & IPN_NOTSRC)
110 			PRINTF("! ");
111 		PRINTF("from ");
112 		printnataddr(np->in_v[0], np->in_names, &np->in_osrc,
113 			     np->in_ifnames[0]);
114 		if (np->in_scmp)
115 			printportcmp(proto, &np->in_tuc.ftu_src);
116 
117 		if (np->in_flags & IPN_NOTDST)
118 			PRINTF(" !");
119 		PRINTF(" to ");
120 		printnataddr(np->in_v[0], np->in_names, &np->in_odst,
121 			     np->in_ifnames[0]);
122 		if (np->in_dcmp)
123 			printportcmp(proto, &np->in_tuc.ftu_dst);
124 	}
125 
126 	if (np->in_redir & (NAT_ENCAP|NAT_DIVERTUDP)) {
127 		PRINTF(" -> src ");
128 		printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
129 			     np->in_ifnames[0]);
130 		if ((np->in_redir & NAT_DIVERTUDP) != 0)
131 			PRINTF(",%u", np->in_spmin);
132 		PRINTF(" dst ");
133 		printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
134 			     np->in_ifnames[0]);
135 		if ((np->in_redir & NAT_DIVERTUDP) != 0)
136 			PRINTF(",%u udp", np->in_dpmin);
137 		PRINTF(";\n");
138 
139 	} else if (np->in_redir & NAT_REWRITE) {
140 		PRINTF(" -> src ");
141 		if (np->in_nsrc.na_type == IPLT_DSTLIST) {
142 			PRINTF("dstlist/");
143 			if (np->in_nsrc.na_subtype == 0)
144 				PRINTF("%d", np->in_nsrc.na_num);
145 			else
146 				PRINTF("%s", base + np->in_nsrc.na_num);
147 		} else {
148 			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
149 				     np->in_ifnames[0]);
150 		}
151 		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
152 		    (np->in_spmin != 0)) {
153 			if ((np->in_flags & IPN_FIXEDSPORT) != 0) {
154 				PRINTF(",port = %u", np->in_spmin);
155 			} else {
156 				PRINTF(",%u", np->in_spmin);
157 				if (np->in_spmax != np->in_spmin)
158 					PRINTF("-%u", np->in_spmax);
159 			}
160 		}
161 		PRINTF(" dst ");
162 		if (np->in_ndst.na_type == IPLT_DSTLIST) {
163 			PRINTF("dstlist/");
164 			if (np->in_ndst.na_subtype == 0)
165 				PRINTF("%d", np->in_nsrc.na_num);
166 			else
167 				PRINTF("%s", base + np->in_ndst.na_num);
168 		} else {
169 			printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
170 				     np->in_ifnames[0]);
171 		}
172 		if ((((np->in_flags & IPN_TCPUDP) != 0)) &&
173 		    (np->in_dpmin != 0)) {
174 			if ((np->in_flags & IPN_FIXEDDPORT) != 0) {
175 				PRINTF(",port = %u", np->in_dpmin);
176 			} else {
177 				PRINTF(",%u", np->in_dpmin);
178 				if (np->in_dpmax != np->in_dpmin)
179 					PRINTF("-%u", np->in_dpmax);
180 			}
181 		}
182 		PRINTF(";\n");
183 
184 	} else if (np->in_redir == NAT_REDIRECT) {
185 		if (!(np->in_flags & IPN_FILTER)) {
186 			printnataddr(np->in_v[0], np->in_names, &np->in_odst,
187 				     np->in_ifnames[0]);
188 			if (np->in_flags & IPN_TCPUDP) {
189 				PRINTF(" port %d", np->in_odport);
190 				if (np->in_odport != np->in_dtop)
191 					PRINTF("-%d", np->in_dtop);
192 			}
193 		}
194 		if (np->in_flags & IPN_NO) {
195 			putchar(' ');
196 			printproto(pr, proto, np);
197 			PRINTF(";\n");
198 			return;
199 		}
200 		PRINTF(" -> ");
201 		printnataddr(np->in_v[1], np->in_names, &np->in_ndst,
202 			     np->in_ifnames[0]);
203 		if (np->in_flags & IPN_TCPUDP) {
204 			if ((np->in_flags & IPN_FIXEDDPORT) != 0)
205 				PRINTF(" port = %d", np->in_dpmin);
206 			else {
207 				PRINTF(" port %d", np->in_dpmin);
208 				if (np->in_dpmin != np->in_dpmax)
209 					PRINTF("-%d", np->in_dpmax);
210 			}
211 		}
212 		putchar(' ');
213 		printproto(pr, proto, np);
214 		if (np->in_flags & IPN_ROUNDR)
215 			PRINTF(" round-robin");
216 		if (np->in_flags & IPN_FRAG)
217 			PRINTF(" frag");
218 		if (np->in_age[0] != 0 || np->in_age[1] != 0) {
219 			PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]);
220 		}
221 		if (np->in_flags & IPN_STICKY)
222 			PRINTF(" sticky");
223 		if (np->in_mssclamp != 0)
224 			PRINTF(" mssclamp %d", np->in_mssclamp);
225 		if (np->in_plabel != -1)
226 			PRINTF(" proxy %s", np->in_names + np->in_plabel);
227 		if (np->in_tag.ipt_tag[0] != '\0')
228 			PRINTF(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag);
229 		PRINTF("\n");
230 		if (opts & OPT_DEBUG)
231 			PRINTF("\tpmax %u\n", np->in_dpmax);
232 
233 	} else {
234 		int protoprinted = 0;
235 
236 		if (!(np->in_flags & IPN_FILTER)) {
237 			printnataddr(np->in_v[0], np->in_names, &np->in_osrc,
238 				     np->in_ifnames[0]);
239 		}
240 		if (np->in_flags & IPN_NO) {
241 			putchar(' ');
242 			printproto(pr, proto, np);
243 			PRINTF(";\n");
244 			return;
245 		}
246 		PRINTF(" -> ");
247 		if (np->in_flags & IPN_SIPRANGE) {
248 			PRINTF("range ");
249 			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
250 				     np->in_ifnames[0]);
251 		} else {
252 			printnataddr(np->in_v[1], np->in_names, &np->in_nsrc,
253 				     np->in_ifnames[0]);
254 		}
255 		if (np->in_plabel != -1) {
256 			PRINTF(" proxy port ");
257 			if (np->in_odport != 0) {
258 				char *s;
259 
260 				s = portname(proto, np->in_odport);
261 				if (s != NULL)
262 					fputs(s, stdout);
263 				else
264 					fputs("???", stdout);
265 			}
266 			PRINTF(" %s/", np->in_names + np->in_plabel);
267 			printproto(pr, proto, NULL);
268 			protoprinted = 1;
269 		} else if (np->in_redir == NAT_MAPBLK) {
270 			if ((np->in_spmin == 0) &&
271 			    (np->in_flags & IPN_AUTOPORTMAP))
272 				PRINTF(" ports auto");
273 			else
274 				PRINTF(" ports %d", np->in_spmin);
275 			if (opts & OPT_DEBUG)
276 				PRINTF("\n\tip modulous %d", np->in_spmax);
277 
278 		} else if (np->in_spmin || np->in_spmax) {
279 			if (np->in_flags & IPN_ICMPQUERY) {
280 				PRINTF(" icmpidmap ");
281 			} else {
282 				PRINTF(" portmap ");
283 			}
284 			printproto(pr, proto, np);
285 			protoprinted = 1;
286 			if (np->in_flags & IPN_AUTOPORTMAP) {
287 				PRINTF(" auto");
288 				if (opts & OPT_DEBUG)
289 					PRINTF(" [%d:%d %d %d]",
290 					       np->in_spmin, np->in_spmax,
291 					       np->in_ippip, np->in_ppip);
292 			} else {
293 				PRINTF(" %d:%d", np->in_spmin, np->in_spmax);
294 			}
295 		}
296 
297 		if (np->in_flags & IPN_FRAG)
298 			PRINTF(" frag");
299 		if (np->in_age[0] != 0 || np->in_age[1] != 0) {
300 			PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]);
301 		}
302 		if (np->in_mssclamp != 0)
303 			PRINTF(" mssclamp %d", np->in_mssclamp);
304 		if (np->in_tag.ipt_tag[0] != '\0')
305 			PRINTF(" tag %s", np->in_tag.ipt_tag);
306 		if (!protoprinted && (np->in_flags & IPN_TCPUDP || proto)) {
307 			putchar(' ');
308 			printproto(pr, proto, np);
309 		}
310 		PRINTF("\n");
311 		if (opts & OPT_DEBUG) {
312 			struct in_addr nip;
313 
314 			nip.s_addr = htonl(np->in_snip);
315 
316 			PRINTF("\tnextip %s pnext %d\n",
317 			       inet_ntoa(nip), np->in_spnext);
318 		}
319 	}
320 
321 	if (opts & OPT_DEBUG) {
322 		PRINTF("\tspace %lu use %u hits %lu flags %#x proto %d/%d",
323 			np->in_space, np->in_use, np->in_hits,
324 			np->in_flags, np->in_pr[0], np->in_pr[1]);
325 		PRINTF(" hv %u/%u\n", np->in_hv[0], np->in_hv[1]);
326 		PRINTF("\tifp[0] %p ifp[1] %p apr %p\n",
327 			np->in_ifps[0], np->in_ifps[1], np->in_apr);
328 		PRINTF("\ttqehead %p/%p comment %p\n",
329 			np->in_tqehead[0], np->in_tqehead[1], np->in_comment);
330 	}
331 }
332