183 lines
7.4 KiB
Diff
183 lines
7.4 KiB
Diff
From 2bd5bbbd39d5c825ed520e8282840b76b8f7fc79 Mon Sep 17 00:00:00 2001
|
|
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
|
Date: Sat, 21 Aug 2021 03:51:39 +0900
|
|
Subject: [PATCH] network: fix logic for checking gateway address is ready
|
|
|
|
This fixes the followings:
|
|
- The corresponding route or address to the gateway address must be in
|
|
the same link.
|
|
- IPv6 link local address is not necessary to be reachable.
|
|
|
|
Fixes an issue reported in https://github.com/systemd/systemd/issues/8686#issuecomment-902562324.
|
|
|
|
(cherry picked from commit 3333350a0e1917395d3654731ca985ea668bca9b)
|
|
|
|
Conflict:NA
|
|
Reference:https://github.com/systemd/systemd/commit/2bd5bbbd39d5c825ed520e8282840b76b8f7fc79
|
|
---
|
|
src/network/networkd-nexthop.c | 7 +---
|
|
src/network/networkd-route.c | 72 ++++++++++++++++++++--------------
|
|
src/network/networkd-route.h | 2 +-
|
|
3 files changed, 44 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c
|
|
index a52e5dcb16..c5cba88f46 100644
|
|
--- a/src/network/networkd-nexthop.c
|
|
+++ b/src/network/networkd-nexthop.c
|
|
@@ -791,12 +791,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
|
|
}
|
|
}
|
|
|
|
- if (nexthop->onlink <= 0 &&
|
|
- in_addr_is_set(nexthop->family, &nexthop->gw) &&
|
|
- !manager_address_is_reachable(link->manager, nexthop->family, &nexthop->gw))
|
|
- return false;
|
|
-
|
|
- return true;
|
|
+ return gateway_is_ready(link, nexthop->onlink, nexthop->family, &nexthop->gw);
|
|
}
|
|
|
|
int request_process_nexthop(Request *req) {
|
|
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
|
|
index 068915616e..b7852f6eec 100644
|
|
--- a/src/network/networkd-route.c
|
|
+++ b/src/network/networkd-route.c
|
|
@@ -753,6 +753,8 @@ static bool prefix_route_address_is_reachable(const Address *a, int family, cons
|
|
|
|
if (a->family != family)
|
|
return false;
|
|
+ if (!address_is_ready(a))
|
|
+ return false;
|
|
if (FLAGS_SET(a->flags, IFA_F_NOPREFIXROUTE))
|
|
return false;
|
|
if (in_addr_is_set(a->family, &a->in_addr_peer))
|
|
@@ -766,37 +768,34 @@ static bool prefix_route_address_is_reachable(const Address *a, int family, cons
|
|
FAMILY_ADDRESS_SIZE(family) * 8) > 0;
|
|
}
|
|
|
|
-bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address) {
|
|
- Link *link;
|
|
+static bool link_address_is_reachable(Link *link, int family, const union in_addr_union *address) {
|
|
+ Route *route;
|
|
|
|
- assert(manager);
|
|
+ assert(link);
|
|
+ assert(link->manager);
|
|
assert(IN_SET(family, AF_INET, AF_INET6));
|
|
assert(address);
|
|
|
|
- HASHMAP_FOREACH(link, manager->links_by_index) {
|
|
- Route *route;
|
|
|
|
- SET_FOREACH(route, link->routes)
|
|
- if (route_address_is_reachable(route, family, address))
|
|
- return true;
|
|
- SET_FOREACH(route, link->routes_foreign)
|
|
- if (route_address_is_reachable(route, family, address))
|
|
- return true;
|
|
- }
|
|
+ SET_FOREACH(route, link->routes)
|
|
+ if (route_address_is_reachable(route, family, address))
|
|
+ return true;
|
|
+ SET_FOREACH(route, link->routes_foreign)
|
|
+ if (route_address_is_reachable(route, family, address))
|
|
+ return true;
|
|
|
|
/* If we do not manage foreign routes, then there may exist a prefix route we do not know,
|
|
* which was created on configuring an address. Hence, also check the addresses. */
|
|
- if (!manager->manage_foreign_routes)
|
|
- HASHMAP_FOREACH(link, manager->links_by_index) {
|
|
- Address *a;
|
|
-
|
|
- SET_FOREACH(a, link->addresses)
|
|
- if (prefix_route_address_is_reachable(a, family, address))
|
|
- return true;
|
|
- SET_FOREACH(a, link->addresses_foreign)
|
|
- if (prefix_route_address_is_reachable(a, family, address))
|
|
- return true;
|
|
- }
|
|
+ if (!link->manager->manage_foreign_routes) {
|
|
+ Address *a;
|
|
+
|
|
+ SET_FOREACH(a, link->addresses)
|
|
+ if (prefix_route_address_is_reachable(a, family, address))
|
|
+ return true;
|
|
+ SET_FOREACH(a, link->addresses_foreign)
|
|
+ if (prefix_route_address_is_reachable(a, family, address))
|
|
+ return true;
|
|
+ }
|
|
|
|
return false;
|
|
}
|
|
@@ -1692,6 +1691,22 @@ int link_request_static_routes(Link *link, bool only_ipv4) {
|
|
return 0;
|
|
}
|
|
|
|
+bool gateway_is_ready(Link *link, int onlink, int family, const union in_addr_union *gw) {
|
|
+ assert(link);
|
|
+ assert(gw);
|
|
+
|
|
+ if (onlink > 0)
|
|
+ return true;
|
|
+
|
|
+ if (!in_addr_is_set(family, gw))
|
|
+ return true;
|
|
+
|
|
+ if (family == AF_INET6 && in6_addr_is_link_local(&gw->in6))
|
|
+ return true;
|
|
+
|
|
+ return link_address_is_reachable(link, family, gw);
|
|
+}
|
|
+
|
|
static int route_is_ready_to_configure(const Route *route, Link *link) {
|
|
MultipathRoute *m;
|
|
NextHop *nh = NULL;
|
|
@@ -1735,19 +1750,13 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
|
|
return r;
|
|
}
|
|
|
|
- if (route->gateway_onlink <= 0 &&
|
|
- in_addr_is_set(route->gw_family, &route->gw) > 0 &&
|
|
- !manager_address_is_reachable(link->manager, route->gw_family, &route->gw))
|
|
+ if (!gateway_is_ready(link, route->gateway_onlink, route->gw_family, &route->gw))
|
|
return false;
|
|
|
|
ORDERED_SET_FOREACH(m, route->multipath_routes) {
|
|
union in_addr_union a = m->gateway.address;
|
|
Link *l = NULL;
|
|
|
|
- if (route->gateway_onlink <= 0 &&
|
|
- !manager_address_is_reachable(link->manager, m->gateway.family, &a))
|
|
- return false;
|
|
-
|
|
if (m->ifname) {
|
|
if (link_get_by_name(link->manager, m->ifname, &l) < 0)
|
|
return false;
|
|
@@ -1759,6 +1768,9 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
|
|
}
|
|
if (l && !link_is_ready_to_configure(l, true))
|
|
return false;
|
|
+
|
|
+ if (!gateway_is_ready(l ?: link, route->gateway_onlink, m->gateway.family, &a))
|
|
+ return false;
|
|
}
|
|
|
|
return true;
|
|
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
|
|
index 2d262819ad..235a91f08d 100644
|
|
--- a/src/network/networkd-route.h
|
|
+++ b/src/network/networkd-route.h
|
|
@@ -78,8 +78,8 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
|
|
int route_remove(const Route *route, Manager *manager, Link *link);
|
|
|
|
int link_has_route(Link *link, const Route *route);
|
|
-bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address);
|
|
int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret);
|
|
+bool gateway_is_ready(Link *link, int onlink, int family, const union in_addr_union *gw);
|
|
|
|
int link_drop_routes(Link *link);
|
|
int link_drop_foreign_routes(Link *link);
|
|
--
|
|
2.33.0
|
|
|