a8c905
From 6db267672de69d6bf4809f433cde106e11145ca8 Mon Sep 17 00:00:00 2001
a8c905
From: Yu Watanabe <watanabe.yu+github@gmail.com>
a8c905
Date: Fri, 17 Jul 2020 21:31:24 +0900
a8c905
Subject: [PATCH] netlink: do not fail when new interface name is already used
a8c905
 as an alternative name
a8c905
a8c905
When renaming a network interface, the new name may be used as an
a8c905
alternative name. In that case, let's swap the current name and the
a8c905
alternative name. That is, first drop the new name from the list of
a8c905
alternative names, then rename the interface, finally set the old name
a8c905
as an alternative name.
a8c905
a8c905
(cherry picked from commit 434a34838034347f45fb9a47df55b1a36e5addfd)
a8c905
a8c905
Related: #1850986
a8c905
---
a8c905
 src/libsystemd/sd-netlink/netlink-util.c | 30 +++++++++++++++++++++---
a8c905
 1 file changed, 27 insertions(+), 3 deletions(-)
a8c905
a8c905
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
a8c905
index 7f09261981..4e42ef9e26 100644
a8c905
--- a/src/libsystemd/sd-netlink/netlink-util.c
a8c905
+++ b/src/libsystemd/sd-netlink/netlink-util.c
a8c905
@@ -1,23 +1,40 @@
a8c905
 /* SPDX-License-Identifier: LGPL-2.1+ */
a8c905
 
a8c905
+#include <net/if.h>
a8c905
+
a8c905
 #include "sd-netlink.h"
a8c905
 
a8c905
 #include "netlink-internal.h"
a8c905
 #include "netlink-util.h"
a8c905
+#include "socket-util.h"
a8c905
+#include "string-util.h"
a8c905
 #include "strv.h"
a8c905
 
a8c905
 int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
a8c905
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
a8c905
+        _cleanup_strv_free_ char **alternative_names = NULL;
a8c905
+        char old_name[IF_NAMESIZE + 1] = {};
a8c905
         int r;
a8c905
 
a8c905
         assert(rtnl);
a8c905
         assert(ifindex > 0);
a8c905
         assert(name);
a8c905
 
a8c905
-        if (!*rtnl) {
a8c905
-                r = sd_netlink_open(rtnl);
a8c905
+        if (!ifname_valid(name))
a8c905
+                return -EINVAL;
a8c905
+
a8c905
+        r = rtnl_get_link_alternative_names(rtnl, ifindex, &alternative_names);
a8c905
+        if (r < 0)
a8c905
+                log_debug_errno(r, "Failed to get alternative names on network interface %i, ignoring: %m",
a8c905
+                                ifindex);
a8c905
+
a8c905
+        if (strv_contains(alternative_names, name)) {
a8c905
+                r = rtnl_delete_link_alternative_names(rtnl, ifindex, STRV_MAKE(name));
a8c905
                 if (r < 0)
a8c905
-                        return r;
a8c905
+                        return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
a8c905
+                                               name, ifindex);
a8c905
+
a8c905
+                if_indextoname(ifindex, old_name);
a8c905
         }
a8c905
 
a8c905
         r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
a8c905
@@ -32,6 +49,13 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
a8c905
         if (r < 0)
a8c905
                 return r;
a8c905
 
a8c905
+        if (!isempty(old_name)) {
a8c905
+                r = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(old_name));
a8c905
+                if (r < 0)
a8c905
+                        log_debug_errno(r, "Failed to set '%s' as an alternative name on network interface %i, ignoring: %m",
a8c905
+                                        old_name, ifindex);
a8c905
+        }
a8c905
+
a8c905
         return 0;
a8c905
 }
a8c905