diff options
author | Alexander Koeppe <format_c@online.de> | 2013-08-19 21:24:23 +0200 |
---|---|---|
committer | Alexander Koeppe <format_c@online.de> | 2013-08-19 22:06:01 +0200 |
commit | a89f0f10de9b70c0bcc0ab31552a12e1a8b83921 (patch) | |
tree | cd83fb885ada95e7d88a3cf8f1aafc890859cd90 | |
parent | d5d7b1f92659094172f5e2f9dec3996db5720b6d (diff) | |
download | libnet-a89f0f10de9b70c0bcc0ab31552a12e1a8b83921.tar.gz |
Fix #34 correct checksum caculation when IPv6 extension headers being used
-rw-r--r-- | libnet/src/common.h | 3 | ||||
-rw-r--r-- | libnet/src/libnet_checksum.c | 28 |
2 files changed, 31 insertions, 0 deletions
diff --git a/libnet/src/common.h b/libnet/src/common.h index c0747e8..7b9f8fb 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..a5009f8 100644 --- a/libnet/src/libnet_checksum.c +++ b/libnet/src/libnet_checksum.c @@ -201,12 +201,40 @@ 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; } + + 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 + */ + 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 { |