4 * Copyright (C) 2012 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 #include <netinet/in.h>
20 #include <arpa/inet.h>
30 # include <linux/a.out.h>
36 #include "netinet/ipl.h"
37 #include "netinet/ip_lookup.h"
38 #include "netinet/ip_pool.h"
39 #include "netinet/ip_htable.h"
43 extern int ippool_yyparse __P((void));
44 extern int ippool_yydebug;
45 extern FILE *ippool_yyin;
49 void usage __P((char *));
50 int main __P((int, char **));
51 int poolcommand __P((int, int, char *[]));
52 int poolnodecommand __P((int, int, char *[]));
53 int loadpoolfile __P((int, char *[], char *));
54 int poollist __P((int, char *[]));
55 void poollist_dead __P((int, char *, int, char *, char *));
56 void poollist_live __P((int, char *, int, int));
57 int poolflush __P((int, char *[]));
58 int poolstats __P((int, char *[]));
59 int gettype __P((char *, u_int *));
60 int getrole __P((char *));
61 int setnodeaddr __P((int, int, void *ptr, char *arg));
62 void showpools_live __P((int, int, ipf_pool_stat_t *, char *));
63 void showhashs_live __P((int, int, iphtstat_t *, char *));
64 void showdstls_live __P((int, int, ipf_dstl_stat_t *, char *));
69 wordtab_t *pool_fields = NULL;
77 fprintf(stderr, "Usage:\t%s\n", prog);
78 fprintf(stderr, "\t-a [-dnv] [-m <name>] [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n");
79 fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
80 fprintf(stderr, "\t-f <file> [-dnuv]\n");
81 fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n");
82 fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-O <fields>]\n");
83 fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n");
84 fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
85 fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
100 assigndefined(getenv("IPPOOL_PREDEFINED"));
102 switch (getopt(argc, argv, "aAf:FlnrRsv"))
105 err = poolnodecommand(0, argc, argv);
108 err = poolcommand(0, argc, argv);
111 err = loadpoolfile(argc, argv, optarg);
114 err = poolflush(argc, argv);
117 err = poollist(argc, argv);
120 opts |= OPT_DONOTHING|OPT_DONTOPEN;
123 err = poolnodecommand(1, argc, argv);
126 err = poolcommand(1, argc, argv);
129 err = poolstats(argc, argv);
145 poolnodecommand(remove, argc, argv)
149 int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
150 char *poolname = NULL;
151 ip_pool_node_t pnode;
157 bzero((char *)&pnode, sizeof(pnode));
158 bzero((char *)&hnode, sizeof(hnode));
160 while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1)
168 if (setnodeaddr(type, role, ptr, optarg) == 0)
175 opts |= OPT_DONOTHING|OPT_DONTOPEN;
180 "cannot set role after ip address\n");
183 role = getrole(optarg);
184 if (role == IPL_LOGNONE)
188 opts |= OPT_NORESOLVE;
193 "cannot set type after ip address\n");
196 type = gettype(optarg, NULL);
199 fprintf(stderr, "unknown type '%s'\n", optarg);
212 fprintf(stderr, "cannot set negative ttl\n");
221 if (argv[optind] != NULL && ipset == 0) {
222 if (setnodeaddr(type, role, ptr, argv[optind]) == 0)
226 if (opts & OPT_DEBUG)
227 fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
230 fprintf(stderr, "no IP address given with -i\n");
234 if (poolname == NULL) {
235 fprintf(stderr, "poolname not given with add/remove node\n");
242 err = load_poolnode(role, poolname, &pnode, ttl, ioctl);
244 err = remove_poolnode(role, poolname, &pnode, ioctl);
248 err = load_hashnode(role, poolname, &hnode, ttl, ioctl);
250 err = remove_hashnode(role, poolname, &hnode, ioctl);
260 poolcommand(remove, argc, argv)
264 int type, role, c, err;
274 bzero((char *)&iph, sizeof(iph));
275 bzero((char *)&pool, sizeof(pool));
277 while ((c = getopt(argc, argv, "dm:no:RSv")) != -1)
288 opts |= OPT_DONOTHING|OPT_DONTOPEN;
291 role = getrole(optarg);
292 if (role == IPL_LOGNONE) {
293 fprintf(stderr, "unknown role '%s'\n", optarg);
298 opts |= OPT_NORESOLVE;
301 iph.iph_seed = atoi(optarg);
308 if (opts & OPT_DEBUG)
309 fprintf(stderr, "poolcommand: opts = %#x\n", opts);
311 if (poolname == NULL) {
312 fprintf(stderr, "poolname not given with add/remove pool\n");
316 type = gettype(argv[optind], &iph.iph_type);
317 if (type == IPLT_NONE) {
318 fprintf(stderr, "unknown type '%s'\n", argv[optind]);
322 if (type == IPLT_HASH) {
323 strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
324 iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
326 } else if (type == IPLT_POOL) {
327 strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
328 pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
329 pool.ipo_unit = role;
336 err = load_hash(&iph, NULL, ioctl);
339 err = load_pool(&pool, ioctl);
346 err = remove_hash(&iph, ioctl);
349 err = remove_pool(&pool, ioctl);
358 loadpoolfile(argc, argv, infile)
360 char *argv[], *infile;
366 while ((c = getopt(argc, argv, "dnRuv")) != -1)
374 opts |= OPT_DONOTHING|OPT_DONTOPEN;
377 opts |= OPT_NORESOLVE;
387 if (opts & OPT_DEBUG)
388 fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
390 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
391 fd = open(IPLOOKUP_NAME, O_RDWR);
393 perror("open(IPLOOKUP_NAME)");
398 if (ippool_parsefile(fd, infile, ioctl) != 0)
405 poolstats(argc, argv)
409 int c, type, role, live_kernel;
410 ipf_pool_stat_t plstat;
411 ipf_dstl_stat_t dlstat;
422 bzero((char *)&op, sizeof(op));
424 while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
439 role = getrole(optarg);
440 if (role == IPL_LOGNONE) {
441 fprintf(stderr, "unknown role '%s'\n", optarg);
446 type = gettype(optarg, NULL);
447 if (type != IPLT_POOL) {
449 "-s not supported for this type yet\n");
458 if (opts & OPT_DEBUG)
459 fprintf(stderr, "poolstats: opts = %#x\n", opts);
461 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
462 fd = open(IPLOOKUP_NAME, O_RDWR);
464 perror("open(IPLOOKUP_NAME)");
469 if (type == IPLT_ALL || type == IPLT_POOL) {
470 op.iplo_type = IPLT_POOL;
471 op.iplo_struct = &plstat;
472 op.iplo_size = sizeof(plstat);
473 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
474 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
476 ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)");
479 printf("%lu\taddress pools\n", plstat.ipls_pools);
480 printf("%lu\taddress pool nodes\n", plstat.ipls_nodes);
484 if (type == IPLT_ALL || type == IPLT_HASH) {
485 op.iplo_type = IPLT_HASH;
486 op.iplo_struct = &htstat;
487 op.iplo_size = sizeof(htstat);
488 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
489 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
491 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
494 printf("%lu\thash tables\n", htstat.iphs_numtables);
495 printf("%lu\thash table nodes\n", htstat.iphs_numnodes);
496 printf("%lu\thash table no memory \n",
501 if (type == IPLT_ALL || type == IPLT_DSTLIST) {
502 op.iplo_type = IPLT_DSTLIST;
503 op.iplo_struct = &dlstat;
504 op.iplo_size = sizeof(dlstat);
505 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
506 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
508 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
511 printf("%u\tdestination lists\n",
512 dlstat.ipls_numlists);
513 printf("%u\tdestination list nodes\n",
514 dlstat.ipls_numnodes);
515 printf("%lu\tdestination list no memory\n",
517 printf("%u\tdestination list zombies\n",
518 dlstat.ipls_numdereflists);
519 printf("%u\tdesetination list node zombies\n",
520 dlstat.ipls_numderefnodes);
528 poolflush(argc, argv)
532 int c, role, type, arg;
533 iplookupflush_t flush;
539 while ((c = getopt(argc, argv, "do:t:v")) != -1)
546 role = getrole(optarg);
547 if (role == IPL_LOGNONE) {
548 fprintf(stderr, "unknown role '%s'\n", optarg);
553 type = gettype(optarg, NULL);
554 if (type == IPLT_NONE) {
555 fprintf(stderr, "unknown type '%s'\n", optarg);
564 if (opts & OPT_DEBUG)
565 fprintf(stderr, "poolflush: opts = %#x\n", opts);
567 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
568 fd = open(IPLOOKUP_NAME, O_RDWR);
570 perror("open(IPLOOKUP_NAME)");
575 bzero((char *)&flush, sizeof(flush));
576 flush.iplf_type = type;
577 flush.iplf_unit = role;
578 flush.iplf_arg = arg;
580 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
581 if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
582 ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)");
587 printf("%u object%s flushed\n", flush.iplf_count,
588 (flush.iplf_count == 1) ? "" : "s");
600 if (!strcasecmp(rolename, "ipf")) {
603 } else if (!strcasecmp(rolename, "nat")) {
605 } else if (!strcasecmp(rolename, "state")) {
607 } else if (!strcasecmp(rolename, "auth")) {
609 } else if (!strcasecmp(rolename, "sync")) {
611 } else if (!strcasecmp(rolename, "scan")) {
613 } else if (!strcasecmp(rolename, "pool")) {
614 role = IPL_LOGLOOKUP;
615 } else if (!strcasecmp(rolename, "count")) {
627 gettype(typename, minor)
633 if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) {
635 } else if (!strcasecmp(typename, "hash")) {
638 *minor = IPHASH_LOOKUP;
639 } else if (!strcasecmp(typename, "group-map")) {
642 *minor = IPHASH_GROUPMAP;
655 char *kernel, *core, *poolname;
656 int c, role, type, live_kernel;
666 while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
684 role = getrole(optarg);
685 if (role == IPL_LOGNONE) {
686 fprintf(stderr, "unknown role '%s'\n", optarg);
691 pool_fields = parsefields(poolfields, optarg);
694 opts |= OPT_NORESOLVE;
697 type = gettype(optarg, NULL);
698 if (type == IPLT_NONE) {
699 fprintf(stderr, "unknown type '%s'\n", optarg);
708 if (opts & OPT_DEBUG)
709 fprintf(stderr, "poollist: opts = %#x\n", opts);
711 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
712 fd = open(IPLOOKUP_NAME, O_RDWR);
714 perror("open(IPLOOKUP_NAME)");
719 bzero((char *)&op, sizeof(op));
720 if (poolname != NULL) {
721 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
722 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
727 poollist_live(role, poolname, type, fd);
729 poollist_dead(role, poolname, type, kernel, core);
735 poollist_dead(role, poolname, type, kernel, core)
737 char *poolname, *kernel, *core;
742 if (openkmem(kernel, core) == -1)
745 if (type == IPLT_ALL || type == IPLT_POOL) {
746 ip_pool_t *pools[IPL_LOGSIZE];
747 struct nlist names[2] = { { "ip_pool_list" } , { "" } };
749 if (nlist(kernel, names) != 1)
752 bzero(&pools, sizeof(pools));
753 if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
756 if (role != IPL_LOGALL) {
758 while (ptr != NULL) {
759 ptr = printpool(ptr, kmemcpywrap, poolname,
763 for (role = 0; role <= IPL_LOGMAX; role++) {
765 while (ptr != NULL) {
766 ptr = printpool(ptr, kmemcpywrap,
774 if (type == IPLT_ALL || type == IPLT_HASH) {
775 iphtable_t *tables[IPL_LOGSIZE];
776 struct nlist names[2] = { { "ipf_htables" } , { "" } };
778 if (nlist(kernel, names) != 1)
781 bzero(&tables, sizeof(tables));
782 if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
785 if (role != IPL_LOGALL) {
787 while (hptr != NULL) {
788 hptr = printhash(hptr, kmemcpywrap,
789 poolname, opts, pool_fields);
792 for (role = 0; role <= IPL_LOGMAX; role++) {
794 while (hptr != NULL) {
795 hptr = printhash(hptr, kmemcpywrap,
806 poollist_live(role, poolname, type, fd)
810 ipf_pool_stat_t plstat;
814 if (type == IPLT_ALL || type == IPLT_POOL) {
815 op.iplo_type = IPLT_POOL;
816 op.iplo_size = sizeof(plstat);
817 op.iplo_struct = &plstat;
818 op.iplo_name[0] = '\0';
821 if (role != IPL_LOGALL) {
824 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
826 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
830 showpools_live(fd, role, &plstat, poolname);
832 for (role = -1; role <= IPL_LOGMAX; role++) {
835 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
837 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
841 showpools_live(fd, role, &plstat, poolname);
848 if (type == IPLT_ALL || type == IPLT_HASH) {
851 op.iplo_type = IPLT_HASH;
852 op.iplo_size = sizeof(htstat);
853 op.iplo_struct = &htstat;
854 op.iplo_name[0] = '\0';
857 if (role != IPL_LOGALL) {
860 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
862 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
865 showhashs_live(fd, role, &htstat, poolname);
867 for (role = 0; role <= IPL_LOGMAX; role++) {
870 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
872 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
876 showhashs_live(fd, role, &htstat, poolname);
882 if (type == IPLT_ALL || type == IPLT_DSTLIST) {
883 ipf_dstl_stat_t dlstat;
885 op.iplo_type = IPLT_DSTLIST;
886 op.iplo_size = sizeof(dlstat);
887 op.iplo_struct = &dlstat;
888 op.iplo_name[0] = '\0';
891 if (role != IPL_LOGALL) {
894 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
896 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
899 showdstls_live(fd, role, &dlstat, poolname);
901 for (role = 0; role <= IPL_LOGMAX; role++) {
904 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
906 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
910 showdstls_live(fd, role, &dlstat, poolname);
919 showpools_live(fd, role, plstp, poolname)
921 ipf_pool_stat_t *plstp;
924 ipflookupiter_t iter;
928 obj.ipfo_rev = IPFILTER_VERSION;
929 obj.ipfo_type = IPFOBJ_LOOKUPITER;
930 obj.ipfo_size = sizeof(iter);
931 obj.ipfo_ptr = &iter;
933 iter.ili_type = IPLT_POOL;
934 iter.ili_otype = IPFLOOKUPITER_LIST;
935 iter.ili_ival = IPFGENITER_LOOKUP;
937 iter.ili_data = &pool;
938 iter.ili_unit = role;
939 *iter.ili_name = '\0';
941 bzero((char *)&pool, sizeof(pool));
943 while (plstp->ipls_list[role + 1] != NULL) {
944 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
945 ipferror(fd, "ioctl(SIOCLOOKUPITER)");
948 if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
949 ((opts & OPT_DEBUG) != 0))
950 printpool_live(&pool, fd, poolname, opts, pool_fields);
952 plstp->ipls_list[role + 1] = pool.ipo_next;
958 showhashs_live(fd, role, htstp, poolname)
963 ipflookupiter_t iter;
967 obj.ipfo_rev = IPFILTER_VERSION;
968 obj.ipfo_type = IPFOBJ_LOOKUPITER;
969 obj.ipfo_size = sizeof(iter);
970 obj.ipfo_ptr = &iter;
972 iter.ili_type = IPLT_HASH;
973 iter.ili_otype = IPFLOOKUPITER_LIST;
974 iter.ili_ival = IPFGENITER_LOOKUP;
976 iter.ili_data = &table;
977 iter.ili_unit = role;
978 *iter.ili_name = '\0';
980 while (htstp->iphs_tables != NULL) {
981 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
982 ipferror(fd, "ioctl(SIOCLOOKUPITER)");
986 printhash_live(&table, fd, poolname, opts, pool_fields);
988 htstp->iphs_tables = table.iph_next;
994 showdstls_live(fd, role, dlstp, poolname)
996 ipf_dstl_stat_t *dlstp;
999 ipflookupiter_t iter;
1003 obj.ipfo_rev = IPFILTER_VERSION;
1004 obj.ipfo_type = IPFOBJ_LOOKUPITER;
1005 obj.ipfo_size = sizeof(iter);
1006 obj.ipfo_ptr = &iter;
1008 iter.ili_type = IPLT_DSTLIST;
1009 iter.ili_otype = IPFLOOKUPITER_LIST;
1010 iter.ili_ival = IPFGENITER_LOOKUP;
1011 iter.ili_nitems = 1;
1012 iter.ili_data = &table;
1013 iter.ili_unit = role;
1014 *iter.ili_name = '\0';
1016 while (dlstp->ipls_list[role] != NULL) {
1017 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
1018 ipferror(fd, "ioctl(SIOCLOOKUPITER)");
1022 printdstl_live(&table, fd, poolname, opts, pool_fields);
1024 dlstp->ipls_list[role] = table.ipld_next;
1030 setnodeaddr(int type, int role, void *ptr, char *arg)
1032 struct in_addr mask;
1035 s = strchr(arg, '/');
1037 mask.s_addr = 0xffffffff;
1038 else if (strchr(s, '.') == NULL) {
1039 if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0)
1042 mask.s_addr = inet_addr(s + 1);
1047 if (type == IPLT_POOL) {
1048 ip_pool_node_t *node = ptr;
1050 if (node->ipn_addr.adf_family == AF_INET)
1051 node->ipn_addr.adf_len = offsetof(addrfamily_t,
1053 sizeof(struct in_addr);
1056 node->ipn_addr.adf_len = offsetof(addrfamily_t,
1058 sizeof(struct in6_addr);
1060 node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
1061 node->ipn_mask.adf_len = node->ipn_addr.adf_len;
1062 node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
1063 } else if (type == IPLT_HASH) {
1064 iphtent_t *node = ptr;
1066 node->ipe_addr.in4.s_addr = inet_addr(arg);
1067 node->ipe_mask.in4.s_addr = mask.s_addr;
1068 node->ipe_family = AF_INET;
1069 node->ipe_unit = role;