|
|
1.1 root 1: /* Taken from Etherboot */
2:
3: #include "libopenbios/ipchecksum.h"
4:
5: unsigned short ipchksum(const void *data, unsigned long length)
6: {
7: unsigned long sum;
8: unsigned long i;
9: const unsigned char *ptr;
10: union {
11: unsigned char byte[2];
12: unsigned short word;
13: } u;
14:
15: /* In the most straight forward way possible,
16: * compute an ip style checksum.
17: */
18: sum = 0;
19: ptr = data;
20: for(i = 0; i < length; i++) {
21: unsigned long value;
22: value = ptr[i];
23: if (i & 1) {
24: value <<= 8;
25: }
26: /* Add the new value */
27: sum += value;
28: /* Wrap around the carry */
29: if (sum > 0xFFFF) {
30: sum = (sum + (sum >> 16)) & 0xFFFF;
31: }
32: }
33: u.byte[0] = (unsigned char) sum;
34: u.byte[1] = (unsigned char) (sum >> 8);
35: return (unsigned short) ~u.word;
36: }
37:
38: unsigned short add_ipchksums(unsigned long offset, unsigned short sum, unsigned short new)
39: {
40: unsigned long checksum;
41: sum = ~sum & 0xFFFF;
42: new = ~new & 0xFFFF;
43: if (offset & 1) {
44: /* byte swap the sum if it came from an odd offset
45: * since the computation is endian independant this
46: * works.
47: */
48: new = (new << 8) | (new >> 8);
49: }
50: checksum = sum + new;
51: if (checksum > 0xFFFF) {
52: checksum -= 0xFFFF;
53: }
54: return (~checksum) & 0xFFFF;
55: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.