summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2022-12-17 14:51:39 +0100
committerGitHub <noreply@github.com>2022-12-17 14:51:39 +0100
commit2c99e8c6e0ccdd147cd6e7a60be255c6a5cd1da9 (patch)
treef424cb35f7cb252c61aece3c356274854b1cefbf /src
parent896785a7d9cabc4b6df707ba95d831382749764e (diff)
parentf68f644a167af3452be853b631fa9144c6716c28 (diff)
downloadsystemd-2c99e8c6e0ccdd147cd6e7a60be255c6a5cd1da9.tar.gz
Merge pull request #25221 from enr0n/nic-rename-fallback
udev: set link alternative name if link is already up during rename
Diffstat (limited to 'src')
-rw-r--r--src/libsystemd/sd-netlink/netlink-util.c28
-rw-r--r--src/libsystemd/sd-netlink/test-netlink.c27
-rw-r--r--src/udev/net/link-config.c2
-rw-r--r--src/udev/udev-event.c16
4 files changed, 46 insertions, 27 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index c6091542d2..af601bd347 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -3,7 +3,6 @@
#include "sd-netlink.h"
#include "fd-util.h"
-#include "format-util.h"
#include "io-util.h"
#include "memory-util.h"
#include "netlink-internal.h"
@@ -15,7 +14,7 @@
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] = {};
+ bool altname_deleted = false;
int r;
assert(rtnl);
@@ -36,31 +35,32 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
name, ifindex);
- r = format_ifname(ifindex, old_name);
- if (r < 0)
- return log_debug_errno(r, "Failed to get current name of network interface %i: %m", ifindex);
+ altname_deleted = true;
}
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
if (r < 0)
- return r;
+ goto fail;
r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
if (r < 0)
- return r;
+ goto fail;
r = sd_netlink_call(*rtnl, message, 0, NULL);
if (r < 0)
- return r;
+ goto fail;
- 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;
+
+fail:
+ if (altname_deleted) {
+ int q = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(name));
+ if (q < 0)
+ log_debug_errno(q, "Failed to restore '%s' as an alternative name on network interface %i, ignoring: %m",
+ name, ifindex);
}
- return 0;
+ return r;
}
int rtnl_set_link_properties(
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index 3f74ecc068..2d93f9eba0 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -8,6 +8,7 @@
#include <linux/if_macsec.h>
#include <linux/l2tp.h>
#include <linux/nl80211.h>
+#include <unistd.h>
#include "sd-netlink.h"
@@ -16,6 +17,7 @@
#include "macro.h"
#include "netlink-genl.h"
#include "netlink-internal.h"
+#include "netlink-util.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -667,6 +669,30 @@ static void test_genl(void) {
}
}
+static void test_rtnl_set_link_name(sd_netlink *rtnl, int ifindex) {
+ _cleanup_strv_free_ char **alternative_names = NULL;
+ int r;
+
+ log_debug("/* %s */", __func__);
+
+ if (geteuid() != 0)
+ return (void) log_tests_skipped("not root");
+
+ /* Test that the new name (which is currently an alternative name) is
+ * restored as an alternative name on error. Create an error by using
+ * an invalid device name, namely one that exceeds IFNAMSIZ
+ * (alternative names can exceed IFNAMSIZ, but not regular names). */
+ r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename"));
+ if (r == -EPERM)
+ return (void) log_tests_skipped("missing required capabilities");
+
+ assert_se(r >= 0);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename") == -EINVAL);
+ assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
+ assert_se(strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
+}
+
int main(void) {
sd_netlink *rtnl;
sd_netlink_message *m;
@@ -698,6 +724,7 @@ int main(void) {
test_pipe(if_loopback);
test_event_loop(if_loopback);
test_link_configure(rtnl, if_loopback);
+ test_rtnl_set_link_name(rtnl, if_loopback);
test_get_addresses(rtnl);
test_message_link_bridge(rtnl);
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 1fbfc58c0d..25edb49d28 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -841,8 +841,6 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
}
}
- if (link->new_name)
- strv_remove(altnames, link->new_name);
strv_remove(altnames, link->ifname);
r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 30326e4d1c..63be5275e4 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -862,7 +862,6 @@ int udev_event_spawn(
static int rename_netif(UdevEvent *event) {
const char *oldname;
sd_device *dev;
- unsigned flags;
int ifindex, r;
assert(event);
@@ -896,16 +895,6 @@ static int rename_netif(UdevEvent *event) {
return 0;
}
- r = rtnl_get_link_info(&event->rtnl, ifindex, NULL, &flags, NULL, NULL, NULL);
- if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to get link flags: %m");
-
- if (FLAGS_SET(flags, IFF_UP)) {
- log_device_info(dev, "Network interface '%s' is already up, refusing to rename to '%s'.",
- oldname, event->name);
- return 0;
- }
-
/* Set ID_RENAMING boolean property here. It will be dropped when the corresponding move uevent is processed. */
r = device_add_property(dev, "ID_RENAMING", "1");
if (r < 0)
@@ -927,6 +916,11 @@ static int rename_netif(UdevEvent *event) {
return log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
+ if (r == -EBUSY) {
+ log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",
+ oldname, event->name);
+ return 0;
+ }
if (r < 0)
return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
ifindex, oldname, event->name);