]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: introduce link_info_get()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 27 Aug 2021 08:02:59 +0000 (17:02 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 31 Aug 2021 12:25:02 +0000 (21:25 +0900)
src/udev/meson.build
src/udev/test-udev-builtin-net_id-netlink.c [new file with mode: 0644]
src/udev/udev-builtin-net_id-netlink.c [new file with mode: 0644]
src/udev/udev-builtin-net_id-netlink.h [new file with mode: 0644]

index 87bb341a56259cd69471ca4169023335b4ce1e89..7de080348f661f622b0722e855f1736748c0fd0e 100644 (file)
@@ -33,6 +33,8 @@ libudevd_core_sources = '''
         udev-builtin-hwdb.c
         udev-builtin-input_id.c
         udev-builtin-keyboard.c
+        udev-builtin-net_id-netlink.c
+        udev-builtin-net_id-netlink.h
         udev-builtin-net_id.c
         udev-builtin-net_setup_link.c
         udev-builtin-path_id.c
@@ -210,6 +212,10 @@ tests += [
          [threads,
           libacl]],
 
+        [['src/udev/test-udev-builtin-net_id-netlink.c',
+          'src/udev/udev-builtin-net_id-netlink.c',
+          'src/udev/udev-builtin-net_id-netlink.h']],
+
         [['src/udev/fido_id/test-fido-id-desc.c',
           'src/udev/fido_id/fido_id_desc.c']],
 ]
diff --git a/src/udev/test-udev-builtin-net_id-netlink.c b/src/udev/test-udev-builtin-net_id-netlink.c
new file mode 100644 (file)
index 0000000..ee9fd67
--- /dev/null
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-device.h"
+
+#include "arphrd-list.h"
+#include "ether-addr-util.h"
+#include "parse-util.h"
+#include "tests.h"
+#include "udev-builtin-net_id-netlink.h"
+
+static void test_link_info_one(sd_netlink *rtnl, int ifindex) {
+        _cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
+        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+        unsigned iftype, iflink;
+        const char *s;
+
+        log_debug("/* %s(ifindex=%i) */", __func__, ifindex);
+
+        assert_se(link_info_get(&rtnl, ifindex, &info) >= 0);
+        assert_se(sd_device_new_from_ifindex(&dev, ifindex) >= 0);
+
+        /* check iftype */
+        log_debug("iftype: %"PRIu16" (%s)", info.iftype, strna(arphrd_to_name(info.iftype)));
+        assert_se(sd_device_get_sysattr_value(dev, "type", &s) >= 0);
+        assert_se(safe_atou(s, &iftype) >= 0);
+        assert_se(iftype == info.iftype);
+
+        /* check hardware address */
+        log_debug("hardware address: %s", HW_ADDR_TO_STR(&info.hw_addr));
+        assert_se(sd_device_get_sysattr_value(dev, "address", &s) >= 0);
+        assert_se(streq(s, HW_ADDR_TO_STR(&info.hw_addr)));
+
+        /* check ifname */
+        log_debug("ifname: %s", info.ifname);
+        assert_se(sd_device_get_sysname(dev, &s) >= 0);
+        assert_se(streq(s, info.ifname));
+
+        /* check iflink */
+        log_debug("iflink: %"PRIu32, info.iflink);
+        assert_se(sd_device_get_sysattr_value(dev, "iflink", &s) >= 0);
+        assert_se(safe_atou(s, &iflink) >= 0);
+        assert_se(iflink == info.iflink);
+
+        /* check phys_port_name */
+        log_debug("phys_port_name: %s (%s)",
+                  strna(info.phys_port_name),
+                  info.support_phys_port_name ? "supported" : "unsupported");
+        if (info.support_phys_port_name) {
+                s = NULL;
+                (void) sd_device_get_sysattr_value(dev, "phys_port_name", &s);
+                assert_se(streq_ptr(s, info.phys_port_name));
+        }
+}
+
+static void test_link_info_get(void) {
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
+
+        log_debug("/* %s */", __func__);
+
+        assert_se(sd_netlink_open(&rtnl) >= 0);
+
+        assert_se(sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0) >= 0);
+        assert_se(sd_netlink_message_request_dump(req, true) >= 0);
+        assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
+
+        for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) {
+                uint16_t nlmsg_type;
+                int ifindex;
+
+                assert_se(sd_netlink_message_get_type(reply_one, &nlmsg_type) >= 0);
+                assert_se(nlmsg_type == RTM_NEWLINK);
+                assert_se(sd_rtnl_message_link_get_ifindex(reply_one, &ifindex) >= 0);
+
+                test_link_info_one(rtnl, ifindex);
+        }
+}
+
+int main(int argc, char *argv[]) {
+        test_setup_logging(LOG_DEBUG);
+
+        test_link_info_get();
+
+        return 0;
+}
diff --git a/src/udev/udev-builtin-net_id-netlink.c b/src/udev/udev-builtin-net_id-netlink.c
new file mode 100644 (file)
index 0000000..7fcd2ec
--- /dev/null
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "netlink-util.h"
+#include "udev-builtin-net_id-netlink.h"
+
+void link_info_clear(LinkInfo *info) {
+        if (!info)
+                return;
+
+        info->ifname = mfree(info->ifname);
+        info->phys_port_name = mfree(info->phys_port_name);
+}
+
+int link_info_get(sd_netlink **rtnl, int ifindex, LinkInfo *ret) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
+        _cleanup_(link_info_clear) LinkInfo info = LINK_INFO_NULL;
+        uint16_t nlmsg_type;
+        int r;
+
+        assert(rtnl);
+        assert(ifindex > 0);
+        assert(ret);
+
+        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 == -EINVAL)
+                return -ENODEV; /* The device does not exist */
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_get_type(reply, &nlmsg_type);
+        if (r < 0)
+                return r;
+        if (nlmsg_type != RTM_NEWLINK)
+                return -ENXIO;
+
+        r = sd_rtnl_message_link_get_ifindex(reply, &info.ifindex);
+        if (r < 0)
+                return r;
+        if (info.ifindex != ifindex)
+                return -ENXIO;
+
+        r = sd_rtnl_message_link_get_type(reply, &info.iftype);
+        if (r < 0)
+                return r;
+
+        r = netlink_message_read_hw_addr(reply, IFLA_ADDRESS, &info.hw_addr);
+        if (r < 0 && r != -ENODATA)
+                return r;
+
+        r = sd_netlink_message_read_string_strdup(reply, IFLA_IFNAME, &info.ifname);
+        if (r < 0)
+                return r;
+
+        r = sd_netlink_message_read_u32(reply, IFLA_LINK, &info.iflink);
+        if (r == -ENODATA)
+                info.iflink = info.ifindex;
+        else if (r < 0)
+                return r;
+
+        r = sd_netlink_message_read_string_strdup(reply, IFLA_PHYS_PORT_NAME, &info.phys_port_name);
+        if (r == -ENODATA) {
+                uint16_t max_attr;
+
+                r = sd_netlink_message_get_max_attribute(reply, &max_attr);
+                if (r < 0)
+                        return r;
+
+                info.support_phys_port_name = max_attr >= IFLA_PHYS_PORT_NAME;
+        } else if (r >= 0)
+                info.support_phys_port_name = true;
+        else
+                return r;
+
+        *ret = info;
+        info = LINK_INFO_NULL;
+        return 0;
+}
diff --git a/src/udev/udev-builtin-net_id-netlink.h b/src/udev/udev-builtin-net_id-netlink.h
new file mode 100644 (file)
index 0000000..286ac19
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-netlink.h"
+
+#include "ether-addr-util.h"
+
+typedef struct LinkInfo {
+        int ifindex;
+        uint16_t iftype;             /* ARPHRD_* */
+
+        struct hw_addr_data hw_addr; /* IFLA_ADDRESS */
+        char *ifname;                /* IFLA_IFNAME */
+        uint32_t iflink;             /* IFLA_LINK */
+        char *phys_port_name;        /* IFLA_PHYS_PORT_NAME */
+
+        bool support_phys_port_name;
+} LinkInfo;
+
+#define LINK_INFO_NULL ((LinkInfo) {})
+
+void link_info_clear(LinkInfo *info);
+int link_info_get(sd_netlink **rtnl, int ifindex, LinkInfo *ret);