ippool.c revision 318206
1145857Sume/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ippool.c 318206 2017-05-12 02:32:01Z cy $	*/
2145857Sume
3145857Sume/*
4145857Sume * Copyright (C) 2012 by Darren Reed.
5145857Sume *
6145857Sume * See the IPFILTER.LICENCE file for details on licencing.
7145857Sume */
8145857Sume#include <sys/types.h>
9145857Sume#include <sys/time.h>
10145857Sume#include <sys/param.h>
11145857Sume#include <sys/socket.h>
12145857Sume#if defined(BSD) && (BSD >= 199306)
13145857Sume# include <sys/cdefs.h>
14145857Sume#endif
15145857Sume#include <sys/ioctl.h>
16145857Sume
17145857Sume#include <net/if.h>
18145857Sume#include <netinet/in.h>
19145857Sume
20145857Sume#include <arpa/inet.h>
21145857Sume
22145857Sume#include <stdio.h>
23145857Sume#include <fcntl.h>
24145857Sume#include <stdlib.h>
25145857Sume#include <string.h>
26145857Sume#include <netdb.h>
27145857Sume#include <ctype.h>
28145857Sume#include <unistd.h>
29145857Sume#ifdef linux
30145857Sume# include <linux/a.out.h>
31145860Sume#else
32145857Sume# include <nlist.h>
33145857Sume#endif
34145857Sume
35145860Sume#include "ipf.h"
36145860Sume#include "netinet/ipl.h"
37145857Sume#include "netinet/ip_lookup.h"
38145857Sume#include "netinet/ip_pool.h"
39145857Sume#include "netinet/ip_htable.h"
40145857Sume#include "kmem.h"
41145857Sume
42145857Sume
43145857Sumeextern	int	ippool_yyparse __P((void));
44145857Sumeextern	int	ippool_yydebug;
45292317Sngieextern	FILE	*ippool_yyin;
46292317Sngieextern	char	*optarg;
47145857Sumeextern	int	lineNum;
48145857Sume
49145857Sumevoid	usage __P((char *));
50145857Sumeint	main __P((int, char **));
51145860Sumeint	poolcommand __P((int, int, char *[]));
52145860Sumeint	poolnodecommand __P((int, int, char *[]));
53145860Sumeint	loadpoolfile __P((int, char *[], char *));
54145860Sumeint	poollist __P((int, char *[]));
55145860Sumevoid	poollist_dead __P((int, char *, int, char *, char *));
56145860Sumevoid	poollist_live __P((int, char *, int, int));
57145857Sumeint	poolflush __P((int, char *[]));
58145860Sumeint	poolstats __P((int, char *[]));
59145857Sumeint	gettype __P((char *, u_int *));
60145857Sumeint	getrole __P((char *));
61145857Sumeint	setnodeaddr __P((int, int, void *ptr, char *arg));
62145857Sumevoid	showpools_live __P((int, int, ipf_pool_stat_t *, char *));
63145857Sumevoid	showhashs_live __P((int, int, iphtstat_t *, char *));
64145857Sumevoid	showdstls_live __P((int, int, ipf_dstl_stat_t *, char *));
65145857Sume
66145857Sumeint	opts = 0;
67145857Sumeint	fd = -1;
68145857Sumeint	use_inet6 = 0;
69145857Sumewordtab_t *pool_fields = NULL;
70145857Sumeint	nohdrfields = 0;
71145857Sume
72145857Sume
73145857Sumevoid
74145857Sumeusage(prog)
75145857Sume	char *prog;
76145857Sume{
77292317Sngie	fprintf(stderr, "Usage:\t%s\n", prog);
78145857Sume	fprintf(stderr, "\t-a [-dnv] [-m <name>] [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n");
79145857Sume	fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
80145857Sume	fprintf(stderr, "\t-f <file> [-dnuv]\n");
81145857Sume	fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n");
82291362Sngie	fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-O <fields>]\n");
83291362Sngie	fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n");
84291362Sngie	fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
85145857Sume	fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
86291362Sngie	exit(1);
87145857Sume}
88145857Sume
89145857Sume
90145857Sumeint
91145857Sumemain(argc, argv)
92145857Sume	int argc;
93145860Sume	char *argv[];
94145860Sume{
95145860Sume	int err = 1;
96145860Sume
97145860Sume	if (argc < 2)
98145860Sume		usage(argv[0]);
99145860Sume
100145860Sume	assigndefined(getenv("IPPOOL_PREDEFINED"));
101145860Sume
102145860Sume	switch (getopt(argc, argv, "aAf:FlnrRsv"))
103145860Sume	{
104145860Sume	case 'a' :
105145860Sume		err = poolnodecommand(0, argc, argv);
106292317Sngie		break;
107292317Sngie	case 'A' :
108292317Sngie		err = poolcommand(0, argc, argv);
109292317Sngie		break;
110145860Sume	case 'f' :
111145860Sume		err = loadpoolfile(argc, argv, optarg);
112145860Sume		break;
113145860Sume	case 'F' :
114292317Sngie		err = poolflush(argc, argv);
115292317Sngie		break;
116292317Sngie	case 'l' :
117145860Sume		err = poollist(argc, argv);
118145860Sume		break;
119145860Sume	case 'n' :
120145860Sume		opts |= OPT_DONOTHING|OPT_DONTOPEN;
121145860Sume		break;
122145860Sume	case 'r' :
123145860Sume		err = poolnodecommand(1, argc, argv);
124145860Sume		break;
125145860Sume	case 'R' :
126145860Sume		err = poolcommand(1, argc, argv);
127145860Sume		break;
128145860Sume	case 's' :
129145860Sume		err = poolstats(argc, argv);
130145860Sume		break;
131292317Sngie	case 'v' :
132292317Sngie		opts |= OPT_VERBOSE;
133292317Sngie		break;
134292317Sngie	default :
135145860Sume		exit(1);
136145860Sume	}
137292317Sngie
138145860Sume	if (err != 0)
139145860Sume		exit(1);
140145860Sume	return 0;
141145860Sume}
142145860Sume
143145860Sume
144145860Sumeint
145145860Sumepoolnodecommand(remove, argc, argv)
146145860Sume	int remove, argc;
147145860Sume	char *argv[];
148145860Sume{
149145860Sume	int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
150145860Sume	char *poolname = NULL;
151145860Sume	ip_pool_node_t pnode;
152145860Sume	iphtent_t hnode;
153145860Sume	void *ptr = &pnode;
154292317Sngie
155292317Sngie	ipset = 0;
156292317Sngie	role = IPL_LOGIPF;
157292317Sngie	bzero((char *)&pnode, sizeof(pnode));
158145860Sume	bzero((char *)&hnode, sizeof(hnode));
159145860Sume
160145860Sume	while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1)
161292317Sngie		switch (c)
162145860Sume		{
163145860Sume		case 'd' :
164145860Sume			opts |= OPT_DEBUG;
165145860Sume			ippool_yydebug++;
166145860Sume			break;
167145860Sume		case 'i' :
168145860Sume			if (setnodeaddr(type, role, ptr, optarg) == 0)
169145860Sume				ipset = 1;
170145860Sume			break;
171145860Sume		case 'm' :
172145860Sume			poolname = optarg;
173145860Sume			break;
174145857Sume		case 'n' :
175145857Sume			opts |= OPT_DONOTHING|OPT_DONTOPEN;
176145857Sume			break;
177145857Sume		case 'o' :
178145857Sume			if (ipset == 1) {
179145857Sume				fprintf(stderr,
180145857Sume					"cannot set role after ip address\n");
181145860Sume				return -1;
182145857Sume			}
183145860Sume			role = getrole(optarg);
184292317Sngie			if (role == IPL_LOGNONE)
185292317Sngie				return -1;
186292317Sngie			break;
187145860Sume		case 'R' :
188145860Sume			opts |= OPT_NORESOLVE;
189145860Sume			break;
190145860Sume		case 't' :
191145860Sume			if (ipset == 1) {
192145860Sume				fprintf(stderr,
193145860Sume					"cannot set type after ip address\n");
194145860Sume				return -1;
195145860Sume			}
196145860Sume			type = gettype(optarg, NULL);
197145860Sume			switch (type) {
198145860Sume			case IPLT_NONE :
199145857Sume				fprintf(stderr, "unknown type '%s'\n", optarg);
200145857Sume				return -1;
201145857Sume			case IPLT_HASH :
202145857Sume				ptr = &hnode;
203145857Sume				break;
204145857Sume			case IPLT_POOL :
205145857Sume			default :
206145857Sume				break;
207145857Sume			}
208145857Sume			break;
209145857Sume		case 'T' :
210145857Sume			ttl = atoi(optarg);
211243346Semaste			if (ttl < 0) {
212145857Sume				fprintf(stderr, "cannot set negative ttl\n");
213145857Sume				return -1;
214145857Sume			}
215145857Sume			break;
216145857Sume		case 'v' :
217145857Sume			opts |= OPT_VERBOSE;
218145857Sume			break;
219145857Sume		}
220145857Sume
221292317Sngie	if (argv[optind] != NULL && ipset == 0) {
222292317Sngie		if (setnodeaddr(type, role, ptr, argv[optind]) == 0)
223292317Sngie			ipset = 1;
224292317Sngie	}
225292317Sngie
226292317Sngie	if (opts & OPT_DEBUG)
227145857Sume		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
228145857Sume
229292317Sngie	if (ipset == 0) {
230292317Sngie		fprintf(stderr, "no IP address given with -i\n");
231145857Sume		return -1;
232145857Sume	}
233145857Sume
234145857Sume	if (poolname == NULL) {
235145857Sume		fprintf(stderr, "poolname not given with add/remove node\n");
236145857Sume		return -1;
237145857Sume	}
238145857Sume
239292317Sngie	switch (type) {
240145857Sume	case IPLT_POOL :
241292317Sngie		if (remove == 0)
242145857Sume			err = load_poolnode(role, poolname, &pnode, ttl, ioctl);
243292317Sngie		else
244292317Sngie			err = remove_poolnode(role, poolname, &pnode, ioctl);
245145857Sume		break;
246292317Sngie	case IPLT_HASH :
247292317Sngie		if (remove == 0)
248145857Sume			err = load_hashnode(role, poolname, &hnode, ttl, ioctl);
249292317Sngie		else
250292317Sngie			err = remove_hashnode(role, poolname, &hnode, ioctl);
251145857Sume		break;
252145857Sume	default :
253145857Sume		break;
254145857Sume	}
255145857Sume	return err;
256145857Sume}
257145857Sume
258145857Sume
259145857Sumeint
260145857Sumepoolcommand(remove, argc, argv)
261145857Sume	int remove, argc;
262145857Sume	char *argv[];
263145857Sume{
264145857Sume	int type, role, c, err;
265145857Sume	char *poolname;
266145857Sume	iphtable_t iph;
267145857Sume	ip_pool_t pool;
268145857Sume
269145857Sume	err = 1;
270292317Sngie	role = 0;
271145857Sume	type = 0;
272145857Sume	poolname = NULL;
273145857Sume	role = IPL_LOGIPF;
274145857Sume	bzero((char *)&iph, sizeof(iph));
275145857Sume	bzero((char *)&pool, sizeof(pool));
276145857Sume
277145857Sume	while ((c = getopt(argc, argv, "dm:no:RSv")) != -1)
278145857Sume		switch (c)
279145857Sume		{
280145857Sume		case 'd' :
281292317Sngie			opts |= OPT_DEBUG;
282292317Sngie			ippool_yydebug++;
283292317Sngie			break;
284292317Sngie		case 'm' :
285292317Sngie			poolname = optarg;
286292317Sngie			break;
287292317Sngie		case 'n' :
288292317Sngie			opts |= OPT_DONOTHING|OPT_DONTOPEN;
289292317Sngie			break;
290292317Sngie		case 'o' :
291292317Sngie			role = getrole(optarg);
292292665Sngie			if (role == IPL_LOGNONE) {
293292665Sngie				fprintf(stderr, "unknown role '%s'\n", optarg);
294304950Sngie				return -1;
295292665Sngie			}
296292317Sngie			break;
297292317Sngie		case 'R' :
298292317Sngie			opts |= OPT_NORESOLVE;
299292317Sngie			break;
300292317Sngie		case 'S' :
301292317Sngie			iph.iph_seed = atoi(optarg);
302292665Sngie			break;
303292665Sngie		case 'v' :
304304950Sngie			opts |= OPT_VERBOSE;
305292665Sngie			break;
306292317Sngie		}
307292317Sngie
308292317Sngie	if (opts & OPT_DEBUG)
309292317Sngie		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
310292317Sngie
311292317Sngie	if (poolname == NULL) {
312292665Sngie		fprintf(stderr, "poolname not given with add/remove pool\n");
313292665Sngie		return -1;
314292665Sngie	}
315304950Sngie
316292665Sngie	type = gettype(argv[optind], &iph.iph_type);
317292317Sngie	if (type == IPLT_NONE) {
318292317Sngie		fprintf(stderr, "unknown type '%s'\n", argv[optind]);
319292317Sngie		return -1;
320292317Sngie	}
321292317Sngie
322292317Sngie	if (type == IPLT_HASH) {
323292317Sngie		strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
324292317Sngie		iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
325292317Sngie		iph.iph_unit = role;
326292317Sngie	} else if (type == IPLT_POOL) {
327292317Sngie		strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
328292317Sngie		pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
329292317Sngie		pool.ipo_unit = role;
330292317Sngie	}
331292317Sngie
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