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