fdpass.c revision 300621f765cdee3e05664169b67aedba9982fe60
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2004 Timo Sirainen */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen fdpass.c - File descriptor passing between processes via UNIX sockets
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen This isn't fully portable, but pretty much all UNIXes nowadays should
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen support this. If you're having runtime problems, check the end of fd_read()
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen and play with the if condition.
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen If this file doesn't compile at all, you should check if this is supported
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen in your system at all. It may require some extra #define to enable it.
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen If not, you're pretty much out of luck. Cygwin didn't last I checked.
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#if defined(irix) || defined (__irix__) || defined(sgi) || defined (__sgi__)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#if !defined(_AIX) && !defined(_XOPEN_SOURCE_EXTENDED)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen# define _XOPEN_SOURCE_EXTENDED /* for Tru64, breaks AIX */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* Solaris uses 32bit socklen_t as cmsg_len, so with Solaris we use
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen _CMSG_DATA_ALIGN() macro to do the alignment for us.
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen Perhaps the best solution would be to change sizeof(size_t) calculations
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen to sizeof(cmsg->cmsg_len)? At least if other OSes have similiar problems.. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen# if defined(_CMSG_DATA_ALIGN) && defined(_CMSG_HDR_ALIGN) /* for Solaris */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (_CMSG_DATA_ALIGN(len) + _CMSG_DATA_ALIGN(sizeof(struct cmsghdr)))
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (_CMSG_DATA_ALIGN(sizeof(struct cmsghdr)) + (len))
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (CMSG_ALIGN(len) + CMSG_ALIGN(sizeof(struct cmsghdr)))
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenssize_t fd_send(int handle, int send_fd, const void *data, size_t size)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* at least one byte is required to be sent with fd passing */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* set the control and controllen before CMSG_FIRSTHDR() */
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen /* set the real length we want to use. it's different than
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen sizeof(buf) in 64bit systems. */
3d6fdafca17c073606b63745ca8638e035e871f4Timo Sirainen# define CHECK_MSG(msg) (msg).msg_controllen >= CMSG_SPACE(sizeof(int))
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen/* Linux 2.0.x doesn't set any cmsg fields. Note that this might make some
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen attacks possible so don't do it unless you really have to. */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen (size_t)(cmsg)->cmsg_len >= (size_t)CMSG_LEN(sizeof(int)) && \
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen (cmsg)->cmsg_level == SOL_SOCKET && (cmsg)->cmsg_type == SCM_RIGHTS)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenssize_t fd_read(int handle, void *data, size_t size, int *fd)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* at least one byte transferred - we should have the fd now.
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen do extra checks to make sure it really is an fd that is being
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen transferred to avoid potential DoS conditions. some systems don't
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen set all these values correctly however so CHECK_MSG() and
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen CHECK_CMSG() are somewhat system dependent */
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen# warning SCM_RIGHTS not supported, privilege separation not possible
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenssize_t fd_send(int handle __attr_unused__, int send_fd __attr_unused__,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const void *data __attr_unused__, size_t size __attr_unused__)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenssize_t fd_read(int handle __attr_unused__, void *data __attr_unused__,