Merge pull request #27655 from yuwata/udev-net-assign-alternative-names-only-on-add-event
udev/net: assign alternative names only on add event
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
|
||||
+15
-26
@@ -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;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct Link {
|
||||
int ifindex;
|
||||
const char *ifname;
|
||||
const char *new_name;
|
||||
char **altnames;
|
||||
|
||||
LinkConfig *config;
|
||||
sd_device *device;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; ) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
+39
-8
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Executable
+86
@@ -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
|
||||
Reference in New Issue
Block a user