Skip to content
Snippets Groups Projects
Commit 0a5ef011 authored by Martine Lenders's avatar Martine Lenders Committed by Martine Lenders
Browse files

gnrc_ipv6_ext_rh: add ICMPv6 error message sending

parent 13e66ce3
No related branches found
No related tags found
No related merge requests found
...@@ -56,14 +56,18 @@ typedef struct __attribute__((packed)) { ...@@ -56,14 +56,18 @@ typedef struct __attribute__((packed)) {
* common among all routing headers, so it should be handled by an * common among all routing headers, so it should be handled by an
* external routing header handler. * external routing header handler.
* *
* @param[in,out] ipv6 The IPv6 header of the incoming packet. * @param[in, out] ipv6 The IPv6 header of the incoming packet.
* @param[in] rh A RPL source routing header. * @param[in] rh A RPL source routing header.
* @param[out] err_ptr A pointer to an erroneous octet within @p rh when
* return value is @ref GNRC_IPV6_EXT_RH_ERROR. For any
* other return value than @ref GNRC_IPV6_EXT_RH_ERROR the
* value of `err_ptr` is not defined.
* *
* @return @ref GNRC_IPV6_EXT_RH_AT_DST, on success * @return @ref GNRC_IPV6_EXT_RH_AT_DST, on success
* @return @ref GNRC_IPV6_EXT_RH_FORWARDED, when @p pkt *should be* forwarded * @return @ref GNRC_IPV6_EXT_RH_FORWARDED, when @p pkt *should be* forwarded
* @return @ref GNRC_IPV6_EXT_RH_ERROR, on error * @return @ref GNRC_IPV6_EXT_RH_ERROR, on error
*/ */
int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh); int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh, void **err_ptr);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "net/ipv6/ext/rh.h" #include "net/ipv6/ext/rh.h"
#include "net/gnrc.h" #include "net/gnrc.h"
#include "net/gnrc/icmpv6/error.h"
#ifdef MODULE_GNRC_RPL_SRH #ifdef MODULE_GNRC_RPL_SRH
#include "net/gnrc/rpl/srh.h" #include "net/gnrc/rpl/srh.h"
#endif #endif
...@@ -35,7 +37,8 @@ static void _forward_pkt(gnrc_pktsnip_t *pkt, ipv6_hdr_t *hdr) ...@@ -35,7 +37,8 @@ static void _forward_pkt(gnrc_pktsnip_t *pkt, ipv6_hdr_t *hdr)
if (--(hdr->hl) == 0) { if (--(hdr->hl) == 0) {
DEBUG("ipv6_ext_rh: hop limit reached 0: drop packet\n"); DEBUG("ipv6_ext_rh: 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; return;
} }
/* remove L2 headers around IPV6 */ /* remove L2 headers around IPV6 */
...@@ -66,6 +69,7 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt) ...@@ -66,6 +69,7 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt)
ipv6_ext_rh_t *ext = pkt->data; ipv6_ext_rh_t *ext = pkt->data;
ipv6_hdr_t *hdr; ipv6_hdr_t *hdr;
int res = GNRC_IPV6_EXT_RH_AT_DST; int res = GNRC_IPV6_EXT_RH_AT_DST;
void *err_ptr = NULL;
/* check seg_left early to avoid duplicating the packet */ /* check seg_left early to avoid duplicating the packet */
if (ext->seg_left == 0) { if (ext->seg_left == 0) {
...@@ -77,11 +81,12 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt) ...@@ -77,11 +81,12 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt)
switch (ext->type) { switch (ext->type) {
#ifdef MODULE_GNRC_RPL_SRH #ifdef MODULE_GNRC_RPL_SRH
case IPV6_EXT_RH_TYPE_RPL_SRH: case IPV6_EXT_RH_TYPE_RPL_SRH:
res = gnrc_rpl_srh_process(hdr, (gnrc_rpl_srh_t *)ext); res = gnrc_rpl_srh_process(hdr, (gnrc_rpl_srh_t *)ext, &err_ptr);
break; break;
#endif #endif
default: default:
res = GNRC_IPV6_EXT_RH_ERROR; res = GNRC_IPV6_EXT_RH_ERROR;
err_ptr = &ext->type;
break; break;
} }
switch (res) { switch (res) {
...@@ -91,7 +96,17 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt) ...@@ -91,7 +96,17 @@ int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt)
case GNRC_IPV6_EXT_RH_AT_DST: case GNRC_IPV6_EXT_RH_AT_DST:
break; break;
default: default:
gnrc_pktbuf_release(pkt); #ifdef MODULE_GNRC_ICMPV6_ERROR
if (err_ptr) {
gnrc_icmpv6_error_param_prob_send(
ICMPV6_ERROR_PARAM_PROB_HDR_FIELD,
err_ptr, pkt
);
}
#else
(void)err_ptr;
#endif
gnrc_pktbuf_release_error(pkt, EINVAL);
break; break;
} }
return res; return res;
......
...@@ -31,10 +31,10 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; ...@@ -31,10 +31,10 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
/* checks if multiple addresses within the source routing header exist on my /* checks if multiple addresses within the source routing header exist on my
* interfaces */ * interfaces */
static bool _contains_multiple_of_my_addr(const ipv6_addr_t *dst, static void *_contains_multiple_of_my_addr(const ipv6_addr_t *dst,
const gnrc_rpl_srh_t *rh, const gnrc_rpl_srh_t *rh,
unsigned num_addr, unsigned num_addr,
unsigned compri_addr_len) unsigned compri_addr_len)
{ {
ipv6_addr_t addr; ipv6_addr_t addr;
uint8_t *addr_vec = (uint8_t *) (rh + 1); uint8_t *addr_vec = (uint8_t *) (rh + 1);
...@@ -45,30 +45,30 @@ static bool _contains_multiple_of_my_addr(const ipv6_addr_t *dst, ...@@ -45,30 +45,30 @@ static bool _contains_multiple_of_my_addr(const ipv6_addr_t *dst,
memcpy(&addr, dst, pref_elided); memcpy(&addr, dst, pref_elided);
for (unsigned i = 0; i < num_addr; i++) { for (unsigned i = 0; i < num_addr; i++) {
uint8_t *addr_vec_ptr = &addr_vec[i * compri_addr_len];
if (i == num_addr - 1) { if (i == num_addr - 1) {
pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr); pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr);
addr_len = sizeof(ipv6_addr_t) - pref_elided; addr_len = sizeof(ipv6_addr_t) - pref_elided;
} }
memcpy(&addr.u8[pref_elided], &addr_vec[i * compri_addr_len], addr_len); memcpy(&addr.u8[pref_elided], addr_vec_ptr, addr_len);
if (gnrc_netif_get_by_ipv6_addr(&addr) != NULL) { if (gnrc_netif_get_by_ipv6_addr(&addr) != NULL) {
if (found && ((i - found_pos) > 1)) { if (found && ((i - found_pos) > 1)) {
DEBUG("RPL SRH: found multiple addresses that belong to me - " DEBUG("RPL SRH: found multiple addresses that belong to me - "
"discard\n"); "discard\n");
/* TODO send an ICMP Parameter Problem (Code 0) and return addr_vec_ptr;
* discard the packet */
return true;
} }
found_pos = i; found_pos = i;
found = true; found = true;
} }
} }
return false; return NULL;
} }
int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh, void **err_ptr)
{ {
ipv6_addr_t addr; ipv6_addr_t addr;
uint8_t *addr_vec = (uint8_t *) (rh + 1); uint8_t *addr_vec = (uint8_t *) (rh + 1), *current_address;
uint8_t num_addr; uint8_t num_addr;
uint8_t current_pos, pref_elided, addr_len, compri_addr_len; uint8_t current_pos, pref_elided, addr_len, compri_addr_len;
const uint8_t new_seg_left = rh->seg_left - 1; const uint8_t new_seg_left = rh->seg_left - 1;
...@@ -83,7 +83,7 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) ...@@ -83,7 +83,7 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
if (rh->seg_left > num_addr) { if (rh->seg_left > num_addr) {
DEBUG("RPL SRH: number of segments left > number of addresses - " DEBUG("RPL SRH: number of segments left > number of addresses - "
"discard\n"); "discard\n");
/* TODO ICMP Parameter Problem - Code 0 */ *err_ptr = &rh->seg_left;
return GNRC_IPV6_EXT_RH_ERROR; return GNRC_IPV6_EXT_RH_ERROR;
} }
...@@ -94,24 +94,27 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) ...@@ -94,24 +94,27 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
compri_addr_len = sizeof(ipv6_addr_t) - GNRC_RPL_SRH_COMPRI(rh->compr); compri_addr_len = sizeof(ipv6_addr_t) - GNRC_RPL_SRH_COMPRI(rh->compr);
addr_len = sizeof(ipv6_addr_t) - pref_elided; addr_len = sizeof(ipv6_addr_t) - pref_elided;
memcpy(&addr, &ipv6->dst, pref_elided); memcpy(&addr, &ipv6->dst, pref_elided);
memcpy(&addr.u8[pref_elided], current_address = &addr_vec[(current_pos - 1) * compri_addr_len];
&addr_vec[(current_pos - 1) * compri_addr_len], memcpy(&addr.u8[pref_elided], current_address, addr_len);
addr_len);
if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) { if (ipv6_addr_is_multicast(&ipv6->dst)) {
DEBUG("RPL SRH: found a multicast address - discard\n"); DEBUG("RPL SRH: found a multicast destination address - discard\n");
/* TODO discard the packet */ *err_ptr = &ipv6->dst;
return GNRC_IPV6_EXT_RH_ERROR;
}
if (ipv6_addr_is_multicast(&addr)) {
DEBUG("RPL SRH: found a multicast addres in next address - discard\n");
*err_ptr = current_address;
return GNRC_IPV6_EXT_RH_ERROR; return GNRC_IPV6_EXT_RH_ERROR;
} }
/* check if multiple addresses of my interface exist */ /* check if multiple addresses of my interface exist */
if (_contains_multiple_of_my_addr(&ipv6->dst, rh, num_addr, if ((*err_ptr = _contains_multiple_of_my_addr(&ipv6->dst, rh, num_addr,
compri_addr_len)) { compri_addr_len))) {
return GNRC_IPV6_EXT_RH_ERROR; return GNRC_IPV6_EXT_RH_ERROR;
} }
rh->seg_left = new_seg_left; rh->seg_left = new_seg_left;
memcpy(&addr_vec[(current_pos - 1) * compri_addr_len], memcpy(current_address, &ipv6->dst.u8[pref_elided], addr_len);
&ipv6->dst.u8[pref_elided], addr_len);
DEBUG("RPL SRH: Next hop: %s at position %d\n", DEBUG("RPL SRH: Next hop: %s at position %d\n",
ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), current_pos); ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), current_pos);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment