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
6382cd038dSYoshinobu Inoue #include <sys/param.h>
6482cd038dSYoshinobu Inoue #include <sys/mbuf.h>
6582cd038dSYoshinobu Inoue #include <sys/systm.h>
6682cd038dSYoshinobu Inoue #include <netinet/in.h>
67686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h>
68a1f7e5f8SHajimu UMEMOTO #include <netinet6/scope6_var.h>
6982cd038dSYoshinobu Inoue
7082cd038dSYoshinobu Inoue /*
7182cd038dSYoshinobu Inoue * Checksum routine for Internet Protocol family headers (Portable Version).
7282cd038dSYoshinobu Inoue *
7382cd038dSYoshinobu Inoue * This routine is very heavily used in the network
7482cd038dSYoshinobu Inoue * code and should be modified for each CPU to be as fast as possible.
7582cd038dSYoshinobu Inoue */
7682cd038dSYoshinobu Inoue
7782cd038dSYoshinobu Inoue #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
784c888125SRui Paulo #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; (void)ADDCARRY(sum);}
7982cd038dSYoshinobu Inoue
806775ef41SMark Johnston union l_util {
816775ef41SMark Johnston uint16_t s[2];
826775ef41SMark Johnston uint32_t l;
836775ef41SMark Johnston };
846775ef41SMark Johnston
856775ef41SMark Johnston union s_util {
866775ef41SMark Johnston uint8_t c[2];
876775ef41SMark Johnston uint16_t s;
886775ef41SMark Johnston };
896775ef41SMark Johnston
90ecade87eSBjoern A. Zeeb static int
_in6_cksum_pseudo(struct ip6_hdr * ip6,uint32_t len,uint8_t nxt,uint16_t csum)91ecade87eSBjoern A. Zeeb _in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
92ecade87eSBjoern A. Zeeb {
93ecade87eSBjoern A. Zeeb int sum;
94ecade87eSBjoern A. Zeeb uint16_t scope, *w;
95ecade87eSBjoern A. Zeeb union {
96ecade87eSBjoern A. Zeeb u_int16_t phs[4];
97ecade87eSBjoern A. Zeeb struct {
98ecade87eSBjoern A. Zeeb u_int32_t ph_len;
99ecade87eSBjoern A. Zeeb u_int8_t ph_zero[3];
100ecade87eSBjoern A. Zeeb u_int8_t ph_nxt;
101ecade87eSBjoern A. Zeeb } __packed ph;
102ecade87eSBjoern A. Zeeb } uph;
103ecade87eSBjoern A. Zeeb
104ecade87eSBjoern A. Zeeb sum = csum;
105ecade87eSBjoern A. Zeeb
106ecade87eSBjoern A. Zeeb /*
107ecade87eSBjoern A. Zeeb * First create IP6 pseudo header and calculate a summary.
108ecade87eSBjoern A. Zeeb */
109ecade87eSBjoern A. Zeeb uph.ph.ph_len = htonl(len);
110ecade87eSBjoern A. Zeeb uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0;
111ecade87eSBjoern A. Zeeb uph.ph.ph_nxt = nxt;
112ecade87eSBjoern A. Zeeb
113ecade87eSBjoern A. Zeeb /* Payload length and upper layer identifier. */
114ecade87eSBjoern A. Zeeb sum += uph.phs[0]; sum += uph.phs[1];
115ecade87eSBjoern A. Zeeb sum += uph.phs[2]; sum += uph.phs[3];
116ecade87eSBjoern A. Zeeb
117ecade87eSBjoern A. Zeeb /* IPv6 source address. */
118ecade87eSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_src);
119ecade87eSBjoern A. Zeeb w = (u_int16_t *)&ip6->ip6_src;
120ecade87eSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
121ecade87eSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
122ecade87eSBjoern A. Zeeb if (scope != 0)
123ecade87eSBjoern A. Zeeb sum -= scope;
124ecade87eSBjoern A. Zeeb
125ecade87eSBjoern A. Zeeb /* IPv6 destination address. */
126ecade87eSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_dst);
127ecade87eSBjoern A. Zeeb w = (u_int16_t *)&ip6->ip6_dst;
128ecade87eSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
129ecade87eSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
130ecade87eSBjoern A. Zeeb if (scope != 0)
131ecade87eSBjoern A. Zeeb sum -= scope;
132ecade87eSBjoern A. Zeeb
133ecade87eSBjoern A. Zeeb return (sum);
134ecade87eSBjoern A. Zeeb }
135ecade87eSBjoern A. Zeeb
136ecade87eSBjoern A. Zeeb int
in6_cksum_pseudo(struct ip6_hdr * ip6,uint32_t len,uint8_t nxt,uint16_t csum)137ecade87eSBjoern A. Zeeb in6_cksum_pseudo(struct ip6_hdr *ip6, uint32_t len, uint8_t nxt, uint16_t csum)
138ecade87eSBjoern A. Zeeb {
1396775ef41SMark Johnston union l_util l_util;
140ecade87eSBjoern A. Zeeb int sum;
141ecade87eSBjoern A. Zeeb
142ecade87eSBjoern A. Zeeb sum = _in6_cksum_pseudo(ip6, len, nxt, csum);
143ecade87eSBjoern A. Zeeb REDUCE;
144ecade87eSBjoern A. Zeeb return (sum);
145ecade87eSBjoern A. Zeeb }
146ecade87eSBjoern A. Zeeb
1476775ef41SMark Johnston static int
in6_cksumdata(void * data,int * lenp,uint8_t * residp,int rlen)1486775ef41SMark Johnston in6_cksumdata(void *data, int *lenp, uint8_t *residp, int rlen)
1496775ef41SMark Johnston {
1506775ef41SMark Johnston union l_util l_util;
1516775ef41SMark Johnston union s_util s_util;
1526775ef41SMark Johnston uint16_t *w;
1536775ef41SMark Johnston int len, sum;
1546775ef41SMark Johnston bool byte_swapped;
1556775ef41SMark Johnston
1566775ef41SMark Johnston KASSERT(*lenp >= 0, ("%s: negative len %d", __func__, *lenp));
1576775ef41SMark Johnston KASSERT(rlen == 0 || rlen == 1, ("%s: rlen %d", __func__, rlen));
1586775ef41SMark Johnston
1596775ef41SMark Johnston len = *lenp;
1606775ef41SMark Johnston sum = 0;
1616775ef41SMark Johnston
1626775ef41SMark Johnston if (len == 0) {
1636775ef41SMark Johnston len = rlen;
1646775ef41SMark Johnston goto out;
1656775ef41SMark Johnston }
1666775ef41SMark Johnston
1676775ef41SMark Johnston byte_swapped = false;
1686775ef41SMark Johnston w = data;
1696775ef41SMark Johnston
1706775ef41SMark Johnston /*
1716775ef41SMark Johnston * Do we have a residual byte left over from the previous buffer?
1726775ef41SMark Johnston */
1736775ef41SMark Johnston if (rlen == 1) {
1746775ef41SMark Johnston s_util.c[0] = *residp;
1756775ef41SMark Johnston s_util.c[1] = *(uint8_t *)w;
1766775ef41SMark Johnston sum += s_util.s;
1776775ef41SMark Johnston w = (uint16_t *)((uint8_t *)w + 1);
1786775ef41SMark Johnston len--;
1796775ef41SMark Johnston rlen = 0;
1806775ef41SMark Johnston }
1816775ef41SMark Johnston
1826775ef41SMark Johnston /*
1836775ef41SMark Johnston * Force to even boundary.
1846775ef41SMark Johnston */
1856775ef41SMark Johnston if ((1 & (uintptr_t)w) && len > 0) {
1866775ef41SMark Johnston REDUCE;
1876775ef41SMark Johnston sum <<= 8;
1886775ef41SMark Johnston s_util.c[0] = *(uint8_t *)w;
1896775ef41SMark Johnston w = (uint16_t *)((uint8_t *)w + 1);
1906775ef41SMark Johnston len--;
1916775ef41SMark Johnston byte_swapped = true;
1926775ef41SMark Johnston }
1936775ef41SMark Johnston
1946775ef41SMark Johnston /*
1956775ef41SMark Johnston * Unroll the loop to make overhead from branches &c small.
1966775ef41SMark Johnston */
1976775ef41SMark Johnston while ((len -= 32) >= 0) {
1986775ef41SMark Johnston sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
1996775ef41SMark Johnston sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
2006775ef41SMark Johnston sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
2016775ef41SMark Johnston sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
2026775ef41SMark Johnston w += 16;
2036775ef41SMark Johnston }
2046775ef41SMark Johnston len += 32;
2056775ef41SMark Johnston while ((len -= 8) >= 0) {
2066775ef41SMark Johnston sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
2076775ef41SMark Johnston w += 4;
2086775ef41SMark Johnston }
2096775ef41SMark Johnston len += 8;
2106775ef41SMark Johnston if (len == 0 && !byte_swapped)
2116775ef41SMark Johnston goto out;
2126775ef41SMark Johnston REDUCE;
2136775ef41SMark Johnston while ((len -= 2) >= 0) {
2146775ef41SMark Johnston sum += *w++;
2156775ef41SMark Johnston }
2166775ef41SMark Johnston if (byte_swapped) {
2176775ef41SMark Johnston REDUCE;
2186775ef41SMark Johnston sum <<= 8;
2196775ef41SMark Johnston if (len == -1) {
2206775ef41SMark Johnston s_util.c[1] = *(uint8_t *)w;
2216775ef41SMark Johnston sum += s_util.s;
2226775ef41SMark Johnston } else /* len == -2 */
2236775ef41SMark Johnston *residp = s_util.c[0];
2246775ef41SMark Johnston len++;
2256775ef41SMark Johnston } else if (len == -1)
2266775ef41SMark Johnston *residp = *(uint8_t *)w;
2276775ef41SMark Johnston out:
2286775ef41SMark Johnston *lenp = len & 1;
2296775ef41SMark Johnston return (sum);
2306775ef41SMark Johnston }
2316775ef41SMark Johnston
2326775ef41SMark Johnston struct in6_cksum_partial_arg {
2336775ef41SMark Johnston int sum;
2346775ef41SMark Johnston int rlen;
2356775ef41SMark Johnston uint8_t resid;
2366775ef41SMark Johnston };
2376775ef41SMark Johnston
2386775ef41SMark Johnston static int
in6_cksum_partial_one(void * _arg,void * data,u_int len)2396775ef41SMark Johnston in6_cksum_partial_one(void *_arg, void *data, u_int len)
2406775ef41SMark Johnston {
2416775ef41SMark Johnston struct in6_cksum_partial_arg *arg = _arg;
2426775ef41SMark Johnston
2436775ef41SMark Johnston arg->sum += in6_cksumdata(data, &len, &arg->resid, arg->rlen);
2446775ef41SMark Johnston arg->rlen = len;
2456775ef41SMark Johnston return (0);
2466775ef41SMark Johnston }
2476775ef41SMark Johnston
24882cd038dSYoshinobu Inoue /*
2496d79f3f6SRebecca Cran * m MUST contain a contiguous IP6 header.
250*fcf81de1SKonstantin Belousov * off_l3 is an offset where ipv6 header starts.
251*fcf81de1SKonstantin Belousov * off_l4 is an offset where TCP/UDP/ICMP6 header starts.
25282cd038dSYoshinobu Inoue * len is a total length of a transport segment.
25382cd038dSYoshinobu Inoue * (e.g. TCP header + TCP payload)
25476b96fbcSMichael Tuexen * cov is the number of bytes to be taken into account for the checksum
25582cd038dSYoshinobu Inoue */
25682cd038dSYoshinobu Inoue int
in6_cksum_partial_l2(struct mbuf * m,uint8_t nxt,uint32_t off_l3,uint32_t off_l4,uint32_t len,uint32_t cov)257*fcf81de1SKonstantin Belousov in6_cksum_partial_l2(struct mbuf *m, uint8_t nxt, uint32_t off_l3,
258*fcf81de1SKonstantin Belousov uint32_t off_l4, uint32_t len, uint32_t cov)
25982cd038dSYoshinobu Inoue {
2606775ef41SMark Johnston struct in6_cksum_partial_arg arg;
2616775ef41SMark Johnston union l_util l_util;
2626775ef41SMark Johnston union s_util s_util;
26382cd038dSYoshinobu Inoue struct ip6_hdr *ip6;
2646775ef41SMark Johnston uint16_t *w, scope;
2652889eb8bSBjoern A. Zeeb int sum;
26629a3d1b0SJun-ichiro itojun Hagino union {
2676775ef41SMark Johnston uint16_t phs[4];
26829a3d1b0SJun-ichiro itojun Hagino struct {
2696775ef41SMark Johnston uint32_t ph_len;
2706775ef41SMark Johnston uint8_t ph_zero[3];
2716775ef41SMark Johnston uint8_t ph_nxt;
2721c0ee39eSWarner Losh } __packed ph;
27329a3d1b0SJun-ichiro itojun Hagino } uph;
27482cd038dSYoshinobu Inoue
2752889eb8bSBjoern A. Zeeb /* Sanity check. */
276*fcf81de1SKonstantin Belousov KASSERT(m->m_pkthdr.len >= off_l4 + len,
277*fcf81de1SKonstantin Belousov ("%s: mbuf len (%d) < off(%d)+len(%d)",
278*fcf81de1SKonstantin Belousov __func__, m->m_pkthdr.len, off_l4, len));
279*fcf81de1SKonstantin Belousov KASSERT(m->m_len >= off_l3 + sizeof(*ip6),
2806775ef41SMark Johnston ("%s: mbuf len %d < sizeof(ip6)", __func__, m->m_len));
28129a3d1b0SJun-ichiro itojun Hagino
28282cd038dSYoshinobu Inoue /*
28382cd038dSYoshinobu Inoue * First create IP6 pseudo header and calculate a summary.
28482cd038dSYoshinobu Inoue */
28582cd038dSYoshinobu Inoue uph.ph.ph_len = htonl(len);
2862889eb8bSBjoern A. Zeeb uph.ph.ph_zero[0] = uph.ph.ph_zero[1] = uph.ph.ph_zero[2] = 0;
28782cd038dSYoshinobu Inoue uph.ph.ph_nxt = nxt;
28882cd038dSYoshinobu Inoue
2892889eb8bSBjoern A. Zeeb /* Payload length and upper layer identifier. */
2902889eb8bSBjoern A. Zeeb sum = uph.phs[0]; sum += uph.phs[1];
29182cd038dSYoshinobu Inoue sum += uph.phs[2]; sum += uph.phs[3];
29282cd038dSYoshinobu Inoue
293*fcf81de1SKonstantin Belousov ip6 = mtodo(m, off_l3);
2942889eb8bSBjoern A. Zeeb
2952889eb8bSBjoern A. Zeeb /* IPv6 source address. */
2962889eb8bSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_src);
2976775ef41SMark Johnston w = (uint16_t *)&ip6->ip6_src;
2982889eb8bSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
2992889eb8bSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
3002889eb8bSBjoern A. Zeeb if (scope != 0)
3012889eb8bSBjoern A. Zeeb sum -= scope;
3022889eb8bSBjoern A. Zeeb
3032889eb8bSBjoern A. Zeeb /* IPv6 destination address. */
3042889eb8bSBjoern A. Zeeb scope = in6_getscope(&ip6->ip6_dst);
3056775ef41SMark Johnston w = (uint16_t *)&ip6->ip6_dst;
3062889eb8bSBjoern A. Zeeb sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
3072889eb8bSBjoern A. Zeeb sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
3082889eb8bSBjoern A. Zeeb if (scope != 0)
3092889eb8bSBjoern A. Zeeb sum -= scope;
3102889eb8bSBjoern A. Zeeb
31182cd038dSYoshinobu Inoue /*
3126775ef41SMark Johnston * Loop over the rest of the mbuf chain and compute the rest of the
3136775ef41SMark Johnston * checksum. m_apply() handles unmapped mbufs.
31482cd038dSYoshinobu Inoue */
3156775ef41SMark Johnston arg.sum = sum;
3166775ef41SMark Johnston arg.rlen = 0;
317*fcf81de1SKonstantin Belousov (void)m_apply(m, off_l4, cov, in6_cksum_partial_one, &arg);
3186775ef41SMark Johnston sum = arg.sum;
3192889eb8bSBjoern A. Zeeb
32082cd038dSYoshinobu Inoue /*
3216775ef41SMark Johnston * Handle a residual byte.
32282cd038dSYoshinobu Inoue */
3236775ef41SMark Johnston if (arg.rlen == 1) {
3246775ef41SMark Johnston s_util.c[0] = arg.resid;
32582cd038dSYoshinobu Inoue s_util.c[1] = 0;
32682cd038dSYoshinobu Inoue sum += s_util.s;
32782cd038dSYoshinobu Inoue }
32882cd038dSYoshinobu Inoue REDUCE;
32982cd038dSYoshinobu Inoue return (~sum & 0xffff);
33082cd038dSYoshinobu Inoue }
33176b96fbcSMichael Tuexen
33276b96fbcSMichael Tuexen int
in6_cksum_partial(struct mbuf * m,uint8_t nxt,uint32_t off,uint32_t len,uint32_t cov)333*fcf81de1SKonstantin Belousov in6_cksum_partial(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len,
334*fcf81de1SKonstantin Belousov uint32_t cov)
335*fcf81de1SKonstantin Belousov {
336*fcf81de1SKonstantin Belousov return (in6_cksum_partial_l2(m, nxt, 0, off, len, cov));
337*fcf81de1SKonstantin Belousov }
338*fcf81de1SKonstantin Belousov
339*fcf81de1SKonstantin Belousov int
in6_cksum(struct mbuf * m,uint8_t nxt,uint32_t off,uint32_t len)3406775ef41SMark Johnston in6_cksum(struct mbuf *m, uint8_t nxt, uint32_t off, uint32_t len)
34176b96fbcSMichael Tuexen {
34276b96fbcSMichael Tuexen return (in6_cksum_partial(m, nxt, off, len, len));
34376b96fbcSMichael Tuexen }
344