diff options
Diffstat (limited to 'src/libsystemd/sd-netlink/netlink-message.c')
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-message.c | 108 |
1 files changed, 71 insertions, 37 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c index b0ed2f2882..df3b3c922e 100644 --- a/src/libsystemd/sd-netlink/netlink-message.c +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -23,19 +21,20 @@ #include <stdbool.h> #include <unistd.h> -#include "util.h" -#include "socket-util.h" +#include "sd-netlink.h" + +#include "alloc-util.h" #include "formats-util.h" -#include "refcnt.h" #include "missing.h" - -#include "sd-netlink.h" -#include "netlink-util.h" #include "netlink-internal.h" #include "netlink-types.h" +#include "netlink-util.h" +#include "refcnt.h" +#include "socket-util.h" +#include "util.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; +#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) @@ -64,7 +63,7 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) { } int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { - _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; const NLType *nl_type; size_t size; int r; @@ -108,10 +107,7 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) { m->hdr->nlmsg_type == RTM_GETNEIGH, -EINVAL); - if (dump) - m->hdr->nlmsg_flags |= NLM_F_DUMP; - else - m->hdr->nlmsg_flags &= ~NLM_F_DUMP; + SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump); return 0; } @@ -124,7 +120,9 @@ sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m) { } sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { - if (m && REFCNT_DEC(m->n_ref) == 0) { + sd_netlink_message *t; + + while (m && REFCNT_DEC(m->n_ref) == 0) { unsigned i; free(m->hdr); @@ -132,9 +130,9 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { for (i = 0; i <= m->n_containers; i++) free(m->containers[i].attributes); - sd_netlink_message_unref(m->next); - - free(m); + t = m; + m = m->next; + free(t); } return NULL; @@ -149,6 +147,15 @@ int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) { return 0; } +int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) { + assert_return(m, -EINVAL); + assert_return(flags, -EINVAL); + + m->hdr->nlmsg_flags = flags; + + return 0; +} + int sd_netlink_message_is_broadcast(sd_netlink_message *m) { assert_return(m, -EINVAL); @@ -202,11 +209,11 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da * and gives us too little data (so don't do that) */ padding = mempcpy(RTA_DATA(rta), data, data_length); - else { + + else /* if no data was passed, make sure we still initialize the padding note that we can have data_length > 0 (used by some containers) */ padding = RTA_DATA(rta); - } /* make sure also the padding at the end of the message is initialized */ padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding; @@ -262,6 +269,24 @@ int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, return 0; } +int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) { + size_t size; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_FLAG); + if (r < 0) + return r; + + r = add_rtattr(m, type, NULL, 0); + if (r < 0) + return r; + + return 0; +} + int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) { int r; @@ -314,6 +339,19 @@ int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, ui return 0; } +int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = add_rtattr(m, type, data, len); + if (r < 0) + return r; + + return 0; +} + int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) { int r; @@ -428,7 +466,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type if (r < 0) return r; - m->containers[m->n_containers ++].offset = r; + m->containers[m->n_containers++].offset = r; return 0; } @@ -459,7 +497,7 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor if (r < 0) return r; - m->containers[m->n_containers ++].offset = r; + m->containers[m->n_containers++].offset = r; return 0; } @@ -471,7 +509,7 @@ int sd_netlink_message_close_container(sd_netlink_message *m) { assert_return(m->n_containers > 0, -EINVAL); m->containers[m->n_containers].type_system = NULL; - m->n_containers --; + m->n_containers--; return 0; } @@ -483,13 +521,13 @@ static int netlink_message_read_internal(sd_netlink_message *m, unsigned short t assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); assert_return(data, -EINVAL); - assert(m->n_containers <= RTNL_CONTAINER_DEPTH); + assert(m->n_containers < RTNL_CONTAINER_DEPTH); assert(m->containers[m->n_containers].attributes); assert(type < m->containers[m->n_containers].n_attributes); attribute = &m->containers[m->n_containers].attributes[type]; - if(!attribute->offset) + if (!attribute->offset) return -ENODATA; rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset); @@ -696,7 +734,7 @@ static int netlink_container_parse(sd_netlink_message *m, _cleanup_free_ struct netlink_attribute *attributes = NULL; attributes = new0(struct netlink_attribute, count); - if(!attributes) + if (!attributes) return -ENOMEM; for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { @@ -803,7 +841,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ else size = (size_t)r; - m->n_containers ++; + m->n_containers++; r = netlink_container_parse(m, &m->containers[m->n_containers], @@ -811,7 +849,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ container, size); if (r < 0) { - m->n_containers --; + m->n_containers--; return r; } @@ -825,11 +863,10 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) { assert_return(m->sealed, -EINVAL); assert_return(m->n_containers > 0, -EINVAL); - free(m->containers[m->n_containers].attributes); - m->containers[m->n_containers].attributes = NULL; + m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes); m->containers[m->n_containers].type_system = NULL; - m->n_containers --; + m->n_containers--; return 0; } @@ -875,17 +912,14 @@ int sd_netlink_message_rewind(sd_netlink_message *m) { if (!m->sealed) rtnl_message_seal(m); - for (i = 1; i <= m->n_containers; i++) { - free(m->containers[i].attributes); - m->containers[i].attributes = NULL; - } + for (i = 1; i <= m->n_containers; i++) + m->containers[i].attributes = mfree(m->containers[i].attributes); m->n_containers = 0; - if (m->containers[0].attributes) { + if (m->containers[0].attributes) /* top-level attributes have already been parsed */ return 0; - } assert(m->hdr); |