1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-19 22:50:17 +03:00

udev: use INTERFACE property rather than sysname when processing network interface (#36627)

sd-device replaces '!' in sysname with '/', hence sysname may be
different from ifname.
Let's use INTERFACE property when we need network interface name.

This fixes the following unexpected renaming of network interfaces
created with '!' in their name, e.g. 'hoge!foo' -> 'hoge_foo':
```
$ run0 ip link add 'hoge!foo' type dummy
$ ip link show 'hoge!foo'
Device "hoge!foo" does not exist.
$ ip link show 'hoge_foo'
410: hoge_foo: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether ee:54:4a:dd:c4:c7 brd ff:ff:ff:ff:ff:ff
```

Closes #26156.
This commit is contained in:
Yu Watanabe 2025-03-13 04:12:57 +09:00 committed by GitHub
commit f9ddbc5b35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 847 additions and 703 deletions

View File

@ -540,6 +540,16 @@
<xi:include href="version-info.xml" xpointer="v257"/>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>v258</constant></term>
<listitem><para>When no renaming is requested, <varname>ID_NET_NAME</varname> property is now
equivalent to <varname>INTERFACE</varname> property.</para>
<xi:include href="version-info.xml" xpointer="v258"/>
</listitem>
</varlistentry>
</variablelist>
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this

View File

@ -297,12 +297,7 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_set_source_mac) {
struct hw_addr_data hw_addr;
r = rtnl_get_link_info(&rtnl, arg_ifindex,
/* ret_iftype = */ NULL,
/* ret_flags = */ NULL,
/* ret_kind = */ NULL,
&hw_addr,
/* ret_permanent_hw_addr = */ NULL);
r = rtnl_get_link_hw_addr(&rtnl, arg_ifindex, &hw_addr);
if (r < 0)
return log_error_errno(r, "Failed to get the source link-layer address: %m");

View File

@ -13,6 +13,43 @@
struct sd_device {
unsigned n_ref;
/* syspath */
char *syspath;
const char *devpath;
const char *sysnum;
char *sysname;
/* only set when device is passed through netlink */
sd_device_action_t action;
uint64_t seqnum;
/* basic kernel properties */
char *subsystem;
char *driver_subsystem; /* only set for the 'drivers' subsystem */
char *driver;
char *devtype;
/* device node properties */
char *devname;
dev_t devnum;
mode_t devmode;
uid_t devuid;
gid_t devgid;
/* block device properties */
uint64_t diskseq; /* Block device sequence number, monothonically incremented by the kernel on create/attach */
/* network interface properties */
int ifindex;
/* determined by devnnum, ifindex, subsystem, and sysname */
char *device_id;
/* sysfs attributes */
Hashmap *sysattr_values; /* cached sysattr values */
Set *sysattrs; /* names of sysattrs */
Iterator sysattrs_iterator;
/* The database version indicates the supported features by the udev database.
* This is saved and parsed in V field.
*
@ -21,68 +58,38 @@ struct sd_device {
*/
unsigned database_version;
sd_device *parent;
/* when device is initialized by udevd */
usec_t usec_initialized;
OrderedHashmap *properties;
/* properties */
OrderedHashmap *properties; /* all properties set from uevent and by udevd */
Iterator properties_iterator;
uint64_t properties_generation; /* changes whenever the properties are changed */
uint64_t properties_iterator_generation; /* generation when iteration was started */
OrderedHashmap *properties_db; /* the subset of the properties that should be written to the db */
char **properties_strv; /* the properties hashmap as a strv */
char *properties_nulstr; /* the same as a nulstr */
size_t properties_nulstr_len;
/* the subset of the properties that should be written to the db */
OrderedHashmap *properties_db;
Hashmap *sysattr_values; /* cached sysattr values */
Set *sysattrs; /* names of sysattrs */
Iterator sysattrs_iterator;
/* TAG keyword */
Set *all_tags, *current_tags;
Iterator all_tags_iterator, current_tags_iterator;
uint64_t all_tags_iterator_generation, current_tags_iterator_generation; /* generation when iteration was started */
uint64_t tags_generation; /* changes whenever the tags are changed */
/* SYMLINK keyword */
Set *devlinks;
Iterator devlinks_iterator;
uint64_t devlinks_generation; /* changes whenever the devlinks are changed */
uint64_t devlinks_iterator_generation; /* generation when iteration was started */
int devlink_priority;
/* parent and child devices */
sd_device *parent;
Hashmap *children;
Iterator children_iterator;
bool children_enumerated;
int ifindex;
char *devtype;
char *devname;
dev_t devnum;
char **properties_strv; /* the properties hashmap as a strv */
char *properties_nulstr; /* the same as a nulstr */
size_t properties_nulstr_len;
char *syspath;
const char *devpath;
const char *sysnum;
char *sysname;
char *subsystem;
char *driver_subsystem; /* only set for the 'drivers' subsystem */
char *driver;
char *device_id;
usec_t usec_initialized;
mode_t devmode;
uid_t devuid;
gid_t devgid;
uint64_t diskseq; /* Block device sequence number, monothonically incremented by the kernel on create/attach */
/* only set when device is passed through netlink */
sd_device_action_t action;
uint64_t seqnum;
bool parent_set:1; /* no need to try to reload parent */
bool sysattrs_read:1; /* don't try to re-read sysattrs once read */
bool property_tags_outdated:1; /* need to update TAGS= or CURRENT_TAGS= property */
@ -92,7 +99,6 @@ struct sd_device {
bool driver_set:1; /* don't reread driver */
bool uevent_loaded:1; /* don't reread uevent */
bool db_loaded; /* don't reread db */
bool is_initialized:1;
bool sealed:1; /* don't read more information from uevent/db */
bool db_persist:1; /* don't clean up the db when switching from initrd to real root */

View File

@ -21,6 +21,7 @@ int device_opendir(sd_device *device, const char *subdir, DIR **ret);
int device_get_sysnum_unsigned(sd_device *device, unsigned *ret);
int device_get_property_bool(sd_device *device, const char *key);
int device_get_property_int(sd_device *device, const char *key, int *ret);
int device_get_ifname(sd_device *device, const char **ret);
int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value);
int device_get_sysattr_unsigned_full(sd_device *device, const char *sysattr, unsigned base, unsigned *ret_value);
static inline int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) {

View File

@ -110,6 +110,19 @@ bool device_is_devtype(sd_device *device, const char *devtype);
static inline bool device_property_can_set(const char *property) {
return property &&
!STR_IN_SET(property,
"ACTION", "DEVLINKS", "DEVNAME", "DEVPATH", "DEVTYPE", "DRIVER",
"IFINDEX", "MAJOR", "MINOR", "SEQNUM", "SUBSYSTEM", "TAGS");
/* basic properties set by kernel, only in netlink event */
"ACTION", "SEQNUM", "SYNTH_UUID",
/* basic properties set by kernel, both in netlink event and uevent file */
"DEVPATH", "DEVPATH_OLD", "SUBSYSTEM", "DEVTYPE", "DRIVER", "MODALIAS",
/* device node */
"DEVNAME", "DEVMODE", "DEVUID", "DEVGID", "MAJOR", "MINOR",
/* block device */
"DISKSEQ", "PARTN",
/* network interface (INTERFACE_OLD is set by udevd) */
"IFINDEX", "INTERFACE", "INTERFACE_OLD",
/* basic properties set by udevd */
"DEVLINKS", "TAGS", "CURRENT_TAGS", "USEC_INITIALIZED", "UDEV_DATABASE_VERSION") &&
/* Similar to SYNTH_UUID, but set based on KEY=VALUE arguments passed by userspace.
* See kernel's f36776fafbaa0094390dd4e7e3e29805e0b82730 (v4.13) */
!startswith(property, "SYNTH_ARG_");
}

View File

@ -366,7 +366,7 @@ _public_ int sd_device_new_from_ifindex(sd_device **ret, int ifindex) {
assert_return(ret, -EINVAL);
assert_return(ifindex > 0, -EINVAL);
r = rtnl_get_ifname_full(NULL, ifindex, &ifname, NULL);
r = rtnl_get_ifname(NULL, ifindex, &ifname);
if (r < 0)
return r;
@ -871,6 +871,21 @@ _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
return 0;
}
int device_get_ifname(sd_device *device, const char **ret) {
int r;
assert_return(device, -EINVAL);
/* First, check if the device is a network interface. */
r = sd_device_get_ifindex(device, NULL);
if (r < 0)
return r;
/* The sysname and ifname may be different, as '!' in sysname are replaced with '/'.
* For network interfaces, we can use INTERFACE property. */
return sd_device_get_property_value(device, "INTERFACE", ret);
}
_public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
int r;

View File

@ -30,50 +30,59 @@ static void test_sd_device_one(sd_device *d) {
usec_t usec;
int ifindex, r;
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
assert_se(path_startswith(syspath, "/sys"));
assert_se(sd_device_get_sysname(d, &sysname) >= 0);
ASSERT_OK(sd_device_get_syspath(d, &syspath));
ASSERT_NOT_NULL(path_startswith(syspath, "/sys"));
ASSERT_OK(sd_device_get_sysname(d, &sysname));
log_info("%s(%s)", __func__, syspath);
assert_se(sd_device_new_from_syspath(&dev, syspath) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
ASSERT_OK(sd_device_new_from_syspath(&dev, syspath));
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
assert_se(sd_device_new_from_path(&dev, syspath) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
ASSERT_OK(sd_device_new_from_path(&dev, syspath));
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
r = sd_device_get_ifindex(d, &ifindex);
if (r >= 0) {
assert_se(ifindex > 0);
if (r < 0)
ASSERT_ERROR(r, ENOENT);
else {
ASSERT_GT(ifindex, 0);
const char *ifname;
ASSERT_OK(device_get_ifname(d, &ifname));
ASSERT_NOT_NULL(endswith(syspath, ifname));
if (strchr(sysname, '/'))
ASSERT_FALSE(streq(ifname, sysname));
else
ASSERT_STREQ(ifname, sysname);
r = sd_device_new_from_ifindex(&dev, ifindex);
if (r == -ENODEV)
if (r < 0) {
ASSERT_ERROR(r, ENODEV);
log_device_warning_errno(d, r,
"Failed to create sd-device object from ifindex %i. "
"Maybe running on a non-host network namespace.", ifindex);
else {
assert_se(r >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else {
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
}
/* This does not require the interface really exists on the network namespace.
* Hence, this should always succeed. */
assert_se(sd_device_new_from_ifname(&dev, sysname) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
assert_se(r == -ENOENT);
ASSERT_OK(sd_device_new_from_ifname(&dev, sysname));
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
}
r = sd_device_get_subsystem(d, &subsystem);
if (r < 0)
assert_se(r == -ENOENT);
ASSERT_ERROR(r, ENOENT);
else {
const char *name, *id;
@ -85,132 +94,145 @@ static void test_sd_device_one(sd_device *d) {
name = sysname;
r = sd_device_new_from_subsystem_sysname(&dev, subsystem, name);
if (r >= 0) {
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
if (r < 0)
ASSERT_ERROR(r, ETOOMANYREFS);
else {
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
}
/* The device ID depends on subsystem. */
assert_se(sd_device_get_device_id(d, &id) >= 0);
ASSERT_OK(sd_device_get_device_id(d, &id));
r = sd_device_new_from_device_id(&dev, id);
if (r == -ENODEV && ifindex > 0)
log_device_warning_errno(d, r,
"Failed to create sd-device object from device ID \"%s\". "
"Maybe running on a non-host network namespace.", id);
else if (r >= 0) {
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
ASSERT_ERROR(r, ETOOMANYREFS);
if (r < 0) {
if (r == -ENODEV && ifindex > 0)
log_device_warning_errno(d, r,
"Failed to create sd-device object from device ID \"%s\". "
"Maybe running on a non-host network namespace.", id);
else
ASSERT_ERROR(r, ETOOMANYREFS);
} else {
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
}
/* These require udev database, and reading database requires device ID. */
r = sd_device_get_is_initialized(d);
ASSERT_OK((r = sd_device_get_is_initialized(d)));
if (r > 0) {
r = sd_device_get_usec_since_initialized(d, &usec);
assert_se((r >= 0 && usec > 0) || r == -ENODATA);
} else
assert(r == 0);
if (r < 0)
ASSERT_ERROR(r, ENODATA);
else
ASSERT_GT(usec, 0U);
}
r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
assert_se(r >= 0 || r == -ENOENT);
if (r < 0)
ASSERT_ERROR(r, ENOENT);
}
is_block = streq_ptr(subsystem, "block");
r = sd_device_get_devname(d, &devname);
if (r >= 0) {
if (r < 0)
ASSERT_ERROR(r, ENOENT);
else {
r = sd_device_new_from_devname(&dev, devname);
if (r >= 0) {
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
assert_se(r == -ENODEV || ERRNO_IS_PRIVILEGE(r));
if (r < 0)
ASSERT_TRUE(r == -ENODEV || ERRNO_IS_NEG_PRIVILEGE(r));
else {
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
}
r = sd_device_new_from_path(&dev, devname);
if (r >= 0) {
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
if (r < 0)
ASSERT_TRUE(r == -ENODEV || ERRNO_IS_NEG_PRIVILEGE(r));
else {
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
_cleanup_close_ int fd = -EBADF;
fd = sd_device_open(d, O_CLOEXEC| O_NONBLOCK | (is_block ? O_RDONLY : O_NOCTTY | O_PATH));
assert_se(fd >= 0 || ERRNO_IS_PRIVILEGE(fd));
} else
assert_se(r == -ENODEV || ERRNO_IS_PRIVILEGE(r));
} else
assert_se(r == -ENOENT);
ASSERT_TRUE(fd >= 0 || ERRNO_IS_NEG_PRIVILEGE(fd));
}
}
r = sd_device_get_devnum(d, &devnum);
if (r >= 0) {
if (r < 0)
ASSERT_ERROR(r, ENOENT);
else {
_cleanup_free_ char *p = NULL;
assert_se(major(devnum) > 0);
ASSERT_GT(major(devnum), 0U);
assert_se(sd_device_new_from_devnum(&dev, is_block ? 'b' : 'c', devnum) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
ASSERT_OK(sd_device_new_from_devnum(&dev, is_block ? 'b' : 'c', devnum));
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
assert_se(asprintf(&p, "/dev/%s/%u:%u", is_block ? "block" : "char", major(devnum), minor(devnum)) >= 0);
assert_se(sd_device_new_from_devname(&dev, p) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
ASSERT_OK(asprintf(&p, "/dev/%s/%u:%u", is_block ? "block" : "char", major(devnum), minor(devnum)));
ASSERT_OK(sd_device_new_from_devname(&dev, p));
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
assert_se(sd_device_new_from_path(&dev, p) >= 0);
assert_se(sd_device_get_syspath(dev, &val) >= 0);
assert_se(streq(syspath, val));
dev = sd_device_unref(dev);
} else
assert_se(r == -ENOENT);
ASSERT_OK(sd_device_new_from_path(&dev, p));
ASSERT_OK(sd_device_get_syspath(dev, &val));
ASSERT_STREQ(syspath, val);
ASSERT_NULL((dev = sd_device_unref(dev)));
}
assert_se(sd_device_get_devpath(d, &val) >= 0);
ASSERT_OK(sd_device_get_devpath(d, &val));
r = sd_device_get_devtype(d, &val);
assert_se(r >= 0 || r == -ENOENT);
r = sd_device_get_devtype(d, NULL);
if (r < 0)
ASSERT_ERROR(r, ENOENT);
r = sd_device_get_driver(d, &val);
assert_se(r >= 0 || r == -ENOENT);
r = sd_device_get_driver(d, NULL);
if (r < 0)
ASSERT_ERROR(r, ENOENT);
r = sd_device_get_sysnum(d, &val);
if (r >= 0) {
assert_se(val > sysname);
assert_se(val < sysname + strlen(sysname));
assert_se(in_charset(val, DIGITS));
assert_se(!ascii_isdigit(val[-1]));
if (r < 0)
ASSERT_ERROR(r, ENOENT);
else {
ASSERT_TRUE(val > sysname);
ASSERT_TRUE(val < sysname + strlen(sysname));
ASSERT_TRUE(in_charset(val, DIGITS));
ASSERT_FALSE(ascii_isdigit(val[-1]));
r = device_get_sysnum_unsigned(d, NULL);
ASSERT_TRUE(r >= 0 || r == -ERANGE); /* sysnum may be too large. */
} else
assert_se(r == -ENOENT);
if (r < 0)
ASSERT_ERROR(r, ERANGE); /* sysnum may be too large. */
}
r = sd_device_get_sysattr_value(d, "nsid", NULL);
if (r >= 0) {
if (r < 0)
ASSERT_TRUE(ERRNO_IS_NEG_PRIVILEGE(r) || IN_SET(r, -ENOENT, -EINVAL));
else {
unsigned x;
assert_se(device_get_sysattr_unsigned(d, "nsid", NULL) >= 0);
r = device_get_sysattr_unsigned(d, "nsid", &x);
assert_se(r >= 0);
assert_se((x > 0) == (r > 0));
} else
assert_se(ERRNO_IS_PRIVILEGE(r) || IN_SET(r, -ENOENT, -EINVAL));
ASSERT_OK((r = device_get_sysattr_unsigned(d, "nsid", &x)));
ASSERT_EQ((x > 0), (r > 0));
}
}
TEST(sd_device_enumerator_devices) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
/* On some CI environments, it seems some loop block devices and corresponding bdi devices sometimes
* disappear during running this test. Let's exclude them here for stability. */
assert_se(sd_device_enumerator_add_match_subsystem(e, "bdi", false) >= 0);
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "bdi", false));
ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e, "loop*"));
/* On CentOS CI, systemd-networkd-tests.py may be running when this test is invoked. The networkd
* test creates and removes many network interfaces, and may interfere with this test. */
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", false) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", false));
FOREACH_DEVICE(e, d)
test_sd_device_one(d);
}
@ -218,8 +240,8 @@ TEST(sd_device_enumerator_devices) {
TEST(sd_device_enumerator_subsystems) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
FOREACH_SUBSYSTEM(e, d)
test_sd_device_one(d);
}
@ -234,15 +256,15 @@ static void test_sd_device_enumerator_filter_subsystem_one(
unsigned n_new_dev = 0, n_removed_dev = 0;
sd_device *dev;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, true) >= 0);
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, subsystem, true));
ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e, "loop*"));
FOREACH_DEVICE(e, d) {
const char *syspath;
sd_device *t;
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
ASSERT_OK(sd_device_get_syspath(d, &syspath));
t = hashmap_remove(h, syspath);
if (!t) {
@ -250,17 +272,17 @@ static void test_sd_device_enumerator_filter_subsystem_one(
n_new_dev++;
}
assert_se(!sd_device_unref(t));
ASSERT_NULL(sd_device_unref(t));
}
HASHMAP_FOREACH(dev, h) {
const char *syspath;
assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
ASSERT_OK(sd_device_get_syspath(dev, &syspath));
log_warning("Device removed: subsystem:%s syspath:%s", subsystem, syspath);
n_removed_dev++;
assert_se(!sd_device_unref(dev));
ASSERT_NULL(sd_device_unref(dev));
}
hashmap_free(h);
@ -276,34 +298,35 @@ static bool test_sd_device_enumerator_filter_subsystem_trial(void) {
Hashmap *h;
char *s;
assert_se(subsystems = hashmap_new(&string_hash_ops));
assert_se(sd_device_enumerator_new(&e) >= 0);
ASSERT_NOT_NULL((subsystems = hashmap_new(&string_hash_ops)));
ASSERT_OK(sd_device_enumerator_new(&e));
/* See comments in TEST(sd_device_enumerator_devices). */
assert_se(sd_device_enumerator_add_match_subsystem(e, "bdi", false) >= 0);
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", false) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "bdi", false));
ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e, "loop*"));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", false));
FOREACH_DEVICE(e, d) {
const char *syspath, *subsystem;
int r;
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
ASSERT_OK(sd_device_get_syspath(d, &syspath));
r = sd_device_get_subsystem(d, &subsystem);
assert_se(r >= 0 || r == -ENOENT);
if (r < 0)
if (r < 0) {
ASSERT_ERROR(r, ENOENT);
continue;
}
h = hashmap_get(subsystems, subsystem);
if (!h) {
char *str;
assert_se(str = strdup(subsystem));
assert_se(h = hashmap_new(&string_hash_ops));
assert_se(hashmap_put(subsystems, str, h) >= 0);
ASSERT_NOT_NULL((str = strdup(subsystem)));
ASSERT_NOT_NULL((h = hashmap_new(&string_hash_ops)));
ASSERT_OK(hashmap_put(subsystems, str, h));
}
assert_se(hashmap_put(h, syspath, d) >= 0);
assert_se(sd_device_ref(d));
ASSERT_OK(hashmap_put(h, syspath, d));
ASSERT_NOT_NULL(sd_device_ref(d));
log_debug("Added subsystem:%s syspath:%s", subsystem, syspath);
}
@ -348,19 +371,19 @@ TEST(sd_device_enumerator_filter_subsystem) {
* several times after the udev queue becomes empty. */
if (!udev_available() || (access("/run/udev", F_OK) < 0 && errno == ENOENT)) {
assert_se(test_sd_device_enumerator_filter_subsystem_trial_many());
ASSERT_TRUE(test_sd_device_enumerator_filter_subsystem_trial_many());
return;
}
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
assert_se(sd_event_default(&event) >= 0);
assert_se(sd_event_add_inotify(event, NULL, "/run/udev" , IN_DELETE, on_inotify, NULL) >= 0);
ASSERT_OK(sd_event_default(&event));
ASSERT_OK(sd_event_add_inotify(event, NULL, "/run/udev" , IN_DELETE, on_inotify, NULL));
if (udev_queue_is_empty() == 0) {
log_debug("udev queue is not empty, waiting for all queued events to be processed.");
assert_se(sd_event_loop(event) >= 0);
ASSERT_OK(sd_event_loop(event));
} else
assert_se(test_sd_device_enumerator_filter_subsystem_trial_many());
ASSERT_TRUE(test_sd_device_enumerator_filter_subsystem_trial_many());
}
TEST(sd_device_enumerator_add_match_sysattr) {
@ -368,21 +391,20 @@ TEST(sd_device_enumerator_add_match_sysattr) {
sd_device *dev;
int ifindex;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", true) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "hoge", true) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "foo", true) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "bar", false) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "baz", false) >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", true));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "hoge", true));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "foo", true));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "bar", false));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "baz", false));
dev = sd_device_enumerator_get_device_first(e);
assert_se(dev);
assert_se(sd_device_get_ifindex(dev, &ifindex) >= 0);
assert_se(ifindex == 1);
ASSERT_NOT_NULL((dev = sd_device_enumerator_get_device_first(e)));
ASSERT_OK(sd_device_get_ifindex(dev, &ifindex));
ASSERT_EQ(ifindex, 1);
assert_se(!sd_device_enumerator_get_device_next(e));
ASSERT_NULL(sd_device_enumerator_get_device_next(e));
}
TEST(sd_device_enumerator_add_match_property) {
@ -390,20 +412,19 @@ TEST(sd_device_enumerator_add_match_property) {
sd_device *dev;
int ifindex;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", true) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true) >= 0);
assert_se(sd_device_enumerator_add_match_property(e, "IFINDE*", "1*") >= 0);
assert_se(sd_device_enumerator_add_match_property(e, "IFINDE*", "hoge") >= 0);
assert_se(sd_device_enumerator_add_match_property(e, "IFINDE*", NULL) >= 0);
assert_se(sd_device_enumerator_add_match_property(e, "AAAAA", "BBBB") >= 0);
assert_se(sd_device_enumerator_add_match_property(e, "FOOOO", NULL) >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", true));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true));
ASSERT_OK(sd_device_enumerator_add_match_property(e, "IFINDE*", "1*"));
ASSERT_OK(sd_device_enumerator_add_match_property(e, "IFINDE*", "hoge"));
ASSERT_OK(sd_device_enumerator_add_match_property(e, "IFINDE*", NULL));
ASSERT_OK(sd_device_enumerator_add_match_property(e, "AAAAA", "BBBB"));
ASSERT_OK(sd_device_enumerator_add_match_property(e, "FOOOO", NULL));
dev = sd_device_enumerator_get_device_first(e);
assert_se(dev);
assert_se(sd_device_get_ifindex(dev, &ifindex) >= 0);
assert_se(ifindex == 1);
ASSERT_NOT_NULL((dev = sd_device_enumerator_get_device_first(e)));
ASSERT_OK(sd_device_get_ifindex(dev, &ifindex));
ASSERT_EQ(ifindex, 1);
}
TEST(sd_device_enumerator_add_match_property_required) {
@ -411,37 +432,36 @@ TEST(sd_device_enumerator_add_match_property_required) {
sd_device *dev;
int ifindex;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", true) >= 0);
assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true) >= 0);
assert_se(sd_device_enumerator_add_match_property_required(e, "IFINDE*", "1*") >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", true));
ASSERT_OK(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true));
ASSERT_OK(sd_device_enumerator_add_match_property_required(e, "IFINDE*", "1*"));
/* Only one required match which should be satisfied. */
dev = sd_device_enumerator_get_device_first(e);
assert_se(dev);
assert_se(sd_device_get_ifindex(dev, &ifindex) >= 0);
assert_se(ifindex == 1);
ASSERT_NOT_NULL((dev = sd_device_enumerator_get_device_first(e)));
ASSERT_OK(sd_device_get_ifindex(dev, &ifindex));
ASSERT_EQ(ifindex, 1);
/* Now let's add a bunch of garbage properties which should not be satisfied. */
assert_se(sd_device_enumerator_add_match_property_required(e, "IFINDE*", "hoge") >= 0);
assert_se(sd_device_enumerator_add_match_property_required(e, "IFINDE*", NULL) >= 0);
assert_se(sd_device_enumerator_add_match_property_required(e, "AAAAA", "BBBB") >= 0);
assert_se(sd_device_enumerator_add_match_property_required(e, "FOOOO", NULL) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_property_required(e, "IFINDE*", "hoge"));
ASSERT_OK(sd_device_enumerator_add_match_property_required(e, "IFINDE*", NULL));
ASSERT_OK(sd_device_enumerator_add_match_property_required(e, "AAAAA", "BBBB"));
ASSERT_OK(sd_device_enumerator_add_match_property_required(e, "FOOOO", NULL));
assert_se(!sd_device_enumerator_get_device_first(e));
ASSERT_NULL(sd_device_enumerator_get_device_first(e));
}
static void check_parent_match(sd_device_enumerator *e, sd_device *dev) {
const char *syspath;
bool found = false;
assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
ASSERT_OK(sd_device_get_syspath(dev, &syspath));
FOREACH_DEVICE(e, d) {
const char *s;
assert_se(sd_device_get_syspath(d, &s) >= 0);
ASSERT_OK(sd_device_get_syspath(d, &s));
if (streq(s, syspath)) {
found = true;
break;
@ -451,8 +471,8 @@ static void check_parent_match(sd_device_enumerator *e, sd_device *dev) {
if (!found) {
log_device_debug(dev, "not enumerated, already removed??");
/* If the original device not found, then the device should be already removed. */
assert_se(access(syspath, F_OK) < 0);
assert_se(errno == ENOENT);
ASSERT_FAIL(access(syspath, F_OK));
ASSERT_EQ(errno, ENOENT);
}
}
@ -460,41 +480,41 @@ TEST(sd_device_enumerator_add_match_parent) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
int r;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
/* See comments in TEST(sd_device_enumerator_devices). */
assert_se(sd_device_enumerator_add_match_subsystem(e, "bdi", false) >= 0);
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", false) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "bdi", false));
ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e, "loop*"));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", false));
if (!slow_tests_enabled())
assert_se(sd_device_enumerator_add_match_subsystem(e, "block", true) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "block", true));
FOREACH_DEVICE(e, dev) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *p = NULL;
const char *syspath;
sd_device *parent;
assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
ASSERT_OK(sd_device_get_syspath(dev, &syspath));
r = sd_device_get_parent(dev, &parent);
if (r < 0) {
assert_se(ERRNO_IS_DEVICE_ABSENT(r));
ASSERT_TRUE(ERRNO_IS_NEG_DEVICE_ABSENT(r));
continue;
}
log_debug("> %s", syspath);
assert_se(sd_device_enumerator_new(&p) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(p) >= 0);
assert_se(sd_device_enumerator_add_match_parent(p, parent) >= 0);
ASSERT_OK(sd_device_enumerator_new(&p));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(p));
ASSERT_OK(sd_device_enumerator_add_match_parent(p, parent));
check_parent_match(p, dev);
/* If the device does not have subsystem, then it is not enumerated. */
r = sd_device_get_subsystem(parent, NULL);
if (r < 0) {
assert_se(r == -ENOENT);
ASSERT_ERROR(r, ENOENT);
continue;
}
check_parent_match(p, parent);
@ -542,49 +562,49 @@ TEST(sd_device_get_child) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
int r;
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
/* See comments in TEST(sd_device_enumerator_devices). */
assert_se(sd_device_enumerator_add_match_subsystem(e, "bdi", false) >= 0);
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "net", false) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "bdi", false));
ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e, "loop*"));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "net", false));
if (!slow_tests_enabled())
assert_se(sd_device_enumerator_add_match_subsystem(e, "block", true) >= 0);
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "block", true));
FOREACH_DEVICE(e, dev) {
const char *syspath, *parent_syspath, *expected_suffix, *suffix;
sd_device *parent;
bool found = false;
assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
ASSERT_OK(sd_device_get_syspath(dev, &syspath));
r = sd_device_get_parent(dev, &parent);
if (r < 0) {
assert_se(ERRNO_IS_DEVICE_ABSENT(r));
ASSERT_TRUE(ERRNO_IS_NEG_DEVICE_ABSENT(r));
continue;
}
assert_se(sd_device_get_syspath(parent, &parent_syspath) >= 0);
assert_se(expected_suffix = path_startswith(syspath, parent_syspath));
ASSERT_OK(sd_device_get_syspath(parent, &parent_syspath));
ASSERT_NOT_NULL((expected_suffix = path_startswith(syspath, parent_syspath)));
log_debug("> %s", syspath);
FOREACH_DEVICE_CHILD_WITH_SUFFIX(parent, child, suffix) {
const char *s;
assert_se(child);
assert_se(suffix);
ASSERT_NOT_NULL(child);
ASSERT_NOT_NULL(suffix);
if (!streq(suffix, expected_suffix))
continue;
assert_se(sd_device_get_syspath(child, &s) >= 0);
assert_se(streq(s, syspath));
ASSERT_OK(sd_device_get_syspath(child, &s));
ASSERT_STREQ(s, syspath);
found = true;
break;
}
assert_se(found);
ASSERT_TRUE(found);
}
}
@ -602,42 +622,42 @@ TEST(sd_device_new_from_nulstr) {
const char *nulstr;
size_t len;
assert_se(sd_device_new_from_syspath(&device, "/sys/class/net/lo") >= 0);
ASSERT_OK(sd_device_new_from_syspath(&device, "/sys/class/net/lo"));
/* Yeah, of course, setting devlink to the loopback interface is nonsense. But this is just a
* test for generating and parsing nulstr. For issue #17772. */
NULSTR_FOREACH(devlink, devlinks) {
log_device_info(device, "setting devlink: %s", devlink);
assert_se(device_add_devlink(device, devlink) >= 0);
assert_se(set_contains(device->devlinks, devlink));
ASSERT_OK(device_add_devlink(device, devlink));
ASSERT_TRUE(set_contains(device->devlinks, devlink));
}
/* For issue #23799 */
assert_se(device_add_tag(device, "tag1", false) >= 0);
assert_se(device_add_tag(device, "tag2", false) >= 0);
assert_se(device_add_tag(device, "current-tag1", true) >= 0);
assert_se(device_add_tag(device, "current-tag2", true) >= 0);
ASSERT_OK(device_add_tag(device, "tag1", false));
ASSERT_OK(device_add_tag(device, "tag2", false));
ASSERT_OK(device_add_tag(device, "current-tag1", true));
ASSERT_OK(device_add_tag(device, "current-tag2", true));
/* These properties are necessary for device_new_from_nulstr(). See device_verify(). */
assert_se(device_add_property_internal(device, "SEQNUM", "1") >= 0);
assert_se(device_add_property_internal(device, "ACTION", "change") >= 0);
ASSERT_OK(device_add_property_internal(device, "SEQNUM", "1"));
ASSERT_OK(device_add_property_internal(device, "ACTION", "change"));
assert_se(device_get_properties_nulstr(device, &nulstr, &len) >= 0);
assert_se(nulstr_copy = newdup(char, nulstr, len));
assert_se(device_new_from_nulstr(&from_nulstr, nulstr_copy, len) >= 0);
ASSERT_OK(device_get_properties_nulstr(device, &nulstr, &len));
ASSERT_NOT_NULL((nulstr_copy = newdup(char, nulstr, len)));
ASSERT_OK(device_new_from_nulstr(&from_nulstr, nulstr_copy, len));
assert_se(sd_device_has_tag(from_nulstr, "tag1") == 1);
assert_se(sd_device_has_tag(from_nulstr, "tag2") == 1);
assert_se(sd_device_has_tag(from_nulstr, "current-tag1") == 1);
assert_se(sd_device_has_tag(from_nulstr, "current-tag2") == 1);
assert_se(sd_device_has_current_tag(from_nulstr, "tag1") == 0);
assert_se(sd_device_has_current_tag(from_nulstr, "tag2") == 0);
assert_se(sd_device_has_current_tag(from_nulstr, "current-tag1") == 1);
assert_se(sd_device_has_current_tag(from_nulstr, "current-tag2") == 1);
ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr, "tag1"));
ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr, "tag2"));
ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr, "current-tag1"));
ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr, "current-tag2"));
ASSERT_OK_ZERO(sd_device_has_current_tag(from_nulstr, "tag1"));
ASSERT_OK_ZERO(sd_device_has_current_tag(from_nulstr, "tag2"));
ASSERT_OK_POSITIVE(sd_device_has_current_tag(from_nulstr, "current-tag1"));
ASSERT_OK_POSITIVE(sd_device_has_current_tag(from_nulstr, "current-tag2"));
NULSTR_FOREACH(devlink, devlinks) {
log_device_info(from_nulstr, "checking devlink: %s", devlink);
assert_se(set_contains(from_nulstr->devlinks, devlink));
ASSERT_TRUE(set_contains(from_nulstr->devlinks, devlink));
}
}
@ -646,43 +666,44 @@ TEST(sd_device_new_from_path) {
_cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL;
int r;
assert_se(mkdtemp_malloc("/tmp/test-sd-device.XXXXXXX", &tmpdir) >= 0);
ASSERT_OK(mkdtemp_malloc("/tmp/test-sd-device.XXXXXXX", &tmpdir));
assert_se(sd_device_enumerator_new(&e) >= 0);
assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0);
assert_se(sd_device_enumerator_add_match_subsystem(e, "block", true) >= 0);
assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0);
assert_se(sd_device_enumerator_add_match_property(e, "DEVNAME", "*") >= 0);
ASSERT_OK(sd_device_enumerator_new(&e));
ASSERT_OK(sd_device_enumerator_allow_uninitialized(e));
ASSERT_OK(sd_device_enumerator_add_match_subsystem(e, "block", true));
ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e, "loop*"));
ASSERT_OK(sd_device_enumerator_add_match_property(e, "DEVNAME", "*"));
FOREACH_DEVICE(e, dev) {
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
const char *syspath, *devpath, *sysname, *s;
_cleanup_free_ char *path = NULL;
assert_se(sd_device_get_sysname(dev, &sysname) >= 0);
ASSERT_OK(sd_device_get_sysname(dev, &sysname));
log_debug("%s(%s)", __func__, sysname);
assert_se(sd_device_get_syspath(dev, &syspath) >= 0);
assert_se(sd_device_new_from_path(&d, syspath) >= 0);
assert_se(sd_device_get_syspath(d, &s) >= 0);
assert_se(streq(s, syspath));
d = sd_device_unref(d);
ASSERT_OK(sd_device_get_syspath(dev, &syspath));
ASSERT_OK(sd_device_new_from_path(&d, syspath));
ASSERT_OK(sd_device_get_syspath(d, &s));
ASSERT_STREQ(s, syspath);
ASSERT_NULL((d = sd_device_unref(d)));
assert_se(sd_device_get_devname(dev, &devpath) >= 0);
ASSERT_OK(sd_device_get_devname(dev, &devpath));
r = sd_device_new_from_path(&d, devpath);
if (r >= 0) {
assert_se(sd_device_get_syspath(d, &s) >= 0);
assert_se(streq(s, syspath));
d = sd_device_unref(d);
} else
assert_se(r == -ENODEV || ERRNO_IS_PRIVILEGE(r));
if (r < 0)
ASSERT_TRUE(r == -ENODEV || ERRNO_IS_NEG_PRIVILEGE(r));
else {
ASSERT_OK(sd_device_get_syspath(d, &s));
ASSERT_STREQ(s, syspath);
ASSERT_NULL((d = sd_device_unref(d)));
}
assert_se(path = path_join(tmpdir, sysname));
assert_se(symlink(syspath, path) >= 0);
assert_se(sd_device_new_from_path(&d, path) >= 0);
assert_se(sd_device_get_syspath(d, &s) >= 0);
assert_se(streq(s, syspath));
ASSERT_NOT_NULL((path = path_join(tmpdir, sysname)));
ASSERT_OK_ERRNO(symlink(syspath, path));
ASSERT_OK(sd_device_new_from_path(&d, path));
ASSERT_OK(sd_device_get_syspath(d, &s));
ASSERT_STREQ(s, syspath);
}
}
@ -693,16 +714,15 @@ static void test_devname_from_devnum_one(const char *path) {
log_debug("> %s", path);
if (stat(path, &st) < 0) {
assert_se(errno == ENOENT);
log_notice("Path %s not found, skipping test", path);
return;
}
assert_se(devname_from_devnum(st.st_mode, st.st_rdev, &resolved) >= 0);
assert_se(path_equal(path, resolved));
resolved = mfree(resolved);
assert_se(devname_from_stat_rdev(&st, &resolved) >= 0);
assert_se(path_equal(path, resolved));
ASSERT_OK(devname_from_devnum(st.st_mode, st.st_rdev, &resolved));
ASSERT_TRUE(path_equal(path, resolved));
ASSERT_NULL((resolved = mfree(resolved)));
ASSERT_OK(devname_from_stat_rdev(&st, &resolved));
ASSERT_TRUE(path_equal(path, resolved));
}
TEST(devname_from_devnum) {

View File

@ -52,34 +52,6 @@ static int parse_newlink_message(
return ifindex;
}
int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
int r;
assert(ifindex > 0);
/* This is similar to if_indextoname(), but also optionally provides alternative names. */
if (!rtnl)
rtnl = &our_rtnl;
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_GETLINK, ifindex);
if (r < 0)
return r;
r = sd_netlink_call(*rtnl, message, 0, &reply);
if (r < 0)
return r;
return parse_newlink_message(reply, ret_name, ret_altnames);
}
int rtnl_resolve_ifname_full(
sd_netlink **rtnl,
ResolveInterfaceNameFlag flags,
@ -159,7 +131,7 @@ int rtnl_resolve_ifname_full(
return -ENODEV;
}
static int 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;
int r;
@ -169,13 +141,7 @@ static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
/* Assign the requested name. */
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
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)
return r;
@ -183,7 +149,7 @@ static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
if (r < 0)
return r;
return sd_netlink_call(*rtnl, message, 0, NULL);
return sd_netlink_call(rtnl, message, 0, NULL);
}
int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_name) {
@ -214,7 +180,7 @@ int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_n
if (ifindex < 0)
return ifindex;
return set_link_name(rtnl, ifindex, new_name);
return set_link_name(*rtnl, ifindex, new_name);
}
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const *alternative_names) {
@ -222,7 +188,6 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* c
bool altname_deleted = false;
int r;
assert(rtnl);
assert(ifindex > 0);
if (isempty(name) && strv_isempty(alternative_names))
@ -231,6 +196,10 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* c
if (name && !ifname_valid(name))
return -EINVAL;
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
if (!rtnl)
rtnl = &our_rtnl;
/* 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)
@ -247,7 +216,7 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* c
altname_deleted = true;
}
r = set_link_name(rtnl, ifindex, name);
r = set_link_name(*rtnl, ifindex, name);
if (r < 0)
goto fail;
}
@ -309,10 +278,9 @@ int rtnl_set_link_properties(
uint32_t mtu,
uint32_t gso_max_size,
size_t gso_max_segments) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
assert(ifindex > 0);
if (!alias &&
@ -325,12 +293,16 @@ int rtnl_set_link_properties(
gso_max_segments == 0)
return 0;
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
if (!rtnl)
rtnl = &our_rtnl;
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
if (r < 0)
return r;
@ -396,22 +368,24 @@ static int rtnl_update_link_alternative_names(
int ifindex,
char* const *alternative_names) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
assert(ifindex > 0);
assert(IN_SET(nlmsg_type, RTM_NEWLINKPROP, RTM_DELLINKPROP));
if (strv_isempty(alternative_names))
return 0;
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
if (!rtnl)
rtnl = &our_rtnl;
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
r = sd_rtnl_message_new_link(*rtnl, &message, nlmsg_type, ifindex);
if (r < 0)
return r;
@ -448,7 +422,6 @@ int rtnl_set_link_alternative_names_by_ifname(
const char *ifname,
char* const *alternative_names) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
@ -457,12 +430,16 @@ int rtnl_set_link_alternative_names_by_ifname(
if (strv_isempty(alternative_names))
return 0;
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
if (!rtnl)
rtnl = &our_rtnl;
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
return r;
}
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_NEWLINKPROP, 0);
if (r < 0)
return r;
@ -490,9 +467,11 @@ int rtnl_set_link_alternative_names_by_ifname(
return 0;
}
int rtnl_get_link_info(
int rtnl_get_link_info_full(
sd_netlink **rtnl,
int ifindex,
char **ret_name,
char ***ret_altnames,
unsigned short *ret_iftype,
unsigned *ret_flags,
char **ret_kind,
@ -500,18 +479,18 @@ int rtnl_get_link_info(
struct hw_addr_data *ret_permanent_hw_addr) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
struct hw_addr_data addr = HW_ADDR_NULL, perm_addr = HW_ADDR_NULL;
_cleanup_free_ char *kind = NULL;
_cleanup_free_ char *name = NULL, *kind = NULL;
_cleanup_strv_free_ char **altnames = NULL;
unsigned short iftype;
unsigned flags;
int r;
assert(rtnl);
assert(ifindex > 0);
if (!ret_iftype && !ret_flags && !ret_kind && !ret_hw_addr && !ret_permanent_hw_addr)
return 0;
if (!rtnl)
rtnl = &our_rtnl;
if (!*rtnl) {
r = sd_netlink_open(rtnl);
if (r < 0)
@ -528,6 +507,12 @@ int rtnl_get_link_info(
if (r < 0)
return r;
r = parse_newlink_message(reply, ret_name ? &name : NULL, ret_altnames ? &altnames : NULL);
if (r < 0)
return r;
if (r != ifindex)
return -EIO;
if (ret_iftype) {
r = sd_rtnl_message_link_get_type(reply, &iftype);
if (r < 0)
@ -565,6 +550,10 @@ int rtnl_get_link_info(
return r;
}
if (ret_name)
*ret_name = TAKE_PTR(name);
if (ret_altnames)
*ret_altnames = TAKE_PTR(altnames);
if (ret_iftype)
*ret_iftype = iftype;
if (ret_flags)
@ -575,7 +564,7 @@ int rtnl_get_link_info(
*ret_hw_addr = addr;
if (ret_permanent_hw_addr)
*ret_permanent_hw_addr = perm_addr;
return 0;
return ifindex;
}
int rtnl_log_parse_error(int r) {

View File

@ -19,7 +19,65 @@ typedef struct RouteVia {
union in_addr_union address;
} _packed_ RouteVia;
int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames);
int rtnl_get_link_info_full(
sd_netlink **rtnl,
int ifindex,
char **ret_name,
char ***ret_altnames,
unsigned short *ret_iftype,
unsigned *ret_flags,
char **ret_kind,
struct hw_addr_data *ret_hw_addr,
struct hw_addr_data *ret_permanent_hw_addr);
static inline int rtnl_get_ifname_full(sd_netlink **rtnl, int ifindex, char **ret_name, char ***ret_altnames) {
return rtnl_get_link_info_full(
rtnl,
ifindex,
ret_name,
ret_altnames,
/* ret_iftype = */ NULL,
/* ret_flags = */ NULL,
/* ret_kind = */ NULL,
/* ret_hw_addr = */ NULL,
/* ret_permanent_hw_addr = */ NULL);
}
static inline int rtnl_get_ifname(sd_netlink **rtnl, int ifindex, char **ret) {
return rtnl_get_ifname_full(rtnl, ifindex, ret, NULL);
}
static inline int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret) {
return rtnl_get_ifname_full(rtnl, ifindex, NULL, ret);
}
static inline int rtnl_get_link_info(
sd_netlink **rtnl,
int ifindex,
unsigned short *ret_iftype,
unsigned *ret_flags,
char **ret_kind,
struct hw_addr_data *ret_hw_addr,
struct hw_addr_data *ret_permanent_hw_addr) {
return rtnl_get_link_info_full(
rtnl,
ifindex,
/* ret_name = */ NULL,
/* ret_altnames = */ NULL,
ret_iftype,
ret_flags,
ret_kind,
ret_hw_addr,
ret_permanent_hw_addr);
}
static inline int rtnl_get_link_hw_addr(sd_netlink **rtnl, int ifindex, struct hw_addr_data *ret) {
return rtnl_get_link_info(
rtnl,
ifindex,
/* ret_iftype = */ NULL,
/* ret_flags = */ NULL,
/* ret_kind = */ NULL,
ret,
/* ret_permanent_hw_addr = */ NULL);
}
typedef enum ResolveInterfaceNameFlag {
RESOLVE_IFNAME_MAIN = 1 << 0, /* resolve main interface name */
@ -34,29 +92,6 @@ int rtnl_resolve_ifname_full(
const char *name,
char **ret_name,
char ***ret_altnames);
int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_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,
const char *alias,
const struct hw_addr_data *hw_addr,
uint32_t txqueues,
uint32_t rxqueues,
uint32_t txqueuelen,
uint32_t mtu,
uint32_t gso_max_size,
size_t gso_max_segments);
static inline int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret) {
return rtnl_get_ifname_full(rtnl, ifindex, NULL, ret);
}
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names);
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char* const *alternative_names);
int rtnl_delete_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names);
static inline int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret) {
return rtnl_resolve_ifname_full(rtnl, RESOLVE_IFNAME_ALTERNATIVE, name, ret, NULL);
}
@ -77,14 +112,26 @@ static inline int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *
return r;
}
int rtnl_get_link_info(
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names);
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char* const *alternative_names);
int rtnl_delete_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names);
int rtnl_rename_link(sd_netlink **rtnl, const char *orig_name, const char *new_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,
unsigned short *ret_iftype,
unsigned *ret_flags,
char **ret_kind,
struct hw_addr_data *ret_hw_addr,
struct hw_addr_data *ret_permanent_hw_addr);
const char *alias,
const struct hw_addr_data *hw_addr,
uint32_t txqueues,
uint32_t rxqueues,
uint32_t txqueuelen,
uint32_t mtu,
uint32_t gso_max_size,
size_t gso_max_segments);
int rtnl_log_parse_error(int r);
int rtnl_log_create_error(int r);

