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