1 /* 2 * Copyright (C) 1993-2001 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2005 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 "ipf.h" 13 #include "ipt.h" 14 #include <sys/ioctl.h> 15 #include <sys/file.h> 16 17 #if !defined(lint) 18 static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed"; 19 static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.35 2003/07/01 01:03:04 darrenr Exp $"; 20 #endif 21 22 extern char *optarg; 23 extern struct frentry *ipfilter[2][2]; 24 extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; 25 extern struct ifnet *get_unit __P((char *, int)); 26 extern void init_ifp __P((void)); 27 extern ipnat_t *natparse __P((char *, int)); 28 extern int fr_running; 29 30 ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; 31 ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; 32 ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw; 33 ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; 34 int opts = OPT_DONOTHING; 35 int use_inet6 = 0; 36 int pfil_delayed_copy = 0; 37 int main __P((int, char *[])); 38 int loadrules __P((char *, int)); 39 int kmemcpy __P((char *, long, int)); 40 int kstrncpy __P((char *, long, int n)); 41 void dumpnat __P((void)); 42 void dumpstate __P((void)); 43 void dumplookups __P((void)); 44 void dumpgroups __P((void)); 45 void drain_log __P((char *)); 46 void fixv4sums __P((mb_t *, ip_t *)); 47 48 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \ 49 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ 50 defined(__osf__) 51 int ipftestioctl __P((int, ioctlcmd_t, ...)); 52 int ipnattestioctl __P((int, ioctlcmd_t, ...)); 53 int ipstatetestioctl __P((int, ioctlcmd_t, ...)); 54 int ipauthtestioctl __P((int, ioctlcmd_t, ...)); 55 int ipscantestioctl __P((int, ioctlcmd_t, ...)); 56 int ipsynctestioctl __P((int, ioctlcmd_t, ...)); 57 int ipooltestioctl __P((int, ioctlcmd_t, ...)); 58 #else 59 int ipftestioctl __P((dev_t, ioctlcmd_t, void *)); 60 int ipnattestioctl __P((dev_t, ioctlcmd_t, void *)); 61 int ipstatetestioctl __P((dev_t, ioctlcmd_t, void *)); 62 int ipauthtestioctl __P((dev_t, ioctlcmd_t, void *)); 63 int ipsynctestioctl __P((dev_t, ioctlcmd_t, void *)); 64 int ipscantestioctl __P((dev_t, ioctlcmd_t, void *)); 65 int ipooltestioctl __P((dev_t, ioctlcmd_t, void *)); 66 #endif 67 68 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ipftestioctl, 69 ipnattestioctl, 70 ipstatetestioctl, 71 ipauthtestioctl, 72 ipsynctestioctl, 73 ipscantestioctl, 74 ipooltestioctl, 75 NULL }; 76 77 78 int main(argc,argv) 79 int argc; 80 char *argv[]; 81 { 82 char *datain, *iface, *ifname, *logout; 83 int fd, i, dir, c, loaded, dump, hlen; 84 struct ifnet *ifp; 85 struct ipread *r; 86 mb_t mb, *m; 87 ip_t *ip; 88 89 m = &mb; 90 dir = 0; 91 dump = 0; 92 hlen = 0; 93 loaded = 0; 94 r = &iptext; 95 iface = NULL; 96 logout = NULL; 97 ifname = "anon0"; 98 datain = NULL; 99 100 MUTEX_INIT(&ipf_rw, "ipf rw mutex"); 101 MUTEX_INIT(&ipf_timeoutlock, "ipf timeout lock"); 102 RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); 103 RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); 104 RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); 105 106 initparse(); 107 fr_loginit(); 108 fr_authinit(); 109 fr_fraginit(); 110 fr_stateinit(); 111 fr_natinit(); 112 appr_init(); 113 ip_lookup_init(); 114 fr_running = 1; 115 116 while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:vxX")) != -1) 117 switch (c) 118 { 119 case '6' : 120 #ifdef USE_INET6 121 use_inet6 = 1; 122 #else 123 fprintf(stderr, "IPv6 not supported\n"); 124 exit(1); 125 #endif 126 break; 127 case 'b' : 128 opts |= OPT_BRIEF; 129 break; 130 case 'd' : 131 opts |= OPT_DEBUG; 132 break; 133 case 'D' : 134 dump = 1; 135 break; 136 case 'F' : 137 if (strcasecmp(optarg, "pcap") == 0) 138 r = &pcap; 139 else if (strcasecmp(optarg, "etherfind") == 0) 140 r = ðerf; 141 else if (strcasecmp(optarg, "snoop") == 0) 142 r = &snoop; 143 else if (strcasecmp(optarg, "tcpdump") == 0) 144 r = &tcpd; 145 else if (strcasecmp(optarg, "hex") == 0) 146 r = &iphex; 147 else if (strcasecmp(optarg, "text") == 0) 148 r = &iptext; 149 break; 150 case 'i' : 151 datain = optarg; 152 break; 153 case 'I' : 154 ifname = optarg; 155 break; 156 case 'l' : 157 logout = optarg; 158 break; 159 case 'o' : 160 opts |= OPT_SAVEOUT; 161 break; 162 case 'r' : 163 if (ipf_parsefile(-1, ipf_addrule, iocfunctions, 164 optarg) == -1) 165 return -1; 166 loaded = 1; 167 break; 168 case 'v' : 169 opts |= OPT_VERBOSE; 170 break; 171 case 'N' : 172 if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl, 173 optarg) == -1) 174 return -1; 175 loaded = 1; 176 opts |= OPT_NAT; 177 break; 178 case 'P' : 179 if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1) 180 return -1; 181 loaded = 1; 182 break; 183 case 'x' : 184 opts |= OPT_HEX; 185 break; 186 } 187 188 if (loaded == 0) { 189 (void)fprintf(stderr,"no rules loaded\n"); 190 exit(-1); 191 } 192 193 if (opts & OPT_SAVEOUT) 194 init_ifp(); 195 196 if (datain) 197 fd = (*r->r_open)(datain); 198 else 199 fd = (*r->r_open)("-"); 200 201 if (fd < 0) 202 exit(-1); 203 204 ip = MTOD(m, ip_t *); 205 while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf), 206 &iface, &dir)) > 0) { 207 if (iface == NULL || *iface == '\0') 208 iface = ifname; 209 ifp = get_unit(iface, IP_V(ip)); 210 if (ifp == NULL) { 211 fprintf(stderr, "out of memory\n"); 212 exit(1); 213 } 214 if (!use_inet6) { 215 ip->ip_off = ntohs(ip->ip_off); 216 ip->ip_len = ntohs(ip->ip_len); 217 if (r->r_flags & R_DO_CKSUM) 218 fixv4sums(m, ip); 219 hlen = IP_HL(ip) << 2; 220 } 221 #ifdef USE_INET6 222 else 223 hlen = sizeof(ip6_t); 224 #endif 225 /* ipfr_slowtimer(); */ 226 m = &mb; 227 m->mb_len = i; 228 i = fr_check(ip, hlen, ifp, dir, &m); 229 if ((opts & OPT_NAT) == 0) 230 switch (i) 231 { 232 case -4 : 233 (void)printf("preauth"); 234 break; 235 case -3 : 236 (void)printf("account"); 237 break; 238 case -2 : 239 (void)printf("auth"); 240 break; 241 case -1 : 242 (void)printf("block"); 243 break; 244 case 0 : 245 (void)printf("pass"); 246 break; 247 case 1 : 248 (void)printf("nomatch"); 249 break; 250 case 3 : 251 (void)printf("block return-rst"); 252 break; 253 case 4 : 254 (void)printf("block return-icmp"); 255 break; 256 case 5 : 257 (void)printf("block return-icmp-as-dest"); 258 break; 259 default : 260 (void)printf("recognised return %#x\n", i); 261 break; 262 } 263 if (!use_inet6) { 264 ip->ip_off = htons(ip->ip_off); 265 ip->ip_len = htons(ip->ip_len); 266 } 267 268 if (!(opts & OPT_BRIEF)) { 269 putchar(' '); 270 printpacket(ip); 271 printf("--------------"); 272 } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) 273 printpacket(ip); 274 if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) 275 #if defined(__sgi) && (IRIX < 605) 276 (*ifp->if_output)(ifp, (void *)m, NULL); 277 #else 278 # if TRU64 >= 1885 279 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 280 # else 281 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 282 # endif 283 #endif 284 if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) 285 putchar('\n'); 286 dir = 0; 287 if (iface != ifname) { 288 free(iface); 289 iface = ifname; 290 } 291 m = &mb; 292 } 293 (*r->r_close)(); 294 295 if (logout != NULL) { 296 drain_log(logout); 297 } 298 299 if (dump == 1) { 300 dumpnat(); 301 dumpstate(); 302 dumplookups(); 303 dumpgroups(); 304 } 305 306 for (i = IPL_LOGMAX; i >= 0; i--) 307 (void) ipflog_clear(i); 308 309 fr_fragunload(); 310 fr_authunload(); 311 fr_stateunload(); 312 fr_natunload(); 313 appr_unload(); 314 315 i = frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 316 i += frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); 317 318 ip_lookup_unload(); 319 320 return 0; 321 } 322 323 324 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \ 325 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ 326 defined(__osf__) 327 int ipftestioctl(int dev, ioctlcmd_t cmd, ...) 328 { 329 caddr_t data; 330 va_list ap; 331 int i; 332 333 va_start(ap, cmd); 334 data = va_arg(ap, caddr_t); 335 va_end(ap); 336 337 i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); 338 if (opts & OPT_DEBUG) 339 fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", 340 (u_int)cmd, data, i); 341 return i; 342 } 343 344 345 int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) 346 { 347 caddr_t data; 348 va_list ap; 349 int i; 350 351 va_start(ap, cmd); 352 data = va_arg(ap, caddr_t); 353 va_end(ap); 354 355 i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); 356 if (opts & OPT_DEBUG) 357 fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", 358 (u_int)cmd, data, i); 359 return i; 360 } 361 362 363 int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) 364 { 365 caddr_t data; 366 va_list ap; 367 int i; 368 369 va_start(ap, cmd); 370 data = va_arg(ap, caddr_t); 371 va_end(ap); 372 373 i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 374 if ((opts & OPT_DEBUG) || (i != 0)) 375 fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", 376 (u_int)cmd, data, i); 377 return i; 378 } 379 380 381 int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) 382 { 383 caddr_t data; 384 va_list ap; 385 int i; 386 387 va_start(ap, cmd); 388 data = va_arg(ap, caddr_t); 389 va_end(ap); 390 391 i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 392 if ((opts & OPT_DEBUG) || (i != 0)) 393 fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", 394 (u_int)cmd, data, i); 395 return i; 396 } 397 398 399 int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) 400 { 401 caddr_t data; 402 va_list ap; 403 int i; 404 405 va_start(ap, cmd); 406 data = va_arg(ap, caddr_t); 407 va_end(ap); 408 409 i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 410 if ((opts & OPT_DEBUG) || (i != 0)) 411 fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", 412 (u_int)cmd, data, i); 413 return i; 414 } 415 416 417 int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) 418 { 419 caddr_t data; 420 va_list ap; 421 int i; 422 423 va_start(ap, cmd); 424 data = va_arg(ap, caddr_t); 425 va_end(ap); 426 427 i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 428 if ((opts & OPT_DEBUG) || (i != 0)) 429 fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", 430 (u_int)cmd, data, i); 431 return i; 432 } 433 434 435 int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) 436 { 437 caddr_t data; 438 va_list ap; 439 int i; 440 441 va_start(ap, cmd); 442 data = va_arg(ap, caddr_t); 443 va_end(ap); 444 445 i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 446 if ((opts & OPT_DEBUG) || (i != 0)) 447 fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", 448 (u_int)cmd, data, i); 449 return i; 450 } 451 #else 452 int ipftestioctl(dev, cmd, data) 453 dev_t dev; 454 ioctlcmd_t cmd; 455 void *data; 456 { 457 int i; 458 459 i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); 460 if ((opts & OPT_DEBUG) || (i != 0)) 461 fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i); 462 return i; 463 } 464 465 466 int ipnattestioctl(dev, cmd, data) 467 dev_t dev; 468 ioctlcmd_t cmd; 469 void *data; 470 { 471 int i; 472 473 i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); 474 if ((opts & OPT_DEBUG) || (i != 0)) 475 fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i); 476 return i; 477 } 478 479 480 int ipstatetestioctl(dev, cmd, data) 481 dev_t dev; 482 ioctlcmd_t cmd; 483 void *data; 484 { 485 int i; 486 487 i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 488 if ((opts & OPT_DEBUG) || (i != 0)) 489 fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i); 490 return i; 491 } 492 493 494 int ipauthtestioctl(dev, cmd, data) 495 dev_t dev; 496 ioctlcmd_t cmd; 497 void *data; 498 { 499 int i; 500 501 i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 502 if ((opts & OPT_DEBUG) || (i != 0)) 503 fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); 504 return i; 505 } 506 507 508 int ipsynctestioctl(dev, cmd, data) 509 dev_t dev; 510 ioctlcmd_t cmd; 511 void *data; 512 { 513 int i; 514 515 i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 516 if ((opts & OPT_DEBUG) || (i != 0)) 517 fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); 518 return i; 519 } 520 521 522 int ipscantestioctl(dev, cmd, data) 523 dev_t dev; 524 ioctlcmd_t cmd; 525 void *data; 526 { 527 int i; 528 529 i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 530 if ((opts & OPT_DEBUG) || (i != 0)) 531 fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); 532 return i; 533 } 534 535 536 int ipooltestioctl(dev, cmd, data) 537 dev_t dev; 538 ioctlcmd_t cmd; 539 void *data; 540 { 541 int i; 542 543 i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 544 if (opts & OPT_DEBUG) 545 fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i); 546 return i; 547 } 548 #endif 549 550 551 int kmemcpy(addr, offset, size) 552 char *addr; 553 long offset; 554 int size; 555 { 556 bcopy((char *)offset, addr, size); 557 return 0; 558 } 559 560 561 int kstrncpy(buf, pos, n) 562 char *buf; 563 long pos; 564 int n; 565 { 566 char *ptr; 567 568 ptr = (char *)pos; 569 570 while ((n-- > 0) && (*buf++ = *ptr++)) 571 ; 572 return 0; 573 } 574 575 576 /* 577 * Display the built up NAT table rules and mapping entries. 578 */ 579 void dumpnat() 580 { 581 ipnat_t *ipn; 582 nat_t *nat; 583 584 printf("List of active MAP/Redirect filters:\n"); 585 for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) 586 printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); 587 printf("\nList of active sessions:\n"); 588 for (nat = nat_instances; nat; nat = nat->nat_next) 589 printactivenat(nat, opts); 590 } 591 592 593 /* 594 * Display the built up state table rules and mapping entries. 595 */ 596 void dumpstate() 597 { 598 ipstate_t *ips; 599 600 printf("List of active state sessions:\n"); 601 for (ips = ips_list; ips != NULL; ) 602 ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE)); 603 } 604 605 606 void dumplookups() 607 { 608 iphtable_t *iph; 609 ip_pool_t *ipl; 610 int i; 611 612 printf("List of configured pools\n"); 613 for (i = 0; i < IPL_LOGSIZE; i++) 614 for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next) 615 printpool(ipl, bcopywrap, opts); 616 617 printf("List of configured hash tables\n"); 618 for (i = 0; i < IPL_LOGSIZE; i++) 619 for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next) 620 printhash(iph, bcopywrap, opts); 621 } 622 623 624 void dumpgroups() 625 { 626 frgroup_t *fg; 627 frentry_t *fr; 628 int i; 629 630 printf("List of groups configured (set 0)\n"); 631 for (i = 0; i < IPL_LOGSIZE; i++) 632 for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) { 633 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 634 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 635 for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { 636 #ifdef USE_QUAD_T 637 printf("%qu ",(unsigned long long)fr->fr_hits); 638 #else 639 printf("%ld ", fr->fr_hits); 640 #endif 641 printfr(fr, ipftestioctl); 642 } 643 } 644 645 printf("List of groups configured (set 1)\n"); 646 for (i = 0; i < IPL_LOGSIZE; i++) 647 for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) { 648 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 649 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 650 for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { 651 #ifdef USE_QUAD_T 652 printf("%qu ",(unsigned long long)fr->fr_hits); 653 #else 654 printf("%ld ", fr->fr_hits); 655 #endif 656 printfr(fr, ipftestioctl); 657 } 658 } 659 } 660 661 662 void drain_log(filename) 663 char *filename; 664 { 665 char buffer[DEFAULT_IPFLOGSIZE]; 666 struct iovec iov; 667 struct uio uio; 668 size_t resid; 669 int fd; 670 671 fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); 672 if (fd == -1) { 673 perror("drain_log:open"); 674 return; 675 } 676 677 while (1) { 678 bzero((char *)&iov, sizeof(iov)); 679 iov.iov_base = buffer; 680 iov.iov_len = sizeof(buffer); 681 682 bzero((char *)&uio, sizeof(uio)); 683 uio.uio_iov = &iov; 684 uio.uio_iovcnt = 1; 685 uio.uio_resid = iov.iov_len; 686 resid = uio.uio_resid; 687 688 if (ipflog_read(0, &uio) == 0) { 689 /* 690 * If nothing was read then break out. 691 */ 692 if (uio.uio_resid == resid) 693 break; 694 write(fd, buffer, resid - uio.uio_resid); 695 } else 696 break; 697 } 698 699 close(fd); 700 } 701 702 703 void fixv4sums(m, ip) 704 mb_t *m; 705 ip_t *ip; 706 { 707 u_char *csump, *hdr; 708 709 ip->ip_sum = 0; 710 ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); 711 712 csump = (u_char *)ip; 713 csump += IP_HL(ip) << 2; 714 715 switch (ip->ip_p) 716 { 717 case IPPROTO_TCP : 718 hdr = csump; 719 csump += offsetof(tcphdr_t, th_sum); 720 break; 721 case IPPROTO_UDP : 722 hdr = csump; 723 csump += offsetof(udphdr_t, uh_sum); 724 break; 725 default : 726 csump = NULL; 727 hdr = NULL; 728 break; 729 } 730 if (hdr != NULL) { 731 *csump = 0; 732 *(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr); 733 } 734 } 735