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