ippool.c revision 353077
1/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ippool.c 353077 2019-10-04 01:43:45Z 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		}
449
450	if (opts & OPT_DEBUG)
451		fprintf(stderr, "poolstats: opts = %#x\n", opts);
452
453	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
454		fd = open(IPLOOKUP_NAME, O_RDWR);
455		if (fd == -1) {
456			perror("open(IPLOOKUP_NAME)");
457			exit(1);
458		}
459	}
460
461	if (type == IPLT_ALL || type == IPLT_POOL) {
462		op.iplo_type = IPLT_POOL;
463		op.iplo_struct = &plstat;
464		op.iplo_size = sizeof(plstat);
465		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
466			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
467			if (c == -1) {
468				ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)");
469				return -1;
470			}
471			printf("%lu\taddress pools\n", plstat.ipls_pools);
472			printf("%lu\taddress pool nodes\n", plstat.ipls_nodes);
473		}
474	}
475
476	if (type == IPLT_ALL || type == IPLT_HASH) {
477		op.iplo_type = IPLT_HASH;
478		op.iplo_struct = &htstat;
479		op.iplo_size = sizeof(htstat);
480		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
481			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
482			if (c == -1) {
483				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
484				return -1;
485			}
486			printf("%lu\thash tables\n", htstat.iphs_numtables);
487			printf("%lu\thash table nodes\n", htstat.iphs_numnodes);
488			printf("%lu\thash table no memory \n",
489				htstat.iphs_nomem);
490		}
491	}
492
493	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
494		op.iplo_type = IPLT_DSTLIST;
495		op.iplo_struct = &dlstat;
496		op.iplo_size = sizeof(dlstat);
497		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
498			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
499			if (c == -1) {
500				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
501				return -1;
502			}
503			printf("%u\tdestination lists\n",
504			       dlstat.ipls_numlists);
505			printf("%u\tdestination list nodes\n",
506			       dlstat.ipls_numnodes);
507			printf("%lu\tdestination list no memory\n",
508			       dlstat.ipls_nomem);
509			printf("%u\tdestination list zombies\n",
510			       dlstat.ipls_numdereflists);
511			printf("%u\tdesetination list node zombies\n",
512			       dlstat.ipls_numderefnodes);
513		}
514	}
515	return 0;
516}
517
518
519int
520poolflush(argc, argv)
521	int argc;
522	char *argv[];
523{
524	int c, role, type, arg;
525	iplookupflush_t flush;
526
527	arg = IPLT_ALL;
528	type = IPLT_ALL;
529	role = IPL_LOGALL;
530
531	while ((c = getopt(argc, argv, "do:t:v")) != -1)
532		switch (c)
533		{
534		case 'd' :
535			opts |= OPT_DEBUG;
536			break;
537		case 'o' :
538			role = getrole(optarg);
539			if (role == IPL_LOGNONE) {
540				fprintf(stderr, "unknown role '%s'\n", optarg);
541				return -1;
542			}
543			break;
544		case 't' :
545			type = gettype(optarg, NULL);
546			if (type == IPLT_NONE) {
547				fprintf(stderr, "unknown type '%s'\n", optarg);
548				return -1;
549			}
550			break;
551		case 'v' :
552			opts |= OPT_VERBOSE;
553			break;
554		}
555
556	if (opts & OPT_DEBUG)
557		fprintf(stderr, "poolflush: opts = %#x\n", opts);
558
559	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
560		fd = open(IPLOOKUP_NAME, O_RDWR);
561		if (fd == -1) {
562			perror("open(IPLOOKUP_NAME)");
563			exit(1);
564		}
565	}
566
567	bzero((char *)&flush, sizeof(flush));
568	flush.iplf_type = type;
569	flush.iplf_unit = role;
570	flush.iplf_arg = arg;
571
572	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
573		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
574			ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)");
575			exit(1);
576		}
577
578	}
579	printf("%u object%s flushed\n", flush.iplf_count,
580	       (flush.iplf_count == 1) ? "" : "s");
581
582	return 0;
583}
584
585
586int
587getrole(rolename)
588	char *rolename;
589{
590	int role;
591
592	if (!strcasecmp(rolename, "ipf")) {
593		role = IPL_LOGIPF;
594#if 0
595	} else if (!strcasecmp(rolename, "nat")) {
596		role = IPL_LOGNAT;
597	} else if (!strcasecmp(rolename, "state")) {
598		role = IPL_LOGSTATE;
599	} else if (!strcasecmp(rolename, "auth")) {
600		role = IPL_LOGAUTH;
601	} else if (!strcasecmp(rolename, "sync")) {
602		role = IPL_LOGSYNC;
603	} else if (!strcasecmp(rolename, "scan")) {
604		role = IPL_LOGSCAN;
605	} else if (!strcasecmp(rolename, "pool")) {
606		role = IPL_LOGLOOKUP;
607	} else if (!strcasecmp(rolename, "count")) {
608		role = IPL_LOGCOUNT;
609#endif
610	} else {
611		role = IPL_LOGNONE;
612	}
613
614	return role;
615}
616
617
618int
619gettype(typename, minor)
620	char *typename;
621	u_int *minor;
622{
623	int type;
624
625	if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) {
626		type = IPLT_POOL;
627	} else if (!strcasecmp(typename, "hash")) {
628		type = IPLT_HASH;
629		if (minor != NULL)
630			*minor = IPHASH_LOOKUP;
631	} else if (!strcasecmp(typename, "group-map")) {
632		type = IPLT_HASH;
633		if (minor != NULL)
634			*minor = IPHASH_GROUPMAP;
635	} else {
636		type = IPLT_NONE;
637	}
638	return type;
639}
640
641
642int
643poollist(argc, argv)
644	int argc;
645	char *argv[];
646{
647	char *kernel, *core, *poolname;
648	int c, role, type, live_kernel;
649	iplookupop_t op;
650
651	core = NULL;
652	kernel = NULL;
653	live_kernel = 1;
654	type = IPLT_ALL;
655	poolname = NULL;
656	role = IPL_LOGALL;
657
658	while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1)
659		switch (c)
660		{
661		case 'd' :
662			opts |= OPT_DEBUG;
663			break;
664		case 'm' :
665			poolname = optarg;
666			break;
667		case 'M' :
668			live_kernel = 0;
669			core = optarg;
670			break;
671		case 'N' :
672			live_kernel = 0;
673			kernel = optarg;
674			break;
675		case 'o' :
676			role = getrole(optarg);
677			if (role == IPL_LOGNONE) {
678				fprintf(stderr, "unknown role '%s'\n", optarg);
679				return -1;
680			}
681			break;
682#if 0
683		case 'O' :
684			/* XXX This option does not work. This function as  */
685			/* XXX used by state and nat can be used to format  */
686			/* XXX output especially useful for scripting. It   */
687			/* XXX is left here with the intention of making    */
688			/* XXX it work for the same purpose at some point.  */
689			pool_fields = parsefields(poolfields, optarg);
690			break;
691#endif
692		case 't' :
693			type = gettype(optarg, NULL);
694			if (type == IPLT_NONE) {
695				fprintf(stderr, "unknown type '%s'\n", optarg);
696				return -1;
697			}
698			break;
699		case 'v' :
700			opts |= OPT_VERBOSE;
701			break;
702		default :
703			usage(argv[0]);
704			break;		/* keep compiler happy */
705		}
706
707	if (argc - optind > 0)
708		usage(argv[0]);
709
710	if (opts & OPT_DEBUG)
711		fprintf(stderr, "poollist: opts = %#x\n", opts);
712
713	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
714		fd = open(IPLOOKUP_NAME, O_RDWR);
715		if (fd == -1) {
716			perror("open(IPLOOKUP_NAME)");
717			exit(1);
718		}
719	}
720
721	bzero((char *)&op, sizeof(op));
722	if (poolname != NULL) {
723		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
724		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
725	}
726	op.iplo_unit = role;
727
728	if (live_kernel)
729		poollist_live(role, poolname, type, fd);
730	else
731		poollist_dead(role, poolname, type, kernel, core);
732	return 0;
733}
734
735
736void
737poollist_dead(role, poolname, type, kernel, core)
738	int role, type;
739	char *poolname, *kernel, *core;
740{
741	iphtable_t *hptr;
742	ip_pool_t *ptr;
743
744	if (openkmem(kernel, core) == -1)
745		exit(-1);
746
747	if (type == IPLT_ALL || type == IPLT_POOL) {
748		ip_pool_t *pools[IPL_LOGSIZE];
749		struct nlist names[2] = { { "ip_pool_list" } , { "" } };
750
751		if (nlist(kernel, names) != 1)
752			return;
753
754		bzero(&pools, sizeof(pools));
755		if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
756			return;
757
758		if (role != IPL_LOGALL) {
759			ptr = pools[role];
760			while (ptr != NULL) {
761				ptr = printpool(ptr, kmemcpywrap, poolname,
762						opts, pool_fields);
763			}
764		} else {
765			for (role = 0; role <= IPL_LOGMAX; role++) {
766				ptr = pools[role];
767				while (ptr != NULL) {
768					ptr = printpool(ptr, kmemcpywrap,
769							poolname, opts,
770							pool_fields);
771				}
772			}
773			role = IPL_LOGALL;
774		}
775	}
776	if (type == IPLT_ALL || type == IPLT_HASH) {
777		iphtable_t *tables[IPL_LOGSIZE];
778		struct nlist names[2] = { { "ipf_htables" } , { "" } };
779
780		if (nlist(kernel, names) != 1)
781			return;
782
783		bzero(&tables, sizeof(tables));
784		if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
785			return;
786
787		if (role != IPL_LOGALL) {
788			hptr = tables[role];
789			while (hptr != NULL) {
790				hptr = printhash(hptr, kmemcpywrap,
791						 poolname, opts, pool_fields);
792			}
793		} else {
794			for (role = 0; role <= IPL_LOGMAX; role++) {
795				hptr = tables[role];
796				while (hptr != NULL) {
797					hptr = printhash(hptr, kmemcpywrap,
798							 poolname, opts,
799							 pool_fields);
800				}
801			}
802		}
803	}
804}
805
806
807void
808poollist_live(role, poolname, type, fd)
809	int role, type, fd;
810	char *poolname;
811{
812	ipf_pool_stat_t plstat;
813	iplookupop_t op;
814	int c;
815
816	if (type == IPLT_ALL || type == IPLT_POOL) {
817		op.iplo_type = IPLT_POOL;
818		op.iplo_size = sizeof(plstat);
819		op.iplo_struct = &plstat;
820		op.iplo_name[0] = '\0';
821		op.iplo_arg = 0;
822
823		if (role != IPL_LOGALL) {
824			op.iplo_unit = role;
825
826			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
827			if (c == -1) {
828				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
829				return;
830			}
831
832			showpools_live(fd, role, &plstat, poolname);
833		} else {
834			for (role = -1; role <= IPL_LOGMAX; role++) {
835				op.iplo_unit = role;
836
837				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
838				if (c == -1) {
839					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
840					return;
841				}
842
843				showpools_live(fd, role, &plstat, poolname);
844			}
845
846			role = IPL_LOGALL;
847		}
848	}
849
850	if (type == IPLT_ALL || type == IPLT_HASH) {
851		iphtstat_t htstat;
852
853		op.iplo_type = IPLT_HASH;
854		op.iplo_size = sizeof(htstat);
855		op.iplo_struct = &htstat;
856		op.iplo_name[0] = '\0';
857		op.iplo_arg = 0;
858
859		if (role != IPL_LOGALL) {
860			op.iplo_unit = role;
861
862			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
863			if (c == -1) {
864				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
865				return;
866			}
867			showhashs_live(fd, role, &htstat, poolname);
868		} else {
869			for (role = 0; role <= IPL_LOGMAX; role++) {
870
871				op.iplo_unit = role;
872				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
873				if (c == -1) {
874					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
875					return;
876				}
877
878				showhashs_live(fd, role, &htstat, poolname);
879			}
880			role = IPL_LOGALL;
881		}
882	}
883
884	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
885		ipf_dstl_stat_t dlstat;
886
887		op.iplo_type = IPLT_DSTLIST;
888		op.iplo_size = sizeof(dlstat);
889		op.iplo_struct = &dlstat;
890		op.iplo_name[0] = '\0';
891		op.iplo_arg = 0;
892
893		if (role != IPL_LOGALL) {
894			op.iplo_unit = role;
895
896			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
897			if (c == -1) {
898				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
899				return;
900			}
901			showdstls_live(fd, role, &dlstat, poolname);
902		} else {
903			for (role = 0; role <= IPL_LOGMAX; role++) {
904
905				op.iplo_unit = role;
906				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
907				if (c == -1) {
908					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
909					return;
910				}
911
912				showdstls_live(fd, role, &dlstat, poolname);
913			}
914			role = IPL_LOGALL;
915		}
916	}
917}
918
919
920void
921showpools_live(fd, role, plstp, poolname)
922	int fd, role;
923	ipf_pool_stat_t *plstp;
924	char *poolname;
925{
926	ipflookupiter_t iter;
927	ip_pool_t pool;
928	ipfobj_t obj;
929
930	obj.ipfo_rev = IPFILTER_VERSION;
931	obj.ipfo_type = IPFOBJ_LOOKUPITER;
932	obj.ipfo_size = sizeof(iter);
933	obj.ipfo_ptr = &iter;
934
935	iter.ili_type = IPLT_POOL;
936	iter.ili_otype = IPFLOOKUPITER_LIST;
937	iter.ili_ival = IPFGENITER_LOOKUP;
938	iter.ili_nitems = 1;
939	iter.ili_data = &pool;
940	iter.ili_unit = role;
941	*iter.ili_name = '\0';
942
943	bzero((char *)&pool, sizeof(pool));
944
945	while (plstp->ipls_list[role + 1] != NULL) {
946		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
947			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
948			break;
949		}
950		if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
951		    ((opts & OPT_DEBUG) != 0))
952			printpool_live(&pool, fd, poolname, opts, pool_fields);
953
954		plstp->ipls_list[role + 1] = pool.ipo_next;
955	}
956}
957
958
959void
960showhashs_live(fd, role, htstp, poolname)
961	int fd, role;
962	iphtstat_t *htstp;
963	char *poolname;
964{
965	ipflookupiter_t iter;
966	iphtable_t table;
967	ipfobj_t obj;
968
969	obj.ipfo_rev = IPFILTER_VERSION;
970	obj.ipfo_type = IPFOBJ_LOOKUPITER;
971	obj.ipfo_size = sizeof(iter);
972	obj.ipfo_ptr = &iter;
973
974	iter.ili_type = IPLT_HASH;
975	iter.ili_otype = IPFLOOKUPITER_LIST;
976	iter.ili_ival = IPFGENITER_LOOKUP;
977	iter.ili_nitems = 1;
978	iter.ili_data = &table;
979	iter.ili_unit = role;
980	*iter.ili_name = '\0';
981
982	while (htstp->iphs_tables != NULL) {
983		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
984			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
985			break;
986		}
987
988		printhash_live(&table, fd, poolname, opts, pool_fields);
989
990		htstp->iphs_tables = table.iph_next;
991	}
992}
993
994
995void
996showdstls_live(fd, role, dlstp, poolname)
997	int fd, role;
998	ipf_dstl_stat_t *dlstp;
999	char *poolname;
1000{
1001	ipflookupiter_t iter;
1002	ippool_dst_t table;
1003	ipfobj_t obj;
1004
1005	obj.ipfo_rev = IPFILTER_VERSION;
1006	obj.ipfo_type = IPFOBJ_LOOKUPITER;
1007	obj.ipfo_size = sizeof(iter);
1008	obj.ipfo_ptr = &iter;
1009
1010	iter.ili_type = IPLT_DSTLIST;
1011	iter.ili_otype = IPFLOOKUPITER_LIST;
1012	iter.ili_ival = IPFGENITER_LOOKUP;
1013	iter.ili_nitems = 1;
1014	iter.ili_data = &table;
1015	iter.ili_unit = role;
1016	*iter.ili_name = '\0';
1017
1018	while (dlstp->ipls_list[role] != NULL) {
1019		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
1020			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
1021			break;
1022		}
1023
1024		printdstl_live(&table, fd, poolname, opts, pool_fields);
1025
1026		dlstp->ipls_list[role] = table.ipld_next;
1027	}
1028}
1029
1030
1031int
1032setnodeaddr(int type, int role, void *ptr, char *arg)
1033{
1034	struct in_addr mask;
1035	char *s;
1036
1037	s = strchr(arg, '/');
1038	if (s == NULL)
1039		mask.s_addr = 0xffffffff;
1040	else if (strchr(s, '.') == NULL) {
1041		if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0)
1042			return -1;
1043	} else {
1044		mask.s_addr = inet_addr(s + 1);
1045	}
1046	if (s != NULL)
1047		*s = '\0';
1048
1049	if (type == IPLT_POOL) {
1050		ip_pool_node_t *node = ptr;
1051
1052#ifdef USE_INET6
1053		if (node->ipn_addr.adf_family == AF_INET)
1054#endif
1055			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1056							  adf_addr) +
1057						 sizeof(struct in_addr);
1058#ifdef USE_INET6
1059		else
1060			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1061							  adf_addr) +
1062						 sizeof(struct in6_addr);
1063#endif
1064		node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
1065		node->ipn_mask.adf_len = node->ipn_addr.adf_len;
1066		node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
1067	} else if (type == IPLT_HASH) {
1068		iphtent_t *node = ptr;
1069
1070		node->ipe_addr.in4.s_addr = inet_addr(arg);
1071		node->ipe_mask.in4.s_addr = mask.s_addr;
1072        	node->ipe_family = AF_INET;
1073        	node->ipe_unit = role;
1074	}
1075
1076	return 0;
1077}
1078