From ef1132384ac684df42a6900e3327f1d62f6f400c Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sat, 17 Nov 2018 01:53:10 +0100 Subject: [PATCH 1/3] gnrc_icmpv6_error: check IPv6 header before starting to build Check for: - if it exists (critical error condition -- non-IPv6 headers should not trigger these functions) => assert - if it has a multicast source (that shouldn't really happen but people might try weird stuff ;-) - if it has an unspecified source (can't determine receiver of error message => don't send it, don't build it) --- sys/include/net/gnrc/icmpv6/error.h | 11 ++++ .../icmpv6/error/gnrc_icmpv6_error.c | 61 ++++++++++++++----- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 7bd527e131..554fc9c102 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -39,6 +39,9 @@ extern "C" { * * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * + * @note Won't send if source address of @p orig_pkt is unspecified or + * multicast + * * @param[in] code The [code for the message](@ref net_icmpv6_error_dst_unr_codes). * @param[in] orig_pkt The invoking packet. */ @@ -49,6 +52,9 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt * * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * + * @note Won't send if source address of @p orig_pkt is unspecified or + * multicast + * * @param[in] mtu The maximum transission unit of the next-hop link. * @param[in] orig_pkt The invoking packet. */ @@ -60,6 +66,9 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, * * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * + * @note Won't send if source address of @p orig_pkt is unspecified or + * multicast + * * @param[in] code The [code for the message](@ref net_icmpv6_error_time_exc_codes). * @param[in] orig_pkt The invoking packet. */ @@ -72,6 +81,8 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, * @pre @p orig_pkt is in receive order. * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * + * @note Won't send if source address of @p orig_pkt is unspecified or + * multicast * * @param[in] code The [code for the message](@ref net_icmpv6_error_param_prob_codes). * @param[in] ptr Pointer to the errorneous octet in @p orig_pkt. 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 ba1e028fb4..cb8b6b588a 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 @@ -192,16 +192,16 @@ static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, return pkt; } -static void _send(gnrc_pktsnip_t *pkt, const gnrc_pktsnip_t *orig_pkt) +static void _send(gnrc_pktsnip_t *pkt, const gnrc_pktsnip_t *orig_pkt, + gnrc_pktsnip_t *ipv6) { if (pkt != NULL) { /* discarding const qualifier is safe here */ - gnrc_pktsnip_t *ipv6 = gnrc_pktsnip_search_type((gnrc_pktsnip_t *)orig_pkt, - GNRC_NETTYPE_IPV6); gnrc_pktsnip_t *netif = gnrc_pktsnip_search_type((gnrc_pktsnip_t *)orig_pkt, GNRC_NETTYPE_NETIF); assert(ipv6 != NULL); ipv6_hdr_t *ipv6_hdr = ipv6->data; + /* overwrite ipv6 parameter pointer ... we don't need it after this */ ipv6 = gnrc_ipv6_hdr_build(pkt, NULL, &ipv6_hdr->src); if (ipv6 == NULL) { DEBUG("gnrc_icmpv6_error: No space in packet buffer left\n"); @@ -237,39 +237,70 @@ 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) +{ + /* discarding const qualifier is safe here */ + gnrc_pktsnip_t *ipv6 = gnrc_pktsnip_search_type((gnrc_pktsnip_t *)orig_pkt, + GNRC_NETTYPE_IPV6); + assert(ipv6 != NULL); + const ipv6_hdr_t *ipv6_hdr = ipv6->data; + + if (ipv6_addr_is_unspecified(&ipv6_hdr->src) || + ipv6_addr_is_multicast(&ipv6_hdr->src)) { + ipv6 = NULL; + } + return ipv6; +} + void gnrc_icmpv6_error_dst_unr_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = _dst_unr_build(code, orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); - DEBUG("gnrc_icmpv6_error: trying to send destination unreachable error\n"); - _send(pkt, orig_pkt); + if (ipv6 != NULL) { + gnrc_pktsnip_t *pkt = _dst_unr_build(code, orig_pkt); + + DEBUG("gnrc_icmpv6_error: trying to send destination unreachable error\n"); + _send(pkt, orig_pkt, ipv6); + } } void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = _pkt_too_big_build(mtu, orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); - DEBUG("gnrc_icmpv6_error: trying to send packet too big error\n"); - _send(pkt, orig_pkt); + if (ipv6 != NULL) { + gnrc_pktsnip_t *pkt = _pkt_too_big_build(mtu, orig_pkt); + + DEBUG("gnrc_icmpv6_error: trying to send packet too big error\n"); + _send(pkt, orig_pkt, ipv6); + } } void gnrc_icmpv6_error_time_exc_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); - DEBUG("gnrc_icmpv6_error: trying to send time exceeded error\n"); - _send(pkt, orig_pkt); + if (ipv6 != NULL) { + gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); + + DEBUG("gnrc_icmpv6_error: trying to send time exceeded error\n"); + _send(pkt, orig_pkt, ipv6); + } } void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, const gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); + gnrc_pktsnip_t *ipv6 = _check_ipv6_hdr(orig_pkt); - DEBUG("gnrc_icmpv6_error: trying to send parameter problem error\n"); - _send(pkt, orig_pkt); + if (ipv6 != NULL) { + gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); + + DEBUG("gnrc_icmpv6_error: trying to send parameter problem error\n"); + _send(pkt, orig_pkt, ipv6); + } } /** @} */ From 0aa96a4579520cd26ec30b92819e4a6d02bbe6af Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sat, 17 Nov 2018 15:22:01 +0100 Subject: [PATCH 2/3] gnrc_icmpv6_error: fix doc alignment --- sys/include/net/gnrc/icmpv6/error.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 554fc9c102..60b00368bd 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -37,7 +37,7 @@ extern "C" { /** * @brief Sends an ICMPv6 destination unreachable message for sending. * - * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 + * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * * @note Won't send if source address of @p orig_pkt is unspecified or * multicast @@ -50,7 +50,7 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt /** * @brief Sends an ICMPv6 packet too big message for sending. * - * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 + * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * * @note Won't send if source address of @p orig_pkt is unspecified or * multicast @@ -64,7 +64,7 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, /** * @brief Sends an ICMPv6 time exceeded message for sending. * - * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 + * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * * @note Won't send if source address of @p orig_pkt is unspecified or * multicast @@ -78,8 +78,8 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, /** * @brief Sends an ICMPv6 parameter problem message for sending. * - * @pre @p orig_pkt is in receive order. - * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 + * @pre @p orig_pkt is in receive order. + * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * * @note Won't send if source address of @p orig_pkt is unspecified or * multicast From 0bdbb68959e040253f4d0b8c3f5600aed2be989b Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sat, 17 Nov 2018 01:55:00 +0100 Subject: [PATCH 3/3] gnrc_ipv6: drop packets with unspecified destination It just doesn't makes sense to handle them any further --- sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c index d049c4c07e..f21a10f8b3 100644 --- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c +++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c @@ -665,6 +665,12 @@ static void _send(gnrc_pktsnip_t *pkt, bool prep_hdr) gnrc_pktbuf_release_error(pkt, EINVAL); return; } + if (ipv6_addr_is_unspecified(&((ipv6_hdr_t *)pkt->data)->dst)) { + DEBUG("ipv6: destination address is unspecified address (::), " + "dropping packet \n"); + gnrc_pktbuf_release_error(pkt, EINVAL); + return; + } tmp_pkt = gnrc_pktbuf_start_write(pkt); if (tmp_pkt == NULL) { DEBUG("ipv6: unable to get write access to IPv6 header, dropping packet\n");