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