fdpass.c revision b7f61a644ca10a271e756201144b68b461a05bca
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen fdpass.c - File descriptor passing between processes via UNIX sockets
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen This isn't fully portable, but pretty much all UNIXes nowadays should
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen support this. If you're having runtime problems, check the end of fd_read()
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen and play with the if condition.
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen If this file doesn't compile at all, you should check if this is supported
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen in your system at all. It may require some extra #define to enable it.
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen If not, you're pretty much out of luck. Cygwin didn't last I checked.
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#if defined(irix) || defined (__irix__) || defined(sgi) || defined (__sgi__)
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen#if !defined(_AIX) && !defined(_XOPEN_SOURCE_EXTENDED)
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen# define _XOPEN_SOURCE_EXTENDED /* for Tru64, breaks AIX */
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen# if defined(_CMSG_DATA_ALIGN) && defined(_CMSG_HDR_ALIGN) /* for Solaris */
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen (_CMSG_DATA_ALIGN(len) + _CMSG_HDR_ALIGN(sizeof(struct cmsghdr)))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (_CMSG_HDR_ALIGN(sizeof(struct cmsghdr)) + (len))
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (CMSG_ALIGN(len) + CMSG_ALIGN(sizeof(struct cmsghdr)))
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenssize_t fd_send(int handle, int send_fd, const void *data, size_t size)
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen /* at least one byte is required to be sent with fd passing */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* set the control and controllen before CMSG_FIRSTHDR() */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* set the real length we want to use. it's different than
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen sizeof(buf) in 64bit systems. */
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen# define CHECK_MSG(msg) (msg).msg_controllen >= CMSG_SPACE(sizeof(int))
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen/* Linux 2.0.x doesn't set any cmsg fields. Note that this might make some
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen attacks possible so don't do it unless you really have to. */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (size_t)(cmsg)->cmsg_len >= (size_t)CMSG_LEN(sizeof(int)) && \
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (cmsg)->cmsg_level == SOL_SOCKET && (cmsg)->cmsg_type == SCM_RIGHTS)
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenssize_t fd_read(int handle, void *data, size_t size, int *fd)
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen /* at least one byte transferred - we should have the fd now.
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen do extra checks to make sure it really is an fd that is being
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen transferred to avoid potential DoS conditions. some systems don't
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen set all these values correctly however so CHECK_MSG() and
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen CHECK_CMSG() are somewhat system dependent */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen# warning SCM_RIGHTS not supported, privilege separation not possible
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenssize_t fd_send(int handle __attr_unused__, int send_fd __attr_unused__,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const void *data __attr_unused__, size_t size __attr_unused__)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainenssize_t fd_read(int handle __attr_unused__, void *data __attr_unused__,