1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-22 13:33:56 +03:00

Merge pull request #25221 from enr0n/nic-rename-fallback

udev: set link alternative name if link is already up during rename
This commit is contained in:
Luca Boccassi 2022-12-17 14:51:39 +01:00 committed by GitHub
commit 2c99e8c6e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 28 deletions

View File

@ -3,7 +3,6 @@
#include "sd-netlink.h" #include "sd-netlink.h"
#include "fd-util.h" #include "fd-util.h"
#include "format-util.h"
#include "io-util.h" #include "io-util.h"
#include "memory-util.h" #include "memory-util.h"
#include "netlink-internal.h" #include "netlink-internal.h"
@ -15,7 +14,7 @@
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
_cleanup_strv_free_ char **alternative_names = NULL; _cleanup_strv_free_ char **alternative_names = NULL;
char old_name[IF_NAMESIZE] = {}; bool altname_deleted = false;
int r; int r;
assert(rtnl); 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", return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
name, ifindex); name, ifindex);
r = format_ifname(ifindex, old_name); altname_deleted = true;
if (r < 0)
return log_debug_errno(r, "Failed to get current name of network interface %i: %m", ifindex);
} }
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
if (r < 0) if (r < 0)
return r; goto fail;
r = sd_netlink_message_append_string(message, IFLA_IFNAME, name); r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
if (r < 0) if (r < 0)
return r; goto fail;
r = sd_netlink_call(*rtnl, message, 0, NULL); r = sd_netlink_call(*rtnl, message, 0, NULL);
if (r < 0) 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; 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 r;
} }
int rtnl_set_link_properties( int rtnl_set_link_properties(

View File

@ -8,6 +8,7 @@
#include <linux/if_macsec.h> #include <linux/if_macsec.h>
#include <linux/l2tp.h> #include <linux/l2tp.h>
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include <unistd.h>
#include "sd-netlink.h" #include "sd-netlink.h"
@ -16,6 +17,7 @@
#include "macro.h" #include "macro.h"
#include "netlink-genl.h" #include "netlink-genl.h"
#include "netlink-internal.h" #include "netlink-internal.h"
#include "netlink-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-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) { int main(void) {
sd_netlink *rtnl; sd_netlink *rtnl;
sd_netlink_message *m; sd_netlink_message *m;
@ -698,6 +724,7 @@ int main(void) {
test_pipe(if_loopback); test_pipe(if_loopback);
test_event_loop(if_loopback); test_event_loop(if_loopback);
test_link_configure(rtnl, if_loopback); test_link_configure(rtnl, if_loopback);
test_rtnl_set_link_name(rtnl, if_loopback);
test_get_addresses(rtnl); test_get_addresses(rtnl);
test_message_link_bridge(rtnl); test_message_link_bridge(rtnl);

View File

@ -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); strv_remove(altnames, link->ifname);
r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames); r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames);

View File

@ -862,7 +862,6 @@ int udev_event_spawn(
static int rename_netif(UdevEvent *event) { static int rename_netif(UdevEvent *event) {
const char *oldname; const char *oldname;
sd_device *dev; sd_device *dev;
unsigned flags;
int ifindex, r; int ifindex, r;
assert(event); assert(event);
@ -896,16 +895,6 @@ static int rename_netif(UdevEvent *event) {
return 0; 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. */ /* 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"); r = device_add_property(dev, "ID_RENAMING", "1");
if (r < 0) 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"); 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); 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) if (r < 0)
return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m", return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
ifindex, oldname, event->name); ifindex, oldname, event->name);

View File

@ -0,0 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Match]
OriginalName=dummy98
[Link]
Name=dummyalt
AlternativeName=dummyalt hogehogehogehogehogehoge

View File

@ -933,6 +933,17 @@ class NetworkctlTests(unittest.TestCase, Utilities):
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env) output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
self.assertRegex(output, 'hogehogehogehogehogehoge') self.assertRegex(output, 'hogehogehogehogehogehoge')
@expectedFailureIfAlternativeNameIsNotAvailable()
def test_rename_to_altname(self):
copy_network_unit('26-netdev-link-local-addressing-yes.network',
'12-dummy.netdev', '12-dummy-rename-to-altname.link')
start_networkd()
self.wait_online(['dummyalt:degraded'])
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummyalt', env=env)
self.assertIn('hogehogehogehogehogehoge', output)
self.assertNotIn('dummy98', output)
def test_reconfigure(self): def test_reconfigure(self):
copy_network_unit('25-address-static.network', '12-dummy.netdev') copy_network_unit('25-address-static.network', '12-dummy.netdev')
start_networkd() start_networkd()