Annotation of embedaddon/bird/lib/checksum.c, revision 1.1.1.1
1.1 misho 1: /*
2: * BIRD Library -- IP One-Complement Checksum
3: *
4: * (c) 1999--2000 Martin Mares <mj@ucw.cz>
5: *
6: * Can be freely distributed and used under the terms of the GNU GPL.
7: */
8:
9: /**
10: * DOC: Miscellaneous functions.
11: */
12:
13: #include <stdarg.h>
14:
15: #include "nest/bird.h"
16: #include "checksum.h"
17:
18: static inline u32
19: add32(u32 sum, u32 x)
20: {
21: u32 z = sum + x;
22: // return z + (z < sum);
23:
24: /* add carry */
25: if (z < x)
26: z++;
27: return z;
28: }
29:
30: static u16
31: ipsum_calc_block(u32 *buf, uint len, u16 isum)
32: {
33: /*
34: * A few simple facts about the IP checksum (see RFC 1071 for detailed
35: * discussion):
36: *
37: * o It's associative and commutative.
38: * o It's byte order independent.
39: * o It's word size independent.
40: *
41: * This gives us a neat 32-bits-at-a-time algorithm which respects
42: * usual alignment requirements and is reasonably fast.
43: */
44:
45: ASSERT(!(len % 4));
46: if (!len)
47: return isum;
48:
49: u32 *end = buf + (len >> 2);
50: u32 sum = isum;
51: while (buf < end)
52: sum = add32(sum, *buf++);
53:
54: sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
55: sum += (sum >> 16); /* add carry */
56: return sum;
57: }
58:
59: static u16
60: ipsum_calc(void *frag, uint len, va_list args)
61: {
62: u16 sum = 0;
63:
64: for(;;)
65: {
66: sum = ipsum_calc_block(frag, len, sum);
67: frag = va_arg(args, void *);
68: if (!frag)
69: break;
70: len = va_arg(args, uint);
71: }
72: return sum;
73: }
74:
75: /**
76: * ipsum_verify - verify an IP checksum
77: * @frag: first packet fragment
78: * @len: length in bytes
79: *
80: * This function verifies whether a given fragmented packet
81: * has correct one's complement checksum as used by the IP
82: * protocol.
83: *
84: * It uses all the clever tricks described in RFC 1071 to speed
85: * up checksum calculation as much as possible.
86: *
87: * Result: 1 if the checksum is correct, 0 else.
88: */
89: int
90: ipsum_verify(void *frag, uint len, ...)
91: {
92: va_list args;
93: u16 sum;
94:
95: va_start(args, len);
96: sum = ipsum_calc(frag, len, args);
97: va_end(args);
98: return sum == 0xffff;
99: }
100:
101: /**
102: * ipsum_calculate - compute an IP checksum
103: * @frag: first packet fragment
104: * @len: length in bytes
105: *
106: * This function calculates a one's complement checksum of a given fragmented
107: * packet.
108: *
109: * It uses all the clever tricks described in RFC 1071 to speed
110: * up checksum calculation as much as possible.
111: */
112: u16
113: ipsum_calculate(void *frag, uint len, ...)
114: {
115: va_list args;
116: u16 sum;
117:
118: va_start(args, len);
119: sum = ipsum_calc(frag, len, args);
120: va_end(args);
121: return 0xffff - sum;
122: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>