sd-netlink: add sd_netlink_sendv
nftables uses a transaction-based netlink model: one netlink write comes with multiple messages. A 'BEGIN' message to tell nf_tables/kernel that a new transaction starts. Then, one more messages to add/delete tables/chains/rules etc. Lastly, an END message that commits all changes. This function will be used to send all the individual messages that should make up a single transaction as a single write.
This commit is contained in:
parent
347ea16797
commit
99c41c0de4
|
@ -139,6 +139,7 @@ int socket_bind(sd_netlink *nl);
|
|||
int socket_broadcast_group_ref(sd_netlink *nl, unsigned group);
|
||||
int socket_broadcast_group_unref(sd_netlink *nl, unsigned group);
|
||||
int socket_write_message(sd_netlink *nl, sd_netlink_message *m);
|
||||
int socket_writev_message(sd_netlink *nl, sd_netlink_message *m[], size_t msgcount);
|
||||
int socket_read_message(sd_netlink *nl);
|
||||
|
||||
int rtnl_rqueue_make_room(sd_netlink *rtnl);
|
||||
|
|
|
@ -238,6 +238,31 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
|
|||
return k;
|
||||
}
|
||||
|
||||
int socket_writev_message(sd_netlink *nl, sd_netlink_message *m[], size_t msgcount) {
|
||||
_cleanup_free_ struct iovec *iovs = NULL;
|
||||
ssize_t k;
|
||||
size_t i;
|
||||
|
||||
assert(nl);
|
||||
assert(msgcount);
|
||||
|
||||
iovs = new0(struct iovec, msgcount);
|
||||
if (!iovs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < msgcount; i++) {
|
||||
assert(m[i]->hdr != NULL);
|
||||
assert(m[i]->hdr->nlmsg_len > 0);
|
||||
iovs[i] = IOVEC_MAKE(m[i]->hdr, m[i]->hdr->nlmsg_len);
|
||||
}
|
||||
|
||||
k = writev(nl->fd, iovs, msgcount);
|
||||
if (k < 0)
|
||||
return -errno;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_group, bool peek) {
|
||||
union sockaddr_union sender;
|
||||
CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct nl_pktinfo))) control;
|
||||
|
|
|
@ -226,6 +226,41 @@ int sd_netlink_send(sd_netlink *nl,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int sd_netlink_sendv(sd_netlink *nl,
|
||||
sd_netlink_message *messages[],
|
||||
size_t msgcount,
|
||||
uint32_t **ret_serial) {
|
||||
_cleanup_free_ uint32_t *serials = NULL;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(!rtnl_pid_changed(nl), -ECHILD);
|
||||
assert_return(messages, -EINVAL);
|
||||
|
||||
if (ret_serial) {
|
||||
serials = new0(uint32_t, msgcount);
|
||||
if (!serials)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < msgcount; i++) {
|
||||
assert_return(!messages[i]->sealed, -EPERM);
|
||||
rtnl_seal_message(nl, messages[i]);
|
||||
if (serials)
|
||||
serials[i] = rtnl_message_get_serial(messages[i]);
|
||||
}
|
||||
|
||||
r = socket_writev_message(nl, messages, msgcount);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_serial)
|
||||
*ret_serial = TAKE_PTR(serials);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int rtnl_rqueue_make_room(sd_netlink *rtnl) {
|
||||
assert(rtnl);
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ sd_netlink *sd_netlink_ref(sd_netlink *nl);
|
|||
sd_netlink *sd_netlink_unref(sd_netlink *nl);
|
||||
|
||||
int sd_netlink_send(sd_netlink *nl, sd_netlink_message *message, uint32_t *serial);
|
||||
int sd_netlink_sendv(sd_netlink *nl, sd_netlink_message *messages[], size_t msgcnt, uint32_t **ret_serial);
|
||||
int sd_netlink_call_async(sd_netlink *nl, sd_netlink_slot **ret_slot, sd_netlink_message *message,
|
||||
sd_netlink_message_handler_t callback, sd_netlink_destroy_t destoy_callback,
|
||||
void *userdata, uint64_t usec, const char *description);
|
||||
|
|
Loading…
Reference in New Issue