ippool.c revision 353091
1/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ippool.c 353091 2019-10-04 02:05:26Z 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>] [-o <role>] [-M <core>] [-N <namelist>]\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:FlrRs"))
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 'r' :
114		err = poolnodecommand(1, argc, argv);
115		break;
116	case 'R' :
117		err = poolcommand(1, argc, argv);
118		break;
119	case 's' :
120		err = poolstats(argc, argv);
121		break;
122	default :
123		exit(1);
124	}
125
126	if (err != 0)
127		exit(1);
128	return 0;
129}
130
131
132int
133poolnodecommand(remove, argc, argv)
134	int remove, argc;
135	char *argv[];
136{
137	int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
138	char *poolname = NULL;
139	ip_pool_node_t pnode;
140	iphtent_t hnode;
141	void *ptr = &pnode;
142
143	ipset = 0;
144	role = IPL_LOGIPF;
145	bzero((char *)&pnode, sizeof(pnode));
146	bzero((char *)&hnode, sizeof(hnode));
147
148	while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1)
149		switch (c)
150		{
151		case 'd' :
152			opts |= OPT_DEBUG;
153			ippool_yydebug++;
154			break;
155		case 'i' :
156			if (setnodeaddr(type, role, ptr, optarg) == 0)
157				ipset = 1;
158			break;
159		case 'm' :
160			poolname = optarg;
161			break;
162		case 'n' :
163			opts |= OPT_DONOTHING|OPT_DONTOPEN;
164			break;
165		case 'o' :
166			if (ipset == 1) {
167				fprintf(stderr,
168					"cannot set role after ip address\n");
169				return -1;
170			}
171			role = getrole(optarg);
172			if (role == IPL_LOGNONE)
173				return -1;
174			break;
175		case 'R' :
176			opts |= OPT_NORESOLVE;
177			break;
178		case 't' :
179			if (ipset == 1) {
180				fprintf(stderr,
181					"cannot set type after ip address\n");
182				return -1;
183			}
184			type = gettype(optarg, NULL);
185			switch (type) {
186			case IPLT_NONE :
187				fprintf(stderr, "unknown type '%s'\n", optarg);
188				return -1;
189			case IPLT_HASH :
190				ptr = &hnode;
191				break;
192			case IPLT_POOL :
193			default :
194				break;
195			}
196			break;
197		case 'T' :
198			ttl = atoi(optarg);
199			if (ttl < 0) {
200				fprintf(stderr, "cannot set negative ttl\n");
201				return -1;
202			}
203			break;
204		case 'v' :
205			opts |= OPT_VERBOSE;
206			break;
207		default :
208			usage(argv[0]);
209			break;		/* keep compiler happy */
210		}
211
212	if (argc - 1 - optind > 0)
213		usage(argv[0]);
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:RS:v")) != -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			if (remove == 0)
296				iph.iph_seed = atoi(optarg);
297			else
298				usage(argv[0]);
299			break;
300		case 'v' :
301			opts |= OPT_VERBOSE;
302			break;
303		default :
304			usage(argv[0]);
305			break;		/* keep compiler happy */
306		}
307
308	if (argc - 1 - optind > 0)
309		usage(argv[0]);
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
360int
361loadpoolfile(argc, argv, infile)
362	int argc;
363	char *argv[], *infile;
364{
365	int c;
366
367	while ((c = getopt(argc, argv, "dnRuv")) != -1)
368		switch (c)
369		{
370		case 'd' :
371			opts |= OPT_DEBUG;
372			ippool_yydebug++;
373			break;
374		case 'n' :
375			opts |= OPT_DONOTHING|OPT_DONTOPEN;
376			break;
377		case 'R' :
378			opts |= OPT_NORESOLVE;
379			break;
380		case 'u' :
381			opts |= OPT_REMOVE;
382			break;
383		case 'v' :
384			opts |= OPT_VERBOSE;
385			break;
386		default :
387			usage(argv[0]);
388			break;		/* keep compiler happy */
389		}
390
391	if (argc - 1 - optind > 0)
392		usage(argv[0]);
393
394	if (opts & OPT_DEBUG)
395		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
396
397	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
398		fd = open(IPLOOKUP_NAME, O_RDWR);
399		if (fd == -1) {
400			perror("open(IPLOOKUP_NAME)");
401			exit(1);
402		}
403	}
404
405	if (ippool_parsefile(fd, infile, ioctl) != 0)
406		return -1;
407	return 0;
408}
409
410
411int
412poolstats(argc, argv)
413	int argc;
414	char *argv[];
415{
416	int c, type, role, live_kernel;
417	ipf_pool_stat_t plstat;
418	ipf_dstl_stat_t dlstat;
419	char *kernel, *core;
420	iphtstat_t htstat;
421	iplookupop_t op;
422
423	core = NULL;
424	kernel = NULL;
425	live_kernel = 1;
426	type = IPLT_ALL;
427	role = IPL_LOGALL;
428
429	bzero((char *)&op, sizeof(op));
430
431	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
432		switch (c)
433		{
434		case 'd' :
435			opts |= OPT_DEBUG;
436			break;
437		case 'M' :
438			live_kernel = 0;
439			core = optarg;
440			break;
441		case 'N' :
442			live_kernel = 0;
443			kernel = optarg;
444			break;
445		case 'o' :
446			role = getrole(optarg);
447			if (role == IPL_LOGNONE) {
448				fprintf(stderr, "unknown role '%s'\n", optarg);
449				return -1;
450			}
451			break;
452		case 't' :
453			type = gettype(optarg, NULL);
454			if (type != IPLT_POOL) {
455				fprintf(stderr,
456					"-s not supported for this type yet\n");
457				return -1;
458			}
459			break;
460		case 'v' :
461			opts |= OPT_VERBOSE;
462			break;
463		default :
464			usage(argv[0]);
465			break;		/* keep compiler happy */
466		}
467
468	if (argc - 1 - optind > 0)
469		usage(argv[0]);
470
471	if (opts & OPT_DEBUG)
472		fprintf(stderr, "poolstats: opts = %#x\n", opts);
473
474	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
475		fd = open(IPLOOKUP_NAME, O_RDWR);
476		if (fd == -1) {
477			perror("open(IPLOOKUP_NAME)");
478			exit(1);
479		}
480	}
481
482	if (type == IPLT_ALL || type == IPLT_POOL) {
483		op.iplo_type = IPLT_POOL;
484		op.iplo_struct = &plstat;
485		op.iplo_size = sizeof(plstat);
486		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
487			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
488			if (c == -1) {
489				ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)");
490				return -1;
491			}
492			printf("%lu\taddress pools\n", plstat.ipls_pools);
493			printf("%lu\taddress pool nodes\n", plstat.ipls_nodes);
494		}
495	}
496
497	if (type == IPLT_ALL || type == IPLT_HASH) {
498		op.iplo_type = IPLT_HASH;
499		op.iplo_struct = &htstat;
500		op.iplo_size = sizeof(htstat);
501		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
502			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
503			if (c == -1) {
504				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
505				return -1;
506			}
507			printf("%lu\thash tables\n", htstat.iphs_numtables);
508			printf("%lu\thash table nodes\n", htstat.iphs_numnodes);
509			printf("%lu\thash table no memory \n",
510				htstat.iphs_nomem);
511		}
512	}
513
514	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
515		op.iplo_type = IPLT_DSTLIST;
516		op.iplo_struct = &dlstat;
517		op.iplo_size = sizeof(dlstat);
518		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
519			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
520			if (c == -1) {
521				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
522				return -1;
523			}
524			printf("%u\tdestination lists\n",
525			       dlstat.ipls_numlists);
526			printf("%u\tdestination list nodes\n",
527			       dlstat.ipls_numnodes);
528			printf("%lu\tdestination list no memory\n",
529			       dlstat.ipls_nomem);
530			printf("%u\tdestination list zombies\n",
531			       dlstat.ipls_numdereflists);
532			printf("%u\tdesetination list node zombies\n",
533			       dlstat.ipls_numderefnodes);
534		}
535	}
536	return 0;
537}
538
539
540int
541poolflush(argc, argv)
542	int argc;
543	char *argv[];
544{
545	int c, role, type, arg;
546	iplookupflush_t flush;
547
548	arg = IPLT_ALL;
549	type = IPLT_ALL;
550	role = IPL_LOGALL;
551
552	while ((c = getopt(argc, argv, "do:t:v")) != -1)
553		switch (c)
554		{
555		case 'd' :
556			opts |= OPT_DEBUG;
557			break;
558		case 'o' :
559			role = getrole(optarg);
560			if (role == IPL_LOGNONE) {
561				fprintf(stderr, "unknown role '%s'\n", optarg);
562				return -1;
563			}
564			break;
565		case 't' :
566			type = gettype(optarg, NULL);
567			if (type == IPLT_NONE) {
568				fprintf(stderr, "unknown type '%s'\n", optarg);
569				return -1;
570			}
571			break;
572		case 'v' :
573			opts |= OPT_VERBOSE;
574			break;
575		default :
576			usage(argv[0]);
577			break;		/* keep compiler happy */
578		}
579
580	if (argc - optind > 0)
581		usage(argv[0]);
582
583	if (opts & OPT_DEBUG)
584		fprintf(stderr, "poolflush: opts = %#x\n", opts);
585
586	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
587		fd = open(IPLOOKUP_NAME, O_RDWR);
588		if (fd == -1) {
589			perror("open(IPLOOKUP_NAME)");
590			exit(1);
591		}
592	}
593
594	bzero((char *)&flush, sizeof(flush));
595	flush.iplf_type = type;
596	flush.iplf_unit = role;
597	flush.iplf_arg = arg;
598
599	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
600		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
601			ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)");
602			exit(1);
603		}
604
605	}
606	printf("%u object%s flushed\n", flush.iplf_count,
607	       (flush.iplf_count == 1) ? "" : "s");
608
609	return 0;
610}
611
612
613int
614getrole(rolename)
615	char *rolename;
616{
617	int role;
618
619	if (!strcasecmp(rolename, "ipf")) {
620		role = IPL_LOGIPF;
621#if 0
622	} else if (!strcasecmp(rolename, "nat")) {
623		role = IPL_LOGNAT;
624	} else if (!strcasecmp(rolename, "state")) {
625		role = IPL_LOGSTATE;
626	} else if (!strcasecmp(rolename, "auth")) {
627		role = IPL_LOGAUTH;
628	} else if (!strcasecmp(rolename, "sync")) {
629		role = IPL_LOGSYNC;
630	} else if (!strcasecmp(rolename, "scan")) {
631		role = IPL_LOGSCAN;
632	} else if (!strcasecmp(rolename, "pool")) {
633		role = IPL_LOGLOOKUP;
634	} else if (!strcasecmp(rolename, "count")) {
635		role = IPL_LOGCOUNT;
636#endif
637	} else {
638		role = IPL_LOGNONE;
639	}
640
641	return role;
642}
643
644
645int
646gettype(typename, minor)
647	char *typename;
648	u_int *minor;
649{
650	int type;
651
652	if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) {
653		type = IPLT_POOL;
654	} else if (!strcasecmp(typename, "hash")) {
655		type = IPLT_HASH;
656		if (minor != NULL)
657			*minor = IPHASH_LOOKUP;
658	} else if (!strcasecmp(typename, "group-map")) {
659		type = IPLT_HASH;
660		if (minor != NULL)
661			*minor = IPHASH_GROUPMAP;
662	} else {
663		type = IPLT_NONE;
664	}
665	return type;
666}
667
668
669int
670poollist(argc, argv)
671	int argc;
672	char *argv[];
673{
674	char *kernel, *core, *poolname;
675	int c, role, type, live_kernel;
676	iplookupop_t op;
677
678	core = NULL;
679	kernel = NULL;
680	live_kernel = 1;
681	type = IPLT_ALL;
682	poolname = NULL;
683	role = IPL_LOGALL;
684
685	while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1)
686		switch (c)
687		{
688		case 'd' :
689			opts |= OPT_DEBUG;
690			break;
691		case 'm' :
692			poolname = optarg;
693			break;
694		case 'M' :
695			live_kernel = 0;
696			core = optarg;
697			break;
698		case 'N' :
699			live_kernel = 0;
700			kernel = optarg;
701			break;
702		case 'o' :
703			role = getrole(optarg);
704			if (role == IPL_LOGNONE) {
705				fprintf(stderr, "unknown role '%s'\n", optarg);
706				return -1;
707			}
708			break;
709#if 0
710		case 'O' :
711			/* XXX This option does not work. This function as  */
712			/* XXX used by state and nat can be used to format  */
713			/* XXX output especially useful for scripting. It   */
714			/* XXX is left here with the intention of making    */
715			/* XXX it work for the same purpose at some point.  */
716			pool_fields = parsefields(poolfields, optarg);
717			break;
718#endif
719		case 't' :
720			type = gettype(optarg, NULL);
721			if (type == IPLT_NONE) {
722				fprintf(stderr, "unknown type '%s'\n", optarg);
723				return -1;
724			}
725			break;
726		case 'v' :
727			opts |= OPT_VERBOSE;
728			break;
729		default :
730			usage(argv[0]);
731			break;		/* keep compiler happy */
732		}
733
734	if (argc - optind > 0)
735		usage(argv[0]);
736
737	if (opts & OPT_DEBUG)
738		fprintf(stderr, "poollist: opts = %#x\n", opts);
739
740	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
741		fd = open(IPLOOKUP_NAME, O_RDWR);
742		if (fd == -1) {
743			perror("open(IPLOOKUP_NAME)");
744			exit(1);
745		}
746	}
747
748	bzero((char *)&op, sizeof(op));
749	if (poolname != NULL) {
750		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
751		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
752	}
753	op.iplo_unit = role;
754
755	if (live_kernel)
756		poollist_live(role, poolname, type, fd);
757	else
758		poollist_dead(role, poolname, type, kernel, core);
759	return 0;
760}
761
762
763void
764poollist_dead(role, poolname, type, kernel, core)
765	int role, type;
766	char *poolname, *kernel, *core;
767{
768	iphtable_t *hptr;
769	ip_pool_t *ptr;
770
771	if (openkmem(kernel, core) == -1)
772		exit(-1);
773
774	if (type == IPLT_ALL || type == IPLT_POOL) {
775		ip_pool_t *pools[IPL_LOGSIZE];
776		struct nlist names[2] = { { "ip_pool_list" } , { "" } };
777
778		if (nlist(kernel, names) != 1)
779			return;
780
781		bzero(&pools, sizeof(pools));
782		if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
783			return;
784
785		if (role != IPL_LOGALL) {
786			ptr = pools[role];
787			while (ptr != NULL) {
788				ptr = printpool(ptr, kmemcpywrap, poolname,
789						opts, pool_fields);
790			}
791		} else {
792			for (role = 0; role <= IPL_LOGMAX; role++) {
793				ptr = pools[role];
794				while (ptr != NULL) {
795					ptr = printpool(ptr, kmemcpywrap,
796							poolname, opts,
797							pool_fields);
798				}
799			}
800			role = IPL_LOGALL;
801		}
802	}
803	if (type == IPLT_ALL || type == IPLT_HASH) {
804		iphtable_t *tables[IPL_LOGSIZE];
805		struct nlist names[2] = { { "ipf_htables" } , { "" } };
806
807		if (nlist(kernel, names) != 1)
808			return;
809
810		bzero(&tables, sizeof(tables));
811		if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
812			return;
813
814		if (role != IPL_LOGALL) {
815			hptr = tables[role];
816			while (hptr != NULL) {
817				hptr = printhash(hptr, kmemcpywrap,
818						 poolname, opts, pool_fields);
819			}
820		} else {
821			for (role = 0; role <= IPL_LOGMAX; role++) {
822				hptr = tables[role];
823				while (hptr != NULL) {
824					hptr = printhash(hptr, kmemcpywrap,
825							 poolname, opts,
826							 pool_fields);
827				}
828			}
829		}
830	}
831}
832
833
834void
835poollist_live(role, poolname, type, fd)
836	int role, type, fd;
837	char *poolname;
838{
839	ipf_pool_stat_t plstat;
840	iplookupop_t op;
841	int c;
842
843	if (type == IPLT_ALL || type == IPLT_POOL) {
844		op.iplo_type = IPLT_POOL;
845		op.iplo_size = sizeof(plstat);
846		op.iplo_struct = &plstat;
847		op.iplo_name[0] = '\0';
848		op.iplo_arg = 0;
849
850		if (role != IPL_LOGALL) {
851			op.iplo_unit = role;
852
853			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
854			if (c == -1) {
855				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
856				return;
857			}
858
859			showpools_live(fd, role, &plstat, poolname);
860		} else {
861			for (role = -1; role <= IPL_LOGMAX; role++) {
862				op.iplo_unit = role;
863
864				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
865				if (c == -1) {
866					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
867					return;
868				}
869
870				showpools_live(fd, role, &plstat, poolname);
871			}
872
873			role = IPL_LOGALL;
874		}
875	}
876
877	if (type == IPLT_ALL || type == IPLT_HASH) {
878		iphtstat_t htstat;
879
880		op.iplo_type = IPLT_HASH;
881		op.iplo_size = sizeof(htstat);
882		op.iplo_struct = &htstat;
883		op.iplo_name[0] = '\0';
884		op.iplo_arg = 0;
885
886		if (role != IPL_LOGALL) {
887			op.iplo_unit = role;
888
889			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
890			if (c == -1) {
891				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
892				return;
893			}
894			showhashs_live(fd, role, &htstat, poolname);
895		} else {
896			for (role = 0; role <= IPL_LOGMAX; role++) {
897
898				op.iplo_unit = role;
899				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
900				if (c == -1) {
901					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
902					return;
903				}
904
905				showhashs_live(fd, role, &htstat, poolname);
906			}
907			role = IPL_LOGALL;
908		}
909	}
910
911	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
912		ipf_dstl_stat_t dlstat;
913
914		op.iplo_type = IPLT_DSTLIST;
915		op.iplo_size = sizeof(dlstat);
916		op.iplo_struct = &dlstat;
917		op.iplo_name[0] = '\0';
918		op.iplo_arg = 0;
919
920		if (role != IPL_LOGALL) {
921			op.iplo_unit = role;
922
923			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
924			if (c == -1) {
925				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
926				return;
927			}
928			showdstls_live(fd, role, &dlstat, poolname);
929		} else {
930			for (role = 0; role <= IPL_LOGMAX; role++) {
931
932				op.iplo_unit = role;
933				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
934				if (c == -1) {
935					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
936					return;
937				}
938
939				showdstls_live(fd, role, &dlstat, poolname);
940			}
941			role = IPL_LOGALL;
942		}
943	}
944}
945
946
947void
948showpools_live(fd, role, plstp, poolname)
949	int fd, role;
950	ipf_pool_stat_t *plstp;
951	char *poolname;
952{
953	ipflookupiter_t iter;
954	ip_pool_t pool;
955	ipfobj_t obj;
956
957	obj.ipfo_rev = IPFILTER_VERSION;
958	obj.ipfo_type = IPFOBJ_LOOKUPITER;
959	obj.ipfo_size = sizeof(iter);
960	obj.ipfo_ptr = &iter;
961
962	iter.ili_type = IPLT_POOL;
963	iter.ili_otype = IPFLOOKUPITER_LIST;
964	iter.ili_ival = IPFGENITER_LOOKUP;
965	iter.ili_nitems = 1;
966	iter.ili_data = &pool;
967	iter.ili_unit = role;
968	*iter.ili_name = '\0';
969
970	bzero((char *)&pool, sizeof(pool));
971
972	while (plstp->ipls_list[role + 1] != NULL) {
973		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
974			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
975			break;
976		}
977		if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
978		    ((opts & OPT_DEBUG) != 0))
979			printpool_live(&pool, fd, poolname, opts, pool_fields);
980
981		plstp->ipls_list[role + 1] = pool.ipo_next;
982	}
983}
984
985
986void
987showhashs_live(fd, role, htstp, poolname)
988	int fd, role;
989	iphtstat_t *htstp;
990	char *poolname;
991{
992	ipflookupiter_t iter;
993	iphtable_t table;
994	ipfobj_t obj;
995
996	obj.ipfo_rev = IPFILTER_VERSION;
997	obj.ipfo_type = IPFOBJ_LOOKUPITER;
998	obj.ipfo_size = sizeof(iter);
999	obj.ipfo_ptr = &iter;
1000
1001	iter.ili_type = IPLT_HASH;
1002	iter.ili_otype = IPFLOOKUPITER_LIST;
1003	iter.ili_ival = IPFGENITER_LOOKUP;
1004	iter.ili_nitems = 1;
1005	iter.ili_data = &table;
1006	iter.ili_unit = role;
1007	*iter.ili_name = '\0';
1008
1009	while (htstp->iphs_tables != NULL) {
1010		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
1011			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
1012			break;
1013		}
1014
1015		printhash_live(&table, fd, poolname, opts, pool_fields);
1016
1017		htstp->iphs_tables = table.iph_next;
1018	}
1019}
1020
1021
1022void
1023showdstls_live(fd, role, dlstp, poolname)
1024	int fd, role;
1025	ipf_dstl_stat_t *dlstp;
1026	char *poolname;
1027{
1028	ipflookupiter_t iter;
1029	ippool_dst_t table;
1030	ipfobj_t obj;
1031
1032	obj.ipfo_rev = IPFILTER_VERSION;
1033	obj.ipfo_type = IPFOBJ_LOOKUPITER;
1034	obj.ipfo_size = sizeof(iter);
1035	obj.ipfo_ptr = &iter;
1036
1037	iter.ili_type = IPLT_DSTLIST;
1038	iter.ili_otype = IPFLOOKUPITER_LIST;
1039	iter.ili_ival = IPFGENITER_LOOKUP;
1040	iter.ili_nitems = 1;
1041	iter.ili_data = &table;
1042	iter.ili_unit = role;
1043	*iter.ili_name = '\0';
1044
1045	while (dlstp->ipls_list[role] != NULL) {
1046		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
1047			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
1048			break;
1049		}
1050
1051		printdstl_live(&table, fd, poolname, opts, pool_fields);
1052
1053		dlstp->ipls_list[role] = table.ipld_next;
1054	}
1055}
1056
1057
1058int
1059setnodeaddr(int type, int role, void *ptr, char *arg)
1060{
1061	struct in_addr mask;
1062	char *s;
1063
1064	s = strchr(arg, '/');
1065	if (s == NULL)
1066		mask.s_addr = 0xffffffff;
1067	else if (strchr(s, '.') == NULL) {
1068		if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0)
1069			return -1;
1070	} else {
1071		mask.s_addr = inet_addr(s + 1);
1072	}
1073	if (s != NULL)
1074		*s = '\0';
1075
1076	if (type == IPLT_POOL) {
1077		ip_pool_node_t *node = ptr;
1078
1079#ifdef USE_INET6
1080		if (node->ipn_addr.adf_family == AF_INET)
1081#endif
1082			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1083							  adf_addr) +
1084						 sizeof(struct in_addr);
1085#ifdef USE_INET6
1086		else
1087			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1088							  adf_addr) +
1089						 sizeof(struct in6_addr);
1090#endif
1091		node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
1092		node->ipn_mask.adf_len = node->ipn_addr.adf_len;
1093		node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
1094	} else if (type == IPLT_HASH) {
1095		iphtent_t *node = ptr;
1096
1097		node->ipe_addr.in4.s_addr = inet_addr(arg);
1098		node->ipe_mask.in4.s_addr = mask.s_addr;
1099        	node->ipe_family = AF_INET;
1100        	node->ipe_unit = role;
1101	}
1102
1103	return 0;
1104}
1105