Skip to content
Snippets Groups Projects
Commit 5ca30b9b authored by Martine Lenders's avatar Martine Lenders
Browse files

gnrc_netif: add general IID to/from l2addr conversion functions

They are required to make GNRC's 6Lo IPHC implementation ready for
hardware addresses other than IEEE 802.15.4's.
parent b271b0d6
No related branches found
No related tags found
No related merge requests found
......@@ -44,6 +44,7 @@
#ifdef MODULE_GNRC_MAC
#include "net/gnrc/netif/mac.h"
#endif
#include "net/ndp.h"
#include "net/netdev.h"
#include "rmutex.h"
......
......@@ -415,6 +415,62 @@ static inline bool gnrc_netif_is_6lbr(const gnrc_netif_t *netif)
#define gnrc_netif_is_6lbr(netif) (false)
#endif
#if defined(MODULE_GNRC_IPV6) || defined(DOXYGEN)
/**
* @brief Converts a given hardware address to an IPv6 IID.
*
* @attention When the link-layer of the interface has link-layer addresses, and
* `NDEBUG` is not defined, the node fails with an assertion instead
* returning `-ENOTSUP`.
*
* @param[in] netif The network interface @p addr came from (either as
* gnrc_netif_t::l2addr or from a packet that came over
* it).
* @param[in] addr A hardware address.
* @param[in] addr_len Number of bytes in @p addr.
* @param[out] iid The IID based on gnrc_netif_t::device_type
*
* @return `sizeof(eui64_t)` on success.
* @return `-ENOTSUP`, when gnrc_netif_t::device_type of @p netif does not
* support IID conversion.
* @return `-EINVAL`, when @p addr_len is invalid for the
* gnrc_netif_t::device_type of @p netif.
*/
int gnrc_netif_ipv6_iid_from_addr(const gnrc_netif_t *netif,
const uint8_t *addr, size_t addr_len,
eui64_t *iid);
/**
* @brief Converts an IPv6 IID to a hardware address
*
* @pre `netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR`
* @pre @p iid was based on a hardware address
* @pre The number of bytes available at @p addr is less or equal to
* @ref GNRC_NETIF_L2ADDR_MAXLEN.
*
* @attention When `NDEBUG` is not defined, the node fails with an assertion
* instead of returning `-ENOTSUP`
*
* @param[in] netif The network interface @p iid came from (either because
* it is paset on gnrc_netif_t::l2addr or from a packet
* that came over it).
* @param[in] iid An IID based on gnrc_netif_t::device_type.
* @param[out] addr The hardware address. It is assumed that @p iid was
* based on a hardware address and that the available bytes
* in @p addr are less or equal to
* `GNRC_NETIF_L2ADDR_MAXLEN`.
*
* @return Length of resulting @p addr on success.
* @return `-ENOTSUP`, when gnrc_netif_t::device_type of @p netif does not
* support reverse IID conversion.
*/
int gnrc_netif_ipv6_iid_to_addr(const gnrc_netif_t *netif, const eui64_t *iid,
uint8_t *addr);
#else /* defined(MODULE_GNRC_IPV6) || defined(DOXYGEN) */
#define gnrc_netif_ipv6_iid_to_addr(netif, addr, addr_len, iid) (-ENOTSUP)
#define gnrc_netif_ipv6_iid_from_addr(netif, iid, addr) (-ENOTSUP)
#endif /* defined(MODULE_GNRC_IPV6) || defined(DOXYGEN) */
#ifdef __cplusplus
}
#endif
......
/*
* Copyright (C) 2018 Freie Universität Berlin
*
* 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
* directory for more details.
*/
/**
* @{
*
* @file
* @brief Functions that are based around a network interface's device type.
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#include <errno.h>
#include "log.h"
#include "net/gnrc/netif.h"
#include "net/ethernet.h"
#include "net/ieee802154.h"
#ifdef MODULE_GNRC_IPV6
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
static void _create_iid_from_short(const uint8_t *addr, size_t addr_len,
eui64_t *iid)
{
const unsigned offset = sizeof(eui64_t) - addr_len;
memset(iid->uint8, 0, sizeof(iid->uint8));
iid->uint8[3] = 0xff;
iid->uint8[4] = 0xfe;
memcpy(&iid->uint8[offset], addr, addr_len);
}
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
int gnrc_netif_ipv6_iid_from_addr(const gnrc_netif_t *netif,
const uint8_t *addr, size_t addr_len,
eui64_t *iid)
{
#if GNRC_NETIF_L2ADDR_MAXLEN > 0
if (netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR) {
switch (netif->device_type) {
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
if (addr_len == ETHERNET_ADDR_LEN) {
ethernet_get_iid(iid, (uint8_t *)addr);
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
if (ieee802154_get_iid(iid, addr, addr_len) != NULL) {
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
if (addr_len == sizeof(eui64_t)) {
memcpy(iid, addr, sizeof(eui64_t));
iid->uint8[0] ^= 0x02;
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* MODULE_NORDIC_SOFTDEVICE_BLE */
#if defined(MODULE_CC110X) || defined(MODULE_NRFMIN)
case NETDEV_TYPE_CC110X:
case NETDEV_TYPE_NRFMIN:
if (addr_len <= 3) {
_create_iid_from_short(addr, addr_len, iid);
return sizeof(eui64_t);
}
else {
return -EINVAL;
}
#endif /* defined(MODULE_CC110X) || defined(MODULE_NRFMIN) */
default:
(void)addr;
(void)addr_len;
(void)iid;
#ifdef DEVELHELP
LOG_ERROR("gnrc_netif: can't convert hardware address to IID "
"on interface %u\n", netif->pid);
#endif /* DEVELHELP */
assert(false);
break;
}
}
#endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */
return -ENOTSUP;
}
int gnrc_netif_ipv6_iid_to_addr(const gnrc_netif_t *netif, const eui64_t *iid,
uint8_t *addr)
{
assert(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR);
switch (netif->device_type) {
#if defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW)
case NETDEV_TYPE_ETHERNET:
case NETDEV_TYPE_ESP_NOW:
addr[0] = iid->uint8[0] ^ 0x02;
addr[1] = iid->uint8[1];
addr[2] = iid->uint8[2];
addr[3] = iid->uint8[5];
addr[4] = iid->uint8[6];
addr[5] = iid->uint8[7];
return ETHERNET_ADDR_LEN;
#endif /* defined(MODULE_NETDEV_ETH) || defined(MODULE_ESP_NOW) */
#if defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE)
case NETDEV_TYPE_IEEE802154:
/* assume address was based on EUI-64
* (see https://tools.ietf.org/html/rfc6775#section-5.2) */
memcpy(addr, iid, sizeof(eui64_t));
addr[0] ^= 0x02;
return sizeof(eui64_t);
#endif /* defined(MODULE_NETDEV_IEEE802154) || defined(MODULE_XBEE) */
#ifdef MODULE_NRFMIN
case NETDEV_TYPE_NRFMIN:
addr[0] = iid->uint8[6];
addr[1] = iid->uint8[7];
return sizeof(uint16_t);
#endif /* MODULE_NETDEV_IEEE802154 */
#ifdef MODULE_NORDIC_SOFTDEVICE_BLE
case NETDEV_TYPE_BLE:
memcpy(addr, iid, sizeof(eui64_t));
addr[0] ^= 0x02;
return sizeof(eui64_t);
#endif /* MODULE_NORDIC_SOFTDEVICE_BLE */
#ifdef MODULE_CC110X
case NETDEV_TYPE_CC110X:
addr[0] = iid->uint8[7];
return sizeof(uint8_t);
#endif /* MODULE_CC110X */
default:
(void)iid;
(void)addr;
#ifdef DEVELHELP
LOG_ERROR("gnrc_netif: can't convert IID to hardware address "
"on interface %u\n", netif->pid);
#endif /* DEVELHELP */
assert(false);
break;
}
return -ENOTSUP;
}
#endif /* MODULE_GNRC_IPV6 */
/** @} */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment