iofbird / bird2.0.1 / lib / checksum.c @ 6b3f1a54
History  View  Annotate  Download (2.39 KB)
1 
/*


2 
* BIRD Library  IP OneComplement Checksum

3 
*

4 
* (c) 19992000 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 32bitsatatime 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 high16 to low16 */ 
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 
} 