Makefile.am | 1 Xtrans.c | 19 Xtrans.h | 4 Xtransint.h | 28 + Xtranslcl.c | 35 + Xtranssock.c | 293 +++++++++++ Xtranstli.c | 1407 --------------------------------------------------------- Xtransutil.c | 20 autogen.sh | 4 configure.ac | 3 doc/xtrans.xml | 565 ++++++++++++++-------- transport.c | 3 xtrans.m4 | 35 + 13 files changed, 765 insertions(+), 1652 deletions(-)
New commits: commit 0153d1670e4a1883e1bb6dd971435d6268eac5ba Author: Alan Coopersmith <alan.coopersm...@oracle.com> Date: Thu Nov 7 20:16:53 2013 -0800 xtrans 1.3.2 Signed-off-by: Alan Coopersmith <alan.coopersm...@oracle.com> diff --git a/configure.ac b/configure.ac index ac346d5..998fb06 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ # Initialize Autoconf AC_PREREQ([2.60]) -AC_INIT([xtrans], [1.3.1], +AC_INIT([xtrans], [1.3.2], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans]) AC_CONFIG_SRCDIR([Makefile.am]) commit 426049c30162ed620cc16bb58edef6aac4e2ee5d Author: Alan Coopersmith <alan.coopersm...@oracle.com> Date: Thu Nov 7 19:17:44 2013 -0800 Allow XTRANS_SEND_FDS on Solaris as well Signed-off-by: Alan Coopersmith <alan.coopersm...@oracle.com> diff --git a/Xtransint.h b/Xtransint.h index 8dee614..1f32f0c 100644 --- a/Xtransint.h +++ b/Xtransint.h @@ -72,8 +72,8 @@ from The Open Group. # define XTRANSDEBUG 1 #endif -#if XTRANS_SEND_FDS && !defined(linux) -#error "FD passing support only on Linux" +#if XTRANS_SEND_FDS && !(defined(linux) || defined(__sun)) +#error "FD passing support only on Linux & Solaris" #endif #ifdef WIN32 commit 76b4f4430f9a857a1b54bfde9ef57a95b87789f5 Author: Alan Coopersmith <alan.coopersm...@oracle.com> Date: Wed Nov 6 22:34:03 2013 -0800 Check if we need to define _XOPEN_SOURCE for struct msghdr.msg_control Required to expose the structure members in Solaris headers, since it was an XPG4/UNIX95 addition to the Solaris ABI. Signed-off-by: Alan Coopersmith <alan.coopersm...@oracle.com> 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() commit 32070a64ba99fb89ec039e26444b1e026d6a978e Author: Alan Coopersmith <alan.coopersm...@oracle.com> Date: Wed Nov 6 21:52:21 2013 -0800 Add stubs for send/recv fd functions in local transports Signed-off-by: Alan Coopersmith <alan.coopersm...@oracle.com> 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), commit 08bf85958fab64951a9ba9e27dcb6b8eb818cc7e Author: Keith Packard <kei...@keithp.com> Date: Thu Nov 7 18:04:30 2013 -0800 Switch to CMSG_* macros for FD passing This should be portable to non-Linux systems Signed-off-by: Keith Packard <kei...@keithp.com> Reviewed-by: Alan Coopersmith <alan.coopersm...@oracle.com> Signed-off-by: Alan Coopersmith <alan.coopersm...@oracle.com> diff --git a/Xtranssock.c b/Xtranssock.c index c96f45b..c9d1033 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; @@ -2275,22 +2282,29 @@ TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) #if XTRANS_SEND_FDS { - struct msghdr msg; - struct fd_pass pass; + 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)) + }; - init_msg_recv(&msg, buf, size, &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; @@ -2310,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); commit 6b54b5cf8086f127aa87096e2bdd2263d1c81683 Author: Keith Packard <kei...@keithp.com> Date: Thu Nov 7 03:49:05 2013 -0800 Actually disable all of the FD passing code unless XTRANS_SEND_FDS is set Stick all of the functions relating to FD passing inside Signed-off-by: Keith Packard <kei...@keithp.com> diff --git a/Xtrans.c b/Xtrans.c index be9a057..735d7b8 100644 --- a/Xtrans.c +++ b/Xtrans.c @@ -879,6 +879,7 @@ 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) { @@ -890,6 +891,7 @@ TRANS(RecvFd) (XtransConnInfo ciptr) { return ciptr->transptr->RecvFd(ciptr); } +#endif int TRANS(Disconnect) (XtransConnInfo ciptr) diff --git a/Xtransint.h b/Xtransint.h index 581af9f..8dee614 100644 --- a/Xtransint.h +++ b/Xtransint.h @@ -291,6 +291,7 @@ typedef struct _Xtransport { int /* size */ ); +#if XTRANS_SEND_FDS int (*SendFd)( XtransConnInfo, /* connection */ int, /* fd */ @@ -300,6 +301,7 @@ typedef struct _Xtransport { int (*RecvFd)( XtransConnInfo /* connection */ ); +#endif int (*Disconnect)( XtransConnInfo /* connection */ diff --git a/Xtranssock.c b/Xtranssock.c index 84e4dcd..c96f45b 100644 --- a/Xtranssock.c +++ b/Xtranssock.c @@ -2506,8 +2506,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), @@ -2548,8 +2550,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), @@ -2591,8 +2595,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), @@ -2641,8 +2647,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), @@ -2697,8 +2705,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), commit f3709f3e0b883a0b4956313f89fa931e9264c346 Author: Keith Packard <kei...@keithp.com> Date: Wed Nov 6 23:16:11 2013 -0800 Update to version 1.3.1 Signed-off-by: Keith Packard <kei...@keithp.com> diff --git a/configure.ac b/configure.ac index 8c3aa3d..ac346d5 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.1], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans]) AC_CONFIG_SRCDIR([Makefile.am]) commit 074614940c570524e1446f55fc12a64415057e1f Author: Mark Kettenis <kette...@openbsd.org> Date: Wed Nov 6 23:13:28 2013 -0800 Don't include file descriptor passing code by default Leave it up to the consumer to request this functionality by defining XTRANS_SEND_FDS. Signed-off-by: Mark Kettenis <kette...@openbsd.org> Reviewed-by: Keith Packard <kei...@keithp.com> Signed-off-by: Keith Packard <kei...@keithp.com> v2 - make sure this is only defined on systems where the code actually works (Linux for now) diff --git a/Xtransint.h b/Xtransint.h index dd886db..581af9f 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) +#error "FD passing support only on Linux" +#endif #ifdef WIN32 # define _WILLWINSOCK_ commit a7094c389ac9fd5ca265996f76eb55cb1133974b Author: Keith Packard <kei...@keithp.com> Date: Sat Nov 2 19:23:41 2013 -0700 Add SEND_FDS version of Readv Now that we've found that libFS uses readv, we can test whether this readv implementation works correctly. Signed-off-by: Keith Packard <kei...@keithp.com> diff --git a/Xtranssock.c b/Xtranssock.c index 23150b2..84e4dcd 100644 --- a/Xtranssock.c +++ b/Xtranssock.c @@ -2273,7 +2273,31 @@ TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) { prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); +#if XTRANS_SEND_FDS + { + struct msghdr msg; + struct fd_pass pass; + + init_msg_recv(&msg, buf, size, &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); + } + } + return size; + } +#else return READV (ciptr, buf, size); +#endif } commit 58151f63553faf81babd1371770b7a7f33cecac1 Author: Keith Packard <kei...@keithp.com> Date: Sat Nov 2 19:10:11 2013 -0700 Revert "Remove 'Readv' interface" This reverts commit 9e8d99c2e27f2c8acbbfb5b760649aa1bfad665e. libFS still uses this API... diff --git a/Xtrans.c b/Xtrans.c index 7c7967f..be9a057 100644 --- a/Xtrans.c +++ b/Xtrans.c @@ -866,6 +866,13 @@ 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) { 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 */ commit 1fb0fd555a16dd8fce4abc6d3fd22b315f46762a Author: Keith Packard <kei...@keithp.com> Date: Thu Oct 31 17:21:53 2013 -0700 Update to version 1.3.0 Adds FD passing interfaces and pulls in current patches past 1.2.7 Signed-off-by: Keith Packard <kei...@keithp.com> diff --git a/configure.ac b/configure.ac index cc3c006..8c3aa3d 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ # Initialize Autoconf AC_PREREQ([2.60]) -AC_INIT([xtrans], [1.2.7], +AC_INIT([xtrans], [1.3.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans]) AC_CONFIG_SRCDIR([Makefile.am]) commit adf920aa25c1709998c7c9276927061bd58e2dfc Author: Keith Packard <kei...@keithp.com> Date: Tue Jan 8 16:47:05 2013 -0800 Add APIs to send file descriptors through the network Exposes new TRANS(SendFd)/TRANS(RecvFd) APIs. Signed-off-by: Keith Packard <kei...@keithp.com> diff --git a/Xtrans.c b/Xtrans.c index ac8b13d..7c7967f 100644 --- a/Xtrans.c +++ b/Xtrans.c @@ -873,6 +873,18 @@ TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) } int +TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) +{ + return ciptr->transptr->SendFd(ciptr, fd, do_close); +} + +int +TRANS(RecvFd) (XtransConnInfo ciptr) +{ + return ciptr->transptr->RecvFd(ciptr); +} + +int TRANS(Disconnect) (XtransConnInfo ciptr) { diff --git a/Xtrans.h b/Xtrans.h index 1b0af45..53b8b62 100644 --- a/Xtrans.h +++ b/Xtrans.h @@ -350,6 +350,10 @@ int TRANS(Writev)( int /* size */ ); +int TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close); + +int TRANS(RecvFd) (XtransConnInfo ciptr); + int TRANS(Disconnect)( XtransConnInfo /* ciptr */ ); diff --git a/Xtransint.h b/Xtransint.h index 3bce8dc..dd886db 100644 --- a/Xtransint.h +++ b/Xtransint.h @@ -72,6 +72,8 @@ from The Open Group. # define XTRANSDEBUG 1 #endif +#define XTRANS_SEND_FDS 1 + #ifdef WIN32 # define _WILLWINSOCK_ #endif @@ -123,6 +125,16 @@ from The Open Group. #define X_TCP_PORT 6000 #endif +#if XTRANS_SEND_FDS + +struct _XtransConnFd { + struct _XtransConnFd *next; + int fd; + int do_close; +}; + +#endif + struct _XtransConnInfo { struct _Xtransport *transptr; int index; @@ -135,6 +147,8 @@ struct _XtransConnInfo { int addrlen; char *peeraddr; int peeraddrlen; + struct _XtransConnFd *recv_fds; + struct _XtransConnFd *send_fds; }; #define XTRANS_OPEN_COTS_CLIENT 1 @@ -275,6 +289,16 @@ typedef struct _Xtransport { int /* size */ ); + int (*SendFd)( + XtransConnInfo, /* connection */ + int, /* fd */ + int /* do_close */ + ); + + int (*RecvFd)( + XtransConnInfo /* connection */ + ); + int (*Disconnect)( XtransConnInfo /* connection */ ); diff --git a/Xtranssock.c b/Xtranssock.c index 24269b2..23150b2 100644 --- a/Xtranssock.c +++ b/Xtranssock.c @@ -2097,47 +2097,176 @@ TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) #endif /* WIN32 */ } +#if XTRANS_SEND_FDS + +static void +appendFd(struct _XtransConnFd **prev, int fd, int do_close) +{ + struct _XtransConnFd *cf, *new; + + new = malloc (sizeof (struct _XtransConnFd)); + if (!new) { + /* XXX mark connection as broken */ + close(fd); + return; + } + new->next = 0; + new->fd = fd; + new->do_close = do_close; + /* search to end of list */ + for (; (cf = *prev); prev = &(cf->next)); + *prev = new; +} static int -TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) +removeFd(struct _XtransConnFd **prev) +{ + struct _XtransConnFd *cf; + int fd; + + if ((cf = *prev)) { + *prev = cf->next; + fd = cf->fd; + free(cf); + } else + fd = -1; + return fd; +} +static void +discardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) { - prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); + struct _XtransConnFd *cf, *next; -#if defined(WIN32) - { - int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); -#ifdef WIN32 - if (ret == SOCKET_ERROR) errno = WSAGetLastError(); -#endif - return ret; + for (cf = *prev; cf != upto; cf = next) { + next = cf->next; + if (do_close || cf->do_close) + close(cf->fd); + free(cf); } -#else - return read (ciptr->fd, buf, size); -#endif /* WIN32 */ + *prev = upto; } +static void +cleanupFds(XtransConnInfo ciptr) +{ + /* Clean up the send list but don't close the fds */ + discardFd(&ciptr->send_fds, NULL, 0); + /* Clean up the recv list and *do* close the fds */ + discardFd(&ciptr->recv_fds, NULL, 1); +} static int -TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) +nFd(struct _XtransConnFd **prev) +{ + struct _XtransConnFd *cf; + int n = 0; + + for (cf = *prev; cf; cf = cf->next) + n++; + return n; +} + +static int +TRANS(SocketRecvFd) (XtransConnInfo ciptr) +{ + prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); + return removeFd(&ciptr->recv_fds); +} +static int +TRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) { - prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); + appendFd(&ciptr->send_fds, fd, do_close); + return 0; +} + +static int +TRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) +{ + errno = EINVAL; + return -1; +} + +static int +TRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) +{ + errno = EINVAL; + return -1; +} + +#define MAX_FDS 128 + +struct fd_pass { + struct cmsghdr cmsghdr; + int fd[MAX_FDS]; +}; + +static inline void init_msg_recv(struct msghdr *msg, struct iovec *iov, int niov, struct fd_pass *pass, int nfd) { + msg->msg_name = NULL; + msg->msg_namelen = 0; + msg->msg_iov = iov; + msg->msg_iovlen = niov; + msg->msg_control = pass; + msg->msg_controllen = sizeof (struct cmsghdr) + nfd * sizeof (int); +} + +static inline void init_msg_send(struct msghdr *msg, struct iovec *iov, int niov, struct fd_pass *pass, int nfd) { + init_msg_recv(msg, iov, niov, pass, nfd); + pass->cmsghdr.cmsg_len = msg->msg_controllen; + pass->cmsghdr.cmsg_level = SOL_SOCKET; + pass->cmsghdr.cmsg_type = SCM_RIGHTS; +} + +#endif /* XTRANS_SEND_FDS */ + +static int +TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) + +{ + prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); #if defined(WIN32) { - int ret = send ((SOCKET)ciptr->fd, buf, size, 0); + int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); #ifdef WIN32 if (ret == SOCKET_ERROR) errno = WSAGetLastError(); #endif return ret; } #else - return write (ciptr->fd, buf, size); +#if XTRANS_SEND_FDS + { + struct msghdr msg; + struct iovec iov; + struct fd_pass pass; + + 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); + } + } + return size; + } +#else + return read(ciptr->fd, buf, size); +#endif /* XTRANS_SEND_FDS */ #endif /* WIN32 */ } - static int TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) @@ -2154,11 +2283,65 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) { prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); +#if XTRANS_SEND_FDS + if (ciptr->send_fds) + { + struct msghdr msg; + struct fd_pass pass; + int nfd; + struct _XtransConnFd *cf; + int i; + + nfd = nFd(&ciptr->send_fds); + cf = ciptr->send_fds; + + /* Set up fds */ + for (i = 0; i < nfd; i++) { + pass.fd[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); + return i; + } +#endif return WRITEV (ciptr, buf, size); } static int +TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) + +{ + prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); + +#if defined(WIN32) + { + int ret = send ((SOCKET)ciptr->fd, buf, size, 0); +#ifdef WIN32 + if (ret == SOCKET_ERROR) errno = WSAGetLastError(); +#endif + return ret; + } +#else +#if XTRANS_SEND_FDS + if (ciptr->send_fds) + { + struct iovec iov; -- To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/e1vkb2q-0006t3...@moszumanska.debian.org