1caf43b02SWarner Losh /*- 251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 351369649SPedro F. Giffuni * 482cd038dSYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 582cd038dSYoshinobu Inoue * All rights reserved. 682cd038dSYoshinobu Inoue * 782cd038dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 882cd038dSYoshinobu Inoue * modification, are permitted provided that the following conditions 982cd038dSYoshinobu Inoue * are met: 1082cd038dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 1182cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 1282cd038dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 1382cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 1482cd038dSYoshinobu Inoue * documentation and/or other materials provided with the distribution. 1582cd038dSYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 1682cd038dSYoshinobu Inoue * may be used to endorse or promote products derived from this software 1782cd038dSYoshinobu Inoue * without specific prior written permission. 1882cd038dSYoshinobu Inoue * 1982cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2082cd038dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2182cd038dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2282cd038dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2382cd038dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2482cd038dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2582cd038dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2682cd038dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2782cd038dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2882cd038dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2982cd038dSYoshinobu Inoue * SUCH DAMAGE. 30b48287a3SDavid E. O'Brien * 31b48287a3SDavid E. O'Brien * $KAME: in6_cksum.c,v 1.10 2000/12/03 00:53:59 itojun Exp $ 3282cd038dSYoshinobu Inoue */ 3382cd038dSYoshinobu Inoue 34caf43b02SWarner Losh /*- 3582cd038dSYoshinobu Inoue * Copyright (c) 1988, 1992, 1993 3682cd038dSYoshinobu Inoue * The Regents of the University of California. All rights reserved. 3782cd038dSYoshinobu Inoue * 3882cd038dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 3982cd038dSYoshinobu Inoue * modification, are permitted provided that the following conditions 4082cd038dSYoshinobu Inoue * are met: 4182cd038dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 4282cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 4382cd038dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 4482cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 4582cd038dSYoshinobu Inoue * documentation and/or other materials provided with the distribution. 46fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 4782cd038dSYoshinobu Inoue * may be used to endorse or promote products derived from this software 4882cd038dSYoshinobu Inoue * without specific prior written permission. 4982cd038dSYoshinobu Inoue * 5082cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5182cd038dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5282cd038dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5382cd038dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5482cd038dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5582cd038dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5682cd038dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5782cd038dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5882cd038dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5982cd038dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6082cd038dSYoshinobu Inoue * SUCH DAMAGE. 6182cd038dSYoshinobu Inoue * 6282cd038dSYoshinobu Inoue * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 6382cd038dSYoshinobu Inoue */ 6482cd038dSYoshinobu Inoue 65b48287a3SDavid E. O'Brien #include <sys/cdefs.h> 66b48287a3SDavid E. O'Brien __FBSDID("$FreeBSD$"); 67b48287a3SDavid E. O'Brien 6882cd038dSYoshinobu Inoue #include <sys/param.h> 6982cd038dSYoshinobu Inoue #include <sys/mbuf.h> 7082cd038dSYoshinobu Inoue #include <sys/systm.h> 7182cd038dSYoshinobu Inoue #include <netinet/in.h> 72686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h> 73a1f7e5f8SHajimu UMEMOTO #include <netinet6/scope6_var.h> 7482cd038dSYoshinobu Inoue 7582cd038dSYoshinobu Inoue /* 7682cd038dSYoshinobu Inoue * Checksum routine for Internet Protocol family headers (Portable Version). 7782cd038dSYoshinobu Inoue * 7882cd038dSYoshinobu Inoue * This routine is very heavily used in the network 7982cd038dSYoshinobu Inoue * code and should be modified for each CPU to be as fast as possible. 8082cd038dSYoshinobu Inoue */ 8182cd038dSYoshinobu Inoue 8282cd038dSYoshinobu Inoue #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) 834c888125SRui Paulo #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; (void)ADDCARRY(sum);} 8482cd038dSYoshinobu Inoue 85*6775ef41SMark Johnston union l_util { 86*6775ef41SMark Johnston uint16_t s[2]; 87*6775ef41SMark Johnston uint32_t l; 88*6775ef41SMark Johnston }; 89*6775ef41SMark Johnston 90*6775ef41SMark Johnston union s_util { 91*6775ef41SMark Johnston uint8_t c[2]; 92*6775ef41SMark Johnston uint16_t s; 93*6775ef41SMark Johnston }; 94*6775ef41SMark Johnston 95ecade87eSBjoern A. Zeeb static int 96ecade87eSBjoern A. Zeeb _in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum) 97ecade87eSBjoern A. Zeeb { 98ecade87eSBjoern A. Zeeb int sum; 99ecade87eSBjoern A. Zeeb uint16_t scope, *w; 100ecade87eSBjoern A. Zeeb union { 101ecade87eSBjoern A. Zeeb u_int16_t phs[4]; 102ecade87eSBjoern A. Zeeb struct { 103ecade87eSBjoern A. Zeeb u_int32_t ph_len; 104ecade87eSBjoern A. Zeeb u_int8_t ph_zero[3]; 105ecade87eSBjoern A. Zeeb u_int8_t ph_nxt; 106ecade87eSBjoern A. Zeeb } __packed ph; 107ecade87eSBjoern A. Zeeb } uph; 108ecade87eSBjoern A. Zeeb 109ecade87eSBjoern A. Zeeb sum = csum; 110ecade87eSBjoern A. Zeeb 111ecade87eSBjoern A. Zeeb /* 112ecade87eSBjoern A. Zeeb * First create IP6 pseudo header and calculate a summary. 113ecade87eSBjoern A. Zeeb */ 114ecade87eSBjoern A. Zeeb uph.ph.ph_len = htonl(len); 115ecade87eSBjoern A. Zeeb uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0; 116ecade87eSBjoern A. Zeeb uph.ph.ph_nxt = nxt; 117ecade87eSBjoern A. Zeeb 118ecade87eSBjoern A. Zeeb /* Payload length and upper layer identifier. */ 119ecade87eSBjoern A. Zeeb sum += uph.phs[0]; sum += uph.phs[1]; 120ecade87eSBjoern A. Zeeb sum += uph.phs[2]; sum += uph.phs[3]; 121ecade87eSBjoern A. Zeeb 122ecade87eSBjoern A. Zeeb /* IPv6 source address. */ 123ecade87eSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_src); 124ecade87eSBjoern A. Zeeb w = (u_int16_t *)&ip6->ip6_src; 125ecade87eSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 126ecade87eSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 127ecade87eSBjoern A. Zeeb if (scope != 0) 128ecade87eSBjoern A. Zeeb sum -= scope; 129ecade87eSBjoern A. Zeeb 130ecade87eSBjoern A. Zeeb /* IPv6 destination address. */ 131ecade87eSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_dst); 132ecade87eSBjoern A. Zeeb w = (u_int16_t *)&ip6->ip6_dst; 133ecade87eSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 134ecade87eSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 135ecade87eSBjoern A. Zeeb if (scope != 0) 136ecade87eSBjoern A. Zeeb sum -= scope; 137ecade87eSBjoern A. Zeeb 138ecade87eSBjoern A. Zeeb return (sum); 139ecade87eSBjoern A. Zeeb } 140ecade87eSBjoern A. Zeeb 141ecade87eSBjoern A. Zeeb int 142ecade87eSBjoern A. Zeeb in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum) 143ecade87eSBjoern A. Zeeb { 144*6775ef41SMark Johnston union l_util l_util; 145ecade87eSBjoern A. Zeeb int sum; 146ecade87eSBjoern A. Zeeb 147ecade87eSBjoern A. Zeeb sum = _in6_cksum_pseudo(ip6, len, nxt, csum); 148ecade87eSBjoern A. Zeeb REDUCE; 149ecade87eSBjoern A. Zeeb return (sum); 150ecade87eSBjoern A. Zeeb } 151ecade87eSBjoern A. Zeeb 152*6775ef41SMark Johnston static int 153*6775ef41SMark Johnston in6_cksumdata(void *data, int *lenp, uint8_t *residp, int rlen) 154*6775ef41SMark Johnston { 155*6775ef41SMark Johnston union l_util l_util; 156*6775ef41SMark Johnston union s_util s_util; 157*6775ef41SMark Johnston uint16_t *w; 158*6775ef41SMark Johnston int len, sum; 159*6775ef41SMark Johnston bool byte_swapped; 160*6775ef41SMark Johnston 161*6775ef41SMark Johnston KASSERT(*lenp >= 0, ("%s: negative len %d", __func__, *lenp)); 162*6775ef41SMark Johnston KASSERT(rlen == 0 || rlen == 1, ("%s: rlen %d", __func__, rlen)); 163*6775ef41SMark Johnston 164*6775ef41SMark Johnston len = *lenp; 165*6775ef41SMark Johnston sum = 0; 166*6775ef41SMark Johnston 167*6775ef41SMark Johnston if (len == 0) { 168*6775ef41SMark Johnston len = rlen; 169*6775ef41SMark Johnston goto out; 170*6775ef41SMark Johnston } 171*6775ef41SMark Johnston 172*6775ef41SMark Johnston byte_swapped = false; 173*6775ef41SMark Johnston w = data; 174*6775ef41SMark Johnston 175*6775ef41SMark Johnston /* 176*6775ef41SMark Johnston * Do we have a residual byte left over from the previous buffer? 177*6775ef41SMark Johnston */ 178*6775ef41SMark Johnston if (rlen == 1) { 179*6775ef41SMark Johnston s_util.c[0] = *residp; 180*6775ef41SMark Johnston s_util.c[1] = *(uint8_t *)w; 181*6775ef41SMark Johnston sum += s_util.s; 182*6775ef41SMark Johnston w = (uint16_t *)((uint8_t *)w + 1); 183*6775ef41SMark Johnston len--; 184*6775ef41SMark Johnston rlen = 0; 185*6775ef41SMark Johnston } 186*6775ef41SMark Johnston 187*6775ef41SMark Johnston /* 188*6775ef41SMark Johnston * Force to even boundary. 189*6775ef41SMark Johnston */ 190*6775ef41SMark Johnston if ((1 & (uintptr_t)w) && len > 0) { 191*6775ef41SMark Johnston REDUCE; 192*6775ef41SMark Johnston sum <<= 8; 193*6775ef41SMark Johnston s_util.c[0] = *(uint8_t *)w; 194*6775ef41SMark Johnston w = (uint16_t *)((uint8_t *)w + 1); 195*6775ef41SMark Johnston len--; 196*6775ef41SMark Johnston byte_swapped = true; 197*6775ef41SMark Johnston } 198*6775ef41SMark Johnston 199*6775ef41SMark Johnston /* 200*6775ef41SMark Johnston * Unroll the loop to make overhead from branches &c small. 201*6775ef41SMark Johnston */ 202*6775ef41SMark Johnston while ((len -= 32) >= 0) { 203*6775ef41SMark Johnston sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 204*6775ef41SMark Johnston sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 205*6775ef41SMark Johnston sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 206*6775ef41SMark Johnston sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 207*6775ef41SMark Johnston w += 16; 208*6775ef41SMark Johnston } 209*6775ef41SMark Johnston len += 32; 210*6775ef41SMark Johnston while ((len -= 8) >= 0) { 211*6775ef41SMark Johnston sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 212*6775ef41SMark Johnston w += 4; 213*6775ef41SMark Johnston } 214*6775ef41SMark Johnston len += 8; 215*6775ef41SMark Johnston if (len == 0 && !byte_swapped) 216*6775ef41SMark Johnston goto out; 217*6775ef41SMark Johnston REDUCE; 218*6775ef41SMark Johnston while ((len -= 2) >= 0) { 219*6775ef41SMark Johnston sum += *w++; 220*6775ef41SMark Johnston } 221*6775ef41SMark Johnston if (byte_swapped) { 222*6775ef41SMark Johnston REDUCE; 223*6775ef41SMark Johnston sum <<= 8; 224*6775ef41SMark Johnston if (len == -1) { 225*6775ef41SMark Johnston s_util.c[1] = *(uint8_t *)w; 226*6775ef41SMark Johnston sum += s_util.s; 227*6775ef41SMark Johnston } else /* len == -2 */ 228*6775ef41SMark Johnston *residp = s_util.c[0]; 229*6775ef41SMark Johnston len++; 230*6775ef41SMark Johnston } else if (len == -1) 231*6775ef41SMark Johnston *residp = *(uint8_t *)w; 232*6775ef41SMark Johnston out: 233*6775ef41SMark Johnston *lenp = len & 1; 234*6775ef41SMark Johnston return (sum); 235*6775ef41SMark Johnston } 236*6775ef41SMark Johnston 237*6775ef41SMark Johnston struct in6_cksum_partial_arg { 238*6775ef41SMark Johnston int sum; 239*6775ef41SMark Johnston int rlen; 240*6775ef41SMark Johnston uint8_t resid; 241*6775ef41SMark Johnston }; 242*6775ef41SMark Johnston 243*6775ef41SMark Johnston static int 244*6775ef41SMark Johnston in6_cksum_partial_one(void *_arg, void *data, u_int len) 245*6775ef41SMark Johnston { 246*6775ef41SMark Johnston struct in6_cksum_partial_arg *arg = _arg; 247*6775ef41SMark Johnston 248*6775ef41SMark Johnston arg->sum += in6_cksumdata(data, &len, &arg->resid, arg->rlen); 249*6775ef41SMark Johnston arg->rlen = len; 250*6775ef41SMark Johnston return (0); 251*6775ef41SMark Johnston } 252*6775ef41SMark Johnston 25382cd038dSYoshinobu Inoue /* 2546d79f3f6SRebecca Cran * m MUST contain a contiguous IP6 header. 2559d5abbddSJens Schweikhardt * off is an offset where TCP/UDP/ICMP6 header starts. 25682cd038dSYoshinobu Inoue * len is a total length of a transport segment. 25782cd038dSYoshinobu Inoue * (e.g. TCP header + TCP payload) 25876b96fbcSMichael Tuexen * cov is the number of bytes to be taken into account for the checksum 25982cd038dSYoshinobu Inoue */ 26082cd038dSYoshinobu Inoue int 261*6775ef41SMark Johnston in6_cksum_partial(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len, 262*6775ef41SMark Johnston uint32_t cov) 26382cd038dSYoshinobu Inoue { 264*6775ef41SMark Johnston struct in6_cksum_partial_arg arg; 265*6775ef41SMark Johnston union l_util l_util; 266*6775ef41SMark Johnston union s_util s_util; 26782cd038dSYoshinobu Inoue struct ip6_hdr *ip6; 268*6775ef41SMark Johnston uint16_t *w, scope; 2692889eb8bSBjoern A. Zeeb int sum; 27029a3d1b0SJun-ichiro itojun Hagino union { 271*6775ef41SMark Johnston uint16_t phs[4]; 27229a3d1b0SJun-ichiro itojun Hagino struct { 273*6775ef41SMark Johnston uint32_t ph_len; 274*6775ef41SMark Johnston uint8_t ph_zero[3]; 275*6775ef41SMark Johnston uint8_t ph_nxt; 2761c0ee39eSWarner Losh } __packed ph; 27729a3d1b0SJun-ichiro itojun Hagino } uph; 27882cd038dSYoshinobu Inoue 2792889eb8bSBjoern A. Zeeb /* Sanity check. */ 2802889eb8bSBjoern A. Zeeb KASSERT(m->m_pkthdr.len >= off + len, ("%s: mbuf len (%d) < off(%d)+" 2812889eb8bSBjoern A. Zeeb "len(%d)", __func__, m->m_pkthdr.len, off, len)); 282*6775ef41SMark Johnston KASSERT(m->m_len >= sizeof(*ip6), 283*6775ef41SMark Johnston ("%s: mbuf len %d < sizeof(ip6)", __func__, m->m_len)); 28429a3d1b0SJun-ichiro itojun Hagino 28582cd038dSYoshinobu Inoue /* 28682cd038dSYoshinobu Inoue * First create IP6 pseudo header and calculate a summary. 28782cd038dSYoshinobu Inoue */ 28882cd038dSYoshinobu Inoue uph.ph.ph_len = htonl(len); 2892889eb8bSBjoern A. Zeeb uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0; 29082cd038dSYoshinobu Inoue uph.ph.ph_nxt = nxt; 29182cd038dSYoshinobu Inoue 2922889eb8bSBjoern A. Zeeb /* Payload length and upper layer identifier. */ 2932889eb8bSBjoern A. Zeeb sum = uph.phs[0]; sum += uph.phs[1]; 29482cd038dSYoshinobu Inoue sum += uph.phs[2]; sum += uph.phs[3]; 29582cd038dSYoshinobu Inoue 2962889eb8bSBjoern A. Zeeb ip6 = mtod(m, struct ip6_hdr *); 2972889eb8bSBjoern A. Zeeb 2982889eb8bSBjoern A. Zeeb /* IPv6 source address. */ 2992889eb8bSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_src); 300*6775ef41SMark Johnston w = (uint16_t *)&ip6->ip6_src; 3012889eb8bSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 3022889eb8bSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 3032889eb8bSBjoern A. Zeeb if (scope != 0) 3042889eb8bSBjoern A. Zeeb sum -= scope; 3052889eb8bSBjoern A. Zeeb 3062889eb8bSBjoern A. Zeeb /* IPv6 destination address. */ 3072889eb8bSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_dst); 308*6775ef41SMark Johnston w = (uint16_t *)&ip6->ip6_dst; 3092889eb8bSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 3102889eb8bSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 3112889eb8bSBjoern A. Zeeb if (scope != 0) 3122889eb8bSBjoern A. Zeeb sum -= scope; 3132889eb8bSBjoern A. Zeeb 31482cd038dSYoshinobu Inoue /* 315*6775ef41SMark Johnston * Loop over the rest of the mbuf chain and compute the rest of the 316*6775ef41SMark Johnston * checksum. m_apply() handles unmapped mbufs. 31782cd038dSYoshinobu Inoue */ 318*6775ef41SMark Johnston arg.sum = sum; 319*6775ef41SMark Johnston arg.rlen = 0; 320*6775ef41SMark Johnston (void)m_apply(m, off, cov, in6_cksum_partial_one, &arg); 321*6775ef41SMark Johnston sum = arg.sum; 3222889eb8bSBjoern A. Zeeb 32382cd038dSYoshinobu Inoue /* 324*6775ef41SMark Johnston * Handle a residual byte. 32582cd038dSYoshinobu Inoue */ 326*6775ef41SMark Johnston if (arg.rlen == 1) { 327*6775ef41SMark Johnston s_util.c[0] = arg.resid; 32882cd038dSYoshinobu Inoue s_util.c[1] = 0; 32982cd038dSYoshinobu Inoue sum += s_util.s; 33082cd038dSYoshinobu Inoue } 33182cd038dSYoshinobu Inoue REDUCE; 33282cd038dSYoshinobu Inoue return (~sum & 0xffff); 33382cd038dSYoshinobu Inoue } 33476b96fbcSMichael Tuexen 33576b96fbcSMichael Tuexen int 336*6775ef41SMark Johnston in6_cksum(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len) 33776b96fbcSMichael Tuexen { 33876b96fbcSMichael Tuexen return (in6_cksum_partial(m, nxt, off, len, len)); 33976b96fbcSMichael Tuexen } 340