From d342d35dd8abad956a3e87c123c5a5d63818d932 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 15 Dec 2015 19:59:05 +0100 Subject: [PATCH] gnrc_sixlowpan: Fix IPHC/NHC packet order problem --- sys/include/net/gnrc/sixlowpan/iphc.h | 12 +++---- .../gnrc/network_layer/sixlowpan/frag/rbuf.c | 2 +- .../network_layer/sixlowpan/gnrc_sixlowpan.c | 35 ++++++++----------- .../sixlowpan/iphc/gnrc_sixlowpan_iphc.c | 26 ++++++++------ 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/sys/include/net/gnrc/sixlowpan/iphc.h b/sys/include/net/gnrc/sixlowpan/iphc.h index 81d9f5a345..6dbfae38c0 100644 --- a/sys/include/net/gnrc/sixlowpan/iphc.h +++ b/sys/include/net/gnrc/sixlowpan/iphc.h @@ -32,11 +32,11 @@ extern "C" { /** * @brief Decompresses a received 6LoWPAN IPHC frame. * - * @pre (ipv6 != NULL) && (ipv6->size >= sizeof(gnrc_ipv6_hdr_t)) + * @pre (dec_hdr != NULL) && (*dec_hdr != NULL) && ((*dec_hdr)->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 + * @param[out] dec_hdr A pre-allocated IPv6 header. Will not be inserted into + * @p pkt. May change due to next headers being added in NHC. + * @param[in] 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. @@ -45,8 +45,8 @@ extern "C" { * @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 datagram_size, - size_t offset); +size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, 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 fefae3c90b..1cd8be7d73 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/rbuf.c @@ -92,7 +92,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, entry->pkt->size, + 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 61d3b2c979..cd9b2960c5 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c +++ b/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c @@ -118,6 +118,7 @@ static void _receive(gnrc_pktsnip_t *pkt) } pkt = gnrc_pktbuf_remove_snip(pkt, sixlowpan); + payload->type = GNRC_NETTYPE_IPV6; } #ifdef MODULE_GNRC_SIXLOWPAN_FRAG else if (sixlowpan_frag_is((sixlowpan_frag_t *)dispatch)) { @@ -129,14 +130,14 @@ static void _receive(gnrc_pktsnip_t *pkt) #ifdef MODULE_GNRC_SIXLOWPAN_IPHC else if (sixlowpan_iphc_is(dispatch)) { size_t dispatch_size; - gnrc_pktsnip_t *sixlowpan; - 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)) == 0) { + gnrc_pktsnip_t *sixlowpan, *tmp; + gnrc_pktsnip_t *dec_hdr = gnrc_pktbuf_add(NULL, NULL, sizeof(ipv6_hdr_t), + GNRC_NETTYPE_IPV6); + if ((dec_hdr == NULL) || + (dispatch_size = gnrc_sixlowpan_iphc_decode(&dec_hdr, pkt, 0, 0)) == 0) { DEBUG("6lo: error on IPHC decoding\n"); - if (ipv6 != NULL) { - gnrc_pktbuf_release(ipv6); + if (dec_hdr != NULL) { + gnrc_pktbuf_release(dec_hdr); } gnrc_pktbuf_release(pkt); return; @@ -144,21 +145,18 @@ static void _receive(gnrc_pktsnip_t *pkt) sixlowpan = gnrc_pktbuf_mark(pkt, dispatch_size, GNRC_NETTYPE_SIXLOWPAN); if (sixlowpan == NULL) { DEBUG("6lo: error on marking IPHC dispatch\n"); - gnrc_pktbuf_release(ipv6); + gnrc_pktbuf_release(dec_hdr); gnrc_pktbuf_release(pkt); return; } - /* Remove IPHC dispatch */ + /* Remove IPHC dispatches */ gnrc_pktbuf_remove_snip(pkt, sixlowpan); - /* Insert IPv6 header instead */ - if (ipv6->next != NULL) { - ipv6->next->next = pkt->next; - } - else { - ipv6->next = pkt->next; - } - pkt->next = ipv6; + /* Insert decoded header instead */ + LL_SEARCH_SCALAR(dec_hdr, tmp, next, NULL); /* search last decoded header */ + tmp->next = pkt->next; + pkt->next = dec_hdr; + payload->type = GNRC_NETTYPE_UNDEF; } #endif else { @@ -167,9 +165,6 @@ static void _receive(gnrc_pktsnip_t *pkt) gnrc_pktbuf_release(pkt); return; } - - payload->type = GNRC_NETTYPE_IPV6; - if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { DEBUG("6lo: No receivers for this packet found\n"); gnrc_pktbuf_release(pkt); 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 267f0da57f..edbc5bdc98 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 @@ -111,16 +111,18 @@ static inline bool _context_overlaps_iid(gnrc_sixlowpan_ctx_t *ctx, (iid->uint8[(ctx->prefix_len / 8) - 8] & byte_mask[ctx->prefix_len % 8]))); } -#ifdef MODULE_GNRC_UDP -inline static size_t iphc_nhc_udp_decode(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *ipv6, size_t offset) +#if defined(MODULE_GNRC_UDP) && defined(MODULE_GNRC_SIXLOWPAN_IPHC_NHC) +inline static size_t iphc_nhc_udp_decode(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t **dec_hdr, + size_t offset) { uint8_t *payload = pkt->data; - uint8_t udp_nhc = payload[offset++]; + gnrc_pktsnip_t *ipv6 = *dec_hdr; ipv6_hdr_t *ipv6_hdr = ipv6->data; - uint8_t tmp; - gnrc_pktsnip_t *udp = gnrc_pktbuf_add(NULL, NULL, sizeof(udp_hdr_t), GNRC_NETTYPE_UDP); + uint8_t udp_nhc = payload[offset++]; + uint8_t tmp; + if (udp == NULL) { DEBUG("6lo: error on IPHC NHC UDP decoding\n"); return 0; @@ -178,21 +180,25 @@ inline static size_t iphc_nhc_udp_decode(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *ip ipv6_hdr->nh = PROTNUM_UDP; ipv6_hdr->len = udp_hdr->length; - ipv6->next = udp; + udp->next = ipv6; + *dec_hdr = udp; return offset; } #endif -size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, size_t datagram_size, - size_t offset) +size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt, + size_t datagram_size, size_t offset) { + gnrc_pktsnip_t *ipv6; gnrc_netif_hdr_t *netif_hdr = pkt->next->data; ipv6_hdr_t *ipv6_hdr; uint8_t *iphc_hdr = pkt->data; size_t payload_offset = SIXLOWPAN_IPHC_HDR_LEN; gnrc_sixlowpan_ctx_t *ctx = NULL; + assert(dec_hdr != NULL); + ipv6 = *dec_hdr; assert(ipv6 != NULL); assert(ipv6->size >= sizeof(ipv6_hdr_t)); @@ -472,7 +478,7 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, siz switch (iphc_hdr[payload_offset] & NHC_ID_MASK) { #ifdef MODULE_GNRC_UDP case NHC_UDP_ID: - payload_offset = iphc_nhc_udp_decode(pkt, ipv6, payload_offset); + payload_offset = iphc_nhc_udp_decode(pkt, dec_hdr, payload_offset); break; #endif @@ -485,7 +491,7 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *pkt, siz return payload_offset; } -#ifdef MODULE_GNRC_UDP +#if defined(MODULE_GNRC_UDP) && defined(MODULE_GNRC_SIXLOWPAN_IPHC_NHC) inline static size_t iphc_nhc_udp_encode(gnrc_pktsnip_t *udp, ipv6_hdr_t *ipv6_hdr) { udp_hdr_t *udp_hdr = udp->data;