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 void 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 void showpools_live(int, int, ipf_pool_stat_t *, char *); 57 void showhashs_live(int, int, iphtstat_t *, char *); 58 void 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(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]\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: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 254 int 255 poolcommand(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 377 int 378 loadpoolfile(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 429 int 430 poolstats(argc, argv) 431 int argc; 432 char *argv[]; 433 { 434 int c, type, role; 435 ipf_pool_stat_t plstat; 436 ipf_dstl_stat_t dlstat; 437 iphtstat_t htstat; 438 iplookupop_t op; 439 440 type = IPLT_ALL; 441 role = IPL_LOGALL; 442 443 bzero((char *)&op, sizeof(op)); 444 445 while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1) 446 switch (c) 447 { 448 case 'd' : 449 opts |= OPT_DEBUG; 450 break; 451 case 'o' : 452 role = getrole(optarg); 453 if (role == IPL_LOGNONE) { 454 fprintf(stderr, "unknown role '%s'\n", optarg); 455 return -1; 456 } 457 break; 458 case 't' : 459 type = gettype(optarg, NULL); 460 if (type != IPLT_POOL) { 461 fprintf(stderr, 462 "-s not supported for this type yet\n"); 463 return -1; 464 } 465 break; 466 case 'v' : 467 opts |= OPT_VERBOSE; 468 break; 469 default : 470 usage(argv[0]); 471 break; /* keep compiler happy */ 472 } 473 474 if (argc - 1 - optind > 0) 475 usage(argv[0]); 476 477 if (opts & OPT_DEBUG) 478 fprintf(stderr, "poolstats: opts = %#x\n", opts); 479 480 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { 481 fd = open(IPLOOKUP_NAME, O_RDWR); 482 if (fd == -1) { 483 perror("open(IPLOOKUP_NAME)"); 484 exit(1); 485 } 486 } 487 488 if (type == IPLT_ALL || type == IPLT_POOL) { 489 op.iplo_type = IPLT_POOL; 490 op.iplo_struct = &plstat; 491 op.iplo_size = sizeof(plstat); 492 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { 493 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 494 if (c == -1) { 495 ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)"); 496 return -1; 497 } 498 printf("%lu\taddress pools\n", plstat.ipls_pools); 499 printf("%lu\taddress pool nodes\n", plstat.ipls_nodes); 500 } 501 } 502 503 if (type == IPLT_ALL || type == IPLT_HASH) { 504 op.iplo_type = IPLT_HASH; 505 op.iplo_struct = &htstat; 506 op.iplo_size = sizeof(htstat); 507 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { 508 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 509 if (c == -1) { 510 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 511 return -1; 512 } 513 printf("%lu\thash tables\n", htstat.iphs_numtables); 514 printf("%lu\thash table nodes\n", htstat.iphs_numnodes); 515 printf("%lu\thash table no memory \n", 516 htstat.iphs_nomem); 517 } 518 } 519 520 if (type == IPLT_ALL || type == IPLT_DSTLIST) { 521 op.iplo_type = IPLT_DSTLIST; 522 op.iplo_struct = &dlstat; 523 op.iplo_size = sizeof(dlstat); 524 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { 525 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 526 if (c == -1) { 527 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 528 return -1; 529 } 530 printf("%u\tdestination lists\n", 531 dlstat.ipls_numlists); 532 printf("%u\tdestination list nodes\n", 533 dlstat.ipls_numnodes); 534 printf("%lu\tdestination list no memory\n", 535 dlstat.ipls_nomem); 536 printf("%u\tdestination list zombies\n", 537 dlstat.ipls_numdereflists); 538 printf("%u\tdesetination list node zombies\n", 539 dlstat.ipls_numderefnodes); 540 } 541 } 542 return 0; 543 } 544 545 546 int 547 poolflush(argc, argv) 548 int argc; 549 char *argv[]; 550 { 551 int c, role, type, arg; 552 iplookupflush_t flush; 553 554 arg = IPLT_ALL; 555 type = IPLT_ALL; 556 role = IPL_LOGALL; 557 558 while ((c = getopt(argc, argv, "do:t:v")) != -1) 559 switch (c) 560 { 561 case 'd' : 562 opts |= OPT_DEBUG; 563 break; 564 case 'o' : 565 role = getrole(optarg); 566 if (role == IPL_LOGNONE) { 567 fprintf(stderr, "unknown role '%s'\n", optarg); 568 return -1; 569 } 570 break; 571 case 't' : 572 type = gettype(optarg, NULL); 573 if (type == IPLT_NONE) { 574 fprintf(stderr, "unknown type '%s'\n", optarg); 575 return -1; 576 } 577 break; 578 case 'v' : 579 opts |= OPT_VERBOSE; 580 break; 581 default : 582 usage(argv[0]); 583 break; /* keep compiler happy */ 584 } 585 586 if (argc - optind > 0) 587 usage(argv[0]); 588 589 if (opts & OPT_DEBUG) 590 fprintf(stderr, "poolflush: opts = %#x\n", opts); 591 592 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { 593 fd = open(IPLOOKUP_NAME, O_RDWR); 594 if (fd == -1) { 595 perror("open(IPLOOKUP_NAME)"); 596 exit(1); 597 } 598 } 599 600 bzero((char *)&flush, sizeof(flush)); 601 flush.iplf_type = type; 602 flush.iplf_unit = role; 603 flush.iplf_arg = arg; 604 605 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { 606 if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) { 607 ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)"); 608 exit(1); 609 } 610 611 } 612 printf("%u object%s flushed\n", flush.iplf_count, 613 (flush.iplf_count == 1) ? "" : "s"); 614 615 return 0; 616 } 617 618 619 int 620 getrole(rolename) 621 char *rolename; 622 { 623 int role; 624 625 if (!strcasecmp(rolename, "ipf")) { 626 role = IPL_LOGIPF; 627 #if 0 628 } else if (!strcasecmp(rolename, "nat")) { 629 role = IPL_LOGNAT; 630 } else if (!strcasecmp(rolename, "state")) { 631 role = IPL_LOGSTATE; 632 } else if (!strcasecmp(rolename, "auth")) { 633 role = IPL_LOGAUTH; 634 } else if (!strcasecmp(rolename, "sync")) { 635 role = IPL_LOGSYNC; 636 } else if (!strcasecmp(rolename, "scan")) { 637 role = IPL_LOGSCAN; 638 } else if (!strcasecmp(rolename, "pool")) { 639 role = IPL_LOGLOOKUP; 640 } else if (!strcasecmp(rolename, "count")) { 641 role = IPL_LOGCOUNT; 642 #endif 643 } else { 644 role = IPL_LOGNONE; 645 } 646 647 return role; 648 } 649 650 651 int 652 gettype(typename, minor) 653 char *typename; 654 u_int *minor; 655 { 656 int type; 657 658 if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) { 659 type = IPLT_POOL; 660 } else if (!strcasecmp(typename, "hash")) { 661 type = IPLT_HASH; 662 if (minor != NULL) 663 *minor = IPHASH_LOOKUP; 664 } else if (!strcasecmp(typename, "group-map")) { 665 type = IPLT_HASH; 666 if (minor != NULL) 667 *minor = IPHASH_GROUPMAP; 668 } else { 669 type = IPLT_NONE; 670 } 671 return type; 672 } 673 674 675 int 676 poollist(argc, argv) 677 int argc; 678 char *argv[]; 679 { 680 char *kernel, *core, *poolname; 681 int c, role, type, live_kernel; 682 iplookupop_t op; 683 684 core = NULL; 685 kernel = NULL; 686 live_kernel = 1; 687 type = IPLT_ALL; 688 poolname = NULL; 689 role = IPL_LOGALL; 690 691 while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1) 692 switch (c) 693 { 694 case 'd' : 695 opts |= OPT_DEBUG; 696 break; 697 case 'm' : 698 poolname = optarg; 699 break; 700 case 'M' : 701 live_kernel = 0; 702 core = optarg; 703 break; 704 case 'N' : 705 live_kernel = 0; 706 kernel = optarg; 707 break; 708 case 'o' : 709 role = getrole(optarg); 710 if (role == IPL_LOGNONE) { 711 fprintf(stderr, "unknown role '%s'\n", optarg); 712 return -1; 713 } 714 break; 715 #if 0 716 case 'O' : 717 /* XXX This option does not work. This function as */ 718 /* XXX used by state and nat can be used to format */ 719 /* XXX output especially useful for scripting. It */ 720 /* XXX is left here with the intention of making */ 721 /* XXX it work for the same purpose at some point. */ 722 pool_fields = parsefields(poolfields, optarg); 723 break; 724 #endif 725 case 't' : 726 type = gettype(optarg, NULL); 727 if (type == IPLT_NONE) { 728 fprintf(stderr, "unknown type '%s'\n", optarg); 729 return -1; 730 } 731 break; 732 case 'v' : 733 opts |= OPT_VERBOSE; 734 break; 735 default : 736 usage(argv[0]); 737 break; /* keep compiler happy */ 738 } 739 740 if (argc - optind > 0) 741 usage(argv[0]); 742 743 if (opts & OPT_DEBUG) 744 fprintf(stderr, "poollist: opts = %#x\n", opts); 745 746 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { 747 fd = open(IPLOOKUP_NAME, O_RDWR); 748 if (fd == -1) { 749 perror("open(IPLOOKUP_NAME)"); 750 exit(1); 751 } 752 } 753 754 bzero((char *)&op, sizeof(op)); 755 if (poolname != NULL) { 756 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name)); 757 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 758 } 759 op.iplo_unit = role; 760 761 if (live_kernel) 762 poollist_live(role, poolname, type, fd); 763 else 764 poollist_dead(role, poolname, type, kernel, core); 765 return 0; 766 } 767 768 769 void 770 poollist_dead(role, poolname, type, kernel, core) 771 int role, type; 772 char *poolname, *kernel, *core; 773 { 774 iphtable_t *hptr; 775 ip_pool_t *ptr; 776 777 if (openkmem(kernel, core) == -1) 778 exit(-1); 779 780 if (type == IPLT_ALL || type == IPLT_POOL) { 781 ip_pool_t *pools[IPL_LOGSIZE]; 782 struct nlist names[2] = { { "ip_pool_list" } , { "" } }; 783 784 if (nlist(kernel, names) != 1) 785 return; 786 787 bzero(&pools, sizeof(pools)); 788 if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools))) 789 return; 790 791 if (role != IPL_LOGALL) { 792 ptr = pools[role]; 793 while (ptr != NULL) { 794 ptr = printpool(ptr, kmemcpywrap, poolname, 795 opts, pool_fields); 796 } 797 } else { 798 for (role = 0; role <= IPL_LOGMAX; role++) { 799 ptr = pools[role]; 800 while (ptr != NULL) { 801 ptr = printpool(ptr, kmemcpywrap, 802 poolname, opts, 803 pool_fields); 804 } 805 } 806 role = IPL_LOGALL; 807 } 808 } 809 if (type == IPLT_ALL || type == IPLT_HASH) { 810 iphtable_t *tables[IPL_LOGSIZE]; 811 struct nlist names[2] = { { "ipf_htables" } , { "" } }; 812 813 if (nlist(kernel, names) != 1) 814 return; 815 816 bzero(&tables, sizeof(tables)); 817 if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables))) 818 return; 819 820 if (role != IPL_LOGALL) { 821 hptr = tables[role]; 822 while (hptr != NULL) { 823 hptr = printhash(hptr, kmemcpywrap, 824 poolname, opts, pool_fields); 825 } 826 } else { 827 for (role = 0; role <= IPL_LOGMAX; role++) { 828 hptr = tables[role]; 829 while (hptr != NULL) { 830 hptr = printhash(hptr, kmemcpywrap, 831 poolname, opts, 832 pool_fields); 833 } 834 } 835 } 836 } 837 } 838 839 840 void 841 poollist_live(role, poolname, type, fd) 842 int role, type, fd; 843 char *poolname; 844 { 845 ipf_pool_stat_t plstat; 846 iplookupop_t op; 847 int c; 848 849 if (type == IPLT_ALL || type == IPLT_POOL) { 850 op.iplo_type = IPLT_POOL; 851 op.iplo_size = sizeof(plstat); 852 op.iplo_struct = &plstat; 853 op.iplo_name[0] = '\0'; 854 op.iplo_arg = 0; 855 856 if (role != IPL_LOGALL) { 857 op.iplo_unit = role; 858 859 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 860 if (c == -1) { 861 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 862 return; 863 } 864 865 showpools_live(fd, role, &plstat, poolname); 866 } else { 867 for (role = -1; role <= IPL_LOGMAX; role++) { 868 op.iplo_unit = role; 869 870 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 871 if (c == -1) { 872 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 873 return; 874 } 875 876 showpools_live(fd, role, &plstat, poolname); 877 } 878 879 role = IPL_LOGALL; 880 } 881 } 882 883 if (type == IPLT_ALL || type == IPLT_HASH) { 884 iphtstat_t htstat; 885 886 op.iplo_type = IPLT_HASH; 887 op.iplo_size = sizeof(htstat); 888 op.iplo_struct = &htstat; 889 op.iplo_name[0] = '\0'; 890 op.iplo_arg = 0; 891 892 if (role != IPL_LOGALL) { 893 op.iplo_unit = role; 894 895 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 896 if (c == -1) { 897 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 898 return; 899 } 900 showhashs_live(fd, role, &htstat, poolname); 901 } else { 902 for (role = 0; role <= IPL_LOGMAX; role++) { 903 904 op.iplo_unit = role; 905 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 906 if (c == -1) { 907 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 908 return; 909 } 910 911 showhashs_live(fd, role, &htstat, poolname); 912 } 913 role = IPL_LOGALL; 914 } 915 } 916 917 if (type == IPLT_ALL || type == IPLT_DSTLIST) { 918 ipf_dstl_stat_t dlstat; 919 920 op.iplo_type = IPLT_DSTLIST; 921 op.iplo_size = sizeof(dlstat); 922 op.iplo_struct = &dlstat; 923 op.iplo_name[0] = '\0'; 924 op.iplo_arg = 0; 925 926 if (role != IPL_LOGALL) { 927 op.iplo_unit = role; 928 929 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 930 if (c == -1) { 931 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 932 return; 933 } 934 showdstls_live(fd, role, &dlstat, poolname); 935 } else { 936 for (role = 0; role <= IPL_LOGMAX; role++) { 937 938 op.iplo_unit = role; 939 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 940 if (c == -1) { 941 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 942 return; 943 } 944 945 showdstls_live(fd, role, &dlstat, poolname); 946 } 947 role = IPL_LOGALL; 948 } 949 } 950 } 951 952 953 void 954 showpools_live(fd, role, plstp, poolname) 955 int fd, role; 956 ipf_pool_stat_t *plstp; 957 char *poolname; 958 { 959 ipflookupiter_t iter; 960 ip_pool_t pool; 961 ipfobj_t obj; 962 963 obj.ipfo_rev = IPFILTER_VERSION; 964 obj.ipfo_type = IPFOBJ_LOOKUPITER; 965 obj.ipfo_size = sizeof(iter); 966 obj.ipfo_ptr = &iter; 967 968 iter.ili_type = IPLT_POOL; 969 iter.ili_otype = IPFLOOKUPITER_LIST; 970 iter.ili_ival = IPFGENITER_LOOKUP; 971 iter.ili_nitems = 1; 972 iter.ili_data = &pool; 973 iter.ili_unit = role; 974 *iter.ili_name = '\0'; 975 976 bzero((char *)&pool, sizeof(pool)); 977 978 while (plstp->ipls_list[role + 1] != NULL) { 979 if (ioctl(fd, SIOCLOOKUPITER, &obj)) { 980 ipferror(fd, "ioctl(SIOCLOOKUPITER)"); 981 break; 982 } 983 if (((pool.ipo_flags & IPOOL_DELETE) == 0) || 984 ((opts & OPT_DEBUG) != 0)) 985 printpool_live(&pool, fd, poolname, opts, pool_fields); 986 987 plstp->ipls_list[role + 1] = pool.ipo_next; 988 } 989 } 990 991 992 void 993 showhashs_live(fd, role, htstp, poolname) 994 int fd, role; 995 iphtstat_t *htstp; 996 char *poolname; 997 { 998 ipflookupiter_t iter; 999 iphtable_t table; 1000 ipfobj_t obj; 1001 1002 obj.ipfo_rev = IPFILTER_VERSION; 1003 obj.ipfo_type = IPFOBJ_LOOKUPITER; 1004 obj.ipfo_size = sizeof(iter); 1005 obj.ipfo_ptr = &iter; 1006 1007 iter.ili_type = IPLT_HASH; 1008 iter.ili_otype = IPFLOOKUPITER_LIST; 1009 iter.ili_ival = IPFGENITER_LOOKUP; 1010 iter.ili_nitems = 1; 1011 iter.ili_data = &table; 1012 iter.ili_unit = role; 1013 *iter.ili_name = '\0'; 1014 1015 while (htstp->iphs_tables != NULL) { 1016 if (ioctl(fd, SIOCLOOKUPITER, &obj)) { 1017 ipferror(fd, "ioctl(SIOCLOOKUPITER)"); 1018 break; 1019 } 1020 1021 printhash_live(&table, fd, poolname, opts, pool_fields); 1022 1023 htstp->iphs_tables = table.iph_next; 1024 } 1025 } 1026 1027 1028 void 1029 showdstls_live(fd, role, dlstp, poolname) 1030 int fd, role; 1031 ipf_dstl_stat_t *dlstp; 1032 char *poolname; 1033 { 1034 ipflookupiter_t iter; 1035 ippool_dst_t table; 1036 ipfobj_t obj; 1037 1038 obj.ipfo_rev = IPFILTER_VERSION; 1039 obj.ipfo_type = IPFOBJ_LOOKUPITER; 1040 obj.ipfo_size = sizeof(iter); 1041 obj.ipfo_ptr = &iter; 1042 1043 iter.ili_type = IPLT_DSTLIST; 1044 iter.ili_otype = IPFLOOKUPITER_LIST; 1045 iter.ili_ival = IPFGENITER_LOOKUP; 1046 iter.ili_nitems = 1; 1047 iter.ili_data = &table; 1048 iter.ili_unit = role; 1049 *iter.ili_name = '\0'; 1050 1051 while (dlstp->ipls_list[role] != NULL) { 1052 if (ioctl(fd, SIOCLOOKUPITER, &obj)) { 1053 ipferror(fd, "ioctl(SIOCLOOKUPITER)"); 1054 break; 1055 } 1056 1057 printdstl_live(&table, fd, poolname, opts, pool_fields); 1058 1059 dlstp->ipls_list[role] = table.ipld_next; 1060 } 1061 } 1062 1063 1064 int 1065 setnodeaddr(int type, int role, void *ptr, char *arg) 1066 { 1067 struct in_addr mask; 1068 sa_family_t family; 1069 char *s; 1070 1071 if (strchr(arg, ':') == NULL) { 1072 family = AF_INET; 1073 s = strchr(arg, '/'); 1074 if (s == NULL) 1075 mask.s_addr = 0xffffffff; 1076 else if (strchr(s, '.') == NULL) { 1077 if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0) 1078 return -1; 1079 } else { 1080 mask.s_addr = inet_addr(s + 1); 1081 } 1082 if (s != NULL) 1083 *s = '\0'; 1084 } else { 1085 family = AF_INET6; 1086 1087 /* XXX for now we use mask for IPv6 prefix length */ 1088 /* XXX mask should be a union with prefix */ 1089 /* XXX Currently address handling is sloppy. */ 1090 1091 if ((s = strchr(arg, '/')) == NULL) 1092 mask.s_addr = 128; 1093 else 1094 mask.s_addr = atoi(s + 1); 1095 } 1096 1097 if (type == IPLT_POOL) { 1098 ip_pool_node_t *node = ptr; 1099 1100 node->ipn_addr.adf_family = family; 1101 1102 #ifdef USE_INET6 1103 if (node->ipn_addr.adf_family == AF_INET) { 1104 #endif 1105 node->ipn_addr.adf_len = offsetof(addrfamily_t, 1106 adf_addr) + 1107 sizeof(struct in_addr); 1108 node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); 1109 #ifdef USE_INET6 1110 } else { 1111 node->ipn_addr.adf_len = offsetof(addrfamily_t, 1112 adf_addr) + 1113 sizeof(struct in6_addr); 1114 inet_pton(AF_INET6, arg, 1115 &node->ipn_addr.adf_addr.in6.s6_addr); 1116 } 1117 #endif 1118 node->ipn_mask.adf_len = node->ipn_addr.adf_len; 1119 node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr; 1120 } else if (type == IPLT_HASH) { 1121 iphtent_t *node = ptr; 1122 1123 node->ipe_family = family; 1124 node->ipe_unit = role; 1125 1126 #ifdef USE_INET6 1127 if (node->ipe_family == AF_INET) { 1128 #endif 1129 node->ipe_addr.in4.s_addr = inet_addr(arg); 1130 node->ipe_mask.in4.s_addr = mask.s_addr; 1131 #ifdef USE_INET6 1132 } else { 1133 inet_pton(AF_INET6, arg, 1134 &node->ipe_addr.in6.__u6_addr.__u6_addr32); 1135 node->ipe_mask.in6.__u6_addr.__u6_addr32[0] = 1136 mask.s_addr; 1137 node->ipe_mask.in6.__u6_addr.__u6_addr32[1] = 1138 node->ipe_mask.in6.__u6_addr.__u6_addr32[2] = 1139 node->ipe_mask.in6.__u6_addr.__u6_addr32[3] = 0; 1140 } 1141 #endif 1142 } 1143 1144 return 0; 1145 } 1146