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 *plstp;
 387         ip_pool_stat_t  plstat;
 388         iphtstat_t  htstat;
 389         iphtable_t *hptr;
 390         iplookupop_t op;
 391         ip_pool_t *ptr;
 392 
 393         core = NULL;
 394         kernel = NULL;
 395         live_kernel = 1;
 396         type = IPLT_ALL;
 397         poolname = NULL;
 398         role = IPL_LOGALL;
 399 
 400         while ((c = getopt(argc, argv, "dG:m:M:N:o:Rt:vz:")) != -1)
 401                 switch (c)
 402                 {
 403                 case 'd' :
 404                         opts |= OPT_DEBUG;
 405                         break;
 406                 case 'G' :
 407                         setzonename_global(optarg);
 408                         break;
 409                 case 'm' :
 410                         poolname = optarg;
 411                         break;
 412                 case 'M' :
 413                         live_kernel = 0;
 414                         core = optarg;
 415                         break;
 416                 case 'N' :
 417                         live_kernel = 0;
 418                         kernel = optarg;
 419                         break;
 420                 case 'o' :
 421                         role = getrole(optarg);
 422                         if (role == IPL_LOGNONE) {
 423                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 424                                 return -1;
 425                         }
 426                         break;
 427                 case 'R' :
 428                         opts |= OPT_NORESOLVE;
 429                         break;
 430                 case 't' :
 431                         type = gettype(optarg, NULL);
 432                         if (type == IPLT_NONE) {
 433                                 fprintf(stderr, "unknown type '%s'\n", optarg);
 434                                 return -1;
 435                         }
 436                         break;
 437                 case 'v' :
 438                         opts |= OPT_VERBOSE;
 439                         break;
 440                 case 'z' :
 441                         setzonename(optarg);
 442                         break;
 443                 }
 444 
 445         if (opts & OPT_DEBUG)
 446                 fprintf(stderr, "poollist: opts = %#x\n", opts);
 447 
 448         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 449                 fd = open(IPLOOKUP_NAME, O_RDWR);
 450                 if (fd == -1) {
 451                         perror("open(IPLOOKUP_NAME)");
 452                         exit(1);
 453                 }
 454 
 455                 if (setzone(fd) != 0) {
 456                         close(fd);
 457                         exit(1);
 458                 }
 459         }
 460 
 461         bzero((char *)&op, sizeof(op));
 462         if (poolname != NULL) {
 463                 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
 464                 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
 465         }
 466         op.iplo_unit = role;
 467 
 468         if (live_kernel == 0) {
 469                 poollist_dead(role, poolname, type, kernel, core);
 470                 return (0);
 471         }
 472 
 473         if (type == IPLT_ALL || type == IPLT_POOL) {
 474                 op.iplo_type = IPLT_POOL;
 475                 op.iplo_size = sizeof(plstat);
 476                 op.iplo_struct = &plstat;
 477                 op.iplo_name[0] = '\0';
 478                 op.iplo_arg = 0;
 479 
 480                 if (role != IPL_LOGALL) {
 481                         op.iplo_unit = role;
 482 
 483                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 484                         if (c == -1) {
 485                                 perror("ioctl(SIOCLOOKUPSTAT)");
 486                                 return -1;
 487                         }
 488 
 489                         showpools_live(fd, role, &plstat, poolname, opts);
 490                 } else {
 491                         for (role = 0; role <= IPL_LOGMAX; role++) {
 492                                 op.iplo_unit = role;
 493 
 494                                 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 495                                 if (c == -1) {
 496                                         perror("ioctl(SIOCLOOKUPSTAT)");
 497                                         return -1;
 498                                 }
 499 
 500                                 showpools_live(fd, role, &plstat, poolname, opts);
 501                         }
 502 
 503                         role = IPL_LOGALL;
 504                 }
 505         }
 506         if (type == IPLT_ALL || type == IPLT_HASH) {
 507                 op.iplo_type = IPLT_HASH;
 508                 op.iplo_size = sizeof(htstat);
 509                 op.iplo_struct = &htstat;
 510                 op.iplo_name[0] = '\0';
 511                 op.iplo_arg = 0;
 512 
 513                 if (role != IPL_LOGALL) {
 514                         op.iplo_unit = role;
 515 
 516                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 517                         if (c == -1) {
 518                                 perror("ioctl(SIOCLOOKUPSTAT)");
 519                                 return -1;
 520                         }
 521                         showhashs_live(fd, role, &htstat, poolname, opts);
 522                 } else {
 523                         for (role = 0; role <= IPL_LOGMAX; role++) {
 524 
 525                                 op.iplo_unit = role;
 526                                 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 527                                 if (c == -1) {
 528                                         perror("ioctl(SIOCLOOKUPSTAT)");
 529                                         return -1;
 530                                 }
 531 
 532                                 showhashs_live(fd, role, &htstat, poolname, opts);
 533                         }
 534                 }
 535         }
 536         return 0;
 537 }
 538 
 539 void poollist_dead(role, poolname, type, kernel, core)
 540 int role, type;
 541 char *poolname, *kernel, *core;
 542 {
 543         iphtable_t *hptr;
 544         ip_pool_t *ptr;
 545 
 546         if (openkmem(kernel, core) == -1)
 547                 exit(-1);
 548 
 549         if (type == IPLT_ALL || type == IPLT_POOL) {
 550                 ip_pool_t *pools[IPL_LOGSIZE];
 551                 struct nlist names[2] = { { "ip_pool_list" } , { "" } };
 552 
 553                 if (nlist(kernel, names) != 1)
 554                         return;
 555 
 556                 bzero(&pools, sizeof(pools));
 557                 if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
 558                         return;
 559 
 560                 if (role != IPL_LOGALL) {
 561                         ptr = pools[role];
 562                         while (ptr != NULL) {
 563                                 ptr = printpool(ptr, kmemcpywrap,
 564                                                 poolname, opts);
 565                         }
 566                 } else {
 567                         for (role = 0; role <= IPL_LOGMAX; role++) {
 568                                 ptr = pools[role];
 569                                 while (ptr != NULL) {
 570                                         ptr = printpool(ptr, kmemcpywrap,
 571                                                         poolname, opts);
 572                                 }
 573                         }
 574                         role = IPL_LOGALL;
 575                 }
 576         }
 577         if (type == IPLT_ALL || type == IPLT_HASH) {
 578                 iphtable_t *tables[IPL_LOGSIZE];
 579                 struct nlist names[2] = { { "ipf_htables" } , { "" } };
 580 
 581                 if (nlist(kernel, names) != 1)
 582                         return;
 583 
 584                 bzero(&tables, sizeof(tables));
 585                 if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
 586                         return;
 587 
 588                 if (role != IPL_LOGALL) {
 589                         hptr = tables[role];
 590                         while (hptr != NULL) {
 591                                 hptr = printhash(hptr, kmemcpywrap,
 592                                                  poolname, opts);
 593                         }
 594                 } else {
 595                         for (role = 0; role <= IPL_LOGMAX; role++) {
 596                                 hptr = tables[role];
 597                                 while (hptr != NULL) {
 598                                         hptr = printhash(hptr, kmemcpywrap,
 599                                                          poolname, opts);
 600                                 }
 601                         }
 602                 }
 603         }
 604 }
 605 
 606 
 607 void
 608 showpools_live(fd, role, plstp, poolname, opts)
 609 int fd, role;
 610 ip_pool_stat_t *plstp;
 611 char *poolname;
 612 int opts;
 613 {
 614         ipflookupiter_t iter;
 615         ip_pool_t pool;
 616         ipfobj_t obj;
 617 
 618         obj.ipfo_rev = IPFILTER_VERSION;
 619         obj.ipfo_type = IPFOBJ_LOOKUPITER;
 620         obj.ipfo_size = sizeof(iter);
 621         obj.ipfo_ptr = &iter;
 622 
 623         iter.ili_type = IPLT_POOL;
 624         iter.ili_otype = IPFLOOKUPITER_LIST;
 625         iter.ili_ival = IPFGENITER_LOOKUP;
 626         iter.ili_data = &pool;
 627         iter.ili_unit = role;
 628         *iter.ili_name = '\0';
 629 
 630         while (plstp->ipls_list[role] != NULL) {
 631                 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
 632                         perror("ioctl(SIOCLOOKUPITER)");
 633                         break;
 634                 }
 635                 (void) printpool_live(&pool, fd, poolname, opts);
 636 
 637                 plstp->ipls_list[role] = pool.ipo_next;
 638         }
 639 }
 640 
 641 int poolstats(argc, argv)
 642 int argc;
 643 char *argv[];
 644 {
 645         int c, type, role;
 646         ip_pool_stat_t plstat;
 647         iphtstat_t htstat;
 648         iplookupop_t op;
 649 
 650         type = IPLT_ALL;
 651         role = IPL_LOGALL;
 652 
 653         bzero((char *)&op, sizeof(op));
 654 
 655         while ((c = getopt(argc, argv, "dG:M:N:o:t:vz:")) != -1)
 656                 switch (c)
 657                 {
 658                 case 'd' :
 659                         opts |= OPT_DEBUG;
 660                         break;
 661                 case 'G' :
 662                         setzonename_global(optarg);
 663                         break;
 664                 case 'M' :
 665                         break;
 666                 case 'N' :
 667                         break;
 668                 case 'o' :
 669                         role = getrole(optarg);
 670                         if (role == IPL_LOGNONE) {
 671                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 672                                 return -1;
 673                         }
 674                         break;
 675                 case 't' :
 676                         type = gettype(optarg, NULL);
 677                         if (type != IPLT_POOL) {
 678                                 fprintf(stderr,
 679                                         "-s not supported for this type yet\n");
 680                                 return -1;
 681                         }
 682                         break;
 683                 case 'v' :
 684                         opts |= OPT_VERBOSE;
 685                         break;
 686                 case 'z' :
 687                         setzonename(optarg);
 688                         break;
 689                 }
 690 
 691         if (opts & OPT_DEBUG)
 692                 fprintf(stderr, "poolstats: opts = %#x\n", opts);
 693 
 694         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 695                 fd = open(IPLOOKUP_NAME, O_RDWR);
 696                 if (fd == -1) {
 697                         perror("open(IPLOOKUP_NAME)");
 698                         exit(1);
 699                 }
 700 
 701                 if (setzone(fd) != 0) {
 702                         close(fd);
 703                         exit(1);
 704                 }
 705         }
 706 
 707         if (type == IPLT_ALL || type == IPLT_POOL) {
 708                 op.iplo_type = IPLT_POOL;
 709                 op.iplo_struct = &plstat;
 710                 op.iplo_size = sizeof(plstat);
 711                 if (!(opts & OPT_DONOTHING)) {
 712                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 713                         if (c == -1) {
 714                                 perror("ioctl(SIOCLOOKUPSTAT)");
 715                                 return -1;
 716                         }
 717                         printf("Pools:\t%lu\n", plstat.ipls_pools);
 718                         printf("Nodes:\t%lu\n", plstat.ipls_nodes);
 719                 }
 720         }
 721 
 722         if (type == IPLT_ALL || type == IPLT_HASH) {
 723                 op.iplo_type = IPLT_HASH;
 724                 op.iplo_struct = &htstat;
 725                 op.iplo_size = sizeof(htstat);
 726                 if (!(opts & OPT_DONOTHING)) {
 727                         c = ioctl(fd, SIOCLOOKUPSTAT, &op);
 728                         if (c == -1) {
 729                                 perror("ioctl(SIOCLOOKUPSTAT)");
 730                                 return -1;
 731                         }
 732                         printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
 733                         printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
 734                         printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
 735                 }
 736         }
 737         return 0;
 738 }
 739 
 740 
 741 int poolflush(argc, argv)
 742 int argc;
 743 char *argv[];
 744 {
 745         int c, role, type, arg;
 746         iplookupflush_t flush;
 747 
 748         arg = IPLT_ALL;
 749         type = IPLT_ALL;
 750         role = IPL_LOGALL;
 751 
 752         while ((c = getopt(argc, argv, "do:t:vz:")) != -1)
 753                 switch (c)
 754                 {
 755                 case 'd' :
 756                         opts |= OPT_DEBUG;
 757                         break;
 758                 case 'o' :
 759                         role = getrole(optarg);
 760                         if (role == IPL_LOGNONE) {
 761                                 fprintf(stderr, "unknown role '%s'\n", optarg);
 762                                 return -1;
 763                         }
 764                         break;
 765                 case 't' :
 766                         type = gettype(optarg, NULL);
 767                         if (type == IPLT_NONE) {
 768                                 fprintf(stderr, "unknown type '%s'\n", optarg);
 769                                 return -1;
 770                         }
 771                         break;
 772                 case 'v' :
 773                         opts |= OPT_VERBOSE;
 774                         break;
 775                 case 'z' :
 776                         setzonename(optarg);
 777                         break;
 778                 }
 779 
 780         if (opts & OPT_DEBUG)
 781                 fprintf(stderr, "poolflush: opts = %#x\n", opts);
 782 
 783         if (!(opts & OPT_DONOTHING) && (fd == -1)) {
 784                 fd = open(IPLOOKUP_NAME, O_RDWR);
 785                 if (fd == -1) {
 786                         perror("open(IPLOOKUP_NAME)");
 787                         exit(1);
 788                 }
 789 
 790                 if (setzone(fd) != 0) {
 791                         close(fd);
 792                         exit(1);
 793                 }
 794         }
 795 
 796         bzero((char *)&flush, sizeof(flush));
 797         flush.iplf_type = type;
 798         flush.iplf_unit = role;
 799         flush.iplf_arg = arg;
 800 
 801         if (!(opts & OPT_DONOTHING)) {
 802                 if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
 803                         perror("ioctl(SIOCLOOKUPFLUSH)");
 804                         exit(1);
 805                 }
 806 
 807         }
 808         printf("%u object%s flushed\n", flush.iplf_count,
 809                (flush.iplf_count == 1) ? "" : "s");
 810 
 811         return 0;
 812 }
 813 
 814 
 815 int getrole(rolename)
 816 char *rolename;
 817 {
 818         int role;
 819 
 820         if (!strcasecmp(rolename, "ipf")) {
 821                 role = IPL_LOGIPF;
 822 #if 0
 823         } else if (!strcasecmp(rolename, "nat")) {
 824                 role = IPL_LOGNAT;
 825         } else if (!strcasecmp(rolename, "state")) {
 826                 role = IPL_LOGSTATE;
 827         } else if (!strcasecmp(rolename, "auth")) {
 828                 role = IPL_LOGAUTH;
 829         } else if (!strcasecmp(rolename, "sync")) {
 830                 role = IPL_LOGSYNC;
 831         } else if (!strcasecmp(rolename, "scan")) {
 832                 role = IPL_LOGSCAN;
 833         } else if (!strcasecmp(rolename, "pool")) {
 834                 role = IPL_LOGLOOKUP;
 835         } else if (!strcasecmp(rolename, "count")) {
 836                 role = IPL_LOGCOUNT;
 837 #endif
 838         } else {
 839                 role = IPL_LOGNONE;
 840         }
 841 
 842         return role;
 843 }
 844 
 845 
 846 int gettype(typename, minor)
 847 char *typename;
 848 u_int *minor;
 849 {
 850         int type;
 851 
 852         if (!strcasecmp(optarg, "tree")) {
 853                 type = IPLT_POOL;
 854         } else if (!strcasecmp(optarg, "hash")) {
 855                 type = IPLT_HASH;
 856                 if (minor != NULL)
 857                         *minor = IPHASH_LOOKUP;
 858         } else if (!strcasecmp(optarg, "group-map")) {
 859                 type = IPLT_HASH;
 860                 if (minor != NULL)
 861                         *minor = IPHASH_GROUPMAP;
 862         } else {
 863                 type = IPLT_NONE;
 864         }
 865         return type;
 866 }
 867 
 868 void showhashs_live(fd, role, htstp, poolname, opts)
 869 int fd, role;
 870 iphtstat_t *htstp;
 871 char *poolname;
 872 int opts;
 873 {
 874         ipflookupiter_t iter;
 875         iphtable_t table;
 876         ipfobj_t obj;
 877 
 878         obj.ipfo_rev = IPFILTER_VERSION;
 879         obj.ipfo_type = IPFOBJ_LOOKUPITER;
 880         obj.ipfo_size = sizeof(iter);
 881         obj.ipfo_ptr = &iter;
 882 
 883         iter.ili_type = IPLT_HASH;
 884         iter.ili_otype = IPFLOOKUPITER_LIST;
 885         iter.ili_ival = IPFGENITER_LOOKUP;
 886         iter.ili_data = &table;
 887         iter.ili_unit = role;
 888         *iter.ili_name = '\0';
 889 
 890         while (htstp->iphs_tables != NULL) {
 891                 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
 892                         perror("ioctl(SIOCLOOKUPITER)");
 893                         break;
 894                 }
 895 
 896                 printhash_live(&table, fd, poolname, opts);
 897 
 898                 htstp->iphs_tables = table.iph_next;
 899         }
 900 }