summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xtrans.c9
-rw-r--r--Xtrans.h6
-rw-r--r--Xtransint.h6
-rw-r--r--Xtranslcl.c35
-rw-r--r--Xtranssock.c110
-rw-r--r--configure.ac2
-rw-r--r--xtrans.m435
7 files changed, 175 insertions, 28 deletions
diff --git a/Xtrans.c b/Xtrans.c
index 6282b96..b563bf3 100644
--- a/Xtrans.c
+++ b/Xtrans.c
@@ -869,12 +869,20 @@ TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
}
int
+TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ return ciptr->transptr->Readv (ciptr, buf, size);
+}
+
+int
TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
{
return ciptr->transptr->Writev (ciptr, buf, size);
}
+#if XTRANS_SEND_FDS
int
TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close)
{
@@ -886,6 +894,7 @@ TRANS(RecvFd) (XtransConnInfo ciptr)
{
return ciptr->transptr->RecvFd(ciptr);
}
+#endif
int
TRANS(Disconnect) (XtransConnInfo ciptr)
diff --git a/Xtrans.h b/Xtrans.h
index 53b8b62..69accd7 100644
--- a/Xtrans.h
+++ b/Xtrans.h
@@ -344,6 +344,12 @@ int TRANS(Write)(
int /* size */
);
+int TRANS(Readv)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* buf */
+ int /* size */
+);
+
int TRANS(Writev)(
XtransConnInfo, /* ciptr */
struct iovec *, /* buf */
diff --git a/Xtransint.h b/Xtransint.h
index dd886db..1f32f0c 100644
--- a/Xtransint.h
+++ b/Xtransint.h
@@ -72,7 +72,9 @@ from The Open Group.
# define XTRANSDEBUG 1
#endif
-#define XTRANS_SEND_FDS 1
+#if XTRANS_SEND_FDS && !(defined(linux) || defined(__sun))
+#error "FD passing support only on Linux & Solaris"
+#endif
#ifdef WIN32
# define _WILLWINSOCK_
@@ -289,6 +291,7 @@ typedef struct _Xtransport {
int /* size */
);
+#if XTRANS_SEND_FDS
int (*SendFd)(
XtransConnInfo, /* connection */
int, /* fd */
@@ -298,6 +301,7 @@ typedef struct _Xtransport {
int (*RecvFd)(
XtransConnInfo /* connection */
);
+#endif
int (*Disconnect)(
XtransConnInfo /* connection */
diff --git a/Xtranslcl.c b/Xtranslcl.c
index 5beef7c..4deb86c 100644
--- a/Xtranslcl.c
+++ b/Xtranslcl.c
@@ -140,6 +140,21 @@ TRANS(ReopenFail)(XtransConnInfo ciptr _X_UNUSED, int fd _X_UNUSED, char *port _
#endif /* TRANS_REOPEN */
+#if XTRANS_SEND_FDS
+static int
+TRANS(LocalRecvFdInvalid)(XtransConnInfo ciptr)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+static int
+TRANS(LocalSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close)
+{
+ errno = EINVAL;
+ return -1;
+}
+#endif
static int
@@ -2368,6 +2383,10 @@ Xtransport TRANS(LocalFuncs) = {
TRANS(LocalWrite),
TRANS(LocalReadv),
TRANS(LocalWritev),
+#if XTRANS_SEND_FDS
+ TRANS(LocalSendFdInvalid),
+ TRANS(LocalRecvFdInvalid),
+#endif
TRANS(LocalDisconnect),
TRANS(LocalClose),
TRANS(LocalCloseForCloning),
@@ -2410,6 +2429,10 @@ Xtransport TRANS(PTSFuncs) = {
TRANS(LocalWrite),
TRANS(LocalReadv),
TRANS(LocalWritev),
+#if XTRANS_SEND_FDS
+ TRANS(LocalSendFdInvalid),
+ TRANS(LocalRecvFdInvalid),
+#endif
TRANS(LocalDisconnect),
TRANS(LocalClose),
TRANS(LocalCloseForCloning),
@@ -2454,6 +2477,10 @@ Xtransport TRANS(NAMEDFuncs) = {
TRANS(LocalWrite),
TRANS(LocalReadv),
TRANS(LocalWritev),
+#if XTRANS_SEND_FDS
+ TRANS(LocalSendFdInvalid),
+ TRANS(LocalRecvFdInvalid),
+#endif
TRANS(LocalDisconnect),
TRANS(LocalClose),
TRANS(LocalCloseForCloning),
@@ -2495,6 +2522,10 @@ Xtransport TRANS(PIPEFuncs) = {
TRANS(LocalWrite),
TRANS(LocalReadv),
TRANS(LocalWritev),
+#if XTRANS_SEND_FDS
+ TRANS(LocalSendFdInvalid),
+ TRANS(LocalRecvFdInvalid),
+#endif
TRANS(LocalDisconnect),
TRANS(LocalClose),
TRANS(LocalCloseForCloning),
@@ -2539,6 +2570,10 @@ Xtransport TRANS(SCOFuncs) = {
TRANS(LocalWrite),
TRANS(LocalReadv),
TRANS(LocalWritev),
+#if XTRANS_SEND_FDS
+ TRANS(LocalSendFdInvalid),
+ TRANS(LocalRecvFdInvalid),
+#endif
TRANS(LocalDisconnect),
TRANS(LocalClose),
TRANS(LocalCloseForCloning),
diff --git a/Xtranssock.c b/Xtranssock.c
index fd3bb3c..0714629 100644
--- a/Xtranssock.c
+++ b/Xtranssock.c
@@ -2237,26 +2237,33 @@ TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
#else
#if XTRANS_SEND_FDS
{
- struct msghdr msg;
- struct iovec iov;
- struct fd_pass pass;
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = size
+ };
+ char cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)];
+ struct msghdr msg = {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = cmsgbuf,
+ .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
+ };
- iov.iov_base = buf;
- iov.iov_len = size;
-
- init_msg_recv(&msg, &iov, 1, &pass, MAX_FDS);
size = recvmsg(ciptr->fd, &msg, 0);
- if (size >= 0 && msg.msg_controllen > sizeof (struct cmsghdr)) {
- if (pass.cmsghdr.cmsg_level == SOL_SOCKET &&
- pass.cmsghdr.cmsg_type == SCM_RIGHTS &&
- !((msg.msg_flags & MSG_TRUNC) ||
- (msg.msg_flags & MSG_CTRUNC)))
- {
- int nfd = (msg.msg_controllen - sizeof (struct cmsghdr)) / sizeof (int);
- int *fd = (int *) CMSG_DATA(&pass.cmsghdr);
- int i;
- for (i = 0; i < nfd; i++)
- appendFd(&ciptr->recv_fds, fd[i], 0);
+ if (size >= 0) {
+ struct cmsghdr *hdr;
+
+ for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
+ if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
+ int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
+ int i;
+ int *fd = (int *) CMSG_DATA(hdr);
+
+ for (i = 0; i < nfd; i++)
+ appendFd(&ciptr->recv_fds, fd[i], 0);
+ }
}
}
return size;
@@ -2273,7 +2280,38 @@ TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
{
prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
+#if XTRANS_SEND_FDS
+ {
+ char cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)];
+ struct msghdr msg = {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = buf,
+ .msg_iovlen = size,
+ .msg_control = cmsgbuf,
+ .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
+ };
+
+ size = recvmsg(ciptr->fd, &msg, 0);
+ if (size >= 0) {
+ struct cmsghdr *hdr;
+
+ for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
+ if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
+ int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
+ int i;
+ int *fd = (int *) CMSG_DATA(hdr);
+
+ for (i = 0; i < nfd; i++)
+ appendFd(&ciptr->recv_fds, fd[i], 0);
+ }
+ }
+ }
+ return size;
+ }
+#else
return READV (ciptr, buf, size);
+#endif
}
@@ -2286,22 +2324,32 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
#if XTRANS_SEND_FDS
if (ciptr->send_fds)
{
- struct msghdr msg;
- struct fd_pass pass;
- int nfd;
- struct _XtransConnFd *cf;
+ char cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)];
+ int nfd = nFd(&ciptr->send_fds);
+ struct _XtransConnFd *cf = ciptr->send_fds;
+ struct msghdr msg = {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = buf,
+ .msg_iovlen = size,
+ .msg_control = cmsgbuf,
+ .msg_controllen = CMSG_LEN(nfd * sizeof(int))
+ };
+ struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
int i;
+ int *fds;
- nfd = nFd(&ciptr->send_fds);
- cf = ciptr->send_fds;
+ hdr->cmsg_len = msg.msg_controllen;
+ hdr->cmsg_level = SOL_SOCKET;
+ hdr->cmsg_type = SCM_RIGHTS;
+ fds = (int *) CMSG_DATA(hdr);
/* Set up fds */
for (i = 0; i < nfd; i++) {
- pass.fd[i] = cf->fd;
+ fds[i] = cf->fd;
cf = cf->next;
}
- init_msg_send(&msg, buf, size, &pass, nfd);
i = sendmsg(ciptr->fd, &msg, 0);
if (i > 0)
discardFd(&ciptr->send_fds, cf, 0);
@@ -2482,8 +2530,10 @@ Xtransport TRANS(SocketTCPFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+#if XTRANS_SEND_FDS
TRANS(SocketSendFdInvalid),
TRANS(SocketRecvFdInvalid),
+#endif
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
@@ -2524,8 +2574,10 @@ Xtransport TRANS(SocketINETFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+#if XTRANS_SEND_FDS
TRANS(SocketSendFdInvalid),
TRANS(SocketRecvFdInvalid),
+#endif
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
@@ -2567,8 +2619,10 @@ Xtransport TRANS(SocketINET6Funcs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+#if XTRANS_SEND_FDS
TRANS(SocketSendFdInvalid),
TRANS(SocketRecvFdInvalid),
+#endif
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
@@ -2617,8 +2671,10 @@ Xtransport TRANS(SocketLocalFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+#if XTRANS_SEND_FDS
TRANS(SocketSendFd),
TRANS(SocketRecvFd),
+#endif
TRANS(SocketDisconnect),
TRANS(SocketUNIXClose),
TRANS(SocketUNIXCloseForCloning),
@@ -2673,8 +2729,10 @@ Xtransport TRANS(SocketUNIXFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+#if XTRANS_SEND_FDS
TRANS(SocketSendFd),
TRANS(SocketRecvFd),
+#endif
TRANS(SocketDisconnect),
TRANS(SocketUNIXClose),
TRANS(SocketUNIXCloseForCloning),
diff --git a/configure.ac b/configure.ac
index 8c3aa3d..998fb06 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@
# Initialize Autoconf
AC_PREREQ([2.60])
-AC_INIT([xtrans], [1.3.0],
+AC_INIT([xtrans], [1.3.2],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans])
AC_CONFIG_SRCDIR([Makefile.am])
diff --git a/xtrans.m4 b/xtrans.m4
index 91c6f9d..d84442e 100644
--- a/xtrans.m4
+++ b/xtrans.m4
@@ -57,6 +57,41 @@ AC_DEFUN([XTRANS_TCP_FLAGS],[
AC_INCLUDES_DEFAULT
#include <sys/socket.h>])
+ # XPG4v2/UNIX95 added msg_control - check to see if we need to define
+ # _XOPEN_SOURCE to get it (such as on Solaris)
+ AC_CHECK_MEMBER([struct msghdr.msg_control], [], [],
+ [
+AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+ ])
+ # First try for Solaris in C99 compliant mode, which requires XPG6/UNIX03
+ if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then
+ unset ac_cv_member_struct_msghdr_msg_control
+ AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=600])
+ AC_CHECK_MEMBER([struct msghdr.msg_control],
+ [AC_DEFINE([_XOPEN_SOURCE], [600],
+ [Defined if needed to expose struct msghdr.msg_control])
+ ], [], [
+#define _XOPEN_SOURCE 600
+AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+ ])
+ fi
+ # If that didn't work, fall back to XPG5/UNIX98 with C89
+ if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then
+ unset ac_cv_member_struct_msghdr_msg_control
+ AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=500])
+ AC_CHECK_MEMBER([struct msghdr.msg_control],
+ [AC_DEFINE([_XOPEN_SOURCE], [500],
+ [Defined if needed to expose struct msghdr.msg_control])
+ ], [], [
+#define _XOPEN_SOURCE 500
+AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+ ])
+ fi
+
+
]) # XTRANS_TCP_FLAGS
# XTRANS_CONNECTION_FLAGS()