Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/cksum.c
2 views
/* SPDX-License-Identifier: BSD-3-Clause */1/*2* Copyright (c) 1988, 1992, 19933* The Regents of the University of California. All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13* 3. Neither the name of the University nor the names of its contributors14* may be used to endorse or promote products derived from this software15* without specific prior written permission.16*17* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*29* @(#)in_cksum.c 8.1 (Berkeley) 6/10/9330* in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp31*/3233#include "slirp.h"3435/*36* Checksum routine for Internet Protocol family headers (Portable Version).37*38* This routine is very heavily used in the network39* code and should be modified for each CPU to be as fast as possible.40*41* XXX Since we will never span more than 1 mbuf, we can optimise this42*/4344#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)45#define REDUCE \46{ \47l_util.l = sum; \48sum = l_util.s[0] + l_util.s[1]; \49ADDCARRY(sum); \50}5152int cksum(struct mbuf *m, int len)53{54register uint16_t *w;55register int sum = 0;56register int mlen = 0;57int byte_swapped = 0;5859union {60uint8_t c[2];61uint16_t s;62} s_util;63union {64uint16_t s[2];65uint32_t l;66} l_util;6768if (m->m_len == 0)69goto cont;70w = mtod(m, uint16_t *);7172mlen = m->m_len;7374if (len < mlen)75mlen = len;76len -= mlen;77/*78* Force to even boundary.79*/80if ((1 & (uintptr_t)w) && (mlen > 0)) {81REDUCE;82sum <<= 8;83s_util.c[0] = *(uint8_t *)w;84w = (uint16_t *)((int8_t *)w + 1);85mlen--;86byte_swapped = 1;87}88/*89* Unroll the loop to make overhead from90* branches &c small.91*/92while ((mlen -= 32) >= 0) {93sum += w[0];94sum += w[1];95sum += w[2];96sum += w[3];97sum += w[4];98sum += w[5];99sum += w[6];100sum += w[7];101sum += w[8];102sum += w[9];103sum += w[10];104sum += w[11];105sum += w[12];106sum += w[13];107sum += w[14];108sum += w[15];109w += 16;110}111mlen += 32;112while ((mlen -= 8) >= 0) {113sum += w[0];114sum += w[1];115sum += w[2];116sum += w[3];117w += 4;118}119mlen += 8;120if (mlen == 0 && byte_swapped == 0)121goto cont;122REDUCE;123while ((mlen -= 2) >= 0) {124sum += *w++;125}126127if (byte_swapped) {128REDUCE;129sum <<= 8;130if (mlen == -1) {131s_util.c[1] = *(uint8_t *)w;132sum += s_util.s;133mlen = 0;134} else135136mlen = -1;137} else if (mlen == -1)138s_util.c[0] = *(uint8_t *)w;139140cont:141if (len) {142DEBUG_ERROR("cksum: out of data");143DEBUG_ERROR(" len = %d", len);144}145if (mlen == -1) {146/* The last mbuf has odd # of bytes. Follow the147standard (the odd byte may be shifted left by 8 bits148or not as determined by endian-ness of the machine) */149s_util.c[1] = 0;150sum += s_util.s;151}152REDUCE;153return (~sum & 0xffff);154}155156int ip6_cksum(struct mbuf *m)157{158/* TODO: Optimize this by being able to pass the ip6_pseudohdr to cksum159* separately from the mbuf */160struct ip6 save_ip, *ip = mtod(m, struct ip6 *);161struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *);162int sum;163164save_ip = *ip;165166ih->ih_src = save_ip.ip_src;167ih->ih_dst = save_ip.ip_dst;168ih->ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl));169ih->ih_zero_hi = 0;170ih->ih_zero_lo = 0;171ih->ih_nh = save_ip.ip_nh;172173sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr)) + ntohl(ih->ih_pl));174175*ip = save_ip;176177return sum;178}179180181