|
|
|
@ -12,13 +12,86 @@
|
|
|
|
|
* @file |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
|
#include "net/gnrc/ipv6/netif.h" |
|
|
|
|
#include "net/gnrc/rpl/srh.h" |
|
|
|
|
|
|
|
|
|
ipv6_addr_t *gnrc_rpl_srh_next_hop(gnrc_rpl_srh_t *rh) |
|
|
|
|
#define ENABLE_DEBUG (0) |
|
|
|
|
#include "debug.h" |
|
|
|
|
|
|
|
|
|
#if ENABLE_DEBUG |
|
|
|
|
static char addr_str[IPV6_ADDR_MAX_STR_LEN]; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#define GNRC_RPL_SRH_PADDING(X) ((X & 0xF0) >> 4) |
|
|
|
|
#define GNRC_RPL_SRH_COMPRE(X) (X & 0x0F) |
|
|
|
|
#define GNRC_RPL_SRH_COMPRI(X) ((X & 0xF0) >> 4) |
|
|
|
|
|
|
|
|
|
int gnrc_rpl_srh_process(ipv6_hdr_t *ipv6, gnrc_rpl_srh_t *rh) |
|
|
|
|
{ |
|
|
|
|
/* TODO */ |
|
|
|
|
if (rh->seg_left == 0) { |
|
|
|
|
return EXT_RH_CODE_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t n = (((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; |
|
|
|
|
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); |
|
|
|
|
bool found = false; |
|
|
|
|
|
|
|
|
|
DEBUG("RPL SRH: %" PRIu8 " addresses in the routing header\n", n); |
|
|
|
|
|
|
|
|
|
if (rh->seg_left > n) { |
|
|
|
|
DEBUG("RPL SRH: number of segments left > number of addresses - discard\n"); |
|
|
|
|
/* TODO ICMP Parameter Problem - Code 0 */ |
|
|
|
|
return EXT_RH_CODE_ERROR; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rh->seg_left--; |
|
|
|
|
i = n - rh->seg_left; |
|
|
|
|
pref_elided = rh->seg_left ? 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); |
|
|
|
|
addr_len = sizeof(ipv6_addr_t) - pref_elided; |
|
|
|
|
memcpy(&addr.u8[pref_elided], &addr_vec[(i - 1) * compri_addr_len], addr_len); |
|
|
|
|
|
|
|
|
|
if (ipv6_addr_is_multicast(&ipv6->dst) || ipv6_addr_is_multicast(&addr)) { |
|
|
|
|
DEBUG("RPL SRH: found a multicast address - discard\n"); |
|
|
|
|
/* TODO discard the packet */ |
|
|
|
|
return EXT_RH_CODE_ERROR; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* check if multiple addresses of my interface exist */ |
|
|
|
|
tmp_pref_elided = GNRC_RPL_SRH_COMPRI(rh->compr); |
|
|
|
|
tmp_addr_len = sizeof(ipv6_addr_t) - tmp_pref_elided; |
|
|
|
|
tmp = ipv6->dst; |
|
|
|
|
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; |
|
|
|
|
tmp = ipv6->dst; |
|
|
|
|
} |
|
|
|
|
memcpy(&tmp.u8[tmp_pref_elided], &addr_vec[k * compri_addr_len], tmp_addr_len); |
|
|
|
|
if (gnrc_ipv6_netif_find_by_addr(NULL, &tmp) != KERNEL_PID_UNDEF) { |
|
|
|
|
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 EXT_RH_CODE_ERROR; |
|
|
|
|
} |
|
|
|
|
found_pos = k; |
|
|
|
|
found = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
memcpy(&addr_vec[(i - 1) * compri_addr_len], &ipv6->dst.u8[pref_elided], addr_len); |
|
|
|
|
|
|
|
|
|
DEBUG("RPL SRH: Next hop: %s at position %d\n", |
|
|
|
|
ipv6_addr_to_str(addr_str, &addr, sizeof(addr_str)), i); |
|
|
|
|
|
|
|
|
|
ipv6->dst = addr; |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
return EXT_RH_CODE_FORWARD; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** @} */ |
|
|
|
|