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