2 * Copyright (C) 1993-2002 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
8 #if defined(__sgi) && (IRIX > 602)
9 # include <sys/ptimers.h>
15 #include <sys/types.h>
16 #if !defined(__SVR4) && !defined(__svr4__)
19 #include <sys/byteorder.h>
22 #include <sys/param.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
29 # include <sys/ioccom.h>
30 # include <sys/sysmacros.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/tcp.h>
37 #if __FreeBSD_version >= 300000
38 # include <net/if_var.h>
41 #include <arpa/nameser.h>
42 #include <arpa/inet.h>
46 #include "netinet/ip_compat.h"
47 #include "netinet/ip_fil.h"
48 #include "netinet/ip_nat.h"
49 #include "netinet/ip_state.h"
50 #include "netinet/ip_proxy.h"
54 #if defined(sun) && !SOLARIS2
55 # define STRERROR(x) sys_errlist[x]
56 extern char *sys_errlist
[];
58 # define STRERROR(x) strerror(x)
62 static const char sccsid
[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
63 static const char rcsid
[] = "@(#)$Id: ipnat.c,v 2.16.2.25 2003/06/05 14:00:28 darrenr Exp $";
68 #define bzero(a,b) memset(a,0,b)
71 char thishost
[MAXHOSTNAMELEN
];
76 extern ipnat_t
*natparse
__P((char *, int));
78 extern void natparsefile
__P((int, char *, int));
79 extern void printnat
__P((ipnat_t
*, int));
80 extern void printactivenat
__P((nat_t
*, int));
81 extern void printhostmap
__P((hostmap_t
*, u_int
));
82 extern char *getsumd
__P((u_32_t
));
84 static int dostats
__P((natstat_t
*, int));
85 static int flushtable
__P((int, int));
86 void usage
__P((char *));
87 int countbits
__P((u_32_t
));
88 char *getnattype
__P((ipnat_t
*));
89 int main
__P((int, char*[]));
90 void printaps
__P((ap_session_t
*, int));
91 static int showhostmap
__P((natstat_t
*nsp
));
92 static int natstat_dead
__P((natstat_t
*, char *));
98 fprintf(stderr
, "Usage: %s [-CFhlnrsv] [-f filename]\n", name
);
107 natstat_t ns
, *nsp
= &ns
;
108 char *file
, *core
, *kernel
;
109 int fd
, opts
, c
, mode
;
118 while ((c
= getopt(argc
, argv
, "CdFf:hlM:N:nrsv")) != -1)
168 if ((kernel
!= NULL
) || (core
!= NULL
)) {
169 (void) setgid(getgid());
170 (void) setuid(getuid());
173 bzero((char *)&ns
, sizeof(ns
));
175 gethostname(thishost
, sizeof(thishost
));
176 thishost
[sizeof(thishost
) - 1] = '\0';
178 if (!(opts
& OPT_NODO
) && (kernel
== NULL
) && (core
== NULL
)) {
179 if (openkmem(kernel
, core
) == -1)
182 if (((fd
= open(IPL_NAT
, mode
)) == -1) &&
183 ((fd
= open(IPL_NAT
, O_RDONLY
)) == -1)) {
184 (void) fprintf(stderr
, "%s: open: %s\n", IPL_NAT
,
187 fprintf(stderr
, "IPFilter enabled?\n");
190 if (ioctl(fd
, SIOCGNATS
, &nsp
) == -1) {
191 perror("ioctl(SIOCGNATS)");
194 (void) setgid(getgid());
195 (void) setuid(getuid());
196 } else if ((kernel
!= NULL
) || (core
!= NULL
)) {
197 if (openkmem(kernel
, core
) == -1)
200 if (natstat_dead(nsp
, kernel
))
202 if (opts
& (OPT_LIST
|OPT_STAT
)) {
203 if (dostats(nsp
, opts
))
209 if (opts
& (OPT_FLUSH
|OPT_CLEAR
))
210 if (flushtable(fd
, opts
))
213 /* NB natparsefile exits with nonzero in case of error */
214 natparsefile(fd
, file
, opts
);
216 if (opts
& (OPT_LIST
|OPT_STAT
))
217 if (dostats(nsp
, opts
))
220 /* TBD why not exit(0)? */
226 * Read NAT statistic information in using a symbol table and memory file
227 * rather than doing ioctl's.
229 static int natstat_dead(nsp
, kernel
)
233 struct nlist nat_nlist
[10] = {
234 { "nat_table" }, /* 0 */
237 { "ipf_nattable_sz" },
238 { "ipf_natrules_sz" },
239 { "ipf_rdrrules_sz" }, /* 5 */
240 { "ipf_hostmap_sz" },
247 if (nlist(kernel
, nat_nlist
) == -1) {
248 fprintf(stderr
, "nlist error\n");
253 * Normally the ioctl copies all of these values into the structure
254 * for us, before returning it to userland, so here we must copy each
255 * one in individually.
257 kmemcpy((char *)&tables
, nat_nlist
[0].n_value
, sizeof(tables
));
258 nsp
->ns_table
[0] = tables
[0];
259 nsp
->ns_table
[1] = tables
[1];
261 kmemcpy((char *)&nsp
->ns_list
, nat_nlist
[1].n_value
,
262 sizeof(nsp
->ns_list
));
263 kmemcpy((char *)&nsp
->ns_maptable
, nat_nlist
[2].n_value
,
264 sizeof(nsp
->ns_maptable
));
265 kmemcpy((char *)&nsp
->ns_nattab_sz
, nat_nlist
[3].n_value
,
266 sizeof(nsp
->ns_nattab_sz
));
267 kmemcpy((char *)&nsp
->ns_rultab_sz
, nat_nlist
[4].n_value
,
268 sizeof(nsp
->ns_rultab_sz
));
269 kmemcpy((char *)&nsp
->ns_rdrtab_sz
, nat_nlist
[5].n_value
,
270 sizeof(nsp
->ns_rdrtab_sz
));
271 kmemcpy((char *)&nsp
->ns_hostmap_sz
, nat_nlist
[6].n_value
,
272 sizeof(nsp
->ns_hostmap_sz
));
273 kmemcpy((char *)&nsp
->ns_instances
, nat_nlist
[7].n_value
,
274 sizeof(nsp
->ns_instances
));
275 kmemcpy((char *)&nsp
->ns_apslist
, nat_nlist
[8].n_value
,
276 sizeof(nsp
->ns_apslist
));
283 * Display NAT statistics.
285 static int dostats(nsp
, opts
)
289 nat_t
**nt
[2], *np
, nat
;
296 if (opts
& OPT_STAT
) {
297 printf("mapped\tin\t%lu\tout\t%lu\n",
298 nsp
->ns_mapped
[0], nsp
->ns_mapped
[1]);
299 printf("added\t%lu\texpired\t%lu\n",
300 nsp
->ns_added
, nsp
->ns_expire
);
301 printf("no memory\t%lu\tbad nat\t%lu\n",
302 nsp
->ns_memfail
, nsp
->ns_badnat
);
303 printf("inuse\t%lu\nrules\t%lu\n",
304 nsp
->ns_inuse
, nsp
->ns_rules
);
305 printf("wilds\t%u\n", nsp
->ns_wilds
);
306 if (opts
& OPT_VERBOSE
)
307 printf("table %p list %p\n",
308 nsp
->ns_table
, nsp
->ns_list
);
312 * Show list of NAT rules and NAT sessions ?
314 if (opts
& OPT_LIST
) {
315 printf("List of active MAP/Redirect filters:\n");
316 while (nsp
->ns_list
) {
317 if (kmemcpy((char *)&ipn
, (long)nsp
->ns_list
,
324 printf("%d ", ipn
.in_hits
);
325 printnat(&ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
326 nsp
->ns_list
= ipn
.in_next
;
329 nt
[0] = (nat_t
**)malloc(sizeof(*nt
) * NAT_SIZE
);
330 if (kmemcpy((char *)nt
[0], (long)nsp
->ns_table
[0],
331 sizeof(**nt
) * NAT_SIZE
)) {
340 printf("\nList of active sessions:\n");
342 for (np
= nsp
->ns_instances
; np
; np
= nat
.nat_next
) {
343 if (kmemcpy((char *)&nat
, (long)np
, sizeof(nat
))) {
344 /* TBD Is this an error? If so, return -1 */
347 printactivenat(&nat
, opts
);
350 if (opts
& OPT_VERBOSE
) {
351 if (showhostmap(nsp
)) {
364 * Display the active host mapping table.
366 static int showhostmap(nsp
)
369 hostmap_t hm
, *hmp
, **maptable
;
372 printf("\nList of active host mappings:\n");
374 maptable
= (hostmap_t
**)malloc(sizeof(hostmap_t
*) *
376 if (kmemcpy((char *)maptable
, (u_long
)nsp
->ns_maptable
,
377 sizeof(hostmap_t
*) * nsp
->ns_hostmap_sz
)) {
378 perror("kmemcpy (maptable)");
383 for (hv
= 0; hv
< nsp
->ns_hostmap_sz
; hv
++) {
387 if (kmemcpy((char *)&hm
, (u_long
)hmp
, sizeof(hm
))) {
388 perror("kmemcpy (hostmap)");
393 printhostmap(&hm
, hv
);
403 * Issue an ioctl to flush either the NAT rules table or the active mapping
406 static int flushtable(fd
, opts
)
412 if (opts
& OPT_FLUSH
) {
414 if (!(opts
& OPT_NODO
) && ioctl(fd
, SIOCIPFFL
, &n
) == -1) {
415 perror("ioctl(SIOCFLNAT)");
418 printf("%d entries flushed from NAT table\n", n
);
422 if (opts
& OPT_CLEAR
) {
424 if (!(opts
& OPT_NODO
) && ioctl(fd
, SIOCIPFFL
, &n
) == -1) {
425 perror("ioctl(SIOCCNATL)");
428 printf("%d entries flushed from NAT list\n", n
);