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;