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