]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: BSD-2-Clause |
9b0e35cb SG |
2 | /* |
3 | * This file was originally taken from the FreeBSD project. | |
4 | * | |
5 | * Copyright (c) 2001 Charles Mott <[email protected]> | |
6 | * Copyright (c) 2008 coresystems GmbH | |
7 | * All rights reserved. | |
9b0e35cb SG |
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 | } |