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