1686cdd19SJun-ichiro itojun Hagino /* $FreeBSD$ */ 229a3d1b0SJun-ichiro itojun Hagino /* $KAME: in6_cksum.c,v 1.9 2000/09/09 15:33:31 itojun Exp $ */ 3686cdd19SJun-ichiro itojun Hagino 482cd038dSYoshinobu Inoue /* 582cd038dSYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 682cd038dSYoshinobu Inoue * All rights reserved. 782cd038dSYoshinobu Inoue * 882cd038dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 982cd038dSYoshinobu Inoue * modification, are permitted provided that the following conditions 1082cd038dSYoshinobu Inoue * are met: 1182cd038dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 1282cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 1382cd038dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 1482cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 1582cd038dSYoshinobu Inoue * documentation and/or other materials provided with the distribution. 1682cd038dSYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 1782cd038dSYoshinobu Inoue * may be used to endorse or promote products derived from this software 1882cd038dSYoshinobu Inoue * without specific prior written permission. 1982cd038dSYoshinobu Inoue * 2082cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2182cd038dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2282cd038dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2382cd038dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2482cd038dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2582cd038dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2682cd038dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2782cd038dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2882cd038dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2982cd038dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3082cd038dSYoshinobu Inoue * SUCH DAMAGE. 3182cd038dSYoshinobu Inoue */ 3282cd038dSYoshinobu Inoue 3382cd038dSYoshinobu Inoue /* 3482cd038dSYoshinobu Inoue * Copyright (c) 1988, 1992, 1993 3582cd038dSYoshinobu Inoue * The Regents of the University of California. All rights reserved. 3682cd038dSYoshinobu Inoue * 3782cd038dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 3882cd038dSYoshinobu Inoue * modification, are permitted provided that the following conditions 3982cd038dSYoshinobu Inoue * are met: 4082cd038dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 4182cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 4282cd038dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 4382cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 4482cd038dSYoshinobu Inoue * documentation and/or other materials provided with the distribution. 4582cd038dSYoshinobu Inoue * 3. All advertising materials mentioning features or use of this software 4682cd038dSYoshinobu Inoue * must display the following acknowledgement: 4782cd038dSYoshinobu Inoue * This product includes software developed by the University of 4882cd038dSYoshinobu Inoue * California, Berkeley and its contributors. 4982cd038dSYoshinobu Inoue * 4. Neither the name of the University nor the names of its contributors 5082cd038dSYoshinobu Inoue * may be used to endorse or promote products derived from this software 5182cd038dSYoshinobu Inoue * without specific prior written permission. 5282cd038dSYoshinobu Inoue * 5382cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5482cd038dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5582cd038dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5682cd038dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5782cd038dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5882cd038dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5982cd038dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6082cd038dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6182cd038dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6282cd038dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6382cd038dSYoshinobu Inoue * SUCH DAMAGE. 6482cd038dSYoshinobu Inoue * 6582cd038dSYoshinobu Inoue * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 6682cd038dSYoshinobu Inoue */ 6782cd038dSYoshinobu Inoue 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> 7382cd038dSYoshinobu Inoue 7482cd038dSYoshinobu Inoue #include <net/net_osdep.h> 7582cd038dSYoshinobu Inoue 7682cd038dSYoshinobu Inoue /* 7782cd038dSYoshinobu Inoue * Checksum routine for Internet Protocol family headers (Portable Version). 7882cd038dSYoshinobu Inoue * 7982cd038dSYoshinobu Inoue * This routine is very heavily used in the network 8082cd038dSYoshinobu Inoue * code and should be modified for each CPU to be as fast as possible. 8182cd038dSYoshinobu Inoue */ 8282cd038dSYoshinobu Inoue 8382cd038dSYoshinobu Inoue #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) 8482cd038dSYoshinobu Inoue #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} 8582cd038dSYoshinobu Inoue 8682cd038dSYoshinobu Inoue /* 8782cd038dSYoshinobu Inoue * m MUST contain a continuous IP6 header. 8882cd038dSYoshinobu Inoue * off is a offset where TCP/UDP/ICMP6 header starts. 8982cd038dSYoshinobu Inoue * len is a total length of a transport segment. 9082cd038dSYoshinobu Inoue * (e.g. TCP header + TCP payload) 9182cd038dSYoshinobu Inoue */ 9282cd038dSYoshinobu Inoue 9382cd038dSYoshinobu Inoue int 9482cd038dSYoshinobu Inoue in6_cksum(m, nxt, off, len) 9582cd038dSYoshinobu Inoue register struct mbuf *m; 9682cd038dSYoshinobu Inoue u_int8_t nxt; 97686cdd19SJun-ichiro itojun Hagino u_int32_t off, len; 9882cd038dSYoshinobu Inoue { 9982cd038dSYoshinobu Inoue register u_int16_t *w; 10082cd038dSYoshinobu Inoue register int sum = 0; 10182cd038dSYoshinobu Inoue register int mlen = 0; 10282cd038dSYoshinobu Inoue int byte_swapped = 0; 103686cdd19SJun-ichiro itojun Hagino #if 0 104686cdd19SJun-ichiro itojun Hagino int srcifid = 0, dstifid = 0; 105686cdd19SJun-ichiro itojun Hagino #endif 10682cd038dSYoshinobu Inoue struct ip6_hdr *ip6; 10729a3d1b0SJun-ichiro itojun Hagino union { 10829a3d1b0SJun-ichiro itojun Hagino u_int16_t phs[4]; 10929a3d1b0SJun-ichiro itojun Hagino struct { 11029a3d1b0SJun-ichiro itojun Hagino u_int32_t ph_len; 11129a3d1b0SJun-ichiro itojun Hagino u_int8_t ph_zero[3]; 11229a3d1b0SJun-ichiro itojun Hagino u_int8_t ph_nxt; 11329a3d1b0SJun-ichiro itojun Hagino } ph __attribute__((__packed__)); 11429a3d1b0SJun-ichiro itojun Hagino } uph; 11582cd038dSYoshinobu Inoue union { 11682cd038dSYoshinobu Inoue u_int8_t c[2]; 11782cd038dSYoshinobu Inoue u_int16_t s; 11882cd038dSYoshinobu Inoue } s_util; 11982cd038dSYoshinobu Inoue union { 12082cd038dSYoshinobu Inoue u_int16_t s[2]; 12182cd038dSYoshinobu Inoue u_int32_t l; 12282cd038dSYoshinobu Inoue } l_util; 12382cd038dSYoshinobu Inoue 12482cd038dSYoshinobu Inoue /* sanity check */ 12582cd038dSYoshinobu Inoue if (m->m_pkthdr.len < off + len) { 12682cd038dSYoshinobu Inoue panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)\n", 12782cd038dSYoshinobu Inoue m->m_pkthdr.len, off, len); 12882cd038dSYoshinobu Inoue } 12982cd038dSYoshinobu Inoue 13029a3d1b0SJun-ichiro itojun Hagino bzero(&uph, sizeof(uph)); 13129a3d1b0SJun-ichiro itojun Hagino 13282cd038dSYoshinobu Inoue /* 13382cd038dSYoshinobu Inoue * First create IP6 pseudo header and calculate a summary. 13482cd038dSYoshinobu Inoue */ 13582cd038dSYoshinobu Inoue ip6 = mtod(m, struct ip6_hdr *); 136686cdd19SJun-ichiro itojun Hagino #if 0 137686cdd19SJun-ichiro itojun Hagino if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 138686cdd19SJun-ichiro itojun Hagino srcifid = ip6->ip6_src.s6_addr16[1]; 139686cdd19SJun-ichiro itojun Hagino ip6->ip6_src.s6_addr16[1] = 0; 140686cdd19SJun-ichiro itojun Hagino } 141686cdd19SJun-ichiro itojun Hagino if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 142686cdd19SJun-ichiro itojun Hagino dstifid = ip6->ip6_dst.s6_addr16[1]; 143686cdd19SJun-ichiro itojun Hagino ip6->ip6_dst.s6_addr16[1] = 0; 144686cdd19SJun-ichiro itojun Hagino } 145686cdd19SJun-ichiro itojun Hagino #endif 14682cd038dSYoshinobu Inoue w = (u_int16_t *)&ip6->ip6_src; 14782cd038dSYoshinobu Inoue uph.ph.ph_len = htonl(len); 14882cd038dSYoshinobu Inoue uph.ph.ph_nxt = nxt; 14982cd038dSYoshinobu Inoue 15082cd038dSYoshinobu Inoue /* IPv6 source address */ 15182cd038dSYoshinobu Inoue sum += w[0]; 15282cd038dSYoshinobu Inoue if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 15382cd038dSYoshinobu Inoue sum += w[1]; 15482cd038dSYoshinobu Inoue sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; 15582cd038dSYoshinobu Inoue sum += w[6]; sum += w[7]; 15682cd038dSYoshinobu Inoue /* IPv6 destination address */ 15782cd038dSYoshinobu Inoue sum += w[8]; 15882cd038dSYoshinobu Inoue if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 15982cd038dSYoshinobu Inoue sum += w[9]; 16082cd038dSYoshinobu Inoue sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; 16182cd038dSYoshinobu Inoue sum += w[14]; sum += w[15]; 16282cd038dSYoshinobu Inoue /* Payload length and upper layer identifier */ 16382cd038dSYoshinobu Inoue sum += uph.phs[0]; sum += uph.phs[1]; 16482cd038dSYoshinobu Inoue sum += uph.phs[2]; sum += uph.phs[3]; 16582cd038dSYoshinobu Inoue 166686cdd19SJun-ichiro itojun Hagino #if 0 167686cdd19SJun-ichiro itojun Hagino if (srcifid) 168686cdd19SJun-ichiro itojun Hagino ip6->ip6_src.s6_addr16[1] = srcifid; 169686cdd19SJun-ichiro itojun Hagino if (dstifid) 170686cdd19SJun-ichiro itojun Hagino ip6->ip6_dst.s6_addr16[1] = dstifid; 171686cdd19SJun-ichiro itojun Hagino #endif 17282cd038dSYoshinobu Inoue /* 17382cd038dSYoshinobu Inoue * Secondly calculate a summary of the first mbuf excluding offset. 17482cd038dSYoshinobu Inoue */ 17582cd038dSYoshinobu Inoue while (m != NULL && off > 0) { 17682cd038dSYoshinobu Inoue if (m->m_len <= off) 17782cd038dSYoshinobu Inoue off -= m->m_len; 17882cd038dSYoshinobu Inoue else 17982cd038dSYoshinobu Inoue break; 18082cd038dSYoshinobu Inoue m = m->m_next; 18182cd038dSYoshinobu Inoue } 18282cd038dSYoshinobu Inoue w = (u_int16_t *)(mtod(m, u_char *) + off); 18382cd038dSYoshinobu Inoue mlen = m->m_len - off; 18482cd038dSYoshinobu Inoue if (len < mlen) 18582cd038dSYoshinobu Inoue mlen = len; 18682cd038dSYoshinobu Inoue len -= mlen; 18782cd038dSYoshinobu Inoue /* 18882cd038dSYoshinobu Inoue * Force to even boundary. 18982cd038dSYoshinobu Inoue */ 19082cd038dSYoshinobu Inoue if ((1 & (long) w) && (mlen > 0)) { 19182cd038dSYoshinobu Inoue REDUCE; 19282cd038dSYoshinobu Inoue sum <<= 8; 19382cd038dSYoshinobu Inoue s_util.c[0] = *(u_char *)w; 19482cd038dSYoshinobu Inoue w = (u_int16_t *)((char *)w + 1); 19582cd038dSYoshinobu Inoue mlen--; 19682cd038dSYoshinobu Inoue byte_swapped = 1; 19782cd038dSYoshinobu Inoue } 19882cd038dSYoshinobu Inoue /* 19982cd038dSYoshinobu Inoue * Unroll the loop to make overhead from 20082cd038dSYoshinobu Inoue * branches &c small. 20182cd038dSYoshinobu Inoue */ 20282cd038dSYoshinobu Inoue while ((mlen -= 32) >= 0) { 20382cd038dSYoshinobu Inoue sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 20482cd038dSYoshinobu Inoue sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 20582cd038dSYoshinobu Inoue sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 20682cd038dSYoshinobu Inoue sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 20782cd038dSYoshinobu Inoue w += 16; 20882cd038dSYoshinobu Inoue } 20982cd038dSYoshinobu Inoue mlen += 32; 21082cd038dSYoshinobu Inoue while ((mlen -= 8) >= 0) { 21182cd038dSYoshinobu Inoue sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 21282cd038dSYoshinobu Inoue w += 4; 21382cd038dSYoshinobu Inoue } 21482cd038dSYoshinobu Inoue mlen += 8; 21582cd038dSYoshinobu Inoue if (mlen == 0 && byte_swapped == 0) 21682cd038dSYoshinobu Inoue goto next; 21782cd038dSYoshinobu Inoue REDUCE; 21882cd038dSYoshinobu Inoue while ((mlen -= 2) >= 0) { 21982cd038dSYoshinobu Inoue sum += *w++; 22082cd038dSYoshinobu Inoue } 22182cd038dSYoshinobu Inoue if (byte_swapped) { 22282cd038dSYoshinobu Inoue REDUCE; 22382cd038dSYoshinobu Inoue sum <<= 8; 22482cd038dSYoshinobu Inoue byte_swapped = 0; 22582cd038dSYoshinobu Inoue if (mlen == -1) { 22682cd038dSYoshinobu Inoue s_util.c[1] = *(char *)w; 22782cd038dSYoshinobu Inoue sum += s_util.s; 22882cd038dSYoshinobu Inoue mlen = 0; 22982cd038dSYoshinobu Inoue } else 23082cd038dSYoshinobu Inoue mlen = -1; 23182cd038dSYoshinobu Inoue } else if (mlen == -1) 23282cd038dSYoshinobu Inoue s_util.c[0] = *(char *)w; 23382cd038dSYoshinobu Inoue next: 23482cd038dSYoshinobu Inoue m = m->m_next; 23582cd038dSYoshinobu Inoue 23682cd038dSYoshinobu Inoue /* 23782cd038dSYoshinobu Inoue * Lastly calculate a summary of the rest of mbufs. 23882cd038dSYoshinobu Inoue */ 23982cd038dSYoshinobu Inoue 24082cd038dSYoshinobu Inoue for (;m && len; m = m->m_next) { 24182cd038dSYoshinobu Inoue if (m->m_len == 0) 24282cd038dSYoshinobu Inoue continue; 24382cd038dSYoshinobu Inoue w = mtod(m, u_int16_t *); 24482cd038dSYoshinobu Inoue if (mlen == -1) { 24582cd038dSYoshinobu Inoue /* 24682cd038dSYoshinobu Inoue * The first byte of this mbuf is the continuation 24782cd038dSYoshinobu Inoue * of a word spanning between this mbuf and the 24882cd038dSYoshinobu Inoue * last mbuf. 24982cd038dSYoshinobu Inoue * 25082cd038dSYoshinobu Inoue * s_util.c[0] is already saved when scanning previous 25182cd038dSYoshinobu Inoue * mbuf. 25282cd038dSYoshinobu Inoue */ 25382cd038dSYoshinobu Inoue s_util.c[1] = *(char *)w; 25482cd038dSYoshinobu Inoue sum += s_util.s; 25582cd038dSYoshinobu Inoue w = (u_int16_t *)((char *)w + 1); 25682cd038dSYoshinobu Inoue mlen = m->m_len - 1; 25782cd038dSYoshinobu Inoue len--; 25882cd038dSYoshinobu Inoue } else 25982cd038dSYoshinobu Inoue mlen = m->m_len; 26082cd038dSYoshinobu Inoue if (len < mlen) 26182cd038dSYoshinobu Inoue mlen = len; 26282cd038dSYoshinobu Inoue len -= mlen; 26382cd038dSYoshinobu Inoue /* 26482cd038dSYoshinobu Inoue * Force to even boundary. 26582cd038dSYoshinobu Inoue */ 26682cd038dSYoshinobu Inoue if ((1 & (long) w) && (mlen > 0)) { 26782cd038dSYoshinobu Inoue REDUCE; 26882cd038dSYoshinobu Inoue sum <<= 8; 26982cd038dSYoshinobu Inoue s_util.c[0] = *(u_char *)w; 27082cd038dSYoshinobu Inoue w = (u_int16_t *)((char *)w + 1); 27182cd038dSYoshinobu Inoue mlen--; 27282cd038dSYoshinobu Inoue byte_swapped = 1; 27382cd038dSYoshinobu Inoue } 27482cd038dSYoshinobu Inoue /* 27582cd038dSYoshinobu Inoue * Unroll the loop to make overhead from 27682cd038dSYoshinobu Inoue * branches &c small. 27782cd038dSYoshinobu Inoue */ 27882cd038dSYoshinobu Inoue while ((mlen -= 32) >= 0) { 27982cd038dSYoshinobu Inoue sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 28082cd038dSYoshinobu Inoue sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 28182cd038dSYoshinobu Inoue sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 28282cd038dSYoshinobu Inoue sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 28382cd038dSYoshinobu Inoue w += 16; 28482cd038dSYoshinobu Inoue } 28582cd038dSYoshinobu Inoue mlen += 32; 28682cd038dSYoshinobu Inoue while ((mlen -= 8) >= 0) { 28782cd038dSYoshinobu Inoue sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 28882cd038dSYoshinobu Inoue w += 4; 28982cd038dSYoshinobu Inoue } 29082cd038dSYoshinobu Inoue mlen += 8; 29182cd038dSYoshinobu Inoue if (mlen == 0 && byte_swapped == 0) 29282cd038dSYoshinobu Inoue continue; 29382cd038dSYoshinobu Inoue REDUCE; 29482cd038dSYoshinobu Inoue while ((mlen -= 2) >= 0) { 29582cd038dSYoshinobu Inoue sum += *w++; 29682cd038dSYoshinobu Inoue } 29782cd038dSYoshinobu Inoue if (byte_swapped) { 29882cd038dSYoshinobu Inoue REDUCE; 29982cd038dSYoshinobu Inoue sum <<= 8; 30082cd038dSYoshinobu Inoue byte_swapped = 0; 30182cd038dSYoshinobu Inoue if (mlen == -1) { 30282cd038dSYoshinobu Inoue s_util.c[1] = *(char *)w; 30382cd038dSYoshinobu Inoue sum += s_util.s; 30482cd038dSYoshinobu Inoue mlen = 0; 30582cd038dSYoshinobu Inoue } else 30682cd038dSYoshinobu Inoue mlen = -1; 30782cd038dSYoshinobu Inoue } else if (mlen == -1) 30882cd038dSYoshinobu Inoue s_util.c[0] = *(char *)w; 30982cd038dSYoshinobu Inoue } 31082cd038dSYoshinobu Inoue if (len) 31182cd038dSYoshinobu Inoue panic("in6_cksum: out of data\n"); 31282cd038dSYoshinobu Inoue if (mlen == -1) { 31382cd038dSYoshinobu Inoue /* The last mbuf has odd # of bytes. Follow the 31482cd038dSYoshinobu Inoue standard (the odd byte may be shifted left by 8 bits 31582cd038dSYoshinobu Inoue or not as determined by endian-ness of the machine) */ 31682cd038dSYoshinobu Inoue s_util.c[1] = 0; 31782cd038dSYoshinobu Inoue sum += s_util.s; 31882cd038dSYoshinobu Inoue } 31982cd038dSYoshinobu Inoue REDUCE; 32082cd038dSYoshinobu Inoue return (~sum & 0xffff); 32182cd038dSYoshinobu Inoue } 322