diff options
author | Volker Lendecke <vl@samba.org> | 2014-12-30 14:05:02 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2015-01-06 00:33:09 +0100 |
commit | bd9b59ae28e8128857e7d8308a23d09a547299e0 (patch) | |
tree | b5f7619994c6e9be4b6e0bc31710867d0a7b9577 /source3 | |
parent | 190554c402f23a9eff1f20670e66f7b94a36b396 (diff) | |
download | samba-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.c | 179 | ||||
-rw-r--r-- | source3/lib/unix_msg/wscript_build | 2 |
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', |