* return bytes# of read on success or negative val on failure. Update fdnum * with number of fds read. */
| 105 | * with number of fds read. |
| 106 | */ |
| 107 | int |
| 108 | read_fd_message(char *ifname, int sockfd, char *buf, int buflen, int *fds, int max_fds, |
| 109 | int *fd_num) |
| 110 | { |
| 111 | struct iovec iov; |
| 112 | struct msghdr msgh; |
| 113 | char control[CMSG_SPACE(max_fds * sizeof(int))]; |
| 114 | struct cmsghdr *cmsg; |
| 115 | int got_fds = 0; |
| 116 | int ret; |
| 117 | |
| 118 | *fd_num = 0; |
| 119 | |
| 120 | memset(&msgh, 0, sizeof(msgh)); |
| 121 | iov.iov_base = buf; |
| 122 | iov.iov_len = buflen; |
| 123 | |
| 124 | msgh.msg_iov = &iov; |
| 125 | msgh.msg_iovlen = 1; |
| 126 | msgh.msg_control = control; |
| 127 | msgh.msg_controllen = sizeof(control); |
| 128 | |
| 129 | ret = recvmsg(sockfd, &msgh, 0); |
| 130 | if (ret <= 0) { |
| 131 | if (ret) |
| 132 | VHOST_LOG_CONFIG(ifname, ERR, "recvmsg failed on fd %d (%s)\n", |
| 133 | sockfd, strerror(errno)); |
| 134 | return ret; |
| 135 | } |
| 136 | |
| 137 | if (msgh.msg_flags & MSG_TRUNC) |
| 138 | VHOST_LOG_CONFIG(ifname, ERR, "truncated msg (fd %d)\n", sockfd); |
| 139 | |
| 140 | /* MSG_CTRUNC may be caused by LSM misconfiguration */ |
| 141 | if (msgh.msg_flags & MSG_CTRUNC) |
| 142 | VHOST_LOG_CONFIG(ifname, ERR, "truncated control data (fd %d)\n", sockfd); |
| 143 | |
| 144 | for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; |
| 145 | cmsg = CMSG_NXTHDR(&msgh, cmsg)) { |
| 146 | if ((cmsg->cmsg_level == SOL_SOCKET) && |
| 147 | (cmsg->cmsg_type == SCM_RIGHTS)) { |
| 148 | got_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); |
| 149 | *fd_num = got_fds; |
| 150 | memcpy(fds, CMSG_DATA(cmsg), got_fds * sizeof(int)); |
| 151 | break; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | /* Clear out unused file descriptors */ |
| 156 | while (got_fds < max_fds) |
| 157 | fds[got_fds++] = -1; |
| 158 | |
| 159 | return ret; |
| 160 | } |
| 161 | |
| 162 | int |
| 163 | send_fd_message(char *ifname, int sockfd, char *buf, int buflen, int *fds, int fd_num) |
no test coverage detected