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