From 4e235561d68b030a03669cb48237a1afa24f0a86 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jan 2024 02:49:22 +0900 Subject: [PATCH 1/3] sd-netlink: unify network interface name getter and resolvers This makes rtnl_resolve_interface() always check the existence of the resolved interface, which previously did not when a decimal formatted ifindex is provided, e.g. "1" or "42". --- src/libsystemd/sd-netlink/netlink-util.c | 266 +++++++++++++---------- src/libsystemd/sd-netlink/netlink-util.h | 44 +++- src/test/test-socket-netlink.c | 22 +- 3 files changed, 198 insertions(+), 134 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 3713fadfb4..e634fd3378 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -11,6 +11,154 @@ #include "process-util.h" #include "strv.h" +static int parse_newlink_message( + sd_netlink_message *message, + char **ret_name, + char ***ret_altnames) { + + _cleanup_strv_free_ char **altnames = NULL; + int r, ifindex; + + assert(message); + + uint16_t type; + r = sd_netlink_message_get_type(message, &type); + if (r < 0) + return r; + if (type != RTM_NEWLINK) + return -EPROTO; + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) + return r; + if (ifindex <= 0) + return -EPROTO; + + if (ret_altnames) { + r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &altnames); + if (r < 0 && r != -ENODATA) + return r; + } + + if (ret_name) { + r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, ret_name); + if (r < 0) + return r; + } + + if (ret_altnames) + *ret_altnames = TAKE_PTR(altnames); + + return ifindex; +} + +int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; + int r; + + assert(ifindex > 0); + + /* This is similar to if_indextoname(), but also optionally provides alternative names. */ + + if (!rtnl) + rtnl = &our_rtnl; + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, ifindex); + if (r < 0) + return r; + + r = sd_netlink_call(*rtnl, message, 0, &reply); + if (r < 0) + return r; + + return parse_newlink_message(reply, ret_name, ret_altnames); +} + +int rtnl_resolve_ifname_full( + sd_netlink **rtnl, + ResolveInterfaceNameFlag flags, + const char *name, + char **ret_name, + char ***ret_altnames) { + + _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; + int r; + + assert(name); + assert(flags > 0); + + /* This is similar to if_nametoindex(), but also resolves alternative names and decimal formatted + * ifindex too. Returns ifindex, and optionally provides the main interface name and alternative + * names.*/ + + if (!rtnl) + rtnl = &our_rtnl; + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + + /* First, use IFLA_IFNAME */ + if (FLAGS_SET(flags, RESOLVE_IFNAME_MAIN) && ifname_valid(name)) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(message, IFLA_IFNAME, name); + if (r < 0) + return r; + + r = sd_netlink_call(*rtnl, message, 0, &reply); + if (r >= 0) + return parse_newlink_message(reply, ret_name, ret_altnames); + if (r != -ENODEV) + return r; + } + + /* Next, try IFLA_ALT_IFNAME */ + if (FLAGS_SET(flags, RESOLVE_IFNAME_ALTERNATIVE) && + ifname_valid_full(name, IFNAME_VALID_ALTERNATIVE)) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(message, IFLA_ALT_IFNAME, name); + if (r < 0) + return r; + + r = sd_netlink_call(*rtnl, message, 0, &reply); + if (r >= 0) + return parse_newlink_message(reply, ret_name, ret_altnames); + /* The kernels older than 76c9ac0ee878f6693d398d3a95ccaf85e1f597a6 (v5.5) return -EINVAL. */ + if (!IN_SET(r, -ENODEV, -EINVAL)) + return r; + } + + /* Finally, assume the string is a decimal formatted ifindex. */ + if (FLAGS_SET(flags, RESOLVE_IFNAME_NUMERIC)) { + int ifindex; + + ifindex = parse_ifindex(name); + if (ifindex <= 0) + return -ENODEV; + + return rtnl_get_ifname_full(rtnl, ifindex, ret_name, ret_altnames); + } + + return -ENODEV; +} + static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; int r; @@ -242,38 +390,6 @@ int rtnl_set_link_properties( return 0; } -int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; - _cleanup_strv_free_ char **names = NULL; - int r; - - assert(rtnl); - assert(ifindex > 0); - assert(ret); - - if (!*rtnl) { - r = sd_netlink_open(rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, ifindex); - if (r < 0) - return r; - - r = sd_netlink_call(*rtnl, message, 0, &reply); - if (r < 0) - return r; - - r = sd_netlink_message_read_strv(reply, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names); - if (r < 0 && r != -ENODATA) - return r; - - *ret = TAKE_PTR(names); - - return 0; -} - static int rtnl_update_link_alternative_names( sd_netlink **rtnl, uint16_t nlmsg_type, @@ -374,92 +490,6 @@ int rtnl_set_link_alternative_names_by_ifname( return 0; } -int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret) { - _cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL; - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL; - int r, ifindex; - - assert(name); - - /* This returns ifindex and the main interface name. */ - - if (!ifname_valid_full(name, IFNAME_VALID_ALTERNATIVE)) - return -EINVAL; - - if (!rtnl) - rtnl = &our_rtnl; - if (!*rtnl) { - r = sd_netlink_open(rtnl); - if (r < 0) - return r; - } - - r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, 0); - if (r < 0) - return r; - - r = sd_netlink_message_append_string(message, IFLA_ALT_IFNAME, name); - if (r < 0) - return r; - - r = sd_netlink_call(*rtnl, message, 0, &reply); - if (r == -EINVAL) - return -ENODEV; /* The device doesn't exist */ - if (r < 0) - return r; - - r = sd_rtnl_message_link_get_ifindex(reply, &ifindex); - if (r < 0) - return r; - assert(ifindex > 0); - - if (ret) { - r = sd_netlink_message_read_string_strdup(reply, IFLA_IFNAME, ret); - if (r < 0) - return r; - } - - return ifindex; -} - -int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name) { - int r; - - /* Like if_nametoindex, but resolves "alternative names" too. */ - - assert(name); - - r = if_nametoindex(name); - if (r > 0) - return r; - - return rtnl_resolve_link_alternative_name(rtnl, name, NULL); -} - -int rtnl_resolve_interface(sd_netlink **rtnl, const char *name) { - int r; - - /* Like rtnl_resolve_ifname, but resolves interface numbers too. */ - - assert(name); - - r = parse_ifindex(name); - if (r > 0) - return r; - assert(r < 0); - - return rtnl_resolve_ifname(rtnl, name); -} - -int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name) { - int r; - - r = rtnl_resolve_interface(rtnl, name); - if (r < 0) - return log_error_errno(r, "Failed to resolve interface \"%s\": %m", name); - return r; -} - int rtnl_get_link_info( sd_netlink **rtnl, int ifindex, diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index 277b4a30cf..4ba64f0f93 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -19,6 +19,22 @@ typedef struct RouteVia { union in_addr_union address; } _packed_ RouteVia; +int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames); + +typedef enum ResolveInterfaceNameFlag { + RESOLVE_IFNAME_MAIN = 1 << 0, /* resolve main interface name */ + RESOLVE_IFNAME_ALTERNATIVE = 1 << 1, /* resolve alternative name */ + RESOLVE_IFNAME_NUMERIC = 1 << 2, /* resolve decimal formatted ifindex */ + _RESOLVE_IFNAME_ALL = RESOLVE_IFNAME_MAIN | RESOLVE_IFNAME_ALTERNATIVE | RESOLVE_IFNAME_NUMERIC, +} ResolveInterfaceNameFlag; + +int rtnl_resolve_ifname_full( + sd_netlink **rtnl, + ResolveInterfaceNameFlag flags, + const char *name, + char **ret_name, + char ***ret_altnames); + int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_name); int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const* alternative_names); static inline int rtnl_append_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names) { @@ -35,14 +51,32 @@ int rtnl_set_link_properties( uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments); -int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret); +static inline int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret) { + return rtnl_get_ifname_full(rtnl, ifindex, NULL, ret); +} int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names); int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char* const *alternative_names); int rtnl_delete_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names); -int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret); -int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name); -int rtnl_resolve_interface(sd_netlink **rtnl, const char *name); -int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name); +static inline int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret) { + return rtnl_resolve_ifname_full(rtnl, RESOLVE_IFNAME_ALTERNATIVE, name, ret, NULL); +} +static inline int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name) { + return rtnl_resolve_ifname_full(rtnl, RESOLVE_IFNAME_MAIN | RESOLVE_IFNAME_ALTERNATIVE, name, NULL, NULL); +} +static inline int rtnl_resolve_interface(sd_netlink **rtnl, const char *name) { + return rtnl_resolve_ifname_full(rtnl, _RESOLVE_IFNAME_ALL, name, NULL, NULL); +} +static inline int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name) { + int r; + + assert(name); + + r = rtnl_resolve_interface(rtnl, name); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface \"%s\": %m", name); + return r; +} + int rtnl_get_link_info( sd_netlink **rtnl, int ifindex, diff --git a/src/test/test-socket-netlink.c b/src/test/test-socket-netlink.c index ad642ca4b1..1cbfe6d66b 100644 --- a/src/test/test-socket-netlink.c +++ b/src/test/test-socket-netlink.c @@ -248,9 +248,9 @@ TEST(in_addr_ifindex_to_string) { test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", LOOPBACK_IFINDEX, "fe80::%1"); test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 0, "fe80::14"); test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); } @@ -265,9 +265,9 @@ TEST(in_addr_ifindex_from_string_auto) { assert_se(family == AF_INET6); assert_se(ifindex == 0); - assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); + assert_se(in_addr_ifindex_from_string_auto("fe80::18%1", &family, &ua, &ifindex) >= 0); assert_se(family == AF_INET6); - assert_se(ifindex == 19); + assert_se(ifindex == 1); assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); assert_se(family == AF_INET6); @@ -288,8 +288,8 @@ static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const TEST(in_addr_ifindex_name_from_string_auto) { test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL); test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com"); - test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL); - test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com"); + test_in_addr_ifindex_name_from_string_auto_one("fe80::18%1", NULL); + test_in_addr_ifindex_name_from_string_auto_one("fe80::18%1#another.test.com", "another.test.com"); } static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, @@ -356,15 +356,15 @@ TEST(in_addr_port_ifindex_name_from_string_auto) { test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com", NULL); test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL, NULL); test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com", NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%1", AF_INET6, 0, 1, NULL, NULL); test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%lo", AF_INET6, 0, 1, NULL, "fe80::18%1"); test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%1", AF_INET6, 53, 1, NULL, NULL); test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo", AF_INET6, 53, 1, NULL, "[fe80::18]:53%1"); - test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com", NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%1#hoge.com", AF_INET6, 0, 1, "hoge.com", NULL); test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com", NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com", NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%1", AF_INET6, 53, 1, NULL, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%1#hoge.com", AF_INET6, 53, 1, "hoge.com", NULL); test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo", AF_INET6, 53, 1, NULL, "[fe80::18]:53%1"); test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo#hoge.com", AF_INET6, 53, 1, "hoge.com", "[fe80::18]:53%1#hoge.com"); } From 3652891c3904992e21739e9bfb004073841db63c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jan 2024 03:35:06 +0900 Subject: [PATCH 2/3] sd-device: use new interface name resolvers --- src/libsystemd/sd-device/sd-device.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 22b6437823..bfc2a8a9ca 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -345,17 +345,11 @@ _public_ int sd_device_new_from_ifname(sd_device **ret, const char *ifname) { assert_return(ret, -EINVAL); assert_return(ifname, -EINVAL); - r = parse_ifindex(ifname); - if (r > 0) - return sd_device_new_from_ifindex(ret, r); + r = device_new_from_main_ifname(ret, ifname); + if (r >= 0) + return r; - if (ifname_valid(ifname)) { - r = device_new_from_main_ifname(ret, ifname); - if (r >= 0) - return r; - } - - r = rtnl_resolve_link_alternative_name(NULL, ifname, &main_name); + r = rtnl_resolve_ifname_full(NULL, RESOLVE_IFNAME_ALTERNATIVE | RESOLVE_IFNAME_NUMERIC, ifname, &main_name, NULL); if (r < 0) return r; @@ -364,14 +358,15 @@ _public_ int sd_device_new_from_ifname(sd_device **ret, const char *ifname) { _public_ int sd_device_new_from_ifindex(sd_device **ret, int ifindex) { _cleanup_(sd_device_unrefp) sd_device *dev = NULL; - char ifname[IF_NAMESIZE]; + _cleanup_free_ char *ifname = NULL; int r, i; assert_return(ret, -EINVAL); assert_return(ifindex > 0, -EINVAL); - if (format_ifname(ifindex, ifname) < 0) - return -ENODEV; + r = rtnl_get_ifname_full(NULL, ifindex, &ifname, NULL); + if (r < 0) + return r; r = device_new_from_main_ifname(&dev, ifname); if (r < 0) From a342d9e0875704136a7f8c4bf00f46782917e15e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 28 Jan 2024 03:27:41 +0900 Subject: [PATCH 3/3] nspawn: resolve network interface names before moving to container network namespace To escape a kernel issue fixed by https://github.com/torvalds/linux/commit/8e15aee621618a3ee3abecaf1fd8c1428098b7ef, let's resolve provided interface names earlier, and adjust the interface name pairs with the result. Fixes #31104. --- src/nspawn/nspawn-network.c | 82 ++++++++++++++++++------------------- src/nspawn/nspawn-network.h | 1 + src/nspawn/nspawn.c | 4 ++ 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index 151bb1d69a..94e751cf65 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -512,6 +512,38 @@ int test_network_interfaces_initialized(char **iface_pairs) { return 0; } +int resolve_network_interface_names(char **iface_pairs) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r; + + /* Due to a bug in kernel fixed by 8e15aee621618a3ee3abecaf1fd8c1428098b7ef (v6.6, backported to + * 6.1.60 and 6.5.9), an interface with alternative names cannot be resolved by the alternative name + * if the interface is moved to another network namespace. Hence, we need to adjust the provided + * names before moving interfaces to container namespace. */ + + STRV_FOREACH_PAIR(from, to, iface_pairs) { + _cleanup_free_ char *name = NULL; + _cleanup_strv_free_ char **altnames = NULL; + + r = rtnl_resolve_ifname_full(&rtnl, _RESOLVE_IFNAME_ALL, *from, &name, &altnames); + if (r < 0) + return r; + + /* Always use the resolved name for 'from'. */ + free_and_replace(*from, name); + + /* If the name 'to' is assigned as an alternative name, we cannot rename the interface. + * Hence, use the assigned interface name (including the alternative names) as is, and + * use the resolved name for 'to'. */ + if (strv_contains(altnames, *to)) { + r = free_and_strdup_warn(to, *from); + if (r < 0) + return r; + } + } + return 0; +} + static int netns_child_begin(int netns_fd, int *ret_original_netns_fd) { _cleanup_close_ int original_netns_fd = -EBADF; int r; @@ -580,37 +612,6 @@ static int netns_fork_and_wait(int netns_fd, int *ret_original_netns_fd) { return 1; } -static int needs_rename(sd_netlink **rtnl, sd_device *dev, const char *name) { - int r; - - assert(rtnl); - assert(dev); - assert(name); - - const char *ifname; - r = sd_device_get_sysname(dev, &ifname); - if (r < 0) - return r; - - if (streq(name, ifname)) - return false; - - int ifindex; - r = sd_device_get_ifindex(dev, &ifindex); - if (r < 0) - return r; - - _cleanup_strv_free_ char **altnames = NULL; - r = rtnl_get_link_alternative_names(rtnl, ifindex, &altnames); - if (r == -EOPNOTSUPP) - return true; /* alternative interface name is not supported, hence the name is not - * assigned to the interface. */ - if (r < 0) - return r; - - return !strv_contains(altnames, name); -} - static int move_wlan_interface_impl(sd_netlink **genl, int netns_fd, sd_device *dev) { _cleanup_(sd_netlink_unrefp) sd_netlink *our_genl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; @@ -666,12 +667,8 @@ static int move_wlan_interface_one( assert(temp_netns_fd); assert(netns_fd >= 0); assert(dev); - assert(name); - r = needs_rename(rtnl, dev, name); - if (r < 0) - return log_device_error_errno(dev, r, "Failed to determine if the interface should be renamed to '%s': %m", name); - if (r == 0) + if (!name) return move_wlan_interface_impl(genl, netns_fd, dev); /* The command NL80211_CMD_SET_WIPHY_NETNS takes phy instead of network interface, and does not take @@ -728,7 +725,6 @@ static int move_network_interface_one(sd_netlink **rtnl, int netns_fd, sd_device assert(rtnl); assert(netns_fd >= 0); assert(dev); - assert(name); if (!*rtnl) { r = sd_netlink_open(rtnl); @@ -749,10 +745,7 @@ static int move_network_interface_one(sd_netlink **rtnl, int netns_fd, sd_device if (r < 0) return log_device_error_errno(dev, r, "Failed to append namespace fd to netlink message: %m"); - r = needs_rename(rtnl, dev, name); - if (r < 0) - return log_device_error_errno(dev, r, "Failed to determine if the interface should be renamed to '%s': %m", name); - if (r > 0) { + if (name) { r = sd_netlink_message_append_string(m, IFLA_IFNAME, name); if (r < 0) return log_device_error_errno(dev, r, "Failed to add netlink interface name: %m"); @@ -777,15 +770,18 @@ int move_network_interfaces(int netns_fd, char **iface_pairs) { STRV_FOREACH_PAIR(from, to, iface_pairs) { _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + const char *name; + + name = streq(*from, *to) ? NULL : *to; r = sd_device_new_from_ifname(&dev, *from); if (r < 0) return log_error_errno(r, "Unknown interface name %s: %m", *from); if (device_is_devtype(dev, "wlan")) - r = move_wlan_interface_one(&rtnl, &genl, &temp_netns_fd, netns_fd, dev, *to); + r = move_wlan_interface_one(&rtnl, &genl, &temp_netns_fd, netns_fd, dev, name); else - r = move_network_interface_one(&rtnl, netns_fd, dev, *to); + r = move_network_interface_one(&rtnl, netns_fd, dev, name); if (r < 0) return r; } diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h index 9729b6e37e..840fe15527 100644 --- a/src/nspawn/nspawn-network.h +++ b/src/nspawn/nspawn-network.h @@ -8,6 +8,7 @@ #include "ether-addr-util.h" int test_network_interfaces_initialized(char **iface_pairs); +int resolve_network_interface_names(char **iface_pairs); int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge, const struct ether_addr *provided_mac); int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 99e44ec3e5..40127a88a6 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5625,6 +5625,10 @@ static int run(int argc, char *argv[]) { if (r < 0) goto finish; + r = resolve_network_interface_names(arg_network_interfaces); + if (r < 0) + goto finish; + r = verify_network_interfaces_initialized(); if (r < 0) goto finish;