]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev/net: assign alternative names only on add uevent
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 16 May 2023 03:28:23 +0000 (12:28 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 16 May 2023 07:37:31 +0000 (16:37 +0900)
Previously, we first assign alternative names to a network interface,
then later change its main name if requested. So, we could not assign
the name that currently assigned as the main name of an interface as an
alternative name. So, we retry to assign the previous main name as an
alternative name on later move uevent.

However, that causes some confusing situation. E.g. if a .link file has
```
Name=foo
AlternativeNames=foo baz
```
then even if the interface is renamed by a user e.g. by invoking 'ip link'
command manually, the interface can be still referenced as 'foo', as the
name is now assigned as an alternative name.

This makes the order of name assignment inverse: the main name is first
changed, and then the requested alternative names are assigned. And
udevd do not assign alternative names on move uevent.

Replaces #27506.

src/udev/net/link-config.c
src/udev/net/link-config.h
src/udev/udev-builtin-net_setup_link.c
src/udev/udev-event.c
src/udev/udev-event.h

index 28571319fcabd5d2fa57b12eecf28ee0cd6ee4df..b554a6827d4ff5684eac69a547e18fdb23651400 100644 (file)
@@ -365,6 +365,7 @@ Link *link_free(Link *link) {
         sd_device_unref(link->device);
         free(link->kind);
         free(link->driver);
+        strv_free(link->altnames);
         return mfree(link);
 }
 
@@ -793,19 +794,22 @@ no_rename:
         return 0;
 }
 
-static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
-        _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL;
+static int link_generate_alternative_names(Link *link) {
+        _cleanup_strv_free_ char **altnames = NULL;
         LinkConfig *config;
         sd_device *device;
         int r;
 
         assert(link);
-        assert(link->config);
-        assert(link->device);
-        assert(rtnl);
+        config = ASSERT_PTR(link->config);
+        device = ASSERT_PTR(link->device);
+        assert(!link->altnames);
 
-        config = link->config;
-        device = link->device;
+        if (link->action != SD_DEVICE_ADD) {
+                log_link_debug(link, "Skipping to apply AlternativeNames= and AlternativeNamesPolicy= on '%s' uevent.",
+                               device_action_to_string(link->action));
+                return 0;
+        }
 
         if (config->alternative_names) {
                 altnames = strv_copy(config->alternative_names);
@@ -843,22 +847,7 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
                         }
                 }
 
-        strv_remove(altnames, link->ifname);
-
-        r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames);
-        if (r < 0)
-                log_link_debug_errno(link, r, "Failed to get alternative names, ignoring: %m");
-
-        STRV_FOREACH(p, current_altnames)
-                strv_remove(altnames, *p);
-
-        strv_uniq(altnames);
-        strv_sort(altnames);
-        r = rtnl_set_link_alternative_names(rtnl, link->ifindex, altnames);
-        if (r < 0)
-                log_link_full_errno(link, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r,
-                                    "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
-
+        link->altnames = TAKE_PTR(altnames);
         return 0;
 }
 
@@ -960,7 +949,7 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
         if (r < 0)
                 return r;
 
-        r = link_apply_alternative_names(link, rtnl);
+        r = link_generate_alternative_names(link);
         if (r < 0)
                 return r;
 
index ed0896e9dee83b4b8ea085b9de0326a492ca82c4..713d41040a6b5d224f73bf4b9ed00d2339fdd1bb 100644 (file)
@@ -27,6 +27,7 @@ typedef struct Link {
         int ifindex;
         const char *ifname;
         const char *new_name;
+        char **altnames;
 
         LinkConfig *config;
         sd_device *device;
index 84a0a6ef3fbe15fc08abf03c5f300c22f62ad996..5bc965f6d809e6b5331a2ed3a9a2ad8eee0eb986 100644 (file)
@@ -52,6 +52,8 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool
         if (link->new_name)
                 udev_builtin_add_property(dev, test, "ID_NET_NAME", link->new_name);
 
+        event->altnames = TAKE_PTR(link->altnames);
+
         STRV_FOREACH(d, link->config->dropins) {
                 _cleanup_free_ char *escaped = NULL;
 
index 7f6d8e4a752aa9619885d0c1e5a70eb8ac36c07d..b3cdb32a63fd10785d74794b65ce615e5b0dc830 100644 (file)
@@ -87,6 +87,7 @@ UdevEvent *udev_event_free(UdevEvent *event) {
         ordered_hashmap_free_free_free(event->seclabel_list);
         free(event->program_result);
         free(event->name);
+        strv_free(event->altnames);
 
         return mfree(event);
 }
@@ -914,9 +915,6 @@ static int rename_netif(UdevEvent *event) {
 
         dev = ASSERT_PTR(event->dev);
 
-        if (!device_for_action(dev, SD_DEVICE_ADD))
-                return 0; /* Rename the interface only when it is added. */
-
         r = sd_device_get_ifindex(dev, &ifindex);
         if (r == -ENOENT)
                 return 0; /* Device is not a network interface. */
@@ -976,7 +974,7 @@ static int rename_netif(UdevEvent *event) {
                 goto revert;
         }
 
-        r = rtnl_set_link_name(&event->rtnl, ifindex, event->name, NULL);
+        r = rtnl_set_link_name(&event->rtnl, ifindex, event->name, event->altnames);
         if (r < 0) {
                 if (r == -EBUSY) {
                         log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",
@@ -1007,6 +1005,35 @@ revert:
         return r;
 }
 
+static int assign_altnames(UdevEvent *event) {
+        sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+        int ifindex, r;
+        const char *s;
+
+        if (strv_isempty(event->altnames))
+                return 0;
+
+        r = sd_device_get_ifindex(dev, &ifindex);
+        if (r == -ENOENT)
+                return 0; /* Device is not a network interface. */
+        if (r < 0)
+                return log_device_warning_errno(dev, r, "Failed to get ifindex: %m");
+
+        r = sd_device_get_sysname(dev, &s);
+        if (r < 0)
+                return log_device_warning_errno(dev, r, "Failed to get sysname: %m");
+
+        /* Filter out the current interface name. */
+        strv_remove(event->altnames, s);
+
+        r = rtnl_append_link_alternative_names(&event->rtnl, ifindex, event->altnames);
+        if (r < 0)
+                log_device_full_errno(dev, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r,
+                                      "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
+
+        return 0;
+}
+
 static int update_devnode(UdevEvent *event) {
         sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
         int r;
@@ -1148,9 +1175,13 @@ int udev_event_execute_rules(
 
         DEVICE_TRACE_POINT(rules_finished, dev);
 
-        r = rename_netif(event);
-        if (r < 0)
-                return r;
+        if (action == SD_DEVICE_ADD) {
+                r = rename_netif(event);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        (void) assign_altnames(event);
+        }
 
         r = update_devnode(event);
         if (r < 0)
index c54c7891b61e094e21693c9efd352bcd807c9058..b99559ca2ee1a76e92b33de283c4aa3037ab1cde 100644 (file)
@@ -22,6 +22,7 @@ typedef struct UdevEvent {
         sd_device *dev_parent;
         sd_device *dev_db_clone;
         char *name;
+        char **altnames;
         char *program_result;
         mode_t mode;
         uid_t uid;