/* * Fernando ALVES 2014 * GPL licenced */ #include #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); }