chiark / gitweb /
sd-rtnl: fix creation of synthetic error replies
[elogind.git] / src / libsystemd / sd-rtnl / rtnl-message.c
index 9099440ad461bf0475eb0a66822c1a1b97be3b5b..23253029e5fefbc4ed69e25fda18da24dd1bf339 100644 (file)
@@ -43,7 +43,7 @@ static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
 
         assert_return(ret, -EINVAL);
 
-        /* Note that 'rtnl' is curretly unused, if we start using it internally
+        /* Note that 'rtnl' is currently unused, if we start using it internally
            we must take care to avoid problems due to mutual references between
            busses and their queued messages. See sd-bus.
          */
@@ -71,8 +71,6 @@ int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
         if (r < 0)
                 return r;
 
-        assert(nl_type->type == NLA_NESTED);
-
         r = message_new_empty(rtnl, &m);
         if (r < 0)
                 return r;
@@ -586,7 +584,7 @@ sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
 }
 
 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
-        if (m && REFCNT_DEC(m->n_ref) <= 0) {
+        if (m && REFCNT_DEC(m->n_ref) == 0) {
                 unsigned i;
 
                 free(m->hdr);
@@ -1348,8 +1346,10 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
                 /* no data */
                 if (errno == ENOBUFS)
                         log_debug("rtnl: kernel receive buffer overrun");
+                else if (errno == EAGAIN)
+                        log_debug("rtnl: no data in socket");
 
-                return (errno == EAGAIN) ? 0 : -errno;
+                return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
         } else if (r == 0)
                 /* connection was closed by the kernel */
                 return -ECONNRESET;
@@ -1361,8 +1361,10 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
                         struct ucred *ucred = (void *)CMSG_DATA(cmsg);
 
                         /* from the kernel */
-                        if (ucred->uid == 0 && ucred->pid == 0)
+                        if (ucred->pid == 0)
                                 auth = true;
+                        else
+                                log_debug("rtnl: ignoring message from PID "PID_FMT, ucred->pid);
                 } else if (cmsg->cmsg_level == SOL_NETLINK &&
                            cmsg->cmsg_type == NETLINK_PKTINFO &&
                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
@@ -1373,9 +1375,17 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool
                 }
         }
 
-        if (!auth)
+        if (!auth) {
                 /* not from the kernel, ignore */
+                if (peek) {
+                        /* drop the message */
+                        r = recvmsg(fd, &msg, 0);
+                        if (r < 0)
+                                return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
+                }
+
                 return 0;
+        }
 
         if (group)
                 *_group = group;
@@ -1464,7 +1474,7 @@ int socket_read_message(sd_rtnl *rtnl) {
                 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
                 if (r < 0) {
                         if (r == -ENOTSUP)
-                                log_debug("sd-rtnl: ignored message with unknown type: %u",
+                                log_debug("sd-rtnl: ignored message with unknown type: %i",
                                           new_msg->nlmsg_type);
 
                         continue;