xref: /illumos-gate/usr/src/cmd/ipf/tools/ippool.c (revision 34ef97d0)
1 /*
2  * Copyright (C) 2003 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
7  * Use is subject to license terms.
8  */
9 
10 #pragma ident	"%Z%%M%	%I%	%E% SMI"
11 
12 #include <sys/types.h>
13 #include <sys/time.h>
14 #include <sys/param.h>
15 #include <sys/socket.h>
16 #if defined(BSD) && (BSD >= 199306)
17 # include <sys/cdefs.h>
18 #endif
19 #include <sys/ioctl.h>
20 
21 #include <net/if.h>
22 #if __FreeBSD_version >= 300000
23 # include <net/if_var.h>
24 #endif
25 #include <netinet/in.h>
26 
27 #include <arpa/inet.h>
28 
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <netdb.h>
34 #include <ctype.h>
35 #include <unistd.h>
36 
37 #include "ipf.h"
38 #include "netinet/ip_lookup.h"
39 #include "netinet/ip_pool.h"
40 #include "netinet/ip_htable.h"
41 #include "kmem.h"
42 
43 
44 extern	int	ippool_yyparse __P((void));
45 extern	int	ippool_yydebug;
46 extern	FILE	*ippool_yyin;
47 extern	char	*optarg;
48 extern	int	lineNum;
49 
50 void	showpools __P((ip_pool_stat_t *));
51 void	usage __P((char *));
52 int	main __P((int, char **));
53 int	poolcommand __P((int, int, char *[]));
54 int	poolnodecommand __P((int, int, char *[]));
55 int	loadpoolfile __P((int, char *[], char *));
56 int	poollist __P((int, char *[]));
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 
62 int	opts = 0;
63 int	fd = -1;
64 int	use_inet6 = 0;
65 
66 
67 void usage(prog)
68 char *prog;
69 {
70 	fprintf(stderr, "Usage:\t%s\n", prog);
71 	fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
72 	fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
73 	fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n");
74 	fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
75 	fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
76 	fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
77 	fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
78 	fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
79 	exit(1);
80 }
81 
82 
83 int main(argc, argv)
84 int argc;
85 char *argv[];
86 {
87 	int err;
88 
89 	if (argc < 2)
90 		usage(argv[0]);
91 
92 	switch (getopt(argc, argv, "aAf:FlrRs"))
93 	{
94 	case 'a' :
95 		err = poolnodecommand(0, argc, argv);
96 		break;
97 	case 'A' :
98 		err = poolcommand(0, argc, argv);
99 		break;
100 	case 'f' :
101 		err = loadpoolfile(argc, argv, optarg);
102 		break;
103 	case 'F' :
104 		err = poolflush(argc, argv);
105 		break;
106 	case 'l' :
107 		err = poollist(argc, argv);
108 		break;
109 	case 'r' :
110 		err = poolnodecommand(1, argc, argv);
111 		break;
112 	case 'R' :
113 		err = poolcommand(1, argc, argv);
114 		break;
115 	case 's' :
116 		err = poolstats(argc, argv);
117 		break;
118 	default :
119 		exit(1);
120 	}
121 
122 	return err;
123 }
124 
125 
126 int poolnodecommand(remove, argc, argv)
127 int remove, argc;
128 char *argv[];
129 {
130 	char *poolname = NULL, *s;
131 	int err, c, ipset, role;
132 	ip_pool_node_t node;
133 	struct in_addr mask;
134 
135 	ipset = 0;
136 	role = IPL_LOGIPF;
137 	bzero((char *)&node, sizeof(node));
138 
139 	while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
140 		switch (c)
141 		{
142 		case 'd' :
143 			opts |= OPT_DEBUG;
144 			ippool_yydebug++;
145 			break;
146 		case 'i' :
147 			s = strchr(optarg, '/');
148 			if (s == NULL)
149 				mask.s_addr = 0xffffffff;
150 			else if (strchr(s, '.') == NULL) {
151 				if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
152 					return -1;
153 			} else {
154 				mask.s_addr = inet_addr(s + 1);
155 			}
156 			if (s != NULL)
157 				*s = '\0';
158 			ipset = 1;
159 			node.ipn_addr.adf_len = sizeof(node.ipn_addr);
160 			node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg);
161 			node.ipn_mask.adf_len = sizeof(node.ipn_mask);
162 			node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
163 			break;
164 		case 'm' :
165 			poolname = optarg;
166 			break;
167 		case 'n' :
168 			opts |= OPT_DONOTHING;
169 			break;
170 		case 'o' :
171 			role = getrole(optarg);
172 			if (role == IPL_LOGNONE)
173 				return -1;
174 			break;
175 		case 'R' :
176 			opts |= OPT_NORESOLVE;
177 			break;
178 		case 'v' :
179 			opts |= OPT_VERBOSE;
180 			break;
181 		}
182 
183 	if (opts & OPT_DEBUG)
184 		fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
185 
186 	if (ipset == 0)
187 		return -1;
188 	if (poolname == NULL) {
189 		fprintf(stderr, "poolname not given with add/remove node\n");
190 		return -1;
191 	}
192 
193 	if (remove == 0)
194 		err = load_poolnode(0, poolname, &node, ioctl);
195 	else
196 		err = remove_poolnode(0, poolname, &node, ioctl);
197 	return err;
198 }
199 
200 
201 int poolcommand(remove, argc, argv)
202 int remove, argc;
203 char *argv[];
204 {
205 	int type, role, c, err;
206 	char *poolname;
207 	iphtable_t iph;
208 	ip_pool_t pool;
209 
210 	err = 1;
211 	role = 0;
212 	type = 0;
213 	poolname = NULL;
214 	role = IPL_LOGIPF;
215 	bzero((char *)&iph, sizeof(iph));
216 	bzero((char *)&pool, sizeof(pool));
217 
218 	while ((c = getopt(argc, argv, "dm:no:RS:t:v")) != -1)
219 		switch (c)
220 		{
221 		case 'd' :
222 			opts |= OPT_DEBUG;
223 			ippool_yydebug++;
224 			break;
225 		case 'm' :
226 			poolname = optarg;
227 			break;
228 		case 'n' :
229 			opts |= OPT_DONOTHING;
230 			break;
231 		case 'o' :
232 			role = getrole(optarg);
233 			if (role == IPL_LOGNONE) {
234 				fprintf(stderr, "unknown role '%s'\n", optarg);
235 				return -1;
236 			}
237 			break;
238 		case 'R' :
239 			opts |= OPT_NORESOLVE;
240 			break;
241 		case 'S' :
242 			iph.iph_seed = atoi(optarg);
243 			break;
244 		case 't' :
245 			type = gettype(optarg, &iph.iph_type);
246 			if (type == IPLT_NONE) {
247 				fprintf(stderr, "unknown type '%s'\n", optarg);
248 				return -1;
249 			}
250 			break;
251 		case 'v' :
252 			opts |= OPT_VERBOSE;
253 			break;
254 		}
255 
256 	if (opts & OPT_DEBUG)
257 		fprintf(stderr, "poolcommand: opts = %#x\n", opts);
258 
259 	if (poolname == NULL) {
260 		fprintf(stderr, "poolname not given with add/remove pool\n");
261 		return -1;
262 	}
263 
264 	if (type == IPLT_HASH) {
265 		strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
266 		iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
267 		iph.iph_unit = role;
268 	} else if (type == IPLT_POOL) {
269 		strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
270 		pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
271 		pool.ipo_unit = role;
272 	}
273 
274 	if (remove == 0) {
275 		switch (type)
276 		{
277 		case IPLT_HASH :
278 			err = load_hash(&iph, NULL, ioctl);
279 			break;
280 		case IPLT_POOL :
281 			err = load_pool(&pool, ioctl);
282 			break;
283 		}
284 	} else {
285 		switch (type)
286 		{
287 		case IPLT_HASH :
288 			err = remove_hash(&iph, ioctl);
289 			break;
290 		case IPLT_POOL :
291 			err = remove_pool(&pool, ioctl);
292 			break;
293 		}
294 	}
295 	return err;
296 }
297 
298 
299 int loadpoolfile(argc, argv, infile)
300 int argc;
301 char *argv[], *infile;
302 {
303 	int c;
304 
305 	infile = optarg;
306 
307 	while ((c = getopt(argc, argv, "dnRuv")) != -1)
308 		switch (c)
309 		{
310 		case 'd' :
311 			opts |= OPT_DEBUG;
312 			ippool_yydebug++;
313 			break;
314 		case 'n' :
315 			opts |= OPT_DONOTHING;
316 			break;
317 		case 'R' :
318 			opts |= OPT_NORESOLVE;
319 			break;
320 		case 'u' :
321 			opts |= OPT_REMOVE;
322 			break;
323 		case 'v' :
324 			opts |= OPT_VERBOSE;
325 			break;
326 		}
327 
328 	if (opts & OPT_DEBUG)
329 		fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
330 
331 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
332 		fd = open(IPLOOKUP_NAME, O_RDWR);
333 		if (fd == -1) {
334 			perror("open(IPLOOKUP_NAME)");
335 			exit(1);
336 		}
337 	}
338 
339 	if (ippool_parsefile(fd, infile, ioctl) != 0)
340 		return -1;
341 	return 0;
342 }
343 
344 
345 int poollist(argc, argv)
346 int argc;
347 char *argv[];
348 {
349 	char *kernel, *core, *poolname;
350 	int c, role, type, live_kernel;
351 	ip_pool_stat_t *plstp, plstat;
352 	iphtstat_t *htstp, htstat;
353 	iphtable_t *hptr;
354 	iplookupop_t op;
355 	ip_pool_t *ptr;
356 
357 	core = NULL;
358 	kernel = NULL;
359 	live_kernel = 1;
360 	type = IPLT_ALL;
361 	poolname = NULL;
362 	role = IPL_LOGALL;
363 
364 	while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
365 		switch (c)
366 		{
367 		case 'd' :
368 			opts |= OPT_DEBUG;
369 			break;
370 		case 'm' :
371 			poolname = optarg;
372 			break;
373 		case 'M' :
374 			live_kernel = 0;
375 			core = optarg;
376 			break;
377 		case 'N' :
378 			live_kernel = 0;
379 			kernel = optarg;
380 			break;
381 		case 'o' :
382 			role = getrole(optarg);
383 			if (role == IPL_LOGNONE) {
384 				fprintf(stderr, "unknown role '%s'\n", optarg);
385 				return -1;
386 			}
387 			break;
388 		case 'R' :
389 			opts |= OPT_NORESOLVE;
390 			break;
391 		case 't' :
392 			type = gettype(optarg, NULL);
393 			if (type == IPLT_NONE) {
394 				fprintf(stderr, "unknown type '%s'\n", optarg);
395 				return -1;
396 			}
397 			break;
398 		case 'v' :
399 			opts |= OPT_VERBOSE;
400 			break;
401 		}
402 
403 	if (opts & OPT_DEBUG)
404 		fprintf(stderr, "poollist: opts = %#x\n", opts);
405 
406 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
407 		fd = open(IPLOOKUP_NAME, O_RDWR);
408 		if (fd == -1) {
409 			perror("open(IPLOOKUP_NAME)");
410 			exit(1);
411 		}
412 	}
413 
414 	bzero((char *)&op, sizeof(op));
415 	if (poolname != NULL) {
416 		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
417 		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
418 	}
419 	op.iplo_unit = role;
420 
421 	if (openkmem(kernel, core) == -1)
422 		exit(-1);
423 
424 	if (type == IPLT_ALL || type == IPLT_POOL) {
425 		plstp = &plstat;
426 		op.iplo_type = IPLT_POOL;
427 		op.iplo_size = sizeof(plstat);
428 		op.iplo_struct = &plstat;
429 		c = ioctl(fd, SIOCLOOKUPSTAT, &op);
430 		if (c == -1) {
431 			perror("ioctl(SIOCLOOKUPSTAT)");
432 			return -1;
433 		}
434 
435 		if (role != IPL_LOGALL) {
436 			ptr = plstp->ipls_list[role];
437 			while (ptr != NULL) {
438 				ptr = printpool(ptr, kmemcpywrap, poolname,
439 						opts);
440 			}
441 		} else {
442 			for (role = 0; role <= IPL_LOGMAX; role++) {
443 				ptr = plstp->ipls_list[role];
444 				while (ptr != NULL) {
445 					ptr = printpool(ptr, kmemcpywrap,
446 							poolname, opts);
447 				}
448 			}
449 			role = IPL_LOGALL;
450 		}
451 	}
452 	if (type == IPLT_ALL || type == IPLT_HASH) {
453 		htstp = &htstat;
454 		op.iplo_type = IPLT_HASH;
455 		op.iplo_size = sizeof(htstat);
456 		op.iplo_struct = &htstat;
457 		c = ioctl(fd, SIOCLOOKUPSTAT, &op);
458 		if (c == -1) {
459 			perror("ioctl(SIOCLOOKUPSTAT)");
460 			return -1;
461 		}
462 
463 		if (role != IPL_LOGALL) {
464 			hptr = htstp->iphs_tables;
465 			while (hptr != NULL) {
466 				hptr = printhash(hptr, kmemcpywrap,
467 						 poolname, opts);
468 			}
469 		} else {
470 			for (role = 0; role <= IPL_LOGMAX; role++) {
471 				hptr = htstp->iphs_tables;
472 				while (hptr != NULL) {
473 					hptr = printhash(hptr, kmemcpywrap,
474 							 poolname, opts);
475 				}
476 
477 				op.iplo_unit = role;
478 				c = ioctl(fd, SIOCLOOKUPSTAT, &op);
479 				if (c == -1) {
480 					perror("ioctl(SIOCLOOKUPSTAT)");
481 					return -1;
482 				}
483 			}
484 		}
485 	}
486 	return 0;
487 }
488 
489 
490 int poolstats(argc, argv)
491 int argc;
492 char *argv[];
493 {
494 	int c, type, role, live_kernel;
495 	ip_pool_stat_t plstat;
496 	char *kernel, *core;
497 	iphtstat_t htstat;
498 	iplookupop_t op;
499 
500 	core = NULL;
501 	kernel = NULL;
502 	live_kernel = 1;
503 	type = IPLT_ALL;
504 	role = IPL_LOGALL;
505 
506 	bzero((char *)&op, sizeof(op));
507 
508 	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
509 		switch (c)
510 		{
511 		case 'd' :
512 			opts |= OPT_DEBUG;
513 			break;
514 		case 'M' :
515 			live_kernel = 0;
516 			core = optarg;
517 			break;
518 		case 'N' :
519 			live_kernel = 0;
520 			kernel = optarg;
521 			break;
522 		case 'o' :
523 			role = getrole(optarg);
524 			if (role == IPL_LOGNONE) {
525 				fprintf(stderr, "unknown role '%s'\n", optarg);
526 				return -1;
527 			}
528 			break;
529 		case 't' :
530 			type = gettype(optarg, NULL);
531 			if (type != IPLT_POOL) {
532 				fprintf(stderr,
533 					"-s not supported for this type yet\n");
534 				return -1;
535 			}
536 			break;
537 		case 'v' :
538 			opts |= OPT_VERBOSE;
539 			break;
540 		}
541 
542 	if (opts & OPT_DEBUG)
543 		fprintf(stderr, "poolstats: opts = %#x\n", opts);
544 
545 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
546 		fd = open(IPLOOKUP_NAME, O_RDWR);
547 		if (fd == -1) {
548 			perror("open(IPLOOKUP_NAME)");
549 			exit(1);
550 		}
551 	}
552 
553 	if (type == IPLT_ALL || type == IPLT_POOL) {
554 		op.iplo_type = IPLT_POOL;
555 		op.iplo_struct = &plstat;
556 		op.iplo_size = sizeof(plstat);
557 		if (!(opts & OPT_DONOTHING)) {
558 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
559 			if (c == -1) {
560 				perror("ioctl(SIOCLOOKUPSTAT)");
561 				return -1;
562 			}
563 			printf("Pools:\t%lu\n", plstat.ipls_pools);
564 			printf("Nodes:\t%lu\n", plstat.ipls_nodes);
565 		}
566 	}
567 
568 	if (type == IPLT_ALL || type == IPLT_HASH) {
569 		op.iplo_type = IPLT_HASH;
570 		op.iplo_struct = &htstat;
571 		op.iplo_size = sizeof(htstat);
572 		if (!(opts & OPT_DONOTHING)) {
573 			c = ioctl(fd, SIOCLOOKUPSTAT, &op);
574 			if (c == -1) {
575 				perror("ioctl(SIOCLOOKUPSTAT)");
576 				return -1;
577 			}
578 			printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
579 			printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
580 			printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
581 		}
582 	}
583 	return 0;
584 }
585 
586 
587 int poolflush(argc, argv)
588 int argc;
589 char *argv[];
590 {
591 	int c, role, type, arg;
592 	iplookupflush_t flush;
593 
594 	arg = IPLT_ALL;
595 	type = IPLT_ALL;
596 	role = IPL_LOGALL;
597 
598 	while ((c = getopt(argc, argv, "do:t:v")) != -1)
599 		switch (c)
600 		{
601 		case 'd' :
602 			opts |= OPT_DEBUG;
603 			break;
604 		case 'o' :
605 			role = getrole(optarg);
606 			if (role == IPL_LOGNONE) {
607 				fprintf(stderr, "unknown role '%s'\n", optarg);
608 				return -1;
609 			}
610 			break;
611 		case 't' :
612 			type = gettype(optarg, NULL);
613 			if (type == IPLT_NONE) {
614 				fprintf(stderr, "unknown type '%s'\n", optarg);
615 				return -1;
616 			}
617 			break;
618 		case 'v' :
619 			opts |= OPT_VERBOSE;
620 			break;
621 		}
622 
623 	if (opts & OPT_DEBUG)
624 		fprintf(stderr, "poolflush: opts = %#x\n", opts);
625 
626 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
627 		fd = open(IPLOOKUP_NAME, O_RDWR);
628 		if (fd == -1) {
629 			perror("open(IPLOOKUP_NAME)");
630 			exit(1);
631 		}
632 	}
633 
634 	bzero((char *)&flush, sizeof(flush));
635 	flush.iplf_type = type;
636 	flush.iplf_unit = role;
637 	flush.iplf_arg = arg;
638 
639 	if (!(opts & OPT_DONOTHING)) {
640 		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
641 			perror("ioctl(SIOCLOOKUPFLUSH)");
642 			exit(1);
643 		}
644 
645 	}
646 	printf("%u object%s flushed\n", flush.iplf_count,
647 	       (flush.iplf_count == 1) ? "" : "s");
648 
649 	return 0;
650 }
651 
652 
653 int getrole(rolename)
654 char *rolename;
655 {
656 	int role;
657 
658 	if (!strcasecmp(rolename, "ipf")) {
659 		role = IPL_LOGIPF;
660 #if 0
661 	} else if (!strcasecmp(rolename, "nat")) {
662 		role = IPL_LOGNAT;
663 	} else if (!strcasecmp(rolename, "state")) {
664 		role = IPL_LOGSTATE;
665 	} else if (!strcasecmp(rolename, "auth")) {
666 		role = IPL_LOGAUTH;
667 	} else if (!strcasecmp(rolename, "sync")) {
668 		role = IPL_LOGSYNC;
669 	} else if (!strcasecmp(rolename, "scan")) {
670 		role = IPL_LOGSCAN;
671 	} else if (!strcasecmp(rolename, "pool")) {
672 		role = IPL_LOGLOOKUP;
673 	} else if (!strcasecmp(rolename, "count")) {
674 		role = IPL_LOGCOUNT;
675 #endif
676 	} else {
677 		role = IPL_LOGNONE;
678 	}
679 
680 	return role;
681 }
682 
683 
684 int gettype(typename, minor)
685 char *typename;
686 u_int *minor;
687 {
688 	int type;
689 
690 	if (!strcasecmp(optarg, "tree")) {
691 		type = IPLT_POOL;
692 	} else if (!strcasecmp(optarg, "hash")) {
693 		type = IPLT_HASH;
694 		if (minor != NULL)
695 			*minor = IPHASH_LOOKUP;
696 	} else if (!strcasecmp(optarg, "group-map")) {
697 		type = IPLT_HASH;
698 		if (minor != NULL)
699 			*minor = IPHASH_GROUPMAP;
700 	} else {
701 		type = IPLT_NONE;
702 	}
703 	return type;
704 }
705