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