2 * Copyright (C) 1993-2001 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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
9 * Use is subject to license terms.
11 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
18 #include <sys/types.h>
19 #if !defined(__SVR4) && !defined(__svr4__)
22 #include <sys/byteorder.h>
25 #include <sys/param.h>
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
35 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
36 # include <sys/ioccom.h>
37 # include <sys/sysmacros.h>
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <netinet/tcp.h>
44 #if __FreeBSD_version >= 300000
45 # include <net/if_var.h>
48 #include <arpa/nameser.h>
49 #include <arpa/inet.h>
53 # include <linux/a.out.h>
58 #include "netinet/ipl.h"
63 # define nlist nlist64
66 #if defined(sun) && !SOLARIS2
67 # define STRERROR(x) sys_errlist[x]
68 extern char *sys_errlist
[];
70 # define STRERROR(x) strerror(x)
73 static const char sccsid
[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
74 static const char rcsid
[] = "@(#)$Id: ipnat.c,v 1.24.2.2 2005/05/10 21:19:30 darrenr Exp $";
78 #define bzero(a,b) memset(a,0,b)
81 char thishost
[MAXHOSTNAMELEN
];
85 void dostats
__P((int, natstat_t
*, int, int));
86 void flushtable
__P((int, int));
87 void usage
__P((char *));
88 int main
__P((int, char*[]));
89 void showhostmap
__P((natstat_t
*nsp
));
90 void natstat_dead
__P((natstat_t
*, char *));
91 void dostats_live
__P((int, natstat_t
*, int));
92 void showhostmap_live
__P((int, natstat_t
*));
99 fprintf(stderr
, "Usage: %s [-CdFhlnrRsv] [-f filename]", name
);
100 fprintf(stderr
, " [-G|-z zonename]\n");
109 char *file
, *core
, *kernel
;
122 while ((c
= getopt(argc
, argv
, "CdFf:G:hlM:N:nrRsvz:")) != -1)
138 setzonename_global(optarg
);
154 opts
|= OPT_DONOTHING
;
158 opts
|= OPT_NORESOLVE
;
179 if ((kernel
!= NULL
) || (core
!= NULL
)) {
180 (void) setgid(getgid());
181 (void) setreuid(getuid(), getuid());
184 bzero((char *)&ns
, sizeof(ns
));
186 if ((opts
& OPT_DONOTHING
) == 0) {
187 if (checkrev(IPL_NAME
) == -1) {
188 fprintf(stderr
, "User/kernel version check failed\n");
194 if (!(opts
& OPT_DONOTHING
) && (kernel
== NULL
) && (core
== NULL
)) {
196 if (openkmem(kernel
, core
) == -1)
199 if (((fd
= open(IPNAT_NAME
, mode
)) == -1) &&
200 ((fd
= open(IPNAT_NAME
, O_RDONLY
)) == -1)) {
201 (void) fprintf(stderr
, "%s: open: %s\n", IPNAT_NAME
,
206 if (setzone(fd
) != 0) {
211 bzero((char *)&obj
, sizeof(obj
));
212 obj
.ipfo_rev
= IPFILTER_VERSION
;
213 obj
.ipfo_size
= sizeof(*nsp
);
214 obj
.ipfo_type
= IPFOBJ_NATSTAT
;
215 obj
.ipfo_ptr
= (void *)nsp
;
216 if (ioctl(fd
, SIOCGNATS
, &obj
) == -1) {
217 perror("ioctl(SIOCGNATS)");
220 (void) setgid(getgid());
221 (void) setreuid(getuid(), getuid());
222 } else if ((kernel
!= NULL
) || (core
!= NULL
)) {
223 if (openkmem(kernel
, core
) == -1)
226 natstat_dead(nsp
, kernel
);
227 if (opts
& (OPT_LIST
|OPT_STAT
))
228 dostats(fd
, nsp
, opts
, 0);
232 if (opts
& (OPT_FLUSH
|OPT_CLEAR
))
233 flushtable(fd
, opts
);
235 ipnat_parsefile(fd
, ipnat_addrule
, ioctl
, file
);
237 if (opts
& (OPT_LIST
|OPT_STAT
))
238 dostats(fd
, nsp
, opts
, 1);
244 * Read NAT statistic information in using a symbol table and memory file
245 * rather than doing ioctl's.
247 void natstat_dead(nsp
, kernel
)
251 struct nlist nat_nlist
[10] = {
252 { "nat_table" }, /* 0 */
255 { "ipf_nattable_sz" },
256 { "ipf_natrules_sz" },
257 { "ipf_rdrrules_sz" }, /* 5 */
258 { "ipf_hostmap_sz" },
265 if (nlist(kernel
, nat_nlist
) == -1) {
266 fprintf(stderr
, "nlist error\n");
271 * Normally the ioctl copies all of these values into the structure
272 * for us, before returning it to userland, so here we must copy each
273 * one in individually.
275 kmemcpy((char *)&tables
, nat_nlist
[0].n_value
, sizeof(tables
));
276 nsp
->ns_table
[0] = tables
[0];
277 nsp
->ns_table
[1] = tables
[1];
279 kmemcpy((char *)&nsp
->ns_list
, nat_nlist
[1].n_value
,
280 sizeof(nsp
->ns_list
));
281 kmemcpy((char *)&nsp
->ns_maptable
, nat_nlist
[2].n_value
,
282 sizeof(nsp
->ns_maptable
));
283 kmemcpy((char *)&nsp
->ns_nattab_sz
, nat_nlist
[3].n_value
,
284 sizeof(nsp
->ns_nattab_sz
));
285 kmemcpy((char *)&nsp
->ns_rultab_sz
, nat_nlist
[4].n_value
,
286 sizeof(nsp
->ns_rultab_sz
));
287 kmemcpy((char *)&nsp
->ns_rdrtab_sz
, nat_nlist
[5].n_value
,
288 sizeof(nsp
->ns_rdrtab_sz
));
289 kmemcpy((char *)&nsp
->ns_hostmap_sz
, nat_nlist
[6].n_value
,
290 sizeof(nsp
->ns_hostmap_sz
));
291 kmemcpy((char *)&nsp
->ns_instances
, nat_nlist
[7].n_value
,
292 sizeof(nsp
->ns_instances
));
293 kmemcpy((char *)&nsp
->ns_apslist
, nat_nlist
[8].n_value
,
294 sizeof(nsp
->ns_apslist
));
299 * Display NAT statistics.
301 void dostats(fd
, nsp
, opts
, alive
)
311 if (opts
& OPT_STAT
) {
312 printf("mapped\tin\t%lu\tout\t%lu\n",
313 nsp
->ns_mapped
[0], nsp
->ns_mapped
[1]);
314 printf("added\t%lu\texpired\t%lu\n",
315 nsp
->ns_added
, nsp
->ns_expire
);
316 printf("no memory\t%lu\tbad nat\t%lu\n",
317 nsp
->ns_memfail
, nsp
->ns_badnat
);
318 printf("inuse\t%lu\norphans\t%u\nrules\t%lu\n",
319 nsp
->ns_inuse
, nsp
->ns_orphans
, nsp
->ns_rules
);
320 printf("wilds\t%u\n", nsp
->ns_wilds
);
321 if (opts
& OPT_VERBOSE
)
322 printf("table %p list %p\n",
323 nsp
->ns_table
, nsp
->ns_list
);
327 * Show list of NAT rules and NAT sessions ?
329 if (opts
& OPT_LIST
) {
331 dostats_live(fd
, nsp
, opts
);
334 printf("List of active MAP/Redirect filters:\n");
335 while (nsp
->ns_list
) {
336 if (kmemcpy((char *)&ipn
, (long)nsp
->ns_list
,
342 printf("%lu ", ipn
.in_hits
);
343 printnat(&ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
344 nsp
->ns_list
= ipn
.in_next
;
347 printf("\nList of active sessions:\n");
349 for (np
= nsp
->ns_instances
; np
; np
= nat
.nat_next
) {
350 if (kmemcpy((char *)&nat
, (long)np
, sizeof(nat
)))
352 printactivenat(&nat
, opts
, 0);
354 printaps(nat
.nat_aps
, opts
);
357 if (opts
& OPT_VERBOSE
)
364 * Display the active host mapping table.
366 void 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 (maptable
== NULL
) {
380 if (kmemcpy((char *)maptable
, (u_long
)nsp
->ns_maptable
,
381 sizeof(hostmap_t
*) * nsp
->ns_hostmap_sz
)) {
382 perror("kmemcpy (maptable)");
386 for (hv
= 0; hv
< nsp
->ns_hostmap_sz
; hv
++) {
390 if (kmemcpy((char *)&hm
, (u_long
)hmp
, sizeof(hm
))) {
391 perror("kmemcpy (hostmap)");
395 printhostmap(&hm
, hv
);
404 * Issue an ioctl to flush either the NAT rules table or the active mapping
407 void flushtable(fd
, opts
)
412 if (opts
& OPT_FLUSH
) {
414 if (!(opts
& OPT_DONOTHING
) && ioctl(fd
, SIOCIPFFL
, &n
) == -1)
415 perror("ioctl(SIOCFLNAT)");
417 printf("%d entries flushed from NAT table\n", n
);
420 if (opts
& OPT_CLEAR
) {
422 if (!(opts
& OPT_DONOTHING
) && ioctl(fd
, SIOCIPFFL
, &n
) == -1)
423 perror("ioctl(SIOCCNATL)");
425 printf("%d entries flushed from NAT list\n", n
);
430 * Display NAT statistics.
432 void dostats_live(fd
, nsp
, opts
)
441 bzero((char *)&obj
, sizeof(obj
));
442 obj
.ipfo_rev
= IPFILTER_VERSION
;
443 obj
.ipfo_type
= IPFOBJ_GENITER
;
444 obj
.ipfo_size
= sizeof(iter
);
445 obj
.ipfo_ptr
= &iter
;
447 iter
.igi_type
= IPFGENITER_IPNAT
;
449 iter
.igi_data
= &ipn
;
452 * Show list of NAT rules and NAT sessions ?
454 printf("List of active MAP/Redirect filters:\n");
455 while (nsp
->ns_list
) {
456 if (ioctl(fd
, SIOCGENITER
, &obj
) == -1)
459 printf("%lu ", ipn
.in_hits
);
460 printnat(&ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
461 nsp
->ns_list
= ipn
.in_next
;
464 printf("\nList of active sessions:\n");
466 iter
.igi_type
= IPFGENITER_NAT
;
468 iter
.igi_data
= &nat
;
470 while (nsp
->ns_instances
!= NULL
) {
471 if (ioctl(fd
, SIOCGENITER
, &obj
) == -1)
473 printactivenat(&nat
, opts
, 1);
475 printaps(nat
.nat_aps
, opts
);
476 nsp
->ns_instances
= nat
.nat_next
;
479 if (opts
& OPT_VERBOSE
)
480 showhostmap_live(fd
, nsp
);
484 * Display the active host mapping table.
486 void showhostmap_live(fd
, nsp
)
494 bzero((char *)&obj
, sizeof(obj
));
495 obj
.ipfo_rev
= IPFILTER_VERSION
;
496 obj
.ipfo_type
= IPFOBJ_GENITER
;
497 obj
.ipfo_size
= sizeof(iter
);
498 obj
.ipfo_ptr
= &iter
;
500 iter
.igi_type
= IPFGENITER_HOSTMAP
;
504 printf("\nList of active host mappings:\n");
506 while (nsp
->ns_maplist
!= NULL
) {
507 if (ioctl(fd
, SIOCGENITER
, &obj
) == -1)
509 printhostmap(&hm
, 0);
510 nsp
->ns_maplist
= hm
.hm_next
;