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