Skip to content
Snippets Groups Projects
Unverified Commit 310ef3c2 authored by Martine Lenders's avatar Martine Lenders Committed by GitHub
Browse files

Merge pull request #10227 from miri64/gnrc_rpl_srh/enh/cleanup-handler

gnrc_rpl_srh: cleanup and optimize SRH processing function
parents 050e06f2 d8317580
No related branches found
No related tags found
No related merge requests found
...@@ -52,6 +52,10 @@ typedef struct __attribute__((packed)) { ...@@ -52,6 +52,10 @@ typedef struct __attribute__((packed)) {
/** /**
* @brief Process the RPL source routing header. * @brief Process the RPL source routing header.
* *
* @pre `rh->seq_left > 0`; The 0 case means the destination is reached and
* common among all routing headers, so it should be handled by an
* 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.
* *
......
/* /*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> * Copyright (C) 2015 Cenk Gündoğan <cnkgndgn@gmail.com>
* Copyright (C) 2018 Freie Universität Berlin
* *
* This file is subject to the terms and conditions of the GNU Lesser * This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level * General Public License v2.1. See the file LICENSE in the top level
...@@ -10,6 +11,8 @@ ...@@ -10,6 +11,8 @@
* @{ * @{
* *
* @file * @file
* @author Cenk Gündoğan <cnkgndgn@gmail.com>
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/ */
#include <string.h> #include <string.h>
...@@ -26,34 +29,74 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; ...@@ -26,34 +29,74 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
#define GNRC_RPL_SRH_COMPRE(X) (X & 0x0F) #define GNRC_RPL_SRH_COMPRE(X) (X & 0x0F)
#define GNRC_RPL_SRH_COMPRI(X) ((X & 0xF0) >> 4) #define GNRC_RPL_SRH_COMPRI(X) ((X & 0xF0) >> 4)
int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) /* checks if multiple addresses within the source routing header exist on my
* interfaces */
static bool _contains_multiple_of_my_addr(const ipv6_addr_t *dst,
const gnrc_rpl_srh_t *rh,
unsigned num_addr,
unsigned compri_addr_len)
{ {
if (rh->seg_left == 0) { ipv6_addr_t addr;
return GNRC_IPV6_EXT_RH_AT_DST; uint8_t *addr_vec = (uint8_t *) (rh + 1);
bool found = false;
uint8_t pref_elided = GNRC_RPL_SRH_COMPRI(rh->compr);
uint8_t addr_len = compri_addr_len;
uint8_t found_pos = 0;
memcpy(&addr, dst, pref_elided);
for (unsigned i = 0; i < num_addr; i++) {
if (i == num_addr - 1) {
pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr);
addr_len = sizeof(ipv6_addr_t) - pref_elided;
}
memcpy(&addr.u8[pref_elided], &addr_vec[i * compri_addr_len], addr_len);
if (gnrc_netif_get_by_ipv6_addr(&addr) != NULL) {
if (found && ((i - found_pos) > 1)) {
DEBUG("RPL SRH: found multiple addresses that belong to me - "
"discard\n");
/* TODO send an ICMP Parameter Problem (Code 0) and
* discard the packet */
return true;
}
found_pos = i;
found = true;
}
} }
return false;
}
uint8_t n = (((rh->len * 8) - GNRC_RPL_SRH_PADDING(rh->pad_resv) - int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
(16 - GNRC_RPL_SRH_COMPRE(rh->compr))) / {
(16 - GNRC_RPL_SRH_COMPRI(rh->compr))) + 1; ipv6_addr_t addr;
ipv6_addr_t addr = ipv6->dst, tmp;
uint8_t i, pref_elided, tmp_pref_elided, addr_len, compri_addr_len, tmp_addr_len, found_pos = 0;
uint8_t *addr_vec = (uint8_t *) (rh + 1); uint8_t *addr_vec = (uint8_t *) (rh + 1);
bool found = false; uint8_t num_addr;
uint8_t current_pos, pref_elided, addr_len, compri_addr_len;
const uint8_t new_seg_left = rh->seg_left - 1;
DEBUG("RPL SRH: %u addresses in the routing header\n", (unsigned) n); assert(rh->seg_left > 0);
num_addr = (((rh->len * 8) - GNRC_RPL_SRH_PADDING(rh->pad_resv) -
(16 - GNRC_RPL_SRH_COMPRE(rh->compr))) /
(16 - GNRC_RPL_SRH_COMPRI(rh->compr))) + 1;
if (rh->seg_left > n) { DEBUG("RPL SRH: %u addresses in the routing header\n", (unsigned) num_addr);
DEBUG("RPL SRH: number of segments left > number of addresses - discard\n");
if (rh->seg_left > num_addr) {
DEBUG("RPL SRH: number of segments left > number of addresses - "
"discard\n");
/* TODO ICMP Parameter Problem - Code 0 */ /* TODO ICMP Parameter Problem - Code 0 */
return GNRC_IPV6_EXT_RH_ERROR; return GNRC_IPV6_EXT_RH_ERROR;
} }
rh->seg_left--; current_pos = num_addr - new_seg_left;
i = n - rh->seg_left; pref_elided = (new_seg_left)
pref_elided = rh->seg_left ? GNRC_RPL_SRH_COMPRI(rh->compr) : GNRC_RPL_SRH_COMPRE(rh->compr); ? GNRC_RPL_SRH_COMPRI(rh->compr)
: GNRC_RPL_SRH_COMPRE(rh->compr);
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.u8[pref_elided], &addr_vec[(i - 1) * compri_addr_len], addr_len); memcpy(&addr, &ipv6->dst, pref_elided);
memcpy(&addr.u8[pref_elided],
&addr_vec[(current_pos - 1) * compri_addr_len],
addr_len);
if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) { if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) {
DEBUG("RPL SRH: found a multicast address - discard\n"); DEBUG("RPL SRH: found a multicast address - discard\n");
...@@ -62,32 +105,18 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) ...@@ -62,32 +105,18 @@ int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh)
} }
/* check if multiple addresses of my interface exist */ /* check if multiple addresses of my interface exist */
tmp_pref_elided = GNRC_RPL_SRH_COMPRI(rh->compr); if (_contains_multiple_of_my_addr(&ipv6->dst, rh, num_addr,
tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided; compri_addr_len)) {
tmp = ipv6->dst; return GNRC_IPV6_EXT_RH_ERROR;
for (uint8_t k = 0; k < n; k++) {
if (k == n - 1) {
tmp_pref_elided = GNRC_RPL_SRH_COMPRE(rh->compr);
tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided;
}
memcpy(&tmp.u8[tmp_pref_elided], &addr_vec[k * compri_addr_len], tmp_addr_len);
if (gnrc_netif_get_by_ipv6_addr(&tmp) != NULL) {
if (found && ((k - found_pos) > 1)) {
DEBUG("RPL SRH: found multiple addresses that belong to me - discard\n");
/* TODO send an ICMP Parameter Problem (Code 0) and discard the packet */
return GNRC_IPV6_EXT_RH_ERROR;
}
found_pos = k;
found = true;
}
} }
rh->seg_left = new_seg_left;
memcpy(&addr_vec[(i - 1) * compri_addr_len], &ipv6->dst.u8[pref_elided], addr_len); memcpy(&addr_vec[(current_pos - 1) * compri_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)), i); ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), current_pos);
ipv6->dst = addr; memcpy(&ipv6->dst, &addr, sizeof(ipv6->dst));
return GNRC_IPV6_EXT_RH_FORWARDED; return GNRC_IPV6_EXT_RH_FORWARDED;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment