ray/src/fling.c

79 lines
1.9 KiB
C
Raw Normal View History

2016-08-13 17:11:11 -07:00
#include "fling.h"
void init_msg(struct msghdr *msg,
struct iovec *iov,
char *buf,
size_t buf_len) {
2016-08-13 17:11:11 -07:00
iov->iov_base = buf;
iov->iov_len = 1;
msg->msg_iov = iov;
msg->msg_iovlen = 1;
msg->msg_control = buf;
msg->msg_controllen = buf_len;
msg->msg_name = NULL;
msg->msg_namelen = 0;
}
int send_fd(int conn, int fd, const char *payload, int size) {
2016-08-13 17:11:11 -07:00
struct msghdr msg;
struct iovec iov;
char buf[CMSG_SPACE(sizeof(int))];
init_msg(&msg, &iov, buf, sizeof(buf));
struct cmsghdr *header = CMSG_FIRSTHDR(&msg);
header->cmsg_level = SOL_SOCKET;
header->cmsg_type = SCM_RIGHTS;
header->cmsg_len = CMSG_LEN(sizeof(int));
*(int *) CMSG_DATA(header) = fd;
2016-08-13 17:11:11 -07:00
/* send file descriptor and payload */
2016-08-13 17:11:11 -07:00
return sendmsg(conn, &msg, 0) != -1 && send(conn, payload, size, 0) == -1;
}
int recv_fd(int conn, char *payload, int size) {
2016-08-13 17:11:11 -07:00
struct msghdr msg;
struct iovec iov;
char buf[CMSG_SPACE(sizeof(int))];
init_msg(&msg, &iov, buf, sizeof(buf));
if (recvmsg(conn, &msg, 0) == -1)
return -1;
int found_fd = -1;
int oh_noes = 0;
for (struct cmsghdr *header = CMSG_FIRSTHDR(&msg); header != NULL;
header = CMSG_NXTHDR(&msg, header))
2016-08-13 17:11:11 -07:00
if (header->cmsg_level == SOL_SOCKET && header->cmsg_type == SCM_RIGHTS) {
int count =
(header->cmsg_len - (CMSG_DATA(header) - (unsigned char *) header)) /
sizeof(int);
2016-08-13 17:11:11 -07:00
for (int i = 0; i < count; ++i) {
int fd = ((int *) CMSG_DATA(header))[i];
2016-08-13 17:11:11 -07:00
if (found_fd == -1) {
found_fd = fd;
} else {
close(fd);
oh_noes = 1;
}
}
}
/* The sender sent us more than one file descriptor. We've closed
* them all to prevent fd leaks but notify the caller that we got
* a bad message. */
2016-08-13 17:11:11 -07:00
if (oh_noes) {
close(found_fd);
errno = EBADMSG;
return -1;
}
ssize_t len = recv(conn, payload, size, 0);
if (len < 0) {
return -1;
}
return found_fd;
}