From 7027519f28e9fc3d07018e59e024a39c0a471463 Mon Sep 17 00:00:00 2001 From: Martine Lenders <mlenders@inf.fu-berlin.de> Date: Wed, 11 Feb 2015 14:10:34 +0100 Subject: [PATCH] ng_ipv6: provide support for ng_netif --- Makefile.dep | 5 + sys/Makefile | 3 + sys/include/net/ng_ipv6.h | 10 +- sys/include/net/ng_ipv6/netif.h | 254 ++++++++++++ sys/net/crosslayer/ng_netif/ng_netif.c | 12 +- sys/net/network_layer/ng_ipv6/netif/Makefile | 3 + .../ng_ipv6/netif/ng_ipv6_netif.c | 382 ++++++++++++++++++ 7 files changed, 664 insertions(+), 5 deletions(-) create mode 100644 sys/include/net/ng_ipv6/netif.h create mode 100644 sys/net/network_layer/ng_ipv6/netif/Makefile create mode 100644 sys/net/network_layer/ng_ipv6/netif/ng_ipv6_netif.c diff --git a/Makefile.dep b/Makefile.dep index a0bb4b074b..ab88197f2b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -52,6 +52,11 @@ ifneq (,$(filter ng_ipv6_nc,$(USEMODULE))) USEMODULE += ng_ipv6_addr endif +ifneq (,$(filter ng_ipv6_netif,$(USEMODULE))) + USEMODULE += ng_ipv6_addr + USEMODULE += ng_netif +endif + ifneq (,$(filter ng_netbase,$(USEMODULE))) USEMODULE += ng_netapi USEMODULE += ng_netreg diff --git a/sys/Makefile b/sys/Makefile index 230a0296ac..8596ac3adc 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -68,6 +68,9 @@ endif ifneq (,$(filter ng_ipv6_nc,$(USEMODULE))) DIRS += net/network_layer/ng_ipv6/nc endif +ifneq (,$(filter ng_ipv6_netif,$(USEMODULE))) + DIRS += net/network_layer/ng_ipv6/netif +endif ifneq (,$(filter ng_netapi,$(USEMODULE))) DIRS += net/crosslayer/ng_netapi endif diff --git a/sys/include/net/ng_ipv6.h b/sys/include/net/ng_ipv6.h index 8990be2d35..0b0086918f 100644 --- a/sys/include/net/ng_ipv6.h +++ b/sys/include/net/ng_ipv6.h @@ -23,12 +23,20 @@ #define NG_IPV6_H_ #include "net/ng_ipv6/addr.h" +#include "net/ng_ipv6/netif.h" #ifdef __cplusplus extern "C" { #endif - +/** + * @brief Default maximum transition unit + * + * @see <a href="https://tools.ietf.org/html/rfc2460#section-5"> + * RFC 2460, section 5 + * </a> + */ +#define NG_IPV6_DEFAULT_MTU (1280) #ifdef __cplusplus } diff --git a/sys/include/net/ng_ipv6/netif.h b/sys/include/net/ng_ipv6/netif.h new file mode 100644 index 0000000000..2608cfa67f --- /dev/null +++ b/sys/include/net/ng_ipv6/netif.h @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2014 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * 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_ng_ipv6_netif IPv6 network interfaces + * @ingroup net_ng_ipv6 + * @brief IPv6 specific information on @ref net_ng_netif. + * @{ + * + * @file + * @brief Definitions for IPv6 specific information of network interfaces. + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ + +#ifndef NG_IPV6_NETIF_H_ +#define NG_IPV6_NETIF_H_ + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#include "kernel_macros.h" +#include "kernel_types.h" +#include "mutex.h" +#include "net/ng_ipv6/addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def NG_IPV6_NETIF_ADDR_NUMOF + * + * @brief Number of IPv6 addresses per interface. + */ +#ifndef NG_IPV6_NETIF_ADDR_NUMOF +#ifdef MODULE_NG_IPV6_ROUTER +#define NG_IPV6_NETIF_ADDR_NUMOF (5) /* router needs all-routers multicast address */ +#else +#define NG_IPV6_NETIF_ADDR_NUMOF (4) +#endif +#endif + +/** + * @{ + * @name Flags for a registered IPv6 address. + * @brief Needed primarily to identify addresses as either anycast or unicast. + * + * @see <a href="https://tools.ietf.org/html/rfc4291#section-2.6"> + * RFC 4291, section 2.6 + * </a> + */ +#define NG_IPV6_NETIF_FLAGS_UNICAST (0x00) /**< unicast address */ +#define NG_IPV6_NETIF_FLAGS_NON_UNICAST (0x01) /**< non-unicast address */ +/** + * @} + */ + +/** + * @brief Type to represent an IPv6 address registered to an interface. + */ +typedef struct { + ng_ipv6_addr_t addr; /**< The address data */ + uint8_t flags; /**< flags */ +} ng_ipv6_netif_addr_t; + +/** + * @brief Definition of IPv6 interface type. + */ +typedef struct { + ng_ipv6_netif_addr_t addrs[NG_IPV6_NETIF_ADDR_NUMOF]; /**< addresses registered + * to the interface */ + mutex_t mutex; /**< mutex for the interface */ + kernel_pid_t pid; /**< PID of the interface */ + uint16_t mtu; /**< Maximum Transmission Unit (MTU) of the interface */ +} ng_ipv6_netif_t; + +/** + * @brief Initializes the module. + */ +void ng_ipv6_netif_init(void); + +/** + * @brief Add interface to IPv6. + * + * @details This function will be called by @ref ng_netif_add(). + * + * @param[in] pid The PID to the interface. + */ +void ng_ipv6_netif_add(kernel_pid_t pid); + +/** + * @brief Remove interface from IPv6. + * + * @details This function will be called by @ref ng_netif_remove(). + * + * @param[in] pid The PID to the interface. + */ +void ng_ipv6_netif_remove(kernel_pid_t pid); + +/** + * @brief Get interface. + * + * @param[in] pid The PID to the interface. + * + * @return The interface describing structure, on success. + * @return NULL, if there is no interface with PID @p pid. + */ +ng_ipv6_netif_t *ng_ipv6_netif_get(kernel_pid_t pid); + +/** + * @brief Adds an address to an interface. + * + * @param[in] pid The PID to the interface. + * @param[in] addr An address you want to add to the interface. + * @param[in] anycast If @p addr should be an anycast address, @p anycast + * must be true. Otherwise set it false. + * If @p addr is a multicast address, @p anycast will be + * ignored. + * + * @see <a href="https://tools.ietf.org/html/rfc4291#section-2.6"> + * RFC 4291, section 2.6 + * </a> + * + * @return 0, on success. + * @return -EINVAL, if @p addr is NULL or unspecified address. + * @return -ENOENT, if @p pid is no interface. + * @return -ENOMEM, if there is no space left to store @p addr. + */ +int ng_ipv6_netif_add_addr(kernel_pid_t pid, const ng_ipv6_addr_t *addr, + bool anycast); + +/** + * @brief Remove an address from the interface. + * + * @param[in] pid The PID to the interface. + * @param[in] addr An address you want to remove from interface. + */ +void ng_ipv6_netif_remove_addr(kernel_pid_t pid, ng_ipv6_addr_t *addr); + +/** + * @brief Removes all addresses from the interface. + * + * @param[in] pid The PID to the interface. + */ +void ng_ipv6_netif_reset_addr(kernel_pid_t pid); + +/** + * @brief Searches for an address on all interfaces. + * + * @param[out] out The reference to the address on the interface. + * @param[in] addr The address you want to search for. + * + * @return The PID to the interface the address is registered to. + * @return KERNEL_PID_UNDEF, if the address can not be found on any interface. + */ +kernel_pid_t ng_ipv6_netif_find_by_addr(ng_ipv6_addr_t **out, + const ng_ipv6_addr_t *addr); + +/** + * @brief Searches for an address on an interface. + * + * @param[in] pid The PID to the interface. + * @param[in] addr The address you want to search for. + * + * @return The reference to the address on the interface. + * @return NULL, if the address can not be found on the interface. + * @return NULL, if @p pid is no interface. + */ +ng_ipv6_addr_t *ng_ipv6_netif_find_addr(kernel_pid_t pid, + const ng_ipv6_addr_t *addr); + +/** + * @brief Searches for the first address matching a prefix best on all + * interfaces. + * + * @param[out] out The reference to the found address on the interface. + * @param[in] prefix The prefix you want to search for. + * + * @return The PID to the interface the address is registered to. + * @return KERNEL_PID_UNDEF, if no matching address can not be found on any + * interface. + */ +kernel_pid_t ng_ipv6_netif_find_by_prefix(ng_ipv6_addr_t **out, + const ng_ipv6_addr_t *prefix); + +/** + * @brief Searches for the first address matching a prefix best on an + * interfaces. + * + * @param[in] pid The PID to the interface. + * @param[in] prefix The prefix you want to search for. + * + * @return The reference to the found address on the interface. + * @return NULL, if no matching address can be found on the interface. + * @return NULL, if @p pid is no interface. + */ +ng_ipv6_addr_t *ng_ipv6_netif_match_prefix(kernel_pid_t pid, + const ng_ipv6_addr_t *prefix); + +/** + * @brief Searches for the best address on an interface usable as a + * source address for a given destination address. + * + * @param[in] pid The PID to the interface. + * @param[in] dest The destination address you want to find a destination + * address for. + * + * @return The reference to the found address on the interface. + * @return NULL, if no matching address can be found on the interface. + * @return NULL, if @p pid is no interface. + */ +ng_ipv6_addr_t *ng_ipv6_netif_find_best_src_addr(kernel_pid_t pid, const ng_ipv6_addr_t *dest); + +/** + * @brief Checks if an address is non-unicast. + * + * @details This only works with addresses you retrieved via the following + * functions: + * + * * ng_ipv6_find_addr() + * * ng_ipv6_find_addr_local() + * * ng_ipv6_find_prefix_match() + * * ng_ipv6_find_prefix_match_local() + * * ng_ipv6_find_best_src_address + * + * The behaviour for other addresses is undefined. + * + * @param[in] addr The address you want to check. + * + * @return true, if address is anycast or multicast. + * @return false, if address is unicast. + */ +static inline bool ng_ipv6_netif_addr_is_non_unicast(const ng_ipv6_addr_t *addr) +{ + return (bool)(container_of(addr, ng_ipv6_netif_addr_t, addr)->flags & + NG_IPV6_NETIF_FLAGS_NON_UNICAST); + +} + +#ifdef __cplusplus +} +#endif + +#endif /* NETIF_H_ */ +/** + * @} + */ diff --git a/sys/net/crosslayer/ng_netif/ng_netif.c b/sys/net/crosslayer/ng_netif/ng_netif.c index fe70a0381e..a42a26867d 100644 --- a/sys/net/crosslayer/ng_netif/ng_netif.c +++ b/sys/net/crosslayer/ng_netif/ng_netif.c @@ -18,12 +18,16 @@ #include "kernel_types.h" #include "net/ng_netif.h" +#ifdef MODULE_NG_IPV6_NETIF +#include "net/ng_ipv6/netif.h" +#endif + static ng_netif_handler_t if_handler[] = { -#ifdef MODULE_NG_IPV6 - { ipv6_if_add, ipv6_if_remove }, +#ifdef MODULE_NG_IPV6_NETIF + { ng_ipv6_netif_add, ng_ipv6_netif_remove }, #endif - /* #ifdef MODULE_NG_IPV4 - * { ipv4_if_add, ipv4_if_remove }, + /* #ifdef MODULE_NG_IPV4_NETIF + * { ipv4_netif_add, ipv4_netif_remove }, * #endif ... you get the idea */ { NULL, NULL } diff --git a/sys/net/network_layer/ng_ipv6/netif/Makefile b/sys/net/network_layer/ng_ipv6/netif/Makefile new file mode 100644 index 0000000000..70b24d5231 --- /dev/null +++ b/sys/net/network_layer/ng_ipv6/netif/Makefile @@ -0,0 +1,3 @@ +MODULE = ng_ipv6_netif + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/network_layer/ng_ipv6/netif/ng_ipv6_netif.c b/sys/net/network_layer/ng_ipv6/netif/ng_ipv6_netif.c new file mode 100644 index 0000000000..2add7223e0 --- /dev/null +++ b/sys/net/network_layer/ng_ipv6/netif/ng_ipv6_netif.c @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2014 Martin Lenders <mlenders@inf.fu-berlin.de> + * + * 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. + */ + +/** + * @addtogroup sys_net_ng_ipv6_netif + * @{ + * + * @file + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ + +#include <errno.h> +#include <string.h> + +#include "kernel_types.h" +#include "mutex.h" +#include "net/ng_ipv6.h" +#include "net/ng_ipv6/addr.h" +#include "net/ng_netif.h" + +#include "net/ng_ipv6/netif.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static ng_ipv6_netif_t ipv6_ifs[NG_NETIF_NUMOF]; + +#if ENABLE_DEBUG +static char addr_str[NG_IPV6_ADDR_MAX_STR_LEN]; +#endif + +static int _add_addr_to_entry(ng_ipv6_netif_t *entry, const ng_ipv6_addr_t *addr, + bool anycast) +{ + for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) { + if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { + return 0; + } + + if (ng_ipv6_addr_is_unspecified(&(entry->addrs[i].addr))) { + DEBUG("Add %s to interface %" PRIkernel_pid "\n", + ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + entry->pid); + memcpy(&(entry->addrs[i].addr), addr, sizeof(ng_ipv6_addr_t)); + + if (anycast || ng_ipv6_addr_is_multicast(addr)) { + entry->addrs[i].flags = NG_IPV6_NETIF_FLAGS_NON_UNICAST; + } + else { + entry->addrs[i].flags = NG_IPV6_NETIF_FLAGS_UNICAST; + } + + return 0; + } + } + + return -ENOMEM; +} + +static void _reset_addr_from_entry(ng_ipv6_netif_t *entry) +{ + DEBUG("Reset IPv6 addresses on interface %" PRIkernel_pid "\n", entry->pid); + memset(entry->addrs, 0, sizeof(entry->addrs)); +} + +void ng_ipv6_netif_init(void) +{ + for (int i = 0; i < NG_NETIF_NUMOF; i++) { + mutex_init(&(ipv6_ifs[i].mutex)); + mutex_lock(&(ipv6_ifs[i].mutex)); + _reset_addr_from_entry(&ipv6_ifs[i]); + ipv6_ifs[i].pid = KERNEL_PID_UNDEF; + mutex_unlock(&(ipv6_ifs[i].mutex)); + } +} + +void ng_ipv6_netif_add(kernel_pid_t pid) +{ + for (int i = 0; i < NG_NETIF_NUMOF; i++) { + if (ipv6_ifs[i].pid == pid) { + return; /* prevent duplicates */ + } + else if (ipv6_ifs[i].pid == KERNEL_PID_UNDEF) { + ng_ipv6_addr_t addr = NG_IPV6_ADDR_ALL_NODES_LINK_LOCAL; + mutex_lock(&ipv6_ifs[i].mutex); + + DEBUG("Add IPv6 interface %" PRIkernel_pid " (i = %d)\n", pid, i); + ipv6_ifs[i].pid = pid; + DEBUG(" * pid = %" PRIkernel_pid "\n", ipv6_ifs[i].pid); + ipv6_ifs[i].mtu = NG_IPV6_DEFAULT_MTU; + DEBUG(" * mtu = %d\n", ipv6_ifs[i].mtu); + + _add_addr_to_entry(&ipv6_ifs[i], &addr, 0); + + mutex_unlock(&ipv6_ifs[i].mutex); + + return; + } + } + + DEBUG("Could not add %" PRIkernel_pid " to IPv6: No space left.\n", pid); +} + +void ng_ipv6_netif_remove(kernel_pid_t pid) +{ + ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid); + + if (entry == NULL) { + return; + } + + mutex_lock(&entry->mutex); + + _reset_addr_from_entry(entry); + DEBUG("Remove IPv6 interface %" PRIkernel_pid "\n", pid); + entry->pid = KERNEL_PID_UNDEF; + + mutex_unlock(&entry->mutex); +} + +ng_ipv6_netif_t *ng_ipv6_netif_get(kernel_pid_t pid) +{ + for (int i = 0; i < NG_NETIF_NUMOF; i++) { + if (ipv6_ifs[i].pid == pid) { + DEBUG("Get IPv6 interface %" PRIkernel_pid " (%p, i = %d)\n", pid, + (void *)(&(ipv6_ifs[i])), i); + return &(ipv6_ifs[i]); + } + } + + return NULL; +} + +int ng_ipv6_netif_add_addr(kernel_pid_t pid, const ng_ipv6_addr_t *addr, + bool anycast) +{ + ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid); + int res; + + if (entry == NULL) { + return -ENOENT; + } + + if ((addr == NULL) || (ng_ipv6_addr_is_unspecified(addr))) { + return -EINVAL; + } + + mutex_lock(&entry->mutex); + + res = _add_addr_to_entry(entry, addr, anycast); + + mutex_unlock(&entry->mutex); + + return res; +} + +void ng_ipv6_netif_remove_addr(kernel_pid_t pid, ng_ipv6_addr_t *addr) +{ + ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid); + + if (entry == NULL) { + return; + } + + mutex_lock(&entry->mutex); + + for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) { + if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { + DEBUG("Remove %s to interface %" PRIkernel_pid "\n", + ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), pid); + ng_ipv6_addr_set_unspecified(&(entry->addrs[i].addr)); + entry->addrs[i].flags = 0; + + mutex_unlock(&entry->mutex); + return; + } + } + + mutex_unlock(&entry->mutex); +} + +void ng_ipv6_netif_reset_addr(kernel_pid_t pid) +{ + ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid); + + if (entry == NULL) { + return; + } + + mutex_lock(&entry->mutex); + + _reset_addr_from_entry(entry); + + mutex_unlock(&entry->mutex); +} + +kernel_pid_t ng_ipv6_netif_find_by_addr(ng_ipv6_addr_t **out, const ng_ipv6_addr_t *addr) +{ + for (int i = 0; i < NG_NETIF_NUMOF; i++) { + if (out != NULL) { + *out = ng_ipv6_netif_find_addr(ipv6_ifs[i].pid, addr); + + if (*out != NULL) { + DEBUG("Found %s on interface %" PRIkernel_pid "\n", + ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)), + ipv6_ifs[i].pid); + return ipv6_ifs[i].pid; + } + } + else { + if (ng_ipv6_netif_find_addr(ipv6_ifs[i].pid, addr) != NULL) { + DEBUG("Found %s on interface %" PRIkernel_pid "\n", + ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)), + ipv6_ifs[i].pid); + return ipv6_ifs[i].pid; + } + } + } + + if (out != NULL) { + *out = NULL; + } + + return KERNEL_PID_UNDEF; +} + +ng_ipv6_addr_t *ng_ipv6_netif_find_addr(kernel_pid_t pid, const ng_ipv6_addr_t *addr) +{ + ng_ipv6_netif_t *entry = ng_ipv6_netif_get(pid); + + if (entry == NULL) { + return NULL; + } + + mutex_lock(&entry->mutex); + + for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) { + if (ng_ipv6_addr_equal(&(entry->addrs[i].addr), addr)) { + mutex_unlock(&entry->mutex); + DEBUG("Found %s on interface %" PRIkernel_pid "\n", + ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + pid); + return &(entry->addrs[i].addr); + } + } + + mutex_unlock(&entry->mutex); + + return NULL; +} + +static uint8_t _find_by_prefix_unsafe(ng_ipv6_addr_t **res, ng_ipv6_netif_t *iface, + const ng_ipv6_addr_t *addr, bool only_unicast) +{ + uint8_t best_match = 0; + + for (int i = 0; i < NG_IPV6_NETIF_ADDR_NUMOF; i++) { + uint8_t match; + + if ((only_unicast && + ng_ipv6_netif_addr_is_non_unicast(&(iface->addrs[i].addr))) || + ng_ipv6_addr_is_unspecified(&(iface->addrs[i].addr))) { + continue; + } + + match = ng_ipv6_addr_match_prefix(&(iface->addrs[i].addr), addr); + + if (match > best_match) { + if (res != NULL) { + *res = &(iface->addrs[i].addr); + } + + best_match = match; + } + } + +#if ENABLE_DEBUG + + if (*res != NULL) { + DEBUG("Found %s on interface %" PRIkernel_pid " matching ", + ng_ipv6_addr_to_str(addr_str, *res, sizeof(addr_str)), + iface->pid); + DEBUG("%s by %" PRIu8 " bits (used as source address = %s)\n", + ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + best_match, + (only_unicast) ? "true" : "false"); + } + else { + DEBUG("Did not found any address on interface %" PRIkernel_pid + " matching %s (used as source address = %s)\n", + iface->pid, + ng_ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), + (only_unicast) ? "true" : "false"); + } + +#endif + return best_match; +} + +kernel_pid_t ng_ipv6_netif_find_by_prefix(ng_ipv6_addr_t **out, const ng_ipv6_addr_t *prefix) +{ + uint8_t best_match = 0; + ng_ipv6_addr_t *tmp_res = NULL; + kernel_pid_t res = KERNEL_PID_UNDEF; + + for (int i = 0; i < NG_NETIF_NUMOF; i++) { + uint8_t match; + + mutex_lock(&(ipv6_ifs[i].mutex)); + + match = _find_by_prefix_unsafe(&tmp_res, ipv6_ifs + i, prefix, false); + + if (match > best_match) { + if (out != NULL) { + *out = tmp_res; + } + + res = ipv6_ifs[i].pid; + best_match = match; + } + + mutex_unlock(&(ipv6_ifs[i].mutex)); + } + +#if ENABLE_DEBUG + + if (res != KERNEL_PID_UNDEF) { + DEBUG("Found %s on interface %" PRIkernel_pid " globally matching ", + ng_ipv6_addr_to_str(addr_str, *out, sizeof(addr_str)), + res); + DEBUG("%s by %" PRIu8 " bits\n", + ng_ipv6_addr_to_str(addr_str, prefix, sizeof(addr_str)), + best_match); + } + else { + DEBUG("Did not found any address globally matching %s\n", + ng_ipv6_addr_to_str(addr_str, prefix, sizeof(addr_str))); + } + +#endif + + return res; +} + +static ng_ipv6_addr_t *_match_prefix(kernel_pid_t pid, const ng_ipv6_addr_t *addr, + bool only_unicast) +{ + ng_ipv6_addr_t *res = NULL; + ng_ipv6_netif_t *iface = ng_ipv6_netif_get(pid); + + mutex_lock(&(iface->mutex)); + + if (_find_by_prefix_unsafe(&res, iface, addr, only_unicast) > 0) { + mutex_unlock(&(iface->mutex)); + return res; + } + + mutex_unlock(&(iface->mutex)); + + return NULL; +} + +ng_ipv6_addr_t *ng_ipv6_netif_match_prefix(kernel_pid_t pid, + const ng_ipv6_addr_t *prefix) +{ + return _match_prefix(pid, prefix, false); +} + +ng_ipv6_addr_t *ng_ipv6_netif_find_best_src_addr(kernel_pid_t pid, const ng_ipv6_addr_t *dest) +{ + return _match_prefix(pid, dest, true); +} + +/** + * @} + */ -- GitLab