]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: introduce rtattr_append_attribute()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 27 Nov 2019 16:28:36 +0000 (01:28 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 18 Dec 2019 13:12:57 +0000 (22:12 +0900)
It will be used in later commit.

src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-util.c
src/libsystemd/sd-netlink/netlink-util.h

index 247868221d07046f5bbcb939e799ee0382a8f949..39e3c36ad2aba25246b0535c6f80b7af268b698b 100644 (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;
 }
 
index 80725f6cb4eabea36445b955f9a66381c5641850..c35d6ba4a5ba58dec09b811adaa4d27c684d17b4 100644 (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;
+}
index 8c43fafec706f0976b90b8c9d2df5ae61fa9e942..1782786841115dde899f58c7471fba2d81542e0e 100644 (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);