ippool.c revision 145510
122208Sdavidn/*	$NetBSD$	*/
222208Sdavidn
322208Sdavidn/*
422208Sdavidn * Copyright (C) 2003 by Darren Reed.
522208Sdavidn *
622208Sdavidn * See the IPFILTER.LICENCE file for details on licencing.
722208Sdavidn */
822208Sdavidn#include <sys/types.h>
922208Sdavidn#include <sys/time.h>
1022208Sdavidn#include <sys/param.h>
1122208Sdavidn#include <sys/socket.h>
1222208Sdavidn#if defined(BSD) && (BSD >= 199306)
1322208Sdavidn# include <sys/cdefs.h>
1422208Sdavidn#endif
1522208Sdavidn#include <sys/ioctl.h>
1622208Sdavidn
1722208Sdavidn#include <net/if.h>
1822208Sdavidn#if __FreeBSD_version >= 300000
1922208Sdavidn# include <net/if_var.h>
2022208Sdavidn#endif
2122208Sdavidn#include <netinet/in.h>
2222208Sdavidn
2322208Sdavidn#include <arpa/inet.h>
2422208Sdavidn
2522208Sdavidn#include <stdio.h>
26216582Scharnier#include <fcntl.h>
27216582Scharnier#include <stdlib.h>
2831331Scharnier#include <string.h>
2991214Sbde#include <netdb.h>
3022208Sdavidn#include <ctype.h>
3122208Sdavidn#include <unistd.h>
3291214Sbde
3331331Scharnier#include "ipf.h"
3422208Sdavidn#include "netinet/ip_lookup.h"
3522208Sdavidn#include "netinet/ip_pool.h"
3622208Sdavidn#include "netinet/ip_htable.h"
3722208Sdavidn#include "kmem.h"
3822208Sdavidn
3922208Sdavidn
40144716Sstefanfextern	int	ippool_yyparse __P((void));
4122208Sdavidnextern	int	ippool_yydebug;
4222208Sdavidnextern	FILE	*ippool_yyin;
4322208Sdavidnextern	char	*optarg;
4422208Sdavidnextern	int	lineNum;
4522208Sdavidn
4622208Sdavidnvoid	showpools __P((ip_pool_stat_t *));
4722208Sdavidnvoid	usage __P((char *));
4822208Sdavidnint	main __P((int, char **));
4922208Sdavidnint	poolcommand __P((int, int, char *[]));
5022208Sdavidnint	poolnodecommand __P((int, int, char *[]));
5122208Sdavidnint	loadpoolfile __P((int, char *[], char *));
5222208Sdavidnint	poollist __P((int, char *[]));
5322208Sdavidnint	poolflush __P((int, char *[]));
5422208Sdavidnint	poolstats __P((int, char *[]));
5522208Sdavidnint	gettype __P((char *, u_int *));
5622208Sdavidnint	getrole __P((char *));
5722208Sdavidn
5822208Sdavidnint	opts = 0;
5922208Sdavidnint	fd = -1;
6090301Simpint	use_inet6 = 0;
6190301Simp
6290301Simp
6390301Simpvoid usage(prog)
6490301Simpchar *prog;
6590301Simp{
6690301Simp	fprintf(stderr, "Usage:\t%s\n", prog);
6790301Simp	fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
6890301Simp	fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
6922208Sdavidn	fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n");
7022208Sdavidn	fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
7122208Sdavidn	fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
7222208Sdavidn	fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
7322208Sdavidn	fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
7422208Sdavidn	fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
7522208Sdavidn	exit(1);
7622208Sdavidn}
7722208Sdavidn
7822208Sdavidn
79216582Scharnierint main(argc, argv)
8022208Sdavidnint argc;
8122208Sdavidnchar *argv[];
8222208Sdavidn{
8322208Sdavidn	int err;
8422208Sdavidn
8522208Sdavidn	if (argc < 2)
8622208Sdavidn		usage(argv[0]);
8722208Sdavidn
8822208Sdavidn	switch (getopt(argc, argv, "aAf:FlrRs"))
8922208Sdavidn	{
9022208Sdavidn	case 'a' :
9122208Sdavidn		err = poolnodecommand(0, argc, argv);
9222208Sdavidn		break;
9322208Sdavidn	case 'A' :
9422208Sdavidn		err = poolcommand(0, argc, argv);
9590301Simp		break;
9622208Sdavidn	case 'f' :
9722208Sdavidn		err = loadpoolfile(argc, argv, optarg);
9822208Sdavidn		break;
9922208Sdavidn	case 'F' :
10022208Sdavidn		err = poolflush(argc, argv);
10122208Sdavidn		break;
10222208Sdavidn	case 'l' :
10322208Sdavidn		err = poollist(argc, argv);
10422208Sdavidn		break;
10522208Sdavidn	case 'r' :
10622208Sdavidn		err = poolnodecommand(1, argc, argv);
10790301Simp		break;
10822208Sdavidn	case 'R' :
10922208Sdavidn		err = poolcommand(1, argc, argv);
11022208Sdavidn		break;
11122208Sdavidn	case 's' :
11222208Sdavidn		err = poolstats(argc, argv);
11322208Sdavidn		break;
11422208Sdavidn	default :
11522208Sdavidn		exit(1);
11622208Sdavidn	}
11722208Sdavidn
11822208Sdavidn	return err;
11922208Sdavidn}
12022208Sdavidn
12122208Sdavidn
12222208Sdavidnint poolnodecommand(remove, argc, argv)
12322208Sdavidnint remove, argc;
12422208Sdavidnchar *argv[];
12522208Sdavidn{
12622208Sdavidn	char *poolname = NULL, *s;
12722208Sdavidn	int err, c, ipset, role;
12822208Sdavidn	ip_pool_node_t node;
12922208Sdavidn	struct in_addr mask;
13022208Sdavidn
13122208Sdavidn	ipset = 0;
13222208Sdavidn	role = IPL_LOGIPF;
13322208Sdavidn	bzero((char *)&node, sizeof(node));
13490301Simp
13522208Sdavidn	while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
13622208Sdavidn		switch (c)
13722208Sdavidn		{
13822208Sdavidn		case 'd' :
13922208Sdavidn			opts |= OPT_DEBUG;
14022208Sdavidn			ippool_yydebug++;
14122208Sdavidn			break;
14222208Sdavidn		case 'i' :
14322208Sdavidn			s = strchr(optarg, '/');
14422208Sdavidn			if (s == NULL)
14522208Sdavidn				mask.s_addr = 0xffffffff;
14622208Sdavidn			else if (strchr(s, '.') == NULL) {
14722208Sdavidn				if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
14822208Sdavidn					return -1;
14922208Sdavidn			} else {
15022208Sdavidn				mask.s_addr = inet_addr(s + 1);
15122208Sdavidn			}
15222208Sdavidn			if (s != NULL)
15322208Sdavidn				*s = '\0';
15422208Sdavidn			ipset = 1;
15522208Sdavidn			node.ipn_addr.adf_len = sizeof(node.ipn_addr);
15622208Sdavidn			node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg);
15722208Sdavidn			node.ipn_mask.adf_len = sizeof(node.ipn_mask);
15822208Sdavidn			node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
15922208Sdavidn			break;
16022208Sdavidn		case 'm' :
16122208Sdavidn			poolname = optarg;
16222208Sdavidn			break;
16322208Sdavidn		case 'n' :
16422208Sdavidn			opts |= OPT_DONOTHING;
16522208Sdavidn			break;
16622208Sdavidn		case 'o' :
16722208Sdavidn			role = getrole(optarg);
16822208Sdavidn			if (role == IPL_LOGNONE)
16922208Sdavidn				return -1;
17022208Sdavidn			break;
17122208Sdavidn		case 'R' :
17222208Sdavidn			opts |= OPT_NORESOLVE;
17322208Sdavidn			break;
17422208Sdavidn		case 'v' :
17522208Sdavidn			opts |= OPT_VERBOSE;
17622208Sdavidn			break;
17722208Sdavidn		}
17822208Sdavidn
17922208Sdavidn	if (opts & OPT_DEBUG)
18022208Sdavidn		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
18122208Sdavidn
18222208Sdavidn	if (ipset == 0)
18322208Sdavidn		return -1;
18422208Sdavidn	if (poolname == NULL) {
18522208Sdavidn		fprintf(stderr, "poolname not given with add/remove node\n");
18622208Sdavidn		return -1;
18722208Sdavidn	}
18822208Sdavidn
18922208Sdavidn	if (remove == 0)
19022208Sdavidn		err = load_poolnode(0, poolname, &node, ioctl);
19122208Sdavidn	else
19222208Sdavidn		err = remove_poolnode(0, poolname, &node, ioctl);
19322208Sdavidn	return err;
19422208Sdavidn}
19522208Sdavidn
19622208Sdavidn
19722208Sdavidnint poolcommand(remove, argc, argv)
19822208Sdavidnint remove, argc;
19922208Sdavidnchar *argv[];
20022208Sdavidn{
20122208Sdavidn	int type, role, c, err;
20222208Sdavidn	char *poolname;
20322208Sdavidn	iphtable_t iph;
20422208Sdavidn	ip_pool_t pool;
20522208Sdavidn
20622208Sdavidn	err = 1;
20722208Sdavidn	role = 0;
20822208Sdavidn	type = 0;
20929003Sdavidn	poolname = NULL;
21022208Sdavidn	role = IPL_LOGIPF;
21122208Sdavidn	bzero((char *)&iph, sizeof(iph));
21222208Sdavidn	bzero((char *)&pool, sizeof(pool));
21322208Sdavidn
21422208Sdavidn	while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1)
21522208Sdavidn		switch (c)
21622208Sdavidn		{
21722208Sdavidn		case 'd' :
21822208Sdavidn			opts |= OPT_DEBUG;
21922208Sdavidn			ippool_yydebug++;
22022208Sdavidn			break;
22122208Sdavidn		case 'm' :
22222208Sdavidn			poolname = optarg;
22322208Sdavidn			break;
22422208Sdavidn		case 'n' :
22522208Sdavidn			opts |= OPT_DONOTHING;
22622208Sdavidn			break;
22722208Sdavidn		case 'o' :
22822208Sdavidn			role = getrole(optarg);
22922208Sdavidn			if (role == IPL_LOGNONE) {
23022208Sdavidn				fprintf(stderr, "unknown role '%s'\n", optarg);
23122208Sdavidn				return -1;
23222208Sdavidn			}
23322208Sdavidn			break;
23422208Sdavidn		case 'R' :
23522208Sdavidn			opts |= OPT_NORESOLVE;
23622208Sdavidn			break;
23722208Sdavidn		case 'S' :
23822208Sdavidn			iph.iph_seed = atoi(optarg);
23922208Sdavidn			break;
24090301Simp		case 't' :
24122208Sdavidn			type = gettype(optarg, &iph.iph_type);
24222208Sdavidn			if (type == IPLT_NONE) {
24322208Sdavidn				fprintf(stderr, "unknown type '%s'\n", optarg);
24422208Sdavidn				return -1;
24522208Sdavidn			}
24622208Sdavidn			break;
24722208Sdavidn		case 'v' :
24822208Sdavidn			opts |= OPT_VERBOSE;
24922208Sdavidn			break;
25022208Sdavidn		}
25122208Sdavidn
25222208Sdavidn	if (opts & OPT_DEBUG)
25322208Sdavidn		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
25422208Sdavidn
25522208Sdavidn	if (poolname == NULL) {
25622208Sdavidn		fprintf(stderr, "poolname not given with add/remove pool\n");
25722208Sdavidn		return -1;
25822208Sdavidn	}
25922208Sdavidn
26022208Sdavidn	if (type == IPLT_HASH) {
26122208Sdavidn		strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
26222208Sdavidn		iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
26322208Sdavidn		iph.iph_unit = role;
26422208Sdavidn	} else if (type == IPLT_POOL) {
26522208Sdavidn		strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
26622208Sdavidn		pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
26722208Sdavidn		pool.ipo_unit = role;
26822208Sdavidn	}
26922208Sdavidn
27022208Sdavidn	if (remove == 0) {
27122208Sdavidn		switch (type)
27222208Sdavidn		{
27322208Sdavidn		case IPLT_HASH :
27490301Simp			err = load_hash(&iph, NULL, ioctl);
27522208Sdavidn			break;
27622208Sdavidn		case IPLT_POOL :
27722208Sdavidn			err = load_pool(&pool, ioctl);
27822208Sdavidn			break;
27922208Sdavidn		}
28022208Sdavidn	} else {
28122208Sdavidn		switch (type)
28222208Sdavidn		{
28322208Sdavidn		case IPLT_HASH :
28422208Sdavidn			err = remove_hash(&iph, ioctl);
28522208Sdavidn			break;
28622208Sdavidn		case IPLT_POOL :
28722208Sdavidn			err = remove_pool(&pool, ioctl);
28822208Sdavidn			break;
28922208Sdavidn		}
29022208Sdavidn	}
29122208Sdavidn	return err;
29222208Sdavidn}
29322208Sdavidn
29422208Sdavidn
29522208Sdavidnint loadpoolfile(argc, argv, infile)
29622208Sdavidnint argc;
29722208Sdavidnchar *argv[], *infile;
29822208Sdavidn{
299108470Sschweikh	int c;
30022208Sdavidn
30122208Sdavidn	infile = optarg;
30222208Sdavidn
30390301Simp	while ((c = getopt(argc, argv, "dnRuv")) != -1)
30422208Sdavidn		switch (c)
30522208Sdavidn		{
30622208Sdavidn		case 'd' :
30722208Sdavidn			opts |= OPT_DEBUG;
30822208Sdavidn			ippool_yydebug++;
30922208Sdavidn			break;
31022208Sdavidn		case 'n' :
31122208Sdavidn			opts |= OPT_DONOTHING;
31222208Sdavidn			break;
31322208Sdavidn		case 'R' :
31422208Sdavidn			opts |= OPT_NORESOLVE;
31522208Sdavidn			break;
31622208Sdavidn		case 'u' :
31722208Sdavidn			opts |= OPT_REMOVE;
31890301Simp			break;
31922208Sdavidn		case 'v' :
32022208Sdavidn			opts |= OPT_VERBOSE;
32122208Sdavidn			break;
32222208Sdavidn		}
32322208Sdavidn
32422208Sdavidn	if (opts & OPT_DEBUG)
32522208Sdavidn		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
32622208Sdavidn
32722208Sdavidn	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
32822208Sdavidn		fd = open(IPLOOKUP_NAME, O_RDWR);
32922208Sdavidn		if (fd == -1) {
33022208Sdavidn			perror("open(IPLOOKUP_NAME)");
33122208Sdavidn			exit(1);
33222208Sdavidn		}
33322208Sdavidn	}
33422208Sdavidn
33522208Sdavidn	if (ippool_parsefile(fd, infile, ioctl) != 0)
33622208Sdavidn		return -1;
33722208Sdavidn	return 0;
33822208Sdavidn}
33922208Sdavidn
34022208Sdavidn
34122208Sdavidnint poollist(argc, argv)
34222208Sdavidnint argc;
34322208Sdavidnchar *argv[];
34422208Sdavidn{
34522208Sdavidn	char *kernel, *core, *poolname;
34622208Sdavidn	int c, role, type, live_kernel;
34722208Sdavidn	ip_pool_stat_t *plstp, plstat;
34822208Sdavidn	iphtstat_t *htstp, htstat;
34922208Sdavidn	iphtable_t *hptr;
35022208Sdavidn	iplookupop_t op;
35122208Sdavidn	ip_pool_t *ptr;
35222208Sdavidn
35322208Sdavidn	core = NULL;
35422208Sdavidn	kernel = NULL;
35522208Sdavidn	live_kernel = 1;
35622208Sdavidn	type = IPLT_ALL;
357126952Sbde	poolname = NULL;
35822208Sdavidn	role = IPL_LOGALL;
35922208Sdavidn
36022208Sdavidn	while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
36122208Sdavidn		switch (c)
36222208Sdavidn		{
36322208Sdavidn		case 'd' :
36422208Sdavidn			opts |= OPT_DEBUG;
36522208Sdavidn			break;
36622208Sdavidn		case 'm' :
36722208Sdavidn			poolname = optarg;
36822208Sdavidn			break;
36922208Sdavidn		case 'M' :
37022208Sdavidn			live_kernel = 0;
37122208Sdavidn			core = optarg;
37222208Sdavidn			break;
37322208Sdavidn		case 'N' :
37422208Sdavidn			live_kernel = 0;
37522208Sdavidn			kernel = optarg;
37622208Sdavidn			break;
37722208Sdavidn		case 'o' :
37822208Sdavidn			role = getrole(optarg);
37922208Sdavidn			if (role == IPL_LOGNONE) {
38022208Sdavidn				fprintf(stderr, "unknown role '%s'\n", optarg);
38122208Sdavidn				return -1;
38222208Sdavidn			}
38322208Sdavidn			break;
38422208Sdavidn		case 'R' :
38522208Sdavidn			opts |= OPT_NORESOLVE;
38622208Sdavidn			break;
38790301Simp		case 't' :
38822208Sdavidn			type = gettype(optarg, NULL);
38922208Sdavidn			if (type == IPLT_NONE) {
39022208Sdavidn				fprintf(stderr, "unknown type '%s'\n", optarg);
391228582Sdim				return -1;
39222208Sdavidn			}
39322208Sdavidn			break;
39422208Sdavidn		case 'v' :
39522208Sdavidn			opts |= OPT_VERBOSE;
39622208Sdavidn			break;
39722208Sdavidn		}
39822208Sdavidn
39922208Sdavidn	if (opts & OPT_DEBUG)
40022208Sdavidn		fprintf(stderr, "poollist: opts = %#x\n", opts);
40122208Sdavidn
40222208Sdavidn	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
40322208Sdavidn		fd = open(IPLOOKUP_NAME, O_RDWR);
40422208Sdavidn		if (fd == -1) {
40522208Sdavidn			perror("open(IPLOOKUP_NAME)");
40622208Sdavidn			exit(1);
40722208Sdavidn		}
40822208Sdavidn	}
40922208Sdavidn
41022208Sdavidn	bzero((char *)&op, sizeof(op));
41122208Sdavidn	if (poolname != NULL) {
41222208Sdavidn		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
41322208Sdavidn		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
41422208Sdavidn	}
41522208Sdavidn	op.iplo_unit = role;
41622208Sdavidn
41722208Sdavidn	if (openkmem(kernel, core) == -1)
41822208Sdavidn		exit(-1);
41922208Sdavidn
42022208Sdavidn	if (type == IPLT_ALL || type == IPLT_POOL) {
42122208Sdavidn		plstp = &plstat;
42222208Sdavidn		op.iplo_type = IPLT_POOL;
42322208Sdavidn		op.iplo_size = sizeof(plstat);
42422208Sdavidn		op.iplo_struct = &plstat;
42522208Sdavidn		c = ioctl(fd, SIOCLOOKUPSTAT, &op);
42622208Sdavidn		if (c == -1) {
42722208Sdavidn			perror("ioctl(SIOCLOOKUPSTAT)");
42822208Sdavidn			return -1;
42922208Sdavidn		}
43022208Sdavidn
43122208Sdavidn		if (role != IPL_LOGALL) {
43222208Sdavidn			ptr = plstp->ipls_list[role];
43322208Sdavidn			while (ptr != NULL) {
43422208Sdavidn				ptr = printpool(ptr, kmemcpywrap, poolname,
43522208Sdavidn						opts);
43622208Sdavidn			}
43722208Sdavidn		} else {
43822208Sdavidn			for (role = 0; role <= IPL_LOGMAX; role++) {
43922208Sdavidn				ptr = plstp->ipls_list[role];
44090301Simp				while (ptr != NULL) {
44122208Sdavidn					ptr = printpool(ptr, kmemcpywrap,
44222208Sdavidn							poolname, opts);
44322208Sdavidn				}
44422208Sdavidn			}
44522208Sdavidn			role = IPL_LOGALL;
44622208Sdavidn		}
44722208Sdavidn	}
44822208Sdavidn	if (type == IPLT_ALL || type == IPLT_HASH) {
44922208Sdavidn		htstp = &htstat;
45022208Sdavidn		op.iplo_type = IPLT_HASH;
45122208Sdavidn		op.iplo_size = sizeof(htstat);
45222208Sdavidn		op.iplo_struct = &htstat;
45322208Sdavidn		c = ioctl(fd, SIOCLOOKUPSTAT, &op);
45422491Sdavidn		if (c == -1) {
45522491Sdavidn			perror("ioctl(SIOCLOOKUPSTAT)");
45622491Sdavidn			return -1;
45722208Sdavidn		}
45822491Sdavidn
45922491Sdavidn		if (role != IPL_LOGALL) {
46022491Sdavidn			hptr = htstp->iphs_tables;
46122491Sdavidn			while (hptr != NULL) {
46222208Sdavidn				hptr = printhash(hptr, kmemcpywrap,
46322491Sdavidn						 poolname, opts);
46422491Sdavidn			}
46522208Sdavidn		} else {
46622491Sdavidn			for (role = 0; role <= IPL_LOGMAX; role++) {
46722491Sdavidn				hptr = htstp->iphs_tables;
46822491Sdavidn				while (hptr != NULL) {
46922491Sdavidn					hptr = printhash(hptr, kmemcpywrap,
47022491Sdavidn							 poolname, opts);
47122491Sdavidn				}
47222208Sdavidn
47322491Sdavidn				op.iplo_unit = role;
47422491Sdavidn				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
47522491Sdavidn				if (c == -1) {
47622208Sdavidn					perror("ioctl(SIOCLOOKUPSTAT)");
47722491Sdavidn					return -1;
47822491Sdavidn				}
47922491Sdavidn			}
48022491Sdavidn		}
48122208Sdavidn	}
48222208Sdavidn	return 0;
48322208Sdavidn}
48422208Sdavidn
48522208Sdavidn
48622208Sdavidnint poolstats(argc, argv)
48722208Sdavidnint argc;
48822208Sdavidnchar *argv[];
489{
490	int c, type, role, live_kernel;
491	ip_pool_stat_t plstat;
492	char *kernel, *core;
493	iphtstat_t htstat;
494	iplookupop_t op;
495
496	core = NULL;
497	kernel = NULL;
498	live_kernel = 1;
499	type = IPLT_ALL;
500	role = IPL_LOGALL;
501
502	bzero((char *)&op, sizeof(op));
503
504	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
505		switch (c)
506		{
507		case 'd' :
508			opts |= OPT_DEBUG;
509			break;
510		case 'M' :
511			live_kernel = 0;
512			core = optarg;
513			break;
514		case 'N' :
515			live_kernel = 0;
516			kernel = optarg;
517			break;
518		case 'o' :
519			role = getrole(optarg);
520			if (role == IPL_LOGNONE) {
521				fprintf(stderr, "unknown role '%s'\n", optarg);
522				return -1;
523			}
524			break;
525		case 't' :
526			type = gettype(optarg, NULL);
527			if (type != IPLT_POOL) {
528				fprintf(stderr,
529					"-s not supported for this type yet\n");
530				return -1;
531			}
532			break;
533		case 'v' :
534			opts |= OPT_VERBOSE;
535			break;
536		}
537
538	if (opts & OPT_DEBUG)
539		fprintf(stderr, "poolstats: opts = %#x\n", opts);
540
541	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
542		fd = open(IPLOOKUP_NAME, O_RDWR);
543		if (fd == -1) {
544			perror("open(IPLOOKUP_NAME)");
545			exit(1);
546		}
547	}
548
549	if (type == IPLT_ALL || type == IPLT_POOL) {
550		op.iplo_type = IPLT_POOL;
551		op.iplo_struct = &plstat;
552		op.iplo_size = sizeof(plstat);
553		if (!(opts & OPT_DONOTHING)) {
554			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
555			if (c == -1) {
556				perror("ioctl(SIOCLOOKUPSTAT)");
557				return -1;
558			}
559			printf("Pools:\t%lu\n", plstat.ipls_pools);
560			printf("Nodes:\t%lu\n", plstat.ipls_nodes);
561		}
562	}
563
564	if (type == IPLT_ALL || type == IPLT_HASH) {
565		op.iplo_type = IPLT_HASH;
566		op.iplo_struct = &htstat;
567		op.iplo_size = sizeof(htstat);
568		if (!(opts & OPT_DONOTHING)) {
569			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
570			if (c == -1) {
571				perror("ioctl(SIOCLOOKUPSTAT)");
572				return -1;
573			}
574			printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
575			printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
576			printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
577		}
578	}
579	return 0;
580}
581
582
583int poolflush(argc, argv)
584int argc;
585char *argv[];
586{
587	int c, role, type, arg;
588	iplookupflush_t flush;
589
590	arg = IPLT_ALL;
591	type = IPLT_ALL;
592	role = IPL_LOGALL;
593
594	while ((c = getopt(argc, argv, "do:t:v")) != -1)
595		switch (c)
596		{
597		case 'd' :
598			opts |= OPT_DEBUG;
599			break;
600		case 'o' :
601			role = getrole(optarg);
602			if (role == IPL_LOGNONE) {
603				fprintf(stderr, "unknown role '%s'\n", optarg);
604				return -1;
605			}
606			break;
607		case 't' :
608			type = gettype(optarg, NULL);
609			if (type == IPLT_NONE) {
610				fprintf(stderr, "unknown type '%s'\n", optarg);
611				return -1;
612			}
613			break;
614		case 'v' :
615			opts |= OPT_VERBOSE;
616			break;
617		}
618
619	if (opts & OPT_DEBUG)
620		fprintf(stderr, "poolflush: opts = %#x\n", opts);
621
622	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
623		fd = open(IPLOOKUP_NAME, O_RDWR);
624		if (fd == -1) {
625			perror("open(IPLOOKUP_NAME)");
626			exit(1);
627		}
628	}
629
630	bzero((char *)&flush, sizeof(flush));
631	flush.iplf_type = type;
632	flush.iplf_unit = role;
633	flush.iplf_arg = arg;
634
635	if (!(opts & OPT_DONOTHING)) {
636		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
637			perror("ioctl(SIOCLOOKUPFLUSH)");
638			exit(1);
639		}
640
641	}
642	printf("%u object%s flushed\n", flush.iplf_count,
643	       (flush.iplf_count == 1) ? "" : "s");
644
645	return 0;
646}
647
648
649int getrole(rolename)
650char *rolename;
651{
652	int role;
653
654	if (!strcasecmp(rolename, "ipf")) {
655		role = IPL_LOGIPF;
656#if 0
657	} else if (!strcasecmp(rolename, "nat")) {
658		role = IPL_LOGNAT;
659	} else if (!strcasecmp(rolename, "state")) {
660		role = IPL_LOGSTATE;
661	} else if (!strcasecmp(rolename, "auth")) {
662		role = IPL_LOGAUTH;
663	} else if (!strcasecmp(rolename, "sync")) {
664		role = IPL_LOGSYNC;
665	} else if (!strcasecmp(rolename, "scan")) {
666		role = IPL_LOGSCAN;
667	} else if (!strcasecmp(rolename, "pool")) {
668		role = IPL_LOGLOOKUP;
669	} else if (!strcasecmp(rolename, "count")) {
670		role = IPL_LOGCOUNT;
671#endif
672	} else {
673		role = IPL_LOGNONE;
674	}
675
676	return role;
677}
678
679
680int gettype(typename, minor)
681char *typename;
682u_int *minor;
683{
684	int type;
685
686	if (!strcasecmp(optarg, "tree")) {
687		type = IPLT_POOL;
688	} else if (!strcasecmp(optarg, "hash")) {
689		type = IPLT_HASH;
690		if (minor != NULL)
691			*minor = IPHASH_LOOKUP;
692	} else if (!strcasecmp(optarg, "group-map")) {
693		type = IPLT_HASH;
694		if (minor != NULL)
695			*minor = IPHASH_GROUPMAP;
696	} else {
697		type = IPLT_NONE;
698	}
699	return type;
700}
701