xref: /illumos-gate/usr/src/cmd/ipf/tools/ippool.c (revision 7c478bd9)
1 /*
2  * Copyright (C) 2003 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * Copyright 2004 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 	iplookupop_t op;
339 	ip_pool_t *ptr;
340 
341 	core = NULL;
342 	kernel = NULL;
343 	live_kernel = 1;
344 	type = IPLT_ALL;
345 	poolname = NULL;
346 	role = IPL_LOGALL;
347 
348 	while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1)
349 		switch (c)
350 		{
351 		case 'd' :
352 			opts |= OPT_DEBUG;
353 			break;
354 		case 'm' :
355 			poolname = optarg;
356 			break;
357 		case 'M' :
358 			live_kernel = 0;
359 			core = optarg;
360 			break;
361 		case 'N' :
362 			live_kernel = 0;
363 			kernel = optarg;
364 			break;
365 		case 'o' :
366 			role = getrole(optarg);
367 			if (role == IPL_LOGNONE) {
368 				fprintf(stderr, "unknown role '%s'\n", optarg);
369 				return -1;
370 			}
371 			break;
372 		case 't' :
373 			type = gettype(optarg, NULL);
374 			if (type == IPLT_NONE) {
375 				fprintf(stderr, "unknown type '%s'\n", optarg);
376 				return -1;
377 			}
378 			break;
379 		case 'v' :
380 			opts |= OPT_VERBOSE;
381 			break;
382 		}
383 
384 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
385 		fd = open(IPLOOKUP_NAME, O_RDWR);
386 		if (fd == -1) {
387 			perror("open(IPLOOKUP_NAME)");
388 			exit(1);
389 		}
390 	}
391 
392 	bzero((char *)&op, sizeof(op));
393 	if (poolname != NULL) {
394 		strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
395 		op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
396 	}
397 	op.iplo_type = type;
398 	op.iplo_unit = role;
399 	op.iplo_size = sizeof(plstat);
400 	op.iplo_struct = &plstat;
401 	plstp = &plstat;
402 
403 	c = ioctl(fd, SIOCLOOKUPSTAT, &op);
404 	if (c == -1) {
405 		perror("ioctl(SIOCLOOKUPSTAT)");
406 		return -1;
407 	}
408 
409 	if (openkmem(kernel, core) == -1)
410 		exit(-1);
411 
412 	if (role != IPL_LOGALL) {
413 		ptr = plstp->ipls_list[role];
414 		while (ptr != NULL) {
415 			ptr = printpool(ptr, kmemcpywrap, opts);
416 		}
417 	} else {
418 		for (role = 0; role <= IPL_LOGMAX; role++) {
419 			ptr = plstp->ipls_list[role];
420 			while (ptr != NULL) {
421 				ptr = printpool(ptr, kmemcpywrap, opts);
422 			}
423 		}
424 	}
425 	return 0;
426 }
427 
428 
429 int poolstats(argc, argv)
430 int argc;
431 char *argv[];
432 {
433 	int c, type, role, live_kernel;
434 	ip_pool_stat_t plstat;
435 	char *kernel, *core;
436 	iplookupop_t op;
437 
438 	core = NULL;
439 	kernel = NULL;
440 	live_kernel = 1;
441 	type = IPLT_ALL;
442 	role = IPL_LOGALL;
443 
444 	bzero((char *)&op, sizeof(op));
445 	op.iplo_struct = &plstat;
446 	op.iplo_size = sizeof(plstat);
447 
448 	while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
449 		switch (c)
450 		{
451 		case 'd' :
452 			opts |= OPT_DEBUG;
453 			break;
454 		case 'M' :
455 			live_kernel = 0;
456 			core = optarg;
457 			break;
458 		case 'N' :
459 			live_kernel = 0;
460 			kernel = optarg;
461 			break;
462 		case 'o' :
463 			role = getrole(optarg);
464 			if (role == IPL_LOGNONE) {
465 				fprintf(stderr, "unknown role '%s'\n", optarg);
466 				return -1;
467 			}
468 			break;
469 		case 't' :
470 			type = gettype(optarg, NULL);
471 			if (type != IPLT_POOL) {
472 				fprintf(stderr,
473 					"-s not supported for this type yet\n");
474 				return -1;
475 			}
476 			break;
477 		case 'v' :
478 			opts |= OPT_VERBOSE;
479 			break;
480 		}
481 
482 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
483 		fd = open(IPLOOKUP_NAME, O_RDWR);
484 		if (fd == -1) {
485 			perror("open(IPLOOKUP_NAME)");
486 			exit(1);
487 		}
488 	}
489 
490 	if (!(opts & OPT_DONOTHING)) {
491 		c = ioctl(fd, SIOCLOOKUPSTAT, &op);
492 		if (c == -1) {
493 			perror("ioctl(SIOCLOOKUPSTAT)");
494 			return -1;
495 		}
496 		printf("Pools:\t%lu\n", plstat.ipls_pools);
497 		printf("Hash Tables:\t%lu\n", plstat.ipls_tables);
498 		printf("Nodes:\t%lu\n", plstat.ipls_nodes);
499 	}
500 	return 0;
501 }
502 
503 
504 int poolflush(argc, argv)
505 int argc;
506 char *argv[];
507 {
508 	int c, role, type, arg;
509 	iplookupflush_t flush;
510 
511 	arg = IPLT_ALL;
512 	type = IPLT_ALL;
513 	role = IPL_LOGALL;
514 
515 	while ((c = getopt(argc, argv, "do:t:v")) != -1)
516 		switch (c)
517 		{
518 		case 'd' :
519 			opts |= OPT_DEBUG;
520 			break;
521 		case 'o' :
522 			role = getrole(optarg);
523 			if (role == IPL_LOGNONE) {
524 				fprintf(stderr, "unknown role '%s'\n", optarg);
525 				return -1;
526 			}
527 			break;
528 		case 't' :
529 			type = gettype(optarg, NULL);
530 			if (type == IPLT_NONE) {
531 				fprintf(stderr, "unknown type '%s'\n", optarg);
532 				return -1;
533 			}
534 			break;
535 		case 'v' :
536 			opts |= OPT_VERBOSE;
537 			break;
538 		}
539 
540 	if (!(opts & OPT_DONOTHING) && (fd == -1)) {
541 		fd = open(IPLOOKUP_NAME, O_RDWR);
542 		if (fd == -1) {
543 			perror("open(IPLOOKUP_NAME)");
544 			exit(1);
545 		}
546 	}
547 
548 	bzero((char *)&flush, sizeof(flush));
549 	flush.iplf_type = type;
550 	flush.iplf_unit = role;
551 	flush.iplf_arg = arg;
552 
553 	if (!(opts & OPT_DONOTHING)) {
554 		if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
555 			perror("ioctl(SIOCLOOKUPFLUSH)");
556 			exit(1);
557 		}
558 
559 	}
560 	printf("%u object%s flushed\n", flush.iplf_count,
561 	       (flush.iplf_count == 1) ? "" : "s");
562 
563 	return 0;
564 }
565 
566 
567 int getrole(rolename)
568 char *rolename;
569 {
570 	int role;
571 
572 	if (!strcasecmp(rolename, "ipf")) {
573 		role = IPL_LOGIPF;
574 #if 0
575 	} else if (!strcasecmp(rolename, "nat")) {
576 		role = IPL_LOGNAT;
577 	} else if (!strcasecmp(rolename, "state")) {
578 		role = IPL_LOGSTATE;
579 	} else if (!strcasecmp(rolename, "auth")) {
580 		role = IPL_LOGAUTH;
581 	} else if (!strcasecmp(rolename, "sync")) {
582 		role = IPL_LOGSYNC;
583 	} else if (!strcasecmp(rolename, "scan")) {
584 		role = IPL_LOGSCAN;
585 	} else if (!strcasecmp(rolename, "pool")) {
586 		role = IPL_LOGLOOKUP;
587 	} else if (!strcasecmp(rolename, "count")) {
588 		role = IPL_LOGCOUNT;
589 #endif
590 	} else {
591 		role = IPL_LOGNONE;
592 	}
593 
594 	return role;
595 }
596 
597 
598 int gettype(typename, minor)
599 char *typename;
600 u_int *minor;
601 {
602 	int type;
603 
604 	if (!strcasecmp(optarg, "pool")) {
605 		type = IPLT_POOL;
606 	} else if (!strcasecmp(optarg, "hash")) {
607 		type = IPLT_HASH;
608 		if (minor != NULL)
609 			*minor = IPHASH_LOOKUP;
610 	} else if (!strcasecmp(optarg, "group-map")) {
611 		type = IPLT_HASH;
612 		if (minor != NULL)
613 			*minor = IPHASH_GROUPMAP;
614 	} else {
615 		type = IPLT_NONE;
616 	}
617 	return type;
618 }
619