diff options
author | Sam Roberts <vieuxtech@gmail.com> | 2013-08-20 20:36:48 -0700 |
---|---|---|
committer | Sam Roberts <vieuxtech@gmail.com> | 2013-08-20 20:36:48 -0700 |
commit | 6abfd26cc3da1d36c23071f458d5eff85489647b (patch) | |
tree | f79c0bb22ceb0fb3542b1297aad8479764faf2bf | |
parent | d5d7b1f92659094172f5e2f9dec3996db5720b6d (diff) | |
parent | a4693ae62c6eaced9fcc849d87f5fd3b98eb8998 (diff) | |
download | libnet-6abfd26cc3da1d36c23071f458d5eff85489647b.tar.gz |
Merge pull request #36 from sam-github/fix-ip6-checksum
Fix ip6 checksum
-rw-r--r-- | libnet/src/common.h | 3 | ||||
-rw-r--r-- | libnet/src/libnet_checksum.c | 39 |
2 files changed, 42 insertions, 0 deletions
diff --git a/libnet/src/common.h b/libnet/src/common.h index c0747e8..de31704 100644 --- a/libnet/src/common.h +++ b/libnet/src/common.h @@ -43,6 +43,9 @@ * included. */ #include <netinet/in.h> +#ifndef IPPROTO_MH +#define IPPROTO_MH 135 /* IPv6 mobility header */ +#endif /* TODO - should ../include/gnuc.h be included here? */ diff --git a/libnet/src/libnet_checksum.c b/libnet/src/libnet_checksum.c index 69ccfea..faf6d44 100644 --- a/libnet/src/libnet_checksum.c +++ b/libnet/src/libnet_checksum.c @@ -201,12 +201,51 @@ libnet_inet_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const ip6h_p = (struct libnet_ipv6_hdr *)iph_p; iph_p = NULL; ip_hl = 40; + uint8_t ip_nh = ip6h_p->ip_nh; + if((uint8_t*)(ip6h_p+1) > end) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): ipv6 hdr not inside packet", __func__); return -1; } + + /* FIXME this entire fragile exercise would be avoided if we just passed + * in the pointer to the protocol block 'q' we are checksumming, which + * we know. + */ + while (ip_nh != protocol && (uint8_t*)ip6h_p + ip_hl + 1 < end) + { + /* next header is not the upper layer protocol */ + switch (ip_nh) + { + case IPPROTO_DSTOPTS: + case IPPROTO_HOPOPTS: + case IPPROTO_ROUTING: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: + case IPPROTO_ESP: + case IPPROTO_MH: + /* + * count option headers to the header length for + * checksum processing + */ + /* Common structure of ipv6 ext headers is: + * uint8: next header protocol + * uint8: length of this header, in multiples of 8, not + * including first eight octets + * The pointer arithmetic below follows from above. + */ + ip_nh = *((uint8_t*)ip6h_p+ip_hl); /* next next header */ + ip_hl += (*((uint8_t*)ip6h_p+ip_hl+1)+1)*8; /* ext header length */ + break; + default: + snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, + "%s(): unsupported extension header (%d)", __func__, ip_nh); + return -1; + } + + } } else { |