1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * This file was originally taken from the FreeBSD project. 4 * 5 * Copyright (c) 2001 Charles Mott <cm@linktel.net> 6 * Copyright (c) 2008 coresystems GmbH 7 * All rights reserved. 8 */ 9 10 #include <common.h> 11 #include <net.h> 12 13 unsigned compute_ip_checksum(const void *vptr, unsigned nbytes) 14 { 15 int sum, oddbyte; 16 const unsigned short *ptr = vptr; 17 18 sum = 0; 19 while (nbytes > 1) { 20 sum += *ptr++; 21 nbytes -= 2; 22 } 23 if (nbytes == 1) { 24 oddbyte = 0; 25 ((u8 *)&oddbyte)[0] = *(u8 *)ptr; 26 ((u8 *)&oddbyte)[1] = 0; 27 sum += oddbyte; 28 } 29 sum = (sum >> 16) + (sum & 0xffff); 30 sum += (sum >> 16); 31 sum = ~sum & 0xffff; 32 33 return sum; 34 } 35 36 unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new) 37 { 38 unsigned long checksum; 39 40 sum = ~sum & 0xffff; 41 new = ~new & 0xffff; 42 if (offset & 1) { 43 /* 44 * byte-swap the sum if it came from an odd offset; since the 45 * computation is endian independant this works. 46 */ 47 new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00); 48 } 49 checksum = sum + new; 50 if (checksum > 0xffff) 51 checksum -= 0xffff; 52 53 return (~checksum) & 0xffff; 54 } 55 56 int ip_checksum_ok(const void *addr, unsigned nbytes) 57 { 58 return !(compute_ip_checksum(addr, nbytes) & 0xfffe); 59 } 60