]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/ndisc: drop only default gateway via the host when a neighbor announcement...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 26 Apr 2025 01:50:26 +0000 (10:50 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 30 Apr 2025 13:17:03 +0000 (22:17 +0900)
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.

src/network/networkd-ndisc.c

index 9063c8baa98fbf996a06258c5e442da8f6b366ff..26d5611ba386d24e7dfb0f4ba2437cb0cca20260 100644 (file)
@@ -2737,10 +2737,15 @@ static int ndisc_neighbor_handle_non_router_message(Link *link, sd_ndisc_neighbo
         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) {