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)
74 static const char sccsid
[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
75 static const char rcsid
[] = "@(#)$Id: ipnat.c,v 1.24.2.2 2005/05/10 21:19:30 darrenr Exp $";
80 #define bzero(a,b) memset(a,0,b)
83 char thishost
[MAXHOSTNAMELEN
];
87 void dostats
__P((int, natstat_t
*, int, int));
88 void flushtable
__P((int, int));
89 void usage
__P((char *));
90 int main
__P((int, char*[]));
91 void showhostmap
__P((natstat_t
*nsp
));
92 void natstat_dead
__P((natstat_t
*, char *));
93 void dostats_live
__P((int, natstat_t
*, int));
94 void showhostmap_live
__P((int, natstat_t
*));
101 fprintf(stderr
, "Usage: %s [-CdFhlnrRsv] [-f filename]", name
);
102 fprintf(stderr
, " [-G|-z zonename]\n");
111 char *file
, *core
, *kernel
;
124 while ((c
= getopt(argc
, argv
, "CdFf:G:hlM:N:nrRsvz:")) != -1)
140 setzonename_global(optarg
);
156 opts
|= OPT_DONOTHING
;
160 opts
|= OPT_NORESOLVE
;
181 if ((kernel
!= NULL
) || (core
!= NULL
)) {
182 (void) setgid(getgid());
183 (void) setreuid(getuid(), getuid());
186 bzero((char *)&ns
, sizeof(ns
));
188 if ((opts
& OPT_DONOTHING
) == 0) {
189 if (checkrev(IPL_NAME
) == -1) {
190 fprintf(stderr
, "User/kernel version check failed\n");
196 if (!(opts
& OPT_DONOTHING
) && (kernel
== NULL
) && (core
== NULL
)) {
198 if (openkmem(kernel
, core
) == -1)
201 if (((fd
= open(IPNAT_NAME
, mode
)) == -1) &&
202 ((fd
= open(IPNAT_NAME
, O_RDONLY
)) == -1)) {
203 (void) fprintf(stderr
, "%s: open: %s\n", IPNAT_NAME
,
208 if (setzone(fd
) != 0) {
213 bzero((char *)&obj
, sizeof(obj
));
214 obj
.ipfo_rev
= IPFILTER_VERSION
;
215 obj
.ipfo_size
= sizeof(*nsp
);
216 obj
.ipfo_type
= IPFOBJ_NATSTAT
;
217 obj
.ipfo_ptr
= (void *)nsp
;
218 if (ioctl(fd
, SIOCGNATS
, &obj
) == -1) {
219 perror("ioctl(SIOCGNATS)");
222 (void) setgid(getgid());
223 (void) setreuid(getuid(), getuid());
224 } else if ((kernel
!= NULL
) || (core
!= NULL
)) {
225 if (openkmem(kernel
, core
) == -1)
228 natstat_dead(nsp
, kernel
);
229 if (opts
& (OPT_LIST
|OPT_STAT
))
230 dostats(fd
, nsp
, opts
, 0);
234 if (opts
& (OPT_FLUSH
|OPT_CLEAR
))
235 flushtable(fd
, opts
);
237 ipnat_parsefile(fd
, ipnat_addrule
, ioctl
, file
);
239 if (opts
& (OPT_LIST
|OPT_STAT
))
240 dostats(fd
, nsp
, opts
, 1);
246 * Read NAT statistic information in using a symbol table and memory file
247 * rather than doing ioctl's.
249 void natstat_dead(nsp
, kernel
)
253 struct nlist nat_nlist
[10] = {
254 { "nat_table" }, /* 0 */
257 { "ipf_nattable_sz" },
258 { "ipf_natrules_sz" },
259 { "ipf_rdrrules_sz" }, /* 5 */
260 { "ipf_hostmap_sz" },
267 if (nlist(kernel
, nat_nlist
) == -1) {
268 fprintf(stderr
, "nlist error\n");
273 * Normally the ioctl copies all of these values into the structure
274 * for us, before returning it to userland, so here we must copy each
275 * one in individually.
277 kmemcpy((char *)&tables
, nat_nlist
[0].n_value
, sizeof(tables
));
278 nsp
->ns_table
[0] = tables
[0];
279 nsp
->ns_table
[1] = tables
[1];
281 kmemcpy((char *)&nsp
->ns_list
, nat_nlist
[1].n_value
,
282 sizeof(nsp
->ns_list
));
283 kmemcpy((char *)&nsp
->ns_maptable
, nat_nlist
[2].n_value
,
284 sizeof(nsp
->ns_maptable
));
285 kmemcpy((char *)&nsp
->ns_nattab_sz
, nat_nlist
[3].n_value
,
286 sizeof(nsp
->ns_nattab_sz
));
287 kmemcpy((char *)&nsp
->ns_rultab_sz
, nat_nlist
[4].n_value
,
288 sizeof(nsp
->ns_rultab_sz
));
289 kmemcpy((char *)&nsp
->ns_rdrtab_sz
, nat_nlist
[5].n_value
,
290 sizeof(nsp
->ns_rdrtab_sz
));
291 kmemcpy((char *)&nsp
->ns_hostmap_sz
, nat_nlist
[6].n_value
,
292 sizeof(nsp
->ns_hostmap_sz
));
293 kmemcpy((char *)&nsp
->ns_instances
, nat_nlist
[7].n_value
,
294 sizeof(nsp
->ns_instances
));
295 kmemcpy((char *)&nsp
->ns_apslist
, nat_nlist
[8].n_value
,
296 sizeof(nsp
->ns_apslist
));
301 * Display NAT statistics.
303 void dostats(fd
, nsp
, opts
, alive
)
313 if (opts
& OPT_STAT
) {
314 printf("mapped\tin\t%lu\tout\t%lu\n",
315 nsp
->ns_mapped
[0], nsp
->ns_mapped
[1]);
316 printf("added\t%lu\texpired\t%lu\n",
317 nsp
->ns_added
, nsp
->ns_expire
);
318 printf("no memory\t%lu\tbad nat\t%lu\n",
319 nsp
->ns_memfail
, nsp
->ns_badnat
);
320 printf("inuse\t%lu\norphans\t%u\nrules\t%lu\n",
321 nsp
->ns_inuse
, nsp
->ns_orphans
, nsp
->ns_rules
);
322 printf("wilds\t%u\n", nsp
->ns_wilds
);
323 if (opts
& OPT_VERBOSE
)
324 printf("table %p list %p\n",
325 nsp
->ns_table
, nsp
->ns_list
);
329 * Show list of NAT rules and NAT sessions ?
331 if (opts
& OPT_LIST
) {
333 dostats_live(fd
, nsp
, opts
);
336 printf("List of active MAP/Redirect filters:\n");
337 while (nsp
->ns_list
) {
338 if (kmemcpy((char *)&ipn
, (long)nsp
->ns_list
,
344 printf("%lu ", ipn
.in_hits
);
345 printnat(&ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
346 nsp
->ns_list
= ipn
.in_next
;
349 printf("\nList of active sessions:\n");
351 for (np
= nsp
->ns_instances
; np
; np
= nat
.nat_next
) {
352 if (kmemcpy((char *)&nat
, (long)np
, sizeof(nat
)))
354 printactivenat(&nat
, opts
, 0);
356 printaps(nat
.nat_aps
, opts
);
359 if (opts
& OPT_VERBOSE
)
366 * Display the active host mapping table.
368 void showhostmap(nsp
)
371 hostmap_t hm
, *hmp
, **maptable
;
374 printf("\nList of active host mappings:\n");
376 maptable
= (hostmap_t
**)malloc(sizeof(hostmap_t
*) *
378 if (maptable
== NULL
) {
382 if (kmemcpy((char *)maptable
, (u_long
)nsp
->ns_maptable
,
383 sizeof(hostmap_t
*) * nsp
->ns_hostmap_sz
)) {
384 perror("kmemcpy (maptable)");
388 for (hv
= 0; hv
< nsp
->ns_hostmap_sz
; hv
++) {
392 if (kmemcpy((char *)&hm
, (u_long
)hmp
, sizeof(hm
))) {
393 perror("kmemcpy (hostmap)");
397 printhostmap(&hm
, hv
);
406 * Issue an ioctl to flush either the NAT rules table or the active mapping
409 void flushtable(fd
, opts
)
414 if (opts
& OPT_FLUSH
) {
416 if (!(opts
& OPT_DONOTHING
) && ioctl(fd
, SIOCIPFFL
, &n
) == -1)
417 perror("ioctl(SIOCFLNAT)");
419 printf("%d entries flushed from NAT table\n", n
);
422 if (opts
& OPT_CLEAR
) {
424 if (!(opts
& OPT_DONOTHING
) && ioctl(fd
, SIOCIPFFL
, &n
) == -1)
425 perror("ioctl(SIOCCNATL)");
427 printf("%d entries flushed from NAT list\n", n
);
432 * Display NAT statistics.
434 void dostats_live(fd
, nsp
, opts
)
443 bzero((char *)&obj
, sizeof(obj
));
444 obj
.ipfo_rev
= IPFILTER_VERSION
;
445 obj
.ipfo_type
= IPFOBJ_GENITER
;
446 obj
.ipfo_size
= sizeof(iter
);
447 obj
.ipfo_ptr
= &iter
;
449 iter
.igi_type
= IPFGENITER_IPNAT
;
451 iter
.igi_data
= &ipn
;
454 * Show list of NAT rules and NAT sessions ?
456 printf("List of active MAP/Redirect filters:\n");
457 while (nsp
->ns_list
) {
458 if (ioctl(fd
, SIOCGENITER
, &obj
) == -1)
461 printf("%lu ", ipn
.in_hits
);
462 printnat(&ipn
, opts
& (OPT_DEBUG
|OPT_VERBOSE
));
463 nsp
->ns_list
= ipn
.in_next
;
466 printf("\nList of active sessions:\n");
468 iter
.igi_type
= IPFGENITER_NAT
;
470 iter
.igi_data
= &nat
;
472 while (nsp
->ns_instances
!= NULL
) {
473 if (ioctl(fd
, SIOCGENITER
, &obj
) == -1)
475 printactivenat(&nat
, opts
, 1);
477 printaps(nat
.nat_aps
, opts
);
478 nsp
->ns_instances
= nat
.nat_next
;
481 if (opts
& OPT_VERBOSE
)
482 showhostmap_live(fd
, nsp
);
486 * Display the active host mapping table.
488 void showhostmap_live(fd
, nsp
)
496 bzero((char *)&obj
, sizeof(obj
));
497 obj
.ipfo_rev
= IPFILTER_VERSION
;
498 obj
.ipfo_type
= IPFOBJ_GENITER
;
499 obj
.ipfo_size
= sizeof(iter
);
500 obj
.ipfo_ptr
= &iter
;
502 iter
.igi_type
= IPFGENITER_HOSTMAP
;
506 printf("\nList of active host mappings:\n");
508 while (nsp
->ns_maplist
!= NULL
) {
509 if (ioctl(fd
, SIOCGENITER
, &obj
) == -1)
511 printhostmap(&hm
, 0);
512 nsp
->ns_maplist
= hm
.hm_next
;