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