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