diff options
author | pjd <pjd@FreeBSD.org> | 2011-01-31 18:35:17 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2011-01-31 18:35:17 +0000 |
commit | 214239b194b6861580bd58356d9abc3e0e9b50b6 (patch) | |
tree | 6ba0be808ae947b55743d27f5ae29dc66e331979 /sbin/hastd/proto_common.c | |
parent | d916d2edb510181e3ab25256b84c439c5e1b8498 (diff) | |
download | FreeBSD-src-214239b194b6861580bd58356d9abc3e0e9b50b6.zip FreeBSD-src-214239b194b6861580bd58356d9abc3e0e9b50b6.tar.gz |
Implement two new functions for sending descriptor and receving descriptor
over UNIX domain sockets and socket pairs.
This is in preparation for capsicum.
MFC after: 1 week
Diffstat (limited to 'sbin/hastd/proto_common.c')
-rw-r--r-- | sbin/hastd/proto_common.c | 75 |
1 files changed, 69 insertions, 6 deletions
diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c index 89c637d..d638d3b 100644 --- a/sbin/hastd/proto_common.c +++ b/sbin/hastd/proto_common.c @@ -46,18 +46,18 @@ __FBSDID("$FreeBSD$"); #endif int -proto_common_send(int fd, const unsigned char *data, size_t size) +proto_common_send(int sock, const unsigned char *data, size_t size) { ssize_t done; size_t sendsize; - PJDLOG_ASSERT(fd >= 0); + PJDLOG_ASSERT(sock >= 0); PJDLOG_ASSERT(data != NULL); PJDLOG_ASSERT(size > 0); do { sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE; - done = send(fd, data, sendsize, MSG_NOSIGNAL); + done = send(sock, data, sendsize, MSG_NOSIGNAL); if (done == 0) return (ENOTCONN); else if (done < 0) { @@ -73,16 +73,16 @@ proto_common_send(int fd, const unsigned char *data, size_t size) } int -proto_common_recv(int fd, unsigned char *data, size_t size) +proto_common_recv(int sock, unsigned char *data, size_t size) { ssize_t done; - PJDLOG_ASSERT(fd >= 0); + PJDLOG_ASSERT(sock >= 0); PJDLOG_ASSERT(data != NULL); PJDLOG_ASSERT(size > 0); do { - done = recv(fd, data, size, MSG_WAITALL); + done = recv(sock, data, size, MSG_WAITALL); } while (done == -1 && errno == EINTR); if (done == 0) return (ENOTCONN); @@ -90,3 +90,66 @@ proto_common_recv(int fd, unsigned char *data, size_t size) return (errno); return (0); } + +int +proto_common_descriptor_send(int sock, int fd) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(fd))]; + struct msghdr msg; + struct cmsghdr *cmsg; + + PJDLOG_ASSERT(sock >= 0); + PJDLOG_ASSERT(fd >= 0); + + bzero(&msg, sizeof(msg)); + bzero(&ctrl, sizeof(ctrl)); + + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + msg.msg_control = ctrl; + msg.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + *((int *)CMSG_DATA(cmsg)) = fd; + + if (sendmsg(sock, &msg, 0) == -1) + return (errno); + + return (0); +} + +int +proto_common_descriptor_recv(int sock, int *fdp) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(*fdp))]; + struct msghdr msg; + struct cmsghdr *cmsg; + + PJDLOG_ASSERT(sock >= 0); + PJDLOG_ASSERT(fdp != NULL); + + bzero(&msg, sizeof(msg)); + bzero(&ctrl, sizeof(ctrl)); + + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + msg.msg_control = ctrl; + msg.msg_controllen = sizeof(ctrl); + + if (recvmsg(sock, &msg, 0) == -1) + return (errno); + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + *fdp = *((int *)CMSG_DATA(cmsg)); + return (0); + } + } + + return (ENOENT); +} |