chiark / gitweb /
sd-rtnl: fix bogus warning about dropping 20 bytes from multi-part messages
[elogind.git] / src / libsystemd / sd-rtnl / rtnl-message.c
index 84ebf65d8ebab93f430cf52a9fb47f454101ebf9..ac920b2d3022b675ad75bef1ab9b712a80b10ea2 100644 (file)
@@ -114,6 +114,24 @@ int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char pr
         return 0;
 }
 
+int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
+        struct rtmsg *rtm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+
+        rtm = NLMSG_DATA(m->hdr);
+
+        if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
+            (rtm->rtm_family == AF_INET6 && prefixlen > 128))
+                return -ERANGE;
+
+        rtm->rtm_src_len = prefixlen;
+
+        return 0;
+}
+
 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
         struct rtmsg *rtm;
 
@@ -143,6 +161,36 @@ int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
         return 0;
 }
 
+int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) {
+        struct rtmsg *rtm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+        assert_return(dst_len, -EINVAL);
+
+        rtm = NLMSG_DATA(m->hdr);
+
+        *dst_len = rtm->rtm_dst_len;
+
+        return 0;
+}
+
+int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
+        struct rtmsg *rtm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+        assert_return(src_len, -EINVAL);
+
+        rtm = NLMSG_DATA(m->hdr);
+
+        *src_len = rtm->rtm_src_len;
+
+        return 0;
+}
+
 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
                               uint16_t nlmsg_type, int rtm_family,
                               unsigned char rtm_protocol) {
@@ -150,7 +198,8 @@ int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
         int r;
 
         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
-        assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
+        assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
+                      rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
         assert_return(ret, -EINVAL);
 
         r = message_new(rtnl, ret, nlmsg_type);
@@ -1331,7 +1380,7 @@ int socket_read_message(sd_rtnl *rtnl) {
                 }
         }
 
-        for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
+        for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
                 const NLType *nl_type;
 
@@ -1346,7 +1395,8 @@ int socket_read_message(sd_rtnl *rtnl) {
                 if (new_msg->nlmsg_type == NLMSG_DONE) {
                         /* finished reading multi-part message */
                         done = true;
-                        break;
+
+                        continue;
                 }
 
                 /* check that we support this message type */