]> 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)
committerLuca Boccassi <luca.boccassi@gmail.com>
Sat, 17 May 2025 11:43:20 +0000 (12:43 +0100)
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)

src/network/networkd-ndisc.c

index 84558a5afc5cb85519fa43fc6dbea49250de15d9..e5903e50036b0bac11e88c9dbf0d14c14d549cf7 100644 (file)
@@ -2224,10 +2224,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) {