summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2014-12-30 14:05:02 +0000
committerJeremy Allison <jra@samba.org>2015-01-06 00:33:09 +0100
commitbd9b59ae28e8128857e7d8308a23d09a547299e0 (patch)
treeb5f7619994c6e9be4b6e0bc31710867d0a7b9577 /source3
parent190554c402f23a9eff1f20670e66f7b94a36b396 (diff)
downloadsamba-bd9b59ae28e8128857e7d8308a23d09a547299e0.tar.gz
samba-bd9b59ae28e8128857e7d8308a23d09a547299e0.tar.xz
samba-bd9b59ae28e8128857e7d8308a23d09a547299e0.zip
lib: Use msghdr in unix_msg
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/lib/unix_msg/unix_msg.c179
-rw-r--r--source3/lib/unix_msg/wscript_build2
2 files changed, 60 insertions, 121 deletions
diff --git a/source3/lib/unix_msg/unix_msg.c b/source3/lib/unix_msg/unix_msg.c
index d85cde9fb3..8d4960f6bc 100644
--- a/source3/lib/unix_msg/unix_msg.c
+++ b/source3/lib/unix_msg/unix_msg.c
@@ -24,6 +24,7 @@
#include "dlinklist.h"
#include "pthreadpool/pthreadpool.h"
#include "lib/iov_buf.h"
+#include "lib/msghdr.h"
#include <fcntl.h>
/*
@@ -43,8 +44,6 @@ struct unix_dgram_msg {
int sock;
ssize_t sent;
int sys_errno;
- struct msghdr msg;
- struct iovec iov;
};
struct unix_dgram_send_queue {
@@ -162,6 +161,22 @@ static void extract_fd_array_from_msghdr(struct msghdr *msg, int **fds,
#endif
}
+static size_t unix_dgram_msg_size(void)
+{
+ size_t msgsize = sizeof(struct unix_dgram_msg);
+ msgsize = (msgsize + 15) & ~15; /* align to 16 */
+ return msgsize;
+}
+
+static struct msghdr_buf *unix_dgram_msghdr(struct unix_dgram_msg *msg)
+{
+ /*
+ * Not portable in C99, but "msg" is aligned and so is
+ * unix_dgram_msg_size()
+ */
+ return (struct msghdr_buf *)(((char *)msg) + unix_dgram_msg_size());
+}
+
static void close_fd_array(int *fds, size_t num_fds)
{
size_t i;
@@ -176,8 +191,10 @@ static void close_fd_array(int *fds, size_t num_fds)
}
}
-static void close_fd_array_cmsg(struct msghdr *msg)
+static void close_fd_array_dgram_msg(struct unix_dgram_msg *dmsg)
{
+ struct msghdr_buf *hdr = unix_dgram_msghdr(dmsg);
+ struct msghdr *msg = msghdr_buf_msghdr(hdr);
int *fds = NULL;
size_t num_fds = 0;
@@ -448,7 +465,7 @@ static void unix_dgram_send_queue_free(struct unix_dgram_send_queue *q)
struct unix_dgram_msg *msg;
msg = q->msgs;
DLIST_REMOVE(q->msgs, msg);
- close_fd_array_cmsg(&msg->msg);
+ close_fd_array_dgram_msg(msg);
free(msg);
}
close(q->sock);
@@ -470,55 +487,17 @@ static struct unix_dgram_send_queue *find_send_queue(
}
static int queue_msg(struct unix_dgram_send_queue *q,
- const struct iovec *iov, int iovlen,
+ const struct iovec *iov, int iovcnt,
const int *fds, size_t num_fds)
{
struct unix_dgram_msg *msg;
- ssize_t data_len;
- uint8_t *data_buf;
- size_t msglen = sizeof(struct unix_dgram_msg);
- int i;
- size_t tmp;
- int ret = -1;
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- size_t fds_size = sizeof(int) * MIN(num_fds, INT8_MAX);
+ struct msghdr_buf *hdr;
+ size_t msglen, needed;
+ ssize_t msghdrlen;
int fds_copy[MIN(num_fds, INT8_MAX)];
- size_t cmsg_len = CMSG_LEN(fds_size);
- size_t cmsg_space = CMSG_SPACE(fds_size);
- char *cmsg_buf;
-
- /*
- * Note: No need to check for overflow here,
- * since cmsg will store <= INT8_MAX fds.
- */
- msglen += cmsg_space;
-
-#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
-
- if (num_fds > INT8_MAX) {
- return EINVAL;
- }
-
-#ifndef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- if (num_fds > 0) {
- return ENOSYS;
- }
-#endif
-
- data_len = iov_buflen(iov, iovlen);
- if (data_len == -1) {
- return EINVAL;
- }
-
- tmp = msglen + data_len;
- if ((tmp < msglen) || (tmp < data_len)) {
- /* overflow */
- return EINVAL;
- }
- msglen = tmp;
+ int i, ret;
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- for (i = 0; i < num_fds; i++) {
+ for (i=0; i<num_fds; i++) {
fds_copy[i] = -1;
}
@@ -529,67 +508,37 @@ static int queue_msg(struct unix_dgram_send_queue *q,
goto fail;
}
}
-#endif
- msg = malloc(msglen);
- if (msg == NULL) {
- ret = ENOMEM;
+ msglen = unix_dgram_msg_size();
+
+ msghdrlen = msghdr_copy(NULL, 0, NULL, 0, iov, iovcnt,
+ fds_copy, num_fds);
+ if (msghdrlen == -1) {
+ ret = EMSGSIZE;
goto fail;
}
- msg->sock = q->sock;
-
- data_buf = (uint8_t *)(msg + 1);
-
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- if (num_fds > 0) {
- cmsg_buf = (char *)data_buf;
- memset(cmsg_buf, 0, cmsg_space);
- data_buf += cmsg_space;
- } else {
- cmsg_buf = NULL;
- cmsg_space = 0;
+ needed = msglen + msghdrlen;
+ if (needed < msglen) {
+ ret = EMSGSIZE;
+ goto fail;
}
-#endif
-
- msg->iov = (struct iovec) {
- .iov_base = (void *)data_buf,
- .iov_len = data_len,
- };
-
- msg->msg = (struct msghdr) {
- .msg_iov = &msg->iov,
- .msg_iovlen = 1,
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- .msg_control = cmsg_buf,
- .msg_controllen = cmsg_space,
-#endif
- };
-
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- if (num_fds > 0) {
- struct cmsghdr *cmsg;
- void *fdptr;
- cmsg = CMSG_FIRSTHDR(&msg->msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = cmsg_len;
- fdptr = CMSG_DATA(cmsg);
- memcpy(fdptr, fds_copy, fds_size);
- msg->msg.msg_controllen = cmsg->cmsg_len;
+ msg = malloc(needed);
+ if (msg == NULL) {
+ ret = ENOMEM;
+ goto fail;
}
-#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+ hdr = unix_dgram_msghdr(msg);
- iov_buf(iov, iovlen, data_buf, data_len);
+ msg->sock = q->sock;
+ msghdr_copy(hdr, msghdrlen, NULL, 0, iov, iovcnt,
+ fds_copy, num_fds);
DLIST_ADD_END(q->msgs, msg, struct unix_dgram_msg);
return 0;
-
fail:
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
close_fd_array(fds_copy, num_fds);
-#endif
return ret;
}
@@ -598,7 +547,9 @@ static void unix_dgram_send_job(void *private_data)
struct unix_dgram_msg *dmsg = private_data;
do {
- dmsg->sent = sendmsg(dmsg->sock, &dmsg->msg, 0);
+ struct msghdr_buf *hdr = unix_dgram_msghdr(dmsg);
+ struct msghdr *msg = msghdr_buf_msghdr(hdr);
+ dmsg->sent = sendmsg(dmsg->sock, msg, 0);
} while ((dmsg->sent == -1) && (errno == EINTR));
if (dmsg->sent == -1) {
@@ -632,7 +583,7 @@ static void unix_dgram_job_finished(struct poll_watch *w, int fd, short events,
msg = q->msgs;
DLIST_REMOVE(q->msgs, msg);
- close_fd_array_cmsg(&msg->msg);
+ close_fd_array_dgram_msg(msg);
free(msg);
if (q->msgs != NULL) {
@@ -653,13 +604,7 @@ static int unix_dgram_send(struct unix_dgram_ctx *ctx,
{
struct unix_dgram_send_queue *q;
struct msghdr msg;
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- struct cmsghdr *cmsg;
- size_t fds_size = sizeof(int) * num_fds;
- size_t cmsg_len = CMSG_LEN(fds_size);
- size_t cmsg_space = CMSG_SPACE(fds_size);
- char cmsg_buf[cmsg_space];
-#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+ ssize_t fdlen;
int ret;
int i;
@@ -714,25 +659,19 @@ static int unix_dgram_send(struct unix_dgram_ctx *ctx,
.msg_iov = discard_const_p(struct iovec, iov),
.msg_iovlen = iovlen
};
-#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
- if (num_fds > 0) {
- void *fdptr;
- memset(cmsg_buf, 0, cmsg_space);
+ fdlen = msghdr_prep_fds(&msg, NULL, 0, fds, num_fds);
+ if (fdlen == -1) {
+ return EINVAL;
+ }
+
+ {
+ uint8_t buf[fdlen];
+ msghdr_prep_fds(&msg, buf, 0, fds, num_fds);
- msg.msg_control = cmsg_buf;
- msg.msg_controllen = cmsg_space;
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = cmsg_len;
- fdptr = CMSG_DATA(cmsg);
- memcpy(fdptr, fds, fds_size);
- msg.msg_controllen = cmsg->cmsg_len;
+ ret = sendmsg(ctx->sock, &msg, 0);
}
-#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
- ret = sendmsg(ctx->sock, &msg, 0);
if (ret >= 0) {
return 0;
}
diff --git a/source3/lib/unix_msg/wscript_build b/source3/lib/unix_msg/wscript_build
index e638ea677d..b16d52cc71 100644
--- a/source3/lib/unix_msg/wscript_build
+++ b/source3/lib/unix_msg/wscript_build
@@ -2,7 +2,7 @@
bld.SAMBA3_SUBSYSTEM('UNIX_MSG',
source='unix_msg.c',
- deps='replace PTHREADPOOL iov_buf')
+ deps='replace PTHREADPOOL iov_buf msghdr')
bld.SAMBA3_BINARY('unix_msg_test',
source='tests.c',