18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1988, 1992, 1993 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The Regents of the University of California. All rights reserved. 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modification, are permitted provided that the following conditions 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are met: 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * documentation and/or other materials provided with the distribution. 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 3. Neither the name of the University nor the names of its contributors 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * may be used to endorse or promote products derived from this software 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * without specific prior written permission. 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SUCH DAMAGE. 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Checksum routine for Internet Protocol family headers (Portable Version). 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This routine is very heavily used in the network 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * code and should be modified for each CPU to be as fast as possible. 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Since we will never span more than 1 mbuf, we can optimise this 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint cksum(struct mbuf *m, int len) 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register u_int16_t *w; 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register int sum = 0; 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register int mlen = 0; 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int byte_swapped = 0; 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int8_t c[2]; 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int16_t s; 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } s_util; 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int16_t s[2]; 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_int32_t l; 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } l_util; 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len == 0) 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto cont; 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner w = mtod(m, u_int16_t *); 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen = m->m_len; 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len < mlen) 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen = len; 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= mlen; 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Force to even boundary. 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((1 & (long) w) && (mlen > 0)) { 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project REDUCE; 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum <<= 8; 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s_util.c[0] = *(u_int8_t *)w; 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project w = (u_int16_t *)((int8_t *)w + 1); 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen--; 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project byte_swapped = 1; 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Unroll the loop to make overhead from 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * branches &c small. 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while ((mlen -= 32) >= 0) { 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project w += 16; 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen += 32; 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while ((mlen -= 8) >= 0) { 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project w += 4; 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen += 8; 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (mlen == 0 && byte_swapped == 0) 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto cont; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project REDUCE; 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while ((mlen -= 2) >= 0) { 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += *w++; 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (byte_swapped) { 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project REDUCE; 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum <<= 8; 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project byte_swapped = 0; 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (mlen == -1) { 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s_util.c[1] = *(u_int8_t *)w; 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += s_util.s; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen = 0; 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mlen = -1; 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (mlen == -1) 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s_util.c[0] = *(u_int8_t *)w; 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcont: 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ERROR((dfd, "cksum: out of data\n")); 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ERROR((dfd, " len = %d\n", len)); 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (mlen == -1) { 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The last mbuf has odd # of bytes. Follow the 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project standard (the odd byte may be shifted left by 8 bits 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project or not as determined by endian-ness of the machine) */ 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s_util.c[1] = 0; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sum += s_util.s; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project REDUCE; 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (~sum & 0xffff); 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 138