1 /* 2 * Copyright (C) 1993-2001 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 "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.44.2.4 2005/07/16 06:05:28 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, ipf_frcache; 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__) || defined(linux) 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_frcache, "ipf cache rwlock"); 105 RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); 106 107 initparse(); 108 if (fr_initialise() == -1) 109 abort(); 110 fr_running = 1; 111 112 while ((c = getopt(argc, argv, "6bdDF:i:I:l:N:P:or:RT:vxX")) != -1) 113 switch (c) 114 { 115 case '6' : 116 #ifdef USE_INET6 117 use_inet6 = 1; 118 #else 119 fprintf(stderr, "IPv6 not supported\n"); 120 exit(1); 121 #endif 122 break; 123 case 'b' : 124 opts |= OPT_BRIEF; 125 break; 126 case 'd' : 127 opts |= OPT_DEBUG; 128 break; 129 case 'D' : 130 dump = 1; 131 break; 132 case 'F' : 133 if (strcasecmp(optarg, "pcap") == 0) 134 r = &pcap; 135 else if (strcasecmp(optarg, "etherfind") == 0) 136 r = ðerf; 137 else if (strcasecmp(optarg, "snoop") == 0) 138 r = &snoop; 139 else if (strcasecmp(optarg, "tcpdump") == 0) 140 r = &tcpd; 141 else if (strcasecmp(optarg, "hex") == 0) 142 r = &iphex; 143 else if (strcasecmp(optarg, "text") == 0) 144 r = &iptext; 145 break; 146 case 'i' : 147 datain = optarg; 148 break; 149 case 'I' : 150 ifname = optarg; 151 break; 152 case 'l' : 153 logout = optarg; 154 break; 155 case 'o' : 156 opts |= OPT_SAVEOUT; 157 break; 158 case 'r' : 159 if (ipf_parsefile(-1, ipf_addrule, iocfunctions, 160 optarg) == -1) 161 return -1; 162 loaded = 1; 163 break; 164 case 'R' : 165 opts |= OPT_NORESOLVE; 166 break; 167 case 'v' : 168 opts |= OPT_VERBOSE; 169 break; 170 case 'N' : 171 if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl, 172 optarg) == -1) 173 return -1; 174 loaded = 1; 175 opts |= OPT_NAT; 176 break; 177 case 'P' : 178 if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1) 179 return -1; 180 loaded = 1; 181 break; 182 case 'T' : 183 ipf_dotuning(-1, optarg, ipftestioctl); 184 break; 185 case 'x' : 186 opts |= OPT_HEX; 187 break; 188 } 189 190 if (loaded == 0) { 191 (void)fprintf(stderr,"no rules loaded\n"); 192 exit(-1); 193 } 194 195 if (opts & OPT_SAVEOUT) 196 init_ifp(); 197 198 if (datain) 199 fd = (*r->r_open)(datain); 200 else 201 fd = (*r->r_open)("-"); 202 203 if (fd < 0) 204 exit(-1); 205 206 ip = MTOD(m, ip_t *); 207 while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf), 208 &iface, &dir)) > 0) { 209 if (iface == NULL || *iface == '\0') 210 iface = ifname; 211 ifp = get_unit(iface, IP_V(ip)); 212 if (ifp == NULL) { 213 fprintf(stderr, "out of memory\n"); 214 exit(1); 215 } 216 if (!use_inet6) { 217 ip->ip_off = ntohs(ip->ip_off); 218 ip->ip_len = ntohs(ip->ip_len); 219 if (r->r_flags & R_DO_CKSUM) 220 fixv4sums(m, ip); 221 hlen = IP_HL(ip) << 2; 222 } 223 #ifdef USE_INET6 224 else 225 hlen = sizeof(ip6_t); 226 #endif 227 /* ipfr_slowtimer(); */ 228 m = &mb; 229 m->mb_len = i; 230 i = fr_check(ip, hlen, ifp, dir, &m); 231 if ((opts & OPT_NAT) == 0) 232 switch (i) 233 { 234 case -4 : 235 (void)printf("preauth"); 236 break; 237 case -3 : 238 (void)printf("account"); 239 break; 240 case -2 : 241 (void)printf("auth"); 242 break; 243 case -1 : 244 (void)printf("block"); 245 break; 246 case 0 : 247 (void)printf("pass"); 248 break; 249 case 1 : 250 (void)printf("nomatch"); 251 break; 252 case 3 : 253 (void)printf("block return-rst"); 254 break; 255 case 4 : 256 (void)printf("block return-icmp"); 257 break; 258 case 5 : 259 (void)printf("block return-icmp-as-dest"); 260 break; 261 default : 262 (void)printf("recognised return %#x\n", i); 263 break; 264 } 265 if (!use_inet6) { 266 ip->ip_off = htons(ip->ip_off); 267 ip->ip_len = htons(ip->ip_len); 268 } 269 270 if (!(opts & OPT_BRIEF)) { 271 putchar(' '); 272 printpacket(ip); 273 printf("--------------"); 274 } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) 275 printpacket(ip); 276 if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) 277 #if defined(__sgi) && (IRIX < 60500) 278 (*ifp->if_output)(ifp, (void *)m, NULL); 279 #else 280 # if TRU64 >= 1885 281 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 282 # else 283 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 284 # endif 285 #endif 286 if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) 287 putchar('\n'); 288 dir = 0; 289 if (iface != ifname) { 290 free(iface); 291 iface = ifname; 292 } 293 m = &mb; 294 } 295 (*r->r_close)(); 296 297 if (logout != NULL) { 298 drain_log(logout); 299 } 300 301 if (dump == 1) { 302 dumpnat(); 303 dumpstate(); 304 dumplookups(); 305 dumpgroups(); 306 } 307 308 fr_deinitialise(); 309 310 return 0; 311 } 312 313 314 #if defined(__NetBSD__) || defined(__OpenBSD__) || SOLARIS || \ 315 (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) || \ 316 defined(__osf__) || defined(linux) 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 if (i != 0) { 332 errno = i; 333 return -1; 334 } 335 return 0; 336 } 337 338 339 int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) 340 { 341 caddr_t data; 342 va_list ap; 343 int i; 344 345 va_start(ap, cmd); 346 data = va_arg(ap, caddr_t); 347 va_end(ap); 348 349 i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); 350 if (opts & OPT_DEBUG) 351 fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", 352 (u_int)cmd, data, i); 353 if (i != 0) { 354 errno = i; 355 return -1; 356 } 357 return 0; 358 } 359 360 361 int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) 362 { 363 caddr_t data; 364 va_list ap; 365 int i; 366 367 va_start(ap, cmd); 368 data = va_arg(ap, caddr_t); 369 va_end(ap); 370 371 i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 372 if ((opts & OPT_DEBUG) || (i != 0)) 373 fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", 374 (u_int)cmd, data, i); 375 if (i != 0) { 376 errno = i; 377 return -1; 378 } 379 return 0; 380 } 381 382 383 int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) 384 { 385 caddr_t data; 386 va_list ap; 387 int i; 388 389 va_start(ap, cmd); 390 data = va_arg(ap, caddr_t); 391 va_end(ap); 392 393 i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 394 if ((opts & OPT_DEBUG) || (i != 0)) 395 fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", 396 (u_int)cmd, data, i); 397 if (i != 0) { 398 errno = i; 399 return -1; 400 } 401 return 0; 402 } 403 404 405 int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) 406 { 407 caddr_t data; 408 va_list ap; 409 int i; 410 411 va_start(ap, cmd); 412 data = va_arg(ap, caddr_t); 413 va_end(ap); 414 415 i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 416 if ((opts & OPT_DEBUG) || (i != 0)) 417 fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", 418 (u_int)cmd, data, i); 419 if (i != 0) { 420 errno = i; 421 return -1; 422 } 423 return 0; 424 } 425 426 427 int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) 428 { 429 caddr_t data; 430 va_list ap; 431 int i; 432 433 va_start(ap, cmd); 434 data = va_arg(ap, caddr_t); 435 va_end(ap); 436 437 i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 438 if ((opts & OPT_DEBUG) || (i != 0)) 439 fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", 440 (u_int)cmd, data, i); 441 if (i != 0) { 442 errno = i; 443 return -1; 444 } 445 return 0; 446 } 447 448 449 int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) 450 { 451 caddr_t data; 452 va_list ap; 453 int i; 454 455 va_start(ap, cmd); 456 data = va_arg(ap, caddr_t); 457 va_end(ap); 458 459 i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 460 if ((opts & OPT_DEBUG) || (i != 0)) 461 fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", 462 (u_int)cmd, data, i); 463 if (i != 0) { 464 errno = i; 465 return -1; 466 } 467 return 0; 468 } 469 #else 470 int ipftestioctl(dev, cmd, data) 471 dev_t dev; 472 ioctlcmd_t cmd; 473 void *data; 474 { 475 int i; 476 477 i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); 478 if ((opts & OPT_DEBUG) || (i != 0)) 479 fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i); 480 if (i != 0) { 481 errno = i; 482 return -1; 483 } 484 return 0; 485 } 486 487 488 int ipnattestioctl(dev, cmd, data) 489 dev_t dev; 490 ioctlcmd_t cmd; 491 void *data; 492 { 493 int i; 494 495 i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); 496 if ((opts & OPT_DEBUG) || (i != 0)) 497 fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i); 498 if (i != 0) { 499 errno = i; 500 return -1; 501 } 502 return 0; 503 } 504 505 506 int ipstatetestioctl(dev, cmd, data) 507 dev_t dev; 508 ioctlcmd_t cmd; 509 void *data; 510 { 511 int i; 512 513 i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 514 if ((opts & OPT_DEBUG) || (i != 0)) 515 fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i); 516 if (i != 0) { 517 errno = i; 518 return -1; 519 } 520 return 0; 521 } 522 523 524 int ipauthtestioctl(dev, cmd, data) 525 dev_t dev; 526 ioctlcmd_t cmd; 527 void *data; 528 { 529 int i; 530 531 i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 532 if ((opts & OPT_DEBUG) || (i != 0)) 533 fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); 534 if (i != 0) { 535 errno = i; 536 return -1; 537 } 538 return 0; 539 } 540 541 542 int ipsynctestioctl(dev, cmd, data) 543 dev_t dev; 544 ioctlcmd_t cmd; 545 void *data; 546 { 547 int i; 548 549 i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 550 if ((opts & OPT_DEBUG) || (i != 0)) 551 fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); 552 if (i != 0) { 553 errno = i; 554 return -1; 555 } 556 return 0; 557 } 558 559 560 int ipscantestioctl(dev, cmd, data) 561 dev_t dev; 562 ioctlcmd_t cmd; 563 void *data; 564 { 565 int i; 566 567 i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 568 if ((opts & OPT_DEBUG) || (i != 0)) 569 fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); 570 if (i != 0) { 571 errno = i; 572 return -1; 573 } 574 return 0; 575 } 576 577 578 int ipooltestioctl(dev, cmd, data) 579 dev_t dev; 580 ioctlcmd_t cmd; 581 void *data; 582 { 583 int i; 584 585 i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 586 if (opts & OPT_DEBUG) 587 fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i); 588 if (i != 0) { 589 errno = i; 590 return -1; 591 } 592 return 0; 593 } 594 #endif 595 596 597 int kmemcpy(addr, offset, size) 598 char *addr; 599 long offset; 600 int size; 601 { 602 bcopy((char *)offset, addr, size); 603 return 0; 604 } 605 606 607 int kstrncpy(buf, pos, n) 608 char *buf; 609 long pos; 610 int n; 611 { 612 char *ptr; 613 614 ptr = (char *)pos; 615 616 while ((n-- > 0) && (*buf++ = *ptr++)) 617 ; 618 return 0; 619 } 620 621 622 /* 623 * Display the built up NAT table rules and mapping entries. 624 */ 625 void dumpnat() 626 { 627 ipnat_t *ipn; 628 nat_t *nat; 629 630 printf("List of active MAP/Redirect filters:\n"); 631 for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) 632 printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); 633 printf("\nList of active sessions:\n"); 634 for (nat = nat_instances; nat; nat = nat->nat_next) { 635 printactivenat(nat, opts); 636 if (nat->nat_aps) 637 printaps(nat->nat_aps, opts); 638 } 639 } 640 641 642 /* 643 * Display the built up state table rules and mapping entries. 644 */ 645 void dumpstate() 646 { 647 ipstate_t *ips; 648 649 printf("List of active state sessions:\n"); 650 for (ips = ips_list; ips != NULL; ) 651 ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE), 652 fr_ticks); 653 } 654 655 656 void dumplookups() 657 { 658 iphtable_t *iph; 659 ip_pool_t *ipl; 660 int i; 661 662 printf("List of configured pools\n"); 663 for (i = 0; i < IPL_LOGSIZE; i++) 664 for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next) 665 printpool(ipl, bcopywrap, NULL, opts); 666 667 printf("List of configured hash tables\n"); 668 for (i = 0; i < IPL_LOGSIZE; i++) 669 for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next) 670 printhash(iph, bcopywrap, NULL, opts); 671 } 672 673 674 void dumpgroups() 675 { 676 frgroup_t *fg; 677 frentry_t *fr; 678 int i; 679 680 printf("List of groups configured (set 0)\n"); 681 for (i = 0; i < IPL_LOGSIZE; i++) 682 for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) { 683 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 684 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 685 for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { 686 #ifdef USE_QUAD_T 687 printf("%qu ",(unsigned long long)fr->fr_hits); 688 #else 689 printf("%ld ", fr->fr_hits); 690 #endif 691 printfr(fr, ipftestioctl); 692 } 693 } 694 695 printf("List of groups configured (set 1)\n"); 696 for (i = 0; i < IPL_LOGSIZE; i++) 697 for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) { 698 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 699 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 700 for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { 701 #ifdef USE_QUAD_T 702 printf("%qu ",(unsigned long long)fr->fr_hits); 703 #else 704 printf("%ld ", fr->fr_hits); 705 #endif 706 printfr(fr, ipftestioctl); 707 } 708 } 709 } 710 711 712 void drain_log(filename) 713 char *filename; 714 { 715 char buffer[DEFAULT_IPFLOGSIZE]; 716 struct iovec iov; 717 struct uio uio; 718 size_t resid; 719 int fd, i; 720 721 fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); 722 if (fd == -1) { 723 perror("drain_log:open"); 724 return; 725 } 726 727 for (i = 0; i <= IPL_LOGMAX; i++) 728 while (1) { 729 bzero((char *)&iov, sizeof(iov)); 730 iov.iov_base = buffer; 731 iov.iov_len = sizeof(buffer); 732 733 bzero((char *)&uio, sizeof(uio)); 734 uio.uio_iov = &iov; 735 uio.uio_iovcnt = 1; 736 uio.uio_resid = iov.iov_len; 737 resid = uio.uio_resid; 738 739 if (ipflog_read(i, &uio) == 0) { 740 /* 741 * If nothing was read then break out. 742 */ 743 if (uio.uio_resid == resid) 744 break; 745 write(fd, buffer, resid - uio.uio_resid); 746 } else 747 break; 748 } 749 750 close(fd); 751 } 752 753 754 void fixv4sums(m, ip) 755 mb_t *m; 756 ip_t *ip; 757 { 758 u_char *csump, *hdr; 759 760 ip->ip_sum = 0; 761 ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); 762 763 csump = (u_char *)ip; 764 csump += IP_HL(ip) << 2; 765 766 switch (ip->ip_p) 767 { 768 case IPPROTO_TCP : 769 hdr = csump; 770 csump += offsetof(tcphdr_t, th_sum); 771 break; 772 case IPPROTO_UDP : 773 hdr = csump; 774 csump += offsetof(udphdr_t, uh_sum); 775 break; 776 default : 777 csump = NULL; 778 hdr = NULL; 779 break; 780 } 781 if (hdr != NULL) { 782 *csump = 0; 783 *(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr); 784 } 785 } 786