From 55adbee48808bda975dd5ee420c605bbddf4c94c Mon Sep 17 00:00:00 2001 From: Martine Lenders <mail@martine-lenders.eu> Date: Thu, 22 Mar 2018 19:01:02 +0000 Subject: [PATCH] gnrc_ipv6_nib: add full RFC4862 DAD support Parts of [RFC4862] were already implemented when NDP via the NIB was first implemented. This change just includes the DAD portion of [RFC4862]. This should be enough to make RIOT fully RFC4862 compliant. [RFC4862]: https://tools.ietf.org/html/rfc4862 --- sys/include/net/gnrc/ipv6/nib.h | 20 ++ sys/include/net/gnrc/netif/ipv6.h | 5 +- sys/net/gnrc/netif/gnrc_netif.c | 13 +- sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c | 3 +- .../gnrc/network_layer/ipv6/nib/_nib-slaac.c | 205 ++++++++++++++++++ .../gnrc/network_layer/ipv6/nib/_nib-slaac.h | 83 +++++++ sys/net/gnrc/network_layer/ipv6/nib/nib.c | 114 ++++------ 7 files changed, 367 insertions(+), 76 deletions(-) create mode 100644 sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c create mode 100644 sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h diff --git a/sys/include/net/gnrc/ipv6/nib.h b/sys/include/net/gnrc/ipv6/nib.h index a119d4d6ca..facc9e6ccf 100644 --- a/sys/include/net/gnrc/ipv6/nib.h +++ b/sys/include/net/gnrc/ipv6/nib.h @@ -202,6 +202,26 @@ extern "C" { * @note Only handled with @ref GNRC_IPV6_NIB_CONF_ROUTER != 0 */ #define GNRC_IPV6_NIB_ROUTE_TIMEOUT (0x4fd0U) + +/** + * @brief Perform DAD event. + * + * This message type is for performing DAD for a given address. The expected + * message context is a TENTATIVE IPv6 address. + * + * @note Only handled with @ref GNRC_IPV6_NIB_CONF_SLAAC != 0 + */ +#define GNRC_IPV6_NIB_DAD (0x4fd1U) + +/** + * @brief Validate a tentative address event. + * + * Moves a TENTATIVE address to VALID state. The expected message context is a + * TENTATIVE IPv6 address. + * + * @note Only handled with @ref GNRC_IPV6_NIB_CONF_SLAAC != 0 + */ +#define GNRC_IPV6_NIB_VALID_ADDR (0x4fd2U) /** @} */ /** diff --git a/sys/include/net/gnrc/netif/ipv6.h b/sys/include/net/gnrc/netif/ipv6.h index cc77981d08..94edf3b592 100644 --- a/sys/include/net/gnrc/netif/ipv6.h +++ b/sys/include/net/gnrc/netif/ipv6.h @@ -151,13 +151,14 @@ typedef struct { * and @ref net_gnrc_ipv6_nib "NIB" */ evtimer_msg_event_t search_rtr; -#if GNRC_IPV6_NIB_CONF_6LN || DOXYGEN +#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC || DOXYGEN /** * @brief Timers for address re-registration * * @note Only available with module @ref net_gnrc_ipv6 "gnrc_ipv6" and * @ref net_gnrc_ipv6_nib "NIB" and if - * @ref GNRC_IPV6_NIB_CONF_6LN != 0 + * @ref GNRC_IPV6_NIB_CONF_6LN != 0 or + * @ref GNRC_IPV6_NIB_CONF_SLAAC != 0 * @note Might also be usable in the later default SLAAC implementation * for NS retransmission timers. */ diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 79f2c23944..e507a3f9fb 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -21,6 +21,7 @@ #include "net/gnrc.h" #ifdef MODULE_GNRC_IPV6_NIB #include "net/gnrc/ipv6/nib.h" +#include "net/gnrc/ipv6.h" #endif /* MODULE_GNRC_IPV6_NIB */ #ifdef MODULE_NETSTATS_IPV6 #include "net/netstats.h" @@ -589,8 +590,13 @@ int gnrc_netif_ipv6_addr_add_internal(gnrc_netif_t *netif, } } #if GNRC_IPV6_NIB_CONF_SLAAC - else { - /* TODO: send out NS to solicited nodes for DAD probing */ + else if (!gnrc_netif_is_6ln(netif)) { + /* cast to remove const qualifier (will still be used NIB internally as + * const) */ + msg_t msg = { .type = GNRC_IPV6_NIB_DAD, + .content = { .ptr = &netif->ipv6.addrs[idx] } }; + + msg_send(&msg, gnrc_ipv6_pid); } #endif #else @@ -961,8 +967,7 @@ static int _create_candidate_set(const gnrc_netif_t *netif, * be included in a candidate set." */ if ((netif->ipv6.addrs_flags[i] == 0) || - (gnrc_netif_ipv6_addr_get_state(netif, i) == - GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE)) { + gnrc_netif_ipv6_addr_dad_trans(netif, i)) { continue; } /* Check if we only want link local addresses */ diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c index 0daddc2169..68fffe6d38 100644 --- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c +++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c @@ -297,7 +297,8 @@ static void *_event_loop(void *args) case GNRC_IPV6_NIB_RTR_TIMEOUT: case GNRC_IPV6_NIB_RECALC_REACH_TIME: case GNRC_IPV6_NIB_REREG_ADDRESS: - case GNRC_IPV6_NIB_ROUTE_TIMEOUT: + case GNRC_IPV6_NIB_DAD: + case GNRC_IPV6_NIB_VALID_ADDR: DEBUG("ipv6: NIB timer event received\n"); gnrc_ipv6_nib_handle_timer_event(msg.content.ptr, msg.type); break; diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c new file mode 100644 index 0000000000..f34f88c5ce --- /dev/null +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -0,0 +1,205 @@ +/* + * 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 + * @author Martine Lenders <m.lenders@fu-berlin.de> + */ + +#include <stdbool.h> + +#include "luid.h" +#include "net/gnrc/netif/internal.h" + +#include "_nib-6ln.h" +#include "_nib-arsm.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static char addr_str[IPV6_ADDR_MAX_STR_LEN]; + +#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC +void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len) +{ + ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; + int idx; + uint8_t flags = GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; + + DEBUG("nib: add address based on %s/%u automatically to interface %u\n", + ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), + pfx_len, netif->pid); +#if GNRC_IPV6_NIB_CONF_6LN + bool new_address = false; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]); + ipv6_addr_init_prefix(&addr, pfx, pfx_len); + if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) { + if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len, + flags)) < 0) { + DEBUG("nib: Can't add link-local address on interface %u\n", + netif->pid); + return; + } +#if GNRC_IPV6_NIB_CONF_6LN + new_address = true; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ + } + +#if GNRC_IPV6_NIB_CONF_6LN + /* mark link-local addresses as valid on 6LN */ + if (gnrc_netif_is_6ln(netif) && ipv6_addr_is_link_local(pfx)) { + /* don't do this beforehand or risk a deadlock: + * - gnrc_netif_ipv6_addr_add_internal() adds VALID (i.e. manually configured + * addresses to the prefix list locking the NIB's mutex which is already + * locked here) */ + netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK; + netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID; + } +#endif /* GNRC_IPV6_NIB_CONF_6LN */ +#if GNRC_IPV6_NIB_CONF_6LN + if (new_address && gnrc_netif_is_6ln(netif) && + !gnrc_netif_is_6lbr(netif)) { + _handle_rereg_address(&netif->ipv6.addrs[idx]); + } +#else /* GNRC_IPV6_NIB_CONF_6LN */ + (void)idx; +#endif /* GNRC_IPV6_NIB_CONF_6LN */ +} +#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ + +#if GNRC_IPV6_NIB_CONF_SLAAC +static bool _try_l2addr_reconfiguration(gnrc_netif_t *netif) +{ + uint8_t hwaddr[GNRC_NETIF_L2ADDR_MAXLEN]; + uint16_t hwaddr_len; + + if (gnrc_netapi_get(netif->pid, NETOPT_SRC_LEN, 0, &hwaddr_len, + sizeof(hwaddr_len)) < 0) { + return false; + } + luid_get(hwaddr, hwaddr_len); +#if GNRC_IPV6_NIB_CONF_6LN + if (hwaddr_len == IEEE802154_LONG_ADDRESS_LEN) { + if (gnrc_netapi_set(netif->pid, NETOPT_ADDRESS_LONG, 0, hwaddr, + hwaddr_len) < 0) { + return false; + } + } + else +#endif + if (gnrc_netapi_set(netif->pid, NETOPT_ADDRESS, 0, hwaddr, + hwaddr_len) < 0) { + return false; + } + return true; +} + +static bool _try_addr_reconfiguration(gnrc_netif_t *netif) +{ + eui64_t orig_iid; + bool remove_old = false, hwaddr_reconf; + + if (gnrc_netif_ipv6_get_iid(netif, &orig_iid) == 0) { + remove_old = true; + } + /* seize netif to netif thread since _try_l2addr_reconfiguration uses + * gnrc_netapi_get()/gnrc_netapi_set(). Since these are synchronous this is + * safe */ + gnrc_netif_release(netif); + /* reacquire netif for IPv6 address reconfiguraton */ + hwaddr_reconf = _try_l2addr_reconfiguration(netif); + gnrc_netif_acquire(netif); + if (hwaddr_reconf) { + if (remove_old) { + for (unsigned i = 0; i < GNRC_NETIF_IPV6_ADDRS_NUMOF; i++) { + ipv6_addr_t *addr = &netif->ipv6.addrs[i]; + if (addr->u64[1].u64 == orig_iid.uint64.u64) { + gnrc_netif_ipv6_addr_remove_internal(netif, addr); + } + } + } + DEBUG("nib: Changed hardware address, due to DAD\n"); + _auto_configure_addr(netif, &ipv6_addr_link_local_prefix, 64U); + } + return hwaddr_reconf; +} + +void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr) +{ + DEBUG("nib: other node has TENTATIVE address %s assigned " + "=> removing that address\n", + ipv6_addr_to_str(addr_str, addr, sizeof(addr_str))); + gnrc_netif_ipv6_addr_remove_internal(netif, addr); + + if (!ipv6_addr_is_link_local(addr) || + !_try_addr_reconfiguration(netif)) { + /* Cannot use target address as personal address and can + * not change hardware address to retry SLAAC => use purely + * DHCPv6 instead */ + /* TODO: implement IA_NA for DHCPv6 */ + /* then => tgt_netif->aac_mode = GNRC_NETIF_AAC_DHCP; */ + DEBUG("nib: would set interface %i to DHCPv6, " + "but is not implemented yet", netif->pid); + } +} + +static int _get_netif_state(gnrc_netif_t **netif, const ipv6_addr_t *addr) +{ + *netif = gnrc_netif_get_by_ipv6_addr(addr); + if (*netif != NULL) { + int idx; + + gnrc_netif_acquire(*netif); + idx = gnrc_netif_ipv6_addr_idx(*netif, addr); + return ((idx >= 0) && gnrc_netif_ipv6_addr_dad_trans(*netif, idx)) ? + idx : -1; + } + return -1; +} + +void _handle_dad(const ipv6_addr_t *addr) +{ + ipv6_addr_t sol_nodes; + gnrc_netif_t *netif = NULL; + int idx = _get_netif_state(&netif, addr); + if (idx >= 0) { + ipv6_addr_set_solicited_nodes(&sol_nodes, addr); + _snd_ns(addr, netif, &ipv6_addr_unspecified, &sol_nodes); + _evtimer_add((void *)addr, GNRC_IPV6_NIB_VALID_ADDR, + &netif->ipv6.addrs_timers[idx], + netif->ipv6.retrans_time); + } + if (netif != NULL) { + /* was acquired in `_get_netif_state()` */ + gnrc_netif_release(netif); + } +} + +void _handle_valid_addr(const ipv6_addr_t *addr) +{ + gnrc_netif_t *netif = NULL; + int idx = _get_netif_state(&netif, addr); + + if (idx >= 0) { + netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK; + netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID; + } + if (netif != NULL) { + /* was acquired in `_get_netif_state()` */ + gnrc_netif_release(netif); + } +} +#else /* GNRC_IPV6_NIB_CONF_SLAAC */ +typedef int dont_be_pedantic; +#endif /* GNRC_IPV6_NIB_CONF_SLAAC */ + +/** @} */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h new file mode 100644 index 0000000000..76264c82ce --- /dev/null +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/** + * @ingroup net_gnrc_ipv6_nib + * @brief + * @{ + * + * @file + * @brief Definions related to SLAAC functionality of the NIB + * @see @ref GNRC_IPV6_NIB_CONF_SLAAC + * @internal + * + * @author Martine Lenders <m.lenders@fu-berlin.de> + */ +#ifndef PRIV_NIB_SLAAC_H +#define PRIV_NIB_SLAAC_H + +#include <stdint.h> + +#include "net/gnrc/ipv6/nib/conf.h" +#include "net/gnrc/netif.h" +#include "net/ipv6/addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC || defined(DOXYGEN) +/** + * @brief Auto-configures an address from a given prefix + * + * @param[in] netif The network interface the address should be added to. + * @param[in] pfx The prefix for the address. + * @param[in] pfx_len Length of @p pfx in bits. + */ +void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, + uint8_t pfx_len); +#else /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ +#define _auto_configure_addr(netif, pfx, pfx_len) \ + (void)netif; (void)pfx; (void)pfx_len; +#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ +#if GNRC_IPV6_NIB_CONF_SLAAC || defined(DOXYGE) +/** + * @brief Removes a tentative address from the interface and tries to + * reconfigure a new address + * + * @param[in] netif The network interface the address is to be removed from. + * @param[in] addr The address to remove. + */ +void _remove_tentative_addr(gnrc_netif_t *netif, const ipv6_addr_t *addr); + +/** + * @brief Handle @ref GNRC_IPV6_NIB_DAD event + * + * @param[in] addr A TENTATIVE address. + */ +void _handle_dad(const ipv6_addr_t *addr); + +/** + * @brief Handle @ref GNRC_IPV6_NIB_VALID_ADDR event + * + * @param[in] addr A TENTATIVE address. + */ +void _handle_valid_addr(const ipv6_addr_t *addr); +#else /* GNRC_IPV6_NIB_CONF_SLAAC */ +#define _remove_tentative_addr(netif, addr) \ + (void)netif; (void)addr +#define _handle_dad(addr) (void)addr +#define _handle_valid_addr(addr) (void)addr +#endif /* GNRC_IPV6_NIB_CONF_SLAAC */ + +#ifdef __cplusplus +} +#endif + +#endif /* PRIV_NIB_SLAAC_H */ +/** @} */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index 918e0707bd..dab240bdb0 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -32,6 +32,7 @@ #include "_nib-router.h" #include "_nib-6ln.h" #include "_nib-6lr.h" +#include "_nib-slaac.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -67,14 +68,6 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif, static void _handle_pfx_timeout(_nib_offl_entry_t *pfx); static void _handle_rtr_timeout(_nib_dr_entry_t *router); static void _handle_snd_na(gnrc_pktsnip_t *pkt); -#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC -static void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t pfx_len); -#else /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ -#define _auto_configure_addr(netif, pfx, pfx_len) (void)netif; \ - (void)pfx; \ - (void)pfx_len -#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ /* needs to be exported for 6LN's ARO handling */ void _handle_search_rtr(gnrc_netif_t *netif); /** @} */ @@ -356,6 +349,12 @@ void gnrc_ipv6_nib_handle_timer_event(void *ctx, uint16_t type) _handle_rereg_address(ctx); break; #endif /* GNRC_IPV6_NIB_CONF_6LN */ + case GNRC_IPV6_NIB_DAD: + _handle_dad(ctx); + break; + case GNRC_IPV6_NIB_VALID_ADDR: + _handle_valid_addr(ctx); + break; default: break; } @@ -838,9 +837,30 @@ static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, DEBUG(" - Destination address: %s\n", ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); #if GNRC_IPV6_NIB_CONF_SLAAC - /* TODO SLAAC behavior */ + gnrc_netif_t *tgt_netif = gnrc_netif_get_by_ipv6_addr(&nbr_sol->tgt); + + if (tgt_netif != NULL) { + int idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_sol->tgt); + + if (gnrc_netif_ipv6_addr_dad_trans(tgt_netif, idx)) { + if (!ipv6_addr_is_unspecified(&ipv6->src)) { + /* (see https://tools.ietf.org/html/rfc4862#section-5.4.3) */ + DEBUG("nib: Neighbor is performing AR, but target address is " + "still TENTATIVE for us => Ignoring NS\n"); + return; + } + /* cancel validation timer */ + evtimer_del(&_nib_evtimer, + &tgt_netif->ipv6.addrs_timers[idx].event); + _remove_tentative_addr(tgt_netif, &nbr_sol->tgt); + return; + } + } #endif /* GNRC_IPV6_NIB_CONF_SLAAC */ - if (!ipv6_addr_is_unspecified(&ipv6->src)) { + if (ipv6_addr_is_unspecified(&ipv6->src)) { + gnrc_ndp_nbr_adv_send(&nbr_sol->tgt, netif, &ipv6->src, false, NULL); + } + else { gnrc_pktsnip_t *reply_aro = NULL; #if GNRC_IPV6_NIB_CONF_6LR ndp_opt_t *sl2ao = NULL; @@ -948,7 +968,21 @@ static void _handle_nbr_adv(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, (nbr_adv->flags & NDP_NBR_ADV_FLAGS_S) ? 'S' : '-', (nbr_adv->flags & NDP_NBR_ADV_FLAGS_O) ? 'O' : '-'); #if GNRC_IPV6_NIB_CONF_SLAAC - /* TODO SLAAC behavior */ + gnrc_netif_t *tgt_netif = gnrc_netif_get_by_ipv6_addr(&nbr_adv->tgt); + + if (tgt_netif != NULL) { + int idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_adv->tgt); + + if (gnrc_netif_ipv6_addr_dad_trans(tgt_netif, idx)) { + /* cancel validation timer */ + evtimer_del(&_nib_evtimer, + &tgt_netif->ipv6.addrs_timers[idx].event); + _remove_tentative_addr(tgt_netif, &nbr_adv->tgt); + return; + } + /* else case beyond scope of RFC4862: + * https://tools.ietf.org/html/rfc4862#section-5.4.4 */ + } #endif /* GNRC_IPV6_NIB_CONF_SLAAC */ if (((nce = _nib_onl_get(&nbr_adv->tgt, netif->pid)) != NULL) && (nce->mode & _NC)) { @@ -1246,11 +1280,9 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6, DEBUG(" - Preferred lifetime: %" PRIu32 "\n", byteorder_ntohl(pio->pref_ltime)); -#if GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN if (pio->flags & NDP_OPT_PI_FLAGS_A) { _auto_configure_addr(netif, &pio->prefix, pio->prefix_len); } -#endif /* GNRC_IPV6_NIB_CONF_SLAAC || GNRC_IPV6_NIB_CONF_6LN */ if ((pio->flags & NDP_OPT_PI_FLAGS_L) || gnrc_netif_is_6lr(netif)) { _nib_offl_entry_t *pfx; @@ -1293,60 +1325,4 @@ static uint32_t _handle_pio(gnrc_netif_t *netif, const icmpv6_hdr_t *icmpv6, return UINT32_MAX; } -#if GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC -static void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, - uint8_t pfx_len) -{ - ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; - int idx; - uint8_t flags = GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; - - DEBUG("nib: add address based on %s/%u automatically to interface %u\n", - ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)), - pfx_len, netif->pid); -#if GNRC_IPV6_NIB_CONF_6LN - bool new_address = false; -#endif /* GNRC_IPV6_NIB_CONF_6LN */ - gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]); - ipv6_addr_init_prefix(&addr, pfx, pfx_len); - if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) { - if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len, - flags)) < 0) { - DEBUG("nib: Can't add link-local address on interface %u\n", - netif->pid); - return; - } -#if GNRC_IPV6_NIB_CONF_6LN - new_address = true; -#endif /* GNRC_IPV6_NIB_CONF_6LN */ - } - -#if GNRC_IPV6_NIB_CONF_6LN - /* mark link-local addresses as valid on 6LN */ - if (gnrc_netif_is_6ln(netif) && ipv6_addr_is_link_local(pfx)) { - /* don't do this beforehand or risk a deadlock: - * * gnrc_netif_ipv6_addr_add_internal() adds VALID (i.e. manually configured - * addresses to the prefix list locking the NIB's mutex which is already - * locked here) */ - netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK; - netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID; - } -#endif /* GNRC_IPV6_NIB_CONF_6LN */ - /* TODO: make this line conditional on 6LN when there is a SLAAC - * implementation */ -#if GNRC_IPV6_NIB_CONF_6LN - if (new_address && gnrc_netif_is_6ln(netif) && - !gnrc_netif_is_6lbr(netif)) { - _handle_rereg_address(&netif->ipv6.addrs[idx]); - } -#else /* GNRC_IPV6_NIB_CONF_6LN */ - (void)idx; -#endif /* GNRC_IPV6_NIB_CONF_6LN */ -#if GNRC_IPV6_NIB_CONF_SLAAC - /* TODO send NS to solicited nodes and wait netif->ipv6.retrans_time to - * confirm uniqueness of the link-local address */ -#endif /* GNRC_IPV6_NIB_CONF_SLAAC */ -} -#endif /* GNRC_IPV6_NIB_CONF_6LN || GNRC_IPV6_NIB_CONF_SLAAC */ - /** @} */ -- GitLab