4 #include <netinet/in.h>
5 #include <netinet/ip.h>
6 #include <netinet/ip6.h>
10 static inline unsigned short csum(unsigned short *buf
, int nwords
)
14 for (sum
= 0; nwords
> 0; nwords
--)
16 sum
= (sum
>> 16) + (sum
& 0xffff);
22 static inline uint16_t calc_csum(void *addr
, size_t len
,
23 int ccsum __maybe_unused
)
25 return csum(addr
, len
>> 1);
28 static inline uint16_t csum_expected(uint16_t sum
, uint16_t computed_sum
)
33 shouldbe
+= ntohs(computed_sum
);
34 shouldbe
= (shouldbe
& 0xFFFF) + (shouldbe
>> 16);
35 shouldbe
= (shouldbe
& 0xFFFF) + (shouldbe
>> 16);
40 /* Taken and modified from tcpdump, Copyright belongs to them! */
48 do { if ((x) > 65535) \
55 sum = l_util.s[0] + l_util.s[1]; \
59 static inline uint16_t __in_cksum(const struct cksum_vec
*vec
, int veclen
)
62 int sum
= 0, mlen
= 0;
73 for (; veclen
!= 0; vec
++, veclen
--) {
77 w
= (const uint16_t *) (void *) vec
->ptr
;
80 s_util
.c
[1] = *(const uint8_t *) w
;
82 w
= (const uint16_t *) (void *) ((const uint8_t *) w
+ 1);
87 if ((1 & (unsigned long) w
) && (mlen
> 0)) {
90 s_util
.c
[0] = *(const uint8_t *) w
;
91 w
= (const uint16_t *) (void *) ((const uint8_t *) w
+ 1);
96 while ((mlen
-= 32) >= 0) {
97 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
98 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
99 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
100 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
106 while ((mlen
-= 8) >= 0) {
107 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
113 if (mlen
== 0 && byte_swapped
== 0)
118 while ((mlen
-= 2) >= 0) {
128 s_util
.c
[1] = *(const uint8_t *) w
;
133 } else if (mlen
== -1)
134 s_util
.c
[0] = *(const uint8_t *) w
;
144 return (~sum
& 0xffff);
147 static inline uint16_t p4_csum(const struct ip
*ip
, const uint8_t *data
,
148 uint16_t len
, uint8_t next_proto
)
150 struct cksum_vec vec
[2];
159 memset(&ph
, 0, sizeof(ph
));
162 ph
.proto
= next_proto
;
163 ph
.src
= ip
->ip_src
.s_addr
;
164 ph
.dst
= ip
->ip_dst
.s_addr
;
166 vec
[0].ptr
= (const uint8_t *) (void *) &ph
;
167 vec
[0].len
= sizeof(ph
);
172 return __in_cksum(vec
, 2);
175 static inline uint16_t p6_csum(const struct ip6_hdr
*ip6
, const uint8_t *data
,
176 uint32_t len
, uint8_t next_proto
)
178 struct cksum_vec vec
[2];
187 memcpy(&ph
.src
, ip6
->ip6_src
.s6_addr
, sizeof(ph
.src
));
188 memcpy(&ph
.dst
, ip6
->ip6_dst
.s6_addr
, sizeof(ph
.dst
));
190 memset(&ph
.mbz
, 0, sizeof(ph
.mbz
));
191 ph
.proto
= next_proto
;
193 vec
[0].ptr
= (const uint8_t *) (void *) &ph
;
194 vec
[0].len
= sizeof(ph
);
199 return __in_cksum(vec
, 2);