A host can send Router Advertisements (RAs) without acting as a router.
In such cases, the lifetime of the RA header should be zero, but may
contain several options, and clients can configure addresses, routes,
and so on with the message. The host may (should?) send Neighbor
Announcements (NAs) without the router flag in that case.
So, when a NA without the router flag is received, let's not drop
configurations based on the previous RA options, but only drop the
default gateway configured based on the RA header.
See RFC 4861 Neighbor Discovery in IPv6, section 6.3.4:
https://www.rfc-editor.org/rfc/rfc4861#section-6.3.4:~:text=%2D%20The%20IsRouter%20flag,as%20a%20host.
> - The IsRouter flag in the cache entry MUST be set based on the Router
> flag in the received advertisement. In those cases where the IsRouter
> flag changes from TRUE to FALSE as a result of this update, the node
> MUST remove that router from the Default Router List and update the
> Destination Cache entries for all destinations using that neighbor as
> a router as specified in Section 7.3.3. This is needed to detect when
> a node that is used as a router stops forwarding packets due to being
> configured as a host.
Fixes a regression caused by
87a33c0740524e894a170f75638012c2c5f90f24 (v256).
Fixes #37198.
(cherry picked from commit
9142bd5a8e9ed94ecbb1e335305e24760b90ad2a)
(cherry picked from commit
a98e9764e348262906ce9480b825a568a4d01cd7)
if (r < 0)
return r;
- (void) ndisc_drop_outdated(link, /* router = */ &address, /* timestamp_usec = */ USEC_INFINITY);
- (void) ndisc_drop_redirect(link, &address);
+ /* Remove the routes configured by Redirect messages. */
+ r = ndisc_drop_redirect(link, &address);
- return 0;
+ /* Also remove the default gateway via the host, but keep the configurations based on the RA options. */
+ _cleanup_(sd_ndisc_router_unrefp) sd_ndisc_router *rt = hashmap_remove(link->ndisc_routers_by_sender, &address);
+ if (rt)
+ RET_GATHER(r, ndisc_router_drop_default(link, rt));
+
+ return r;
}
static int ndisc_neighbor_handle_router_message(Link *link, sd_ndisc_neighbor *na) {