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