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>] [-O <fields>]\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:FlnrRsv"))
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 'n' :
120 		opts |= OPT_DONOTHING|OPT_DONTOPEN;
121 		break;
122 	case 'r' :
123 		err = poolnodecommand(1, argc, argv);
124 		break;
125 	case 'R' :
126 		err = poolcommand(1, argc, argv);
127 		break;
128 	case 's' :
129 		err = poolstats(argc, argv);
130 		break;
131 	case 'v' :
132 		opts |= OPT_VERBOSE;
133 		break;
134 	default :
135 		exit(1);
136 	}
137 
138 	if (err != 0)
139 		exit(1);
140 	return 0;
141 }
142 
143 
144 int
145 poolnodecommand(remove, argc, argv)
146 	int remove, argc;
147 	char *argv[];
148 {
149 	int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0;
150 	char *poolname = NULL;
151 	ip_pool_node_t pnode;
152 	iphtent_t hnode;
153 	void *ptr = &pnode;
154 
155 	ipset = 0;
156 	role = IPL_LOGIPF;
157 	bzero((char *)&pnode, sizeof(pnode));
158 	bzero((char *)&hnode, sizeof(hnode));
159 
160 	while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1)
161 		switch (c)
162 		{
163 		case 'd' :
164 			opts |= OPT_DEBUG;
165 			ippool_yydebug++;
166 			break;
167 		case 'i' :
168 			if (setnodeaddr(type, role, ptr, optarg) == 0)
169 				ipset = 1;
170 			break;
171 		case 'm' :
172 			poolname = optarg;
173 			break;
174 		case 'n' :
175 			opts |= OPT_DONOTHING|OPT_DONTOPEN;
176 			break;
177 		case 'o' :
178 			if (ipset == 1) {
179 				fprintf(stderr,
180 					"cannot set role after ip address\n");
181 				return -1;
182 			}
183 			role = getrole(optarg);
184 			if (role == IPL_LOGNONE)
185 				return -1;
186 			break;
187 		case 'R' :
188 			opts |= OPT_NORESOLVE;
189 			break;
190 		case 't' :
191 			if (ipset == 1) {
192 				fprintf(stderr,
193 					"cannot set type after ip address\n");
194 				return -1;
195 			}
196 			type = gettype(optarg, NULL);
197 			switch (type) {
198 			case IPLT_NONE :
199 				fprintf(stderr, "unknown type '%s'\n", optarg);
200 				return -1;
201 			case IPLT_HASH :
202 				ptr = &hnode;
203 				break;
204 			case IPLT_POOL :
205 			default :
206 				break;
207 			}
208 			break;
209 		case 'T' :
210 			ttl = atoi(optarg);
211 			if (ttl < 0) {
212 				fprintf(stderr, "cannot set negative ttl\n");
213 				return -1;
214 			}
215 			break;
216 		case 'v' :
217 			opts |= OPT_VERBOSE;
218 			break;
219 		}
220 
221 	if (argv[optind] != NULL && ipset == 0) {
222 		if (setnodeaddr(type, role, ptr, argv[optind]) == 0)
223 			ipset = 1;
224 	}
225 
226 	if (opts & OPT_DEBUG)
227 		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
228 
229 	if (ipset == 0) {
230 		fprintf(stderr, "no IP address given with -i\n");
231 		return -1;
232 	}
233 
234 	if (poolname == NULL) {
235 		fprintf(stderr, "poolname not given with add/remove node\n");
236 		return -1;
237 	}
238 
239 	switch (type) {
240 	case IPLT_POOL :
241 		if (remove == 0)
242 			err = load_poolnode(role, poolname, &pnode, ttl, ioctl);
243 		else
244 			err = remove_poolnode(role, poolname, &pnode, ioctl);
245 		break;
246 	case IPLT_HASH :
247 		if (remove == 0)
248 			err = load_hashnode(role, poolname, &hnode, ttl, ioctl);
249 		else
250 			err = remove_hashnode(role, poolname, &hnode, ioctl);
251 		break;
252 	default :
253 		break;
254 	}
255 	return err;
256 }
257 
258 
259 int
260 poolcommand(remove, argc, argv)
261 	int remove, argc;
262 	char *argv[];
263 {
264 	int type, role, c, err;
265 	char *poolname;
266 	iphtable_t iph;
267 	ip_pool_t pool;
268 
269 	err = 1;
270 	role = 0;
271 	type = 0;
272 	poolname = NULL;
273 	role = IPL_LOGIPF;
274 	bzero((char *)&iph, sizeof(iph));
275 	bzero((char *)&pool, sizeof(pool));
276 
277 	while ((c = getopt(argc, argv, "dm:no:RSv")) != -1)
278 		switch (c)
279 		{
280 		case 'd' :
281 			opts |= OPT_DEBUG;
282 			ippool_yydebug++;
283 			break;
284 		case 'm' :
285 			poolname = optarg;
286 			break;
287 		case 'n' :
288 			opts |= OPT_DONOTHING|OPT_DONTOPEN;
289 			break;
290 		case 'o' :
291 			role = getrole(optarg);
292 			if (role == IPL_LOGNONE) {
293 				fprintf(stderr, "unknown role '%s'\n", optarg);
294 				return -1;
295 			}
296 			break;
297 		case 'R' :
298 			opts |= OPT_NORESOLVE;
299 			break;
300 		case 'S' :
301 			iph.iph_seed = atoi(optarg);
302 			break;
303 		case 'v' :
304 			opts |= OPT_VERBOSE;
305 			break;
306 		}
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 	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 
404 int
405 poolstats(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 
527 int
528 poolflush(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 
594 int
595 getrole(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 
626 int
627 gettype(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 
650 int
651 poollist(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 
734 void
735 poollist_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 
805 void
806 poollist_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 
918 void
919 showpools_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 
957 void
958 showhashs_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 
993 void
994 showdstls_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 
1029 int
1030 setnodeaddr(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 		if (node->ipn_addr.adf_family == AF_INET)
1051 			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1052 							  adf_addr) +
1053 						 sizeof(struct in_addr);
1054 #ifdef USE_INET6
1055 		else
1056 			node->ipn_addr.adf_len = offsetof(addrfamily_t,
1057 							  adf_addr) +
1058 						 sizeof(struct in6_addr);
1059 #endif
1060 		node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
1061 		node->ipn_mask.adf_len = node->ipn_addr.adf_len;
1062 		node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
1063 	} else if (type == IPLT_HASH) {
1064 		iphtent_t *node = ptr;
1065 
1066 		node->ipe_addr.in4.s_addr = inet_addr(arg);
1067 		node->ipe_mask.in4.s_addr = mask.s_addr;
1068         	node->ipe_family = AF_INET;
1069         	node->ipe_unit = role;
1070 	}
1071 
1072 	return 0;
1073 }
1074