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:
parent
9667e10b1a
commit
6497a8aa9b
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user