freebsd-dev/contrib/ipfilter/tools/ippool.c
Cy Schubert 9658b6b3f4 As with ipf(8), give ippool(8) the ability to load IP pools from multiple
files. This allows for loading, during the same invocation of ippool, of
multiple sources of input using multiple tools to concurrently maintain the
files such as fail2ban, macro preprocessors, and manually.

MFC after:	1 week
2020-02-18 11:26:49 +00:00

1158 lines
24 KiB
C

/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/socket.h>
# include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <ctype.h>
#include <unistd.h>
# include <nlist.h>
#include "ipf.h"
#include "netinet/ipl.h"
#include "netinet/ip_lookup.h"
#include "netinet/ip_pool.h"
#include "netinet/ip_htable.h"
#include "kmem.h"
extern int ippool_yyparse __P((void));
extern int ippool_yydebug;
extern FILE *ippool_yyin;
extern char *optarg;
extern int lineNum;
void usage __P((char *));
int main __P((int, char **));
int poolcommand __P((int, int, char *[]));
int poolnodecommand __P((int, int, char *[]));
int loadpoolfile __P((int, char *[], char *));
int poollist __P((int, char *[]));
void poollist_dead __P((int, char *, int, char *, char *));
void poollist_live __P((int, char *, int, int));
int poolflush __P((int, char *[]));
int poolstats __P((int, char *[]));
int gettype __P((char *, u_int *));
int getrole __P((char *));
int setnodeaddr __P((int, int, void *ptr, char *arg));
void showpools_live __P((int, int, ipf_pool_stat_t *, char *));
void showhashs_live __P((int, int, iphtstat_t *, char *));
void showdstls_live __P((int, int, ipf_dstl_stat_t *, char *));
int opts = 0;
int fd = -1;
int use_inet6 = 0;
wordtab_t *pool_fields = NULL;
int nohdrfields = 0;
void
usage(prog)
char *prog;
{
fprintf(stderr, "Usage:\t%s\n", prog);
fprintf(stderr, "\t-a [-dnv] -m <name> [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n");
fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
fprintf(stderr, "\t-f <file> [-dnuvR]\n");
fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n");
fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-o <role>] [-M <core>] [-N <namelist>]\n");
fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n");
fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
exit(1);
}
int
main(argc, argv)
int argc;
char *argv[];
{
int err = 1;
if (argc < 2)
usage(argv[0]);
assigndefined(getenv("IPPOOL_PREDEFINED"));
switch (getopt(argc, argv, "aAf:FlrRs"))
{
case 'a' :
err = poolnodecommand(0, argc, argv);
break;
case 'A' :
err = poolcommand(0, argc, argv);
break;
case 'f' :
err = loadpoolfile(argc, argv, optarg);
break;
case 'F' :
err = poolflush(argc, argv);
break;
case 'l' :
err = poollist(argc, argv);
break;
case 'r' :
err = poolnodecommand(1, argc, argv);
break;
case 'R' :
err = poolcommand(1, argc, argv);
break;
case 's' :
err = poolstats(argc, argv);
break;
default :
exit(1);
}
if (err != 0)
exit(1);
return 0;
}
int
poolnodecommand(remove, argc, argv)
int remove, argc;
char *argv[];
{
int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
char *poolname = NULL;
ip_pool_node_t pnode;
iphtent_t hnode;
void *ptr = &pnode;
ipset = 0;
role = IPL_LOGIPF;
bzero((char *)&pnode, sizeof(pnode));
bzero((char *)&hnode, sizeof(hnode));
while ((c = getopt(argc, argv, "di:m:no:t:T:v")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
case 'i' :
if (setnodeaddr(type, role, ptr, optarg) == 0)
ipset = 1;
break;
case 'm' :
poolname = optarg;
break;
case 'n' :
opts |= OPT_DONOTHING|OPT_DONTOPEN;
break;
case 'o' :
if (ipset == 1) {
fprintf(stderr,
"cannot set role after ip address\n");
return -1;
}
role = getrole(optarg);
if (role == IPL_LOGNONE)
return -1;
break;
case 't' :
if (ipset == 1) {
fprintf(stderr,
"cannot set type after ip address\n");
return -1;
}
type = gettype(optarg, NULL);
switch (type) {
case IPLT_NONE :
fprintf(stderr, "unknown type '%s'\n", optarg);
return -1;
case IPLT_HASH :
ptr = &hnode;
break;
case IPLT_POOL :
default :
break;
}
break;
case 'T' :
if (remove == 0) {
ttl = atoi(optarg);
if (ttl < 0) {
fprintf(stderr, "cannot set negative ttl\n");
return -1;
}
} else {
usage(argv[0]);
}
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
break; /* keep compiler happy */
}
if (argc - 1 - optind > 0)
usage(argv[0]);
if (argv[optind] != NULL && ipset == 0) {
if (setnodeaddr(type, role, ptr, argv[optind]) == 0)
ipset = 1;
}
if (opts & OPT_DEBUG)
fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
if (ipset == 0) {
fprintf(stderr, "no IP address given with -i\n");
return -1;
}
if (poolname == NULL) {
fprintf(stderr, "poolname not given with add/remove node\n");
return -1;
}
switch (type) {
case IPLT_POOL :
if (remove == 0)
err = load_poolnode(role, poolname, &pnode, ttl, ioctl);
else
err = remove_poolnode(role, poolname, &pnode, ioctl);
break;
case IPLT_HASH :
if (remove == 0)
err = load_hashnode(role, poolname, &hnode, ttl, ioctl);
else
err = remove_hashnode(role, poolname, &hnode, ioctl);
break;
default :
break;
}
return err;
}
int
poolcommand(remove, argc, argv)
int remove, argc;
char *argv[];
{
int type, role, c, err;
char *poolname, *typearg = NULL;
iphtable_t iph;
ip_pool_t pool;
err = 1;
role = 0;
type = 0;
poolname = NULL;
role = IPL_LOGIPF;
bzero((char *)&iph, sizeof(iph));
bzero((char *)&pool, sizeof(pool));
while ((c = getopt(argc, argv, "dm:no:S:vt:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
case 'm' :
poolname = optarg;
break;
case 'n' :
opts |= OPT_DONOTHING|OPT_DONTOPEN;
break;
case 'o' :
role = getrole(optarg);
if (role == IPL_LOGNONE) {
fprintf(stderr, "unknown role '%s'\n", optarg);
return -1;
}
break;
case 'S' :
if (remove == 0)
iph.iph_seed = atoi(optarg);
else
usage(argv[0]);
break;
case 't' :
type = gettype(optarg, &iph.iph_type);
typearg = optarg;
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
break; /* keep compiler happy */
}
if (argc - 1 - optind > 0)
usage(argv[0]);
if (opts & OPT_DEBUG)
fprintf(stderr, "poolcommand: opts = %#x\n", opts);
if (poolname == NULL) {
fprintf(stderr, "poolname not given with add/remove pool\n");
return -1;
}
if (type == IPLT_NONE && remove == 0) {
if (typearg == NULL) {
fprintf(stderr, "type must be specified\n");
usage(argv[0]);
} else {
fprintf(stderr, "unknown type '%s'\n", typearg);
}
return -1;
}
if (type == IPLT_HASH || (type == IPLT_NONE && remove == 1)) {
strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
iph.iph_unit = role;
}
if (type == IPLT_POOL || (type == IPLT_NONE && remove == 1)) {
strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
pool.ipo_unit = role;
}
if (remove == 0) {
switch (type)
{
case IPLT_HASH :
err = load_hash(&iph, NULL, ioctl);
break;
case IPLT_POOL :
err = load_pool(&pool, ioctl);
break;
}
} else {
switch (type)
{
case IPLT_HASH :
err = remove_hash(&iph, ioctl);
break;
case IPLT_POOL :
err = remove_pool(&pool, ioctl);
break;
case IPLT_NONE :
err = 1;
{
int err_h, err_p;
err_h = remove_hash(&iph, ioctl);
err_p = remove_pool(&pool, ioctl);
if (err_h == 0 || err_p == 0)
err = 0;
}
break;
}
}
return err;
}
int
loadpoolfile(argc, argv, infile)
int argc;
char *argv[], *infile;
{
int c;
while ((c = getopt(argc, argv, "dnuvf:")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
ippool_yydebug++;
break;
case 'f' :
if (loadpoolfile(argc, argv, optarg) != 0)
return(-1);
break;
case 'n' :
opts |= OPT_DONOTHING|OPT_DONTOPEN;
break;
case 'u' :
opts |= OPT_REMOVE;
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
break; /* keep compiler happy */
}
if (argc - 1 - optind > 0)
usage(argv[0]);
if (opts & OPT_DEBUG)
fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
fd = open(IPLOOKUP_NAME, O_RDWR);
if (fd == -1) {
perror("open(IPLOOKUP_NAME)");
exit(1);
}
}
if (ippool_parsefile(fd, infile, ioctl) != 0)
return -1;
return 0;
}
int
poolstats(argc, argv)
int argc;
char *argv[];
{
int c, type, role, live_kernel;
ipf_pool_stat_t plstat;
ipf_dstl_stat_t dlstat;
char *kernel, *core;
iphtstat_t htstat;
iplookupop_t op;
core = NULL;
kernel = NULL;
live_kernel = 1;
type = IPLT_ALL;
role = IPL_LOGALL;
bzero((char *)&op, sizeof(op));
while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
case 'M' :
live_kernel = 0;
core = optarg;
break;
case 'N' :
live_kernel = 0;
kernel = optarg;
break;
case 'o' :
role = getrole(optarg);
if (role == IPL_LOGNONE) {
fprintf(stderr, "unknown role '%s'\n", optarg);
return -1;
}
break;
case 't' :
type = gettype(optarg, NULL);
if (type != IPLT_POOL) {
fprintf(stderr,
"-s not supported for this type yet\n");
return -1;
}
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
break; /* keep compiler happy */
}
if (argc - 1 - optind > 0)
usage(argv[0]);
if (opts & OPT_DEBUG)
fprintf(stderr, "poolstats: opts = %#x\n", opts);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
fd = open(IPLOOKUP_NAME, O_RDWR);
if (fd == -1) {
perror("open(IPLOOKUP_NAME)");
exit(1);
}
}
if (type == IPLT_ALL || type == IPLT_POOL) {
op.iplo_type = IPLT_POOL;
op.iplo_struct = &plstat;
op.iplo_size = sizeof(plstat);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)");
return -1;
}
printf("%lu\taddress pools\n", plstat.ipls_pools);
printf("%lu\taddress pool nodes\n", plstat.ipls_nodes);
}
}
if (type == IPLT_ALL || type == IPLT_HASH) {
op.iplo_type = IPLT_HASH;
op.iplo_struct = &htstat;
op.iplo_size = sizeof(htstat);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return -1;
}
printf("%lu\thash tables\n", htstat.iphs_numtables);
printf("%lu\thash table nodes\n", htstat.iphs_numnodes);
printf("%lu\thash table no memory \n",
htstat.iphs_nomem);
}
}
if (type == IPLT_ALL || type == IPLT_DSTLIST) {
op.iplo_type = IPLT_DSTLIST;
op.iplo_struct = &dlstat;
op.iplo_size = sizeof(dlstat);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return -1;
}
printf("%u\tdestination lists\n",
dlstat.ipls_numlists);
printf("%u\tdestination list nodes\n",
dlstat.ipls_numnodes);
printf("%lu\tdestination list no memory\n",
dlstat.ipls_nomem);
printf("%u\tdestination list zombies\n",
dlstat.ipls_numdereflists);
printf("%u\tdesetination list node zombies\n",
dlstat.ipls_numderefnodes);
}
}
return 0;
}
int
poolflush(argc, argv)
int argc;
char *argv[];
{
int c, role, type, arg;
iplookupflush_t flush;
arg = IPLT_ALL;
type = IPLT_ALL;
role = IPL_LOGALL;
while ((c = getopt(argc, argv, "do:t:v")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
case 'o' :
role = getrole(optarg);
if (role == IPL_LOGNONE) {
fprintf(stderr, "unknown role '%s'\n", optarg);
return -1;
}
break;
case 't' :
type = gettype(optarg, NULL);
if (type == IPLT_NONE) {
fprintf(stderr, "unknown type '%s'\n", optarg);
return -1;
}
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
break; /* keep compiler happy */
}
if (argc - optind > 0)
usage(argv[0]);
if (opts & OPT_DEBUG)
fprintf(stderr, "poolflush: opts = %#x\n", opts);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
fd = open(IPLOOKUP_NAME, O_RDWR);
if (fd == -1) {
perror("open(IPLOOKUP_NAME)");
exit(1);
}
}
bzero((char *)&flush, sizeof(flush));
flush.iplf_type = type;
flush.iplf_unit = role;
flush.iplf_arg = arg;
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)");
exit(1);
}
}
printf("%u object%s flushed\n", flush.iplf_count,
(flush.iplf_count == 1) ? "" : "s");
return 0;
}
int
getrole(rolename)
char *rolename;
{
int role;
if (!strcasecmp(rolename, "ipf")) {
role = IPL_LOGIPF;
#if 0
} else if (!strcasecmp(rolename, "nat")) {
role = IPL_LOGNAT;
} else if (!strcasecmp(rolename, "state")) {
role = IPL_LOGSTATE;
} else if (!strcasecmp(rolename, "auth")) {
role = IPL_LOGAUTH;
} else if (!strcasecmp(rolename, "sync")) {
role = IPL_LOGSYNC;
} else if (!strcasecmp(rolename, "scan")) {
role = IPL_LOGSCAN;
} else if (!strcasecmp(rolename, "pool")) {
role = IPL_LOGLOOKUP;
} else if (!strcasecmp(rolename, "count")) {
role = IPL_LOGCOUNT;
#endif
} else {
role = IPL_LOGNONE;
}
return role;
}
int
gettype(typename, minor)
char *typename;
u_int *minor;
{
int type;
if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) {
type = IPLT_POOL;
} else if (!strcasecmp(typename, "hash")) {
type = IPLT_HASH;
if (minor != NULL)
*minor = IPHASH_LOOKUP;
} else if (!strcasecmp(typename, "group-map")) {
type = IPLT_HASH;
if (minor != NULL)
*minor = IPHASH_GROUPMAP;
} else {
type = IPLT_NONE;
}
return type;
}
int
poollist(argc, argv)
int argc;
char *argv[];
{
char *kernel, *core, *poolname;
int c, role, type, live_kernel;
iplookupop_t op;
core = NULL;
kernel = NULL;
live_kernel = 1;
type = IPLT_ALL;
poolname = NULL;
role = IPL_LOGALL;
while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
case 'm' :
poolname = optarg;
break;
case 'M' :
live_kernel = 0;
core = optarg;
break;
case 'N' :
live_kernel = 0;
kernel = optarg;
break;
case 'o' :
role = getrole(optarg);
if (role == IPL_LOGNONE) {
fprintf(stderr, "unknown role '%s'\n", optarg);
return -1;
}
break;
#if 0
case 'O' :
/* XXX This option does not work. This function as */
/* XXX used by state and nat can be used to format */
/* XXX output especially useful for scripting. It */
/* XXX is left here with the intention of making */
/* XXX it work for the same purpose at some point. */
pool_fields = parsefields(poolfields, optarg);
break;
#endif
case 't' :
type = gettype(optarg, NULL);
if (type == IPLT_NONE) {
fprintf(stderr, "unknown type '%s'\n", optarg);
return -1;
}
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
default :
usage(argv[0]);
break; /* keep compiler happy */
}
if (argc - optind > 0)
usage(argv[0]);
if (opts & OPT_DEBUG)
fprintf(stderr, "poollist: opts = %#x\n", opts);
if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
fd = open(IPLOOKUP_NAME, O_RDWR);
if (fd == -1) {
perror("open(IPLOOKUP_NAME)");
exit(1);
}
}
bzero((char *)&op, sizeof(op));
if (poolname != NULL) {
strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
}
op.iplo_unit = role;
if (live_kernel)
poollist_live(role, poolname, type, fd);
else
poollist_dead(role, poolname, type, kernel, core);
return 0;
}
void
poollist_dead(role, poolname, type, kernel, core)
int role, type;
char *poolname, *kernel, *core;
{
iphtable_t *hptr;
ip_pool_t *ptr;
if (openkmem(kernel, core) == -1)
exit(-1);
if (type == IPLT_ALL || type == IPLT_POOL) {
ip_pool_t *pools[IPL_LOGSIZE];
struct nlist names[2] = { { "ip_pool_list" } , { "" } };
if (nlist(kernel, names) != 1)
return;
bzero(&pools, sizeof(pools));
if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
return;
if (role != IPL_LOGALL) {
ptr = pools[role];
while (ptr != NULL) {
ptr = printpool(ptr, kmemcpywrap, poolname,
opts, pool_fields);
}
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
ptr = pools[role];
while (ptr != NULL) {
ptr = printpool(ptr, kmemcpywrap,
poolname, opts,
pool_fields);
}
}
role = IPL_LOGALL;
}
}
if (type == IPLT_ALL || type == IPLT_HASH) {
iphtable_t *tables[IPL_LOGSIZE];
struct nlist names[2] = { { "ipf_htables" } , { "" } };
if (nlist(kernel, names) != 1)
return;
bzero(&tables, sizeof(tables));
if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
return;
if (role != IPL_LOGALL) {
hptr = tables[role];
while (hptr != NULL) {
hptr = printhash(hptr, kmemcpywrap,
poolname, opts, pool_fields);
}
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
hptr = tables[role];
while (hptr != NULL) {
hptr = printhash(hptr, kmemcpywrap,
poolname, opts,
pool_fields);
}
}
}
}
}
void
poollist_live(role, poolname, type, fd)
int role, type, fd;
char *poolname;
{
ipf_pool_stat_t plstat;
iplookupop_t op;
int c;
if (type == IPLT_ALL || type == IPLT_POOL) {
op.iplo_type = IPLT_POOL;
op.iplo_size = sizeof(plstat);
op.iplo_struct = &plstat;
op.iplo_name[0] = '\0';
op.iplo_arg = 0;
if (role != IPL_LOGALL) {
op.iplo_unit = role;
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return;
}
showpools_live(fd, role, &plstat, poolname);
} else {
for (role = -1; role <= IPL_LOGMAX; role++) {
op.iplo_unit = role;
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return;
}
showpools_live(fd, role, &plstat, poolname);
}
role = IPL_LOGALL;
}
}
if (type == IPLT_ALL || type == IPLT_HASH) {
iphtstat_t htstat;
op.iplo_type = IPLT_HASH;
op.iplo_size = sizeof(htstat);
op.iplo_struct = &htstat;
op.iplo_name[0] = '\0';
op.iplo_arg = 0;
if (role != IPL_LOGALL) {
op.iplo_unit = role;
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return;
}
showhashs_live(fd, role, &htstat, poolname);
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
op.iplo_unit = role;
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return;
}
showhashs_live(fd, role, &htstat, poolname);
}
role = IPL_LOGALL;
}
}
if (type == IPLT_ALL || type == IPLT_DSTLIST) {
ipf_dstl_stat_t dlstat;
op.iplo_type = IPLT_DSTLIST;
op.iplo_size = sizeof(dlstat);
op.iplo_struct = &dlstat;
op.iplo_name[0] = '\0';
op.iplo_arg = 0;
if (role != IPL_LOGALL) {
op.iplo_unit = role;
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return;
}
showdstls_live(fd, role, &dlstat, poolname);
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
op.iplo_unit = role;
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
return;
}
showdstls_live(fd, role, &dlstat, poolname);
}
role = IPL_LOGALL;
}
}
}
void
showpools_live(fd, role, plstp, poolname)
int fd, role;
ipf_pool_stat_t *plstp;
char *poolname;
{
ipflookupiter_t iter;
ip_pool_t pool;
ipfobj_t obj;
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_type = IPFOBJ_LOOKUPITER;
obj.ipfo_size = sizeof(iter);
obj.ipfo_ptr = &iter;
iter.ili_type = IPLT_POOL;
iter.ili_otype = IPFLOOKUPITER_LIST;
iter.ili_ival = IPFGENITER_LOOKUP;
iter.ili_nitems = 1;
iter.ili_data = &pool;
iter.ili_unit = role;
*iter.ili_name = '\0';
bzero((char *)&pool, sizeof(pool));
while (plstp->ipls_list[role + 1] != NULL) {
if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
ipferror(fd, "ioctl(SIOCLOOKUPITER)");
break;
}
if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
((opts & OPT_DEBUG) != 0))
printpool_live(&pool, fd, poolname, opts, pool_fields);
plstp->ipls_list[role + 1] = pool.ipo_next;
}
}
void
showhashs_live(fd, role, htstp, poolname)
int fd, role;
iphtstat_t *htstp;
char *poolname;
{
ipflookupiter_t iter;
iphtable_t table;
ipfobj_t obj;
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_type = IPFOBJ_LOOKUPITER;
obj.ipfo_size = sizeof(iter);
obj.ipfo_ptr = &iter;
iter.ili_type = IPLT_HASH;
iter.ili_otype = IPFLOOKUPITER_LIST;
iter.ili_ival = IPFGENITER_LOOKUP;
iter.ili_nitems = 1;
iter.ili_data = &table;
iter.ili_unit = role;
*iter.ili_name = '\0';
while (htstp->iphs_tables != NULL) {
if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
ipferror(fd, "ioctl(SIOCLOOKUPITER)");
break;
}
printhash_live(&table, fd, poolname, opts, pool_fields);
htstp->iphs_tables = table.iph_next;
}
}
void
showdstls_live(fd, role, dlstp, poolname)
int fd, role;
ipf_dstl_stat_t *dlstp;
char *poolname;
{
ipflookupiter_t iter;
ippool_dst_t table;
ipfobj_t obj;
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_type = IPFOBJ_LOOKUPITER;
obj.ipfo_size = sizeof(iter);
obj.ipfo_ptr = &iter;
iter.ili_type = IPLT_DSTLIST;
iter.ili_otype = IPFLOOKUPITER_LIST;
iter.ili_ival = IPFGENITER_LOOKUP;
iter.ili_nitems = 1;
iter.ili_data = &table;
iter.ili_unit = role;
*iter.ili_name = '\0';
while (dlstp->ipls_list[role] != NULL) {
if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
ipferror(fd, "ioctl(SIOCLOOKUPITER)");
break;
}
printdstl_live(&table, fd, poolname, opts, pool_fields);
dlstp->ipls_list[role] = table.ipld_next;
}
}
int
setnodeaddr(int type, int role, void *ptr, char *arg)
{
struct in_addr mask;
sa_family_t family;
char *s;
if (strchr(arg, ':') == NULL) {
family = AF_INET;
s = strchr(arg, '/');
if (s == NULL)
mask.s_addr = 0xffffffff;
else if (strchr(s, '.') == NULL) {
if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0)
return -1;
} else {
mask.s_addr = inet_addr(s + 1);
}
if (s != NULL)
*s = '\0';
} else {
family = AF_INET6;
/* XXX for now we use mask for IPv6 prefix length */
/* XXX mask should be a union with prefix */
/* XXX Currently address handling is sloppy. */
if ((s = strchr(arg, '/')) == NULL)
mask.s_addr = 128;
else
mask.s_addr = atoi(s + 1);
}
if (type == IPLT_POOL) {
ip_pool_node_t *node = ptr;
node->ipn_addr.adf_family = family;
#ifdef USE_INET6
if (node->ipn_addr.adf_family == AF_INET) {
#endif
node->ipn_addr.adf_len = offsetof(addrfamily_t,
adf_addr) +
sizeof(struct in_addr);
node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
#ifdef USE_INET6
} else {
node->ipn_addr.adf_len = offsetof(addrfamily_t,
adf_addr) +
sizeof(struct in6_addr);
inet_pton(AF_INET6, arg,
&node->ipn_addr.adf_addr.in6.s6_addr);
}
#endif
node->ipn_mask.adf_len = node->ipn_addr.adf_len;
node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
} else if (type == IPLT_HASH) {
iphtent_t *node = ptr;
node->ipe_family = family;
node->ipe_unit = role;
#ifdef USE_INET6
if (node->ipe_family == AF_INET) {
#endif
node->ipe_addr.in4.s_addr = inet_addr(arg);
node->ipe_mask.in4.s_addr = mask.s_addr;
#ifdef USE_INET6
} else {
inet_pton(AF_INET6, arg,
&node->ipe_addr.in6.__u6_addr.__u6_addr32);
node->ipe_mask.in6.__u6_addr.__u6_addr32[0] =
mask.s_addr;
node->ipe_mask.in6.__u6_addr.__u6_addr32[1] =
node->ipe_mask.in6.__u6_addr.__u6_addr32[2] =
node->ipe_mask.in6.__u6_addr.__u6_addr32[3] = 0;
}
#endif
}
return 0;
}