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