/* * 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. */ /** * @defgroup net_l2util Stack-independent helpers for IPv6 over X * @ingroup net * @brief This implements some common helper functions for IPv6 over X * implementations based on [network device types] * (@ref net_netdev_type). * * @attention If you add a new [network device type](@ref net_netdev_type) * have at least a look at the implementation of these functions. * @{ * * @file * @brief Link-layer helper function definitions * * @author Martine Lenders */ #ifndef NET_L2UTIL_H #define NET_L2UTIL_H #include #include "net/eui64.h" #include "net/ndp.h" #ifdef __cplusplus extern "C" { #endif #define L2UTIL_ADDR_MAX_LEN (8U) /**< maximum expected length for addresses */ /** * @brief Converts a given hardware address to an EUI-64. * * @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] dev_type The network device type of the device @p addr came from * (either because it is the configured address of the * device 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] eui64 The EUI-64 based on gnrc_netif_t::device_type * * @return `sizeof(eui64_t)` on success. * @return `-ENOTSUP`, when @p dev_type does not support EUI-64 conversion. * @return `-EINVAL`, when @p addr_len is invalid for the @p dev_type. */ int l2util_eui64_from_addr(int dev_type, const uint8_t *addr, size_t addr_len, eui64_t *eui64); /** * @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] dev_type The network device type of the device @p addr came from * (either because it is the configured address of the * device 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 @p dev_type does not support IID conversion. * @return `-EINVAL`, when @p addr_len is invalid for the @p dev_type. */ int l2util_ipv6_iid_from_addr(int dev_type, const uint8_t *addr, size_t addr_len, eui64_t *iid); /** * @brief Converts an IPv6 IID to a hardware address * * @pre @p iid was based on a hardware address * @pre The number of bytes available at @p addr is less or equal to * @ref L2UTIL_ADDR_MAX_LEN. * * @attention When `NDEBUG` is not defined, the node fails with an assertion * instead of returning `-ENOTSUP` * * @param[in] dev_type The network device type of the device the @p iid came * from (either because it is based on the configured * address of the device or from a packet that came over * it). * @param[in] iid An IID based on @p dev_type. * @param[out] addr The hardware address. It is assumed that @p iid was * based on a hardware address and that the available * number of bytes in @p addr are greater or equal to * @ref L2UTIL_ADDR_MAX_LEN. * * @return Length of resulting @p addr on success. * @return `-ENOTSUP`, when @p dev_type does not support reverse IID * conversion. */ int l2util_ipv6_iid_to_addr(int dev_type, const eui64_t *iid, uint8_t *addr); /** * @brief Derives the length of the link-layer address in an NDP link-layer * address option from that option's length field and the given device * type. * * @note If an RFC exists that specifies how IPv6 operates over a link-layer, * this function usually implements the section "Unicast Address * Mapping". * * @see [RFC 4861, section 4.6.1](https://tools.ietf.org/html/rfc4861#section-4.6.1) * * @attention When `NDEBUG` is not defined, the node fails with an assertion * instead of returning `-ENOTSUP` * * @param[in] dev_type The network device type of the device the @p opt came * over in an NDP message. * @param[in] opt An NDP source/target link-layer address option. * * @return Length of the link-layer address in @p opt on success * @return `-ENOTSUP`, when implementation does not know how to derive the * length of the link-layer address from @p opt's length field based * on @p dev_type. * @return `-EINVAL` if `opt->len` was an invalid value for the given * @p dev_type. */ int l2util_ndp_addr_len_from_l2ao(int dev_type, const ndp_opt_t *opt); /** * @brief Converts an IPv6 multicast address to a multicast address * of the respective link layer. * * @pre There is enough allocated space in @p l2_group for an address for a * device of type @p dev_type (e.g. 6 bytes for an ethernet address). * * @param[in] dev_type The network device type of the device @p l2_addr * should be generated for. * @param[in] ipv6_group An IPv6 multicast address. * @param[out] l2_group A link layer multicast address * * @return Length of @p l2_group in bytes * @return `-ENOTSUP` if link layer does not support multicast. */ int l2util_ipv6_group_to_l2_group(int dev_type, const ipv6_addr_t *ipv6_group, uint8_t *l2_group); /** * @brief Converts a hardware address to a human readable string. * * @details The format will be like `xx:xx:xx:xx` where `xx` are the bytes * of @p addr in hexadecimal representation. * * @pre `(out != NULL) && ((addr != NULL) || (addr_len == 0))` * @pre @p out **MUST** have allocated at least 3 * @p addr_len bytes. * * @param[in] addr A hardware address. * @param[in] addr_len Length of @p addr. * @param[out] out A string to store the output in. Must at least have * 3 * @p addr_len bytes allocated. * * @return @p out. */ char *l2util_addr_to_str(const uint8_t *addr, size_t addr_len, char *out); /** * @brief Parses a string of colon-separated hexadecimals to a hardware * address. * * @details The input format must be like `xx:xx:xx:xx` where `xx` will be the * bytes of @p addr in hexadecimal representation. * * @pre `(out != NULL)` * @pre @p out **MUST** have allocated at least * @ref GNRC_NETIF_L2ADDR_MAXLEN bytes. * * @param[in] str A string of colon-separated hexadecimals. * @param[out] out The resulting hardware address. Must at least have * @ref GNRC_NETIF_L2ADDR_MAXLEN bytes allocated. * * @return Actual length of @p out on success. * @return 0, on failure. */ size_t l2util_addr_from_str(const char *str, uint8_t *out); /** * @brief Checks if two l2 addresses are equal. * * @param[in] addr_a First hardware address. * @param[in] addr_a_len Length of first hardware address. * @param[in] addr_b Second hardware address. * @param[in] addr_b_len Length of second hardware address. * * @return true if the addresses match, false if not. */ static inline bool l2util_addr_equal(const uint8_t *addr_a, uint8_t addr_a_len, const uint8_t *addr_b, uint8_t addr_b_len) { if (addr_a_len != addr_b_len) { return false; } return memcmp(addr_a, addr_b, addr_a_len) == 0; } #ifdef __cplusplus } #endif #endif /* NET_L2UTIL_H */ /** @} */