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