xref: /illumos-gate/usr/src/cmd/ipf/tools/ippool.c (revision e86372a01d2d16a5dd4a64e144ed978ba17fe7dd)
1 /*
2  * Copyright (C) 2003 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
7  * Use is subject to license terms.
8  *
9  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
10  * Copyright 2017 Gary Mills
11  */
12 
13 #include <sys/types.h>
14 #include <sys/time.h>
15 #include <sys/param.h>
16 #include <sys/socket.h>
17 #if defined(BSD) && (BSD >= 199306)
18 # include <sys/cdefs.h>
19 #endif
20 #include <sys/ioctl.h>
21 
22 #include <net/if.h>
23 #if __FreeBSD_version >= 300000
24 # include <net/if_var.h>
25 #endif
26 #include <netinet/in.h>
27 
28 #include <arpa/inet.h>
29 
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <netdb.h>
35 #include <ctype.h>
36 #include <unistd.h>
37 #include <nlist.h>
38 
39 #include "ipf.h"
40 #include "netinet/ipl.h"
41 #include "netinet/ip_lookup.h"
42 #include "netinet/ip_pool.h"
43 #include "netinet/ip_htable.h"
44 #include "kmem.h"
45 #include "ipfzone.h"
46 
47 extern	int	ippool_yyparse __P((void));
48 extern	int	ippool_yydebug;
49 extern	FILE	*ippool_yyin;
50 extern	char	*optarg;
51 extern	int	lineNum;
52 
53 void	showpools __P((ip_pool_stat_t *));
54 void	usage __P((char *));
55 int	main __P((int, char **));
56 int	poolcommand __P((int, int, char *[]));
57 int	poolnodecommand __P((int, int, char *[]));
58 int	loadpoolfile __P((int, char *[], char *));
59 int	poollist __P((int, char *[]));
60 int	poolflush __P((int, char *[]));
61 int	poolstats __P((int, char *[]));
62 int	gettype __P((char *, u_int *));
63 int	getrole __P((char *));
64 void	poollist_dead __P((int, char *, int, char *, char *));
65 void	showpools_live(int, int, ip_pool_stat_t *, char *, int);
66 void	showhashs_live(int, int, iphtstat_t *, char *, int);
67 
68 int	opts = 0;
69 int	fd = -1;
70 int	use_inet6 = 0;
71 
72 
73 void usage(prog)
74 char *prog;
75 {
76 	const char *zoneopt = "[-G|-z zonename] ";
77 	fprintf(stderr, "Usage:\t%s\n", prog);
78 	fprintf(stderr, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
79 	    zoneopt);
80 	fprintf(stderr, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n",
81 	    zoneopt);
82 	fprintf(stderr, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt);
83 	fprintf(stderr, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt);
84 	fprintf(stderr, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt);
85 	fprintf(stderr, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
86 	    zoneopt);
87 	fprintf(stderr, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n",
88 	    zoneopt);
89 	fprintf(stderr, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n",
90 	    zoneopt);
91 	exit(1);
92 }
93 
94 
95 int main(argc, argv)
96 int argc;
97 char *argv[];
98 {
99 	int err;
100 
101 	if (argc < 2)
102 		usage(argv[0]);
103 
104 	switch (getopt(argc, argv, "aAf:FlrRs"))
105 	{
106 	case 'a' :
107 		err = poolnodecommand(0, argc, argv);
108 		break;
109 	case 'A' :
110 		err = poolcommand(0, argc, argv);
111 		break;
112 	case 'f' :
113 		err = loadpoolfile(argc, argv, optarg);
114 		break;
115 	case 'F' :
116 		err = poolflush(argc, argv);
117 		break;
118 	case 'l' :
119 		err = poollist(argc, argv);
120 		break;
121 	case 'r' :
122 		err = poolnodecommand(1, argc, argv);
123 		break;
124 	case 'R' :
125 		err = poolcommand(1, argc, argv);
126 		break;
127 	case 's' :
128 		err = poolstats(argc, argv);
129 		break;
130 	default :
131 		exit(1);
132 	}
133 
134 	return err;
135 }
136 
137 
138 int poolnodecommand(remove, argc, argv)
139 int remove, argc;
140 char *argv[];
141 {
142 	char *poolname = NULL, *s;
143 	int err, c, ipset, role;
144 	ip_pool_node_t node;
145 	struct in_addr mask;
146 
147 	ipset = 0;
148 	role = IPL_LOGIPF;
149 	bzero((char *)&node, sizeof(node));
150 
151 	while ((c = getopt(argc, argv, "di:G:m:no:Rvz:")) != -1)
152 		switch (c)
153 		{
154 		case 'd' :
155 			opts |= OPT_DEBUG;
156 			ippool_yydebug++;
157 			break;
158 		case 'G' :
159 			setzonename_global(optarg);
160 			break;
161 		case 'i' :
162 			s = strchr(optarg, '/');
163 			if (s == NULL)
164 				mask.s_addr = 0xffffffff;
165 			else if (strchr(s, '.') == NULL) {
166 				if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
167 					return -1;
168 			} else {
169 				mask.s_addr = inet_addr(s + 1);
170 			}
171 			if (s != NULL)
172 				*s = '\0';
173 			ipset = 1;
174 			node.ipn_addr.adf_len = sizeof(node.ipn_addr);
175 			node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg);
176 			node.ipn_mask.adf_len = sizeof(node.ipn_mask);
177 			node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
178 			break;
179 		case 'm' :
180 			poolname = optarg;
181 			break;
182 		case 'n' :
183 			opts |= OPT_DONOTHING;
184 			break;
185 		case 'o' :
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 'v' :
194 			opts |= OPT_VERBOSE;
195 			break;
196 		case 'z' :
197 			setzonename(optarg);
198 			break;
199 		}
200 
201 	if (opts & OPT_DEBUG)
202 		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
203 
204 	if (ipset == 0)
205 		return -1;
206 	if (poolname == NULL) {
207 		fprintf(stderr, "poolname not given with add/remove node\n");
208 		return -1;
209 	}
210 
211 	if (remove == 0)
212 		err = load_poolnode(0, poolname, &node, ioctl);
213 	else
214 		err = remove_poolnode(0, poolname, &node, ioctl);
215 	return err;
216 }
217 
218 
219 int poolcommand(remove, argc, argv)
220 int remove, argc;
221 char *argv[];
222 {
223 	int type, role, c, err;
224 	char *poolname;
225 	iphtable_t iph;
226 	ip_pool_t pool;
227 
228 	err = 1;
229 	role = 0;
230 	type = 0;
231 	poolname = NULL;
232 	role = IPL_LOGIPF;
233 	bzero((char *)&iph, sizeof(iph));
234 	bzero((char *)&pool, sizeof(pool));
235 
236 	while ((c = getopt(argc, argv, "dG:m:no:RS:t:vz:")) != -1)
237 		switch (c)
238 		{
239 		case 'd' :
240 			opts |= OPT_DEBUG;
241 			ippool_yydebug++;
242 			break;
243 		case 'G' :
244 			setzonename_global(optarg);
245 			break;
246 		case 'm' :
247 			poolname = optarg;
248 			break;
249 		case 'n' :
250 			opts |= OPT_DONOTHING;
251 			break;
252 		case 'o' :
253 			role = getrole(optarg);
254 			if (role == IPL_LOGNONE) {
255 				fprintf(stderr, "unknown role '%s'\n", optarg);
256 				return -1;
257 			}
258 			break;
259 		case 'R' :
260 			opts |= OPT_NORESOLVE;
261 			break;
262 		case 'S' :
263 			iph.iph_seed = atoi(optarg);
264 			break;
265 		case 't' :
266 			type = gettype(optarg, &iph.iph_type);
267 			if (type == IPLT_NONE) {
268 				fprintf(stderr, "unknown type '%s'\n", optarg);
269 				return -1;
270 			}
271 			break;
272 		case 'v' :
273 			opts |= OPT_VERBOSE;
274 			break;
275 		case 'z' :
276 			setzonename(optarg);
277 			break;
278 		}
279 
280 	if (opts & OPT_DEBUG)
281 		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
282 
283 	if (poolname == NULL) {
284 		fprintf(stderr, "poolname not given with add/remove pool\n");
285 		return -1;
286 	}
287 
288 	if (type == IPLT_HASH) {
289 		strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
290 		iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
291 		iph.iph_unit = role;
292 	} else if (type == IPLT_POOL) {
293 		strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
294 		pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
295 		pool.ipo_unit = role;
296 	}
297 
298 	if (remove == 0) {
299 		switch (type)
300 		{
301 		case IPLT_HASH :
302 			err = load_hash(&iph, NULL, ioctl);
303 			break;
304 		case IPLT_POOL :
305 			err = load_pool(&pool, ioctl);
306 			break;
307 		}
308 	} else {
309 		switch (type)
310 		{
311 		case IPLT_HASH :
312 			err = remove_hash(&iph, ioctl);
313 			break;
314 		case IPLT_POOL :
315 			err = remove_pool(&pool, ioctl);
316 			break;
317 		}
318 	}
319 	return err;
320 }
321 
322 
323 int loadpoolfile(argc, argv, infile)
324 int argc;
325 char *argv[], *infile;
326 {
327 	int c;
328 
329 	infile = optarg;
330 
331 	while ((c = getopt(argc, argv, "dG:nRuvz:")) != -1)
332 		switch (c)
333 		{
334 		case 'd' :
335 			opts |= OPT_DEBUG;
336 			ippool_yydebug++;
337 			break;
338 		case 'G' :
339 			setzonename_global(optarg);
340 			break;
341 		case 'n' :
342 			opts |= OPT_DONOTHING;
343 			break;
344 		case 'R' :
345 			opts |= OPT_NORESOLVE;
346 			break;
347 		case 'u' :
348 			opts |= OPT_REMOVE;
349 			break;
350 		case 'v' :
351 			opts |= OPT_VERBOSE;
352 			break;
353 		case 'z' :
354 			setzonename(optarg);
355 			break;
356 		}
357 
358 	if (opts & OPT_DEBUG)
359 		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
360 
361 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
362 		fd = open(IPLOOKUP_NAME, O_RDWR);
363 		if (fd == -1) {
364 			perror("open(IPLOOKUP_NAME)");
365 			exit(1);
366 		}
367 
368 		if (setzone(fd) != 0) {
369 			close(fd);
370 			exit(1);
371 		}
372 	}
373 
374 	if (ippool_parsefile(fd, infile, ioctl) != 0)
375 		return -1;
376 	return 0;
377 }
378 
379 
380 int poollist(argc, argv)
381 int argc;
382 char *argv[];
383 {
384 	char *kernel, *core, *poolname;
385 	int c, role, type, live_kernel;
386 	ip_pool_stat_t  plstat;
387 	iphtstat_t  htstat;
388 	iphtable_t *hptr;
389 	iplookupop_t op;
390 	ip_pool_t *ptr;
391 
392 	core = NULL;
393 	kernel = NULL;
394 	live_kernel = 1;
395 	type = IPLT_ALL;
396 	poolname = NULL;
397 	role = IPL_LOGALL;
398 
399 	while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1)
400 		switch (c)
401 		{
402 		case 'd' :
403 			opts |= OPT_DEBUG;
404 			break;
405 		case 'G' :
406 			setzonename_global(optarg);
407 			break;
408 		case 'm' :
409 			poolname = optarg;
410 			break;
411 		case 'M' :
412 			live_kernel = 0;
413 			core = optarg;
414 			break;
415 		case 'N' :
416 			live_kernel = 0;
417 			kernel = optarg;
418 			break;
419 		case 'o' :
420 			role = getrole(optarg);
421 			if (role == IPL_LOGNONE) {
422 				fprintf(stderr, "unknown role '%s'\n", optarg);
423 				return -1;
424 			}
425 			break;
426 		case 'R' :
427 			opts |= OPT_NORESOLVE;
428 			break;
429 		case 't' :
430 			type = gettype(optarg, NULL);
431 			if (type == IPLT_NONE) {
432 				fprintf(stderr, "unknown type '%s'\n", optarg);
433 				return -1;
434 			}
435 			break;
436 		case 'v' :
437 			opts |= OPT_VERBOSE;
438 			break;
439 		case 'z' :
440 			setzonename(optarg);
441 			break;
442 		}
443 
444 	if (opts & OPT_DEBUG)
445 		fprintf(stderr, "poollist: opts = %#x\n", opts);
446 
447 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
448 		fd = open(IPLOOKUP_NAME, O_RDWR);
449 		if (fd == -1) {
450 			perror("open(IPLOOKUP_NAME)");
451 			exit(1);
452 		}
453 
454 		if (setzone(fd) != 0) {
455 			close(fd);
456 			exit(1);
457 		}
458 	}
459 
460 	bzero((char *)&op, sizeof(op));
461 	if (poolname != NULL) {
462 		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
463 		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
464 	}
465 	op.iplo_unit = role;
466 
467 	if (live_kernel == 0) {
468 		poollist_dead(role, poolname, type, kernel, core);
469 		return (0);
470 	}
471 
472 	if (type == IPLT_ALL || type == IPLT_POOL) {
473 		op.iplo_type = IPLT_POOL;
474 		op.iplo_size = sizeof(plstat);
475 		op.iplo_struct = &plstat;
476 		op.iplo_name[0] = '\0';
477 		op.iplo_arg = 0;
478 
479 		if (role != IPL_LOGALL) {
480 			op.iplo_unit = role;
481 
482 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
483 			if (c == -1) {
484 				perror("ioctl(SIOCLOOKUPSTAT)");
485 				return -1;
486 			}
487 
488 			showpools_live(fd, role, &plstat, poolname, opts);
489 		} else {
490 			for (role = 0; role <= IPL_LOGMAX; role++) {
491 				op.iplo_unit = role;
492 
493 				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
494 				if (c == -1) {
495 					perror("ioctl(SIOCLOOKUPSTAT)");
496 					return -1;
497 				}
498 
499 				showpools_live(fd, role, &plstat, poolname, opts);
500 			}
501 
502 			role = IPL_LOGALL;
503 		}
504 	}
505 	if (type == IPLT_ALL || type == IPLT_HASH) {
506 		op.iplo_type = IPLT_HASH;
507 		op.iplo_size = sizeof(htstat);
508 		op.iplo_struct = &htstat;
509 		op.iplo_name[0] = '\0';
510 		op.iplo_arg = 0;
511 
512 		if (role != IPL_LOGALL) {
513 			op.iplo_unit = role;
514 
515 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
516 			if (c == -1) {
517 				perror("ioctl(SIOCLOOKUPSTAT)");
518 				return -1;
519 			}
520 			showhashs_live(fd, role, &htstat, poolname, opts);
521 		} else {
522 			for (role = 0; role <= IPL_LOGMAX; role++) {
523 
524 				op.iplo_unit = role;
525 				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
526 				if (c == -1) {
527 					perror("ioctl(SIOCLOOKUPSTAT)");
528 					return -1;
529 				}
530 
531 				showhashs_live(fd, role, &htstat, poolname, opts);
532 			}
533 		}
534 	}
535 	return 0;
536 }
537 
538 void poollist_dead(role, poolname, type, kernel, core)
539 int role, type;
540 char *poolname, *kernel, *core;
541 {
542 	iphtable_t *hptr;
543 	ip_pool_t *ptr;
544 
545 	if (openkmem(kernel, core) == -1)
546 		exit(-1);
547 
548 	if (type == IPLT_ALL || type == IPLT_POOL) {
549 		ip_pool_t *pools[IPL_LOGSIZE];
550 		struct nlist names[2] = { { "ip_pool_list" } , { "" } };
551 
552 		if (nlist(kernel, names) != 1)
553 			return;
554 
555 		bzero(&pools, sizeof(pools));
556 		if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
557 			return;
558 
559 		if (role != IPL_LOGALL) {
560 			ptr = pools[role];
561 			while (ptr != NULL) {
562 				ptr = printpool(ptr, kmemcpywrap,
563 						poolname, opts);
564 			}
565 		} else {
566 			for (role = 0; role <= IPL_LOGMAX; role++) {
567 				ptr = pools[role];
568 				while (ptr != NULL) {
569 					ptr = printpool(ptr, kmemcpywrap,
570 							poolname, opts);
571 				}
572 			}
573 			role = IPL_LOGALL;
574 		}
575 	}
576 	if (type == IPLT_ALL || type == IPLT_HASH) {
577 		iphtable_t *tables[IPL_LOGSIZE];
578 		struct nlist names[2] = { { "ipf_htables" } , { "" } };
579 
580 		if (nlist(kernel, names) != 1)
581 			return;
582 
583 		bzero(&tables, sizeof(tables));
584 		if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
585 			return;
586 
587 		if (role != IPL_LOGALL) {
588 			hptr = tables[role];
589 			while (hptr != NULL) {
590 				hptr = printhash(hptr, kmemcpywrap,
591 						 poolname, opts);
592 			}
593 		} else {
594 			for (role = 0; role <= IPL_LOGMAX; role++) {
595 				hptr = tables[role];
596 				while (hptr != NULL) {
597 					hptr = printhash(hptr, kmemcpywrap,
598 							 poolname, opts);
599 				}
600 			}
601 		}
602 	}
603 }
604 
605 
606 void
607 showpools_live(fd, role, plstp, poolname, opts)
608 int fd, role;
609 ip_pool_stat_t *plstp;
610 char *poolname;
611 int opts;
612 {
613 	ipflookupiter_t iter;
614 	ip_pool_t pool;
615 	ipfobj_t obj;
616 
617 	obj.ipfo_rev = IPFILTER_VERSION;
618 	obj.ipfo_type = IPFOBJ_LOOKUPITER;
619 	obj.ipfo_size = sizeof(iter);
620 	obj.ipfo_ptr = &iter;
621 
622 	iter.ili_type = IPLT_POOL;
623 	iter.ili_otype = IPFLOOKUPITER_LIST;
624 	iter.ili_ival = IPFGENITER_LOOKUP;
625 	iter.ili_data = &pool;
626 	iter.ili_unit = role;
627 	*iter.ili_name = '\0';
628 
629 	while (plstp->ipls_list[role] != NULL) {
630 		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
631 			perror("ioctl(SIOCLOOKUPITER)");
632 			break;
633 		}
634 		(void) printpool_live(&pool, fd, poolname, opts);
635 
636 		plstp->ipls_list[role] = pool.ipo_next;
637 	}
638 }
639 
640 int poolstats(argc, argv)
641 int argc;
642 char *argv[];
643 {
644 	int c, type, role;
645 	ip_pool_stat_t plstat;
646 	iphtstat_t htstat;
647 	iplookupop_t op;
648 
649 	type = IPLT_ALL;
650 	role = IPL_LOGALL;
651 
652 	bzero((char *)&op, sizeof(op));
653 
654 	while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1)
655 		switch (c)
656 		{
657 		case 'd' :
658 			opts |= OPT_DEBUG;
659 			break;
660 		case 'G' :
661 			setzonename_global(optarg);
662 			break;
663 		case 'M' :
664 			break;
665 		case 'N' :
666 			break;
667 		case 'o' :
668 			role = getrole(optarg);
669 			if (role == IPL_LOGNONE) {
670 				fprintf(stderr, "unknown role '%s'\n", optarg);
671 				return -1;
672 			}
673 			break;
674 		case 't' :
675 			type = gettype(optarg, NULL);
676 			if (type != IPLT_POOL) {
677 				fprintf(stderr,
678 					"-s not supported for this type yet\n");
679 				return -1;
680 			}
681 			break;
682 		case 'v' :
683 			opts |= OPT_VERBOSE;
684 			break;
685 		case 'z' :
686 			setzonename(optarg);
687 			break;
688 		}
689 
690 	if (opts & OPT_DEBUG)
691 		fprintf(stderr, "poolstats: opts = %#x\n", opts);
692 
693 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
694 		fd = open(IPLOOKUP_NAME, O_RDWR);
695 		if (fd == -1) {
696 			perror("open(IPLOOKUP_NAME)");
697 			exit(1);
698 		}
699 
700 		if (setzone(fd) != 0) {
701 			close(fd);
702 			exit(1);
703 		}
704 	}
705 
706 	if (type == IPLT_ALL || type == IPLT_POOL) {
707 		op.iplo_type = IPLT_POOL;
708 		op.iplo_struct = &plstat;
709 		op.iplo_size = sizeof(plstat);
710 		if (!(opts & OPT_DONOTHING)) {
711 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
712 			if (c == -1) {
713 				perror("ioctl(SIOCLOOKUPSTAT)");
714 				return -1;
715 			}
716 			printf("Pools:\t%lu\n", plstat.ipls_pools);
717 			printf("Nodes:\t%lu\n", plstat.ipls_nodes);
718 		}
719 	}
720 
721 	if (type == IPLT_ALL || type == IPLT_HASH) {
722 		op.iplo_type = IPLT_HASH;
723 		op.iplo_struct = &htstat;
724 		op.iplo_size = sizeof(htstat);
725 		if (!(opts & OPT_DONOTHING)) {
726 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
727 			if (c == -1) {
728 				perror("ioctl(SIOCLOOKUPSTAT)");
729 				return -1;
730 			}
731 			printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
732 			printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
733 			printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
734 		}
735 	}
736 	return 0;
737 }
738 
739 
740 int poolflush(argc, argv)
741 int argc;
742 char *argv[];
743 {
744 	int c, role, type, arg;
745 	iplookupflush_t flush;
746 
747 	arg = IPLT_ALL;
748 	type = IPLT_ALL;
749 	role = IPL_LOGALL;
750 
751 	while ((c = getopt(argc, argv, "do:t:vz:")) != -1)
752 		switch (c)
753 		{
754 		case 'd' :
755 			opts |= OPT_DEBUG;
756 			break;
757 		case 'o' :
758 			role = getrole(optarg);
759 			if (role == IPL_LOGNONE) {
760 				fprintf(stderr, "unknown role '%s'\n", optarg);
761 				return -1;
762 			}
763 			break;
764 		case 't' :
765 			type = gettype(optarg, NULL);
766 			if (type == IPLT_NONE) {
767 				fprintf(stderr, "unknown type '%s'\n", optarg);
768 				return -1;
769 			}
770 			break;
771 		case 'v' :
772 			opts |= OPT_VERBOSE;
773 			break;
774 		case 'z' :
775 			setzonename(optarg);
776 			break;
777 		}
778 
779 	if (opts & OPT_DEBUG)
780 		fprintf(stderr, "poolflush: opts = %#x\n", opts);
781 
782 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
783 		fd = open(IPLOOKUP_NAME, O_RDWR);
784 		if (fd == -1) {
785 			perror("open(IPLOOKUP_NAME)");
786 			exit(1);
787 		}
788 
789 		if (setzone(fd) != 0) {
790 			close(fd);
791 			exit(1);
792 		}
793 	}
794 
795 	bzero((char *)&flush, sizeof(flush));
796 	flush.iplf_type = type;
797 	flush.iplf_unit = role;
798 	flush.iplf_arg = arg;
799 
800 	if (!(opts & OPT_DONOTHING)) {
801 		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
802 			perror("ioctl(SIOCLOOKUPFLUSH)");
803 			exit(1);
804 		}
805 
806 	}
807 	printf("%u object%s flushed\n", flush.iplf_count,
808 	       (flush.iplf_count == 1) ? "" : "s");
809 
810 	return 0;
811 }
812 
813 
814 int getrole(rolename)
815 char *rolename;
816 {
817 	int role;
818 
819 	if (!strcasecmp(rolename, "ipf")) {
820 		role = IPL_LOGIPF;
821 #if 0
822 	} else if (!strcasecmp(rolename, "nat")) {
823 		role = IPL_LOGNAT;
824 	} else if (!strcasecmp(rolename, "state")) {
825 		role = IPL_LOGSTATE;
826 	} else if (!strcasecmp(rolename, "auth")) {
827 		role = IPL_LOGAUTH;
828 	} else if (!strcasecmp(rolename, "sync")) {
829 		role = IPL_LOGSYNC;
830 	} else if (!strcasecmp(rolename, "scan")) {
831 		role = IPL_LOGSCAN;
832 	} else if (!strcasecmp(rolename, "pool")) {
833 		role = IPL_LOGLOOKUP;
834 	} else if (!strcasecmp(rolename, "count")) {
835 		role = IPL_LOGCOUNT;
836 #endif
837 	} else {
838 		role = IPL_LOGNONE;
839 	}
840 
841 	return role;
842 }
843 
844 
845 int gettype(typename, minor)
846 char *typename;
847 u_int *minor;
848 {
849 	int type;
850 
851 	if (!strcasecmp(optarg, "tree")) {
852 		type = IPLT_POOL;
853 	} else if (!strcasecmp(optarg, "hash")) {
854 		type = IPLT_HASH;
855 		if (minor != NULL)
856 			*minor = IPHASH_LOOKUP;
857 	} else if (!strcasecmp(optarg, "group-map")) {
858 		type = IPLT_HASH;
859 		if (minor != NULL)
860 			*minor = IPHASH_GROUPMAP;
861 	} else {
862 		type = IPLT_NONE;
863 	}
864 	return type;
865 }
866 
867 void showhashs_live(fd, role, htstp, poolname, opts)
868 int fd, role;
869 iphtstat_t *htstp;
870 char *poolname;
871 int opts;
872 {
873 	ipflookupiter_t iter;
874 	iphtable_t table;
875 	ipfobj_t obj;
876 
877 	obj.ipfo_rev = IPFILTER_VERSION;
878 	obj.ipfo_type = IPFOBJ_LOOKUPITER;
879 	obj.ipfo_size = sizeof(iter);
880 	obj.ipfo_ptr = &iter;
881 
882 	iter.ili_type = IPLT_HASH;
883 	iter.ili_otype = IPFLOOKUPITER_LIST;
884 	iter.ili_ival = IPFGENITER_LOOKUP;
885 	iter.ili_data = &table;
886 	iter.ili_unit = role;
887 	*iter.ili_name = '\0';
888 
889 	while (htstp->iphs_tables != NULL) {
890 		if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
891 			perror("ioctl(SIOCLOOKUPITER)");
892 			break;
893 		}
894 
895 		printhash_live(&table, fd, poolname, opts);
896 
897 		htstp->iphs_tables = table.iph_next;
898 	}
899 }
900