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