From 0b54c87081d80a1dfee05b8d4ed8f380520bae5e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 14 May 2021 16:00:52 +0900 Subject: [PATCH 1/3] network: introduce link_get_by_name() --- src/network/networkd-link.c | 88 +++++++++++++++++++++++++--------- src/network/networkd-link.h | 1 + src/network/networkd-manager.c | 1 + src/network/networkd-manager.h | 1 + 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index d493afda4c..b58b99d8d6 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -512,14 +512,28 @@ int link_get(Manager *m, int ifindex, Link **ret) { assert(m); assert(ifindex > 0); - assert(ret); link = hashmap_get(m->links, INT_TO_PTR(ifindex)); if (!link) return -ENODEV; - *ret = link; + if (ret) + *ret = link; + return 0; +} +int link_get_by_name(Manager *m, const char *ifname, Link **ret) { + Link *link; + + assert(m); + assert(ifname); + + link = hashmap_get(m->links_by_name, ifname); + if (!link) + return -ENODEV; + + if (ret) + *ret = link; return 0; } @@ -1669,6 +1683,8 @@ static void link_drop_requests(Link *link) { static Link *link_drop(Link *link) { + char **n; + if (!link) return NULL; @@ -1694,6 +1710,11 @@ static Link *link_drop(Link *link) { (void) unlink(link->state_file); link_clean(link); + STRV_FOREACH(n, link->alternative_names) + hashmap_remove(link->manager->links_by_name, *n); + + hashmap_remove(link->manager->links_by_name, link->ifname); + /* The following must be called at last. */ assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); return link_unref(link); @@ -2164,8 +2185,33 @@ static int link_get_network(Link *link, Network **ret) { return -ENOENT; } +static int link_update_alternative_names(Link *link, sd_netlink_message *message) { + _cleanup_strv_free_ char **altnames = NULL; + char **n; + int r; + + assert(link); + assert(message); + + r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &altnames); + if (r < 0 && r != -ENODATA) + return r; + + STRV_FOREACH(n, link->alternative_names) + hashmap_remove(link->manager->links_by_name, *n); + + strv_free_and_replace(link->alternative_names, altnames); + + STRV_FOREACH(n, link->alternative_names) { + r = hashmap_ensure_put(&link->manager->links_by_name, &string_hash_ops, *n, link); + if (r < 0) + return r; + } + + return 0; +} + static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool force) { - _cleanup_strv_free_ char **s = NULL; Network *network; int r; @@ -2175,12 +2221,10 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for if (r < 0) return r; - r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s); - if (r < 0 && r != -ENODATA) + r = link_update_alternative_names(link, m); + if (r < 0) return r; - strv_free_and_replace(link->alternative_names, s); - r = link_get_network(link, &network); if (r == -ENOENT) { link_enter_unmanaged(link); @@ -2345,7 +2389,6 @@ static int link_initialized_and_synced(Link *link) { } static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - _cleanup_strv_free_ char **s = NULL; int r; r = sd_netlink_message_get_errno(m); @@ -2355,14 +2398,12 @@ static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin return 0; } - r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s); - if (r < 0 && r != -ENODATA) { + r = link_update_alternative_names(link, m); + if (r < 0) { link_enter_failed(link); - return 0; + return r; } - strv_free_and_replace(link->alternative_names, s); - r = link_initialized_and_synced(link); if (r < 0) link_enter_failed(link); @@ -2505,10 +2546,6 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { if (r < 0) log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m"); - r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &link->alternative_names); - if (r < 0 && r != -ENODATA) - return r; - if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) return -ENOMEM; @@ -2518,6 +2555,14 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) return -ENOMEM; + r = hashmap_ensure_put(&manager->links_by_name, &string_hash_ops, link->ifname, link); + if (r < 0) + return r; + + r = link_update_alternative_names(link, message); + if (r < 0) + return r; + r = link_update_flags(link, message, false); if (r < 0) return r; @@ -2835,7 +2880,6 @@ static int link_admin_state_down(Link *link) { } static int link_update(Link *link, sd_netlink_message *m) { - _cleanup_strv_free_ char **s = NULL; hw_addr_data hw_addr; const char *ifname; uint32_t mtu; @@ -2865,12 +2909,12 @@ static int link_update(Link *link, sd_netlink_message *m) { r = link_add(manager, m, &link); if (r < 0) return r; + } else { + r = link_update_alternative_names(link, m); + if (r < 0) + return r; } - r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s); - if (r >= 0) - strv_free_and_replace(link->alternative_names, s); - r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu); if (r >= 0 && mtu > 0) { link->mtu = mtu; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index fbc593f124..54e0ae5593 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -210,6 +210,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref); int link_get(Manager *m, int ifindex, Link **ret); +int link_get_by_name(Manager *m, const char *ifname, Link **ret); int link_up(Link *link); int link_down(Link *link, link_netlink_message_handler_t callback); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index fd576169a9..fc207e4b3b 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -458,6 +458,7 @@ Manager* manager_free(Manager *m) { m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref); m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref); + m->links_by_name = hashmap_free(m->links_by_name); m->links = hashmap_free_with_destructor(m->links, link_unref); m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref); diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 3f8f81b865..0791351609 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -44,6 +44,7 @@ struct Manager { LinkAddressState ipv6_address_state; Hashmap *links; + Hashmap *links_by_name; Hashmap *netdevs; OrderedHashmap *networks; Hashmap *dhcp6_prefixes; From 8ed87c498301cf2b4860b4b7d76b690567e6f1a3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 14 May 2021 11:58:20 +0900 Subject: [PATCH 2/3] network: route: parse earlier if device specifier in MultiPathRoute= is ifindex --- src/network/networkd-route.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index e6c1d71265..f613da9922 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1575,25 +1575,23 @@ static int route_is_ready_to_configure(const Route *route, Link *link) { 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) { - Link *l; - - r = resolve_interface(&link->manager->rtnl, m->ifname); - if (r < 0) + if (link_get_by_name(link->manager, m->ifname, &l) < 0) return false; - m->ifindex = r; + m->ifindex = l->ifindex; + } else if (m->ifindex > 0) { if (link_get(link->manager, m->ifindex, &l) < 0) return false; - - if (!link_is_ready_to_configure(l, true)) - return false; } + if (l && !link_is_ready_to_configure(l, true)) + return false; } return true; @@ -2755,9 +2753,14 @@ int config_parse_multipath_route( if (dev) { *dev++ = '\0'; - m->ifname = strdup(dev); - if (!m->ifname) - return log_oom(); + r = parse_ifindex(dev); + if (r > 0) + m->ifindex = r; + else { + m->ifname = strdup(dev); + if (!m->ifname) + return log_oom(); + } } r = in_addr_from_string_auto(word, &family, &a); From 70a2d9dd3193e88ec89363826161ae04131baf6a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 13 May 2021 16:47:42 +0900 Subject: [PATCH 3/3] network: route: check validity of interface name in MultiPathRoute= --- src/network/networkd-route.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f613da9922..e588f3a215 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -2757,6 +2757,12 @@ int config_parse_multipath_route( if (r > 0) m->ifindex = r; else { + if (!ifname_valid_full(dev, IFNAME_VALID_ALTERNATIVE)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid interface name '%s' in %s=, ignoring: %s", dev, lvalue, rvalue); + return 0; + } + m->ifname = strdup(dev); if (!m->ifname) return log_oom();