chiark / gitweb /
rtnl: add call_async and call_async_cancel
[elogind.git] / src / libsystemd-rtnl / rtnl-message.c
index 9a40a75a9f761d3c41adf4e62f7910248eabd463..1ce68626688d7ae7bc3e231bf1fd102bcf54dee3 100644 (file)
@@ -19,6 +19,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <linux/rtnetlink.h>
 #include <netinet/in.h>
 #include <netinet/ether.h>
 #include <stdbool.h>
@@ -67,6 +68,27 @@ static int message_new(sd_rtnl_message **ret, size_t initial_size) {
         return 0;
 }
 
+int message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) {
+        struct nlmsgerr *err;
+        int r;
+
+        assert(error <= 0);
+
+        r = message_new(ret, NLMSG_SPACE(sizeof(struct nlmsgerr)));
+        if (r < 0)
+                return r;
+
+        (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
+        (*ret)->hdr->nlmsg_type = NLMSG_ERROR;
+        (*ret)->hdr->nlmsg_seq = serial;
+
+        err = NLMSG_DATA((*ret)->hdr);
+
+        err->error = error;
+
+        return 0;
+}
+
 int sd_rtnl_message_route_new(uint16_t nlmsg_type, unsigned char rtm_family,
                               unsigned char rtm_dst_len, unsigned char rtm_src_len,
                               unsigned char rtm_tos, unsigned char rtm_table,
@@ -186,6 +208,7 @@ static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data,
         uint32_t rta_length, message_length;
         struct nlmsghdr *new_hdr;
         struct rtattr *rta;
+        char *padding;
 
         assert_return(m, -EINVAL);
         assert_return(m->hdr, -EINVAL);
@@ -193,10 +216,9 @@ static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data,
         assert_return(data, -EINVAL);
         assert_return(data_length > 0, -EINVAL);
 
-        /* get the size of the new rta attribute (without padding at the end) */
+        /* get the size of the new rta attribute (with padding at the end) */
         rta_length = RTA_LENGTH(data_length);
-        /* get the new message size (with padding between the old message and the new attrib,
-         * but no padding after)
+        /* get the new message size (with padding at the end)
          */
         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
 
@@ -217,7 +239,9 @@ static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *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)
          */
-        memcpy(RTA_DATA(rta), data, data_length);
+        padding = mempcpy(RTA_DATA(rta), data, data_length);
+        /* make sure also the padding at the end of the message is initialized */
+        memset(padding, '\0', (unsigned char *) m->hdr + m->hdr->nlmsg_len - (unsigned char *) padding);
 
         return 0;
 }
@@ -364,16 +388,16 @@ int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data)
         return message_read(m, type, data);
 }
 
-int message_get_serial(sd_rtnl_message *m) {
+uint32_t message_get_serial(sd_rtnl_message *m) {
         assert(m);
 
         return m->hdr->nlmsg_seq;
 }
 
-int message_get_errno(sd_rtnl_message *m) {
+int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
         struct nlmsgerr *err;
 
-        assert(m);
+        assert_return(m, -EINVAL);
 
         if (m->hdr->nlmsg_type != NLMSG_ERROR)
                 return 0;