Home | History | Annotate | Line # | Download | only in tools
      1 /*	$NetBSD: ippool.c,v 1.4 2013/10/20 03:09:11 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2012 by Darren Reed.
      5  *
      6  * See the IPFILTER.LICENCE file for details on licencing.
      7  */
      8 #include <sys/types.h>
      9 #include <sys/time.h>
     10 #include <sys/param.h>
     11 #include <sys/socket.h>
     12 #if defined(BSD) && (BSD >= 199306)
     13 # include <sys/cdefs.h>
     14 #endif
     15 #include <sys/ioctl.h>
     16 
     17 #include <net/if.h>
     18 #if __FreeBSD_version >= 300000
     19 # include <net/if_var.h>
     20 #endif
     21 #include <netinet/in.h>
     22 
     23 #include <arpa/inet.h>
     24 
     25 #include <stdio.h>
     26 #include <fcntl.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <netdb.h>
     30 #include <ctype.h>
     31 #include <unistd.h>
     32 #ifdef linux
     33 # include <linux/a.out.h>
     34 #else
     35 # include <nlist.h>
     36 #endif
     37 
     38 #include "ipf.h"
     39 #include "netinet/ipl.h"
     40 #include "netinet/ip_lookup.h"
     41 #include "netinet/ip_pool.h"
     42 #include "netinet/ip_htable.h"
     43 #include "kmem.h"
     44 
     45 
     46 extern	int	ippool_yyparse __P((void));
     47 extern	int	ippool_yydebug;
     48 extern	FILE	*ippool_yyin;
     49 extern	char	*optarg;
     50 extern	int	lineNum;
     51 
     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((int, int, void *ptr, char *arg));
     65 void	showpools_live __P((int, int, ipf_pool_stat_t *, char *));
     66 void	showhashs_live __P((int, int, iphtstat_t *, char *));
     67 void	showdstls_live __P((int, int, ipf_dstl_stat_t *, char *));
     68 
     69 int	opts = 0;
     70 int	fd = -1;
     71 int	use_inet6 = 0;
     72 wordtab_t *pool_fields = NULL;
     73 int	nohdrfields = 0;
     74 
     75 
     76 void
     77 usage(prog)
     78 	char *prog;
     79 {
     80 	fprintf(stderr, "Usage:\t%s\n", prog);
     81 	fprintf(stderr, "\t-a [-dnv] [-m <name>] [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n");
     82 	fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
     83 	fprintf(stderr, "\t-f <file> [-dnuv]\n");
     84 	fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n");
     85 	fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-O <fields>]\n");
     86 	fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n");
     87 	fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
     88 	fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
     89 	exit(1);
     90 }
     91 
     92 
     93 int
     94 main(argc, argv)
     95 	int argc;
     96 	char *argv[];
     97 {
     98 	int err = 1;
     99 
    100 	if (argc < 2)
    101 		usage(argv[0]);
    102 
    103 	assigndefined(getenv("IPPOOL_PREDEFINED"));
    104 
    105 	switch (getopt(argc, argv, "aAf:FlnrRsv"))
    106 	{
    107 	case 'a' :
    108 		err = poolnodecommand(0, argc, argv);
    109 		break;
    110 	case 'A' :
    111 		err = poolcommand(0, argc, argv);
    112 		break;
    113 	case 'f' :
    114 		err = loadpoolfile(argc, argv, optarg);
    115 		break;
    116 	case 'F' :
    117 		err = poolflush(argc, argv);
    118 		break;
    119 	case 'l' :
    120 		err = poollist(argc, argv);
    121 		break;
    122 	case 'n' :
    123 		opts |= OPT_DONOTHING|OPT_DONTOPEN;
    124 		break;
    125 	case 'r' :
    126 		err = poolnodecommand(1, argc, argv);
    127 		break;
    128 	case 'R' :
    129 		err = poolcommand(1, argc, argv);
    130 		break;
    131 	case 's' :
    132 		err = poolstats(argc, argv);
    133 		break;
    134 	case 'v' :
    135 		opts |= OPT_VERBOSE;
    136 		break;
    137 	default :
    138 		exit(1);
    139 	}
    140 
    141 	if (err != 0)
    142 		exit(1);
    143 	return 0;
    144 }
    145 
    146 
    147 int
    148 poolnodecommand(remove, argc, argv)
    149 	int remove, argc;
    150 	char *argv[];
    151 {
    152 	int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
    153 	char *poolname = NULL;
    154 	ip_pool_node_t pnode;
    155 	iphtent_t hnode;
    156 	void *ptr = &pnode;
    157 
    158 	ipset = 0;
    159 	role = IPL_LOGIPF;
    160 	bzero((char *)&pnode, sizeof(pnode));
    161 	bzero((char *)&hnode, sizeof(hnode));
    162 
    163 	while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1)
    164 		switch (c)
    165 		{
    166 		case 'd' :
    167 			opts |= OPT_DEBUG;
    168 			ippool_yydebug++;
    169 			break;
    170 		case 'i' :
    171 			if (setnodeaddr(type, role, ptr, optarg) == 0)
    172 				ipset = 1;
    173 			break;
    174 		case 'm' :
    175 			poolname = optarg;
    176 			break;
    177 		case 'n' :
    178 			opts |= OPT_DONOTHING|OPT_DONTOPEN;
    179 			break;
    180 		case 'o' :
    181 			if (ipset == 1) {
    182 				fprintf(stderr,
    183 					"cannot set role after ip address\n");
    184 				return -1;
    185 			}
    186 			role = getrole(optarg);
    187 			if (role == IPL_LOGNONE)
    188 				return -1;
    189 			break;
    190 		case 'R' :
    191 			opts |= OPT_NORESOLVE;
    192 			break;
    193 		case 't' :
    194 			if (ipset == 1) {
    195 				fprintf(stderr,
    196 					"cannot set type after ip address\n");
    197 				return -1;
    198 			}
    199 			type = gettype(optarg, NULL);
    200 			switch (type) {
    201 			case IPLT_NONE :
    202 				fprintf(stderr, "unknown type '%s'\n", optarg);
    203 				return -1;
    204 			case IPLT_HASH :
    205 				ptr = &hnode;
    206 				break;
    207 			case IPLT_POOL :
    208 			default :
    209 				break;
    210 			}
    211 			break;
    212 		case 'T' :
    213 			ttl = atoi(optarg);
    214 			if (ttl < 0) {
    215 				fprintf(stderr, "cannot set negative ttl\n");
    216 				return -1;
    217 			}
    218 			break;
    219 		case 'v' :
    220 			opts |= OPT_VERBOSE;
    221 			break;
    222 		}
    223 
    224 	if (argv[optind] != NULL && ipset == 0) {
    225 		if (setnodeaddr(type, role, ptr, argv[optind]) == 0)
    226 			ipset = 1;
    227 	}
    228 
    229 	if (opts & OPT_DEBUG)
    230 		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
    231 
    232 	if (ipset == 0) {
    233 		fprintf(stderr, "no IP address given with -i\n");
    234 		return -1;
    235 	}
    236 
    237 	if (poolname == NULL) {
    238 		fprintf(stderr, "poolname not given with add/remove node\n");
    239 		return -1;
    240 	}
    241 
    242 	switch (type) {
    243 	case IPLT_POOL :
    244 		if (remove == 0)
    245 			err = load_poolnode(role, poolname, &pnode, ttl, ioctl);
    246 		else
    247 			err = remove_poolnode(role, poolname, &pnode, ioctl);
    248 		break;
    249 	case IPLT_HASH :
    250 		if (remove == 0)
    251 			err = load_hashnode(role, poolname, &hnode, ttl, ioctl);
    252 		else
    253 			err = remove_hashnode(role, poolname, &hnode, ioctl);
    254 		break;
    255 	default :
    256 		break;
    257 	}
    258 	return err;
    259 }
    260 
    261 
    262 int
    263 poolcommand(remove, argc, argv)
    264 	int remove, argc;
    265 	char *argv[];
    266 {
    267 	int type, role, c, err;
    268 	char *poolname;
    269 	iphtable_t iph;
    270 	ip_pool_t pool;
    271 
    272 	err = 1;
    273 	role = 0;
    274 	type = 0;
    275 	poolname = NULL;
    276 	role = IPL_LOGIPF;
    277 	bzero((char *)&iph, sizeof(iph));
    278 	bzero((char *)&pool, sizeof(pool));
    279 
    280 	while ((c = getopt(argc, argv, "dm:no:RSv")) != -1)
    281 		switch (c)
    282 		{
    283 		case 'd' :
    284 			opts |= OPT_DEBUG;
    285 			ippool_yydebug++;
    286 			break;
    287 		case 'm' :
    288 			poolname = optarg;
    289 			break;
    290 		case 'n' :
    291 			opts |= OPT_DONOTHING|OPT_DONTOPEN;
    292 			break;
    293 		case 'o' :
    294 			role = getrole(optarg);
    295 			if (role == IPL_LOGNONE) {
    296 				fprintf(stderr, "unknown role '%s'\n", optarg);
    297 				return -1;
    298 			}
    299 			break;
    300 		case 'R' :
    301 			opts |= OPT_NORESOLVE;
    302 			break;
    303 		case 'S' :
    304 			iph.iph_seed = atoi(optarg);
    305 			break;
    306 		case 'v' :
    307 			opts |= OPT_VERBOSE;
    308 			break;
    309 		}
    310 
    311 	if (opts & OPT_DEBUG)
    312 		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
    313 
    314 	if (poolname == NULL) {
    315 		fprintf(stderr, "poolname not given with add/remove pool\n");
    316 		return -1;
    317 	}
    318 
    319 	type = gettype(argv[optind], &iph.iph_type);
    320 	if (type == IPLT_NONE) {
    321 		fprintf(stderr, "unknown type '%s'\n", argv[optind]);
    322 		return -1;
    323 	}
    324 
    325 	if (type == IPLT_HASH) {
    326 		strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
    327 		iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
    328 		iph.iph_unit = role;
    329 	} else if (type == IPLT_POOL) {
    330 		strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
    331 		pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
    332 		pool.ipo_unit = role;
    333 	}
    334 
    335 	if (remove == 0) {
    336 		switch (type)
    337 		{
    338 		case IPLT_HASH :
    339 			err = load_hash(&iph, NULL, ioctl);
    340 			break;
    341 		case IPLT_POOL :
    342 			err = load_pool(&pool, ioctl);
    343 			break;
    344 		}
    345 	} else {
    346 		switch (type)
    347 		{
    348 		case IPLT_HASH :
    349 			err = remove_hash(&iph, ioctl);
    350 			break;
    351 		case IPLT_POOL :
    352 			err = remove_pool(&pool, ioctl);
    353 			break;
    354 		}
    355 	}
    356 	return err;
    357 }
    358 
    359 
    360 int
    361 loadpoolfile(argc, argv, infile)
    362 	int argc;
    363 	char *argv[], *infile;
    364 {
    365 	int c;
    366 
    367 	infile = optarg;
    368 
    369 	while ((c = getopt(argc, argv, "dnRuv")) != -1)
    370 		switch (c)
    371 		{
    372 		case 'd' :
    373 			opts |= OPT_DEBUG;
    374 			ippool_yydebug++;
    375 			break;
    376 		case 'n' :
    377 			opts |= OPT_DONOTHING|OPT_DONTOPEN;
    378 			break;
    379 		case 'R' :
    380 			opts |= OPT_NORESOLVE;
    381 			break;
    382 		case 'u' :
    383 			opts |= OPT_REMOVE;
    384 			break;
    385 		case 'v' :
    386 			opts |= OPT_VERBOSE;
    387 			break;
    388 		}
    389 
    390 	if (opts & OPT_DEBUG)
    391 		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
    392 
    393 	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
    394 		fd = open(IPLOOKUP_NAME, O_RDWR);
    395 		if (fd == -1) {
    396 			perror("open(IPLOOKUP_NAME)");
    397 			exit(1);
    398 		}
    399 	}
    400 
    401 	if (ippool_parsefile(fd, infile, ioctl) != 0)
    402 		return -1;
    403 	return 0;
    404 }
    405 
    406 
    407 int
    408 poolstats(argc, argv)
    409 	int argc;
    410 	char *argv[];
    411 {
    412 	int c, type, role;
    413 	ipf_pool_stat_t plstat;
    414 	ipf_dstl_stat_t dlstat;
    415 	iphtstat_t htstat;
    416 	iplookupop_t op;
    417 
    418 	type = IPLT_ALL;
    419 	role = IPL_LOGALL;
    420 
    421 	bzero((char *)&op, sizeof(op));
    422 
    423 	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
    424 		switch (c)
    425 		{
    426 		case 'd' :
    427 			opts |= OPT_DEBUG;
    428 			break;
    429 		case 'M' :
    430 			break;
    431 		case 'N' :
    432 			break;
    433 		case 'o' :
    434 			role = getrole(optarg);
    435 			if (role == IPL_LOGNONE) {
    436 				fprintf(stderr, "unknown role '%s'\n", optarg);
    437 				return -1;
    438 			}
    439 			break;
    440 		case 't' :
    441 			type = gettype(optarg, NULL);
    442 			if (type != IPLT_POOL) {
    443 				fprintf(stderr,
    444 					"-s not supported for this type yet\n");
    445 				return -1;
    446 			}
    447 			break;
    448 		case 'v' :
    449 			opts |= OPT_VERBOSE;
    450 			break;
    451 		}
    452 
    453 	if (opts & OPT_DEBUG)
    454 		fprintf(stderr, "poolstats: opts = %#x\n", opts);
    455 
    456 	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
    457 		fd = open(IPLOOKUP_NAME, O_RDWR);
    458 		if (fd == -1) {
    459 			perror("open(IPLOOKUP_NAME)");
    460 			exit(1);
    461 		}
    462 	}
    463 
    464 	if (type == IPLT_ALL || type == IPLT_POOL) {
    465 		op.iplo_type = IPLT_POOL;
    466 		op.iplo_struct = &plstat;
    467 		op.iplo_size = sizeof(plstat);
    468 		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
    469 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    470 			if (c == -1) {
    471 				ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)");
    472 				return -1;
    473 			}
    474 			printf("%lu\taddress pools\n", plstat.ipls_pools);
    475 			printf("%lu\taddress pool nodes\n", plstat.ipls_nodes);
    476 		}
    477 	}
    478 
    479 	if (type == IPLT_ALL || type == IPLT_HASH) {
    480 		op.iplo_type = IPLT_HASH;
    481 		op.iplo_struct = &htstat;
    482 		op.iplo_size = sizeof(htstat);
    483 		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
    484 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    485 			if (c == -1) {
    486 				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    487 				return -1;
    488 			}
    489 			printf("%lu\thash tables\n", htstat.iphs_numtables);
    490 			printf("%lu\thash table nodes\n", htstat.iphs_numnodes);
    491 			printf("%lu\thash table no memory \n",
    492 				htstat.iphs_nomem);
    493 		}
    494 	}
    495 
    496 	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
    497 		op.iplo_type = IPLT_DSTLIST;
    498 		op.iplo_struct = &dlstat;
    499 		op.iplo_size = sizeof(dlstat);
    500 		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
    501 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    502 			if (c == -1) {
    503 				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    504 				return -1;
    505 			}
    506 			printf("%u\tdestination lists\n",
    507 			       dlstat.ipls_numlists);
    508 			printf("%u\tdestination list nodes\n",
    509 			       dlstat.ipls_numnodes);
    510 			printf("%lu\tdestination list no memory\n",
    511 			       dlstat.ipls_nomem);
    512 			printf("%u\tdestination list zombies\n",
    513 			       dlstat.ipls_numdereflists);
    514 			printf("%u\tdesetination list node zombies\n",
    515 			       dlstat.ipls_numderefnodes);
    516 		}
    517 	}
    518 	return 0;
    519 }
    520 
    521 
    522 int
    523 poolflush(argc, argv)
    524 	int argc;
    525 	char *argv[];
    526 {
    527 	int c, role, type, arg;
    528 	iplookupflush_t flush;
    529 
    530 	arg = IPLT_ALL;
    531 	type = IPLT_ALL;
    532 	role = IPL_LOGALL;
    533 
    534 	while ((c = getopt(argc, argv, "do:t:v")) != -1)
    535 		switch (c)
    536 		{
    537 		case 'd' :
    538 			opts |= OPT_DEBUG;
    539 			break;
    540 		case 'o' :
    541 			role = getrole(optarg);
    542 			if (role == IPL_LOGNONE) {
    543 				fprintf(stderr, "unknown role '%s'\n", optarg);
    544 				return -1;
    545 			}
    546 			break;
    547 		case 't' :
    548 			type = gettype(optarg, NULL);
    549 			if (type == IPLT_NONE) {
    550 				fprintf(stderr, "unknown type '%s'\n", optarg);
    551 				return -1;
    552 			}
    553 			break;
    554 		case 'v' :
    555 			opts |= OPT_VERBOSE;
    556 			break;
    557 		}
    558 
    559 	if (opts & OPT_DEBUG)
    560 		fprintf(stderr, "poolflush: opts = %#x\n", opts);
    561 
    562 	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
    563 		fd = open(IPLOOKUP_NAME, O_RDWR);
    564 		if (fd == -1) {
    565 			perror("open(IPLOOKUP_NAME)");
    566 			exit(1);
    567 		}
    568 	}
    569 
    570 	bzero((char *)&flush, sizeof(flush));
    571 	flush.iplf_type = type;
    572 	flush.iplf_unit = role;
    573 	flush.iplf_arg = arg;
    574 
    575 	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
    576 		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
    577 			ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)");
    578 			exit(1);
    579 		}
    580 
    581 	}
    582 	printf("%u object%s flushed\n", flush.iplf_count,
    583 	       (flush.iplf_count == 1) ? "" : "s");
    584 
    585 	return 0;
    586 }
    587 
    588 
    589 int
    590 getrole(rolename)
    591 	char *rolename;
    592 {
    593 	int role;
    594 
    595 	if (!strcasecmp(rolename, "ipf")) {
    596 		role = IPL_LOGIPF;
    597 #if 0
    598 	} else if (!strcasecmp(rolename, "nat")) {
    599 		role = IPL_LOGNAT;
    600 	} else if (!strcasecmp(rolename, "state")) {
    601 		role = IPL_LOGSTATE;
    602 	} else if (!strcasecmp(rolename, "auth")) {
    603 		role = IPL_LOGAUTH;
    604 	} else if (!strcasecmp(rolename, "sync")) {
    605 		role = IPL_LOGSYNC;
    606 	} else if (!strcasecmp(rolename, "scan")) {
    607 		role = IPL_LOGSCAN;
    608 	} else if (!strcasecmp(rolename, "pool")) {
    609 		role = IPL_LOGLOOKUP;
    610 	} else if (!strcasecmp(rolename, "count")) {
    611 		role = IPL_LOGCOUNT;
    612 #endif
    613 	} else {
    614 		role = IPL_LOGNONE;
    615 	}
    616 
    617 	return role;
    618 }
    619 
    620 
    621 int
    622 gettype(typename, minor)
    623 	char *typename;
    624 	u_int *minor;
    625 {
    626 	int type;
    627 
    628 	if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) {
    629 		type = IPLT_POOL;
    630 	} else if (!strcasecmp(typename, "hash")) {
    631 		type = IPLT_HASH;
    632 		if (minor != NULL)
    633 			*minor = IPHASH_LOOKUP;
    634 	} else if (!strcasecmp(typename, "group-map")) {
    635 		type = IPLT_HASH;
    636 		if (minor != NULL)
    637 			*minor = IPHASH_GROUPMAP;
    638 	} else {
    639 		type = IPLT_NONE;
    640 	}
    641 	return type;
    642 }
    643 
    644 
    645 int
    646 poollist(argc, argv)
    647 	int argc;
    648 	char *argv[];
    649 {
    650 	char *kernel, *core, *poolname;
    651 	int c, role, type, live_kernel;
    652 	iplookupop_t op;
    653 
    654 	core = NULL;
    655 	kernel = NULL;
    656 	live_kernel = 1;
    657 	type = IPLT_ALL;
    658 	poolname = NULL;
    659 	role = IPL_LOGALL;
    660 
    661 	while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
    662 		switch (c)
    663 		{
    664 		case 'd' :
    665 			opts |= OPT_DEBUG;
    666 			break;
    667 		case 'm' :
    668 			poolname = optarg;
    669 			break;
    670 		case 'M' :
    671 			live_kernel = 0;
    672 			core = optarg;
    673 			break;
    674 		case 'N' :
    675 			live_kernel = 0;
    676 			kernel = optarg;
    677 			break;
    678 		case 'o' :
    679 			role = getrole(optarg);
    680 			if (role == IPL_LOGNONE) {
    681 				fprintf(stderr, "unknown role '%s'\n", optarg);
    682 				return -1;
    683 			}
    684 			break;
    685 		case 'O' :
    686 			pool_fields = parsefields(poolfields, optarg);
    687 			break;
    688 		case 'R' :
    689 			opts |= OPT_NORESOLVE;
    690 			break;
    691 		case 't' :
    692 			type = gettype(optarg, NULL);
    693 			if (type == IPLT_NONE) {
    694 				fprintf(stderr, "unknown type '%s'\n", optarg);
    695 				return -1;
    696 			}
    697 			break;
    698 		case 'v' :
    699 			opts |= OPT_VERBOSE;
    700 			break;
    701 		}
    702 
    703 	if (opts & OPT_DEBUG)
    704 		fprintf(stderr, "poollist: opts = %#x\n", opts);
    705 
    706 	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
    707 		fd = open(IPLOOKUP_NAME, O_RDWR);
    708 		if (fd == -1) {
    709 			perror("open(IPLOOKUP_NAME)");
    710 			exit(1);
    711 		}
    712 	}
    713 
    714 	bzero((char *)&op, sizeof(op));
    715 	if (poolname != NULL) {
    716 		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
    717 		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
    718 	}
    719 	op.iplo_unit = role;
    720 
    721 	if (live_kernel)
    722 		poollist_live(role, poolname, type, fd);
    723 	else
    724 		poollist_dead(role, poolname, type, kernel, core);
    725 	return 0;
    726 }
    727 
    728 
    729 void
    730 poollist_dead(role, poolname, type, kernel, core)
    731 	int role, type;
    732 	char *poolname, *kernel, *core;
    733 {
    734 	iphtable_t *hptr;
    735 	ip_pool_t *ptr;
    736 
    737 	if (openkmem(kernel, core) == -1)
    738 		exit(-1);
    739 
    740 	if (type == IPLT_ALL || type == IPLT_POOL) {
    741 		ip_pool_t *pools[IPL_LOGSIZE];
    742 		struct nlist names[2] = { { "ip_pool_list" } , { "" } };
    743 
    744 		if (nlist(kernel, names) != 1)
    745 			return;
    746 
    747 		bzero(&pools, sizeof(pools));
    748 		if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
    749 			return;
    750 
    751 		if (role != IPL_LOGALL) {
    752 			ptr = pools[role];
    753 			while (ptr != NULL) {
    754 				ptr = printpool(ptr, kmemcpywrap, poolname,
    755 						opts, pool_fields);
    756 			}
    757 		} else {
    758 			for (role = 0; role <= IPL_LOGMAX; role++) {
    759 				ptr = pools[role];
    760 				while (ptr != NULL) {
    761 					ptr = printpool(ptr, kmemcpywrap,
    762 							poolname, opts,
    763 							pool_fields);
    764 				}
    765 			}
    766 			role = IPL_LOGALL;
    767 		}
    768 	}
    769 	if (type == IPLT_ALL || type == IPLT_HASH) {
    770 		iphtable_t *tables[IPL_LOGSIZE];
    771 		struct nlist names[2] = { { "ipf_htables" } , { "" } };
    772 
    773 		if (nlist(kernel, names) != 1)
    774 			return;
    775 
    776 		bzero(&tables, sizeof(tables));
    777 		if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
    778 			return;
    779 
    780 		if (role != IPL_LOGALL) {
    781 			hptr = tables[role];
    782 			while (hptr != NULL) {
    783 				hptr = printhash(hptr, kmemcpywrap,
    784 						 poolname, opts, pool_fields);
    785 			}
    786 		} else {
    787 			for (role = 0; role <= IPL_LOGMAX; role++) {
    788 				hptr = tables[role];
    789 				while (hptr != NULL) {
    790 					hptr = printhash(hptr, kmemcpywrap,
    791 							 poolname, opts,
    792 							 pool_fields);
    793 				}
    794 			}
    795 		}
    796 	}
    797 }
    798 
    799 
    800 void
    801 poollist_live(role, poolname, type, fd)
    802 	int role, type, fd;
    803 	char *poolname;
    804 {
    805 	ipf_pool_stat_t plstat;
    806 	iplookupop_t op;
    807 	int unit;
    808 	int c;
    809 
    810 	if (type == IPLT_ALL || type == IPLT_POOL) {
    811 		op.iplo_type = IPLT_POOL;
    812 		op.iplo_size = sizeof(plstat);
    813 		op.iplo_struct = &plstat;
    814 		op.iplo_name[0] = '\0';
    815 		op.iplo_arg = 0;
    816 
    817 		if (role != IPL_LOGALL) {
    818 			op.iplo_unit = role;
    819 
    820 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    821 			if (c == -1) {
    822 				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    823 				return;
    824 			}
    825 
    826 			showpools_live(fd, role, &plstat, poolname);
    827 		} else {
    828 			for (unit = -1; unit <= IPL_LOGMAX; unit++) {
    829 				op.iplo_unit = unit;
    830 
    831 				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    832 				if (c == -1) {
    833 					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    834 					return;
    835 				}
    836 
    837 				showpools_live(fd, unit, &plstat, poolname);
    838 			}
    839 		}
    840 	}
    841 
    842 	if (type == IPLT_ALL || type == IPLT_HASH) {
    843 		iphtstat_t htstat;
    844 
    845 		op.iplo_type = IPLT_HASH;
    846 		op.iplo_size = sizeof(htstat);
    847 		op.iplo_struct = &htstat;
    848 		op.iplo_name[0] = '\0';
    849 		op.iplo_arg = 0;
    850 
    851 		if (role != IPL_LOGALL) {
    852 			op.iplo_unit = role;
    853 
    854 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    855 			if (c == -1) {
    856 				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    857 				return;
    858 			}
    859 			showhashs_live(fd, role, &htstat, poolname);
    860 		} else {
    861 			for (unit = 0; unit <= IPL_LOGMAX; unit++) {
    862 
    863 				op.iplo_unit = unit;
    864 				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    865 				if (c == -1) {
    866 					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    867 					return;
    868 				}
    869 
    870 				showhashs_live(fd, unit, &htstat, poolname);
    871 			}
    872 		}
    873 	}
    874 
    875 	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
    876 		ipf_dstl_stat_t dlstat;
    877 
    878 		op.iplo_type = IPLT_DSTLIST;
    879 		op.iplo_size = sizeof(dlstat);
    880 		op.iplo_struct = &dlstat;
    881 		op.iplo_name[0] = '\0';
    882 		op.iplo_arg = 0;
    883 
    884 		if (role != IPL_LOGALL) {
    885 			op.iplo_unit = role;
    886 
    887 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    888 			if (c == -1) {
    889 				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    890 				return;
    891 			}
    892 			showdstls_live(fd, role, &dlstat, poolname);
    893 		} else {
    894 			for (unit = 0; unit <= IPL_LOGMAX; unit++) {
    895 
    896 				op.iplo_unit = unit;
    897 				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
    898 				if (c == -1) {
    899 					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
    900 					return;
    901 				}
    902 
    903 				showdstls_live(fd, unit, &dlstat, poolname);
    904 			}
    905 		}
    906 	}
    907 }
    908 
    909 
    910 void
    911 showpools_live(fd, role, plstp, poolname)
    912 	int fd, role;
    913 	ipf_pool_stat_t *plstp;
    914 	char *poolname;
    915 {
    916 	ipflookupiter_t iter;
    917 	ip_pool_t pool;
    918 	ipfobj_t obj;
    919 
    920 	obj.ipfo_rev = IPFILTER_VERSION;
    921 	obj.ipfo_type = IPFOBJ_LOOKUPITER;
    922 	obj.ipfo_size = sizeof(iter);
    923 	obj.ipfo_ptr = &iter;
    924 
    925 	iter.ili_type = IPLT_POOL;
    926 	iter.ili_otype = IPFLOOKUPITER_LIST;
    927 	iter.ili_ival = IPFGENITER_LOOKUP;
    928 	iter.ili_nitems = 1;
    929 	iter.ili_data = &pool;
    930 	iter.ili_unit = role;
    931 	*iter.ili_name = '\0';
    932 
    933 	bzero((char *)&pool, sizeof(pool));
    934 
    935 	while (plstp->ipls_list[role + 1] != NULL) {
    936 		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
    937 			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
    938 			break;
    939 		}
    940 		if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
    941 		    ((opts & OPT_DEBUG) != 0))
    942 			printpool_live(&pool, fd, poolname, opts, pool_fields);
    943 
    944 		plstp->ipls_list[role + 1] = pool.ipo_next;
    945 	}
    946 }
    947 
    948 
    949 void
    950 showhashs_live(fd, role, htstp, poolname)
    951 	int fd, role;
    952 	iphtstat_t *htstp;
    953 	char *poolname;
    954 {
    955 	ipflookupiter_t iter;
    956 	iphtable_t table;
    957 	ipfobj_t obj;
    958 
    959 	obj.ipfo_rev = IPFILTER_VERSION;
    960 	obj.ipfo_type = IPFOBJ_LOOKUPITER;
    961 	obj.ipfo_size = sizeof(iter);
    962 	obj.ipfo_ptr = &iter;
    963 
    964 	iter.ili_type = IPLT_HASH;
    965 	iter.ili_otype = IPFLOOKUPITER_LIST;
    966 	iter.ili_ival = IPFGENITER_LOOKUP;
    967 	iter.ili_nitems = 1;
    968 	iter.ili_data = &table;
    969 	iter.ili_unit = role;
    970 	*iter.ili_name = '\0';
    971 
    972 	while (htstp->iphs_tables != NULL) {
    973 		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
    974 			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
    975 			break;
    976 		}
    977 
    978 		printhash_live(&table, fd, poolname, opts, pool_fields);
    979 
    980 		htstp->iphs_tables = table.iph_next;
    981 	}
    982 }
    983 
    984 
    985 void
    986 showdstls_live(fd, role, dlstp, poolname)
    987 	int fd, role;
    988 	ipf_dstl_stat_t *dlstp;
    989 	char *poolname;
    990 {
    991 	ipflookupiter_t iter;
    992 	ippool_dst_t table;
    993 	ipfobj_t obj;
    994 
    995 	obj.ipfo_rev = IPFILTER_VERSION;
    996 	obj.ipfo_type = IPFOBJ_LOOKUPITER;
    997 	obj.ipfo_size = sizeof(iter);
    998 	obj.ipfo_ptr = &iter;
    999 
   1000 	iter.ili_type = IPLT_DSTLIST;
   1001 	iter.ili_otype = IPFLOOKUPITER_LIST;
   1002 	iter.ili_ival = IPFGENITER_LOOKUP;
   1003 	iter.ili_nitems = 1;
   1004 	iter.ili_data = &table;
   1005 	iter.ili_unit = role;
   1006 	*iter.ili_name = '\0';
   1007 
   1008 	while (dlstp->ipls_list[role] != NULL) {
   1009 		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
   1010 			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
   1011 			break;
   1012 		}
   1013 
   1014 		printdstl_live(&table, fd, poolname, opts, pool_fields);
   1015 
   1016 		dlstp->ipls_list[role] = table.ipld_next;
   1017 	}
   1018 }
   1019 
   1020 
   1021 int
   1022 setnodeaddr(int type, int role, void *ptr, char *arg)
   1023 {
   1024 	struct in_addr mask;
   1025 	char *s;
   1026 
   1027 	s = strchr(arg, '/');
   1028 	if (s == NULL)
   1029 		mask.s_addr = 0xffffffff;
   1030 	else if (strchr(s, '.') == NULL) {
   1031 		if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0)
   1032 			return -1;
   1033 	} else {
   1034 		mask.s_addr = inet_addr(s + 1);
   1035 	}
   1036 	if (s != NULL)
   1037 		*s = '\0';
   1038 
   1039 	if (type == IPLT_POOL) {
   1040 		ip_pool_node_t *node = ptr;
   1041 
   1042 		if (node->ipn_addr.adf_family == AF_INET)
   1043 			node->ipn_addr.adf_len = offsetof(addrfamily_t,
   1044 							  adf_addr) +
   1045 						 sizeof(struct in_addr);
   1046 #ifdef USE_INET6
   1047 		else
   1048 			node->ipn_addr.adf_len = offsetof(addrfamily_t,
   1049 							  adf_addr) +
   1050 						 sizeof(struct in6_addr);
   1051 #endif
   1052 		node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
   1053 		node->ipn_mask.adf_len = node->ipn_addr.adf_len;
   1054 		node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
   1055 	} else if (type == IPLT_HASH) {
   1056 		iphtent_t *node = ptr;
   1057 
   1058 		node->ipe_addr.in4.s_addr = inet_addr(arg);
   1059 		node->ipe_mask.in4.s_addr = mask.s_addr;
   1060         	node->ipe_family = AF_INET;
   1061         	node->ipe_unit = role;
   1062 	}
   1063 
   1064 	return 0;
   1065 }
   1066