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, "dm:M:N:o:t:v")) != -1) 674 switch (c) 675 { 676 case 'd' : 677 opts |= OPT_DEBUG; 678 break; 679 case 'm' : 680 poolname = optarg; 681 break; 682 case 'M' : 683 live_kernel = 0; 684 core = optarg; 685 break; 686 case 'N' : 687 live_kernel = 0; 688 kernel = optarg; 689 break; 690 case 'o' : 691 role = getrole(optarg); 692 if (role == IPL_LOGNONE) { 693 fprintf(stderr, "unknown role '%s'\n", optarg); 694 return (-1); 695 } 696 break; 697 #if 0 698 case 'O' : 699 /* XXX This option does not work. This function as */ 700 /* XXX used by state and nat can be used to format */ 701 /* XXX output especially useful for scripting. It */ 702 /* XXX is left here with the intention of making */ 703 /* XXX it work for the same purpose at some point. */ 704 pool_fields = parsefields(poolfields, optarg); 705 break; 706 #endif 707 case 't' : 708 type = gettype(optarg, NULL); 709 if (type == IPLT_NONE) { 710 fprintf(stderr, "unknown type '%s'\n", optarg); 711 return (-1); 712 } 713 break; 714 case 'v' : 715 opts |= OPT_VERBOSE; 716 break; 717 default : 718 usage(argv[0]); 719 break; /* keep compiler happy */ 720 } 721 722 if (argc - optind > 0) 723 usage(argv[0]); 724 725 if (opts & OPT_DEBUG) 726 fprintf(stderr, "poollist: opts = %#x\n", opts); 727 728 if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { 729 fd = open(IPLOOKUP_NAME, O_RDWR); 730 if (fd == -1) { 731 perror("open(IPLOOKUP_NAME)"); 732 exit(1); 733 } 734 } 735 736 bzero((char *)&op, sizeof(op)); 737 if (poolname != NULL) { 738 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name)); 739 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 740 } 741 op.iplo_unit = role; 742 743 if (live_kernel) 744 poollist_live(role, poolname, type, fd); 745 else 746 poollist_dead(role, poolname, type, kernel, core); 747 return (0); 748 } 749 750 751 void 752 poollist_dead(int role, char *poolname, int type, char *kernel, char *core) 753 { 754 iphtable_t *hptr; 755 ip_pool_t *ptr; 756 757 if (openkmem(kernel, core) == -1) 758 exit(-1); 759 760 if (type == IPLT_ALL || type == IPLT_POOL) { 761 ip_pool_t *pools[IPL_LOGSIZE]; 762 struct nlist names[2] = { { "ip_pool_list" } , { "" } }; 763 764 if (nlist(kernel, names) != 1) 765 return; 766 767 bzero(&pools, sizeof(pools)); 768 if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools))) 769 return; 770 771 if (role != IPL_LOGALL) { 772 ptr = pools[role]; 773 while (ptr != NULL) { 774 ptr = printpool(ptr, kmemcpywrap, poolname, 775 opts, pool_fields); 776 } 777 } else { 778 for (role = 0; role <= IPL_LOGMAX; role++) { 779 ptr = pools[role]; 780 while (ptr != NULL) { 781 ptr = printpool(ptr, kmemcpywrap, 782 poolname, opts, 783 pool_fields); 784 } 785 } 786 role = IPL_LOGALL; 787 } 788 } 789 if (type == IPLT_ALL || type == IPLT_HASH) { 790 iphtable_t *tables[IPL_LOGSIZE]; 791 struct nlist names[2] = { { "ipf_htables" } , { "" } }; 792 793 if (nlist(kernel, names) != 1) 794 return; 795 796 bzero(&tables, sizeof(tables)); 797 if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables))) 798 return; 799 800 if (role != IPL_LOGALL) { 801 hptr = tables[role]; 802 while (hptr != NULL) { 803 hptr = printhash(hptr, kmemcpywrap, 804 poolname, opts, pool_fields); 805 } 806 } else { 807 for (role = 0; role <= IPL_LOGMAX; role++) { 808 hptr = tables[role]; 809 while (hptr != NULL) { 810 hptr = printhash(hptr, kmemcpywrap, 811 poolname, opts, 812 pool_fields); 813 } 814 } 815 } 816 } 817 } 818 819 820 void 821 poollist_live(int role, char *poolname, int type, int fd) 822 { 823 ipf_pool_stat_t plstat; 824 iplookupop_t op; 825 int c; 826 827 if (type == IPLT_ALL || type == IPLT_POOL) { 828 op.iplo_type = IPLT_POOL; 829 op.iplo_size = sizeof(plstat); 830 op.iplo_struct = &plstat; 831 op.iplo_name[0] = '\0'; 832 op.iplo_arg = 0; 833 834 if (role != IPL_LOGALL) { 835 op.iplo_unit = role; 836 837 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 838 if (c == -1) { 839 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 840 return; 841 } 842 843 showpools_live(fd, role, &plstat, poolname); 844 } else { 845 for (role = -1; role <= IPL_LOGMAX; role++) { 846 op.iplo_unit = role; 847 848 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 849 if (c == -1) { 850 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 851 return; 852 } 853 854 showpools_live(fd, role, &plstat, poolname); 855 } 856 857 role = IPL_LOGALL; 858 } 859 } 860 861 if (type == IPLT_ALL || type == IPLT_HASH) { 862 iphtstat_t htstat; 863 864 op.iplo_type = IPLT_HASH; 865 op.iplo_size = sizeof(htstat); 866 op.iplo_struct = &htstat; 867 op.iplo_name[0] = '\0'; 868 op.iplo_arg = 0; 869 870 if (role != IPL_LOGALL) { 871 op.iplo_unit = role; 872 873 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 874 if (c == -1) { 875 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 876 return; 877 } 878 showhashs_live(fd, role, &htstat, poolname); 879 } else { 880 for (role = 0; role <= IPL_LOGMAX; role++) { 881 882 op.iplo_unit = role; 883 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 884 if (c == -1) { 885 ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); 886 return; 887 } 888 889 showhashs_live(fd, role, &htstat, poolname); 890 } 891 role = IPL_LOGALL; 892 } 893 } 894 895 if (type == IPLT_ALL || type == IPLT_DSTLIST) { 896 ipf_dstl_stat_t dlstat; 897 898 op.iplo_type = IPLT_DSTLIST; 899 op.iplo_size = sizeof(dlstat); 900 op.iplo_struct = &dlstat; 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 showdstls_live(fd, role, &dlstat, 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 showdstls_live(fd, role, &dlstat, poolname); 924 } 925 role = IPL_LOGALL; 926 } 927 } 928 } 929 930 931 void 932 showpools_live(int fd, int role, ipf_pool_stat_t *plstp, char *poolname) 933 { 934 ipflookupiter_t iter; 935 ip_pool_t pool; 936 ipfobj_t obj; 937 938 obj.ipfo_rev = IPFILTER_VERSION; 939 obj.ipfo_type = IPFOBJ_LOOKUPITER; 940 obj.ipfo_size = sizeof(iter); 941 obj.ipfo_ptr = &iter; 942 943 iter.ili_type = IPLT_POOL; 944 iter.ili_otype = IPFLOOKUPITER_LIST; 945 iter.ili_ival = IPFGENITER_LOOKUP; 946 iter.ili_nitems = 1; 947 iter.ili_data = &pool; 948 iter.ili_unit = role; 949 *iter.ili_name = '\0'; 950 951 bzero((char *)&pool, sizeof(pool)); 952 953 while (plstp->ipls_list[role + 1] != NULL) { 954 if (ioctl(fd, SIOCLOOKUPITER, &obj)) { 955 ipferror(fd, "ioctl(SIOCLOOKUPITER)"); 956 break; 957 } 958 if (((pool.ipo_flags & IPOOL_DELETE) == 0) || 959 ((opts & OPT_DEBUG) != 0)) 960 printpool_live(&pool, fd, poolname, opts, pool_fields); 961 962 plstp->ipls_list[role + 1] = pool.ipo_next; 963 } 964 } 965 966 967 void 968 showhashs_live(int fd, int role, iphtstat_t *htstp, char *poolname) 969 { 970 ipflookupiter_t iter; 971 iphtable_t table; 972 ipfobj_t obj; 973 974 obj.ipfo_rev = IPFILTER_VERSION; 975 obj.ipfo_type = IPFOBJ_LOOKUPITER; 976 obj.ipfo_size = sizeof(iter); 977 obj.ipfo_ptr = &iter; 978 979 iter.ili_type = IPLT_HASH; 980 iter.ili_otype = IPFLOOKUPITER_LIST; 981 iter.ili_ival = IPFGENITER_LOOKUP; 982 iter.ili_nitems = 1; 983 iter.ili_data = &table; 984 iter.ili_unit = role; 985 *iter.ili_name = '\0'; 986 987 while (htstp->iphs_tables != NULL) { 988 if (ioctl(fd, SIOCLOOKUPITER, &obj)) { 989 ipferror(fd, "ioctl(SIOCLOOKUPITER)"); 990 break; 991 } 992 993 printhash_live(&table, fd, poolname, opts, pool_fields); 994 995 htstp->iphs_tables = table.iph_next; 996 } 997 } 998 999 1000 void 1001 showdstls_live(int fd, int role, ipf_dstl_stat_t *dlstp, char *poolname) 1002 { 1003 ipflookupiter_t iter; 1004 ippool_dst_t table; 1005 ipfobj_t obj; 1006 1007 obj.ipfo_rev = IPFILTER_VERSION; 1008 obj.ipfo_type = IPFOBJ_LOOKUPITER; 1009 obj.ipfo_size = sizeof(iter); 1010 obj.ipfo_ptr = &iter; 1011 1012 iter.ili_type = IPLT_DSTLIST; 1013 iter.ili_otype = IPFLOOKUPITER_LIST; 1014 iter.ili_ival = IPFGENITER_LOOKUP; 1015 iter.ili_nitems = 1; 1016 iter.ili_data = &table; 1017 iter.ili_unit = role; 1018 *iter.ili_name = '\0'; 1019 1020 while (dlstp->ipls_list[role] != NULL) { 1021 if (ioctl(fd, SIOCLOOKUPITER, &obj)) { 1022 ipferror(fd, "ioctl(SIOCLOOKUPITER)"); 1023 break; 1024 } 1025 1026 printdstl_live(&table, fd, poolname, opts, pool_fields); 1027 1028 dlstp->ipls_list[role] = table.ipld_next; 1029 } 1030 } 1031 1032 1033 int 1034 setnodeaddr(int type, int role, void *ptr, char *arg) 1035 { 1036 struct in_addr mask; 1037 sa_family_t family; 1038 char *s; 1039 1040 if (strchr(arg, ':') == NULL) { 1041 family = AF_INET; 1042 s = strchr(arg, '/'); 1043 if (s == NULL) 1044 mask.s_addr = 0xffffffff; 1045 else if (strchr(s, '.') == NULL) { 1046 if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0) 1047 return (-1); 1048 } else { 1049 mask.s_addr = inet_addr(s + 1); 1050 } 1051 if (s != NULL) 1052 *s = '\0'; 1053 } else { 1054 family = AF_INET6; 1055 1056 /* XXX for now we use mask for IPv6 prefix length */ 1057 /* XXX mask should be a union with prefix */ 1058 /* XXX Currently address handling is sloppy. */ 1059 1060 if ((s = strchr(arg, '/')) == NULL) 1061 mask.s_addr = 128; 1062 else 1063 mask.s_addr = atoi(s + 1); 1064 } 1065 1066 if (type == IPLT_POOL) { 1067 ip_pool_node_t *node = ptr; 1068 1069 node->ipn_addr.adf_family = family; 1070 1071 #ifdef USE_INET6 1072 if (node->ipn_addr.adf_family == AF_INET) { 1073 #endif 1074 node->ipn_addr.adf_len = offsetof(addrfamily_t, 1075 adf_addr) + 1076 sizeof(struct in_addr); 1077 node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); 1078 #ifdef USE_INET6 1079 } else { 1080 node->ipn_addr.adf_len = offsetof(addrfamily_t, 1081 adf_addr) + 1082 sizeof(struct in6_addr); 1083 inet_pton(AF_INET6, arg, 1084 &node->ipn_addr.adf_addr.in6.s6_addr); 1085 } 1086 #endif 1087 node->ipn_mask.adf_len = node->ipn_addr.adf_len; 1088 node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr; 1089 } else if (type == IPLT_HASH) { 1090 iphtent_t *node = ptr; 1091 1092 node->ipe_family = family; 1093 node->ipe_unit = role; 1094 1095 #ifdef USE_INET6 1096 if (node->ipe_family == AF_INET) { 1097 #endif 1098 node->ipe_addr.in4.s_addr = inet_addr(arg); 1099 node->ipe_mask.in4.s_addr = mask.s_addr; 1100 #ifdef USE_INET6 1101 } else { 1102 inet_pton(AF_INET6, arg, 1103 &node->ipe_addr.in6.__u6_addr.__u6_addr32); 1104 node->ipe_mask.in6.__u6_addr.__u6_addr32[0] = 1105 mask.s_addr; 1106 node->ipe_mask.in6.__u6_addr.__u6_addr32[1] = 1107 node->ipe_mask.in6.__u6_addr.__u6_addr32[2] = 1108 node->ipe_mask.in6.__u6_addr.__u6_addr32[3] = 0; 1109 } 1110 #endif 1111 } 1112 1113 return (0); 1114 } 1115