From 5c1073266e4a8672d461fbf4bcd9e95cc67421a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 16 Dec 2015 00:49:19 +0100 Subject: [PATCH] reds-stream: add send_msgfd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new function to send fd with unix socket anciliary data. Signed-off-by: Marc-André Lureau Acked-by: Frediano Ziglio --- server/reds-stream.c | 40 ++++++++++++++++++++++++++++++++++++++++ server/reds-stream.h | 1 + 2 files changed, 41 insertions(+) diff --git a/server/reds-stream.c b/server/reds-stream.c index edc25f78..2b1c5b98 100644 --- a/server/reds-stream.c +++ b/server/reds-stream.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -254,6 +255,45 @@ int reds_stream_is_plain_unix(const RedsStream *s) } +int reds_stream_send_msgfd(RedsStream *stream, int fd) +{ + struct msghdr msgh = { 0, }; + struct iovec iov; + int r; + + const size_t fd_size = 1 * sizeof(int); + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + char data[CMSG_SPACE(fd_size)]; + } control; + + spice_return_val_if_fail(reds_stream_is_plain_unix(stream), -1); + + /* set the payload */ + iov.iov_base = (char*)"@"; + iov.iov_len = 1; + msgh.msg_iovlen = 1; + msgh.msg_iov = &iov; + + if (fd != -1) { + msgh.msg_control = control.data; + msgh.msg_controllen = sizeof(control.data); + + cmsg = CMSG_FIRSTHDR(&msgh); + cmsg->cmsg_len = CMSG_LEN(fd_size); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(cmsg), &fd, fd_size); + } + + do { + r = sendmsg(stream->socket, &msgh, MSG_NOSIGNAL); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + + return r; +} + ssize_t reds_stream_writev(RedsStream *s, const struct iovec *iov, int iovcnt) { int i; diff --git a/server/reds-stream.h b/server/reds-stream.h index 9e53b228..72e5dd19 100644 --- a/server/reds-stream.h +++ b/server/reds-stream.h @@ -74,6 +74,7 @@ int reds_stream_enable_ssl(RedsStream *stream, SSL_CTX *ctx); void reds_stream_set_info_flag(RedsStream *stream, unsigned int flag); int reds_stream_get_family(const RedsStream *stream); int reds_stream_is_plain_unix(const RedsStream *stream); +int reds_stream_send_msgfd(RedsStream *stream, int fd); typedef enum { REDS_SASL_ERROR_OK,