From 713146eebaf8095a1ac5afe4847e5fe0b373abd7 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Mon, 2 Jan 2017 15:35:27 +0000 Subject: [PATCH] nd6: cull destination cache on router removal As per RFC requirements, upon removing a router from the default router list, remove any entries pointing to it from the destination cache. While here, synchronize timing out entries in the default router list with the rest of the timer code. When removing a netif, clear the destination cache altogether in order to prevent more general inconsistency. When this happens, the entries for other netifs will have to be rebuilt, but removing netifs should be sufficiently rare that this is not worth optimizing. --- src/core/ipv6/nd6.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/core/ipv6/nd6.c b/src/core/ipv6/nd6.c index 301bc469..c6c12df8 100644 --- a/src/core/ipv6/nd6.c +++ b/src/core/ipv6/nd6.c @@ -957,15 +957,22 @@ nd6_tmr(void) for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { if (default_router_list[i].neighbor_entry != NULL) { /* Active entry. */ - if (default_router_list[i].invalidation_timer > 0) { - default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - } - if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - /* Less than 1 second remaining. Clear this entry. */ + if (default_router_list[i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) { + /* No more than 1 second remaining. Clear this entry. Also clear any of + * its destination cache entries, as per RFC 4861 Sec. 5.3 and 6.3.5. */ + s8_t j; + for (j = 0; j < LWIP_ND6_NUM_DESTINATIONS; j++) { + if (ip6_addr_cmp(&destination_cache[j].next_hop_addr, + &default_router_list[i].neighbor_entry->next_hop_address)) { + ip6_addr_set_any(&destination_cache[j].destination_addr); + } + } default_router_list[i].neighbor_entry->isrouter = 0; default_router_list[i].neighbor_entry = NULL; default_router_list[i].invalidation_timer = 0; default_router_list[i].flags = 0; + } else { + default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; } } } @@ -2280,6 +2287,10 @@ nd6_cleanup_netif(struct netif *netif) nd6_free_neighbor_cache_entry(i); } } + /* Clear the destination cache, since many entries may now have become + * invalid for one of several reasons. As destination cache entries have no + * netif association, use a sledgehammer approach (this can be improved). */ + nd6_clear_destination_cache(); } #if LWIP_IPV6_MLD