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);
631 SWRAP_SYMBOL_ENTRY(fcntl64);
633 SWRAP_SYMBOL_ENTRY(fcntl);
635 SWRAP_SYMBOL_ENTRY(fopen);
637 SWRAP_SYMBOL_ENTRY(fopen64);
640 SWRAP_SYMBOL_ENTRY(eventfd);
642 SWRAP_SYMBOL_ENTRY(getpeername);
643 SWRAP_SYMBOL_ENTRY(getsockname);
644 SWRAP_SYMBOL_ENTRY(getsockopt);
645 SWRAP_SYMBOL_ENTRY(ioctl);
646 SWRAP_SYMBOL_ENTRY(listen);
647 SWRAP_SYMBOL_ENTRY(open);
649 SWRAP_SYMBOL_ENTRY(open64);
652 SWRAP_SYMBOL_ENTRY(openat64);
654 SWRAP_SYMBOL_ENTRY(openat);
655 SWRAP_SYMBOL_ENTRY(pipe);
656 SWRAP_SYMBOL_ENTRY(read);
657 SWRAP_SYMBOL_ENTRY(readv);
658 SWRAP_SYMBOL_ENTRY(recv);
659 SWRAP_SYMBOL_ENTRY(recvfrom);
660 SWRAP_SYMBOL_ENTRY(recvmsg);
662 SWRAP_SYMBOL_ENTRY(recvmmsg);
664 SWRAP_SYMBOL_ENTRY(send);
665 SWRAP_SYMBOL_ENTRY(sendmsg);
667 SWRAP_SYMBOL_ENTRY(sendmmsg);
669 SWRAP_SYMBOL_ENTRY(sendto);
670 SWRAP_SYMBOL_ENTRY(setsockopt);
672 SWRAP_SYMBOL_ENTRY(signalfd);
674 SWRAP_SYMBOL_ENTRY(socket);
675 SWRAP_SYMBOL_ENTRY(socketpair);
676 #ifdef HAVE_TIMERFD_CREATE
677 SWRAP_SYMBOL_ENTRY(timerfd_create);
679 SWRAP_SYMBOL_ENTRY(write);
680 SWRAP_SYMBOL_ENTRY(writev);
682 SWRAP_SYMBOL_ENTRY(syscall);
685 #undef SWRAP_SYMBOL_ENTRY
687 #define SWRAP_SYMBOL_ENTRY(i) \
689 __rtld_default_##i f; \
694 typedef bool (*__rtld_default_uid_wrapper_syscall_valid)(long int sysno);
695 typedef long int (*__rtld_default_uid_wrapper_syscall_va)(long int sysno, va_list va);
698 struct swrap_rtld_default_symbols {
700 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_valid);
701 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_va);
706 #undef SWRAP_SYMBOL_ENTRY
712 struct swrap_libc_symbols symbols;
716 struct swrap_rtld_default_symbols symbols;
720 static struct swrap swrap;
723 static char *socket_wrapper_dir(void);
725 #define LIBC_NAME "libc.so"
732 static const char *swrap_str_lib(enum swrap_lib lib)
737 case SWRAP_LIBSOCKET:
741 /* Compiler would warn us about unhandled enum value if we get here */
745 static void *swrap_load_lib_handle(enum swrap_lib lib)
747 int flags = RTLD_LAZY;
752 const char *env_preload = getenv("LD_PRELOAD");
753 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
754 bool enable_deepbind = true;
756 /* Don't do a deepbind if we run with libasan */
757 if (env_preload != NULL && strlen(env_preload) < 1024) {
758 const char *p = strstr(env_preload, "libasan.so");
760 enable_deepbind = false;
764 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
765 enable_deepbind = false;
768 if (enable_deepbind) {
769 flags |= RTLD_DEEPBIND;
774 case SWRAP_LIBSOCKET:
775 #ifdef HAVE_LIBSOCKET
776 handle = swrap.libc.socket_handle;
777 if (handle == NULL) {
778 for (i = 10; i >= 0; i--) {
779 char soname[256] = {0};
781 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
782 handle = dlopen(soname, flags);
783 if (handle != NULL) {
788 swrap.libc.socket_handle = handle;
793 handle = swrap.libc.handle;
795 if (handle == NULL) {
796 handle = dlopen(LIBC_SO, flags);
798 swrap.libc.handle = handle;
801 if (handle == NULL) {
802 for (i = 10; i >= 0; i--) {
803 char soname[256] = {0};
805 snprintf(soname, sizeof(soname), "libc.so.%d", i);
806 handle = dlopen(soname, flags);
807 if (handle != NULL) {
812 swrap.libc.handle = handle;
817 if (handle == NULL) {
819 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
821 SWRAP_LOG(SWRAP_LOG_ERROR,
822 "Failed to dlopen library: %s",
831 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
836 handle = swrap_load_lib_handle(lib);
838 func = dlsym(handle, fn_name);
840 SWRAP_LOG(SWRAP_LOG_ERROR,
841 "Failed to find %s: %s",
847 SWRAP_LOG(SWRAP_LOG_TRACE,
855 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
856 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
860 ret = pthread_mutex_lock(mutex);
862 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
863 getpid(), getppid(), caller, line, name, strerror(ret));
868 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
869 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
873 ret = pthread_mutex_unlock(mutex);
875 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
876 getpid(), getppid(), caller, line, name, strerror(ret));
882 * These macros have a thread race condition on purpose!
884 * This is an optimization to avoid locking each time we check if the symbol is
887 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
888 swrap.libc.symbols._libc_##sym_name.obj = \
889 _swrap_bind_symbol(lib, #sym_name); \
892 #define swrap_bind_symbol_libc(sym_name) \
893 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
895 #define swrap_bind_symbol_libsocket(sym_name) \
896 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
898 #define swrap_bind_symbol_rtld_default_optional(sym_name) do { \
899 swrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
900 dlsym(RTLD_DEFAULT, #sym_name); \
903 static void swrap_bind_symbol_all(void);
905 /****************************************************************************
907 ****************************************************************************
909 * Functions especially from libc need to be loaded individually, you can't
910 * load all at once or gdb will segfault at startup. The same applies to
911 * valgrind and has probably something todo with with the linker. So we need
912 * load each function at the point it is called the first time.
914 ****************************************************************************/
917 static int libc_accept4(int sockfd,
918 struct sockaddr *addr,
922 swrap_bind_symbol_all();
924 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
927 #else /* HAVE_ACCEPT4 */
929 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
931 swrap_bind_symbol_all();
933 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
935 #endif /* HAVE_ACCEPT4 */
937 static int libc_bind(int sockfd,
938 const struct sockaddr *addr,
941 swrap_bind_symbol_all();
943 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
946 static int libc_close(int fd)
948 swrap_bind_symbol_all();
950 return swrap.libc.symbols._libc_close.f(fd);
953 #ifdef HAVE___CLOSE_NOCANCEL
954 static int libc___close_nocancel(int fd)
956 swrap_bind_symbol_all();
958 return swrap.libc.symbols._libc___close_nocancel.f(fd);
960 #endif /* HAVE___CLOSE_NOCANCEL */
962 static int libc_connect(int sockfd,
963 const struct sockaddr *addr,
966 swrap_bind_symbol_all();
968 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
971 static int libc_dup(int fd)
973 swrap_bind_symbol_all();
975 return swrap.libc.symbols._libc_dup.f(fd);
978 static int libc_dup2(int oldfd, int newfd)
980 swrap_bind_symbol_all();
982 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
986 static int libc_eventfd(int count, int flags)
988 swrap_bind_symbol_all();
990 return swrap.libc.symbols._libc_eventfd.f(count, flags);
994 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
995 static int libc_vfcntl(int fd, int cmd, va_list ap)
1000 swrap_bind_symbol_all();
1002 arg = va_arg(ap, void *);
1005 * If fcntl64 exists then this is a system were fcntl is
1006 * renamed (including when building this file), and so we must
1007 * assume that the binary under test was built with
1008 * -D_FILE_OFFSET_BITS=64 and pass on to fcntl64.
1010 * If we are wrong, then fcntl is unwrapped, but while that is
1011 * not ideal, is is also unlikely.
1013 * In any case, it is always wrong to map fcntl64() to fcntl()
1014 * as this will cause a thunk from struct flock -> flock64
1015 * that the caller had already prepared for.
1018 rc = swrap.libc.symbols._libc_fcntl64.f(fd, cmd, arg);
1020 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
1026 static int libc_getpeername(int sockfd,
1027 struct sockaddr *addr,
1030 swrap_bind_symbol_all();
1032 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
1035 static int libc_getsockname(int sockfd,
1036 struct sockaddr *addr,
1039 swrap_bind_symbol_all();
1041 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
1044 static int libc_getsockopt(int sockfd,
1050 swrap_bind_symbol_all();
1052 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
1059 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1060 static int libc_vioctl(int d, unsigned long int request, va_list ap)
1065 swrap_bind_symbol_all();
1067 arg = va_arg(ap, void *);
1069 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
1074 static int libc_listen(int sockfd, int backlog)
1076 swrap_bind_symbol_all();
1078 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
1081 static FILE *libc_fopen(const char *name, const char *mode)
1083 swrap_bind_symbol_all();
1085 return swrap.libc.symbols._libc_fopen.f(name, mode);
1089 static FILE *libc_fopen64(const char *name, const char *mode)
1091 swrap_bind_symbol_all();
1093 return swrap.libc.symbols._libc_fopen64.f(name, mode);
1095 #endif /* HAVE_FOPEN64 */
1097 static void swrap_inject_o_largefile(int *flags)
1099 (void)*flags; /* maybe unused */
1100 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1102 if (((*flags) & O_PATH) == 0)
1105 *flags |= O_LARGEFILE;
1110 static int libc_vopen(const char *pathname, int flags, va_list ap)
1115 swrap_bind_symbol_all();
1117 swrap_inject_o_largefile(&flags);
1119 if (flags & O_CREAT) {
1120 mode = va_arg(ap, int);
1122 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1127 static int libc_open(const char *pathname, int flags, ...)
1132 va_start(ap, flags);
1133 fd = libc_vopen(pathname, flags, ap);
1140 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1145 swrap_bind_symbol_all();
1147 swrap_inject_o_largefile(&flags);
1149 if (flags & O_CREAT) {
1150 mode = va_arg(ap, int);
1152 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1156 #endif /* HAVE_OPEN64 */
1158 #ifdef HAVE_OPENAT64
1160 libc_vopenat64(int dirfd, const char *pathname, int flags, va_list ap)
1165 swrap_bind_symbol_all();
1167 swrap_inject_o_largefile(&flags);
1169 if (flags & O_CREAT) {
1170 mode = va_arg(ap, int);
1172 fd = swrap.libc.symbols._libc_openat64.f(dirfd,
1179 #endif /* HAVE_OPENAT64 */
1181 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1186 swrap_bind_symbol_all();
1188 swrap_inject_o_largefile(&flags);
1190 if (flags & O_CREAT) {
1191 mode = va_arg(ap, int);
1193 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1202 static int libc_openat(int dirfd, const char *path, int flags, ...)
1207 va_start(ap, flags);
1208 fd = libc_vopenat(dirfd, path, flags, ap);
1215 static int libc_pipe(int pipefd[2])
1217 swrap_bind_symbol_all();
1219 return swrap.libc.symbols._libc_pipe.f(pipefd);
1222 static int libc_read(int fd, void *buf, size_t count)
1224 swrap_bind_symbol_all();
1226 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1229 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1231 swrap_bind_symbol_all();
1233 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1236 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1238 swrap_bind_symbol_all();
1240 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1243 static int libc_recvfrom(int sockfd,
1247 struct sockaddr *src_addr,
1250 swrap_bind_symbol_all();
1252 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1260 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1262 swrap_bind_symbol_all();
1264 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1267 #ifdef HAVE_RECVMMSG
1268 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1270 static ssize_t libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
1271 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1272 /* Linux legacy glibc < 2.21 */
1273 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
1275 /* Linux glibc >= 2.21 */
1276 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
1279 swrap_bind_symbol_all();
1281 return swrap.libc.symbols._libc_recvmmsg.f(sockfd, msgvec, vlen, flags, timeout);
1285 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1287 swrap_bind_symbol_all();
1289 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1292 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1294 swrap_bind_symbol_all();
1296 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1299 #ifdef HAVE_SENDMMSG
1300 #if defined(HAVE_SENDMMSG_SSIZE_T)
1302 static ssize_t libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags)
1305 static int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
1308 swrap_bind_symbol_all();
1310 return swrap.libc.symbols._libc_sendmmsg.f(sockfd, msgvec, vlen, flags);
1314 static int libc_sendto(int sockfd,
1318 const struct sockaddr *dst_addr,
1321 swrap_bind_symbol_all();
1323 return swrap.libc.symbols._libc_sendto.f(sockfd,
1331 static int libc_setsockopt(int sockfd,
1337 swrap_bind_symbol_all();
1339 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1346 #ifdef HAVE_SIGNALFD
1347 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1349 swrap_bind_symbol_all();
1351 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1355 static int libc_socket(int domain, int type, int protocol)
1357 swrap_bind_symbol_all();
1359 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1362 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1364 swrap_bind_symbol_all();
1366 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1369 #ifdef HAVE_TIMERFD_CREATE
1370 static int libc_timerfd_create(int clockid, int flags)
1372 swrap_bind_symbol_all();
1374 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1378 static ssize_t libc_write(int fd, const void *buf, size_t count)
1380 swrap_bind_symbol_all();
1382 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1385 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1387 swrap_bind_symbol_all();
1389 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1393 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1394 static long int libc_vsyscall(long int sysno, va_list va)
1400 swrap_bind_symbol_all();
1402 for (i = 0; i < 8; i++) {
1403 args[i] = va_arg(va, long int);
1406 rc = swrap.libc.symbols._libc_syscall.f(sysno,
1419 static bool swrap_uwrap_syscall_valid(long int sysno)
1421 swrap_bind_symbol_all();
1423 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f == NULL) {
1427 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f(
1431 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1432 static long int swrap_uwrap_syscall_va(long int sysno, va_list va)
1434 swrap_bind_symbol_all();
1436 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f == NULL) {
1438 * Fallback to libc, if uid_wrapper_syscall_va is not
1441 return libc_vsyscall(sysno, va);
1444 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f(
1448 #endif /* HAVE_SYSCALL */
1450 /* DO NOT call this function during library initialization! */
1451 static void __swrap_bind_symbol_all_once(void)
1454 swrap_bind_symbol_libsocket(accept4);
1456 swrap_bind_symbol_libsocket(accept);
1458 swrap_bind_symbol_libsocket(bind);
1459 swrap_bind_symbol_libc(close);
1460 #ifdef HAVE___CLOSE_NOCANCEL
1461 swrap_bind_symbol_libc(__close_nocancel);
1463 swrap_bind_symbol_libsocket(connect);
1464 swrap_bind_symbol_libc(dup);
1465 swrap_bind_symbol_libc(dup2);
1467 swrap_bind_symbol_libc(fcntl64);
1469 swrap_bind_symbol_libc(fcntl);
1471 swrap_bind_symbol_libc(fopen);
1473 swrap_bind_symbol_libc(fopen64);
1476 swrap_bind_symbol_libc(eventfd);
1478 swrap_bind_symbol_libsocket(getpeername);
1479 swrap_bind_symbol_libsocket(getsockname);
1480 swrap_bind_symbol_libsocket(getsockopt);
1481 swrap_bind_symbol_libc(ioctl);
1482 swrap_bind_symbol_libsocket(listen);
1483 swrap_bind_symbol_libc(open);
1485 swrap_bind_symbol_libc(open64);
1487 #ifdef HAVE_OPENAT64
1488 swrap_bind_symbol_libc(openat64);
1490 swrap_bind_symbol_libc(openat);
1491 swrap_bind_symbol_libsocket(pipe);
1492 swrap_bind_symbol_libc(read);
1493 swrap_bind_symbol_libsocket(readv);
1494 swrap_bind_symbol_libsocket(recv);
1495 swrap_bind_symbol_libsocket(recvfrom);
1496 swrap_bind_symbol_libsocket(recvmsg);
1497 #ifdef HAVE_RECVMMSG
1498 swrap_bind_symbol_libsocket(recvmmsg);
1500 swrap_bind_symbol_libsocket(send);
1501 swrap_bind_symbol_libsocket(sendmsg);
1502 #ifdef HAVE_SENDMMSG
1503 swrap_bind_symbol_libsocket(sendmmsg);
1505 swrap_bind_symbol_libsocket(sendto);
1506 swrap_bind_symbol_libsocket(setsockopt);
1507 #ifdef HAVE_SIGNALFD
1508 swrap_bind_symbol_libsocket(signalfd);
1510 swrap_bind_symbol_libsocket(socket);
1511 swrap_bind_symbol_libsocket(socketpair);
1512 #ifdef HAVE_TIMERFD_CREATE
1513 swrap_bind_symbol_libc(timerfd_create);
1515 swrap_bind_symbol_libc(write);
1516 swrap_bind_symbol_libsocket(writev);
1518 swrap_bind_symbol_libc(syscall);
1519 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
1520 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
1524 static void swrap_bind_symbol_all(void)
1526 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1528 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1531 /*********************************************************
1532 * SWRAP HELPER FUNCTIONS
1533 *********************************************************/
1536 * We return 127.0.0.0 (default) or 10.53.57.0.
1538 * This can be controlled by:
1539 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1541 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1543 static in_addr_t swrap_ipv4_net(void)
1545 static int initialized;
1546 static in_addr_t hv;
1547 const char *net_str = NULL;
1556 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1557 if (net_str == NULL) {
1558 net_str = "127.0.0.0";
1561 ret = inet_pton(AF_INET, net_str, &nv);
1563 SWRAP_LOG(SWRAP_LOG_ERROR,
1564 "INVALID IPv4 Network [%s]",
1569 hv = ntohl(nv.s_addr);
1579 SWRAP_LOG(SWRAP_LOG_ERROR,
1580 "INVALID IPv4 Network [%s][0x%x] should be "
1581 "127.0.0.0 or 10.53.57.0",
1582 net_str, (unsigned)hv);
1590 * This returns 127.255.255.255 or 10.255.255.255
1592 static in_addr_t swrap_ipv4_bcast(void)
1596 hv = swrap_ipv4_net();
1597 hv |= IN_CLASSA_HOST;
1603 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1605 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1609 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1610 SWRAP_LOG(SWRAP_LOG_ERROR,
1611 "swrap_ipv4_iface(%u) invalid!",
1617 hv = swrap_ipv4_net();
1627 static const struct in6_addr *swrap_ipv6(void)
1629 static struct in6_addr v;
1630 static int initialized;
1638 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1647 static void set_port(int family, int prt, struct swrap_address *addr)
1651 addr->sa.in.sin_port = htons(prt);
1655 addr->sa.in6.sin6_port = htons(prt);
1661 static size_t socket_length(int family)
1665 return sizeof(struct sockaddr_in);
1668 return sizeof(struct sockaddr_in6);
1674 struct swrap_sockaddr_buf {
1678 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1679 const struct sockaddr *saddr)
1681 unsigned int port = 0;
1682 char addr[64] = {0,};
1684 switch (saddr->sa_family) {
1686 const struct sockaddr_in *in =
1687 (const struct sockaddr_in *)(const void *)saddr;
1689 port = ntohs(in->sin_port);
1691 inet_ntop(saddr->sa_family,
1693 addr, sizeof(addr));
1698 const struct sockaddr_in6 *in6 =
1699 (const struct sockaddr_in6 *)(const void *)saddr;
1701 port = ntohs(in6->sin6_port);
1703 inet_ntop(saddr->sa_family,
1705 addr, sizeof(addr));
1710 snprintf(addr, sizeof(addr),
1711 "<Unknown address family %u>",
1716 snprintf(buf->str, sizeof(buf->str),
1717 "addr[%s]/port[%u]",
1723 static struct socket_info *swrap_get_socket_info(int si_index)
1725 return (struct socket_info *)(&(sockets[si_index].info));
1728 static int swrap_get_refcount(struct socket_info *si)
1730 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1731 return sic->meta.refcount;
1734 static void swrap_inc_refcount(struct socket_info *si)
1736 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1738 sic->meta.refcount += 1;
1741 static void swrap_dec_refcount(struct socket_info *si)
1743 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1745 sic->meta.refcount -= 1;
1748 static int swrap_get_next_free(struct socket_info *si)
1750 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1752 return sic->meta.next_free;
1755 static void swrap_set_next_free(struct socket_info *si, int next_free)
1757 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1759 sic->meta.next_free = next_free;
1762 static int swrap_un_path(struct sockaddr_un *un,
1763 const char *swrap_dir,
1770 ret = snprintf(un->sun_path,
1771 sizeof(un->sun_path),
1777 if ((size_t)ret >= sizeof(un->sun_path)) {
1778 return ENAMETOOLONG;
1784 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1785 const char *swrap_dir)
1789 ret = snprintf(un->sun_path,
1790 sizeof(un->sun_path),
1794 if ((size_t)ret >= sizeof(un->sun_path)) {
1795 return ENAMETOOLONG;
1801 static bool swrap_dir_usable(const char *swrap_dir)
1803 struct sockaddr_un un;
1806 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1811 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1819 static char *socket_wrapper_dir(void)
1821 char *swrap_dir = NULL;
1822 char *s = getenv("SOCKET_WRAPPER_DIR");
1826 if (s == NULL || s[0] == '\0') {
1827 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1831 swrap_dir = realpath(s, NULL);
1832 if (swrap_dir == NULL) {
1833 SWRAP_LOG(SWRAP_LOG_ERROR,
1834 "Unable to resolve socket_wrapper dir path: %s - %s",
1840 ok = swrap_dir_usable(swrap_dir);
1847 ok = swrap_dir_usable(s);
1849 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1853 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1855 SWRAP_LOG(SWRAP_LOG_ERROR,
1856 "realpath(SOCKET_WRAPPER_DIR) too long and "
1857 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1862 swrap_dir = strdup(s);
1863 if (swrap_dir == NULL) {
1864 SWRAP_LOG(SWRAP_LOG_ERROR,
1865 "Unable to duplicate socket_wrapper dir path");
1869 SWRAP_LOG(SWRAP_LOG_WARN,
1870 "realpath(SOCKET_WRAPPER_DIR) too long, "
1871 "using original SOCKET_WRAPPER_DIR\n");
1874 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1878 static unsigned int socket_wrapper_mtu(void)
1880 static unsigned int max_mtu = 0;
1885 swrap_mutex_lock(&mtu_update_mutex);
1891 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1893 s = getenv("SOCKET_WRAPPER_MTU");
1898 tmp = strtol(s, &endp, 10);
1903 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1909 swrap_mutex_unlock(&mtu_update_mutex);
1913 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1915 pthread_mutexattr_t ma;
1916 bool need_destroy = false;
1919 #define __CHECK(cmd) do { \
1922 SWRAP_LOG(SWRAP_LOG_ERROR, \
1923 "%s: %s - failed %d", \
1929 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1930 __CHECK(pthread_mutexattr_init(&ma));
1931 need_destroy = true;
1932 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1933 __CHECK(pthread_mutex_init(m, &ma));
1936 pthread_mutexattr_destroy(&ma);
1941 static size_t socket_wrapper_max_sockets(void)
1947 if (socket_info_max != 0) {
1948 return socket_info_max;
1951 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1953 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1954 if (s == NULL || s[0] == '\0') {
1958 tmp = strtoul(s, &endp, 10);
1963 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1964 SWRAP_LOG(SWRAP_LOG_ERROR,
1965 "Invalid number of sockets specified, "
1966 "using default (%zu)",
1970 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1971 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1972 SWRAP_LOG(SWRAP_LOG_ERROR,
1973 "Invalid number of sockets specified, "
1974 "using maximum (%zu).",
1978 socket_info_max = tmp;
1981 return socket_info_max;
1984 static void socket_wrapper_init_fds_idx(void)
1989 if (socket_fds_idx != NULL) {
1993 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1995 SWRAP_LOG(SWRAP_LOG_ERROR,
1996 "Failed to allocate socket fds index array: %s",
2001 for (i = 0; i < socket_fds_max; i++) {
2005 socket_fds_idx = tmp;
2008 static void socket_wrapper_init_sockets(void)
2014 swrap_bind_symbol_all();
2016 swrap_mutex_lock(&sockets_mutex);
2018 if (sockets != NULL) {
2019 swrap_mutex_unlock(&sockets_mutex);
2023 SWRAP_LOG(SWRAP_LOG_DEBUG,
2024 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
2025 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
2028 * Intialize the static cache early before
2029 * any thread is able to start.
2031 (void)swrap_ipv4_net();
2033 socket_wrapper_init_fds_idx();
2035 /* Needs to be called inside the sockets_mutex lock here. */
2036 max_sockets = socket_wrapper_max_sockets();
2038 sockets = (struct socket_info_container *)calloc(max_sockets,
2039 sizeof(struct socket_info_container));
2041 if (sockets == NULL) {
2042 SWRAP_LOG(SWRAP_LOG_ERROR,
2043 "Failed to allocate sockets array: %s",
2045 swrap_mutex_unlock(&sockets_mutex);
2049 swrap_mutex_lock(&first_free_mutex);
2050 swrap_mutex_lock(&sockets_si_global);
2054 for (i = 0; i < max_sockets; i++) {
2055 swrap_set_next_free(&sockets[i].info, i+1);
2058 /* mark the end of the free list */
2059 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
2061 swrap_mutex_unlock(&sockets_si_global);
2062 swrap_mutex_unlock(&first_free_mutex);
2063 swrap_mutex_unlock(&sockets_mutex);
2069 bool socket_wrapper_enabled(void)
2071 char *s = socket_wrapper_dir();
2079 socket_wrapper_init_sockets();
2084 static unsigned int socket_wrapper_default_iface(void)
2086 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
2089 if (sscanf(s, "%u", &iface) == 1) {
2090 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
2096 return 1;/* 127.0.0.1 */
2099 static void set_socket_info_index(int fd, int idx)
2101 SWRAP_LOG(SWRAP_LOG_TRACE,
2104 socket_fds_idx[fd] = idx;
2105 /* This builtin issues a full memory barrier. */
2106 __sync_synchronize();
2109 static void reset_socket_info_index(int fd)
2111 SWRAP_LOG(SWRAP_LOG_TRACE,
2114 set_socket_info_index(fd, -1);
2117 static int find_socket_info_index(int fd)
2123 if (socket_fds_idx == NULL) {
2127 if ((size_t)fd >= socket_fds_max) {
2129 * Do not add a log here as some applications do stupid things
2132 * for (fd = 0; fd <= getdtablesize(); fd++) {
2136 * This would produce millions of lines of debug messages.
2139 SWRAP_LOG(SWRAP_LOG_ERROR,
2140 "Looking for a socket info for the fd %d is over the "
2141 "max socket index limit of %zu.",
2148 /* This builtin issues a full memory barrier. */
2149 __sync_synchronize();
2150 return socket_fds_idx[fd];
2153 static int swrap_add_socket_info(const struct socket_info *si_input)
2155 struct socket_info *si = NULL;
2158 if (si_input == NULL) {
2163 swrap_mutex_lock(&first_free_mutex);
2164 if (first_free == -1) {
2169 si_index = first_free;
2170 si = swrap_get_socket_info(si_index);
2174 first_free = swrap_get_next_free(si);
2176 swrap_inc_refcount(si);
2178 SWRAP_UNLOCK_SI(si);
2181 swrap_mutex_unlock(&first_free_mutex);
2186 static int swrap_create_socket(struct socket_info *si, int fd)
2190 if ((size_t)fd >= socket_fds_max) {
2191 SWRAP_LOG(SWRAP_LOG_ERROR,
2192 "The max socket index limit of %zu has been reached, "
2200 idx = swrap_add_socket_info(si);
2205 set_socket_info_index(fd, idx);
2210 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2217 p = strrchr(un->sun_path, '/');
2218 if (p) p++; else p = un->sun_path;
2220 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2221 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2227 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2228 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2235 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2241 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2245 case SOCKET_TYPE_CHAR_TCP:
2246 case SOCKET_TYPE_CHAR_UDP: {
2247 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2249 if ((*len) < sizeof(*in2)) {
2250 SWRAP_LOG(SWRAP_LOG_ERROR,
2251 "V4: *len(%zu) < sizeof(*in2)=%zu",
2252 (size_t)*len, sizeof(*in2));
2257 memset(in2, 0, sizeof(*in2));
2258 in2->sin_family = AF_INET;
2259 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2260 in2->sin_port = htons(prt);
2262 *len = sizeof(*in2);
2266 case SOCKET_TYPE_CHAR_TCP_V6:
2267 case SOCKET_TYPE_CHAR_UDP_V6: {
2268 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2270 if ((*len) < sizeof(*in2)) {
2271 SWRAP_LOG(SWRAP_LOG_ERROR,
2272 "V6: *len(%zu) < sizeof(*in2)=%zu",
2273 (size_t)*len, sizeof(*in2));
2274 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2279 memset(in2, 0, sizeof(*in2));
2280 in2->sin6_family = AF_INET6;
2281 in2->sin6_addr = *swrap_ipv6();
2282 in2->sin6_addr.s6_addr[15] = iface;
2283 in2->sin6_port = htons(prt);
2285 *len = sizeof(*in2);
2290 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2299 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2306 char *swrap_dir = NULL;
2308 if (bcast) *bcast = 0;
2310 switch (inaddr->sa_family) {
2312 const struct sockaddr_in *in =
2313 (const struct sockaddr_in *)(const void *)inaddr;
2314 unsigned int addr = ntohl(in->sin_addr.s_addr);
2318 const unsigned int sw_net_addr = swrap_ipv4_net();
2319 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2323 u_type = SOCKET_TYPE_CHAR_TCP;
2326 u_type = SOCKET_TYPE_CHAR_UDP;
2327 a_type = SOCKET_TYPE_CHAR_UDP;
2328 b_type = SOCKET_TYPE_CHAR_UDP;
2331 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2332 errno = ESOCKTNOSUPPORT;
2336 prt = ntohs(in->sin_port);
2337 if (a_type && addr == 0xFFFFFFFF) {
2338 /* 255.255.255.255 only udp */
2341 iface = socket_wrapper_default_iface();
2342 } else if (b_type && addr == sw_bcast_addr) {
2351 iface = socket_wrapper_default_iface();
2352 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2353 /* 127.0.0.X or 10.53.57.X */
2356 iface = (addr & 0x000000FF);
2358 struct swrap_sockaddr_buf buf = {};
2359 SWRAP_LOG(SWRAP_LOG_WARN,
2361 swrap_sockaddr_string(&buf, inaddr));
2362 errno = ENETUNREACH;
2365 if (bcast) *bcast = is_bcast;
2370 const struct sockaddr_in6 *in =
2371 (const struct sockaddr_in6 *)(const void *)inaddr;
2372 struct in6_addr cmp1, cmp2;
2376 type = SOCKET_TYPE_CHAR_TCP_V6;
2379 type = SOCKET_TYPE_CHAR_UDP_V6;
2382 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2383 errno = ESOCKTNOSUPPORT;
2387 /* XXX no multicast/broadcast */
2389 prt = ntohs(in->sin6_port);
2391 cmp1 = *swrap_ipv6();
2392 cmp2 = in->sin6_addr;
2393 cmp2.s6_addr[15] = 0;
2394 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2395 iface = in->sin6_addr.s6_addr[15];
2397 struct swrap_sockaddr_buf buf = {};
2398 SWRAP_LOG(SWRAP_LOG_WARN,
2400 swrap_sockaddr_string(&buf, inaddr));
2401 errno = ENETUNREACH;
2409 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2410 errno = ENETUNREACH;
2415 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2420 swrap_dir = socket_wrapper_dir();
2421 if (swrap_dir == NULL) {
2427 swrap_un_path_EINVAL(un, swrap_dir);
2428 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2429 SAFE_FREE(swrap_dir);
2430 /* the caller need to do more processing */
2434 swrap_un_path(un, swrap_dir, type, iface, prt);
2435 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2437 SAFE_FREE(swrap_dir);
2442 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2450 char *swrap_dir = NULL;
2452 if (bcast) *bcast = 0;
2454 switch (si->family) {
2456 const struct sockaddr_in *in =
2457 (const struct sockaddr_in *)(const void *)inaddr;
2458 unsigned int addr = ntohl(in->sin_addr.s_addr);
2463 const unsigned int sw_net_addr = swrap_ipv4_net();
2464 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2466 prt = ntohs(in->sin_port);
2470 u_type = SOCKET_TYPE_CHAR_TCP;
2471 d_type = SOCKET_TYPE_CHAR_TCP;
2474 u_type = SOCKET_TYPE_CHAR_UDP;
2475 d_type = SOCKET_TYPE_CHAR_UDP;
2476 a_type = SOCKET_TYPE_CHAR_UDP;
2477 b_type = SOCKET_TYPE_CHAR_UDP;
2480 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2481 errno = ESOCKTNOSUPPORT;
2489 iface = socket_wrapper_default_iface();
2490 } else if (a_type && addr == 0xFFFFFFFF) {
2491 /* 255.255.255.255 only udp */
2494 iface = socket_wrapper_default_iface();
2495 } else if (b_type && addr == sw_bcast_addr) {
2496 /* 127.255.255.255 only udp */
2499 iface = socket_wrapper_default_iface();
2500 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2504 iface = (addr & 0x000000FF);
2506 errno = EADDRNOTAVAIL;
2510 /* Store the bind address for connect() */
2511 if (si->bindname.sa_socklen == 0) {
2512 struct sockaddr_in bind_in;
2513 socklen_t blen = sizeof(struct sockaddr_in);
2515 ZERO_STRUCT(bind_in);
2516 bind_in.sin_family = in->sin_family;
2517 bind_in.sin_port = in->sin_port;
2518 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2519 si->bindname.sa_socklen = blen;
2520 memcpy(&si->bindname.sa.in, &bind_in, blen);
2527 const struct sockaddr_in6 *in =
2528 (const struct sockaddr_in6 *)(const void *)inaddr;
2529 struct in6_addr cmp1, cmp2;
2533 type = SOCKET_TYPE_CHAR_TCP_V6;
2536 type = SOCKET_TYPE_CHAR_UDP_V6;
2539 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2540 errno = ESOCKTNOSUPPORT;
2544 /* XXX no multicast/broadcast */
2546 prt = ntohs(in->sin6_port);
2548 cmp1 = *swrap_ipv6();
2549 cmp2 = in->sin6_addr;
2550 cmp2.s6_addr[15] = 0;
2551 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2552 iface = socket_wrapper_default_iface();
2553 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2554 iface = in->sin6_addr.s6_addr[15];
2556 errno = EADDRNOTAVAIL;
2560 /* Store the bind address for connect() */
2561 if (si->bindname.sa_socklen == 0) {
2562 struct sockaddr_in6 bind_in;
2563 socklen_t blen = sizeof(struct sockaddr_in6);
2565 ZERO_STRUCT(bind_in);
2566 bind_in.sin6_family = in->sin6_family;
2567 bind_in.sin6_port = in->sin6_port;
2569 bind_in.sin6_addr = *swrap_ipv6();
2570 bind_in.sin6_addr.s6_addr[15] = iface;
2572 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2573 si->bindname.sa_socklen = blen;
2580 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2581 errno = EADDRNOTAVAIL;
2586 if (bcast) *bcast = is_bcast;
2588 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2593 swrap_dir = socket_wrapper_dir();
2594 if (swrap_dir == NULL) {
2600 /* handle auto-allocation of ephemeral ports */
2601 for (prt = 5001; prt < 10000; prt++) {
2602 swrap_un_path(un, swrap_dir, type, iface, prt);
2603 if (stat(un->sun_path, &st) == 0) continue;
2605 set_port(si->family, prt, &si->myname);
2606 set_port(si->family, prt, &si->bindname);
2613 SAFE_FREE(swrap_dir);
2618 swrap_un_path(un, swrap_dir, type, iface, prt);
2619 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2621 SAFE_FREE(swrap_dir);
2626 static struct socket_info *find_socket_info(int fd)
2628 int idx = find_socket_info_index(fd);
2634 return swrap_get_socket_info(idx);
2638 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2640 struct socket_info_fd *f;
2641 const struct socket_info *last_s = NULL;
2643 /* first catch invalid input */
2644 switch (sa->sa_family) {
2646 if (len < sizeof(struct sockaddr_in)) {
2652 if (len < sizeof(struct sockaddr_in6)) {
2662 for (f = socket_fds; f; f = f->next) {
2663 struct socket_info *s = swrap_get_socket_info(f->si_index);
2670 if (s->myname == NULL) {
2673 if (s->myname->sa_family != sa->sa_family) {
2676 switch (s->myname->sa_family) {
2678 struct sockaddr_in *sin1, *sin2;
2680 sin1 = (struct sockaddr_in *)s->myname;
2681 sin2 = (struct sockaddr_in *)sa;
2683 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2686 if (sin1->sin_port != sin2->sin_port) {
2689 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2699 struct sockaddr_in6 *sin1, *sin2;
2701 sin1 = (struct sockaddr_in6 *)s->myname;
2702 sin2 = (struct sockaddr_in6 *)sa;
2704 if (sin1->sin6_port != sin2->sin6_port) {
2707 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2729 static void swrap_remove_stale(int fd);
2731 static int sockaddr_convert_to_un(struct socket_info *si,
2732 const struct sockaddr *in_addr,
2734 struct sockaddr_un *out_addr,
2738 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2740 (void) in_len; /* unused */
2742 if (out_addr == NULL) {
2746 out->sa_family = AF_UNIX;
2747 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2748 out->sa_len = sizeof(*out_addr);
2751 switch (in_addr->sa_family) {
2753 const struct sockaddr_in *sin;
2754 if (si->family != AF_INET) {
2757 if (in_len < sizeof(struct sockaddr_in)) {
2760 sin = (const struct sockaddr_in *)(const void *)in_addr;
2761 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2766 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2767 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2781 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2782 errno = ESOCKTNOSUPPORT;
2786 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2788 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2794 errno = EAFNOSUPPORT;
2795 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2799 static int sockaddr_convert_from_un(const struct socket_info *si,
2800 const struct sockaddr_un *in_addr,
2801 socklen_t un_addrlen,
2803 struct sockaddr *out_addr,
2804 socklen_t *out_addrlen)
2808 if (out_addr == NULL || out_addrlen == NULL)
2811 if (un_addrlen == 0) {
2826 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2827 errno = ESOCKTNOSUPPORT;
2830 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2831 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2832 out_addr->sa_len = *out_addrlen;
2839 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2840 errno = EAFNOSUPPORT;
2844 enum swrap_packet_type {
2846 SWRAP_CONNECT_UNREACH,
2854 SWRAP_SENDTO_UNREACH,
2865 struct swrap_file_hdr {
2867 uint16_t version_major;
2868 uint16_t version_minor;
2871 uint32_t frame_max_len;
2872 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2875 #define SWRAP_FILE_HDR_SIZE 24
2877 struct swrap_packet_frame {
2879 uint32_t micro_seconds;
2880 uint32_t recorded_length;
2881 uint32_t full_length;
2883 #define SWRAP_PACKET_FRAME_SIZE 16
2885 union swrap_packet_ip {
2889 uint16_t packet_length;
2890 uint16_t identification;
2895 uint16_t hdr_checksum;
2899 #define SWRAP_PACKET_IP_V4_SIZE 20
2902 uint8_t flow_label_high;
2903 uint16_t flow_label_low;
2904 uint16_t payload_length;
2905 uint8_t next_header;
2907 uint8_t src_addr[16];
2908 uint8_t dest_addr[16];
2910 #define SWRAP_PACKET_IP_V6_SIZE 40
2912 #define SWRAP_PACKET_IP_SIZE 40
2914 union swrap_packet_payload {
2916 uint16_t source_port;
2926 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2928 uint16_t source_port;
2933 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2940 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2947 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2949 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2951 #define SWRAP_PACKET_MIN_ALLOC \
2952 (SWRAP_PACKET_FRAME_SIZE + \
2953 SWRAP_PACKET_IP_SIZE + \
2954 SWRAP_PACKET_PAYLOAD_SIZE)
2956 static const char *swrap_pcap_init_file(void)
2958 static int initialized = 0;
2959 static const char *s = NULL;
2960 static const struct swrap_file_hdr h;
2961 static const struct swrap_packet_frame f;
2962 static const union swrap_packet_ip i;
2963 static const union swrap_packet_payload p;
2965 if (initialized == 1) {
2971 * TODO: don't use the structs use plain buffer offsets
2972 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2974 * for now make sure we disable PCAP support
2975 * if the struct has alignment!
2977 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2980 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2983 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2986 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2989 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2992 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2995 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2998 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
3001 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
3004 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
3008 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
3012 if (strncmp(s, "./", 2) == 0) {
3015 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
3019 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
3020 const struct sockaddr *src,
3021 const struct sockaddr *dest,
3023 const uint8_t *payload,
3025 unsigned long tcp_seqno,
3026 unsigned long tcp_ack,
3027 unsigned char tcp_ctl,
3029 size_t *_packet_len)
3031 uint8_t *base = NULL;
3032 uint8_t *buf = NULL;
3035 struct swrap_packet_frame *frame;
3039 union swrap_packet_ip *ip;
3041 union swrap_packet_payload *pay;
3044 size_t nonwire_len = sizeof(struct swrap_packet_frame);
3045 size_t wire_hdr_len = 0;
3046 size_t wire_len = 0;
3047 size_t ip_hdr_len = 0;
3048 size_t icmp_hdr_len = 0;
3049 size_t icmp_truncate_len = 0;
3050 uint8_t protocol = 0, icmp_protocol = 0;
3051 const struct sockaddr_in *src_in = NULL;
3052 const struct sockaddr_in *dest_in = NULL;
3054 const struct sockaddr_in6 *src_in6 = NULL;
3055 const struct sockaddr_in6 *dest_in6 = NULL;
3060 switch (src->sa_family) {
3062 src_in = (const struct sockaddr_in *)(const void *)src;
3063 dest_in = (const struct sockaddr_in *)(const void *)dest;
3064 src_port = src_in->sin_port;
3065 dest_port = dest_in->sin_port;
3066 ip_hdr_len = sizeof(i.ip->v4);
3070 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
3071 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
3072 src_port = src_in6->sin6_port;
3073 dest_port = dest_in6->sin6_port;
3074 ip_hdr_len = sizeof(i.ip->v6);
3081 switch (socket_type) {
3083 protocol = 0x06; /* TCP */
3084 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
3085 wire_len = wire_hdr_len + payload_len;
3089 protocol = 0x11; /* UDP */
3090 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
3091 wire_len = wire_hdr_len + payload_len;
3099 icmp_protocol = protocol;
3100 switch (src->sa_family) {
3102 protocol = 0x01; /* ICMPv4 */
3103 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
3107 protocol = 0x3A; /* ICMPv6 */
3108 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
3112 if (wire_len > 64 ) {
3113 icmp_truncate_len = wire_len - 64;
3115 wire_len += icmp_hdr_len;
3118 packet_len = nonwire_len + wire_len;
3119 alloc_len = packet_len;
3120 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
3121 alloc_len = SWRAP_PACKET_MIN_ALLOC;
3124 base = (uint8_t *)calloc(1, alloc_len);
3132 f.frame->seconds = tval->tv_sec;
3133 f.frame->micro_seconds = tval->tv_usec;
3134 f.frame->recorded_length = wire_len - icmp_truncate_len;
3135 f.frame->full_length = wire_len - icmp_truncate_len;
3137 buf += SWRAP_PACKET_FRAME_SIZE;
3140 switch (src->sa_family) {
3142 if (src_in == NULL || dest_in == NULL) {
3147 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3148 i.ip->v4.tos = 0x00;
3149 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
3150 i.ip->v4.identification = htons(0xFFFF);
3151 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3152 i.ip->v4.fragment = htons(0x0000);
3153 i.ip->v4.ttl = 0xFF;
3154 i.ip->v4.protocol = protocol;
3155 i.ip->v4.hdr_checksum = htons(0x0000);
3156 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
3157 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
3158 buf += SWRAP_PACKET_IP_V4_SIZE;
3162 if (src_in6 == NULL || dest_in6 == NULL) {
3167 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3168 i.ip->v6.flow_label_high = 0x00;
3169 i.ip->v6.flow_label_low = 0x0000;
3170 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3171 i.ip->v6.next_header = protocol;
3172 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
3173 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
3174 buf += SWRAP_PACKET_IP_V6_SIZE;
3180 pay = (union swrap_packet_payload *)(void *)buf;
3181 switch (src->sa_family) {
3183 pay->icmp4.type = 0x03; /* destination unreachable */
3184 pay->icmp4.code = 0x01; /* host unreachable */
3185 pay->icmp4.checksum = htons(0x0000);
3186 pay->icmp4.unused = htonl(0x00000000);
3188 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3190 /* set the ip header in the ICMP payload */
3192 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3193 i.ip->v4.tos = 0x00;
3194 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3195 i.ip->v4.identification = htons(0xFFFF);
3196 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3197 i.ip->v4.fragment = htons(0x0000);
3198 i.ip->v4.ttl = 0xFF;
3199 i.ip->v4.protocol = icmp_protocol;
3200 i.ip->v4.hdr_checksum = htons(0x0000);
3201 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3202 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3204 buf += SWRAP_PACKET_IP_V4_SIZE;
3206 src_port = dest_in->sin_port;
3207 dest_port = src_in->sin_port;
3211 pay->icmp6.type = 0x01; /* destination unreachable */
3212 pay->icmp6.code = 0x03; /* address unreachable */
3213 pay->icmp6.checksum = htons(0x0000);
3214 pay->icmp6.unused = htonl(0x00000000);
3215 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3217 /* set the ip header in the ICMP payload */
3219 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3220 i.ip->v6.flow_label_high = 0x00;
3221 i.ip->v6.flow_label_low = 0x0000;
3222 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3223 i.ip->v6.next_header = protocol;
3224 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3225 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3227 buf += SWRAP_PACKET_IP_V6_SIZE;
3229 src_port = dest_in6->sin6_port;
3230 dest_port = src_in6->sin6_port;
3236 pay = (union swrap_packet_payload *)(void *)buf;
3238 switch (socket_type) {
3240 pay->tcp.source_port = src_port;
3241 pay->tcp.dest_port = dest_port;
3242 pay->tcp.seq_num = htonl(tcp_seqno);
3243 pay->tcp.ack_num = htonl(tcp_ack);
3244 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3245 pay->tcp.control = tcp_ctl;
3246 pay->tcp.window = htons(0x7FFF);
3247 pay->tcp.checksum = htons(0x0000);
3248 pay->tcp.urg = htons(0x0000);
3249 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3254 pay->udp.source_port = src_port;
3255 pay->udp.dest_port = dest_port;
3256 pay->udp.length = htons(8 + payload_len);
3257 pay->udp.checksum = htons(0x0000);
3258 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3263 if (payload && payload_len > 0) {
3264 memcpy(buf, payload, payload_len);
3267 *_packet_len = packet_len - icmp_truncate_len;
3271 static int swrap_pcap_get_fd(const char *fname)
3279 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3281 struct swrap_file_hdr file_hdr;
3282 file_hdr.magic = 0xA1B2C3D4;
3283 file_hdr.version_major = 0x0002;
3284 file_hdr.version_minor = 0x0004;
3285 file_hdr.timezone = 0x00000000;
3286 file_hdr.sigfigs = 0x00000000;
3287 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3288 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3290 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3297 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3302 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3303 const struct sockaddr *addr,
3304 enum swrap_packet_type type,
3305 const void *buf, size_t len,
3308 const struct sockaddr *src_addr;
3309 const struct sockaddr *dest_addr;
3310 unsigned long tcp_seqno = 0;
3311 unsigned long tcp_ack = 0;
3312 unsigned char tcp_ctl = 0;
3313 int unreachable = 0;
3317 switch (si->family) {
3329 case SWRAP_CONNECT_SEND:
3330 if (si->type != SOCK_STREAM) {
3334 src_addr = &si->myname.sa.s;
3337 tcp_seqno = si->io.pck_snd;
3338 tcp_ack = si->io.pck_rcv;
3339 tcp_ctl = 0x02; /* SYN */
3341 si->io.pck_snd += 1;
3345 case SWRAP_CONNECT_RECV:
3346 if (si->type != SOCK_STREAM) {
3350 dest_addr = &si->myname.sa.s;
3353 tcp_seqno = si->io.pck_rcv;
3354 tcp_ack = si->io.pck_snd;
3355 tcp_ctl = 0x12; /** SYN,ACK */
3357 si->io.pck_rcv += 1;
3361 case SWRAP_CONNECT_UNREACH:
3362 if (si->type != SOCK_STREAM) {
3366 dest_addr = &si->myname.sa.s;
3369 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3370 tcp_seqno = si->io.pck_snd - 1;
3371 tcp_ack = si->io.pck_rcv;
3372 tcp_ctl = 0x02; /* SYN */
3377 case SWRAP_CONNECT_ACK:
3378 if (si->type != SOCK_STREAM) {
3382 src_addr = &si->myname.sa.s;
3385 tcp_seqno = si->io.pck_snd;
3386 tcp_ack = si->io.pck_rcv;
3387 tcp_ctl = 0x10; /* ACK */
3391 case SWRAP_ACCEPT_SEND:
3392 if (si->type != SOCK_STREAM) {
3396 dest_addr = &si->myname.sa.s;
3399 tcp_seqno = si->io.pck_rcv;
3400 tcp_ack = si->io.pck_snd;
3401 tcp_ctl = 0x02; /* SYN */
3403 si->io.pck_rcv += 1;
3407 case SWRAP_ACCEPT_RECV:
3408 if (si->type != SOCK_STREAM) {
3412 src_addr = &si->myname.sa.s;
3415 tcp_seqno = si->io.pck_snd;
3416 tcp_ack = si->io.pck_rcv;
3417 tcp_ctl = 0x12; /* SYN,ACK */
3419 si->io.pck_snd += 1;
3423 case SWRAP_ACCEPT_ACK:
3424 if (si->type != SOCK_STREAM) {
3428 dest_addr = &si->myname.sa.s;
3431 tcp_seqno = si->io.pck_rcv;
3432 tcp_ack = si->io.pck_snd;
3433 tcp_ctl = 0x10; /* ACK */
3438 src_addr = &si->myname.sa.s;
3439 dest_addr = &si->peername.sa.s;
3441 tcp_seqno = si->io.pck_snd;
3442 tcp_ack = si->io.pck_rcv;
3443 tcp_ctl = 0x18; /* PSH,ACK */
3445 si->io.pck_snd += len;
3449 case SWRAP_SEND_RST:
3450 dest_addr = &si->myname.sa.s;
3451 src_addr = &si->peername.sa.s;
3453 if (si->type == SOCK_DGRAM) {
3454 return swrap_pcap_marshall_packet(si,
3456 SWRAP_SENDTO_UNREACH,
3462 tcp_seqno = si->io.pck_rcv;
3463 tcp_ack = si->io.pck_snd;
3464 tcp_ctl = 0x14; /** RST,ACK */
3468 case SWRAP_PENDING_RST:
3469 dest_addr = &si->myname.sa.s;
3470 src_addr = &si->peername.sa.s;
3472 if (si->type == SOCK_DGRAM) {
3476 tcp_seqno = si->io.pck_rcv;
3477 tcp_ack = si->io.pck_snd;
3478 tcp_ctl = 0x14; /* RST,ACK */
3483 dest_addr = &si->myname.sa.s;
3484 src_addr = &si->peername.sa.s;
3486 tcp_seqno = si->io.pck_rcv;
3487 tcp_ack = si->io.pck_snd;
3488 tcp_ctl = 0x18; /* PSH,ACK */
3490 si->io.pck_rcv += len;
3494 case SWRAP_RECV_RST:
3495 dest_addr = &si->myname.sa.s;
3496 src_addr = &si->peername.sa.s;
3498 if (si->type == SOCK_DGRAM) {
3502 tcp_seqno = si->io.pck_rcv;
3503 tcp_ack = si->io.pck_snd;
3504 tcp_ctl = 0x14; /* RST,ACK */
3509 src_addr = &si->myname.sa.s;
3512 si->io.pck_snd += len;
3516 case SWRAP_SENDTO_UNREACH:
3517 dest_addr = &si->myname.sa.s;
3524 case SWRAP_RECVFROM:
3525 dest_addr = &si->myname.sa.s;
3528 si->io.pck_rcv += len;
3532 case SWRAP_CLOSE_SEND:
3533 if (si->type != SOCK_STREAM) {
3537 src_addr = &si->myname.sa.s;
3538 dest_addr = &si->peername.sa.s;
3540 tcp_seqno = si->io.pck_snd;
3541 tcp_ack = si->io.pck_rcv;
3542 tcp_ctl = 0x11; /* FIN, ACK */
3544 si->io.pck_snd += 1;
3548 case SWRAP_CLOSE_RECV:
3549 if (si->type != SOCK_STREAM) {
3553 dest_addr = &si->myname.sa.s;
3554 src_addr = &si->peername.sa.s;
3556 tcp_seqno = si->io.pck_rcv;
3557 tcp_ack = si->io.pck_snd;
3558 tcp_ctl = 0x11; /* FIN,ACK */
3560 si->io.pck_rcv += 1;
3564 case SWRAP_CLOSE_ACK:
3565 if (si->type != SOCK_STREAM) {
3569 src_addr = &si->myname.sa.s;
3570 dest_addr = &si->peername.sa.s;
3572 tcp_seqno = si->io.pck_snd;
3573 tcp_ack = si->io.pck_rcv;
3574 tcp_ctl = 0x10; /* ACK */
3581 swrapGetTimeOfDay(&tv);
3583 return swrap_pcap_packet_init(&tv,
3587 (const uint8_t *)buf,
3596 static void swrap_pcap_dump_packet(struct socket_info *si,
3597 const struct sockaddr *addr,
3598 enum swrap_packet_type type,
3599 const void *buf, size_t len)
3601 const char *file_name;
3603 size_t packet_len = 0;
3606 swrap_mutex_lock(&pcap_dump_mutex);
3608 file_name = swrap_pcap_init_file();
3613 packet = swrap_pcap_marshall_packet(si,
3619 if (packet == NULL) {
3623 fd = swrap_pcap_get_fd(file_name);
3625 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3634 swrap_mutex_unlock(&pcap_dump_mutex);
3637 /****************************************************************************
3639 ***************************************************************************/
3641 #ifdef HAVE_SIGNALFD
3642 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3646 rc = libc_signalfd(fd, mask, flags);
3648 swrap_remove_stale(fd);
3654 int signalfd(int fd, const sigset_t *mask, int flags)
3656 return swrap_signalfd(fd, mask, flags);
3660 /****************************************************************************
3662 ***************************************************************************/
3664 static int swrap_socket(int family, int type, int protocol)
3666 struct socket_info *si = NULL;
3667 struct socket_info _si = { 0 };
3670 int real_type = type;
3673 * Remove possible addition flags passed to socket() so
3674 * do not fail checking the type.
3675 * See https://lwn.net/Articles/281965/
3678 real_type &= ~SOCK_CLOEXEC;
3680 #ifdef SOCK_NONBLOCK
3681 real_type &= ~SOCK_NONBLOCK;
3684 if (!socket_wrapper_enabled()) {
3685 return libc_socket(family, type, protocol);
3696 #endif /* AF_NETLINK */
3699 #endif /* AF_PACKET */
3701 fd = libc_socket(family, type, protocol);
3703 /* Check if we have a stale fd and remove it */
3704 swrap_remove_stale(fd);
3705 SWRAP_LOG(SWRAP_LOG_TRACE,
3706 "Unix socket fd=%d",
3711 errno = EAFNOSUPPORT;
3715 switch (real_type) {
3721 errno = EPROTONOSUPPORT;
3729 if (real_type == SOCK_STREAM) {
3734 if (real_type == SOCK_DGRAM) {
3739 errno = EPROTONOSUPPORT;
3744 * We must call libc_socket with type, from the caller, not the version
3745 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3747 fd = libc_socket(AF_UNIX, type, 0);
3753 /* Check if we have a stale fd and remove it */
3754 swrap_remove_stale(fd);
3757 si->family = family;
3759 /* however, the rest of the socket_wrapper code expects just
3760 * the type, not the flags */
3761 si->type = real_type;
3762 si->protocol = protocol;
3765 * Setup myname so getsockname() can succeed to find out the socket
3768 switch(si->family) {
3770 struct sockaddr_in sin = {
3771 .sin_family = AF_INET,
3774 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3775 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3780 struct sockaddr_in6 sin6 = {
3781 .sin6_family = AF_INET6,
3784 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3785 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3794 ret = swrap_create_socket(si, fd);
3796 int saved_errno = errno;
3798 errno = saved_errno;
3802 SWRAP_LOG(SWRAP_LOG_TRACE,
3803 "Created %s socket for protocol %s, fd=%d",
3804 family == AF_INET ? "IPv4" : "IPv6",
3805 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3811 int socket(int family, int type, int protocol)
3813 return swrap_socket(family, type, protocol);
3816 /****************************************************************************
3818 ***************************************************************************/
3820 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3824 rc = libc_socketpair(family, type, protocol, sv);
3826 swrap_remove_stale(sv[0]);
3827 swrap_remove_stale(sv[1]);
3833 int socketpair(int family, int type, int protocol, int sv[2])
3835 return swrap_socketpair(family, type, protocol, sv);
3838 /****************************************************************************
3840 ***************************************************************************/
3842 #ifdef HAVE_TIMERFD_CREATE
3843 static int swrap_timerfd_create(int clockid, int flags)
3847 fd = libc_timerfd_create(clockid, flags);
3849 swrap_remove_stale(fd);
3855 int timerfd_create(int clockid, int flags)
3857 return swrap_timerfd_create(clockid, flags);
3861 /****************************************************************************
3863 ***************************************************************************/
3865 static int swrap_pipe(int pipefd[2])
3869 rc = libc_pipe(pipefd);
3871 swrap_remove_stale(pipefd[0]);
3872 swrap_remove_stale(pipefd[1]);
3878 int pipe(int pipefd[2])
3880 return swrap_pipe(pipefd);
3883 /****************************************************************************
3885 ***************************************************************************/
3887 static int swrap_accept(int s,
3888 struct sockaddr *addr,
3892 struct socket_info *parent_si, *child_si;
3893 struct socket_info new_si = { 0 };
3896 struct swrap_address un_addr = {
3897 .sa_socklen = sizeof(struct sockaddr_un),
3899 struct swrap_address un_my_addr = {
3900 .sa_socklen = sizeof(struct sockaddr_un),
3902 struct swrap_address in_addr = {
3903 .sa_socklen = sizeof(struct sockaddr_storage),
3905 struct swrap_address in_my_addr = {
3906 .sa_socklen = sizeof(struct sockaddr_storage),
3910 parent_si = find_socket_info(s);
3913 return libc_accept4(s, addr, addrlen, flags);
3916 return libc_accept(s, addr, addrlen);
3922 * prevent parent_si from being altered / closed
3925 SWRAP_LOCK_SI(parent_si);
3928 * assume out sockaddr have the same size as the in parent
3931 in_addr.sa_socklen = socket_length(parent_si->family);
3932 if (in_addr.sa_socklen <= 0) {
3933 SWRAP_UNLOCK_SI(parent_si);
3938 SWRAP_UNLOCK_SI(parent_si);
3941 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3944 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3947 int saved_errno = errno;
3948 if (saved_errno == ENOTSOCK) {
3949 /* Remove stale fds */
3950 swrap_remove_stale(s);
3952 errno = saved_errno;
3958 /* Check if we have a stale fd and remove it */
3959 swrap_remove_stale(fd);
3961 if (un_addr.sa.un.sun_path[0] == '\0') {
3963 * FreeBSD seems to have a problem where
3964 * accept4() on the unix socket doesn't
3965 * ECONNABORTED for already disconnected connections.
3967 * Let's try libc_getpeername() to get the peer address
3968 * as a fallback, but it'll likely return ENOTCONN,
3969 * which we have to map to ECONNABORTED.
3971 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3972 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3974 int saved_errno = errno;
3976 if (saved_errno == ENOTCONN) {
3978 * If the connection is already disconnected
3979 * we should return ECONNABORTED.
3981 saved_errno = ECONNABORTED;
3983 errno = saved_errno;
3988 ret = libc_getsockname(fd,
3990 &un_my_addr.sa_socklen);
3992 int saved_errno = errno;
3994 if (saved_errno == ENOTCONN) {
3996 * If the connection is already disconnected
3997 * we should return ECONNABORTED.
3999 saved_errno = ECONNABORTED;
4001 errno = saved_errno;
4005 SWRAP_LOCK_SI(parent_si);
4007 ret = sockaddr_convert_from_un(parent_si,
4012 &in_addr.sa_socklen);
4014 int saved_errno = errno;
4015 SWRAP_UNLOCK_SI(parent_si);
4017 errno = saved_errno;
4023 child_si->family = parent_si->family;
4024 child_si->type = parent_si->type;
4025 child_si->protocol = parent_si->protocol;
4026 child_si->bound = 1;
4027 child_si->is_server = 1;
4028 child_si->connected = 1;
4030 SWRAP_UNLOCK_SI(parent_si);
4032 child_si->peername = (struct swrap_address) {
4033 .sa_socklen = in_addr.sa_socklen,
4035 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
4037 if (addr != NULL && addrlen != NULL) {
4038 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
4040 memcpy(addr, &in_addr.sa.ss, copy_len);
4042 *addrlen = in_addr.sa_socklen;
4045 ret = sockaddr_convert_from_un(child_si,
4047 un_my_addr.sa_socklen,
4050 &in_my_addr.sa_socklen);
4052 int saved_errno = errno;
4054 errno = saved_errno;
4058 SWRAP_LOG(SWRAP_LOG_TRACE,
4059 "accept() path=%s, fd=%d",
4060 un_my_addr.sa.un.sun_path, s);
4062 child_si->myname = (struct swrap_address) {
4063 .sa_socklen = in_my_addr.sa_socklen,
4065 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
4067 idx = swrap_create_socket(&new_si, fd);
4069 int saved_errno = errno;
4071 errno = saved_errno;
4076 struct socket_info *si = swrap_get_socket_info(idx);
4079 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
4080 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
4081 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
4082 SWRAP_UNLOCK_SI(si);
4089 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
4091 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
4095 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4096 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
4098 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
4101 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
4104 static int autobind_start_init;
4105 static int autobind_start;
4107 /* using sendto() or connect() on an unbound socket would give the
4108 recipient no way to reply, as unlike UDP and TCP, a unix domain
4109 socket can't auto-assign ephemeral port numbers, so we need to
4111 Note: this might change the family from ipv6 to ipv4
4113 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
4115 struct swrap_address un_addr = {
4116 .sa_socklen = sizeof(struct sockaddr_un),
4122 char *swrap_dir = NULL;
4124 swrap_mutex_lock(&autobind_start_mutex);
4126 if (autobind_start_init != 1) {
4127 autobind_start_init = 1;
4128 autobind_start = getpid();
4129 autobind_start %= 50000;
4130 autobind_start += 10000;
4133 un_addr.sa.un.sun_family = AF_UNIX;
4137 struct sockaddr_in in;
4141 type = SOCKET_TYPE_CHAR_TCP;
4144 type = SOCKET_TYPE_CHAR_UDP;
4147 errno = ESOCKTNOSUPPORT;
4152 memset(&in, 0, sizeof(in));
4153 in.sin_family = AF_INET;
4154 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
4155 socket_wrapper_default_iface()));
4157 si->myname = (struct swrap_address) {
4158 .sa_socklen = sizeof(in),
4160 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
4165 struct sockaddr_in6 in6;
4167 if (si->family != family) {
4168 errno = ENETUNREACH;
4175 type = SOCKET_TYPE_CHAR_TCP_V6;
4178 type = SOCKET_TYPE_CHAR_UDP_V6;
4181 errno = ESOCKTNOSUPPORT;
4186 memset(&in6, 0, sizeof(in6));
4187 in6.sin6_family = AF_INET6;
4188 in6.sin6_addr = *swrap_ipv6();
4189 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4191 si->myname = (struct swrap_address) {
4192 .sa_socklen = sizeof(in6),
4194 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4199 errno = ESOCKTNOSUPPORT;
4204 if (autobind_start > 60000) {
4205 autobind_start = 10000;
4208 swrap_dir = socket_wrapper_dir();
4209 if (swrap_dir == NULL) {
4215 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4216 port = autobind_start + i;
4217 swrap_un_path(&un_addr.sa.un,
4220 socket_wrapper_default_iface(),
4223 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4225 if (errno == EALREADY || errno == EADDRINUSE) {
4231 si->un_addr = un_addr.sa.un;
4234 autobind_start = port + 1;
4237 if (i == SOCKET_MAX_SOCKETS) {
4238 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4239 "interface "SOCKET_FORMAT,
4242 socket_wrapper_default_iface(),
4249 si->family = family;
4250 set_port(si->family, port, &si->myname);
4255 SAFE_FREE(swrap_dir);
4256 swrap_mutex_unlock(&autobind_start_mutex);
4260 /****************************************************************************
4262 ***************************************************************************/
4264 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4268 struct swrap_address un_addr = {
4269 .sa_socklen = sizeof(struct sockaddr_un),
4271 struct socket_info *si = find_socket_info(s);
4272 struct swrap_sockaddr_buf buf = {};
4276 return libc_connect(s, serv_addr, addrlen);
4281 if (si->bound == 0) {
4282 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4288 if (si->family != serv_addr->sa_family) {
4289 SWRAP_LOG(SWRAP_LOG_ERROR,
4290 "called for fd=%d (family=%d) called with invalid family=%d",
4291 s, si->family, serv_addr->sa_family);
4297 ret = sockaddr_convert_to_un(si, serv_addr,
4298 addrlen, &un_addr.sa.un, 0, &bcast);
4304 errno = ENETUNREACH;
4309 if (si->type == SOCK_DGRAM) {
4310 si->defer_connect = 1;
4313 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4315 ret = libc_connect(s,
4317 un_addr.sa_socklen);
4320 SWRAP_LOG(SWRAP_LOG_TRACE,
4321 "connect(%s) path=%s, fd=%d",
4322 swrap_sockaddr_string(&buf, serv_addr),
4323 un_addr.sa.un.sun_path, s);
4326 /* to give better errors */
4327 if (ret == -1 && errno == ENOENT) {
4328 errno = EHOSTUNREACH;
4332 si->peername = (struct swrap_address) {
4333 .sa_socklen = addrlen,
4336 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4340 * When we connect() on a socket than we have to bind the
4341 * outgoing connection on the interface we use for the
4342 * transport. We already bound it on the right interface
4343 * but here we have to update the name so getsockname()
4344 * returns correct information.
4346 if (si->bindname.sa_socklen > 0) {
4347 si->myname = (struct swrap_address) {
4348 .sa_socklen = si->bindname.sa_socklen,
4351 memcpy(&si->myname.sa.ss,
4352 &si->bindname.sa.ss,
4353 si->bindname.sa_socklen);
4355 /* Cleanup bindname */
4356 si->bindname = (struct swrap_address) {
4361 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4362 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4364 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4368 SWRAP_UNLOCK_SI(si);
4372 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4374 return swrap_connect(s, serv_addr, addrlen);
4377 /****************************************************************************
4379 ***************************************************************************/
4381 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4384 struct swrap_address un_addr = {
4385 .sa_socklen = sizeof(struct sockaddr_un),
4387 struct socket_info *si = find_socket_info(s);
4388 struct swrap_sockaddr_buf buf = {};
4389 int ret_errno = errno;
4396 return libc_bind(s, myaddr, addrlen);
4401 switch (si->family) {
4403 const struct sockaddr_in *sin;
4404 if (addrlen < sizeof(struct sockaddr_in)) {
4405 bind_error = EINVAL;
4409 sin = (const struct sockaddr_in *)(const void *)myaddr;
4411 if (sin->sin_family != AF_INET) {
4412 bind_error = EAFNOSUPPORT;
4415 /* special case for AF_UNSPEC */
4416 if (sin->sin_family == AF_UNSPEC &&
4417 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4426 const struct sockaddr_in6 *sin6;
4427 if (addrlen < sizeof(struct sockaddr_in6)) {
4428 bind_error = EINVAL;
4432 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4434 if (sin6->sin6_family != AF_INET6) {
4435 bind_error = EAFNOSUPPORT;
4442 bind_error = EINVAL;
4446 if (bind_error != 0) {
4447 ret_errno = bind_error;
4453 in_use = check_addr_port_in_use(myaddr, addrlen);
4461 si->myname.sa_socklen = addrlen;
4462 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4464 ret = sockaddr_convert_to_un(si,
4475 unlink(un_addr.sa.un.sun_path);
4477 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4482 SWRAP_LOG(SWRAP_LOG_TRACE,
4483 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4484 swrap_sockaddr_string(&buf, myaddr),
4485 un_addr.sa.un.sun_path, s, ret, ret_errno);
4492 SWRAP_UNLOCK_SI(si);
4497 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4499 return swrap_bind(s, myaddr, addrlen);
4502 /****************************************************************************
4504 ***************************************************************************/
4506 #ifdef HAVE_BINDRESVPORT
4507 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4509 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4511 struct swrap_address myaddr = {
4512 .sa_socklen = sizeof(struct sockaddr_storage),
4515 static uint16_t port;
4520 #define SWRAP_STARTPORT 600
4521 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4522 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4525 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4529 salen = myaddr.sa_socklen;
4532 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4538 memset(&myaddr.sa.ss, 0, salen);
4543 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4546 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4548 salen = sizeof(struct sockaddr_in);
4549 sinp->sin_port = htons(port);
4553 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4555 salen = sizeof(struct sockaddr_in6);
4556 sin6p->sin6_port = htons(port);
4560 errno = EAFNOSUPPORT;
4565 if (port > SWRAP_ENDPORT) {
4566 port = SWRAP_STARTPORT;
4569 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4570 if (rc == 0 || errno != EADDRINUSE) {
4578 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4580 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4584 /****************************************************************************
4586 ***************************************************************************/
4588 static int swrap_listen(int s, int backlog)
4591 struct socket_info *si = find_socket_info(s);
4594 return libc_listen(s, backlog);
4599 if (si->bound == 0) {
4600 ret = swrap_auto_bind(s, si, si->family);
4607 ret = libc_listen(s, backlog);
4613 SWRAP_UNLOCK_SI(si);
4618 int listen(int s, int backlog)
4620 return swrap_listen(s, backlog);
4623 /****************************************************************************
4625 ***************************************************************************/
4627 static FILE *swrap_fopen(const char *name, const char *mode)
4631 fp = libc_fopen(name, mode);
4633 int fd = fileno(fp);
4635 swrap_remove_stale(fd);
4641 #undef fopen /* Needed for LFS handling */
4642 FILE *fopen(const char *name, const char *mode)
4644 return swrap_fopen(name, mode);
4647 /****************************************************************************
4649 ***************************************************************************/
4652 static FILE *swrap_fopen64(const char *name, const char *mode)
4656 fp = libc_fopen64(name, mode);
4658 int fd = fileno(fp);
4660 swrap_remove_stale(fd);
4666 FILE *fopen64(const char *name, const char *mode)
4668 return swrap_fopen64(name, mode);
4670 #endif /* HAVE_FOPEN64 */
4672 /****************************************************************************
4674 ***************************************************************************/
4676 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4680 ret = libc_vopen(pathname, flags, ap);
4683 * There are methods for closing descriptors (libc-internal code
4684 * paths, direct syscalls) which close descriptors in ways that
4685 * we can't intercept, so try to recover when we notice that
4688 swrap_remove_stale(ret);
4693 #undef open /* Needed for LFS handling */
4694 int open(const char *pathname, int flags, ...)
4699 va_start(ap, flags);
4700 fd = swrap_vopen(pathname, flags, ap);
4706 /****************************************************************************
4708 ***************************************************************************/
4711 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4715 ret = libc_vopen64(pathname, flags, ap);
4718 * There are methods for closing descriptors (libc-internal code
4719 * paths, direct syscalls) which close descriptors in ways that
4720 * we can't intercept, so try to recover when we notice that
4723 swrap_remove_stale(ret);
4728 int open64(const char *pathname, int flags, ...)
4733 va_start(ap, flags);
4734 fd = swrap_vopen64(pathname, flags, ap);
4739 #endif /* HAVE_OPEN64 */
4741 /****************************************************************************
4743 ***************************************************************************/
4745 #ifdef HAVE_OPENAT64
4747 swrap_vopenat64(int dirfd, const char *pathname, int flags, va_list ap)
4751 ret = libc_vopenat64(dirfd, pathname, flags, ap);
4754 * There are methods for closing descriptors (libc-internal code
4755 * paths, direct syscalls) which close descriptors in ways that
4756 * we can't intercept, so try to recover when we notice that
4759 swrap_remove_stale(ret);
4764 int openat64(int dirfd, const char *pathname, int flags, ...)
4769 va_start(ap, flags);
4770 fd = swrap_vopenat64(dirfd, pathname, flags, ap);
4775 #endif /* HAVE_OPENAT64 */
4777 /****************************************************************************
4779 ***************************************************************************/
4781 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4785 ret = libc_vopenat(dirfd, path, flags, ap);
4788 * There are methods for closing descriptors (libc-internal code
4789 * paths, direct syscalls) which close descriptors in ways that
4790 * we can't intercept, so try to recover when we notice that
4793 swrap_remove_stale(ret);
4799 #undef openat /* Needed for LFS handling */
4800 int openat(int dirfd, const char *path, int flags, ...)
4805 va_start(ap, flags);
4806 fd = swrap_vopenat(dirfd, path, flags, ap);
4812 /****************************************************************************
4814 ***************************************************************************/
4816 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4818 struct socket_info *si = find_socket_info(s);
4823 return libc_getpeername(s, name, addrlen);
4828 if (si->peername.sa_socklen == 0)
4834 len = MIN(*addrlen, si->peername.sa_socklen);
4840 memcpy(name, &si->peername.sa.ss, len);
4841 *addrlen = si->peername.sa_socklen;
4845 SWRAP_UNLOCK_SI(si);
4850 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4851 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4853 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4856 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4859 /****************************************************************************
4861 ***************************************************************************/
4863 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4865 struct socket_info *si = find_socket_info(s);
4870 return libc_getsockname(s, name, addrlen);
4875 len = MIN(*addrlen, si->myname.sa_socklen);
4881 memcpy(name, &si->myname.sa.ss, len);
4882 *addrlen = si->myname.sa_socklen;
4886 SWRAP_UNLOCK_SI(si);
4891 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4892 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4894 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4897 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4900 /****************************************************************************
4902 ***************************************************************************/
4905 # ifdef SO_PROTOTYPE /* The Solaris name */
4906 # define SO_PROTOCOL SO_PROTOTYPE
4907 # endif /* SO_PROTOTYPE */
4908 #endif /* SO_PROTOCOL */
4910 static int swrap_getsockopt(int s, int level, int optname,
4911 void *optval, socklen_t *optlen)
4913 struct socket_info *si = find_socket_info(s);
4917 return libc_getsockopt(s,
4926 if (level == SOL_SOCKET) {
4930 if (optval == NULL || optlen == NULL ||
4931 *optlen < (socklen_t)sizeof(int)) {
4937 *optlen = sizeof(int);
4938 *(int *)optval = si->family;
4941 #endif /* SO_DOMAIN */
4945 if (optval == NULL || optlen == NULL ||
4946 *optlen < (socklen_t)sizeof(int)) {
4952 *optlen = sizeof(int);
4953 *(int *)optval = si->protocol;
4956 #endif /* SO_PROTOCOL */
4958 if (optval == NULL || optlen == NULL ||
4959 *optlen < (socklen_t)sizeof(int)) {
4965 *optlen = sizeof(int);
4966 *(int *)optval = si->type;
4970 ret = libc_getsockopt(s,
4977 } else if (level == IPPROTO_TCP) {
4982 * This enables sending packets directly out over TCP.
4983 * As a unix socket is doing that any way, report it as
4986 if (optval == NULL || optlen == NULL ||
4987 *optlen < (socklen_t)sizeof(int)) {
4993 *optlen = sizeof(int);
4994 *(int *)optval = si->tcp_nodelay;
4998 #endif /* TCP_NODELAY */
5001 struct tcp_info info;
5002 socklen_t ilen = sizeof(info);
5004 #ifdef HAVE_NETINET_TCP_FSM_H
5005 /* This is FreeBSD */
5006 # define __TCP_LISTEN TCPS_LISTEN
5007 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
5008 # define __TCP_CLOSE TCPS_CLOSED
5011 # define __TCP_LISTEN TCP_LISTEN
5012 # define __TCP_ESTABLISHED TCP_ESTABLISHED
5013 # define __TCP_CLOSE TCP_CLOSE
5017 if (si->listening) {
5018 info.tcpi_state = __TCP_LISTEN;
5019 } else if (si->connected) {
5021 * For now we just fake a few values
5022 * supported both by FreeBSD and Linux
5024 info.tcpi_state = __TCP_ESTABLISHED;
5025 info.tcpi_rto = 200000; /* 200 msec */
5026 info.tcpi_rtt = 5000; /* 5 msec */
5027 info.tcpi_rttvar = 5000; /* 5 msec */
5029 info.tcpi_state = __TCP_CLOSE;
5030 info.tcpi_rto = 1000000; /* 1 sec */
5032 info.tcpi_rttvar = 250000; /* 250 msec */
5035 if (optval == NULL || optlen == NULL ||
5036 *optlen < (socklen_t)ilen) {
5043 memcpy(optval, &info, ilen);
5048 #endif /* TCP_INFO */
5054 errno = ENOPROTOOPT;
5058 SWRAP_UNLOCK_SI(si);
5062 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5063 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
5065 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
5068 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
5071 /****************************************************************************
5073 ***************************************************************************/
5075 static int swrap_setsockopt(int s, int level, int optname,
5076 const void *optval, socklen_t optlen)
5078 struct socket_info *si = find_socket_info(s);
5082 return libc_setsockopt(s,
5089 if (level == SOL_SOCKET) {
5090 return libc_setsockopt(s,
5099 if (level == IPPROTO_TCP) {
5106 * This enables sending packets directly out over TCP.
5107 * A unix socket is doing that any way.
5109 if (optval == NULL || optlen == 0 ||
5110 optlen < (socklen_t)sizeof(int)) {
5116 i = *discard_const_p(int, optval);
5117 if (i != 0 && i != 1) {
5122 si->tcp_nodelay = i;
5127 #endif /* TCP_NODELAY */
5133 switch (si->family) {
5135 if (level == IPPROTO_IP) {
5137 if (optname == IP_PKTINFO) {
5138 si->pktinfo = AF_INET;
5140 #endif /* IP_PKTINFO */
5146 if (level == IPPROTO_IPV6) {
5147 #ifdef IPV6_RECVPKTINFO
5148 if (optname == IPV6_RECVPKTINFO) {
5149 si->pktinfo = AF_INET6;
5151 #endif /* IPV6_PKTINFO */
5157 errno = ENOPROTOOPT;
5163 SWRAP_UNLOCK_SI(si);
5167 int setsockopt(int s, int level, int optname,
5168 const void *optval, socklen_t optlen)
5170 return swrap_setsockopt(s, level, optname, optval, optlen);
5173 /****************************************************************************
5175 ***************************************************************************/
5177 static int swrap_vioctl(int s, unsigned long int r, va_list va)
5179 struct socket_info *si = find_socket_info(s);
5181 int *value_ptr = NULL;
5185 return libc_vioctl(s, r, va);
5192 rc = libc_vioctl(s, r, va);
5197 value_ptr = ((int *)va_arg(ap, int *));
5200 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
5201 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5202 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
5203 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5208 /* this is FreeBSD */
5209 FALL_THROUGH; /* to TIOCOUTQ */
5210 #endif /* FIONWRITE */
5211 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
5213 * This may return more bytes then the application
5214 * sent into the socket, for tcp it should
5215 * return the number of unacked bytes.
5217 * On AF_UNIX, all bytes are immediately acked!
5220 value_ptr = ((int *)va_arg(ap, int *));
5228 SWRAP_UNLOCK_SI(si);
5232 #ifdef HAVE_IOCTL_INT
5233 int ioctl(int s, int r, ...)
5235 int ioctl(int s, unsigned long int r, ...)
5243 rc = swrap_vioctl(s, (unsigned long int) r, va);
5254 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5257 # ifdef _ALIGN /* BSD */
5258 #define CMSG_ALIGN _ALIGN
5260 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5261 # endif /* _ALIGN */
5262 #endif /* CMSG_ALIGN */
5265 * @brief Add a cmsghdr to a msghdr.
5267 * This is an function to add any type of cmsghdr. It will operate on the
5268 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5269 * the buffer position after the added cmsg element. Hence, this function is
5270 * intended to be used with an intermediate msghdr and not on the original
5271 * one handed in by the client.
5273 * @param[in] msg The msghdr to which to add the cmsg.
5275 * @param[in] level The cmsg level to set.
5277 * @param[in] type The cmsg type to set.
5279 * @param[in] data The cmsg data to set.
5281 * @param[in] len the length of the data to set.
5283 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5289 size_t cmlen = CMSG_LEN(len);
5290 size_t cmspace = CMSG_SPACE(len);
5291 uint8_t cmbuf[cmspace];
5292 void *cast_ptr = (void *)cmbuf;
5293 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5296 memset(cmbuf, 0, cmspace);
5298 if (msg->msg_controllen < cmlen) {
5299 cmlen = msg->msg_controllen;
5300 msg->msg_flags |= MSG_CTRUNC;
5303 if (msg->msg_controllen < cmspace) {
5304 cmspace = msg->msg_controllen;
5308 * We copy the full input data into an intermediate cmsghdr first
5309 * in order to more easily cope with truncation.
5311 cm->cmsg_len = cmlen;
5312 cm->cmsg_level = level;
5313 cm->cmsg_type = type;
5314 memcpy(CMSG_DATA(cm), data, len);
5317 * We now copy the possibly truncated buffer.
5318 * We copy cmlen bytes, but consume cmspace bytes,
5319 * leaving the possible padding uninitialiazed.
5321 p = (uint8_t *)msg->msg_control;
5322 memcpy(p, cm, cmlen);
5324 msg->msg_control = p;
5325 msg->msg_controllen -= cmspace;
5330 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5333 /* Add packet info */
5334 switch (si->pktinfo) {
5335 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5337 struct sockaddr_in *sin;
5338 #if defined(HAVE_STRUCT_IN_PKTINFO)
5339 struct in_pktinfo pkt;
5340 #elif defined(IP_RECVDSTADDR)
5344 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5345 sin = &si->bindname.sa.in;
5347 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5350 sin = &si->myname.sa.in;
5355 #if defined(HAVE_STRUCT_IN_PKTINFO)
5356 pkt.ipi_ifindex = socket_wrapper_default_iface();
5357 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5358 #elif defined(IP_RECVDSTADDR)
5359 pkt = sin->sin_addr;
5362 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5367 #endif /* IP_PKTINFO */
5368 #if defined(HAVE_IPV6)
5370 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5371 struct sockaddr_in6 *sin6;
5372 struct in6_pktinfo pkt6;
5374 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5375 sin6 = &si->bindname.sa.in6;
5377 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5380 sin6 = &si->myname.sa.in6;
5385 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5386 pkt6.ipi6_addr = sin6->sin6_addr;
5388 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5389 &pkt6, sizeof(pkt6));
5390 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5394 #endif /* IPV6_PKTINFO */
5402 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5403 struct msghdr *omsg)
5407 if (si->pktinfo > 0) {
5408 rc = swrap_msghdr_add_pktinfo(si, omsg);
5414 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5416 size_t *cm_data_space);
5417 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5419 size_t *cm_data_space);
5420 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5422 size_t *cm_data_space);
5424 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5426 size_t *cm_data_space)
5428 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5429 struct cmsghdr *cmsg;
5433 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5437 for (cmsg = CMSG_FIRSTHDR(msg);
5439 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5440 switch (cmsg->cmsg_level) {
5442 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5447 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5452 rc = swrap_sendmsg_copy_cmsg(cmsg,
5458 int saved_errno = errno;
5459 SAFE_FREE(*cm_data);
5461 errno = saved_errno;
5469 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5471 size_t *cm_data_space)
5476 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5478 p = realloc((*cm_data), cmspace);
5484 p = (*cm_data) + (*cm_data_space);
5485 *cm_data_space = cmspace;
5487 memcpy(p, cmsg, cmsg->cmsg_len);
5492 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5494 size_t *cm_data_space);
5497 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5499 size_t *cm_data_space)
5503 switch(cmsg->cmsg_type) {
5506 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5513 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5525 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5527 size_t *cm_data_space)
5529 (void)cmsg; /* unused */
5530 (void)cm_data; /* unused */
5531 (void)cm_data_space; /* unused */
5534 * Passing a IP pktinfo to a unix socket might be rejected by the
5535 * Kernel, at least on FreeBSD. So skip this cmsg.
5540 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5542 size_t *cm_data_space)
5546 switch (cmsg->cmsg_type) {
5548 SWRAP_LOG(SWRAP_LOG_TRACE,
5549 "Ignoring SCM_RIGHTS on inet socket!");
5552 #ifdef SCM_CREDENTIALS
5553 case SCM_CREDENTIALS:
5554 SWRAP_LOG(SWRAP_LOG_TRACE,
5555 "Ignoring SCM_CREDENTIALS on inet socket!");
5558 #endif /* SCM_CREDENTIALS */
5560 rc = swrap_sendmsg_copy_cmsg(cmsg,
5569 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5572 * We only allow up to 6 fds at a time
5573 * as that's more than enough for Samba
5574 * and it means we can keep the logic simple
5575 * and work with fixed size arrays.
5577 * We also keep sizeof(struct swrap_unix_scm_rights)
5578 * under PIPE_BUF (4096) in order to allow a non-blocking
5579 * write into the pipe.
5582 #define PIPE_BUF 4096
5584 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5585 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5586 struct swrap_unix_scm_rights_payload {
5588 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5589 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5591 struct swrap_unix_scm_rights {
5593 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5594 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5596 uint32_t payload_size;
5597 struct swrap_unix_scm_rights_payload payload;
5600 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5602 int saved_errno = errno;
5605 for (i = 0; i < num; i++) {
5606 struct socket_info *si = array[i];
5612 swrap_dec_refcount(si);
5613 if (si->fd_passed > 0) {
5616 SWRAP_UNLOCK_SI(si);
5620 errno = saved_errno;
5623 static void swrap_undo_si_idx_array(size_t num, int *array)
5625 int saved_errno = errno;
5628 swrap_mutex_lock(&first_free_mutex);
5630 for (i = 0; i < num; i++) {
5631 struct socket_info *si = NULL;
5633 if (array[i] == -1) {
5637 si = swrap_get_socket_info(array[i]);
5643 swrap_dec_refcount(si);
5644 SWRAP_UNLOCK_SI(si);
5646 swrap_set_next_free(si, first_free);
5647 first_free = array[i];
5651 swrap_mutex_unlock(&first_free_mutex);
5652 errno = saved_errno;
5655 static void swrap_close_fd_array(size_t num, const int *array)
5657 int saved_errno = errno;
5660 for (i = 0; i < num; i++) {
5661 if (array[i] == -1) {
5664 libc_close(array[i]);
5667 errno = saved_errno;
5675 union __swrap_cmsghdr {
5677 struct cmsghdr *cmsg;
5680 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5682 size_t *cm_data_space,
5683 int *scm_rights_pipe_fd)
5685 struct swrap_unix_scm_rights info;
5686 struct swrap_unix_scm_rights_payload *payload = NULL;
5687 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5688 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5689 size_t info_idx = 0;
5692 union __swrap_fds __fds_in = { .p = NULL, };
5693 const int *fds_in = NULL;
5695 size_t size_fds_out;
5696 union __swrap_fds __fds_out = { .p = NULL, };
5697 int *fds_out = NULL;
5700 size_t new_cm_data_space;
5701 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5702 struct cmsghdr *new_cmsg = NULL;
5705 int pipefd[2] = { -1, -1 };
5710 * We pass this a buffer to the kernel make sure any padding
5714 info.magic = swrap_unix_scm_right_magic;
5715 memcpy(info.package_name,
5716 SOCKET_WRAPPER_PACKAGE,
5717 sizeof(info.package_name));
5718 memcpy(info.package_version,
5719 SOCKET_WRAPPER_VERSION,
5720 sizeof(info.package_version));
5721 info.full_size = sizeof(info);
5722 info.payload_size = sizeof(info.payload);
5723 payload = &info.payload;
5725 if (*scm_rights_pipe_fd != -1) {
5726 SWRAP_LOG(SWRAP_LOG_ERROR,
5727 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5732 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5733 SWRAP_LOG(SWRAP_LOG_ERROR,
5734 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5735 (size_t)cmsg->cmsg_len,
5740 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5741 if ((size_fds_in % sizeof(int)) != 0) {
5742 SWRAP_LOG(SWRAP_LOG_ERROR,
5743 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5744 (size_t)cmsg->cmsg_len,
5750 num_fds_in = size_fds_in / sizeof(int);
5751 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5752 SWRAP_LOG(SWRAP_LOG_ERROR,
5753 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5755 "SWRAP_MAX_PASSED_FDS(%zu)",
5756 (size_t)cmsg->cmsg_len,
5759 SWRAP_MAX_PASSED_FDS);
5763 if (num_fds_in == 0) {
5764 SWRAP_LOG(SWRAP_LOG_ERROR,
5765 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5767 (size_t)cmsg->cmsg_len,
5773 __fds_in.p = CMSG_DATA(cmsg);
5774 fds_in = __fds_in.fds;
5775 num_fds_out = num_fds_in + 1;
5777 SWRAP_LOG(SWRAP_LOG_TRACE,
5778 "num_fds_in=%zu num_fds_out=%zu",
5779 num_fds_in, num_fds_out);
5781 size_fds_out = sizeof(int) * num_fds_out;
5782 cmsg_len = CMSG_LEN(size_fds_out);
5783 cmsg_space = CMSG_SPACE(size_fds_out);
5785 new_cm_data_space = *cm_data_space + cmsg_space;
5787 p = realloc((*cm_data), new_cm_data_space);
5792 p = (*cm_data) + (*cm_data_space);
5793 memset(p, 0, cmsg_space);
5795 new_cmsg = __new_cmsg.cmsg;
5797 __fds_out.p = CMSG_DATA(new_cmsg);
5798 fds_out = __fds_out.fds;
5799 memcpy(fds_out, fds_in, size_fds_in);
5800 new_cmsg->cmsg_len = cmsg->cmsg_len;
5802 for (i = 0; i < num_fds_in; i++) {
5805 payload->idxs[i] = -1;
5806 payload->num_idxs++;
5808 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5809 if (si_idx_array[i] == -1) {
5813 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5814 if (si_array[i] == NULL) {
5815 SWRAP_LOG(SWRAP_LOG_ERROR,
5816 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5817 i, fds_in[i], i, si_idx_array[i]);
5822 for (j = 0; j < i; j++) {
5823 if (si_array[j] == si_array[i]) {
5824 payload->idxs[i] = payload->idxs[j];
5828 if (payload->idxs[i] == -1) {
5829 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5830 SWRAP_LOG(SWRAP_LOG_ERROR,
5831 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5832 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5833 i, fds_in[i], i, si_idx_array[i],
5835 SWRAP_MAX_PASSED_SOCKET_INFO);
5839 payload->idxs[i] = info_idx;
5845 for (i = 0; i < num_fds_in; i++) {
5846 struct socket_info *si = si_array[i];
5849 SWRAP_LOG(SWRAP_LOG_TRACE,
5850 "fds_in[%zu]=%d not an inet socket",
5855 SWRAP_LOG(SWRAP_LOG_TRACE,
5856 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5857 "passing as info.idxs[%zu]=%d!",
5860 i, payload->idxs[i]);
5864 payload->infos[payload->idxs[i]] = *si;
5865 payload->infos[payload->idxs[i]].fd_passed = 0;
5866 SWRAP_UNLOCK_SI(si);
5871 int saved_errno = errno;
5872 SWRAP_LOG(SWRAP_LOG_ERROR,
5873 "pipe() failed - %d %s",
5875 strerror(saved_errno));
5876 swrap_dec_fd_passed_array(num_fds_in, si_array);
5877 errno = saved_errno;
5881 sret = libc_write(pipefd[1], &info, sizeof(info));
5882 if (sret != sizeof(info)) {
5883 int saved_errno = errno;
5885 saved_errno = EINVAL;
5887 SWRAP_LOG(SWRAP_LOG_ERROR,
5888 "write() failed - sret=%zd - %d %s",
5890 strerror(saved_errno));
5891 swrap_dec_fd_passed_array(num_fds_in, si_array);
5892 libc_close(pipefd[1]);
5893 libc_close(pipefd[0]);
5894 errno = saved_errno;
5897 libc_close(pipefd[1]);
5900 * Add the pipe read end to the end of the passed fd array
5902 fds_out[num_fds_in] = pipefd[0];
5903 new_cmsg->cmsg_len = cmsg_len;
5905 /* we're done ... */
5906 *scm_rights_pipe_fd = pipefd[0];
5907 *cm_data_space = new_cm_data_space;
5912 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5914 size_t *cm_data_space,
5915 int *scm_rights_pipe_fd)
5919 switch (cmsg->cmsg_type) {
5921 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5924 scm_rights_pipe_fd);
5927 rc = swrap_sendmsg_copy_cmsg(cmsg,
5936 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5938 size_t *cm_data_space)
5940 int scm_rights_pipe_fd = -1;
5941 struct swrap_unix_scm_rights info;
5942 struct swrap_unix_scm_rights_payload *payload = NULL;
5943 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5946 union __swrap_fds __fds_in = { .p = NULL, };
5947 const int *fds_in = NULL;
5949 size_t size_fds_out;
5950 union __swrap_fds __fds_out = { .p = NULL, };
5951 int *fds_out = NULL;
5954 size_t new_cm_data_space;
5955 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5956 struct cmsghdr *new_cmsg = NULL;
5962 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5963 SWRAP_LOG(SWRAP_LOG_ERROR,
5964 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5965 (size_t)cmsg->cmsg_len,
5970 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5971 if ((size_fds_in % sizeof(int)) != 0) {
5972 SWRAP_LOG(SWRAP_LOG_ERROR,
5973 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5974 (size_t)cmsg->cmsg_len,
5980 num_fds_in = size_fds_in / sizeof(int);
5981 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5982 SWRAP_LOG(SWRAP_LOG_ERROR,
5983 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5984 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5985 (size_t)cmsg->cmsg_len,
5988 SWRAP_MAX_PASSED_FDS+1);
5992 if (num_fds_in <= 1) {
5993 SWRAP_LOG(SWRAP_LOG_ERROR,
5994 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5996 (size_t)cmsg->cmsg_len,
6002 __fds_in.p = CMSG_DATA(cmsg);
6003 fds_in = __fds_in.fds;
6004 num_fds_out = num_fds_in - 1;
6006 SWRAP_LOG(SWRAP_LOG_TRACE,
6007 "num_fds_in=%zu num_fds_out=%zu",
6008 num_fds_in, num_fds_out);
6010 for (i = 0; i < num_fds_in; i++) {
6011 /* Check if we have a stale fd and remove it */
6012 swrap_remove_stale(fds_in[i]);
6015 scm_rights_pipe_fd = fds_in[num_fds_out];
6016 size_fds_out = sizeof(int) * num_fds_out;
6017 cmsg_len = CMSG_LEN(size_fds_out);
6018 cmsg_space = CMSG_SPACE(size_fds_out);
6020 new_cm_data_space = *cm_data_space + cmsg_space;
6022 p = realloc((*cm_data), new_cm_data_space);
6024 swrap_close_fd_array(num_fds_in, fds_in);
6028 p = (*cm_data) + (*cm_data_space);
6029 memset(p, 0, cmsg_space);
6031 new_cmsg = __new_cmsg.cmsg;
6033 __fds_out.p = CMSG_DATA(new_cmsg);
6034 fds_out = __fds_out.fds;
6035 memcpy(fds_out, fds_in, size_fds_out);
6036 new_cmsg->cmsg_len = cmsg_len;
6038 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
6039 if (sret != sizeof(info)) {
6040 int saved_errno = errno;
6042 saved_errno = EINVAL;
6044 SWRAP_LOG(SWRAP_LOG_ERROR,
6045 "read() failed - sret=%zd - %d %s",
6047 strerror(saved_errno));
6048 swrap_close_fd_array(num_fds_in, fds_in);
6049 errno = saved_errno;
6052 libc_close(scm_rights_pipe_fd);
6053 payload = &info.payload;
6055 if (info.magic != swrap_unix_scm_right_magic) {
6056 SWRAP_LOG(SWRAP_LOG_ERROR,
6057 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
6058 (unsigned long long)info.magic,
6059 (unsigned long long)swrap_unix_scm_right_magic);
6060 swrap_close_fd_array(num_fds_out, fds_out);
6065 cmp = memcmp(info.package_name,
6066 SOCKET_WRAPPER_PACKAGE,
6067 sizeof(info.package_name));
6069 SWRAP_LOG(SWRAP_LOG_ERROR,
6070 "info.package_name='%.*s' != '%s'",
6071 (int)sizeof(info.package_name),
6073 SOCKET_WRAPPER_PACKAGE);
6074 swrap_close_fd_array(num_fds_out, fds_out);
6079 cmp = memcmp(info.package_version,
6080 SOCKET_WRAPPER_VERSION,
6081 sizeof(info.package_version));
6083 SWRAP_LOG(SWRAP_LOG_ERROR,
6084 "info.package_version='%.*s' != '%s'",
6085 (int)sizeof(info.package_version),
6086 info.package_version,
6087 SOCKET_WRAPPER_VERSION);
6088 swrap_close_fd_array(num_fds_out, fds_out);
6093 if (info.full_size != sizeof(info)) {
6094 SWRAP_LOG(SWRAP_LOG_ERROR,
6095 "info.full_size=%zu != sizeof(info)=%zu",
6096 (size_t)info.full_size,
6098 swrap_close_fd_array(num_fds_out, fds_out);
6103 if (info.payload_size != sizeof(info.payload)) {
6104 SWRAP_LOG(SWRAP_LOG_ERROR,
6105 "info.payload_size=%zu != sizeof(info.payload)=%zu",
6106 (size_t)info.payload_size,
6107 sizeof(info.payload));
6108 swrap_close_fd_array(num_fds_out, fds_out);
6113 if (payload->num_idxs != num_fds_out) {
6114 SWRAP_LOG(SWRAP_LOG_ERROR,
6115 "info.num_idxs=%u != num_fds_out=%zu",
6116 payload->num_idxs, num_fds_out);
6117 swrap_close_fd_array(num_fds_out, fds_out);
6122 for (i = 0; i < num_fds_out; i++) {
6125 si_idx_array[i] = -1;
6127 if (payload->idxs[i] == -1) {
6128 SWRAP_LOG(SWRAP_LOG_TRACE,
6129 "fds_out[%zu]=%d not an inet socket",
6134 if (payload->idxs[i] < 0) {
6135 SWRAP_LOG(SWRAP_LOG_ERROR,
6136 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
6137 i, fds_out[i], i, payload->idxs[i]);
6138 swrap_close_fd_array(num_fds_out, fds_out);
6143 if (payload->idxs[i] >= payload->num_idxs) {
6144 SWRAP_LOG(SWRAP_LOG_ERROR,
6145 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
6146 i, fds_out[i], i, payload->idxs[i],
6148 swrap_close_fd_array(num_fds_out, fds_out);
6153 if ((size_t)fds_out[i] >= socket_fds_max) {
6154 SWRAP_LOG(SWRAP_LOG_ERROR,
6155 "The max socket index limit of %zu has been reached, "
6159 swrap_close_fd_array(num_fds_out, fds_out);
6164 SWRAP_LOG(SWRAP_LOG_TRACE,
6166 "received as info.idxs[%zu]=%d!",
6168 i, payload->idxs[i]);
6170 for (j = 0; j < i; j++) {
6171 if (payload->idxs[j] == -1) {
6174 if (payload->idxs[j] == payload->idxs[i]) {
6175 si_idx_array[i] = si_idx_array[j];
6178 if (si_idx_array[i] == -1) {
6179 const struct socket_info *si = &payload->infos[payload->idxs[i]];
6181 si_idx_array[i] = swrap_add_socket_info(si);
6182 if (si_idx_array[i] == -1) {
6183 int saved_errno = errno;
6184 SWRAP_LOG(SWRAP_LOG_ERROR,
6185 "The max socket index limit of %zu has been reached, "
6189 swrap_undo_si_idx_array(i, si_idx_array);
6190 swrap_close_fd_array(num_fds_out, fds_out);
6191 errno = saved_errno;
6194 SWRAP_LOG(SWRAP_LOG_TRACE,
6195 "Imported %s socket for protocol %s, fd=%d",
6196 si->family == AF_INET ? "IPv4" : "IPv6",
6197 si->type == SOCK_DGRAM ? "UDP" : "TCP",
6202 for (i = 0; i < num_fds_out; i++) {
6203 if (si_idx_array[i] == -1) {
6206 set_socket_info_index(fds_out[i], si_idx_array[i]);
6209 /* we're done ... */
6210 *cm_data_space = new_cm_data_space;
6215 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6217 size_t *cm_data_space)
6221 switch (cmsg->cmsg_type) {
6223 rc = swrap_recvmsg_unix_scm_rights(cmsg,
6228 rc = swrap_sendmsg_copy_cmsg(cmsg,
6237 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6239 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6240 struct msghdr *msg_tmp,
6241 int *scm_rights_pipe_fd)
6243 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6244 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6245 struct cmsghdr *cmsg = NULL;
6246 uint8_t *cm_data = NULL;
6247 size_t cm_data_space = 0;
6251 *scm_rights_pipe_fd = -1;
6254 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6258 for (cmsg = CMSG_FIRSTHDR(msg_in);
6260 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6261 switch (cmsg->cmsg_level) {
6263 rc = swrap_sendmsg_unix_sol_socket(cmsg,
6266 scm_rights_pipe_fd);
6270 rc = swrap_sendmsg_copy_cmsg(cmsg,
6276 int saved_errno = errno;
6278 errno = saved_errno;
6283 msg_tmp->msg_controllen = cm_data_space;
6284 msg_tmp->msg_control = cm_data;
6287 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6288 *msg_tmp = *_msg_in;
6290 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6293 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6295 int scm_rights_pipe_fd)
6297 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6298 int saved_errno = errno;
6299 SAFE_FREE(msg_tmp->msg_control);
6300 if (scm_rights_pipe_fd != -1) {
6301 libc_close(scm_rights_pipe_fd);
6303 errno = saved_errno;
6304 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6308 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6309 struct msghdr *msg_tmp,
6310 uint8_t **tmp_control)
6312 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6313 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6314 uint8_t *cm_data = NULL;
6315 size_t cm_data_space = 0;
6318 *tmp_control = NULL;
6320 SWRAP_LOG(SWRAP_LOG_TRACE,
6321 "msg_in->msg_controllen=%zu",
6322 (size_t)msg_in->msg_controllen);
6325 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6330 * We need to give the kernel a bit more space in order
6331 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6332 * swrap_recvmsg_after_unix() will hide it again.
6334 cm_data_space = msg_in->msg_controllen;
6335 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6336 cm_data_space += cm_extra_space;
6338 cm_data = calloc(1, cm_data_space);
6339 if (cm_data == NULL) {
6343 msg_tmp->msg_controllen = cm_data_space;
6344 msg_tmp->msg_control = cm_data;
6345 *tmp_control = cm_data;
6347 SWRAP_LOG(SWRAP_LOG_TRACE,
6348 "msg_tmp->msg_controllen=%zu",
6349 (size_t)msg_tmp->msg_controllen);
6351 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6353 *tmp_control = NULL;
6355 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6358 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6359 uint8_t **tmp_control,
6360 struct msghdr *msg_out,
6363 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6364 struct cmsghdr *cmsg = NULL;
6365 uint8_t *cm_data = NULL;
6366 size_t cm_data_space = 0;
6370 int saved_errno = errno;
6371 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6372 saved_errno, strerror(saved_errno));
6373 SAFE_FREE(*tmp_control);
6374 /* msg_out should not be touched on error */
6375 errno = saved_errno;
6379 SWRAP_LOG(SWRAP_LOG_TRACE,
6380 "msg_tmp->msg_controllen=%zu",
6381 (size_t)msg_tmp->msg_controllen);
6384 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6385 int saved_errno = errno;
6386 *msg_out = *msg_tmp;
6387 SAFE_FREE(*tmp_control);
6388 errno = saved_errno;
6392 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6394 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6395 switch (cmsg->cmsg_level) {
6397 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6403 rc = swrap_sendmsg_copy_cmsg(cmsg,
6409 int saved_errno = errno;
6411 SAFE_FREE(*tmp_control);
6412 errno = saved_errno;
6418 * msg_tmp->msg_control (*tmp_control) was created by
6419 * swrap_recvmsg_before_unix() and msg_out->msg_control
6420 * is still the buffer of the caller.
6422 msg_tmp->msg_control = msg_out->msg_control;
6423 msg_tmp->msg_controllen = msg_out->msg_controllen;
6424 *msg_out = *msg_tmp;
6426 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6427 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6428 msg_out->msg_controllen = cm_data_space;
6430 SAFE_FREE(*tmp_control);
6432 SWRAP_LOG(SWRAP_LOG_TRACE,
6433 "msg_out->msg_controllen=%zu",
6434 (size_t)msg_out->msg_controllen);
6436 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6437 int saved_errno = errno;
6438 *msg_out = *msg_tmp;
6439 SAFE_FREE(*tmp_control);
6440 errno = saved_errno;
6442 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6445 static ssize_t swrap_sendmsg_before(int fd,
6446 struct socket_info *si,
6448 struct iovec *tmp_iov,
6449 struct sockaddr_un *tmp_un,
6450 const struct sockaddr_un **to_un,
6451 const struct sockaddr **to,
6456 struct swrap_sockaddr_buf buf = {};
6474 if (!si->connected) {
6479 if (msg->msg_iovlen == 0) {
6483 mtu = socket_wrapper_mtu();
6484 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6486 nlen = len + msg->msg_iov[i].iov_len;
6496 msg->msg_iovlen = i;
6497 if (msg->msg_iovlen == 0) {
6498 *tmp_iov = msg->msg_iov[0];
6499 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6501 msg->msg_iov = tmp_iov;
6502 msg->msg_iovlen = 1;
6507 if (si->connected) {
6508 if (msg->msg_name != NULL) {
6510 * We are dealing with unix sockets and if we
6511 * are connected, we should only talk to the
6512 * connected unix path. Using the fd to send
6513 * to another server would be hard to achieve.
6515 msg->msg_name = NULL;
6516 msg->msg_namelen = 0;
6518 SWRAP_LOG(SWRAP_LOG_TRACE,
6519 "connected(%s) fd=%d",
6520 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6523 const struct sockaddr *msg_name;
6524 msg_name = (const struct sockaddr *)msg->msg_name;
6526 if (msg_name == NULL) {
6532 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6544 msg->msg_name = tmp_un;
6545 msg->msg_namelen = sizeof(*tmp_un);
6548 if (si->bound == 0) {
6549 ret = swrap_auto_bind(fd, si, si->family);
6551 SWRAP_UNLOCK_SI(si);
6552 if (errno == ENOTSOCK) {
6553 swrap_remove_stale(fd);
6556 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6562 if (!si->defer_connect) {
6566 ret = sockaddr_convert_to_un(si,
6568 si->peername.sa_socklen,
6576 SWRAP_LOG(SWRAP_LOG_TRACE,
6577 "deferred connect(%s) path=%s, fd=%d",
6578 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6579 tmp_un->sun_path, fd);
6581 ret = libc_connect(fd,
6582 (struct sockaddr *)(void *)tmp_un,
6585 /* to give better errors */
6586 if (ret == -1 && errno == ENOENT) {
6587 errno = EHOSTUNREACH;
6594 si->defer_connect = 0;
6597 errno = EHOSTUNREACH;
6603 SWRAP_UNLOCK_SI(si);
6608 static void swrap_sendmsg_after(int fd,
6609 struct socket_info *si,
6611 const struct sockaddr *to,
6614 int saved_errno = errno;
6621 /* to give better errors */
6623 if (saved_errno == ENOENT) {
6624 saved_errno = EHOSTUNREACH;
6625 } else if (saved_errno == ENOTSOCK) {
6626 /* If the fd is not a socket, remove it */
6627 swrap_remove_stale(fd);
6631 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6632 avail += msg->msg_iov[i].iov_len;
6636 remain = MIN(80, avail);
6641 /* we capture it as one single packet */
6642 buf = (uint8_t *)malloc(remain);
6644 /* we just not capture the packet */
6645 errno = saved_errno;
6649 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6650 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6651 if (this_time > 0) {
6653 msg->msg_iov[i].iov_base,
6657 remain -= this_time;
6666 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6667 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6669 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6674 if (si->connected) {
6675 to = &si->peername.sa.s;
6678 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6679 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6681 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6686 SWRAP_UNLOCK_SI(si);
6689 errno = saved_errno;
6692 static int swrap_recvmsg_before(int fd,
6693 struct socket_info *si,
6695 struct iovec *tmp_iov)
6702 (void)fd; /* unused */
6707 if (!si->connected) {
6712 if (msg->msg_iovlen == 0) {
6716 mtu = socket_wrapper_mtu();
6717 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6719 nlen = len + msg->msg_iov[i].iov_len;
6724 msg->msg_iovlen = i;
6725 if (msg->msg_iovlen == 0) {
6726 *tmp_iov = msg->msg_iov[0];
6727 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6729 msg->msg_iov = tmp_iov;
6730 msg->msg_iovlen = 1;
6735 if (msg->msg_name == NULL) {
6740 if (msg->msg_iovlen == 0) {
6744 if (si->bound == 0) {
6745 ret = swrap_auto_bind(fd, si, si->family);
6747 SWRAP_UNLOCK_SI(si);
6749 * When attempting to read or write to a
6750 * descriptor, if an underlying autobind fails
6751 * because it's not a socket, stop intercepting
6752 * uses of that descriptor.
6754 if (errno == ENOTSOCK) {
6755 swrap_remove_stale(fd);
6758 SWRAP_LOG(SWRAP_LOG_ERROR,
6759 "swrap_recvmsg_before failed");
6766 errno = EHOSTUNREACH;
6772 SWRAP_UNLOCK_SI(si);
6777 static int swrap_recvmsg_after(int fd,
6778 struct socket_info *si,
6780 const struct sockaddr_un *un_addr,
6781 socklen_t un_addrlen,
6784 int saved_errno = errno;
6786 uint8_t *buf = NULL;
6792 /* to give better errors */
6794 if (saved_errno == ENOENT) {
6795 saved_errno = EHOSTUNREACH;
6796 } else if (saved_errno == ENOTSOCK) {
6797 /* If the fd is not a socket, remove it */
6798 swrap_remove_stale(fd);
6802 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6803 avail += msg->msg_iov[i].iov_len;
6808 /* Convert the socket address before we leave */
6809 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6810 rc = sockaddr_convert_from_un(si,
6827 remain = MIN(80, avail);
6832 /* we capture it as one single packet */
6833 buf = (uint8_t *)malloc(remain);
6835 /* we just not capture the packet */
6836 SWRAP_UNLOCK_SI(si);
6837 errno = saved_errno;
6841 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6842 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6844 msg->msg_iov[i].iov_base,
6847 remain -= this_time;
6852 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6853 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6854 } else if (ret == 0) { /* END OF FILE */
6855 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6856 } else if (ret > 0) {
6857 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6866 if (un_addr != NULL) {
6867 swrap_pcap_dump_packet(si,
6873 swrap_pcap_dump_packet(si,
6886 errno = saved_errno;
6888 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6890 msg->msg_controllen > 0 &&
6891 msg->msg_control != NULL) {
6892 rc = swrap_msghdr_add_socket_info(si, msg);
6894 SWRAP_UNLOCK_SI(si);
6900 SWRAP_UNLOCK_SI(si);
6904 /****************************************************************************
6906 ***************************************************************************/
6908 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6909 struct sockaddr *from, socklen_t *fromlen)
6911 struct swrap_address from_addr = {
6912 .sa_socklen = sizeof(struct sockaddr_un),
6915 struct socket_info *si = find_socket_info(s);
6916 struct swrap_address saddr = {
6917 .sa_socklen = sizeof(struct sockaddr_storage),
6924 return libc_recvfrom(s,
6936 if (from != NULL && fromlen != NULL) {
6937 msg.msg_name = from; /* optional address */
6938 msg.msg_namelen = *fromlen; /* size of address */
6940 msg.msg_name = &saddr.sa.s; /* optional address */
6941 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6943 msg.msg_iov = &tmp; /* scatter/gather array */
6944 msg.msg_iovlen = 1; /* # elements in msg_iov */
6945 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6946 msg.msg_control = NULL; /* ancillary data, see below */
6947 msg.msg_controllen = 0; /* ancillary data buffer len */
6948 msg.msg_flags = 0; /* flags on received message */
6951 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6956 buf = msg.msg_iov[0].iov_base;
6957 len = msg.msg_iov[0].iov_len;
6959 ret = libc_recvfrom(s,
6964 &from_addr.sa_socklen);
6969 tret = swrap_recvmsg_after(s,
6973 from_addr.sa_socklen,
6979 if (from != NULL && fromlen != NULL) {
6980 *fromlen = msg.msg_namelen;
6986 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6987 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6988 struct sockaddr *from, Psocklen_t fromlen)
6990 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6991 struct sockaddr *from, socklen_t *fromlen)
6994 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6997 /****************************************************************************
6999 ***************************************************************************/
7001 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
7002 const struct sockaddr *to, socklen_t tolen)
7006 struct swrap_address un_addr = {
7007 .sa_socklen = sizeof(struct sockaddr_un),
7009 const struct sockaddr_un *to_un = NULL;
7012 struct socket_info *si = find_socket_info(s);
7016 return libc_sendto(s, buf, len, flags, to, tolen);
7019 tmp.iov_base = discard_const_p(char, buf);
7023 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
7024 msg.msg_namelen = tolen; /* size of address */
7025 msg.msg_iov = &tmp; /* scatter/gather array */
7026 msg.msg_iovlen = 1; /* # elements in msg_iov */
7027 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7028 msg.msg_control = NULL; /* ancillary data, see below */
7029 msg.msg_controllen = 0; /* ancillary data buffer len */
7030 msg.msg_flags = 0; /* flags on received message */
7033 rc = swrap_sendmsg_before(s,
7045 buf = msg.msg_iov[0].iov_base;
7046 len = msg.msg_iov[0].iov_len;
7051 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7053 char *swrap_dir = NULL;
7055 type = SOCKET_TYPE_CHAR_UDP;
7057 swrap_dir = socket_wrapper_dir();
7058 if (swrap_dir == NULL) {
7062 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7063 swrap_un_path(&un_addr.sa.un,
7068 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
7070 /* ignore the any errors in broadcast sends */
7076 un_addr.sa_socklen);
7079 SAFE_FREE(swrap_dir);
7083 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7085 SWRAP_UNLOCK_SI(si);
7092 * If it is a dgram socket and we are connected, don't include the
7095 if (si->type == SOCK_DGRAM && si->connected) {
7096 ret = libc_sendto(s,
7103 ret = libc_sendto(s,
7107 (struct sockaddr *)msg.msg_name,
7111 SWRAP_UNLOCK_SI(si);
7113 swrap_sendmsg_after(s, si, &msg, to, ret);
7118 ssize_t sendto(int s, const void *buf, size_t len, int flags,
7119 const struct sockaddr *to, socklen_t tolen)
7121 return swrap_sendto(s, buf, len, flags, to, tolen);
7124 /****************************************************************************
7126 ***************************************************************************/
7128 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
7130 struct socket_info *si;
7132 struct swrap_address saddr = {
7133 .sa_socklen = sizeof(struct sockaddr_storage),
7139 si = find_socket_info(s);
7141 return libc_recv(s, buf, len, flags);
7148 msg.msg_name = &saddr.sa.s; /* optional address */
7149 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7150 msg.msg_iov = &tmp; /* scatter/gather array */
7151 msg.msg_iovlen = 1; /* # elements in msg_iov */
7152 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7153 msg.msg_control = NULL; /* ancillary data, see below */
7154 msg.msg_controllen = 0; /* ancillary data buffer len */
7155 msg.msg_flags = 0; /* flags on received message */
7158 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7163 buf = msg.msg_iov[0].iov_base;
7164 len = msg.msg_iov[0].iov_len;
7166 ret = libc_recv(s, buf, len, flags);
7168 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7176 ssize_t recv(int s, void *buf, size_t len, int flags)
7178 return swrap_recv(s, buf, len, flags);
7181 /****************************************************************************
7183 ***************************************************************************/
7185 static ssize_t swrap_read(int s, void *buf, size_t len)
7187 struct socket_info *si;
7190 struct swrap_address saddr = {
7191 .sa_socklen = sizeof(struct sockaddr_storage),
7196 si = find_socket_info(s);
7198 return libc_read(s, buf, len);
7205 msg.msg_name = &saddr.sa.ss; /* optional address */
7206 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7207 msg.msg_iov = &tmp; /* scatter/gather array */
7208 msg.msg_iovlen = 1; /* # elements in msg_iov */
7209 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7210 msg.msg_control = NULL; /* ancillary data, see below */
7211 msg.msg_controllen = 0; /* ancillary data buffer len */
7212 msg.msg_flags = 0; /* flags on received message */
7215 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7217 if (tret == -ENOTSOCK) {
7218 return libc_read(s, buf, len);
7223 buf = msg.msg_iov[0].iov_base;
7224 len = msg.msg_iov[0].iov_len;
7226 ret = libc_read(s, buf, len);
7228 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7236 ssize_t read(int s, void *buf, size_t len)
7238 return swrap_read(s, buf, len);
7241 /****************************************************************************
7243 ***************************************************************************/
7245 static ssize_t swrap_write(int s, const void *buf, size_t len)
7249 struct sockaddr_un un_addr;
7252 struct socket_info *si;
7254 si = find_socket_info(s);
7256 return libc_write(s, buf, len);
7259 tmp.iov_base = discard_const_p(char, buf);
7263 msg.msg_name = NULL; /* optional address */
7264 msg.msg_namelen = 0; /* size of address */
7265 msg.msg_iov = &tmp; /* scatter/gather array */
7266 msg.msg_iovlen = 1; /* # elements in msg_iov */
7267 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7268 msg.msg_control = NULL; /* ancillary data, see below */
7269 msg.msg_controllen = 0; /* ancillary data buffer len */
7270 msg.msg_flags = 0; /* flags on received message */
7273 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7278 buf = msg.msg_iov[0].iov_base;
7279 len = msg.msg_iov[0].iov_len;
7281 ret = libc_write(s, buf, len);
7283 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7288 ssize_t write(int s, const void *buf, size_t len)
7290 return swrap_write(s, buf, len);
7293 /****************************************************************************
7295 ***************************************************************************/
7297 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7301 struct sockaddr_un un_addr;
7304 struct socket_info *si = find_socket_info(s);
7307 return libc_send(s, buf, len, flags);
7310 tmp.iov_base = discard_const_p(char, buf);
7314 msg.msg_name = NULL; /* optional address */
7315 msg.msg_namelen = 0; /* size of address */
7316 msg.msg_iov = &tmp; /* scatter/gather array */
7317 msg.msg_iovlen = 1; /* # elements in msg_iov */
7318 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7319 msg.msg_control = NULL; /* ancillary data, see below */
7320 msg.msg_controllen = 0; /* ancillary data buffer len */
7321 msg.msg_flags = 0; /* flags on received message */
7324 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7329 buf = msg.msg_iov[0].iov_base;
7330 len = msg.msg_iov[0].iov_len;
7332 ret = libc_send(s, buf, len, flags);
7334 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7339 ssize_t send(int s, const void *buf, size_t len, int flags)
7341 return swrap_send(s, buf, len, flags);
7344 /****************************************************************************
7346 ***************************************************************************/
7348 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7350 struct swrap_address from_addr = {
7351 .sa_socklen = sizeof(struct sockaddr_un),
7353 struct swrap_address convert_addr = {
7354 .sa_socklen = sizeof(struct sockaddr_storage),
7356 struct socket_info *si;
7359 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7360 size_t msg_ctrllen_filled;
7361 size_t msg_ctrllen_left;
7367 si = find_socket_info(s);
7369 uint8_t *tmp_control = NULL;
7370 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7374 ret = libc_recvmsg(s, &msg, flags);
7375 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7378 tmp.iov_base = NULL;
7382 msg.msg_name = &from_addr.sa; /* optional address */
7383 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7384 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7385 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7386 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7387 msg_ctrllen_filled = 0;
7388 msg_ctrllen_left = omsg->msg_controllen;
7390 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7391 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7392 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7395 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7400 ret = libc_recvmsg(s, &msg, flags);
7402 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7403 msg_ctrllen_filled += msg.msg_controllen;
7404 msg_ctrllen_left -= msg.msg_controllen;
7406 if (omsg->msg_control != NULL) {
7409 p = omsg->msg_control;
7410 p += msg_ctrllen_filled;
7412 msg.msg_control = p;
7413 msg.msg_controllen = msg_ctrllen_left;
7415 msg.msg_control = NULL;
7416 msg.msg_controllen = 0;
7421 * We convert the unix address to a IP address so we need a buffer
7422 * which can store the address in case of SOCK_DGRAM, see below.
7424 msg.msg_name = &convert_addr.sa;
7425 msg.msg_namelen = convert_addr.sa_socklen;
7427 rc = swrap_recvmsg_after(s,
7431 from_addr.sa_socklen,
7437 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7438 if (omsg->msg_control != NULL) {
7439 /* msg.msg_controllen = space left */
7440 msg_ctrllen_left = msg.msg_controllen;
7441 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7444 /* Update the original message length */
7445 omsg->msg_controllen = msg_ctrllen_filled;
7446 omsg->msg_flags = msg.msg_flags;
7448 omsg->msg_iovlen = msg.msg_iovlen;
7455 * The msg_name field points to a caller-allocated buffer that is
7456 * used to return the source address if the socket is unconnected. The
7457 * caller should set msg_namelen to the size of this buffer before this
7458 * call; upon return from a successful call, msg_name will contain the
7459 * length of the returned address. If the application does not need
7460 * to know the source address, msg_name can be specified as NULL.
7462 if (si->type == SOCK_STREAM) {
7463 omsg->msg_namelen = 0;
7464 } else if (omsg->msg_name != NULL &&
7465 omsg->msg_namelen != 0 &&
7466 omsg->msg_namelen >= msg.msg_namelen) {
7467 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7468 omsg->msg_namelen = msg.msg_namelen;
7471 SWRAP_UNLOCK_SI(si);
7476 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7478 return swrap_recvmsg(sockfd, msg, flags);
7481 /****************************************************************************
7483 ***************************************************************************/
7485 #ifdef HAVE_RECVMMSG
7486 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7488 static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7489 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7490 /* Linux legacy glibc < 2.21 */
7491 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7493 /* Linux glibc >= 2.21 */
7494 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7497 struct socket_info *si = find_socket_info(s);
7498 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7499 struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7502 struct swrap_address from_addr;
7503 struct swrap_address convert_addr;
7504 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7505 size_t msg_ctrllen_filled;
7506 size_t msg_ctrllen_left;
7508 } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7515 if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7516 vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7522 uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7524 for (i = 0; i < vlen; i++) {
7525 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7526 struct msghdr *msg = &msgvec[i].msg_hdr;
7528 rc = swrap_recvmsg_before_unix(omsg, msg,
7536 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7541 for (i = 0; i < ret; i++) {
7542 omsgvec[i].msg_len = msgvec[i].msg_len;
7546 saved_errno = errno;
7547 for (i = 0; i < vlen; i++) {
7548 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7549 struct msghdr *msg = &msgvec[i].msg_hdr;
7551 if (i == 0 || i < ret) {
7552 swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7554 SAFE_FREE(tmp_control[i]);
7556 errno = saved_errno;
7561 for (i = 0; i < vlen; i++) {
7562 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7563 struct msghdr *msg = &msgvec[i].msg_hdr;
7565 tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7566 tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7568 msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7569 msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7570 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7571 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7572 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7573 tmp[i].msg_ctrllen_filled = 0;
7574 tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7576 msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7577 msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7578 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7581 rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7588 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7593 for (i = 0; i < ret; i++) {
7594 omsgvec[i].msg_len = msgvec[i].msg_len;
7599 saved_errno = errno;
7600 for (i = 0; i < vlen; i++) {
7601 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7602 struct msghdr *msg = &msgvec[i].msg_hdr;
7604 if (!(i == 0 || i < ret)) {
7608 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7609 tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7610 tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7612 if (omsg->msg_control != NULL) {
7615 p = omsg->msg_control;
7616 p += tmp[i].msg_ctrllen_filled;
7618 msg->msg_control = p;
7619 msg->msg_controllen = tmp[i].msg_ctrllen_left;
7621 msg->msg_control = NULL;
7622 msg->msg_controllen = 0;
7627 * We convert the unix address to a IP address so we need a buffer
7628 * which can store the address in case of SOCK_DGRAM, see below.
7630 msg->msg_name = &tmp[i].convert_addr.sa;
7631 msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7633 swrap_recvmsg_after(s, si, msg,
7634 &tmp[i].from_addr.sa.un,
7635 tmp[i].from_addr.sa_socklen,
7638 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7639 if (omsg->msg_control != NULL) {
7640 /* msg->msg_controllen = space left */
7641 tmp[i].msg_ctrllen_left = msg->msg_controllen;
7642 tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7645 /* Update the original message length */
7646 omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7647 omsg->msg_flags = msg->msg_flags;
7649 omsg->msg_iovlen = msg->msg_iovlen;
7656 * The msg_name field points to a caller-allocated buffer that is
7657 * used to return the source address if the socket is unconnected. The
7658 * caller should set msg_namelen to the size of this buffer before this
7659 * call; upon return from a successful call, msg_name will contain the
7660 * length of the returned address. If the application does not need
7661 * to know the source address, msg_name can be specified as NULL.
7663 if (si->type == SOCK_STREAM) {
7664 omsg->msg_namelen = 0;
7665 } else if (omsg->msg_name != NULL &&
7666 omsg->msg_namelen != 0 &&
7667 omsg->msg_namelen >= msg->msg_namelen) {
7668 memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7669 omsg->msg_namelen = msg->msg_namelen;
7672 SWRAP_UNLOCK_SI(si);
7674 errno = saved_errno;
7679 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7681 ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7682 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7683 /* Linux legacy glibc < 2.21 */
7684 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7686 /* Linux glibc >= 2.21 */
7687 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7690 return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7692 #endif /* HAVE_RECVMMSG */
7694 /****************************************************************************
7696 ***************************************************************************/
7698 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7702 struct sockaddr_un un_addr;
7703 const struct sockaddr_un *to_un = NULL;
7704 const struct sockaddr *to = NULL;
7707 struct socket_info *si = find_socket_info(s);
7711 int scm_rights_pipe_fd = -1;
7713 rc = swrap_sendmsg_before_unix(omsg, &msg,
7714 &scm_rights_pipe_fd);
7718 ret = libc_sendmsg(s, &msg, flags);
7719 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7722 ZERO_STRUCT(un_addr);
7724 tmp.iov_base = NULL;
7731 if (si->connected == 0) {
7732 msg.msg_name = omsg->msg_name; /* optional address */
7733 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7735 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7736 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7738 SWRAP_UNLOCK_SI(si);
7740 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7741 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7742 uint8_t *cmbuf = NULL;
7745 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7751 msg.msg_controllen = 0;
7752 msg.msg_control = NULL;
7754 msg.msg_control = cmbuf;
7755 msg.msg_controllen = cmlen;
7758 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7760 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7762 int saved_errno = errno;
7763 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7764 SAFE_FREE(msg.msg_control);
7766 errno = saved_errno;
7773 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7780 char *swrap_dir = NULL;
7782 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7783 avail += msg.msg_iov[i].iov_len;
7789 /* we capture it as one single packet */
7790 buf = (uint8_t *)malloc(remain);
7792 int saved_errno = errno;
7793 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7794 SAFE_FREE(msg.msg_control);
7796 errno = saved_errno;
7800 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7801 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7803 msg.msg_iov[i].iov_base,
7806 remain -= this_time;
7809 type = SOCKET_TYPE_CHAR_UDP;
7811 swrap_dir = socket_wrapper_dir();
7812 if (swrap_dir == NULL) {
7813 int saved_errno = errno;
7814 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7815 SAFE_FREE(msg.msg_control);
7818 errno = saved_errno;
7822 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7823 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7824 if (stat(un_addr.sun_path, &st) != 0) continue;
7826 msg.msg_name = &un_addr; /* optional address */
7827 msg.msg_namelen = sizeof(un_addr); /* size of address */
7829 /* ignore the any errors in broadcast sends */
7830 libc_sendmsg(s, &msg, flags);
7833 SAFE_FREE(swrap_dir);
7837 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7840 SWRAP_UNLOCK_SI(si);
7845 ret = libc_sendmsg(s, &msg, flags);
7847 swrap_sendmsg_after(s, si, &msg, to, ret);
7849 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7851 int saved_errno = errno;
7852 SAFE_FREE(msg.msg_control);
7853 errno = saved_errno;
7860 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7862 return swrap_sendmsg(s, omsg, flags);
7865 /****************************************************************************
7867 ***************************************************************************/
7869 #ifdef HAVE_SENDMMSG
7870 #if defined(HAVE_SENDMMSG_SSIZE_T)
7872 static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7875 static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7878 struct socket_info *si = find_socket_info(s);
7879 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7880 struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7883 struct sockaddr_un un_addr;
7884 const struct sockaddr_un *to_un;
7885 const struct sockaddr *to;
7887 } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7890 char *swrap_dir = NULL;
7892 int found_bcast = 0;
7897 if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7898 vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7904 int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7906 for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7907 scm_rights_pipe_fd[i] = -1;
7910 for (i = 0; i < vlen; i++) {
7911 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7912 struct msghdr *msg = &msgvec[i].msg_hdr;
7914 rc = swrap_sendmsg_before_unix(omsg, msg,
7915 &scm_rights_pipe_fd[i]);
7922 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7927 for (i = 0; i < ret; i++) {
7928 omsgvec[i].msg_len = msgvec[i].msg_len;
7932 saved_errno = errno;
7933 for (i = 0; i < vlen; i++) {
7934 struct msghdr *msg = &msgvec[i].msg_hdr;
7936 swrap_sendmsg_after_unix(msg, ret,
7937 scm_rights_pipe_fd[i]);
7939 errno = saved_errno;
7945 connected = si->connected;
7946 SWRAP_UNLOCK_SI(si);
7948 for (i = 0; i < vlen; i++) {
7949 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7950 struct msghdr *msg = &msgvec[i].msg_hdr;
7952 if (connected == 0) {
7953 msg->msg_name = omsg->msg_name; /* optional address */
7954 msg->msg_namelen = omsg->msg_namelen; /* size of address */
7956 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7957 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7959 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7960 if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7961 uint8_t *cmbuf = NULL;
7964 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7971 msg->msg_control = cmbuf;
7972 msg->msg_controllen = cmlen;
7975 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7978 rc = swrap_sendmsg_before(s, si, msg,
7996 swrap_dir = socket_wrapper_dir();
7997 if (swrap_dir == NULL) {
8002 for (i = 0; i < vlen; i++) {
8003 struct msghdr *msg = &msgvec[i].msg_hdr;
8004 struct sockaddr_un *un_addr = &tmp[i].un_addr;
8005 const struct sockaddr *to = tmp[i].to;
8008 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
8016 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
8017 avail += msg->msg_iov[l].iov_len;
8023 /* we capture it as one single packet */
8024 buf = (uint8_t *)malloc(remain);
8030 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
8031 size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
8033 msg->msg_iov[l].iov_base,
8036 remain -= this_time;
8039 type = SOCKET_TYPE_CHAR_UDP;
8041 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
8042 swrap_un_path(un_addr, swrap_dir, type, iface, prt);
8043 if (stat(un_addr->sun_path, &st) != 0) continue;
8045 msg->msg_name = un_addr; /* optional address */
8046 msg->msg_namelen = sizeof(*un_addr); /* size of address */
8049 * ignore the any errors in broadcast sends and
8050 * do a single sendmsg instead of sendmmsg
8052 libc_sendmsg(s, msg, flags);
8056 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
8057 SWRAP_UNLOCK_SI(si);
8061 msgvec[i].msg_len = len;
8068 ret = libc_sendmmsg(s, msgvec, vlen, flags);
8074 for (i = 0; i < ret; i++) {
8075 omsgvec[i].msg_len = msgvec[i].msg_len;
8079 saved_errno = errno;
8080 for (i = 0; i < vlen; i++) {
8081 struct msghdr *msg = &msgvec[i].msg_hdr;
8083 if (i == 0 || i < ret) {
8084 swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
8086 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8087 SAFE_FREE(msg->msg_control);
8090 SAFE_FREE(swrap_dir);
8091 errno = saved_errno;
8096 #if defined(HAVE_SENDMMSG_SSIZE_T)
8098 ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
8101 int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
8104 return swrap_sendmmsg(s, msgvec, vlen, flags);
8106 #endif /* HAVE_SENDMMSG */
8108 /****************************************************************************
8110 ***************************************************************************/
8112 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
8114 struct socket_info *si;
8117 struct swrap_address saddr = {
8118 .sa_socklen = sizeof(struct sockaddr_storage)
8123 si = find_socket_info(s);
8125 return libc_readv(s, vector, count);
8128 tmp.iov_base = NULL;
8132 msg.msg_name = &saddr.sa.s; /* optional address */
8133 msg.msg_namelen = saddr.sa_socklen; /* size of address */
8134 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8135 msg.msg_iovlen = count; /* # elements in msg_iov */
8136 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8137 msg.msg_control = NULL; /* ancillary data, see below */
8138 msg.msg_controllen = 0; /* ancillary data buffer len */
8139 msg.msg_flags = 0; /* flags on received message */
8142 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
8144 if (rc == -ENOTSOCK) {
8145 return libc_readv(s, vector, count);
8150 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
8152 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
8160 ssize_t readv(int s, const struct iovec *vector, int count)
8162 return swrap_readv(s, vector, count);
8165 /****************************************************************************
8167 ***************************************************************************/
8169 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
8173 struct sockaddr_un un_addr;
8176 struct socket_info *si = find_socket_info(s);
8179 return libc_writev(s, vector, count);
8182 tmp.iov_base = NULL;
8186 msg.msg_name = NULL; /* optional address */
8187 msg.msg_namelen = 0; /* size of address */
8188 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8189 msg.msg_iovlen = count; /* # elements in msg_iov */
8190 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8191 msg.msg_control = NULL; /* ancillary data, see below */
8192 msg.msg_controllen = 0; /* ancillary data buffer len */
8193 msg.msg_flags = 0; /* flags on received message */
8196 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
8198 if (rc == -ENOTSOCK) {
8199 return libc_readv(s, vector, count);
8204 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
8206 swrap_sendmsg_after(s, si, &msg, NULL, ret);
8211 ssize_t writev(int s, const struct iovec *vector, int count)
8213 return swrap_writev(s, vector, count);
8216 /****************************
8218 ***************************/
8220 static int swrap_remove_wrapper(const char *__func_name,
8221 int (*__close_fd_fn)(int fd),
8224 struct socket_info *si = NULL;
8226 int ret_errno = errno;
8229 swrap_mutex_lock(&socket_reset_mutex);
8231 si_index = find_socket_info_index(fd);
8232 if (si_index == -1) {
8233 swrap_mutex_unlock(&socket_reset_mutex);
8234 return __close_fd_fn(fd);
8237 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8238 reset_socket_info_index(fd);
8240 si = swrap_get_socket_info(si_index);
8242 swrap_mutex_lock(&first_free_mutex);
8245 ret = __close_fd_fn(fd);
8250 swrap_dec_refcount(si);
8252 if (swrap_get_refcount(si) > 0) {
8253 /* there are still references left */
8257 if (si->fd_passed) {
8261 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8262 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8265 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8266 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8267 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8270 if (si->un_addr.sun_path[0] != '\0') {
8271 unlink(si->un_addr.sun_path);
8275 swrap_set_next_free(si, first_free);
8276 first_free = si_index;
8279 SWRAP_UNLOCK_SI(si);
8280 swrap_mutex_unlock(&first_free_mutex);
8281 swrap_mutex_unlock(&socket_reset_mutex);
8287 static int swrap_noop_close(int fd)
8289 (void)fd; /* unused */
8293 static void swrap_remove_stale(int fd)
8295 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8299 * This allows socket_wrapper aware applications to
8300 * indicate that the given fd does not belong to
8303 * We already overload a lot of unrelated functions
8304 * like eventfd(), timerfd_create(), ... in order to
8305 * call swrap_remove_stale() on the returned fd, but
8306 * we'll never be able to handle all possible syscalls.
8308 * socket_wrapper_indicate_no_inet_fd() gives them a way
8311 * We don't export swrap_remove_stale() in order to
8312 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8315 void socket_wrapper_indicate_no_inet_fd(int fd)
8317 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8320 static int swrap_close(int fd)
8322 return swrap_remove_wrapper(__func__, libc_close, fd);
8327 return swrap_close(fd);
8330 #ifdef HAVE___CLOSE_NOCANCEL
8332 static int swrap___close_nocancel(int fd)
8334 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8337 int __close_nocancel(int fd);
8338 int __close_nocancel(int fd)
8340 return swrap___close_nocancel(fd);
8343 #endif /* HAVE___CLOSE_NOCANCEL */
8345 /****************************
8347 ***************************/
8349 static int swrap_dup(int fd)
8351 struct socket_info *si;
8354 idx = find_socket_info_index(fd);
8356 return libc_dup(fd);
8359 si = swrap_get_socket_info(idx);
8361 dup_fd = libc_dup(fd);
8363 int saved_errno = errno;
8364 errno = saved_errno;
8368 if ((size_t)dup_fd >= socket_fds_max) {
8369 SWRAP_LOG(SWRAP_LOG_ERROR,
8370 "The max socket index limit of %zu has been reached, "
8381 swrap_inc_refcount(si);
8383 SWRAP_UNLOCK_SI(si);
8385 /* Make sure we don't have an entry for the fd */
8386 swrap_remove_stale(dup_fd);
8388 set_socket_info_index(dup_fd, idx);
8395 return swrap_dup(fd);
8398 /****************************
8400 ***************************/
8402 static int swrap_dup2(int fd, int newfd)
8404 struct socket_info *si;
8407 idx = find_socket_info_index(fd);
8409 return libc_dup2(fd, newfd);
8412 si = swrap_get_socket_info(idx);
8416 * According to the manpage:
8418 * "If oldfd is a valid file descriptor, and newfd has the same
8419 * value as oldfd, then dup2() does nothing, and returns newfd."
8424 if ((size_t)newfd >= socket_fds_max) {
8425 SWRAP_LOG(SWRAP_LOG_ERROR,
8426 "The max socket index limit of %zu has been reached, "
8434 if (find_socket_info(newfd)) {
8435 /* dup2() does an implicit close of newfd, which we
8436 * need to emulate */
8440 dup_fd = libc_dup2(fd, newfd);
8442 int saved_errno = errno;
8443 errno = saved_errno;
8449 swrap_inc_refcount(si);
8451 SWRAP_UNLOCK_SI(si);
8453 /* Make sure we don't have an entry for the fd */
8454 swrap_remove_stale(dup_fd);
8456 set_socket_info_index(dup_fd, idx);
8461 int dup2(int fd, int newfd)
8463 return swrap_dup2(fd, newfd);
8466 /****************************
8468 ***************************/
8470 static int swrap_vfcntl(int fd, int cmd, va_list va)
8472 struct socket_info *si;
8473 int rc, dup_fd, idx;
8475 idx = find_socket_info_index(fd);
8477 return libc_vfcntl(fd, cmd, va);
8480 si = swrap_get_socket_info(idx);
8484 dup_fd = libc_vfcntl(fd, cmd, va);
8486 int saved_errno = errno;
8487 errno = saved_errno;
8491 /* Make sure we don't have an entry for the fd */
8492 swrap_remove_stale(dup_fd);
8494 if ((size_t)dup_fd >= socket_fds_max) {
8495 SWRAP_LOG(SWRAP_LOG_ERROR,
8496 "The max socket index limit of %zu has been reached, "
8507 swrap_inc_refcount(si);
8509 SWRAP_UNLOCK_SI(si);
8512 set_socket_info_index(dup_fd, idx);
8517 rc = libc_vfcntl(fd, cmd, va);
8524 #undef fcntl /* Needed for LFS handling */
8525 int fcntl(int fd, int cmd, ...)
8532 rc = swrap_vfcntl(fd, cmd, va);
8539 /****************************
8541 ***************************/
8544 static int swrap_eventfd(int count, int flags)
8548 fd = libc_eventfd(count, flags);
8550 swrap_remove_stale(fd);
8556 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8557 int eventfd(unsigned int count, int flags)
8559 int eventfd(int count, int flags)
8562 return swrap_eventfd(count, flags);
8567 int pledge(const char *promises, const char *paths[])
8569 (void)promises; /* unused */
8570 (void)paths; /* unused */
8574 #endif /* HAVE_PLEDGE */
8577 static bool swrap_is_swrap_related_syscall(long int sysno)
8583 #endif /* SYS_close */
8588 #endif /* SYS_recvmmsg */
8593 #endif /* SYS_sendmmsg */
8600 static long int swrap_syscall(long int sysno, va_list vp)
8608 int fd = (int)va_arg(vp, int);
8610 SWRAP_LOG(SWRAP_LOG_TRACE,
8611 "calling swrap_close syscall %lu",
8613 rc = swrap_close(fd);
8616 #endif /* SYS_close */
8621 int fd = (int)va_arg(vp, int);
8622 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8623 unsigned int vlen = va_arg(vp, unsigned int);
8624 int flags = va_arg(vp, int);
8625 struct timespec *timeout = va_arg(vp, struct timespec *);
8627 SWRAP_LOG(SWRAP_LOG_TRACE,
8628 "calling swrap_recvmmsg syscall %lu",
8630 rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
8633 #endif /* SYS_recvmmsg */
8638 int fd = (int)va_arg(vp, int);
8639 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8640 unsigned int vlen = va_arg(vp, unsigned int);
8641 int flags = va_arg(vp, int);
8643 SWRAP_LOG(SWRAP_LOG_TRACE,
8644 "calling swrap_sendmmsg syscall %lu",
8646 rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
8649 #endif /* SYS_sendmmsg */
8660 #ifdef HAVE_SYSCALL_INT
8661 int syscall(int sysno, ...)
8663 long int syscall(long int sysno, ...)
8666 #ifdef HAVE_SYSCALL_INT
8673 va_start(va, sysno);
8676 * We should only handle the syscall numbers
8679 if (!swrap_is_swrap_related_syscall(sysno)) {
8681 * We need to give socket_wrapper a
8682 * chance to take over...
8684 if (swrap_uwrap_syscall_valid(sysno)) {
8685 rc = swrap_uwrap_syscall_va(sysno, va);
8690 rc = libc_vsyscall(sysno, va);
8695 if (!socket_wrapper_enabled()) {
8696 rc = libc_vsyscall(sysno, va);
8701 rc = swrap_syscall(sysno, va);
8707 /* used by uid_wrapper */
8708 bool socket_wrapper_syscall_valid(long int sysno);
8709 bool socket_wrapper_syscall_valid(long int sysno)
8711 if (!swrap_is_swrap_related_syscall(sysno)) {
8715 if (!socket_wrapper_enabled()) {
8722 /* used by uid_wrapper */
8723 long int socket_wrapper_syscall_va(long int sysno, va_list va);
8724 long int socket_wrapper_syscall_va(long int sysno, va_list va)
8726 if (!swrap_is_swrap_related_syscall(sysno)) {
8731 if (!socket_wrapper_enabled()) {
8732 return libc_vsyscall(sysno, va);
8735 return swrap_syscall(sysno, va);
8737 #endif /* HAVE_SYSCALL */
8739 static void swrap_thread_prepare(void)
8742 * This function should only be called here!!
8744 * We bind all symobls to avoid deadlocks of the fork is
8745 * interrupted by a signal handler using a symbol of this
8748 swrap_bind_symbol_all();
8753 static void swrap_thread_parent(void)
8758 static void swrap_thread_child(void)
8763 /****************************
8765 ***************************/
8766 void swrap_constructor(void)
8768 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8769 SWRAP_LOG(SWRAP_LOG_ERROR,
8771 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8772 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8773 "sizeof(struct socket_info)=%zu",
8775 sizeof(struct swrap_unix_scm_rights),
8776 sizeof(struct swrap_unix_scm_rights_payload),
8777 sizeof(struct socket_info));
8784 * If we hold a lock and the application forks, then the child
8785 * is not able to unlock the mutex and we are in a deadlock.
8786 * This should prevent such deadlocks.
8788 pthread_atfork(&swrap_thread_prepare,
8789 &swrap_thread_parent,
8790 &swrap_thread_child);
8793 /****************************
8795 ***************************/
8798 * This function is called when the library is unloaded and makes sure that
8799 * sockets get closed and the unix file for the socket are unlinked.
8801 void swrap_destructor(void)
8805 if (socket_fds_idx != NULL) {
8806 for (i = 0; i < socket_fds_max; ++i) {
8807 if (socket_fds_idx[i] != -1) {
8811 SAFE_FREE(socket_fds_idx);
8816 if (swrap.libc.handle != NULL
8818 && swrap.libc.handle != RTLD_NEXT
8821 dlclose(swrap.libc.handle);
8823 if (swrap.libc.socket_handle
8825 && swrap.libc.socket_handle != RTLD_NEXT
8828 dlclose(swrap.libc.socket_handle);
8832 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8834 * On FreeBSD 12 (and maybe other platforms)
8835 * system libraries like libresolv prefix there
8836 * syscalls with '_' in order to always use
8837 * the symbols from libc.
8839 * In the interaction with resolv_wrapper,
8840 * we need to inject socket wrapper into libresolv,
8841 * which means we need to private all socket
8842 * related syscalls also with the '_' prefix.
8844 * This is tested in Samba's 'make test',
8845 * there we noticed that providing '_read',
8846 * '_open' and '_close' would cause errors, which
8847 * means we skip '_read', '_write' and
8848 * all non socket related calls without
8849 * further analyzing the problem.
8851 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8852 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8855 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8857 SWRAP_SYMBOL_ALIAS(accept, _accept);
8858 SWRAP_SYMBOL_ALIAS(bind, _bind);
8859 SWRAP_SYMBOL_ALIAS(connect, _connect);
8860 SWRAP_SYMBOL_ALIAS(dup, _dup);
8861 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8862 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8863 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8864 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8865 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8866 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8867 SWRAP_SYMBOL_ALIAS(listen, _listen);
8868 SWRAP_SYMBOL_ALIAS(readv, _readv);
8869 SWRAP_SYMBOL_ALIAS(recv, _recv);
8870 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8871 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8872 SWRAP_SYMBOL_ALIAS(send, _send);
8873 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8874 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8875 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8876 SWRAP_SYMBOL_ALIAS(socket, _socket);
8877 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8878 SWRAP_SYMBOL_ALIAS(writev, _writev);
8880 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */