]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: introduce sd_netlink_message_read_strv()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 15 Dec 2019 12:32:25 +0000 (21:32 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 16 Dec 2019 01:52:17 +0000 (10:52 +0900)
The combination of sd_netlink_message_enter_container() and
sd_netlink_message_read_string() only reads the last element if the attribute is
duplicated, such a situation easily happens for IFLA_ALT_IFNAME.
The function introduced here reads all matched attributes.

src/libsystemd/sd-netlink/netlink-message.c
src/systemd/sd-netlink.h

index 3b7f3eb7876c939ad57590a51e2daef64759322c..aaf8811d8dea88b1b4438ffc1b2921eff113b9a9 100644 (file)
@@ -8,11 +8,12 @@
 
 #include "alloc-util.h"
 #include "format-util.h"
+#include "memory-util.h"
 #include "netlink-internal.h"
 #include "netlink-types.h"
 #include "netlink-util.h"
 #include "socket-util.h"
-#include "memory-util.h"
+#include "strv.h"
 
 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
@@ -828,6 +829,63 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
         return 0;
 }
 
+int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
+        _cleanup_strv_free_ char **s = NULL;
+        const NLTypeSystem *type_system;
+        const NLType *nl_type;
+        struct rtattr *rta;
+        void *container;
+        unsigned short rt_len;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
+
+        r = type_system_get_type(m->containers[m->n_containers].type_system,
+                                 &nl_type,
+                                 container_type);
+        if (r < 0)
+                return r;
+
+        if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
+                return -EINVAL;
+
+        r = type_system_get_type_system(m->containers[m->n_containers].type_system,
+                                        &type_system,
+                                        container_type);
+        if (r < 0)
+                return r;
+
+        r = type_system_get_type(type_system, &nl_type, type_id);
+        if (r < 0)
+                return r;
+
+        if (type_get_type(nl_type) != NETLINK_TYPE_STRING)
+                return -EINVAL;
+
+        r = netlink_message_read_internal(m, container_type, &container, NULL);
+        if (r < 0)
+                return r;
+
+        rt_len = (unsigned short) r;
+        rta = container;
+
+        for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
+                unsigned short type;
+
+                type = RTA_TYPE(rta);
+                if (type != type_id)
+                        continue;
+
+                r = strv_extend(&s, RTA_DATA(rta));
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = TAKE_PTR(s);
+        return 0;
+}
+
 static int netlink_container_parse(sd_netlink_message *m,
                                    struct netlink_container *container,
                                    struct rtattr *rta,
index b34befebc8fb29594b03bf844b5bd071dd4e91f7..fbddcea3d7cb76f685b69287b85eaa4206e8876c 100644 (file)
@@ -100,6 +100,7 @@ int sd_netlink_message_close_container(sd_netlink_message *m);
 int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data);
 int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data);
 int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data);
+int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret);
 int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data);
 int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data);
 int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data);