//#include //#include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* function: ip_checksum_add * adds data to a checksum * current_sum - the current checksum (or 0 to start a new checksum) * data - the data to add to the checksum * len - length of data */ uint32_t ip_checksum_add(uint32_t current_sum, const void *data, int len) { uint32_t checksum = current_sum; int left = len; const uint16_t *data_16 = data; while(left > 1) { checksum += *data_16; data_16++; left -= 2; } if(left) { checksum += *(uint8_t *)data_16; } return checksum; } /* function: ipv6_pseudo_header_checksum * calculate the pseudo header checksum for use in tcp/udp/icmp headers * current_sum - the current checksum or 0 to start a new checksum * ip6 - the ipv6 header */ uint32_t ipv6_pseudo_header_checksum(uint32_t current_sum, const struct ip6_hdr *ip6) { uint32_t checksum_len, checksum_next; checksum_len = htonl(ntohs(ip6->ip6_plen)); checksum_next = htonl(ip6->ip6_nxt); current_sum = ip_checksum_add(current_sum,&(ip6->ip6_src),sizeof(struct in6_addr)); current_sum = ip_checksum_add(current_sum,&(ip6->ip6_dst),sizeof(struct in6_addr)); current_sum = ip_checksum_add(current_sum,&checksum_len,sizeof(checksum_len)); current_sum = ip_checksum_add(current_sum,&checksum_next,sizeof(checksum_next)); return current_sum; } int main() { uint32_t current_sum=0; struct ip6_hdr *ip6; ip6->ip6_plen = 0x0008; ip6->ip6_nxt = 0x11; unsigned char *src_addr = "1:2"; unsigned char *dst_addr = "2:3"; memcpy(&ip6->ip6_src,src_addr,sizeof(struct in6_addr)); memcpy(&ip6->ip6_dst,dst_addr,sizeof(struct in6_addr)); printf("ipv6_pseudo_header_checksum = %x\n", ntohs(ipv6_pseudo_header_checksum(current_sum, ip6))); }