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