summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/network/networkd-dhcp-server.c2
-rw-r--r--src/network/networkd-manager.c37
-rw-r--r--src/network/networkd-manager.h2
-rw-r--r--src/network/networkd-radv.c4
-rw-r--r--src/network/networkd-route.c59
-rw-r--r--src/network/networkd-route.h1
6 files changed, 63 insertions, 42 deletions
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index e4af517c20..3443e498a1 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -363,7 +363,7 @@ static int dhcp4_server_configure(Link *link) {
else {
/* Emission is requested, but nothing explicitly configured. Let's find a suitable upling */
if (!acquired_uplink) {
- uplink = manager_find_uplink(link->manager, link);
+ (void) manager_find_uplink(link->manager, AF_INET, link, &uplink);
acquired_uplink = true;
}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index d4b4043211..60e6d6f369 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -719,43 +719,6 @@ int manager_enumerate(Manager *m) {
return 0;
}
-Link* manager_find_uplink(Manager *m, Link *exclude) {
- _cleanup_free_ struct local_address *gateways = NULL;
- int n;
-
- assert(m);
-
- /* Looks for a suitable "uplink", via black magic: an
- * interface that is up and where the default route with the
- * highest priority points to. */
-
- n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways);
- if (n < 0) {
- log_warning_errno(n, "Failed to determine list of default gateways: %m");
- return NULL;
- }
-
- for (int i = 0; i < n; i++) {
- Link *link;
-
- link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex));
- if (!link) {
- log_debug("Weird, found a gateway for a link we don't know. Ignoring.");
- continue;
- }
-
- if (link == exclude)
- continue;
-
- if (link->operstate < LINK_OPERSTATE_ROUTABLE)
- continue;
-
- return link;
- }
-
- return NULL;
-}
-
static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
const sd_bus_error *e;
int r;
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index 6b9b0697b2..c7fea16ab2 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -111,8 +111,6 @@ bool manager_should_reload(Manager *m);
int manager_enumerate(Manager *m);
-Link* manager_find_uplink(Manager *m, Link *exclude);
-
int manager_set_hostname(Manager *m, const char *hostname);
int manager_set_timezone(Manager *m, const char *timezone);
diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c
index 0eaa4c29c9..45cfd7a9a7 100644
--- a/src/network/networkd-radv.c
+++ b/src/network/networkd-radv.c
@@ -646,10 +646,10 @@ static int radv_set_domains(Link *link, Link *uplink) {
}
int radv_emit_dns(Link *link) {
- Link *uplink;
+ Link *uplink = NULL;
int r;
- uplink = manager_find_uplink(link->manager, link);
+ (void) manager_find_uplink(link->manager, AF_INET6, link, &uplink);
r = radv_set_dns(link, uplink);
if (r < 0)
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 7d93825813..c76cdbedee 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -771,6 +771,65 @@ bool manager_address_is_reachable(Manager *manager, int family, const union in_a
return false;
}
+static Route *routes_get_default_gateway(Set *routes, int family, Route *gw) {
+ Route *route;
+
+ SET_FOREACH(route, routes) {
+ if (family != AF_UNSPEC && route->family != family)
+ continue;
+ if (route->dst_prefixlen != 0)
+ continue;
+ if (route->src_prefixlen != 0)
+ continue;
+ if (route->table != RT_TABLE_MAIN)
+ continue;
+ if (route->type != RTN_UNICAST)
+ continue;
+ if (route->scope != RT_SCOPE_UNIVERSE)
+ continue;
+ if (!in_addr_is_set(route->gw_family, &route->gw))
+ continue;
+ if (gw) {
+ if (route->gw_weight > gw->gw_weight)
+ continue;
+ if (route->priority >= gw->priority)
+ continue;
+ }
+ gw = route;
+ }
+
+ return gw;
+}
+
+int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret) {
+ Route *gw = NULL;
+ Link *link;
+
+ assert(m);
+ assert(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6));
+
+ /* Looks for a suitable "uplink", via black magic: an interface that is up and where the
+ * default route with the highest priority points to. */
+
+ HASHMAP_FOREACH(link, m->links) {
+ if (link == exclude)
+ continue;
+
+ if (link->state != LINK_STATE_CONFIGURED)
+ continue;
+
+ gw = routes_get_default_gateway(link->routes, family, gw);
+ gw = routes_get_default_gateway(link->routes_foreign, family, gw);
+ }
+
+ if (!gw)
+ return -ENOENT;
+
+ assert(gw->link);
+ *ret = gw->link;
+ return 0;
+}
+
static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *manager) {
_cleanup_free_ char *dst = NULL, *src = NULL, *gw_alloc = NULL, *prefsrc = NULL,
*table = NULL, *scope = NULL, *proto = NULL;
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
index 095a07e05d..fa0b3ba0fc 100644
--- a/src/network/networkd-route.h
+++ b/src/network/networkd-route.h
@@ -78,6 +78,7 @@ 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);
int link_drop_routes(Link *link);
int link_drop_foreign_routes(Link *link);