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