diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-05-17 01:39:40 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-17 01:39:40 +0900 |
commit | 8c7dd49ad1c936bfff8f976f61cfcb7037c48103 (patch) | |
tree | 951c2d9221c7e71f2453da849a7d1af9eea7428b | |
parent | a5a4d5a18e6270b3623dc5c48f1c61344f1d0555 (diff) | |
parent | 40b6b448bda5294582e685091123952fbcd43502 (diff) | |
download | systemd-8c7dd49ad1c936bfff8f976f61cfcb7037c48103.tar.gz |
Merge pull request #27655 from yuwata/udev-net-assign-alternative-names-only-on-add-event
udev/net: assign alternative names only on add event
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-util.c | 89 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-util.h | 5 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/test-netlink.c | 6 | ||||
-rw-r--r-- | src/udev/net/link-config.c | 41 | ||||
-rw-r--r-- | src/udev/net/link-config.h | 1 | ||||
-rw-r--r-- | src/udev/udev-builtin-blkid.c | 3 | ||||
-rw-r--r-- | src/udev/udev-builtin-btrfs.c | 3 | ||||
-rw-r--r-- | src/udev/udev-builtin-hwdb.c | 3 | ||||
-rw-r--r-- | src/udev/udev-builtin-input_id.c | 6 | ||||
-rw-r--r-- | src/udev/udev-builtin-keyboard.c | 3 | ||||
-rw-r--r-- | src/udev/udev-builtin-kmod.c | 5 | ||||
-rw-r--r-- | src/udev/udev-builtin-net_id.c | 3 | ||||
-rw-r--r-- | src/udev/udev-builtin-net_setup_link.c | 9 | ||||
-rw-r--r-- | src/udev/udev-builtin-path_id.c | 5 | ||||
-rw-r--r-- | src/udev/udev-builtin-uaccess.c | 3 | ||||
-rw-r--r-- | src/udev/udev-builtin-usb_id.c | 5 | ||||
-rw-r--r-- | src/udev/udev-builtin.c | 7 | ||||
-rw-r--r-- | src/udev/udev-builtin.h | 5 | ||||
-rw-r--r-- | src/udev/udev-event.c | 47 | ||||
-rw-r--r-- | src/udev/udev-event.h | 1 | ||||
-rw-r--r-- | src/udev/udev-rules.c | 2 | ||||
-rw-r--r-- | src/udev/udevadm-test-builtin.c | 13 | ||||
-rwxr-xr-x | test/units/testsuite-17.12.sh | 86 |
23 files changed, 262 insertions, 89 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c index 6cd916a209..6ded66b935 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 72d16fa9a9..2f9f7e9676 100644 --- a/src/libsystemd/sd-netlink/netlink-util.h +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -28,7 +28,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/net/link-config.c b/src/udev/net/link-config.c index 4c83eede7a..b554a6827d 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -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); } @@ -724,7 +725,7 @@ static int link_generate_new_name(Link *link) { config = link->config; device = link->device; - if (link->action == SD_DEVICE_MOVE) { + if (link->action != SD_DEVICE_ADD) { log_link_debug(link, "Skipping to apply Name= and NamePolicy= on '%s' uevent.", device_action_to_string(link->action)); goto no_rename; @@ -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); @@ -836,29 +840,14 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) { default: assert_not_reached(); } - if (!isempty(n)) { + if (ifname_valid_full(n, IFNAME_VALID_ALTERNATIVE)) { r = strv_extend(&altnames, n); if (r < 0) return log_oom(); } } - strv_remove(altnames, link->ifname); - - r = rtnl_get_link_alternative_names(rtnl, link->ifindex, ¤t_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; diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index ed0896e9de..713d41040a 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -27,6 +27,7 @@ typedef struct Link { int ifindex; const char *ifname; const char *new_name; + char **altnames; LinkConfig *config; sd_device *device; diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index 2b2205513b..11419a3e61 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -315,7 +315,8 @@ notloop: return 0; } -static int builtin_blkid(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); const char *devnode, *root_partition = NULL, *data, *name; _cleanup_(blkid_free_probep) blkid_probe pr = NULL; _cleanup_free_ char *backing_fname = NULL; diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c index 79f91ea2ae..9b12aebb3a 100644 --- a/src/udev/udev-builtin-btrfs.c +++ b/src/udev/udev-builtin-btrfs.c @@ -12,7 +12,8 @@ #include "strxcpyx.h" #include "udev-builtin.h" -static int builtin_btrfs(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); struct btrfs_ioctl_vol_args args = {}; _cleanup_close_ int fd = -EBADF; int r; diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c index 8d652e46fe..19e07e734f 100644 --- a/src/udev/udev-builtin-hwdb.c +++ b/src/udev/udev-builtin-hwdb.c @@ -118,7 +118,7 @@ next: return r; } -static int builtin_hwdb(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) { static const struct option options[] = { { "filter", required_argument, NULL, 'f' }, { "device", required_argument, NULL, 'd' }, @@ -131,6 +131,7 @@ static int builtin_hwdb(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[ const char *subsystem = NULL; const char *prefix = NULL; _cleanup_(sd_device_unrefp) sd_device *srcdev = NULL; + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); int r; if (!hwdb) diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c index 540f390530..295e8d2159 100644 --- a/src/udev/udev-builtin-input_id.c +++ b/src/udev/udev-builtin-input_id.c @@ -369,8 +369,8 @@ static bool test_key(sd_device *dev, return found; } -static int builtin_input_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { - sd_device *pdev; +static int builtin_input_id(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *pdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; @@ -380,8 +380,6 @@ static int builtin_input_id(sd_device *dev, sd_netlink **rtnl, int argc, char *a bool is_pointer; bool is_key; - assert(dev); - /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ for (pdev = dev; pdev; ) { diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c index 80cfdee0c1..da67c2be1c 100644 --- a/src/udev/udev-builtin-keyboard.c +++ b/src/udev/udev-builtin-keyboard.c @@ -159,7 +159,8 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) { return 0; } -static int builtin_keyboard(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_keyboard(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); unsigned release[1024]; unsigned release_count = 0; _cleanup_close_ int fd = -EBADF; diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c index eade042f35..3ab5c485f8 100644 --- a/src/udev/udev-builtin-kmod.c +++ b/src/udev/udev-builtin-kmod.c @@ -22,11 +22,10 @@ _printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *fi log_internalv(priority, 0, file, line, fn, format, args); } -static int builtin_kmod(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_kmod(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); int r; - assert(dev); - if (!ctx) return 0; diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 5e2b69d6f7..998478ec4e 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -1096,7 +1096,8 @@ static int get_link_info(sd_device *dev, LinkInfo *info) { return 0; } -static int builtin_net_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); const char *prefix; NetNames names = {}; LinkInfo info = {}; diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c index 18450536b5..5bc965f6d8 100644 --- a/src/udev/udev-builtin-net_setup_link.c +++ b/src/udev/udev-builtin-net_setup_link.c @@ -12,7 +12,8 @@ static LinkConfigContext *ctx = NULL; -static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, char **argv, bool test) { +static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); _cleanup_(link_freep) Link *link = NULL; _cleanup_free_ char *joined = NULL; int r; @@ -20,7 +21,7 @@ static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, c if (argc > 1) return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); - r = link_new(ctx, rtnl, dev, &link); + r = link_new(ctx, &event->rtnl, dev, &link); if (r == -ENODEV) { log_device_debug_errno(dev, r, "Link vanished while getting information, ignoring."); return 0; @@ -41,7 +42,7 @@ static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, c return log_device_error_errno(dev, r, "Failed to get link config: %m"); } - r = link_apply_config(ctx, rtnl, link); + r = link_apply_config(ctx, &event->rtnl, link); if (r == -ENODEV) log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring."); else if (r < 0) @@ -51,6 +52,8 @@ static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, c 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; diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index ff6682cad9..404196f409 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -589,15 +589,14 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) { return 0; } -static int builtin_path_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); _cleanup_(sd_device_unrefp) sd_device *dev_other_branch = NULL; _cleanup_free_ char *path = NULL, *compat_path = NULL; bool supported_transport = false, supported_parent = false; const char *subsystem; int r; - assert(dev); - /* walk up the chain of devices and compose path */ for (sd_device *parent = dev; parent; ) { const char *subsys, *sysname; diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c index 6e73d99375..36c993cbb0 100644 --- a/src/udev/udev-builtin-uaccess.c +++ b/src/udev/udev-builtin-uaccess.c @@ -16,7 +16,8 @@ #include "log.h" #include "udev-builtin.h" -static int builtin_uaccess(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_uaccess(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); const char *path = NULL, *seat; bool changed_acl = false; uid_t uid; diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c index 91deb64292..8e83c9c342 100644 --- a/src/udev/udev-builtin-usb_id.c +++ b/src/udev/udev-builtin-usb_id.c @@ -224,7 +224,8 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) { * 6.) If the device supplies a serial number, this number * is concatenated with the identification with an underscore '_'. */ -static int builtin_usb_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) { +static int builtin_usb_id(UdevEvent *event, int argc, char *argv[], bool test) { + sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev); char vendor_str[64] = ""; char vendor_str_enc[256]; const char *vendor_id; @@ -250,8 +251,6 @@ static int builtin_usb_id(sd_device *dev, sd_netlink **rtnl, int argc, char *arg const char *syspath, *sysname, *devtype, *interface_syspath; int r; - assert(dev); - r = sd_device_get_syspath(dev, &syspath); if (r < 0) return r; diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c index 566641e400..a8dd656b00 100644 --- a/src/udev/udev-builtin.c +++ b/src/udev/udev-builtin.c @@ -98,11 +98,12 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) { return _UDEV_BUILTIN_INVALID; } -int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, const char *command, bool test) { +int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test) { _cleanup_strv_free_ char **argv = NULL; int r; - assert(dev); + assert(event); + assert(event->dev); assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); assert(command); @@ -115,7 +116,7 @@ int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, /* we need '0' here to reset the internal state */ optind = 0; - return builtins[cmd]->cmd(dev, rtnl, strv_length(argv), argv, test); + return builtins[cmd]->cmd(event, strv_length(argv), argv, test); } int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val) { diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h index 490b2dbe96..b2cf81ad31 100644 --- a/src/udev/udev-builtin.h +++ b/src/udev/udev-builtin.h @@ -7,6 +7,7 @@ #include "sd-netlink.h" #include "macro.h" +#include "udev-event.h" typedef enum UdevBuiltinCommand { #if HAVE_BLKID @@ -32,7 +33,7 @@ typedef enum UdevBuiltinCommand { typedef struct UdevBuiltin { const char *name; - int (*cmd)(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test); + int (*cmd)(UdevEvent *event, int argc, char *argv[], bool test); const char *help; int (*init)(void); void (*exit)(void); @@ -76,7 +77,7 @@ void udev_builtin_exit(void); UdevBuiltinCommand udev_builtin_lookup(const char *command); const char *udev_builtin_name(UdevBuiltinCommand cmd); bool udev_builtin_run_once(UdevBuiltinCommand cmd); -int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, const char *command, bool test); +int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test); void udev_builtin_list(void); bool udev_builtin_should_reload(void); int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val); diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index a8d7db40b4..b3cdb32a63 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -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); + 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) @@ -1185,7 +1216,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s if (builtin_cmd != _UDEV_BUILTIN_INVALID) { log_device_debug(event->dev, "Running built-in command \"%s\"", command); - r = udev_builtin_run(event->dev, &event->rtnl, builtin_cmd, command, false); + r = udev_builtin_run(event, builtin_cmd, command, false); if (r < 0) log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command); } else { diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h index c54c7891b6..b99559ca2e 100644 --- a/src/udev/udev-event.h +++ b/src/udev/udev-event.h @@ -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; diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index d6e701f3cc..fc1ef34964 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -2193,7 +2193,7 @@ static int udev_rule_apply_token_to_event( log_event_debug(dev, token, "Importing properties from results of builtin command '%s'", buf); - r = udev_builtin_run(dev, &event->rtnl, cmd, buf, false); + r = udev_builtin_run(event, cmd, buf, false); if (r < 0) { /* remember failure */ log_event_debug_errno(dev, token, r, "Failed to run builtin '%s': %m", buf); diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c index 81b633611e..5d1fafbd03 100644 --- a/src/udev/udevadm-test-builtin.c +++ b/src/udev/udevadm-test-builtin.c @@ -72,7 +72,7 @@ static int parse_argv(int argc, char *argv[]) { } int builtin_main(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(udev_event_freep) UdevEvent *event = NULL; _cleanup_(sd_device_unrefp) sd_device *dev = NULL; UdevBuiltinCommand cmd; int r; @@ -87,8 +87,7 @@ int builtin_main(int argc, char *argv[], void *userdata) { cmd = udev_builtin_lookup(arg_command); if (cmd < 0) { - log_error("Unknown command '%s'", arg_command); - r = -EINVAL; + r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown command '%s'", arg_command); goto finish; } @@ -98,7 +97,13 @@ int builtin_main(int argc, char *argv[], void *userdata) { goto finish; } - r = udev_builtin_run(dev, &rtnl, cmd, arg_command, true); + event = udev_event_new(dev, 0, NULL, LOG_DEBUG); + if (!event) { + r = log_oom(); + goto finish; + } + + r = udev_builtin_run(event, cmd, arg_command, true); if (r < 0) log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command); diff --git a/test/units/testsuite-17.12.sh b/test/units/testsuite-17.12.sh new file mode 100755 index 0000000000..df74d356ee --- /dev/null +++ b/test/units/testsuite-17.12.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -ex +set -o pipefail + +# shellcheck source=test/units/assert.sh +. "$(dirname "$0")"/assert.sh + +create_link_file() { + name=${1?} + + mkdir -p /run/systemd/network/ + cat >/run/systemd/network/10-test.link <<EOF +[Match] +Kind=dummy +MACAddress=00:50:56:c0:00:18 + +[Link] +Name=$name +AlternativeName=test1 test2 test3 test4 +EOF + udevadm control --reload +} + +udevadm control --log-level=debug + +create_link_file test1 +ip link add address 00:50:56:c0:00:18 type dummy +udevadm wait --settle --timeout=30 /sys/class/net/test1 +output=$(ip link show dev test1) +if ! [[ "$output" =~ altname ]]; then + echo "alternative name for network interface not supported, skipping test." + exit 0 +fi +assert_not_in "altname test1" "$output" +assert_in "altname test2" "$output" +assert_in "altname test3" "$output" +assert_in "altname test4" "$output" + +# By triggering add event, Name= and AlternativeNames= are re-applied +create_link_file test2 +udevadm trigger --action add --settle /sys/class/net/test1 +udevadm wait --settle --timeout=30 /sys/class/net/test2 +output=$(ip link show dev test2) +assert_in "altname test1" "$output" +assert_not_in "altname test2" "$output" +assert_in "altname test3" "$output" +assert_in "altname test4" "$output" + +# Name= and AlternativeNames= are not applied on move event +create_link_file test3 +udevadm trigger --action move --settle /sys/class/net/test2 +udevadm wait --settle --timeout=30 /sys/class/net/test2 +output=$(ip link show dev test2) +assert_in "altname test1" "$output" +assert_not_in "altname test2" "$output" +assert_in "altname test3" "$output" +assert_in "altname test4" "$output" + +# Test move event triggered by manual renaming +ip link set dev test2 name hoge +udevadm wait --settle --timeout=30 /sys/class/net/hoge +output=$(ip link show dev hoge) +assert_in "altname test1" "$output" +assert_not_in "altname test2" "$output" +assert_in "altname test3" "$output" +assert_in "altname test4" "$output" +assert_not_in "altname hoge" "$output" + +# Re-test add event +udevadm trigger --action add --settle /sys/class/net/hoge +udevadm wait --settle --timeout=30 /sys/class/net/test3 +output=$(ip link show dev test3) +assert_in "altname test1" "$output" +assert_in "altname test2" "$output" +assert_not_in "altname test3" "$output" +assert_in "altname test4" "$output" +assert_not_in "altname hoge" "$output" + +# cleanup +ip link del dev test3 + +rm -f /run/systemd/network/10-test.link +udevadm control --reload --log-level=info + +exit 0 |