sd-netlink: introduce sd_netlink_message_read_strv()
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.
This commit is contained in:
parent
ffeb16f5d8
commit
8f3c185966
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue