]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: add sd_netlink_sendv
authorFlorian Westphal <fw@strlen.de>
Fri, 19 Jun 2020 12:58:41 +0000 (14:58 +0200)
committerFlorian Westphal <fw@strlen.de>
Tue, 15 Dec 2020 23:35:56 +0000 (00:35 +0100)
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.

src/libsystemd/sd-netlink/netlink-internal.h
src/libsystemd/sd-netlink/netlink-socket.c
src/libsystemd/sd-netlink/sd-netlink.c
src/systemd/sd-netlink.h

index 1240f0d66d94b10d3e1259703f2452fab5247660..2845700ffb463e15e69d0dead43d5d69c1110a36 100644 (file)
@@ -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);
index 228e38df909267b8d3919d3f86609db39aff5f47..a1a839f57a9b7f700cc0cdbd69632e4a6427b239 100644 (file)
@@ -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;
index 7801101807b210e0f8d3ae0f04174fd049ff433f..5a8b4d932223701aa6d827a4ae170ebe842a9846 100644 (file)
@@ -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);
 
index 15fa84de2839fcacbf7270aa058c4b997b3285c6..2b52c4ca88870423c217c8fe52ad3acf4f0748d1 100644 (file)
@@ -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);