From 14982526145de84201c7e3b4fc6be6aa5e9a08f7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 17 Jul 2020 21:29:13 +0900 Subject: [PATCH 1/3] netlink: introduce rtnl_get/delete_link_alternative_names() --- src/libsystemd/sd-netlink/netlink-util.c | 45 ++++++++++++++++++++++-- src/libsystemd/sd-netlink/netlink-util.h | 2 ++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 7387cffaa3..83f2a9b926 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -85,12 +85,45 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, return 0; } -int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names) { +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, int ifindex, char * const *alternative_names) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; int r; assert(rtnl); assert(ifindex > 0); + assert(IN_SET(nlmsg_type, RTM_NEWLINKPROP, RTM_DELLINKPROP)); if (strv_isempty(alternative_names)) return 0; @@ -101,7 +134,7 @@ int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const return r; } - r = sd_rtnl_message_new_link(*rtnl, &message, RTM_NEWLINKPROP, ifindex); + r = sd_rtnl_message_new_link(*rtnl, &message, nlmsg_type, ifindex); if (r < 0) return r; @@ -124,6 +157,14 @@ int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const return 0; } +int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names) { + return rtnl_update_link_alternative_names(rtnl, RTM_NEWLINKPROP, ifindex, alternative_names); +} + +int rtnl_delete_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names) { + return rtnl_update_link_alternative_names(rtnl, RTM_DELLINKPROP, ifindex, alternative_names); +} + int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; int r; diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h index 8ed94063e3..04e6a98e6b 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -53,8 +53,10 @@ static inline bool rtnl_message_type_is_tclass(uint16_t type) { int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name); int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu); +int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***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); int rtnl_get_link_iftype(sd_netlink **rtnl, int ifindex, unsigned short *ret); From 434a34838034347f45fb9a47df55b1a36e5addfd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 17 Jul 2020 21:31:24 +0900 Subject: [PATCH 2/3] netlink: do not fail when new interface name is already used as an alternative name When renaming a network interface, the new name may be used as an alternative name. In that case, let's swap the current name and the alternative name. That is, first drop the new name from the list of alternative names, then rename the interface, finally set the old name as an alternative name. --- src/libsystemd/sd-netlink/netlink-util.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 83f2a9b926..a6ea5eb6d5 100644 --- a/src/libsystemd/sd-netlink/netlink-util.c +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -2,6 +2,7 @@ #include "sd-netlink.h" +#include "format-util.h" #include "memory-util.h" #include "netlink-internal.h" #include "netlink-util.h" @@ -9,6 +10,8 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; + _cleanup_strv_free_ char **alternative_names = NULL; + char old_name[IF_NAMESIZE + 1] = {}; int r; assert(rtnl); @@ -18,10 +21,18 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { if (!ifname_valid(name)) return -EINVAL; - if (!*rtnl) { - r = sd_netlink_open(rtnl); + r = rtnl_get_link_alternative_names(rtnl, ifindex, &alternative_names); + if (r < 0) + log_debug_errno(r, "Failed to get alternative names on network interface %i, ignoring: %m", + ifindex); + + if (strv_contains(alternative_names, name)) { + r = rtnl_delete_link_alternative_names(rtnl, ifindex, STRV_MAKE(name)); if (r < 0) - return r; + return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m", + name, ifindex); + + format_ifname(ifindex, old_name); } r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); @@ -36,6 +47,13 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { if (r < 0) return r; + if (!isempty(old_name)) { + r = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(old_name)); + if (r < 0) + log_debug_errno(r, "Failed to set '%s' as an alternative name on network interface %i, ignoring: %m", + old_name, ifindex); + } + return 0; } From 97fdae33dfe8e7e0a4e5230564f6cdebc4450eec Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 17 Jul 2020 21:36:05 +0900 Subject: [PATCH 3/3] udev: do not try to reassign alternative names Setting alternative names may fail if some of them are already assigned. --- src/udev/net/link-config.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 39bdfb73dd..72ef0c56be 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -358,7 +358,7 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr int link_config_apply(link_config_ctx *ctx, link_config *config, sd_device *device, const char **name) { - _cleanup_strv_free_ char **altnames = NULL; + _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL; struct ether_addr generated_mac; struct ether_addr *mac = NULL; const char *new_name = NULL; @@ -539,9 +539,17 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, if (new_name) strv_remove(altnames, new_name); strv_remove(altnames, old_name); + + r = rtnl_get_link_alternative_names(&ctx->rtnl, ifindex, ¤t_altnames); + if (r < 0) + log_debug_errno(r, "Failed to get alternative names on %s, ignoring: %m", old_name); + + char **p; + STRV_FOREACH(p, current_altnames) + strv_remove(altnames, *p); + strv_uniq(altnames); strv_sort(altnames); - r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, altnames); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not set AlternativeName= or apply AlternativeNamesPolicy= on %s, ignoring: %m", old_name);