diff options
-rw-r--r-- | src/network/networkd-dhcp-server.c | 2 | ||||
-rw-r--r-- | src/network/networkd-manager.c | 37 | ||||
-rw-r--r-- | src/network/networkd-manager.h | 2 | ||||
-rw-r--r-- | src/network/networkd-radv.c | 4 | ||||
-rw-r--r-- | src/network/networkd-route.c | 59 | ||||
-rw-r--r-- | src/network/networkd-route.h | 1 |
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); |