diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-07-04 15:46:02 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-04 15:46:02 +0200 |
commit | 52d8bcd131e7f3c9b7629412302e1ea46ddb70ca (patch) | |
tree | 058dc3ab1e4bec683ebb9afb7aef2bee88586dd2 /src | |
parent | 534b8b80b7de26f38fbf846c92c731d1cd88dbc8 (diff) | |
parent | 9104009e5ea9276c26b02c35fbff26c93f155ccd (diff) | |
download | systemd-52d8bcd131e7f3c9b7629412302e1ea46ddb70ca.tar.gz |
Merge pull request #12949 from yuwata/sd-netlink-sd-netlink-message-enter-array
sd-netlink: introduce sd_netlink_message_enter_array()
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message.c | 50 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-socket.c | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types.c | 15 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/test-netlink.c | 45 | ||||
-rw-r--r-- | src/systemd/sd-netlink.h | 1 |
5 files changed, 96 insertions, 17 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index 68b232b7d4..7850406323 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -802,24 +802,18 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, static int netlink_container_parse(sd_netlink_message *m, struct netlink_container *container, - int count, struct rtattr *rta, unsigned rt_len) { _cleanup_free_ struct netlink_attribute *attributes = NULL; - - attributes = new0(struct netlink_attribute, count); - if (!attributes) - return -ENOMEM; + size_t n_allocated = 0; for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { unsigned short type; type = RTA_TYPE(rta); - /* if the kernel is newer than the headers we used - when building, we ignore out-of-range attributes */ - if (type >= count) - continue; + if (!GREEDY_REALLOC0(attributes, n_allocated, type + 1)) + return -ENOMEM; if (attributes[type].offset != 0) log_debug("rtnl: message parse - overwriting repeated attribute"); @@ -830,7 +824,7 @@ static int netlink_container_parse(sd_netlink_message *m, } container->attributes = TAKE_PTR(attributes); - container->n_attributes = count; + container->n_attributes = n_allocated; return 0; } @@ -911,14 +905,13 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ r = netlink_message_read_internal(m, type_id, &container, NULL); if (r < 0) return r; - else - size = (size_t)r; + + size = (size_t)r; m->n_containers++; r = netlink_container_parse(m, &m->containers[m->n_containers], - type_system_get_count(type_system), container, size); if (r < 0) { @@ -931,6 +924,36 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ return 0; } +int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id) { + void *container; + size_t size; + int r; + + assert_return(m, -EINVAL); + assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); + + r = netlink_message_read_internal(m, type_id, &container, NULL); + if (r < 0) + return r; + + size = (size_t) r; + + m->n_containers++; + + r = netlink_container_parse(m, + &m->containers[m->n_containers], + container, + size); + if (r < 0) { + m->n_containers--; + return r; + } + + m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system; + + return 0; +} + int sd_netlink_message_exit_container(sd_netlink_message *m) { assert_return(m, -EINVAL); assert_return(m->sealed, -EINVAL); @@ -1015,7 +1038,6 @@ int sd_netlink_message_rewind(sd_netlink_message *m) { r = netlink_container_parse(m, &m->containers[m->n_containers], - type_system_get_count(type_system), (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), NLMSG_PAYLOAD(m->hdr, size)); if (r < 0) diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c index d1c95b260f..98edb7e2ba 100644 --- a/src/libsystemd/sd-netlink/netlink-socket.c +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -392,7 +392,7 @@ int socket_read_message(sd_netlink *rtnl) { /* check that the size matches the message type */ if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) { - log_debug("sd-netlink: message larger than expected, dropping"); + log_debug("sd-netlink: message is shorter than expected, dropping"); continue; } diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 0ac3d1664b..6850773977 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -785,9 +785,20 @@ static const NLTypeSystem genl_wireguard_type_system = { .types = genl_wireguard_cmds, }; +static const NLType genl_mcast_group_types[] = { + [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NETLINK_TYPE_STRING }, + [CTRL_ATTR_MCAST_GRP_ID] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem genl_mcast_group_type_system = { + .count = ELEMENTSOF(genl_mcast_group_types), + .types = genl_mcast_group_types, +}; + static const NLType genl_get_family_types[] = { - [CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING }, - [CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 }, + [CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING }, + [CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 }, + [CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_mcast_group_type_system }, }; static const NLTypeSystem genl_get_family_type_system = { diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c index b13fa224cc..868fcd0124 100644 --- a/src/libsystemd/sd-netlink/test-netlink.c +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -2,6 +2,7 @@ #include <net/if.h> #include <netinet/ether.h> +#include <linux/genetlink.h> #include "sd-netlink.h" @@ -11,6 +12,7 @@ #include "missing.h" #include "netlink-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "string-util.h" #include "util.h" @@ -507,6 +509,48 @@ static void test_message(sd_netlink *rtnl) { assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT); } +static void test_array(void) { + _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, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0); + + assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0); + 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_se(sd_netlink_message_close_container(m) >= 0); + + rtnl_message_seal(m); + assert_se(sd_netlink_message_rewind(m) >= 0); + + assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0); + 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_se(id == i + 1000); + xsprintf(expected, "hoge%" PRIu32, id); + assert_se(streq(name, expected)); + } + assert_se(sd_netlink_message_exit_container(m) >= 0); + +} + int main(void) { sd_netlink *rtnl; sd_netlink_message *m; @@ -524,6 +568,7 @@ int main(void) { test_route(rtnl); test_message(rtnl); test_container(rtnl); + test_array(); if_loopback = (int) if_nametoindex("lo"); assert_se(if_loopback > 0); diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h index d27e0ad201..b0a51185e9 100644 --- a/src/systemd/sd-netlink.h +++ b/src/systemd/sd-netlink.h @@ -105,6 +105,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data); int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data); int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type); +int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type); int sd_netlink_message_exit_container(sd_netlink_message *m); int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type); |