1 /*
   2  * Copyright (C) 2003 by Darren Reed.
   3  *
   4  * See the IPFILTER.LICENCE file for details on licencing.
   5  *
   6  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
   7  * Use is subject to license terms.
   8  *
   9  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  10  * Copyright 2017 Gary Mills
  11  */
  12 
  13 #include <sys/types.h>
  14 #include <sys/time.h>
  15 #include <sys/param.h>
  16 #include <sys/socket.h>
  17 #if defined(BSD) && (BSD >= 199306)
  18 # include <sys/cdefs.h>
  19 #endif
  20 #include <sys/ioctl.h>
  21 
  22 #include <net/if.h>
  23 #if __FreeBSD_version >= 300000
  24 # include <net/if_var.h>
  25 #endif
  26 #include <netinet/in.h>
  27 
  28 #include <arpa/inet.h>
  29 
  30 #include <stdio.h>
  31 #include <fcntl.h>
  32 #include <stdlib.h>
  33 #include <string.h>
  34 #include <netdb.h>
  35 #include <ctype.h>
  36 #include <unistd.h>
  37 #include <nlist.h>
  38 
  39 #include "ipf.h"
  40 #include "netinet/ipl.h"
  41 #include "netinet/ip_lookup.h"
  42 #include "netinet/ip_pool.h"
  43 #include "netinet/ip_htable.h"
  44 #include "kmem.h"
  45 #include "ipfzone.h"
  46 
  47 extern  int     ippool_yyparse __P((void));
  48 extern  int     ippool_yydebug;
  49 extern  FILE    *ippool_yyin;
  50 extern  char    *optarg;
  51 extern  int     lineNum;
  52 
  53 void    showpools __P((ip_pool_stat_t *));
  54 void    usage __P((char *));
  55 int     main __P((int, char **));
  56 int     poolcommand __P((int, int, char *[]));
  57 int     poolnodecommand __P((int, int, char *[]));
  58 int     loadpoolfile __P((int, char *[], char *));
  59 int     poollist __P((int, char *[]));
  60 int     poolflush __P((int, char *[]));
  61 int     poolstats __P((int, char *[]));
  62 int     gettype __P((char *, u_int *));
  63 int     getrole __P((char *));
  64 void    poollist_dead __P((int, char *, int, char *, char *));
  65 void    showpools_live(int, int, ip_pool_stat_t *, char *, int);
  66 void    showhashs_live(int, int, iphtstat_t *, char *, int);
  67 
  68 int     opts = 0;
  69 int     fd = -1;
  70 int     use_inet6 = 0;
  71 
  72 
  73 void usage(prog)
  74 char *prog;
  75 {
  76         const char *zoneopt = "[-G|-z zonename] ";
  77         fprintf(stderr, "Usage:\t%s\n", prog);
  78         fprintf(stderr, "\t\t\t-a [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
  79             zoneopt);
  80         fprintf(stderr, "\t\t\t-A [-dnv] %s[-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n",
  81             zoneopt);
  82         fprintf(stderr, "\t\t\t-f <file> %s[-dnuv]\n", zoneopt);
  83         fprintf(stderr, "\t\t\t-F [-dv] %s[-o <role>] [-t <type>]\n", zoneopt);
  84         fprintf(stderr, "\t\t\t-l [-dv] %s[-m <name>] [-t <type>]\n", zoneopt);
  85         fprintf(stderr, "\t\t\t-r [-dnv] %s[-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n",
  86             zoneopt);
  87         fprintf(stderr, "\t\t\t-R [-dnv] %s[-m <name>] [-o <role>] [-t <type>]\n",
  88             zoneopt);
  89         fprintf(stderr, "\t\t\t-s [-dtv] %s[-M <core>] [-N <namelist>]\n",
  90             zoneopt);
  91         exit(1);
  92 }
  93 
  94 
  95 int main(argc, argv)
  96 int argc;
  97 char *argv[];
  98 {
  99         int err;
 100 
 101         if (argc < 2)
 102                 usage(argv[0]);
 103 
 104         switch (getopt(argc, argv, "aAf:FlrRs"))
 105         {
 106         case 'a' :
 107                 err = poolnodecommand(0, argc, argv);
 108                 break;
 109         case 'A' :
 110                 err = poolcommand(0, argc, argv);
 111                 break;
 112         case 'f' :
 113                 err = loadpoolfile(argc, argv, optarg);
 114                 break;
 115         case 'F' :
 116                 err = poolflush(argc, argv);
 117                 break;
 118         case 'l' :
 119                 err = poollist(argc, argv);
 120                 break;
 121         case 'r' :
 122                 err = poolnodecommand(1, argc, argv);
 123                 break;
 124         case 'R' :
 125                 err = poolcommand(1, argc, argv);
 126                 break;
 127         case 's' :
 128                 err = poolstats(argc, argv);
 129                 break;
 130         default :
 131                 exit(1);
 132         }
 133 
 134         return err;
 135 }
 136 
 137 
 138 int poolnodecommand(remove, argc, argv)
 139 int remove, argc;
 140 char *argv[];
 141 {
 142         char *poolname = NULL, *s;
 143         int err, c, ipset, role;
 144         ip_pool_node_t node;
 145         struct in_addr mask;
 146 
 147         ipset = 0;
 148         role = IPL_LOGIPF;
 149         bzero((char *)&node, sizeof(node));
 150 
 151         while ((c = getopt(argc, argv, "di:G:m:no:Rvz:")) != -1)
 152                 switch (c)
 153                 {
 154                 case 'd' :
 155                         opts |= OPT_DEBUG;
 156                         ippool_yydebug++;
 157                         break;
 158                 case 'G' :
 159                         setzonename_global(optarg);
 160                         break;
 161                 case 'i' :
 162                         s = strchr(optarg, '/');
 163                         if (s == NULL)
 164                                 mask.s_addr = 0xffffffff;
 165                         else if (strchr(s, '.') == NULL) {
 166                                 if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
 167                                         return -1;
 168                         } else {
 169                                 mask.s_addr = inet_addr(s + 1);
 170                         }
 171                         if (s != NULL)
 172                                 *s = '\0';
 173                         ipset = 1;
 174                         node.ipn_addr.adf_len = sizeof(node.ipn_addr);
 175                         node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg);
 176                         node.ipn_mask.adf_len = sizeof(node.ipn_mask);
 177                         node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
 178                         break;
 179                 case 'm' :
 180                         poolname = optarg;
 181                         break;
 182                 case 'n' :
 183                         opts |= OPT_DONOTHING;
 184                         break;
 185                 case 'o' :
 186                         role = getrole(optarg);
 187                         if (role == IPL_LOGNONE)
 188                                 return -1;
 189                         break;
 190                 case 'R' :
 191                         opts |= OPT_NORESOLVE;
 192                         break;
 193                 case 'v' :
 194                         opts |= OPT_VERBOSE;
 195                         break;
 196                 case 'z' :
 197                         setzonename(optarg);
 198                         break;
 199                 }
 200 
 201         if (opts & OPT_DEBUG)
 202                 fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
 203 
 204         if (ipset == 0)
 205                 return -1;
 206         if (poolname == NULL) {
 207                 fprintf(stderr, "poolname not given with add/remove node\n");
 208                 return -1;
 209         }
 210 
 211         if (remove == 0)
 212                 err = load_poolnode(0, poolname, &node, ioctl);
 213         else
 214                 err = remove_poolnode(0, poolname, &node, ioctl);
 215         return err;
 216 }
 217 
 218 
 219 int poolcommand(remove, argc, argv)
 220 int remove, argc;
 221 char *argv[];
 222 {
 223         int type, role, c, err;
 224         char *poolname;
 225         iphtable_t iph;
 226         ip_pool_t pool;
 227 
 228         err = 1;
 229         role = 0;
 230         type = 0;
 231         poolname = NULL;
 232         role = IPL_LOGIPF;
 233         bzero((char *)&iph, sizeof(iph));
 234         bzero((char *)&pool, sizeof(pool));
 235 
 236         while ((c = getopt(argc, argv, "dG:m:no:RS:t:vz:")) != -1)
 237                 switch (c)
 238                 {
 239                 case 'd' :
 240                         opts |= OPT_DEBUG;
 241                         ippool_yydebug++;
 242                         break;
 243                 case 'G' :
 244                         setzonename_global(optarg);
 245                         break;
 246                 case 'm' :
 247                         poolname = optarg;
 248                         break;
 249                 case 'n' :
 250                         opts |= OPT_DONOTHING;
 251                         break;
 252                 case 'o' :
 253                         role = getrole(optarg);
 254                         if (role == IPL_LOGNONE) {
 255                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 256                                 return -1;
 257                         }
 258                         break;
 259                 case 'R' :
 260                         opts |= OPT_NORESOLVE;
 261                         break;
 262                 case 'S' :
 263                         iph.iph_seed = atoi(optarg);
 264                         break;
 265                 case 't' :
 266                         type = gettype(optarg, &iph.iph_type);
 267                         if (type == IPLT_NONE) {
 268                                 fprintf(stderr, "unknown type '%s'\n", optarg);
 269                                 return -1;
 270                         }
 271                         break;
 272                 case 'v' :
 273                         opts |= OPT_VERBOSE;
 274                         break;
 275                 case 'z' :
 276                         setzonename(optarg);
 277                         break;
 278                 }
 279 
 280         if (opts & OPT_DEBUG)
 281                 fprintf(stderr, "poolcommand: opts = %#x\n", opts);
 282 
 283         if (poolname == NULL) {
 284                 fprintf(stderr, "poolname not given with add/remove pool\n");
 285                 return -1;
 286         }
 287 
 288         if (type == IPLT_HASH) {
 289                 strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
 290                 iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
 291                 iph.iph_unit = role;
 292         } else if (type == IPLT_POOL) {
 293                 strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
 294                 pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
 295                 pool.ipo_unit = role;
 296         }
 297 
 298         if (remove == 0) {
 299                 switch (type)
 300                 {
 301                 case IPLT_HASH :
 302                         err = load_hash(&iph, NULL, ioctl);
 303                         break;
 304                 case IPLT_POOL :
 305                         err = load_pool(&pool, ioctl);
 306                         break;
 307                 }
 308         } else {
 309                 switch (type)
 310                 {
 311                 case IPLT_HASH :
 312                         err = remove_hash(&iph, ioctl);
 313                         break;
 314                 case IPLT_POOL :
 315                         err = remove_pool(&pool, ioctl);
 316                         break;
 317                 }
 318         }
 319         return err;
 320 }
 321 
 322 
 323 int loadpoolfile(argc, argv, infile)
 324 int argc;
 325 char *argv[], *infile;
 326 {
 327         int c;
 328 
 329         infile = optarg;
 330 
 331         while ((c = getopt(argc, argv, "dG:nRuvz:")) != -1)
 332                 switch (c)
 333                 {
 334                 case 'd' :
 335                         opts |= OPT_DEBUG;
 336                         ippool_yydebug++;
 337                         break;
 338                 case 'G' :
 339                         setzonename_global(optarg);
 340                         break;
 341                 case 'n' :
 342                         opts |= OPT_DONOTHING;
 343                         break;
 344                 case 'R' :
 345                         opts |= OPT_NORESOLVE;
 346                         break;
 347                 case 'u' :
 348                         opts |= OPT_REMOVE;
 349                         break;
 350                 case 'v' :
 351                         opts |= OPT_VERBOSE;
 352                         break;
 353                 case 'z' :
 354                         setzonename(optarg);
 355                         break;
 356                 }
 357 
 358         if (opts & OPT_DEBUG)
 359                 fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
 360 
 361         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 362                 fd = open(IPLOOKUP_NAME, O_RDWR);
 363                 if (fd == -1) {
 364                         perror("open(IPLOOKUP_NAME)");
 365                         exit(1);
 366                 }
 367 
 368                 if (setzone(fd) != 0) {
 369                         close(fd);
 370                         exit(1);
 371                 }
 372         }
 373 
 374         if (ippool_parsefile(fd, infile, ioctl) != 0)
 375                 return -1;
 376         return 0;
 377 }
 378 
 379 
 380 int poollist(argc, argv)
 381 int argc;
 382 char *argv[];
 383 {
 384         char *kernel, *core, *poolname;
 385         int c, role, type, live_kernel;
 386         ip_pool_stat_t  plstat;
 387         iphtstat_t  htstat;
 388         iphtable_t *hptr;
 389         iplookupop_t op;
 390         ip_pool_t *ptr;
 391 
 392         core = NULL;
 393         kernel = NULL;
 394         live_kernel = 1;
 395         type = IPLT_ALL;
 396         poolname = NULL;
 397         role = IPL_LOGALL;
 398 
 399         while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1)
 400                 switch (c)
 401                 {
 402                 case 'd' :
 403                         opts |= OPT_DEBUG;
 404                         break;
 405                 case 'G' :
 406                         setzonename_global(optarg);
 407                         break;
 408                 case 'm' :
 409                         poolname = optarg;
 410                         break;
 411                 case 'M' :
 412                         live_kernel = 0;
 413                         core = optarg;
 414                         break;
 415                 case 'N' :
 416                         live_kernel = 0;
 417                         kernel = optarg;
 418                         break;
 419                 case 'o' :
 420                         role = getrole(optarg);
 421                         if (role == IPL_LOGNONE) {
 422                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 423                                 return -1;
 424                         }
 425                         break;
 426                 case 'R' :
 427                         opts |= OPT_NORESOLVE;
 428                         break;
 429                 case 't' :
 430                         type = gettype(optarg, NULL);
 431                         if (type == IPLT_NONE) {
 432                                 fprintf(stderr, "unknown type '%s'\n", optarg);
 433                                 return -1;
 434                         }
 435                         break;
 436                 case 'v' :
 437                         opts |= OPT_VERBOSE;
 438                         break;
 439                 case 'z' :
 440                         setzonename(optarg);
 441                         break;
 442                 }
 443 
 444         if (opts & OPT_DEBUG)
 445                 fprintf(stderr, "poollist: opts = %#x\n", opts);
 446 
 447         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 448                 fd = open(IPLOOKUP_NAME, O_RDWR);
 449                 if (fd == -1) {
 450                         perror("open(IPLOOKUP_NAME)");
 451                         exit(1);
 452                 }
 453 
 454                 if (setzone(fd) != 0) {
 455                         close(fd);
 456                         exit(1);
 457                 }
 458         }
 459 
 460         bzero((char *)&op, sizeof(op));
 461         if (poolname != NULL) {
 462                 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
 463                 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
 464         }
 465         op.iplo_unit = role;
 466 
 467         if (live_kernel == 0) {
 468                 poollist_dead(role, poolname, type, kernel, core);
 469                 return (0);
 470         }
 471 
 472         if (type == IPLT_ALL || type == IPLT_POOL) {
 473                 op.iplo_type = IPLT_POOL;
 474                 op.iplo_size = sizeof(plstat);
 475                 op.iplo_struct = &plstat;
 476                 op.iplo_name[0] = '\0';
 477                 op.iplo_arg = 0;
 478 
 479                 if (role != IPL_LOGALL) {
 480                         op.iplo_unit = role;
 481 
 482                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 483                         if (c == -1) {
 484                                 perror("ioctl(SIOCLOOKUPSTAT)");
 485                                 return -1;
 486                         }
 487 
 488                         showpools_live(fd, role, &plstat, poolname, opts);
 489                 } else {
 490                         for (role = 0; role <= IPL_LOGMAX; role++) {
 491                                 op.iplo_unit = role;
 492 
 493                                 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 494                                 if (c == -1) {
 495                                         perror("ioctl(SIOCLOOKUPSTAT)");
 496                                         return -1;
 497                                 }
 498 
 499                                 showpools_live(fd, role, &plstat, poolname, opts);
 500                         }
 501 
 502                         role = IPL_LOGALL;
 503                 }
 504         }
 505         if (type == IPLT_ALL || type == IPLT_HASH) {
 506                 op.iplo_type = IPLT_HASH;
 507                 op.iplo_size = sizeof(htstat);
 508                 op.iplo_struct = &htstat;
 509                 op.iplo_name[0] = '\0';
 510                 op.iplo_arg = 0;
 511 
 512                 if (role != IPL_LOGALL) {
 513                         op.iplo_unit = role;
 514 
 515                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 516                         if (c == -1) {
 517                                 perror("ioctl(SIOCLOOKUPSTAT)");
 518                                 return -1;
 519                         }
 520                         showhashs_live(fd, role, &htstat, poolname, opts);
 521                 } else {
 522                         for (role = 0; role <= IPL_LOGMAX; role++) {
 523 
 524                                 op.iplo_unit = role;
 525                                 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 526                                 if (c == -1) {
 527                                         perror("ioctl(SIOCLOOKUPSTAT)");
 528                                         return -1;
 529                                 }
 530 
 531                                 showhashs_live(fd, role, &htstat, poolname, opts);
 532                         }
 533                 }
 534         }
 535         return 0;
 536 }
 537 
 538 void poollist_dead(role, poolname, type, kernel, core)
 539 int role, type;
 540 char *poolname, *kernel, *core;
 541 {
 542         iphtable_t *hptr;
 543         ip_pool_t *ptr;
 544 
 545         if (openkmem(kernel, core) == -1)
 546                 exit(-1);
 547 
 548         if (type == IPLT_ALL || type == IPLT_POOL) {
 549                 ip_pool_t *pools[IPL_LOGSIZE];
 550                 struct nlist names[2] = { { "ip_pool_list" } , { "" } };
 551 
 552                 if (nlist(kernel, names) != 1)
 553                         return;
 554 
 555                 bzero(&pools, sizeof(pools));
 556                 if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
 557                         return;
 558 
 559                 if (role != IPL_LOGALL) {
 560                         ptr = pools[role];
 561                         while (ptr != NULL) {
 562                                 ptr = printpool(ptr, kmemcpywrap,
 563                                                 poolname, opts);
 564                         }
 565                 } else {
 566                         for (role = 0; role <= IPL_LOGMAX; role++) {
 567                                 ptr = pools[role];
 568                                 while (ptr != NULL) {
 569                                         ptr = printpool(ptr, kmemcpywrap,
 570                                                         poolname, opts);
 571                                 }
 572                         }
 573                         role = IPL_LOGALL;
 574                 }
 575         }
 576         if (type == IPLT_ALL || type == IPLT_HASH) {
 577                 iphtable_t *tables[IPL_LOGSIZE];
 578                 struct nlist names[2] = { { "ipf_htables" } , { "" } };
 579 
 580                 if (nlist(kernel, names) != 1)
 581                         return;
 582 
 583                 bzero(&tables, sizeof(tables));
 584                 if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
 585                         return;
 586 
 587                 if (role != IPL_LOGALL) {
 588                         hptr = tables[role];
 589                         while (hptr != NULL) {
 590                                 hptr = printhash(hptr, kmemcpywrap,
 591                                                  poolname, opts);
 592                         }
 593                 } else {
 594                         for (role = 0; role <= IPL_LOGMAX; role++) {
 595                                 hptr = tables[role];
 596                                 while (hptr != NULL) {
 597                                         hptr = printhash(hptr, kmemcpywrap,
 598                                                          poolname, opts);
 599                                 }
 600                         }
 601                 }
 602         }
 603 }
 604 
 605 
 606 void
 607 showpools_live(fd, role, plstp, poolname, opts)
 608 int fd, role;
 609 ip_pool_stat_t *plstp;
 610 char *poolname;
 611 int opts;
 612 {
 613         ipflookupiter_t iter;
 614         ip_pool_t pool;
 615         ipfobj_t obj;
 616 
 617         obj.ipfo_rev = IPFILTER_VERSION;
 618         obj.ipfo_type = IPFOBJ_LOOKUPITER;
 619         obj.ipfo_size = sizeof(iter);
 620         obj.ipfo_ptr = &iter;
 621 
 622         iter.ili_type = IPLT_POOL;
 623         iter.ili_otype = IPFLOOKUPITER_LIST;
 624         iter.ili_ival = IPFGENITER_LOOKUP;
 625         iter.ili_data = &pool;
 626         iter.ili_unit = role;
 627         *iter.ili_name = '\0';
 628 
 629         while (plstp->ipls_list[role] != NULL) {
 630                 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
 631                         perror("ioctl(SIOCLOOKUPITER)");
 632                         break;
 633                 }
 634                 (void) printpool_live(&pool, fd, poolname, opts);
 635 
 636                 plstp->ipls_list[role] = pool.ipo_next;
 637         }
 638 }
 639 
 640 int poolstats(argc, argv)
 641 int argc;
 642 char *argv[];
 643 {
 644         int c, type, role;
 645         ip_pool_stat_t plstat;
 646         iphtstat_t htstat;
 647         iplookupop_t op;
 648 
 649         type = IPLT_ALL;
 650         role = IPL_LOGALL;
 651 
 652         bzero((char *)&op, sizeof(op));
 653 
 654         while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1)
 655                 switch (c)
 656                 {
 657                 case 'd' :
 658                         opts |= OPT_DEBUG;
 659                         break;
 660                 case 'G' :
 661                         setzonename_global(optarg);
 662                         break;
 663                 case 'M' :
 664                         break;
 665                 case 'N' :
 666                         break;
 667                 case 'o' :
 668                         role = getrole(optarg);
 669                         if (role == IPL_LOGNONE) {
 670                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 671                                 return -1;
 672                         }
 673                         break;
 674                 case 't' :
 675                         type = gettype(optarg, NULL);
 676                         if (type != IPLT_POOL) {
 677                                 fprintf(stderr,
 678                                         "-s not supported for this type yet\n");
 679                                 return -1;
 680                         }
 681                         break;
 682                 case 'v' :
 683                         opts |= OPT_VERBOSE;
 684                         break;
 685                 case 'z' :
 686                         setzonename(optarg);
 687                         break;
 688                 }
 689 
 690         if (opts & OPT_DEBUG)
 691                 fprintf(stderr, "poolstats: opts = %#x\n", opts);
 692 
 693         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 694                 fd = open(IPLOOKUP_NAME, O_RDWR);
 695                 if (fd == -1) {
 696                         perror("open(IPLOOKUP_NAME)");
 697                         exit(1);
 698                 }
 699 
 700                 if (setzone(fd) != 0) {
 701                         close(fd);
 702                         exit(1);
 703                 }
 704         }
 705 
 706         if (type == IPLT_ALL || type == IPLT_POOL) {
 707                 op.iplo_type = IPLT_POOL;
 708                 op.iplo_struct = &plstat;
 709                 op.iplo_size = sizeof(plstat);
 710                 if (!(opts & OPT_DONOTHING)) {
 711                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 712                         if (c == -1) {
 713                                 perror("ioctl(SIOCLOOKUPSTAT)");
 714                                 return -1;
 715                         }
 716                         printf("Pools:\t%lu\n", plstat.ipls_pools);
 717                         printf("Nodes:\t%lu\n", plstat.ipls_nodes);
 718                 }
 719         }
 720 
 721         if (type == IPLT_ALL || type == IPLT_HASH) {
 722                 op.iplo_type = IPLT_HASH;
 723                 op.iplo_struct = &htstat;
 724                 op.iplo_size = sizeof(htstat);
 725                 if (!(opts & OPT_DONOTHING)) {
 726                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 727                         if (c == -1) {
 728                                 perror("ioctl(SIOCLOOKUPSTAT)");
 729                                 return -1;
 730                         }
 731                         printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
 732                         printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
 733                         printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
 734                 }
 735         }
 736         return 0;
 737 }
 738 
 739 
 740 int poolflush(argc, argv)
 741 int argc;
 742 char *argv[];
 743 {
 744         int c, role, type, arg;
 745         iplookupflush_t flush;
 746 
 747         arg = IPLT_ALL;
 748         type = IPLT_ALL;
 749         role = IPL_LOGALL;
 750 
 751         while ((c = getopt(argc, argv, "do:t:vz:")) != -1)
 752                 switch (c)
 753                 {
 754                 case 'd' :
 755                         opts |= OPT_DEBUG;
 756                         break;
 757                 case 'o' :
 758                         role = getrole(optarg);
 759                         if (role == IPL_LOGNONE) {
 760                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 761                                 return -1;
 762                         }
 763                         break;
 764                 case 't' :
 765                         type = gettype(optarg, NULL);
 766                         if (type == IPLT_NONE) {
 767                                 fprintf(stderr, "unknown type '%s'\n", optarg);
 768                                 return -1;
 769                         }
 770                         break;
 771                 case 'v' :
 772                         opts |= OPT_VERBOSE;
 773                         break;
 774                 case 'z' :
 775                         setzonename(optarg);
 776                         break;
 777                 }
 778 
 779         if (opts & OPT_DEBUG)
 780                 fprintf(stderr, "poolflush: opts = %#x\n", opts);
 781 
 782         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 783                 fd = open(IPLOOKUP_NAME, O_RDWR);
 784                 if (fd == -1) {
 785                         perror("open(IPLOOKUP_NAME)");
 786                         exit(1);
 787                 }
 788 
 789                 if (setzone(fd) != 0) {
 790                         close(fd);
 791                         exit(1);
 792                 }
 793         }
 794 
 795         bzero((char *)&flush, sizeof(flush));
 796         flush.iplf_type = type;
 797         flush.iplf_unit = role;
 798         flush.iplf_arg = arg;
 799 
 800         if (!(opts & OPT_DONOTHING)) {
 801                 if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
 802                         perror("ioctl(SIOCLOOKUPFLUSH)");
 803                         exit(1);
 804                 }
 805 
 806         }
 807         printf("%u object%s flushed\n", flush.iplf_count,
 808                (flush.iplf_count == 1) ? "" : "s");
 809 
 810         return 0;
 811 }
 812 
 813 
 814 int getrole(rolename)
 815 char *rolename;
 816 {
 817         int role;
 818 
 819         if (!strcasecmp(rolename, "ipf")) {
 820                 role = IPL_LOGIPF;
 821 #if 0
 822         } else if (!strcasecmp(rolename, "nat")) {
 823                 role = IPL_LOGNAT;
 824         } else if (!strcasecmp(rolename, "state")) {
 825                 role = IPL_LOGSTATE;
 826         } else if (!strcasecmp(rolename, "auth")) {
 827                 role = IPL_LOGAUTH;
 828         } else if (!strcasecmp(rolename, "sync")) {
 829                 role = IPL_LOGSYNC;
 830         } else if (!strcasecmp(rolename, "scan")) {
 831                 role = IPL_LOGSCAN;
 832         } else if (!strcasecmp(rolename, "pool")) {
 833                 role = IPL_LOGLOOKUP;
 834         } else if (!strcasecmp(rolename, "count")) {
 835                 role = IPL_LOGCOUNT;
 836 #endif
 837         } else {
 838                 role = IPL_LOGNONE;
 839         }
 840 
 841         return role;
 842 }
 843 
 844 
 845 int gettype(typename, minor)
 846 char *typename;
 847 u_int *minor;
 848 {
 849         int type;
 850 
 851         if (!strcasecmp(optarg, "tree")) {
 852                 type = IPLT_POOL;
 853         } else if (!strcasecmp(optarg, "hash")) {
 854                 type = IPLT_HASH;
 855                 if (minor != NULL)
 856                         *minor = IPHASH_LOOKUP;
 857         } else if (!strcasecmp(optarg, "group-map")) {
 858                 type = IPLT_HASH;
 859                 if (minor != NULL)
 860                         *minor = IPHASH_GROUPMAP;
 861         } else {
 862                 type = IPLT_NONE;
 863         }
 864         return type;
 865 }
 866 
 867 void showhashs_live(fd, role, htstp, poolname, opts)
 868 int fd, role;
 869 iphtstat_t *htstp;
 870 char *poolname;
 871 int opts;
 872 {
 873         ipflookupiter_t iter;
 874         iphtable_t table;
 875         ipfobj_t obj;
 876 
 877         obj.ipfo_rev = IPFILTER_VERSION;
 878         obj.ipfo_type = IPFOBJ_LOOKUPITER;
 879         obj.ipfo_size = sizeof(iter);
 880         obj.ipfo_ptr = &iter;
 881 
 882         iter.ili_type = IPLT_HASH;
 883         iter.ili_otype = IPFLOOKUPITER_LIST;
 884         iter.ili_ival = IPFGENITER_LOOKUP;
 885         iter.ili_data = &table;
 886         iter.ili_unit = role;
 887         *iter.ili_name = '\0';
 888 
 889         while (htstp->iphs_tables != NULL) {
 890                 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
 891                         perror("ioctl(SIOCLOOKUPITER)");
 892                         break;
 893                 }
 894 
 895                 printhash_live(&table, fd, poolname, opts);
 896 
 897                 htstp->iphs_tables = table.iph_next;
 898         }
 899 }