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