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