diff options
Diffstat (limited to 'sbin/hastd/proto_common.c')
-rw-r--r-- | sbin/hastd/proto_common.c | 86 |
1 files changed, 80 insertions, 6 deletions
diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c index 84680c2b..b22ea17 100644 --- a/sbin/hastd/proto_common.c +++ b/sbin/hastd/proto_common.c @@ -33,11 +33,11 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/socket.h> -#include <assert.h> #include <errno.h> #include <stdlib.h> #include <strings.h> +#include "pjdlog.h" #include "proto_impl.h" /* Maximum size of packet we want to use when sending data. */ @@ -45,15 +45,49 @@ __FBSDID("$FreeBSD$"); #define MAX_SEND_SIZE 32768 #endif +static int +proto_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)); + bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + + if (sendmsg(sock, &msg, 0) == -1) + return (errno); + + return (0); +} + 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, int fd) { ssize_t done; size_t sendsize; + 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) { @@ -65,20 +99,60 @@ proto_common_send(int fd, const unsigned char *data, size_t size) size -= done; } while (size > 0); + if (fd == -1) + return (0); + return (proto_descriptor_send(sock, fd)); +} + +#include <stdio.h> +static int +proto_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); + + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + return (EINVAL); + } + bcopy(CMSG_DATA(cmsg), fdp, sizeof(*fdp)); + return (0); } int -proto_common_recv(int fd, unsigned char *data, size_t size) +proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp) { ssize_t done; + 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); else if (done < 0) return (errno); - return (0); + if (fdp == NULL) + return (0); + return (proto_descriptor_recv(sock, fdp)); } |