1 /* $NetBSD: printnat.c,v 1.4 2018/02/04 08:19:42 mrg Exp $ */
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 __attribute__((__used__)) const char rcsid[] = "@(#)Id: printnat.c,v 1.1.1.2 2012/07/22 13:44:41 darrenr Exp $";
17 #endif
18
19
20 /*
21 * Print out a NAT rule
22 */
23 void
printnat(np,opts)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