1 /* 2 * Copyright (C) 2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 7 * Use is subject to license terms. 8 */ 9 10 #pragma ident "%Z%%M% %I% %E% SMI" 11 12 #include <sys/types.h> 13 #include <sys/time.h> 14 #include <sys/param.h> 15 #include <sys/socket.h> 16 #if defined(BSD) && (BSD >= 199306) 17 # include <sys/cdefs.h> 18 #endif 19 #include <sys/ioctl.h> 20 21 #include <net/if.h> 22 #if __FreeBSD_version >= 300000 23 # include <net/if_var.h> 24 #endif 25 #include <netinet/in.h> 26 27 #include <arpa/inet.h> 28 29 #include <stdio.h> 30 #include <fcntl.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <netdb.h> 34 #include <ctype.h> 35 #include <unistd.h> 36 37 #include "ipf.h" 38 #include "netinet/ip_lookup.h" 39 #include "netinet/ip_pool.h" 40 #include "netinet/ip_htable.h" 41 #include "kmem.h" 42 43 44 extern int ippool_yyparse __P((void)); 45 extern int ippool_yydebug; 46 extern FILE *ippool_yyin; 47 extern char *optarg; 48 extern int lineNum; 49 50 void showpools __P((ip_pool_stat_t *)); 51 void usage __P((char *)); 52 int main __P((int, char **)); 53 int poolcommand __P((int, int, char *[])); 54 int poolnodecommand __P((int, int, char *[])); 55 int loadpoolfile __P((int, char *[], char *)); 56 int poollist __P((int, char *[])); 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 62 int opts = 0; 63 int fd = -1; 64 int use_inet6 = 0; 65 66 67 void usage(prog) 68 char *prog; 69 { 70 fprintf(stderr, "Usage:\t%s\n", prog); 71 fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); 72 fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n"); 73 fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n"); 74 fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n"); 75 fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n"); 76 fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); 77 fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n"); 78 fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n"); 79 exit(1); 80 } 81 82 83 int main(argc, argv) 84 int argc; 85 char *argv[]; 86 { 87 int err; 88 89 if (argc < 2) 90 usage(argv[0]); 91 92 switch (getopt(argc, argv, "aAf:FlrRs")) 93 { 94 case 'a' : 95 err = poolnodecommand(0, argc, argv); 96 break; 97 case 'A' : 98 err = poolcommand(0, argc, argv); 99 break; 100 case 'f' : 101 err = loadpoolfile(argc, argv, optarg); 102 break; 103 case 'F' : 104 err = poolflush(argc, argv); 105 break; 106 case 'l' : 107 err = poollist(argc, argv); 108 break; 109 case 'r' : 110 err = poolnodecommand(1, argc, argv); 111 break; 112 case 'R' : 113 err = poolcommand(1, argc, argv); 114 break; 115 case 's' : 116 err = poolstats(argc, argv); 117 break; 118 default : 119 exit(1); 120 } 121 122 return err; 123 } 124 125 126 int poolnodecommand(remove, argc, argv) 127 int remove, argc; 128 char *argv[]; 129 { 130 char *poolname = NULL, *s; 131 int err, c, ipset, role; 132 ip_pool_node_t node; 133 struct in_addr mask; 134 135 ipset = 0; 136 role = IPL_LOGIPF; 137 bzero((char *)&node, sizeof(node)); 138 139 while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1) 140 switch (c) 141 { 142 case 'd' : 143 opts |= OPT_DEBUG; 144 ippool_yydebug++; 145 break; 146 case 'i' : 147 s = strchr(optarg, '/'); 148 if (s == NULL) 149 mask.s_addr = 0xffffffff; 150 else if (strchr(s, '.') == NULL) { 151 if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0) 152 return -1; 153 } else { 154 mask.s_addr = inet_addr(s + 1); 155 } 156 if (s != NULL) 157 *s = '\0'; 158 ipset = 1; 159 node.ipn_addr.adf_len = sizeof(node.ipn_addr); 160 node.ipn_addr.adf_addr.in4.s_addr = inet_addr(optarg); 161 node.ipn_mask.adf_len = sizeof(node.ipn_mask); 162 node.ipn_mask.adf_addr.in4.s_addr = mask.s_addr; 163 break; 164 case 'm' : 165 poolname = optarg; 166 break; 167 case 'n' : 168 opts |= OPT_DONOTHING; 169 break; 170 case 'o' : 171 role = getrole(optarg); 172 if (role == IPL_LOGNONE) 173 return -1; 174 break; 175 case 'R' : 176 opts |= OPT_NORESOLVE; 177 break; 178 case 'v' : 179 opts |= OPT_VERBOSE; 180 break; 181 } 182 183 if (opts & OPT_DEBUG) 184 fprintf(stderr, "poolnodecommand: opts = %#x\n", opts); 185 186 if (ipset == 0) 187 return -1; 188 if (poolname == NULL) { 189 fprintf(stderr, "poolname not given with add/remove node\n"); 190 return -1; 191 } 192 193 if (remove == 0) 194 err = load_poolnode(0, poolname, &node, ioctl); 195 else 196 err = remove_poolnode(0, poolname, &node, ioctl); 197 return err; 198 } 199 200 201 int poolcommand(remove, argc, argv) 202 int remove, argc; 203 char *argv[]; 204 { 205 int type, role, c, err; 206 char *poolname; 207 iphtable_t iph; 208 ip_pool_t pool; 209 210 err = 1; 211 role = 0; 212 type = 0; 213 poolname = NULL; 214 role = IPL_LOGIPF; 215 bzero((char *)&iph, sizeof(iph)); 216 bzero((char *)&pool, sizeof(pool)); 217 218 while ((c = getopt(argc, argv, "dm:no:RS:t:v")) != -1) 219 switch (c) 220 { 221 case 'd' : 222 opts |= OPT_DEBUG; 223 ippool_yydebug++; 224 break; 225 case 'm' : 226 poolname = optarg; 227 break; 228 case 'n' : 229 opts |= OPT_DONOTHING; 230 break; 231 case 'o' : 232 role = getrole(optarg); 233 if (role == IPL_LOGNONE) { 234 fprintf(stderr, "unknown role '%s'\n", optarg); 235 return -1; 236 } 237 break; 238 case 'R' : 239 opts |= OPT_NORESOLVE; 240 break; 241 case 'S' : 242 iph.iph_seed = atoi(optarg); 243 break; 244 case 't' : 245 type = gettype(optarg, &iph.iph_type); 246 if (type == IPLT_NONE) { 247 fprintf(stderr, "unknown type '%s'\n", optarg); 248 return -1; 249 } 250 break; 251 case 'v' : 252 opts |= OPT_VERBOSE; 253 break; 254 } 255 256 if (opts & OPT_DEBUG) 257 fprintf(stderr, "poolcommand: opts = %#x\n", opts); 258 259 if (poolname == NULL) { 260 fprintf(stderr, "poolname not given with add/remove pool\n"); 261 return -1; 262 } 263 264 if (type == IPLT_HASH) { 265 strncpy(iph.iph_name, poolname, sizeof(iph.iph_name)); 266 iph.iph_name[sizeof(iph.iph_name) - 1] = '\0'; 267 iph.iph_unit = role; 268 } else if (type == IPLT_POOL) { 269 strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name)); 270 pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0'; 271 pool.ipo_unit = role; 272 } 273 274 if (remove == 0) { 275 switch (type) 276 { 277 case IPLT_HASH : 278 err = load_hash(&iph, NULL, ioctl); 279 break; 280 case IPLT_POOL : 281 err = load_pool(&pool, ioctl); 282 break; 283 } 284 } else { 285 switch (type) 286 { 287 case IPLT_HASH : 288 err = remove_hash(&iph, ioctl); 289 break; 290 case IPLT_POOL : 291 err = remove_pool(&pool, ioctl); 292 break; 293 } 294 } 295 return err; 296 } 297 298 299 int loadpoolfile(argc, argv, infile) 300 int argc; 301 char *argv[], *infile; 302 { 303 int c; 304 305 infile = optarg; 306 307 while ((c = getopt(argc, argv, "dnRuv")) != -1) 308 switch (c) 309 { 310 case 'd' : 311 opts |= OPT_DEBUG; 312 ippool_yydebug++; 313 break; 314 case 'n' : 315 opts |= OPT_DONOTHING; 316 break; 317 case 'R' : 318 opts |= OPT_NORESOLVE; 319 break; 320 case 'u' : 321 opts |= OPT_REMOVE; 322 break; 323 case 'v' : 324 opts |= OPT_VERBOSE; 325 break; 326 } 327 328 if (opts & OPT_DEBUG) 329 fprintf(stderr, "loadpoolfile: opts = %#x\n", opts); 330 331 if (!(opts & OPT_DONOTHING) && (fd == -1)) { 332 fd = open(IPLOOKUP_NAME, O_RDWR); 333 if (fd == -1) { 334 perror("open(IPLOOKUP_NAME)"); 335 exit(1); 336 } 337 } 338 339 if (ippool_parsefile(fd, infile, ioctl) != 0) 340 return -1; 341 return 0; 342 } 343 344 345 int poollist(argc, argv) 346 int argc; 347 char *argv[]; 348 { 349 char *kernel, *core, *poolname; 350 int c, role, type, live_kernel; 351 ip_pool_stat_t *plstp, plstat; 352 iphtstat_t *htstp, htstat; 353 iphtable_t *hptr; 354 iplookupop_t op; 355 ip_pool_t *ptr; 356 357 core = NULL; 358 kernel = NULL; 359 live_kernel = 1; 360 type = IPLT_ALL; 361 poolname = NULL; 362 role = IPL_LOGALL; 363 364 while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1) 365 switch (c) 366 { 367 case 'd' : 368 opts |= OPT_DEBUG; 369 break; 370 case 'm' : 371 poolname = optarg; 372 break; 373 case 'M' : 374 live_kernel = 0; 375 core = optarg; 376 break; 377 case 'N' : 378 live_kernel = 0; 379 kernel = optarg; 380 break; 381 case 'o' : 382 role = getrole(optarg); 383 if (role == IPL_LOGNONE) { 384 fprintf(stderr, "unknown role '%s'\n", optarg); 385 return -1; 386 } 387 break; 388 case 'R' : 389 opts |= OPT_NORESOLVE; 390 break; 391 case 't' : 392 type = gettype(optarg, NULL); 393 if (type == IPLT_NONE) { 394 fprintf(stderr, "unknown type '%s'\n", optarg); 395 return -1; 396 } 397 break; 398 case 'v' : 399 opts |= OPT_VERBOSE; 400 break; 401 } 402 403 if (opts & OPT_DEBUG) 404 fprintf(stderr, "poollist: opts = %#x\n", opts); 405 406 if (!(opts & OPT_DONOTHING) && (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 bzero((char *)&op, sizeof(op)); 415 if (poolname != NULL) { 416 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name)); 417 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 418 } 419 op.iplo_unit = role; 420 421 if (openkmem(kernel, core) == -1) 422 exit(-1); 423 424 if (type == IPLT_ALL || type == IPLT_POOL) { 425 plstp = &plstat; 426 op.iplo_type = IPLT_POOL; 427 op.iplo_size = sizeof(plstat); 428 op.iplo_struct = &plstat; 429 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 430 if (c == -1) { 431 perror("ioctl(SIOCLOOKUPSTAT)"); 432 return -1; 433 } 434 435 if (role != IPL_LOGALL) { 436 ptr = plstp->ipls_list[role]; 437 while (ptr != NULL) { 438 ptr = printpool(ptr, kmemcpywrap, poolname, 439 opts); 440 } 441 } else { 442 for (role = 0; role <= IPL_LOGMAX; role++) { 443 ptr = plstp->ipls_list[role]; 444 while (ptr != NULL) { 445 ptr = printpool(ptr, kmemcpywrap, 446 poolname, opts); 447 } 448 } 449 role = IPL_LOGALL; 450 } 451 } 452 if (type == IPLT_ALL || type == IPLT_HASH) { 453 htstp = &htstat; 454 op.iplo_type = IPLT_HASH; 455 op.iplo_size = sizeof(htstat); 456 op.iplo_struct = &htstat; 457 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 458 if (c == -1) { 459 perror("ioctl(SIOCLOOKUPSTAT)"); 460 return -1; 461 } 462 463 if (role != IPL_LOGALL) { 464 hptr = htstp->iphs_tables; 465 while (hptr != NULL) { 466 hptr = printhash(hptr, kmemcpywrap, 467 poolname, opts); 468 } 469 } else { 470 for (role = 0; role <= IPL_LOGMAX; role++) { 471 hptr = htstp->iphs_tables; 472 while (hptr != NULL) { 473 hptr = printhash(hptr, kmemcpywrap, 474 poolname, opts); 475 } 476 477 op.iplo_unit = role; 478 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 479 if (c == -1) { 480 perror("ioctl(SIOCLOOKUPSTAT)"); 481 return -1; 482 } 483 } 484 } 485 } 486 return 0; 487 } 488 489 490 int poolstats(argc, argv) 491 int argc; 492 char *argv[]; 493 { 494 int c, type, role, live_kernel; 495 ip_pool_stat_t plstat; 496 char *kernel, *core; 497 iphtstat_t htstat; 498 iplookupop_t op; 499 500 core = NULL; 501 kernel = NULL; 502 live_kernel = 1; 503 type = IPLT_ALL; 504 role = IPL_LOGALL; 505 506 bzero((char *)&op, sizeof(op)); 507 508 while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1) 509 switch (c) 510 { 511 case 'd' : 512 opts |= OPT_DEBUG; 513 break; 514 case 'M' : 515 live_kernel = 0; 516 core = optarg; 517 break; 518 case 'N' : 519 live_kernel = 0; 520 kernel = optarg; 521 break; 522 case 'o' : 523 role = getrole(optarg); 524 if (role == IPL_LOGNONE) { 525 fprintf(stderr, "unknown role '%s'\n", optarg); 526 return -1; 527 } 528 break; 529 case 't' : 530 type = gettype(optarg, NULL); 531 if (type != IPLT_POOL) { 532 fprintf(stderr, 533 "-s not supported for this type yet\n"); 534 return -1; 535 } 536 break; 537 case 'v' : 538 opts |= OPT_VERBOSE; 539 break; 540 } 541 542 if (opts & OPT_DEBUG) 543 fprintf(stderr, "poolstats: opts = %#x\n", opts); 544 545 if (!(opts & OPT_DONOTHING) && (fd == -1)) { 546 fd = open(IPLOOKUP_NAME, O_RDWR); 547 if (fd == -1) { 548 perror("open(IPLOOKUP_NAME)"); 549 exit(1); 550 } 551 } 552 553 if (type == IPLT_ALL || type == IPLT_POOL) { 554 op.iplo_type = IPLT_POOL; 555 op.iplo_struct = &plstat; 556 op.iplo_size = sizeof(plstat); 557 if (!(opts & OPT_DONOTHING)) { 558 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 559 if (c == -1) { 560 perror("ioctl(SIOCLOOKUPSTAT)"); 561 return -1; 562 } 563 printf("Pools:\t%lu\n", plstat.ipls_pools); 564 printf("Nodes:\t%lu\n", plstat.ipls_nodes); 565 } 566 } 567 568 if (type == IPLT_ALL || type == IPLT_HASH) { 569 op.iplo_type = IPLT_HASH; 570 op.iplo_struct = &htstat; 571 op.iplo_size = sizeof(htstat); 572 if (!(opts & OPT_DONOTHING)) { 573 c = ioctl(fd, SIOCLOOKUPSTAT, &op); 574 if (c == -1) { 575 perror("ioctl(SIOCLOOKUPSTAT)"); 576 return -1; 577 } 578 printf("Hash Tables:\t%lu\n", htstat.iphs_numtables); 579 printf("Nodes:\t%lu\n", htstat.iphs_numnodes); 580 printf("Out of Memory:\t%lu\n", htstat.iphs_nomem); 581 } 582 } 583 return 0; 584 } 585 586 587 int poolflush(argc, argv) 588 int argc; 589 char *argv[]; 590 { 591 int c, role, type, arg; 592 iplookupflush_t flush; 593 594 arg = IPLT_ALL; 595 type = IPLT_ALL; 596 role = IPL_LOGALL; 597 598 while ((c = getopt(argc, argv, "do:t:v")) != -1) 599 switch (c) 600 { 601 case 'd' : 602 opts |= OPT_DEBUG; 603 break; 604 case 'o' : 605 role = getrole(optarg); 606 if (role == IPL_LOGNONE) { 607 fprintf(stderr, "unknown role '%s'\n", optarg); 608 return -1; 609 } 610 break; 611 case 't' : 612 type = gettype(optarg, NULL); 613 if (type == IPLT_NONE) { 614 fprintf(stderr, "unknown type '%s'\n", optarg); 615 return -1; 616 } 617 break; 618 case 'v' : 619 opts |= OPT_VERBOSE; 620 break; 621 } 622 623 if (opts & OPT_DEBUG) 624 fprintf(stderr, "poolflush: opts = %#x\n", opts); 625 626 if (!(opts & OPT_DONOTHING) && (fd == -1)) { 627 fd = open(IPLOOKUP_NAME, O_RDWR); 628 if (fd == -1) { 629 perror("open(IPLOOKUP_NAME)"); 630 exit(1); 631 } 632 } 633 634 bzero((char *)&flush, sizeof(flush)); 635 flush.iplf_type = type; 636 flush.iplf_unit = role; 637 flush.iplf_arg = arg; 638 639 if (!(opts & OPT_DONOTHING)) { 640 if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) { 641 perror("ioctl(SIOCLOOKUPFLUSH)"); 642 exit(1); 643 } 644 645 } 646 printf("%u object%s flushed\n", flush.iplf_count, 647 (flush.iplf_count == 1) ? "" : "s"); 648 649 return 0; 650 } 651 652 653 int getrole(rolename) 654 char *rolename; 655 { 656 int role; 657 658 if (!strcasecmp(rolename, "ipf")) { 659 role = IPL_LOGIPF; 660 #if 0 661 } else if (!strcasecmp(rolename, "nat")) { 662 role = IPL_LOGNAT; 663 } else if (!strcasecmp(rolename, "state")) { 664 role = IPL_LOGSTATE; 665 } else if (!strcasecmp(rolename, "auth")) { 666 role = IPL_LOGAUTH; 667 } else if (!strcasecmp(rolename, "sync")) { 668 role = IPL_LOGSYNC; 669 } else if (!strcasecmp(rolename, "scan")) { 670 role = IPL_LOGSCAN; 671 } else if (!strcasecmp(rolename, "pool")) { 672 role = IPL_LOGLOOKUP; 673 } else if (!strcasecmp(rolename, "count")) { 674 role = IPL_LOGCOUNT; 675 #endif 676 } else { 677 role = IPL_LOGNONE; 678 } 679 680 return role; 681 } 682 683 684 int gettype(typename, minor) 685 char *typename; 686 u_int *minor; 687 { 688 int type; 689 690 if (!strcasecmp(optarg, "tree")) { 691 type = IPLT_POOL; 692 } else if (!strcasecmp(optarg, "hash")) { 693 type = IPLT_HASH; 694 if (minor != NULL) 695 *minor = IPHASH_LOOKUP; 696 } else if (!strcasecmp(optarg, "group-map")) { 697 type = IPLT_HASH; 698 if (minor != NULL) 699 *minor = IPHASH_GROUPMAP; 700 } else { 701 type = IPLT_NONE; 702 } 703 return type; 704 } 705