1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 22:43:50 +01:00

Merge pull request #8594 from miri64/gnrc_icmpv6_error/enh/use-icmpv6-error

gnrc_icmpv6_error: fix and use where appropriate
This commit is contained in:
Martine Lenders 2018-11-16 19:05:55 +01:00 committed by GitHub
commit 3b1a7d0eee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 268 additions and 147 deletions

View File

@ -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

View File

@ -33,133 +33,63 @@
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);
#if defined(MODULE_GNRC_ICMPV6_ERROR) || defined(DOXYGEN)
/**
* @brief Sends an ICMPv6 destination unreachable message for sending.
*
* @param[in] code The code for the message @see net/icmpv6.h.
* @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6
*
* @param[in] code The [code for the message](@ref net_icmpv6_error_dst_unr_codes).
* @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, 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.
*/
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,
const gnrc_pktsnip_t *orig_pkt);
/**
* @brief Sends an ICMPv6 time exceeded message for sending.
*
* @param[in] code The code for the message @see net/icmpv6.h.
* @pre @p orig_pkt contains a packet snip of type @ref GNRC_NETTYPE_IPV6
*
* @param[in] code The [code for the message](@ref net_icmpv6_error_time_exc_codes).
* @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,
const gnrc_pktsnip_t *orig_pkt);
/**
* @brief Sends an ICMPv6 parameter problem message for sending.
*
* @param[in] code The code for the message @see net/icmpv6.h.
* @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](@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.
*/
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,
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
}

View File

@ -75,6 +75,7 @@ extern "C" {
* @{
* @name Codes for destination unreachable messages
*
* @anchor net_icmpv6_error_dst_unr_codes
* @see <a href="https://tools.ietf.org/html/rfc4443#section-3.1">
* RFC 4443, section 3.1
* </a>
@ -97,6 +98,7 @@ extern "C" {
* @{
* @name Codes for time exceeded messages
*
* @anchor net_icmpv6_error_time_exc_codes
* @see <a href="https://tools.ietf.org/html/rfc4443#section-3.3">
* RFC 4443, section 3.3
* </a>
@ -111,6 +113,7 @@ extern "C" {
* @{
* @name Codes for parameter problem messages
*
* @anchor net_icmpv6_error_param_prob_codes
* @see <a href="https://tools.ietf.org/html/rfc4443#section-3.4">
* RFC 4443, section 3.4
* </a>

View File

@ -12,59 +12,145 @@
* @file
*/
#include "net/ipv6.h"
#include "net/gnrc/icmpv6.h"
#include "net/gnrc/netif.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"
/* 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) \
((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(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);
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));
}
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;
}
}
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,
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));
/* 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;
}
}
}
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,
const 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,
const 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,
const gnrc_pktsnip_t *orig_pkt)
{
return _icmpv6_error_build(ICMPV6_TIME_EXC, code, orig_pkt, 0);
}
@ -74,8 +160,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,
const gnrc_pktsnip_t *orig_pkt)
{
gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, ICMPV6_PARAM_PROB, code,
_fit(orig_pkt));
@ -83,39 +169,107 @@ gnrc_pktsnip_t *gnrc_icmpv6_error_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;
}
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)) {
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");
}
}
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, 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);
DEBUG("gnrc_icmpv6_error: trying to send packet too big error\n");
_send(pkt, 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);
DEBUG("gnrc_icmpv6_error: trying to send time exceeded error\n");
_send(pkt, orig_pkt);
}
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);
DEBUG("gnrc_icmpv6_error: trying to send parameter problem error\n");
_send(pkt, orig_pkt);
}
/** @} */

View File

@ -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;
}

View File

@ -17,6 +17,7 @@
#include <stdbool.h>
#include <string.h>
#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;
}

View File

@ -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 */
}

View File

@ -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);
}
}