1 /* $NetBSD: ippool.c,v 1.6 2008/05/20 07:08:07 darrenr Exp $ */
4 * Copyright (C) 2002-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
10 #include <sys/param.h>
11 #include <sys/socket.h>
12 #if defined(BSD) && (BSD >= 199306)
13 # include <sys/cdefs.h>
15 #include <sys/ioctl.h>
18 #if __FreeBSD_version >= 300000
19 # include <net/if_var.h>
21 #include <netinet/in.h>
23 #include <arpa/inet.h>
33 # include <linux/a.out.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 usage
__P((char *));
53 int main
__P((int, char **));
54 int poolcommand
__P((int, int, char *[]));
55 int poolnodecommand
__P((int, int, char *[]));
56 int loadpoolfile
__P((int, char *[], char *));
57 int poollist
__P((int, char *[]));
58 void poollist_dead
__P((int, char *, int, char *, char *));
59 void poollist_live
__P((int, char *, int, int));
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 int setnodeaddr
__P((ip_pool_node_t
*node
, char *arg
));
65 void showpools_live
__P((int, int, ip_pool_stat_t
*, char *));
66 void showhashs_live
__P((int, int, iphtstat_t
*, char *));
76 fprintf(stderr
, "Usage:\t%s\n", prog
);
77 fprintf(stderr
, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
78 fprintf(stderr
, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
79 fprintf(stderr
, "\t\t\t-f <file> [-dnuv]\n");
80 fprintf(stderr
, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
81 fprintf(stderr
, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
82 fprintf(stderr
, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
83 fprintf(stderr
, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
84 fprintf(stderr
, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
98 switch (getopt(argc
, argv
, "aAf:FlrRs"))
101 err
= poolnodecommand(0, argc
, argv
);
104 err
= poolcommand(0, argc
, argv
);
107 err
= loadpoolfile(argc
, argv
, optarg
);
110 err
= poolflush(argc
, argv
);
113 err
= poollist(argc
, argv
);
116 err
= poolnodecommand(1, argc
, argv
);
119 err
= poolcommand(1, argc
, argv
);
122 err
= poolstats(argc
, argv
);
134 int poolnodecommand(remove
, argc
, argv
)
138 int err
, c
, ipset
, role
;
139 char *poolname
= NULL
;
144 bzero((char *)&node
, sizeof(node
));
146 while ((c
= getopt(argc
, argv
, "di:m:no:Rv")) != -1)
154 if (setnodeaddr(&node
, optarg
) == 0)
161 opts
|= OPT_DONOTHING
;
164 role
= getrole(optarg
);
165 if (role
== IPL_LOGNONE
)
169 opts
|= OPT_NORESOLVE
;
176 if (argv
[optind
] != NULL
&& ipset
== 0) {
177 if (setnodeaddr(&node
, argv
[optind
]) == 0)
181 if (opts
& OPT_DEBUG
)
182 fprintf(stderr
, "poolnodecommand: opts = %#x\n", opts
);
185 fprintf(stderr
, "no IP address given with -i\n");
189 if (poolname
== NULL
) {
190 fprintf(stderr
, "poolname not given with add/remove node\n");
195 err
= load_poolnode(0, poolname
, &node
, ioctl
);
197 err
= remove_poolnode(0, poolname
, &node
, ioctl
);
202 int poolcommand(remove
, argc
, argv
)
206 int type
, role
, c
, err
;
216 bzero((char *)&iph
, sizeof(iph
));
217 bzero((char *)&pool
, sizeof(pool
));
219 while ((c
= getopt(argc
, argv
, "dm:no:RSt:v")) != -1)
230 opts
|= OPT_DONOTHING
;
233 role
= getrole(optarg
);
234 if (role
== IPL_LOGNONE
) {
235 fprintf(stderr
, "unknown role '%s'\n", optarg
);
240 opts
|= OPT_NORESOLVE
;
243 iph
.iph_seed
= atoi(optarg
);
246 type
= gettype(optarg
, &iph
.iph_type
);
247 if (type
== IPLT_NONE
) {
248 fprintf(stderr
, "unknown type '%s'\n", optarg
);
257 if (opts
& OPT_DEBUG
)
258 fprintf(stderr
, "poolcommand: opts = %#x\n", opts
);
260 if (poolname
== NULL
) {
261 fprintf(stderr
, "poolname not given with add/remove pool\n");
265 if (type
== IPLT_HASH
) {
266 strncpy(iph
.iph_name
, poolname
, sizeof(iph
.iph_name
));
267 iph
.iph_name
[sizeof(iph
.iph_name
) - 1] = '\0';
269 } else if (type
== IPLT_POOL
) {
270 strncpy(pool
.ipo_name
, poolname
, sizeof(pool
.ipo_name
));
271 pool
.ipo_name
[sizeof(pool
.ipo_name
) - 1] = '\0';
272 pool
.ipo_unit
= role
;
279 err
= load_hash(&iph
, NULL
, ioctl
);
282 err
= load_pool(&pool
, ioctl
);
289 err
= remove_hash(&iph
, ioctl
);
292 err
= remove_pool(&pool
, ioctl
);
300 int loadpoolfile(argc
, argv
, infile
)
302 char *argv
[], *infile
;
308 while ((c
= getopt(argc
, argv
, "dnRuv")) != -1)
316 opts
|= OPT_DONOTHING
;
319 opts
|= OPT_NORESOLVE
;
329 if (opts
& OPT_DEBUG
)
330 fprintf(stderr
, "loadpoolfile: opts = %#x\n", opts
);
332 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
333 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
335 perror("open(IPLOOKUP_NAME)");
340 if (ippool_parsefile(fd
, infile
, ioctl
) != 0)
346 int poolstats(argc
, argv
)
350 int c
, type
, role
, live_kernel
;
351 ip_pool_stat_t plstat
;
362 bzero((char *)&op
, sizeof(op
));
364 while ((c
= getopt(argc
, argv
, "dM:N:o:t:v")) != -1)
379 role
= getrole(optarg
);
380 if (role
== IPL_LOGNONE
) {
381 fprintf(stderr
, "unknown role '%s'\n", optarg
);
386 type
= gettype(optarg
, NULL
);
387 if (type
!= IPLT_POOL
) {
389 "-s not supported for this type yet\n");
398 if (opts
& OPT_DEBUG
)
399 fprintf(stderr
, "poolstats: opts = %#x\n", opts
);
401 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
402 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
404 perror("open(IPLOOKUP_NAME)");
409 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
410 op
.iplo_type
= IPLT_POOL
;
411 op
.iplo_struct
= &plstat
;
412 op
.iplo_size
= sizeof(plstat
);
413 if (!(opts
& OPT_DONOTHING
)) {
414 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
416 perror("ioctl(SIOCLOOKUPSTAT)");
419 printf("Pools:\t%lu\n", plstat
.ipls_pools
);
420 printf("Nodes:\t%lu\n", plstat
.ipls_nodes
);
424 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
425 op
.iplo_type
= IPLT_HASH
;
426 op
.iplo_struct
= &htstat
;
427 op
.iplo_size
= sizeof(htstat
);
428 if (!(opts
& OPT_DONOTHING
)) {
429 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
431 perror("ioctl(SIOCLOOKUPSTAT)");
434 printf("Hash Tables:\t%lu\n", htstat
.iphs_numtables
);
435 printf("Nodes:\t%lu\n", htstat
.iphs_numnodes
);
436 printf("Out of Memory:\t%lu\n", htstat
.iphs_nomem
);
443 int poolflush(argc
, argv
)
447 int c
, role
, type
, arg
;
448 iplookupflush_t flush
;
454 while ((c
= getopt(argc
, argv
, "do:t:v")) != -1)
461 role
= getrole(optarg
);
462 if (role
== IPL_LOGNONE
) {
463 fprintf(stderr
, "unknown role '%s'\n", optarg
);
468 type
= gettype(optarg
, NULL
);
469 if (type
== IPLT_NONE
) {
470 fprintf(stderr
, "unknown type '%s'\n", optarg
);
479 if (opts
& OPT_DEBUG
)
480 fprintf(stderr
, "poolflush: opts = %#x\n", opts
);
482 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
483 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
485 perror("open(IPLOOKUP_NAME)");
490 bzero((char *)&flush
, sizeof(flush
));
491 flush
.iplf_type
= type
;
492 flush
.iplf_unit
= role
;
493 flush
.iplf_arg
= arg
;
495 if (!(opts
& OPT_DONOTHING
)) {
496 if (ioctl(fd
, SIOCLOOKUPFLUSH
, &flush
) == -1) {
497 perror("ioctl(SIOCLOOKUPFLUSH)");
502 printf("%u object%s flushed\n", flush
.iplf_count
,
503 (flush
.iplf_count
== 1) ? "" : "s");
509 int getrole(rolename
)
514 if (!strcasecmp(rolename
, "ipf")) {
517 } else if (!strcasecmp(rolename
, "nat")) {
519 } else if (!strcasecmp(rolename
, "state")) {
521 } else if (!strcasecmp(rolename
, "auth")) {
523 } else if (!strcasecmp(rolename
, "sync")) {
525 } else if (!strcasecmp(rolename
, "scan")) {
527 } else if (!strcasecmp(rolename
, "pool")) {
528 role
= IPL_LOGLOOKUP
;
529 } else if (!strcasecmp(rolename
, "count")) {
540 int gettype(typename
, minor
)
546 if (!strcasecmp(optarg
, "tree") || !strcasecmp(optarg
, "pool")) {
548 } else if (!strcasecmp(optarg
, "hash")) {
551 *minor
= IPHASH_LOOKUP
;
552 } else if (!strcasecmp(optarg
, "group-map")) {
555 *minor
= IPHASH_GROUPMAP
;
563 int poollist(argc
, argv
)
567 char *kernel
, *core
, *poolname
;
568 int c
, role
, type
, live_kernel
;
578 while ((c
= getopt(argc
, argv
, "dm:M:N:o:Rt:v")) != -1)
596 role
= getrole(optarg
);
597 if (role
== IPL_LOGNONE
) {
598 fprintf(stderr
, "unknown role '%s'\n", optarg
);
603 opts
|= OPT_NORESOLVE
;
606 type
= gettype(optarg
, NULL
);
607 if (type
== IPLT_NONE
) {
608 fprintf(stderr
, "unknown type '%s'\n", optarg
);
617 if (opts
& OPT_DEBUG
)
618 fprintf(stderr
, "poollist: opts = %#x\n", opts
);
620 if (!(opts
& OPT_DONOTHING
) && (fd
== -1)) {
621 fd
= open(IPLOOKUP_NAME
, O_RDWR
);
623 perror("open(IPLOOKUP_NAME)");
628 bzero((char *)&op
, sizeof(op
));
629 if (poolname
!= NULL
) {
630 strncpy(op
.iplo_name
, poolname
, sizeof(op
.iplo_name
));
631 op
.iplo_name
[sizeof(op
.iplo_name
) - 1] = '\0';
636 poollist_live(role
, poolname
, type
, fd
);
638 poollist_dead(role
, poolname
, type
, kernel
, core
);
643 void poollist_dead(role
, poolname
, type
, kernel
, core
)
645 char *poolname
, *kernel
, *core
;
650 if (openkmem(kernel
, core
) == -1)
653 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
654 ip_pool_t
*pools
[IPL_LOGSIZE
];
655 struct nlist names
[2] = { { "ip_pool_list" } , { "" } };
657 if (nlist(kernel
, names
) != 1)
660 bzero(&pools
, sizeof(pools
));
661 if (kmemcpy((char *)&pools
, names
[0].n_value
, sizeof(pools
)))
664 if (role
!= IPL_LOGALL
) {
666 while (ptr
!= NULL
) {
667 ptr
= printpool(ptr
, kmemcpywrap
, poolname
,
671 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
673 while (ptr
!= NULL
) {
674 ptr
= printpool(ptr
, kmemcpywrap
,
681 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
682 iphtable_t
*tables
[IPL_LOGSIZE
];
683 struct nlist names
[2] = { { "ipf_htables" } , { "" } };
685 if (nlist(kernel
, names
) != 1)
688 bzero(&tables
, sizeof(tables
));
689 if (kmemcpy((char *)&tables
, names
[0].n_value
, sizeof(tables
)))
692 if (role
!= IPL_LOGALL
) {
694 while (hptr
!= NULL
) {
695 hptr
= printhash(hptr
, kmemcpywrap
,
699 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
701 while (hptr
!= NULL
) {
702 hptr
= printhash(hptr
, kmemcpywrap
,
711 void poollist_live(role
, poolname
, type
, fd
)
715 ip_pool_stat_t plstat
;
720 if (type
== IPLT_ALL
|| type
== IPLT_POOL
) {
721 op
.iplo_type
= IPLT_POOL
;
722 op
.iplo_size
= sizeof(plstat
);
723 op
.iplo_struct
= &plstat
;
724 op
.iplo_name
[0] = '\0';
727 if (role
!= IPL_LOGALL
) {
730 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
732 perror("ioctl(SIOCLOOKUPSTAT)");
736 showpools_live(fd
, role
, &plstat
, poolname
);
738 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
741 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
743 perror("ioctl(SIOCLOOKUPSTAT)");
747 showpools_live(fd
, role
, &plstat
, poolname
);
754 if (type
== IPLT_ALL
|| type
== IPLT_HASH
) {
755 op
.iplo_type
= IPLT_HASH
;
756 op
.iplo_size
= sizeof(htstat
);
757 op
.iplo_struct
= &htstat
;
758 op
.iplo_name
[0] = '\0';
761 if (role
!= IPL_LOGALL
) {
764 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
766 perror("ioctl(SIOCLOOKUPSTAT)");
769 showhashs_live(fd
, role
, &htstat
, poolname
);
771 for (role
= 0; role
<= IPL_LOGMAX
; role
++) {
774 c
= ioctl(fd
, SIOCLOOKUPSTAT
, &op
);
776 perror("ioctl(SIOCLOOKUPSTAT)");
780 showhashs_live(fd
, role
, &htstat
, poolname
);
787 void showpools_live(fd
, role
, plstp
, poolname
)
789 ip_pool_stat_t
*plstp
;
792 ipflookupiter_t iter
;
796 obj
.ipfo_rev
= IPFILTER_VERSION
;
797 obj
.ipfo_type
= IPFOBJ_LOOKUPITER
;
798 obj
.ipfo_size
= sizeof(iter
);
799 obj
.ipfo_ptr
= &iter
;
801 iter
.ili_type
= IPLT_POOL
;
802 iter
.ili_otype
= IPFLOOKUPITER_LIST
;
803 iter
.ili_ival
= IPFGENITER_LOOKUP
;
805 iter
.ili_data
= &pool
;
806 iter
.ili_unit
= role
;
807 *iter
.ili_name
= '\0';
809 while (plstp
->ipls_list
[role
] != NULL
) {
810 if (ioctl(fd
, SIOCLOOKUPITER
, &obj
)) {
811 perror("ioctl(SIOCLOOKUPITER)");
814 printpool_live(&pool
, fd
, poolname
, opts
);
816 plstp
->ipls_list
[role
] = pool
.ipo_next
;
821 void showhashs_live(fd
, role
, htstp
, poolname
)
826 ipflookupiter_t iter
;
830 obj
.ipfo_rev
= IPFILTER_VERSION
;
831 obj
.ipfo_type
= IPFOBJ_LOOKUPITER
;
832 obj
.ipfo_size
= sizeof(iter
);
833 obj
.ipfo_ptr
= &iter
;
835 iter
.ili_type
= IPLT_HASH
;
836 iter
.ili_otype
= IPFLOOKUPITER_LIST
;
837 iter
.ili_ival
= IPFGENITER_LOOKUP
;
839 iter
.ili_data
= &table
;
840 iter
.ili_unit
= role
;
841 *iter
.ili_name
= '\0';
843 while (htstp
->iphs_tables
!= NULL
) {
844 if (ioctl(fd
, SIOCLOOKUPITER
, &obj
)) {
845 perror("ioctl(SIOCLOOKUPITER)");
849 printhash_live(&table
, fd
, poolname
, opts
);
851 htstp
->iphs_tables
= table
.iph_next
;
856 int setnodeaddr(ip_pool_node_t
*node
, char *arg
)
861 s
= strchr(arg
, '/');
863 mask
.s_addr
= 0xffffffff;
864 else if (strchr(s
, '.') == NULL
) {
865 if (ntomask(4, atoi(s
+ 1), &mask
.s_addr
) != 0)
868 mask
.s_addr
= inet_addr(s
+ 1);
872 node
->ipn_addr
.adf_len
= sizeof(node
->ipn_addr
);
873 node
->ipn_addr
.adf_addr
.in4
.s_addr
= inet_addr(arg
);
874 node
->ipn_mask
.adf_len
= sizeof(node
->ipn_mask
);
875 node
->ipn_mask
.adf_addr
.in4
.s_addr
= mask
.s_addr
;