summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Roberts <vieuxtech@gmail.com>2013-08-20 20:36:48 -0700
committerSam Roberts <vieuxtech@gmail.com>2013-08-20 20:36:48 -0700
commit6abfd26cc3da1d36c23071f458d5eff85489647b (patch)
treef79c0bb22ceb0fb3542b1297aad8479764faf2bf
parentd5d7b1f92659094172f5e2f9dec3996db5720b6d (diff)
parenta4693ae62c6eaced9fcc849d87f5fd3b98eb8998 (diff)
downloadlibnet-6abfd26cc3da1d36c23071f458d5eff85489647b.tar.gz
Merge pull request #36 from sam-github/fix-ip6-checksum
Fix ip6 checksum
-rw-r--r--libnet/src/common.h3
-rw-r--r--libnet/src/libnet_checksum.c39
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
{