ippool.c revision 353093
1155852Sgallatin/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ippool.c 353093 2019-10-04 02:09:51Z cy $	*/
2155852Sgallatin
3155852Sgallatin/*
4155852Sgallatin * Copyright (C) 2012 by Darren Reed.
5155852Sgallatin *
6155852Sgallatin * See the IPFILTER.LICENCE file for details on licencing.
7155852Sgallatin */
8155852Sgallatin#include <sys/types.h>
9155852Sgallatin#include <sys/time.h>
10155852Sgallatin#include <sys/param.h>
11155852Sgallatin#include <sys/socket.h>
12155852Sgallatin# include <sys/cdefs.h>
13155852Sgallatin#include <sys/ioctl.h>
14155852Sgallatin
15155852Sgallatin#include <net/if.h>
16155852Sgallatin#include <netinet/in.h>
17155852Sgallatin
18155852Sgallatin#include <arpa/inet.h>
19155852Sgallatin
20155852Sgallatin#include <stdio.h>
21155852Sgallatin#include <fcntl.h>
22155852Sgallatin#include <stdlib.h>
23155852Sgallatin#include <string.h>
24155852Sgallatin#include <netdb.h>
25155852Sgallatin#include <ctype.h>
26155852Sgallatin#include <unistd.h>
27155852Sgallatin# include <nlist.h>
28155852Sgallatin
29155852Sgallatin#include "ipf.h"
30155852Sgallatin#include "netinet/ipl.h"
31155852Sgallatin#include "netinet/ip_lookup.h"
32155852Sgallatin#include "netinet/ip_pool.h"
33155852Sgallatin#include "netinet/ip_htable.h"
34155852Sgallatin#include "kmem.h"
35159612Sgallatin
36159612Sgallatin
37155852Sgallatinextern	int	ippool_yyparse __P((void));
38159612Sgallatinextern	int	ippool_yydebug;
39159612Sgallatinextern	FILE	*ippool_yyin;
40159612Sgallatinextern	char	*optarg;
41159612Sgallatinextern	int	lineNum;
42155852Sgallatin
43155852Sgallatinvoid	usage __P((char *));
44155852Sgallatinint	main __P((int, char **));
45155852Sgallatinint	poolcommand __P((int, int, char *[]));
46155852Sgallatinint	poolnodecommand __P((int, int, char *[]));
47155852Sgallatinint	loadpoolfile __P((int, char *[], char *));
48155852Sgallatinint	poollist __P((int, char *[]));
49155852Sgallatinvoid	poollist_dead __P((int, char *, int, char *, char *));
50155852Sgallatinvoid	poollist_live __P((int, char *, int, int));
51155852Sgallatinint	poolflush __P((int, char *[]));
52155852Sgallatinint	poolstats __P((int, char *[]));
53159612Sgallatinint	gettype __P((char *, u_int *));
54155852Sgallatinint	getrole __P((char *));
55155852Sgallatinint	setnodeaddr __P((int, int, void *ptr, char *arg));
56159612Sgallatinvoid	showpools_live __P((int, int, ipf_pool_stat_t *, char *));
57159612Sgallatinvoid	showhashs_live __P((int, int, iphtstat_t *, char *));
58155852Sgallatinvoid	showdstls_live __P((int, int, ipf_dstl_stat_t *, char *));
59159612Sgallatin
60159612Sgallatinint	opts = 0;
61159612Sgallatinint	fd = -1;
62159612Sgallatinint	use_inet6 = 0;
63159612Sgallatinwordtab_t *pool_fields = NULL;
64159612Sgallatinint	nohdrfields = 0;
65155852Sgallatin
66155852Sgallatin
67159612Sgallatinvoid
68155852Sgallatinusage(prog)
69155852Sgallatin	char *prog;
70155852Sgallatin{
71155852Sgallatin	fprintf(stderr, "Usage:\t%s\n", prog);
72155852Sgallatin	fprintf(stderr, "\t-a [-dnv] -m <name> [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n");
73155852Sgallatin	fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
74159612Sgallatin	fprintf(stderr, "\t-f <file> [-dnuvR]\n");
75155852Sgallatin	fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n");
76155852Sgallatin	fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-o <role>] [-M <core>] [-N <namelist>]\n");
77159612Sgallatin	fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n");
78159612Sgallatin	fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
79155852Sgallatin	fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
80155852Sgallatin	exit(1);
81159612Sgallatin}
82155852Sgallatin
83155852Sgallatin
84159612Sgallatinint
85159612Sgallatinmain(argc, argv)
86155852Sgallatin	int argc;
87155852Sgallatin	char *argv[];
88155852Sgallatin{
89155852Sgallatin	int err = 1;
90155852Sgallatin
91155852Sgallatin	if (argc < 2)
92155852Sgallatin		usage(argv[0]);
93155852Sgallatin
94155852Sgallatin	assigndefined(getenv("IPPOOL_PREDEFINED"));
95155852Sgallatin
96155852Sgallatin	switch (getopt(argc, argv, "aAf:FlrRs"))
97155852Sgallatin	{
98155852Sgallatin	case 'a' :
99155852Sgallatin		err = poolnodecommand(0, argc, argv);
100159612Sgallatin		break;
101155852Sgallatin	case 'A' :
102155852Sgallatin		err = poolcommand(0, argc, argv);
103155852Sgallatin		break;
104155852Sgallatin	case 'f' :
105159612Sgallatin		err = loadpoolfile(argc, argv, optarg);
106159612Sgallatin		break;
107159612Sgallatin	case 'F' :
108159612Sgallatin		err = poolflush(argc, argv);
109159612Sgallatin		break;
110159612Sgallatin	case 'l' :
111159612Sgallatin		err = poollist(argc, argv);
112159612Sgallatin		break;
113159612Sgallatin	case 'r' :
114155852Sgallatin		err = poolnodecommand(1, argc, argv);
115159612Sgallatin		break;
116159612Sgallatin	case 'R' :
117155852Sgallatin		err = poolcommand(1, argc, argv);
118159612Sgallatin		break;
119155852Sgallatin	case 's' :
120155852Sgallatin		err = poolstats(argc, argv);
121159612Sgallatin		break;
122159612Sgallatin	default :
123155852Sgallatin		exit(1);
124159612Sgallatin	}
125159612Sgallatin
126155852Sgallatin	if (err != 0)
127155852Sgallatin		exit(1);
128159612Sgallatin	return 0;
129155852Sgallatin}
130155852Sgallatin
131159612Sgallatin
132155852Sgallatinint
133159612Sgallatinpoolnodecommand(remove, argc, argv)
134159612Sgallatin	int remove, argc;
135155852Sgallatin	char *argv[];
136159612Sgallatin{
137159612Sgallatin	int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
138159612Sgallatin	char *poolname = NULL;
139155852Sgallatin	ip_pool_node_t pnode;
140155852Sgallatin	iphtent_t hnode;
141159612Sgallatin	void *ptr = &pnode;
142155852Sgallatin
143155852Sgallatin	ipset = 0;
144159612Sgallatin	role = IPL_LOGIPF;
145159612Sgallatin	bzero((char *)&pnode, sizeof(pnode));
146155852Sgallatin	bzero((char *)&hnode, sizeof(hnode));
147155852Sgallatin
148155852Sgallatin	while ((c = getopt(argc, argv, "di:m:no:t:T:v")) != -1)
149155852Sgallatin		switch (c)
150159612Sgallatin		{
151155852Sgallatin		case 'd' :
152159612Sgallatin			opts |= OPT_DEBUG;
153159612Sgallatin			ippool_yydebug++;
154155852Sgallatin			break;
155155852Sgallatin		case 'i' :
156159612Sgallatin			if (setnodeaddr(type, role, ptr, optarg) == 0)
157155852Sgallatin				ipset = 1;
158155852Sgallatin			break;
159155852Sgallatin		case 'm' :
160159612Sgallatin			poolname = optarg;
161155852Sgallatin			break;
162155852Sgallatin		case 'n' :
163155852Sgallatin			opts |= OPT_DONOTHING|OPT_DONTOPEN;
164159612Sgallatin			break;
165159612Sgallatin		case 'o' :
166155852Sgallatin			if (ipset == 1) {
167159612Sgallatin				fprintf(stderr,
168159612Sgallatin					"cannot set role after ip address\n");
169159612Sgallatin				return -1;
170155852Sgallatin			}
171155852Sgallatin			role = getrole(optarg);
172155852Sgallatin			if (role == IPL_LOGNONE)
173155852Sgallatin				return -1;
174155852Sgallatin			break;
175159612Sgallatin		case 't' :
176159612Sgallatin			if (ipset == 1) {
177159612Sgallatin				fprintf(stderr,
178159612Sgallatin					"cannot set type after ip address\n");
179159612Sgallatin				return -1;
180155852Sgallatin			}
181155852Sgallatin			type = gettype(optarg, NULL);
182155852Sgallatin			switch (type) {
183155852Sgallatin			case IPLT_NONE :
184159612Sgallatin				fprintf(stderr, "unknown type '%s'\n", optarg);
185159612Sgallatin				return -1;
186155852Sgallatin			case IPLT_HASH :
187155852Sgallatin				ptr = &hnode;
188155852Sgallatin				break;
189155852Sgallatin			case IPLT_POOL :
190155852Sgallatin			default :
191155852Sgallatin				break;
192159612Sgallatin			}
193155852Sgallatin			break;
194155852Sgallatin		case 'T' :
195155852Sgallatin			ttl = atoi(optarg);
196155852Sgallatin			if (ttl < 0) {
197159612Sgallatin				fprintf(stderr, "cannot set negative ttl\n");
198155852Sgallatin				return -1;
199155852Sgallatin			}
200159612Sgallatin			break;
201155852Sgallatin		case 'v' :
202155852Sgallatin			opts |= OPT_VERBOSE;
203155852Sgallatin			break;
204159612Sgallatin		default :
205155852Sgallatin			usage(argv[0]);
206155852Sgallatin			break;		/* keep compiler happy */
207155852Sgallatin		}
208155852Sgallatin
209155852Sgallatin	if (argc - 1 - optind > 0)
210155852Sgallatin		usage(argv[0]);
211155852Sgallatin
212159612Sgallatin	if (argv[optind] != NULL && ipset == 0) {
213159612Sgallatin		if (setnodeaddr(type, role, ptr, argv[optind]) == 0)
214159612Sgallatin			ipset = 1;
215159612Sgallatin	}
216155852Sgallatin
217159612Sgallatin	if (opts & OPT_DEBUG)
218159612Sgallatin		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
219159612Sgallatin
220155852Sgallatin	if (ipset == 0) {
221159612Sgallatin		fprintf(stderr, "no IP address given with -i\n");
222159612Sgallatin		return -1;
223155852Sgallatin	}
224159612Sgallatin
225159612Sgallatin	if (poolname == NULL) {
226159612Sgallatin		fprintf(stderr, "poolname not given with add/remove node\n");
227159612Sgallatin		return -1;
228159612Sgallatin	}
229159612Sgallatin
230159612Sgallatin	switch (type) {
231159612Sgallatin	case IPLT_POOL :
232155852Sgallatin		if (remove == 0)
233155852Sgallatin			err = load_poolnode(role, poolname, &pnode, ttl, ioctl);
234159612Sgallatin		else
235159612Sgallatin			err = remove_poolnode(role, poolname, &pnode, ioctl);
236159612Sgallatin		break;
237159612Sgallatin	case IPLT_HASH :
238159612Sgallatin		if (remove == 0)
239159612Sgallatin			err = load_hashnode(role, poolname, &hnode, ttl, ioctl);
240159612Sgallatin		else
241159612Sgallatin			err = remove_hashnode(role, poolname, &hnode, ioctl);
242159612Sgallatin		break;
243159612Sgallatin	default :
244159612Sgallatin		break;
245159612Sgallatin	}
246155852Sgallatin	return err;
247155852Sgallatin}
248159612Sgallatin
249159612Sgallatin
250159612Sgallatinint
251159612Sgallatinpoolcommand(remove, argc, argv)
252155852Sgallatin	int remove, argc;
253155852Sgallatin	char *argv[];
254155852Sgallatin{
255155852Sgallatin	int type, role, c, err;
256155852Sgallatin	char *poolname;
257155852Sgallatin	iphtable_t iph;
258155852Sgallatin	ip_pool_t pool;
259155852Sgallatin
260155852Sgallatin	err = 1;
261159612Sgallatin	role = 0;
262159612Sgallatin	type = 0;
263159612Sgallatin	poolname = NULL;
264159612Sgallatin	role = IPL_LOGIPF;
265159612Sgallatin	bzero((char *)&iph, sizeof(iph));
266159612Sgallatin	bzero((char *)&pool, sizeof(pool));
267155852Sgallatin
268159612Sgallatin	while ((c = getopt(argc, argv, "dm:no:S:v")) != -1)
269159612Sgallatin		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 'v' :
295			opts |= OPT_VERBOSE;
296			break;
297		default :
298			usage(argv[0]);
299			break;		/* keep compiler happy */
300		}
301
302	if (argc - 1 - optind > 0)
303		usage(argv[0]);
304
305	if (opts & OPT_DEBUG)
306		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
307
308	if (poolname == NULL) {
309		fprintf(stderr, "poolname not given with add/remove pool\n");
310		return -1;
311	}
312
313	type = gettype(argv[optind], &iph.iph_type);
314	if (type == IPLT_NONE) {
315		fprintf(stderr, "unknown type '%s'\n", argv[optind]);
316		return -1;
317	}
318
319	if (type == IPLT_HASH) {
320		strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
321		iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
322		iph.iph_unit = role;
323	} else if (type == IPLT_POOL) {
324		strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
325		pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
326		pool.ipo_unit = role;
327	}
328
329	if (remove == 0) {
330		switch (type)
331		{
332		case IPLT_HASH :
333			err = load_hash(&iph, NULL, ioctl);
334			break;
335		case IPLT_POOL :
336			err = load_pool(&pool, ioctl);
337			break;
338		}
339	} else {
340		switch (type)
341		{
342		case IPLT_HASH :
343			err = remove_hash(&iph, ioctl);
344			break;
345		case IPLT_POOL :
346			err = remove_pool(&pool, ioctl);
347			break;
348		}
349	}
350	return err;
351}
352
353
354int
355loadpoolfile(argc, argv, infile)
356	int argc;
357	char *argv[], *infile;
358{
359	int c;
360
361	while ((c = getopt(argc, argv, "dnuv")) != -1)
362		switch (c)
363		{
364		case 'd' :
365			opts |= OPT_DEBUG;
366			ippool_yydebug++;
367			break;
368		case 'n' :
369			opts |= OPT_DONOTHING|OPT_DONTOPEN;
370			break;
371		case 'u' :
372			opts |= OPT_REMOVE;
373			break;
374		case 'v' :
375			opts |= OPT_VERBOSE;
376			break;
377		default :
378			usage(argv[0]);
379			break;		/* keep compiler happy */
380		}
381
382	if (argc - 1 - optind > 0)
383		usage(argv[0]);
384
385	if (opts & OPT_DEBUG)
386		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
387
388	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
389		fd = open(IPLOOKUP_NAME, O_RDWR);
390		if (fd == -1) {
391			perror("open(IPLOOKUP_NAME)");
392			exit(1);
393		}
394	}
395
396	if (ippool_parsefile(fd, infile, ioctl) != 0)
397		return -1;
398	return 0;
399}
400
401
402int
403poolstats(argc, argv)
404	int argc;
405	char *argv[];
406{
407	int c, type, role, live_kernel;
408	ipf_pool_stat_t plstat;
409	ipf_dstl_stat_t dlstat;
410	char *kernel, *core;
411	iphtstat_t htstat;
412	iplookupop_t op;
413
414	core = NULL;
415	kernel = NULL;
416	live_kernel = 1;
417	type = IPLT_ALL;
418	role = IPL_LOGALL;
419
420	bzero((char *)&op, sizeof(op));
421
422	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
423		switch (c)
424		{
425		case 'd' :
426			opts |= OPT_DEBUG;
427			break;
428		case 'M' :
429			live_kernel = 0;
430			core = optarg;
431			break;
432		case 'N' :
433			live_kernel = 0;
434			kernel = optarg;
435			break;
436		case 'o' :
437			role = getrole(optarg);
438			if (role == IPL_LOGNONE) {
439				fprintf(stderr, "unknown role '%s'\n", optarg);
440				return -1;
441			}
442			break;
443		case 't' :
444			type = gettype(optarg, NULL);
445			if (type != IPLT_POOL) {
446				fprintf(stderr,
447					"-s not supported for this type yet\n");
448				return -1;
449			}
450			break;
451		case 'v' :
452			opts |= OPT_VERBOSE;
453			break;
454		default :
455			usage(argv[0]);
456			break;		/* keep compiler happy */
457		}
458
459	if (argc - 1 - optind > 0)
460		usage(argv[0]);
461
462	if (opts & OPT_DEBUG)
463		fprintf(stderr, "poolstats: opts = %#x\n", opts);
464
465	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
466		fd = open(IPLOOKUP_NAME, O_RDWR);
467		if (fd == -1) {
468			perror("open(IPLOOKUP_NAME)");
469			exit(1);
470		}
471	}
472
473	if (type == IPLT_ALL || type == IPLT_POOL) {
474		op.iplo_type = IPLT_POOL;
475		op.iplo_struct = &plstat;
476		op.iplo_size = sizeof(plstat);
477		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
478			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
479			if (c == -1) {
480				ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)");
481				return -1;
482			}
483			printf("%lu\taddress pools\n", plstat.ipls_pools);
484			printf("%lu\taddress pool nodes\n", plstat.ipls_nodes);
485		}
486	}
487
488	if (type == IPLT_ALL || type == IPLT_HASH) {
489		op.iplo_type = IPLT_HASH;
490		op.iplo_struct = &htstat;
491		op.iplo_size = sizeof(htstat);
492		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
493			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
494			if (c == -1) {
495				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
496				return -1;
497			}
498			printf("%lu\thash tables\n", htstat.iphs_numtables);
499			printf("%lu\thash table nodes\n", htstat.iphs_numnodes);
500			printf("%lu\thash table no memory \n",
501				htstat.iphs_nomem);
502		}
503	}
504
505	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
506		op.iplo_type = IPLT_DSTLIST;
507		op.iplo_struct = &dlstat;
508		op.iplo_size = sizeof(dlstat);
509		if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
510			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
511			if (c == -1) {
512				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
513				return -1;
514			}
515			printf("%u\tdestination lists\n",
516			       dlstat.ipls_numlists);
517			printf("%u\tdestination list nodes\n",
518			       dlstat.ipls_numnodes);
519			printf("%lu\tdestination list no memory\n",
520			       dlstat.ipls_nomem);
521			printf("%u\tdestination list zombies\n",
522			       dlstat.ipls_numdereflists);
523			printf("%u\tdesetination list node zombies\n",
524			       dlstat.ipls_numderefnodes);
525		}
526	}
527	return 0;
528}
529
530
531int
532poolflush(argc, argv)
533	int argc;
534	char *argv[];
535{
536	int c, role, type, arg;
537	iplookupflush_t flush;
538
539	arg = IPLT_ALL;
540	type = IPLT_ALL;
541	role = IPL_LOGALL;
542
543	while ((c = getopt(argc, argv, "do:t:v")) != -1)
544		switch (c)
545		{
546		case 'd' :
547			opts |= OPT_DEBUG;
548			break;
549		case 'o' :
550			role = getrole(optarg);
551			if (role == IPL_LOGNONE) {
552				fprintf(stderr, "unknown role '%s'\n", optarg);
553				return -1;
554			}
555			break;
556		case 't' :
557			type = gettype(optarg, NULL);
558			if (type == IPLT_NONE) {
559				fprintf(stderr, "unknown type '%s'\n", optarg);
560				return -1;
561			}
562			break;
563		case 'v' :
564			opts |= OPT_VERBOSE;
565			break;
566		default :
567			usage(argv[0]);
568			break;		/* keep compiler happy */
569		}
570
571	if (argc - optind > 0)
572		usage(argv[0]);
573
574	if (opts & OPT_DEBUG)
575		fprintf(stderr, "poolflush: opts = %#x\n", opts);
576
577	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
578		fd = open(IPLOOKUP_NAME, O_RDWR);
579		if (fd == -1) {
580			perror("open(IPLOOKUP_NAME)");
581			exit(1);
582		}
583	}
584
585	bzero((char *)&flush, sizeof(flush));
586	flush.iplf_type = type;
587	flush.iplf_unit = role;
588	flush.iplf_arg = arg;
589
590	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) {
591		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
592			ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)");
593			exit(1);
594		}
595
596	}
597	printf("%u object%s flushed\n", flush.iplf_count,
598	       (flush.iplf_count == 1) ? "" : "s");
599
600	return 0;
601}
602
603
604int
605getrole(rolename)
606	char *rolename;
607{
608	int role;
609
610	if (!strcasecmp(rolename, "ipf")) {
611		role = IPL_LOGIPF;
612#if 0
613	} else if (!strcasecmp(rolename, "nat")) {
614		role = IPL_LOGNAT;
615	} else if (!strcasecmp(rolename, "state")) {
616		role = IPL_LOGSTATE;
617	} else if (!strcasecmp(rolename, "auth")) {
618		role = IPL_LOGAUTH;
619	} else if (!strcasecmp(rolename, "sync")) {
620		role = IPL_LOGSYNC;
621	} else if (!strcasecmp(rolename, "scan")) {
622		role = IPL_LOGSCAN;
623	} else if (!strcasecmp(rolename, "pool")) {
624		role = IPL_LOGLOOKUP;
625	} else if (!strcasecmp(rolename, "count")) {
626		role = IPL_LOGCOUNT;
627#endif
628	} else {
629		role = IPL_LOGNONE;
630	}
631
632	return role;
633}
634
635
636int
637gettype(typename, minor)
638	char *typename;
639	u_int *minor;
640{
641	int type;
642
643	if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) {
644		type = IPLT_POOL;
645	} else if (!strcasecmp(typename, "hash")) {
646		type = IPLT_HASH;
647		if (minor != NULL)
648			*minor = IPHASH_LOOKUP;
649	} else if (!strcasecmp(typename, "group-map")) {
650		type = IPLT_HASH;
651		if (minor != NULL)
652			*minor = IPHASH_GROUPMAP;
653	} else {
654		type = IPLT_NONE;
655	}
656	return type;
657}
658
659
660int
661poollist(argc, argv)
662	int argc;
663	char *argv[];
664{
665	char *kernel, *core, *poolname;
666	int c, role, type, live_kernel;
667	iplookupop_t op;
668
669	core = NULL;
670	kernel = NULL;
671	live_kernel = 1;
672	type = IPLT_ALL;
673	poolname = NULL;
674	role = IPL_LOGALL;
675
676	while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1)
677		switch (c)
678		{
679		case 'd' :
680			opts |= OPT_DEBUG;
681			break;
682		case 'm' :
683			poolname = optarg;
684			break;
685		case 'M' :
686			live_kernel = 0;
687			core = optarg;
688			break;
689		case 'N' :
690			live_kernel = 0;
691			kernel = optarg;
692			break;
693		case 'o' :
694			role = getrole(optarg);
695			if (role == IPL_LOGNONE) {
696				fprintf(stderr, "unknown role '%s'\n", optarg);
697				return -1;
698			}
699			break;
700#if 0
701		case 'O' :
702			/* XXX This option does not work. This function as  */
703			/* XXX used by state and nat can be used to format  */
704			/* XXX output especially useful for scripting. It   */
705			/* XXX is left here with the intention of making    */
706			/* XXX it work for the same purpose at some point.  */
707			pool_fields = parsefields(poolfields, optarg);
708			break;
709#endif
710		case 't' :
711			type = gettype(optarg, NULL);
712			if (type == IPLT_NONE) {
713				fprintf(stderr, "unknown type '%s'\n", optarg);
714				return -1;
715			}
716			break;
717		case 'v' :
718			opts |= OPT_VERBOSE;
719			break;
720		default :
721			usage(argv[0]);
722			break;		/* keep compiler happy */
723		}
724
725	if (argc - optind > 0)
726		usage(argv[0]);
727
728	if (opts & OPT_DEBUG)
729		fprintf(stderr, "poollist: opts = %#x\n", opts);
730
731	if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) {
732		fd = open(IPLOOKUP_NAME, O_RDWR);
733		if (fd == -1) {
734			perror("open(IPLOOKUP_NAME)");
735			exit(1);
736		}
737	}
738
739	bzero((char *)&op, sizeof(op));
740	if (poolname != NULL) {
741		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
742		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
743	}
744	op.iplo_unit = role;
745
746	if (live_kernel)
747		poollist_live(role, poolname, type, fd);
748	else
749		poollist_dead(role, poolname, type, kernel, core);
750	return 0;
751}
752
753
754void
755poollist_dead(role, poolname, type, kernel, core)
756	int role, type;
757	char *poolname, *kernel, *core;
758{
759	iphtable_t *hptr;
760	ip_pool_t *ptr;
761
762	if (openkmem(kernel, core) == -1)
763		exit(-1);
764
765	if (type == IPLT_ALL || type == IPLT_POOL) {
766		ip_pool_t *pools[IPL_LOGSIZE];
767		struct nlist names[2] = { { "ip_pool_list" } , { "" } };
768
769		if (nlist(kernel, names) != 1)
770			return;
771
772		bzero(&pools, sizeof(pools));
773		if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
774			return;
775
776		if (role != IPL_LOGALL) {
777			ptr = pools[role];
778			while (ptr != NULL) {
779				ptr = printpool(ptr, kmemcpywrap, poolname,
780						opts, pool_fields);
781			}
782		} else {
783			for (role = 0; role <= IPL_LOGMAX; role++) {
784				ptr = pools[role];
785				while (ptr != NULL) {
786					ptr = printpool(ptr, kmemcpywrap,
787							poolname, opts,
788							pool_fields);
789				}
790			}
791			role = IPL_LOGALL;
792		}
793	}
794	if (type == IPLT_ALL || type == IPLT_HASH) {
795		iphtable_t *tables[IPL_LOGSIZE];
796		struct nlist names[2] = { { "ipf_htables" } , { "" } };
797
798		if (nlist(kernel, names) != 1)
799			return;
800
801		bzero(&tables, sizeof(tables));
802		if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
803			return;
804
805		if (role != IPL_LOGALL) {
806			hptr = tables[role];
807			while (hptr != NULL) {
808				hptr = printhash(hptr, kmemcpywrap,
809						 poolname, opts, pool_fields);
810			}
811		} else {
812			for (role = 0; role <= IPL_LOGMAX; role++) {
813				hptr = tables[role];
814				while (hptr != NULL) {
815					hptr = printhash(hptr, kmemcpywrap,
816							 poolname, opts,
817							 pool_fields);
818				}
819			}
820		}
821	}
822}
823
824
825void
826poollist_live(role, poolname, type, fd)
827	int role, type, fd;
828	char *poolname;
829{
830	ipf_pool_stat_t plstat;
831	iplookupop_t op;
832	int c;
833
834	if (type == IPLT_ALL || type == IPLT_POOL) {
835		op.iplo_type = IPLT_POOL;
836		op.iplo_size = sizeof(plstat);
837		op.iplo_struct = &plstat;
838		op.iplo_name[0] = '\0';
839		op.iplo_arg = 0;
840
841		if (role != IPL_LOGALL) {
842			op.iplo_unit = role;
843
844			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
845			if (c == -1) {
846				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
847				return;
848			}
849
850			showpools_live(fd, role, &plstat, poolname);
851		} else {
852			for (role = -1; role <= IPL_LOGMAX; role++) {
853				op.iplo_unit = role;
854
855				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
856				if (c == -1) {
857					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
858					return;
859				}
860
861				showpools_live(fd, role, &plstat, poolname);
862			}
863
864			role = IPL_LOGALL;
865		}
866	}
867
868	if (type == IPLT_ALL || type == IPLT_HASH) {
869		iphtstat_t htstat;
870
871		op.iplo_type = IPLT_HASH;
872		op.iplo_size = sizeof(htstat);
873		op.iplo_struct = &htstat;
874		op.iplo_name[0] = '\0';
875		op.iplo_arg = 0;
876
877		if (role != IPL_LOGALL) {
878			op.iplo_unit = role;
879
880			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
881			if (c == -1) {
882				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
883				return;
884			}
885			showhashs_live(fd, role, &htstat, poolname);
886		} else {
887			for (role = 0; role <= IPL_LOGMAX; role++) {
888
889				op.iplo_unit = role;
890				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
891				if (c == -1) {
892					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
893					return;
894				}
895
896				showhashs_live(fd, role, &htstat, poolname);
897			}
898			role = IPL_LOGALL;
899		}
900	}
901
902	if (type == IPLT_ALL || type == IPLT_DSTLIST) {
903		ipf_dstl_stat_t dlstat;
904
905		op.iplo_type = IPLT_DSTLIST;
906		op.iplo_size = sizeof(dlstat);
907		op.iplo_struct = &dlstat;
908		op.iplo_name[0] = '\0';
909		op.iplo_arg = 0;
910
911		if (role != IPL_LOGALL) {
912			op.iplo_unit = role;
913
914			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
915			if (c == -1) {
916				ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
917				return;
918			}
919			showdstls_live(fd, role, &dlstat, poolname);
920		} else {
921			for (role = 0; role <= IPL_LOGMAX; role++) {
922
923				op.iplo_unit = role;
924				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
925				if (c == -1) {
926					ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
927					return;
928				}
929
930				showdstls_live(fd, role, &dlstat, poolname);
931			}
932			role = IPL_LOGALL;
933		}
934	}
935}
936
937
938void
939showpools_live(fd, role, plstp, poolname)
940	int fd, role;
941	ipf_pool_stat_t *plstp;
942	char *poolname;
943{
944	ipflookupiter_t iter;
945	ip_pool_t pool;
946	ipfobj_t obj;
947
948	obj.ipfo_rev = IPFILTER_VERSION;
949	obj.ipfo_type = IPFOBJ_LOOKUPITER;
950	obj.ipfo_size = sizeof(iter);
951	obj.ipfo_ptr = &iter;
952
953	iter.ili_type = IPLT_POOL;
954	iter.ili_otype = IPFLOOKUPITER_LIST;
955	iter.ili_ival = IPFGENITER_LOOKUP;
956	iter.ili_nitems = 1;
957	iter.ili_data = &pool;
958	iter.ili_unit = role;
959	*iter.ili_name = '\0';
960
961	bzero((char *)&pool, sizeof(pool));
962
963	while (plstp->ipls_list[role + 1] != NULL) {
964		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
965			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
966			break;
967		}
968		if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
969		    ((opts & OPT_DEBUG) != 0))
970			printpool_live(&pool, fd, poolname, opts, pool_fields);
971
972		plstp->ipls_list[role + 1] = pool.ipo_next;
973	}
974}
975
976
977void
978showhashs_live(fd, role, htstp, poolname)
979	int fd, role;
980	iphtstat_t *htstp;
981	char *poolname;
982{
983	ipflookupiter_t iter;
984	iphtable_t table;
985	ipfobj_t obj;
986
987	obj.ipfo_rev = IPFILTER_VERSION;
988	obj.ipfo_type = IPFOBJ_LOOKUPITER;
989	obj.ipfo_size = sizeof(iter);
990	obj.ipfo_ptr = &iter;
991
992	iter.ili_type = IPLT_HASH;
993	iter.ili_otype = IPFLOOKUPITER_LIST;
994	iter.ili_ival = IPFGENITER_LOOKUP;
995	iter.ili_nitems = 1;
996	iter.ili_data = &table;
997	iter.ili_unit = role;
998	*iter.ili_name = '\0';
999
1000	while (htstp->iphs_tables != NULL) {
1001		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
1002			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
1003			break;
1004		}
1005
1006		printhash_live(&table, fd, poolname, opts, pool_fields);
1007
1008		htstp->iphs_tables = table.iph_next;
1009	}
1010}
1011
1012
1013void
1014showdstls_live(fd, role, dlstp, poolname)
1015	int fd, role;
1016	ipf_dstl_stat_t *dlstp;
1017	char *poolname;
1018{
1019	ipflookupiter_t iter;
1020	ippool_dst_t table;
1021	ipfobj_t obj;
1022
1023	obj.ipfo_rev = IPFILTER_VERSION;
1024	obj.ipfo_type = IPFOBJ_LOOKUPITER;
1025	obj.ipfo_size = sizeof(iter);
1026	obj.ipfo_ptr = &iter;
1027
1028	iter.ili_type = IPLT_DSTLIST;
1029	iter.ili_otype = IPFLOOKUPITER_LIST;
1030	iter.ili_ival = IPFGENITER_LOOKUP;
1031	iter.ili_nitems = 1;
1032	iter.ili_data = &table;
1033	iter.ili_unit = role;
1034	*iter.ili_name = '\0';
1035
1036	while (dlstp->ipls_list[role] != NULL) {
1037		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
1038			ipferror(fd, "ioctl(SIOCLOOKUPITER)");
1039			break;
1040		}
1041
1042		printdstl_live(&table, fd, poolname, opts, pool_fields);
1043
1044		dlstp->ipls_list[role] = table.ipld_next;
1045	}
1046}
1047
1048
1049int
1050setnodeaddr(int type, int role, void *ptr, char *arg)
1051{
1052	struct in_addr mask;
1053	char *s;
1054
1055	s = strchr(arg, '/');
1056	if (s == NULL)
1057		mask.s_addr = 0xffffffff;
1058	else if (strchr(s, '.') == NULL) {
1059		if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0)
1060			return -1;
1061	} else {
1062		mask.s_addr = inet_addr(s + 1);
1063	}
1064	if (s != NULL)
1065		*s = '\0';
1066
1067	if (type == IPLT_POOL) {
1068		ip_pool_node_t *node = ptr;
1069
1070#ifdef USE_INET6
1071		if (node->ipn_addr.adf_family == AF_INET)
1072#endif
1073			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1074							  adf_addr) +
1075						 sizeof(struct in_addr);
1076#ifdef USE_INET6
1077		else
1078			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1079							  adf_addr) +
1080						 sizeof(struct in6_addr);
1081#endif
1082		node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
1083		node->ipn_mask.adf_len = node->ipn_addr.adf_len;
1084		node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
1085	} else if (type == IPLT_HASH) {
1086		iphtent_t *node = ptr;
1087
1088		node->ipe_addr.in4.s_addr = inet_addr(arg);
1089		node->ipe_mask.in4.s_addr = mask.s_addr;
1090        	node->ipe_family = AF_INET;
1091        	node->ipe_unit = role;
1092	}
1093
1094	return 0;
1095}
1096