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