1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-08 21:17:47 +03:00

sd-netlink: introduce rtattr_append_attribute()

It will be used in later commit.
This commit is contained in:
Yu Watanabe 2019-11-28 01:28:36 +09:00
parent 9667e10b1a
commit 6497a8aa9b
3 changed files with 70 additions and 31 deletions

View File

@ -142,11 +142,9 @@ int sd_netlink_message_is_broadcast(const sd_netlink_message *m) {
/* If successful the updated message will be correctly aligned, if
unsuccessful the old message is untouched. */
static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) {
uint32_t rta_length;
size_t message_length, padding_length;
size_t message_length;
struct nlmsghdr *new_hdr;
struct rtattr *rta;
char *padding;
unsigned i;
int offset;
@ -154,16 +152,10 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
assert(m->hdr);
assert(!m->sealed);
assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
assert(!data || data_length);
/* get offset of the new attribute */
offset = m->hdr->nlmsg_len;
/* get the size of the new rta attribute (with padding at the end) */
rta_length = RTA_LENGTH(data_length);
assert(!data || data_length > 0);
/* get the new message size (with padding at the end) */
message_length = offset + RTA_ALIGN(rta_length);
message_length = m->hdr->nlmsg_len + RTA_SPACE(data_length);
/* buffer should be smaller than both one page or 8K to be accepted by the kernel */
if (message_length > MIN(page_size(), 8192UL))
@ -176,33 +168,19 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
m->hdr = new_hdr;
/* get pointer to the attribute we are about to add */
rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
rtattr_append_attribute_internal(rta, type, data, data_length);
/* if we are inside containers, extend them */
for (i = 0; i < m->n_containers; i++)
GET_CONTAINER(m, i)->rta_len += message_length - offset;
/* fill in the attribute */
rta->rta_type = type;
rta->rta_len = rta_length;
if (data)
/* we don't deal with the case where the user lies about the type
* and gives us too little data (so don't do that)
*/
padding = mempcpy(RTA_DATA(rta), data, data_length);
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;
memzero(padding, padding_length);
GET_CONTAINER(m, i)->rta_len += RTA_SPACE(data_length);
/* update message size */
offset = m->hdr->nlmsg_len;
m->hdr->nlmsg_len = message_length;
/* return old message size */
return offset;
}

View File

@ -2,6 +2,7 @@
#include "sd-netlink.h"
#include "memory-util.h"
#include "netlink-internal.h"
#include "netlink-util.h"
#include "strv.h"
@ -178,3 +179,60 @@ int rtnl_log_parse_error(int r) {
int rtnl_log_create_error(int r) {
return log_error_errno(r, "Failed to create netlink message: %m");
}
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length) {
size_t padding_length;
char *padding;
assert(rta);
assert(!data || data_length > 0);
/* fill in the attribute */
rta->rta_type = type;
rta->rta_len = RTA_LENGTH(data_length);
if (data)
/* we don't deal with the case where the user lies about the type
* and gives us too little data (so don't do that)
*/
padding = mempcpy(RTA_DATA(rta), data, data_length);
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 = (char *) rta + RTA_SPACE(data_length) - padding;
memzero(padding, padding_length);
}
int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length) {
struct rtattr *new_rta, *sub_rta;
size_t message_length;
assert(rta);
assert(!data || data_length > 0);
/* get the new message size (with padding at the end) */
message_length = RTA_ALIGN(rta ? (*rta)->rta_len : 0) + RTA_SPACE(data_length);
/* buffer should be smaller than both one page or 8K to be accepted by the kernel */
if (message_length > MIN(page_size(), 8192UL))
return -ENOBUFS;
/* realloc to fit the new attribute */
new_rta = realloc(*rta, message_length);
if (!new_rta)
return -ENOMEM;
*rta = new_rta;
/* get pointer to the attribute we are about to add */
sub_rta = (struct rtattr *) ((uint8_t *) *rta + RTA_ALIGN((*rta)->rta_len));
rtattr_append_attribute_internal(sub_rta, type, data, data_length);
/* update rta_len */
(*rta)->rta_len = message_length;
return 0;
}

View File

@ -77,3 +77,6 @@ int rtnl_log_create_error(int r);
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length);
int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length);