]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: handle ignoring ll gateway being link ll
authorDevon Pringle <devon.pringle@opengear.com>
Mon, 14 Dec 2020 04:22:18 +0000 (14:22 +1000)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 16 Dec 2020 16:56:01 +0000 (17:56 +0100)
In the event where network discovery gets a route with the gateway being
the interfaces local link address, networkd will fail the interface.

systemd-networkd[44319]: br_lan: Configuring route: dst: fdcd:41a4:5559:ec03::/64, src: n/a, gw: fe80::e4da:7eff:fe77:5c5e, prefsrc: n/a, scope: global, table: main, proto: ra, type: unicast
systemd-networkd[44319]: br_lan: Could not set NDisc route or address: Gateway can not be a local address. Invalid argument
systemd-networkd[44319]: br_lan: Failed
systemd-networkd[44319]: br_lan: State changed: configuring -> failed

This patch, instead of allowing the interface to fail, will instead log
the event and skip setting the route.

src/network/networkd-ndisc.c

index 903c995e743e7a5931e0a04b81c7bcb6e8bac914..32b8482527921e9a6ee0d2a8b1ad64d72174ac6a 100644 (file)
@@ -820,7 +820,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
 
 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
         _cleanup_(route_freep) Route *route = NULL;
-        struct in6_addr gateway;
+        union in_addr_union gateway;
         uint32_t lifetime;
         unsigned preference, prefixlen;
         usec_t time_now;
@@ -835,10 +835,20 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
         if (lifetime == 0)
                 return 0;
 
-        r = sd_ndisc_router_get_address(rt, &gateway);
+        r = sd_ndisc_router_get_address(rt, &gateway.in6);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
 
+        if (link_has_ipv6_address(link, &gateway.in6) == 0) {
+                _cleanup_free_ char *buf = NULL;
+
+                if (DEBUG_LOGGING) {
+                        (void) in_addr_to_string(AF_INET6, &gateway, &buf);
+                        log_link_debug(link, "Advertised route gateway, %s, is local to the link, ignoring route", strnull(buf));
+                }
+                return 0;
+        }
+
         r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get route prefix length: %m");
@@ -860,7 +870,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
         route->priority = link->network->dhcp6_route_metric;
         route->protocol = RTPROT_RA;
         route->pref = preference;
-        route->gw.in6 = gateway;
+        route->gw.in6 = gateway.in6;
         route->gw_family = AF_INET6;
         route->dst_prefixlen = prefixlen;
         route->lifetime = time_now + lifetime * USEC_PER_SEC;