4 * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 * Copyright (c) 2006-2021, Stefan Metzmacher <metze@samba.org>
6 * Copyright (c) 2013-2021, Andreas Schneider <asn@samba.org>
7 * Copyright (c) 2014-2017, Michael Adam <obnox@samba.org>
8 * Copyright (c) 2016-2018, Anoop C S <anoopcs@redhat.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the author nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 Socket wrapper library. Passes all socket communication over
41 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
48 * Make sure we do not redirect (f)open(at)() or fcntl() to their 64bit
51 #undef _FILE_OFFSET_BITS
53 #include <sys/types.h>
56 #ifdef HAVE_SYS_SYSCALL_H
57 #include <sys/syscall.h>
62 #include <sys/socket.h>
63 #include <sys/ioctl.h>
64 #ifdef HAVE_SYS_FILIO_H
65 #include <sys/filio.h>
67 #ifdef HAVE_SYS_SIGNALFD_H
68 #include <sys/signalfd.h>
70 #ifdef HAVE_SYS_EVENTFD_H
71 #include <sys/eventfd.h>
73 #ifdef HAVE_SYS_TIMERFD_H
74 #include <sys/timerfd.h>
79 #include <netinet/in.h>
80 #include <netinet/tcp.h>
81 #ifdef HAVE_NETINET_TCP_FSM_H
82 #include <netinet/tcp_fsm.h>
84 #include <arpa/inet.h>
93 #ifdef HAVE_GNU_LIB_NAMES_H
94 #include <gnu/lib-names.h>
101 #include "socket_wrapper.h"
103 #ifdef __USE_FILE_OFFSET64
104 #error -D_FILE_OFFSET_BITS=64 should not be set for socket_wrapper!
107 enum swrap_dbglvl_e
{
114 /* GCC have printf type attribute check. */
115 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
116 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
118 #define PRINTF_ATTRIBUTE(a,b)
119 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
121 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
122 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
124 #define CONSTRUCTOR_ATTRIBUTE
125 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
127 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
128 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
130 #define DESTRUCTOR_ATTRIBUTE
134 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
135 # define FALL_THROUGH __attribute__ ((fallthrough))
136 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
137 # define FALL_THROUGH ((void)0)
138 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
139 #endif /* FALL_THROUGH */
141 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
142 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
144 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
147 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
148 # define SWRAP_THREAD __thread
150 # define SWRAP_THREAD
154 #define MIN(a,b) ((a)<(b)?(a):(b))
158 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
162 #define ZERO_STRUCTP(x) do { \
164 memset((char *)(x), 0, sizeof(*(x))); \
169 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
172 #ifndef discard_const
173 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
176 #ifndef discard_const_p
177 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
180 #define UNUSED(x) (void)(x)
183 # ifndef IPV6_RECVPKTINFO
184 # define IPV6_RECVPKTINFO IPV6_PKTINFO
185 # endif /* IPV6_RECVPKTINFO */
186 #endif /* IPV6_PKTINFO */
189 * On BSD IP_PKTINFO has a different name because during
190 * the time when they implemented it, there was no RFC.
191 * The name for IPv6 is the same as on Linux.
194 # ifdef IP_RECVDSTADDR
195 # define IP_PKTINFO IP_RECVDSTADDR
199 #define socket_wrapper_init_mutex(m) \
200 _socket_wrapper_init_mutex(m, #m)
202 /* Add new global locks here please */
203 # define SWRAP_REINIT_ALL do { \
205 ret = socket_wrapper_init_mutex(&sockets_mutex); \
206 if (ret != 0) exit(-1); \
207 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
208 if (ret != 0) exit(-1); \
209 ret = socket_wrapper_init_mutex(&first_free_mutex); \
210 if (ret != 0) exit(-1); \
211 ret = socket_wrapper_init_mutex(&sockets_si_global); \
212 if (ret != 0) exit(-1); \
213 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
214 if (ret != 0) exit(-1); \
215 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
216 if (ret != 0) exit(-1); \
217 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
218 if (ret != 0) exit(-1); \
221 # define SWRAP_LOCK_ALL do { \
222 swrap_mutex_lock(&sockets_mutex); \
223 swrap_mutex_lock(&socket_reset_mutex); \
224 swrap_mutex_lock(&first_free_mutex); \
225 swrap_mutex_lock(&sockets_si_global); \
226 swrap_mutex_lock(&autobind_start_mutex); \
227 swrap_mutex_lock(&pcap_dump_mutex); \
228 swrap_mutex_lock(&mtu_update_mutex); \
231 # define SWRAP_UNLOCK_ALL do { \
232 swrap_mutex_unlock(&mtu_update_mutex); \
233 swrap_mutex_unlock(&pcap_dump_mutex); \
234 swrap_mutex_unlock(&autobind_start_mutex); \
235 swrap_mutex_unlock(&sockets_si_global); \
236 swrap_mutex_unlock(&first_free_mutex); \
237 swrap_mutex_unlock(&socket_reset_mutex); \
238 swrap_mutex_unlock(&sockets_mutex); \
241 #define SOCKET_INFO_CONTAINER(si) \
242 (struct socket_info_container *)(si)
244 #define SWRAP_LOCK_SI(si) do { \
245 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
247 swrap_mutex_lock(&sockets_si_global); \
253 #define SWRAP_UNLOCK_SI(si) do { \
254 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
256 swrap_mutex_unlock(&sockets_si_global); \
262 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
263 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
265 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
268 /* we need to use a very terse format here as IRIX 6.4 silently
269 truncates names to 16 chars, so if we use a longer name then we
270 can't tell which port a packet came from with recvfrom()
272 with this format we have 8 chars left for the directory name
274 #define SOCKET_FORMAT "%c%02X%04X"
275 #define SOCKET_TYPE_CHAR_TCP 'T'
276 #define SOCKET_TYPE_CHAR_UDP 'U'
277 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
278 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
281 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
282 * format PCAP capture files (as the caller will simply continue from here).
284 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
285 #define SOCKET_WRAPPER_MTU_MIN 512
286 #define SOCKET_WRAPPER_MTU_MAX 32768
288 #define SOCKET_MAX_SOCKETS 1024
291 * Maximum number of socket_info structures that can
292 * be used. Can be overriden by the environment variable
293 * SOCKET_WRAPPER_MAX_SOCKETS.
295 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
297 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
299 /* This limit is to avoid broadcast sendto() needing to stat too many
300 * files. It may be raised (with a performance cost) to up to 254
301 * without changing the format above */
302 #define MAX_WRAPPED_INTERFACES 64
304 struct swrap_address
{
305 socklen_t sa_socklen
;
308 struct sockaddr_in in
;
310 struct sockaddr_in6 in6
;
312 struct sockaddr_un un
;
313 struct sockaddr_storage ss
;
317 static int first_free
;
322 * Remember to update swrap_unix_scm_right_magic
339 /* The unix path so we can unlink it on close() */
340 struct sockaddr_un un_addr
;
342 struct swrap_address bindname
;
343 struct swrap_address myname
;
344 struct swrap_address peername
;
347 unsigned long pck_snd
;
348 unsigned long pck_rcv
;
352 struct socket_info_meta
354 unsigned int refcount
;
357 * As long as we don't use shared memory
358 * for the sockets array, we use
359 * sockets_si_global as a single mutex.
361 * pthread_mutex_t mutex;
365 struct socket_info_container
367 struct socket_info info
;
368 struct socket_info_meta meta
;
371 static struct socket_info_container
*sockets
;
373 static size_t socket_info_max
= 0;
376 * Allocate the socket array always on the limit value. We want it to be
377 * at least bigger than the default so if we reach the limit we can
378 * still deal with duplicate fds pointing to the same socket_info.
380 static size_t socket_fds_max
= SOCKET_WRAPPER_MAX_SOCKETS_LIMIT
;
382 /* Hash table to map fds to corresponding socket_info index */
383 static int *socket_fds_idx
;
385 /* Mutex for syncronizing port selection during swrap_auto_bind() */
386 static pthread_mutex_t autobind_start_mutex
= PTHREAD_MUTEX_INITIALIZER
;
388 /* Mutex to guard the initialization of array of socket_info structures */
389 static pthread_mutex_t sockets_mutex
= PTHREAD_MUTEX_INITIALIZER
;
391 /* Mutex to guard the socket reset in swrap_remove_wrapper() */
392 static pthread_mutex_t socket_reset_mutex
= PTHREAD_MUTEX_INITIALIZER
;
394 /* Mutex to synchronize access to first free index in socket_info array */
395 static pthread_mutex_t first_free_mutex
= PTHREAD_MUTEX_INITIALIZER
;
398 * Mutex to synchronize access to to socket_info structures
399 * We use a single global mutex in order to avoid leaking
400 * ~ 38M copy on write memory per fork.
401 * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
403 static pthread_mutex_t sockets_si_global
= PTHREAD_MUTEX_INITIALIZER
;
405 /* Mutex to synchronize access to packet capture dump file */
406 static pthread_mutex_t pcap_dump_mutex
= PTHREAD_MUTEX_INITIALIZER
;
408 /* Mutex for synchronizing mtu value fetch*/
409 static pthread_mutex_t mtu_update_mutex
= PTHREAD_MUTEX_INITIALIZER
;
411 /* Function prototypes */
413 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
414 /* xlC and other oldschool compilers support (only) this */
415 #pragma init (swrap_constructor)
417 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE
;
418 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
419 #pragma fini (swrap_destructor)
421 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
423 #ifndef HAVE_GETPROGNAME
424 static const char *getprogname(void)
426 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
427 return program_invocation_short_name
;
428 #elif defined(HAVE_GETEXECNAME)
429 return getexecname();
432 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
434 #endif /* HAVE_GETPROGNAME */
436 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *func
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
437 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
439 static void swrap_log(enum swrap_dbglvl_e dbglvl
,
441 const char *format
, ...)
446 unsigned int lvl
= 0;
447 const char *prefix
= "SWRAP";
448 const char *progname
= getprogname();
450 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
459 va_start(va
, format
);
460 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
464 case SWRAP_LOG_ERROR
:
465 prefix
= "SWRAP_ERROR";
468 prefix
= "SWRAP_WARN";
470 case SWRAP_LOG_DEBUG
:
471 prefix
= "SWRAP_DEBUG";
473 case SWRAP_LOG_TRACE
:
474 prefix
= "SWRAP_TRACE";
478 if (progname
== NULL
) {
479 progname
= "<unknown>";
483 "%s[%s (%u)] - %s: %s\n",
486 (unsigned int)getpid(),
491 /*********************************************************
492 * SWRAP LOADING LIBC FUNCTIONS
493 *********************************************************/
498 typedef int (*__libc_accept4
)(int sockfd
,
499 struct sockaddr
*addr
,
503 typedef int (*__libc_accept
)(int sockfd
,
504 struct sockaddr
*addr
,
507 typedef int (*__libc_bind
)(int sockfd
,
508 const struct sockaddr
*addr
,
510 typedef int (*__libc_close
)(int fd
);
511 #ifdef HAVE___CLOSE_NOCANCEL
512 typedef int (*__libc___close_nocancel
)(int fd
);
514 typedef int (*__libc_connect
)(int sockfd
,
515 const struct sockaddr
*addr
,
517 typedef int (*__libc_dup
)(int fd
);
518 typedef int (*__libc_dup2
)(int oldfd
, int newfd
);
519 typedef int (*__libc_fcntl
)(int fd
, int cmd
, ...);
521 typedef int (*__libc_fcntl64
)(int fd
, int cmd
, ...);
523 typedef FILE *(*__libc_fopen
)(const char *name
, const char *mode
);
525 typedef FILE *(*__libc_fopen64
)(const char *name
, const char *mode
);
528 typedef int (*__libc_eventfd
)(int count
, int flags
);
530 typedef int (*__libc_getpeername
)(int sockfd
,
531 struct sockaddr
*addr
,
533 typedef int (*__libc_getsockname
)(int sockfd
,
534 struct sockaddr
*addr
,
536 typedef int (*__libc_getsockopt
)(int sockfd
,
541 typedef int (*__libc_ioctl
)(int d
, unsigned long int request
, ...);
542 typedef int (*__libc_listen
)(int sockfd
, int backlog
);
543 typedef int (*__libc_open
)(const char *pathname
, int flags
, ...);
545 typedef int (*__libc_open64
)(const char *pathname
, int flags
, ...);
546 #endif /* HAVE_OPEN64 */
548 typedef int (*__libc_openat64
)(int dirfd
, const char *pathname
, int flags
, ...);
549 #endif /* HAVE_OPENAT64 */
550 typedef int (*__libc_openat
)(int dirfd
, const char *path
, int flags
, ...);
551 typedef int (*__libc_pipe
)(int pipefd
[2]);
552 typedef int (*__libc_read
)(int fd
, void *buf
, size_t count
);
553 typedef ssize_t (*__libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
554 typedef int (*__libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
555 typedef int (*__libc_recvfrom
)(int sockfd
,
559 struct sockaddr
*src_addr
,
561 typedef int (*__libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
563 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
565 typedef ssize_t (*__libc_recvmmsg
)(int sockfd
, struct mmsghdr
*msgvec
, size_t vlen
, int flags
, const struct timespec
*timeout
);
566 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
567 /* Linux legacy glibc < 2.21 */
568 typedef int (*__libc_recvmmsg
)(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
, const struct timespec
*timeout
);
570 /* Linux glibc >= 2.21 */
571 typedef int (*__libc_recvmmsg
)(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
, struct timespec
*timeout
);
573 #endif /* HAVE_RECVMMSG */
574 typedef int (*__libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
575 typedef int (*__libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
577 #if defined(HAVE_SENDMMSG_SSIZE_T)
579 typedef ssize_t (*__libc_sendmmsg
)(int sockfd
, struct mmsghdr
*msgvec
, size_t vlen
, int flags
);
582 typedef int (*__libc_sendmmsg
)(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
);
584 #endif /* HAVE_SENDMMSG */
585 typedef int (*__libc_sendto
)(int sockfd
,
589 const struct sockaddr
*dst_addr
,
591 typedef int (*__libc_setsockopt
)(int sockfd
,
597 typedef int (*__libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
599 typedef int (*__libc_socket
)(int domain
, int type
, int protocol
);
600 typedef int (*__libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
601 #ifdef HAVE_TIMERFD_CREATE
602 typedef int (*__libc_timerfd_create
)(int clockid
, int flags
);
604 typedef ssize_t (*__libc_write
)(int fd
, const void *buf
, size_t count
);
605 typedef ssize_t (*__libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
607 typedef long int (*__libc_syscall
)(long int sysno
, ...);
610 #define SWRAP_SYMBOL_ENTRY(i) \
616 struct swrap_libc_symbols
{
618 SWRAP_SYMBOL_ENTRY(accept4
);
620 SWRAP_SYMBOL_ENTRY(accept
);
622 SWRAP_SYMBOL_ENTRY(bind
);
623 SWRAP_SYMBOL_ENTRY(close
);
624 #ifdef HAVE___CLOSE_NOCANCEL
625 SWRAP_SYMBOL_ENTRY(__close_nocancel
);
627 SWRAP_SYMBOL_ENTRY(connect
);
628 SWRAP_SYMBOL_ENTRY(dup
);
629 SWRAP_SYMBOL_ENTRY(dup2
);
630 SWRAP_SYMBOL_ENTRY(fcntl
);
632 SWRAP_SYMBOL_ENTRY(fcntl64
);
634 SWRAP_SYMBOL_ENTRY(fopen
);
636 SWRAP_SYMBOL_ENTRY(fopen64
);
639 SWRAP_SYMBOL_ENTRY(eventfd
);
641 SWRAP_SYMBOL_ENTRY(getpeername
);
642 SWRAP_SYMBOL_ENTRY(getsockname
);
643 SWRAP_SYMBOL_ENTRY(getsockopt
);
644 SWRAP_SYMBOL_ENTRY(ioctl
);
645 SWRAP_SYMBOL_ENTRY(listen
);
646 SWRAP_SYMBOL_ENTRY(open
);
648 SWRAP_SYMBOL_ENTRY(open64
);
651 SWRAP_SYMBOL_ENTRY(openat64
);
653 SWRAP_SYMBOL_ENTRY(openat
);
654 SWRAP_SYMBOL_ENTRY(pipe
);
655 SWRAP_SYMBOL_ENTRY(read
);
656 SWRAP_SYMBOL_ENTRY(readv
);
657 SWRAP_SYMBOL_ENTRY(recv
);
658 SWRAP_SYMBOL_ENTRY(recvfrom
);
659 SWRAP_SYMBOL_ENTRY(recvmsg
);
661 SWRAP_SYMBOL_ENTRY(recvmmsg
);
663 SWRAP_SYMBOL_ENTRY(send
);
664 SWRAP_SYMBOL_ENTRY(sendmsg
);
666 SWRAP_SYMBOL_ENTRY(sendmmsg
);
668 SWRAP_SYMBOL_ENTRY(sendto
);
669 SWRAP_SYMBOL_ENTRY(setsockopt
);
671 SWRAP_SYMBOL_ENTRY(signalfd
);
673 SWRAP_SYMBOL_ENTRY(socket
);
674 SWRAP_SYMBOL_ENTRY(socketpair
);
675 #ifdef HAVE_TIMERFD_CREATE
676 SWRAP_SYMBOL_ENTRY(timerfd_create
);
678 SWRAP_SYMBOL_ENTRY(write
);
679 SWRAP_SYMBOL_ENTRY(writev
);
681 SWRAP_SYMBOL_ENTRY(syscall
);
684 #undef SWRAP_SYMBOL_ENTRY
686 #define SWRAP_SYMBOL_ENTRY(i) \
688 __rtld_default_##i f; \
693 typedef bool (*__rtld_default_uid_wrapper_syscall_valid
)(long int sysno
);
694 typedef long int (*__rtld_default_uid_wrapper_syscall_va
)(long int sysno
, va_list va
);
697 struct swrap_rtld_default_symbols
{
699 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_valid
);
700 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_va
);
705 #undef SWRAP_SYMBOL_ENTRY
711 struct swrap_libc_symbols symbols
;
715 struct swrap_rtld_default_symbols symbols
;
719 static struct swrap swrap
;
722 static char *socket_wrapper_dir(void);
724 #define LIBC_NAME "libc.so"
731 static const char *swrap_str_lib(enum swrap_lib lib
)
736 case SWRAP_LIBSOCKET
:
740 /* Compiler would warn us about unhandled enum value if we get here */
744 static void *swrap_load_lib_handle(enum swrap_lib lib
)
746 int flags
= RTLD_LAZY
;
751 const char *env_preload
= getenv("LD_PRELOAD");
752 const char *env_deepbind
= getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
753 bool enable_deepbind
= true;
755 /* Don't do a deepbind if we run with libasan */
756 if (env_preload
!= NULL
&& strlen(env_preload
) < 1024) {
757 const char *p
= strstr(env_preload
, "libasan.so");
759 enable_deepbind
= false;
763 if (env_deepbind
!= NULL
&& strlen(env_deepbind
) >= 1) {
764 enable_deepbind
= false;
767 if (enable_deepbind
) {
768 flags
|= RTLD_DEEPBIND
;
773 case SWRAP_LIBSOCKET
:
774 #ifdef HAVE_LIBSOCKET
775 handle
= swrap
.libc
.socket_handle
;
776 if (handle
== NULL
) {
777 for (i
= 10; i
>= 0; i
--) {
778 char soname
[256] = {0};
780 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
781 handle
= dlopen(soname
, flags
);
782 if (handle
!= NULL
) {
787 swrap
.libc
.socket_handle
= handle
;
792 handle
= swrap
.libc
.handle
;
794 if (handle
== NULL
) {
795 handle
= dlopen(LIBC_SO
, flags
);
797 swrap
.libc
.handle
= handle
;
800 if (handle
== NULL
) {
801 for (i
= 10; i
>= 0; i
--) {
802 char soname
[256] = {0};
804 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
805 handle
= dlopen(soname
, flags
);
806 if (handle
!= NULL
) {
811 swrap
.libc
.handle
= handle
;
816 if (handle
== NULL
) {
818 handle
= swrap
.libc
.handle
= swrap
.libc
.socket_handle
= RTLD_NEXT
;
820 SWRAP_LOG(SWRAP_LOG_ERROR
,
821 "Failed to dlopen library: %s",
830 static void *_swrap_bind_symbol(enum swrap_lib lib
, const char *fn_name
)
835 handle
= swrap_load_lib_handle(lib
);
837 func
= dlsym(handle
, fn_name
);
839 SWRAP_LOG(SWRAP_LOG_ERROR
,
840 "Failed to find %s: %s",
846 SWRAP_LOG(SWRAP_LOG_TRACE
,
854 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
855 static void _swrap_mutex_lock(pthread_mutex_t
*mutex
, const char *name
, const char *caller
, unsigned line
)
859 ret
= pthread_mutex_lock(mutex
);
861 SWRAP_LOG(SWRAP_LOG_ERROR
, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
862 getpid(), getppid(), caller
, line
, name
, strerror(ret
));
867 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
868 static void _swrap_mutex_unlock(pthread_mutex_t
*mutex
, const char *name
, const char *caller
, unsigned line
)
872 ret
= pthread_mutex_unlock(mutex
);
874 SWRAP_LOG(SWRAP_LOG_ERROR
, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
875 getpid(), getppid(), caller
, line
, name
, strerror(ret
));
881 * These macros have a thread race condition on purpose!
883 * This is an optimization to avoid locking each time we check if the symbol is
886 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
887 swrap.libc.symbols._libc_##sym_name.obj = \
888 _swrap_bind_symbol(lib, #sym_name); \
891 #define swrap_bind_symbol_libc(sym_name) \
892 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
894 #define swrap_bind_symbol_libsocket(sym_name) \
895 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
897 #define swrap_bind_symbol_rtld_default_optional(sym_name) do { \
898 swrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
899 dlsym(RTLD_DEFAULT, #sym_name); \
902 static void swrap_bind_symbol_all(void);
904 /****************************************************************************
906 ****************************************************************************
908 * Functions especially from libc need to be loaded individually, you can't
909 * load all at once or gdb will segfault at startup. The same applies to
910 * valgrind and has probably something todo with with the linker. So we need
911 * load each function at the point it is called the first time.
913 ****************************************************************************/
916 static int libc_accept4(int sockfd
,
917 struct sockaddr
*addr
,
921 swrap_bind_symbol_all();
923 return swrap
.libc
.symbols
._libc_accept4
.f(sockfd
, addr
, addrlen
, flags
);
926 #else /* HAVE_ACCEPT4 */
928 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
930 swrap_bind_symbol_all();
932 return swrap
.libc
.symbols
._libc_accept
.f(sockfd
, addr
, addrlen
);
934 #endif /* HAVE_ACCEPT4 */
936 static int libc_bind(int sockfd
,
937 const struct sockaddr
*addr
,
940 swrap_bind_symbol_all();
942 return swrap
.libc
.symbols
._libc_bind
.f(sockfd
, addr
, addrlen
);
945 static int libc_close(int fd
)
947 swrap_bind_symbol_all();
949 return swrap
.libc
.symbols
._libc_close
.f(fd
);
952 #ifdef HAVE___CLOSE_NOCANCEL
953 static int libc___close_nocancel(int fd
)
955 swrap_bind_symbol_all();
957 return swrap
.libc
.symbols
._libc___close_nocancel
.f(fd
);
959 #endif /* HAVE___CLOSE_NOCANCEL */
961 static int libc_connect(int sockfd
,
962 const struct sockaddr
*addr
,
965 swrap_bind_symbol_all();
967 return swrap
.libc
.symbols
._libc_connect
.f(sockfd
, addr
, addrlen
);
970 static int libc_dup(int fd
)
972 swrap_bind_symbol_all();
974 return swrap
.libc
.symbols
._libc_dup
.f(fd
);
977 static int libc_dup2(int oldfd
, int newfd
)
979 swrap_bind_symbol_all();
981 return swrap
.libc
.symbols
._libc_dup2
.f(oldfd
, newfd
);
985 static int libc_eventfd(int count
, int flags
)
987 swrap_bind_symbol_all();
989 return swrap
.libc
.symbols
._libc_eventfd
.f(count
, flags
);
993 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
994 static int libc_vfcntl(int fd
, int cmd
, va_list ap
)
999 swrap_bind_symbol_all();
1001 arg
= va_arg(ap
, void *);
1003 rc
= swrap
.libc
.symbols
._libc_fcntl
.f(fd
, cmd
, arg
);
1009 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1010 static int libc_vfcntl64(int fd
, int cmd
, va_list ap
)
1015 swrap_bind_symbol_all();
1017 arg
= va_arg(ap
, void *);
1019 rc
= swrap
.libc
.symbols
._libc_fcntl64
.f(fd
, cmd
, arg
);
1025 static int libc_getpeername(int sockfd
,
1026 struct sockaddr
*addr
,
1029 swrap_bind_symbol_all();
1031 return swrap
.libc
.symbols
._libc_getpeername
.f(sockfd
, addr
, addrlen
);
1034 static int libc_getsockname(int sockfd
,
1035 struct sockaddr
*addr
,
1038 swrap_bind_symbol_all();
1040 return swrap
.libc
.symbols
._libc_getsockname
.f(sockfd
, addr
, addrlen
);
1043 static int libc_getsockopt(int sockfd
,
1049 swrap_bind_symbol_all();
1051 return swrap
.libc
.symbols
._libc_getsockopt
.f(sockfd
,
1058 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1059 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
1064 swrap_bind_symbol_all();
1066 arg
= va_arg(ap
, void *);
1068 rc
= swrap
.libc
.symbols
._libc_ioctl
.f(d
, request
, arg
);
1073 static int libc_listen(int sockfd
, int backlog
)
1075 swrap_bind_symbol_all();
1077 return swrap
.libc
.symbols
._libc_listen
.f(sockfd
, backlog
);
1080 static FILE *libc_fopen(const char *name
, const char *mode
)
1082 swrap_bind_symbol_all();
1084 return swrap
.libc
.symbols
._libc_fopen
.f(name
, mode
);
1088 static FILE *libc_fopen64(const char *name
, const char *mode
)
1090 swrap_bind_symbol_all();
1092 return swrap
.libc
.symbols
._libc_fopen64
.f(name
, mode
);
1094 #endif /* HAVE_FOPEN64 */
1096 static void swrap_inject_o_largefile(int *flags
)
1098 (void)*flags
; /* maybe unused */
1099 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1101 if (((*flags
) & O_PATH
) == 0)
1104 *flags
|= O_LARGEFILE
;
1109 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
1114 swrap_bind_symbol_all();
1116 swrap_inject_o_largefile(&flags
);
1118 if (flags
& O_CREAT
) {
1119 mode
= va_arg(ap
, int);
1121 fd
= swrap
.libc
.symbols
._libc_open
.f(pathname
, flags
, (mode_t
)mode
);
1126 static int libc_open(const char *pathname
, int flags
, ...)
1131 va_start(ap
, flags
);
1132 fd
= libc_vopen(pathname
, flags
, ap
);
1139 static int libc_vopen64(const char *pathname
, int flags
, va_list ap
)
1144 swrap_bind_symbol_all();
1146 swrap_inject_o_largefile(&flags
);
1148 if (flags
& O_CREAT
) {
1149 mode
= va_arg(ap
, int);
1151 fd
= swrap
.libc
.symbols
._libc_open64
.f(pathname
, flags
, (mode_t
)mode
);
1155 #endif /* HAVE_OPEN64 */
1157 #ifdef HAVE_OPENAT64
1159 libc_vopenat64(int dirfd
, const char *pathname
, int flags
, va_list ap
)
1164 swrap_bind_symbol_all();
1166 swrap_inject_o_largefile(&flags
);
1168 if (flags
& O_CREAT
) {
1169 mode
= va_arg(ap
, int);
1171 fd
= swrap
.libc
.symbols
._libc_openat64
.f(dirfd
,
1178 #endif /* HAVE_OPENAT64 */
1180 static int libc_vopenat(int dirfd
, const char *path
, int flags
, va_list ap
)
1185 swrap_bind_symbol_all();
1187 swrap_inject_o_largefile(&flags
);
1189 if (flags
& O_CREAT
) {
1190 mode
= va_arg(ap
, int);
1192 fd
= swrap
.libc
.symbols
._libc_openat
.f(dirfd
,
1201 static int libc_openat(int dirfd
, const char *path
, int flags
, ...)
1206 va_start(ap
, flags
);
1207 fd
= libc_vopenat(dirfd
, path
, flags
, ap
);
1214 static int libc_pipe(int pipefd
[2])
1216 swrap_bind_symbol_all();
1218 return swrap
.libc
.symbols
._libc_pipe
.f(pipefd
);
1221 static int libc_read(int fd
, void *buf
, size_t count
)
1223 swrap_bind_symbol_all();
1225 return swrap
.libc
.symbols
._libc_read
.f(fd
, buf
, count
);
1228 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
1230 swrap_bind_symbol_all();
1232 return swrap
.libc
.symbols
._libc_readv
.f(fd
, iov
, iovcnt
);
1235 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
1237 swrap_bind_symbol_all();
1239 return swrap
.libc
.symbols
._libc_recv
.f(sockfd
, buf
, len
, flags
);
1242 static int libc_recvfrom(int sockfd
,
1246 struct sockaddr
*src_addr
,
1249 swrap_bind_symbol_all();
1251 return swrap
.libc
.symbols
._libc_recvfrom
.f(sockfd
,
1259 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
1261 swrap_bind_symbol_all();
1263 return swrap
.libc
.symbols
._libc_recvmsg
.f(sockfd
, msg
, flags
);
1266 #ifdef HAVE_RECVMMSG
1267 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1269 static ssize_t
libc_recvmmsg(int sockfd
, struct mmsghdr
*msgvec
, size_t vlen
, int flags
, const struct timespec
*timeout
)
1270 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1271 /* Linux legacy glibc < 2.21 */
1272 static int libc_recvmmsg(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
, const struct timespec
*timeout
)
1274 /* Linux glibc >= 2.21 */
1275 static int libc_recvmmsg(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
, struct timespec
*timeout
)
1278 swrap_bind_symbol_all();
1280 return swrap
.libc
.symbols
._libc_recvmmsg
.f(sockfd
, msgvec
, vlen
, flags
, timeout
);
1284 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
1286 swrap_bind_symbol_all();
1288 return swrap
.libc
.symbols
._libc_send
.f(sockfd
, buf
, len
, flags
);
1291 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
1293 swrap_bind_symbol_all();
1295 return swrap
.libc
.symbols
._libc_sendmsg
.f(sockfd
, msg
, flags
);
1298 #ifdef HAVE_SENDMMSG
1299 #if defined(HAVE_SENDMMSG_SSIZE_T)
1301 static ssize_t
libc_sendmmsg(int sockfd
, struct mmsghdr
*msgvec
, size_t vlen
, int flags
)
1304 static int libc_sendmmsg(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
)
1307 swrap_bind_symbol_all();
1309 return swrap
.libc
.symbols
._libc_sendmmsg
.f(sockfd
, msgvec
, vlen
, flags
);
1313 static int libc_sendto(int sockfd
,
1317 const struct sockaddr
*dst_addr
,
1320 swrap_bind_symbol_all();
1322 return swrap
.libc
.symbols
._libc_sendto
.f(sockfd
,
1330 static int libc_setsockopt(int sockfd
,
1336 swrap_bind_symbol_all();
1338 return swrap
.libc
.symbols
._libc_setsockopt
.f(sockfd
,
1345 #ifdef HAVE_SIGNALFD
1346 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
1348 swrap_bind_symbol_all();
1350 return swrap
.libc
.symbols
._libc_signalfd
.f(fd
, mask
, flags
);
1354 static int libc_socket(int domain
, int type
, int protocol
)
1356 swrap_bind_symbol_all();
1358 return swrap
.libc
.symbols
._libc_socket
.f(domain
, type
, protocol
);
1361 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
1363 swrap_bind_symbol_all();
1365 return swrap
.libc
.symbols
._libc_socketpair
.f(domain
, type
, protocol
, sv
);
1368 #ifdef HAVE_TIMERFD_CREATE
1369 static int libc_timerfd_create(int clockid
, int flags
)
1371 swrap_bind_symbol_all();
1373 return swrap
.libc
.symbols
._libc_timerfd_create
.f(clockid
, flags
);
1377 static ssize_t
libc_write(int fd
, const void *buf
, size_t count
)
1379 swrap_bind_symbol_all();
1381 return swrap
.libc
.symbols
._libc_write
.f(fd
, buf
, count
);
1384 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
1386 swrap_bind_symbol_all();
1388 return swrap
.libc
.symbols
._libc_writev
.f(fd
, iov
, iovcnt
);
1391 /* JEMALLOC: This tells socket_wrapper if it should handle syscall() */
1392 static bool swrap_handle_syscall
;
1395 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1396 static long int libc_vsyscall(long int sysno
, va_list va
)
1405 * This is a workaround to prevent a deadlock in jemalloc calling
1406 * malloc_init() twice. The first allocation call will trigger a
1407 * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
1408 * so it goes to socket or uid wrapper. In this code path we need to
1409 * avoid any allocation calls. This will prevent the deadlock.
1411 * We also need to avoid dlopen() as that would trigger the recursion
1412 * into malloc_init(), so we use dlsym(RTLD_NEXT), until we reached
1413 * swrap_constructor() or any real socket call at that time
1414 * swrap_bind_symbol_all() will replace the function pointer again after
1417 if (swrap_handle_syscall
) {
1418 swrap_bind_symbol_all();
1419 } else if (swrap
.libc
.symbols
._libc_syscall
.obj
== NULL
) {
1420 swrap
.libc
.symbols
._libc_syscall
.obj
= dlsym(RTLD_NEXT
,
1424 for (i
= 0; i
< 8; i
++) {
1425 args
[i
] = va_arg(va
, long int);
1428 rc
= swrap
.libc
.symbols
._libc_syscall
.f(sysno
,
1441 static bool swrap_uwrap_syscall_valid(long int sysno
)
1443 swrap_bind_symbol_all();
1445 if (swrap
.rtld_default
.symbols
._rtld_default_uid_wrapper_syscall_valid
.f
== NULL
) {
1449 return swrap
.rtld_default
.symbols
._rtld_default_uid_wrapper_syscall_valid
.f(
1453 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1454 static long int swrap_uwrap_syscall_va(long int sysno
, va_list va
)
1456 swrap_bind_symbol_all();
1458 if (swrap
.rtld_default
.symbols
._rtld_default_uid_wrapper_syscall_va
.f
== NULL
) {
1460 * Fallback to libc, if uid_wrapper_syscall_va is not
1463 return libc_vsyscall(sysno
, va
);
1466 return swrap
.rtld_default
.symbols
._rtld_default_uid_wrapper_syscall_va
.f(
1470 #endif /* HAVE_SYSCALL */
1472 /* DO NOT call this function during library initialization! */
1473 static void __swrap_bind_symbol_all_once(void)
1476 swrap_bind_symbol_libsocket(accept4
);
1478 swrap_bind_symbol_libsocket(accept
);
1480 swrap_bind_symbol_libsocket(bind
);
1481 swrap_bind_symbol_libc(close
);
1482 #ifdef HAVE___CLOSE_NOCANCEL
1483 swrap_bind_symbol_libc(__close_nocancel
);
1485 swrap_bind_symbol_libsocket(connect
);
1486 swrap_bind_symbol_libc(dup
);
1487 swrap_bind_symbol_libc(dup2
);
1488 swrap_bind_symbol_libc(fcntl
);
1490 swrap_bind_symbol_libc(fcntl64
);
1492 swrap_bind_symbol_libc(fopen
);
1494 swrap_bind_symbol_libc(fopen64
);
1497 swrap_bind_symbol_libc(eventfd
);
1499 swrap_bind_symbol_libsocket(getpeername
);
1500 swrap_bind_symbol_libsocket(getsockname
);
1501 swrap_bind_symbol_libsocket(getsockopt
);
1502 swrap_bind_symbol_libc(ioctl
);
1503 swrap_bind_symbol_libsocket(listen
);
1504 swrap_bind_symbol_libc(open
);
1506 swrap_bind_symbol_libc(open64
);
1508 #ifdef HAVE_OPENAT64
1509 swrap_bind_symbol_libc(openat64
);
1511 swrap_bind_symbol_libc(openat
);
1512 swrap_bind_symbol_libsocket(pipe
);
1513 swrap_bind_symbol_libc(read
);
1514 swrap_bind_symbol_libsocket(readv
);
1515 swrap_bind_symbol_libsocket(recv
);
1516 swrap_bind_symbol_libsocket(recvfrom
);
1517 swrap_bind_symbol_libsocket(recvmsg
);
1518 #ifdef HAVE_RECVMMSG
1519 swrap_bind_symbol_libsocket(recvmmsg
);
1521 swrap_bind_symbol_libsocket(send
);
1522 swrap_bind_symbol_libsocket(sendmsg
);
1523 #ifdef HAVE_SENDMMSG
1524 swrap_bind_symbol_libsocket(sendmmsg
);
1526 swrap_bind_symbol_libsocket(sendto
);
1527 swrap_bind_symbol_libsocket(setsockopt
);
1528 #ifdef HAVE_SIGNALFD
1529 swrap_bind_symbol_libsocket(signalfd
);
1531 swrap_bind_symbol_libsocket(socket
);
1532 swrap_bind_symbol_libsocket(socketpair
);
1533 #ifdef HAVE_TIMERFD_CREATE
1534 swrap_bind_symbol_libc(timerfd_create
);
1536 swrap_bind_symbol_libc(write
);
1537 swrap_bind_symbol_libsocket(writev
);
1539 swrap_bind_symbol_libc(syscall
);
1540 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid
);
1541 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va
);
1544 swrap_handle_syscall
= true;
1547 static void swrap_bind_symbol_all(void)
1549 static pthread_once_t all_symbol_binding_once
= PTHREAD_ONCE_INIT
;
1551 pthread_once(&all_symbol_binding_once
, __swrap_bind_symbol_all_once
);
1554 /*********************************************************
1555 * SWRAP HELPER FUNCTIONS
1556 *********************************************************/
1559 * We return 127.0.0.0 (default) or 10.53.57.0.
1561 * This can be controlled by:
1562 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1564 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1566 static in_addr_t
swrap_ipv4_net(void)
1568 static int initialized
;
1569 static in_addr_t hv
;
1570 const char *net_str
= NULL
;
1579 net_str
= getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1580 if (net_str
== NULL
) {
1581 net_str
= "127.0.0.0";
1584 ret
= inet_pton(AF_INET
, net_str
, &nv
);
1586 SWRAP_LOG(SWRAP_LOG_ERROR
,
1587 "INVALID IPv4 Network [%s]",
1592 hv
= ntohl(nv
.s_addr
);
1602 SWRAP_LOG(SWRAP_LOG_ERROR
,
1603 "INVALID IPv4 Network [%s][0x%x] should be "
1604 "127.0.0.0 or 10.53.57.0",
1605 net_str
, (unsigned)hv
);
1613 * This returns 127.255.255.255 or 10.255.255.255
1615 static in_addr_t
swrap_ipv4_bcast(void)
1619 hv
= swrap_ipv4_net();
1620 hv
|= IN_CLASSA_HOST
;
1626 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1628 static in_addr_t
swrap_ipv4_iface(unsigned int iface
)
1632 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1633 SWRAP_LOG(SWRAP_LOG_ERROR
,
1634 "swrap_ipv4_iface(%u) invalid!",
1640 hv
= swrap_ipv4_net();
1650 static const struct in6_addr
*swrap_ipv6(void)
1652 static struct in6_addr v
;
1653 static int initialized
;
1661 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
1670 static void set_port(int family
, int prt
, struct swrap_address
*addr
)
1674 addr
->sa
.in
.sin_port
= htons(prt
);
1678 addr
->sa
.in6
.sin6_port
= htons(prt
);
1684 static size_t socket_length(int family
)
1688 return sizeof(struct sockaddr_in
);
1691 return sizeof(struct sockaddr_in6
);
1697 struct swrap_sockaddr_buf
{
1701 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf
*buf
,
1702 const struct sockaddr
*saddr
)
1704 unsigned int port
= 0;
1705 char addr
[64] = {0,};
1707 switch (saddr
->sa_family
) {
1709 const struct sockaddr_in
*in
=
1710 (const struct sockaddr_in
*)(const void *)saddr
;
1712 port
= ntohs(in
->sin_port
);
1714 inet_ntop(saddr
->sa_family
,
1716 addr
, sizeof(addr
));
1721 const struct sockaddr_in6
*in6
=
1722 (const struct sockaddr_in6
*)(const void *)saddr
;
1724 port
= ntohs(in6
->sin6_port
);
1726 inet_ntop(saddr
->sa_family
,
1728 addr
, sizeof(addr
));
1733 snprintf(addr
, sizeof(addr
),
1734 "<Unknown address family %u>",
1739 snprintf(buf
->str
, sizeof(buf
->str
),
1740 "addr[%s]/port[%u]",
1746 static struct socket_info
*swrap_get_socket_info(int si_index
)
1748 return (struct socket_info
*)(&(sockets
[si_index
].info
));
1751 static int swrap_get_refcount(struct socket_info
*si
)
1753 struct socket_info_container
*sic
= SOCKET_INFO_CONTAINER(si
);
1754 return sic
->meta
.refcount
;
1757 static void swrap_inc_refcount(struct socket_info
*si
)
1759 struct socket_info_container
*sic
= SOCKET_INFO_CONTAINER(si
);
1761 sic
->meta
.refcount
+= 1;
1764 static void swrap_dec_refcount(struct socket_info
*si
)
1766 struct socket_info_container
*sic
= SOCKET_INFO_CONTAINER(si
);
1768 sic
->meta
.refcount
-= 1;
1771 static int swrap_get_next_free(struct socket_info
*si
)
1773 struct socket_info_container
*sic
= SOCKET_INFO_CONTAINER(si
);
1775 return sic
->meta
.next_free
;
1778 static void swrap_set_next_free(struct socket_info
*si
, int next_free
)
1780 struct socket_info_container
*sic
= SOCKET_INFO_CONTAINER(si
);
1782 sic
->meta
.next_free
= next_free
;
1785 static int swrap_un_path(struct sockaddr_un
*un
,
1786 const char *swrap_dir
,
1793 ret
= snprintf(un
->sun_path
,
1794 sizeof(un
->sun_path
),
1800 if ((size_t)ret
>= sizeof(un
->sun_path
)) {
1801 return ENAMETOOLONG
;
1807 static int swrap_un_path_EINVAL(struct sockaddr_un
*un
,
1808 const char *swrap_dir
)
1812 ret
= snprintf(un
->sun_path
,
1813 sizeof(un
->sun_path
),
1817 if ((size_t)ret
>= sizeof(un
->sun_path
)) {
1818 return ENAMETOOLONG
;
1824 static bool swrap_dir_usable(const char *swrap_dir
)
1826 struct sockaddr_un un
;
1829 ret
= swrap_un_path(&un
, swrap_dir
, SOCKET_TYPE_CHAR_TCP
, 0, 0);
1834 ret
= swrap_un_path_EINVAL(&un
, swrap_dir
);
1842 static char *socket_wrapper_dir(void)
1844 char *swrap_dir
= NULL
;
1845 char *s
= getenv("SOCKET_WRAPPER_DIR");
1849 if (s
== NULL
|| s
[0] == '\0') {
1850 SWRAP_LOG(SWRAP_LOG_WARN
, "SOCKET_WRAPPER_DIR not set");
1854 swrap_dir
= realpath(s
, NULL
);
1855 if (swrap_dir
== NULL
) {
1856 SWRAP_LOG(SWRAP_LOG_ERROR
,
1857 "Unable to resolve socket_wrapper dir path: %s - %s",
1863 ok
= swrap_dir_usable(swrap_dir
);
1870 ok
= swrap_dir_usable(s
);
1872 SWRAP_LOG(SWRAP_LOG_ERROR
, "SOCKET_WRAPPER_DIR is too long");
1876 t
= getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1878 SWRAP_LOG(SWRAP_LOG_ERROR
,
1879 "realpath(SOCKET_WRAPPER_DIR) too long and "
1880 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1885 swrap_dir
= strdup(s
);
1886 if (swrap_dir
== NULL
) {
1887 SWRAP_LOG(SWRAP_LOG_ERROR
,
1888 "Unable to duplicate socket_wrapper dir path");
1892 SWRAP_LOG(SWRAP_LOG_WARN
,
1893 "realpath(SOCKET_WRAPPER_DIR) too long, "
1894 "using original SOCKET_WRAPPER_DIR\n");
1897 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", swrap_dir
);
1901 static unsigned int socket_wrapper_mtu(void)
1903 static unsigned int max_mtu
= 0;
1908 swrap_mutex_lock(&mtu_update_mutex
);
1914 max_mtu
= SOCKET_WRAPPER_MTU_DEFAULT
;
1916 s
= getenv("SOCKET_WRAPPER_MTU");
1921 tmp
= strtol(s
, &endp
, 10);
1926 if (tmp
< SOCKET_WRAPPER_MTU_MIN
|| tmp
> SOCKET_WRAPPER_MTU_MAX
) {
1932 swrap_mutex_unlock(&mtu_update_mutex
);
1936 static int _socket_wrapper_init_mutex(pthread_mutex_t
*m
, const char *name
)
1938 pthread_mutexattr_t ma
;
1939 bool need_destroy
= false;
1942 #define __CHECK(cmd) do { \
1945 SWRAP_LOG(SWRAP_LOG_ERROR, \
1946 "%s: %s - failed %d", \
1952 *m
= (pthread_mutex_t
)PTHREAD_MUTEX_INITIALIZER
;
1953 __CHECK(pthread_mutexattr_init(&ma
));
1954 need_destroy
= true;
1955 __CHECK(pthread_mutexattr_settype(&ma
, PTHREAD_MUTEX_ERRORCHECK
));
1956 __CHECK(pthread_mutex_init(m
, &ma
));
1959 pthread_mutexattr_destroy(&ma
);
1964 static size_t socket_wrapper_max_sockets(void)
1970 if (socket_info_max
!= 0) {
1971 return socket_info_max
;
1974 socket_info_max
= SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT
;
1976 s
= getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1977 if (s
== NULL
|| s
[0] == '\0') {
1981 tmp
= strtoul(s
, &endp
, 10);
1986 tmp
= SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT
;
1987 SWRAP_LOG(SWRAP_LOG_ERROR
,
1988 "Invalid number of sockets specified, "
1989 "using default (%zu)",
1993 if (tmp
> SOCKET_WRAPPER_MAX_SOCKETS_LIMIT
) {
1994 tmp
= SOCKET_WRAPPER_MAX_SOCKETS_LIMIT
;
1995 SWRAP_LOG(SWRAP_LOG_ERROR
,
1996 "Invalid number of sockets specified, "
1997 "using maximum (%zu).",
2001 socket_info_max
= tmp
;
2004 return socket_info_max
;
2007 static void socket_wrapper_init_fds_idx(void)
2012 if (socket_fds_idx
!= NULL
) {
2016 tmp
= (int *)calloc(socket_fds_max
, sizeof(int));
2018 SWRAP_LOG(SWRAP_LOG_ERROR
,
2019 "Failed to allocate socket fds index array: %s",
2024 for (i
= 0; i
< socket_fds_max
; i
++) {
2028 socket_fds_idx
= tmp
;
2031 static void socket_wrapper_init_sockets(void)
2037 swrap_bind_symbol_all();
2039 swrap_mutex_lock(&sockets_mutex
);
2041 if (sockets
!= NULL
) {
2042 swrap_mutex_unlock(&sockets_mutex
);
2046 SWRAP_LOG(SWRAP_LOG_DEBUG
,
2047 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
2048 SOCKET_WRAPPER_PACKAGE
, SOCKET_WRAPPER_VERSION
);
2051 * Intialize the static cache early before
2052 * any thread is able to start.
2054 (void)swrap_ipv4_net();
2056 socket_wrapper_init_fds_idx();
2058 /* Needs to be called inside the sockets_mutex lock here. */
2059 max_sockets
= socket_wrapper_max_sockets();
2061 sockets
= (struct socket_info_container
*)calloc(max_sockets
,
2062 sizeof(struct socket_info_container
));
2064 if (sockets
== NULL
) {
2065 SWRAP_LOG(SWRAP_LOG_ERROR
,
2066 "Failed to allocate sockets array: %s",
2068 swrap_mutex_unlock(&sockets_mutex
);
2072 swrap_mutex_lock(&first_free_mutex
);
2073 swrap_mutex_lock(&sockets_si_global
);
2077 for (i
= 0; i
< max_sockets
; i
++) {
2078 swrap_set_next_free(&sockets
[i
].info
, i
+1);
2081 /* mark the end of the free list */
2082 swrap_set_next_free(&sockets
[max_sockets
-1].info
, -1);
2084 swrap_mutex_unlock(&sockets_si_global
);
2085 swrap_mutex_unlock(&first_free_mutex
);
2086 swrap_mutex_unlock(&sockets_mutex
);
2092 bool socket_wrapper_enabled(void)
2094 char *s
= socket_wrapper_dir();
2102 socket_wrapper_init_sockets();
2107 static unsigned int socket_wrapper_default_iface(void)
2109 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
2112 if (sscanf(s
, "%u", &iface
) == 1) {
2113 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
2119 return 1;/* 127.0.0.1 */
2122 static void set_socket_info_index(int fd
, int idx
)
2124 SWRAP_LOG(SWRAP_LOG_TRACE
,
2127 socket_fds_idx
[fd
] = idx
;
2128 /* This builtin issues a full memory barrier. */
2129 __sync_synchronize();
2132 static void reset_socket_info_index(int fd
)
2134 SWRAP_LOG(SWRAP_LOG_TRACE
,
2137 set_socket_info_index(fd
, -1);
2140 static int find_socket_info_index(int fd
)
2146 if (socket_fds_idx
== NULL
) {
2150 if ((size_t)fd
>= socket_fds_max
) {
2152 * Do not add a log here as some applications do stupid things
2155 * for (fd = 0; fd <= getdtablesize(); fd++) {
2159 * This would produce millions of lines of debug messages.
2162 SWRAP_LOG(SWRAP_LOG_ERROR
,
2163 "Looking for a socket info for the fd %d is over the "
2164 "max socket index limit of %zu.",
2171 /* This builtin issues a full memory barrier. */
2172 __sync_synchronize();
2173 return socket_fds_idx
[fd
];
2176 static int swrap_add_socket_info(const struct socket_info
*si_input
)
2178 struct socket_info
*si
= NULL
;
2181 if (si_input
== NULL
) {
2186 swrap_mutex_lock(&first_free_mutex
);
2187 if (first_free
== -1) {
2192 si_index
= first_free
;
2193 si
= swrap_get_socket_info(si_index
);
2197 first_free
= swrap_get_next_free(si
);
2199 swrap_inc_refcount(si
);
2201 SWRAP_UNLOCK_SI(si
);
2204 swrap_mutex_unlock(&first_free_mutex
);
2209 static int swrap_create_socket(struct socket_info
*si
, int fd
)
2213 if ((size_t)fd
>= socket_fds_max
) {
2214 SWRAP_LOG(SWRAP_LOG_ERROR
,
2215 "The max socket index limit of %zu has been reached, "
2223 idx
= swrap_add_socket_info(si
);
2228 set_socket_info_index(fd
, idx
);
2233 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
2240 p
= strrchr(un
->sun_path
, '/');
2241 if (p
) p
++; else p
= un
->sun_path
;
2243 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
2244 SWRAP_LOG(SWRAP_LOG_ERROR
, "sun_path[%s] p[%s]",
2250 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
2251 SWRAP_LOG(SWRAP_LOG_ERROR
, "type %c iface %u port %u",
2258 SWRAP_LOG(SWRAP_LOG_ERROR
, "type %c iface %u port %u",
2264 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
2268 case SOCKET_TYPE_CHAR_TCP
:
2269 case SOCKET_TYPE_CHAR_UDP
: {
2270 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
2272 if ((*len
) < sizeof(*in2
)) {
2273 SWRAP_LOG(SWRAP_LOG_ERROR
,
2274 "V4: *len(%zu) < sizeof(*in2)=%zu",
2275 (size_t)*len
, sizeof(*in2
));
2280 memset(in2
, 0, sizeof(*in2
));
2281 in2
->sin_family
= AF_INET
;
2282 in2
->sin_addr
.s_addr
= htonl(swrap_ipv4_iface(iface
));
2283 in2
->sin_port
= htons(prt
);
2285 *len
= sizeof(*in2
);
2289 case SOCKET_TYPE_CHAR_TCP_V6
:
2290 case SOCKET_TYPE_CHAR_UDP_V6
: {
2291 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
2293 if ((*len
) < sizeof(*in2
)) {
2294 SWRAP_LOG(SWRAP_LOG_ERROR
,
2295 "V6: *len(%zu) < sizeof(*in2)=%zu",
2296 (size_t)*len
, sizeof(*in2
));
2297 SWRAP_LOG(SWRAP_LOG_ERROR
, "LINE:%d", __LINE__
);
2302 memset(in2
, 0, sizeof(*in2
));
2303 in2
->sin6_family
= AF_INET6
;
2304 in2
->sin6_addr
= *swrap_ipv6();
2305 in2
->sin6_addr
.s6_addr
[15] = iface
;
2306 in2
->sin6_port
= htons(prt
);
2308 *len
= sizeof(*in2
);
2313 SWRAP_LOG(SWRAP_LOG_ERROR
, "type %c iface %u port %u",
2322 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
2329 char *swrap_dir
= NULL
;
2331 if (bcast
) *bcast
= 0;
2333 switch (inaddr
->sa_family
) {
2335 const struct sockaddr_in
*in
=
2336 (const struct sockaddr_in
*)(const void *)inaddr
;
2337 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
2341 const unsigned int sw_net_addr
= swrap_ipv4_net();
2342 const unsigned int sw_bcast_addr
= swrap_ipv4_bcast();
2346 u_type
= SOCKET_TYPE_CHAR_TCP
;
2349 u_type
= SOCKET_TYPE_CHAR_UDP
;
2350 a_type
= SOCKET_TYPE_CHAR_UDP
;
2351 b_type
= SOCKET_TYPE_CHAR_UDP
;
2354 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!");
2355 errno
= ESOCKTNOSUPPORT
;
2359 prt
= ntohs(in
->sin_port
);
2360 if (a_type
&& addr
== 0xFFFFFFFF) {
2361 /* 255.255.255.255 only udp */
2364 iface
= socket_wrapper_default_iface();
2365 } else if (b_type
&& addr
== sw_bcast_addr
) {
2374 iface
= socket_wrapper_default_iface();
2375 } else if ((addr
& 0xFFFFFF00) == sw_net_addr
) {
2376 /* 127.0.0.X or 10.53.57.X */
2379 iface
= (addr
& 0x000000FF);
2381 struct swrap_sockaddr_buf buf
= {};
2382 SWRAP_LOG(SWRAP_LOG_WARN
,
2384 swrap_sockaddr_string(&buf
, inaddr
));
2385 errno
= ENETUNREACH
;
2388 if (bcast
) *bcast
= is_bcast
;
2393 const struct sockaddr_in6
*in
=
2394 (const struct sockaddr_in6
*)(const void *)inaddr
;
2395 struct in6_addr cmp1
, cmp2
;
2399 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2402 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2405 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!");
2406 errno
= ESOCKTNOSUPPORT
;
2410 /* XXX no multicast/broadcast */
2412 prt
= ntohs(in
->sin6_port
);
2414 cmp1
= *swrap_ipv6();
2415 cmp2
= in
->sin6_addr
;
2416 cmp2
.s6_addr
[15] = 0;
2417 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
2418 iface
= in
->sin6_addr
.s6_addr
[15];
2420 struct swrap_sockaddr_buf buf
= {};
2421 SWRAP_LOG(SWRAP_LOG_WARN
,
2423 swrap_sockaddr_string(&buf
, inaddr
));
2424 errno
= ENETUNREACH
;
2432 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!");
2433 errno
= ENETUNREACH
;
2438 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set");
2443 swrap_dir
= socket_wrapper_dir();
2444 if (swrap_dir
== NULL
) {
2450 swrap_un_path_EINVAL(un
, swrap_dir
);
2451 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
2452 SAFE_FREE(swrap_dir
);
2453 /* the caller need to do more processing */
2457 swrap_un_path(un
, swrap_dir
, type
, iface
, prt
);
2458 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
2460 SAFE_FREE(swrap_dir
);
2465 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
2473 char *swrap_dir
= NULL
;
2475 if (bcast
) *bcast
= 0;
2477 switch (si
->family
) {
2479 const struct sockaddr_in
*in
=
2480 (const struct sockaddr_in
*)(const void *)inaddr
;
2481 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
2486 const unsigned int sw_net_addr
= swrap_ipv4_net();
2487 const unsigned int sw_bcast_addr
= swrap_ipv4_bcast();
2489 prt
= ntohs(in
->sin_port
);
2493 u_type
= SOCKET_TYPE_CHAR_TCP
;
2494 d_type
= SOCKET_TYPE_CHAR_TCP
;
2497 u_type
= SOCKET_TYPE_CHAR_UDP
;
2498 d_type
= SOCKET_TYPE_CHAR_UDP
;
2499 a_type
= SOCKET_TYPE_CHAR_UDP
;
2500 b_type
= SOCKET_TYPE_CHAR_UDP
;
2503 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!");
2504 errno
= ESOCKTNOSUPPORT
;
2512 iface
= socket_wrapper_default_iface();
2513 } else if (a_type
&& addr
== 0xFFFFFFFF) {
2514 /* 255.255.255.255 only udp */
2517 iface
= socket_wrapper_default_iface();
2518 } else if (b_type
&& addr
== sw_bcast_addr
) {
2519 /* 127.255.255.255 only udp */
2522 iface
= socket_wrapper_default_iface();
2523 } else if ((addr
& 0xFFFFFF00) == sw_net_addr
) {
2527 iface
= (addr
& 0x000000FF);
2529 errno
= EADDRNOTAVAIL
;
2533 /* Store the bind address for connect() */
2534 if (si
->bindname
.sa_socklen
== 0) {
2535 struct sockaddr_in bind_in
;
2536 socklen_t blen
= sizeof(struct sockaddr_in
);
2538 ZERO_STRUCT(bind_in
);
2539 bind_in
.sin_family
= in
->sin_family
;
2540 bind_in
.sin_port
= in
->sin_port
;
2541 bind_in
.sin_addr
.s_addr
= htonl(swrap_ipv4_iface(iface
));
2542 si
->bindname
.sa_socklen
= blen
;
2543 memcpy(&si
->bindname
.sa
.in
, &bind_in
, blen
);
2550 const struct sockaddr_in6
*in
=
2551 (const struct sockaddr_in6
*)(const void *)inaddr
;
2552 struct in6_addr cmp1
, cmp2
;
2556 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2559 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2562 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!");
2563 errno
= ESOCKTNOSUPPORT
;
2567 /* XXX no multicast/broadcast */
2569 prt
= ntohs(in
->sin6_port
);
2571 cmp1
= *swrap_ipv6();
2572 cmp2
= in
->sin6_addr
;
2573 cmp2
.s6_addr
[15] = 0;
2574 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
2575 iface
= socket_wrapper_default_iface();
2576 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
2577 iface
= in
->sin6_addr
.s6_addr
[15];
2579 errno
= EADDRNOTAVAIL
;
2583 /* Store the bind address for connect() */
2584 if (si
->bindname
.sa_socklen
== 0) {
2585 struct sockaddr_in6 bind_in
;
2586 socklen_t blen
= sizeof(struct sockaddr_in6
);
2588 ZERO_STRUCT(bind_in
);
2589 bind_in
.sin6_family
= in
->sin6_family
;
2590 bind_in
.sin6_port
= in
->sin6_port
;
2592 bind_in
.sin6_addr
= *swrap_ipv6();
2593 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
2595 memcpy(&si
->bindname
.sa
.in6
, &bind_in
, blen
);
2596 si
->bindname
.sa_socklen
= blen
;
2603 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family");
2604 errno
= EADDRNOTAVAIL
;
2609 if (bcast
) *bcast
= is_bcast
;
2611 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
2616 swrap_dir
= socket_wrapper_dir();
2617 if (swrap_dir
== NULL
) {
2623 /* handle auto-allocation of ephemeral ports */
2624 for (prt
= 5001; prt
< 10000; prt
++) {
2625 swrap_un_path(un
, swrap_dir
, type
, iface
, prt
);
2626 if (stat(un
->sun_path
, &st
) == 0) continue;
2628 set_port(si
->family
, prt
, &si
->myname
);
2629 set_port(si
->family
, prt
, &si
->bindname
);
2636 SAFE_FREE(swrap_dir
);
2641 swrap_un_path(un
, swrap_dir
, type
, iface
, prt
);
2642 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
2644 SAFE_FREE(swrap_dir
);
2649 static struct socket_info
*find_socket_info(int fd
)
2651 int idx
= find_socket_info_index(fd
);
2657 return swrap_get_socket_info(idx
);
2661 static bool check_addr_port_in_use(const struct sockaddr
*sa
, socklen_t len
)
2663 struct socket_info_fd
*f
;
2664 const struct socket_info
*last_s
= NULL
;
2666 /* first catch invalid input */
2667 switch (sa
->sa_family
) {
2669 if (len
< sizeof(struct sockaddr_in
)) {
2675 if (len
< sizeof(struct sockaddr_in6
)) {
2685 for (f
= socket_fds
; f
; f
= f
->next
) {
2686 struct socket_info
*s
= swrap_get_socket_info(f
->si_index
);
2693 if (s
->myname
== NULL
) {
2696 if (s
->myname
->sa_family
!= sa
->sa_family
) {
2699 switch (s
->myname
->sa_family
) {
2701 struct sockaddr_in
*sin1
, *sin2
;
2703 sin1
= (struct sockaddr_in
*)s
->myname
;
2704 sin2
= (struct sockaddr_in
*)sa
;
2706 if (sin1
->sin_addr
.s_addr
== htonl(INADDR_ANY
)) {
2709 if (sin1
->sin_port
!= sin2
->sin_port
) {
2712 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
2722 struct sockaddr_in6
*sin1
, *sin2
;
2724 sin1
= (struct sockaddr_in6
*)s
->myname
;
2725 sin2
= (struct sockaddr_in6
*)sa
;
2727 if (sin1
->sin6_port
!= sin2
->sin6_port
) {
2730 if (!IN6_ARE_ADDR_EQUAL(&sin1
->sin6_addr
,
2752 static void swrap_remove_stale(int fd
);
2754 static int sockaddr_convert_to_un(struct socket_info
*si
,
2755 const struct sockaddr
*in_addr
,
2757 struct sockaddr_un
*out_addr
,
2761 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
2763 (void) in_len
; /* unused */
2765 if (out_addr
== NULL
) {
2769 out
->sa_family
= AF_UNIX
;
2770 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2771 out
->sa_len
= sizeof(*out_addr
);
2774 switch (in_addr
->sa_family
) {
2776 const struct sockaddr_in
*sin
;
2777 if (si
->family
!= AF_INET
) {
2780 if (in_len
< sizeof(struct sockaddr_in
)) {
2783 sin
= (const struct sockaddr_in
*)(const void *)in_addr
;
2784 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
2789 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2790 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2804 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!");
2805 errno
= ESOCKTNOSUPPORT
;
2809 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
2811 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
2817 errno
= EAFNOSUPPORT
;
2818 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family");
2822 static int sockaddr_convert_from_un(const struct socket_info
*si
,
2823 const struct sockaddr_un
*in_addr
,
2824 socklen_t un_addrlen
,
2826 struct sockaddr
*out_addr
,
2827 socklen_t
*out_addrlen
)
2831 if (out_addr
== NULL
|| out_addrlen
== NULL
)
2834 if (un_addrlen
== 0) {
2849 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!");
2850 errno
= ESOCKTNOSUPPORT
;
2853 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
2854 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2855 out_addr
->sa_len
= *out_addrlen
;
2862 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family");
2863 errno
= EAFNOSUPPORT
;
2867 enum swrap_packet_type
{
2869 SWRAP_CONNECT_UNREACH
,
2877 SWRAP_SENDTO_UNREACH
,
2888 struct swrap_file_hdr
{
2890 uint16_t version_major
;
2891 uint16_t version_minor
;
2894 uint32_t frame_max_len
;
2895 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2898 #define SWRAP_FILE_HDR_SIZE 24
2900 struct swrap_packet_frame
{
2902 uint32_t micro_seconds
;
2903 uint32_t recorded_length
;
2904 uint32_t full_length
;
2906 #define SWRAP_PACKET_FRAME_SIZE 16
2908 union swrap_packet_ip
{
2912 uint16_t packet_length
;
2913 uint16_t identification
;
2918 uint16_t hdr_checksum
;
2922 #define SWRAP_PACKET_IP_V4_SIZE 20
2925 uint8_t flow_label_high
;
2926 uint16_t flow_label_low
;
2927 uint16_t payload_length
;
2928 uint8_t next_header
;
2930 uint8_t src_addr
[16];
2931 uint8_t dest_addr
[16];
2933 #define SWRAP_PACKET_IP_V6_SIZE 40
2935 #define SWRAP_PACKET_IP_SIZE 40
2937 union swrap_packet_payload
{
2939 uint16_t source_port
;
2949 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2951 uint16_t source_port
;
2956 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2963 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2970 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2972 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2974 #define SWRAP_PACKET_MIN_ALLOC \
2975 (SWRAP_PACKET_FRAME_SIZE + \
2976 SWRAP_PACKET_IP_SIZE + \
2977 SWRAP_PACKET_PAYLOAD_SIZE)
2979 static const char *swrap_pcap_init_file(void)
2981 static int initialized
= 0;
2982 static const char *s
= NULL
;
2983 static const struct swrap_file_hdr h
;
2984 static const struct swrap_packet_frame f
;
2985 static const union swrap_packet_ip i
;
2986 static const union swrap_packet_payload p
;
2988 if (initialized
== 1) {
2994 * TODO: don't use the structs use plain buffer offsets
2995 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2997 * for now make sure we disable PCAP support
2998 * if the struct has alignment!
3000 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
3003 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
3006 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
3009 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
3012 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
3015 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
3018 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
3021 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
3024 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
3027 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
3031 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
3035 if (strncmp(s
, "./", 2) == 0) {
3038 SWRAP_LOG(SWRAP_LOG_TRACE
, "SOCKET_WRAPPER_PCAP_FILE: %s", s
);
3042 static uint8_t *swrap_pcap_packet_init(struct timeval
*tval
,
3043 const struct sockaddr
*src
,
3044 const struct sockaddr
*dest
,
3046 const uint8_t *payload
,
3048 unsigned long tcp_seqno
,
3049 unsigned long tcp_ack
,
3050 unsigned char tcp_ctl
,
3052 size_t *_packet_len
)
3054 uint8_t *base
= NULL
;
3055 uint8_t *buf
= NULL
;
3058 struct swrap_packet_frame
*frame
;
3062 union swrap_packet_ip
*ip
;
3064 union swrap_packet_payload
*pay
;
3067 size_t nonwire_len
= sizeof(struct swrap_packet_frame
);
3068 size_t wire_hdr_len
= 0;
3069 size_t wire_len
= 0;
3070 size_t ip_hdr_len
= 0;
3071 size_t icmp_hdr_len
= 0;
3072 size_t icmp_truncate_len
= 0;
3073 uint8_t protocol
= 0, icmp_protocol
= 0;
3074 const struct sockaddr_in
*src_in
= NULL
;
3075 const struct sockaddr_in
*dest_in
= NULL
;
3077 const struct sockaddr_in6
*src_in6
= NULL
;
3078 const struct sockaddr_in6
*dest_in6
= NULL
;
3083 switch (src
->sa_family
) {
3085 src_in
= (const struct sockaddr_in
*)(const void *)src
;
3086 dest_in
= (const struct sockaddr_in
*)(const void *)dest
;
3087 src_port
= src_in
->sin_port
;
3088 dest_port
= dest_in
->sin_port
;
3089 ip_hdr_len
= sizeof(i
.ip
->v4
);
3093 src_in6
= (const struct sockaddr_in6
*)(const void *)src
;
3094 dest_in6
= (const struct sockaddr_in6
*)(const void *)dest
;
3095 src_port
= src_in6
->sin6_port
;
3096 dest_port
= dest_in6
->sin6_port
;
3097 ip_hdr_len
= sizeof(i
.ip
->v6
);
3104 switch (socket_type
) {
3106 protocol
= 0x06; /* TCP */
3107 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
3108 wire_len
= wire_hdr_len
+ payload_len
;
3112 protocol
= 0x11; /* UDP */
3113 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
3114 wire_len
= wire_hdr_len
+ payload_len
;
3122 icmp_protocol
= protocol
;
3123 switch (src
->sa_family
) {
3125 protocol
= 0x01; /* ICMPv4 */
3126 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
3130 protocol
= 0x3A; /* ICMPv6 */
3131 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
3135 if (wire_len
> 64 ) {
3136 icmp_truncate_len
= wire_len
- 64;
3138 wire_len
+= icmp_hdr_len
;
3141 packet_len
= nonwire_len
+ wire_len
;
3142 alloc_len
= packet_len
;
3143 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
3144 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
3147 base
= (uint8_t *)calloc(1, alloc_len
);
3155 f
.frame
->seconds
= tval
->tv_sec
;
3156 f
.frame
->micro_seconds
= tval
->tv_usec
;
3157 f
.frame
->recorded_length
= wire_len
- icmp_truncate_len
;
3158 f
.frame
->full_length
= wire_len
- icmp_truncate_len
;
3160 buf
+= SWRAP_PACKET_FRAME_SIZE
;
3163 switch (src
->sa_family
) {
3165 if (src_in
== NULL
|| dest_in
== NULL
) {
3170 i
.ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
3171 i
.ip
->v4
.tos
= 0x00;
3172 i
.ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
3173 i
.ip
->v4
.identification
= htons(0xFFFF);
3174 i
.ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
3175 i
.ip
->v4
.fragment
= htons(0x0000);
3176 i
.ip
->v4
.ttl
= 0xFF;
3177 i
.ip
->v4
.protocol
= protocol
;
3178 i
.ip
->v4
.hdr_checksum
= htons(0x0000);
3179 i
.ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
3180 i
.ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
3181 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
3185 if (src_in6
== NULL
|| dest_in6
== NULL
) {
3190 i
.ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
3191 i
.ip
->v6
.flow_label_high
= 0x00;
3192 i
.ip
->v6
.flow_label_low
= 0x0000;
3193 i
.ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
3194 i
.ip
->v6
.next_header
= protocol
;
3195 memcpy(i
.ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
3196 memcpy(i
.ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
3197 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
3203 pay
= (union swrap_packet_payload
*)(void *)buf
;
3204 switch (src
->sa_family
) {
3206 pay
->icmp4
.type
= 0x03; /* destination unreachable */
3207 pay
->icmp4
.code
= 0x01; /* host unreachable */
3208 pay
->icmp4
.checksum
= htons(0x0000);
3209 pay
->icmp4
.unused
= htonl(0x00000000);
3211 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
3213 /* set the ip header in the ICMP payload */
3215 i
.ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
3216 i
.ip
->v4
.tos
= 0x00;
3217 i
.ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
3218 i
.ip
->v4
.identification
= htons(0xFFFF);
3219 i
.ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
3220 i
.ip
->v4
.fragment
= htons(0x0000);
3221 i
.ip
->v4
.ttl
= 0xFF;
3222 i
.ip
->v4
.protocol
= icmp_protocol
;
3223 i
.ip
->v4
.hdr_checksum
= htons(0x0000);
3224 i
.ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
3225 i
.ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
3227 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
3229 src_port
= dest_in
->sin_port
;
3230 dest_port
= src_in
->sin_port
;
3234 pay
->icmp6
.type
= 0x01; /* destination unreachable */
3235 pay
->icmp6
.code
= 0x03; /* address unreachable */
3236 pay
->icmp6
.checksum
= htons(0x0000);
3237 pay
->icmp6
.unused
= htonl(0x00000000);
3238 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
3240 /* set the ip header in the ICMP payload */
3242 i
.ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
3243 i
.ip
->v6
.flow_label_high
= 0x00;
3244 i
.ip
->v6
.flow_label_low
= 0x0000;
3245 i
.ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
3246 i
.ip
->v6
.next_header
= protocol
;
3247 memcpy(i
.ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
3248 memcpy(i
.ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
3250 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
3252 src_port
= dest_in6
->sin6_port
;
3253 dest_port
= src_in6
->sin6_port
;
3259 pay
= (union swrap_packet_payload
*)(void *)buf
;
3261 switch (socket_type
) {
3263 pay
->tcp
.source_port
= src_port
;
3264 pay
->tcp
.dest_port
= dest_port
;
3265 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
3266 pay
->tcp
.ack_num
= htonl(tcp_ack
);
3267 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
3268 pay
->tcp
.control
= tcp_ctl
;
3269 pay
->tcp
.window
= htons(0x7FFF);
3270 pay
->tcp
.checksum
= htons(0x0000);
3271 pay
->tcp
.urg
= htons(0x0000);
3272 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
3277 pay
->udp
.source_port
= src_port
;
3278 pay
->udp
.dest_port
= dest_port
;
3279 pay
->udp
.length
= htons(8 + payload_len
);
3280 pay
->udp
.checksum
= htons(0x0000);
3281 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
3286 if (payload
&& payload_len
> 0) {
3287 memcpy(buf
, payload
, payload_len
);
3290 *_packet_len
= packet_len
- icmp_truncate_len
;
3294 static int swrap_pcap_get_fd(const char *fname
)
3302 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
3304 struct swrap_file_hdr file_hdr
;
3305 file_hdr
.magic
= 0xA1B2C3D4;
3306 file_hdr
.version_major
= 0x0002;
3307 file_hdr
.version_minor
= 0x0004;
3308 file_hdr
.timezone
= 0x00000000;
3309 file_hdr
.sigfigs
= 0x00000000;
3310 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
3311 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
3313 if (libc_write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
3320 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
3325 static uint8_t *swrap_pcap_marshall_packet(struct socket_info
*si
,
3326 const struct sockaddr
*addr
,
3327 enum swrap_packet_type type
,
3328 const void *buf
, size_t len
,
3331 const struct sockaddr
*src_addr
;
3332 const struct sockaddr
*dest_addr
;
3333 unsigned long tcp_seqno
= 0;
3334 unsigned long tcp_ack
= 0;
3335 unsigned char tcp_ctl
= 0;
3336 int unreachable
= 0;
3340 switch (si
->family
) {
3352 case SWRAP_CONNECT_SEND
:
3353 if (si
->type
!= SOCK_STREAM
) {
3357 src_addr
= &si
->myname
.sa
.s
;
3360 tcp_seqno
= si
->io
.pck_snd
;
3361 tcp_ack
= si
->io
.pck_rcv
;
3362 tcp_ctl
= 0x02; /* SYN */
3364 si
->io
.pck_snd
+= 1;
3368 case SWRAP_CONNECT_RECV
:
3369 if (si
->type
!= SOCK_STREAM
) {
3373 dest_addr
= &si
->myname
.sa
.s
;
3376 tcp_seqno
= si
->io
.pck_rcv
;
3377 tcp_ack
= si
->io
.pck_snd
;
3378 tcp_ctl
= 0x12; /** SYN,ACK */
3380 si
->io
.pck_rcv
+= 1;
3384 case SWRAP_CONNECT_UNREACH
:
3385 if (si
->type
!= SOCK_STREAM
) {
3389 dest_addr
= &si
->myname
.sa
.s
;
3392 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3393 tcp_seqno
= si
->io
.pck_snd
- 1;
3394 tcp_ack
= si
->io
.pck_rcv
;
3395 tcp_ctl
= 0x02; /* SYN */
3400 case SWRAP_CONNECT_ACK
:
3401 if (si
->type
!= SOCK_STREAM
) {
3405 src_addr
= &si
->myname
.sa
.s
;
3408 tcp_seqno
= si
->io
.pck_snd
;
3409 tcp_ack
= si
->io
.pck_rcv
;
3410 tcp_ctl
= 0x10; /* ACK */
3414 case SWRAP_ACCEPT_SEND
:
3415 if (si
->type
!= SOCK_STREAM
) {
3419 dest_addr
= &si
->myname
.sa
.s
;
3422 tcp_seqno
= si
->io
.pck_rcv
;
3423 tcp_ack
= si
->io
.pck_snd
;
3424 tcp_ctl
= 0x02; /* SYN */
3426 si
->io
.pck_rcv
+= 1;
3430 case SWRAP_ACCEPT_RECV
:
3431 if (si
->type
!= SOCK_STREAM
) {
3435 src_addr
= &si
->myname
.sa
.s
;
3438 tcp_seqno
= si
->io
.pck_snd
;
3439 tcp_ack
= si
->io
.pck_rcv
;
3440 tcp_ctl
= 0x12; /* SYN,ACK */
3442 si
->io
.pck_snd
+= 1;
3446 case SWRAP_ACCEPT_ACK
:
3447 if (si
->type
!= SOCK_STREAM
) {
3451 dest_addr
= &si
->myname
.sa
.s
;
3454 tcp_seqno
= si
->io
.pck_rcv
;
3455 tcp_ack
= si
->io
.pck_snd
;
3456 tcp_ctl
= 0x10; /* ACK */
3461 src_addr
= &si
->myname
.sa
.s
;
3462 dest_addr
= &si
->peername
.sa
.s
;
3464 tcp_seqno
= si
->io
.pck_snd
;
3465 tcp_ack
= si
->io
.pck_rcv
;
3466 tcp_ctl
= 0x18; /* PSH,ACK */
3468 si
->io
.pck_snd
+= len
;
3472 case SWRAP_SEND_RST
:
3473 dest_addr
= &si
->myname
.sa
.s
;
3474 src_addr
= &si
->peername
.sa
.s
;
3476 if (si
->type
== SOCK_DGRAM
) {
3477 return swrap_pcap_marshall_packet(si
,
3479 SWRAP_SENDTO_UNREACH
,
3485 tcp_seqno
= si
->io
.pck_rcv
;
3486 tcp_ack
= si
->io
.pck_snd
;
3487 tcp_ctl
= 0x14; /** RST,ACK */
3491 case SWRAP_PENDING_RST
:
3492 dest_addr
= &si
->myname
.sa
.s
;
3493 src_addr
= &si
->peername
.sa
.s
;
3495 if (si
->type
== SOCK_DGRAM
) {
3499 tcp_seqno
= si
->io
.pck_rcv
;
3500 tcp_ack
= si
->io
.pck_snd
;
3501 tcp_ctl
= 0x14; /* RST,ACK */
3506 dest_addr
= &si
->myname
.sa
.s
;
3507 src_addr
= &si
->peername
.sa
.s
;
3509 tcp_seqno
= si
->io
.pck_rcv
;
3510 tcp_ack
= si
->io
.pck_snd
;
3511 tcp_ctl
= 0x18; /* PSH,ACK */
3513 si
->io
.pck_rcv
+= len
;
3517 case SWRAP_RECV_RST
:
3518 dest_addr
= &si
->myname
.sa
.s
;
3519 src_addr
= &si
->peername
.sa
.s
;
3521 if (si
->type
== SOCK_DGRAM
) {
3525 tcp_seqno
= si
->io
.pck_rcv
;
3526 tcp_ack
= si
->io
.pck_snd
;
3527 tcp_ctl
= 0x14; /* RST,ACK */
3532 src_addr
= &si
->myname
.sa
.s
;
3535 si
->io
.pck_snd
+= len
;
3539 case SWRAP_SENDTO_UNREACH
:
3540 dest_addr
= &si
->myname
.sa
.s
;
3547 case SWRAP_RECVFROM
:
3548 dest_addr
= &si
->myname
.sa
.s
;
3551 si
->io
.pck_rcv
+= len
;
3555 case SWRAP_CLOSE_SEND
:
3556 if (si
->type
!= SOCK_STREAM
) {
3560 src_addr
= &si
->myname
.sa
.s
;
3561 dest_addr
= &si
->peername
.sa
.s
;
3563 tcp_seqno
= si
->io
.pck_snd
;
3564 tcp_ack
= si
->io
.pck_rcv
;
3565 tcp_ctl
= 0x11; /* FIN, ACK */
3567 si
->io
.pck_snd
+= 1;
3571 case SWRAP_CLOSE_RECV
:
3572 if (si
->type
!= SOCK_STREAM
) {
3576 dest_addr
= &si
->myname
.sa
.s
;
3577 src_addr
= &si
->peername
.sa
.s
;
3579 tcp_seqno
= si
->io
.pck_rcv
;
3580 tcp_ack
= si
->io
.pck_snd
;
3581 tcp_ctl
= 0x11; /* FIN,ACK */
3583 si
->io
.pck_rcv
+= 1;
3587 case SWRAP_CLOSE_ACK
:
3588 if (si
->type
!= SOCK_STREAM
) {
3592 src_addr
= &si
->myname
.sa
.s
;
3593 dest_addr
= &si
->peername
.sa
.s
;
3595 tcp_seqno
= si
->io
.pck_snd
;
3596 tcp_ack
= si
->io
.pck_rcv
;
3597 tcp_ctl
= 0x10; /* ACK */
3604 swrapGetTimeOfDay(&tv
);
3606 return swrap_pcap_packet_init(&tv
,
3610 (const uint8_t *)buf
,
3619 static void swrap_pcap_dump_packet(struct socket_info
*si
,
3620 const struct sockaddr
*addr
,
3621 enum swrap_packet_type type
,
3622 const void *buf
, size_t len
)
3624 const char *file_name
;
3626 size_t packet_len
= 0;
3629 swrap_mutex_lock(&pcap_dump_mutex
);
3631 file_name
= swrap_pcap_init_file();
3636 packet
= swrap_pcap_marshall_packet(si
,
3642 if (packet
== NULL
) {
3646 fd
= swrap_pcap_get_fd(file_name
);
3648 if (libc_write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
3657 swrap_mutex_unlock(&pcap_dump_mutex
);
3660 /****************************************************************************
3662 ***************************************************************************/
3664 #ifdef HAVE_SIGNALFD
3665 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
3669 rc
= libc_signalfd(fd
, mask
, flags
);
3671 swrap_remove_stale(fd
);
3677 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
3679 return swrap_signalfd(fd
, mask
, flags
);
3683 /****************************************************************************
3685 ***************************************************************************/
3687 static int swrap_socket(int family
, int type
, int protocol
)
3689 struct socket_info
*si
= NULL
;
3690 struct socket_info _si
= { 0 };
3693 int real_type
= type
;
3696 * Remove possible addition flags passed to socket() so
3697 * do not fail checking the type.
3698 * See https://lwn.net/Articles/281965/
3701 real_type
&= ~SOCK_CLOEXEC
;
3703 #ifdef SOCK_NONBLOCK
3704 real_type
&= ~SOCK_NONBLOCK
;
3707 if (!socket_wrapper_enabled()) {
3708 return libc_socket(family
, type
, protocol
);
3719 #endif /* AF_NETLINK */
3722 #endif /* AF_PACKET */
3724 fd
= libc_socket(family
, type
, protocol
);
3726 /* Check if we have a stale fd and remove it */
3727 swrap_remove_stale(fd
);
3728 SWRAP_LOG(SWRAP_LOG_TRACE
,
3729 "Unix socket fd=%d",
3734 errno
= EAFNOSUPPORT
;
3738 switch (real_type
) {
3744 errno
= EPROTONOSUPPORT
;
3752 if (real_type
== SOCK_STREAM
) {
3757 if (real_type
== SOCK_DGRAM
) {
3762 errno
= EPROTONOSUPPORT
;
3767 * We must call libc_socket with type, from the caller, not the version
3768 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3770 fd
= libc_socket(AF_UNIX
, type
, 0);
3776 /* Check if we have a stale fd and remove it */
3777 swrap_remove_stale(fd
);
3780 si
->family
= family
;
3782 /* however, the rest of the socket_wrapper code expects just
3783 * the type, not the flags */
3784 si
->type
= real_type
;
3785 si
->protocol
= protocol
;
3788 * Setup myname so getsockname() can succeed to find out the socket
3791 switch(si
->family
) {
3793 struct sockaddr_in sin
= {
3794 .sin_family
= AF_INET
,
3797 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in
);
3798 memcpy(&si
->myname
.sa
.in
, &sin
, si
->myname
.sa_socklen
);
3803 struct sockaddr_in6 sin6
= {
3804 .sin6_family
= AF_INET6
,
3807 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in6
);
3808 memcpy(&si
->myname
.sa
.in6
, &sin6
, si
->myname
.sa_socklen
);
3817 ret
= swrap_create_socket(si
, fd
);
3819 int saved_errno
= errno
;
3821 errno
= saved_errno
;
3825 SWRAP_LOG(SWRAP_LOG_TRACE
,
3826 "Created %s socket for protocol %s, fd=%d",
3827 family
== AF_INET
? "IPv4" : "IPv6",
3828 real_type
== SOCK_DGRAM
? "UDP" : "TCP",
3834 int socket(int family
, int type
, int protocol
)
3836 return swrap_socket(family
, type
, protocol
);
3839 /****************************************************************************
3841 ***************************************************************************/
3843 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
3847 rc
= libc_socketpair(family
, type
, protocol
, sv
);
3849 swrap_remove_stale(sv
[0]);
3850 swrap_remove_stale(sv
[1]);
3856 int socketpair(int family
, int type
, int protocol
, int sv
[2])
3858 return swrap_socketpair(family
, type
, protocol
, sv
);
3861 /****************************************************************************
3863 ***************************************************************************/
3865 #ifdef HAVE_TIMERFD_CREATE
3866 static int swrap_timerfd_create(int clockid
, int flags
)
3870 fd
= libc_timerfd_create(clockid
, flags
);
3872 swrap_remove_stale(fd
);
3878 int timerfd_create(int clockid
, int flags
)
3880 return swrap_timerfd_create(clockid
, flags
);
3884 /****************************************************************************
3886 ***************************************************************************/
3888 static int swrap_pipe(int pipefd
[2])
3892 rc
= libc_pipe(pipefd
);
3894 swrap_remove_stale(pipefd
[0]);
3895 swrap_remove_stale(pipefd
[1]);
3901 int pipe(int pipefd
[2])
3903 return swrap_pipe(pipefd
);
3906 /****************************************************************************
3908 ***************************************************************************/
3910 static int swrap_accept(int s
,
3911 struct sockaddr
*addr
,
3915 struct socket_info
*parent_si
, *child_si
;
3916 struct socket_info new_si
= { 0 };
3919 struct swrap_address un_addr
= {
3920 .sa_socklen
= sizeof(struct sockaddr_un
),
3922 struct swrap_address un_my_addr
= {
3923 .sa_socklen
= sizeof(struct sockaddr_un
),
3925 struct swrap_address in_addr
= {
3926 .sa_socklen
= sizeof(struct sockaddr_storage
),
3928 struct swrap_address in_my_addr
= {
3929 .sa_socklen
= sizeof(struct sockaddr_storage
),
3933 parent_si
= find_socket_info(s
);
3936 return libc_accept4(s
, addr
, addrlen
, flags
);
3939 return libc_accept(s
, addr
, addrlen
);
3945 * prevent parent_si from being altered / closed
3948 SWRAP_LOCK_SI(parent_si
);
3951 * assume out sockaddr have the same size as the in parent
3954 in_addr
.sa_socklen
= socket_length(parent_si
->family
);
3955 if (in_addr
.sa_socklen
<= 0) {
3956 SWRAP_UNLOCK_SI(parent_si
);
3961 SWRAP_UNLOCK_SI(parent_si
);
3964 ret
= libc_accept4(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
, flags
);
3967 ret
= libc_accept(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
);
3970 int saved_errno
= errno
;
3971 if (saved_errno
== ENOTSOCK
) {
3972 /* Remove stale fds */
3973 swrap_remove_stale(s
);
3975 errno
= saved_errno
;
3981 /* Check if we have a stale fd and remove it */
3982 swrap_remove_stale(fd
);
3984 if (un_addr
.sa
.un
.sun_path
[0] == '\0') {
3986 * FreeBSD seems to have a problem where
3987 * accept4() on the unix socket doesn't
3988 * ECONNABORTED for already disconnected connections.
3990 * Let's try libc_getpeername() to get the peer address
3991 * as a fallback, but it'll likely return ENOTCONN,
3992 * which we have to map to ECONNABORTED.
3994 un_addr
.sa_socklen
= sizeof(struct sockaddr_un
),
3995 ret
= libc_getpeername(fd
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
);
3997 int saved_errno
= errno
;
3999 if (saved_errno
== ENOTCONN
) {
4001 * If the connection is already disconnected
4002 * we should return ECONNABORTED.
4004 saved_errno
= ECONNABORTED
;
4006 errno
= saved_errno
;
4011 ret
= libc_getsockname(fd
,
4013 &un_my_addr
.sa_socklen
);
4015 int saved_errno
= errno
;
4017 if (saved_errno
== ENOTCONN
) {
4019 * If the connection is already disconnected
4020 * we should return ECONNABORTED.
4022 saved_errno
= ECONNABORTED
;
4024 errno
= saved_errno
;
4028 SWRAP_LOCK_SI(parent_si
);
4030 ret
= sockaddr_convert_from_un(parent_si
,
4035 &in_addr
.sa_socklen
);
4037 int saved_errno
= errno
;
4038 SWRAP_UNLOCK_SI(parent_si
);
4040 errno
= saved_errno
;
4046 child_si
->family
= parent_si
->family
;
4047 child_si
->type
= parent_si
->type
;
4048 child_si
->protocol
= parent_si
->protocol
;
4049 child_si
->bound
= 1;
4050 child_si
->is_server
= 1;
4051 child_si
->connected
= 1;
4053 SWRAP_UNLOCK_SI(parent_si
);
4055 child_si
->peername
= (struct swrap_address
) {
4056 .sa_socklen
= in_addr
.sa_socklen
,
4058 memcpy(&child_si
->peername
.sa
.ss
, &in_addr
.sa
.ss
, in_addr
.sa_socklen
);
4060 if (addr
!= NULL
&& addrlen
!= NULL
) {
4061 size_t copy_len
= MIN(*addrlen
, in_addr
.sa_socklen
);
4063 memcpy(addr
, &in_addr
.sa
.ss
, copy_len
);
4065 *addrlen
= in_addr
.sa_socklen
;
4068 ret
= sockaddr_convert_from_un(child_si
,
4070 un_my_addr
.sa_socklen
,
4073 &in_my_addr
.sa_socklen
);
4075 int saved_errno
= errno
;
4077 errno
= saved_errno
;
4081 SWRAP_LOG(SWRAP_LOG_TRACE
,
4082 "accept() path=%s, fd=%d",
4083 un_my_addr
.sa
.un
.sun_path
, s
);
4085 child_si
->myname
= (struct swrap_address
) {
4086 .sa_socklen
= in_my_addr
.sa_socklen
,
4088 memcpy(&child_si
->myname
.sa
.ss
, &in_my_addr
.sa
.ss
, in_my_addr
.sa_socklen
);
4090 idx
= swrap_create_socket(&new_si
, fd
);
4092 int saved_errno
= errno
;
4094 errno
= saved_errno
;
4099 struct socket_info
*si
= swrap_get_socket_info(idx
);
4102 swrap_pcap_dump_packet(si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
4103 swrap_pcap_dump_packet(si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
4104 swrap_pcap_dump_packet(si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
4105 SWRAP_UNLOCK_SI(si
);
4112 int accept4(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
, int flags
)
4114 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
, flags
);
4118 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4119 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
4121 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
4124 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
, 0);
4127 static int autobind_start_init
;
4128 static int autobind_start
;
4130 /* using sendto() or connect() on an unbound socket would give the
4131 recipient no way to reply, as unlike UDP and TCP, a unix domain
4132 socket can't auto-assign ephemeral port numbers, so we need to
4134 Note: this might change the family from ipv6 to ipv4
4136 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
4138 struct swrap_address un_addr
= {
4139 .sa_socklen
= sizeof(struct sockaddr_un
),
4145 char *swrap_dir
= NULL
;
4147 swrap_mutex_lock(&autobind_start_mutex
);
4149 if (autobind_start_init
!= 1) {
4150 autobind_start_init
= 1;
4151 autobind_start
= getpid();
4152 autobind_start
%= 50000;
4153 autobind_start
+= 10000;
4156 un_addr
.sa
.un
.sun_family
= AF_UNIX
;
4160 struct sockaddr_in in
;
4164 type
= SOCKET_TYPE_CHAR_TCP
;
4167 type
= SOCKET_TYPE_CHAR_UDP
;
4170 errno
= ESOCKTNOSUPPORT
;
4175 memset(&in
, 0, sizeof(in
));
4176 in
.sin_family
= AF_INET
;
4177 in
.sin_addr
.s_addr
= htonl(swrap_ipv4_iface(
4178 socket_wrapper_default_iface()));
4180 si
->myname
= (struct swrap_address
) {
4181 .sa_socklen
= sizeof(in
),
4183 memcpy(&si
->myname
.sa
.in
, &in
, si
->myname
.sa_socklen
);
4188 struct sockaddr_in6 in6
;
4190 if (si
->family
!= family
) {
4191 errno
= ENETUNREACH
;
4198 type
= SOCKET_TYPE_CHAR_TCP_V6
;
4201 type
= SOCKET_TYPE_CHAR_UDP_V6
;
4204 errno
= ESOCKTNOSUPPORT
;
4209 memset(&in6
, 0, sizeof(in6
));
4210 in6
.sin6_family
= AF_INET6
;
4211 in6
.sin6_addr
= *swrap_ipv6();
4212 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
4214 si
->myname
= (struct swrap_address
) {
4215 .sa_socklen
= sizeof(in6
),
4217 memcpy(&si
->myname
.sa
.in6
, &in6
, si
->myname
.sa_socklen
);
4222 errno
= ESOCKTNOSUPPORT
;
4227 if (autobind_start
> 60000) {
4228 autobind_start
= 10000;
4231 swrap_dir
= socket_wrapper_dir();
4232 if (swrap_dir
== NULL
) {
4238 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
4239 port
= autobind_start
+ i
;
4240 swrap_un_path(&un_addr
.sa
.un
,
4243 socket_wrapper_default_iface(),
4246 ret
= libc_bind(fd
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
4248 if (errno
== EALREADY
|| errno
== EADDRINUSE
) {
4254 si
->un_addr
= un_addr
.sa
.un
;
4257 autobind_start
= port
+ 1;
4260 if (i
== SOCKET_MAX_SOCKETS
) {
4261 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
4262 "interface "SOCKET_FORMAT
,
4265 socket_wrapper_default_iface(),
4272 si
->family
= family
;
4273 set_port(si
->family
, port
, &si
->myname
);
4278 SAFE_FREE(swrap_dir
);
4279 swrap_mutex_unlock(&autobind_start_mutex
);
4283 /****************************************************************************
4285 ***************************************************************************/
4287 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
4291 struct swrap_address un_addr
= {
4292 .sa_socklen
= sizeof(struct sockaddr_un
),
4294 struct socket_info
*si
= find_socket_info(s
);
4295 struct swrap_sockaddr_buf buf
= {};
4299 return libc_connect(s
, serv_addr
, addrlen
);
4304 if (si
->bound
== 0) {
4305 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
4311 if (si
->family
!= serv_addr
->sa_family
) {
4312 SWRAP_LOG(SWRAP_LOG_ERROR
,
4313 "called for fd=%d (family=%d) called with invalid family=%d",
4314 s
, si
->family
, serv_addr
->sa_family
);
4320 ret
= sockaddr_convert_to_un(si
, serv_addr
,
4321 addrlen
, &un_addr
.sa
.un
, 0, &bcast
);
4327 errno
= ENETUNREACH
;
4332 if (si
->type
== SOCK_DGRAM
) {
4333 si
->defer_connect
= 1;
4336 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
4338 ret
= libc_connect(s
,
4340 un_addr
.sa_socklen
);
4343 SWRAP_LOG(SWRAP_LOG_TRACE
,
4344 "connect(%s) path=%s, fd=%d",
4345 swrap_sockaddr_string(&buf
, serv_addr
),
4346 un_addr
.sa
.un
.sun_path
, s
);
4349 /* to give better errors */
4350 if (ret
== -1 && errno
== ENOENT
) {
4351 errno
= EHOSTUNREACH
;
4355 si
->peername
= (struct swrap_address
) {
4356 .sa_socklen
= addrlen
,
4359 memcpy(&si
->peername
.sa
.ss
, serv_addr
, addrlen
);
4363 * When we connect() on a socket than we have to bind the
4364 * outgoing connection on the interface we use for the
4365 * transport. We already bound it on the right interface
4366 * but here we have to update the name so getsockname()
4367 * returns correct information.
4369 if (si
->bindname
.sa_socklen
> 0) {
4370 si
->myname
= (struct swrap_address
) {
4371 .sa_socklen
= si
->bindname
.sa_socklen
,
4374 memcpy(&si
->myname
.sa
.ss
,
4375 &si
->bindname
.sa
.ss
,
4376 si
->bindname
.sa_socklen
);
4378 /* Cleanup bindname */
4379 si
->bindname
= (struct swrap_address
) {
4384 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
4385 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
4387 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
4391 SWRAP_UNLOCK_SI(si
);
4395 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
4397 return swrap_connect(s
, serv_addr
, addrlen
);
4400 /****************************************************************************
4402 ***************************************************************************/
4404 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
4407 struct swrap_address un_addr
= {
4408 .sa_socklen
= sizeof(struct sockaddr_un
),
4410 struct socket_info
*si
= find_socket_info(s
);
4411 struct swrap_sockaddr_buf buf
= {};
4412 int ret_errno
= errno
;
4419 return libc_bind(s
, myaddr
, addrlen
);
4424 switch (si
->family
) {
4426 const struct sockaddr_in
*sin
;
4427 if (addrlen
< sizeof(struct sockaddr_in
)) {
4428 bind_error
= EINVAL
;
4432 sin
= (const struct sockaddr_in
*)(const void *)myaddr
;
4434 if (sin
->sin_family
!= AF_INET
) {
4435 bind_error
= EAFNOSUPPORT
;
4438 /* special case for AF_UNSPEC */
4439 if (sin
->sin_family
== AF_UNSPEC
&&
4440 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
4449 const struct sockaddr_in6
*sin6
;
4450 if (addrlen
< sizeof(struct sockaddr_in6
)) {
4451 bind_error
= EINVAL
;
4455 sin6
= (const struct sockaddr_in6
*)(const void *)myaddr
;
4457 if (sin6
->sin6_family
!= AF_INET6
) {
4458 bind_error
= EAFNOSUPPORT
;
4465 bind_error
= EINVAL
;
4469 if (bind_error
!= 0) {
4470 ret_errno
= bind_error
;
4476 in_use
= check_addr_port_in_use(myaddr
, addrlen
);
4484 si
->myname
.sa_socklen
= addrlen
;
4485 memcpy(&si
->myname
.sa
.ss
, myaddr
, addrlen
);
4487 ret
= sockaddr_convert_to_un(si
,
4498 unlink(un_addr
.sa
.un
.sun_path
);
4500 ret
= libc_bind(s
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
4505 SWRAP_LOG(SWRAP_LOG_TRACE
,
4506 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4507 swrap_sockaddr_string(&buf
, myaddr
),
4508 un_addr
.sa
.un
.sun_path
, s
, ret
, ret_errno
);
4515 SWRAP_UNLOCK_SI(si
);
4520 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
4522 return swrap_bind(s
, myaddr
, addrlen
);
4525 /****************************************************************************
4527 ***************************************************************************/
4529 #ifdef HAVE_BINDRESVPORT
4530 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
4532 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
4534 struct swrap_address myaddr
= {
4535 .sa_socklen
= sizeof(struct sockaddr_storage
),
4538 static uint16_t port
;
4543 #define SWRAP_STARTPORT 600
4544 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4545 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4548 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
4552 salen
= myaddr
.sa_socklen
;
4555 rc
= swrap_getsockname(sd
, &myaddr
.sa
.s
, &salen
);
4561 memset(&myaddr
.sa
.ss
, 0, salen
);
4566 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
4569 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)(void *)sa
;
4571 salen
= sizeof(struct sockaddr_in
);
4572 sinp
->sin_port
= htons(port
);
4576 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)(void *)sa
;
4578 salen
= sizeof(struct sockaddr_in6
);
4579 sin6p
->sin6_port
= htons(port
);
4583 errno
= EAFNOSUPPORT
;
4588 if (port
> SWRAP_ENDPORT
) {
4589 port
= SWRAP_STARTPORT
;
4592 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
4593 if (rc
== 0 || errno
!= EADDRINUSE
) {
4601 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
4603 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
4607 /****************************************************************************
4609 ***************************************************************************/
4611 static int swrap_listen(int s
, int backlog
)
4614 struct socket_info
*si
= find_socket_info(s
);
4617 return libc_listen(s
, backlog
);
4622 if (si
->bound
== 0) {
4623 ret
= swrap_auto_bind(s
, si
, si
->family
);
4630 ret
= libc_listen(s
, backlog
);
4636 SWRAP_UNLOCK_SI(si
);
4641 int listen(int s
, int backlog
)
4643 return swrap_listen(s
, backlog
);
4646 /****************************************************************************
4648 ***************************************************************************/
4650 static FILE *swrap_fopen(const char *name
, const char *mode
)
4654 fp
= libc_fopen(name
, mode
);
4656 int fd
= fileno(fp
);
4658 swrap_remove_stale(fd
);
4664 #undef fopen /* Needed for LFS handling */
4665 FILE *fopen(const char *name
, const char *mode
)
4667 return swrap_fopen(name
, mode
);
4670 /****************************************************************************
4672 ***************************************************************************/
4675 static FILE *swrap_fopen64(const char *name
, const char *mode
)
4679 fp
= libc_fopen64(name
, mode
);
4681 int fd
= fileno(fp
);
4683 swrap_remove_stale(fd
);
4689 FILE *fopen64(const char *name
, const char *mode
)
4691 return swrap_fopen64(name
, mode
);
4693 #endif /* HAVE_FOPEN64 */
4695 /****************************************************************************
4697 ***************************************************************************/
4699 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
4703 ret
= libc_vopen(pathname
, flags
, ap
);
4706 * There are methods for closing descriptors (libc-internal code
4707 * paths, direct syscalls) which close descriptors in ways that
4708 * we can't intercept, so try to recover when we notice that
4711 swrap_remove_stale(ret
);
4716 #undef open /* Needed for LFS handling */
4717 int open(const char *pathname
, int flags
, ...)
4722 va_start(ap
, flags
);
4723 fd
= swrap_vopen(pathname
, flags
, ap
);
4729 /****************************************************************************
4731 ***************************************************************************/
4734 static int swrap_vopen64(const char *pathname
, int flags
, va_list ap
)
4738 ret
= libc_vopen64(pathname
, flags
, ap
);
4741 * There are methods for closing descriptors (libc-internal code
4742 * paths, direct syscalls) which close descriptors in ways that
4743 * we can't intercept, so try to recover when we notice that
4746 swrap_remove_stale(ret
);
4751 int open64(const char *pathname
, int flags
, ...)
4756 va_start(ap
, flags
);
4757 fd
= swrap_vopen64(pathname
, flags
, ap
);
4762 #endif /* HAVE_OPEN64 */
4764 /****************************************************************************
4766 ***************************************************************************/
4768 #ifdef HAVE_OPENAT64
4770 swrap_vopenat64(int dirfd
, const char *pathname
, int flags
, va_list ap
)
4774 ret
= libc_vopenat64(dirfd
, pathname
, flags
, ap
);
4777 * There are methods for closing descriptors (libc-internal code
4778 * paths, direct syscalls) which close descriptors in ways that
4779 * we can't intercept, so try to recover when we notice that
4782 swrap_remove_stale(ret
);
4787 int openat64(int dirfd
, const char *pathname
, int flags
, ...)
4792 va_start(ap
, flags
);
4793 fd
= swrap_vopenat64(dirfd
, pathname
, flags
, ap
);
4798 #endif /* HAVE_OPENAT64 */
4800 /****************************************************************************
4802 ***************************************************************************/
4804 static int swrap_vopenat(int dirfd
, const char *path
, int flags
, va_list ap
)
4808 ret
= libc_vopenat(dirfd
, path
, flags
, ap
);
4811 * There are methods for closing descriptors (libc-internal code
4812 * paths, direct syscalls) which close descriptors in ways that
4813 * we can't intercept, so try to recover when we notice that
4816 swrap_remove_stale(ret
);
4822 #undef openat /* Needed for LFS handling */
4823 int openat(int dirfd
, const char *path
, int flags
, ...)
4828 va_start(ap
, flags
);
4829 fd
= swrap_vopenat(dirfd
, path
, flags
, ap
);
4835 /****************************************************************************
4837 ***************************************************************************/
4839 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
4841 struct socket_info
*si
= find_socket_info(s
);
4846 return libc_getpeername(s
, name
, addrlen
);
4851 if (si
->peername
.sa_socklen
== 0)
4857 len
= MIN(*addrlen
, si
->peername
.sa_socklen
);
4863 memcpy(name
, &si
->peername
.sa
.ss
, len
);
4864 *addrlen
= si
->peername
.sa_socklen
;
4868 SWRAP_UNLOCK_SI(si
);
4873 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4874 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
4876 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
4879 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
4882 /****************************************************************************
4884 ***************************************************************************/
4886 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
4888 struct socket_info
*si
= find_socket_info(s
);
4893 return libc_getsockname(s
, name
, addrlen
);
4898 len
= MIN(*addrlen
, si
->myname
.sa_socklen
);
4904 memcpy(name
, &si
->myname
.sa
.ss
, len
);
4905 *addrlen
= si
->myname
.sa_socklen
;
4909 SWRAP_UNLOCK_SI(si
);
4914 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4915 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
4917 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
4920 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
4923 /****************************************************************************
4925 ***************************************************************************/
4928 # ifdef SO_PROTOTYPE /* The Solaris name */
4929 # define SO_PROTOCOL SO_PROTOTYPE
4930 # endif /* SO_PROTOTYPE */
4931 #endif /* SO_PROTOCOL */
4933 static int swrap_getsockopt(int s
, int level
, int optname
,
4934 void *optval
, socklen_t
*optlen
)
4936 struct socket_info
*si
= find_socket_info(s
);
4940 return libc_getsockopt(s
,
4949 if (level
== SOL_SOCKET
) {
4953 if (optval
== NULL
|| optlen
== NULL
||
4954 *optlen
< (socklen_t
)sizeof(int)) {
4960 *optlen
= sizeof(int);
4961 *(int *)optval
= si
->family
;
4964 #endif /* SO_DOMAIN */
4968 if (optval
== NULL
|| optlen
== NULL
||
4969 *optlen
< (socklen_t
)sizeof(int)) {
4975 *optlen
= sizeof(int);
4976 *(int *)optval
= si
->protocol
;
4979 #endif /* SO_PROTOCOL */
4981 if (optval
== NULL
|| optlen
== NULL
||
4982 *optlen
< (socklen_t
)sizeof(int)) {
4988 *optlen
= sizeof(int);
4989 *(int *)optval
= si
->type
;
4993 ret
= libc_getsockopt(s
,
5000 } else if (level
== IPPROTO_TCP
) {
5005 * This enables sending packets directly out over TCP.
5006 * As a unix socket is doing that any way, report it as
5009 if (optval
== NULL
|| optlen
== NULL
||
5010 *optlen
< (socklen_t
)sizeof(int)) {
5016 *optlen
= sizeof(int);
5017 *(int *)optval
= si
->tcp_nodelay
;
5021 #endif /* TCP_NODELAY */
5024 struct tcp_info info
;
5025 socklen_t ilen
= sizeof(info
);
5027 #ifdef HAVE_NETINET_TCP_FSM_H
5028 /* This is FreeBSD */
5029 # define __TCP_LISTEN TCPS_LISTEN
5030 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
5031 # define __TCP_CLOSE TCPS_CLOSED
5034 # define __TCP_LISTEN TCP_LISTEN
5035 # define __TCP_ESTABLISHED TCP_ESTABLISHED
5036 # define __TCP_CLOSE TCP_CLOSE
5040 if (si
->listening
) {
5041 info
.tcpi_state
= __TCP_LISTEN
;
5042 } else if (si
->connected
) {
5044 * For now we just fake a few values
5045 * supported both by FreeBSD and Linux
5047 info
.tcpi_state
= __TCP_ESTABLISHED
;
5048 info
.tcpi_rto
= 200000; /* 200 msec */
5049 info
.tcpi_rtt
= 5000; /* 5 msec */
5050 info
.tcpi_rttvar
= 5000; /* 5 msec */
5052 info
.tcpi_state
= __TCP_CLOSE
;
5053 info
.tcpi_rto
= 1000000; /* 1 sec */
5055 info
.tcpi_rttvar
= 250000; /* 250 msec */
5058 if (optval
== NULL
|| optlen
== NULL
||
5059 *optlen
< (socklen_t
)ilen
) {
5066 memcpy(optval
, &info
, ilen
);
5071 #endif /* TCP_INFO */
5077 errno
= ENOPROTOOPT
;
5081 SWRAP_UNLOCK_SI(si
);
5085 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5086 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
5088 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
5091 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
5094 /****************************************************************************
5096 ***************************************************************************/
5098 static int swrap_setsockopt(int s
, int level
, int optname
,
5099 const void *optval
, socklen_t optlen
)
5101 struct socket_info
*si
= find_socket_info(s
);
5105 return libc_setsockopt(s
,
5112 if (level
== SOL_SOCKET
) {
5113 return libc_setsockopt(s
,
5122 if (level
== IPPROTO_TCP
) {
5129 * This enables sending packets directly out over TCP.
5130 * A unix socket is doing that any way.
5132 if (optval
== NULL
|| optlen
== 0 ||
5133 optlen
< (socklen_t
)sizeof(int)) {
5139 i
= *discard_const_p(int, optval
);
5140 if (i
!= 0 && i
!= 1) {
5145 si
->tcp_nodelay
= i
;
5150 #endif /* TCP_NODELAY */
5156 switch (si
->family
) {
5158 if (level
== IPPROTO_IP
) {
5160 if (optname
== IP_PKTINFO
) {
5161 si
->pktinfo
= AF_INET
;
5163 #endif /* IP_PKTINFO */
5169 if (level
== IPPROTO_IPV6
) {
5170 #ifdef IPV6_RECVPKTINFO
5171 if (optname
== IPV6_RECVPKTINFO
) {
5172 si
->pktinfo
= AF_INET6
;
5174 #endif /* IPV6_PKTINFO */
5180 errno
= ENOPROTOOPT
;
5186 SWRAP_UNLOCK_SI(si
);
5190 int setsockopt(int s
, int level
, int optname
,
5191 const void *optval
, socklen_t optlen
)
5193 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
5196 /****************************************************************************
5198 ***************************************************************************/
5200 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
5202 struct socket_info
*si
= find_socket_info(s
);
5204 int *value_ptr
= NULL
;
5208 return libc_vioctl(s
, r
, va
);
5215 rc
= libc_vioctl(s
, r
, va
);
5220 value_ptr
= ((int *)va_arg(ap
, int *));
5223 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
5224 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
5225 } else if (value_ptr
!= NULL
&& *value_ptr
== 0) { /* END OF FILE */
5226 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
5231 /* this is FreeBSD */
5232 FALL_THROUGH
; /* to TIOCOUTQ */
5233 #endif /* FIONWRITE */
5234 case TIOCOUTQ
: /* same as SIOCOUTQ on Linux */
5236 * This may return more bytes then the application
5237 * sent into the socket, for tcp it should
5238 * return the number of unacked bytes.
5240 * On AF_UNIX, all bytes are immediately acked!
5243 value_ptr
= ((int *)va_arg(ap
, int *));
5251 SWRAP_UNLOCK_SI(si
);
5255 #ifdef HAVE_IOCTL_INT
5256 int ioctl(int s
, int r
, ...)
5258 int ioctl(int s
, unsigned long int r
, ...)
5266 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
5277 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5280 # ifdef _ALIGN /* BSD */
5281 #define CMSG_ALIGN _ALIGN
5283 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5284 # endif /* _ALIGN */
5285 #endif /* CMSG_ALIGN */
5288 * @brief Add a cmsghdr to a msghdr.
5290 * This is an function to add any type of cmsghdr. It will operate on the
5291 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5292 * the buffer position after the added cmsg element. Hence, this function is
5293 * intended to be used with an intermediate msghdr and not on the original
5294 * one handed in by the client.
5296 * @param[in] msg The msghdr to which to add the cmsg.
5298 * @param[in] level The cmsg level to set.
5300 * @param[in] type The cmsg type to set.
5302 * @param[in] data The cmsg data to set.
5304 * @param[in] len the length of the data to set.
5306 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
5312 size_t cmlen
= CMSG_LEN(len
);
5313 size_t cmspace
= CMSG_SPACE(len
);
5314 uint8_t cmbuf
[cmspace
];
5315 void *cast_ptr
= (void *)cmbuf
;
5316 struct cmsghdr
*cm
= (struct cmsghdr
*)cast_ptr
;
5319 memset(cmbuf
, 0, cmspace
);
5321 if (msg
->msg_controllen
< cmlen
) {
5322 cmlen
= msg
->msg_controllen
;
5323 msg
->msg_flags
|= MSG_CTRUNC
;
5326 if (msg
->msg_controllen
< cmspace
) {
5327 cmspace
= msg
->msg_controllen
;
5331 * We copy the full input data into an intermediate cmsghdr first
5332 * in order to more easily cope with truncation.
5334 cm
->cmsg_len
= cmlen
;
5335 cm
->cmsg_level
= level
;
5336 cm
->cmsg_type
= type
;
5337 memcpy(CMSG_DATA(cm
), data
, len
);
5340 * We now copy the possibly truncated buffer.
5341 * We copy cmlen bytes, but consume cmspace bytes,
5342 * leaving the possible padding uninitialiazed.
5344 p
= (uint8_t *)msg
->msg_control
;
5345 memcpy(p
, cm
, cmlen
);
5347 msg
->msg_control
= p
;
5348 msg
->msg_controllen
-= cmspace
;
5353 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
5356 /* Add packet info */
5357 switch (si
->pktinfo
) {
5358 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5360 struct sockaddr_in
*sin
;
5361 #if defined(HAVE_STRUCT_IN_PKTINFO)
5362 struct in_pktinfo pkt
;
5363 #elif defined(IP_RECVDSTADDR)
5367 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in
)) {
5368 sin
= &si
->bindname
.sa
.in
;
5370 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in
)) {
5373 sin
= &si
->myname
.sa
.in
;
5378 #if defined(HAVE_STRUCT_IN_PKTINFO)
5379 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
5380 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
5381 #elif defined(IP_RECVDSTADDR)
5382 pkt
= sin
->sin_addr
;
5385 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
5390 #endif /* IP_PKTINFO */
5391 #if defined(HAVE_IPV6)
5393 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5394 struct sockaddr_in6
*sin6
;
5395 struct in6_pktinfo pkt6
;
5397 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in6
)) {
5398 sin6
= &si
->bindname
.sa
.in6
;
5400 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in6
)) {
5403 sin6
= &si
->myname
.sa
.in6
;
5408 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
5409 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
5411 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
5412 &pkt6
, sizeof(pkt6
));
5413 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5417 #endif /* IPV6_PKTINFO */
5425 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
5426 struct msghdr
*omsg
)
5430 if (si
->pktinfo
> 0) {
5431 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
5437 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr
*cmsg
,
5439 size_t *cm_data_space
);
5440 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr
*cmsg
,
5442 size_t *cm_data_space
);
5443 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr
*cmsg
,
5445 size_t *cm_data_space
);
5447 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr
*_msg
,
5449 size_t *cm_data_space
)
5451 struct msghdr
*msg
= discard_const_p(struct msghdr
, _msg
);
5452 struct cmsghdr
*cmsg
;
5456 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
5460 for (cmsg
= CMSG_FIRSTHDR(msg
);
5462 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
5463 switch (cmsg
->cmsg_level
) {
5465 rc
= swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg
,
5470 rc
= swrap_sendmsg_filter_cmsg_sol_socket(cmsg
,
5475 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
5481 int saved_errno
= errno
;
5482 SAFE_FREE(*cm_data
);
5484 errno
= saved_errno
;
5492 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr
*cmsg
,
5494 size_t *cm_data_space
)
5499 cmspace
= *cm_data_space
+ CMSG_ALIGN(cmsg
->cmsg_len
);
5501 p
= realloc((*cm_data
), cmspace
);
5507 p
= (*cm_data
) + (*cm_data_space
);
5508 *cm_data_space
= cmspace
;
5510 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
5515 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr
*cmsg
,
5517 size_t *cm_data_space
);
5520 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr
*cmsg
,
5522 size_t *cm_data_space
)
5526 switch(cmsg
->cmsg_type
) {
5529 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
5536 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
5548 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr
*cmsg
,
5550 size_t *cm_data_space
)
5552 (void)cmsg
; /* unused */
5553 (void)cm_data
; /* unused */
5554 (void)cm_data_space
; /* unused */
5557 * Passing a IP pktinfo to a unix socket might be rejected by the
5558 * Kernel, at least on FreeBSD. So skip this cmsg.
5563 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr
*cmsg
,
5565 size_t *cm_data_space
)
5569 switch (cmsg
->cmsg_type
) {
5571 SWRAP_LOG(SWRAP_LOG_TRACE
,
5572 "Ignoring SCM_RIGHTS on inet socket!");
5575 #ifdef SCM_CREDENTIALS
5576 case SCM_CREDENTIALS
:
5577 SWRAP_LOG(SWRAP_LOG_TRACE
,
5578 "Ignoring SCM_CREDENTIALS on inet socket!");
5581 #endif /* SCM_CREDENTIALS */
5583 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
5592 static const uint64_t swrap_unix_scm_right_magic
= 0x8e0e13f27c42fc36;
5595 * We only allow up to 6 fds at a time
5596 * as that's more than enough for Samba
5597 * and it means we can keep the logic simple
5598 * and work with fixed size arrays.
5600 * We also keep sizeof(struct swrap_unix_scm_rights)
5601 * under PIPE_BUF (4096) in order to allow a non-blocking
5602 * write into the pipe.
5605 #define PIPE_BUF 4096
5607 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5608 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5609 struct swrap_unix_scm_rights_payload
{
5611 int8_t idxs
[SWRAP_MAX_PASSED_FDS
];
5612 struct socket_info infos
[SWRAP_MAX_PASSED_SOCKET_INFO
];
5614 struct swrap_unix_scm_rights
{
5616 char package_name
[sizeof(SOCKET_WRAPPER_PACKAGE
)];
5617 char package_version
[sizeof(SOCKET_WRAPPER_VERSION
)];
5619 uint32_t payload_size
;
5620 struct swrap_unix_scm_rights_payload payload
;
5623 static void swrap_dec_fd_passed_array(size_t num
, struct socket_info
**array
)
5625 int saved_errno
= errno
;
5628 for (i
= 0; i
< num
; i
++) {
5629 struct socket_info
*si
= array
[i
];
5635 swrap_dec_refcount(si
);
5636 if (si
->fd_passed
> 0) {
5639 SWRAP_UNLOCK_SI(si
);
5643 errno
= saved_errno
;
5646 static void swrap_undo_si_idx_array(size_t num
, int *array
)
5648 int saved_errno
= errno
;
5651 swrap_mutex_lock(&first_free_mutex
);
5653 for (i
= 0; i
< num
; i
++) {
5654 struct socket_info
*si
= NULL
;
5656 if (array
[i
] == -1) {
5660 si
= swrap_get_socket_info(array
[i
]);
5666 swrap_dec_refcount(si
);
5667 SWRAP_UNLOCK_SI(si
);
5669 swrap_set_next_free(si
, first_free
);
5670 first_free
= array
[i
];
5674 swrap_mutex_unlock(&first_free_mutex
);
5675 errno
= saved_errno
;
5678 static void swrap_close_fd_array(size_t num
, const int *array
)
5680 int saved_errno
= errno
;
5683 for (i
= 0; i
< num
; i
++) {
5684 if (array
[i
] == -1) {
5687 libc_close(array
[i
]);
5690 errno
= saved_errno
;
5698 union __swrap_cmsghdr
{
5700 struct cmsghdr
*cmsg
;
5703 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr
*cmsg
,
5705 size_t *cm_data_space
,
5706 int *scm_rights_pipe_fd
)
5708 struct swrap_unix_scm_rights info
;
5709 struct swrap_unix_scm_rights_payload
*payload
= NULL
;
5710 int si_idx_array
[SWRAP_MAX_PASSED_FDS
];
5711 struct socket_info
*si_array
[SWRAP_MAX_PASSED_FDS
] = { NULL
, };
5712 size_t info_idx
= 0;
5715 union __swrap_fds __fds_in
= { .p
= NULL
, };
5716 const int *fds_in
= NULL
;
5718 size_t size_fds_out
;
5719 union __swrap_fds __fds_out
= { .p
= NULL
, };
5720 int *fds_out
= NULL
;
5723 size_t new_cm_data_space
;
5724 union __swrap_cmsghdr __new_cmsg
= { .p
= NULL
, };
5725 struct cmsghdr
*new_cmsg
= NULL
;
5728 int pipefd
[2] = { -1, -1 };
5733 * We pass this a buffer to the kernel make sure any padding
5737 info
.magic
= swrap_unix_scm_right_magic
;
5738 memcpy(info
.package_name
,
5739 SOCKET_WRAPPER_PACKAGE
,
5740 sizeof(info
.package_name
));
5741 memcpy(info
.package_version
,
5742 SOCKET_WRAPPER_VERSION
,
5743 sizeof(info
.package_version
));
5744 info
.full_size
= sizeof(info
);
5745 info
.payload_size
= sizeof(info
.payload
);
5746 payload
= &info
.payload
;
5748 if (*scm_rights_pipe_fd
!= -1) {
5749 SWRAP_LOG(SWRAP_LOG_ERROR
,
5750 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5755 if (cmsg
->cmsg_len
< CMSG_LEN(0)) {
5756 SWRAP_LOG(SWRAP_LOG_ERROR
,
5757 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5758 (size_t)cmsg
->cmsg_len
,
5763 size_fds_in
= cmsg
->cmsg_len
- CMSG_LEN(0);
5764 if ((size_fds_in
% sizeof(int)) != 0) {
5765 SWRAP_LOG(SWRAP_LOG_ERROR
,
5766 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5767 (size_t)cmsg
->cmsg_len
,
5773 num_fds_in
= size_fds_in
/ sizeof(int);
5774 if (num_fds_in
> SWRAP_MAX_PASSED_FDS
) {
5775 SWRAP_LOG(SWRAP_LOG_ERROR
,
5776 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5778 "SWRAP_MAX_PASSED_FDS(%zu)",
5779 (size_t)cmsg
->cmsg_len
,
5782 SWRAP_MAX_PASSED_FDS
);
5786 if (num_fds_in
== 0) {
5787 SWRAP_LOG(SWRAP_LOG_ERROR
,
5788 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5790 (size_t)cmsg
->cmsg_len
,
5796 __fds_in
.p
= CMSG_DATA(cmsg
);
5797 fds_in
= __fds_in
.fds
;
5798 num_fds_out
= num_fds_in
+ 1;
5800 SWRAP_LOG(SWRAP_LOG_TRACE
,
5801 "num_fds_in=%zu num_fds_out=%zu",
5802 num_fds_in
, num_fds_out
);
5804 size_fds_out
= sizeof(int) * num_fds_out
;
5805 cmsg_len
= CMSG_LEN(size_fds_out
);
5806 cmsg_space
= CMSG_SPACE(size_fds_out
);
5808 new_cm_data_space
= *cm_data_space
+ cmsg_space
;
5810 p
= realloc((*cm_data
), new_cm_data_space
);
5815 p
= (*cm_data
) + (*cm_data_space
);
5816 memset(p
, 0, cmsg_space
);
5818 new_cmsg
= __new_cmsg
.cmsg
;
5820 __fds_out
.p
= CMSG_DATA(new_cmsg
);
5821 fds_out
= __fds_out
.fds
;
5822 memcpy(fds_out
, fds_in
, size_fds_in
);
5823 new_cmsg
->cmsg_len
= cmsg
->cmsg_len
;
5825 for (i
= 0; i
< num_fds_in
; i
++) {
5828 payload
->idxs
[i
] = -1;
5829 payload
->num_idxs
++;
5831 si_idx_array
[i
] = find_socket_info_index(fds_in
[i
]);
5832 if (si_idx_array
[i
] == -1) {
5836 si_array
[i
] = swrap_get_socket_info(si_idx_array
[i
]);
5837 if (si_array
[i
] == NULL
) {
5838 SWRAP_LOG(SWRAP_LOG_ERROR
,
5839 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5840 i
, fds_in
[i
], i
, si_idx_array
[i
]);
5845 for (j
= 0; j
< i
; j
++) {
5846 if (si_array
[j
] == si_array
[i
]) {
5847 payload
->idxs
[i
] = payload
->idxs
[j
];
5851 if (payload
->idxs
[i
] == -1) {
5852 if (info_idx
>= SWRAP_MAX_PASSED_SOCKET_INFO
) {
5853 SWRAP_LOG(SWRAP_LOG_ERROR
,
5854 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5855 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5856 i
, fds_in
[i
], i
, si_idx_array
[i
],
5858 SWRAP_MAX_PASSED_SOCKET_INFO
);
5862 payload
->idxs
[i
] = info_idx
;
5868 for (i
= 0; i
< num_fds_in
; i
++) {
5869 struct socket_info
*si
= si_array
[i
];
5872 SWRAP_LOG(SWRAP_LOG_TRACE
,
5873 "fds_in[%zu]=%d not an inet socket",
5878 SWRAP_LOG(SWRAP_LOG_TRACE
,
5879 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5880 "passing as info.idxs[%zu]=%d!",
5883 i
, payload
->idxs
[i
]);
5887 payload
->infos
[payload
->idxs
[i
]] = *si
;
5888 payload
->infos
[payload
->idxs
[i
]].fd_passed
= 0;
5889 SWRAP_UNLOCK_SI(si
);
5894 int saved_errno
= errno
;
5895 SWRAP_LOG(SWRAP_LOG_ERROR
,
5896 "pipe() failed - %d %s",
5898 strerror(saved_errno
));
5899 swrap_dec_fd_passed_array(num_fds_in
, si_array
);
5900 errno
= saved_errno
;
5904 sret
= libc_write(pipefd
[1], &info
, sizeof(info
));
5905 if (sret
!= sizeof(info
)) {
5906 int saved_errno
= errno
;
5908 saved_errno
= EINVAL
;
5910 SWRAP_LOG(SWRAP_LOG_ERROR
,
5911 "write() failed - sret=%zd - %d %s",
5913 strerror(saved_errno
));
5914 swrap_dec_fd_passed_array(num_fds_in
, si_array
);
5915 libc_close(pipefd
[1]);
5916 libc_close(pipefd
[0]);
5917 errno
= saved_errno
;
5920 libc_close(pipefd
[1]);
5923 * Add the pipe read end to the end of the passed fd array
5925 fds_out
[num_fds_in
] = pipefd
[0];
5926 new_cmsg
->cmsg_len
= cmsg_len
;
5928 /* we're done ... */
5929 *scm_rights_pipe_fd
= pipefd
[0];
5930 *cm_data_space
= new_cm_data_space
;
5935 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr
*cmsg
,
5937 size_t *cm_data_space
,
5938 int *scm_rights_pipe_fd
)
5942 switch (cmsg
->cmsg_type
) {
5944 rc
= swrap_sendmsg_unix_scm_rights(cmsg
,
5947 scm_rights_pipe_fd
);
5950 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
5959 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr
*cmsg
,
5961 size_t *cm_data_space
)
5963 int scm_rights_pipe_fd
= -1;
5964 struct swrap_unix_scm_rights info
;
5965 struct swrap_unix_scm_rights_payload
*payload
= NULL
;
5966 int si_idx_array
[SWRAP_MAX_PASSED_FDS
];
5969 union __swrap_fds __fds_in
= { .p
= NULL
, };
5970 const int *fds_in
= NULL
;
5972 size_t size_fds_out
;
5973 union __swrap_fds __fds_out
= { .p
= NULL
, };
5974 int *fds_out
= NULL
;
5977 size_t new_cm_data_space
;
5978 union __swrap_cmsghdr __new_cmsg
= { .p
= NULL
, };
5979 struct cmsghdr
*new_cmsg
= NULL
;
5985 if (cmsg
->cmsg_len
< CMSG_LEN(0)) {
5986 SWRAP_LOG(SWRAP_LOG_ERROR
,
5987 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5988 (size_t)cmsg
->cmsg_len
,
5993 size_fds_in
= cmsg
->cmsg_len
- CMSG_LEN(0);
5994 if ((size_fds_in
% sizeof(int)) != 0) {
5995 SWRAP_LOG(SWRAP_LOG_ERROR
,
5996 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5997 (size_t)cmsg
->cmsg_len
,
6003 num_fds_in
= size_fds_in
/ sizeof(int);
6004 if (num_fds_in
> (SWRAP_MAX_PASSED_FDS
+ 1)) {
6005 SWRAP_LOG(SWRAP_LOG_ERROR
,
6006 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
6007 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
6008 (size_t)cmsg
->cmsg_len
,
6011 SWRAP_MAX_PASSED_FDS
+1);
6015 if (num_fds_in
<= 1) {
6016 SWRAP_LOG(SWRAP_LOG_ERROR
,
6017 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
6019 (size_t)cmsg
->cmsg_len
,
6025 __fds_in
.p
= CMSG_DATA(cmsg
);
6026 fds_in
= __fds_in
.fds
;
6027 num_fds_out
= num_fds_in
- 1;
6029 SWRAP_LOG(SWRAP_LOG_TRACE
,
6030 "num_fds_in=%zu num_fds_out=%zu",
6031 num_fds_in
, num_fds_out
);
6033 for (i
= 0; i
< num_fds_in
; i
++) {
6034 /* Check if we have a stale fd and remove it */
6035 swrap_remove_stale(fds_in
[i
]);
6038 scm_rights_pipe_fd
= fds_in
[num_fds_out
];
6039 size_fds_out
= sizeof(int) * num_fds_out
;
6040 cmsg_len
= CMSG_LEN(size_fds_out
);
6041 cmsg_space
= CMSG_SPACE(size_fds_out
);
6043 new_cm_data_space
= *cm_data_space
+ cmsg_space
;
6045 p
= realloc((*cm_data
), new_cm_data_space
);
6047 swrap_close_fd_array(num_fds_in
, fds_in
);
6051 p
= (*cm_data
) + (*cm_data_space
);
6052 memset(p
, 0, cmsg_space
);
6054 new_cmsg
= __new_cmsg
.cmsg
;
6056 __fds_out
.p
= CMSG_DATA(new_cmsg
);
6057 fds_out
= __fds_out
.fds
;
6058 memcpy(fds_out
, fds_in
, size_fds_out
);
6059 new_cmsg
->cmsg_len
= cmsg_len
;
6061 sret
= read(scm_rights_pipe_fd
, &info
, sizeof(info
));
6062 if (sret
!= sizeof(info
)) {
6063 int saved_errno
= errno
;
6065 saved_errno
= EINVAL
;
6067 SWRAP_LOG(SWRAP_LOG_ERROR
,
6068 "read() failed - sret=%zd - %d %s",
6070 strerror(saved_errno
));
6071 swrap_close_fd_array(num_fds_in
, fds_in
);
6072 errno
= saved_errno
;
6075 libc_close(scm_rights_pipe_fd
);
6076 payload
= &info
.payload
;
6078 if (info
.magic
!= swrap_unix_scm_right_magic
) {
6079 SWRAP_LOG(SWRAP_LOG_ERROR
,
6080 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
6081 (unsigned long long)info
.magic
,
6082 (unsigned long long)swrap_unix_scm_right_magic
);
6083 swrap_close_fd_array(num_fds_out
, fds_out
);
6088 cmp
= memcmp(info
.package_name
,
6089 SOCKET_WRAPPER_PACKAGE
,
6090 sizeof(info
.package_name
));
6092 SWRAP_LOG(SWRAP_LOG_ERROR
,
6093 "info.package_name='%.*s' != '%s'",
6094 (int)sizeof(info
.package_name
),
6096 SOCKET_WRAPPER_PACKAGE
);
6097 swrap_close_fd_array(num_fds_out
, fds_out
);
6102 cmp
= memcmp(info
.package_version
,
6103 SOCKET_WRAPPER_VERSION
,
6104 sizeof(info
.package_version
));
6106 SWRAP_LOG(SWRAP_LOG_ERROR
,
6107 "info.package_version='%.*s' != '%s'",
6108 (int)sizeof(info
.package_version
),
6109 info
.package_version
,
6110 SOCKET_WRAPPER_VERSION
);
6111 swrap_close_fd_array(num_fds_out
, fds_out
);
6116 if (info
.full_size
!= sizeof(info
)) {
6117 SWRAP_LOG(SWRAP_LOG_ERROR
,
6118 "info.full_size=%zu != sizeof(info)=%zu",
6119 (size_t)info
.full_size
,
6121 swrap_close_fd_array(num_fds_out
, fds_out
);
6126 if (info
.payload_size
!= sizeof(info
.payload
)) {
6127 SWRAP_LOG(SWRAP_LOG_ERROR
,
6128 "info.payload_size=%zu != sizeof(info.payload)=%zu",
6129 (size_t)info
.payload_size
,
6130 sizeof(info
.payload
));
6131 swrap_close_fd_array(num_fds_out
, fds_out
);
6136 if (payload
->num_idxs
!= num_fds_out
) {
6137 SWRAP_LOG(SWRAP_LOG_ERROR
,
6138 "info.num_idxs=%u != num_fds_out=%zu",
6139 payload
->num_idxs
, num_fds_out
);
6140 swrap_close_fd_array(num_fds_out
, fds_out
);
6145 for (i
= 0; i
< num_fds_out
; i
++) {
6148 si_idx_array
[i
] = -1;
6150 if (payload
->idxs
[i
] == -1) {
6151 SWRAP_LOG(SWRAP_LOG_TRACE
,
6152 "fds_out[%zu]=%d not an inet socket",
6157 if (payload
->idxs
[i
] < 0) {
6158 SWRAP_LOG(SWRAP_LOG_ERROR
,
6159 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
6160 i
, fds_out
[i
], i
, payload
->idxs
[i
]);
6161 swrap_close_fd_array(num_fds_out
, fds_out
);
6166 if (payload
->idxs
[i
] >= payload
->num_idxs
) {
6167 SWRAP_LOG(SWRAP_LOG_ERROR
,
6168 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
6169 i
, fds_out
[i
], i
, payload
->idxs
[i
],
6171 swrap_close_fd_array(num_fds_out
, fds_out
);
6176 if ((size_t)fds_out
[i
] >= socket_fds_max
) {
6177 SWRAP_LOG(SWRAP_LOG_ERROR
,
6178 "The max socket index limit of %zu has been reached, "
6182 swrap_close_fd_array(num_fds_out
, fds_out
);
6187 SWRAP_LOG(SWRAP_LOG_TRACE
,
6189 "received as info.idxs[%zu]=%d!",
6191 i
, payload
->idxs
[i
]);
6193 for (j
= 0; j
< i
; j
++) {
6194 if (payload
->idxs
[j
] == -1) {
6197 if (payload
->idxs
[j
] == payload
->idxs
[i
]) {
6198 si_idx_array
[i
] = si_idx_array
[j
];
6201 if (si_idx_array
[i
] == -1) {
6202 const struct socket_info
*si
= &payload
->infos
[payload
->idxs
[i
]];
6204 si_idx_array
[i
] = swrap_add_socket_info(si
);
6205 if (si_idx_array
[i
] == -1) {
6206 int saved_errno
= errno
;
6207 SWRAP_LOG(SWRAP_LOG_ERROR
,
6208 "The max socket index limit of %zu has been reached, "
6212 swrap_undo_si_idx_array(i
, si_idx_array
);
6213 swrap_close_fd_array(num_fds_out
, fds_out
);
6214 errno
= saved_errno
;
6217 SWRAP_LOG(SWRAP_LOG_TRACE
,
6218 "Imported %s socket for protocol %s, fd=%d",
6219 si
->family
== AF_INET
? "IPv4" : "IPv6",
6220 si
->type
== SOCK_DGRAM
? "UDP" : "TCP",
6225 for (i
= 0; i
< num_fds_out
; i
++) {
6226 if (si_idx_array
[i
] == -1) {
6229 set_socket_info_index(fds_out
[i
], si_idx_array
[i
]);
6232 /* we're done ... */
6233 *cm_data_space
= new_cm_data_space
;
6238 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr
*cmsg
,
6240 size_t *cm_data_space
)
6244 switch (cmsg
->cmsg_type
) {
6246 rc
= swrap_recvmsg_unix_scm_rights(cmsg
,
6251 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
6260 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6262 static int swrap_sendmsg_before_unix(const struct msghdr
*_msg_in
,
6263 struct msghdr
*msg_tmp
,
6264 int *scm_rights_pipe_fd
)
6266 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6267 struct msghdr
*msg_in
= discard_const_p(struct msghdr
, _msg_in
);
6268 struct cmsghdr
*cmsg
= NULL
;
6269 uint8_t *cm_data
= NULL
;
6270 size_t cm_data_space
= 0;
6274 *scm_rights_pipe_fd
= -1;
6277 if (msg_in
->msg_controllen
== 0 || msg_in
->msg_control
== NULL
) {
6281 for (cmsg
= CMSG_FIRSTHDR(msg_in
);
6283 cmsg
= CMSG_NXTHDR(msg_in
, cmsg
)) {
6284 switch (cmsg
->cmsg_level
) {
6286 rc
= swrap_sendmsg_unix_sol_socket(cmsg
,
6289 scm_rights_pipe_fd
);
6293 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
6299 int saved_errno
= errno
;
6301 errno
= saved_errno
;
6306 msg_tmp
->msg_controllen
= cm_data_space
;
6307 msg_tmp
->msg_control
= cm_data
;
6310 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6311 *msg_tmp
= *_msg_in
;
6313 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6316 static ssize_t
swrap_sendmsg_after_unix(struct msghdr
*msg_tmp
,
6318 int scm_rights_pipe_fd
)
6320 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6321 int saved_errno
= errno
;
6322 SAFE_FREE(msg_tmp
->msg_control
);
6323 if (scm_rights_pipe_fd
!= -1) {
6324 libc_close(scm_rights_pipe_fd
);
6326 errno
= saved_errno
;
6327 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6331 static int swrap_recvmsg_before_unix(struct msghdr
*msg_in
,
6332 struct msghdr
*msg_tmp
,
6333 uint8_t **tmp_control
)
6335 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6336 const size_t cm_extra_space
= CMSG_SPACE(sizeof(int));
6337 uint8_t *cm_data
= NULL
;
6338 size_t cm_data_space
= 0;
6341 *tmp_control
= NULL
;
6343 SWRAP_LOG(SWRAP_LOG_TRACE
,
6344 "msg_in->msg_controllen=%zu",
6345 (size_t)msg_in
->msg_controllen
);
6348 if (msg_in
->msg_controllen
== 0 || msg_in
->msg_control
== NULL
) {
6353 * We need to give the kernel a bit more space in order
6354 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6355 * swrap_recvmsg_after_unix() will hide it again.
6357 cm_data_space
= msg_in
->msg_controllen
;
6358 if (cm_data_space
< (INT32_MAX
- cm_extra_space
)) {
6359 cm_data_space
+= cm_extra_space
;
6361 cm_data
= calloc(1, cm_data_space
);
6362 if (cm_data
== NULL
) {
6366 msg_tmp
->msg_controllen
= cm_data_space
;
6367 msg_tmp
->msg_control
= cm_data
;
6368 *tmp_control
= cm_data
;
6370 SWRAP_LOG(SWRAP_LOG_TRACE
,
6371 "msg_tmp->msg_controllen=%zu",
6372 (size_t)msg_tmp
->msg_controllen
);
6374 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6376 *tmp_control
= NULL
;
6378 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6381 static ssize_t
swrap_recvmsg_after_unix(struct msghdr
*msg_tmp
,
6382 uint8_t **tmp_control
,
6383 struct msghdr
*msg_out
,
6386 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6387 struct cmsghdr
*cmsg
= NULL
;
6388 uint8_t *cm_data
= NULL
;
6389 size_t cm_data_space
= 0;
6393 int saved_errno
= errno
;
6394 SWRAP_LOG(SWRAP_LOG_TRACE
, "ret=%zd - %d - %s", ret
,
6395 saved_errno
, strerror(saved_errno
));
6396 SAFE_FREE(*tmp_control
);
6397 /* msg_out should not be touched on error */
6398 errno
= saved_errno
;
6402 SWRAP_LOG(SWRAP_LOG_TRACE
,
6403 "msg_tmp->msg_controllen=%zu",
6404 (size_t)msg_tmp
->msg_controllen
);
6407 if (msg_tmp
->msg_controllen
== 0 || msg_tmp
->msg_control
== NULL
) {
6408 int saved_errno
= errno
;
6409 *msg_out
= *msg_tmp
;
6410 SAFE_FREE(*tmp_control
);
6411 errno
= saved_errno
;
6415 for (cmsg
= CMSG_FIRSTHDR(msg_tmp
);
6417 cmsg
= CMSG_NXTHDR(msg_tmp
, cmsg
)) {
6418 switch (cmsg
->cmsg_level
) {
6420 rc
= swrap_recvmsg_unix_sol_socket(cmsg
,
6426 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
6432 int saved_errno
= errno
;
6434 SAFE_FREE(*tmp_control
);
6435 errno
= saved_errno
;
6441 * msg_tmp->msg_control (*tmp_control) was created by
6442 * swrap_recvmsg_before_unix() and msg_out->msg_control
6443 * is still the buffer of the caller.
6445 msg_tmp
->msg_control
= msg_out
->msg_control
;
6446 msg_tmp
->msg_controllen
= msg_out
->msg_controllen
;
6447 *msg_out
= *msg_tmp
;
6449 cm_data_space
= MIN(cm_data_space
, msg_out
->msg_controllen
);
6450 memcpy(msg_out
->msg_control
, cm_data
, cm_data_space
);
6451 msg_out
->msg_controllen
= cm_data_space
;
6453 SAFE_FREE(*tmp_control
);
6455 SWRAP_LOG(SWRAP_LOG_TRACE
,
6456 "msg_out->msg_controllen=%zu",
6457 (size_t)msg_out
->msg_controllen
);
6459 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6460 int saved_errno
= errno
;
6461 *msg_out
= *msg_tmp
;
6462 SAFE_FREE(*tmp_control
);
6463 errno
= saved_errno
;
6465 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6468 static ssize_t
swrap_sendmsg_before(int fd
,
6469 struct socket_info
*si
,
6471 struct iovec
*tmp_iov
,
6472 struct sockaddr_un
*tmp_un
,
6473 const struct sockaddr_un
**to_un
,
6474 const struct sockaddr
**to
,
6479 struct swrap_sockaddr_buf buf
= {};
6497 if (!si
->connected
) {
6502 if (msg
->msg_iovlen
== 0) {
6506 mtu
= socket_wrapper_mtu();
6507 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
6509 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
6519 msg
->msg_iovlen
= i
;
6520 if (msg
->msg_iovlen
== 0) {
6521 *tmp_iov
= msg
->msg_iov
[0];
6522 tmp_iov
->iov_len
= MIN((size_t)tmp_iov
->iov_len
,
6524 msg
->msg_iov
= tmp_iov
;
6525 msg
->msg_iovlen
= 1;
6530 if (si
->connected
) {
6531 if (msg
->msg_name
!= NULL
) {
6533 * We are dealing with unix sockets and if we
6534 * are connected, we should only talk to the
6535 * connected unix path. Using the fd to send
6536 * to another server would be hard to achieve.
6538 msg
->msg_name
= NULL
;
6539 msg
->msg_namelen
= 0;
6541 SWRAP_LOG(SWRAP_LOG_TRACE
,
6542 "connected(%s) fd=%d",
6543 swrap_sockaddr_string(&buf
, &si
->peername
.sa
.s
),
6546 const struct sockaddr
*msg_name
;
6547 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
6549 if (msg_name
== NULL
) {
6555 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
6567 msg
->msg_name
= tmp_un
;
6568 msg
->msg_namelen
= sizeof(*tmp_un
);
6571 if (si
->bound
== 0) {
6572 ret
= swrap_auto_bind(fd
, si
, si
->family
);
6574 SWRAP_UNLOCK_SI(si
);
6575 if (errno
== ENOTSOCK
) {
6576 swrap_remove_stale(fd
);
6579 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
6585 if (!si
->defer_connect
) {
6589 ret
= sockaddr_convert_to_un(si
,
6591 si
->peername
.sa_socklen
,
6599 SWRAP_LOG(SWRAP_LOG_TRACE
,
6600 "deferred connect(%s) path=%s, fd=%d",
6601 swrap_sockaddr_string(&buf
, &si
->peername
.sa
.s
),
6602 tmp_un
->sun_path
, fd
);
6604 ret
= libc_connect(fd
,
6605 (struct sockaddr
*)(void *)tmp_un
,
6608 /* to give better errors */
6609 if (ret
== -1 && errno
== ENOENT
) {
6610 errno
= EHOSTUNREACH
;
6617 si
->defer_connect
= 0;
6620 errno
= EHOSTUNREACH
;
6626 SWRAP_UNLOCK_SI(si
);
6631 static void swrap_sendmsg_after(int fd
,
6632 struct socket_info
*si
,
6634 const struct sockaddr
*to
,
6637 int saved_errno
= errno
;
6644 /* to give better errors */
6646 if (saved_errno
== ENOENT
) {
6647 saved_errno
= EHOSTUNREACH
;
6648 } else if (saved_errno
== ENOTSOCK
) {
6649 /* If the fd is not a socket, remove it */
6650 swrap_remove_stale(fd
);
6654 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
6655 avail
+= msg
->msg_iov
[i
].iov_len
;
6659 remain
= MIN(80, avail
);
6664 /* we capture it as one single packet */
6665 buf
= (uint8_t *)malloc(remain
);
6667 /* we just not capture the packet */
6668 errno
= saved_errno
;
6672 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
6673 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
6674 if (this_time
> 0) {
6676 msg
->msg_iov
[i
].iov_base
,
6680 remain
-= this_time
;
6689 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
6690 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
6692 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
6697 if (si
->connected
) {
6698 to
= &si
->peername
.sa
.s
;
6701 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
6702 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
6704 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
6709 SWRAP_UNLOCK_SI(si
);
6712 errno
= saved_errno
;
6715 static int swrap_recvmsg_before(int fd
,
6716 struct socket_info
*si
,
6718 struct iovec
*tmp_iov
)
6725 (void)fd
; /* unused */
6730 if (!si
->connected
) {
6735 if (msg
->msg_iovlen
== 0) {
6739 mtu
= socket_wrapper_mtu();
6740 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
6742 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
6747 msg
->msg_iovlen
= i
;
6748 if (msg
->msg_iovlen
== 0) {
6749 *tmp_iov
= msg
->msg_iov
[0];
6750 tmp_iov
->iov_len
= MIN((size_t)tmp_iov
->iov_len
,
6752 msg
->msg_iov
= tmp_iov
;
6753 msg
->msg_iovlen
= 1;
6758 if (msg
->msg_name
== NULL
) {
6763 if (msg
->msg_iovlen
== 0) {
6767 if (si
->bound
== 0) {
6768 ret
= swrap_auto_bind(fd
, si
, si
->family
);
6770 SWRAP_UNLOCK_SI(si
);
6772 * When attempting to read or write to a
6773 * descriptor, if an underlying autobind fails
6774 * because it's not a socket, stop intercepting
6775 * uses of that descriptor.
6777 if (errno
== ENOTSOCK
) {
6778 swrap_remove_stale(fd
);
6781 SWRAP_LOG(SWRAP_LOG_ERROR
,
6782 "swrap_recvmsg_before failed");
6789 errno
= EHOSTUNREACH
;
6795 SWRAP_UNLOCK_SI(si
);
6800 static int swrap_recvmsg_after(int fd
,
6801 struct socket_info
*si
,
6803 const struct sockaddr_un
*un_addr
,
6804 socklen_t un_addrlen
,
6807 int saved_errno
= errno
;
6809 uint8_t *buf
= NULL
;
6815 /* to give better errors */
6817 if (saved_errno
== ENOENT
) {
6818 saved_errno
= EHOSTUNREACH
;
6819 } else if (saved_errno
== ENOTSOCK
) {
6820 /* If the fd is not a socket, remove it */
6821 swrap_remove_stale(fd
);
6825 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
6826 avail
+= msg
->msg_iov
[i
].iov_len
;
6831 /* Convert the socket address before we leave */
6832 if (si
->type
== SOCK_DGRAM
&& un_addr
!= NULL
) {
6833 rc
= sockaddr_convert_from_un(si
,
6850 remain
= MIN(80, avail
);
6855 /* we capture it as one single packet */
6856 buf
= (uint8_t *)malloc(remain
);
6858 /* we just not capture the packet */
6859 SWRAP_UNLOCK_SI(si
);
6860 errno
= saved_errno
;
6864 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
6865 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
6867 msg
->msg_iov
[i
].iov_base
,
6870 remain
-= this_time
;
6875 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
6876 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
6877 } else if (ret
== 0) { /* END OF FILE */
6878 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
6879 } else if (ret
> 0) {
6880 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
6889 if (un_addr
!= NULL
) {
6890 swrap_pcap_dump_packet(si
,
6896 swrap_pcap_dump_packet(si
,
6909 errno
= saved_errno
;
6911 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6913 msg
->msg_controllen
> 0 &&
6914 msg
->msg_control
!= NULL
) {
6915 rc
= swrap_msghdr_add_socket_info(si
, msg
);
6917 SWRAP_UNLOCK_SI(si
);
6923 SWRAP_UNLOCK_SI(si
);
6927 /****************************************************************************
6929 ***************************************************************************/
6931 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
6932 struct sockaddr
*from
, socklen_t
*fromlen
)
6934 struct swrap_address from_addr
= {
6935 .sa_socklen
= sizeof(struct sockaddr_un
),
6938 struct socket_info
*si
= find_socket_info(s
);
6939 struct swrap_address saddr
= {
6940 .sa_socklen
= sizeof(struct sockaddr_storage
),
6947 return libc_recvfrom(s
,
6959 if (from
!= NULL
&& fromlen
!= NULL
) {
6960 msg
.msg_name
= from
; /* optional address */
6961 msg
.msg_namelen
= *fromlen
; /* size of address */
6963 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
6964 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
6966 msg
.msg_iov
= &tmp
; /* scatter/gather array */
6967 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
6968 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6969 msg
.msg_control
= NULL
; /* ancillary data, see below */
6970 msg
.msg_controllen
= 0; /* ancillary data buffer len */
6971 msg
.msg_flags
= 0; /* flags on received message */
6974 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
6979 buf
= msg
.msg_iov
[0].iov_base
;
6980 len
= msg
.msg_iov
[0].iov_len
;
6982 ret
= libc_recvfrom(s
,
6987 &from_addr
.sa_socklen
);
6992 tret
= swrap_recvmsg_after(s
,
6996 from_addr
.sa_socklen
,
7002 if (from
!= NULL
&& fromlen
!= NULL
) {
7003 *fromlen
= msg
.msg_namelen
;
7009 #ifdef HAVE_ACCEPT_PSOCKLEN_T
7010 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
7011 struct sockaddr
*from
, Psocklen_t fromlen
)
7013 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
7014 struct sockaddr
*from
, socklen_t
*fromlen
)
7017 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
7020 /****************************************************************************
7022 ***************************************************************************/
7024 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
7025 const struct sockaddr
*to
, socklen_t tolen
)
7029 struct swrap_address un_addr
= {
7030 .sa_socklen
= sizeof(struct sockaddr_un
),
7032 const struct sockaddr_un
*to_un
= NULL
;
7035 struct socket_info
*si
= find_socket_info(s
);
7039 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
7042 tmp
.iov_base
= discard_const_p(char, buf
);
7046 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
7047 msg
.msg_namelen
= tolen
; /* size of address */
7048 msg
.msg_iov
= &tmp
; /* scatter/gather array */
7049 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
7050 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7051 msg
.msg_control
= NULL
; /* ancillary data, see below */
7052 msg
.msg_controllen
= 0; /* ancillary data buffer len */
7053 msg
.msg_flags
= 0; /* flags on received message */
7056 rc
= swrap_sendmsg_before(s
,
7068 buf
= msg
.msg_iov
[0].iov_base
;
7069 len
= msg
.msg_iov
[0].iov_len
;
7074 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
7076 char *swrap_dir
= NULL
;
7078 type
= SOCKET_TYPE_CHAR_UDP
;
7080 swrap_dir
= socket_wrapper_dir();
7081 if (swrap_dir
== NULL
) {
7085 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
7086 swrap_un_path(&un_addr
.sa
.un
,
7091 if (stat(un_addr
.sa
.un
.sun_path
, &st
) != 0) continue;
7093 /* ignore the any errors in broadcast sends */
7099 un_addr
.sa_socklen
);
7102 SAFE_FREE(swrap_dir
);
7106 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
7108 SWRAP_UNLOCK_SI(si
);
7115 * If it is a dgram socket and we are connected, don't include the
7118 if (si
->type
== SOCK_DGRAM
&& si
->connected
) {
7119 ret
= libc_sendto(s
,
7126 ret
= libc_sendto(s
,
7130 (struct sockaddr
*)msg
.msg_name
,
7134 SWRAP_UNLOCK_SI(si
);
7136 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
7141 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
7142 const struct sockaddr
*to
, socklen_t tolen
)
7144 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
7147 /****************************************************************************
7149 ***************************************************************************/
7151 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
7153 struct socket_info
*si
;
7155 struct swrap_address saddr
= {
7156 .sa_socklen
= sizeof(struct sockaddr_storage
),
7162 si
= find_socket_info(s
);
7164 return libc_recv(s
, buf
, len
, flags
);
7171 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
7172 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
7173 msg
.msg_iov
= &tmp
; /* scatter/gather array */
7174 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
7175 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7176 msg
.msg_control
= NULL
; /* ancillary data, see below */
7177 msg
.msg_controllen
= 0; /* ancillary data buffer len */
7178 msg
.msg_flags
= 0; /* flags on received message */
7181 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
7186 buf
= msg
.msg_iov
[0].iov_base
;
7187 len
= msg
.msg_iov
[0].iov_len
;
7189 ret
= libc_recv(s
, buf
, len
, flags
);
7191 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
7199 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
7201 return swrap_recv(s
, buf
, len
, flags
);
7204 /****************************************************************************
7206 ***************************************************************************/
7208 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
7210 struct socket_info
*si
;
7213 struct swrap_address saddr
= {
7214 .sa_socklen
= sizeof(struct sockaddr_storage
),
7219 si
= find_socket_info(s
);
7221 return libc_read(s
, buf
, len
);
7228 msg
.msg_name
= &saddr
.sa
.ss
; /* optional address */
7229 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
7230 msg
.msg_iov
= &tmp
; /* scatter/gather array */
7231 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
7232 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7233 msg
.msg_control
= NULL
; /* ancillary data, see below */
7234 msg
.msg_controllen
= 0; /* ancillary data buffer len */
7235 msg
.msg_flags
= 0; /* flags on received message */
7238 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
7240 if (tret
== -ENOTSOCK
) {
7241 return libc_read(s
, buf
, len
);
7246 buf
= msg
.msg_iov
[0].iov_base
;
7247 len
= msg
.msg_iov
[0].iov_len
;
7249 ret
= libc_read(s
, buf
, len
);
7251 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
7259 ssize_t
read(int s
, void *buf
, size_t len
)
7261 return swrap_read(s
, buf
, len
);
7264 /****************************************************************************
7266 ***************************************************************************/
7268 static ssize_t
swrap_write(int s
, const void *buf
, size_t len
)
7272 struct sockaddr_un un_addr
;
7275 struct socket_info
*si
;
7277 si
= find_socket_info(s
);
7279 return libc_write(s
, buf
, len
);
7282 tmp
.iov_base
= discard_const_p(char, buf
);
7286 msg
.msg_name
= NULL
; /* optional address */
7287 msg
.msg_namelen
= 0; /* size of address */
7288 msg
.msg_iov
= &tmp
; /* scatter/gather array */
7289 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
7290 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7291 msg
.msg_control
= NULL
; /* ancillary data, see below */
7292 msg
.msg_controllen
= 0; /* ancillary data buffer len */
7293 msg
.msg_flags
= 0; /* flags on received message */
7296 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
7301 buf
= msg
.msg_iov
[0].iov_base
;
7302 len
= msg
.msg_iov
[0].iov_len
;
7304 ret
= libc_write(s
, buf
, len
);
7306 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
7311 ssize_t
write(int s
, const void *buf
, size_t len
)
7313 return swrap_write(s
, buf
, len
);
7316 /****************************************************************************
7318 ***************************************************************************/
7320 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
7324 struct sockaddr_un un_addr
;
7327 struct socket_info
*si
= find_socket_info(s
);
7330 return libc_send(s
, buf
, len
, flags
);
7333 tmp
.iov_base
= discard_const_p(char, buf
);
7337 msg
.msg_name
= NULL
; /* optional address */
7338 msg
.msg_namelen
= 0; /* size of address */
7339 msg
.msg_iov
= &tmp
; /* scatter/gather array */
7340 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
7341 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7342 msg
.msg_control
= NULL
; /* ancillary data, see below */
7343 msg
.msg_controllen
= 0; /* ancillary data buffer len */
7344 msg
.msg_flags
= 0; /* flags on received message */
7347 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
7352 buf
= msg
.msg_iov
[0].iov_base
;
7353 len
= msg
.msg_iov
[0].iov_len
;
7355 ret
= libc_send(s
, buf
, len
, flags
);
7357 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
7362 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
7364 return swrap_send(s
, buf
, len
, flags
);
7367 /****************************************************************************
7369 ***************************************************************************/
7371 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
7373 struct swrap_address from_addr
= {
7374 .sa_socklen
= sizeof(struct sockaddr_un
),
7376 struct swrap_address convert_addr
= {
7377 .sa_socklen
= sizeof(struct sockaddr_storage
),
7379 struct socket_info
*si
;
7382 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7383 size_t msg_ctrllen_filled
;
7384 size_t msg_ctrllen_left
;
7390 si
= find_socket_info(s
);
7392 uint8_t *tmp_control
= NULL
;
7393 rc
= swrap_recvmsg_before_unix(omsg
, &msg
, &tmp_control
);
7397 ret
= libc_recvmsg(s
, &msg
, flags
);
7398 return swrap_recvmsg_after_unix(&msg
, &tmp_control
, omsg
, ret
);
7401 tmp
.iov_base
= NULL
;
7405 msg
.msg_name
= &from_addr
.sa
; /* optional address */
7406 msg
.msg_namelen
= from_addr
.sa_socklen
; /* size of address */
7407 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
7408 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
7409 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7410 msg_ctrllen_filled
= 0;
7411 msg_ctrllen_left
= omsg
->msg_controllen
;
7413 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
7414 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
7415 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
7418 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
7423 ret
= libc_recvmsg(s
, &msg
, flags
);
7425 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7426 msg_ctrllen_filled
+= msg
.msg_controllen
;
7427 msg_ctrllen_left
-= msg
.msg_controllen
;
7429 if (omsg
->msg_control
!= NULL
) {
7432 p
= omsg
->msg_control
;
7433 p
+= msg_ctrllen_filled
;
7435 msg
.msg_control
= p
;
7436 msg
.msg_controllen
= msg_ctrllen_left
;
7438 msg
.msg_control
= NULL
;
7439 msg
.msg_controllen
= 0;
7444 * We convert the unix address to a IP address so we need a buffer
7445 * which can store the address in case of SOCK_DGRAM, see below.
7447 msg
.msg_name
= &convert_addr
.sa
;
7448 msg
.msg_namelen
= convert_addr
.sa_socklen
;
7450 rc
= swrap_recvmsg_after(s
,
7454 from_addr
.sa_socklen
,
7460 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7461 if (omsg
->msg_control
!= NULL
) {
7462 /* msg.msg_controllen = space left */
7463 msg_ctrllen_left
= msg
.msg_controllen
;
7464 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
7467 /* Update the original message length */
7468 omsg
->msg_controllen
= msg_ctrllen_filled
;
7469 omsg
->msg_flags
= msg
.msg_flags
;
7471 omsg
->msg_iovlen
= msg
.msg_iovlen
;
7478 * The msg_name field points to a caller-allocated buffer that is
7479 * used to return the source address if the socket is unconnected. The
7480 * caller should set msg_namelen to the size of this buffer before this
7481 * call; upon return from a successful call, msg_name will contain the
7482 * length of the returned address. If the application does not need
7483 * to know the source address, msg_name can be specified as NULL.
7485 if (si
->type
== SOCK_STREAM
) {
7486 omsg
->msg_namelen
= 0;
7487 } else if (omsg
->msg_name
!= NULL
&&
7488 omsg
->msg_namelen
!= 0 &&
7489 omsg
->msg_namelen
>= msg
.msg_namelen
) {
7490 memcpy(omsg
->msg_name
, msg
.msg_name
, msg
.msg_namelen
);
7491 omsg
->msg_namelen
= msg
.msg_namelen
;
7494 SWRAP_UNLOCK_SI(si
);
7499 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
7501 return swrap_recvmsg(sockfd
, msg
, flags
);
7504 /****************************************************************************
7506 ***************************************************************************/
7508 #ifdef HAVE_RECVMMSG
7509 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7511 static ssize_t
swrap_recvmmsg(int s
, struct mmsghdr
*omsgvec
, size_t _vlen
, int flags
, const struct timespec
*timeout
)
7512 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7513 /* Linux legacy glibc < 2.21 */
7514 static int swrap_recvmmsg(int s
, struct mmsghdr
*omsgvec
, unsigned int _vlen
, int flags
, const struct timespec
*timeout
)
7516 /* Linux glibc >= 2.21 */
7517 static int swrap_recvmmsg(int s
, struct mmsghdr
*omsgvec
, unsigned int _vlen
, int flags
, struct timespec
*timeout
)
7520 struct socket_info
*si
= find_socket_info(s
);
7521 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7522 struct mmsghdr msgvec
[__SWRAP_RECVMMSG_MAX_VLEN
] = {};
7525 struct swrap_address from_addr
;
7526 struct swrap_address convert_addr
;
7527 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7528 size_t msg_ctrllen_filled
;
7529 size_t msg_ctrllen_left
;
7531 } tmp
[__SWRAP_RECVMMSG_MAX_VLEN
] = {};
7538 if (_vlen
> __SWRAP_RECVMMSG_MAX_VLEN
) {
7539 vlen
= __SWRAP_RECVMMSG_MAX_VLEN
;
7545 uint8_t *tmp_control
[__SWRAP_RECVMMSG_MAX_VLEN
] = { NULL
, };
7547 for (i
= 0; i
< vlen
; i
++) {
7548 struct msghdr
*omsg
= &omsgvec
[i
].msg_hdr
;
7549 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7551 rc
= swrap_recvmsg_before_unix(omsg
, msg
,
7559 ret
= libc_recvmmsg(s
, msgvec
, vlen
, flags
, timeout
);
7564 for (i
= 0; i
< ret
; i
++) {
7565 omsgvec
[i
].msg_len
= msgvec
[i
].msg_len
;
7569 saved_errno
= errno
;
7570 for (i
= 0; i
< vlen
; i
++) {
7571 struct msghdr
*omsg
= &omsgvec
[i
].msg_hdr
;
7572 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7574 if (i
== 0 || i
< ret
) {
7575 swrap_recvmsg_after_unix(msg
, &tmp_control
[i
], omsg
, ret
);
7577 SAFE_FREE(tmp_control
[i
]);
7579 errno
= saved_errno
;
7584 for (i
= 0; i
< vlen
; i
++) {
7585 struct msghdr
*omsg
= &omsgvec
[i
].msg_hdr
;
7586 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7588 tmp
[i
].from_addr
.sa_socklen
= sizeof(struct sockaddr_un
);
7589 tmp
[i
].convert_addr
.sa_socklen
= sizeof(struct sockaddr_storage
);
7591 msg
->msg_name
= &tmp
[i
].from_addr
.sa
; /* optional address */
7592 msg
->msg_namelen
= tmp
[i
].from_addr
.sa_socklen
; /* size of address */
7593 msg
->msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
7594 msg
->msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
7595 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7596 tmp
[i
].msg_ctrllen_filled
= 0;
7597 tmp
[i
].msg_ctrllen_left
= omsg
->msg_controllen
;
7599 msg
->msg_control
= omsg
->msg_control
; /* ancillary data, see below */
7600 msg
->msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
7601 msg
->msg_flags
= omsg
->msg_flags
; /* flags on received message */
7604 rc
= swrap_recvmsg_before(s
, si
, msg
, &tmp
[i
].iov
);
7611 ret
= libc_recvmmsg(s
, msgvec
, vlen
, flags
, timeout
);
7616 for (i
= 0; i
< ret
; i
++) {
7617 omsgvec
[i
].msg_len
= msgvec
[i
].msg_len
;
7622 saved_errno
= errno
;
7623 for (i
= 0; i
< vlen
; i
++) {
7624 struct msghdr
*omsg
= &omsgvec
[i
].msg_hdr
;
7625 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7627 if (!(i
== 0 || i
< ret
)) {
7631 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7632 tmp
[i
].msg_ctrllen_filled
+= msg
->msg_controllen
;
7633 tmp
[i
].msg_ctrllen_left
-= msg
->msg_controllen
;
7635 if (omsg
->msg_control
!= NULL
) {
7638 p
= omsg
->msg_control
;
7639 p
+= tmp
[i
].msg_ctrllen_filled
;
7641 msg
->msg_control
= p
;
7642 msg
->msg_controllen
= tmp
[i
].msg_ctrllen_left
;
7644 msg
->msg_control
= NULL
;
7645 msg
->msg_controllen
= 0;
7650 * We convert the unix address to a IP address so we need a buffer
7651 * which can store the address in case of SOCK_DGRAM, see below.
7653 msg
->msg_name
= &tmp
[i
].convert_addr
.sa
;
7654 msg
->msg_namelen
= tmp
[i
].convert_addr
.sa_socklen
;
7656 swrap_recvmsg_after(s
, si
, msg
,
7657 &tmp
[i
].from_addr
.sa
.un
,
7658 tmp
[i
].from_addr
.sa_socklen
,
7661 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7662 if (omsg
->msg_control
!= NULL
) {
7663 /* msg->msg_controllen = space left */
7664 tmp
[i
].msg_ctrllen_left
= msg
->msg_controllen
;
7665 tmp
[i
].msg_ctrllen_filled
= omsg
->msg_controllen
- tmp
[i
].msg_ctrllen_left
;
7668 /* Update the original message length */
7669 omsg
->msg_controllen
= tmp
[i
].msg_ctrllen_filled
;
7670 omsg
->msg_flags
= msg
->msg_flags
;
7672 omsg
->msg_iovlen
= msg
->msg_iovlen
;
7679 * The msg_name field points to a caller-allocated buffer that is
7680 * used to return the source address if the socket is unconnected. The
7681 * caller should set msg_namelen to the size of this buffer before this
7682 * call; upon return from a successful call, msg_name will contain the
7683 * length of the returned address. If the application does not need
7684 * to know the source address, msg_name can be specified as NULL.
7686 if (si
->type
== SOCK_STREAM
) {
7687 omsg
->msg_namelen
= 0;
7688 } else if (omsg
->msg_name
!= NULL
&&
7689 omsg
->msg_namelen
!= 0 &&
7690 omsg
->msg_namelen
>= msg
->msg_namelen
) {
7691 memcpy(omsg
->msg_name
, msg
->msg_name
, msg
->msg_namelen
);
7692 omsg
->msg_namelen
= msg
->msg_namelen
;
7695 SWRAP_UNLOCK_SI(si
);
7697 errno
= saved_errno
;
7702 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7704 ssize_t
recvmmsg(int sockfd
, struct mmsghdr
*msgvec
, size_t vlen
, int flags
, const struct timespec
*timeout
)
7705 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7706 /* Linux legacy glibc < 2.21 */
7707 int recvmmsg(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
, const struct timespec
*timeout
)
7709 /* Linux glibc >= 2.21 */
7710 int recvmmsg(int sockfd
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
, struct timespec
*timeout
)
7713 return swrap_recvmmsg(sockfd
, msgvec
, vlen
, flags
, timeout
);
7715 #endif /* HAVE_RECVMMSG */
7717 /****************************************************************************
7719 ***************************************************************************/
7721 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
7725 struct sockaddr_un un_addr
;
7726 const struct sockaddr_un
*to_un
= NULL
;
7727 const struct sockaddr
*to
= NULL
;
7730 struct socket_info
*si
= find_socket_info(s
);
7734 int scm_rights_pipe_fd
= -1;
7736 rc
= swrap_sendmsg_before_unix(omsg
, &msg
,
7737 &scm_rights_pipe_fd
);
7741 ret
= libc_sendmsg(s
, &msg
, flags
);
7742 return swrap_sendmsg_after_unix(&msg
, ret
, scm_rights_pipe_fd
);
7745 ZERO_STRUCT(un_addr
);
7747 tmp
.iov_base
= NULL
;
7754 if (si
->connected
== 0) {
7755 msg
.msg_name
= omsg
->msg_name
; /* optional address */
7756 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
7758 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
7759 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
7761 SWRAP_UNLOCK_SI(si
);
7763 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7764 if (omsg
!= NULL
&& omsg
->msg_controllen
> 0 && omsg
->msg_control
!= NULL
) {
7765 uint8_t *cmbuf
= NULL
;
7768 rc
= swrap_sendmsg_filter_cmsghdr(omsg
, &cmbuf
, &cmlen
);
7774 msg
.msg_controllen
= 0;
7775 msg
.msg_control
= NULL
;
7777 msg
.msg_control
= cmbuf
;
7778 msg
.msg_controllen
= cmlen
;
7781 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
7783 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
7785 int saved_errno
= errno
;
7786 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7787 SAFE_FREE(msg
.msg_control
);
7789 errno
= saved_errno
;
7796 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
7803 char *swrap_dir
= NULL
;
7805 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
7806 avail
+= msg
.msg_iov
[i
].iov_len
;
7812 /* we capture it as one single packet */
7813 buf
= (uint8_t *)malloc(remain
);
7815 int saved_errno
= errno
;
7816 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7817 SAFE_FREE(msg
.msg_control
);
7819 errno
= saved_errno
;
7823 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
7824 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
7826 msg
.msg_iov
[i
].iov_base
,
7829 remain
-= this_time
;
7832 type
= SOCKET_TYPE_CHAR_UDP
;
7834 swrap_dir
= socket_wrapper_dir();
7835 if (swrap_dir
== NULL
) {
7836 int saved_errno
= errno
;
7837 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7838 SAFE_FREE(msg
.msg_control
);
7841 errno
= saved_errno
;
7845 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
7846 swrap_un_path(&un_addr
, swrap_dir
, type
, iface
, prt
);
7847 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
7849 msg
.msg_name
= &un_addr
; /* optional address */
7850 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
7852 /* ignore the any errors in broadcast sends */
7853 libc_sendmsg(s
, &msg
, flags
);
7856 SAFE_FREE(swrap_dir
);
7860 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
7863 SWRAP_UNLOCK_SI(si
);
7868 ret
= libc_sendmsg(s
, &msg
, flags
);
7870 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
7872 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7874 int saved_errno
= errno
;
7875 SAFE_FREE(msg
.msg_control
);
7876 errno
= saved_errno
;
7883 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
7885 return swrap_sendmsg(s
, omsg
, flags
);
7888 /****************************************************************************
7890 ***************************************************************************/
7892 #ifdef HAVE_SENDMMSG
7893 #if defined(HAVE_SENDMMSG_SSIZE_T)
7895 static ssize_t
swrap_sendmmsg(int s
, struct mmsghdr
*omsgvec
, size_t _vlen
, int flags
)
7898 static int swrap_sendmmsg(int s
, struct mmsghdr
*omsgvec
, unsigned int _vlen
, int flags
)
7901 struct socket_info
*si
= find_socket_info(s
);
7902 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7903 struct mmsghdr msgvec
[__SWRAP_SENDMMSG_MAX_VLEN
] = {};
7906 struct sockaddr_un un_addr
;
7907 const struct sockaddr_un
*to_un
;
7908 const struct sockaddr
*to
;
7910 } tmp
[__SWRAP_SENDMMSG_MAX_VLEN
] = {};
7913 char *swrap_dir
= NULL
;
7915 int found_bcast
= 0;
7920 if (_vlen
> __SWRAP_SENDMMSG_MAX_VLEN
) {
7921 vlen
= __SWRAP_SENDMMSG_MAX_VLEN
;
7927 int scm_rights_pipe_fd
[__SWRAP_SENDMMSG_MAX_VLEN
];
7929 for (i
= 0; i
< __SWRAP_SENDMMSG_MAX_VLEN
; i
++) {
7930 scm_rights_pipe_fd
[i
] = -1;
7933 for (i
= 0; i
< vlen
; i
++) {
7934 struct msghdr
*omsg
= &omsgvec
[i
].msg_hdr
;
7935 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7937 rc
= swrap_sendmsg_before_unix(omsg
, msg
,
7938 &scm_rights_pipe_fd
[i
]);
7945 ret
= libc_sendmmsg(s
, msgvec
, vlen
, flags
);
7950 for (i
= 0; i
< ret
; i
++) {
7951 omsgvec
[i
].msg_len
= msgvec
[i
].msg_len
;
7955 saved_errno
= errno
;
7956 for (i
= 0; i
< vlen
; i
++) {
7957 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7959 swrap_sendmsg_after_unix(msg
, ret
,
7960 scm_rights_pipe_fd
[i
]);
7962 errno
= saved_errno
;
7968 connected
= si
->connected
;
7969 SWRAP_UNLOCK_SI(si
);
7971 for (i
= 0; i
< vlen
; i
++) {
7972 struct msghdr
*omsg
= &omsgvec
[i
].msg_hdr
;
7973 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
7975 if (connected
== 0) {
7976 msg
->msg_name
= omsg
->msg_name
; /* optional address */
7977 msg
->msg_namelen
= omsg
->msg_namelen
; /* size of address */
7979 msg
->msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
7980 msg
->msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
7982 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7983 if (omsg
->msg_controllen
> 0 && omsg
->msg_control
!= NULL
) {
7984 uint8_t *cmbuf
= NULL
;
7987 rc
= swrap_sendmsg_filter_cmsghdr(omsg
, &cmbuf
, &cmlen
);
7994 msg
->msg_control
= cmbuf
;
7995 msg
->msg_controllen
= cmlen
;
7998 msg
->msg_flags
= omsg
->msg_flags
; /* flags on received message */
8001 rc
= swrap_sendmsg_before(s
, si
, msg
,
8019 swrap_dir
= socket_wrapper_dir();
8020 if (swrap_dir
== NULL
) {
8025 for (i
= 0; i
< vlen
; i
++) {
8026 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
8027 struct sockaddr_un
*un_addr
= &tmp
[i
].un_addr
;
8028 const struct sockaddr
*to
= tmp
[i
].to
;
8031 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
8039 for (l
= 0; l
< (size_t)msg
->msg_iovlen
; l
++) {
8040 avail
+= msg
->msg_iov
[l
].iov_len
;
8046 /* we capture it as one single packet */
8047 buf
= (uint8_t *)malloc(remain
);
8053 for (l
= 0; l
< (size_t)msg
->msg_iovlen
; l
++) {
8054 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[l
].iov_len
);
8056 msg
->msg_iov
[l
].iov_base
,
8059 remain
-= this_time
;
8062 type
= SOCKET_TYPE_CHAR_UDP
;
8064 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
8065 swrap_un_path(un_addr
, swrap_dir
, type
, iface
, prt
);
8066 if (stat(un_addr
->sun_path
, &st
) != 0) continue;
8068 msg
->msg_name
= un_addr
; /* optional address */
8069 msg
->msg_namelen
= sizeof(*un_addr
); /* size of address */
8072 * ignore the any errors in broadcast sends and
8073 * do a single sendmsg instead of sendmmsg
8075 libc_sendmsg(s
, msg
, flags
);
8079 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
8080 SWRAP_UNLOCK_SI(si
);
8084 msgvec
[i
].msg_len
= len
;
8091 ret
= libc_sendmmsg(s
, msgvec
, vlen
, flags
);
8097 for (i
= 0; i
< ret
; i
++) {
8098 omsgvec
[i
].msg_len
= msgvec
[i
].msg_len
;
8102 saved_errno
= errno
;
8103 for (i
= 0; i
< vlen
; i
++) {
8104 struct msghdr
*msg
= &msgvec
[i
].msg_hdr
;
8106 if (i
== 0 || i
< ret
) {
8107 swrap_sendmsg_after(s
, si
, msg
, tmp
[i
].to
, ret
);
8109 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8110 SAFE_FREE(msg
->msg_control
);
8113 SAFE_FREE(swrap_dir
);
8114 errno
= saved_errno
;
8119 #if defined(HAVE_SENDMMSG_SSIZE_T)
8121 ssize_t
sendmmsg(int s
, struct mmsghdr
*msgvec
, size_t vlen
, int flags
)
8124 int sendmmsg(int s
, struct mmsghdr
*msgvec
, unsigned int vlen
, int flags
)
8127 return swrap_sendmmsg(s
, msgvec
, vlen
, flags
);
8129 #endif /* HAVE_SENDMMSG */
8131 /****************************************************************************
8133 ***************************************************************************/
8135 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
8137 struct socket_info
*si
;
8140 struct swrap_address saddr
= {
8141 .sa_socklen
= sizeof(struct sockaddr_storage
)
8146 si
= find_socket_info(s
);
8148 return libc_readv(s
, vector
, count
);
8151 tmp
.iov_base
= NULL
;
8155 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
8156 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
8157 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
8158 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
8159 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8160 msg
.msg_control
= NULL
; /* ancillary data, see below */
8161 msg
.msg_controllen
= 0; /* ancillary data buffer len */
8162 msg
.msg_flags
= 0; /* flags on received message */
8165 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
8167 if (rc
== -ENOTSOCK
) {
8168 return libc_readv(s
, vector
, count
);
8173 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
8175 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
8183 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
8185 return swrap_readv(s
, vector
, count
);
8188 /****************************************************************************
8190 ***************************************************************************/
8192 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
8196 struct sockaddr_un un_addr
;
8199 struct socket_info
*si
= find_socket_info(s
);
8202 return libc_writev(s
, vector
, count
);
8205 tmp
.iov_base
= NULL
;
8209 msg
.msg_name
= NULL
; /* optional address */
8210 msg
.msg_namelen
= 0; /* size of address */
8211 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
8212 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
8213 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8214 msg
.msg_control
= NULL
; /* ancillary data, see below */
8215 msg
.msg_controllen
= 0; /* ancillary data buffer len */
8216 msg
.msg_flags
= 0; /* flags on received message */
8219 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
8221 if (rc
== -ENOTSOCK
) {
8222 return libc_readv(s
, vector
, count
);
8227 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
8229 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
8234 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
8236 return swrap_writev(s
, vector
, count
);
8239 /****************************
8241 ***************************/
8243 static int swrap_remove_wrapper(const char *__func_name
,
8244 int (*__close_fd_fn
)(int fd
),
8247 struct socket_info
*si
= NULL
;
8249 int ret_errno
= errno
;
8252 swrap_mutex_lock(&socket_reset_mutex
);
8254 si_index
= find_socket_info_index(fd
);
8255 if (si_index
== -1) {
8256 swrap_mutex_unlock(&socket_reset_mutex
);
8257 return __close_fd_fn(fd
);
8260 swrap_log(SWRAP_LOG_TRACE
, __func_name
, "Remove wrapper for fd=%d", fd
);
8261 reset_socket_info_index(fd
);
8263 si
= swrap_get_socket_info(si_index
);
8265 swrap_mutex_lock(&first_free_mutex
);
8268 ret
= __close_fd_fn(fd
);
8273 swrap_dec_refcount(si
);
8275 if (swrap_get_refcount(si
) > 0) {
8276 /* there are still references left */
8280 if (si
->fd_passed
) {
8284 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
8285 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
8288 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
8289 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
8290 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
8293 if (si
->un_addr
.sun_path
[0] != '\0') {
8294 unlink(si
->un_addr
.sun_path
);
8298 swrap_set_next_free(si
, first_free
);
8299 first_free
= si_index
;
8302 SWRAP_UNLOCK_SI(si
);
8303 swrap_mutex_unlock(&first_free_mutex
);
8304 swrap_mutex_unlock(&socket_reset_mutex
);
8310 static int swrap_noop_close(int fd
)
8312 (void)fd
; /* unused */
8316 static void swrap_remove_stale(int fd
)
8318 swrap_remove_wrapper(__func__
, swrap_noop_close
, fd
);
8322 * This allows socket_wrapper aware applications to
8323 * indicate that the given fd does not belong to
8326 * We already overload a lot of unrelated functions
8327 * like eventfd(), timerfd_create(), ... in order to
8328 * call swrap_remove_stale() on the returned fd, but
8329 * we'll never be able to handle all possible syscalls.
8331 * socket_wrapper_indicate_no_inet_fd() gives them a way
8334 * We don't export swrap_remove_stale() in order to
8335 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8338 void socket_wrapper_indicate_no_inet_fd(int fd
)
8340 swrap_remove_wrapper(__func__
, swrap_noop_close
, fd
);
8343 static int swrap_close(int fd
)
8345 return swrap_remove_wrapper(__func__
, libc_close
, fd
);
8350 return swrap_close(fd
);
8353 #ifdef HAVE___CLOSE_NOCANCEL
8355 static int swrap___close_nocancel(int fd
)
8357 return swrap_remove_wrapper(__func__
, libc___close_nocancel
, fd
);
8360 int __close_nocancel(int fd
);
8361 int __close_nocancel(int fd
)
8363 return swrap___close_nocancel(fd
);
8366 #endif /* HAVE___CLOSE_NOCANCEL */
8368 /****************************
8370 ***************************/
8372 static int swrap_dup(int fd
)
8374 struct socket_info
*si
;
8377 idx
= find_socket_info_index(fd
);
8379 return libc_dup(fd
);
8382 si
= swrap_get_socket_info(idx
);
8384 dup_fd
= libc_dup(fd
);
8386 int saved_errno
= errno
;
8387 errno
= saved_errno
;
8391 if ((size_t)dup_fd
>= socket_fds_max
) {
8392 SWRAP_LOG(SWRAP_LOG_ERROR
,
8393 "The max socket index limit of %zu has been reached, "
8404 swrap_inc_refcount(si
);
8406 SWRAP_UNLOCK_SI(si
);
8408 /* Make sure we don't have an entry for the fd */
8409 swrap_remove_stale(dup_fd
);
8411 set_socket_info_index(dup_fd
, idx
);
8418 return swrap_dup(fd
);
8421 /****************************
8423 ***************************/
8425 static int swrap_dup2(int fd
, int newfd
)
8427 struct socket_info
*si
;
8430 idx
= find_socket_info_index(fd
);
8432 return libc_dup2(fd
, newfd
);
8435 si
= swrap_get_socket_info(idx
);
8439 * According to the manpage:
8441 * "If oldfd is a valid file descriptor, and newfd has the same
8442 * value as oldfd, then dup2() does nothing, and returns newfd."
8447 if ((size_t)newfd
>= socket_fds_max
) {
8448 SWRAP_LOG(SWRAP_LOG_ERROR
,
8449 "The max socket index limit of %zu has been reached, "
8457 if (find_socket_info(newfd
)) {
8458 /* dup2() does an implicit close of newfd, which we
8459 * need to emulate */
8463 dup_fd
= libc_dup2(fd
, newfd
);
8465 int saved_errno
= errno
;
8466 errno
= saved_errno
;
8472 swrap_inc_refcount(si
);
8474 SWRAP_UNLOCK_SI(si
);
8476 /* Make sure we don't have an entry for the fd */
8477 swrap_remove_stale(dup_fd
);
8479 set_socket_info_index(dup_fd
, idx
);
8484 int dup2(int fd
, int newfd
)
8486 return swrap_dup2(fd
, newfd
);
8489 /****************************
8491 ***************************/
8493 static int swrap_vfcntl(int fd
, int cmd
, va_list va
)
8495 struct socket_info
*si
;
8496 int rc
, dup_fd
, idx
;
8498 idx
= find_socket_info_index(fd
);
8500 return libc_vfcntl(fd
, cmd
, va
);
8503 si
= swrap_get_socket_info(idx
);
8507 dup_fd
= libc_vfcntl(fd
, cmd
, va
);
8509 int saved_errno
= errno
;
8510 errno
= saved_errno
;
8514 /* Make sure we don't have an entry for the fd */
8515 swrap_remove_stale(dup_fd
);
8517 if ((size_t)dup_fd
>= socket_fds_max
) {
8518 SWRAP_LOG(SWRAP_LOG_ERROR
,
8519 "The max socket index limit of %zu has been reached, "
8530 swrap_inc_refcount(si
);
8532 SWRAP_UNLOCK_SI(si
);
8535 set_socket_info_index(dup_fd
, idx
);
8540 rc
= libc_vfcntl(fd
, cmd
, va
);
8547 #undef fcntl /* Needed for LFS handling */
8548 int fcntl(int fd
, int cmd
, ...)
8555 rc
= swrap_vfcntl(fd
, cmd
, va
);
8562 /****************************
8564 ***************************/
8567 static int swrap_vfcntl64(int fd
, int cmd
, va_list va
)
8569 struct socket_info
*si
;
8570 int rc
, dup_fd
, idx
;
8572 idx
= find_socket_info_index(fd
);
8574 return libc_vfcntl64(fd
, cmd
, va
);
8577 si
= swrap_get_socket_info(idx
);
8581 dup_fd
= libc_vfcntl64(fd
, cmd
, va
);
8583 int saved_errno
= errno
;
8584 errno
= saved_errno
;
8588 /* Make sure we don't have an entry for the fd */
8589 swrap_remove_stale(dup_fd
);
8591 if ((size_t)dup_fd
>= socket_fds_max
) {
8592 SWRAP_LOG(SWRAP_LOG_ERROR
,
8593 "The max socket index limit of %zu has been reached, "
8604 swrap_inc_refcount(si
);
8606 SWRAP_UNLOCK_SI(si
);
8609 set_socket_info_index(dup_fd
, idx
);
8614 rc
= libc_vfcntl64(fd
, cmd
, va
);
8621 int fcntl64(int fd
, int cmd
, ...)
8628 rc
= swrap_vfcntl64(fd
, cmd
, va
);
8636 /****************************
8638 ***************************/
8641 static int swrap_eventfd(int count
, int flags
)
8645 fd
= libc_eventfd(count
, flags
);
8647 swrap_remove_stale(fd
);
8653 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8654 int eventfd(unsigned int count
, int flags
)
8656 int eventfd(int count
, int flags
)
8659 return swrap_eventfd(count
, flags
);
8664 int pledge(const char *promises
, const char *paths
[])
8666 (void)promises
; /* unused */
8667 (void)paths
; /* unused */
8671 #endif /* HAVE_PLEDGE */
8674 static bool swrap_is_swrap_related_syscall(long int sysno
)
8680 #endif /* SYS_close */
8685 #endif /* SYS_recvmmsg */
8690 #endif /* SYS_sendmmsg */
8697 static long int swrap_syscall(long int sysno
, va_list vp
)
8705 int fd
= (int)va_arg(vp
, int);
8707 SWRAP_LOG(SWRAP_LOG_TRACE
,
8708 "calling swrap_close syscall %lu",
8710 rc
= swrap_close(fd
);
8713 #endif /* SYS_close */
8718 int fd
= (int)va_arg(vp
, int);
8719 struct mmsghdr
*msgvec
= va_arg(vp
, struct mmsghdr
*);
8720 unsigned int vlen
= va_arg(vp
, unsigned int);
8721 int flags
= va_arg(vp
, int);
8722 struct timespec
*timeout
= va_arg(vp
, struct timespec
*);
8724 SWRAP_LOG(SWRAP_LOG_TRACE
,
8725 "calling swrap_recvmmsg syscall %lu",
8727 rc
= swrap_recvmmsg(fd
, msgvec
, vlen
, flags
, timeout
);
8730 #endif /* SYS_recvmmsg */
8735 int fd
= (int)va_arg(vp
, int);
8736 struct mmsghdr
*msgvec
= va_arg(vp
, struct mmsghdr
*);
8737 unsigned int vlen
= va_arg(vp
, unsigned int);
8738 int flags
= va_arg(vp
, int);
8740 SWRAP_LOG(SWRAP_LOG_TRACE
,
8741 "calling swrap_sendmmsg syscall %lu",
8743 rc
= swrap_sendmmsg(fd
, msgvec
, vlen
, flags
);
8746 #endif /* SYS_sendmmsg */
8757 #ifdef HAVE_SYSCALL_INT
8758 int syscall(int sysno
, ...)
8760 long int syscall(long int sysno
, ...)
8763 #ifdef HAVE_SYSCALL_INT
8770 va_start(va
, sysno
);
8775 * This is a workaround to prevent a deadlock in jemalloc calling
8776 * malloc_init() twice. The first allocation call will trigger a
8777 * malloc_init() of jemalloc. The functions calls syscall(SYS_open, ...)
8778 * so it goes to socket or uid wrapper. In this code path we need to
8779 * avoid any allocation calls. This will prevent the deadlock.
8781 if (!swrap_handle_syscall
) {
8782 rc
= libc_vsyscall(sysno
, va
);
8788 * We should only handle the syscall numbers
8791 if (!swrap_is_swrap_related_syscall(sysno
)) {
8793 * We need to give socket_wrapper a
8794 * chance to take over...
8796 if (swrap_uwrap_syscall_valid(sysno
)) {
8797 rc
= swrap_uwrap_syscall_va(sysno
, va
);
8802 rc
= libc_vsyscall(sysno
, va
);
8807 if (!socket_wrapper_enabled()) {
8808 rc
= libc_vsyscall(sysno
, va
);
8813 rc
= swrap_syscall(sysno
, va
);
8819 /* used by uid_wrapper */
8820 bool socket_wrapper_syscall_valid(long int sysno
);
8821 bool socket_wrapper_syscall_valid(long int sysno
)
8823 if (!swrap_is_swrap_related_syscall(sysno
)) {
8827 if (!socket_wrapper_enabled()) {
8834 /* used by uid_wrapper */
8835 long int socket_wrapper_syscall_va(long int sysno
, va_list va
);
8836 long int socket_wrapper_syscall_va(long int sysno
, va_list va
)
8838 if (!swrap_is_swrap_related_syscall(sysno
)) {
8843 if (!socket_wrapper_enabled()) {
8844 return libc_vsyscall(sysno
, va
);
8847 return swrap_syscall(sysno
, va
);
8849 #endif /* HAVE_SYSCALL */
8851 static void swrap_thread_prepare(void)
8854 * This function should only be called here!!
8856 * We bind all symobls to avoid deadlocks of the fork is
8857 * interrupted by a signal handler using a symbol of this
8860 swrap_bind_symbol_all();
8865 static void swrap_thread_parent(void)
8870 static void swrap_thread_child(void)
8875 /****************************
8877 ***************************/
8878 void swrap_constructor(void)
8880 if (PIPE_BUF
< sizeof(struct swrap_unix_scm_rights
)) {
8881 SWRAP_LOG(SWRAP_LOG_ERROR
,
8883 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8884 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8885 "sizeof(struct socket_info)=%zu",
8887 sizeof(struct swrap_unix_scm_rights
),
8888 sizeof(struct swrap_unix_scm_rights_payload
),
8889 sizeof(struct socket_info
));
8896 * If we hold a lock and the application forks, then the child
8897 * is not able to unlock the mutex and we are in a deadlock.
8898 * This should prevent such deadlocks.
8900 pthread_atfork(&swrap_thread_prepare
,
8901 &swrap_thread_parent
,
8902 &swrap_thread_child
);
8904 /* Let socket_wrapper handle syscall() */
8905 swrap_handle_syscall
= true;
8908 /****************************
8910 ***************************/
8913 * This function is called when the library is unloaded and makes sure that
8914 * sockets get closed and the unix file for the socket are unlinked.
8916 void swrap_destructor(void)
8920 if (socket_fds_idx
!= NULL
) {
8921 for (i
= 0; i
< socket_fds_max
; ++i
) {
8922 if (socket_fds_idx
[i
] != -1) {
8926 SAFE_FREE(socket_fds_idx
);
8931 if (swrap
.libc
.handle
!= NULL
8933 && swrap
.libc
.handle
!= RTLD_NEXT
8936 dlclose(swrap
.libc
.handle
);
8938 if (swrap
.libc
.socket_handle
8940 && swrap
.libc
.socket_handle
!= RTLD_NEXT
8943 dlclose(swrap
.libc
.socket_handle
);
8947 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8949 * On FreeBSD 12 (and maybe other platforms)
8950 * system libraries like libresolv prefix there
8951 * syscalls with '_' in order to always use
8952 * the symbols from libc.
8954 * In the interaction with resolv_wrapper,
8955 * we need to inject socket wrapper into libresolv,
8956 * which means we need to private all socket
8957 * related syscalls also with the '_' prefix.
8959 * This is tested in Samba's 'make test',
8960 * there we noticed that providing '_read',
8961 * '_open' and '_close' would cause errors, which
8962 * means we skip '_read', '_write' and
8963 * all non socket related calls without
8964 * further analyzing the problem.
8966 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8967 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8970 SWRAP_SYMBOL_ALIAS(accept4
, _accept4
);
8972 SWRAP_SYMBOL_ALIAS(accept
, _accept
);
8973 SWRAP_SYMBOL_ALIAS(bind
, _bind
);
8974 SWRAP_SYMBOL_ALIAS(connect
, _connect
);
8975 SWRAP_SYMBOL_ALIAS(dup
, _dup
);
8976 SWRAP_SYMBOL_ALIAS(dup2
, _dup2
);
8977 SWRAP_SYMBOL_ALIAS(fcntl
, _fcntl
);
8978 SWRAP_SYMBOL_ALIAS(getpeername
, _getpeername
);
8979 SWRAP_SYMBOL_ALIAS(getsockname
, _getsockname
);
8980 SWRAP_SYMBOL_ALIAS(getsockopt
, _getsockopt
);
8981 SWRAP_SYMBOL_ALIAS(ioctl
, _ioctl
);
8982 SWRAP_SYMBOL_ALIAS(listen
, _listen
);
8983 SWRAP_SYMBOL_ALIAS(readv
, _readv
);
8984 SWRAP_SYMBOL_ALIAS(recv
, _recv
);
8985 SWRAP_SYMBOL_ALIAS(recvfrom
, _recvfrom
);
8986 SWRAP_SYMBOL_ALIAS(recvmsg
, _recvmsg
);
8987 SWRAP_SYMBOL_ALIAS(send
, _send
);
8988 SWRAP_SYMBOL_ALIAS(sendmsg
, _sendmsg
);
8989 SWRAP_SYMBOL_ALIAS(sendto
, _sendto
);
8990 SWRAP_SYMBOL_ALIAS(setsockopt
, _setsockopt
);
8991 SWRAP_SYMBOL_ALIAS(socket
, _socket
);
8992 SWRAP_SYMBOL_ALIAS(socketpair
, _socketpair
);
8993 SWRAP_SYMBOL_ALIAS(writev
, _writev
);
8995 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */