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
This commit is contained in:
parent
2ec483c58e
commit
8046c499ab
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=218139
@ -216,6 +216,42 @@ proto_recv(const struct proto_conn *conn, void *data, size_t size)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
proto_descriptor_send(const struct proto_conn *conn, int fd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
PJDLOG_ASSERT(conn != NULL);
|
||||||
|
PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
|
||||||
|
PJDLOG_ASSERT(conn->pc_proto != NULL);
|
||||||
|
PJDLOG_ASSERT(conn->pc_proto->hp_descriptor_send != NULL);
|
||||||
|
|
||||||
|
ret = conn->pc_proto->hp_descriptor_send(conn->pc_ctx, fd);
|
||||||
|
if (ret != 0) {
|
||||||
|
errno = ret;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
proto_descriptor_recv(const struct proto_conn *conn, int *fdp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
PJDLOG_ASSERT(conn != NULL);
|
||||||
|
PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC);
|
||||||
|
PJDLOG_ASSERT(conn->pc_proto != NULL);
|
||||||
|
PJDLOG_ASSERT(conn->pc_proto->hp_descriptor_recv != NULL);
|
||||||
|
|
||||||
|
ret = conn->pc_proto->hp_descriptor_recv(conn->pc_ctx, fdp);
|
||||||
|
if (ret != 0) {
|
||||||
|
errno = ret;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
proto_descriptor(const struct proto_conn *conn)
|
proto_descriptor(const struct proto_conn *conn)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,8 @@ int proto_server(const char *addr, struct proto_conn **connp);
|
|||||||
int proto_accept(struct proto_conn *conn, struct proto_conn **newconnp);
|
int proto_accept(struct proto_conn *conn, struct proto_conn **newconnp);
|
||||||
int proto_send(const struct proto_conn *conn, const void *data, size_t size);
|
int proto_send(const struct proto_conn *conn, const void *data, size_t size);
|
||||||
int proto_recv(const struct proto_conn *conn, void *data, size_t size);
|
int proto_recv(const struct proto_conn *conn, void *data, size_t size);
|
||||||
|
int proto_descriptor_send(const struct proto_conn *conn, int fd);
|
||||||
|
int proto_descriptor_recv(const struct proto_conn *conn, int *fdp);
|
||||||
int proto_descriptor(const struct proto_conn *conn);
|
int proto_descriptor(const struct proto_conn *conn);
|
||||||
bool proto_address_match(const struct proto_conn *conn, const char *addr);
|
bool proto_address_match(const struct proto_conn *conn, const char *addr);
|
||||||
void proto_local_address(const struct proto_conn *conn, char *addr,
|
void proto_local_address(const struct proto_conn *conn, char *addr,
|
||||||
|
@ -46,18 +46,18 @@ __FBSDID("$FreeBSD$");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
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;
|
ssize_t done;
|
||||||
size_t sendsize;
|
size_t sendsize;
|
||||||
|
|
||||||
PJDLOG_ASSERT(fd >= 0);
|
PJDLOG_ASSERT(sock >= 0);
|
||||||
PJDLOG_ASSERT(data != NULL);
|
PJDLOG_ASSERT(data != NULL);
|
||||||
PJDLOG_ASSERT(size > 0);
|
PJDLOG_ASSERT(size > 0);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE;
|
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)
|
if (done == 0)
|
||||||
return (ENOTCONN);
|
return (ENOTCONN);
|
||||||
else if (done < 0) {
|
else if (done < 0) {
|
||||||
@ -73,16 +73,16 @@ proto_common_send(int fd, const unsigned char *data, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
ssize_t done;
|
||||||
|
|
||||||
PJDLOG_ASSERT(fd >= 0);
|
PJDLOG_ASSERT(sock >= 0);
|
||||||
PJDLOG_ASSERT(data != NULL);
|
PJDLOG_ASSERT(data != NULL);
|
||||||
PJDLOG_ASSERT(size > 0);
|
PJDLOG_ASSERT(size > 0);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
done = recv(fd, data, size, MSG_WAITALL);
|
done = recv(sock, data, size, MSG_WAITALL);
|
||||||
} while (done == -1 && errno == EINTR);
|
} while (done == -1 && errno == EINTR);
|
||||||
if (done == 0)
|
if (done == 0)
|
||||||
return (ENOTCONN);
|
return (ENOTCONN);
|
||||||
@ -90,3 +90,66 @@ proto_common_recv(int fd, unsigned char *data, size_t size)
|
|||||||
return (errno);
|
return (errno);
|
||||||
return (0);
|
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);
|
||||||
|
}
|
||||||
|
@ -45,6 +45,8 @@ typedef int hp_server_t(const char *, void **);
|
|||||||
typedef int hp_accept_t(void *, void **);
|
typedef int hp_accept_t(void *, void **);
|
||||||
typedef int hp_send_t(void *, const unsigned char *, size_t);
|
typedef int hp_send_t(void *, const unsigned char *, size_t);
|
||||||
typedef int hp_recv_t(void *, unsigned char *, size_t);
|
typedef int hp_recv_t(void *, unsigned char *, size_t);
|
||||||
|
typedef int hp_descriptor_send_t(void *, int);
|
||||||
|
typedef int hp_descriptor_recv_t(void *, int *);
|
||||||
typedef int hp_descriptor_t(const void *);
|
typedef int hp_descriptor_t(const void *);
|
||||||
typedef bool hp_address_match_t(const void *, const char *);
|
typedef bool hp_address_match_t(const void *, const char *);
|
||||||
typedef void hp_local_address_t(const void *, char *, size_t);
|
typedef void hp_local_address_t(const void *, char *, size_t);
|
||||||
@ -59,6 +61,8 @@ struct hast_proto {
|
|||||||
hp_accept_t *hp_accept;
|
hp_accept_t *hp_accept;
|
||||||
hp_send_t *hp_send;
|
hp_send_t *hp_send;
|
||||||
hp_recv_t *hp_recv;
|
hp_recv_t *hp_recv;
|
||||||
|
hp_descriptor_send_t *hp_descriptor_send;
|
||||||
|
hp_descriptor_recv_t *hp_descriptor_recv;
|
||||||
hp_descriptor_t *hp_descriptor;
|
hp_descriptor_t *hp_descriptor;
|
||||||
hp_address_match_t *hp_address_match;
|
hp_address_match_t *hp_address_match;
|
||||||
hp_local_address_t *hp_local_address;
|
hp_local_address_t *hp_local_address;
|
||||||
@ -69,7 +73,9 @@ struct hast_proto {
|
|||||||
|
|
||||||
void proto_register(struct hast_proto *proto, bool isdefault);
|
void proto_register(struct hast_proto *proto, bool isdefault);
|
||||||
|
|
||||||
int proto_common_send(int fd, const unsigned char *data, size_t size);
|
int proto_common_send(int sock, const unsigned char *data, size_t size);
|
||||||
int proto_common_recv(int fd, unsigned char *data, size_t size);
|
int proto_common_recv(int sock, unsigned char *data, size_t size);
|
||||||
|
int proto_common_descriptor_send(int sock, int fd);
|
||||||
|
int proto_common_descriptor_recv(int sock, int *fdp);
|
||||||
|
|
||||||
#endif /* !_PROTO_IMPL_H_ */
|
#endif /* !_PROTO_IMPL_H_ */
|
||||||
|
@ -160,6 +160,34 @@ sp_recv(void *ctx, unsigned char *data, size_t size)
|
|||||||
return (proto_common_recv(fd, data, size));
|
return (proto_common_recv(fd, data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sp_descriptor_send(void *ctx, int fd)
|
||||||
|
{
|
||||||
|
struct sp_ctx *spctx = ctx;
|
||||||
|
|
||||||
|
PJDLOG_ASSERT(spctx != NULL);
|
||||||
|
PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
|
||||||
|
PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT);
|
||||||
|
PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
|
||||||
|
PJDLOG_ASSERT(fd > 0);
|
||||||
|
|
||||||
|
return (proto_common_descriptor_send(spctx->sp_fd[0], fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sp_descriptor_recv(void *ctx, int *fdp)
|
||||||
|
{
|
||||||
|
struct sp_ctx *spctx = ctx;
|
||||||
|
|
||||||
|
PJDLOG_ASSERT(spctx != NULL);
|
||||||
|
PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
|
||||||
|
PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_SERVER);
|
||||||
|
PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
|
||||||
|
PJDLOG_ASSERT(fdp != NULL);
|
||||||
|
|
||||||
|
return (proto_common_descriptor_recv(spctx->sp_fd[1], fdp));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sp_descriptor(const void *ctx)
|
sp_descriptor(const void *ctx)
|
||||||
{
|
{
|
||||||
@ -224,6 +252,8 @@ static struct hast_proto sp_proto = {
|
|||||||
.hp_client = sp_client,
|
.hp_client = sp_client,
|
||||||
.hp_send = sp_send,
|
.hp_send = sp_send,
|
||||||
.hp_recv = sp_recv,
|
.hp_recv = sp_recv,
|
||||||
|
.hp_descriptor_send = sp_descriptor_send,
|
||||||
|
.hp_descriptor_recv = sp_descriptor_recv,
|
||||||
.hp_descriptor = sp_descriptor,
|
.hp_descriptor = sp_descriptor,
|
||||||
.hp_close = sp_close
|
.hp_close = sp_close
|
||||||
};
|
};
|
||||||
|
@ -225,6 +225,32 @@ uds_recv(void *ctx, unsigned char *data, size_t size)
|
|||||||
return (proto_common_recv(uctx->uc_fd, data, size));
|
return (proto_common_recv(uctx->uc_fd, data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
uds_descriptor_send(void *ctx, int fd)
|
||||||
|
{
|
||||||
|
struct uds_ctx *uctx = ctx;
|
||||||
|
|
||||||
|
PJDLOG_ASSERT(uctx != NULL);
|
||||||
|
PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
|
||||||
|
PJDLOG_ASSERT(uctx->uc_fd >= 0);
|
||||||
|
PJDLOG_ASSERT(fd >= 0);
|
||||||
|
|
||||||
|
return (proto_common_descriptor_send(uctx->uc_fd, fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
uds_descriptor_recv(void *ctx, int *fdp)
|
||||||
|
{
|
||||||
|
struct uds_ctx *uctx = ctx;
|
||||||
|
|
||||||
|
PJDLOG_ASSERT(uctx != NULL);
|
||||||
|
PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC);
|
||||||
|
PJDLOG_ASSERT(uctx->uc_fd >= 0);
|
||||||
|
PJDLOG_ASSERT(fdp != NULL);
|
||||||
|
|
||||||
|
return (proto_common_descriptor_recv(uctx->uc_fd, fdp));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
uds_descriptor(const void *ctx)
|
uds_descriptor(const void *ctx)
|
||||||
{
|
{
|
||||||
@ -307,6 +333,8 @@ static struct hast_proto uds_proto = {
|
|||||||
.hp_accept = uds_accept,
|
.hp_accept = uds_accept,
|
||||||
.hp_send = uds_send,
|
.hp_send = uds_send,
|
||||||
.hp_recv = uds_recv,
|
.hp_recv = uds_recv,
|
||||||
|
.hp_descriptor_send = uds_descriptor_send,
|
||||||
|
.hp_descriptor_recv = uds_descriptor_recv,
|
||||||
.hp_descriptor = uds_descriptor,
|
.hp_descriptor = uds_descriptor,
|
||||||
.hp_local_address = uds_local_address,
|
.hp_local_address = uds_local_address,
|
||||||
.hp_remote_address = uds_remote_address,
|
.hp_remote_address = uds_remote_address,
|
||||||
|
Loading…
Reference in New Issue
Block a user