Update changelog
[l2tpns.git] / ipv6_u.c
1 /*
2 * Fernando ALVES 2014
3 * GPL licenced
4 */
5
6 #include <arpa/inet.h>
7
8 #include "ipv6_u.h"
9
10 uint16_t ipv6_checksum(struct ipv6_pseudo_hdr *p_pshdr, uint8_t *buff, int lenbuff)
11 {
12 uint32_t sum = 0;
13 uint16_t *ptrw = (uint16_t *) p_pshdr;
14 uint16_t word16;
15 int i;
16
17 // Size pseudo header 40 byte (20 word)
18 for (i = 0; i < (sizeof(*p_pshdr)/2); i++)
19 {
20 word16 = ntohs(*((uint16_t *)ptrw));
21 sum += word16;
22 ++ptrw;
23 }
24
25 ptrw = (uint16_t *) buff;
26 while (lenbuff > 1)
27 {
28 word16 = ntohs(*((uint16_t *) ptrw));
29 sum += word16;
30 ++ptrw;
31 lenbuff -= 2;
32 }
33
34 if (lenbuff > 0)
35 {
36 word16 = ntohs(*((uint8_t *) ptrw));
37 sum += word16;
38 }
39
40 // take only 16 bits out of the 32 bit sum and add up the carries
41 while (sum >> 16)
42 sum = (sum & 0xFFFF) + (sum >> 16);
43
44 // one's complement the result
45 sum = ~sum;
46
47 return htons((uint16_t) sum);
48 }