From 8871b929abea6c0f67819572157f4572b8f8e4c6 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 18 Jun 2021 00:59:57 +0200 Subject: [PATCH] gnrc_ipv6_nib: consider all local interfaces when looking for address If a node has two interfaces A with 2001:16b8:45b5:9af8:5884:3bff:fe4f:a903 and B with 2001:16b8:45b5:9afa:5884:3bff:fe4f:a902 and receives a neighbor solicitation on A for an address configured on interface B, answer the neighbor solicitation instead of bailing out with > Target address 2001:16b8:45b5:9afa:5884:3bff:fe4f:a902 is not assigned > to the local interface --- sys/net/gnrc/network_layer/ipv6/nib/nib.c | 24 +++++++++++++++-------- sys/net/gnrc/network_layer/ndp/gnrc_ndp.c | 9 +++++++-- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index e2000a4086..b2e826699a 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -881,6 +881,7 @@ static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, const ndp_nbr_sol_t *nbr_sol, size_t icmpv6_len) { size_t tmp_len = icmpv6_len - sizeof(ndp_nbr_sol_t); + gnrc_netif_t *tgt_netif; int tgt_idx; ndp_opt_t *opt; @@ -906,13 +907,23 @@ static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str))); return; } - /* check if target is assigned only now in case the length was wrong */ - tgt_idx = gnrc_netif_ipv6_addr_idx(netif, &nbr_sol->tgt); + + /* check if the address belongs to this host */ + tgt_netif = gnrc_netif_get_by_ipv6_addr(&nbr_sol->tgt); + + if (tgt_netif != NULL) { + /* check if target is assigned only now in case the length was wrong */ + tgt_idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_sol->tgt); + } else { + tgt_idx = -1; + } + if (tgt_idx < 0) { DEBUG("nib: Target address %s is not assigned to the local interface\n", ipv6_addr_to_str(addr_str, &nbr_sol->tgt, sizeof(addr_str))); return; } + /* pre-check option length */ FOREACH_OPT(nbr_sol, opt, tmp_len) { if (tmp_len > icmpv6_len) { @@ -934,19 +945,16 @@ 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 IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) - gnrc_netif_t *tgt_netif = gnrc_netif_get_by_ipv6_addr(&nbr_sol->tgt); if (tgt_netif != NULL) { - int idx; - gnrc_netif_acquire(tgt_netif); - idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_sol->tgt); + tgt_idx = gnrc_netif_ipv6_addr_idx(tgt_netif, &nbr_sol->tgt); /* if idx < 0: * nbr_sol->tgt was removed between getting tgt_netif by nbr_sol->tgt * and gnrc_netif_acquire(tgt_netif). This is like `tgt_netif` would * have been NULL in the first place so just continue as if it would * have. */ - if ((idx >= 0) && gnrc_netif_ipv6_addr_dad_trans(tgt_netif, idx)) { + if ((tgt_idx >= 0) && gnrc_netif_ipv6_addr_dad_trans(tgt_netif, tgt_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 " @@ -956,7 +964,7 @@ static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, } /* cancel validation timer */ evtimer_del(&_nib_evtimer, - &tgt_netif->ipv6.addrs_timers[idx].event); + &tgt_netif->ipv6.addrs_timers[tgt_idx].event); /* _remove_tentative_addr() context switches to `tgt_netif->pid` so * release `tgt_netif`. We are done here anyway. */ gnrc_netif_release(tgt_netif); diff --git a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c index 2fc4d16437..d0226b5087 100644 --- a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c +++ b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c @@ -331,11 +331,16 @@ void gnrc_ndp_nbr_adv_send(const ipv6_addr_t *tgt, gnrc_netif_t *netif, gnrc_netif_acquire(netif); do { /* XXX: hidden goto */ int tgt_idx; + gnrc_netif_t *tgt_netif = gnrc_netif_get_by_ipv6_addr(tgt); - if ((tgt_idx = gnrc_netif_ipv6_addr_idx(netif, tgt)) < 0) { + if (tgt_netif == NULL) { DEBUG("ndp: tgt not assigned to interface. Abort sending\n"); break; } + + tgt_idx = gnrc_netif_ipv6_addr_idx(tgt_netif, tgt); + assert(tgt_idx >= 0); + if (gnrc_netif_is_rtr(netif) && gnrc_netif_is_rtr_adv(netif)) { adv_flags |= NDP_NBR_ADV_FLAGS_R; } @@ -368,7 +373,7 @@ void gnrc_ndp_nbr_adv_send(const ipv6_addr_t *tgt, gnrc_netif_t *netif, } /* TODO: also check if the node provides proxy services for tgt */ if ((pkt != NULL) && - (netif->ipv6.addrs_flags[tgt_idx] & + (tgt_netif->ipv6.addrs_flags[tgt_idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_ANYCAST)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NDP_NBR_ADV_FLAGS_O;