From c32f1076f695436e25f37c144b69b86ab5e3a5a9 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Mon, 14 Oct 2019 11:22:43 +0200 Subject: [PATCH] gnrc_icmpv6_error: consider originator's destination address correctly While 485dbd1fdac9c965c1f734b1dda711b35bb4ac1a (from #12175) was right in assuming that the for most ICMPv6 error messages the originating packet's destination address must not be a multicast, this is not the case for _all_ ICMPv6 error messages (see [RFC 4443], section 2.4(e.3)). Additionally, 485dbd1fdac9c965c1f734b1dda711b35bb4ac1a removed the check for the source address ([RFC 4443], section 2.4(e.6)), which this PR re-adds. [RFC 4443]: https://tools.ietf.org/html/rfc4443#section-2.4 --- .../icmpv6/error/gnrc_icmpv6_error.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c b/sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c index 95d73a2ad0..bbe02165a5 100644 --- a/sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c +++ b/sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c @@ -234,7 +234,8 @@ static void _send(gnrc_pktsnip_t *pkt, const gnrc_pktsnip_t *orig_pkt, } } -static gnrc_pktsnip_t *_check_ipv6_hdr(const gnrc_pktsnip_t *orig_pkt) +static gnrc_pktsnip_t *_check_ipv6_hdr(const gnrc_pktsnip_t *orig_pkt, + uint8_t type, uint8_t code) { /* discarding const qualifier is safe here */ gnrc_pktsnip_t *ipv6 = gnrc_pktsnip_search_type((gnrc_pktsnip_t *)orig_pkt, @@ -242,16 +243,27 @@ static gnrc_pktsnip_t *_check_ipv6_hdr(const gnrc_pktsnip_t *orig_pkt) assert(ipv6 != NULL); const ipv6_hdr_t *ipv6_hdr = ipv6->data; + /* see https://tools.ietf.org/html/rfc4443#section-2.4 (e.6) */ if (ipv6_addr_is_unspecified(&ipv6_hdr->src) || - ipv6_addr_is_multicast(&ipv6_hdr->dst)) { + ipv6_addr_is_multicast(&ipv6_hdr->src)) { ipv6 = NULL; } + /* ipv6_hdr->dst may only be multicast for Packet Too Big Messages + * and Parameter Problem Messages with code 2, see + * https://tools.ietf.org/html/rfc4443#section-2.4 (e.3) */ + else if (ipv6_addr_is_multicast(&ipv6_hdr->dst)) { + if ((type != ICMPV6_PKT_TOO_BIG) && + ((type != ICMPV6_PARAM_PROB) || + (code != ICMPV6_ERROR_PARAM_PROB_OPT))) { + ipv6 = NULL; + } + } return ipv6; } void gnrc_icmpv6_error_dst_unr_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt, ICMPV6_DST_UNR, code); if (ipv6 != NULL) { gnrc_pktsnip_t *pkt = _dst_unr_build(code, orig_pkt); @@ -264,7 +276,7 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt, ICMPV6_PKT_TOO_BIG, 0); if (ipv6 != NULL) { gnrc_pktsnip_t *pkt = _pkt_too_big_build(mtu, orig_pkt); @@ -277,7 +289,7 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, void gnrc_icmpv6_error_time_exc_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt, ICMPV6_TIME_EXC, code); if (ipv6 != NULL) { gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); @@ -290,7 +302,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt, ICMPV6_PARAM_PROB, code); if (ipv6 != NULL) { gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt);