diff options
-rw-r--r-- | Xtrans.c | 9 | ||||
-rw-r--r-- | Xtrans.h | 6 | ||||
-rw-r--r-- | Xtransint.h | 6 | ||||
-rw-r--r-- | Xtranslcl.c | 35 | ||||
-rw-r--r-- | Xtranssock.c | 110 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | xtrans.m4 | 35 |
7 files changed, 175 insertions, 28 deletions
@@ -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) @@ -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]) @@ -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() |