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