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);
1392 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1393 static long int libc_vsyscall(long int sysno, va_list va)
1399 swrap_bind_symbol_all();
1401 for (i = 0; i < 8; i++) {
1402 args[i] = va_arg(va, long int);
1405 rc = swrap.libc.symbols._libc_syscall.f(sysno,
1418 static bool swrap_uwrap_syscall_valid(long int sysno)
1420 swrap_bind_symbol_all();
1422 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f == NULL) {
1426 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f(
1430 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1431 static long int swrap_uwrap_syscall_va(long int sysno, va_list va)
1433 swrap_bind_symbol_all();
1435 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f == NULL) {
1437 * Fallback to libc, if uid_wrapper_syscall_va is not
1440 return libc_vsyscall(sysno, va);
1443 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f(
1447 #endif /* HAVE_SYSCALL */
1449 /* DO NOT call this function during library initialization! */
1450 static void __swrap_bind_symbol_all_once(void)
1453 swrap_bind_symbol_libsocket(accept4);
1455 swrap_bind_symbol_libsocket(accept);
1457 swrap_bind_symbol_libsocket(bind);
1458 swrap_bind_symbol_libc(close);
1459 #ifdef HAVE___CLOSE_NOCANCEL
1460 swrap_bind_symbol_libc(__close_nocancel);
1462 swrap_bind_symbol_libsocket(connect);
1463 swrap_bind_symbol_libc(dup);
1464 swrap_bind_symbol_libc(dup2);
1465 swrap_bind_symbol_libc(fcntl);
1467 swrap_bind_symbol_libc(fcntl64);
1469 swrap_bind_symbol_libc(fopen);
1471 swrap_bind_symbol_libc(fopen64);
1474 swrap_bind_symbol_libc(eventfd);
1476 swrap_bind_symbol_libsocket(getpeername);
1477 swrap_bind_symbol_libsocket(getsockname);
1478 swrap_bind_symbol_libsocket(getsockopt);
1479 swrap_bind_symbol_libc(ioctl);
1480 swrap_bind_symbol_libsocket(listen);
1481 swrap_bind_symbol_libc(open);
1483 swrap_bind_symbol_libc(open64);
1485 #ifdef HAVE_OPENAT64
1486 swrap_bind_symbol_libc(openat64);
1488 swrap_bind_symbol_libc(openat);
1489 swrap_bind_symbol_libsocket(pipe);
1490 swrap_bind_symbol_libc(read);
1491 swrap_bind_symbol_libsocket(readv);
1492 swrap_bind_symbol_libsocket(recv);
1493 swrap_bind_symbol_libsocket(recvfrom);
1494 swrap_bind_symbol_libsocket(recvmsg);
1495 #ifdef HAVE_RECVMMSG
1496 swrap_bind_symbol_libsocket(recvmmsg);
1498 swrap_bind_symbol_libsocket(send);
1499 swrap_bind_symbol_libsocket(sendmsg);
1500 #ifdef HAVE_SENDMMSG
1501 swrap_bind_symbol_libsocket(sendmmsg);
1503 swrap_bind_symbol_libsocket(sendto);
1504 swrap_bind_symbol_libsocket(setsockopt);
1505 #ifdef HAVE_SIGNALFD
1506 swrap_bind_symbol_libsocket(signalfd);
1508 swrap_bind_symbol_libsocket(socket);
1509 swrap_bind_symbol_libsocket(socketpair);
1510 #ifdef HAVE_TIMERFD_CREATE
1511 swrap_bind_symbol_libc(timerfd_create);
1513 swrap_bind_symbol_libc(write);
1514 swrap_bind_symbol_libsocket(writev);
1516 swrap_bind_symbol_libc(syscall);
1517 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
1518 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
1522 static void swrap_bind_symbol_all(void)
1524 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1526 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1529 /*********************************************************
1530 * SWRAP HELPER FUNCTIONS
1531 *********************************************************/
1534 * We return 127.0.0.0 (default) or 10.53.57.0.
1536 * This can be controlled by:
1537 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1539 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1541 static in_addr_t swrap_ipv4_net(void)
1543 static int initialized;
1544 static in_addr_t hv;
1545 const char *net_str = NULL;
1554 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1555 if (net_str == NULL) {
1556 net_str = "127.0.0.0";
1559 ret = inet_pton(AF_INET, net_str, &nv);
1561 SWRAP_LOG(SWRAP_LOG_ERROR,
1562 "INVALID IPv4 Network [%s]",
1567 hv = ntohl(nv.s_addr);
1577 SWRAP_LOG(SWRAP_LOG_ERROR,
1578 "INVALID IPv4 Network [%s][0x%x] should be "
1579 "127.0.0.0 or 10.53.57.0",
1580 net_str, (unsigned)hv);
1588 * This returns 127.255.255.255 or 10.255.255.255
1590 static in_addr_t swrap_ipv4_bcast(void)
1594 hv = swrap_ipv4_net();
1595 hv |= IN_CLASSA_HOST;
1601 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1603 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1607 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1608 SWRAP_LOG(SWRAP_LOG_ERROR,
1609 "swrap_ipv4_iface(%u) invalid!",
1615 hv = swrap_ipv4_net();
1625 static const struct in6_addr *swrap_ipv6(void)
1627 static struct in6_addr v;
1628 static int initialized;
1636 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1645 static void set_port(int family, int prt, struct swrap_address *addr)
1649 addr->sa.in.sin_port = htons(prt);
1653 addr->sa.in6.sin6_port = htons(prt);
1659 static size_t socket_length(int family)
1663 return sizeof(struct sockaddr_in);
1666 return sizeof(struct sockaddr_in6);
1672 struct swrap_sockaddr_buf {
1676 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1677 const struct sockaddr *saddr)
1679 unsigned int port = 0;
1680 char addr[64] = {0,};
1682 switch (saddr->sa_family) {
1684 const struct sockaddr_in *in =
1685 (const struct sockaddr_in *)(const void *)saddr;
1687 port = ntohs(in->sin_port);
1689 inet_ntop(saddr->sa_family,
1691 addr, sizeof(addr));
1696 const struct sockaddr_in6 *in6 =
1697 (const struct sockaddr_in6 *)(const void *)saddr;
1699 port = ntohs(in6->sin6_port);
1701 inet_ntop(saddr->sa_family,
1703 addr, sizeof(addr));
1708 snprintf(addr, sizeof(addr),
1709 "<Unknown address family %u>",
1714 snprintf(buf->str, sizeof(buf->str),
1715 "addr[%s]/port[%u]",
1721 static struct socket_info *swrap_get_socket_info(int si_index)
1723 return (struct socket_info *)(&(sockets[si_index].info));
1726 static int swrap_get_refcount(struct socket_info *si)
1728 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1729 return sic->meta.refcount;
1732 static void swrap_inc_refcount(struct socket_info *si)
1734 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1736 sic->meta.refcount += 1;
1739 static void swrap_dec_refcount(struct socket_info *si)
1741 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1743 sic->meta.refcount -= 1;
1746 static int swrap_get_next_free(struct socket_info *si)
1748 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1750 return sic->meta.next_free;
1753 static void swrap_set_next_free(struct socket_info *si, int next_free)
1755 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1757 sic->meta.next_free = next_free;
1760 static int swrap_un_path(struct sockaddr_un *un,
1761 const char *swrap_dir,
1768 ret = snprintf(un->sun_path,
1769 sizeof(un->sun_path),
1775 if ((size_t)ret >= sizeof(un->sun_path)) {
1776 return ENAMETOOLONG;
1782 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1783 const char *swrap_dir)
1787 ret = snprintf(un->sun_path,
1788 sizeof(un->sun_path),
1792 if ((size_t)ret >= sizeof(un->sun_path)) {
1793 return ENAMETOOLONG;
1799 static bool swrap_dir_usable(const char *swrap_dir)
1801 struct sockaddr_un un;
1804 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1809 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1817 static char *socket_wrapper_dir(void)
1819 char *swrap_dir = NULL;
1820 char *s = getenv("SOCKET_WRAPPER_DIR");
1824 if (s == NULL || s[0] == '\0') {
1825 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1829 swrap_dir = realpath(s, NULL);
1830 if (swrap_dir == NULL) {
1831 SWRAP_LOG(SWRAP_LOG_ERROR,
1832 "Unable to resolve socket_wrapper dir path: %s - %s",
1838 ok = swrap_dir_usable(swrap_dir);
1845 ok = swrap_dir_usable(s);
1847 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1851 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1853 SWRAP_LOG(SWRAP_LOG_ERROR,
1854 "realpath(SOCKET_WRAPPER_DIR) too long and "
1855 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1860 swrap_dir = strdup(s);
1861 if (swrap_dir == NULL) {
1862 SWRAP_LOG(SWRAP_LOG_ERROR,
1863 "Unable to duplicate socket_wrapper dir path");
1867 SWRAP_LOG(SWRAP_LOG_WARN,
1868 "realpath(SOCKET_WRAPPER_DIR) too long, "
1869 "using original SOCKET_WRAPPER_DIR\n");
1872 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1876 static unsigned int socket_wrapper_mtu(void)
1878 static unsigned int max_mtu = 0;
1883 swrap_mutex_lock(&mtu_update_mutex);
1889 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1891 s = getenv("SOCKET_WRAPPER_MTU");
1896 tmp = strtol(s, &endp, 10);
1901 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1907 swrap_mutex_unlock(&mtu_update_mutex);
1911 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1913 pthread_mutexattr_t ma;
1914 bool need_destroy = false;
1917 #define __CHECK(cmd) do { \
1920 SWRAP_LOG(SWRAP_LOG_ERROR, \
1921 "%s: %s - failed %d", \
1927 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1928 __CHECK(pthread_mutexattr_init(&ma));
1929 need_destroy = true;
1930 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1931 __CHECK(pthread_mutex_init(m, &ma));
1934 pthread_mutexattr_destroy(&ma);
1939 static size_t socket_wrapper_max_sockets(void)
1945 if (socket_info_max != 0) {
1946 return socket_info_max;
1949 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1951 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1952 if (s == NULL || s[0] == '\0') {
1956 tmp = strtoul(s, &endp, 10);
1961 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1962 SWRAP_LOG(SWRAP_LOG_ERROR,
1963 "Invalid number of sockets specified, "
1964 "using default (%zu)",
1968 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1969 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1970 SWRAP_LOG(SWRAP_LOG_ERROR,
1971 "Invalid number of sockets specified, "
1972 "using maximum (%zu).",
1976 socket_info_max = tmp;
1979 return socket_info_max;
1982 static void socket_wrapper_init_fds_idx(void)
1987 if (socket_fds_idx != NULL) {
1991 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1993 SWRAP_LOG(SWRAP_LOG_ERROR,
1994 "Failed to allocate socket fds index array: %s",
1999 for (i = 0; i < socket_fds_max; i++) {
2003 socket_fds_idx = tmp;
2006 static void socket_wrapper_init_sockets(void)
2012 swrap_bind_symbol_all();
2014 swrap_mutex_lock(&sockets_mutex);
2016 if (sockets != NULL) {
2017 swrap_mutex_unlock(&sockets_mutex);
2021 SWRAP_LOG(SWRAP_LOG_DEBUG,
2022 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
2023 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
2026 * Intialize the static cache early before
2027 * any thread is able to start.
2029 (void)swrap_ipv4_net();
2031 socket_wrapper_init_fds_idx();
2033 /* Needs to be called inside the sockets_mutex lock here. */
2034 max_sockets = socket_wrapper_max_sockets();
2036 sockets = (struct socket_info_container *)calloc(max_sockets,
2037 sizeof(struct socket_info_container));
2039 if (sockets == NULL) {
2040 SWRAP_LOG(SWRAP_LOG_ERROR,
2041 "Failed to allocate sockets array: %s",
2043 swrap_mutex_unlock(&sockets_mutex);
2047 swrap_mutex_lock(&first_free_mutex);
2048 swrap_mutex_lock(&sockets_si_global);
2052 for (i = 0; i < max_sockets; i++) {
2053 swrap_set_next_free(&sockets[i].info, i+1);
2056 /* mark the end of the free list */
2057 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
2059 swrap_mutex_unlock(&sockets_si_global);
2060 swrap_mutex_unlock(&first_free_mutex);
2061 swrap_mutex_unlock(&sockets_mutex);
2067 bool socket_wrapper_enabled(void)
2069 char *s = socket_wrapper_dir();
2077 socket_wrapper_init_sockets();
2082 static unsigned int socket_wrapper_default_iface(void)
2084 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
2087 if (sscanf(s, "%u", &iface) == 1) {
2088 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
2094 return 1;/* 127.0.0.1 */
2097 static void set_socket_info_index(int fd, int idx)
2099 SWRAP_LOG(SWRAP_LOG_TRACE,
2102 socket_fds_idx[fd] = idx;
2103 /* This builtin issues a full memory barrier. */
2104 __sync_synchronize();
2107 static void reset_socket_info_index(int fd)
2109 SWRAP_LOG(SWRAP_LOG_TRACE,
2112 set_socket_info_index(fd, -1);
2115 static int find_socket_info_index(int fd)
2121 if (socket_fds_idx == NULL) {
2125 if ((size_t)fd >= socket_fds_max) {
2127 * Do not add a log here as some applications do stupid things
2130 * for (fd = 0; fd <= getdtablesize(); fd++) {
2134 * This would produce millions of lines of debug messages.
2137 SWRAP_LOG(SWRAP_LOG_ERROR,
2138 "Looking for a socket info for the fd %d is over the "
2139 "max socket index limit of %zu.",
2146 /* This builtin issues a full memory barrier. */
2147 __sync_synchronize();
2148 return socket_fds_idx[fd];
2151 static int swrap_add_socket_info(const struct socket_info *si_input)
2153 struct socket_info *si = NULL;
2156 if (si_input == NULL) {
2161 swrap_mutex_lock(&first_free_mutex);
2162 if (first_free == -1) {
2167 si_index = first_free;
2168 si = swrap_get_socket_info(si_index);
2172 first_free = swrap_get_next_free(si);
2174 swrap_inc_refcount(si);
2176 SWRAP_UNLOCK_SI(si);
2179 swrap_mutex_unlock(&first_free_mutex);
2184 static int swrap_create_socket(struct socket_info *si, int fd)
2188 if ((size_t)fd >= socket_fds_max) {
2189 SWRAP_LOG(SWRAP_LOG_ERROR,
2190 "The max socket index limit of %zu has been reached, "
2198 idx = swrap_add_socket_info(si);
2203 set_socket_info_index(fd, idx);
2208 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2215 p = strrchr(un->sun_path, '/');
2216 if (p) p++; else p = un->sun_path;
2218 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2219 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2225 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2226 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2233 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2239 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2243 case SOCKET_TYPE_CHAR_TCP:
2244 case SOCKET_TYPE_CHAR_UDP: {
2245 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2247 if ((*len) < sizeof(*in2)) {
2248 SWRAP_LOG(SWRAP_LOG_ERROR,
2249 "V4: *len(%zu) < sizeof(*in2)=%zu",
2250 (size_t)*len, sizeof(*in2));
2255 memset(in2, 0, sizeof(*in2));
2256 in2->sin_family = AF_INET;
2257 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2258 in2->sin_port = htons(prt);
2260 *len = sizeof(*in2);
2264 case SOCKET_TYPE_CHAR_TCP_V6:
2265 case SOCKET_TYPE_CHAR_UDP_V6: {
2266 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2268 if ((*len) < sizeof(*in2)) {
2269 SWRAP_LOG(SWRAP_LOG_ERROR,
2270 "V6: *len(%zu) < sizeof(*in2)=%zu",
2271 (size_t)*len, sizeof(*in2));
2272 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2277 memset(in2, 0, sizeof(*in2));
2278 in2->sin6_family = AF_INET6;
2279 in2->sin6_addr = *swrap_ipv6();
2280 in2->sin6_addr.s6_addr[15] = iface;
2281 in2->sin6_port = htons(prt);
2283 *len = sizeof(*in2);
2288 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2297 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2304 char *swrap_dir = NULL;
2306 if (bcast) *bcast = 0;
2308 switch (inaddr->sa_family) {
2310 const struct sockaddr_in *in =
2311 (const struct sockaddr_in *)(const void *)inaddr;
2312 unsigned int addr = ntohl(in->sin_addr.s_addr);
2316 const unsigned int sw_net_addr = swrap_ipv4_net();
2317 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2321 u_type = SOCKET_TYPE_CHAR_TCP;
2324 u_type = SOCKET_TYPE_CHAR_UDP;
2325 a_type = SOCKET_TYPE_CHAR_UDP;
2326 b_type = SOCKET_TYPE_CHAR_UDP;
2329 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2330 errno = ESOCKTNOSUPPORT;
2334 prt = ntohs(in->sin_port);
2335 if (a_type && addr == 0xFFFFFFFF) {
2336 /* 255.255.255.255 only udp */
2339 iface = socket_wrapper_default_iface();
2340 } else if (b_type && addr == sw_bcast_addr) {
2349 iface = socket_wrapper_default_iface();
2350 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2351 /* 127.0.0.X or 10.53.57.X */
2354 iface = (addr & 0x000000FF);
2356 struct swrap_sockaddr_buf buf = {};
2357 SWRAP_LOG(SWRAP_LOG_WARN,
2359 swrap_sockaddr_string(&buf, inaddr));
2360 errno = ENETUNREACH;
2363 if (bcast) *bcast = is_bcast;
2368 const struct sockaddr_in6 *in =
2369 (const struct sockaddr_in6 *)(const void *)inaddr;
2370 struct in6_addr cmp1, cmp2;
2374 type = SOCKET_TYPE_CHAR_TCP_V6;
2377 type = SOCKET_TYPE_CHAR_UDP_V6;
2380 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2381 errno = ESOCKTNOSUPPORT;
2385 /* XXX no multicast/broadcast */
2387 prt = ntohs(in->sin6_port);
2389 cmp1 = *swrap_ipv6();
2390 cmp2 = in->sin6_addr;
2391 cmp2.s6_addr[15] = 0;
2392 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2393 iface = in->sin6_addr.s6_addr[15];
2395 struct swrap_sockaddr_buf buf = {};
2396 SWRAP_LOG(SWRAP_LOG_WARN,
2398 swrap_sockaddr_string(&buf, inaddr));
2399 errno = ENETUNREACH;
2407 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2408 errno = ENETUNREACH;
2413 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2418 swrap_dir = socket_wrapper_dir();
2419 if (swrap_dir == NULL) {
2425 swrap_un_path_EINVAL(un, swrap_dir);
2426 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2427 SAFE_FREE(swrap_dir);
2428 /* the caller need to do more processing */
2432 swrap_un_path(un, swrap_dir, type, iface, prt);
2433 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2435 SAFE_FREE(swrap_dir);
2440 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2448 char *swrap_dir = NULL;
2450 if (bcast) *bcast = 0;
2452 switch (si->family) {
2454 const struct sockaddr_in *in =
2455 (const struct sockaddr_in *)(const void *)inaddr;
2456 unsigned int addr = ntohl(in->sin_addr.s_addr);
2461 const unsigned int sw_net_addr = swrap_ipv4_net();
2462 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2464 prt = ntohs(in->sin_port);
2468 u_type = SOCKET_TYPE_CHAR_TCP;
2469 d_type = SOCKET_TYPE_CHAR_TCP;
2472 u_type = SOCKET_TYPE_CHAR_UDP;
2473 d_type = SOCKET_TYPE_CHAR_UDP;
2474 a_type = SOCKET_TYPE_CHAR_UDP;
2475 b_type = SOCKET_TYPE_CHAR_UDP;
2478 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2479 errno = ESOCKTNOSUPPORT;
2487 iface = socket_wrapper_default_iface();
2488 } else if (a_type && addr == 0xFFFFFFFF) {
2489 /* 255.255.255.255 only udp */
2492 iface = socket_wrapper_default_iface();
2493 } else if (b_type && addr == sw_bcast_addr) {
2494 /* 127.255.255.255 only udp */
2497 iface = socket_wrapper_default_iface();
2498 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2502 iface = (addr & 0x000000FF);
2504 errno = EADDRNOTAVAIL;
2508 /* Store the bind address for connect() */
2509 if (si->bindname.sa_socklen == 0) {
2510 struct sockaddr_in bind_in;
2511 socklen_t blen = sizeof(struct sockaddr_in);
2513 ZERO_STRUCT(bind_in);
2514 bind_in.sin_family = in->sin_family;
2515 bind_in.sin_port = in->sin_port;
2516 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2517 si->bindname.sa_socklen = blen;
2518 memcpy(&si->bindname.sa.in, &bind_in, blen);
2525 const struct sockaddr_in6 *in =
2526 (const struct sockaddr_in6 *)(const void *)inaddr;
2527 struct in6_addr cmp1, cmp2;
2531 type = SOCKET_TYPE_CHAR_TCP_V6;
2534 type = SOCKET_TYPE_CHAR_UDP_V6;
2537 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2538 errno = ESOCKTNOSUPPORT;
2542 /* XXX no multicast/broadcast */
2544 prt = ntohs(in->sin6_port);
2546 cmp1 = *swrap_ipv6();
2547 cmp2 = in->sin6_addr;
2548 cmp2.s6_addr[15] = 0;
2549 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2550 iface = socket_wrapper_default_iface();
2551 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2552 iface = in->sin6_addr.s6_addr[15];
2554 errno = EADDRNOTAVAIL;
2558 /* Store the bind address for connect() */
2559 if (si->bindname.sa_socklen == 0) {
2560 struct sockaddr_in6 bind_in;
2561 socklen_t blen = sizeof(struct sockaddr_in6);
2563 ZERO_STRUCT(bind_in);
2564 bind_in.sin6_family = in->sin6_family;
2565 bind_in.sin6_port = in->sin6_port;
2567 bind_in.sin6_addr = *swrap_ipv6();
2568 bind_in.sin6_addr.s6_addr[15] = iface;
2570 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2571 si->bindname.sa_socklen = blen;
2578 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2579 errno = EADDRNOTAVAIL;
2584 if (bcast) *bcast = is_bcast;
2586 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2591 swrap_dir = socket_wrapper_dir();
2592 if (swrap_dir == NULL) {
2598 /* handle auto-allocation of ephemeral ports */
2599 for (prt = 5001; prt < 10000; prt++) {
2600 swrap_un_path(un, swrap_dir, type, iface, prt);
2601 if (stat(un->sun_path, &st) == 0) continue;
2603 set_port(si->family, prt, &si->myname);
2604 set_port(si->family, prt, &si->bindname);
2611 SAFE_FREE(swrap_dir);
2616 swrap_un_path(un, swrap_dir, type, iface, prt);
2617 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2619 SAFE_FREE(swrap_dir);
2624 static struct socket_info *find_socket_info(int fd)
2626 int idx = find_socket_info_index(fd);
2632 return swrap_get_socket_info(idx);
2636 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2638 struct socket_info_fd *f;
2639 const struct socket_info *last_s = NULL;
2641 /* first catch invalid input */
2642 switch (sa->sa_family) {
2644 if (len < sizeof(struct sockaddr_in)) {
2650 if (len < sizeof(struct sockaddr_in6)) {
2660 for (f = socket_fds; f; f = f->next) {
2661 struct socket_info *s = swrap_get_socket_info(f->si_index);
2668 if (s->myname == NULL) {
2671 if (s->myname->sa_family != sa->sa_family) {
2674 switch (s->myname->sa_family) {
2676 struct sockaddr_in *sin1, *sin2;
2678 sin1 = (struct sockaddr_in *)s->myname;
2679 sin2 = (struct sockaddr_in *)sa;
2681 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2684 if (sin1->sin_port != sin2->sin_port) {
2687 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2697 struct sockaddr_in6 *sin1, *sin2;
2699 sin1 = (struct sockaddr_in6 *)s->myname;
2700 sin2 = (struct sockaddr_in6 *)sa;
2702 if (sin1->sin6_port != sin2->sin6_port) {
2705 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2727 static void swrap_remove_stale(int fd);
2729 static int sockaddr_convert_to_un(struct socket_info *si,
2730 const struct sockaddr *in_addr,
2732 struct sockaddr_un *out_addr,
2736 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2738 (void) in_len; /* unused */
2740 if (out_addr == NULL) {
2744 out->sa_family = AF_UNIX;
2745 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2746 out->sa_len = sizeof(*out_addr);
2749 switch (in_addr->sa_family) {
2751 const struct sockaddr_in *sin;
2752 if (si->family != AF_INET) {
2755 if (in_len < sizeof(struct sockaddr_in)) {
2758 sin = (const struct sockaddr_in *)(const void *)in_addr;
2759 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2764 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2765 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2779 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2780 errno = ESOCKTNOSUPPORT;
2784 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2786 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2792 errno = EAFNOSUPPORT;
2793 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2797 static int sockaddr_convert_from_un(const struct socket_info *si,
2798 const struct sockaddr_un *in_addr,
2799 socklen_t un_addrlen,
2801 struct sockaddr *out_addr,
2802 socklen_t *out_addrlen)
2806 if (out_addr == NULL || out_addrlen == NULL)
2809 if (un_addrlen == 0) {
2824 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2825 errno = ESOCKTNOSUPPORT;
2828 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2829 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2830 out_addr->sa_len = *out_addrlen;
2837 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2838 errno = EAFNOSUPPORT;
2842 enum swrap_packet_type {
2844 SWRAP_CONNECT_UNREACH,
2852 SWRAP_SENDTO_UNREACH,
2863 struct swrap_file_hdr {
2865 uint16_t version_major;
2866 uint16_t version_minor;
2869 uint32_t frame_max_len;
2870 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2873 #define SWRAP_FILE_HDR_SIZE 24
2875 struct swrap_packet_frame {
2877 uint32_t micro_seconds;
2878 uint32_t recorded_length;
2879 uint32_t full_length;
2881 #define SWRAP_PACKET_FRAME_SIZE 16
2883 union swrap_packet_ip {
2887 uint16_t packet_length;
2888 uint16_t identification;
2893 uint16_t hdr_checksum;
2897 #define SWRAP_PACKET_IP_V4_SIZE 20
2900 uint8_t flow_label_high;
2901 uint16_t flow_label_low;
2902 uint16_t payload_length;
2903 uint8_t next_header;
2905 uint8_t src_addr[16];
2906 uint8_t dest_addr[16];
2908 #define SWRAP_PACKET_IP_V6_SIZE 40
2910 #define SWRAP_PACKET_IP_SIZE 40
2912 union swrap_packet_payload {
2914 uint16_t source_port;
2924 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2926 uint16_t source_port;
2931 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2938 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2945 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2947 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2949 #define SWRAP_PACKET_MIN_ALLOC \
2950 (SWRAP_PACKET_FRAME_SIZE + \
2951 SWRAP_PACKET_IP_SIZE + \
2952 SWRAP_PACKET_PAYLOAD_SIZE)
2954 static const char *swrap_pcap_init_file(void)
2956 static int initialized = 0;
2957 static const char *s = NULL;
2958 static const struct swrap_file_hdr h;
2959 static const struct swrap_packet_frame f;
2960 static const union swrap_packet_ip i;
2961 static const union swrap_packet_payload p;
2963 if (initialized == 1) {
2969 * TODO: don't use the structs use plain buffer offsets
2970 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2972 * for now make sure we disable PCAP support
2973 * if the struct has alignment!
2975 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2978 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2981 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2984 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2987 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2990 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2993 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2996 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2999 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
3002 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
3006 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
3010 if (strncmp(s, "./", 2) == 0) {
3013 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
3017 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
3018 const struct sockaddr *src,
3019 const struct sockaddr *dest,
3021 const uint8_t *payload,
3023 unsigned long tcp_seqno,
3024 unsigned long tcp_ack,
3025 unsigned char tcp_ctl,
3027 size_t *_packet_len)
3029 uint8_t *base = NULL;
3030 uint8_t *buf = NULL;
3033 struct swrap_packet_frame *frame;
3037 union swrap_packet_ip *ip;
3039 union swrap_packet_payload *pay;
3042 size_t nonwire_len = sizeof(struct swrap_packet_frame);
3043 size_t wire_hdr_len = 0;
3044 size_t wire_len = 0;
3045 size_t ip_hdr_len = 0;
3046 size_t icmp_hdr_len = 0;
3047 size_t icmp_truncate_len = 0;
3048 uint8_t protocol = 0, icmp_protocol = 0;
3049 const struct sockaddr_in *src_in = NULL;
3050 const struct sockaddr_in *dest_in = NULL;
3052 const struct sockaddr_in6 *src_in6 = NULL;
3053 const struct sockaddr_in6 *dest_in6 = NULL;
3058 switch (src->sa_family) {
3060 src_in = (const struct sockaddr_in *)(const void *)src;
3061 dest_in = (const struct sockaddr_in *)(const void *)dest;
3062 src_port = src_in->sin_port;
3063 dest_port = dest_in->sin_port;
3064 ip_hdr_len = sizeof(i.ip->v4);
3068 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
3069 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
3070 src_port = src_in6->sin6_port;
3071 dest_port = dest_in6->sin6_port;
3072 ip_hdr_len = sizeof(i.ip->v6);
3079 switch (socket_type) {
3081 protocol = 0x06; /* TCP */
3082 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
3083 wire_len = wire_hdr_len + payload_len;
3087 protocol = 0x11; /* UDP */
3088 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
3089 wire_len = wire_hdr_len + payload_len;
3097 icmp_protocol = protocol;
3098 switch (src->sa_family) {
3100 protocol = 0x01; /* ICMPv4 */
3101 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
3105 protocol = 0x3A; /* ICMPv6 */
3106 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
3110 if (wire_len > 64 ) {
3111 icmp_truncate_len = wire_len - 64;
3113 wire_len += icmp_hdr_len;
3116 packet_len = nonwire_len + wire_len;
3117 alloc_len = packet_len;
3118 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
3119 alloc_len = SWRAP_PACKET_MIN_ALLOC;
3122 base = (uint8_t *)calloc(1, alloc_len);
3130 f.frame->seconds = tval->tv_sec;
3131 f.frame->micro_seconds = tval->tv_usec;
3132 f.frame->recorded_length = wire_len - icmp_truncate_len;
3133 f.frame->full_length = wire_len - icmp_truncate_len;
3135 buf += SWRAP_PACKET_FRAME_SIZE;
3138 switch (src->sa_family) {
3140 if (src_in == NULL || dest_in == NULL) {
3145 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3146 i.ip->v4.tos = 0x00;
3147 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
3148 i.ip->v4.identification = htons(0xFFFF);
3149 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3150 i.ip->v4.fragment = htons(0x0000);
3151 i.ip->v4.ttl = 0xFF;
3152 i.ip->v4.protocol = protocol;
3153 i.ip->v4.hdr_checksum = htons(0x0000);
3154 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
3155 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
3156 buf += SWRAP_PACKET_IP_V4_SIZE;
3160 if (src_in6 == NULL || dest_in6 == NULL) {
3165 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3166 i.ip->v6.flow_label_high = 0x00;
3167 i.ip->v6.flow_label_low = 0x0000;
3168 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3169 i.ip->v6.next_header = protocol;
3170 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
3171 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
3172 buf += SWRAP_PACKET_IP_V6_SIZE;
3178 pay = (union swrap_packet_payload *)(void *)buf;
3179 switch (src->sa_family) {
3181 pay->icmp4.type = 0x03; /* destination unreachable */
3182 pay->icmp4.code = 0x01; /* host unreachable */
3183 pay->icmp4.checksum = htons(0x0000);
3184 pay->icmp4.unused = htonl(0x00000000);
3186 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3188 /* set the ip header in the ICMP payload */
3190 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3191 i.ip->v4.tos = 0x00;
3192 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3193 i.ip->v4.identification = htons(0xFFFF);
3194 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3195 i.ip->v4.fragment = htons(0x0000);
3196 i.ip->v4.ttl = 0xFF;
3197 i.ip->v4.protocol = icmp_protocol;
3198 i.ip->v4.hdr_checksum = htons(0x0000);
3199 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3200 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3202 buf += SWRAP_PACKET_IP_V4_SIZE;
3204 src_port = dest_in->sin_port;
3205 dest_port = src_in->sin_port;
3209 pay->icmp6.type = 0x01; /* destination unreachable */
3210 pay->icmp6.code = 0x03; /* address unreachable */
3211 pay->icmp6.checksum = htons(0x0000);
3212 pay->icmp6.unused = htonl(0x00000000);
3213 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3215 /* set the ip header in the ICMP payload */
3217 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3218 i.ip->v6.flow_label_high = 0x00;
3219 i.ip->v6.flow_label_low = 0x0000;
3220 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3221 i.ip->v6.next_header = protocol;
3222 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3223 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3225 buf += SWRAP_PACKET_IP_V6_SIZE;
3227 src_port = dest_in6->sin6_port;
3228 dest_port = src_in6->sin6_port;
3234 pay = (union swrap_packet_payload *)(void *)buf;
3236 switch (socket_type) {
3238 pay->tcp.source_port = src_port;
3239 pay->tcp.dest_port = dest_port;
3240 pay->tcp.seq_num = htonl(tcp_seqno);
3241 pay->tcp.ack_num = htonl(tcp_ack);
3242 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3243 pay->tcp.control = tcp_ctl;
3244 pay->tcp.window = htons(0x7FFF);
3245 pay->tcp.checksum = htons(0x0000);
3246 pay->tcp.urg = htons(0x0000);
3247 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3252 pay->udp.source_port = src_port;
3253 pay->udp.dest_port = dest_port;
3254 pay->udp.length = htons(8 + payload_len);
3255 pay->udp.checksum = htons(0x0000);
3256 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3261 if (payload && payload_len > 0) {
3262 memcpy(buf, payload, payload_len);
3265 *_packet_len = packet_len - icmp_truncate_len;
3269 static int swrap_pcap_get_fd(const char *fname)
3277 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3279 struct swrap_file_hdr file_hdr;
3280 file_hdr.magic = 0xA1B2C3D4;
3281 file_hdr.version_major = 0x0002;
3282 file_hdr.version_minor = 0x0004;
3283 file_hdr.timezone = 0x00000000;
3284 file_hdr.sigfigs = 0x00000000;
3285 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3286 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3288 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3295 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3300 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3301 const struct sockaddr *addr,
3302 enum swrap_packet_type type,
3303 const void *buf, size_t len,
3306 const struct sockaddr *src_addr;
3307 const struct sockaddr *dest_addr;
3308 unsigned long tcp_seqno = 0;
3309 unsigned long tcp_ack = 0;
3310 unsigned char tcp_ctl = 0;
3311 int unreachable = 0;
3315 switch (si->family) {
3327 case SWRAP_CONNECT_SEND:
3328 if (si->type != SOCK_STREAM) {
3332 src_addr = &si->myname.sa.s;
3335 tcp_seqno = si->io.pck_snd;
3336 tcp_ack = si->io.pck_rcv;
3337 tcp_ctl = 0x02; /* SYN */
3339 si->io.pck_snd += 1;
3343 case SWRAP_CONNECT_RECV:
3344 if (si->type != SOCK_STREAM) {
3348 dest_addr = &si->myname.sa.s;
3351 tcp_seqno = si->io.pck_rcv;
3352 tcp_ack = si->io.pck_snd;
3353 tcp_ctl = 0x12; /** SYN,ACK */
3355 si->io.pck_rcv += 1;
3359 case SWRAP_CONNECT_UNREACH:
3360 if (si->type != SOCK_STREAM) {
3364 dest_addr = &si->myname.sa.s;
3367 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3368 tcp_seqno = si->io.pck_snd - 1;
3369 tcp_ack = si->io.pck_rcv;
3370 tcp_ctl = 0x02; /* SYN */
3375 case SWRAP_CONNECT_ACK:
3376 if (si->type != SOCK_STREAM) {
3380 src_addr = &si->myname.sa.s;
3383 tcp_seqno = si->io.pck_snd;
3384 tcp_ack = si->io.pck_rcv;
3385 tcp_ctl = 0x10; /* ACK */
3389 case SWRAP_ACCEPT_SEND:
3390 if (si->type != SOCK_STREAM) {
3394 dest_addr = &si->myname.sa.s;
3397 tcp_seqno = si->io.pck_rcv;
3398 tcp_ack = si->io.pck_snd;
3399 tcp_ctl = 0x02; /* SYN */
3401 si->io.pck_rcv += 1;
3405 case SWRAP_ACCEPT_RECV:
3406 if (si->type != SOCK_STREAM) {
3410 src_addr = &si->myname.sa.s;
3413 tcp_seqno = si->io.pck_snd;
3414 tcp_ack = si->io.pck_rcv;
3415 tcp_ctl = 0x12; /* SYN,ACK */
3417 si->io.pck_snd += 1;
3421 case SWRAP_ACCEPT_ACK:
3422 if (si->type != SOCK_STREAM) {
3426 dest_addr = &si->myname.sa.s;
3429 tcp_seqno = si->io.pck_rcv;
3430 tcp_ack = si->io.pck_snd;
3431 tcp_ctl = 0x10; /* ACK */
3436 src_addr = &si->myname.sa.s;
3437 dest_addr = &si->peername.sa.s;
3439 tcp_seqno = si->io.pck_snd;
3440 tcp_ack = si->io.pck_rcv;
3441 tcp_ctl = 0x18; /* PSH,ACK */
3443 si->io.pck_snd += len;
3447 case SWRAP_SEND_RST:
3448 dest_addr = &si->myname.sa.s;
3449 src_addr = &si->peername.sa.s;
3451 if (si->type == SOCK_DGRAM) {
3452 return swrap_pcap_marshall_packet(si,
3454 SWRAP_SENDTO_UNREACH,
3460 tcp_seqno = si->io.pck_rcv;
3461 tcp_ack = si->io.pck_snd;
3462 tcp_ctl = 0x14; /** RST,ACK */
3466 case SWRAP_PENDING_RST:
3467 dest_addr = &si->myname.sa.s;
3468 src_addr = &si->peername.sa.s;
3470 if (si->type == SOCK_DGRAM) {
3474 tcp_seqno = si->io.pck_rcv;
3475 tcp_ack = si->io.pck_snd;
3476 tcp_ctl = 0x14; /* RST,ACK */
3481 dest_addr = &si->myname.sa.s;
3482 src_addr = &si->peername.sa.s;
3484 tcp_seqno = si->io.pck_rcv;
3485 tcp_ack = si->io.pck_snd;
3486 tcp_ctl = 0x18; /* PSH,ACK */
3488 si->io.pck_rcv += len;
3492 case SWRAP_RECV_RST:
3493 dest_addr = &si->myname.sa.s;
3494 src_addr = &si->peername.sa.s;
3496 if (si->type == SOCK_DGRAM) {
3500 tcp_seqno = si->io.pck_rcv;
3501 tcp_ack = si->io.pck_snd;
3502 tcp_ctl = 0x14; /* RST,ACK */
3507 src_addr = &si->myname.sa.s;
3510 si->io.pck_snd += len;
3514 case SWRAP_SENDTO_UNREACH:
3515 dest_addr = &si->myname.sa.s;
3522 case SWRAP_RECVFROM:
3523 dest_addr = &si->myname.sa.s;
3526 si->io.pck_rcv += len;
3530 case SWRAP_CLOSE_SEND:
3531 if (si->type != SOCK_STREAM) {
3535 src_addr = &si->myname.sa.s;
3536 dest_addr = &si->peername.sa.s;
3538 tcp_seqno = si->io.pck_snd;
3539 tcp_ack = si->io.pck_rcv;
3540 tcp_ctl = 0x11; /* FIN, ACK */
3542 si->io.pck_snd += 1;
3546 case SWRAP_CLOSE_RECV:
3547 if (si->type != SOCK_STREAM) {
3551 dest_addr = &si->myname.sa.s;
3552 src_addr = &si->peername.sa.s;
3554 tcp_seqno = si->io.pck_rcv;
3555 tcp_ack = si->io.pck_snd;
3556 tcp_ctl = 0x11; /* FIN,ACK */
3558 si->io.pck_rcv += 1;
3562 case SWRAP_CLOSE_ACK:
3563 if (si->type != SOCK_STREAM) {
3567 src_addr = &si->myname.sa.s;
3568 dest_addr = &si->peername.sa.s;
3570 tcp_seqno = si->io.pck_snd;
3571 tcp_ack = si->io.pck_rcv;
3572 tcp_ctl = 0x10; /* ACK */
3579 swrapGetTimeOfDay(&tv);
3581 return swrap_pcap_packet_init(&tv,
3585 (const uint8_t *)buf,
3594 static void swrap_pcap_dump_packet(struct socket_info *si,
3595 const struct sockaddr *addr,
3596 enum swrap_packet_type type,
3597 const void *buf, size_t len)
3599 const char *file_name;
3601 size_t packet_len = 0;
3604 swrap_mutex_lock(&pcap_dump_mutex);
3606 file_name = swrap_pcap_init_file();
3611 packet = swrap_pcap_marshall_packet(si,
3617 if (packet == NULL) {
3621 fd = swrap_pcap_get_fd(file_name);
3623 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3632 swrap_mutex_unlock(&pcap_dump_mutex);
3635 /****************************************************************************
3637 ***************************************************************************/
3639 #ifdef HAVE_SIGNALFD
3640 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3644 rc = libc_signalfd(fd, mask, flags);
3646 swrap_remove_stale(fd);
3652 int signalfd(int fd, const sigset_t *mask, int flags)
3654 return swrap_signalfd(fd, mask, flags);
3658 /****************************************************************************
3660 ***************************************************************************/
3662 static int swrap_socket(int family, int type, int protocol)
3664 struct socket_info *si = NULL;
3665 struct socket_info _si = { 0 };
3668 int real_type = type;
3671 * Remove possible addition flags passed to socket() so
3672 * do not fail checking the type.
3673 * See https://lwn.net/Articles/281965/
3676 real_type &= ~SOCK_CLOEXEC;
3678 #ifdef SOCK_NONBLOCK
3679 real_type &= ~SOCK_NONBLOCK;
3682 if (!socket_wrapper_enabled()) {
3683 return libc_socket(family, type, protocol);
3694 #endif /* AF_NETLINK */
3697 #endif /* AF_PACKET */
3699 fd = libc_socket(family, type, protocol);
3701 /* Check if we have a stale fd and remove it */
3702 swrap_remove_stale(fd);
3703 SWRAP_LOG(SWRAP_LOG_TRACE,
3704 "Unix socket fd=%d",
3709 errno = EAFNOSUPPORT;
3713 switch (real_type) {
3719 errno = EPROTONOSUPPORT;
3727 if (real_type == SOCK_STREAM) {
3732 if (real_type == SOCK_DGRAM) {
3737 errno = EPROTONOSUPPORT;
3742 * We must call libc_socket with type, from the caller, not the version
3743 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3745 fd = libc_socket(AF_UNIX, type, 0);
3751 /* Check if we have a stale fd and remove it */
3752 swrap_remove_stale(fd);
3755 si->family = family;
3757 /* however, the rest of the socket_wrapper code expects just
3758 * the type, not the flags */
3759 si->type = real_type;
3760 si->protocol = protocol;
3763 * Setup myname so getsockname() can succeed to find out the socket
3766 switch(si->family) {
3768 struct sockaddr_in sin = {
3769 .sin_family = AF_INET,
3772 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3773 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3778 struct sockaddr_in6 sin6 = {
3779 .sin6_family = AF_INET6,
3782 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3783 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3792 ret = swrap_create_socket(si, fd);
3794 int saved_errno = errno;
3796 errno = saved_errno;
3800 SWRAP_LOG(SWRAP_LOG_TRACE,
3801 "Created %s socket for protocol %s, fd=%d",
3802 family == AF_INET ? "IPv4" : "IPv6",
3803 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3809 int socket(int family, int type, int protocol)
3811 return swrap_socket(family, type, protocol);
3814 /****************************************************************************
3816 ***************************************************************************/
3818 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3822 rc = libc_socketpair(family, type, protocol, sv);
3824 swrap_remove_stale(sv[0]);
3825 swrap_remove_stale(sv[1]);
3831 int socketpair(int family, int type, int protocol, int sv[2])
3833 return swrap_socketpair(family, type, protocol, sv);
3836 /****************************************************************************
3838 ***************************************************************************/
3840 #ifdef HAVE_TIMERFD_CREATE
3841 static int swrap_timerfd_create(int clockid, int flags)
3845 fd = libc_timerfd_create(clockid, flags);
3847 swrap_remove_stale(fd);
3853 int timerfd_create(int clockid, int flags)
3855 return swrap_timerfd_create(clockid, flags);
3859 /****************************************************************************
3861 ***************************************************************************/
3863 static int swrap_pipe(int pipefd[2])
3867 rc = libc_pipe(pipefd);
3869 swrap_remove_stale(pipefd[0]);
3870 swrap_remove_stale(pipefd[1]);
3876 int pipe(int pipefd[2])
3878 return swrap_pipe(pipefd);
3881 /****************************************************************************
3883 ***************************************************************************/
3885 static int swrap_accept(int s,
3886 struct sockaddr *addr,
3890 struct socket_info *parent_si, *child_si;
3891 struct socket_info new_si = { 0 };
3894 struct swrap_address un_addr = {
3895 .sa_socklen = sizeof(struct sockaddr_un),
3897 struct swrap_address un_my_addr = {
3898 .sa_socklen = sizeof(struct sockaddr_un),
3900 struct swrap_address in_addr = {
3901 .sa_socklen = sizeof(struct sockaddr_storage),
3903 struct swrap_address in_my_addr = {
3904 .sa_socklen = sizeof(struct sockaddr_storage),
3908 parent_si = find_socket_info(s);
3911 return libc_accept4(s, addr, addrlen, flags);
3914 return libc_accept(s, addr, addrlen);
3920 * prevent parent_si from being altered / closed
3923 SWRAP_LOCK_SI(parent_si);
3926 * assume out sockaddr have the same size as the in parent
3929 in_addr.sa_socklen = socket_length(parent_si->family);
3930 if (in_addr.sa_socklen <= 0) {
3931 SWRAP_UNLOCK_SI(parent_si);
3936 SWRAP_UNLOCK_SI(parent_si);
3939 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3942 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3945 int saved_errno = errno;
3946 if (saved_errno == ENOTSOCK) {
3947 /* Remove stale fds */
3948 swrap_remove_stale(s);
3950 errno = saved_errno;
3956 /* Check if we have a stale fd and remove it */
3957 swrap_remove_stale(fd);
3959 if (un_addr.sa.un.sun_path[0] == '\0') {
3961 * FreeBSD seems to have a problem where
3962 * accept4() on the unix socket doesn't
3963 * ECONNABORTED for already disconnected connections.
3965 * Let's try libc_getpeername() to get the peer address
3966 * as a fallback, but it'll likely return ENOTCONN,
3967 * which we have to map to ECONNABORTED.
3969 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3970 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3972 int saved_errno = errno;
3974 if (saved_errno == ENOTCONN) {
3976 * If the connection is already disconnected
3977 * we should return ECONNABORTED.
3979 saved_errno = ECONNABORTED;
3981 errno = saved_errno;
3986 ret = libc_getsockname(fd,
3988 &un_my_addr.sa_socklen);
3990 int saved_errno = errno;
3992 if (saved_errno == ENOTCONN) {
3994 * If the connection is already disconnected
3995 * we should return ECONNABORTED.
3997 saved_errno = ECONNABORTED;
3999 errno = saved_errno;
4003 SWRAP_LOCK_SI(parent_si);
4005 ret = sockaddr_convert_from_un(parent_si,
4010 &in_addr.sa_socklen);
4012 int saved_errno = errno;
4013 SWRAP_UNLOCK_SI(parent_si);
4015 errno = saved_errno;
4021 child_si->family = parent_si->family;
4022 child_si->type = parent_si->type;
4023 child_si->protocol = parent_si->protocol;
4024 child_si->bound = 1;
4025 child_si->is_server = 1;
4026 child_si->connected = 1;
4028 SWRAP_UNLOCK_SI(parent_si);
4030 child_si->peername = (struct swrap_address) {
4031 .sa_socklen = in_addr.sa_socklen,
4033 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
4035 if (addr != NULL && addrlen != NULL) {
4036 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
4038 memcpy(addr, &in_addr.sa.ss, copy_len);
4040 *addrlen = in_addr.sa_socklen;
4043 ret = sockaddr_convert_from_un(child_si,
4045 un_my_addr.sa_socklen,
4048 &in_my_addr.sa_socklen);
4050 int saved_errno = errno;
4052 errno = saved_errno;
4056 SWRAP_LOG(SWRAP_LOG_TRACE,
4057 "accept() path=%s, fd=%d",
4058 un_my_addr.sa.un.sun_path, s);
4060 child_si->myname = (struct swrap_address) {
4061 .sa_socklen = in_my_addr.sa_socklen,
4063 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
4065 idx = swrap_create_socket(&new_si, fd);
4067 int saved_errno = errno;
4069 errno = saved_errno;
4074 struct socket_info *si = swrap_get_socket_info(idx);
4077 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
4078 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
4079 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
4080 SWRAP_UNLOCK_SI(si);
4087 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
4089 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
4093 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4094 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
4096 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
4099 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
4102 static int autobind_start_init;
4103 static int autobind_start;
4105 /* using sendto() or connect() on an unbound socket would give the
4106 recipient no way to reply, as unlike UDP and TCP, a unix domain
4107 socket can't auto-assign ephemeral port numbers, so we need to
4109 Note: this might change the family from ipv6 to ipv4
4111 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
4113 struct swrap_address un_addr = {
4114 .sa_socklen = sizeof(struct sockaddr_un),
4120 char *swrap_dir = NULL;
4122 swrap_mutex_lock(&autobind_start_mutex);
4124 if (autobind_start_init != 1) {
4125 autobind_start_init = 1;
4126 autobind_start = getpid();
4127 autobind_start %= 50000;
4128 autobind_start += 10000;
4131 un_addr.sa.un.sun_family = AF_UNIX;
4135 struct sockaddr_in in;
4139 type = SOCKET_TYPE_CHAR_TCP;
4142 type = SOCKET_TYPE_CHAR_UDP;
4145 errno = ESOCKTNOSUPPORT;
4150 memset(&in, 0, sizeof(in));
4151 in.sin_family = AF_INET;
4152 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
4153 socket_wrapper_default_iface()));
4155 si->myname = (struct swrap_address) {
4156 .sa_socklen = sizeof(in),
4158 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
4163 struct sockaddr_in6 in6;
4165 if (si->family != family) {
4166 errno = ENETUNREACH;
4173 type = SOCKET_TYPE_CHAR_TCP_V6;
4176 type = SOCKET_TYPE_CHAR_UDP_V6;
4179 errno = ESOCKTNOSUPPORT;
4184 memset(&in6, 0, sizeof(in6));
4185 in6.sin6_family = AF_INET6;
4186 in6.sin6_addr = *swrap_ipv6();
4187 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4189 si->myname = (struct swrap_address) {
4190 .sa_socklen = sizeof(in6),
4192 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4197 errno = ESOCKTNOSUPPORT;
4202 if (autobind_start > 60000) {
4203 autobind_start = 10000;
4206 swrap_dir = socket_wrapper_dir();
4207 if (swrap_dir == NULL) {
4213 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4214 port = autobind_start + i;
4215 swrap_un_path(&un_addr.sa.un,
4218 socket_wrapper_default_iface(),
4221 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4223 if (errno == EALREADY || errno == EADDRINUSE) {
4229 si->un_addr = un_addr.sa.un;
4232 autobind_start = port + 1;
4235 if (i == SOCKET_MAX_SOCKETS) {
4236 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4237 "interface "SOCKET_FORMAT,
4240 socket_wrapper_default_iface(),
4247 si->family = family;
4248 set_port(si->family, port, &si->myname);
4253 SAFE_FREE(swrap_dir);
4254 swrap_mutex_unlock(&autobind_start_mutex);
4258 /****************************************************************************
4260 ***************************************************************************/
4262 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4266 struct swrap_address un_addr = {
4267 .sa_socklen = sizeof(struct sockaddr_un),
4269 struct socket_info *si = find_socket_info(s);
4270 struct swrap_sockaddr_buf buf = {};
4274 return libc_connect(s, serv_addr, addrlen);
4279 if (si->bound == 0) {
4280 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4286 if (si->family != serv_addr->sa_family) {
4287 SWRAP_LOG(SWRAP_LOG_ERROR,
4288 "called for fd=%d (family=%d) called with invalid family=%d",
4289 s, si->family, serv_addr->sa_family);
4295 ret = sockaddr_convert_to_un(si, serv_addr,
4296 addrlen, &un_addr.sa.un, 0, &bcast);
4302 errno = ENETUNREACH;
4307 if (si->type == SOCK_DGRAM) {
4308 si->defer_connect = 1;
4311 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4313 ret = libc_connect(s,
4315 un_addr.sa_socklen);
4318 SWRAP_LOG(SWRAP_LOG_TRACE,
4319 "connect(%s) path=%s, fd=%d",
4320 swrap_sockaddr_string(&buf, serv_addr),
4321 un_addr.sa.un.sun_path, s);
4324 /* to give better errors */
4325 if (ret == -1 && errno == ENOENT) {
4326 errno = EHOSTUNREACH;
4330 si->peername = (struct swrap_address) {
4331 .sa_socklen = addrlen,
4334 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4338 * When we connect() on a socket than we have to bind the
4339 * outgoing connection on the interface we use for the
4340 * transport. We already bound it on the right interface
4341 * but here we have to update the name so getsockname()
4342 * returns correct information.
4344 if (si->bindname.sa_socklen > 0) {
4345 si->myname = (struct swrap_address) {
4346 .sa_socklen = si->bindname.sa_socklen,
4349 memcpy(&si->myname.sa.ss,
4350 &si->bindname.sa.ss,
4351 si->bindname.sa_socklen);
4353 /* Cleanup bindname */
4354 si->bindname = (struct swrap_address) {
4359 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4360 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4362 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4366 SWRAP_UNLOCK_SI(si);
4370 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4372 return swrap_connect(s, serv_addr, addrlen);
4375 /****************************************************************************
4377 ***************************************************************************/
4379 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4382 struct swrap_address un_addr = {
4383 .sa_socklen = sizeof(struct sockaddr_un),
4385 struct socket_info *si = find_socket_info(s);
4386 struct swrap_sockaddr_buf buf = {};
4387 int ret_errno = errno;
4394 return libc_bind(s, myaddr, addrlen);
4399 switch (si->family) {
4401 const struct sockaddr_in *sin;
4402 if (addrlen < sizeof(struct sockaddr_in)) {
4403 bind_error = EINVAL;
4407 sin = (const struct sockaddr_in *)(const void *)myaddr;
4409 if (sin->sin_family != AF_INET) {
4410 bind_error = EAFNOSUPPORT;
4413 /* special case for AF_UNSPEC */
4414 if (sin->sin_family == AF_UNSPEC &&
4415 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4424 const struct sockaddr_in6 *sin6;
4425 if (addrlen < sizeof(struct sockaddr_in6)) {
4426 bind_error = EINVAL;
4430 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4432 if (sin6->sin6_family != AF_INET6) {
4433 bind_error = EAFNOSUPPORT;
4440 bind_error = EINVAL;
4444 if (bind_error != 0) {
4445 ret_errno = bind_error;
4451 in_use = check_addr_port_in_use(myaddr, addrlen);
4459 si->myname.sa_socklen = addrlen;
4460 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4462 ret = sockaddr_convert_to_un(si,
4473 unlink(un_addr.sa.un.sun_path);
4475 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4480 SWRAP_LOG(SWRAP_LOG_TRACE,
4481 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4482 swrap_sockaddr_string(&buf, myaddr),
4483 un_addr.sa.un.sun_path, s, ret, ret_errno);
4490 SWRAP_UNLOCK_SI(si);
4495 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4497 return swrap_bind(s, myaddr, addrlen);
4500 /****************************************************************************
4502 ***************************************************************************/
4504 #ifdef HAVE_BINDRESVPORT
4505 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4507 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4509 struct swrap_address myaddr = {
4510 .sa_socklen = sizeof(struct sockaddr_storage),
4513 static uint16_t port;
4518 #define SWRAP_STARTPORT 600
4519 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4520 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4523 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4527 salen = myaddr.sa_socklen;
4530 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4536 memset(&myaddr.sa.ss, 0, salen);
4541 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4544 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4546 salen = sizeof(struct sockaddr_in);
4547 sinp->sin_port = htons(port);
4551 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4553 salen = sizeof(struct sockaddr_in6);
4554 sin6p->sin6_port = htons(port);
4558 errno = EAFNOSUPPORT;
4563 if (port > SWRAP_ENDPORT) {
4564 port = SWRAP_STARTPORT;
4567 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4568 if (rc == 0 || errno != EADDRINUSE) {
4576 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4578 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4582 /****************************************************************************
4584 ***************************************************************************/
4586 static int swrap_listen(int s, int backlog)
4589 struct socket_info *si = find_socket_info(s);
4592 return libc_listen(s, backlog);
4597 if (si->bound == 0) {
4598 ret = swrap_auto_bind(s, si, si->family);
4605 ret = libc_listen(s, backlog);
4611 SWRAP_UNLOCK_SI(si);
4616 int listen(int s, int backlog)
4618 return swrap_listen(s, backlog);
4621 /****************************************************************************
4623 ***************************************************************************/
4625 static FILE *swrap_fopen(const char *name, const char *mode)
4629 fp = libc_fopen(name, mode);
4631 int fd = fileno(fp);
4633 swrap_remove_stale(fd);
4639 #undef fopen /* Needed for LFS handling */
4640 FILE *fopen(const char *name, const char *mode)
4642 return swrap_fopen(name, mode);
4645 /****************************************************************************
4647 ***************************************************************************/
4650 static FILE *swrap_fopen64(const char *name, const char *mode)
4654 fp = libc_fopen64(name, mode);
4656 int fd = fileno(fp);
4658 swrap_remove_stale(fd);
4664 FILE *fopen64(const char *name, const char *mode)
4666 return swrap_fopen64(name, mode);
4668 #endif /* HAVE_FOPEN64 */
4670 /****************************************************************************
4672 ***************************************************************************/
4674 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4678 ret = libc_vopen(pathname, flags, ap);
4681 * There are methods for closing descriptors (libc-internal code
4682 * paths, direct syscalls) which close descriptors in ways that
4683 * we can't intercept, so try to recover when we notice that
4686 swrap_remove_stale(ret);
4691 #undef open /* Needed for LFS handling */
4692 int open(const char *pathname, int flags, ...)
4697 va_start(ap, flags);
4698 fd = swrap_vopen(pathname, flags, ap);
4704 /****************************************************************************
4706 ***************************************************************************/
4709 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4713 ret = libc_vopen64(pathname, flags, ap);
4716 * There are methods for closing descriptors (libc-internal code
4717 * paths, direct syscalls) which close descriptors in ways that
4718 * we can't intercept, so try to recover when we notice that
4721 swrap_remove_stale(ret);
4726 int open64(const char *pathname, int flags, ...)
4731 va_start(ap, flags);
4732 fd = swrap_vopen64(pathname, flags, ap);
4737 #endif /* HAVE_OPEN64 */
4739 /****************************************************************************
4741 ***************************************************************************/
4743 #ifdef HAVE_OPENAT64
4745 swrap_vopenat64(int dirfd, const char *pathname, int flags, va_list ap)
4749 ret = libc_vopenat64(dirfd, pathname, flags, ap);
4752 * There are methods for closing descriptors (libc-internal code
4753 * paths, direct syscalls) which close descriptors in ways that
4754 * we can't intercept, so try to recover when we notice that
4757 swrap_remove_stale(ret);
4762 int openat64(int dirfd, const char *pathname, int flags, ...)
4767 va_start(ap, flags);
4768 fd = swrap_vopenat64(dirfd, pathname, flags, ap);
4773 #endif /* HAVE_OPENAT64 */
4775 /****************************************************************************
4777 ***************************************************************************/
4779 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4783 ret = libc_vopenat(dirfd, path, flags, ap);
4786 * There are methods for closing descriptors (libc-internal code
4787 * paths, direct syscalls) which close descriptors in ways that
4788 * we can't intercept, so try to recover when we notice that
4791 swrap_remove_stale(ret);
4797 #undef openat /* Needed for LFS handling */
4798 int openat(int dirfd, const char *path, int flags, ...)
4803 va_start(ap, flags);
4804 fd = swrap_vopenat(dirfd, path, flags, ap);
4810 /****************************************************************************
4812 ***************************************************************************/
4814 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4816 struct socket_info *si = find_socket_info(s);
4821 return libc_getpeername(s, name, addrlen);
4826 if (si->peername.sa_socklen == 0)
4832 len = MIN(*addrlen, si->peername.sa_socklen);
4838 memcpy(name, &si->peername.sa.ss, len);
4839 *addrlen = si->peername.sa_socklen;
4843 SWRAP_UNLOCK_SI(si);
4848 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4849 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4851 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4854 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4857 /****************************************************************************
4859 ***************************************************************************/
4861 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4863 struct socket_info *si = find_socket_info(s);
4868 return libc_getsockname(s, name, addrlen);
4873 len = MIN(*addrlen, si->myname.sa_socklen);
4879 memcpy(name, &si->myname.sa.ss, len);
4880 *addrlen = si->myname.sa_socklen;
4884 SWRAP_UNLOCK_SI(si);
4889 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4890 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4892 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4895 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4898 /****************************************************************************
4900 ***************************************************************************/
4903 # ifdef SO_PROTOTYPE /* The Solaris name */
4904 # define SO_PROTOCOL SO_PROTOTYPE
4905 # endif /* SO_PROTOTYPE */
4906 #endif /* SO_PROTOCOL */
4908 static int swrap_getsockopt(int s, int level, int optname,
4909 void *optval, socklen_t *optlen)
4911 struct socket_info *si = find_socket_info(s);
4915 return libc_getsockopt(s,
4924 if (level == SOL_SOCKET) {
4928 if (optval == NULL || optlen == NULL ||
4929 *optlen < (socklen_t)sizeof(int)) {
4935 *optlen = sizeof(int);
4936 *(int *)optval = si->family;
4939 #endif /* SO_DOMAIN */
4943 if (optval == NULL || optlen == NULL ||
4944 *optlen < (socklen_t)sizeof(int)) {
4950 *optlen = sizeof(int);
4951 *(int *)optval = si->protocol;
4954 #endif /* SO_PROTOCOL */
4956 if (optval == NULL || optlen == NULL ||
4957 *optlen < (socklen_t)sizeof(int)) {
4963 *optlen = sizeof(int);
4964 *(int *)optval = si->type;
4968 ret = libc_getsockopt(s,
4975 } else if (level == IPPROTO_TCP) {
4980 * This enables sending packets directly out over TCP.
4981 * As a unix socket is doing that any way, report it as
4984 if (optval == NULL || optlen == NULL ||
4985 *optlen < (socklen_t)sizeof(int)) {
4991 *optlen = sizeof(int);
4992 *(int *)optval = si->tcp_nodelay;
4996 #endif /* TCP_NODELAY */
4999 struct tcp_info info;
5000 socklen_t ilen = sizeof(info);
5002 #ifdef HAVE_NETINET_TCP_FSM_H
5003 /* This is FreeBSD */
5004 # define __TCP_LISTEN TCPS_LISTEN
5005 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
5006 # define __TCP_CLOSE TCPS_CLOSED
5009 # define __TCP_LISTEN TCP_LISTEN
5010 # define __TCP_ESTABLISHED TCP_ESTABLISHED
5011 # define __TCP_CLOSE TCP_CLOSE
5015 if (si->listening) {
5016 info.tcpi_state = __TCP_LISTEN;
5017 } else if (si->connected) {
5019 * For now we just fake a few values
5020 * supported both by FreeBSD and Linux
5022 info.tcpi_state = __TCP_ESTABLISHED;
5023 info.tcpi_rto = 200000; /* 200 msec */
5024 info.tcpi_rtt = 5000; /* 5 msec */
5025 info.tcpi_rttvar = 5000; /* 5 msec */
5027 info.tcpi_state = __TCP_CLOSE;
5028 info.tcpi_rto = 1000000; /* 1 sec */
5030 info.tcpi_rttvar = 250000; /* 250 msec */
5033 if (optval == NULL || optlen == NULL ||
5034 *optlen < (socklen_t)ilen) {
5041 memcpy(optval, &info, ilen);
5046 #endif /* TCP_INFO */
5052 errno = ENOPROTOOPT;
5056 SWRAP_UNLOCK_SI(si);
5060 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5061 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
5063 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
5066 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
5069 /****************************************************************************
5071 ***************************************************************************/
5073 static int swrap_setsockopt(int s, int level, int optname,
5074 const void *optval, socklen_t optlen)
5076 struct socket_info *si = find_socket_info(s);
5080 return libc_setsockopt(s,
5087 if (level == SOL_SOCKET) {
5088 return libc_setsockopt(s,
5097 if (level == IPPROTO_TCP) {
5104 * This enables sending packets directly out over TCP.
5105 * A unix socket is doing that any way.
5107 if (optval == NULL || optlen == 0 ||
5108 optlen < (socklen_t)sizeof(int)) {
5114 i = *discard_const_p(int, optval);
5115 if (i != 0 && i != 1) {
5120 si->tcp_nodelay = i;
5125 #endif /* TCP_NODELAY */
5131 switch (si->family) {
5133 if (level == IPPROTO_IP) {
5135 if (optname == IP_PKTINFO) {
5136 si->pktinfo = AF_INET;
5138 #endif /* IP_PKTINFO */
5144 if (level == IPPROTO_IPV6) {
5145 #ifdef IPV6_RECVPKTINFO
5146 if (optname == IPV6_RECVPKTINFO) {
5147 si->pktinfo = AF_INET6;
5149 #endif /* IPV6_PKTINFO */
5155 errno = ENOPROTOOPT;
5161 SWRAP_UNLOCK_SI(si);
5165 int setsockopt(int s, int level, int optname,
5166 const void *optval, socklen_t optlen)
5168 return swrap_setsockopt(s, level, optname, optval, optlen);
5171 /****************************************************************************
5173 ***************************************************************************/
5175 static int swrap_vioctl(int s, unsigned long int r, va_list va)
5177 struct socket_info *si = find_socket_info(s);
5179 int *value_ptr = NULL;
5183 return libc_vioctl(s, r, va);
5190 rc = libc_vioctl(s, r, va);
5195 value_ptr = ((int *)va_arg(ap, int *));
5198 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
5199 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5200 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
5201 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5206 /* this is FreeBSD */
5207 FALL_THROUGH; /* to TIOCOUTQ */
5208 #endif /* FIONWRITE */
5209 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
5211 * This may return more bytes then the application
5212 * sent into the socket, for tcp it should
5213 * return the number of unacked bytes.
5215 * On AF_UNIX, all bytes are immediately acked!
5218 value_ptr = ((int *)va_arg(ap, int *));
5226 SWRAP_UNLOCK_SI(si);
5230 #ifdef HAVE_IOCTL_INT
5231 int ioctl(int s, int r, ...)
5233 int ioctl(int s, unsigned long int r, ...)
5241 rc = swrap_vioctl(s, (unsigned long int) r, va);
5252 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5255 # ifdef _ALIGN /* BSD */
5256 #define CMSG_ALIGN _ALIGN
5258 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5259 # endif /* _ALIGN */
5260 #endif /* CMSG_ALIGN */
5263 * @brief Add a cmsghdr to a msghdr.
5265 * This is an function to add any type of cmsghdr. It will operate on the
5266 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5267 * the buffer position after the added cmsg element. Hence, this function is
5268 * intended to be used with an intermediate msghdr and not on the original
5269 * one handed in by the client.
5271 * @param[in] msg The msghdr to which to add the cmsg.
5273 * @param[in] level The cmsg level to set.
5275 * @param[in] type The cmsg type to set.
5277 * @param[in] data The cmsg data to set.
5279 * @param[in] len the length of the data to set.
5281 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5287 size_t cmlen = CMSG_LEN(len);
5288 size_t cmspace = CMSG_SPACE(len);
5289 uint8_t cmbuf[cmspace];
5290 void *cast_ptr = (void *)cmbuf;
5291 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5294 memset(cmbuf, 0, cmspace);
5296 if (msg->msg_controllen < cmlen) {
5297 cmlen = msg->msg_controllen;
5298 msg->msg_flags |= MSG_CTRUNC;
5301 if (msg->msg_controllen < cmspace) {
5302 cmspace = msg->msg_controllen;
5306 * We copy the full input data into an intermediate cmsghdr first
5307 * in order to more easily cope with truncation.
5309 cm->cmsg_len = cmlen;
5310 cm->cmsg_level = level;
5311 cm->cmsg_type = type;
5312 memcpy(CMSG_DATA(cm), data, len);
5315 * We now copy the possibly truncated buffer.
5316 * We copy cmlen bytes, but consume cmspace bytes,
5317 * leaving the possible padding uninitialiazed.
5319 p = (uint8_t *)msg->msg_control;
5320 memcpy(p, cm, cmlen);
5322 msg->msg_control = p;
5323 msg->msg_controllen -= cmspace;
5328 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5331 /* Add packet info */
5332 switch (si->pktinfo) {
5333 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5335 struct sockaddr_in *sin;
5336 #if defined(HAVE_STRUCT_IN_PKTINFO)
5337 struct in_pktinfo pkt;
5338 #elif defined(IP_RECVDSTADDR)
5342 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5343 sin = &si->bindname.sa.in;
5345 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5348 sin = &si->myname.sa.in;
5353 #if defined(HAVE_STRUCT_IN_PKTINFO)
5354 pkt.ipi_ifindex = socket_wrapper_default_iface();
5355 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5356 #elif defined(IP_RECVDSTADDR)
5357 pkt = sin->sin_addr;
5360 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5365 #endif /* IP_PKTINFO */
5366 #if defined(HAVE_IPV6)
5368 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5369 struct sockaddr_in6 *sin6;
5370 struct in6_pktinfo pkt6;
5372 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5373 sin6 = &si->bindname.sa.in6;
5375 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5378 sin6 = &si->myname.sa.in6;
5383 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5384 pkt6.ipi6_addr = sin6->sin6_addr;
5386 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5387 &pkt6, sizeof(pkt6));
5388 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5392 #endif /* IPV6_PKTINFO */
5400 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5401 struct msghdr *omsg)
5405 if (si->pktinfo > 0) {
5406 rc = swrap_msghdr_add_pktinfo(si, omsg);
5412 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5414 size_t *cm_data_space);
5415 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5417 size_t *cm_data_space);
5418 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5420 size_t *cm_data_space);
5422 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5424 size_t *cm_data_space)
5426 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5427 struct cmsghdr *cmsg;
5431 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5435 for (cmsg = CMSG_FIRSTHDR(msg);
5437 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5438 switch (cmsg->cmsg_level) {
5440 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5445 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5450 rc = swrap_sendmsg_copy_cmsg(cmsg,
5456 int saved_errno = errno;
5457 SAFE_FREE(*cm_data);
5459 errno = saved_errno;
5467 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5469 size_t *cm_data_space)
5474 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5476 p = realloc((*cm_data), cmspace);
5482 p = (*cm_data) + (*cm_data_space);
5483 *cm_data_space = cmspace;
5485 memcpy(p, cmsg, cmsg->cmsg_len);
5490 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5492 size_t *cm_data_space);
5495 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5497 size_t *cm_data_space)
5501 switch(cmsg->cmsg_type) {
5504 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5511 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5523 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5525 size_t *cm_data_space)
5527 (void)cmsg; /* unused */
5528 (void)cm_data; /* unused */
5529 (void)cm_data_space; /* unused */
5532 * Passing a IP pktinfo to a unix socket might be rejected by the
5533 * Kernel, at least on FreeBSD. So skip this cmsg.
5538 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5540 size_t *cm_data_space)
5544 switch (cmsg->cmsg_type) {
5546 SWRAP_LOG(SWRAP_LOG_TRACE,
5547 "Ignoring SCM_RIGHTS on inet socket!");
5550 #ifdef SCM_CREDENTIALS
5551 case SCM_CREDENTIALS:
5552 SWRAP_LOG(SWRAP_LOG_TRACE,
5553 "Ignoring SCM_CREDENTIALS on inet socket!");
5556 #endif /* SCM_CREDENTIALS */
5558 rc = swrap_sendmsg_copy_cmsg(cmsg,
5567 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5570 * We only allow up to 6 fds at a time
5571 * as that's more than enough for Samba
5572 * and it means we can keep the logic simple
5573 * and work with fixed size arrays.
5575 * We also keep sizeof(struct swrap_unix_scm_rights)
5576 * under PIPE_BUF (4096) in order to allow a non-blocking
5577 * write into the pipe.
5580 #define PIPE_BUF 4096
5582 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5583 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5584 struct swrap_unix_scm_rights_payload {
5586 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5587 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5589 struct swrap_unix_scm_rights {
5591 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5592 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5594 uint32_t payload_size;
5595 struct swrap_unix_scm_rights_payload payload;
5598 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5600 int saved_errno = errno;
5603 for (i = 0; i < num; i++) {
5604 struct socket_info *si = array[i];
5610 swrap_dec_refcount(si);
5611 if (si->fd_passed > 0) {
5614 SWRAP_UNLOCK_SI(si);
5618 errno = saved_errno;
5621 static void swrap_undo_si_idx_array(size_t num, int *array)
5623 int saved_errno = errno;
5626 swrap_mutex_lock(&first_free_mutex);
5628 for (i = 0; i < num; i++) {
5629 struct socket_info *si = NULL;
5631 if (array[i] == -1) {
5635 si = swrap_get_socket_info(array[i]);
5641 swrap_dec_refcount(si);
5642 SWRAP_UNLOCK_SI(si);
5644 swrap_set_next_free(si, first_free);
5645 first_free = array[i];
5649 swrap_mutex_unlock(&first_free_mutex);
5650 errno = saved_errno;
5653 static void swrap_close_fd_array(size_t num, const int *array)
5655 int saved_errno = errno;
5658 for (i = 0; i < num; i++) {
5659 if (array[i] == -1) {
5662 libc_close(array[i]);
5665 errno = saved_errno;
5673 union __swrap_cmsghdr {
5675 struct cmsghdr *cmsg;
5678 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5680 size_t *cm_data_space,
5681 int *scm_rights_pipe_fd)
5683 struct swrap_unix_scm_rights info;
5684 struct swrap_unix_scm_rights_payload *payload = NULL;
5685 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5686 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5687 size_t info_idx = 0;
5690 union __swrap_fds __fds_in = { .p = NULL, };
5691 const int *fds_in = NULL;
5693 size_t size_fds_out;
5694 union __swrap_fds __fds_out = { .p = NULL, };
5695 int *fds_out = NULL;
5698 size_t new_cm_data_space;
5699 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5700 struct cmsghdr *new_cmsg = NULL;
5703 int pipefd[2] = { -1, -1 };
5708 * We pass this a buffer to the kernel make sure any padding
5712 info.magic = swrap_unix_scm_right_magic;
5713 memcpy(info.package_name,
5714 SOCKET_WRAPPER_PACKAGE,
5715 sizeof(info.package_name));
5716 memcpy(info.package_version,
5717 SOCKET_WRAPPER_VERSION,
5718 sizeof(info.package_version));
5719 info.full_size = sizeof(info);
5720 info.payload_size = sizeof(info.payload);
5721 payload = &info.payload;
5723 if (*scm_rights_pipe_fd != -1) {
5724 SWRAP_LOG(SWRAP_LOG_ERROR,
5725 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5730 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5731 SWRAP_LOG(SWRAP_LOG_ERROR,
5732 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5733 (size_t)cmsg->cmsg_len,
5738 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5739 if ((size_fds_in % sizeof(int)) != 0) {
5740 SWRAP_LOG(SWRAP_LOG_ERROR,
5741 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5742 (size_t)cmsg->cmsg_len,
5748 num_fds_in = size_fds_in / sizeof(int);
5749 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5750 SWRAP_LOG(SWRAP_LOG_ERROR,
5751 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5753 "SWRAP_MAX_PASSED_FDS(%zu)",
5754 (size_t)cmsg->cmsg_len,
5757 SWRAP_MAX_PASSED_FDS);
5761 if (num_fds_in == 0) {
5762 SWRAP_LOG(SWRAP_LOG_ERROR,
5763 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5765 (size_t)cmsg->cmsg_len,
5771 __fds_in.p = CMSG_DATA(cmsg);
5772 fds_in = __fds_in.fds;
5773 num_fds_out = num_fds_in + 1;
5775 SWRAP_LOG(SWRAP_LOG_TRACE,
5776 "num_fds_in=%zu num_fds_out=%zu",
5777 num_fds_in, num_fds_out);
5779 size_fds_out = sizeof(int) * num_fds_out;
5780 cmsg_len = CMSG_LEN(size_fds_out);
5781 cmsg_space = CMSG_SPACE(size_fds_out);
5783 new_cm_data_space = *cm_data_space + cmsg_space;
5785 p = realloc((*cm_data), new_cm_data_space);
5790 p = (*cm_data) + (*cm_data_space);
5791 memset(p, 0, cmsg_space);
5793 new_cmsg = __new_cmsg.cmsg;
5795 __fds_out.p = CMSG_DATA(new_cmsg);
5796 fds_out = __fds_out.fds;
5797 memcpy(fds_out, fds_in, size_fds_in);
5798 new_cmsg->cmsg_len = cmsg->cmsg_len;
5800 for (i = 0; i < num_fds_in; i++) {
5803 payload->idxs[i] = -1;
5804 payload->num_idxs++;
5806 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5807 if (si_idx_array[i] == -1) {
5811 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5812 if (si_array[i] == NULL) {
5813 SWRAP_LOG(SWRAP_LOG_ERROR,
5814 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5815 i, fds_in[i], i, si_idx_array[i]);
5820 for (j = 0; j < i; j++) {
5821 if (si_array[j] == si_array[i]) {
5822 payload->idxs[i] = payload->idxs[j];
5826 if (payload->idxs[i] == -1) {
5827 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5828 SWRAP_LOG(SWRAP_LOG_ERROR,
5829 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5830 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5831 i, fds_in[i], i, si_idx_array[i],
5833 SWRAP_MAX_PASSED_SOCKET_INFO);
5837 payload->idxs[i] = info_idx;
5843 for (i = 0; i < num_fds_in; i++) {
5844 struct socket_info *si = si_array[i];
5847 SWRAP_LOG(SWRAP_LOG_TRACE,
5848 "fds_in[%zu]=%d not an inet socket",
5853 SWRAP_LOG(SWRAP_LOG_TRACE,
5854 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5855 "passing as info.idxs[%zu]=%d!",
5858 i, payload->idxs[i]);
5862 payload->infos[payload->idxs[i]] = *si;
5863 payload->infos[payload->idxs[i]].fd_passed = 0;
5864 SWRAP_UNLOCK_SI(si);
5869 int saved_errno = errno;
5870 SWRAP_LOG(SWRAP_LOG_ERROR,
5871 "pipe() failed - %d %s",
5873 strerror(saved_errno));
5874 swrap_dec_fd_passed_array(num_fds_in, si_array);
5875 errno = saved_errno;
5879 sret = libc_write(pipefd[1], &info, sizeof(info));
5880 if (sret != sizeof(info)) {
5881 int saved_errno = errno;
5883 saved_errno = EINVAL;
5885 SWRAP_LOG(SWRAP_LOG_ERROR,
5886 "write() failed - sret=%zd - %d %s",
5888 strerror(saved_errno));
5889 swrap_dec_fd_passed_array(num_fds_in, si_array);
5890 libc_close(pipefd[1]);
5891 libc_close(pipefd[0]);
5892 errno = saved_errno;
5895 libc_close(pipefd[1]);
5898 * Add the pipe read end to the end of the passed fd array
5900 fds_out[num_fds_in] = pipefd[0];
5901 new_cmsg->cmsg_len = cmsg_len;
5903 /* we're done ... */
5904 *scm_rights_pipe_fd = pipefd[0];
5905 *cm_data_space = new_cm_data_space;
5910 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5912 size_t *cm_data_space,
5913 int *scm_rights_pipe_fd)
5917 switch (cmsg->cmsg_type) {
5919 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5922 scm_rights_pipe_fd);
5925 rc = swrap_sendmsg_copy_cmsg(cmsg,
5934 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5936 size_t *cm_data_space)
5938 int scm_rights_pipe_fd = -1;
5939 struct swrap_unix_scm_rights info;
5940 struct swrap_unix_scm_rights_payload *payload = NULL;
5941 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5944 union __swrap_fds __fds_in = { .p = NULL, };
5945 const int *fds_in = NULL;
5947 size_t size_fds_out;
5948 union __swrap_fds __fds_out = { .p = NULL, };
5949 int *fds_out = NULL;
5952 size_t new_cm_data_space;
5953 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5954 struct cmsghdr *new_cmsg = NULL;
5960 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5961 SWRAP_LOG(SWRAP_LOG_ERROR,
5962 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5963 (size_t)cmsg->cmsg_len,
5968 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5969 if ((size_fds_in % sizeof(int)) != 0) {
5970 SWRAP_LOG(SWRAP_LOG_ERROR,
5971 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5972 (size_t)cmsg->cmsg_len,
5978 num_fds_in = size_fds_in / sizeof(int);
5979 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5980 SWRAP_LOG(SWRAP_LOG_ERROR,
5981 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5982 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5983 (size_t)cmsg->cmsg_len,
5986 SWRAP_MAX_PASSED_FDS+1);
5990 if (num_fds_in <= 1) {
5991 SWRAP_LOG(SWRAP_LOG_ERROR,
5992 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5994 (size_t)cmsg->cmsg_len,
6000 __fds_in.p = CMSG_DATA(cmsg);
6001 fds_in = __fds_in.fds;
6002 num_fds_out = num_fds_in - 1;
6004 SWRAP_LOG(SWRAP_LOG_TRACE,
6005 "num_fds_in=%zu num_fds_out=%zu",
6006 num_fds_in, num_fds_out);
6008 for (i = 0; i < num_fds_in; i++) {
6009 /* Check if we have a stale fd and remove it */
6010 swrap_remove_stale(fds_in[i]);
6013 scm_rights_pipe_fd = fds_in[num_fds_out];
6014 size_fds_out = sizeof(int) * num_fds_out;
6015 cmsg_len = CMSG_LEN(size_fds_out);
6016 cmsg_space = CMSG_SPACE(size_fds_out);
6018 new_cm_data_space = *cm_data_space + cmsg_space;
6020 p = realloc((*cm_data), new_cm_data_space);
6022 swrap_close_fd_array(num_fds_in, fds_in);
6026 p = (*cm_data) + (*cm_data_space);
6027 memset(p, 0, cmsg_space);
6029 new_cmsg = __new_cmsg.cmsg;
6031 __fds_out.p = CMSG_DATA(new_cmsg);
6032 fds_out = __fds_out.fds;
6033 memcpy(fds_out, fds_in, size_fds_out);
6034 new_cmsg->cmsg_len = cmsg_len;
6036 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
6037 if (sret != sizeof(info)) {
6038 int saved_errno = errno;
6040 saved_errno = EINVAL;
6042 SWRAP_LOG(SWRAP_LOG_ERROR,
6043 "read() failed - sret=%zd - %d %s",
6045 strerror(saved_errno));
6046 swrap_close_fd_array(num_fds_in, fds_in);
6047 errno = saved_errno;
6050 libc_close(scm_rights_pipe_fd);
6051 payload = &info.payload;
6053 if (info.magic != swrap_unix_scm_right_magic) {
6054 SWRAP_LOG(SWRAP_LOG_ERROR,
6055 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
6056 (unsigned long long)info.magic,
6057 (unsigned long long)swrap_unix_scm_right_magic);
6058 swrap_close_fd_array(num_fds_out, fds_out);
6063 cmp = memcmp(info.package_name,
6064 SOCKET_WRAPPER_PACKAGE,
6065 sizeof(info.package_name));
6067 SWRAP_LOG(SWRAP_LOG_ERROR,
6068 "info.package_name='%.*s' != '%s'",
6069 (int)sizeof(info.package_name),
6071 SOCKET_WRAPPER_PACKAGE);
6072 swrap_close_fd_array(num_fds_out, fds_out);
6077 cmp = memcmp(info.package_version,
6078 SOCKET_WRAPPER_VERSION,
6079 sizeof(info.package_version));
6081 SWRAP_LOG(SWRAP_LOG_ERROR,
6082 "info.package_version='%.*s' != '%s'",
6083 (int)sizeof(info.package_version),
6084 info.package_version,
6085 SOCKET_WRAPPER_VERSION);
6086 swrap_close_fd_array(num_fds_out, fds_out);
6091 if (info.full_size != sizeof(info)) {
6092 SWRAP_LOG(SWRAP_LOG_ERROR,
6093 "info.full_size=%zu != sizeof(info)=%zu",
6094 (size_t)info.full_size,
6096 swrap_close_fd_array(num_fds_out, fds_out);
6101 if (info.payload_size != sizeof(info.payload)) {
6102 SWRAP_LOG(SWRAP_LOG_ERROR,
6103 "info.payload_size=%zu != sizeof(info.payload)=%zu",
6104 (size_t)info.payload_size,
6105 sizeof(info.payload));
6106 swrap_close_fd_array(num_fds_out, fds_out);
6111 if (payload->num_idxs != num_fds_out) {
6112 SWRAP_LOG(SWRAP_LOG_ERROR,
6113 "info.num_idxs=%u != num_fds_out=%zu",
6114 payload->num_idxs, num_fds_out);
6115 swrap_close_fd_array(num_fds_out, fds_out);
6120 for (i = 0; i < num_fds_out; i++) {
6123 si_idx_array[i] = -1;
6125 if (payload->idxs[i] == -1) {
6126 SWRAP_LOG(SWRAP_LOG_TRACE,
6127 "fds_out[%zu]=%d not an inet socket",
6132 if (payload->idxs[i] < 0) {
6133 SWRAP_LOG(SWRAP_LOG_ERROR,
6134 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
6135 i, fds_out[i], i, payload->idxs[i]);
6136 swrap_close_fd_array(num_fds_out, fds_out);
6141 if (payload->idxs[i] >= payload->num_idxs) {
6142 SWRAP_LOG(SWRAP_LOG_ERROR,
6143 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
6144 i, fds_out[i], i, payload->idxs[i],
6146 swrap_close_fd_array(num_fds_out, fds_out);
6151 if ((size_t)fds_out[i] >= socket_fds_max) {
6152 SWRAP_LOG(SWRAP_LOG_ERROR,
6153 "The max socket index limit of %zu has been reached, "
6157 swrap_close_fd_array(num_fds_out, fds_out);
6162 SWRAP_LOG(SWRAP_LOG_TRACE,
6164 "received as info.idxs[%zu]=%d!",
6166 i, payload->idxs[i]);
6168 for (j = 0; j < i; j++) {
6169 if (payload->idxs[j] == -1) {
6172 if (payload->idxs[j] == payload->idxs[i]) {
6173 si_idx_array[i] = si_idx_array[j];
6176 if (si_idx_array[i] == -1) {
6177 const struct socket_info *si = &payload->infos[payload->idxs[i]];
6179 si_idx_array[i] = swrap_add_socket_info(si);
6180 if (si_idx_array[i] == -1) {
6181 int saved_errno = errno;
6182 SWRAP_LOG(SWRAP_LOG_ERROR,
6183 "The max socket index limit of %zu has been reached, "
6187 swrap_undo_si_idx_array(i, si_idx_array);
6188 swrap_close_fd_array(num_fds_out, fds_out);
6189 errno = saved_errno;
6192 SWRAP_LOG(SWRAP_LOG_TRACE,
6193 "Imported %s socket for protocol %s, fd=%d",
6194 si->family == AF_INET ? "IPv4" : "IPv6",
6195 si->type == SOCK_DGRAM ? "UDP" : "TCP",
6200 for (i = 0; i < num_fds_out; i++) {
6201 if (si_idx_array[i] == -1) {
6204 set_socket_info_index(fds_out[i], si_idx_array[i]);
6207 /* we're done ... */
6208 *cm_data_space = new_cm_data_space;
6213 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6215 size_t *cm_data_space)
6219 switch (cmsg->cmsg_type) {
6221 rc = swrap_recvmsg_unix_scm_rights(cmsg,
6226 rc = swrap_sendmsg_copy_cmsg(cmsg,
6235 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6237 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6238 struct msghdr *msg_tmp,
6239 int *scm_rights_pipe_fd)
6241 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6242 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6243 struct cmsghdr *cmsg = NULL;
6244 uint8_t *cm_data = NULL;
6245 size_t cm_data_space = 0;
6249 *scm_rights_pipe_fd = -1;
6252 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6256 for (cmsg = CMSG_FIRSTHDR(msg_in);
6258 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6259 switch (cmsg->cmsg_level) {
6261 rc = swrap_sendmsg_unix_sol_socket(cmsg,
6264 scm_rights_pipe_fd);
6268 rc = swrap_sendmsg_copy_cmsg(cmsg,
6274 int saved_errno = errno;
6276 errno = saved_errno;
6281 msg_tmp->msg_controllen = cm_data_space;
6282 msg_tmp->msg_control = cm_data;
6285 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6286 *msg_tmp = *_msg_in;
6288 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6291 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6293 int scm_rights_pipe_fd)
6295 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6296 int saved_errno = errno;
6297 SAFE_FREE(msg_tmp->msg_control);
6298 if (scm_rights_pipe_fd != -1) {
6299 libc_close(scm_rights_pipe_fd);
6301 errno = saved_errno;
6302 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6306 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6307 struct msghdr *msg_tmp,
6308 uint8_t **tmp_control)
6310 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6311 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6312 uint8_t *cm_data = NULL;
6313 size_t cm_data_space = 0;
6316 *tmp_control = NULL;
6318 SWRAP_LOG(SWRAP_LOG_TRACE,
6319 "msg_in->msg_controllen=%zu",
6320 (size_t)msg_in->msg_controllen);
6323 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6328 * We need to give the kernel a bit more space in order
6329 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6330 * swrap_recvmsg_after_unix() will hide it again.
6332 cm_data_space = msg_in->msg_controllen;
6333 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6334 cm_data_space += cm_extra_space;
6336 cm_data = calloc(1, cm_data_space);
6337 if (cm_data == NULL) {
6341 msg_tmp->msg_controllen = cm_data_space;
6342 msg_tmp->msg_control = cm_data;
6343 *tmp_control = cm_data;
6345 SWRAP_LOG(SWRAP_LOG_TRACE,
6346 "msg_tmp->msg_controllen=%zu",
6347 (size_t)msg_tmp->msg_controllen);
6349 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6351 *tmp_control = NULL;
6353 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6356 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6357 uint8_t **tmp_control,
6358 struct msghdr *msg_out,
6361 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6362 struct cmsghdr *cmsg = NULL;
6363 uint8_t *cm_data = NULL;
6364 size_t cm_data_space = 0;
6368 int saved_errno = errno;
6369 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6370 saved_errno, strerror(saved_errno));
6371 SAFE_FREE(*tmp_control);
6372 /* msg_out should not be touched on error */
6373 errno = saved_errno;
6377 SWRAP_LOG(SWRAP_LOG_TRACE,
6378 "msg_tmp->msg_controllen=%zu",
6379 (size_t)msg_tmp->msg_controllen);
6382 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6383 int saved_errno = errno;
6384 *msg_out = *msg_tmp;
6385 SAFE_FREE(*tmp_control);
6386 errno = saved_errno;
6390 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6392 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6393 switch (cmsg->cmsg_level) {
6395 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6401 rc = swrap_sendmsg_copy_cmsg(cmsg,
6407 int saved_errno = errno;
6409 SAFE_FREE(*tmp_control);
6410 errno = saved_errno;
6416 * msg_tmp->msg_control (*tmp_control) was created by
6417 * swrap_recvmsg_before_unix() and msg_out->msg_control
6418 * is still the buffer of the caller.
6420 msg_tmp->msg_control = msg_out->msg_control;
6421 msg_tmp->msg_controllen = msg_out->msg_controllen;
6422 *msg_out = *msg_tmp;
6424 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6425 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6426 msg_out->msg_controllen = cm_data_space;
6428 SAFE_FREE(*tmp_control);
6430 SWRAP_LOG(SWRAP_LOG_TRACE,
6431 "msg_out->msg_controllen=%zu",
6432 (size_t)msg_out->msg_controllen);
6434 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6435 int saved_errno = errno;
6436 *msg_out = *msg_tmp;
6437 SAFE_FREE(*tmp_control);
6438 errno = saved_errno;
6440 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6443 static ssize_t swrap_sendmsg_before(int fd,
6444 struct socket_info *si,
6446 struct iovec *tmp_iov,
6447 struct sockaddr_un *tmp_un,
6448 const struct sockaddr_un **to_un,
6449 const struct sockaddr **to,
6454 struct swrap_sockaddr_buf buf = {};
6472 if (!si->connected) {
6477 if (msg->msg_iovlen == 0) {
6481 mtu = socket_wrapper_mtu();
6482 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6484 nlen = len + msg->msg_iov[i].iov_len;
6494 msg->msg_iovlen = i;
6495 if (msg->msg_iovlen == 0) {
6496 *tmp_iov = msg->msg_iov[0];
6497 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6499 msg->msg_iov = tmp_iov;
6500 msg->msg_iovlen = 1;
6505 if (si->connected) {
6506 if (msg->msg_name != NULL) {
6508 * We are dealing with unix sockets and if we
6509 * are connected, we should only talk to the
6510 * connected unix path. Using the fd to send
6511 * to another server would be hard to achieve.
6513 msg->msg_name = NULL;
6514 msg->msg_namelen = 0;
6516 SWRAP_LOG(SWRAP_LOG_TRACE,
6517 "connected(%s) fd=%d",
6518 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6521 const struct sockaddr *msg_name;
6522 msg_name = (const struct sockaddr *)msg->msg_name;
6524 if (msg_name == NULL) {
6530 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6542 msg->msg_name = tmp_un;
6543 msg->msg_namelen = sizeof(*tmp_un);
6546 if (si->bound == 0) {
6547 ret = swrap_auto_bind(fd, si, si->family);
6549 SWRAP_UNLOCK_SI(si);
6550 if (errno == ENOTSOCK) {
6551 swrap_remove_stale(fd);
6554 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6560 if (!si->defer_connect) {
6564 ret = sockaddr_convert_to_un(si,
6566 si->peername.sa_socklen,
6574 SWRAP_LOG(SWRAP_LOG_TRACE,
6575 "deferred connect(%s) path=%s, fd=%d",
6576 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6577 tmp_un->sun_path, fd);
6579 ret = libc_connect(fd,
6580 (struct sockaddr *)(void *)tmp_un,
6583 /* to give better errors */
6584 if (ret == -1 && errno == ENOENT) {
6585 errno = EHOSTUNREACH;
6592 si->defer_connect = 0;
6595 errno = EHOSTUNREACH;
6601 SWRAP_UNLOCK_SI(si);
6606 static void swrap_sendmsg_after(int fd,
6607 struct socket_info *si,
6609 const struct sockaddr *to,
6612 int saved_errno = errno;
6619 /* to give better errors */
6621 if (saved_errno == ENOENT) {
6622 saved_errno = EHOSTUNREACH;
6623 } else if (saved_errno == ENOTSOCK) {
6624 /* If the fd is not a socket, remove it */
6625 swrap_remove_stale(fd);
6629 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6630 avail += msg->msg_iov[i].iov_len;
6634 remain = MIN(80, avail);
6639 /* we capture it as one single packet */
6640 buf = (uint8_t *)malloc(remain);
6642 /* we just not capture the packet */
6643 errno = saved_errno;
6647 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6648 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6649 if (this_time > 0) {
6651 msg->msg_iov[i].iov_base,
6655 remain -= this_time;
6664 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6665 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6667 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6672 if (si->connected) {
6673 to = &si->peername.sa.s;
6676 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6677 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6679 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6684 SWRAP_UNLOCK_SI(si);
6687 errno = saved_errno;
6690 static int swrap_recvmsg_before(int fd,
6691 struct socket_info *si,
6693 struct iovec *tmp_iov)
6700 (void)fd; /* unused */
6705 if (!si->connected) {
6710 if (msg->msg_iovlen == 0) {
6714 mtu = socket_wrapper_mtu();
6715 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6717 nlen = len + msg->msg_iov[i].iov_len;
6722 msg->msg_iovlen = i;
6723 if (msg->msg_iovlen == 0) {
6724 *tmp_iov = msg->msg_iov[0];
6725 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6727 msg->msg_iov = tmp_iov;
6728 msg->msg_iovlen = 1;
6733 if (msg->msg_name == NULL) {
6738 if (msg->msg_iovlen == 0) {
6742 if (si->bound == 0) {
6743 ret = swrap_auto_bind(fd, si, si->family);
6745 SWRAP_UNLOCK_SI(si);
6747 * When attempting to read or write to a
6748 * descriptor, if an underlying autobind fails
6749 * because it's not a socket, stop intercepting
6750 * uses of that descriptor.
6752 if (errno == ENOTSOCK) {
6753 swrap_remove_stale(fd);
6756 SWRAP_LOG(SWRAP_LOG_ERROR,
6757 "swrap_recvmsg_before failed");
6764 errno = EHOSTUNREACH;
6770 SWRAP_UNLOCK_SI(si);
6775 static int swrap_recvmsg_after(int fd,
6776 struct socket_info *si,
6778 const struct sockaddr_un *un_addr,
6779 socklen_t un_addrlen,
6782 int saved_errno = errno;
6784 uint8_t *buf = NULL;
6790 /* to give better errors */
6792 if (saved_errno == ENOENT) {
6793 saved_errno = EHOSTUNREACH;
6794 } else if (saved_errno == ENOTSOCK) {
6795 /* If the fd is not a socket, remove it */
6796 swrap_remove_stale(fd);
6800 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6801 avail += msg->msg_iov[i].iov_len;
6806 /* Convert the socket address before we leave */
6807 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6808 rc = sockaddr_convert_from_un(si,
6825 remain = MIN(80, avail);
6830 /* we capture it as one single packet */
6831 buf = (uint8_t *)malloc(remain);
6833 /* we just not capture the packet */
6834 SWRAP_UNLOCK_SI(si);
6835 errno = saved_errno;
6839 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6840 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6842 msg->msg_iov[i].iov_base,
6845 remain -= this_time;
6850 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6851 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6852 } else if (ret == 0) { /* END OF FILE */
6853 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6854 } else if (ret > 0) {
6855 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6864 if (un_addr != NULL) {
6865 swrap_pcap_dump_packet(si,
6871 swrap_pcap_dump_packet(si,
6884 errno = saved_errno;
6886 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6888 msg->msg_controllen > 0 &&
6889 msg->msg_control != NULL) {
6890 rc = swrap_msghdr_add_socket_info(si, msg);
6892 SWRAP_UNLOCK_SI(si);
6898 SWRAP_UNLOCK_SI(si);
6902 /****************************************************************************
6904 ***************************************************************************/
6906 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6907 struct sockaddr *from, socklen_t *fromlen)
6909 struct swrap_address from_addr = {
6910 .sa_socklen = sizeof(struct sockaddr_un),
6913 struct socket_info *si = find_socket_info(s);
6914 struct swrap_address saddr = {
6915 .sa_socklen = sizeof(struct sockaddr_storage),
6922 return libc_recvfrom(s,
6934 if (from != NULL && fromlen != NULL) {
6935 msg.msg_name = from; /* optional address */
6936 msg.msg_namelen = *fromlen; /* size of address */
6938 msg.msg_name = &saddr.sa.s; /* optional address */
6939 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6941 msg.msg_iov = &tmp; /* scatter/gather array */
6942 msg.msg_iovlen = 1; /* # elements in msg_iov */
6943 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6944 msg.msg_control = NULL; /* ancillary data, see below */
6945 msg.msg_controllen = 0; /* ancillary data buffer len */
6946 msg.msg_flags = 0; /* flags on received message */
6949 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6954 buf = msg.msg_iov[0].iov_base;
6955 len = msg.msg_iov[0].iov_len;
6957 ret = libc_recvfrom(s,
6962 &from_addr.sa_socklen);
6967 tret = swrap_recvmsg_after(s,
6971 from_addr.sa_socklen,
6977 if (from != NULL && fromlen != NULL) {
6978 *fromlen = msg.msg_namelen;
6984 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6985 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6986 struct sockaddr *from, Psocklen_t fromlen)
6988 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6989 struct sockaddr *from, socklen_t *fromlen)
6992 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6995 /****************************************************************************
6997 ***************************************************************************/
6999 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
7000 const struct sockaddr *to, socklen_t tolen)
7004 struct swrap_address un_addr = {
7005 .sa_socklen = sizeof(struct sockaddr_un),
7007 const struct sockaddr_un *to_un = NULL;
7010 struct socket_info *si = find_socket_info(s);
7014 return libc_sendto(s, buf, len, flags, to, tolen);
7017 tmp.iov_base = discard_const_p(char, buf);
7021 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
7022 msg.msg_namelen = tolen; /* size of address */
7023 msg.msg_iov = &tmp; /* scatter/gather array */
7024 msg.msg_iovlen = 1; /* # elements in msg_iov */
7025 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7026 msg.msg_control = NULL; /* ancillary data, see below */
7027 msg.msg_controllen = 0; /* ancillary data buffer len */
7028 msg.msg_flags = 0; /* flags on received message */
7031 rc = swrap_sendmsg_before(s,
7043 buf = msg.msg_iov[0].iov_base;
7044 len = msg.msg_iov[0].iov_len;
7049 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7051 char *swrap_dir = NULL;
7053 type = SOCKET_TYPE_CHAR_UDP;
7055 swrap_dir = socket_wrapper_dir();
7056 if (swrap_dir == NULL) {
7060 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7061 swrap_un_path(&un_addr.sa.un,
7066 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
7068 /* ignore the any errors in broadcast sends */
7074 un_addr.sa_socklen);
7077 SAFE_FREE(swrap_dir);
7081 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7083 SWRAP_UNLOCK_SI(si);
7090 * If it is a dgram socket and we are connected, don't include the
7093 if (si->type == SOCK_DGRAM && si->connected) {
7094 ret = libc_sendto(s,
7101 ret = libc_sendto(s,
7105 (struct sockaddr *)msg.msg_name,
7109 SWRAP_UNLOCK_SI(si);
7111 swrap_sendmsg_after(s, si, &msg, to, ret);
7116 ssize_t sendto(int s, const void *buf, size_t len, int flags,
7117 const struct sockaddr *to, socklen_t tolen)
7119 return swrap_sendto(s, buf, len, flags, to, tolen);
7122 /****************************************************************************
7124 ***************************************************************************/
7126 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
7128 struct socket_info *si;
7130 struct swrap_address saddr = {
7131 .sa_socklen = sizeof(struct sockaddr_storage),
7137 si = find_socket_info(s);
7139 return libc_recv(s, buf, len, flags);
7146 msg.msg_name = &saddr.sa.s; /* optional address */
7147 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7148 msg.msg_iov = &tmp; /* scatter/gather array */
7149 msg.msg_iovlen = 1; /* # elements in msg_iov */
7150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7151 msg.msg_control = NULL; /* ancillary data, see below */
7152 msg.msg_controllen = 0; /* ancillary data buffer len */
7153 msg.msg_flags = 0; /* flags on received message */
7156 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7161 buf = msg.msg_iov[0].iov_base;
7162 len = msg.msg_iov[0].iov_len;
7164 ret = libc_recv(s, buf, len, flags);
7166 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7174 ssize_t recv(int s, void *buf, size_t len, int flags)
7176 return swrap_recv(s, buf, len, flags);
7179 /****************************************************************************
7181 ***************************************************************************/
7183 static ssize_t swrap_read(int s, void *buf, size_t len)
7185 struct socket_info *si;
7188 struct swrap_address saddr = {
7189 .sa_socklen = sizeof(struct sockaddr_storage),
7194 si = find_socket_info(s);
7196 return libc_read(s, buf, len);
7203 msg.msg_name = &saddr.sa.ss; /* optional address */
7204 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7205 msg.msg_iov = &tmp; /* scatter/gather array */
7206 msg.msg_iovlen = 1; /* # elements in msg_iov */
7207 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7208 msg.msg_control = NULL; /* ancillary data, see below */
7209 msg.msg_controllen = 0; /* ancillary data buffer len */
7210 msg.msg_flags = 0; /* flags on received message */
7213 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7215 if (tret == -ENOTSOCK) {
7216 return libc_read(s, buf, len);
7221 buf = msg.msg_iov[0].iov_base;
7222 len = msg.msg_iov[0].iov_len;
7224 ret = libc_read(s, buf, len);
7226 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7234 ssize_t read(int s, void *buf, size_t len)
7236 return swrap_read(s, buf, len);
7239 /****************************************************************************
7241 ***************************************************************************/
7243 static ssize_t swrap_write(int s, const void *buf, size_t len)
7247 struct sockaddr_un un_addr;
7250 struct socket_info *si;
7252 si = find_socket_info(s);
7254 return libc_write(s, buf, len);
7257 tmp.iov_base = discard_const_p(char, buf);
7261 msg.msg_name = NULL; /* optional address */
7262 msg.msg_namelen = 0; /* size of address */
7263 msg.msg_iov = &tmp; /* scatter/gather array */
7264 msg.msg_iovlen = 1; /* # elements in msg_iov */
7265 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7266 msg.msg_control = NULL; /* ancillary data, see below */
7267 msg.msg_controllen = 0; /* ancillary data buffer len */
7268 msg.msg_flags = 0; /* flags on received message */
7271 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7276 buf = msg.msg_iov[0].iov_base;
7277 len = msg.msg_iov[0].iov_len;
7279 ret = libc_write(s, buf, len);
7281 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7286 ssize_t write(int s, const void *buf, size_t len)
7288 return swrap_write(s, buf, len);
7291 /****************************************************************************
7293 ***************************************************************************/
7295 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7299 struct sockaddr_un un_addr;
7302 struct socket_info *si = find_socket_info(s);
7305 return libc_send(s, buf, len, flags);
7308 tmp.iov_base = discard_const_p(char, buf);
7312 msg.msg_name = NULL; /* optional address */
7313 msg.msg_namelen = 0; /* size of address */
7314 msg.msg_iov = &tmp; /* scatter/gather array */
7315 msg.msg_iovlen = 1; /* # elements in msg_iov */
7316 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7317 msg.msg_control = NULL; /* ancillary data, see below */
7318 msg.msg_controllen = 0; /* ancillary data buffer len */
7319 msg.msg_flags = 0; /* flags on received message */
7322 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7327 buf = msg.msg_iov[0].iov_base;
7328 len = msg.msg_iov[0].iov_len;
7330 ret = libc_send(s, buf, len, flags);
7332 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7337 ssize_t send(int s, const void *buf, size_t len, int flags)
7339 return swrap_send(s, buf, len, flags);
7342 /****************************************************************************
7344 ***************************************************************************/
7346 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7348 struct swrap_address from_addr = {
7349 .sa_socklen = sizeof(struct sockaddr_un),
7351 struct swrap_address convert_addr = {
7352 .sa_socklen = sizeof(struct sockaddr_storage),
7354 struct socket_info *si;
7357 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7358 size_t msg_ctrllen_filled;
7359 size_t msg_ctrllen_left;
7365 si = find_socket_info(s);
7367 uint8_t *tmp_control = NULL;
7368 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7372 ret = libc_recvmsg(s, &msg, flags);
7373 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7376 tmp.iov_base = NULL;
7380 msg.msg_name = &from_addr.sa; /* optional address */
7381 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7382 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7383 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7384 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7385 msg_ctrllen_filled = 0;
7386 msg_ctrllen_left = omsg->msg_controllen;
7388 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7389 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7390 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7393 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7398 ret = libc_recvmsg(s, &msg, flags);
7400 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7401 msg_ctrllen_filled += msg.msg_controllen;
7402 msg_ctrllen_left -= msg.msg_controllen;
7404 if (omsg->msg_control != NULL) {
7407 p = omsg->msg_control;
7408 p += msg_ctrllen_filled;
7410 msg.msg_control = p;
7411 msg.msg_controllen = msg_ctrllen_left;
7413 msg.msg_control = NULL;
7414 msg.msg_controllen = 0;
7419 * We convert the unix address to a IP address so we need a buffer
7420 * which can store the address in case of SOCK_DGRAM, see below.
7422 msg.msg_name = &convert_addr.sa;
7423 msg.msg_namelen = convert_addr.sa_socklen;
7425 rc = swrap_recvmsg_after(s,
7429 from_addr.sa_socklen,
7435 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7436 if (omsg->msg_control != NULL) {
7437 /* msg.msg_controllen = space left */
7438 msg_ctrllen_left = msg.msg_controllen;
7439 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7442 /* Update the original message length */
7443 omsg->msg_controllen = msg_ctrllen_filled;
7444 omsg->msg_flags = msg.msg_flags;
7446 omsg->msg_iovlen = msg.msg_iovlen;
7453 * The msg_name field points to a caller-allocated buffer that is
7454 * used to return the source address if the socket is unconnected. The
7455 * caller should set msg_namelen to the size of this buffer before this
7456 * call; upon return from a successful call, msg_name will contain the
7457 * length of the returned address. If the application does not need
7458 * to know the source address, msg_name can be specified as NULL.
7460 if (si->type == SOCK_STREAM) {
7461 omsg->msg_namelen = 0;
7462 } else if (omsg->msg_name != NULL &&
7463 omsg->msg_namelen != 0 &&
7464 omsg->msg_namelen >= msg.msg_namelen) {
7465 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7466 omsg->msg_namelen = msg.msg_namelen;
7469 SWRAP_UNLOCK_SI(si);
7474 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7476 return swrap_recvmsg(sockfd, msg, flags);
7479 /****************************************************************************
7481 ***************************************************************************/
7483 #ifdef HAVE_RECVMMSG
7484 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7486 static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7487 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7488 /* Linux legacy glibc < 2.21 */
7489 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7491 /* Linux glibc >= 2.21 */
7492 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7495 struct socket_info *si = find_socket_info(s);
7496 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7497 struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7500 struct swrap_address from_addr;
7501 struct swrap_address convert_addr;
7502 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7503 size_t msg_ctrllen_filled;
7504 size_t msg_ctrllen_left;
7506 } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7513 if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7514 vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7520 uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7522 for (i = 0; i < vlen; i++) {
7523 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7524 struct msghdr *msg = &msgvec[i].msg_hdr;
7526 rc = swrap_recvmsg_before_unix(omsg, msg,
7534 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7539 for (i = 0; i < ret; i++) {
7540 omsgvec[i].msg_len = msgvec[i].msg_len;
7544 saved_errno = errno;
7545 for (i = 0; i < vlen; i++) {
7546 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7547 struct msghdr *msg = &msgvec[i].msg_hdr;
7549 if (i == 0 || i < ret) {
7550 swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7552 SAFE_FREE(tmp_control[i]);
7554 errno = saved_errno;
7559 for (i = 0; i < vlen; i++) {
7560 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7561 struct msghdr *msg = &msgvec[i].msg_hdr;
7563 tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7564 tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7566 msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7567 msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7568 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7569 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7570 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7571 tmp[i].msg_ctrllen_filled = 0;
7572 tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7574 msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7575 msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7576 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7579 rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7586 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7591 for (i = 0; i < ret; i++) {
7592 omsgvec[i].msg_len = msgvec[i].msg_len;
7597 saved_errno = errno;
7598 for (i = 0; i < vlen; i++) {
7599 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7600 struct msghdr *msg = &msgvec[i].msg_hdr;
7602 if (!(i == 0 || i < ret)) {
7606 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7607 tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7608 tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7610 if (omsg->msg_control != NULL) {
7613 p = omsg->msg_control;
7614 p += tmp[i].msg_ctrllen_filled;
7616 msg->msg_control = p;
7617 msg->msg_controllen = tmp[i].msg_ctrllen_left;
7619 msg->msg_control = NULL;
7620 msg->msg_controllen = 0;
7625 * We convert the unix address to a IP address so we need a buffer
7626 * which can store the address in case of SOCK_DGRAM, see below.
7628 msg->msg_name = &tmp[i].convert_addr.sa;
7629 msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7631 swrap_recvmsg_after(s, si, msg,
7632 &tmp[i].from_addr.sa.un,
7633 tmp[i].from_addr.sa_socklen,
7636 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7637 if (omsg->msg_control != NULL) {
7638 /* msg->msg_controllen = space left */
7639 tmp[i].msg_ctrllen_left = msg->msg_controllen;
7640 tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7643 /* Update the original message length */
7644 omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7645 omsg->msg_flags = msg->msg_flags;
7647 omsg->msg_iovlen = msg->msg_iovlen;
7654 * The msg_name field points to a caller-allocated buffer that is
7655 * used to return the source address if the socket is unconnected. The
7656 * caller should set msg_namelen to the size of this buffer before this
7657 * call; upon return from a successful call, msg_name will contain the
7658 * length of the returned address. If the application does not need
7659 * to know the source address, msg_name can be specified as NULL.
7661 if (si->type == SOCK_STREAM) {
7662 omsg->msg_namelen = 0;
7663 } else if (omsg->msg_name != NULL &&
7664 omsg->msg_namelen != 0 &&
7665 omsg->msg_namelen >= msg->msg_namelen) {
7666 memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7667 omsg->msg_namelen = msg->msg_namelen;
7670 SWRAP_UNLOCK_SI(si);
7672 errno = saved_errno;
7677 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7679 ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7680 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7681 /* Linux legacy glibc < 2.21 */
7682 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7684 /* Linux glibc >= 2.21 */
7685 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7688 return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7690 #endif /* HAVE_RECVMMSG */
7692 /****************************************************************************
7694 ***************************************************************************/
7696 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7700 struct sockaddr_un un_addr;
7701 const struct sockaddr_un *to_un = NULL;
7702 const struct sockaddr *to = NULL;
7705 struct socket_info *si = find_socket_info(s);
7709 int scm_rights_pipe_fd = -1;
7711 rc = swrap_sendmsg_before_unix(omsg, &msg,
7712 &scm_rights_pipe_fd);
7716 ret = libc_sendmsg(s, &msg, flags);
7717 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7720 ZERO_STRUCT(un_addr);
7722 tmp.iov_base = NULL;
7729 if (si->connected == 0) {
7730 msg.msg_name = omsg->msg_name; /* optional address */
7731 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7733 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7734 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7736 SWRAP_UNLOCK_SI(si);
7738 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7739 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7740 uint8_t *cmbuf = NULL;
7743 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7749 msg.msg_controllen = 0;
7750 msg.msg_control = NULL;
7752 msg.msg_control = cmbuf;
7753 msg.msg_controllen = cmlen;
7756 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7758 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7760 int saved_errno = errno;
7761 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7762 SAFE_FREE(msg.msg_control);
7764 errno = saved_errno;
7771 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7778 char *swrap_dir = NULL;
7780 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7781 avail += msg.msg_iov[i].iov_len;
7787 /* we capture it as one single packet */
7788 buf = (uint8_t *)malloc(remain);
7790 int saved_errno = errno;
7791 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7792 SAFE_FREE(msg.msg_control);
7794 errno = saved_errno;
7798 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7799 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7801 msg.msg_iov[i].iov_base,
7804 remain -= this_time;
7807 type = SOCKET_TYPE_CHAR_UDP;
7809 swrap_dir = socket_wrapper_dir();
7810 if (swrap_dir == NULL) {
7811 int saved_errno = errno;
7812 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7813 SAFE_FREE(msg.msg_control);
7816 errno = saved_errno;
7820 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7821 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7822 if (stat(un_addr.sun_path, &st) != 0) continue;
7824 msg.msg_name = &un_addr; /* optional address */
7825 msg.msg_namelen = sizeof(un_addr); /* size of address */
7827 /* ignore the any errors in broadcast sends */
7828 libc_sendmsg(s, &msg, flags);
7831 SAFE_FREE(swrap_dir);
7835 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7838 SWRAP_UNLOCK_SI(si);
7843 ret = libc_sendmsg(s, &msg, flags);
7845 swrap_sendmsg_after(s, si, &msg, to, ret);
7847 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7849 int saved_errno = errno;
7850 SAFE_FREE(msg.msg_control);
7851 errno = saved_errno;
7858 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7860 return swrap_sendmsg(s, omsg, flags);
7863 /****************************************************************************
7865 ***************************************************************************/
7867 #ifdef HAVE_SENDMMSG
7868 #if defined(HAVE_SENDMMSG_SSIZE_T)
7870 static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7873 static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7876 struct socket_info *si = find_socket_info(s);
7877 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7878 struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7881 struct sockaddr_un un_addr;
7882 const struct sockaddr_un *to_un;
7883 const struct sockaddr *to;
7885 } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7888 char *swrap_dir = NULL;
7890 int found_bcast = 0;
7895 if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7896 vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7902 int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7904 for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7905 scm_rights_pipe_fd[i] = -1;
7908 for (i = 0; i < vlen; i++) {
7909 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7910 struct msghdr *msg = &msgvec[i].msg_hdr;
7912 rc = swrap_sendmsg_before_unix(omsg, msg,
7913 &scm_rights_pipe_fd[i]);
7920 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7925 for (i = 0; i < ret; i++) {
7926 omsgvec[i].msg_len = msgvec[i].msg_len;
7930 saved_errno = errno;
7931 for (i = 0; i < vlen; i++) {
7932 struct msghdr *msg = &msgvec[i].msg_hdr;
7934 swrap_sendmsg_after_unix(msg, ret,
7935 scm_rights_pipe_fd[i]);
7937 errno = saved_errno;
7943 connected = si->connected;
7944 SWRAP_UNLOCK_SI(si);
7946 for (i = 0; i < vlen; i++) {
7947 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7948 struct msghdr *msg = &msgvec[i].msg_hdr;
7950 if (connected == 0) {
7951 msg->msg_name = omsg->msg_name; /* optional address */
7952 msg->msg_namelen = omsg->msg_namelen; /* size of address */
7954 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7955 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7957 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7958 if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7959 uint8_t *cmbuf = NULL;
7962 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7969 msg->msg_control = cmbuf;
7970 msg->msg_controllen = cmlen;
7973 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7976 rc = swrap_sendmsg_before(s, si, msg,
7994 swrap_dir = socket_wrapper_dir();
7995 if (swrap_dir == NULL) {
8000 for (i = 0; i < vlen; i++) {
8001 struct msghdr *msg = &msgvec[i].msg_hdr;
8002 struct sockaddr_un *un_addr = &tmp[i].un_addr;
8003 const struct sockaddr *to = tmp[i].to;
8006 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
8014 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
8015 avail += msg->msg_iov[l].iov_len;
8021 /* we capture it as one single packet */
8022 buf = (uint8_t *)malloc(remain);
8028 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
8029 size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
8031 msg->msg_iov[l].iov_base,
8034 remain -= this_time;
8037 type = SOCKET_TYPE_CHAR_UDP;
8039 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
8040 swrap_un_path(un_addr, swrap_dir, type, iface, prt);
8041 if (stat(un_addr->sun_path, &st) != 0) continue;
8043 msg->msg_name = un_addr; /* optional address */
8044 msg->msg_namelen = sizeof(*un_addr); /* size of address */
8047 * ignore the any errors in broadcast sends and
8048 * do a single sendmsg instead of sendmmsg
8050 libc_sendmsg(s, msg, flags);
8054 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
8055 SWRAP_UNLOCK_SI(si);
8059 msgvec[i].msg_len = len;
8066 ret = libc_sendmmsg(s, msgvec, vlen, flags);
8072 for (i = 0; i < ret; i++) {
8073 omsgvec[i].msg_len = msgvec[i].msg_len;
8077 saved_errno = errno;
8078 for (i = 0; i < vlen; i++) {
8079 struct msghdr *msg = &msgvec[i].msg_hdr;
8081 if (i == 0 || i < ret) {
8082 swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
8084 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8085 SAFE_FREE(msg->msg_control);
8088 SAFE_FREE(swrap_dir);
8089 errno = saved_errno;
8094 #if defined(HAVE_SENDMMSG_SSIZE_T)
8096 ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
8099 int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
8102 return swrap_sendmmsg(s, msgvec, vlen, flags);
8104 #endif /* HAVE_SENDMMSG */
8106 /****************************************************************************
8108 ***************************************************************************/
8110 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
8112 struct socket_info *si;
8115 struct swrap_address saddr = {
8116 .sa_socklen = sizeof(struct sockaddr_storage)
8121 si = find_socket_info(s);
8123 return libc_readv(s, vector, count);
8126 tmp.iov_base = NULL;
8130 msg.msg_name = &saddr.sa.s; /* optional address */
8131 msg.msg_namelen = saddr.sa_socklen; /* size of address */
8132 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8133 msg.msg_iovlen = count; /* # elements in msg_iov */
8134 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8135 msg.msg_control = NULL; /* ancillary data, see below */
8136 msg.msg_controllen = 0; /* ancillary data buffer len */
8137 msg.msg_flags = 0; /* flags on received message */
8140 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
8142 if (rc == -ENOTSOCK) {
8143 return libc_readv(s, vector, count);
8148 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
8150 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
8158 ssize_t readv(int s, const struct iovec *vector, int count)
8160 return swrap_readv(s, vector, count);
8163 /****************************************************************************
8165 ***************************************************************************/
8167 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
8171 struct sockaddr_un un_addr;
8174 struct socket_info *si = find_socket_info(s);
8177 return libc_writev(s, vector, count);
8180 tmp.iov_base = NULL;
8184 msg.msg_name = NULL; /* optional address */
8185 msg.msg_namelen = 0; /* size of address */
8186 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8187 msg.msg_iovlen = count; /* # elements in msg_iov */
8188 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8189 msg.msg_control = NULL; /* ancillary data, see below */
8190 msg.msg_controllen = 0; /* ancillary data buffer len */
8191 msg.msg_flags = 0; /* flags on received message */
8194 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
8196 if (rc == -ENOTSOCK) {
8197 return libc_readv(s, vector, count);
8202 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
8204 swrap_sendmsg_after(s, si, &msg, NULL, ret);
8209 ssize_t writev(int s, const struct iovec *vector, int count)
8211 return swrap_writev(s, vector, count);
8214 /****************************
8216 ***************************/
8218 static int swrap_remove_wrapper(const char *__func_name,
8219 int (*__close_fd_fn)(int fd),
8222 struct socket_info *si = NULL;
8224 int ret_errno = errno;
8227 swrap_mutex_lock(&socket_reset_mutex);
8229 si_index = find_socket_info_index(fd);
8230 if (si_index == -1) {
8231 swrap_mutex_unlock(&socket_reset_mutex);
8232 return __close_fd_fn(fd);
8235 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8236 reset_socket_info_index(fd);
8238 si = swrap_get_socket_info(si_index);
8240 swrap_mutex_lock(&first_free_mutex);
8243 ret = __close_fd_fn(fd);
8248 swrap_dec_refcount(si);
8250 if (swrap_get_refcount(si) > 0) {
8251 /* there are still references left */
8255 if (si->fd_passed) {
8259 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8260 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8263 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8264 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8265 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8268 if (si->un_addr.sun_path[0] != '\0') {
8269 unlink(si->un_addr.sun_path);
8273 swrap_set_next_free(si, first_free);
8274 first_free = si_index;
8277 SWRAP_UNLOCK_SI(si);
8278 swrap_mutex_unlock(&first_free_mutex);
8279 swrap_mutex_unlock(&socket_reset_mutex);
8285 static int swrap_noop_close(int fd)
8287 (void)fd; /* unused */
8291 static void swrap_remove_stale(int fd)
8293 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8297 * This allows socket_wrapper aware applications to
8298 * indicate that the given fd does not belong to
8301 * We already overload a lot of unrelated functions
8302 * like eventfd(), timerfd_create(), ... in order to
8303 * call swrap_remove_stale() on the returned fd, but
8304 * we'll never be able to handle all possible syscalls.
8306 * socket_wrapper_indicate_no_inet_fd() gives them a way
8309 * We don't export swrap_remove_stale() in order to
8310 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8313 void socket_wrapper_indicate_no_inet_fd(int fd)
8315 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8318 static int swrap_close(int fd)
8320 return swrap_remove_wrapper(__func__, libc_close, fd);
8325 return swrap_close(fd);
8328 #ifdef HAVE___CLOSE_NOCANCEL
8330 static int swrap___close_nocancel(int fd)
8332 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8335 int __close_nocancel(int fd);
8336 int __close_nocancel(int fd)
8338 return swrap___close_nocancel(fd);
8341 #endif /* HAVE___CLOSE_NOCANCEL */
8343 /****************************
8345 ***************************/
8347 static int swrap_dup(int fd)
8349 struct socket_info *si;
8352 idx = find_socket_info_index(fd);
8354 return libc_dup(fd);
8357 si = swrap_get_socket_info(idx);
8359 dup_fd = libc_dup(fd);
8361 int saved_errno = errno;
8362 errno = saved_errno;
8366 if ((size_t)dup_fd >= socket_fds_max) {
8367 SWRAP_LOG(SWRAP_LOG_ERROR,
8368 "The max socket index limit of %zu has been reached, "
8379 swrap_inc_refcount(si);
8381 SWRAP_UNLOCK_SI(si);
8383 /* Make sure we don't have an entry for the fd */
8384 swrap_remove_stale(dup_fd);
8386 set_socket_info_index(dup_fd, idx);
8393 return swrap_dup(fd);
8396 /****************************
8398 ***************************/
8400 static int swrap_dup2(int fd, int newfd)
8402 struct socket_info *si;
8405 idx = find_socket_info_index(fd);
8407 return libc_dup2(fd, newfd);
8410 si = swrap_get_socket_info(idx);
8414 * According to the manpage:
8416 * "If oldfd is a valid file descriptor, and newfd has the same
8417 * value as oldfd, then dup2() does nothing, and returns newfd."
8422 if ((size_t)newfd >= socket_fds_max) {
8423 SWRAP_LOG(SWRAP_LOG_ERROR,
8424 "The max socket index limit of %zu has been reached, "
8432 if (find_socket_info(newfd)) {
8433 /* dup2() does an implicit close of newfd, which we
8434 * need to emulate */
8438 dup_fd = libc_dup2(fd, newfd);
8440 int saved_errno = errno;
8441 errno = saved_errno;
8447 swrap_inc_refcount(si);
8449 SWRAP_UNLOCK_SI(si);
8451 /* Make sure we don't have an entry for the fd */
8452 swrap_remove_stale(dup_fd);
8454 set_socket_info_index(dup_fd, idx);
8459 int dup2(int fd, int newfd)
8461 return swrap_dup2(fd, newfd);
8464 /****************************
8466 ***************************/
8468 static int swrap_vfcntl(int fd, int cmd, va_list va)
8470 struct socket_info *si;
8471 int rc, dup_fd, idx;
8473 idx = find_socket_info_index(fd);
8475 return libc_vfcntl(fd, cmd, va);
8478 si = swrap_get_socket_info(idx);
8482 dup_fd = libc_vfcntl(fd, cmd, va);
8484 int saved_errno = errno;
8485 errno = saved_errno;
8489 /* Make sure we don't have an entry for the fd */
8490 swrap_remove_stale(dup_fd);
8492 if ((size_t)dup_fd >= socket_fds_max) {
8493 SWRAP_LOG(SWRAP_LOG_ERROR,
8494 "The max socket index limit of %zu has been reached, "
8505 swrap_inc_refcount(si);
8507 SWRAP_UNLOCK_SI(si);
8510 set_socket_info_index(dup_fd, idx);
8515 rc = libc_vfcntl(fd, cmd, va);
8522 #undef fcntl /* Needed for LFS handling */
8523 int fcntl(int fd, int cmd, ...)
8530 rc = swrap_vfcntl(fd, cmd, va);
8537 /****************************
8539 ***************************/
8542 static int swrap_vfcntl64(int fd, int cmd, va_list va)
8544 struct socket_info *si;
8545 int rc, dup_fd, idx;
8547 idx = find_socket_info_index(fd);
8549 return libc_vfcntl64(fd, cmd, va);
8552 si = swrap_get_socket_info(idx);
8556 dup_fd = libc_vfcntl64(fd, cmd, va);
8558 int saved_errno = errno;
8559 errno = saved_errno;
8563 /* Make sure we don't have an entry for the fd */
8564 swrap_remove_stale(dup_fd);
8566 if ((size_t)dup_fd >= socket_fds_max) {
8567 SWRAP_LOG(SWRAP_LOG_ERROR,
8568 "The max socket index limit of %zu has been reached, "
8579 swrap_inc_refcount(si);
8581 SWRAP_UNLOCK_SI(si);
8584 set_socket_info_index(dup_fd, idx);
8589 rc = libc_vfcntl64(fd, cmd, va);
8596 int fcntl64(int fd, int cmd, ...)
8603 rc = swrap_vfcntl64(fd, cmd, va);
8611 /****************************
8613 ***************************/
8616 static int swrap_eventfd(int count, int flags)
8620 fd = libc_eventfd(count, flags);
8622 swrap_remove_stale(fd);
8628 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8629 int eventfd(unsigned int count, int flags)
8631 int eventfd(int count, int flags)
8634 return swrap_eventfd(count, flags);
8639 int pledge(const char *promises, const char *paths[])
8641 (void)promises; /* unused */
8642 (void)paths; /* unused */
8646 #endif /* HAVE_PLEDGE */
8649 static bool swrap_is_swrap_related_syscall(long int sysno)
8655 #endif /* SYS_close */
8660 #endif /* SYS_recvmmsg */
8665 #endif /* SYS_sendmmsg */
8672 static long int swrap_syscall(long int sysno, va_list vp)
8680 int fd = (int)va_arg(vp, int);
8682 SWRAP_LOG(SWRAP_LOG_TRACE,
8683 "calling swrap_close syscall %lu",
8685 rc = swrap_close(fd);
8688 #endif /* SYS_close */
8693 int fd = (int)va_arg(vp, int);
8694 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8695 unsigned int vlen = va_arg(vp, unsigned int);
8696 int flags = va_arg(vp, int);
8697 struct timespec *timeout = va_arg(vp, struct timespec *);
8699 SWRAP_LOG(SWRAP_LOG_TRACE,
8700 "calling swrap_recvmmsg syscall %lu",
8702 rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
8705 #endif /* SYS_recvmmsg */
8710 int fd = (int)va_arg(vp, int);
8711 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8712 unsigned int vlen = va_arg(vp, unsigned int);
8713 int flags = va_arg(vp, int);
8715 SWRAP_LOG(SWRAP_LOG_TRACE,
8716 "calling swrap_sendmmsg syscall %lu",
8718 rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
8721 #endif /* SYS_sendmmsg */
8732 #ifdef HAVE_SYSCALL_INT
8733 int syscall(int sysno, ...)
8735 long int syscall(long int sysno, ...)
8738 #ifdef HAVE_SYSCALL_INT
8745 va_start(va, sysno);
8748 * We should only handle the syscall numbers
8751 if (!swrap_is_swrap_related_syscall(sysno)) {
8753 * We need to give socket_wrapper a
8754 * chance to take over...
8756 if (swrap_uwrap_syscall_valid(sysno)) {
8757 rc = swrap_uwrap_syscall_va(sysno, va);
8762 rc = libc_vsyscall(sysno, va);
8767 if (!socket_wrapper_enabled()) {
8768 rc = libc_vsyscall(sysno, va);
8773 rc = swrap_syscall(sysno, va);
8779 /* used by uid_wrapper */
8780 bool socket_wrapper_syscall_valid(long int sysno);
8781 bool socket_wrapper_syscall_valid(long int sysno)
8783 if (!swrap_is_swrap_related_syscall(sysno)) {
8787 if (!socket_wrapper_enabled()) {
8794 /* used by uid_wrapper */
8795 long int socket_wrapper_syscall_va(long int sysno, va_list va);
8796 long int socket_wrapper_syscall_va(long int sysno, va_list va)
8798 if (!swrap_is_swrap_related_syscall(sysno)) {
8803 if (!socket_wrapper_enabled()) {
8804 return libc_vsyscall(sysno, va);
8807 return swrap_syscall(sysno, va);
8809 #endif /* HAVE_SYSCALL */
8811 static void swrap_thread_prepare(void)
8814 * This function should only be called here!!
8816 * We bind all symobls to avoid deadlocks of the fork is
8817 * interrupted by a signal handler using a symbol of this
8820 swrap_bind_symbol_all();
8825 static void swrap_thread_parent(void)
8830 static void swrap_thread_child(void)
8835 /****************************
8837 ***************************/
8838 void swrap_constructor(void)
8840 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8841 SWRAP_LOG(SWRAP_LOG_ERROR,
8843 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8844 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8845 "sizeof(struct socket_info)=%zu",
8847 sizeof(struct swrap_unix_scm_rights),
8848 sizeof(struct swrap_unix_scm_rights_payload),
8849 sizeof(struct socket_info));
8856 * If we hold a lock and the application forks, then the child
8857 * is not able to unlock the mutex and we are in a deadlock.
8858 * This should prevent such deadlocks.
8860 pthread_atfork(&swrap_thread_prepare,
8861 &swrap_thread_parent,
8862 &swrap_thread_child);
8865 /****************************
8867 ***************************/
8870 * This function is called when the library is unloaded and makes sure that
8871 * sockets get closed and the unix file for the socket are unlinked.
8873 void swrap_destructor(void)
8877 if (socket_fds_idx != NULL) {
8878 for (i = 0; i < socket_fds_max; ++i) {
8879 if (socket_fds_idx[i] != -1) {
8883 SAFE_FREE(socket_fds_idx);
8888 if (swrap.libc.handle != NULL
8890 && swrap.libc.handle != RTLD_NEXT
8893 dlclose(swrap.libc.handle);
8895 if (swrap.libc.socket_handle
8897 && swrap.libc.socket_handle != RTLD_NEXT
8900 dlclose(swrap.libc.socket_handle);
8904 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8906 * On FreeBSD 12 (and maybe other platforms)
8907 * system libraries like libresolv prefix there
8908 * syscalls with '_' in order to always use
8909 * the symbols from libc.
8911 * In the interaction with resolv_wrapper,
8912 * we need to inject socket wrapper into libresolv,
8913 * which means we need to private all socket
8914 * related syscalls also with the '_' prefix.
8916 * This is tested in Samba's 'make test',
8917 * there we noticed that providing '_read',
8918 * '_open' and '_close' would cause errors, which
8919 * means we skip '_read', '_write' and
8920 * all non socket related calls without
8921 * further analyzing the problem.
8923 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8924 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8927 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8929 SWRAP_SYMBOL_ALIAS(accept, _accept);
8930 SWRAP_SYMBOL_ALIAS(bind, _bind);
8931 SWRAP_SYMBOL_ALIAS(connect, _connect);
8932 SWRAP_SYMBOL_ALIAS(dup, _dup);
8933 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8934 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8935 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8936 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8937 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8938 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8939 SWRAP_SYMBOL_ALIAS(listen, _listen);
8940 SWRAP_SYMBOL_ALIAS(readv, _readv);
8941 SWRAP_SYMBOL_ALIAS(recv, _recv);
8942 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8943 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8944 SWRAP_SYMBOL_ALIAS(send, _send);
8945 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8946 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8947 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8948 SWRAP_SYMBOL_ALIAS(socket, _socket);
8949 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8950 SWRAP_SYMBOL_ALIAS(writev, _writev);
8952 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */