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.
10 * Copyright 2017 Gary Mills
13 #include <sys/types.h>
15 #include <sys/param.h>
16 #include <sys/socket.h>
17 #if defined(BSD) && (BSD >= 199306)
18 # include <sys/cdefs.h>
20 #include <sys/ioctl.h>
23 #if __FreeBSD_version >= 300000
24 # include <net/if_var.h>
26 #include <netinet/in.h>
28 #include <arpa/inet.h>
40 #include "netinet/ipl.h"
41 #include "netinet/ip_lookup.h"
42 #include "netinet/ip_pool.h"
43 #include "netinet/ip_htable.h"
47 extern int ippool_yyparse
__P((void));
48 extern int ippool_yydebug
;
49 extern FILE *ippool_yyin
;
53 void showpools
__P((ip_pool_stat_t
*));
54 void usage
__P((char *));
55 int main
__P((int, char **));
56 int poolcommand
__P((int, int, char *[]));
57 int poolnodecommand
__P((int, int, char *[]));
58 int loadpoolfile
__P((int, char *[], char *));
59 int poollist
__P((int, char *[]));
60 int poolflush
__P((int, char *[]));
61 int poolstats
__P((int, char *[]));
62 int gettype
__P((char *, u_int
*));
63 int getrole
__P((char *));
64 void poollist_dead
__P((int, char *, int, char *, char *));
65 void showpools_live(int, int, ip_pool_stat_t
*, char *, int);
66 void showhashs_live(int, int, iphtstat_t
*, char *, int);
76 const char *zoneopt
= "[-G|-z zonename] ";
77 fprintf(stderr
, "Usage:\t%s\n", prog
);
78 fprintf(stderr
, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
80 fprintf(stderr
, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n",
82 fprintf(stderr
, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt
);
83 fprintf(stderr
, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt
);
84 fprintf(stderr
, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt
);
85 fprintf(stderr
, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
87 fprintf(stderr
, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n",
89 fprintf(stderr
, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n",
104 switch (getopt(argc
, argv
, "aAf:FlrRs"))
107 err
= poolnodecommand(0, argc
, argv
);
110 err
= poolcommand(0, argc
, argv
);
113 err
= loadpoolfile(argc
, argv
, optarg
);
116 err
= poolflush(argc
, argv
);
119 err
= poollist(argc
, argv
);
122 err
= poolnodecommand(1, argc
, argv
);
125 err
= poolcommand(1, argc
, argv
);
128 err
= poolstats(argc
, argv
);
138 int poolnodecommand(remove
, argc
, argv
)
142 char *poolname
= NULL
, *s
;
143 int err
, c
, ipset
, role
;
149 bzero((char *)&node
, sizeof(node
));
151 while ((c
= getopt(argc
, argv
, "di:G:m:no:Rvz:")) != -1)
159 setzonename_global(optarg
);
162 s
= strchr(optarg
, '/');
164 mask
.s_addr
= 0xffffffff;
165 else if (strchr(s
, '.') == NULL
) {
166 if (ntomask(4, atoi(s
+ 1), &mask
.s_addr
) != 0)
169 mask
.s_addr
= inet_addr(s
+ 1);
174 node
.ipn_addr
.adf_len
= sizeof(node
.ipn_addr
);
175 node
.ipn_addr
.adf_addr
.in4
.s_addr
= inet_addr(optarg
);
176 node
.ipn_mask
.adf_len
= sizeof(node
.ipn_mask
);
177 node
.ipn_mask
.adf_addr
.in4
.s_addr
= mask
.s_addr
;
183 opts
|= OPT_DONOTHING
;
186 role
= getrole(optarg
);
187 if (role
== IPL_LOGNONE
)
191 opts
|= OPT_NORESOLVE
;
201 if (opts
& OPT_DEBUG
)
202 fprintf(stderr
, "poolnodecommand: opts = %#x\n", opts
);
206 if (poolname
== NULL
) {
207 fprintf(stderr
, "poolname not given with add/remove node\n");
212 err
= load_poolnode(0, poolname
, &node
, ioctl
);
214 err
= remove_poolnode(0, poolname
, &node
, ioctl
);
219 int poolcommand(remove
, argc
, argv
)
223 int type
, role
, c
, err
;
233 bzero((char *)&iph
, sizeof(iph
));
234 bzero((char *)&pool
, sizeof(pool
));
236 while ((c
= getopt(argc
, argv
, "dG:m:no:RS:t:vz:")) != -1)
244 setzonename_global(optarg
);
250 opts
|= OPT_DONOTHING
;
253 role
= getrole(optarg
);
254 if (role
== IPL_LOGNONE
) {
255 fprintf(stderr
, "unknown role '%s'\n", optarg
);
260 opts
|= OPT_NORESOLVE
;
263 iph
.iph_seed
= atoi(optarg
);
266 type
= gettype(optarg
, &iph
.iph_type
);
267 if (type
== IPLT_NONE
) {
268 fprintf(stderr
, "unknown type '%s'\n", optarg
);
280 if (opts
& OPT_DEBUG
)
281 fprintf(stderr
, "poolcommand: opts = %#x\n", opts
);
283 if (poolname
== NULL
) {
284 fprintf(stderr
, "poolname not given with add/remove pool\n");
288 if (type
== IPLT_HASH
) {
289 strncpy(iph
.iph_name
, poolname
, sizeof(iph
.iph_name
));
290 iph
.iph_name
[sizeof(iph
.iph_name
) - 1] = '\0';
292 } else if (type
== IPLT_POOL
) {
293 strncpy(pool
.ipo_name
, poolname
, sizeof(pool
.ipo_name
));
294 pool
.ipo_name
[sizeof(pool
.ipo_name
) - 1] = '\0';
295 pool
.ipo_unit
= role
;
302 err
= load_hash(&iph
, NULL
, ioctl
);
305 err
= load_pool(&pool
, ioctl
);
312 err
= remove_hash(&iph
, ioctl
);
315 err
= remove_pool(&pool
, ioctl
);
323 int loadpoolfile(argc
, argv
, infile
)
325 char *argv
[], *infile
;
331 while ((c
= getopt(argc
, argv
, "dG:nRuvz:")) != -1)
339 setzonename_global(optarg
);
342 opts
|= OPT_DONOTHING
;
345 opts
|= OPT_NORESOLVE
;
358 if (opts
& OPT_DEBUG
)
359 fprintf(stderr
, "loadpoolfile: opts = %#x\n", opts
);
361 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
362 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
364 perror("open(IPLOOKUP_NAME)");
368 if (setzone(fd
) != 0) {
374 if (ippool_parsefile(fd
, infile
, ioctl
) != 0)
380 int poollist(argc
, argv
)
384 char *kernel
, *core
, *poolname
;
385 int c
, role
, type
, live_kernel
;
386 ip_pool_stat_t plstat
;
399 while ((c
= getopt(argc
, argv
, "dG:m:M:N:o:Rt:vz:")) != -1)
406 setzonename_global(optarg
);
420 role
= getrole(optarg
);
421 if (role
== IPL_LOGNONE
) {
422 fprintf(stderr
, "unknown role '%s'\n", optarg
);
427 opts
|= OPT_NORESOLVE
;
430 type
= gettype(optarg
, NULL
);
431 if (type
== IPLT_NONE
) {
432 fprintf(stderr
, "unknown type '%s'\n", optarg
);
444 if (opts
& OPT_DEBUG
)
445 fprintf(stderr
, "poollist: opts = %#x\n", opts
);
447 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
448 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
450 perror("open(IPLOOKUP_NAME)");
454 if (setzone(fd
) != 0) {
460 bzero((char *)&op
, sizeof(op
));
461 if (poolname
!= NULL
) {
462 strncpy(op
.iplo_name
, poolname
, sizeof(op
.iplo_name
));
463 op
.iplo_name
[sizeof(op
.iplo_name
) - 1] = '\0';
467 if (live_kernel
== 0) {
468 poollist_dead(role
, poolname
, type
, kernel
, core
);
472 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
) {
506 op
.iplo_type
= IPLT_HASH
;
507 op
.iplo_size
= sizeof(htstat
);
508 op
.iplo_struct
= &htstat
;
509 op
.iplo_name
[0] = '\0';
512 if (role
!= IPL_LOGALL
) {
515 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
517 perror("ioctl(SIOCLOOKUPSTAT)");
520 showhashs_live(fd
, role
, &htstat
, poolname
, opts
);
522 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
525 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
527 perror("ioctl(SIOCLOOKUPSTAT)");
531 showhashs_live(fd
, role
, &htstat
, poolname
, opts
);
538 void poollist_dead(role
, poolname
, type
, kernel
, core
)
540 char *poolname
, *kernel
, *core
;
545 if (openkmem(kernel
, core
) == -1)
548 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
549 ip_pool_t
*pools
[IPL_LOGSIZE
];
550 struct nlist names
[2] = { { "ip_pool_list" } , { "" } };
552 if (nlist(kernel
, names
) != 1)
555 bzero(&pools
, sizeof(pools
));
556 if (kmemcpy((char *)&pools
, names
[0].n_value
, sizeof(pools
)))
559 if (role
!= IPL_LOGALL
) {
561 while (ptr
!= NULL
) {
562 ptr
= printpool(ptr
, kmemcpywrap
,
566 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
568 while (ptr
!= NULL
) {
569 ptr
= printpool(ptr
, kmemcpywrap
,
576 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
577 iphtable_t
*tables
[IPL_LOGSIZE
];
578 struct nlist names
[2] = { { "ipf_htables" } , { "" } };
580 if (nlist(kernel
, names
) != 1)
583 bzero(&tables
, sizeof(tables
));
584 if (kmemcpy((char *)&tables
, names
[0].n_value
, sizeof(tables
)))
587 if (role
!= IPL_LOGALL
) {
589 while (hptr
!= NULL
) {
590 hptr
= printhash(hptr
, kmemcpywrap
,
594 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
596 while (hptr
!= NULL
) {
597 hptr
= printhash(hptr
, kmemcpywrap
,
607 showpools_live(fd
, role
, plstp
, poolname
, opts
)
609 ip_pool_stat_t
*plstp
;
613 ipflookupiter_t iter
;
617 obj
.ipfo_rev
= IPFILTER_VERSION
;
618 obj
.ipfo_type
= IPFOBJ_LOOKUPITER
;
619 obj
.ipfo_size
= sizeof(iter
);
620 obj
.ipfo_ptr
= &iter
;
622 iter
.ili_type
= IPLT_POOL
;
623 iter
.ili_otype
= IPFLOOKUPITER_LIST
;
624 iter
.ili_ival
= IPFGENITER_LOOKUP
;
625 iter
.ili_data
= &pool
;
626 iter
.ili_unit
= role
;
627 *iter
.ili_name
= '\0';
629 while (plstp
->ipls_list
[role
] != NULL
) {
630 if (ioctl(fd
, SIOCLOOKUPITER
, &obj
)) {
631 perror("ioctl(SIOCLOOKUPITER)");
634 (void) printpool_live(&pool
, fd
, poolname
, opts
);
636 plstp
->ipls_list
[role
] = pool
.ipo_next
;
640 int poolstats(argc
, argv
)
645 ip_pool_stat_t plstat
;
652 bzero((char *)&op
, sizeof(op
));
654 while ((c
= getopt(argc
, argv
, "dG:M:N:o:t:vz:")) != -1)
661 setzonename_global(optarg
);
668 role
= getrole(optarg
);
669 if (role
== IPL_LOGNONE
) {
670 fprintf(stderr
, "unknown role '%s'\n", optarg
);
675 type
= gettype(optarg
, NULL
);
676 if (type
!= IPLT_POOL
) {
678 "-s not supported for this type yet\n");
690 if (opts
& OPT_DEBUG
)
691 fprintf(stderr
, "poolstats: opts = %#x\n", opts
);
693 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
694 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
696 perror("open(IPLOOKUP_NAME)");
700 if (setzone(fd
) != 0) {
706 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
707 op
.iplo_type
= IPLT_POOL
;
708 op
.iplo_struct
= &plstat
;
709 op
.iplo_size
= sizeof(plstat
);
710 if (!(opts
& OPT_DONOTHING
)) {
711 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
713 perror("ioctl(SIOCLOOKUPSTAT)");
716 printf("Pools:\t%lu\n", plstat
.ipls_pools
);
717 printf("Nodes:\t%lu\n", plstat
.ipls_nodes
);
721 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
722 op
.iplo_type
= IPLT_HASH
;
723 op
.iplo_struct
= &htstat
;
724 op
.iplo_size
= sizeof(htstat
);
725 if (!(opts
& OPT_DONOTHING
)) {
726 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
728 perror("ioctl(SIOCLOOKUPSTAT)");
731 printf("Hash Tables:\t%lu\n", htstat
.iphs_numtables
);
732 printf("Nodes:\t%lu\n", htstat
.iphs_numnodes
);
733 printf("Out of Memory:\t%lu\n", htstat
.iphs_nomem
);
740 int poolflush(argc
, argv
)
744 int c
, role
, type
, arg
;
745 iplookupflush_t flush
;
751 while ((c
= getopt(argc
, argv
, "do:t:vz:")) != -1)
758 role
= getrole(optarg
);
759 if (role
== IPL_LOGNONE
) {
760 fprintf(stderr
, "unknown role '%s'\n", optarg
);
765 type
= gettype(optarg
, NULL
);
766 if (type
== IPLT_NONE
) {
767 fprintf(stderr
, "unknown type '%s'\n", optarg
);
779 if (opts
& OPT_DEBUG
)
780 fprintf(stderr
, "poolflush: opts = %#x\n", opts
);
782 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
783 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
785 perror("open(IPLOOKUP_NAME)");
789 if (setzone(fd
) != 0) {
795 bzero((char *)&flush
, sizeof(flush
));
796 flush
.iplf_type
= type
;
797 flush
.iplf_unit
= role
;
798 flush
.iplf_arg
= arg
;
800 if (!(opts
& OPT_DONOTHING
)) {
801 if (ioctl(fd
, SIOCLOOKUPFLUSH
, &flush
) == -1) {
802 perror("ioctl(SIOCLOOKUPFLUSH)");
807 printf("%u object%s flushed\n", flush
.iplf_count
,
808 (flush
.iplf_count
== 1) ? "" : "s");
814 int getrole(rolename
)
819 if (!strcasecmp(rolename
, "ipf")) {
822 } else if (!strcasecmp(rolename
, "nat")) {
824 } else if (!strcasecmp(rolename
, "state")) {
826 } else if (!strcasecmp(rolename
, "auth")) {
828 } else if (!strcasecmp(rolename
, "sync")) {
830 } else if (!strcasecmp(rolename
, "scan")) {
832 } else if (!strcasecmp(rolename
, "pool")) {
833 role
= IPL_LOGLOOKUP
;
834 } else if (!strcasecmp(rolename
, "count")) {
845 int gettype(typename
, minor
)
851 if (!strcasecmp(optarg
, "tree")) {
853 } else if (!strcasecmp(optarg
, "hash")) {
856 *minor
= IPHASH_LOOKUP
;
857 } else if (!strcasecmp(optarg
, "group-map")) {
860 *minor
= IPHASH_GROUPMAP
;
867 void showhashs_live(fd
, role
, htstp
, poolname
, opts
)
873 ipflookupiter_t iter
;
877 obj
.ipfo_rev
= IPFILTER_VERSION
;
878 obj
.ipfo_type
= IPFOBJ_LOOKUPITER
;
879 obj
.ipfo_size
= sizeof(iter
);
880 obj
.ipfo_ptr
= &iter
;
882 iter
.ili_type
= IPLT_HASH
;
883 iter
.ili_otype
= IPFLOOKUPITER_LIST
;
884 iter
.ili_ival
= IPFGENITER_LOOKUP
;
885 iter
.ili_data
= &table
;
886 iter
.ili_unit
= role
;
887 *iter
.ili_name
= '\0';
889 while (htstp
->iphs_tables
!= NULL
) {
890 if (ioctl(fd
, SIOCLOOKUPITER
, &obj
)) {
891 perror("ioctl(SIOCLOOKUPITER)");
895 printhash_live(&table
, fd
, poolname
, opts
);
897 htstp
->iphs_tables
= table
.iph_next
;