diff --git a/sys/net/gnrc/transport_layer/udp/gnrc_udp.c b/sys/net/gnrc/transport_layer/udp/gnrc_udp.c index f6d33bf154..6c4a02de76 100644 --- a/sys/net/gnrc/transport_layer/udp/gnrc_udp.c +++ b/sys/net/gnrc/transport_layer/udp/gnrc_udp.c @@ -68,7 +68,7 @@ static uint16_t _calc_csum(gnrc_pktsnip_t *hdr, gnrc_pktsnip_t *pseudo_hdr, uint16_t len = (uint16_t)hdr->size; /* process the payload */ - while (payload && payload != hdr) { + while (payload && payload != hdr && payload != pseudo_hdr) { csum = inet_csum_slice(csum, (uint8_t *)(payload->data), payload->size, len); len += (uint16_t)payload->size; payload = payload->next; @@ -104,21 +104,29 @@ static void _receive(gnrc_pktsnip_t *pkt) return; } pkt = udp; - udp = gnrc_pktbuf_mark(pkt, sizeof(udp_hdr_t), GNRC_NETTYPE_UDP); - if (udp == NULL) { - DEBUG("udp: error marking UDP header, dropping packet\n"); - gnrc_pktbuf_release(pkt); - return; + + LL_SEARCH_SCALAR(pkt, ipv6, type, GNRC_NETTYPE_IPV6); + + assert(ipv6 != NULL); + + if ((ipv6->next != NULL) && (ipv6->next->type == GNRC_NETTYPE_UDP) && + (ipv6->next->size == sizeof(udp_hdr_t))) { + /* UDP header was already marked. Take it. */ + udp = ipv6->next; + } + else { + udp = gnrc_pktbuf_mark(pkt, sizeof(udp_hdr_t), GNRC_NETTYPE_UDP); + if (udp == NULL) { + DEBUG("udp: error marking UDP header, dropping packet\n"); + gnrc_pktbuf_release(pkt); + return; + } } /* mark payload as Type: UNDEF */ pkt->type = GNRC_NETTYPE_UNDEF; /* get explicit pointer to UDP header */ hdr = (udp_hdr_t *)udp->data; - LL_SEARCH_SCALAR(pkt, ipv6, type, GNRC_NETTYPE_IPV6); - - assert(ipv6 != NULL); - /* validate checksum */ if (_calc_csum(udp, ipv6, pkt)) { DEBUG("udp: received packet with invalid checksum, dropping it\n");