From a30bdebc2c1f1b57161628d2b1e91a40fc3fcf43 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:08:03 +0100 Subject: [PATCH 01/18] gnrc_icmpv6_error: remove static inline from functions --- sys/include/net/gnrc/icmpv6/error.h | 58 ++----------------- .../icmpv6/error/gnrc_icmpv6_error.c | 57 ++++++++++++++++++ 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 20d0343196..14f25fb9d9 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -85,19 +85,7 @@ gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr, * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] orig_pkt The invoking packet. */ -static inline void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) -{ - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_dst_unr_build(code, orig_pkt); - - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, EHOSTUNREACH); -#else - (void)orig_pkt; -#endif -} +void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt); /** * @brief Sends an ICMPv6 packet too big message for sending. @@ -105,19 +93,7 @@ static inline void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t * * @param[in] mtu The maximum transission unit of the next-hop link. * @param[in] orig_pkt The invoking packet. */ -static inline void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) -{ - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_pkt_too_big_build(mtu, orig_pkt); - - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, EMSGSIZE); -#else - (void)orig_pkt; -#endif -} +void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt); /** * @brief Sends an ICMPv6 time exceeded message for sending. @@ -125,19 +101,7 @@ static inline void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] orig_pkt The invoking packet. */ -static inline void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) -{ - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_time_exc_build(code, orig_pkt); - - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, ETIMEDOUT); -#else - (void)orig_pkt; -#endif -} +void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt); /** * @brief Sends an ICMPv6 parameter problem message for sending. @@ -146,20 +110,8 @@ static inline void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t * @param[in] ptr Pointer to the errorneous octet in @p orig_pkt. * @param[in] orig_pkt The invoking packet. */ -static inline void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, - gnrc_pktsnip_t *orig_pkt) -{ - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_param_prob_build(code, ptr, orig_pkt); - - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, EINVAL); -#else - (void)orig_pkt; -#endif -} +void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, + gnrc_pktsnip_t *orig_pkt); #ifdef __cplusplus } 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 4313414c45..ee8d2cd419 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 @@ -118,4 +118,61 @@ gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr, return pkt; } +void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) +{ + gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_dst_unr_build(code, orig_pkt); + + if (pkt != NULL) { + gnrc_netapi_send(gnrc_ipv6_pid, pkt); + } +#ifdef MODULE_GNRC_PKTBUF + gnrc_pktbuf_release_error(orig_pkt, EHOSTUNREACH); +#else + (void)orig_pkt; +#endif +} + +void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) +{ + gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_pkt_too_big_build(mtu, orig_pkt); + + if (pkt != NULL) { + gnrc_netapi_send(gnrc_ipv6_pid, pkt); + } +#ifdef MODULE_GNRC_PKTBUF + gnrc_pktbuf_release_error(orig_pkt, EMSGSIZE); +#else + (void)orig_pkt; +#endif +} + +void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) +{ + gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_time_exc_build(code, orig_pkt); + + if (pkt != NULL) { + gnrc_netapi_send(gnrc_ipv6_pid, pkt); + } +#ifdef MODULE_GNRC_PKTBUF + gnrc_pktbuf_release_error(orig_pkt, ETIMEDOUT); +#else + (void)orig_pkt; +#endif +} + +void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, + gnrc_pktsnip_t *orig_pkt) +{ + gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_param_prob_build(code, ptr, orig_pkt); + + if (pkt != NULL) { + gnrc_netapi_send(gnrc_ipv6_pid, pkt); + } +#ifdef MODULE_GNRC_PKTBUF + gnrc_pktbuf_release_error(orig_pkt, EINVAL); +#else + (void)orig_pkt; +#endif +} + /** @} */ From 3b56c78a3b6dcc5e15e2256ac6b03fb38a640f20 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:16:42 +0100 Subject: [PATCH 02/18] gnrc_icmpv6_error: make build functions private --- sys/include/net/gnrc/icmpv6/error.h | 46 ------------------- .../icmpv6/error/gnrc_icmpv6_error.c | 21 +++++---- 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 14f25fb9d9..a6dd7ad440 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -33,52 +33,6 @@ extern "C" { #endif -/** - * @brief Builds an ICMPv6 destination unreachable message for sending. - * - * @param[in] code The code for the message @see net/icmpv6.h. - * @param[in] orig_pkt The invoking packet. - * - * @return The destination unreachable message on success. - * @return NULL, on failure. - */ -gnrc_pktsnip_t *gnrc_icmpv6_error_dst_unr_build(uint8_t code, gnrc_pktsnip_t *orig_pkt); - -/** - * @brief Builds an ICMPv6 packet too big message for sending. - * - * @param[in] mtu The maximum transission unit of the next-hop link. - * @param[in] orig_pkt The invoking packet. - * - * @return The packet too big message on success. - * @return NULL, on failure. - */ -gnrc_pktsnip_t *gnrc_icmpv6_error_pkt_too_big_build(uint32_t mtu, gnrc_pktsnip_t *orig_pkt); - -/** - * @brief Builds an ICMPv6 time exceeded message for sending. - * - * @param[in] code The code for the message @see net/icmpv6.h. - * @param[in] orig_pkt The invoking packet. - * - * @return The time exceeded message on success. - * @return NULL, on failure. - */ -gnrc_pktsnip_t *gnrc_icmpv6_error_time_exc_build(uint8_t code, gnrc_pktsnip_t *orig_pkt); - -/** - * @brief Builds an ICMPv6 parameter problem message for sending. - * - * @param[in] code The code for the message @see net/icmpv6.h. - * @param[in] ptr Pointer to the errorneous octet in @p orig_pkt. - * @param[in] orig_pkt The invoking packet. - * - * @return The parameter problem message on success. - * @return NULL, on failure. - */ -gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr, - gnrc_pktsnip_t *orig_pkt); - /** * @brief Sends an ICMPv6 destination unreachable message for sending. * 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 ee8d2cd419..9f61111a41 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 @@ -54,17 +54,20 @@ static gnrc_pktsnip_t *_icmpv6_error_build(uint8_t type, uint8_t code, return pkt; } -gnrc_pktsnip_t *gnrc_icmpv6_error_dst_unr_build(uint8_t code, gnrc_pktsnip_t *orig_pkt) +static inline gnrc_pktsnip_t *_dst_unr_build(uint8_t code, + gnrc_pktsnip_t *orig_pkt) { return _icmpv6_error_build(ICMPV6_DST_UNR, code, orig_pkt, 0); } -gnrc_pktsnip_t *gnrc_icmpv6_error_pkt_too_big_build(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) +static inline gnrc_pktsnip_t *_pkt_too_big_build(uint32_t mtu, + gnrc_pktsnip_t *orig_pkt) { return _icmpv6_error_build(ICMPV6_PKT_TOO_BIG, 0, orig_pkt, mtu); } -gnrc_pktsnip_t *gnrc_icmpv6_error_time_exc_build(uint8_t code, gnrc_pktsnip_t *orig_pkt) +static inline gnrc_pktsnip_t *_time_exc_build(uint8_t code, + gnrc_pktsnip_t *orig_pkt) { return _icmpv6_error_build(ICMPV6_TIME_EXC, code, orig_pkt, 0); } @@ -74,8 +77,8 @@ static inline bool _in_range(uint8_t *ptr, uint8_t *start, size_t sz) return (ptr >= start) && (ptr < (start + sz)); } -gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr, - gnrc_pktsnip_t *orig_pkt) +static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, + gnrc_pktsnip_t *orig_pkt) { gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, ICMPV6_PARAM_PROB, code, _fit(orig_pkt)); @@ -120,7 +123,7 @@ gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr, void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_dst_unr_build(code, orig_pkt); + gnrc_pktsnip_t *pkt = _dst_unr_build(code, orig_pkt); if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); @@ -134,7 +137,7 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_pkt_too_big_build(mtu, orig_pkt); + gnrc_pktsnip_t *pkt = _pkt_too_big_build(mtu, orig_pkt); if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); @@ -148,7 +151,7 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_time_exc_build(code, orig_pkt); + gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); @@ -163,7 +166,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, gnrc_pktsnip_t *orig_pkt) { - gnrc_pktsnip_t *pkt = gnrc_icmpv6_error_param_prob_build(code, ptr, orig_pkt); + gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); From 6ec456b0fc7dfc8cd23683e0064d8a03d512b03e Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:20:16 +0100 Subject: [PATCH 03/18] gnrc_icmpv6_error: don't release orig_pkt on error The stack might still wants to do something with the packet after copying it to the error message. --- .../icmpv6/error/gnrc_icmpv6_error.c | 20 ------------------- 1 file changed, 20 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 9f61111a41..0cbf6ddfd2 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 @@ -128,11 +128,6 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, EHOSTUNREACH); -#else - (void)orig_pkt; -#endif } void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) @@ -142,11 +137,6 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, EMSGSIZE); -#else - (void)orig_pkt; -#endif } void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) @@ -156,11 +146,6 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, ETIMEDOUT); -#else - (void)orig_pkt; -#endif } void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, @@ -171,11 +156,6 @@ void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); } -#ifdef MODULE_GNRC_PKTBUF - gnrc_pktbuf_release_error(orig_pkt, EINVAL); -#else - (void)orig_pkt; -#endif } /** @} */ From 36617f37338b189af71f49876aa58e2fb3c1c819 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:23:31 +0100 Subject: [PATCH 04/18] gnrc_icmpv6_error: make input pointers constant --- sys/include/net/gnrc/icmpv6/error.h | 10 ++++---- .../icmpv6/error/gnrc_icmpv6_error.c | 23 +++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index a6dd7ad440..9d0692424a 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -39,7 +39,7 @@ extern "C" { * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] orig_pkt The invoking packet. */ -void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt); +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. @@ -47,7 +47,8 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt); * @param[in] mtu The maximum transission unit of the next-hop link. * @param[in] orig_pkt The invoking packet. */ -void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt); +void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, + const gnrc_pktsnip_t *orig_pkt); /** * @brief Sends an ICMPv6 time exceeded message for sending. @@ -55,7 +56,8 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt); * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] orig_pkt The invoking packet. */ -void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt); +void gnrc_icmpv6_error_time_exc_send(uint8_t code, + const gnrc_pktsnip_t *orig_pkt); /** * @brief Sends an ICMPv6 parameter problem message for sending. @@ -65,7 +67,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt); * @param[in] orig_pkt The invoking packet. */ void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, - gnrc_pktsnip_t *orig_pkt); + const gnrc_pktsnip_t *orig_pkt); #ifdef __cplusplus } 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 0cbf6ddfd2..eb58422518 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 @@ -26,7 +26,7 @@ /* TODO: generalize and centralize (see https://github.com/RIOT-OS/RIOT/pull/3184) */ #define MIN(a, b) ((a) < (b)) ? (a) : (b) -static inline size_t _fit(gnrc_pktsnip_t *pkt) +static inline size_t _fit(const gnrc_pktsnip_t *pkt) { /* TODO: replace IPV6_MIN_MTU with known path MTU? */ return MIN((gnrc_pkt_len(pkt) + ICMPV6_ERROR_SZ), IPV6_MIN_MTU); @@ -34,7 +34,8 @@ static inline size_t _fit(gnrc_pktsnip_t *pkt) /* Build a generic error message */ static gnrc_pktsnip_t *_icmpv6_error_build(uint8_t type, uint8_t code, - gnrc_pktsnip_t *orig_pkt, uint32_t value) + const gnrc_pktsnip_t *orig_pkt, + uint32_t value) { gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, type, code, _fit(orig_pkt)); @@ -55,19 +56,19 @@ static gnrc_pktsnip_t *_icmpv6_error_build(uint8_t type, uint8_t code, } static inline gnrc_pktsnip_t *_dst_unr_build(uint8_t code, - gnrc_pktsnip_t *orig_pkt) + const gnrc_pktsnip_t *orig_pkt) { return _icmpv6_error_build(ICMPV6_DST_UNR, code, orig_pkt, 0); } static inline gnrc_pktsnip_t *_pkt_too_big_build(uint32_t mtu, - gnrc_pktsnip_t *orig_pkt) + const gnrc_pktsnip_t *orig_pkt) { return _icmpv6_error_build(ICMPV6_PKT_TOO_BIG, 0, orig_pkt, mtu); } static inline gnrc_pktsnip_t *_time_exc_build(uint8_t code, - gnrc_pktsnip_t *orig_pkt) + const gnrc_pktsnip_t *orig_pkt) { return _icmpv6_error_build(ICMPV6_TIME_EXC, code, orig_pkt, 0); } @@ -78,7 +79,7 @@ static inline bool _in_range(uint8_t *ptr, uint8_t *start, size_t sz) } static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, - gnrc_pktsnip_t *orig_pkt) + const gnrc_pktsnip_t *orig_pkt) { gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, ICMPV6_PARAM_PROB, code, _fit(orig_pkt)); @@ -121,7 +122,7 @@ static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, return pkt; } -void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) +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); @@ -130,7 +131,8 @@ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) } } -void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, 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 *pkt = _pkt_too_big_build(mtu, orig_pkt); @@ -139,7 +141,8 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, gnrc_pktsnip_t *orig_pkt) } } -void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) +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); @@ -149,7 +152,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *orig_pkt) } void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, - gnrc_pktsnip_t *orig_pkt) + const gnrc_pktsnip_t *orig_pkt) { gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); From a7a8227e36c74ce10386d7a6bd39ccb862e0dfcf Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:29:21 +0100 Subject: [PATCH 05/18] gnrc_icmpv6_error: centralize send function --- .../icmpv6/error/gnrc_icmpv6_error.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 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 eb58422518..41dc9730f8 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 @@ -122,13 +122,18 @@ static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, return pkt; } +static void _send(gnrc_pktsnip_t *pkt) +{ + if (pkt != NULL) { + gnrc_netapi_send(gnrc_ipv6_pid, pkt); + } +} + 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); - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } + _send(pkt); } void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, @@ -136,9 +141,7 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, { gnrc_pktsnip_t *pkt = _pkt_too_big_build(mtu, orig_pkt); - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } + _send(pkt); } void gnrc_icmpv6_error_time_exc_send(uint8_t code, @@ -146,9 +149,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, { gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } + _send(pkt); } void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, @@ -156,9 +157,7 @@ void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, { gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); - if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); - } + _send(pkt); } /** @} */ From ba13d8f5bfb888c5838d639e226374b3bb82ef76 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:33:09 +0100 Subject: [PATCH 06/18] gnrc_icmpv6_error: introduce debug messages --- .../network_layer/icmpv6/error/gnrc_icmpv6_error.c | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 41dc9730f8..3533b721e0 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 @@ -18,6 +18,9 @@ #include "net/gnrc/icmpv6/error.h" #include "net/gnrc/icmpv6.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + /* all error messages are basically the same size and format */ #define ICMPV6_ERROR_SZ (sizeof(icmpv6_error_dst_unr_t)) #define ICMPV6_ERROR_SET_VALUE(data, value) \ @@ -127,12 +130,16 @@ static void _send(gnrc_pktsnip_t *pkt) if (pkt != NULL) { gnrc_netapi_send(gnrc_ipv6_pid, pkt); } + else { + DEBUG("gnrc_icmpv6_error: No space in packet buffer left\n"); + } } 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); + DEBUG("gnrc_icmpv6_error: trying to send destination unreachable error\n"); _send(pkt); } @@ -141,6 +148,7 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, { 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); } @@ -149,6 +157,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, { gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); + DEBUG("gnrc_icmpv6_error: trying to send time exceeded error\n"); _send(pkt); } @@ -157,6 +166,7 @@ void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, { gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); + DEBUG("gnrc_icmpv6_error: trying to send parameter problem error\n"); _send(pkt); } From c8c8564d518b63288870d3566311d40be2058b63 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:34:22 +0100 Subject: [PATCH 07/18] gnrc_icmpv6_error: use netapi_dispatch_send instead of netapi_send --- .../gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 3533b721e0..e2e901fc73 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 @@ -128,7 +128,12 @@ static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, static void _send(gnrc_pktsnip_t *pkt) { if (pkt != NULL) { - gnrc_netapi_send(gnrc_ipv6_pid, pkt); + if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, + GNRC_NETREG_DEMUX_CTX_ALL, + pkt)) { + DEBUG("gnrc_icmpv6_error: No send handler found.\n"); + gnrc_pktbuf_release(pkt); + } } else { DEBUG("gnrc_icmpv6_error: No space in packet buffer left\n"); From c4175a5e5275966681584dfc32591a9a1d891f62 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:37:40 +0100 Subject: [PATCH 08/18] gnrc_icmpv6_error: adapt _fit() to get MTU from netif --- .../icmpv6/error/gnrc_icmpv6_error.c | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 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 e2e901fc73..a6495a048c 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 @@ -26,13 +26,41 @@ #define ICMPV6_ERROR_SET_VALUE(data, value) \ ((icmpv6_error_pkt_too_big_t *)(data))->mtu = byteorder_htonl(value) -/* TODO: generalize and centralize (see https://github.com/RIOT-OS/RIOT/pull/3184) */ #define MIN(a, b) ((a) < (b)) ? (a) : (b) -static inline size_t _fit(const gnrc_pktsnip_t *pkt) +/** + * @brief Get packet fit. + * + * Get's the minimum size for an ICMPv6 error message packet, based on the + * invoking packet's size and the interface the invoking packet came over. + * + * @param[in] orig_pkt The invoking packet + * + * @return The supposed size of the ICMPv6 error message. + */ +static size_t _fit(const gnrc_pktsnip_t *orig_pkt) { - /* TODO: replace IPV6_MIN_MTU with known path MTU? */ - return MIN((gnrc_pkt_len(pkt) + ICMPV6_ERROR_SZ), IPV6_MIN_MTU); + /* discarding const qualifier is safe here */ + gnrc_pktsnip_t *netif_hdr = gnrc_pktsnip_search_type( + (gnrc_pktsnip_t *)orig_pkt, GNRC_NETTYPE_NETIF + ); + size_t pkt_len = gnrc_pkt_len(orig_pkt) + ICMPV6_ERROR_SZ + + sizeof(ipv6_hdr_t); + + if (netif_hdr) { + gnrc_netif_hdr_t *data = netif_hdr->data; + gnrc_netif_t *netif = gnrc_netif_get_by_pid(data->if_pid); + + DEBUG("gnrc_icmpv6_error: fitting to MTU of iface %u (%u)\n", + netif->pid, netif->ipv6.mtu); + return MIN(pkt_len, netif->ipv6.mtu - sizeof(ipv6_hdr_t)); + } + else { + /* packet does not have a netif header (most likely because it did not + * came from remote) => just assume pkt_len as ideal */ + DEBUG("gnrc_icmpv6_error: copying whole packet\n"); + return pkt_len; + } } /* Build a generic error message */ From f0da2a0cd7be701eafd66bd697cafc7d2d234c58 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 16:07:16 +0100 Subject: [PATCH 09/18] gnrc_icmpv6_error: don't include netif header into fit --- sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c | 1 + 1 file changed, 1 insertion(+) 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 a6495a048c..2ea403fc63 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 @@ -51,6 +51,7 @@ static size_t _fit(const gnrc_pktsnip_t *orig_pkt) gnrc_netif_hdr_t *data = netif_hdr->data; gnrc_netif_t *netif = gnrc_netif_get_by_pid(data->if_pid); + pkt_len -= netif_hdr->size; DEBUG("gnrc_icmpv6_error: fitting to MTU of iface %u (%u)\n", netif->pid, netif->ipv6.mtu); return MIN(pkt_len, netif->ipv6.mtu - sizeof(ipv6_hdr_t)); From 335342a4664e69250acbfa0377468fc4552072af Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 14:44:36 +0100 Subject: [PATCH 10/18] gnrc_icmpv6_error: fix build function for send and recv order --- .../icmpv6/error/gnrc_icmpv6_error.c | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 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 2ea403fc63..c58b2ff578 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 @@ -64,6 +64,41 @@ static size_t _fit(const gnrc_pktsnip_t *orig_pkt) } } +static inline bool _in_orig_pkt(const gnrc_pktsnip_t *orig_pkt) +{ + return (orig_pkt != NULL) && (orig_pkt->type != GNRC_NETTYPE_NETIF); +} + +static size_t _copy_rcv_snip(gnrc_pktsnip_t *pkt, + const gnrc_pktsnip_t *orig_snip) +{ + /* always skip ICMPv6 error header */ + size_t offset = ICMPV6_ERROR_SZ; + const gnrc_pktsnip_t *ptr = orig_snip; + + while (_in_orig_pkt(ptr->next)) { + offset += ptr->next->size; + ptr = ptr->next; + } + + if (offset < pkt->size) { + uint8_t *data = pkt->data; + + memcpy(data + offset, orig_snip->data, + MIN(pkt->size - offset, orig_snip->size)); + } + return offset; +} + +static inline bool _check_send_order(const gnrc_pktsnip_t *pkt) +{ + /* sent packets in IPv6 start either with netif header or + * with IPv6 header (but then the NETIF header doesn't follow) */ + return (pkt->type == GNRC_NETTYPE_NETIF) || + ((pkt->type == GNRC_NETTYPE_IPV6) && + ((pkt->next == NULL) || (pkt->next->type != GNRC_NETTYPE_NETIF))); +} + /* Build a generic error message */ static gnrc_pktsnip_t *_icmpv6_error_build(uint8_t type, uint8_t code, const gnrc_pktsnip_t *orig_pkt, @@ -71,16 +106,30 @@ static gnrc_pktsnip_t *_icmpv6_error_build(uint8_t type, uint8_t code, { gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, type, code, _fit(orig_pkt)); - /* copy as much of the originating packet into error message as fits the message's size */ + /* copy as much of the originating packet into error message as fits the + * message's size */ if (pkt != NULL) { - size_t offset = ICMPV6_ERROR_SZ; - uint8_t *data = pkt->data; - ICMPV6_ERROR_SET_VALUE(data, value); - while ((orig_pkt != NULL) && (offset < pkt->size)) { - memcpy(data + offset, orig_pkt->data, - MIN(pkt->size - offset, orig_pkt->size)); - offset += MIN(pkt->size - offset, orig_pkt->size); - orig_pkt = orig_pkt->next; + ICMPV6_ERROR_SET_VALUE(pkt->data, value); + if (_check_send_order(orig_pkt)) { + const gnrc_pktsnip_t *ptr = (orig_pkt->type == GNRC_NETTYPE_NETIF) + ? orig_pkt->next + : orig_pkt; + size_t offset = ICMPV6_ERROR_SZ; + + while ((ptr != NULL) && (offset < pkt->size)) { + uint8_t *data = pkt->data; + + memcpy(data + offset, ptr->data, MIN(pkt->size - offset, + ptr->size)); + offset += ptr->size; + ptr = ptr->next; + } + } + else { + while (_in_orig_pkt(orig_pkt)) { + _copy_rcv_snip(pkt, orig_pkt); + orig_pkt = orig_pkt->next; + } } } From 0b4230e5f68496c178958c51b3b2cfcc8176dc37 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 16:17:32 +0100 Subject: [PATCH 11/18] gnrc_icmpv6_error: fix and optimize pointer search in _param_prob_build --- sys/include/net/gnrc/icmpv6/error.h | 2 ++ .../icmpv6/error/gnrc_icmpv6_error.c | 30 ++++++------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 9d0692424a..74ee6f6db7 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -62,6 +62,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. + * * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] ptr Pointer to the errorneous octet in @p orig_pkt. * @param[in] orig_pkt The invoking packet. 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 c58b2ff578..e142450d07 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 @@ -168,36 +168,24 @@ static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, /* copy as much of the originating packet into error message and * determine relative *ptr* offset */ if (pkt != NULL) { - size_t offset = sizeof(icmpv6_error_param_prob_t); - uint8_t *data = pkt->data; + icmpv6_error_param_prob_t *hdr = pkt->data; uint32_t ptr_offset = 0U; - bool found_offset = false; - while (orig_pkt != NULL) { - /* copy as long as it fits into packet */ - if (offset < pkt->size) { - memcpy(data + offset, orig_pkt->data, - MIN(pkt->size - offset, orig_pkt->size)); - offset += MIN(pkt->size - offset, orig_pkt->size); - } + while (_in_orig_pkt(orig_pkt)) { + /* copy as long as it fits into packet; parameter problem can only + * come from received packets */ + size_t offset = _copy_rcv_snip(pkt, orig_pkt); if (_in_range(ptr, orig_pkt->data, orig_pkt->size)) { - ptr_offset += (uint32_t)(((uint8_t *)ptr) - ((uint8_t *)orig_pkt->data)); - found_offset = true; + ptr_offset = (uint32_t)(((uint8_t *)ptr) - + ((uint8_t *)orig_pkt->data) + + (offset - ICMPV6_ERROR_SZ)); } - else if (!found_offset) { - ptr_offset += (uint32_t)orig_pkt->size; - } - orig_pkt = orig_pkt->next; - - if ((offset < pkt->size) && found_offset) { - break; - } } /* set "pointer" field to relative pointer offset */ - ((icmpv6_error_param_prob_t *)data)->ptr = byteorder_htonl(ptr_offset); + hdr->ptr = byteorder_htonl(ptr_offset); } return pkt; From d161379e4770ad1a2638f61dbbbb46a22d0a71e1 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 16:18:51 +0100 Subject: [PATCH 12/18] gnrc_icmpv6_error: re-order header inclusions --- sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c | 4 ++-- 1 file changed, 2 insertions(+), 2 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 e142450d07..6a7b63b770 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 @@ -12,11 +12,11 @@ * @file */ +#include "net/ipv6.h" +#include "net/gnrc/icmpv6.h" #include "net/gnrc/pktbuf.h" -#include "net/ipv6.h" #include "net/gnrc/icmpv6/error.h" -#include "net/gnrc/icmpv6.h" #define ENABLE_DEBUG (0) #include "debug.h" From b99e9f41851978de4bf74dae47fb71c226053484 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 16:23:54 +0100 Subject: [PATCH 13/18] gnrc_icmpv6_error: append IPv6 and netif header before sending --- sys/include/net/gnrc/icmpv6/error.h | 7 ++++ .../icmpv6/error/gnrc_icmpv6_error.c | 41 ++++++++++++++++--- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 74ee6f6db7..8306b99f17 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -36,6 +36,8 @@ 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 + * * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] orig_pkt The invoking packet. */ @@ -44,6 +46,8 @@ 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 + * * @param[in] mtu The maximum transission unit of the next-hop link. * @param[in] orig_pkt The invoking packet. */ @@ -53,6 +57,8 @@ 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 + * * @param[in] code The code for the message @see net/icmpv6.h. * @param[in] orig_pkt The invoking packet. */ @@ -63,6 +69,7 @@ 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 * * @param[in] code The code for the message @see net/icmpv6.h. * @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 6a7b63b770..ba1e028fb4 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 @@ -14,6 +14,7 @@ #include "net/ipv6.h" #include "net/gnrc/icmpv6.h" +#include "net/gnrc/netif.h" #include "net/gnrc/pktbuf.h" #include "net/gnrc/icmpv6/error.h" @@ -191,9 +192,39 @@ static gnrc_pktsnip_t *_param_prob_build(uint8_t code, void *ptr, return pkt; } -static void _send(gnrc_pktsnip_t *pkt) +static void _send(gnrc_pktsnip_t *pkt, const gnrc_pktsnip_t *orig_pkt) { 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; + ipv6 = gnrc_ipv6_hdr_build(pkt, NULL, &ipv6_hdr->src); + if (ipv6 == NULL) { + DEBUG("gnrc_icmpv6_error: No space in packet buffer left\n"); + gnrc_pktbuf_release(pkt); + return; + } + pkt = ipv6; + if (netif) { + /* copy interface from original netif header to assure packet + * goes out where it came from */ + gnrc_netif_hdr_t *netif_hdr = netif->data; + kernel_pid_t netif_pid = netif_hdr->if_pid; + + netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0); + if (netif == NULL) { + DEBUG("gnrc_icmpv6_error: No space in packet buffer left\n"); + gnrc_pktbuf_release(pkt); + return; + } + netif_hdr = netif->data; + netif_hdr->if_pid = netif_pid; + LL_PREPEND(pkt, netif); + } if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) { @@ -211,7 +242,7 @@ 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); DEBUG("gnrc_icmpv6_error: trying to send destination unreachable error\n"); - _send(pkt); + _send(pkt, orig_pkt); } void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, @@ -220,7 +251,7 @@ void gnrc_icmpv6_error_pkt_too_big_send(uint32_t mtu, 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); + _send(pkt, orig_pkt); } void gnrc_icmpv6_error_time_exc_send(uint8_t code, @@ -229,7 +260,7 @@ void gnrc_icmpv6_error_time_exc_send(uint8_t code, gnrc_pktsnip_t *pkt = _time_exc_build(code, orig_pkt); DEBUG("gnrc_icmpv6_error: trying to send time exceeded error\n"); - _send(pkt); + _send(pkt, orig_pkt); } void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, @@ -238,7 +269,7 @@ void gnrc_icmpv6_error_param_prob_send(uint8_t code, void *ptr, gnrc_pktsnip_t *pkt = _param_prob_build(code, ptr, orig_pkt); DEBUG("gnrc_icmpv6_error: trying to send parameter problem error\n"); - _send(pkt); + _send(pkt, orig_pkt); } /** @} */ From 697ad17ed18281913e9db78a4beb74ce8d0f4e5f Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 16:24:30 +0100 Subject: [PATCH 14/18] icmpv6_error: doc: provide better references to error codes --- sys/include/net/gnrc/icmpv6/error.h | 7 ++++--- sys/include/net/icmpv6.h | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 8306b99f17..552c93be34 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -38,7 +38,7 @@ extern "C" { * * @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6 * - * @param[in] code The code for the message @see net/icmpv6.h. + * @param[in] code The [code for the message](@ref net_icmpv6_error_dst_unr_codes). * @param[in] orig_pkt The invoking packet. */ void gnrc_icmpv6_error_dst_unr_send(uint8_t code, const gnrc_pktsnip_t *orig_pkt); @@ -59,7 +59,7 @@ 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 * - * @param[in] code The code for the message @see net/icmpv6.h. + * @param[in] code The [code for the message](@ref net_icmpv6_error_time_exc_codes). * @param[in] orig_pkt The invoking packet. */ void gnrc_icmpv6_error_time_exc_send(uint8_t code, @@ -71,7 +71,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 * - * @param[in] code The code for the message @see net/icmpv6.h. + * + * @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. * @param[in] orig_pkt The invoking packet. */ diff --git a/sys/include/net/icmpv6.h b/sys/include/net/icmpv6.h index 3a9e606e16..29d0bec7e0 100644 --- a/sys/include/net/icmpv6.h +++ b/sys/include/net/icmpv6.h @@ -75,6 +75,7 @@ extern "C" { * @{ * @name Codes for destination unreachable messages * + * @anchor net_icmpv6_error_dst_unr_codes * @see * RFC 4443, section 3.1 * @@ -97,6 +98,7 @@ extern "C" { * @{ * @name Codes for time exceeded messages * + * @anchor net_icmpv6_error_time_exc_codes * @see * RFC 4443, section 3.3 * @@ -111,6 +113,7 @@ extern "C" { * @{ * @name Codes for parameter problem messages * + * @anchor net_icmpv6_error_param_prob_codes * @see * RFC 4443, section 3.4 * From 04a28270893fb691ab69578fe96e0848af4aa907 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 14 Nov 2018 13:54:12 +0100 Subject: [PATCH 15/18] gnrc_icmpv6_error: provide NOPs when compiled without module This is aimed to make the usage code of this module more readable. --- sys/include/net/gnrc/icmpv6/error.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sys/include/net/gnrc/icmpv6/error.h b/sys/include/net/gnrc/icmpv6/error.h index 552c93be34..7bd527e131 100644 --- a/sys/include/net/gnrc/icmpv6/error.h +++ b/sys/include/net/gnrc/icmpv6/error.h @@ -33,6 +33,7 @@ extern "C" { #endif +#if defined(MODULE_GNRC_ICMPV6_ERROR) || defined(DOXYGEN) /** * @brief Sends an ICMPv6 destination unreachable message for sending. * @@ -78,6 +79,17 @@ 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); +#else /* defined(MODULE_GNRC_ICMPV6_ERROR) || defined(DOXYGEN) */ +/* NOPs to make the usage code more readable */ +#define gnrc_icmpv6_error_dst_unr_send(code, orig_pkt) \ + (void)code; (void)orig_pkt +#define gnrc_icmpv6_error_pkt_too_big_send(mtu, orig_pkt) \ + (void)mtu; (void)orig_pkt +#define gnrc_icmpv6_error_time_exc_send(code, orig_pkt) \ + (void)code; (void)orig_pkt +#define gnrc_icmpv6_error_param_prob_send(code, ptr, orig_pkt) \ + (void)code; (void)ptr, (void)orig_pkt +#endif /* defined(MODULE_GNRC_ICMPV6_ERROR) || defined(DOXYGEN) */ #ifdef __cplusplus } From db2da19ea434c4b89005480d39abaceaa1304eb2 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 18 Feb 2018 17:41:10 +0100 Subject: [PATCH 16/18] gnrc_ipv6: send IPv6 error messages where appropriate --- sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c | 23 ++++++++++++++++--- .../network_layer/ipv6/nib/_nib-internal.c | 3 +++ sys/net/gnrc/network_layer/ipv6/nib/nib.c | 9 ++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c index 255095f639..b030e39959 100644 --- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c +++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c @@ -321,7 +321,8 @@ static void _send_to_iface(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) ((gnrc_netif_hdr_t *)pkt->data)->if_pid = netif->pid; if (gnrc_pkt_len(pkt->next) > netif->ipv6.mtu) { DEBUG("ipv6: packet too big\n"); - gnrc_pktbuf_release(pkt); + gnrc_icmpv6_error_pkt_too_big_send(netif->ipv6.mtu, pkt); + gnrc_pktbuf_release_error(pkt, EMSGSIZE); return; } #ifdef MODULE_NETSTATS_IPV6 @@ -742,6 +743,7 @@ static void _receive(gnrc_pktsnip_t *pkt) #ifdef MODULE_GNRC_IPV6_WHITELIST if (!gnrc_ipv6_whitelisted(&((ipv6_hdr_t *)(pkt->data))->src)) { DEBUG("ipv6: Source address not whitelisted, dropping packet\n"); + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_PROHIB, pkt); gnrc_pktbuf_release(pkt); return; } @@ -749,6 +751,7 @@ static void _receive(gnrc_pktsnip_t *pkt) #ifdef MODULE_GNRC_IPV6_BLACKLIST if (gnrc_ipv6_blacklisted(&((ipv6_hdr_t *)(pkt->data))->src)) { DEBUG("ipv6: Source address blacklisted, dropping packet\n"); + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_PROHIB, pkt); gnrc_pktbuf_release(pkt); return; } @@ -779,6 +782,7 @@ static void _receive(gnrc_pktsnip_t *pkt) else if (!gnrc_ipv6_whitelisted(&((ipv6_hdr_t *)(ipv6->data))->src)) { /* if ipv6 header already marked*/ DEBUG("ipv6: Source address not whitelisted, dropping packet\n"); + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_PROHIB, pkt); gnrc_pktbuf_release(pkt); return; } @@ -787,6 +791,7 @@ static void _receive(gnrc_pktsnip_t *pkt) else if (gnrc_ipv6_blacklisted(&((ipv6_hdr_t *)(ipv6->data))->src)) { /* if ipv6 header already marked*/ DEBUG("ipv6: Source address blacklisted, dropping packet\n"); + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_PROHIB, pkt); gnrc_pktbuf_release(pkt); return; } @@ -812,7 +817,9 @@ static void _receive(gnrc_pktsnip_t *pkt) DEBUG("ipv6: invalid payload length: %d, actual: %d, dropping packet\n", (int) byteorder_ntohs(hdr->len), (int) (gnrc_pkt_len_upto(pkt, GNRC_NETTYPE_IPV6) - sizeof(ipv6_hdr_t))); - gnrc_pktbuf_release(pkt); + gnrc_icmpv6_error_param_prob_send(ICMPV6_ERROR_PARAM_PROB_HDR_FIELD, + &(hdr->len), pkt); + gnrc_pktbuf_release_error(pkt, EINVAL); return; } @@ -836,6 +843,15 @@ static void _receive(gnrc_pktsnip_t *pkt) if ((ipv6_addr_is_link_local(&(hdr->src))) || (ipv6_addr_is_link_local(&(hdr->dst)))) { DEBUG("ipv6: do not forward packets with link-local source or" " destination address\n"); +#ifdef MODULE_GNRC_ICMPV6_ERROR + if (ipv6_addr_is_link_local(&(hdr->src)) && + !ipv6_addr_is_link_local(&(hdr->dst))) { + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_SCOPE, pkt); + } + else if (!ipv6_addr_is_multicast(&(hdr->dst))) { + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, pkt); + } +#endif gnrc_pktbuf_release(pkt); return; } @@ -868,7 +884,8 @@ static void _receive(gnrc_pktsnip_t *pkt) } else { DEBUG("ipv6: hop limit reached 0: drop packet\n"); - gnrc_pktbuf_release(pkt); + gnrc_icmpv6_error_time_exc_send(ICMPV6_ERROR_TIME_EXC_HL, pkt); + gnrc_pktbuf_release_error(pkt, ETIMEDOUT); return; } diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c index 65d3a32c33..4c33f9d536 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-internal.c @@ -17,6 +17,7 @@ #include #include +#include "net/gnrc/icmpv6/error.h" #include "net/gnrc/ipv6.h" #include "net/gnrc/ipv6/nib/conf.h" #include "net/gnrc/ipv6/nib/nc.h" @@ -265,6 +266,8 @@ void _nib_nc_remove(_nib_onl_entry_t *node) (ptr != NULL) && (tmp = (ptr->next), 1); ptr = tmp) { gnrc_pktqueue_t *entry = gnrc_pktqueue_remove(&node->pktqueue, ptr); + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, + entry->pkt); gnrc_pktbuf_release_error(entry->pkt, EHOSTUNREACH); entry->pkt = NULL; } diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index 81eb765d4f..17bb9b91ae 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -18,6 +18,7 @@ #include "log.h" #include "net/ipv6/addr.h" +#include "net/gnrc/icmpv6/error.h" #include "net/gnrc/nettype.h" #include "net/gnrc/netif/internal.h" #include "net/gnrc/ipv6/nib.h" @@ -203,6 +204,8 @@ int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, * we also shouldn't release), but if netif is not defined we * should release in any case. */ if (netif == NULL) { + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, + pkt); gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); } res = -EHOSTUNREACH; @@ -225,6 +228,8 @@ int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst, memcpy(&route.next_hop, dst, sizeof(route.next_hop)); } else { + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_NO_ROUTE, + pkt); res = -ENETUNREACH; gnrc_pktbuf_release_error(pkt, ENETUNREACH); break; @@ -1168,9 +1173,13 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif, } } else { + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, + pkt); gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); } #else /* GNRC_IPV6_NIB_CONF_QUEUE_PKT */ + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, + pkt); gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); #endif /* GNRC_IPV6_NIB_CONF_QUEUE_PKT */ } From e801829c7ac2427782559e0eab09fbffd0522dd5 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 18 Feb 2018 17:41:28 +0100 Subject: [PATCH 17/18] gnrc_udp: send ICMPv6 error messages where appropriate --- sys/net/gnrc/transport_layer/udp/gnrc_udp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/net/gnrc/transport_layer/udp/gnrc_udp.c b/sys/net/gnrc/transport_layer/udp/gnrc_udp.c index ceeb4d33a0..0478ae21fa 100644 --- a/sys/net/gnrc/transport_layer/udp/gnrc_udp.c +++ b/sys/net/gnrc/transport_layer/udp/gnrc_udp.c @@ -27,6 +27,7 @@ #include "net/ipv6/hdr.h" #include "net/gnrc/udp.h" #include "net/gnrc.h" +#include "net/gnrc/icmpv6/error.h" #include "net/inet_csum.h" @@ -157,6 +158,8 @@ static void _receive(gnrc_pktsnip_t *pkt) /* send payload to receivers */ if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_UDP, port, pkt)) { DEBUG("udp: unable to forward packet as no one is interested in it\n"); + /* TODO determine if IPv6 packet, when IPv4 is implemented */ + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_PORT, pkt); gnrc_pktbuf_release(pkt); } } From 897e688194dc853a6f1ee95a42a20333b1769589 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Sun, 18 Feb 2018 17:42:04 +0100 Subject: [PATCH 18/18] examples: activate gnrc_icmpv6_error for gnrc_networking --- examples/gnrc_networking/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/gnrc_networking/Makefile b/examples/gnrc_networking/Makefile index 4d361f8250..7aac1aee12 100644 --- a/examples/gnrc_networking/Makefile +++ b/examples/gnrc_networking/Makefile @@ -20,6 +20,8 @@ BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-mega2560 arduino-uno \ # NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present USEMODULE += gnrc_netdev_default USEMODULE += auto_init_gnrc_netif +# Activate ICMPv6 error messages +USEMODULE += gnrc_icmpv6_error # Specify the mandatory networking modules for IPv6 and UDP USEMODULE += gnrc_ipv6_router_default USEMODULE += gnrc_udp