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