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