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