1/* $NetBSD: ip_fil.c,v 1.6 2023/06/24 05:31:51 msaitoh Exp $ */ 2 3/* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * Id: ip_fil.c,v 1.1.1.2 2012/07/22 13:44:12 darrenr Exp 9 */ 10#if !defined(lint) 11static __attribute__((__used__)) const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 12static __attribute__((__used__)) const char rcsid[] = "@(#)Id: ip_fil.c,v 1.1.1.2 2012/07/22 13:44:12 darrenr Exp"; 13#endif 14 15#include "ipf.h" 16#include "md5.h" 17#include "ipt.h" 18 19ipf_main_softc_t ipfmain; 20 21static struct ifnet **ifneta = NULL; 22static int nifs = 0; 23 24struct rtentry; 25 26static void ipf_setifpaddr __P((struct ifnet *, char *)); 27void init_ifp __P((void)); 28#if defined(__sgi) && (IRIX < 60500) 29static int no_output __P((struct ifnet *, struct mbuf *, 30 struct sockaddr *)); 31static int write_output __P((struct ifnet *, struct mbuf *, 32 struct sockaddr *)); 33#else 34# if TRU64 >= 1885 35static int no_output __P((struct ifnet *, struct mbuf *, 36 struct sockaddr *, struct rtentry *, char *)); 37static int write_output __P((struct ifnet *, struct mbuf *, 38 struct sockaddr *, struct rtentry *, char *)); 39# else 40#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100) 41static int no_output(struct ifnet *, struct mbuf *, 42 const struct sockaddr *, struct rtentry *); 43static int write_output(struct ifnet *, struct mbuf *, 44 const struct sockaddr *, struct rtentry *); 45#else 46static int no_output __P((struct ifnet *, struct mbuf *, 47 struct sockaddr *, struct rtentry *)); 48static int write_output __P((struct ifnet *, struct mbuf *, 49 struct sockaddr *, struct rtentry *)); 50#endif 51# endif 52#endif 53 54 55int 56ipfattach(softc) 57 ipf_main_softc_t *softc; 58{ 59 return 0; 60} 61 62 63int 64ipfdetach(softc) 65 ipf_main_softc_t *softc; 66{ 67 return 0; 68} 69 70 71/* 72 * Filter ioctl interface. 73 */ 74int 75ipfioctl(softc, dev, cmd, data, mode) 76 ipf_main_softc_t *softc; 77 int dev; 78 ioctlcmd_t cmd; 79 void *data; 80 int mode; 81{ 82 int error = 0, unit = 0, uid; 83 84 uid = getuid(); 85 unit = dev; 86 87 SPL_NET(s); 88 89 error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL); 90 if (error != -1) { 91 SPL_X(s); 92 return error; 93 } 94 SPL_X(s); 95 return error; 96} 97 98 99void 100ipf_forgetifp(softc, ifp) 101 ipf_main_softc_t *softc; 102 void *ifp; 103{ 104 register frentry_t *f; 105 106 WRITE_ENTER(&softc->ipf_mutex); 107 for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL); 108 f = f->fr_next) 109 if (f->fr_ifa == ifp) 110 f->fr_ifa = (void *)-1; 111 for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL); 112 f = f->fr_next) 113 if (f->fr_ifa == ifp) 114 f->fr_ifa = (void *)-1; 115 for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL); 116 f = f->fr_next) 117 if (f->fr_ifa == ifp) 118 f->fr_ifa = (void *)-1; 119 for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL); 120 f = f->fr_next) 121 if (f->fr_ifa == ifp) 122 f->fr_ifa = (void *)-1; 123 RWLOCK_EXIT(&softc->ipf_mutex); 124 ipf_nat_sync(softc, ifp); 125 ipf_lookup_sync(softc, ifp); 126} 127 128 129static int 130#if defined(__sgi) && (IRIX < 60500) 131no_output(ifp, m, s) 132#else 133# if TRU64 >= 1885 134no_output (ifp, m, s, rt, cp) 135 char *cp; 136# else 137no_output(ifp, m, s, rt) 138# endif 139 struct rtentry *rt; 140#endif 141 struct ifnet *ifp; 142 struct mbuf *m; 143 const struct sockaddr *s; 144{ 145 return 0; 146} 147 148 149static int 150#if defined(__sgi) && (IRIX < 60500) 151write_output(ifp, m, s) 152#else 153# if TRU64 >= 1885 154write_output (ifp, m, s, rt, cp) 155 char *cp; 156# else 157write_output(ifp, m, s, rt) 158# endif 159 struct rtentry *rt; 160#endif 161 struct ifnet *ifp; 162 struct mbuf *m; 163 const struct sockaddr *s; 164{ 165 char fname[32]; 166 mb_t *mb; 167 ip_t *ip; 168 int fd; 169 170 mb = (mb_t *)m; 171 ip = MTOD(mb, ip_t *); 172 173#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 174 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 175 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 176 sprintf(fname, "/tmp/%s", ifp->if_xname); 177#else 178 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 179#endif 180 fd = open(fname, O_WRONLY|O_APPEND); 181 if (fd == -1) { 182 perror("open"); 183 return -1; 184 } 185 write(fd, (char *)ip, ntohs(ip->ip_len)); 186 close(fd); 187 return 0; 188} 189 190 191static void 192ipf_setifpaddr(ifp, addr) 193 struct ifnet *ifp; 194 char *addr; 195{ 196#ifdef __sgi 197 struct in_ifaddr *ifa; 198#else 199 struct ifaddr *ifa; 200#endif 201 202#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 203 if (ifp->if_addrlist.tqh_first != NULL) 204#else 205# ifdef __sgi 206 if (ifp->in_ifaddr != NULL) 207# else 208 if (ifp->if_addrlist != NULL) 209# endif 210#endif 211 return; 212 213 ifa = (struct ifaddr *)calloc(1, sizeof(*ifa)); 214#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 215 ifp->if_addrlist.tqh_first = ifa; 216#else 217# ifdef __sgi 218 ifp->in_ifaddr = ifa; 219# else 220 ifp->if_addrlist = ifa; 221# endif 222#endif 223 224 if (ifa != NULL) { 225 struct sockaddr_in *sin; 226 227#ifdef __sgi 228 sin = (struct sockaddr_in *)&ifa->ia_addr; 229#else 230 sin = (struct sockaddr_in *)&ifa->ifa_addr; 231#endif 232#ifdef USE_INET6 233 if (index(addr, ':') != NULL) { 234 struct sockaddr_in6 *sin6; 235 236 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 237 sin6->sin6_family = AF_INET6; 238 inet_pton(AF_INET6, addr, &sin6->sin6_addr); 239 } else 240#endif 241 { 242 sin->sin_family = AF_INET; 243 sin->sin_addr.s_addr = inet_addr(addr); 244 if (sin->sin_addr.s_addr == 0) 245 abort(); 246 } 247 } 248} 249 250struct ifnet * 251get_unit(name, family) 252 char *name; 253 int family; 254{ 255 struct ifnet *ifp, **ifpp, **old_ifneta; 256 char *addr; 257#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 258 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 259 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 260 261 if (!*name) 262 return NULL; 263 264 if (name == NULL) 265 name = "anon0"; 266 267 addr = strchr(name, '='); 268 if (addr != NULL) 269 *addr++ = '\0'; 270 271 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 272 if (!strcmp(name, ifp->if_xname)) { 273 if (addr != NULL) 274 ipf_setifpaddr(ifp, addr); 275 return ifp; 276 } 277 } 278#else 279 char *s, ifname[LIFNAMSIZ+1]; 280 281 if (name == NULL) 282 name = "anon0"; 283 284 addr = strchr(name, '='); 285 if (addr != NULL) 286 *addr++ = '\0'; 287 288 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 289 COPYIFNAME(family, ifp, ifname); 290 if (!strcmp(name, ifname)) { 291 if (addr != NULL) 292 ipf_setifpaddr(ifp, addr); 293 return ifp; 294 } 295 } 296#endif 297 298 if (!ifneta) { 299 ifneta = (struct ifnet **)calloc(1, sizeof(ifp) * 2); 300 if (!ifneta) 301 return NULL; 302 ifneta[1] = NULL; 303 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); 304 if (!ifneta[0]) { 305 free(ifneta); 306 return NULL; 307 } 308 nifs = 1; 309 } else { 310 old_ifneta = ifneta; 311 nifs++; 312 ifneta = (struct ifnet **)realloc(ifneta, 313 (nifs + 1) * sizeof(ifp)); 314 if (!ifneta) { 315 free(old_ifneta); 316 nifs = 0; 317 return NULL; 318 } 319 ifneta[nifs] = NULL; 320 ifneta[nifs - 1] = (struct ifnet *)calloc(1, sizeof(*ifp)); 321 if (!ifneta[nifs - 1]) { 322 nifs--; 323 return NULL; 324 } 325 } 326 ifp = ifneta[nifs - 1]; 327 328#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 329 TAILQ_INIT(&ifp->if_addrlist); 330#endif 331#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 332 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 333 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 334 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 335#else 336 s = name + strlen(name) - 1; 337 for (; s > name; s--) { 338 if (!ISDIGIT(*s)) { 339 s++; 340 break; 341 } 342 } 343 344 if ((s > name) && (*s != 0) && ISDIGIT(*s)) { 345 ifp->if_unit = atoi(s); 346 ifp->if_name = (char *)malloc(s - name + 1); 347 (void) strncpy(ifp->if_name, name, s - name); 348 ifp->if_name[s - name] = '\0'; 349 } else { 350 ifp->if_name = strdup(name); 351 ifp->if_unit = -1; 352 } 353#endif 354 ifp->if_output = (void *)no_output; 355 356 if (addr != NULL) { 357 ipf_setifpaddr(ifp, addr); 358 } 359 360 return ifp; 361} 362 363 364char * 365get_ifname(ifp) 366 struct ifnet *ifp; 367{ 368 static char ifname[LIFNAMSIZ]; 369 370#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ 371 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 372 sprintf(ifname, "%s", ifp->if_xname); 373#else 374 if (ifp->if_unit != -1) 375 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 376 else 377 strcpy(ifname, ifp->if_name); 378#endif 379 return ifname; 380} 381 382 383 384void 385init_ifp() 386{ 387 struct ifnet *ifp, **ifpp; 388 char fname[32]; 389 int fd; 390 391#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 392 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 393 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 394 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 395 ifp->if_output = (void *)write_output; 396 sprintf(fname, "/tmp/%s", ifp->if_xname); 397 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 398 if (fd == -1) 399 perror("open"); 400 else 401 close(fd); 402 } 403#else 404 405 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 406 ifp->if_output = (void *)write_output; 407 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 408 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 409 if (fd == -1) 410 perror("open"); 411 else 412 close(fd); 413 } 414#endif 415} 416 417 418int 419ipf_fastroute(m, mpp, fin, fdp) 420 mb_t *m, **mpp; 421 fr_info_t *fin; 422 frdest_t *fdp; 423{ 424 struct ifnet *ifp; 425 ip_t *ip = fin->fin_ip; 426 frdest_t node; 427 int error = 0; 428 frentry_t *fr; 429 void *sifp; 430 int sout; 431 432 sifp = fin->fin_ifp; 433 sout = fin->fin_out; 434 fr = fin->fin_fr; 435 ip->ip_sum = 0; 436 437 if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 438 (fdp->fd_type == FRD_DSTLIST)) { 439 bzero(&node, sizeof(node)); 440 ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node); 441 fdp = &node; 442 } 443 ifp = fdp->fd_ptr; 444 445 if (ifp == NULL) 446 return 0; /* no routing table out here */ 447 448 if (fin->fin_out == 0) { 449 fin->fin_ifp = ifp; 450 fin->fin_out = 1; 451 (void) ipf_acctpkt(fin, NULL); 452 fin->fin_fr = NULL; 453 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 454 u_32_t pass; 455 456 (void) ipf_state_check(fin, &pass); 457 } 458 459 switch (ipf_nat_checkout(fin, NULL)) 460 { 461 case 0 : 462 break; 463 case 1 : 464 ip->ip_sum = 0; 465 break; 466 case -1 : 467 error = -1; 468 goto done; 469 break; 470 } 471 472 } 473 474 m->mb_ifp = ifp; 475 printpacket(fin->fin_out, m); 476 477#if defined(__sgi) && (IRIX < 60500) 478 (*ifp->if_output)(ifp, (void *)ip, NULL); 479# if TRU64 >= 1885 480 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 481# else 482 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 483# endif 484#endif 485done: 486 fin->fin_ifp = sifp; 487 fin->fin_out = sout; 488 return error; 489} 490 491 492int 493ipf_send_reset(fin) 494 fr_info_t *fin; 495{ 496 ipfkverbose("- TCP RST sent\n"); 497 return 0; 498} 499 500 501int 502ipf_send_icmp_err(type, fin, dst) 503 int type; 504 fr_info_t *fin; 505 int dst; 506{ 507 ipfkverbose("- ICMP unreachable sent\n"); 508 return 0; 509} 510 511 512void 513m_freem(m) 514 mb_t *m; 515{ 516 return; 517} 518 519 520void 521m_copydata(m, off, len, cp) 522 mb_t *m; 523 int off, len; 524 void * cp; 525{ 526 bcopy((char *)m + off, cp, len); 527} 528 529 530int 531ipfuiomove(buf, len, rwflag, uio) 532 void *buf; 533 int len, rwflag; 534 struct uio *uio; 535{ 536 int left, ioc, num, offset; 537 struct iovec *io; 538 char *start; 539 540 if (rwflag == UIO_READ) { 541 left = len; 542 ioc = 0; 543 544 offset = uio->uio_offset; 545 546 while ((left > 0) && (ioc < uio->uio_iovcnt)) { 547 io = uio->uio_iov + ioc; 548 num = io->iov_len; 549 if (num > left) 550 num = left; 551 start = (char *)io->iov_base + offset; 552 if (start > (char *)io->iov_base + io->iov_len) { 553 offset -= io->iov_len; 554 ioc++; 555 continue; 556 } 557 bcopy(buf, start, num); 558 uio->uio_resid -= num; 559 uio->uio_offset += num; 560 left -= num; 561 if (left > 0) 562 ioc++; 563 } 564 if (left > 0) 565 return EFAULT; 566 } 567 return 0; 568} 569 570 571u_32_t 572ipf_newisn(fin) 573 fr_info_t *fin; 574{ 575 static int iss_seq_off = 0; 576 u_char hash[16]; 577 u_32_t newiss; 578 MD5_CTX ctx; 579 580 /* 581 * Compute the base value of the ISS. It is a hash 582 * of (saddr, sport, daddr, dport, secret). 583 */ 584 MD5Init(&ctx); 585 586 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 587 sizeof(fin->fin_fi.fi_src)); 588 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 589 sizeof(fin->fin_fi.fi_dst)); 590 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 591 592 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 593 594 MD5Final(hash, &ctx); 595 596 memcpy(&newiss, hash, sizeof(newiss)); 597 598 /* 599 * Now increment our "timer", and add it in to 600 * the computed value. 601 * 602 * XXX Use `addin'? 603 * XXX TCP_ISSINCR too large to use? 604 */ 605 iss_seq_off += 0x00010000; 606 newiss += iss_seq_off; 607 return newiss; 608} 609 610 611/* ------------------------------------------------------------------------ */ 612/* Function: ipf_nextipid */ 613/* Returns: int - 0 == success, -1 == error (packet should be dropped) */ 614/* Parameters: fin(I) - pointer to packet information */ 615/* */ 616/* Returns the next IPv4 ID to use for this packet. */ 617/* ------------------------------------------------------------------------ */ 618EXTERN_INLINE u_short 619ipf_nextipid(fin) 620 fr_info_t *fin; 621{ 622 static u_short ipid = 0; 623 ipf_main_softc_t *softc = fin->fin_main_soft; 624 u_short id; 625 626 MUTEX_ENTER(&softc->ipf_rw); 627 if (fin->fin_pktnum != 0) { 628 /* 629 * The -1 is for aligned test results. 630 */ 631 id = (fin->fin_pktnum - 1) & 0xffff; 632 } else { 633 } 634 id = ipid++; 635 MUTEX_EXIT(&softc->ipf_rw); 636 637 return id; 638} 639 640 641EXTERN_INLINE int 642ipf_checkv4sum(fin) 643 fr_info_t *fin; 644{ 645 646 if (fin->fin_flx & FI_SHORT) 647 return 1; 648 649 if (ipf_checkl4sum(fin) == -1) { 650 fin->fin_flx |= FI_BAD; 651 return -1; 652 } 653 return 0; 654} 655 656 657#ifdef USE_INET6 658EXTERN_INLINE int 659ipf_checkv6sum(fin) 660 fr_info_t *fin; 661{ 662 if (fin->fin_flx & FI_SHORT) 663 return 1; 664 665 if (ipf_checkl4sum(fin) == -1) { 666 fin->fin_flx |= FI_BAD; 667 return -1; 668 } 669 return 0; 670} 671#endif 672 673 674#if 0 675/* 676 * See above for description, except that all addressing is in user space. 677 */ 678int 679copyoutptr(softc, src, dst, size) 680 void *src, *dst; 681 size_t size; 682{ 683 caddr_t ca; 684 685 bcopy(dst, (char *)&ca, sizeof(ca)); 686 bcopy(src, ca, size); 687 return 0; 688} 689 690 691/* 692 * See above for description, except that all addressing is in user space. 693 */ 694int 695copyinptr(src, dst, size) 696 void *src, *dst; 697 size_t size; 698{ 699 caddr_t ca; 700 701 bcopy(src, (char *)&ca, sizeof(ca)); 702 bcopy(ca, dst, size); 703 return 0; 704} 705#endif 706 707 708/* 709 * return the first IP Address associated with an interface 710 */ 711int 712ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) 713 ipf_main_softc_t *softc; 714 int v, atype; 715 void *ifptr; 716 i6addr_t *inp, *inpmask; 717{ 718 struct ifnet *ifp = ifptr; 719#ifdef __sgi 720 struct in_ifaddr *ifa; 721#else 722 struct ifaddr *ifa; 723#endif 724 725#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 726 ifa = ifp->if_addrlist.tqh_first; 727#else 728# ifdef __sgi 729 ifa = (struct in_ifaddr *)ifp->in_ifaddr; 730# else 731 ifa = ifp->if_addrlist; 732# endif 733#endif 734 if (ifa != NULL) { 735 if (v == 4) { 736 struct sockaddr_in *sin, mask; 737 738 mask.sin_addr.s_addr = 0xffffffff; 739 740#ifdef __sgi 741 sin = (struct sockaddr_in *)&ifa->ia_addr; 742#else 743 sin = (struct sockaddr_in *)&ifa->ifa_addr; 744#endif 745 746 return ipf_ifpfillv4addr(atype, sin, &mask, 747 &inp->in4, &inpmask->in4); 748 } 749#ifdef USE_INET6 750 if (v == 6) { 751 struct sockaddr_in6 *sin6, mask; 752 753 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 754 ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; 755 ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; 756 ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; 757 ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; 758 return ipf_ifpfillv6addr(atype, sin6, &mask, 759 inp, inpmask); 760 } 761#endif 762 } 763 return 0; 764} 765 766 767/* 768 * This function is not meant to be random, rather just produce a 769 * sequence of numbers that isn't linear to show "randomness". 770 */ 771u_32_t 772ipf_random() 773{ 774 static unsigned int last = 0xa5a5a5a5; 775 static int calls = 0; 776 int number; 777 778 calls++; 779 780 /* 781 * These are deliberately chosen to ensure that there is some 782 * attempt to test whether the output covers the range in test n18. 783 */ 784 switch (calls) 785 { 786 case 1 : 787 number = 0; 788 break; 789 case 2 : 790 number = 4; 791 break; 792 case 3 : 793 number = 3999; 794 break; 795 case 4 : 796 number = 4000; 797 break; 798 case 5 : 799 number = 48999; 800 break; 801 case 6 : 802 number = 49000; 803 break; 804 default : 805 number = last; 806 last *= calls; 807 last++; 808 number ^= last; 809 break; 810 } 811 return number; 812} 813 814 815int 816ipf_verifysrc(fin) 817 fr_info_t *fin; 818{ 819 return 1; 820} 821 822 823int 824ipf_inject(fin, m) 825 fr_info_t *fin; 826 mb_t *m; 827{ 828 FREE_MB_T(m); 829 830 return 0; 831} 832 833 834u_int 835ipf_pcksum(fin, hlen, sum) 836 fr_info_t *fin; 837 int hlen; 838 u_int sum; 839{ 840 u_short *sp; 841 u_int sum2; 842 int slen; 843 844 slen = fin->fin_plen - hlen; 845 sp = (u_short *)((u_char *)fin->fin_ip + hlen); 846 847 for (; slen > 1; slen -= 2) 848 sum += *sp++; 849 if (slen) 850 sum += ntohs(*(u_char *)sp << 8); 851 while (sum > 0xffff) 852 sum = (sum & 0xffff) + (sum >> 16); 853 sum2 = (u_short)(~sum & 0xffff); 854 855 return sum2; 856} 857 858 859void * 860ipf_pullup(m, fin, plen) 861 mb_t *m; 862 fr_info_t *fin; 863 int plen; 864{ 865 if (M_LEN(m) >= plen) 866 return fin->fin_ip; 867 868 /* 869 * Fake ipf_pullup failing 870 */ 871 fin->fin_reason = FRB_PULLUP; 872 *fin->fin_mp = NULL; 873 fin->fin_m = NULL; 874 fin->fin_ip = NULL; 875 return NULL; 876} 877