From 221019166f315252304b3459902ead613b905de5 Mon Sep 17 00:00:00 2001 From: Devon Pringle Date: Mon, 14 Dec 2020 14:22:18 +1000 Subject: [PATCH] networkd: handle ignoring ll gateway being link ll 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 | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 903c995e74..32b8482527 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -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;