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 (!use_inet6) { 211 ip->ip_off = ntohs(ip->ip_off); 212 ip->ip_len = ntohs(ip->ip_len); 213 if (r->r_flags & R_DO_CKSUM) 214 fixv4sums(m, ip); 215 hlen = IP_HL(ip) << 2; 216 } 217 #ifdef USE_INET6 218 else 219 hlen = sizeof(ip6_t); 220 #endif 221 /* ipfr_slowtimer(); */ 222 m = &mb; 223 m->mb_len = i; 224 i = fr_check(ip, hlen, ifp, dir, &m); 225 if ((opts & OPT_NAT) == 0) 226 switch (i) 227 { 228 case -4 : 229 (void)printf("preauth"); 230 break; 231 case -3 : 232 (void)printf("account"); 233 break; 234 case -2 : 235 (void)printf("auth"); 236 break; 237 case -1 : 238 (void)printf("block"); 239 break; 240 case 0 : 241 (void)printf("pass"); 242 break; 243 case 1 : 244 (void)printf("nomatch"); 245 break; 246 case 3 : 247 (void)printf("block return-rst"); 248 break; 249 case 4 : 250 (void)printf("block return-icmp"); 251 break; 252 case 5 : 253 (void)printf("block return-icmp-as-dest"); 254 break; 255 default : 256 (void)printf("recognised return %#x\n", i); 257 break; 258 } 259 if (!use_inet6) { 260 ip->ip_off = htons(ip->ip_off); 261 ip->ip_len = htons(ip->ip_len); 262 } 263 264 if (!(opts & OPT_BRIEF)) { 265 putchar(' '); 266 printpacket(ip); 267 printf("--------------"); 268 } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) 269 printpacket(ip); 270 if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) 271 #if defined(__sgi) && (IRIX < 605) 272 (*ifp->if_output)(ifp, (void *)m, NULL); 273 #else 274 # if TRU64 >= 1885 275 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 276 # else 277 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 278 # endif 279 #endif 280 if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) 281 putchar('\n'); 282 dir = 0; 283 if (iface != ifname) { 284 free(iface); 285 iface = ifname; 286 } 287 m = &mb; 288 } 289 (*r->r_close)(); 290 291 if (logout != NULL) { 292 drain_log(logout); 293 } 294 295 if (dump == 1) { 296 dumpnat(); 297 dumpstate(); 298 dumplookups(); 299 dumpgroups(); 300 } 301 302 for (i = IPL_LOGMAX; i >= 0; i--) 303 (void) ipflog_clear(i); 304 305 fr_fragunload(); 306 fr_authunload(); 307 fr_stateunload(); 308 fr_natunload(); 309 appr_unload(); 310 311 i = frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 312 i += frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); 313 314 ip_lookup_unload(); 315 316 return 0; 317 } 318 319 320 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \ 321 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ 322 defined(__osf__) 323 int ipftestioctl(int dev, ioctlcmd_t cmd, ...) 324 { 325 caddr_t data; 326 va_list ap; 327 int i; 328 329 va_start(ap, cmd); 330 data = va_arg(ap, caddr_t); 331 va_end(ap); 332 333 i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); 334 if (opts & OPT_DEBUG) 335 fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", 336 (u_int)cmd, data, i); 337 return i; 338 } 339 340 341 int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) 342 { 343 caddr_t data; 344 va_list ap; 345 int i; 346 347 va_start(ap, cmd); 348 data = va_arg(ap, caddr_t); 349 va_end(ap); 350 351 i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); 352 if (opts & OPT_DEBUG) 353 fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", 354 (u_int)cmd, data, i); 355 return i; 356 } 357 358 359 int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) 360 { 361 caddr_t data; 362 va_list ap; 363 int i; 364 365 va_start(ap, cmd); 366 data = va_arg(ap, caddr_t); 367 va_end(ap); 368 369 i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 370 if ((opts & OPT_DEBUG) || (i != 0)) 371 fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", 372 (u_int)cmd, data, i); 373 return i; 374 } 375 376 377 int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) 378 { 379 caddr_t data; 380 va_list ap; 381 int i; 382 383 va_start(ap, cmd); 384 data = va_arg(ap, caddr_t); 385 va_end(ap); 386 387 i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 388 if ((opts & OPT_DEBUG) || (i != 0)) 389 fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", 390 (u_int)cmd, data, i); 391 return i; 392 } 393 394 395 int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) 396 { 397 caddr_t data; 398 va_list ap; 399 int i; 400 401 va_start(ap, cmd); 402 data = va_arg(ap, caddr_t); 403 va_end(ap); 404 405 i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 406 if ((opts & OPT_DEBUG) || (i != 0)) 407 fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", 408 (u_int)cmd, data, i); 409 return i; 410 } 411 412 413 int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) 414 { 415 caddr_t data; 416 va_list ap; 417 int i; 418 419 va_start(ap, cmd); 420 data = va_arg(ap, caddr_t); 421 va_end(ap); 422 423 i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 424 if ((opts & OPT_DEBUG) || (i != 0)) 425 fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", 426 (u_int)cmd, data, i); 427 return i; 428 } 429 430 431 int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) 432 { 433 caddr_t data; 434 va_list ap; 435 int i; 436 437 va_start(ap, cmd); 438 data = va_arg(ap, caddr_t); 439 va_end(ap); 440 441 i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 442 if ((opts & OPT_DEBUG) || (i != 0)) 443 fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", 444 (u_int)cmd, data, i); 445 return i; 446 } 447 #else 448 int ipftestioctl(dev, cmd, data) 449 dev_t dev; 450 ioctlcmd_t cmd; 451 void *data; 452 { 453 int i; 454 455 i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); 456 if ((opts & OPT_DEBUG) || (i != 0)) 457 fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i); 458 return i; 459 } 460 461 462 int ipnattestioctl(dev, cmd, data) 463 dev_t dev; 464 ioctlcmd_t cmd; 465 void *data; 466 { 467 int i; 468 469 i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); 470 if ((opts & OPT_DEBUG) || (i != 0)) 471 fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i); 472 return i; 473 } 474 475 476 int ipstatetestioctl(dev, cmd, data) 477 dev_t dev; 478 ioctlcmd_t cmd; 479 void *data; 480 { 481 int i; 482 483 i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 484 if ((opts & OPT_DEBUG) || (i != 0)) 485 fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i); 486 return i; 487 } 488 489 490 int ipauthtestioctl(dev, cmd, data) 491 dev_t dev; 492 ioctlcmd_t cmd; 493 void *data; 494 { 495 int i; 496 497 i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 498 if ((opts & OPT_DEBUG) || (i != 0)) 499 fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); 500 return i; 501 } 502 503 504 int ipsynctestioctl(dev, cmd, data) 505 dev_t dev; 506 ioctlcmd_t cmd; 507 void *data; 508 { 509 int i; 510 511 i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 512 if ((opts & OPT_DEBUG) || (i != 0)) 513 fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); 514 return i; 515 } 516 517 518 int ipscantestioctl(dev, cmd, data) 519 dev_t dev; 520 ioctlcmd_t cmd; 521 void *data; 522 { 523 int i; 524 525 i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 526 if ((opts & OPT_DEBUG) || (i != 0)) 527 fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); 528 return i; 529 } 530 531 532 int ipooltestioctl(dev, cmd, data) 533 dev_t dev; 534 ioctlcmd_t cmd; 535 void *data; 536 { 537 int i; 538 539 i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 540 if (opts & OPT_DEBUG) 541 fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i); 542 return i; 543 } 544 #endif 545 546 547 int kmemcpy(addr, offset, size) 548 char *addr; 549 long offset; 550 int size; 551 { 552 bcopy((char *)offset, addr, size); 553 return 0; 554 } 555 556 557 int kstrncpy(buf, pos, n) 558 char *buf; 559 long pos; 560 int n; 561 { 562 char *ptr; 563 564 ptr = (char *)pos; 565 566 while ((n-- > 0) && (*buf++ = *ptr++)) 567 ; 568 return 0; 569 } 570 571 572 /* 573 * Display the built up NAT table rules and mapping entries. 574 */ 575 void dumpnat() 576 { 577 ipnat_t *ipn; 578 nat_t *nat; 579 580 printf("List of active MAP/Redirect filters:\n"); 581 for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) 582 printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); 583 printf("\nList of active sessions:\n"); 584 for (nat = nat_instances; nat; nat = nat->nat_next) 585 printactivenat(nat, opts); 586 } 587 588 589 /* 590 * Display the built up state table rules and mapping entries. 591 */ 592 void dumpstate() 593 { 594 ipstate_t *ips; 595 596 printf("List of active state sessions:\n"); 597 for (ips = ips_list; ips != NULL; ) 598 ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE)); 599 } 600 601 602 void dumplookups() 603 { 604 iphtable_t *iph; 605 ip_pool_t *ipl; 606 int i; 607 608 printf("List of configured pools\n"); 609 for (i = 0; i < IPL_LOGSIZE; i++) 610 for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next) 611 printpool(ipl, bcopywrap, opts); 612 613 printf("List of configured hash tables\n"); 614 for (i = 0; i < IPL_LOGSIZE; i++) 615 for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next) 616 printhash(iph, bcopywrap, opts); 617 } 618 619 620 void dumpgroups() 621 { 622 frgroup_t *fg; 623 frentry_t *fr; 624 int i; 625 626 printf("List of groups configured (set 0)\n"); 627 for (i = 0; i < IPL_LOGSIZE; i++) 628 for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) { 629 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 630 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 631 for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { 632 #ifdef USE_QUAD_T 633 printf("%qu ",(unsigned long long)fr->fr_hits); 634 #else 635 printf("%ld ", fr->fr_hits); 636 #endif 637 printfr(fr, ipftestioctl); 638 } 639 } 640 641 printf("List of groups configured (set 1)\n"); 642 for (i = 0; i < IPL_LOGSIZE; i++) 643 for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) { 644 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 645 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 646 for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { 647 #ifdef USE_QUAD_T 648 printf("%qu ",(unsigned long long)fr->fr_hits); 649 #else 650 printf("%ld ", fr->fr_hits); 651 #endif 652 printfr(fr, ipftestioctl); 653 } 654 } 655 } 656 657 658 void drain_log(filename) 659 char *filename; 660 { 661 char buffer[DEFAULT_IPFLOGSIZE]; 662 struct iovec iov; 663 struct uio uio; 664 size_t resid; 665 int fd; 666 667 fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); 668 if (fd == -1) { 669 perror("drain_log:open"); 670 return; 671 } 672 673 while (1) { 674 bzero((char *)&iov, sizeof(iov)); 675 iov.iov_base = buffer; 676 iov.iov_len = sizeof(buffer); 677 678 bzero((char *)&uio, sizeof(uio)); 679 uio.uio_iov = &iov; 680 uio.uio_iovcnt = 1; 681 uio.uio_resid = iov.iov_len; 682 resid = uio.uio_resid; 683 684 if (ipflog_read(0, &uio) == 0) { 685 /* 686 * If nothing was read then break out. 687 */ 688 if (uio.uio_resid == resid) 689 break; 690 write(fd, buffer, resid - uio.uio_resid); 691 } else 692 break; 693 } 694 695 close(fd); 696 } 697 698 699 void fixv4sums(m, ip) 700 mb_t *m; 701 ip_t *ip; 702 { 703 u_char *csump, *hdr; 704 705 ip->ip_sum = 0; 706 ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); 707 708 csump = (u_char *)ip; 709 csump += IP_HL(ip) << 2; 710 711 switch (ip->ip_p) 712 { 713 case IPPROTO_TCP : 714 hdr = csump; 715 csump += offsetof(tcphdr_t, th_sum); 716 break; 717 case IPPROTO_UDP : 718 hdr = csump; 719 csump += offsetof(udphdr_t, uh_sum); 720 break; 721 default : 722 csump = NULL; 723 hdr = NULL; 724 break; 725 } 726 if (hdr != NULL) { 727 *csump = 0; 728 *(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr); 729 } 730 } 731