2 * Copyright (C) 2003 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
12 #include <sys/types.h>
14 #include <sys/param.h>
15 #include <sys/socket.h>
16 #if defined(BSD) && (BSD >= 199306)
17 # include <sys/cdefs.h>
19 #include <sys/ioctl.h>
22 #if __FreeBSD_version >= 300000
23 # include <net/if_var.h>
25 #include <netinet/in.h>
27 #include <arpa/inet.h>
39 #include "netinet/ipl.h"
40 #include "netinet/ip_lookup.h"
41 #include "netinet/ip_pool.h"
42 #include "netinet/ip_htable.h"
46 extern int ippool_yyparse
__P((void));
47 extern int ippool_yydebug
;
48 extern FILE *ippool_yyin
;
52 void showpools
__P((ip_pool_stat_t
*));
53 void usage
__P((char *));
54 int main
__P((int, char **));
55 int poolcommand
__P((int, int, char *[]));
56 int poolnodecommand
__P((int, int, char *[]));
57 int loadpoolfile
__P((int, char *[], char *));
58 int poollist
__P((int, char *[]));
59 int poolflush
__P((int, char *[]));
60 int poolstats
__P((int, char *[]));
61 int gettype
__P((char *, u_int
*));
62 int getrole
__P((char *));
63 void poollist_dead
__P((int, char *, int, char *, char *));
64 void showpools_live(int, int, ip_pool_stat_t
*, char *, int);
65 void showhashs_live(int, int, iphtstat_t
*, char *, int);
75 const char *zoneopt
= "[-G|-z zonename] ";
76 fprintf(stderr
, "Usage:\t%s\n", prog
);
77 fprintf(stderr
, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
79 fprintf(stderr
, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n",
81 fprintf(stderr
, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt
);
82 fprintf(stderr
, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt
);
83 fprintf(stderr
, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt
);
84 fprintf(stderr
, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
86 fprintf(stderr
, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n",
88 fprintf(stderr
, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n",
103 switch (getopt(argc
, argv
, "aAf:FlrRs"))
106 err
= poolnodecommand(0, argc
, argv
);
109 err
= poolcommand(0, argc
, argv
);
112 err
= loadpoolfile(argc
, argv
, optarg
);
115 err
= poolflush(argc
, argv
);
118 err
= poollist(argc
, argv
);
121 err
= poolnodecommand(1, argc
, argv
);
124 err
= poolcommand(1, argc
, argv
);
127 err
= poolstats(argc
, argv
);
137 int poolnodecommand(remove
, argc
, argv
)
141 char *poolname
= NULL
, *s
;
142 int err
, c
, ipset
, role
;
148 bzero((char *)&node
, sizeof(node
));
150 while ((c
= getopt(argc
, argv
, "di:G:m:no:Rvz:")) != -1)
158 setzonename_global(optarg
);
161 s
= strchr(optarg
, '/');
163 mask
.s_addr
= 0xffffffff;
164 else if (strchr(s
, '.') == NULL
) {
165 if (ntomask(4, atoi(s
+ 1), &mask
.s_addr
) != 0)
168 mask
.s_addr
= inet_addr(s
+ 1);
173 node
.ipn_addr
.adf_len
= sizeof(node
.ipn_addr
);
174 node
.ipn_addr
.adf_addr
.in4
.s_addr
= inet_addr(optarg
);
175 node
.ipn_mask
.adf_len
= sizeof(node
.ipn_mask
);
176 node
.ipn_mask
.adf_addr
.in4
.s_addr
= mask
.s_addr
;
182 opts
|= OPT_DONOTHING
;
185 role
= getrole(optarg
);
186 if (role
== IPL_LOGNONE
)
190 opts
|= OPT_NORESOLVE
;
200 if (opts
& OPT_DEBUG
)
201 fprintf(stderr
, "poolnodecommand: opts = %#x\n", opts
);
205 if (poolname
== NULL
) {
206 fprintf(stderr
, "poolname not given with add/remove node\n");
211 err
= load_poolnode(0, poolname
, &node
, ioctl
);
213 err
= remove_poolnode(0, poolname
, &node
, ioctl
);
218 int poolcommand(remove
, argc
, argv
)
222 int type
, role
, c
, err
;
232 bzero((char *)&iph
, sizeof(iph
));
233 bzero((char *)&pool
, sizeof(pool
));
235 while ((c
= getopt(argc
, argv
, "dG:m:no:RS:t:vz:")) != -1)
243 setzonename_global(optarg
);
249 opts
|= OPT_DONOTHING
;
252 role
= getrole(optarg
);
253 if (role
== IPL_LOGNONE
) {
254 fprintf(stderr
, "unknown role '%s'\n", optarg
);
259 opts
|= OPT_NORESOLVE
;
262 iph
.iph_seed
= atoi(optarg
);
265 type
= gettype(optarg
, &iph
.iph_type
);
266 if (type
== IPLT_NONE
) {
267 fprintf(stderr
, "unknown type '%s'\n", optarg
);
279 if (opts
& OPT_DEBUG
)
280 fprintf(stderr
, "poolcommand: opts = %#x\n", opts
);
282 if (poolname
== NULL
) {
283 fprintf(stderr
, "poolname not given with add/remove pool\n");
287 if (type
== IPLT_HASH
) {
288 strncpy(iph
.iph_name
, poolname
, sizeof(iph
.iph_name
));
289 iph
.iph_name
[sizeof(iph
.iph_name
) - 1] = '\0';
291 } else if (type
== IPLT_POOL
) {
292 strncpy(pool
.ipo_name
, poolname
, sizeof(pool
.ipo_name
));
293 pool
.ipo_name
[sizeof(pool
.ipo_name
) - 1] = '\0';
294 pool
.ipo_unit
= role
;
301 err
= load_hash(&iph
, NULL
, ioctl
);
304 err
= load_pool(&pool
, ioctl
);
311 err
= remove_hash(&iph
, ioctl
);
314 err
= remove_pool(&pool
, ioctl
);
322 int loadpoolfile(argc
, argv
, infile
)
324 char *argv
[], *infile
;
330 while ((c
= getopt(argc
, argv
, "dG:nRuvz:")) != -1)
338 setzonename_global(optarg
);
341 opts
|= OPT_DONOTHING
;
344 opts
|= OPT_NORESOLVE
;
357 if (opts
& OPT_DEBUG
)
358 fprintf(stderr
, "loadpoolfile: opts = %#x\n", opts
);
360 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
361 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
363 perror("open(IPLOOKUP_NAME)");
367 if (setzone(fd
) != 0) {
373 if (ippool_parsefile(fd
, infile
, ioctl
) != 0)
379 int poollist(argc
, argv
)
383 char *kernel
, *core
, *poolname
;
384 int c
, role
, type
, live_kernel
;
385 ip_pool_stat_t
*plstp
, plstat
;
386 iphtstat_t
*htstp
, htstat
;
398 while ((c
= getopt(argc
, argv
, "dG:m:M:N:o:Rt:vz:")) != -1)
405 setzonename_global(optarg
);
419 role
= getrole(optarg
);
420 if (role
== IPL_LOGNONE
) {
421 fprintf(stderr
, "unknown role '%s'\n", optarg
);
426 opts
|= OPT_NORESOLVE
;
429 type
= gettype(optarg
, NULL
);
430 if (type
== IPLT_NONE
) {
431 fprintf(stderr
, "unknown type '%s'\n", optarg
);
443 if (opts
& OPT_DEBUG
)
444 fprintf(stderr
, "poollist: opts = %#x\n", opts
);
446 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
447 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
449 perror("open(IPLOOKUP_NAME)");
453 if (setzone(fd
) != 0) {
459 bzero((char *)&op
, sizeof(op
));
460 if (poolname
!= NULL
) {
461 strncpy(op
.iplo_name
, poolname
, sizeof(op
.iplo_name
));
462 op
.iplo_name
[sizeof(op
.iplo_name
) - 1] = '\0';
466 if (live_kernel
== 0) {
467 poollist_dead(role
, poolname
, type
, kernel
, core
);
471 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
473 op
.iplo_type
= IPLT_POOL
;
474 op
.iplo_size
= sizeof(plstat
);
475 op
.iplo_struct
= &plstat
;
476 op
.iplo_name
[0] = '\0';
479 if (role
!= IPL_LOGALL
) {
482 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
484 perror("ioctl(SIOCLOOKUPSTAT)");
488 showpools_live(fd
, role
, &plstat
, poolname
, opts
);
490 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
493 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
495 perror("ioctl(SIOCLOOKUPSTAT)");
499 showpools_live(fd
, role
, &plstat
, poolname
, opts
);
505 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
507 op
.iplo_type
= IPLT_HASH
;
508 op
.iplo_size
= sizeof(htstat
);
509 op
.iplo_struct
= &htstat
;
510 op
.iplo_name
[0] = '\0';
513 if (role
!= IPL_LOGALL
) {
516 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
518 perror("ioctl(SIOCLOOKUPSTAT)");
521 showhashs_live(fd
, role
, &htstat
, poolname
, opts
);
523 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
526 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
528 perror("ioctl(SIOCLOOKUPSTAT)");
532 showhashs_live(fd
, role
, &htstat
, poolname
, opts
);
539 void poollist_dead(role
, poolname
, type
, kernel
, core
)
541 char *poolname
, *kernel
, *core
;
546 if (openkmem(kernel
, core
) == -1)
549 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
550 ip_pool_t
*pools
[IPL_LOGSIZE
];
551 struct nlist names
[2] = { { "ip_pool_list" } , { "" } };
553 if (nlist(kernel
, names
) != 1)
556 bzero(&pools
, sizeof(pools
));
557 if (kmemcpy((char *)&pools
, names
[0].n_value
, sizeof(pools
)))
560 if (role
!= IPL_LOGALL
) {
562 while (ptr
!= NULL
) {
563 ptr
= printpool(ptr
, kmemcpywrap
,
567 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
569 while (ptr
!= NULL
) {
570 ptr
= printpool(ptr
, kmemcpywrap
,
577 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
578 iphtable_t
*tables
[IPL_LOGSIZE
];
579 struct nlist names
[2] = { { "ipf_htables" } , { "" } };
581 if (nlist(kernel
, names
) != 1)
584 bzero(&tables
, sizeof(tables
));
585 if (kmemcpy((char *)&tables
, names
[0].n_value
, sizeof(tables
)))
588 if (role
!= IPL_LOGALL
) {
590 while (hptr
!= NULL
) {
591 hptr
= printhash(hptr
, kmemcpywrap
,
595 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
597 while (hptr
!= NULL
) {
598 hptr
= printhash(hptr
, kmemcpywrap
,
608 showpools_live(fd
, role
, plstp
, poolname
, opts
)
610 ip_pool_stat_t
*plstp
;
614 ipflookupiter_t iter
;
618 obj
.ipfo_rev
= IPFILTER_VERSION
;
619 obj
.ipfo_type
= IPFOBJ_LOOKUPITER
;
620 obj
.ipfo_size
= sizeof(iter
);
621 obj
.ipfo_ptr
= &iter
;
623 iter
.ili_type
= IPLT_POOL
;
624 iter
.ili_otype
= IPFLOOKUPITER_LIST
;
625 iter
.ili_ival
= IPFGENITER_LOOKUP
;
626 iter
.ili_data
= &pool
;
627 iter
.ili_unit
= role
;
628 *iter
.ili_name
= '\0';
630 while (plstp
->ipls_list
[role
] != NULL
) {
631 if (ioctl(fd
, SIOCLOOKUPITER
, &obj
)) {
632 perror("ioctl(SIOCLOOKUPITER)");
635 (void) printpool_live(&pool
, fd
, poolname
, opts
);
637 plstp
->ipls_list
[role
] = pool
.ipo_next
;
641 int poolstats(argc
, argv
)
645 int c
, type
, role
, live_kernel
;
646 ip_pool_stat_t plstat
;
657 bzero((char *)&op
, sizeof(op
));
659 while ((c
= getopt(argc
, argv
, "dG:M:N:o:t:vz:")) != -1)
666 setzonename_global(optarg
);
677 role
= getrole(optarg
);
678 if (role
== IPL_LOGNONE
) {
679 fprintf(stderr
, "unknown role '%s'\n", optarg
);
684 type
= gettype(optarg
, NULL
);
685 if (type
!= IPLT_POOL
) {
687 "-s not supported for this type yet\n");
699 if (opts
& OPT_DEBUG
)
700 fprintf(stderr
, "poolstats: opts = %#x\n", opts
);
702 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
703 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
705 perror("open(IPLOOKUP_NAME)");
709 if (setzone(fd
) != 0) {
715 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
716 op
.iplo_type
= IPLT_POOL
;
717 op
.iplo_struct
= &plstat
;
718 op
.iplo_size
= sizeof(plstat
);
719 if (!(opts
& OPT_DONOTHING
)) {
720 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
722 perror("ioctl(SIOCLOOKUPSTAT)");
725 printf("Pools:\t%lu\n", plstat
.ipls_pools
);
726 printf("Nodes:\t%lu\n", plstat
.ipls_nodes
);
730 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
731 op
.iplo_type
= IPLT_HASH
;
732 op
.iplo_struct
= &htstat
;
733 op
.iplo_size
= sizeof(htstat
);
734 if (!(opts
& OPT_DONOTHING
)) {
735 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
737 perror("ioctl(SIOCLOOKUPSTAT)");
740 printf("Hash Tables:\t%lu\n", htstat
.iphs_numtables
);
741 printf("Nodes:\t%lu\n", htstat
.iphs_numnodes
);
742 printf("Out of Memory:\t%lu\n", htstat
.iphs_nomem
);
749 int poolflush(argc
, argv
)
753 int c
, role
, type
, arg
;
754 iplookupflush_t flush
;
760 while ((c
= getopt(argc
, argv
, "do:t:vz:")) != -1)
767 role
= getrole(optarg
);
768 if (role
== IPL_LOGNONE
) {
769 fprintf(stderr
, "unknown role '%s'\n", optarg
);
774 type
= gettype(optarg
, NULL
);
775 if (type
== IPLT_NONE
) {
776 fprintf(stderr
, "unknown type '%s'\n", optarg
);
788 if (opts
& OPT_DEBUG
)
789 fprintf(stderr
, "poolflush: opts = %#x\n", opts
);
791 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
792 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
794 perror("open(IPLOOKUP_NAME)");
798 if (setzone(fd
) != 0) {
804 bzero((char *)&flush
, sizeof(flush
));
805 flush
.iplf_type
= type
;
806 flush
.iplf_unit
= role
;
807 flush
.iplf_arg
= arg
;
809 if (!(opts
& OPT_DONOTHING
)) {
810 if (ioctl(fd
, SIOCLOOKUPFLUSH
, &flush
) == -1) {
811 perror("ioctl(SIOCLOOKUPFLUSH)");
816 printf("%u object%s flushed\n", flush
.iplf_count
,
817 (flush
.iplf_count
== 1) ? "" : "s");
823 int getrole(rolename
)
828 if (!strcasecmp(rolename
, "ipf")) {
831 } else if (!strcasecmp(rolename
, "nat")) {
833 } else if (!strcasecmp(rolename
, "state")) {
835 } else if (!strcasecmp(rolename
, "auth")) {
837 } else if (!strcasecmp(rolename
, "sync")) {
839 } else if (!strcasecmp(rolename
, "scan")) {
841 } else if (!strcasecmp(rolename
, "pool")) {
842 role
= IPL_LOGLOOKUP
;
843 } else if (!strcasecmp(rolename
, "count")) {
854 int gettype(typename
, minor
)
860 if (!strcasecmp(optarg
, "tree")) {
862 } else if (!strcasecmp(optarg
, "hash")) {
865 *minor
= IPHASH_LOOKUP
;
866 } else if (!strcasecmp(optarg
, "group-map")) {
869 *minor
= IPHASH_GROUPMAP
;
876 void showhashs_live(fd
, role
, htstp
, poolname
, opts
)
882 ipflookupiter_t iter
;
886 obj
.ipfo_rev
= IPFILTER_VERSION
;
887 obj
.ipfo_type
= IPFOBJ_LOOKUPITER
;
888 obj
.ipfo_size
= sizeof(iter
);
889 obj
.ipfo_ptr
= &iter
;
891 iter
.ili_type
= IPLT_HASH
;
892 iter
.ili_otype
= IPFLOOKUPITER_LIST
;
893 iter
.ili_ival
= IPFGENITER_LOOKUP
;
894 iter
.ili_data
= &table
;
895 iter
.ili_unit
= role
;
896 *iter
.ili_name
= '\0';
898 while (htstp
->iphs_tables
!= NULL
) {
899 if (ioctl(fd
, SIOCLOOKUPITER
, &obj
)) {
900 perror("ioctl(SIOCLOOKUPITER)");
904 printhash_live(&table
, fd
, poolname
, opts
);
906 htstp
->iphs_tables
= table
.iph_next
;