systemd/0404-sd-netlink-make-rtnl_set_link_name-optionally-append.patch

192 lines
8.5 KiB
Diff
Raw Normal View History

From ea5725b1e621c2733c28f818c3a58615a385337e Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 13:29:37 +0900
Subject: [PATCH] sd-netlink: make rtnl_set_link_name() optionally append
alternative names
(cherry picked from commit 81824455008070253c62bf5c27187028ba8e7e99)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/netlink-util.c | 89 ++++++++++++++++++------
src/libsystemd/sd-netlink/netlink-util.h | 5 +-
src/libsystemd/sd-netlink/test-netlink.c | 6 +-
src/udev/udev-event.c | 2 +-
4 files changed, 78 insertions(+), 24 deletions(-)
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index cfcf2578d6..5438737b42 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -11,44 +11,93 @@
#include "process-util.h"
#include "strv.h"
-int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
+static int 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;
- bool altname_deleted = false;
int r;
assert(rtnl);
assert(ifindex > 0);
assert(name);
- if (!ifname_valid(name))
+ /* Assign the requested name. */
+ r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
+ if (r < 0)
+ return r;
+
+ return sd_netlink_call(*rtnl, message, 0, NULL);
+}
+
+int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const *alternative_names) {
+ _cleanup_strv_free_ char **original_altnames = NULL, **new_altnames = NULL;
+ bool altname_deleted = false;
+ int r;
+
+ assert(rtnl);
+ assert(ifindex > 0);
+
+ if (isempty(name) && strv_isempty(alternative_names))
+ return 0;
+
+ if (name && !ifname_valid(name))
return -EINVAL;
- r = rtnl_get_link_alternative_names(rtnl, ifindex, &alternative_names);
+ /* If the requested name is already assigned as an alternative name, then first drop it. */
+ r = rtnl_get_link_alternative_names(rtnl, ifindex, &original_altnames);
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 log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
- name, ifindex);
+ if (name) {
+ if (strv_contains(original_altnames, name)) {
+ r = rtnl_delete_link_alternative_names(rtnl, ifindex, STRV_MAKE(name));
+ if (r < 0)
+ return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
+ name, ifindex);
+
+ altname_deleted = true;
+ }
- altname_deleted = true;
+ r = set_link_name(rtnl, ifindex, name);
+ if (r < 0)
+ goto fail;
}
- r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
- if (r < 0)
- goto fail;
+ /* Filter out already assigned names from requested alternative names. Also, dedup the request. */
+ STRV_FOREACH(a, alternative_names) {
+ if (streq_ptr(name, *a))
+ continue;
- r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
- if (r < 0)
- goto fail;
+ if (strv_contains(original_altnames, *a))
+ continue;
- r = sd_netlink_call(*rtnl, message, 0, NULL);
- if (r < 0)
- goto fail;
+ if (strv_contains(new_altnames, *a))
+ continue;
+
+ if (!ifname_valid_full(*a, IFNAME_VALID_ALTERNATIVE))
+ continue;
+
+ r = strv_extend(&new_altnames, *a);
+ if (r < 0)
+ return r;
+ }
+
+ strv_sort(new_altnames);
+
+ /* Finally, assign alternative names. */
+ r = rtnl_set_link_alternative_names(rtnl, ifindex, new_altnames);
+ if (r == -EEXIST) /* Already assigned to another interface? */
+ STRV_FOREACH(a, new_altnames) {
+ r = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(*a));
+ if (r < 0)
+ log_debug_errno(r, "Failed to assign '%s' as an alternative name on network interface %i, ignoring: %m",
+ *a, ifindex);
+ }
+ else if (r < 0)
+ log_debug_errno(r, "Failed to assign alternative names on network interface %i, ignoring: %m", ifindex);
return 0;
diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h
index d14392a018..888e28642d 100644
--- a/src/libsystemd/sd-netlink/netlink-util.h
+++ b/src/libsystemd/sd-netlink/netlink-util.h
@@ -29,7 +29,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free);
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret);
-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, char* const* alternative_names);
+static inline int rtnl_append_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names) {
+ return rtnl_set_link_name(rtnl, ifindex, NULL, alternative_names);
+}
int rtnl_set_link_properties(
sd_netlink **rtnl,
int ifindex,
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index 9ad8ecf320..43124b99ae 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -662,12 +662,13 @@ TEST(rtnl_set_link_name) {
assert_se(strv_contains(alternative_names, "testlongalternativename"));
assert_se(strv_contains(alternative_names, "test-shortname"));
- assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename") == -EINVAL);
- assert_se(rtnl_set_link_name(&rtnl, ifindex, "test-shortname") >= 0);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename", NULL) == -EINVAL);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "test-shortname", STRV_MAKE("testlongalternativename", "test-shortname", "test-additional-name")) >= 0);
alternative_names = strv_free(alternative_names);
assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
assert_se(strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(strv_contains(alternative_names, "test-additional-name"));
assert_se(!strv_contains(alternative_names, "test-shortname"));
assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
@@ -675,6 +676,7 @@ TEST(rtnl_set_link_name) {
alternative_names = strv_free(alternative_names);
assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
assert_se(!strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(strv_contains(alternative_names, "test-additional-name"));
assert_se(!strv_contains(alternative_names, "test-shortname"));
}
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index cf90d6f205..2662806d61 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -980,7 +980,7 @@ static int rename_netif(UdevEvent *event) {
goto revert;
}
- r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
+ r = rtnl_set_link_name(&event->rtnl, ifindex, event->name, NULL);
if (r < 0) {
if (r == -EBUSY) {
log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",