From: Yu Watanabe Date: Thu, 6 May 2021 19:29:52 +0000 (+0900) Subject: network: delay resolving interface specifier in MultiPathRoute= X-Git-Tag: v249-rc1~240^2~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e8f52f3c19626aab2236ab0560c3e98538b382a2;p=thirdparty%2Fsystemd.git network: delay resolving interface specifier in MultiPathRoute= The interface may not exist when .network files are loaded. --- diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 448c50d4ab4..4ab3b1020c7 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -409,6 +409,15 @@ int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void return 0; } +MultipathRoute *multipath_route_free(MultipathRoute *m) { + if (!m) + return NULL; + + free(m->ifname); + + return mfree(m); +} + int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret) { _cleanup_ordered_set_free_free_ OrderedSet *set = NULL; int r; @@ -420,7 +429,7 @@ int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, O return -EBADMSG; for (; size >= sizeof(struct rtnexthop); ) { - _cleanup_free_ MultipathRoute *m = NULL; + _cleanup_(multipath_route_freep) MultipathRoute *m = NULL; if (NLMSG_ALIGN(rtnh->rtnh_len) > size) return -EBADMSG; diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index a3a3951ff79..394c821ffba 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -19,10 +19,14 @@ typedef struct RouteVia { typedef struct MultipathRoute { RouteVia gateway; - int ifindex; uint32_t weight; + int ifindex; + char *ifname; } MultipathRoute; +MultipathRoute *multipath_route_free(MultipathRoute *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free); + int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret); uint32_t rtnl_message_get_serial(sd_netlink_message *m); void rtnl_message_seal(sd_netlink_message *m); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 8f3d84129a8..b5ea14089a5 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -288,7 +288,7 @@ Route *route_free(Route *route) { set_remove(route->manager->routes_foreign, route); } - ordered_set_free_free(route->multipath_routes); + ordered_set_free_with_destructor(route->multipath_routes, multipath_route_free); sd_event_source_unref(route->expire); @@ -1299,20 +1299,41 @@ static bool route_has_gateway(const Route *route) { } static int link_set_routes_internal(Link *link, bool with_gateway) { - Route *rt; + Route *route; int r; assert(link); assert(link->network); - HASHMAP_FOREACH(rt, link->network->routes_by_section) { - if (rt->gateway_from_dhcp_or_ra) + HASHMAP_FOREACH(route, link->network->routes_by_section) { + bool multipath_ok = true; + MultipathRoute *m; + + if (route->gateway_from_dhcp_or_ra) + continue; + + if (route_has_gateway(route) != with_gateway) continue; - if (route_has_gateway(rt) != with_gateway) + ORDERED_SET_FOREACH(m, route->multipath_routes) { + if (isempty(m->ifname)) + continue; + + r = resolve_interface(&link->manager->rtnl, m->ifname); + if (r < 0) { + log_link_debug_errno(link, r, + "Failed to resolve interface name '%s' for multipath route, " + "ignoring the route: %m", m->ifname); + multipath_ok = false; + break; + } + + m->ifindex = r; + } + if (!multipath_ok) continue; - r = route_configure(rt, link, with_gateway ? route_handler_with_gateway : route_handler_without_gateway, NULL); + r = route_configure(route, link, with_gateway ? route_handler_with_gateway : route_handler_without_gateway, NULL); if (r < 0) return log_link_warning_errno(link, r, "Could not set routes: %m"); @@ -2460,13 +2481,14 @@ int config_parse_multipath_route( void *data, void *userdata) { + _cleanup_(multipath_route_freep) MultipathRoute *m = NULL; _cleanup_(route_free_or_set_invalidp) Route *n = NULL; - _cleanup_free_ char *word = NULL, *buf = NULL; - _cleanup_free_ MultipathRoute *m = NULL; + _cleanup_free_ char *word = NULL; Network *network = userdata; - const char *p, *ip, *dev; union in_addr_union a; int family, r; + const char *p; + char *dev; assert(filename); assert(section); @@ -2484,7 +2506,7 @@ int config_parse_multipath_route( } if (isempty(rvalue)) { - n->multipath_routes = ordered_set_free_free(n->multipath_routes); + n->multipath_routes = ordered_set_free_with_destructor(n->multipath_routes, multipath_route_free); return 0; } @@ -2504,15 +2526,14 @@ int config_parse_multipath_route( dev = strchr(word, '@'); if (dev) { - buf = strndup(word, dev - word); - if (!buf) + *dev++ = '\0'; + + m->ifname = strdup(dev); + if (!m->ifname) return log_oom(); - ip = buf; - dev++; - } else - ip = word; + } - r = in_addr_from_string_auto(ip, &family, &a); + r = in_addr_from_string_auto(word, &family, &a); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue); @@ -2521,16 +2542,6 @@ int config_parse_multipath_route( m->gateway.address = a; m->gateway.family = family; - if (dev) { - r = resolve_interface(NULL, dev); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Invalid interface name or index, ignoring assignment: %s", dev); - return 0; - } - m->ifindex = r; - } - if (!isempty(p)) { r = safe_atou32(p, &m->weight); if (r < 0) {