ippool.c revision 170268
1/*	$FreeBSD: head/contrib/ipfilter/tools/ippool.c 170268 2007-06-04 02:54:36Z darrenr $	*/
2
3/*
4 * Copyright (C) 2002-2006 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
46extern	int	ippool_yyparse __P((void));
47extern	int	ippool_yydebug;
48extern	FILE	*ippool_yyin;
49extern	char	*optarg;
50extern	int	lineNum;
51
52void	usage __P((char *));
53int	main __P((int, char **));
54int	poolcommand __P((int, int, char *[]));
55int	poolnodecommand __P((int, int, char *[]));
56int	loadpoolfile __P((int, char *[], char *));
57int	poollist __P((int, char *[]));
58void	poollist_dead __P((int, char *, int, char *, char *));
59void	poollist_live __P((int, char *, int, int));
60int	poolflush __P((int, char *[]));
61int	poolstats __P((int, char *[]));
62int	gettype __P((char *, u_int *));
63int	getrole __P((char *));
64int	setnodeaddr __P((ip_pool_node_t *node, char *arg));
65void	showpools_live __P((int, int, ip_pool_stat_t *, char *));
66void	showhashs_live __P((int, int, iphtstat_t *, char *));
67
68int	opts = 0;
69int	fd = -1;
70int	use_inet6 = 0;
71
72
73void usage(prog)
74char *prog;
75{
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");
85	exit(1);
86}
87
88
89int main(argc, argv)
90int argc;
91char *argv[];
92{
93	int err;
94
95	if (argc < 2)
96		usage(argv[0]);
97
98	switch (getopt(argc, argv, "aAf:FlrRs"))
99	{
100	case 'a' :
101		err = poolnodecommand(0, argc, argv);
102		break;
103	case 'A' :
104		err = poolcommand(0, argc, argv);
105		break;
106	case 'f' :
107		err = loadpoolfile(argc, argv, optarg);
108		break;
109	case 'F' :
110		err = poolflush(argc, argv);
111		break;
112	case 'l' :
113		err = poollist(argc, argv);
114		break;
115	case 'r' :
116		err = poolnodecommand(1, argc, argv);
117		break;
118	case 'R' :
119		err = poolcommand(1, argc, argv);
120		break;
121	case 's' :
122		err = poolstats(argc, argv);
123		break;
124	default :
125		exit(1);
126	}
127
128	if (err != 0)
129		exit(1);
130	return 0;
131}
132
133
134int poolnodecommand(remove, argc, argv)
135int remove, argc;
136char *argv[];
137{
138	int err, c, ipset, role;
139	char *poolname = NULL;
140	ip_pool_node_t node;
141
142	ipset = 0;
143	role = IPL_LOGIPF;
144	bzero((char *)&node, sizeof(node));
145
146	while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
147		switch (c)
148		{
149		case 'd' :
150			opts |= OPT_DEBUG;
151			ippool_yydebug++;
152			break;
153		case 'i' :
154			if (setnodeaddr(&node, optarg) == 0)
155				ipset = 1;
156			break;
157		case 'm' :
158			poolname = optarg;
159			break;
160		case 'n' :
161			opts |= OPT_DONOTHING;
162			break;
163		case 'o' :
164			role = getrole(optarg);
165			if (role == IPL_LOGNONE)
166				return -1;
167			break;
168		case 'R' :
169			opts |= OPT_NORESOLVE;
170			break;
171		case 'v' :
172			opts |= OPT_VERBOSE;
173			break;
174		}
175
176	if (argv[optind] != NULL && ipset == 0) {
177		if (setnodeaddr(&node, argv[optind]) == 0)
178			ipset = 1;
179	}
180
181	if (opts & OPT_DEBUG)
182		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
183
184	if (ipset == 0) {
185		fprintf(stderr, "no IP address given with -i\n");
186		return -1;
187	}
188
189	if (poolname == NULL) {
190		fprintf(stderr, "poolname not given with add/remove node\n");
191		return -1;
192	}
193
194	if (remove == 0)
195		err = load_poolnode(0, poolname, &node, ioctl);
196	else
197		err = remove_poolnode(0, poolname, &node, ioctl);
198	return err;
199}
200
201
202int poolcommand(remove, argc, argv)
203int remove, argc;
204char *argv[];
205{
206	int type, role, c, err;
207	char *poolname;
208	iphtable_t iph;
209	ip_pool_t pool;
210
211	err = 1;
212	role = 0;
213	type = 0;
214	poolname = NULL;
215	role = IPL_LOGIPF;
216	bzero((char *)&iph, sizeof(iph));
217	bzero((char *)&pool, sizeof(pool));
218
219	while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1)
220		switch (c)
221		{
222		case 'd' :
223			opts |= OPT_DEBUG;
224			ippool_yydebug++;
225			break;
226		case 'm' :
227			poolname = optarg;
228			break;
229		case 'n' :
230			opts |= OPT_DONOTHING;
231			break;
232		case 'o' :
233			role = getrole(optarg);
234			if (role == IPL_LOGNONE) {
235				fprintf(stderr, "unknown role '%s'\n", optarg);
236				return -1;
237			}
238			break;
239		case 'R' :
240			opts |= OPT_NORESOLVE;
241			break;
242		case 'S' :
243			iph.iph_seed = atoi(optarg);
244			break;
245		case 't' :
246			type = gettype(optarg, &iph.iph_type);
247			if (type == IPLT_NONE) {
248				fprintf(stderr, "unknown type '%s'\n", optarg);
249				return -1;
250			}
251			break;
252		case 'v' :
253			opts |= OPT_VERBOSE;
254			break;
255		}
256
257	if (opts & OPT_DEBUG)
258		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
259
260	if (poolname == NULL) {
261		fprintf(stderr, "poolname not given with add/remove pool\n");
262		return -1;
263	}
264
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';
268		iph.iph_unit = role;
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;
273	}
274
275	if (remove == 0) {
276		switch (type)
277		{
278		case IPLT_HASH :
279			err = load_hash(&iph, NULL, ioctl);
280			break;
281		case IPLT_POOL :
282			err = load_pool(&pool, ioctl);
283			break;
284		}
285	} else {
286		switch (type)
287		{
288		case IPLT_HASH :
289			err = remove_hash(&iph, ioctl);
290			break;
291		case IPLT_POOL :
292			err = remove_pool(&pool, ioctl);
293			break;
294		}
295	}
296	return err;
297}
298
299
300int loadpoolfile(argc, argv, infile)
301int argc;
302char *argv[], *infile;
303{
304	int c;
305
306	infile = optarg;
307
308	while ((c = getopt(argc, argv, "dnRuv")) != -1)
309		switch (c)
310		{
311		case 'd' :
312			opts |= OPT_DEBUG;
313			ippool_yydebug++;
314			break;
315		case 'n' :
316			opts |= OPT_DONOTHING;
317			break;
318		case 'R' :
319			opts |= OPT_NORESOLVE;
320			break;
321		case 'u' :
322			opts |= OPT_REMOVE;
323			break;
324		case 'v' :
325			opts |= OPT_VERBOSE;
326			break;
327		}
328
329	if (opts & OPT_DEBUG)
330		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
331
332	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
333		fd = open(IPLOOKUP_NAME, O_RDWR);
334		if (fd == -1) {
335			perror("open(IPLOOKUP_NAME)");
336			exit(1);
337		}
338	}
339
340	if (ippool_parsefile(fd, infile, ioctl) != 0)
341		return -1;
342	return 0;
343}
344
345
346int poolstats(argc, argv)
347int argc;
348char *argv[];
349{
350	int c, type, role, live_kernel;
351	ip_pool_stat_t plstat;
352	char *kernel, *core;
353	iphtstat_t htstat;
354	iplookupop_t op;
355
356	core = NULL;
357	kernel = NULL;
358	live_kernel = 1;
359	type = IPLT_ALL;
360	role = IPL_LOGALL;
361
362	bzero((char *)&op, sizeof(op));
363
364	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
365		switch (c)
366		{
367		case 'd' :
368			opts |= OPT_DEBUG;
369			break;
370		case 'M' :
371			live_kernel = 0;
372			core = optarg;
373			break;
374		case 'N' :
375			live_kernel = 0;
376			kernel = optarg;
377			break;
378		case 'o' :
379			role = getrole(optarg);
380			if (role == IPL_LOGNONE) {
381				fprintf(stderr, "unknown role '%s'\n", optarg);
382				return -1;
383			}
384			break;
385		case 't' :
386			type = gettype(optarg, NULL);
387			if (type != IPLT_POOL) {
388				fprintf(stderr,
389					"-s not supported for this type yet\n");
390				return -1;
391			}
392			break;
393		case 'v' :
394			opts |= OPT_VERBOSE;
395			break;
396		}
397
398	if (opts & OPT_DEBUG)
399		fprintf(stderr, "poolstats: opts = %#x\n", opts);
400
401	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
402		fd = open(IPLOOKUP_NAME, O_RDWR);
403		if (fd == -1) {
404			perror("open(IPLOOKUP_NAME)");
405			exit(1);
406		}
407	}
408
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);
415			if (c == -1) {
416				perror("ioctl(SIOCLOOKUPSTAT)");
417				return -1;
418			}
419			printf("Pools:\t%lu\n", plstat.ipls_pools);
420			printf("Nodes:\t%lu\n", plstat.ipls_nodes);
421		}
422	}
423
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);
430			if (c == -1) {
431				perror("ioctl(SIOCLOOKUPSTAT)");
432				return -1;
433			}
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);
437		}
438	}
439	return 0;
440}
441
442
443int poolflush(argc, argv)
444int argc;
445char *argv[];
446{
447	int c, role, type, arg;
448	iplookupflush_t flush;
449
450	arg = IPLT_ALL;
451	type = IPLT_ALL;
452	role = IPL_LOGALL;
453
454	while ((c = getopt(argc, argv, "do:t:v")) != -1)
455		switch (c)
456		{
457		case 'd' :
458			opts |= OPT_DEBUG;
459			break;
460		case 'o' :
461			role = getrole(optarg);
462			if (role == IPL_LOGNONE) {
463				fprintf(stderr, "unknown role '%s'\n", optarg);
464				return -1;
465			}
466			break;
467		case 't' :
468			type = gettype(optarg, NULL);
469			if (type == IPLT_NONE) {
470				fprintf(stderr, "unknown type '%s'\n", optarg);
471				return -1;
472			}
473			break;
474		case 'v' :
475			opts |= OPT_VERBOSE;
476			break;
477		}
478
479	if (opts & OPT_DEBUG)
480		fprintf(stderr, "poolflush: opts = %#x\n", opts);
481
482	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
483		fd = open(IPLOOKUP_NAME, O_RDWR);
484		if (fd == -1) {
485			perror("open(IPLOOKUP_NAME)");
486			exit(1);
487		}
488	}
489
490	bzero((char *)&flush, sizeof(flush));
491	flush.iplf_type = type;
492	flush.iplf_unit = role;
493	flush.iplf_arg = arg;
494
495	if (!(opts & OPT_DONOTHING)) {
496		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
497			perror("ioctl(SIOCLOOKUPFLUSH)");
498			exit(1);
499		}
500
501	}
502	printf("%zd object%s flushed\n", flush.iplf_count,
503	       (flush.iplf_count == 1) ? "" : "s");
504
505	return 0;
506}
507
508
509int getrole(rolename)
510char *rolename;
511{
512	int role;
513
514	if (!strcasecmp(rolename, "ipf")) {
515		role = IPL_LOGIPF;
516#if 0
517	} else if (!strcasecmp(rolename, "nat")) {
518		role = IPL_LOGNAT;
519	} else if (!strcasecmp(rolename, "state")) {
520		role = IPL_LOGSTATE;
521	} else if (!strcasecmp(rolename, "auth")) {
522		role = IPL_LOGAUTH;
523	} else if (!strcasecmp(rolename, "sync")) {
524		role = IPL_LOGSYNC;
525	} else if (!strcasecmp(rolename, "scan")) {
526		role = IPL_LOGSCAN;
527	} else if (!strcasecmp(rolename, "pool")) {
528		role = IPL_LOGLOOKUP;
529	} else if (!strcasecmp(rolename, "count")) {
530		role = IPL_LOGCOUNT;
531#endif
532	} else {
533		role = IPL_LOGNONE;
534	}
535
536	return role;
537}
538
539
540int gettype(typename, minor)
541char *typename;
542u_int *minor;
543{
544	int type;
545
546	if (!strcasecmp(optarg, "tree") || !strcasecmp(optarg, "pool")) {
547		type = IPLT_POOL;
548	} else if (!strcasecmp(optarg, "hash")) {
549		type = IPLT_HASH;
550		if (minor != NULL)
551			*minor = IPHASH_LOOKUP;
552	} else if (!strcasecmp(optarg, "group-map")) {
553		type = IPLT_HASH;
554		if (minor != NULL)
555			*minor = IPHASH_GROUPMAP;
556	} else {
557		type = IPLT_NONE;
558	}
559	return type;
560}
561
562
563int poollist(argc, argv)
564int argc;
565char *argv[];
566{
567	char *kernel, *core, *poolname;
568	int c, role, type, live_kernel;
569	iplookupop_t op;
570
571	core = NULL;
572	kernel = NULL;
573	live_kernel = 1;
574	type = IPLT_ALL;
575	poolname = NULL;
576	role = IPL_LOGALL;
577
578	while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
579		switch (c)
580		{
581		case 'd' :
582			opts |= OPT_DEBUG;
583			break;
584		case 'm' :
585			poolname = optarg;
586			break;
587		case 'M' :
588			live_kernel = 0;
589			core = optarg;
590			break;
591		case 'N' :
592			live_kernel = 0;
593			kernel = optarg;
594			break;
595		case 'o' :
596			role = getrole(optarg);
597			if (role == IPL_LOGNONE) {
598				fprintf(stderr, "unknown role '%s'\n", optarg);
599				return -1;
600			}
601			break;
602		case 'R' :
603			opts |= OPT_NORESOLVE;
604			break;
605		case 't' :
606			type = gettype(optarg, NULL);
607			if (type == IPLT_NONE) {
608				fprintf(stderr, "unknown type '%s'\n", optarg);
609				return -1;
610			}
611			break;
612		case 'v' :
613			opts |= OPT_VERBOSE;
614			break;
615		}
616
617	if (opts & OPT_DEBUG)
618		fprintf(stderr, "poollist: opts = %#x\n", opts);
619
620	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
621		fd = open(IPLOOKUP_NAME, O_RDWR);
622		if (fd == -1) {
623			perror("open(IPLOOKUP_NAME)");
624			exit(1);
625		}
626	}
627
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';
632	}
633	op.iplo_unit = role;
634
635	if (live_kernel)
636		poollist_live(role, poolname, type, fd);
637	else
638		poollist_dead(role, poolname, type, kernel, core);
639	return 0;
640}
641
642
643void poollist_dead(role, poolname, type, kernel, core)
644int role, type;
645char *poolname, *kernel, *core;
646{
647	iphtable_t *hptr;
648	ip_pool_t *ptr;
649
650	if (openkmem(kernel, core) == -1)
651		exit(-1);
652
653	if (type == IPLT_ALL || type == IPLT_POOL) {
654		ip_pool_t *pools[IPL_LOGSIZE];
655		struct nlist names[2] = { { "ip_pool_list" } , { "" } };
656
657		if (nlist(kernel, names) != 1)
658			return;
659
660		bzero(&pools, sizeof(pools));
661		if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
662			return;
663
664		if (role != IPL_LOGALL) {
665			ptr = pools[role];
666			while (ptr != NULL) {
667				ptr = printpool(ptr, kmemcpywrap, poolname,
668						opts);
669			}
670		} else {
671			for (role = 0; role <= IPL_LOGMAX; role++) {
672				ptr = pools[role];
673				while (ptr != NULL) {
674					ptr = printpool(ptr, kmemcpywrap,
675							poolname, opts);
676				}
677			}
678			role = IPL_LOGALL;
679		}
680	}
681	if (type == IPLT_ALL || type == IPLT_HASH) {
682		iphtable_t *tables[IPL_LOGSIZE];
683		struct nlist names[2] = { { "ipf_htables" } , { "" } };
684
685		if (nlist(kernel, names) != 1)
686			return;
687
688		bzero(&tables, sizeof(tables));
689		if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
690			return;
691
692		if (role != IPL_LOGALL) {
693			hptr = tables[role];
694			while (hptr != NULL) {
695				hptr = printhash(hptr, kmemcpywrap,
696						 poolname, opts);
697			}
698		} else {
699			for (role = 0; role <= IPL_LOGMAX; role++) {
700				hptr = tables[role];
701				while (hptr != NULL) {
702					hptr = printhash(hptr, kmemcpywrap,
703							 poolname, opts);
704				}
705			}
706		}
707	}
708}
709
710
711void poollist_live(role, poolname, type, fd)
712int role, type, fd;
713char *poolname;
714{
715	ip_pool_stat_t plstat;
716	iphtstat_t htstat;
717	iplookupop_t op;
718	int c;
719
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';
725		op.iplo_arg = 0;
726
727		if (role != IPL_LOGALL) {
728			op.iplo_unit = role;
729
730			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
731			if (c == -1) {
732				perror("ioctl(SIOCLOOKUPSTAT)");
733				return;
734			}
735
736			showpools_live(fd, role, &plstat, poolname);
737		} else {
738			for (role = 0; role <= IPL_LOGMAX; role++) {
739				op.iplo_unit = role;
740
741				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
742				if (c == -1) {
743					perror("ioctl(SIOCLOOKUPSTAT)");
744					return;
745				}
746
747				showpools_live(fd, role, &plstat, poolname);
748			}
749
750			role = IPL_LOGALL;
751		}
752	}
753
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';
759		op.iplo_arg = 0;
760
761		if (role != IPL_LOGALL) {
762			op.iplo_unit = role;
763
764			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
765			if (c == -1) {
766				perror("ioctl(SIOCLOOKUPSTAT)");
767				return;
768			}
769			showhashs_live(fd, role, &htstat, poolname);
770		} else {
771			for (role = 0; role <= IPL_LOGMAX; role++) {
772
773				op.iplo_unit = role;
774				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
775				if (c == -1) {
776					perror("ioctl(SIOCLOOKUPSTAT)");
777					return;
778				}
779
780				showhashs_live(fd, role, &htstat, poolname);
781			}
782		}
783	}
784}
785
786
787void showpools_live(fd, role, plstp, poolname)
788int fd, role;
789ip_pool_stat_t *plstp;
790char *poolname;
791{
792	ipflookupiter_t iter;
793	ip_pool_t pool;
794	ipfobj_t obj;
795
796	obj.ipfo_rev = IPFILTER_VERSION;
797	obj.ipfo_type = IPFOBJ_LOOKUPITER;
798	obj.ipfo_size = sizeof(iter);
799	obj.ipfo_ptr = &iter;
800
801	iter.ili_type = IPLT_POOL;
802	iter.ili_otype = IPFLOOKUPITER_LIST;
803	iter.ili_ival = IPFGENITER_LOOKUP;
804	iter.ili_nitems = 1;
805	iter.ili_data = &pool;
806	iter.ili_unit = role;
807	*iter.ili_name = '\0';
808
809	while (plstp->ipls_list[role] != NULL) {
810		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
811			perror("ioctl(SIOCLOOKUPITER)");
812			break;
813		}
814		printpool_live(&pool, fd, poolname, opts);
815
816		plstp->ipls_list[role] = pool.ipo_next;
817	}
818}
819
820
821void showhashs_live(fd, role, htstp, poolname)
822int fd, role;
823iphtstat_t *htstp;
824char *poolname;
825{
826	ipflookupiter_t iter;
827	iphtable_t table;
828	ipfobj_t obj;
829
830	obj.ipfo_rev = IPFILTER_VERSION;
831	obj.ipfo_type = IPFOBJ_LOOKUPITER;
832	obj.ipfo_size = sizeof(iter);
833	obj.ipfo_ptr = &iter;
834
835	iter.ili_type = IPLT_HASH;
836	iter.ili_otype = IPFLOOKUPITER_LIST;
837	iter.ili_ival = IPFGENITER_LOOKUP;
838	iter.ili_nitems = 1;
839	iter.ili_data = &table;
840	iter.ili_unit = role;
841	*iter.ili_name = '\0';
842
843	while (htstp->iphs_tables != NULL) {
844		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
845			perror("ioctl(SIOCLOOKUPITER)");
846			break;
847		}
848
849		printhash_live(&table, fd, poolname, opts);
850
851		htstp->iphs_tables = table.iph_next;
852	}
853}
854
855
856int setnodeaddr(ip_pool_node_t *node, char *arg)
857{
858	struct in_addr mask;
859	char *s;
860
861	s = strchr(arg, '/');
862	if (s == NULL)
863		mask.s_addr = 0xffffffff;
864	else if (strchr(s, '.') == NULL) {
865		if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
866			return -1;
867	} else {
868		mask.s_addr = inet_addr(s + 1);
869	}
870	if (s != NULL)
871		*s = '\0';
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;
876
877	return 0;
878}
879