View File

@ -30,20 +30,20 @@ TEST(message_newlink_bridge) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
uint32_t cost;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
assert_se(sd_rtnl_message_link_set_family(message, AF_BRIDGE) >= 0);
assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0);
assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
assert_se(sd_netlink_message_close_container(message) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1));
ASSERT_OK(sd_rtnl_message_link_set_family(message, AF_BRIDGE));
ASSERT_OK(sd_netlink_message_open_container(message, IFLA_PROTINFO));
ASSERT_OK(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10));
ASSERT_OK(sd_netlink_message_close_container(message));
assert_se(sd_netlink_message_rewind(message, rtnl) >= 0);
ASSERT_OK(sd_netlink_message_rewind(message, rtnl));
assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0);
assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
assert_se(cost == 10);
assert_se(sd_netlink_message_exit_container(message) >= 0);
ASSERT_OK(sd_netlink_message_enter_container(message, IFLA_PROTINFO));
ASSERT_OK(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost));
ASSERT_EQ(cost, 10U);
ASSERT_OK(sd_netlink_message_exit_container(message));
}
TEST(message_getlink) {
@ -56,33 +56,33 @@ TEST(message_getlink) {
const char *str_data;
struct ether_addr eth_data;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
ifindex = (int) if_nametoindex("lo");
/* we'd really like to test NEWLINK, but let's not mess with the running kernel */
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex));
ASSERT_OK_EQ(sd_netlink_call(rtnl, message, 0, &reply), 1);
/* u8 */
assert_se(sd_netlink_message_read_u8(reply, IFLA_CARRIER, &u8_data) >= 0);
assert_se(sd_netlink_message_read_u8(reply, IFLA_OPERSTATE, &u8_data) >= 0);
assert_se(sd_netlink_message_read_u8(reply, IFLA_LINKMODE, &u8_data) >= 0);
ASSERT_OK(sd_netlink_message_read_u8(reply, IFLA_CARRIER, &u8_data));
ASSERT_OK(sd_netlink_message_read_u8(reply, IFLA_OPERSTATE, &u8_data));
ASSERT_OK(sd_netlink_message_read_u8(reply, IFLA_LINKMODE, &u8_data));
/* u16 */
assert_se(sd_netlink_message_get_type(reply, &u16_data) >= 0);
assert_se(u16_data == RTM_NEWLINK);
ASSERT_OK(sd_netlink_message_get_type(reply, &u16_data));
ASSERT_EQ(u16_data, RTM_NEWLINK);
/* u32 */
assert_se(sd_netlink_message_read_u32(reply, IFLA_MTU, &u32_data) >= 0);
assert_se(sd_netlink_message_read_u32(reply, IFLA_GROUP, &u32_data) >= 0);
assert_se(sd_netlink_message_read_u32(reply, IFLA_TXQLEN, &u32_data) >= 0);
assert_se(sd_netlink_message_read_u32(reply, IFLA_NUM_TX_QUEUES, &u32_data) >= 0);
ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_MTU, &u32_data));
ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_GROUP, &u32_data));
ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_TXQLEN, &u32_data));
ASSERT_OK(sd_netlink_message_read_u32(reply, IFLA_NUM_TX_QUEUES, &u32_data));
/* string */
assert_se(sd_netlink_message_read_string(reply, IFLA_IFNAME, &str_data) >= 0);
ASSERT_OK(sd_netlink_message_read_string(reply, IFLA_IFNAME, &str_data));
/* ether_addr */
assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &eth_data) >= 0);
ASSERT_OK(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &eth_data));
}
TEST(message_address) {
@ -94,21 +94,20 @@ TEST(message_address) {
const char *label;
int r;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl) >= 0);
ifindex = (int) if_nametoindex("lo");
assert_se(sd_rtnl_message_new_addr(rtnl, &message, RTM_GETADDR, ifindex, AF_INET) >= 0);
assert_se(sd_netlink_message_set_request_dump(message, true) >= 0);
ASSERT_OK(sd_rtnl_message_new_addr(rtnl, &message, RTM_GETADDR, ifindex, AF_INET) >= 0);
ASSERT_OK(sd_netlink_message_set_request_dump(message, true) >= 0);
r = sd_netlink_call(rtnl, message, 0, &reply);
assert_se(r >= 0);
ASSERT_OK((r = sd_netlink_call(rtnl, message, 0, &reply)));
/* If the loopback device is down we won't get any results. */
if (r > 0) {
assert_se(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data) >= 0);
assert_se(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data) >= 0);
assert_se(sd_netlink_message_read_string(reply, IFA_LABEL, &label) >= 0);
assert_se(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache) >= 0);
ASSERT_OK(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data));
ASSERT_OK(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data));
ASSERT_OK(sd_netlink_message_read_string(reply, IFA_LABEL, &label));
ASSERT_OK(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache));
}
}
@ -118,36 +117,36 @@ TEST(message_route) {
struct in_addr addr, addr_data;
uint32_t index = 2, u32_data;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC) >= 0);
ASSERT_OK(sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC) >= 0);
addr.s_addr = htobe32(INADDR_LOOPBACK);
assert_se(sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr) >= 0);
assert_se(sd_netlink_message_append_u32(req, RTA_OIF, index) >= 0);
ASSERT_OK(sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr) >= 0);
ASSERT_OK(sd_netlink_message_append_u32(req, RTA_OIF, index) >= 0);
assert_se(sd_netlink_message_rewind(req, rtnl) >= 0);
ASSERT_OK(sd_netlink_message_rewind(req, rtnl) >= 0);
assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
assert_se(addr_data.s_addr == addr.s_addr);
ASSERT_OK(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
ASSERT_EQ(addr_data.s_addr, addr.s_addr);
assert_se(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
assert_se(u32_data == index);
ASSERT_OK(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data) >= 0);
ASSERT_EQ(u32_data, index);
assert_se((req = sd_netlink_message_unref(req)) == NULL);
ASSERT_NULL((req = sd_netlink_message_unref(req)));
}
static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
const char *data;
assert_se(rtnl);
assert_se(m);
ASSERT_NOT_NULL(rtnl);
ASSERT_NOT_NULL(m);
assert_se(streq_ptr(userdata, "foo"));
ASSERT_STREQ(userdata, "foo");
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
assert_se(streq(data, "lo"));
ASSERT_OK(sd_netlink_message_read_string(m, IFLA_IFNAME, &data));
ASSERT_STREQ(data, "lo");
log_info("%s: got link info about %s", __func__, data);
return 1;
@ -160,21 +159,21 @@ TEST(netlink_event_loop) {
_cleanup_free_ char *userdata = NULL;
int ifindex;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
ifindex = (int) if_nametoindex("lo");
assert_se(userdata = strdup("foo"));
ASSERT_NOT_NULL((userdata = strdup("foo")));
assert_se(sd_event_default(&event) >= 0);
assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0);
ASSERT_OK(sd_event_default(&event));
ASSERT_OK(sd_netlink_attach_event(rtnl, event, 0));
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, userdata, 0, NULL) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, userdata, 0, NULL));
assert_se(sd_event_run(event, 0) >= 0);
ASSERT_OK(sd_event_run(event, 0));
assert_se(sd_netlink_detach_event(rtnl) >= 0);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
ASSERT_OK(sd_netlink_detach_event(rtnl));
ASSERT_NULL((rtnl = sd_netlink_unref(rtnl)));
}
static void test_async_destroy(void *userdata) {
@ -189,45 +188,45 @@ TEST(netlink_call_async) {
const char *description;
int ifindex;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
ifindex = (int) if_nametoindex("lo");
assert_se(userdata = strdup("foo"));
ASSERT_NOT_NULL((userdata = strdup("foo")));
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, userdata, 0, "hogehoge") >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
ASSERT_OK(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, userdata, 0, "hogehoge"));
assert_se(sd_netlink_slot_get_netlink(slot) == rtnl);
ASSERT_PTR_EQ(sd_netlink_slot_get_netlink(slot), rtnl);
assert_se(sd_netlink_slot_get_userdata(slot) == userdata);
assert_se(sd_netlink_slot_set_userdata(slot, NULL) == userdata);
assert_se(sd_netlink_slot_get_userdata(slot) == NULL);
assert_se(sd_netlink_slot_set_userdata(slot, userdata) == NULL);
assert_se(sd_netlink_slot_get_userdata(slot) == userdata);
ASSERT_PTR_EQ(sd_netlink_slot_get_userdata(slot), userdata);
ASSERT_PTR_EQ(sd_netlink_slot_set_userdata(slot, NULL), userdata);
ASSERT_NULL(sd_netlink_slot_get_userdata(slot));
ASSERT_NULL(sd_netlink_slot_set_userdata(slot, userdata));
ASSERT_PTR_EQ(sd_netlink_slot_get_userdata(slot), userdata);
assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
assert_se(destroy_callback == test_async_destroy);
assert_se(sd_netlink_slot_set_destroy_callback(slot, NULL) >= 0);
assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 0);
assert_se(destroy_callback == NULL);
assert_se(sd_netlink_slot_set_destroy_callback(slot, test_async_destroy) >= 0);
assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
assert_se(destroy_callback == test_async_destroy);
ASSERT_OK_EQ(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback), 1);
ASSERT_PTR_EQ(destroy_callback, test_async_destroy);
ASSERT_OK(sd_netlink_slot_set_destroy_callback(slot, NULL));
ASSERT_OK_ZERO(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback));
ASSERT_NULL(destroy_callback);
ASSERT_OK(sd_netlink_slot_set_destroy_callback(slot, test_async_destroy));
ASSERT_OK_EQ(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback), 1);
ASSERT_PTR_EQ(destroy_callback, test_async_destroy);
assert_se(sd_netlink_slot_get_floating(slot) == 0);
assert_se(sd_netlink_slot_set_floating(slot, 1) == 1);
assert_se(sd_netlink_slot_get_floating(slot) == 1);
ASSERT_OK_ZERO(sd_netlink_slot_get_floating(slot));
ASSERT_OK_EQ(sd_netlink_slot_set_floating(slot, 1), 1);
ASSERT_OK_EQ(sd_netlink_slot_get_floating(slot), 1);
assert_se(sd_netlink_slot_get_description(slot, &description) == 1);
assert_se(streq(description, "hogehoge"));
assert_se(sd_netlink_slot_set_description(slot, NULL) >= 0);
assert_se(sd_netlink_slot_get_description(slot, &description) == 0);
assert_se(description == NULL);
ASSERT_OK_EQ(sd_netlink_slot_get_description(slot, &description), 1);
ASSERT_STREQ(description, "hogehoge");
ASSERT_OK(sd_netlink_slot_set_description(slot, NULL));
ASSERT_OK_ZERO(sd_netlink_slot_get_description(slot, &description));
ASSERT_NULL(description);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, &reply) >= 0);
ASSERT_OK(sd_netlink_wait(rtnl, 0));
ASSERT_OK(sd_netlink_process(rtnl, &reply));
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
ASSERT_NULL((rtnl = sd_netlink_unref(rtnl)));
}
struct test_async_object {
@ -236,7 +235,7 @@ struct test_async_object {
};
static struct test_async_object *test_async_object_free(struct test_async_object *t) {
assert_se(t);
ASSERT_NOT_NULL(t);
free(t->ifname);
return mfree(t);
@ -249,14 +248,14 @@ static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata
struct test_async_object *t = userdata;
const char *data;
assert_se(rtnl);
assert_se(m);
assert_se(userdata);
ASSERT_NOT_NULL(rtnl);
ASSERT_NOT_NULL(m);
ASSERT_NOT_NULL(userdata);
log_info("%s: got link info about %s", __func__, t->ifname);
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
assert_se(streq(data, "lo"));
ASSERT_OK(sd_netlink_message_read_string(m, IFLA_IFNAME, &data));
ASSERT_STREQ(data, "lo");
return 1;
}
@ -264,7 +263,7 @@ static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata
static void test_async_object_destroy(void *userdata) {
struct test_async_object *t = userdata;
assert_se(userdata);
ASSERT_NOT_NULL(userdata);
log_info("%s: n_ref=%u", __func__, t->n_ref);
test_async_object_unref(t);
@ -277,66 +276,61 @@ TEST(async_destroy_callback) {
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
int ifindex;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
ifindex = (int) if_nametoindex("lo");
assert_se(t = new(struct test_async_object, 1));
ASSERT_NOT_NULL((t = new(struct test_async_object, 1)));
*t = (struct test_async_object) {
.n_ref = 1,
};
assert_se(t->ifname = strdup("lo"));
ASSERT_NOT_NULL((t->ifname = strdup("lo")));
/* destroy callback is called after processing message */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL));
assert_se(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
ASSERT_EQ(t->n_ref, 1U);
ASSERT_PTR_EQ(test_async_object_ref(t), t);
ASSERT_EQ(t->n_ref, 2U);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, &reply) == 1);
assert_se(t->n_ref == 1);
ASSERT_OK(sd_netlink_wait(rtnl, 0));
ASSERT_OK_EQ(sd_netlink_process(rtnl, &reply), 1);
ASSERT_EQ(t->n_ref, 1U);
assert_se(!sd_netlink_message_unref(m));
ASSERT_NULL(sd_netlink_message_unref(m));
/* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
ASSERT_OK(sd_netlink_call_async(rtnl, &slot, m, link_handler2, test_async_object_destroy, t, 0, NULL));
assert_se(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
ASSERT_EQ(t->n_ref, 1U);
ASSERT_PTR_EQ(test_async_object_ref(t), t);
ASSERT_EQ(t->n_ref, 2U);
assert_se(!(slot = sd_netlink_slot_unref(slot)));
assert_se(t->n_ref == 1);
ASSERT_NULL((slot = sd_netlink_slot_unref(slot)));
ASSERT_EQ(t->n_ref, 1U);
assert_se(!sd_netlink_message_unref(m));
ASSERT_NULL(sd_netlink_message_unref(m));
/* destroy callback is also called by sd_netlink_unref() */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex));
ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL));
assert_se(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
ASSERT_EQ(t->n_ref, 1U);
ASSERT_PTR_EQ(test_async_object_ref(t), t);
ASSERT_EQ(t->n_ref, 2U);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
assert_se(t->n_ref == 1);
ASSERT_NULL((rtnl = sd_netlink_unref(rtnl)));
ASSERT_EQ(t->n_ref, 1U);
}
static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int *counter = userdata;
int r;
int r, *counter = userdata;
(*counter)--;
r = sd_netlink_message_get_errno(m);
ASSERT_OK((r = sd_netlink_message_get_errno(m)));
log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
assert_se(r >= 0);
return 1;
}
@ -345,24 +339,24 @@ TEST(pipe) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
int ifindex, counter = 0;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
ifindex = (int) if_nametoindex("lo");
assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex));
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex));
counter++;
assert_se(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0, NULL) >= 0);
ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0, NULL));
counter++;
assert_se(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0, NULL) >= 0);
ASSERT_OK(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0, NULL));
while (counter > 0) {
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, NULL) >= 0);
ASSERT_OK(sd_netlink_wait(rtnl, 0));
ASSERT_OK(sd_netlink_process(rtnl, NULL));
}
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
ASSERT_NULL((rtnl = sd_netlink_unref(rtnl)));
}
TEST(message_container) {
@ -372,74 +366,74 @@ TEST(message_container) {
uint32_t u32_data;
const char *string_data;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0));
assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0);
assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
assert_se(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
ASSERT_OK(sd_netlink_message_open_container(m, IFLA_LINKINFO));
ASSERT_OK(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan"));
ASSERT_OK(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100));
ASSERT_OK(sd_netlink_message_close_container(m));
ASSERT_OK(sd_netlink_message_close_container(m));
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
ASSERT_OK(sd_netlink_message_rewind(m, rtnl));
assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0);
assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
assert_se(streq("vlan", string_data));
ASSERT_OK(sd_netlink_message_enter_container(m, IFLA_LINKINFO));
ASSERT_OK(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data));
ASSERT_STREQ("vlan", string_data);
assert_se(sd_netlink_message_enter_container(m, IFLA_INFO_DATA) >= 0);
assert_se(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0);
assert_se(sd_netlink_message_exit_container(m) >= 0);
ASSERT_OK(sd_netlink_message_enter_container(m, IFLA_INFO_DATA));
ASSERT_OK(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data));
ASSERT_OK(sd_netlink_message_exit_container(m));
assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
assert_se(streq("vlan", string_data));
assert_se(sd_netlink_message_exit_container(m) >= 0);
ASSERT_OK(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data));
ASSERT_STREQ("vlan", string_data);
ASSERT_OK(sd_netlink_message_exit_container(m));
assert_se(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
ASSERT_FAIL(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data));
}
TEST(sd_netlink_add_match) {
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
assert_se(sd_netlink_add_match(rtnl, &s2, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
assert_se(sd_netlink_add_match(rtnl, NULL, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
ASSERT_OK(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL));
ASSERT_OK(sd_netlink_add_match(rtnl, &s2, RTM_NEWLINK, link_handler, NULL, NULL, NULL));
ASSERT_OK(sd_netlink_add_match(rtnl, NULL, RTM_NEWLINK, link_handler, NULL, NULL, NULL));
assert_se(!(s1 = sd_netlink_slot_unref(s1)));
assert_se(!(s2 = sd_netlink_slot_unref(s2)));
ASSERT_NULL((s1 = sd_netlink_slot_unref(s1)));
ASSERT_NULL((s2 = sd_netlink_slot_unref(s2)));
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
ASSERT_NULL((rtnl = sd_netlink_unref(rtnl)));
}
TEST(dump_addresses) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
assert_se(sd_netlink_message_set_request_dump(req, true) >= 0);
assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
ASSERT_OK(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC));
ASSERT_OK(sd_netlink_message_set_request_dump(req, true));
ASSERT_OK(sd_netlink_call(rtnl, req, 0, &reply));
for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
uint16_t type;
unsigned char scope, flags;
int family, ifindex;
assert_se(sd_netlink_message_get_type(m, &type) >= 0);
assert_se(type == RTM_NEWADDR);
ASSERT_OK(sd_netlink_message_get_type(m, &type));
ASSERT_EQ(type, RTM_NEWADDR);
assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0);
assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0);
assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0);
assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0);
ASSERT_OK(sd_rtnl_message_addr_get_ifindex(m, &ifindex));
ASSERT_OK(sd_rtnl_message_addr_get_family(m, &family));
ASSERT_OK(sd_rtnl_message_addr_get_scope(m, &scope));
ASSERT_OK(sd_rtnl_message_addr_get_flags(m, &flags));
assert_se(ifindex > 0);
assert_se(IN_SET(family, AF_INET, AF_INET6));
ASSERT_GT(ifindex, 0);
ASSERT_TRUE(IN_SET(family, AF_INET, AF_INET6));
log_info("got IPv%i address on ifindex %i", family == AF_INET ? 4 : 6, ifindex);
}
@ -449,51 +443,51 @@ TEST(sd_netlink_message_get_errno) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
ASSERT_OK(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m));
ASSERT_ERROR(sd_netlink_message_get_errno(m), ETIMEDOUT);
}
TEST(message_array) {
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
assert_se(sd_genl_socket_open(&genl) >= 0);
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
ASSERT_OK(sd_genl_socket_open(&genl));
ASSERT_OK(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m));
assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
ASSERT_OK(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS));
for (unsigned i = 0; i < 10; i++) {
char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
uint32_t id = i + 1000;
xsprintf(name, "hoge%" PRIu32, id);
assert_se(sd_netlink_message_open_array(m, i + 1) >= 0);
assert_se(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id) >= 0);
assert_se(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name) >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
ASSERT_OK(sd_netlink_message_open_array(m, i + 1));
ASSERT_OK(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id));
ASSERT_OK(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name));
ASSERT_OK(sd_netlink_message_close_container(m));
}
assert_se(sd_netlink_message_close_container(m) >= 0);
ASSERT_OK(sd_netlink_message_close_container(m));
message_seal(m);
assert_se(sd_netlink_message_rewind(m, genl) >= 0);
ASSERT_OK(sd_netlink_message_rewind(m, genl));
assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
ASSERT_OK(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS));
for (unsigned i = 0; i < 10; i++) {
char expected[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
const char *name;
uint32_t id;
assert_se(sd_netlink_message_enter_array(m, i + 1) >= 0);
assert_se(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id) >= 0);
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name) >= 0);
assert_se(sd_netlink_message_exit_container(m) >= 0);
ASSERT_OK(sd_netlink_message_enter_array(m, i + 1));
ASSERT_OK(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id));
ASSERT_OK(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name));
ASSERT_OK(sd_netlink_message_exit_container(m));
assert_se(id == i + 1000);
ASSERT_EQ(id, i + 1000);
xsprintf(expected, "hoge%" PRIu32, id);
assert_se(streq(name, expected));
ASSERT_STREQ(name, expected);
}
assert_se(sd_netlink_message_exit_container(m) >= 0);
ASSERT_OK(sd_netlink_message_exit_container(m));
}
TEST(message_strv) {
@ -502,31 +496,31 @@ TEST(message_strv) {
_cleanup_strv_free_ char **names_in = NULL, **names_out;
const char *p;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1) >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1));
for (unsigned i = 0; i < 10; i++) {
char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
xsprintf(name, "hoge%" PRIu32, i + 1000);
assert_se(strv_extend(&names_in, name) >= 0);
ASSERT_OK(strv_extend(&names_in, name));
}
assert_se(sd_netlink_message_open_container(m, IFLA_PROP_LIST) >= 0);
assert_se(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, (const char**) names_in) >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
ASSERT_OK(sd_netlink_message_open_container(m, IFLA_PROP_LIST));
ASSERT_OK(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, (const char**) names_in));
ASSERT_OK(sd_netlink_message_close_container(m));
message_seal(m);
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
ASSERT_OK(sd_netlink_message_rewind(m, rtnl));
assert_se(sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names_out) >= 0);
assert_se(strv_equal(names_in, names_out));
ASSERT_OK(sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names_out));
ASSERT_TRUE(strv_equal(names_in, names_out));
assert_se(sd_netlink_message_enter_container(m, IFLA_PROP_LIST) >= 0);
assert_se(sd_netlink_message_read_string(m, IFLA_ALT_IFNAME, &p) >= 0);
assert_se(streq(p, "hoge1009"));
assert_se(sd_netlink_message_exit_container(m) >= 0);
ASSERT_OK(sd_netlink_message_enter_container(m, IFLA_PROP_LIST));
ASSERT_OK(sd_netlink_message_read_string(m, IFLA_ALT_IFNAME, &p));
ASSERT_STREQ(p, "hoge1009");
ASSERT_OK(sd_netlink_message_exit_container(m));
}
static int genl_ctrl_match_callback(sd_netlink *genl, sd_netlink_message *m, void *userdata) {
@ -534,26 +528,26 @@ static int genl_ctrl_match_callback(sd_netlink *genl, sd_netlink_message *m, voi
uint16_t id;
uint8_t cmd;
assert_se(genl);
assert_se(m);
ASSERT_NOT_NULL(genl);
ASSERT_NOT_NULL(m);
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
assert_se(streq(name, CTRL_GENL_NAME));
ASSERT_OK(sd_genl_message_get_family_name(genl, m, &name));
ASSERT_STREQ(name, CTRL_GENL_NAME);
assert_se(sd_genl_message_get_command(genl, m, &cmd) >= 0);
ASSERT_OK(sd_genl_message_get_command(genl, m, &cmd));
switch (cmd) {
case CTRL_CMD_NEWFAMILY:
case CTRL_CMD_DELFAMILY:
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name) >= 0);
assert_se(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id) >= 0);
ASSERT_OK(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name));
ASSERT_OK(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id));
log_debug("%s: %s (id=%"PRIu16") family is %s.",
__func__, name, id, cmd == CTRL_CMD_NEWFAMILY ? "added" : "removed");
break;
case CTRL_CMD_NEWMCAST_GRP:
case CTRL_CMD_DELMCAST_GRP:
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name) >= 0);
assert_se(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id) >= 0);
ASSERT_OK(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name));
ASSERT_OK(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id));
log_debug("%s: multicast group for %s (id=%"PRIu16") family is %s.",
__func__, name, id, cmd == CTRL_CMD_NEWMCAST_GRP ? "added" : "removed");
break;
@ -572,36 +566,35 @@ TEST(genl) {
uint8_t cmd;
int r;
assert_se(sd_genl_socket_open(&genl) >= 0);
assert_se(sd_event_default(&event) >= 0);
assert_se(sd_netlink_attach_event(genl, event, 0) >= 0);
ASSERT_OK(sd_genl_socket_open(&genl));
ASSERT_OK(sd_event_default(&event));
ASSERT_OK(sd_netlink_attach_event(genl, event, 0));
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
assert_se(streq(name, CTRL_GENL_NAME));
assert_se(sd_genl_message_get_command(genl, m, &cmd) >= 0);
assert_se(cmd == CTRL_CMD_GETFAMILY);
ASSERT_OK(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m));
ASSERT_OK(sd_genl_message_get_family_name(genl, m, &name));
ASSERT_STREQ(name, CTRL_GENL_NAME);
ASSERT_OK(sd_genl_message_get_command(genl, m, &cmd));
ASSERT_EQ(cmd, CTRL_CMD_GETFAMILY);
assert_se(sd_genl_add_match(genl, NULL, CTRL_GENL_NAME, "notify", 0, genl_ctrl_match_callback, NULL, NULL, "genl-ctrl-notify") >= 0);
ASSERT_OK(sd_genl_add_match(genl, NULL, CTRL_GENL_NAME, "notify", 0, genl_ctrl_match_callback, NULL, NULL, "genl-ctrl-notify"));
m = sd_netlink_message_unref(m);
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) < 0);
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) == -EOPNOTSUPP);
ASSERT_NULL((m = sd_netlink_message_unref(m)));
ASSERT_FAIL(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m));
ASSERT_ERROR(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m), EOPNOTSUPP);
/* These families may not be supported by kernel. Hence, ignore results. */
(void) sd_genl_message_new(genl, FOU_GENL_NAME, 0, &m);
m = sd_netlink_message_unref(m);
ASSERT_NULL((m = sd_netlink_message_unref(m)));
(void) sd_genl_message_new(genl, L2TP_GENL_NAME, 0, &m);
m = sd_netlink_message_unref(m);
ASSERT_NULL((m = sd_netlink_message_unref(m)));
(void) sd_genl_message_new(genl, MACSEC_GENL_NAME, 0, &m);
m = sd_netlink_message_unref(m);
ASSERT_NULL((m = sd_netlink_message_unref(m)));
(void) sd_genl_message_new(genl, NL80211_GENL_NAME, 0, &m);
m = sd_netlink_message_unref(m);
ASSERT_NULL((m = sd_netlink_message_unref(m)));
(void) sd_genl_message_new(genl, NETLBL_NLTYPE_UNLABELED_NAME, 0, &m);
for (;;) {
r = sd_event_run(event, 500 * USEC_PER_MSEC);
assert_se(r >= 0);
ASSERT_OK((r = sd_event_run(event, 500 * USEC_PER_MSEC)));
if (r == 0)
return;
}
@ -614,10 +607,10 @@ static void remove_dummy_interfacep(int *ifindex) {
if (!ifindex || *ifindex <= 0)
return;
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_DELLINK, *ifindex) >= 0);
assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_DELLINK, *ifindex));
ASSERT_OK_EQ(sd_netlink_call(rtnl, message, 0, NULL), 1);
}
TEST(rtnl_set_link_name) {
@ -630,28 +623,28 @@ TEST(rtnl_set_link_name) {
if (geteuid() != 0)
return (void) log_tests_skipped("not root");
assert_se(sd_netlink_open(&rtnl) >= 0);
ASSERT_OK(sd_netlink_open(&rtnl));
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 0) >= 0);
assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink") >= 0);
assert_se(sd_netlink_message_open_container(message, IFLA_LINKINFO) >= 0);
assert_se(sd_netlink_message_append_string(message, IFLA_INFO_KIND, "dummy") >= 0);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 0));
ASSERT_OK(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink"));
ASSERT_OK(sd_netlink_message_open_container(message, IFLA_LINKINFO));
ASSERT_OK(sd_netlink_message_append_string(message, IFLA_INFO_KIND, "dummy"));
r = sd_netlink_call(rtnl, message, 0, &reply);
if (r == -EPERM)
return (void) log_tests_skipped("missing required capabilities");
if (r == -EOPNOTSUPP)
return (void) log_tests_skipped("dummy network interface is not supported");
assert_se(r >= 0);
ASSERT_OK(r);
message = sd_netlink_message_unref(message);
reply = sd_netlink_message_unref(reply);
ASSERT_NULL((message = sd_netlink_message_unref(message)));
ASSERT_NULL((reply = sd_netlink_message_unref(reply)));
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, 0) >= 0);
assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink") >= 0);
assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
ASSERT_OK(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, 0));
ASSERT_OK(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink"));
ASSERT_OK_EQ(sd_netlink_call(rtnl, message, 0, &reply), 1);
assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
assert_se(ifindex > 0);
ASSERT_OK(sd_rtnl_message_link_get_ifindex(reply, &ifindex));
ASSERT_GT(ifindex, 0);
/* Test that the new name (which is currently an alternative name) is
* restored as an alternative name on error. Create an error by using
@ -662,45 +655,48 @@ TEST(rtnl_set_link_name) {
return (void) log_tests_skipped("missing required capabilities");
if (r == -EOPNOTSUPP)
return (void) log_tests_skipped("alternative name is not supported");
assert_se(r >= 0);
ASSERT_OK(r);
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-shortname"));
ASSERT_OK(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names));
ASSERT_TRUE(strv_contains(alternative_names, "testlongalternativename"));
ASSERT_TRUE(strv_contains(alternative_names, "test-shortname"));
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);
ASSERT_ERROR(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename", NULL), EINVAL);
ASSERT_OK(rtnl_set_link_name(&rtnl, ifindex, "test-shortname", STRV_MAKE("testlongalternativename", "test-shortname", "test-additional-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"));
ASSERT_NULL((alternative_names = strv_free(alternative_names)));
ASSERT_OK(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names));
ASSERT_TRUE(strv_contains(alternative_names, "testlongalternativename"));
ASSERT_TRUE(strv_contains(alternative_names, "test-additional-name"));
ASSERT_FALSE(strv_contains(alternative_names, "test-shortname"));
assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
ASSERT_OK(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")));
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_NULL((alternative_names = strv_free(alternative_names)));
ASSERT_OK_EQ(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names), ifindex);
ASSERT_FALSE(strv_contains(alternative_names, "testlongalternativename"));
ASSERT_TRUE(strv_contains(alternative_names, "test-additional-name"));
ASSERT_FALSE(strv_contains(alternative_names, "test-shortname"));
_cleanup_free_ char *resolved = NULL;
assert_se(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved) == ifindex);
assert_se(streq_ptr(resolved, "test-shortname"));
resolved = mfree(resolved);
ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", NULL), ifindex);
ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved), ifindex);
ASSERT_STREQ(resolved, "test-shortname");
ASSERT_NULL((resolved = mfree(resolved)));
assert_se(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname") >= 0);
assert_se(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname2") >= 0);
assert_se(rtnl_rename_link(NULL, "test-shortname2", "test-shortname3") >= 0);
ASSERT_OK(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname"));
ASSERT_OK(rtnl_rename_link(&rtnl, "test-shortname", "test-shortname2"));
ASSERT_OK(rtnl_rename_link(NULL, "test-shortname2", "test-shortname3"));
assert_se(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved) == ifindex);
assert_se(streq_ptr(resolved, "test-shortname3"));
resolved = mfree(resolved);
ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", NULL), ifindex);
ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-additional-name", &resolved), ifindex);
ASSERT_STREQ(resolved, "test-shortname3");
ASSERT_NULL((resolved = mfree(resolved)));
assert_se(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", &resolved) == ifindex);
assert_se(streq_ptr(resolved, "test-shortname3"));
resolved = mfree(resolved);
ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", NULL), ifindex);
ASSERT_OK_EQ(rtnl_resolve_link_alternative_name(&rtnl, "test-shortname3", &resolved), ifindex);
ASSERT_STREQ(resolved, "test-shortname3");
ASSERT_NULL((resolved = mfree(resolved)));
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -25,6 +25,7 @@ static const NamingScheme naming_schemes[] = {
{ "v254", NAMING_V254 },
{ "v255", NAMING_V255 },
{ "v257", NAMING_V257 },
{ "v258", NAMING_V258 },
/* … add more schemes here, as the logic to name devices is updated … */
EXTRA_NET_NAMING_MAP

View File

@ -45,6 +45,7 @@ typedef enum NamingSchemeFlags {
NAMING_SR_IOV_R = 1 << 17, /* Use "r" suffix for SR-IOV VF representors */
NAMING_FIRMWARE_NODE_SUN = 1 << 18, /* Use firmware_node/sun to get PCI slot number */
NAMING_DEVICETREE_PORT_ALIASES = 1 << 19, /* Include aliases of OF nodes of a netdev itself, not just its parent. See PR #33958. */
NAMING_USE_INTERFACE_PROPERTY = 1 << 20, /* Use INTERFACE udev property, rather than sysname, when no renaming is requested. */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
@ -65,6 +66,7 @@ typedef enum NamingSchemeFlags {
* systemd version 255, naming scheme "v255". */
NAMING_V255 = NAMING_V254 & ~NAMING_BRIDGE_MULTIFUNCTION_SLOT,
NAMING_V257 = NAMING_V255 | NAMING_FIRMWARE_NODE_SUN | NAMING_DEVICETREE_PORT_ALIASES,
NAMING_V258 = NAMING_V257 | NAMING_USE_INTERFACE_PROPERTY,
EXTRA_NET_NAMING_SCHEMES

View File

@ -335,8 +335,8 @@ static inline int run_test_table(void) {
({ \
typeof(expr) _result = (expr); \
if (_result >= 0) { \
log_error_errno(_result, "%s:%i: Assertion failed: expected \"%s\" to fail, but it succeeded", \
PROJECT_FILE, __LINE__, #expr); \
log_error("%s:%i: Assertion failed: expected \"%s\" to fail, but it succeeded.", \
PROJECT_FILE, __LINE__, #expr); \
abort(); \
} \
})
@ -418,6 +418,16 @@ static inline int run_test_table(void) {
} \
})
#define ASSERT_PTR_EQ(expr1, expr2) \
({ \
const void *_expr1 = (expr1), *_expr2 = (expr2); \
if (_expr1 != _expr2) { \
log_error("%s:%i: Assertion failed: expected \"%s == %s\", got \"0x%p != 0x%p\"", \
PROJECT_FILE, __LINE__, #expr1, #expr2, _expr1, _expr2); \
abort(); \
} \
})
/* DECIMAL_STR_FMT() uses _Generic which cannot be used in string concatenation so we have to format the
* input into strings first and then format those into the final assertion message. */

View File

@ -325,22 +325,6 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
return 0;
}
static int device_unsigned_attribute(sd_device *device, const char *attr, unsigned *type) {
const char *s;
int r;
r = sd_device_get_sysattr_value(device, attr, &s);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to query %s: %m", attr);
r = safe_atou(s, type);
if (r < 0)
return log_device_warning_errno(device, r, "Failed to parse %s \"%s\": %m", attr, s);
log_device_debug(device, "Device has %s=%u", attr, *type);
return 0;
}
int link_config_load(LinkConfigContext *ctx) {
_cleanup_strv_free_ char **files = NULL;
int r;
@ -400,7 +384,7 @@ int link_new(LinkConfigContext *ctx, UdevEvent *event, Link **ret) {
.event = udev_event_ref(event),
};
r = sd_device_get_sysname(dev, &link->ifname);
r = device_get_ifname(dev, &link->ifname);
if (r < 0)
return r;
@ -412,13 +396,17 @@ int link_new(LinkConfigContext *ctx, UdevEvent *event, Link **ret) {
if (r < 0)
return r;
r = device_unsigned_attribute(dev, "name_assign_type", &link->name_assign_type);
r = device_get_sysattr_unsigned(dev, "name_assign_type", &link->name_assign_type);
if (r < 0)
log_link_debug_errno(link, r, "Failed to get \"name_assign_type\" attribute, ignoring: %m");
else
log_link_debug(link, "Device has name_assign_type attribute: %u", link->name_assign_type);
r = device_unsigned_attribute(dev, "addr_assign_type", &link->addr_assign_type);
r = device_get_sysattr_unsigned(dev, "addr_assign_type", &link->addr_assign_type);
if (r < 0)
log_link_debug_errno(link, r, "Failed to get \"addr_assign_type\" attribute, ignoring: %m");
else
log_link_debug(link, "Device has addr_assign_type attribute: %u", link->addr_assign_type);
r = rtnl_get_link_info(&event->rtnl, link->ifindex, &link->iftype, &link->flags,
&link->kind, &link->hw_addr, &link->permanent_hw_addr);
@ -804,6 +792,9 @@ static int link_generate_new_name(Link *link) {
log_link_debug(link, "Policies didn't yield a name and Name= is not given, not renaming.");
no_rename:
if (!naming_scheme_has(NAMING_USE_INTERFACE_PROPERTY))
return sd_device_get_sysname(device, &link->new_name);
link->new_name = link->ifname;
return 0;
}

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "device-private.h"
#include "device-util.h"
#include "errno-util.h"
#include "ethtool-util.h"
@ -13,16 +14,16 @@ static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_close_ int ethtool_fd = -EBADF;
_cleanup_free_ char *driver = NULL;
const char *sysname;
const char *ifname;
int r;
r = sd_device_get_sysname(dev, &sysname);
r = device_get_ifname(dev, &ifname);
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get sysname: %m");
return log_device_warning_errno(dev, r, "Failed to get network interface name: %m");
r = ethtool_get_driver(&ethtool_fd, sysname, &driver);
r = ethtool_get_driver(&ethtool_fd, ifname, &driver);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) {
log_device_debug_errno(dev, r, "Querying driver name via ethtool API is not supported by device '%s', ignoring: %m", sysname);
log_device_debug_errno(dev, r, "Querying driver name via ethtool API is not supported by device '%s', ignoring: %m", ifname);
return 0;
}
if (r == -ENODEV) {
@ -30,7 +31,7 @@ static int builtin_net_driver_set_driver(UdevEvent *event, int argc, char **argv
return 0;
}
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get driver for '%s': %m", sysname);
return log_device_warning_errno(dev, r, "Failed to get driver for '%s': %m", ifname);
return udev_builtin_add_property(event, "ID_NET_DRIVER", driver);
}

View File

@ -35,7 +35,11 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv) {
/* Set ID_NET_NAME= with the current interface name. */
const char *value;
if (sd_device_get_sysname(dev, &value) >= 0)
if (naming_scheme_has(NAMING_USE_INTERFACE_PROPERTY))
r = device_get_ifname(dev, &value);
else
r = sd_device_get_sysname(dev, &value);
if (r >= 0)
(void) udev_builtin_add_property(event, "ID_NET_NAME", value);
return 0;

View File

@ -96,11 +96,8 @@ static int device_rename(sd_device *device, const char *name) {
if (r < 0)
return r;
r = sd_device_get_property_value(device, "INTERFACE", &s);
if (r == -ENOENT)
if (device_get_ifname(device, &s) < 0)
return 0;
if (r < 0)
return r;
/* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
r = device_add_property_internal(device, "INTERFACE_OLD", s);
@ -138,9 +135,9 @@ static int rename_netif(UdevEvent *event) {
return 0;
}
r = sd_device_get_sysname(dev, &s);
r = device_get_ifname(dev, &s);
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get sysname: %m");
return log_device_warning_errno(dev, r, "Failed to get ifname: %m");
if (streq(event->name, s))
return 0; /* The interface name is already requested name. */
@ -245,9 +242,9 @@ static int assign_altnames(UdevEvent *event) {
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get ifindex: %m");
r = sd_device_get_sysname(dev, &s);
r = device_get_ifname(dev, &s);
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to get sysname: %m");
return log_device_warning_errno(dev, r, "Failed to get ifname: %m");
/* Filter out the current interface name. */
strv_remove(event->altnames, s);

View File

@ -0,0 +1,46 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
mkdir -p /run/systemd/network/
cat >/run/systemd/network/10-rename-test.link <<EOF
[Match]
OriginalName=testif
[Link]
Name=te!st!if
EOF
udevadm control --log-level=debug --reload
# Check if any interfaces originally named with '!' in their name have been renamed unexpectedly.
ip link add 'hoge!foo' type dummy
udevadm wait --settle --timeout=30 '/sys/class/net/hoge!foo'
output=$(udevadm info --query property '/sys/class/net/hoge!foo')
assert_in 'INTERFACE=hoge!foo' "$output"
assert_in 'ID_NET_DRIVER=dummy' "$output"
assert_in 'ID_NET_NAME=hoge!foo' "$output"
assert_not_in 'ID_RENAMING=' "$output"
ip link show dev 'hoge!foo'
ip link del dev 'hoge!foo'
# Check if the interface renamed to include '!' as expected.
ip link add 'testif' type dummy
udevadm wait --settle --timeout=30 '/sys/class/net/te!st!if'
output=$(udevadm info --query property '/sys/class/net/te!st!if')
assert_in 'INTERFACE=te!st!if' "$output"
assert_in 'ID_NET_DRIVER=dummy' "$output"
assert_in 'ID_NET_NAME=te!st!if' "$output"
assert_not_in 'ID_RENAMING=' "$output"
ip link show dev 'te!st!if'
ip link del dev 'te!st!if'
# cleanup
rm -f /run/systemd/network/10-rename-test.link
udevadm control --log-level=info --reload
exit 0