| 160 | } |
| 161 | |
| 162 | int |
| 163 | send_fd_message(char *ifname, int sockfd, char *buf, int buflen, int *fds, int fd_num) |
| 164 | { |
| 165 | |
| 166 | struct iovec iov; |
| 167 | struct msghdr msgh; |
| 168 | size_t fdsize = fd_num * sizeof(int); |
| 169 | char control[CMSG_SPACE(fdsize)]; |
| 170 | struct cmsghdr *cmsg; |
| 171 | int ret; |
| 172 | |
| 173 | memset(&msgh, 0, sizeof(msgh)); |
| 174 | iov.iov_base = buf; |
| 175 | iov.iov_len = buflen; |
| 176 | |
| 177 | msgh.msg_iov = &iov; |
| 178 | msgh.msg_iovlen = 1; |
| 179 | |
| 180 | if (fds && fd_num > 0) { |
| 181 | msgh.msg_control = control; |
| 182 | msgh.msg_controllen = sizeof(control); |
| 183 | cmsg = CMSG_FIRSTHDR(&msgh); |
| 184 | if (cmsg == NULL) { |
| 185 | VHOST_LOG_CONFIG(ifname, ERR, "cmsg == NULL\n"); |
| 186 | errno = EINVAL; |
| 187 | return -1; |
| 188 | } |
| 189 | cmsg->cmsg_len = CMSG_LEN(fdsize); |
| 190 | cmsg->cmsg_level = SOL_SOCKET; |
| 191 | cmsg->cmsg_type = SCM_RIGHTS; |
| 192 | memcpy(CMSG_DATA(cmsg), fds, fdsize); |
| 193 | } else { |
| 194 | msgh.msg_control = NULL; |
| 195 | msgh.msg_controllen = 0; |
| 196 | } |
| 197 | |
| 198 | do { |
| 199 | ret = sendmsg(sockfd, &msgh, MSG_NOSIGNAL); |
| 200 | } while (ret < 0 && errno == EINTR); |
| 201 | |
| 202 | if (ret < 0) { |
| 203 | VHOST_LOG_CONFIG(ifname, ERR, "sendmsg error on fd %d (%s)\n", |
| 204 | sockfd, strerror(errno)); |
| 205 | return ret; |
| 206 | } |
| 207 | |
| 208 | return ret; |
| 209 | } |
| 210 | |
| 211 | static void |
| 212 | vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket) |
no test coverage detected