l2tpns/ipv6_u.c
2014-09-11 16:19:57 +02:00

48 lines
845 B
C

/*
* Fernando ALVES 2014
* GPL licenced
*/
#include <arpa/inet.h>
#include "ipv6_u.h"
uint16_t ipv6_checksum(struct ipv6_pseudo_hdr *p_pshdr, uint8_t *buff, int lenbuff)
{
uint32_t sum = 0;
uint16_t *ptrw = (uint16_t *) p_pshdr;
uint16_t word16;
int i;
// Size pseudo header 40 byte (20 word)
for (i = 0; i < (sizeof(*p_pshdr)/2); i++)
{
word16 = ntohs(*((uint16_t *)ptrw));
sum += word16;
++ptrw;
}
ptrw = (uint16_t *) buff;
while (lenbuff > 1)
{
word16 = ntohs(*((uint16_t *) ptrw));
sum += word16;
++ptrw;
lenbuff -= 2;
}
if (lenbuff > 0)
{
word16 = ntohs(*((uint8_t *) ptrw));
sum += word16;
}
// take only 16 bits out of the 32 bit sum and add up the carries
while (sum >> 16)
sum = (sum & 0xFFFF) + (sum >> 16);
// one's complement the result
sum = ~sum;
return htons((uint16_t) sum);
}