From ab9d57dec5ccaed72f8e5e9d5ed49649e1d76fbe Mon Sep 17 00:00:00 2001
From: Martine Lenders <mlenders@inf.fu-berlin.de>
Date: Thu, 20 Aug 2015 12:35:44 +0200
Subject: [PATCH] gnrc_sixlowpan_iphc: set correct length for IPv6 header

---
 sys/include/net/gnrc/sixlowpan/iphc.h             | 15 +++++++++------
 sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c  |  2 +-
 .../gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c |  2 +-
 .../sixlowpan/iphc/gnrc_sixlowpan_iphc.c          | 10 ++++++++--
 4 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/sys/include/net/gnrc/sixlowpan/iphc.h b/sys/include/net/gnrc/sixlowpan/iphc.h
index e962549026..81d9f5a345 100644
--- a/sys/include/net/gnrc/sixlowpan/iphc.h
+++ b/sys/include/net/gnrc/sixlowpan/iphc.h
@@ -34,16 +34,19 @@ extern "C" {
  *
  * @pre (ipv6 != NULL) && (ipv6->size >= sizeof(gnrc_ipv6_hdr_t))
  *
- * @param[out] ipv6     A pre-allocated IPv6 header. Will not be inserted into
- *                      @p pkt
- * @param[in,out] pkt   A received 6LoWPAN IPHC frame. IPHC dispatch will not
- *                      be marked.
- * @param[in] offset    Offset of the IPHC dispatch in 6LoWPaN frame.
+ * @param[out] ipv6         A pre-allocated IPv6 header. Will not be inserted into
+ *                          @p pkt
+ * @param[in,out] pkt       A received 6LoWPAN IPHC frame. IPHC dispatch will not
+ *                          be marked.
+ * @param[in] datagram_size Size of the full uncompressed IPv6 datagram. May be 0, if @p pkt
+ *                          contains the full (unfragmented) IPv6 datagram.
+ * @param[in] offset        Offset of the IPHC dispatch in 6LoWPaN frame.
  *
  * @return  length of the HC dispatches + inline values on success.
  * @return  0 on error.
  */
-size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, size_t offset);
+size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, size_t datagram_size,
+                                  size_t offset);
 
 /**
  * @brief   Compresses a 6LoWPAN for IPHC.
diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c
index 7f87f0f458..e51869812c 100644
--- a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c
+++ b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c
@@ -93,7 +93,7 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
 #ifdef MODULE_GNRC_SIXLOWPAN_IPHC
         else if (sixlowpan_iphc_is(data)) {
             size_t iphc_len;
-            iphc_len = gnrc_sixlowpan_iphc_decode(entry->pkt, pkt,
+            iphc_len = gnrc_sixlowpan_iphc_decode(entry->pkt, pkt, entry->pkt->size,
                                                   sizeof(sixlowpan_frag_t));
             if (iphc_len == 0) {
                 DEBUG("6lo rfrag: could not decode IPHC dispatch\n");
diff --git a/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c b/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c
index 999552f0ed..52513ebd2c 100644
--- a/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c
+++ b/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c
@@ -129,7 +129,7 @@ static void _receive(gnrc_pktsnip_t *pkt)
         gnrc_pktsnip_t *ipv6 = gnrc_pktbuf_add(NULL, NULL, sizeof(ipv6_hdr_t),
                                                GNRC_NETTYPE_IPV6);
         if ((ipv6 == NULL) ||
-            (dispatch_size = gnrc_sixlowpan_iphc_decode(ipv6, pkt, 0)) == 0) {
+            (dispatch_size = gnrc_sixlowpan_iphc_decode(ipv6, pkt, 0, 0)) == 0) {
             DEBUG("6lo: error on IPHC decoding\n");
             if (ipv6 != NULL) {
                 gnrc_pktbuf_release(ipv6);
diff --git a/sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c b/sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c
index 5209d0abfd..e8a1e00b0e 100644
--- a/sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c
+++ b/sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c
@@ -90,7 +90,8 @@ static inline bool _context_overlaps_iid(gnrc_sixlowpan_ctx_t *ctx,
              (iid->uint8[(ctx->prefix_len / 8) - 8] & byte_mask[ctx->prefix_len % 8])));
 }
 
-size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, size_t offset)
+size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, size_t datagram_size,
+                                  size_t offset)
 {
     gnrc_netif_hdr_t *netif_hdr = pkt->next->data;
     ipv6_hdr_t *ipv6_hdr;
@@ -370,7 +371,12 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, siz
 
     /* set IPv6 header payload length field to the length of whatever is left
      * after removing the 6LoWPAN header */
-    ipv6_hdr->len = byteorder_htons((uint16_t)(pkt->size - payload_offset));
+    if (datagram_size == 0) {
+        ipv6_hdr->len = byteorder_htons((uint16_t)(pkt->size - payload_offset));
+    }
+    else {
+        ipv6_hdr->len = byteorder_htons((uint16_t)(datagram_size - sizeof(ipv6_hdr_t)));
+    }
 
 
     return payload_offset;
-- 
GitLab