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