diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 5799ee627a..7ca28d05f7 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -363,6 +363,20 @@ void ipv6_iface_print_addrs(void); */ void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t* dest)); +/** + * @brief Calculates the IPv6 upper-layer checksum. + * + * @see + * RFC 2460, section 8.1 + * + * @param[in] ipv6_header Pointer to the IPv6 header of the packet. + * @param[in] buf Pointer to the upper-layer payload of the IP datagram. + * @param[in] len The length of the upper-layer header and data. + * @param[in] proto Upper-layer protocol number according to RFC1700. + * + * @return The IPv6 upper-layer checksum. + */ +uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t proto); /** * @} */ diff --git a/sys/net/sixlowpan/ip.c b/sys/net/sixlowpan/ip.c index 7203e79e22..9094eda01a 100644 --- a/sys/net/sixlowpan/ip.c +++ b/sys/net/sixlowpan/ip.c @@ -35,6 +35,9 @@ #include "net_help.h" #define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +char addr_str[IPV6_MAX_ADDR_STR_LEN]; +#endif #include "debug.h" #define IP_PKT_RECV_BUF_SIZE (64) @@ -311,12 +314,11 @@ void ipv6_process(void) switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { + icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); /* checksum test*/ - if (icmpv6_csum(IPV6_PROTO_NUM_ICMPV6) != 0xffff) { + if (ipv6_csum(ipv6_buf, (uint8_t*) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { printf("ERROR: wrong checksum\n"); } - - icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_demultiplex(icmp_buf); break; } @@ -706,3 +708,16 @@ void ipv6_register_rpl_handler(int pid) { rpl_process_pid = pid; } + +uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t proto) +{ + uint16_t sum = 0; + DEBUG("Calculate checksum over src: %s, dst: %s, len: %04X, buf: %p, proto: %u\n", + ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), + ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), + len, buf, proto); + sum = len + proto; + sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); + sum = csum(sum, buf, len); + return (sum == 0) ? 0xffff : HTONS(sum); +}