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, ...);
520 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
522 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
525 typedef int (*__libc_eventfd)(int count, int flags);
527 typedef int (*__libc_getpeername)(int sockfd,
528 struct sockaddr *addr,
530 typedef int (*__libc_getsockname)(int sockfd,
531 struct sockaddr *addr,
533 typedef int (*__libc_getsockopt)(int sockfd,
538 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
539 typedef int (*__libc_listen)(int sockfd, int backlog);
540 typedef int (*__libc_open)(const char *pathname, int flags, ...);
542 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
543 #endif /* HAVE_OPEN64 */
545 typedef int (*__libc_openat64)(int dirfd, const char *pathname, int flags, ...);
546 #endif /* HAVE_OPENAT64 */
547 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
548 typedef int (*__libc_pipe)(int pipefd[2]);
549 typedef int (*__libc_read)(int fd, void *buf, size_t count);
550 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
551 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
552 typedef int (*__libc_recvfrom)(int sockfd,
556 struct sockaddr *src_addr,
558 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
560 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
562 typedef ssize_t (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout);
563 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
564 /* Linux legacy glibc < 2.21 */
565 typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout);
567 /* Linux glibc >= 2.21 */
568 typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);
570 #endif /* HAVE_RECVMMSG */
571 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
572 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
574 #if defined(HAVE_SENDMMSG_SSIZE_T)
576 typedef ssize_t (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags);
579 typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags);
581 #endif /* HAVE_SENDMMSG */
582 typedef int (*__libc_sendto)(int sockfd,
586 const struct sockaddr *dst_addr,
588 typedef int (*__libc_setsockopt)(int sockfd,
594 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
596 typedef int (*__libc_socket)(int domain, int type, int protocol);
597 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
598 #ifdef HAVE_TIMERFD_CREATE
599 typedef int (*__libc_timerfd_create)(int clockid, int flags);
601 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
602 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
604 typedef long int (*__libc_syscall)(long int sysno, ...);
607 #define SWRAP_SYMBOL_ENTRY(i) \
613 struct swrap_libc_symbols {
615 SWRAP_SYMBOL_ENTRY(accept4);
617 SWRAP_SYMBOL_ENTRY(accept);
619 SWRAP_SYMBOL_ENTRY(bind);
620 SWRAP_SYMBOL_ENTRY(close);
621 #ifdef HAVE___CLOSE_NOCANCEL
622 SWRAP_SYMBOL_ENTRY(__close_nocancel);
624 SWRAP_SYMBOL_ENTRY(connect);
625 SWRAP_SYMBOL_ENTRY(dup);
626 SWRAP_SYMBOL_ENTRY(dup2);
628 SWRAP_SYMBOL_ENTRY(fcntl64);
630 SWRAP_SYMBOL_ENTRY(fcntl);
632 SWRAP_SYMBOL_ENTRY(fopen);
634 SWRAP_SYMBOL_ENTRY(fopen64);
637 SWRAP_SYMBOL_ENTRY(eventfd);
639 SWRAP_SYMBOL_ENTRY(getpeername);
640 SWRAP_SYMBOL_ENTRY(getsockname);
641 SWRAP_SYMBOL_ENTRY(getsockopt);
642 SWRAP_SYMBOL_ENTRY(ioctl);
643 SWRAP_SYMBOL_ENTRY(listen);
644 SWRAP_SYMBOL_ENTRY(open);
646 SWRAP_SYMBOL_ENTRY(open64);
649 SWRAP_SYMBOL_ENTRY(openat64);
651 SWRAP_SYMBOL_ENTRY(openat);
652 SWRAP_SYMBOL_ENTRY(pipe);
653 SWRAP_SYMBOL_ENTRY(read);
654 SWRAP_SYMBOL_ENTRY(readv);
655 SWRAP_SYMBOL_ENTRY(recv);
656 SWRAP_SYMBOL_ENTRY(recvfrom);
657 SWRAP_SYMBOL_ENTRY(recvmsg);
659 SWRAP_SYMBOL_ENTRY(recvmmsg);
661 SWRAP_SYMBOL_ENTRY(send);
662 SWRAP_SYMBOL_ENTRY(sendmsg);
664 SWRAP_SYMBOL_ENTRY(sendmmsg);
666 SWRAP_SYMBOL_ENTRY(sendto);
667 SWRAP_SYMBOL_ENTRY(setsockopt);
669 SWRAP_SYMBOL_ENTRY(signalfd);
671 SWRAP_SYMBOL_ENTRY(socket);
672 SWRAP_SYMBOL_ENTRY(socketpair);
673 #ifdef HAVE_TIMERFD_CREATE
674 SWRAP_SYMBOL_ENTRY(timerfd_create);
676 SWRAP_SYMBOL_ENTRY(write);
677 SWRAP_SYMBOL_ENTRY(writev);
679 SWRAP_SYMBOL_ENTRY(syscall);
682 #undef SWRAP_SYMBOL_ENTRY
684 #define SWRAP_SYMBOL_ENTRY(i) \
686 __rtld_default_##i f; \
691 typedef bool (*__rtld_default_uid_wrapper_syscall_valid)(long int sysno);
692 typedef long int (*__rtld_default_uid_wrapper_syscall_va)(long int sysno, va_list va);
695 struct swrap_rtld_default_symbols {
697 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_valid);
698 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_va);
703 #undef SWRAP_SYMBOL_ENTRY
709 struct swrap_libc_symbols symbols;
713 struct swrap_rtld_default_symbols symbols;
717 static struct swrap swrap;
720 static char *socket_wrapper_dir(void);
722 #define LIBC_NAME "libc.so"
729 static const char *swrap_str_lib(enum swrap_lib lib)
734 case SWRAP_LIBSOCKET:
738 /* Compiler would warn us about unhandled enum value if we get here */
742 static void *swrap_load_lib_handle(enum swrap_lib lib)
744 int flags = RTLD_LAZY;
749 const char *env_preload = getenv("LD_PRELOAD");
750 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
751 bool enable_deepbind = true;
753 /* Don't do a deepbind if we run with libasan */
754 if (env_preload != NULL && strlen(env_preload) < 1024) {
755 const char *p = strstr(env_preload, "libasan.so");
757 enable_deepbind = false;
761 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
762 enable_deepbind = false;
765 if (enable_deepbind) {
766 flags |= RTLD_DEEPBIND;
771 case SWRAP_LIBSOCKET:
772 #ifdef HAVE_LIBSOCKET
773 handle = swrap.libc.socket_handle;
774 if (handle == NULL) {
775 for (i = 10; i >= 0; i--) {
776 char soname[256] = {0};
778 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
779 handle = dlopen(soname, flags);
780 if (handle != NULL) {
785 swrap.libc.socket_handle = handle;
790 handle = swrap.libc.handle;
792 if (handle == NULL) {
793 handle = dlopen(LIBC_SO, flags);
795 swrap.libc.handle = handle;
798 if (handle == NULL) {
799 for (i = 10; i >= 0; i--) {
800 char soname[256] = {0};
802 snprintf(soname, sizeof(soname), "libc.so.%d", i);
803 handle = dlopen(soname, flags);
804 if (handle != NULL) {
809 swrap.libc.handle = handle;
814 if (handle == NULL) {
816 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
818 SWRAP_LOG(SWRAP_LOG_ERROR,
819 "Failed to dlopen library: %s",
828 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
833 handle = swrap_load_lib_handle(lib);
835 func = dlsym(handle, fn_name);
837 SWRAP_LOG(SWRAP_LOG_ERROR,
838 "Failed to find %s: %s",
844 SWRAP_LOG(SWRAP_LOG_TRACE,
852 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
853 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
857 ret = pthread_mutex_lock(mutex);
859 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
860 getpid(), getppid(), caller, line, name, strerror(ret));
865 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
866 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
870 ret = pthread_mutex_unlock(mutex);
872 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
873 getpid(), getppid(), caller, line, name, strerror(ret));
879 * These macros have a thread race condition on purpose!
881 * This is an optimization to avoid locking each time we check if the symbol is
884 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
885 swrap.libc.symbols._libc_##sym_name.obj = \
886 _swrap_bind_symbol(lib, #sym_name); \
889 #define swrap_bind_symbol_libc(sym_name) \
890 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
892 #define swrap_bind_symbol_libsocket(sym_name) \
893 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
895 #define swrap_bind_symbol_rtld_default_optional(sym_name) do { \
896 swrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
897 dlsym(RTLD_DEFAULT, #sym_name); \
900 static void swrap_bind_symbol_all(void);
902 /****************************************************************************
904 ****************************************************************************
906 * Functions especially from libc need to be loaded individually, you can't
907 * load all at once or gdb will segfault at startup. The same applies to
908 * valgrind and has probably something todo with with the linker. So we need
909 * load each function at the point it is called the first time.
911 ****************************************************************************/
914 static int libc_accept4(int sockfd,
915 struct sockaddr *addr,
919 swrap_bind_symbol_all();
921 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
924 #else /* HAVE_ACCEPT4 */
926 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
928 swrap_bind_symbol_all();
930 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
932 #endif /* HAVE_ACCEPT4 */
934 static int libc_bind(int sockfd,
935 const struct sockaddr *addr,
938 swrap_bind_symbol_all();
940 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
943 static int libc_close(int fd)
945 swrap_bind_symbol_all();
947 return swrap.libc.symbols._libc_close.f(fd);
950 #ifdef HAVE___CLOSE_NOCANCEL
951 static int libc___close_nocancel(int fd)
953 swrap_bind_symbol_all();
955 return swrap.libc.symbols._libc___close_nocancel.f(fd);
957 #endif /* HAVE___CLOSE_NOCANCEL */
959 static int libc_connect(int sockfd,
960 const struct sockaddr *addr,
963 swrap_bind_symbol_all();
965 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
968 static int libc_dup(int fd)
970 swrap_bind_symbol_all();
972 return swrap.libc.symbols._libc_dup.f(fd);
975 static int libc_dup2(int oldfd, int newfd)
977 swrap_bind_symbol_all();
979 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
983 static int libc_eventfd(int count, int flags)
985 swrap_bind_symbol_all();
987 return swrap.libc.symbols._libc_eventfd.f(count, flags);
991 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
992 static int libc_vfcntl(int fd, int cmd, va_list ap)
997 swrap_bind_symbol_all();
999 arg = va_arg(ap, void *);
1002 * If fcntl64 exists then this is a system were fcntl is
1003 * renamed (including when building this file), and so we must
1004 * assume that the binary under test was built with
1005 * -D_FILE_OFFSET_BITS=64 and pass on to fcntl64.
1007 * If we are wrong, then fcntl is unwrapped, but while that is
1008 * not ideal, is is also unlikely.
1010 * In any case, it is always wrong to map fcntl64() to fcntl()
1011 * as this will cause a thunk from struct flock -> flock64
1012 * that the caller had already prepared for.
1015 rc = swrap.libc.symbols._libc_fcntl64.f(fd, cmd, arg);
1017 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
1023 static int libc_getpeername(int sockfd,
1024 struct sockaddr *addr,
1027 swrap_bind_symbol_all();
1029 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
1032 static int libc_getsockname(int sockfd,
1033 struct sockaddr *addr,
1036 swrap_bind_symbol_all();
1038 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
1041 static int libc_getsockopt(int sockfd,
1047 swrap_bind_symbol_all();
1049 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
1056 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1057 static int libc_vioctl(int d, unsigned long int request, va_list ap)
1062 swrap_bind_symbol_all();
1064 arg = va_arg(ap, void *);
1066 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
1071 static int libc_listen(int sockfd, int backlog)
1073 swrap_bind_symbol_all();
1075 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
1078 static FILE *libc_fopen(const char *name, const char *mode)
1080 swrap_bind_symbol_all();
1082 return swrap.libc.symbols._libc_fopen.f(name, mode);
1086 static FILE *libc_fopen64(const char *name, const char *mode)
1088 swrap_bind_symbol_all();
1090 return swrap.libc.symbols._libc_fopen64.f(name, mode);
1092 #endif /* HAVE_FOPEN64 */
1094 static void swrap_inject_o_largefile(int *flags)
1096 (void)*flags; /* maybe unused */
1097 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1099 if (((*flags) & O_PATH) == 0)
1102 *flags |= O_LARGEFILE;
1107 static int libc_vopen(const char *pathname, int flags, va_list ap)
1112 swrap_bind_symbol_all();
1114 swrap_inject_o_largefile(&flags);
1116 if (flags & O_CREAT) {
1117 mode = va_arg(ap, int);
1119 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1124 static int libc_open(const char *pathname, int flags, ...)
1129 va_start(ap, flags);
1130 fd = libc_vopen(pathname, flags, ap);
1137 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1142 swrap_bind_symbol_all();
1144 swrap_inject_o_largefile(&flags);
1146 if (flags & O_CREAT) {
1147 mode = va_arg(ap, int);
1149 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1153 #endif /* HAVE_OPEN64 */
1155 #ifdef HAVE_OPENAT64
1157 libc_vopenat64(int dirfd, const char *pathname, int flags, va_list ap)
1162 swrap_bind_symbol_all();
1164 swrap_inject_o_largefile(&flags);
1166 if (flags & O_CREAT) {
1167 mode = va_arg(ap, int);
1169 fd = swrap.libc.symbols._libc_openat64.f(dirfd,
1176 #endif /* HAVE_OPENAT64 */
1178 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1183 swrap_bind_symbol_all();
1185 swrap_inject_o_largefile(&flags);
1187 if (flags & O_CREAT) {
1188 mode = va_arg(ap, int);
1190 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1199 static int libc_openat(int dirfd, const char *path, int flags, ...)
1204 va_start(ap, flags);
1205 fd = libc_vopenat(dirfd, path, flags, ap);
1212 static int libc_pipe(int pipefd[2])
1214 swrap_bind_symbol_all();
1216 return swrap.libc.symbols._libc_pipe.f(pipefd);
1219 static int libc_read(int fd, void *buf, size_t count)
1221 swrap_bind_symbol_all();
1223 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1226 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1228 swrap_bind_symbol_all();
1230 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1233 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1235 swrap_bind_symbol_all();
1237 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1240 static int libc_recvfrom(int sockfd,
1244 struct sockaddr *src_addr,
1247 swrap_bind_symbol_all();
1249 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1257 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1259 swrap_bind_symbol_all();
1261 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1264 #ifdef HAVE_RECVMMSG
1265 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1267 static ssize_t libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
1268 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1269 /* Linux legacy glibc < 2.21 */
1270 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
1272 /* Linux glibc >= 2.21 */
1273 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
1276 swrap_bind_symbol_all();
1278 return swrap.libc.symbols._libc_recvmmsg.f(sockfd, msgvec, vlen, flags, timeout);
1282 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1284 swrap_bind_symbol_all();
1286 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1289 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1291 swrap_bind_symbol_all();
1293 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1296 #ifdef HAVE_SENDMMSG
1297 #if defined(HAVE_SENDMMSG_SSIZE_T)
1299 static ssize_t libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags)
1302 static int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
1305 swrap_bind_symbol_all();
1307 return swrap.libc.symbols._libc_sendmmsg.f(sockfd, msgvec, vlen, flags);
1311 static int libc_sendto(int sockfd,
1315 const struct sockaddr *dst_addr,
1318 swrap_bind_symbol_all();
1320 return swrap.libc.symbols._libc_sendto.f(sockfd,
1328 static int libc_setsockopt(int sockfd,
1334 swrap_bind_symbol_all();
1336 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1343 #ifdef HAVE_SIGNALFD
1344 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1346 swrap_bind_symbol_all();
1348 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1352 static int libc_socket(int domain, int type, int protocol)
1354 swrap_bind_symbol_all();
1356 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1359 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1361 swrap_bind_symbol_all();
1363 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1366 #ifdef HAVE_TIMERFD_CREATE
1367 static int libc_timerfd_create(int clockid, int flags)
1369 swrap_bind_symbol_all();
1371 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1375 static ssize_t libc_write(int fd, const void *buf, size_t count)
1377 swrap_bind_symbol_all();
1379 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1382 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1384 swrap_bind_symbol_all();
1386 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1390 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1391 static long int libc_vsyscall(long int sysno, va_list va)
1397 swrap_bind_symbol_all();
1399 for (i = 0; i < 8; i++) {
1400 args[i] = va_arg(va, long int);
1403 rc = swrap.libc.symbols._libc_syscall.f(sysno,
1416 static bool swrap_uwrap_syscall_valid(long int sysno)
1418 swrap_bind_symbol_all();
1420 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f == NULL) {
1424 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f(
1428 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1429 static long int swrap_uwrap_syscall_va(long int sysno, va_list va)
1431 swrap_bind_symbol_all();
1433 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f == NULL) {
1435 * Fallback to libc, if uid_wrapper_syscall_va is not
1438 return libc_vsyscall(sysno, va);
1441 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f(
1445 #endif /* HAVE_SYSCALL */
1447 /* DO NOT call this function during library initialization! */
1448 static void __swrap_bind_symbol_all_once(void)
1451 swrap_bind_symbol_libsocket(accept4);
1453 swrap_bind_symbol_libsocket(accept);
1455 swrap_bind_symbol_libsocket(bind);
1456 swrap_bind_symbol_libc(close);
1457 #ifdef HAVE___CLOSE_NOCANCEL
1458 swrap_bind_symbol_libc(__close_nocancel);
1460 swrap_bind_symbol_libsocket(connect);
1461 swrap_bind_symbol_libc(dup);
1462 swrap_bind_symbol_libc(dup2);
1464 swrap_bind_symbol_libc(fcntl64);
1466 swrap_bind_symbol_libc(fcntl);
1468 swrap_bind_symbol_libc(fopen);
1470 swrap_bind_symbol_libc(fopen64);
1473 swrap_bind_symbol_libc(eventfd);
1475 swrap_bind_symbol_libsocket(getpeername);
1476 swrap_bind_symbol_libsocket(getsockname);
1477 swrap_bind_symbol_libsocket(getsockopt);
1478 swrap_bind_symbol_libc(ioctl);
1479 swrap_bind_symbol_libsocket(listen);
1480 swrap_bind_symbol_libc(open);
1482 swrap_bind_symbol_libc(open64);
1484 #ifdef HAVE_OPENAT64
1485 swrap_bind_symbol_libc(openat64);
1487 swrap_bind_symbol_libc(openat);
1488 swrap_bind_symbol_libsocket(pipe);
1489 swrap_bind_symbol_libc(read);
1490 swrap_bind_symbol_libsocket(readv);
1491 swrap_bind_symbol_libsocket(recv);
1492 swrap_bind_symbol_libsocket(recvfrom);
1493 swrap_bind_symbol_libsocket(recvmsg);
1494 #ifdef HAVE_RECVMMSG
1495 swrap_bind_symbol_libsocket(recvmmsg);
1497 swrap_bind_symbol_libsocket(send);
1498 swrap_bind_symbol_libsocket(sendmsg);
1499 #ifdef HAVE_SENDMMSG
1500 swrap_bind_symbol_libsocket(sendmmsg);
1502 swrap_bind_symbol_libsocket(sendto);
1503 swrap_bind_symbol_libsocket(setsockopt);
1504 #ifdef HAVE_SIGNALFD
1505 swrap_bind_symbol_libsocket(signalfd);
1507 swrap_bind_symbol_libsocket(socket);
1508 swrap_bind_symbol_libsocket(socketpair);
1509 #ifdef HAVE_TIMERFD_CREATE
1510 swrap_bind_symbol_libc(timerfd_create);
1512 swrap_bind_symbol_libc(write);
1513 swrap_bind_symbol_libsocket(writev);
1515 swrap_bind_symbol_libc(syscall);
1516 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
1517 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
1521 static void swrap_bind_symbol_all(void)
1523 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1525 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1528 /*********************************************************
1529 * SWRAP HELPER FUNCTIONS
1530 *********************************************************/
1533 * We return 127.0.0.0 (default) or 10.53.57.0.
1535 * This can be controlled by:
1536 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1538 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1540 static in_addr_t swrap_ipv4_net(void)
1542 static int initialized;
1543 static in_addr_t hv;
1544 const char *net_str = NULL;
1553 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1554 if (net_str == NULL) {
1555 net_str = "127.0.0.0";
1558 ret = inet_pton(AF_INET, net_str, &nv);
1560 SWRAP_LOG(SWRAP_LOG_ERROR,
1561 "INVALID IPv4 Network [%s]",
1566 hv = ntohl(nv.s_addr);
1576 SWRAP_LOG(SWRAP_LOG_ERROR,
1577 "INVALID IPv4 Network [%s][0x%x] should be "
1578 "127.0.0.0 or 10.53.57.0",
1579 net_str, (unsigned)hv);
1587 * This returns 127.255.255.255 or 10.255.255.255
1589 static in_addr_t swrap_ipv4_bcast(void)
1593 hv = swrap_ipv4_net();
1594 hv |= IN_CLASSA_HOST;
1600 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1602 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1606 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1607 SWRAP_LOG(SWRAP_LOG_ERROR,
1608 "swrap_ipv4_iface(%u) invalid!",
1614 hv = swrap_ipv4_net();
1624 static const struct in6_addr *swrap_ipv6(void)
1626 static struct in6_addr v;
1627 static int initialized;
1635 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1644 static void set_port(int family, int prt, struct swrap_address *addr)
1648 addr->sa.in.sin_port = htons(prt);
1652 addr->sa.in6.sin6_port = htons(prt);
1658 static size_t socket_length(int family)
1662 return sizeof(struct sockaddr_in);
1665 return sizeof(struct sockaddr_in6);
1671 struct swrap_sockaddr_buf {
1675 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1676 const struct sockaddr *saddr)
1678 unsigned int port = 0;
1679 char addr[64] = {0,};
1681 switch (saddr->sa_family) {
1683 const struct sockaddr_in *in =
1684 (const struct sockaddr_in *)(const void *)saddr;
1686 port = ntohs(in->sin_port);
1688 inet_ntop(saddr->sa_family,
1690 addr, sizeof(addr));
1695 const struct sockaddr_in6 *in6 =
1696 (const struct sockaddr_in6 *)(const void *)saddr;
1698 port = ntohs(in6->sin6_port);
1700 inet_ntop(saddr->sa_family,
1702 addr, sizeof(addr));
1707 snprintf(addr, sizeof(addr),
1708 "<Unknown address family %u>",
1713 snprintf(buf->str, sizeof(buf->str),
1714 "addr[%s]/port[%u]",
1720 static struct socket_info *swrap_get_socket_info(int si_index)
1722 return (struct socket_info *)(&(sockets[si_index].info));
1725 static int swrap_get_refcount(struct socket_info *si)
1727 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1728 return sic->meta.refcount;
1731 static void swrap_inc_refcount(struct socket_info *si)
1733 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1735 sic->meta.refcount += 1;
1738 static void swrap_dec_refcount(struct socket_info *si)
1740 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1742 sic->meta.refcount -= 1;
1745 static int swrap_get_next_free(struct socket_info *si)
1747 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1749 return sic->meta.next_free;
1752 static void swrap_set_next_free(struct socket_info *si, int next_free)
1754 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1756 sic->meta.next_free = next_free;
1759 static int swrap_un_path(struct sockaddr_un *un,
1760 const char *swrap_dir,
1767 ret = snprintf(un->sun_path,
1768 sizeof(un->sun_path),
1774 if ((size_t)ret >= sizeof(un->sun_path)) {
1775 return ENAMETOOLONG;
1781 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1782 const char *swrap_dir)
1786 ret = snprintf(un->sun_path,
1787 sizeof(un->sun_path),
1791 if ((size_t)ret >= sizeof(un->sun_path)) {
1792 return ENAMETOOLONG;
1798 static bool swrap_dir_usable(const char *swrap_dir)
1800 struct sockaddr_un un;
1803 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1808 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1816 static char *socket_wrapper_dir(void)
1818 char *swrap_dir = NULL;
1819 char *s = getenv("SOCKET_WRAPPER_DIR");
1823 if (s == NULL || s[0] == '\0') {
1824 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1828 swrap_dir = realpath(s, NULL);
1829 if (swrap_dir == NULL) {
1830 SWRAP_LOG(SWRAP_LOG_ERROR,
1831 "Unable to resolve socket_wrapper dir path: %s - %s",
1837 ok = swrap_dir_usable(swrap_dir);
1844 ok = swrap_dir_usable(s);
1846 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1850 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1852 SWRAP_LOG(SWRAP_LOG_ERROR,
1853 "realpath(SOCKET_WRAPPER_DIR) too long and "
1854 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1859 swrap_dir = strdup(s);
1860 if (swrap_dir == NULL) {
1861 SWRAP_LOG(SWRAP_LOG_ERROR,
1862 "Unable to duplicate socket_wrapper dir path");
1866 SWRAP_LOG(SWRAP_LOG_WARN,
1867 "realpath(SOCKET_WRAPPER_DIR) too long, "
1868 "using original SOCKET_WRAPPER_DIR\n");
1871 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1875 static unsigned int socket_wrapper_mtu(void)
1877 static unsigned int max_mtu = 0;
1882 swrap_mutex_lock(&mtu_update_mutex);
1888 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1890 s = getenv("SOCKET_WRAPPER_MTU");
1895 tmp = strtol(s, &endp, 10);
1900 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1906 swrap_mutex_unlock(&mtu_update_mutex);
1910 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1912 pthread_mutexattr_t ma;
1913 bool need_destroy = false;
1916 #define __CHECK(cmd) do { \
1919 SWRAP_LOG(SWRAP_LOG_ERROR, \
1920 "%s: %s - failed %d", \
1926 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1927 __CHECK(pthread_mutexattr_init(&ma));
1928 need_destroy = true;
1929 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1930 __CHECK(pthread_mutex_init(m, &ma));
1933 pthread_mutexattr_destroy(&ma);
1938 static size_t socket_wrapper_max_sockets(void)
1944 if (socket_info_max != 0) {
1945 return socket_info_max;
1948 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1950 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1951 if (s == NULL || s[0] == '\0') {
1955 tmp = strtoul(s, &endp, 10);
1960 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1961 SWRAP_LOG(SWRAP_LOG_ERROR,
1962 "Invalid number of sockets specified, "
1963 "using default (%zu)",
1967 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1968 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1969 SWRAP_LOG(SWRAP_LOG_ERROR,
1970 "Invalid number of sockets specified, "
1971 "using maximum (%zu).",
1975 socket_info_max = tmp;
1978 return socket_info_max;
1981 static void socket_wrapper_init_fds_idx(void)
1986 if (socket_fds_idx != NULL) {
1990 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1992 SWRAP_LOG(SWRAP_LOG_ERROR,
1993 "Failed to allocate socket fds index array: %s",
1998 for (i = 0; i < socket_fds_max; i++) {
2002 socket_fds_idx = tmp;
2005 static void socket_wrapper_init_sockets(void)
2011 swrap_bind_symbol_all();
2013 swrap_mutex_lock(&sockets_mutex);
2015 if (sockets != NULL) {
2016 swrap_mutex_unlock(&sockets_mutex);
2020 SWRAP_LOG(SWRAP_LOG_DEBUG,
2021 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
2022 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
2025 * Intialize the static cache early before
2026 * any thread is able to start.
2028 (void)swrap_ipv4_net();
2030 socket_wrapper_init_fds_idx();
2032 /* Needs to be called inside the sockets_mutex lock here. */
2033 max_sockets = socket_wrapper_max_sockets();
2035 sockets = (struct socket_info_container *)calloc(max_sockets,
2036 sizeof(struct socket_info_container));
2038 if (sockets == NULL) {
2039 SWRAP_LOG(SWRAP_LOG_ERROR,
2040 "Failed to allocate sockets array: %s",
2042 swrap_mutex_unlock(&sockets_mutex);
2046 swrap_mutex_lock(&first_free_mutex);
2047 swrap_mutex_lock(&sockets_si_global);
2051 for (i = 0; i < max_sockets; i++) {
2052 swrap_set_next_free(&sockets[i].info, i+1);
2055 /* mark the end of the free list */
2056 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
2058 swrap_mutex_unlock(&sockets_si_global);
2059 swrap_mutex_unlock(&first_free_mutex);
2060 swrap_mutex_unlock(&sockets_mutex);
2066 bool socket_wrapper_enabled(void)
2068 char *s = socket_wrapper_dir();
2076 socket_wrapper_init_sockets();
2081 static unsigned int socket_wrapper_default_iface(void)
2083 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
2086 if (sscanf(s, "%u", &iface) == 1) {
2087 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
2093 return 1;/* 127.0.0.1 */
2096 static void set_socket_info_index(int fd, int idx)
2098 SWRAP_LOG(SWRAP_LOG_TRACE,
2101 socket_fds_idx[fd] = idx;
2102 /* This builtin issues a full memory barrier. */
2103 __sync_synchronize();
2106 static void reset_socket_info_index(int fd)
2108 SWRAP_LOG(SWRAP_LOG_TRACE,
2111 set_socket_info_index(fd, -1);
2114 static int find_socket_info_index(int fd)
2120 if (socket_fds_idx == NULL) {
2124 if ((size_t)fd >= socket_fds_max) {
2126 * Do not add a log here as some applications do stupid things
2129 * for (fd = 0; fd <= getdtablesize(); fd++) {
2133 * This would produce millions of lines of debug messages.
2136 SWRAP_LOG(SWRAP_LOG_ERROR,
2137 "Looking for a socket info for the fd %d is over the "
2138 "max socket index limit of %zu.",
2145 /* This builtin issues a full memory barrier. */
2146 __sync_synchronize();
2147 return socket_fds_idx[fd];
2150 static int swrap_add_socket_info(const struct socket_info *si_input)
2152 struct socket_info *si = NULL;
2155 if (si_input == NULL) {
2160 swrap_mutex_lock(&first_free_mutex);
2161 if (first_free == -1) {
2166 si_index = first_free;
2167 si = swrap_get_socket_info(si_index);
2171 first_free = swrap_get_next_free(si);
2173 swrap_inc_refcount(si);
2175 SWRAP_UNLOCK_SI(si);
2178 swrap_mutex_unlock(&first_free_mutex);
2183 static int swrap_create_socket(struct socket_info *si, int fd)
2187 if ((size_t)fd >= socket_fds_max) {
2188 SWRAP_LOG(SWRAP_LOG_ERROR,
2189 "The max socket index limit of %zu has been reached, "
2197 idx = swrap_add_socket_info(si);
2202 set_socket_info_index(fd, idx);
2207 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2214 p = strrchr(un->sun_path, '/');
2215 if (p) p++; else p = un->sun_path;
2217 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2218 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2224 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2225 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2232 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2238 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2242 case SOCKET_TYPE_CHAR_TCP:
2243 case SOCKET_TYPE_CHAR_UDP: {
2244 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2246 if ((*len) < sizeof(*in2)) {
2247 SWRAP_LOG(SWRAP_LOG_ERROR,
2248 "V4: *len(%zu) < sizeof(*in2)=%zu",
2249 (size_t)*len, sizeof(*in2));
2254 memset(in2, 0, sizeof(*in2));
2255 in2->sin_family = AF_INET;
2256 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2257 in2->sin_port = htons(prt);
2259 *len = sizeof(*in2);
2263 case SOCKET_TYPE_CHAR_TCP_V6:
2264 case SOCKET_TYPE_CHAR_UDP_V6: {
2265 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2267 if ((*len) < sizeof(*in2)) {
2268 SWRAP_LOG(SWRAP_LOG_ERROR,
2269 "V6: *len(%zu) < sizeof(*in2)=%zu",
2270 (size_t)*len, sizeof(*in2));
2271 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2276 memset(in2, 0, sizeof(*in2));
2277 in2->sin6_family = AF_INET6;
2278 in2->sin6_addr = *swrap_ipv6();
2279 in2->sin6_addr.s6_addr[15] = iface;
2280 in2->sin6_port = htons(prt);
2282 *len = sizeof(*in2);
2287 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2296 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2303 char *swrap_dir = NULL;
2305 if (bcast) *bcast = 0;
2307 switch (inaddr->sa_family) {
2309 const struct sockaddr_in *in =
2310 (const struct sockaddr_in *)(const void *)inaddr;
2311 unsigned int addr = ntohl(in->sin_addr.s_addr);
2315 const unsigned int sw_net_addr = swrap_ipv4_net();
2316 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2320 u_type = SOCKET_TYPE_CHAR_TCP;
2323 u_type = SOCKET_TYPE_CHAR_UDP;
2324 a_type = SOCKET_TYPE_CHAR_UDP;
2325 b_type = SOCKET_TYPE_CHAR_UDP;
2328 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2329 errno = ESOCKTNOSUPPORT;
2333 prt = ntohs(in->sin_port);
2334 if (a_type && addr == 0xFFFFFFFF) {
2335 /* 255.255.255.255 only udp */
2338 iface = socket_wrapper_default_iface();
2339 } else if (b_type && addr == sw_bcast_addr) {
2348 iface = socket_wrapper_default_iface();
2349 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2350 /* 127.0.0.X or 10.53.57.X */
2353 iface = (addr & 0x000000FF);
2355 struct swrap_sockaddr_buf buf = {};
2356 SWRAP_LOG(SWRAP_LOG_WARN,
2358 swrap_sockaddr_string(&buf, inaddr));
2359 errno = ENETUNREACH;
2362 if (bcast) *bcast = is_bcast;
2367 const struct sockaddr_in6 *in =
2368 (const struct sockaddr_in6 *)(const void *)inaddr;
2369 struct in6_addr cmp1, cmp2;
2373 type = SOCKET_TYPE_CHAR_TCP_V6;
2376 type = SOCKET_TYPE_CHAR_UDP_V6;
2379 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2380 errno = ESOCKTNOSUPPORT;
2384 /* XXX no multicast/broadcast */
2386 prt = ntohs(in->sin6_port);
2388 cmp1 = *swrap_ipv6();
2389 cmp2 = in->sin6_addr;
2390 cmp2.s6_addr[15] = 0;
2391 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2392 iface = in->sin6_addr.s6_addr[15];
2394 struct swrap_sockaddr_buf buf = {};
2395 SWRAP_LOG(SWRAP_LOG_WARN,
2397 swrap_sockaddr_string(&buf, inaddr));
2398 errno = ENETUNREACH;
2406 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2407 errno = ENETUNREACH;
2412 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2417 swrap_dir = socket_wrapper_dir();
2418 if (swrap_dir == NULL) {
2424 swrap_un_path_EINVAL(un, swrap_dir);
2425 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2426 SAFE_FREE(swrap_dir);
2427 /* the caller need to do more processing */
2431 swrap_un_path(un, swrap_dir, type, iface, prt);
2432 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2434 SAFE_FREE(swrap_dir);
2439 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2447 char *swrap_dir = NULL;
2449 if (bcast) *bcast = 0;
2451 switch (si->family) {
2453 const struct sockaddr_in *in =
2454 (const struct sockaddr_in *)(const void *)inaddr;
2455 unsigned int addr = ntohl(in->sin_addr.s_addr);
2460 const unsigned int sw_net_addr = swrap_ipv4_net();
2461 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2463 prt = ntohs(in->sin_port);
2467 u_type = SOCKET_TYPE_CHAR_TCP;
2468 d_type = SOCKET_TYPE_CHAR_TCP;
2471 u_type = SOCKET_TYPE_CHAR_UDP;
2472 d_type = SOCKET_TYPE_CHAR_UDP;
2473 a_type = SOCKET_TYPE_CHAR_UDP;
2474 b_type = SOCKET_TYPE_CHAR_UDP;
2477 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2478 errno = ESOCKTNOSUPPORT;
2486 iface = socket_wrapper_default_iface();
2487 } else if (a_type && addr == 0xFFFFFFFF) {
2488 /* 255.255.255.255 only udp */
2491 iface = socket_wrapper_default_iface();
2492 } else if (b_type && addr == sw_bcast_addr) {
2493 /* 127.255.255.255 only udp */
2496 iface = socket_wrapper_default_iface();
2497 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2501 iface = (addr & 0x000000FF);
2503 errno = EADDRNOTAVAIL;
2507 /* Store the bind address for connect() */
2508 if (si->bindname.sa_socklen == 0) {
2509 struct sockaddr_in bind_in;
2510 socklen_t blen = sizeof(struct sockaddr_in);
2512 ZERO_STRUCT(bind_in);
2513 bind_in.sin_family = in->sin_family;
2514 bind_in.sin_port = in->sin_port;
2515 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2516 si->bindname.sa_socklen = blen;
2517 memcpy(&si->bindname.sa.in, &bind_in, blen);
2524 const struct sockaddr_in6 *in =
2525 (const struct sockaddr_in6 *)(const void *)inaddr;
2526 struct in6_addr cmp1, cmp2;
2530 type = SOCKET_TYPE_CHAR_TCP_V6;
2533 type = SOCKET_TYPE_CHAR_UDP_V6;
2536 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2537 errno = ESOCKTNOSUPPORT;
2541 /* XXX no multicast/broadcast */
2543 prt = ntohs(in->sin6_port);
2545 cmp1 = *swrap_ipv6();
2546 cmp2 = in->sin6_addr;
2547 cmp2.s6_addr[15] = 0;
2548 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2549 iface = socket_wrapper_default_iface();
2550 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2551 iface = in->sin6_addr.s6_addr[15];
2553 errno = EADDRNOTAVAIL;
2557 /* Store the bind address for connect() */
2558 if (si->bindname.sa_socklen == 0) {
2559 struct sockaddr_in6 bind_in;
2560 socklen_t blen = sizeof(struct sockaddr_in6);
2562 ZERO_STRUCT(bind_in);
2563 bind_in.sin6_family = in->sin6_family;
2564 bind_in.sin6_port = in->sin6_port;
2566 bind_in.sin6_addr = *swrap_ipv6();
2567 bind_in.sin6_addr.s6_addr[15] = iface;
2569 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2570 si->bindname.sa_socklen = blen;
2577 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2578 errno = EADDRNOTAVAIL;
2583 if (bcast) *bcast = is_bcast;
2585 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2590 swrap_dir = socket_wrapper_dir();
2591 if (swrap_dir == NULL) {
2597 /* handle auto-allocation of ephemeral ports */
2598 for (prt = 5001; prt < 10000; prt++) {
2599 swrap_un_path(un, swrap_dir, type, iface, prt);
2600 if (stat(un->sun_path, &st) == 0) continue;
2602 set_port(si->family, prt, &si->myname);
2603 set_port(si->family, prt, &si->bindname);
2610 SAFE_FREE(swrap_dir);
2615 swrap_un_path(un, swrap_dir, type, iface, prt);
2616 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2618 SAFE_FREE(swrap_dir);
2623 static struct socket_info *find_socket_info(int fd)
2625 int idx = find_socket_info_index(fd);
2631 return swrap_get_socket_info(idx);
2635 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2637 struct socket_info_fd *f;
2638 const struct socket_info *last_s = NULL;
2640 /* first catch invalid input */
2641 switch (sa->sa_family) {
2643 if (len < sizeof(struct sockaddr_in)) {
2649 if (len < sizeof(struct sockaddr_in6)) {
2659 for (f = socket_fds; f; f = f->next) {
2660 struct socket_info *s = swrap_get_socket_info(f->si_index);
2667 if (s->myname == NULL) {
2670 if (s->myname->sa_family != sa->sa_family) {
2673 switch (s->myname->sa_family) {
2675 struct sockaddr_in *sin1, *sin2;
2677 sin1 = (struct sockaddr_in *)s->myname;
2678 sin2 = (struct sockaddr_in *)sa;
2680 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2683 if (sin1->sin_port != sin2->sin_port) {
2686 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2696 struct sockaddr_in6 *sin1, *sin2;
2698 sin1 = (struct sockaddr_in6 *)s->myname;
2699 sin2 = (struct sockaddr_in6 *)sa;
2701 if (sin1->sin6_port != sin2->sin6_port) {
2704 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2726 static void swrap_remove_stale(int fd);
2728 static int sockaddr_convert_to_un(struct socket_info *si,
2729 const struct sockaddr *in_addr,
2731 struct sockaddr_un *out_addr,
2735 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2737 (void) in_len; /* unused */
2739 if (out_addr == NULL) {
2743 out->sa_family = AF_UNIX;
2744 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2745 out->sa_len = sizeof(*out_addr);
2748 switch (in_addr->sa_family) {
2750 const struct sockaddr_in *sin;
2751 if (si->family != AF_INET) {
2754 if (in_len < sizeof(struct sockaddr_in)) {
2757 sin = (const struct sockaddr_in *)(const void *)in_addr;
2758 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2763 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2764 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2778 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2779 errno = ESOCKTNOSUPPORT;
2783 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2785 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2791 errno = EAFNOSUPPORT;
2792 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2796 static int sockaddr_convert_from_un(const struct socket_info *si,
2797 const struct sockaddr_un *in_addr,
2798 socklen_t un_addrlen,
2800 struct sockaddr *out_addr,
2801 socklen_t *out_addrlen)
2805 if (out_addr == NULL || out_addrlen == NULL)
2808 if (un_addrlen == 0) {
2823 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2824 errno = ESOCKTNOSUPPORT;
2827 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2828 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2829 out_addr->sa_len = *out_addrlen;
2836 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2837 errno = EAFNOSUPPORT;
2841 enum swrap_packet_type {
2843 SWRAP_CONNECT_UNREACH,
2851 SWRAP_SENDTO_UNREACH,
2862 struct swrap_file_hdr {
2864 uint16_t version_major;
2865 uint16_t version_minor;
2868 uint32_t frame_max_len;
2869 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2872 #define SWRAP_FILE_HDR_SIZE 24
2874 struct swrap_packet_frame {
2876 uint32_t micro_seconds;
2877 uint32_t recorded_length;
2878 uint32_t full_length;
2880 #define SWRAP_PACKET_FRAME_SIZE 16
2882 union swrap_packet_ip {
2886 uint16_t packet_length;
2887 uint16_t identification;
2892 uint16_t hdr_checksum;
2896 #define SWRAP_PACKET_IP_V4_SIZE 20
2899 uint8_t flow_label_high;
2900 uint16_t flow_label_low;
2901 uint16_t payload_length;
2902 uint8_t next_header;
2904 uint8_t src_addr[16];
2905 uint8_t dest_addr[16];
2907 #define SWRAP_PACKET_IP_V6_SIZE 40
2909 #define SWRAP_PACKET_IP_SIZE 40
2911 union swrap_packet_payload {
2913 uint16_t source_port;
2923 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2925 uint16_t source_port;
2930 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2937 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2944 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2946 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2948 #define SWRAP_PACKET_MIN_ALLOC \
2949 (SWRAP_PACKET_FRAME_SIZE + \
2950 SWRAP_PACKET_IP_SIZE + \
2951 SWRAP_PACKET_PAYLOAD_SIZE)
2953 static const char *swrap_pcap_init_file(void)
2955 static int initialized = 0;
2956 static const char *s = NULL;
2957 static const struct swrap_file_hdr h;
2958 static const struct swrap_packet_frame f;
2959 static const union swrap_packet_ip i;
2960 static const union swrap_packet_payload p;
2962 if (initialized == 1) {
2968 * TODO: don't use the structs use plain buffer offsets
2969 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2971 * for now make sure we disable PCAP support
2972 * if the struct has alignment!
2974 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2977 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2980 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2983 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2986 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2989 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2992 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2995 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2998 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
3001 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
3005 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
3009 if (strncmp(s, "./", 2) == 0) {
3012 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
3016 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
3017 const struct sockaddr *src,
3018 const struct sockaddr *dest,
3020 const uint8_t *payload,
3022 unsigned long tcp_seqno,
3023 unsigned long tcp_ack,
3024 unsigned char tcp_ctl,
3026 size_t *_packet_len)
3028 uint8_t *base = NULL;
3029 uint8_t *buf = NULL;
3032 struct swrap_packet_frame *frame;
3036 union swrap_packet_ip *ip;
3038 union swrap_packet_payload *pay;
3041 size_t nonwire_len = sizeof(struct swrap_packet_frame);
3042 size_t wire_hdr_len = 0;
3043 size_t wire_len = 0;
3044 size_t ip_hdr_len = 0;
3045 size_t icmp_hdr_len = 0;
3046 size_t icmp_truncate_len = 0;
3047 uint8_t protocol = 0, icmp_protocol = 0;
3048 const struct sockaddr_in *src_in = NULL;
3049 const struct sockaddr_in *dest_in = NULL;
3051 const struct sockaddr_in6 *src_in6 = NULL;
3052 const struct sockaddr_in6 *dest_in6 = NULL;
3057 switch (src->sa_family) {
3059 src_in = (const struct sockaddr_in *)(const void *)src;
3060 dest_in = (const struct sockaddr_in *)(const void *)dest;
3061 src_port = src_in->sin_port;
3062 dest_port = dest_in->sin_port;
3063 ip_hdr_len = sizeof(i.ip->v4);
3067 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
3068 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
3069 src_port = src_in6->sin6_port;
3070 dest_port = dest_in6->sin6_port;
3071 ip_hdr_len = sizeof(i.ip->v6);
3078 switch (socket_type) {
3080 protocol = 0x06; /* TCP */
3081 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
3082 wire_len = wire_hdr_len + payload_len;
3086 protocol = 0x11; /* UDP */
3087 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
3088 wire_len = wire_hdr_len + payload_len;
3096 icmp_protocol = protocol;
3097 switch (src->sa_family) {
3099 protocol = 0x01; /* ICMPv4 */
3100 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
3104 protocol = 0x3A; /* ICMPv6 */
3105 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
3109 if (wire_len > 64 ) {
3110 icmp_truncate_len = wire_len - 64;
3112 wire_len += icmp_hdr_len;
3115 packet_len = nonwire_len + wire_len;
3116 alloc_len = packet_len;
3117 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
3118 alloc_len = SWRAP_PACKET_MIN_ALLOC;
3121 base = (uint8_t *)calloc(1, alloc_len);
3129 f.frame->seconds = tval->tv_sec;
3130 f.frame->micro_seconds = tval->tv_usec;
3131 f.frame->recorded_length = wire_len - icmp_truncate_len;
3132 f.frame->full_length = wire_len - icmp_truncate_len;
3134 buf += SWRAP_PACKET_FRAME_SIZE;
3137 switch (src->sa_family) {
3139 if (src_in == NULL || dest_in == NULL) {
3144 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3145 i.ip->v4.tos = 0x00;
3146 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
3147 i.ip->v4.identification = htons(0xFFFF);
3148 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3149 i.ip->v4.fragment = htons(0x0000);
3150 i.ip->v4.ttl = 0xFF;
3151 i.ip->v4.protocol = protocol;
3152 i.ip->v4.hdr_checksum = htons(0x0000);
3153 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
3154 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
3155 buf += SWRAP_PACKET_IP_V4_SIZE;
3159 if (src_in6 == NULL || dest_in6 == NULL) {
3164 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3165 i.ip->v6.flow_label_high = 0x00;
3166 i.ip->v6.flow_label_low = 0x0000;
3167 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3168 i.ip->v6.next_header = protocol;
3169 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
3170 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
3171 buf += SWRAP_PACKET_IP_V6_SIZE;
3177 pay = (union swrap_packet_payload *)(void *)buf;
3178 switch (src->sa_family) {
3180 pay->icmp4.type = 0x03; /* destination unreachable */
3181 pay->icmp4.code = 0x01; /* host unreachable */
3182 pay->icmp4.checksum = htons(0x0000);
3183 pay->icmp4.unused = htonl(0x00000000);
3185 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3187 /* set the ip header in the ICMP payload */
3189 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3190 i.ip->v4.tos = 0x00;
3191 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3192 i.ip->v4.identification = htons(0xFFFF);
3193 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3194 i.ip->v4.fragment = htons(0x0000);
3195 i.ip->v4.ttl = 0xFF;
3196 i.ip->v4.protocol = icmp_protocol;
3197 i.ip->v4.hdr_checksum = htons(0x0000);
3198 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3199 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3201 buf += SWRAP_PACKET_IP_V4_SIZE;
3203 src_port = dest_in->sin_port;
3204 dest_port = src_in->sin_port;
3208 pay->icmp6.type = 0x01; /* destination unreachable */
3209 pay->icmp6.code = 0x03; /* address unreachable */
3210 pay->icmp6.checksum = htons(0x0000);
3211 pay->icmp6.unused = htonl(0x00000000);
3212 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3214 /* set the ip header in the ICMP payload */
3216 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3217 i.ip->v6.flow_label_high = 0x00;
3218 i.ip->v6.flow_label_low = 0x0000;
3219 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3220 i.ip->v6.next_header = protocol;
3221 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3222 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3224 buf += SWRAP_PACKET_IP_V6_SIZE;
3226 src_port = dest_in6->sin6_port;
3227 dest_port = src_in6->sin6_port;
3233 pay = (union swrap_packet_payload *)(void *)buf;
3235 switch (socket_type) {
3237 pay->tcp.source_port = src_port;
3238 pay->tcp.dest_port = dest_port;
3239 pay->tcp.seq_num = htonl(tcp_seqno);
3240 pay->tcp.ack_num = htonl(tcp_ack);
3241 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3242 pay->tcp.control = tcp_ctl;
3243 pay->tcp.window = htons(0x7FFF);
3244 pay->tcp.checksum = htons(0x0000);
3245 pay->tcp.urg = htons(0x0000);
3246 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3251 pay->udp.source_port = src_port;
3252 pay->udp.dest_port = dest_port;
3253 pay->udp.length = htons(8 + payload_len);
3254 pay->udp.checksum = htons(0x0000);
3255 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3260 if (payload && payload_len > 0) {
3261 memcpy(buf, payload, payload_len);
3264 *_packet_len = packet_len - icmp_truncate_len;
3268 static int swrap_pcap_get_fd(const char *fname)
3276 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3278 struct swrap_file_hdr file_hdr;
3279 file_hdr.magic = 0xA1B2C3D4;
3280 file_hdr.version_major = 0x0002;
3281 file_hdr.version_minor = 0x0004;
3282 file_hdr.timezone = 0x00000000;
3283 file_hdr.sigfigs = 0x00000000;
3284 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3285 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3287 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3294 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3299 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3300 const struct sockaddr *addr,
3301 enum swrap_packet_type type,
3302 const void *buf, size_t len,
3305 const struct sockaddr *src_addr;
3306 const struct sockaddr *dest_addr;
3307 unsigned long tcp_seqno = 0;
3308 unsigned long tcp_ack = 0;
3309 unsigned char tcp_ctl = 0;
3310 int unreachable = 0;
3314 switch (si->family) {
3326 case SWRAP_CONNECT_SEND:
3327 if (si->type != SOCK_STREAM) {
3331 src_addr = &si->myname.sa.s;
3334 tcp_seqno = si->io.pck_snd;
3335 tcp_ack = si->io.pck_rcv;
3336 tcp_ctl = 0x02; /* SYN */
3338 si->io.pck_snd += 1;
3342 case SWRAP_CONNECT_RECV:
3343 if (si->type != SOCK_STREAM) {
3347 dest_addr = &si->myname.sa.s;
3350 tcp_seqno = si->io.pck_rcv;
3351 tcp_ack = si->io.pck_snd;
3352 tcp_ctl = 0x12; /** SYN,ACK */
3354 si->io.pck_rcv += 1;
3358 case SWRAP_CONNECT_UNREACH:
3359 if (si->type != SOCK_STREAM) {
3363 dest_addr = &si->myname.sa.s;
3366 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3367 tcp_seqno = si->io.pck_snd - 1;
3368 tcp_ack = si->io.pck_rcv;
3369 tcp_ctl = 0x02; /* SYN */
3374 case SWRAP_CONNECT_ACK:
3375 if (si->type != SOCK_STREAM) {
3379 src_addr = &si->myname.sa.s;
3382 tcp_seqno = si->io.pck_snd;
3383 tcp_ack = si->io.pck_rcv;
3384 tcp_ctl = 0x10; /* ACK */
3388 case SWRAP_ACCEPT_SEND:
3389 if (si->type != SOCK_STREAM) {
3393 dest_addr = &si->myname.sa.s;
3396 tcp_seqno = si->io.pck_rcv;
3397 tcp_ack = si->io.pck_snd;
3398 tcp_ctl = 0x02; /* SYN */
3400 si->io.pck_rcv += 1;
3404 case SWRAP_ACCEPT_RECV:
3405 if (si->type != SOCK_STREAM) {
3409 src_addr = &si->myname.sa.s;
3412 tcp_seqno = si->io.pck_snd;
3413 tcp_ack = si->io.pck_rcv;
3414 tcp_ctl = 0x12; /* SYN,ACK */
3416 si->io.pck_snd += 1;
3420 case SWRAP_ACCEPT_ACK:
3421 if (si->type != SOCK_STREAM) {
3425 dest_addr = &si->myname.sa.s;
3428 tcp_seqno = si->io.pck_rcv;
3429 tcp_ack = si->io.pck_snd;
3430 tcp_ctl = 0x10; /* ACK */
3435 src_addr = &si->myname.sa.s;
3436 dest_addr = &si->peername.sa.s;
3438 tcp_seqno = si->io.pck_snd;
3439 tcp_ack = si->io.pck_rcv;
3440 tcp_ctl = 0x18; /* PSH,ACK */
3442 si->io.pck_snd += len;
3446 case SWRAP_SEND_RST:
3447 dest_addr = &si->myname.sa.s;
3448 src_addr = &si->peername.sa.s;
3450 if (si->type == SOCK_DGRAM) {
3451 return swrap_pcap_marshall_packet(si,
3453 SWRAP_SENDTO_UNREACH,
3459 tcp_seqno = si->io.pck_rcv;
3460 tcp_ack = si->io.pck_snd;
3461 tcp_ctl = 0x14; /** RST,ACK */
3465 case SWRAP_PENDING_RST:
3466 dest_addr = &si->myname.sa.s;
3467 src_addr = &si->peername.sa.s;
3469 if (si->type == SOCK_DGRAM) {
3473 tcp_seqno = si->io.pck_rcv;
3474 tcp_ack = si->io.pck_snd;
3475 tcp_ctl = 0x14; /* RST,ACK */
3480 dest_addr = &si->myname.sa.s;
3481 src_addr = &si->peername.sa.s;
3483 tcp_seqno = si->io.pck_rcv;
3484 tcp_ack = si->io.pck_snd;
3485 tcp_ctl = 0x18; /* PSH,ACK */
3487 si->io.pck_rcv += len;
3491 case SWRAP_RECV_RST:
3492 dest_addr = &si->myname.sa.s;
3493 src_addr = &si->peername.sa.s;
3495 if (si->type == SOCK_DGRAM) {
3499 tcp_seqno = si->io.pck_rcv;
3500 tcp_ack = si->io.pck_snd;
3501 tcp_ctl = 0x14; /* RST,ACK */
3506 src_addr = &si->myname.sa.s;
3509 si->io.pck_snd += len;
3513 case SWRAP_SENDTO_UNREACH:
3514 dest_addr = &si->myname.sa.s;
3521 case SWRAP_RECVFROM:
3522 dest_addr = &si->myname.sa.s;
3525 si->io.pck_rcv += len;
3529 case SWRAP_CLOSE_SEND:
3530 if (si->type != SOCK_STREAM) {
3534 src_addr = &si->myname.sa.s;
3535 dest_addr = &si->peername.sa.s;
3537 tcp_seqno = si->io.pck_snd;
3538 tcp_ack = si->io.pck_rcv;
3539 tcp_ctl = 0x11; /* FIN, ACK */
3541 si->io.pck_snd += 1;
3545 case SWRAP_CLOSE_RECV:
3546 if (si->type != SOCK_STREAM) {
3550 dest_addr = &si->myname.sa.s;
3551 src_addr = &si->peername.sa.s;
3553 tcp_seqno = si->io.pck_rcv;
3554 tcp_ack = si->io.pck_snd;
3555 tcp_ctl = 0x11; /* FIN,ACK */
3557 si->io.pck_rcv += 1;
3561 case SWRAP_CLOSE_ACK:
3562 if (si->type != SOCK_STREAM) {
3566 src_addr = &si->myname.sa.s;
3567 dest_addr = &si->peername.sa.s;
3569 tcp_seqno = si->io.pck_snd;
3570 tcp_ack = si->io.pck_rcv;
3571 tcp_ctl = 0x10; /* ACK */
3578 swrapGetTimeOfDay(&tv);
3580 return swrap_pcap_packet_init(&tv,
3584 (const uint8_t *)buf,
3593 static void swrap_pcap_dump_packet(struct socket_info *si,
3594 const struct sockaddr *addr,
3595 enum swrap_packet_type type,
3596 const void *buf, size_t len)
3598 const char *file_name;
3600 size_t packet_len = 0;
3603 swrap_mutex_lock(&pcap_dump_mutex);
3605 file_name = swrap_pcap_init_file();
3610 packet = swrap_pcap_marshall_packet(si,
3616 if (packet == NULL) {
3620 fd = swrap_pcap_get_fd(file_name);
3622 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3631 swrap_mutex_unlock(&pcap_dump_mutex);
3634 /****************************************************************************
3636 ***************************************************************************/
3638 #ifdef HAVE_SIGNALFD
3639 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3643 rc = libc_signalfd(fd, mask, flags);
3645 swrap_remove_stale(fd);
3651 int signalfd(int fd, const sigset_t *mask, int flags)
3653 return swrap_signalfd(fd, mask, flags);
3657 /****************************************************************************
3659 ***************************************************************************/
3661 static int swrap_socket(int family, int type, int protocol)
3663 struct socket_info *si = NULL;
3664 struct socket_info _si = { 0 };
3667 int real_type = type;
3670 * Remove possible addition flags passed to socket() so
3671 * do not fail checking the type.
3672 * See https://lwn.net/Articles/281965/
3675 real_type &= ~SOCK_CLOEXEC;
3677 #ifdef SOCK_NONBLOCK
3678 real_type &= ~SOCK_NONBLOCK;
3681 if (!socket_wrapper_enabled()) {
3682 return libc_socket(family, type, protocol);
3693 #endif /* AF_NETLINK */
3696 #endif /* AF_PACKET */
3698 fd = libc_socket(family, type, protocol);
3700 /* Check if we have a stale fd and remove it */
3701 swrap_remove_stale(fd);
3702 SWRAP_LOG(SWRAP_LOG_TRACE,
3703 "Unix socket fd=%d",
3708 errno = EAFNOSUPPORT;
3712 switch (real_type) {
3718 errno = EPROTONOSUPPORT;
3726 if (real_type == SOCK_STREAM) {
3731 if (real_type == SOCK_DGRAM) {
3736 errno = EPROTONOSUPPORT;
3741 * We must call libc_socket with type, from the caller, not the version
3742 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3744 fd = libc_socket(AF_UNIX, type, 0);
3750 /* Check if we have a stale fd and remove it */
3751 swrap_remove_stale(fd);
3754 si->family = family;
3756 /* however, the rest of the socket_wrapper code expects just
3757 * the type, not the flags */
3758 si->type = real_type;
3759 si->protocol = protocol;
3762 * Setup myname so getsockname() can succeed to find out the socket
3765 switch(si->family) {
3767 struct sockaddr_in sin = {
3768 .sin_family = AF_INET,
3771 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3772 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3777 struct sockaddr_in6 sin6 = {
3778 .sin6_family = AF_INET6,
3781 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3782 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3791 ret = swrap_create_socket(si, fd);
3793 int saved_errno = errno;
3795 errno = saved_errno;
3799 SWRAP_LOG(SWRAP_LOG_TRACE,
3800 "Created %s socket for protocol %s, fd=%d",
3801 family == AF_INET ? "IPv4" : "IPv6",
3802 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3808 int socket(int family, int type, int protocol)
3810 return swrap_socket(family, type, protocol);
3813 /****************************************************************************
3815 ***************************************************************************/
3817 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3821 rc = libc_socketpair(family, type, protocol, sv);
3823 swrap_remove_stale(sv[0]);
3824 swrap_remove_stale(sv[1]);
3830 int socketpair(int family, int type, int protocol, int sv[2])
3832 return swrap_socketpair(family, type, protocol, sv);
3835 /****************************************************************************
3837 ***************************************************************************/
3839 #ifdef HAVE_TIMERFD_CREATE
3840 static int swrap_timerfd_create(int clockid, int flags)
3844 fd = libc_timerfd_create(clockid, flags);
3846 swrap_remove_stale(fd);
3852 int timerfd_create(int clockid, int flags)
3854 return swrap_timerfd_create(clockid, flags);
3858 /****************************************************************************
3860 ***************************************************************************/
3862 static int swrap_pipe(int pipefd[2])
3866 rc = libc_pipe(pipefd);
3868 swrap_remove_stale(pipefd[0]);
3869 swrap_remove_stale(pipefd[1]);
3875 int pipe(int pipefd[2])
3877 return swrap_pipe(pipefd);
3880 /****************************************************************************
3882 ***************************************************************************/
3884 static int swrap_accept(int s,
3885 struct sockaddr *addr,
3889 struct socket_info *parent_si, *child_si;
3890 struct socket_info new_si = { 0 };
3893 struct swrap_address un_addr = {
3894 .sa_socklen = sizeof(struct sockaddr_un),
3896 struct swrap_address un_my_addr = {
3897 .sa_socklen = sizeof(struct sockaddr_un),
3899 struct swrap_address in_addr = {
3900 .sa_socklen = sizeof(struct sockaddr_storage),
3902 struct swrap_address in_my_addr = {
3903 .sa_socklen = sizeof(struct sockaddr_storage),
3907 parent_si = find_socket_info(s);
3910 return libc_accept4(s, addr, addrlen, flags);
3913 return libc_accept(s, addr, addrlen);
3919 * prevent parent_si from being altered / closed
3922 SWRAP_LOCK_SI(parent_si);
3925 * assume out sockaddr have the same size as the in parent
3928 in_addr.sa_socklen = socket_length(parent_si->family);
3929 if (in_addr.sa_socklen <= 0) {
3930 SWRAP_UNLOCK_SI(parent_si);
3935 SWRAP_UNLOCK_SI(parent_si);
3938 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3941 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3944 int saved_errno = errno;
3945 if (saved_errno == ENOTSOCK) {
3946 /* Remove stale fds */
3947 swrap_remove_stale(s);
3949 errno = saved_errno;
3955 /* Check if we have a stale fd and remove it */
3956 swrap_remove_stale(fd);
3958 if (un_addr.sa.un.sun_path[0] == '\0') {
3960 * FreeBSD seems to have a problem where
3961 * accept4() on the unix socket doesn't
3962 * ECONNABORTED for already disconnected connections.
3964 * Let's try libc_getpeername() to get the peer address
3965 * as a fallback, but it'll likely return ENOTCONN,
3966 * which we have to map to ECONNABORTED.
3968 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3969 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3971 int saved_errno = errno;
3973 if (saved_errno == ENOTCONN) {
3975 * If the connection is already disconnected
3976 * we should return ECONNABORTED.
3978 saved_errno = ECONNABORTED;
3980 errno = saved_errno;
3985 ret = libc_getsockname(fd,
3987 &un_my_addr.sa_socklen);
3989 int saved_errno = errno;
3991 if (saved_errno == ENOTCONN) {
3993 * If the connection is already disconnected
3994 * we should return ECONNABORTED.
3996 saved_errno = ECONNABORTED;
3998 errno = saved_errno;
4002 SWRAP_LOCK_SI(parent_si);
4004 ret = sockaddr_convert_from_un(parent_si,
4009 &in_addr.sa_socklen);
4011 int saved_errno = errno;
4012 SWRAP_UNLOCK_SI(parent_si);
4014 errno = saved_errno;
4020 child_si->family = parent_si->family;
4021 child_si->type = parent_si->type;
4022 child_si->protocol = parent_si->protocol;
4023 child_si->bound = 1;
4024 child_si->is_server = 1;
4025 child_si->connected = 1;
4027 SWRAP_UNLOCK_SI(parent_si);
4029 child_si->peername = (struct swrap_address) {
4030 .sa_socklen = in_addr.sa_socklen,
4032 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
4034 if (addr != NULL && addrlen != NULL) {
4035 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
4037 memcpy(addr, &in_addr.sa.ss, copy_len);
4039 *addrlen = in_addr.sa_socklen;
4042 ret = sockaddr_convert_from_un(child_si,
4044 un_my_addr.sa_socklen,
4047 &in_my_addr.sa_socklen);
4049 int saved_errno = errno;
4051 errno = saved_errno;
4055 SWRAP_LOG(SWRAP_LOG_TRACE,
4056 "accept() path=%s, fd=%d",
4057 un_my_addr.sa.un.sun_path, s);
4059 child_si->myname = (struct swrap_address) {
4060 .sa_socklen = in_my_addr.sa_socklen,
4062 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
4064 idx = swrap_create_socket(&new_si, fd);
4066 int saved_errno = errno;
4068 errno = saved_errno;
4073 struct socket_info *si = swrap_get_socket_info(idx);
4076 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
4077 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
4078 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
4079 SWRAP_UNLOCK_SI(si);
4086 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
4088 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
4092 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4093 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
4095 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
4098 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
4101 static int autobind_start_init;
4102 static int autobind_start;
4104 /* using sendto() or connect() on an unbound socket would give the
4105 recipient no way to reply, as unlike UDP and TCP, a unix domain
4106 socket can't auto-assign ephemeral port numbers, so we need to
4108 Note: this might change the family from ipv6 to ipv4
4110 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
4112 struct swrap_address un_addr = {
4113 .sa_socklen = sizeof(struct sockaddr_un),
4119 char *swrap_dir = NULL;
4121 swrap_mutex_lock(&autobind_start_mutex);
4123 if (autobind_start_init != 1) {
4124 autobind_start_init = 1;
4125 autobind_start = getpid();
4126 autobind_start %= 50000;
4127 autobind_start += 10000;
4130 un_addr.sa.un.sun_family = AF_UNIX;
4134 struct sockaddr_in in;
4138 type = SOCKET_TYPE_CHAR_TCP;
4141 type = SOCKET_TYPE_CHAR_UDP;
4144 errno = ESOCKTNOSUPPORT;
4149 memset(&in, 0, sizeof(in));
4150 in.sin_family = AF_INET;
4151 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
4152 socket_wrapper_default_iface()));
4154 si->myname = (struct swrap_address) {
4155 .sa_socklen = sizeof(in),
4157 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
4162 struct sockaddr_in6 in6;
4164 if (si->family != family) {
4165 errno = ENETUNREACH;
4172 type = SOCKET_TYPE_CHAR_TCP_V6;
4175 type = SOCKET_TYPE_CHAR_UDP_V6;
4178 errno = ESOCKTNOSUPPORT;
4183 memset(&in6, 0, sizeof(in6));
4184 in6.sin6_family = AF_INET6;
4185 in6.sin6_addr = *swrap_ipv6();
4186 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4188 si->myname = (struct swrap_address) {
4189 .sa_socklen = sizeof(in6),
4191 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4196 errno = ESOCKTNOSUPPORT;
4201 if (autobind_start > 60000) {
4202 autobind_start = 10000;
4205 swrap_dir = socket_wrapper_dir();
4206 if (swrap_dir == NULL) {
4212 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4213 port = autobind_start + i;
4214 swrap_un_path(&un_addr.sa.un,
4217 socket_wrapper_default_iface(),
4220 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4222 if (errno == EALREADY || errno == EADDRINUSE) {
4228 si->un_addr = un_addr.sa.un;
4231 autobind_start = port + 1;
4234 if (i == SOCKET_MAX_SOCKETS) {
4235 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4236 "interface "SOCKET_FORMAT,
4239 socket_wrapper_default_iface(),
4246 si->family = family;
4247 set_port(si->family, port, &si->myname);
4252 SAFE_FREE(swrap_dir);
4253 swrap_mutex_unlock(&autobind_start_mutex);
4257 /****************************************************************************
4259 ***************************************************************************/
4261 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4265 struct swrap_address un_addr = {
4266 .sa_socklen = sizeof(struct sockaddr_un),
4268 struct socket_info *si = find_socket_info(s);
4269 struct swrap_sockaddr_buf buf = {};
4273 return libc_connect(s, serv_addr, addrlen);
4278 if (si->bound == 0) {
4279 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4285 if (si->family != serv_addr->sa_family) {
4286 SWRAP_LOG(SWRAP_LOG_ERROR,
4287 "called for fd=%d (family=%d) called with invalid family=%d",
4288 s, si->family, serv_addr->sa_family);
4294 ret = sockaddr_convert_to_un(si, serv_addr,
4295 addrlen, &un_addr.sa.un, 0, &bcast);
4301 errno = ENETUNREACH;
4306 if (si->type == SOCK_DGRAM) {
4307 si->defer_connect = 1;
4310 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4312 ret = libc_connect(s,
4314 un_addr.sa_socklen);
4317 SWRAP_LOG(SWRAP_LOG_TRACE,
4318 "connect(%s) path=%s, fd=%d",
4319 swrap_sockaddr_string(&buf, serv_addr),
4320 un_addr.sa.un.sun_path, s);
4323 /* to give better errors */
4324 if (ret == -1 && errno == ENOENT) {
4325 errno = EHOSTUNREACH;
4329 si->peername = (struct swrap_address) {
4330 .sa_socklen = addrlen,
4333 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4337 * When we connect() on a socket than we have to bind the
4338 * outgoing connection on the interface we use for the
4339 * transport. We already bound it on the right interface
4340 * but here we have to update the name so getsockname()
4341 * returns correct information.
4343 if (si->bindname.sa_socklen > 0) {
4344 si->myname = (struct swrap_address) {
4345 .sa_socklen = si->bindname.sa_socklen,
4348 memcpy(&si->myname.sa.ss,
4349 &si->bindname.sa.ss,
4350 si->bindname.sa_socklen);
4352 /* Cleanup bindname */
4353 si->bindname = (struct swrap_address) {
4358 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4359 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4361 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4365 SWRAP_UNLOCK_SI(si);
4369 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4371 return swrap_connect(s, serv_addr, addrlen);
4374 /****************************************************************************
4376 ***************************************************************************/
4378 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4381 struct swrap_address un_addr = {
4382 .sa_socklen = sizeof(struct sockaddr_un),
4384 struct socket_info *si = find_socket_info(s);
4385 struct swrap_sockaddr_buf buf = {};
4386 int ret_errno = errno;
4393 return libc_bind(s, myaddr, addrlen);
4398 switch (si->family) {
4400 const struct sockaddr_in *sin;
4401 if (addrlen < sizeof(struct sockaddr_in)) {
4402 bind_error = EINVAL;
4406 sin = (const struct sockaddr_in *)(const void *)myaddr;
4408 if (sin->sin_family != AF_INET) {
4409 bind_error = EAFNOSUPPORT;
4412 /* special case for AF_UNSPEC */
4413 if (sin->sin_family == AF_UNSPEC &&
4414 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4423 const struct sockaddr_in6 *sin6;
4424 if (addrlen < sizeof(struct sockaddr_in6)) {
4425 bind_error = EINVAL;
4429 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4431 if (sin6->sin6_family != AF_INET6) {
4432 bind_error = EAFNOSUPPORT;
4439 bind_error = EINVAL;
4443 if (bind_error != 0) {
4444 ret_errno = bind_error;
4450 in_use = check_addr_port_in_use(myaddr, addrlen);
4458 si->myname.sa_socklen = addrlen;
4459 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4461 ret = sockaddr_convert_to_un(si,
4472 unlink(un_addr.sa.un.sun_path);
4474 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4479 SWRAP_LOG(SWRAP_LOG_TRACE,
4480 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4481 swrap_sockaddr_string(&buf, myaddr),
4482 un_addr.sa.un.sun_path, s, ret, ret_errno);
4489 SWRAP_UNLOCK_SI(si);
4494 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4496 return swrap_bind(s, myaddr, addrlen);
4499 /****************************************************************************
4501 ***************************************************************************/
4503 #ifdef HAVE_BINDRESVPORT
4504 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4506 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4508 struct swrap_address myaddr = {
4509 .sa_socklen = sizeof(struct sockaddr_storage),
4512 static uint16_t port;
4517 #define SWRAP_STARTPORT 600
4518 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4519 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4522 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4526 salen = myaddr.sa_socklen;
4529 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4535 memset(&myaddr.sa.ss, 0, salen);
4540 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4543 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4545 salen = sizeof(struct sockaddr_in);
4546 sinp->sin_port = htons(port);
4550 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4552 salen = sizeof(struct sockaddr_in6);
4553 sin6p->sin6_port = htons(port);
4557 errno = EAFNOSUPPORT;
4562 if (port > SWRAP_ENDPORT) {
4563 port = SWRAP_STARTPORT;
4566 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4567 if (rc == 0 || errno != EADDRINUSE) {
4575 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4577 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4581 /****************************************************************************
4583 ***************************************************************************/
4585 static int swrap_listen(int s, int backlog)
4588 struct socket_info *si = find_socket_info(s);
4591 return libc_listen(s, backlog);
4596 if (si->bound == 0) {
4597 ret = swrap_auto_bind(s, si, si->family);
4604 ret = libc_listen(s, backlog);
4610 SWRAP_UNLOCK_SI(si);
4615 int listen(int s, int backlog)
4617 return swrap_listen(s, backlog);
4620 /****************************************************************************
4622 ***************************************************************************/
4624 static FILE *swrap_fopen(const char *name, const char *mode)
4628 fp = libc_fopen(name, mode);
4630 int fd = fileno(fp);
4632 swrap_remove_stale(fd);
4638 #undef fopen /* Needed for LFS handling */
4639 FILE *fopen(const char *name, const char *mode)
4641 return swrap_fopen(name, mode);
4644 /****************************************************************************
4646 ***************************************************************************/
4649 static FILE *swrap_fopen64(const char *name, const char *mode)
4653 fp = libc_fopen64(name, mode);
4655 int fd = fileno(fp);
4657 swrap_remove_stale(fd);
4663 FILE *fopen64(const char *name, const char *mode)
4665 return swrap_fopen64(name, mode);
4667 #endif /* HAVE_FOPEN64 */
4669 /****************************************************************************
4671 ***************************************************************************/
4673 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4677 ret = libc_vopen(pathname, flags, ap);
4680 * There are methods for closing descriptors (libc-internal code
4681 * paths, direct syscalls) which close descriptors in ways that
4682 * we can't intercept, so try to recover when we notice that
4685 swrap_remove_stale(ret);
4690 #undef open /* Needed for LFS handling */
4691 int open(const char *pathname, int flags, ...)
4696 va_start(ap, flags);
4697 fd = swrap_vopen(pathname, flags, ap);
4703 /****************************************************************************
4705 ***************************************************************************/
4708 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4712 ret = libc_vopen64(pathname, flags, ap);
4715 * There are methods for closing descriptors (libc-internal code
4716 * paths, direct syscalls) which close descriptors in ways that
4717 * we can't intercept, so try to recover when we notice that
4720 swrap_remove_stale(ret);
4725 int open64(const char *pathname, int flags, ...)
4730 va_start(ap, flags);
4731 fd = swrap_vopen64(pathname, flags, ap);
4736 #endif /* HAVE_OPEN64 */
4738 /****************************************************************************
4740 ***************************************************************************/
4742 #ifdef HAVE_OPENAT64
4744 swrap_vopenat64(int dirfd, const char *pathname, int flags, va_list ap)
4748 ret = libc_vopenat64(dirfd, pathname, flags, ap);
4751 * There are methods for closing descriptors (libc-internal code
4752 * paths, direct syscalls) which close descriptors in ways that
4753 * we can't intercept, so try to recover when we notice that
4756 swrap_remove_stale(ret);
4761 int openat64(int dirfd, const char *pathname, int flags, ...)
4766 va_start(ap, flags);
4767 fd = swrap_vopenat64(dirfd, pathname, flags, ap);
4772 #endif /* HAVE_OPENAT64 */
4774 /****************************************************************************
4776 ***************************************************************************/
4778 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4782 ret = libc_vopenat(dirfd, path, flags, ap);
4785 * There are methods for closing descriptors (libc-internal code
4786 * paths, direct syscalls) which close descriptors in ways that
4787 * we can't intercept, so try to recover when we notice that
4790 swrap_remove_stale(ret);
4796 #undef openat /* Needed for LFS handling */
4797 int openat(int dirfd, const char *path, int flags, ...)
4802 va_start(ap, flags);
4803 fd = swrap_vopenat(dirfd, path, flags, ap);
4809 /****************************************************************************
4811 ***************************************************************************/
4813 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4815 struct socket_info *si = find_socket_info(s);
4820 return libc_getpeername(s, name, addrlen);
4825 if (si->peername.sa_socklen == 0)
4831 len = MIN(*addrlen, si->peername.sa_socklen);
4837 memcpy(name, &si->peername.sa.ss, len);
4838 *addrlen = si->peername.sa_socklen;
4842 SWRAP_UNLOCK_SI(si);
4847 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4848 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4850 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4853 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4856 /****************************************************************************
4858 ***************************************************************************/
4860 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4862 struct socket_info *si = find_socket_info(s);
4867 return libc_getsockname(s, name, addrlen);
4872 len = MIN(*addrlen, si->myname.sa_socklen);
4878 memcpy(name, &si->myname.sa.ss, len);
4879 *addrlen = si->myname.sa_socklen;
4883 SWRAP_UNLOCK_SI(si);
4888 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4889 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4891 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4894 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4897 /****************************************************************************
4899 ***************************************************************************/
4902 # ifdef SO_PROTOTYPE /* The Solaris name */
4903 # define SO_PROTOCOL SO_PROTOTYPE
4904 # endif /* SO_PROTOTYPE */
4905 #endif /* SO_PROTOCOL */
4907 static int swrap_getsockopt(int s, int level, int optname,
4908 void *optval, socklen_t *optlen)
4910 struct socket_info *si = find_socket_info(s);
4914 return libc_getsockopt(s,
4923 if (level == SOL_SOCKET) {
4927 if (optval == NULL || optlen == NULL ||
4928 *optlen < (socklen_t)sizeof(int)) {
4934 *optlen = sizeof(int);
4935 *(int *)optval = si->family;
4938 #endif /* SO_DOMAIN */
4942 if (optval == NULL || optlen == NULL ||
4943 *optlen < (socklen_t)sizeof(int)) {
4949 *optlen = sizeof(int);
4950 *(int *)optval = si->protocol;
4953 #endif /* SO_PROTOCOL */
4955 if (optval == NULL || optlen == NULL ||
4956 *optlen < (socklen_t)sizeof(int)) {
4962 *optlen = sizeof(int);
4963 *(int *)optval = si->type;
4967 ret = libc_getsockopt(s,
4974 } else if (level == IPPROTO_TCP) {
4979 * This enables sending packets directly out over TCP.
4980 * As a unix socket is doing that any way, report it as
4983 if (optval == NULL || optlen == NULL ||
4984 *optlen < (socklen_t)sizeof(int)) {
4990 *optlen = sizeof(int);
4991 *(int *)optval = si->tcp_nodelay;
4995 #endif /* TCP_NODELAY */
4998 struct tcp_info info;
4999 socklen_t ilen = sizeof(info);
5001 #ifdef HAVE_NETINET_TCP_FSM_H
5002 /* This is FreeBSD */
5003 # define __TCP_LISTEN TCPS_LISTEN
5004 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
5005 # define __TCP_CLOSE TCPS_CLOSED
5008 # define __TCP_LISTEN TCP_LISTEN
5009 # define __TCP_ESTABLISHED TCP_ESTABLISHED
5010 # define __TCP_CLOSE TCP_CLOSE
5014 if (si->listening) {
5015 info.tcpi_state = __TCP_LISTEN;
5016 } else if (si->connected) {
5018 * For now we just fake a few values
5019 * supported both by FreeBSD and Linux
5021 info.tcpi_state = __TCP_ESTABLISHED;
5022 info.tcpi_rto = 200000; /* 200 msec */
5023 info.tcpi_rtt = 5000; /* 5 msec */
5024 info.tcpi_rttvar = 5000; /* 5 msec */
5026 info.tcpi_state = __TCP_CLOSE;
5027 info.tcpi_rto = 1000000; /* 1 sec */
5029 info.tcpi_rttvar = 250000; /* 250 msec */
5032 if (optval == NULL || optlen == NULL ||
5033 *optlen < (socklen_t)ilen) {
5040 memcpy(optval, &info, ilen);
5045 #endif /* TCP_INFO */
5051 errno = ENOPROTOOPT;
5055 SWRAP_UNLOCK_SI(si);
5059 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5060 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
5062 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
5065 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
5068 /****************************************************************************
5070 ***************************************************************************/
5072 static int swrap_setsockopt(int s, int level, int optname,
5073 const void *optval, socklen_t optlen)
5075 struct socket_info *si = find_socket_info(s);
5079 return libc_setsockopt(s,
5086 if (level == SOL_SOCKET) {
5087 return libc_setsockopt(s,
5096 if (level == IPPROTO_TCP) {
5103 * This enables sending packets directly out over TCP.
5104 * A unix socket is doing that any way.
5106 if (optval == NULL || optlen == 0 ||
5107 optlen < (socklen_t)sizeof(int)) {
5113 i = *discard_const_p(int, optval);
5114 if (i != 0 && i != 1) {
5119 si->tcp_nodelay = i;
5124 #endif /* TCP_NODELAY */
5130 switch (si->family) {
5132 if (level == IPPROTO_IP) {
5134 if (optname == IP_PKTINFO) {
5135 si->pktinfo = AF_INET;
5137 #endif /* IP_PKTINFO */
5143 if (level == IPPROTO_IPV6) {
5144 #ifdef IPV6_RECVPKTINFO
5145 if (optname == IPV6_RECVPKTINFO) {
5146 si->pktinfo = AF_INET6;
5148 #endif /* IPV6_PKTINFO */
5154 errno = ENOPROTOOPT;
5160 SWRAP_UNLOCK_SI(si);
5164 int setsockopt(int s, int level, int optname,
5165 const void *optval, socklen_t optlen)
5167 return swrap_setsockopt(s, level, optname, optval, optlen);
5170 /****************************************************************************
5172 ***************************************************************************/
5174 static int swrap_vioctl(int s, unsigned long int r, va_list va)
5176 struct socket_info *si = find_socket_info(s);
5178 int *value_ptr = NULL;
5182 return libc_vioctl(s, r, va);
5189 rc = libc_vioctl(s, r, va);
5194 value_ptr = ((int *)va_arg(ap, int *));
5197 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
5198 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5199 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
5200 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5205 /* this is FreeBSD */
5206 FALL_THROUGH; /* to TIOCOUTQ */
5207 #endif /* FIONWRITE */
5208 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
5210 * This may return more bytes then the application
5211 * sent into the socket, for tcp it should
5212 * return the number of unacked bytes.
5214 * On AF_UNIX, all bytes are immediately acked!
5217 value_ptr = ((int *)va_arg(ap, int *));
5225 SWRAP_UNLOCK_SI(si);
5229 #ifdef HAVE_IOCTL_INT
5230 int ioctl(int s, int r, ...)
5232 int ioctl(int s, unsigned long int r, ...)
5240 rc = swrap_vioctl(s, (unsigned long int) r, va);
5251 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5254 # ifdef _ALIGN /* BSD */
5255 #define CMSG_ALIGN _ALIGN
5257 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5258 # endif /* _ALIGN */
5259 #endif /* CMSG_ALIGN */
5262 * @brief Add a cmsghdr to a msghdr.
5264 * This is an function to add any type of cmsghdr. It will operate on the
5265 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5266 * the buffer position after the added cmsg element. Hence, this function is
5267 * intended to be used with an intermediate msghdr and not on the original
5268 * one handed in by the client.
5270 * @param[in] msg The msghdr to which to add the cmsg.
5272 * @param[in] level The cmsg level to set.
5274 * @param[in] type The cmsg type to set.
5276 * @param[in] data The cmsg data to set.
5278 * @param[in] len the length of the data to set.
5280 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5286 size_t cmlen = CMSG_LEN(len);
5287 size_t cmspace = CMSG_SPACE(len);
5288 uint8_t cmbuf[cmspace];
5289 void *cast_ptr = (void *)cmbuf;
5290 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5293 memset(cmbuf, 0, cmspace);
5295 if (msg->msg_controllen < cmlen) {
5296 cmlen = msg->msg_controllen;
5297 msg->msg_flags |= MSG_CTRUNC;
5300 if (msg->msg_controllen < cmspace) {
5301 cmspace = msg->msg_controllen;
5305 * We copy the full input data into an intermediate cmsghdr first
5306 * in order to more easily cope with truncation.
5308 cm->cmsg_len = cmlen;
5309 cm->cmsg_level = level;
5310 cm->cmsg_type = type;
5311 memcpy(CMSG_DATA(cm), data, len);
5314 * We now copy the possibly truncated buffer.
5315 * We copy cmlen bytes, but consume cmspace bytes,
5316 * leaving the possible padding uninitialiazed.
5318 p = (uint8_t *)msg->msg_control;
5319 memcpy(p, cm, cmlen);
5321 msg->msg_control = p;
5322 msg->msg_controllen -= cmspace;
5327 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5330 /* Add packet info */
5331 switch (si->pktinfo) {
5332 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5334 struct sockaddr_in *sin;
5335 #if defined(HAVE_STRUCT_IN_PKTINFO)
5336 struct in_pktinfo pkt;
5337 #elif defined(IP_RECVDSTADDR)
5341 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5342 sin = &si->bindname.sa.in;
5344 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5347 sin = &si->myname.sa.in;
5352 #if defined(HAVE_STRUCT_IN_PKTINFO)
5353 pkt.ipi_ifindex = socket_wrapper_default_iface();
5354 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5355 #elif defined(IP_RECVDSTADDR)
5356 pkt = sin->sin_addr;
5359 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5364 #endif /* IP_PKTINFO */
5365 #if defined(HAVE_IPV6)
5367 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5368 struct sockaddr_in6 *sin6;
5369 struct in6_pktinfo pkt6;
5371 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5372 sin6 = &si->bindname.sa.in6;
5374 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5377 sin6 = &si->myname.sa.in6;
5382 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5383 pkt6.ipi6_addr = sin6->sin6_addr;
5385 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5386 &pkt6, sizeof(pkt6));
5387 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5391 #endif /* IPV6_PKTINFO */
5399 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5400 struct msghdr *omsg)
5404 if (si->pktinfo > 0) {
5405 rc = swrap_msghdr_add_pktinfo(si, omsg);
5411 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5413 size_t *cm_data_space);
5414 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5416 size_t *cm_data_space);
5417 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5419 size_t *cm_data_space);
5421 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5423 size_t *cm_data_space)
5425 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5426 struct cmsghdr *cmsg;
5430 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5434 for (cmsg = CMSG_FIRSTHDR(msg);
5436 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5437 switch (cmsg->cmsg_level) {
5439 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5444 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5449 rc = swrap_sendmsg_copy_cmsg(cmsg,
5455 int saved_errno = errno;
5456 SAFE_FREE(*cm_data);
5458 errno = saved_errno;
5466 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5468 size_t *cm_data_space)
5473 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5475 p = realloc((*cm_data), cmspace);
5481 p = (*cm_data) + (*cm_data_space);
5482 *cm_data_space = cmspace;
5484 memcpy(p, cmsg, cmsg->cmsg_len);
5489 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5491 size_t *cm_data_space);
5494 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5496 size_t *cm_data_space)
5500 switch(cmsg->cmsg_type) {
5503 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5510 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5522 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5524 size_t *cm_data_space)
5526 (void)cmsg; /* unused */
5527 (void)cm_data; /* unused */
5528 (void)cm_data_space; /* unused */
5531 * Passing a IP pktinfo to a unix socket might be rejected by the
5532 * Kernel, at least on FreeBSD. So skip this cmsg.
5537 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5539 size_t *cm_data_space)
5543 switch (cmsg->cmsg_type) {
5545 SWRAP_LOG(SWRAP_LOG_TRACE,
5546 "Ignoring SCM_RIGHTS on inet socket!");
5549 #ifdef SCM_CREDENTIALS
5550 case SCM_CREDENTIALS:
5551 SWRAP_LOG(SWRAP_LOG_TRACE,
5552 "Ignoring SCM_CREDENTIALS on inet socket!");
5555 #endif /* SCM_CREDENTIALS */
5557 rc = swrap_sendmsg_copy_cmsg(cmsg,
5566 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5569 * We only allow up to 6 fds at a time
5570 * as that's more than enough for Samba
5571 * and it means we can keep the logic simple
5572 * and work with fixed size arrays.
5574 * We also keep sizeof(struct swrap_unix_scm_rights)
5575 * under PIPE_BUF (4096) in order to allow a non-blocking
5576 * write into the pipe.
5579 #define PIPE_BUF 4096
5581 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5582 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5583 struct swrap_unix_scm_rights_payload {
5585 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5586 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5588 struct swrap_unix_scm_rights {
5590 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5591 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5593 uint32_t payload_size;
5594 struct swrap_unix_scm_rights_payload payload;
5597 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5599 int saved_errno = errno;
5602 for (i = 0; i < num; i++) {
5603 struct socket_info *si = array[i];
5609 swrap_dec_refcount(si);
5610 if (si->fd_passed > 0) {
5613 SWRAP_UNLOCK_SI(si);
5617 errno = saved_errno;
5620 static void swrap_undo_si_idx_array(size_t num, int *array)
5622 int saved_errno = errno;
5625 swrap_mutex_lock(&first_free_mutex);
5627 for (i = 0; i < num; i++) {
5628 struct socket_info *si = NULL;
5630 if (array[i] == -1) {
5634 si = swrap_get_socket_info(array[i]);
5640 swrap_dec_refcount(si);
5641 SWRAP_UNLOCK_SI(si);
5643 swrap_set_next_free(si, first_free);
5644 first_free = array[i];
5648 swrap_mutex_unlock(&first_free_mutex);
5649 errno = saved_errno;
5652 static void swrap_close_fd_array(size_t num, const int *array)
5654 int saved_errno = errno;
5657 for (i = 0; i < num; i++) {
5658 if (array[i] == -1) {
5661 libc_close(array[i]);
5664 errno = saved_errno;
5672 union __swrap_cmsghdr {
5674 struct cmsghdr *cmsg;
5677 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5679 size_t *cm_data_space,
5680 int *scm_rights_pipe_fd)
5682 struct swrap_unix_scm_rights info;
5683 struct swrap_unix_scm_rights_payload *payload = NULL;
5684 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5685 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5686 size_t info_idx = 0;
5689 union __swrap_fds __fds_in = { .p = NULL, };
5690 const int *fds_in = NULL;
5692 size_t size_fds_out;
5693 union __swrap_fds __fds_out = { .p = NULL, };
5694 int *fds_out = NULL;
5697 size_t new_cm_data_space;
5698 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5699 struct cmsghdr *new_cmsg = NULL;
5702 int pipefd[2] = { -1, -1 };
5707 * We pass this a buffer to the kernel make sure any padding
5711 info.magic = swrap_unix_scm_right_magic;
5712 memcpy(info.package_name,
5713 SOCKET_WRAPPER_PACKAGE,
5714 sizeof(info.package_name));
5715 memcpy(info.package_version,
5716 SOCKET_WRAPPER_VERSION,
5717 sizeof(info.package_version));
5718 info.full_size = sizeof(info);
5719 info.payload_size = sizeof(info.payload);
5720 payload = &info.payload;
5722 if (*scm_rights_pipe_fd != -1) {
5723 SWRAP_LOG(SWRAP_LOG_ERROR,
5724 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5729 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5730 SWRAP_LOG(SWRAP_LOG_ERROR,
5731 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5732 (size_t)cmsg->cmsg_len,
5737 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5738 if ((size_fds_in % sizeof(int)) != 0) {
5739 SWRAP_LOG(SWRAP_LOG_ERROR,
5740 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5741 (size_t)cmsg->cmsg_len,
5747 num_fds_in = size_fds_in / sizeof(int);
5748 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5749 SWRAP_LOG(SWRAP_LOG_ERROR,
5750 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5752 "SWRAP_MAX_PASSED_FDS(%zu)",
5753 (size_t)cmsg->cmsg_len,
5756 SWRAP_MAX_PASSED_FDS);
5760 if (num_fds_in == 0) {
5761 SWRAP_LOG(SWRAP_LOG_ERROR,
5762 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5764 (size_t)cmsg->cmsg_len,
5770 __fds_in.p = CMSG_DATA(cmsg);
5771 fds_in = __fds_in.fds;
5772 num_fds_out = num_fds_in + 1;
5774 SWRAP_LOG(SWRAP_LOG_TRACE,
5775 "num_fds_in=%zu num_fds_out=%zu",
5776 num_fds_in, num_fds_out);
5778 size_fds_out = sizeof(int) * num_fds_out;
5779 cmsg_len = CMSG_LEN(size_fds_out);
5780 cmsg_space = CMSG_SPACE(size_fds_out);
5782 new_cm_data_space = *cm_data_space + cmsg_space;
5784 p = realloc((*cm_data), new_cm_data_space);
5789 p = (*cm_data) + (*cm_data_space);
5790 memset(p, 0, cmsg_space);
5792 new_cmsg = __new_cmsg.cmsg;
5794 __fds_out.p = CMSG_DATA(new_cmsg);
5795 fds_out = __fds_out.fds;
5796 memcpy(fds_out, fds_in, size_fds_in);
5797 new_cmsg->cmsg_len = cmsg->cmsg_len;
5799 for (i = 0; i < num_fds_in; i++) {
5802 payload->idxs[i] = -1;
5803 payload->num_idxs++;
5805 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5806 if (si_idx_array[i] == -1) {
5810 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5811 if (si_array[i] == NULL) {
5812 SWRAP_LOG(SWRAP_LOG_ERROR,
5813 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5814 i, fds_in[i], i, si_idx_array[i]);
5819 for (j = 0; j < i; j++) {
5820 if (si_array[j] == si_array[i]) {
5821 payload->idxs[i] = payload->idxs[j];
5825 if (payload->idxs[i] == -1) {
5826 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5827 SWRAP_LOG(SWRAP_LOG_ERROR,
5828 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5829 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5830 i, fds_in[i], i, si_idx_array[i],
5832 SWRAP_MAX_PASSED_SOCKET_INFO);
5836 payload->idxs[i] = info_idx;
5842 for (i = 0; i < num_fds_in; i++) {
5843 struct socket_info *si = si_array[i];
5846 SWRAP_LOG(SWRAP_LOG_TRACE,
5847 "fds_in[%zu]=%d not an inet socket",
5852 SWRAP_LOG(SWRAP_LOG_TRACE,
5853 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5854 "passing as info.idxs[%zu]=%d!",
5857 i, payload->idxs[i]);
5861 payload->infos[payload->idxs[i]] = *si;
5862 payload->infos[payload->idxs[i]].fd_passed = 0;
5863 SWRAP_UNLOCK_SI(si);
5868 int saved_errno = errno;
5869 SWRAP_LOG(SWRAP_LOG_ERROR,
5870 "pipe() failed - %d %s",
5872 strerror(saved_errno));
5873 swrap_dec_fd_passed_array(num_fds_in, si_array);
5874 errno = saved_errno;
5878 sret = libc_write(pipefd[1], &info, sizeof(info));
5879 if (sret != sizeof(info)) {
5880 int saved_errno = errno;
5882 saved_errno = EINVAL;
5884 SWRAP_LOG(SWRAP_LOG_ERROR,
5885 "write() failed - sret=%zd - %d %s",
5887 strerror(saved_errno));
5888 swrap_dec_fd_passed_array(num_fds_in, si_array);
5889 libc_close(pipefd[1]);
5890 libc_close(pipefd[0]);
5891 errno = saved_errno;
5894 libc_close(pipefd[1]);
5897 * Add the pipe read end to the end of the passed fd array
5899 fds_out[num_fds_in] = pipefd[0];
5900 new_cmsg->cmsg_len = cmsg_len;
5902 /* we're done ... */
5903 *scm_rights_pipe_fd = pipefd[0];
5904 *cm_data_space = new_cm_data_space;
5909 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5911 size_t *cm_data_space,
5912 int *scm_rights_pipe_fd)
5916 switch (cmsg->cmsg_type) {
5918 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5921 scm_rights_pipe_fd);
5924 rc = swrap_sendmsg_copy_cmsg(cmsg,
5933 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5935 size_t *cm_data_space)
5937 int scm_rights_pipe_fd = -1;
5938 struct swrap_unix_scm_rights info;
5939 struct swrap_unix_scm_rights_payload *payload = NULL;
5940 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5943 union __swrap_fds __fds_in = { .p = NULL, };
5944 const int *fds_in = NULL;
5946 size_t size_fds_out;
5947 union __swrap_fds __fds_out = { .p = NULL, };
5948 int *fds_out = NULL;
5951 size_t new_cm_data_space;
5952 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5953 struct cmsghdr *new_cmsg = NULL;
5959 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5960 SWRAP_LOG(SWRAP_LOG_ERROR,
5961 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5962 (size_t)cmsg->cmsg_len,
5967 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5968 if ((size_fds_in % sizeof(int)) != 0) {
5969 SWRAP_LOG(SWRAP_LOG_ERROR,
5970 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5971 (size_t)cmsg->cmsg_len,
5977 num_fds_in = size_fds_in / sizeof(int);
5978 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5979 SWRAP_LOG(SWRAP_LOG_ERROR,
5980 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5981 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5982 (size_t)cmsg->cmsg_len,
5985 SWRAP_MAX_PASSED_FDS+1);
5989 if (num_fds_in <= 1) {
5990 SWRAP_LOG(SWRAP_LOG_ERROR,
5991 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5993 (size_t)cmsg->cmsg_len,
5999 __fds_in.p = CMSG_DATA(cmsg);
6000 fds_in = __fds_in.fds;
6001 num_fds_out = num_fds_in - 1;
6003 SWRAP_LOG(SWRAP_LOG_TRACE,
6004 "num_fds_in=%zu num_fds_out=%zu",
6005 num_fds_in, num_fds_out);
6007 for (i = 0; i < num_fds_in; i++) {
6008 /* Check if we have a stale fd and remove it */
6009 swrap_remove_stale(fds_in[i]);
6012 scm_rights_pipe_fd = fds_in[num_fds_out];
6013 size_fds_out = sizeof(int) * num_fds_out;
6014 cmsg_len = CMSG_LEN(size_fds_out);
6015 cmsg_space = CMSG_SPACE(size_fds_out);
6017 new_cm_data_space = *cm_data_space + cmsg_space;
6019 p = realloc((*cm_data), new_cm_data_space);
6021 swrap_close_fd_array(num_fds_in, fds_in);
6025 p = (*cm_data) + (*cm_data_space);
6026 memset(p, 0, cmsg_space);
6028 new_cmsg = __new_cmsg.cmsg;
6030 __fds_out.p = CMSG_DATA(new_cmsg);
6031 fds_out = __fds_out.fds;
6032 memcpy(fds_out, fds_in, size_fds_out);
6033 new_cmsg->cmsg_len = cmsg_len;
6035 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
6036 if (sret != sizeof(info)) {
6037 int saved_errno = errno;
6039 saved_errno = EINVAL;
6041 SWRAP_LOG(SWRAP_LOG_ERROR,
6042 "read() failed - sret=%zd - %d %s",
6044 strerror(saved_errno));
6045 swrap_close_fd_array(num_fds_in, fds_in);
6046 errno = saved_errno;
6049 libc_close(scm_rights_pipe_fd);
6050 payload = &info.payload;
6052 if (info.magic != swrap_unix_scm_right_magic) {
6053 SWRAP_LOG(SWRAP_LOG_ERROR,
6054 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
6055 (unsigned long long)info.magic,
6056 (unsigned long long)swrap_unix_scm_right_magic);
6057 swrap_close_fd_array(num_fds_out, fds_out);
6062 cmp = memcmp(info.package_name,
6063 SOCKET_WRAPPER_PACKAGE,
6064 sizeof(info.package_name));
6066 SWRAP_LOG(SWRAP_LOG_ERROR,
6067 "info.package_name='%.*s' != '%s'",
6068 (int)sizeof(info.package_name),
6070 SOCKET_WRAPPER_PACKAGE);
6071 swrap_close_fd_array(num_fds_out, fds_out);
6076 cmp = memcmp(info.package_version,
6077 SOCKET_WRAPPER_VERSION,
6078 sizeof(info.package_version));
6080 SWRAP_LOG(SWRAP_LOG_ERROR,
6081 "info.package_version='%.*s' != '%s'",
6082 (int)sizeof(info.package_version),
6083 info.package_version,
6084 SOCKET_WRAPPER_VERSION);
6085 swrap_close_fd_array(num_fds_out, fds_out);
6090 if (info.full_size != sizeof(info)) {
6091 SWRAP_LOG(SWRAP_LOG_ERROR,
6092 "info.full_size=%zu != sizeof(info)=%zu",
6093 (size_t)info.full_size,
6095 swrap_close_fd_array(num_fds_out, fds_out);
6100 if (info.payload_size != sizeof(info.payload)) {
6101 SWRAP_LOG(SWRAP_LOG_ERROR,
6102 "info.payload_size=%zu != sizeof(info.payload)=%zu",
6103 (size_t)info.payload_size,
6104 sizeof(info.payload));
6105 swrap_close_fd_array(num_fds_out, fds_out);
6110 if (payload->num_idxs != num_fds_out) {
6111 SWRAP_LOG(SWRAP_LOG_ERROR,
6112 "info.num_idxs=%u != num_fds_out=%zu",
6113 payload->num_idxs, num_fds_out);
6114 swrap_close_fd_array(num_fds_out, fds_out);
6119 for (i = 0; i < num_fds_out; i++) {
6122 si_idx_array[i] = -1;
6124 if (payload->idxs[i] == -1) {
6125 SWRAP_LOG(SWRAP_LOG_TRACE,
6126 "fds_out[%zu]=%d not an inet socket",
6131 if (payload->idxs[i] < 0) {
6132 SWRAP_LOG(SWRAP_LOG_ERROR,
6133 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
6134 i, fds_out[i], i, payload->idxs[i]);
6135 swrap_close_fd_array(num_fds_out, fds_out);
6140 if (payload->idxs[i] >= payload->num_idxs) {
6141 SWRAP_LOG(SWRAP_LOG_ERROR,
6142 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
6143 i, fds_out[i], i, payload->idxs[i],
6145 swrap_close_fd_array(num_fds_out, fds_out);
6150 if ((size_t)fds_out[i] >= socket_fds_max) {
6151 SWRAP_LOG(SWRAP_LOG_ERROR,
6152 "The max socket index limit of %zu has been reached, "
6156 swrap_close_fd_array(num_fds_out, fds_out);
6161 SWRAP_LOG(SWRAP_LOG_TRACE,
6163 "received as info.idxs[%zu]=%d!",
6165 i, payload->idxs[i]);
6167 for (j = 0; j < i; j++) {
6168 if (payload->idxs[j] == -1) {
6171 if (payload->idxs[j] == payload->idxs[i]) {
6172 si_idx_array[i] = si_idx_array[j];
6175 if (si_idx_array[i] == -1) {
6176 const struct socket_info *si = &payload->infos[payload->idxs[i]];
6178 si_idx_array[i] = swrap_add_socket_info(si);
6179 if (si_idx_array[i] == -1) {
6180 int saved_errno = errno;
6181 SWRAP_LOG(SWRAP_LOG_ERROR,
6182 "The max socket index limit of %zu has been reached, "
6186 swrap_undo_si_idx_array(i, si_idx_array);
6187 swrap_close_fd_array(num_fds_out, fds_out);
6188 errno = saved_errno;
6191 SWRAP_LOG(SWRAP_LOG_TRACE,
6192 "Imported %s socket for protocol %s, fd=%d",
6193 si->family == AF_INET ? "IPv4" : "IPv6",
6194 si->type == SOCK_DGRAM ? "UDP" : "TCP",
6199 for (i = 0; i < num_fds_out; i++) {
6200 if (si_idx_array[i] == -1) {
6203 set_socket_info_index(fds_out[i], si_idx_array[i]);
6206 /* we're done ... */
6207 *cm_data_space = new_cm_data_space;
6212 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6214 size_t *cm_data_space)
6218 switch (cmsg->cmsg_type) {
6220 rc = swrap_recvmsg_unix_scm_rights(cmsg,
6225 rc = swrap_sendmsg_copy_cmsg(cmsg,
6234 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6236 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6237 struct msghdr *msg_tmp,
6238 int *scm_rights_pipe_fd)
6240 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6241 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6242 struct cmsghdr *cmsg = NULL;
6243 uint8_t *cm_data = NULL;
6244 size_t cm_data_space = 0;
6248 *scm_rights_pipe_fd = -1;
6251 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6255 for (cmsg = CMSG_FIRSTHDR(msg_in);
6257 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6258 switch (cmsg->cmsg_level) {
6260 rc = swrap_sendmsg_unix_sol_socket(cmsg,
6263 scm_rights_pipe_fd);
6267 rc = swrap_sendmsg_copy_cmsg(cmsg,
6273 int saved_errno = errno;
6275 errno = saved_errno;
6280 msg_tmp->msg_controllen = cm_data_space;
6281 msg_tmp->msg_control = cm_data;
6284 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6285 *msg_tmp = *_msg_in;
6287 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6290 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6292 int scm_rights_pipe_fd)
6294 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6295 int saved_errno = errno;
6296 SAFE_FREE(msg_tmp->msg_control);
6297 if (scm_rights_pipe_fd != -1) {
6298 libc_close(scm_rights_pipe_fd);
6300 errno = saved_errno;
6301 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6305 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6306 struct msghdr *msg_tmp,
6307 uint8_t **tmp_control)
6309 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6310 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6311 uint8_t *cm_data = NULL;
6312 size_t cm_data_space = 0;
6315 *tmp_control = NULL;
6317 SWRAP_LOG(SWRAP_LOG_TRACE,
6318 "msg_in->msg_controllen=%zu",
6319 (size_t)msg_in->msg_controllen);
6322 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6327 * We need to give the kernel a bit more space in order
6328 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6329 * swrap_recvmsg_after_unix() will hide it again.
6331 cm_data_space = msg_in->msg_controllen;
6332 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6333 cm_data_space += cm_extra_space;
6335 cm_data = calloc(1, cm_data_space);
6336 if (cm_data == NULL) {
6340 msg_tmp->msg_controllen = cm_data_space;
6341 msg_tmp->msg_control = cm_data;
6342 *tmp_control = cm_data;
6344 SWRAP_LOG(SWRAP_LOG_TRACE,
6345 "msg_tmp->msg_controllen=%zu",
6346 (size_t)msg_tmp->msg_controllen);
6348 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6350 *tmp_control = NULL;
6352 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6355 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6356 uint8_t **tmp_control,
6357 struct msghdr *msg_out,
6360 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6361 struct cmsghdr *cmsg = NULL;
6362 uint8_t *cm_data = NULL;
6363 size_t cm_data_space = 0;
6367 int saved_errno = errno;
6368 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6369 saved_errno, strerror(saved_errno));
6370 SAFE_FREE(*tmp_control);
6371 /* msg_out should not be touched on error */
6372 errno = saved_errno;
6376 SWRAP_LOG(SWRAP_LOG_TRACE,
6377 "msg_tmp->msg_controllen=%zu",
6378 (size_t)msg_tmp->msg_controllen);
6381 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6382 int saved_errno = errno;
6383 *msg_out = *msg_tmp;
6384 SAFE_FREE(*tmp_control);
6385 errno = saved_errno;
6389 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6391 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6392 switch (cmsg->cmsg_level) {
6394 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6400 rc = swrap_sendmsg_copy_cmsg(cmsg,
6406 int saved_errno = errno;
6408 SAFE_FREE(*tmp_control);
6409 errno = saved_errno;
6415 * msg_tmp->msg_control (*tmp_control) was created by
6416 * swrap_recvmsg_before_unix() and msg_out->msg_control
6417 * is still the buffer of the caller.
6419 msg_tmp->msg_control = msg_out->msg_control;
6420 msg_tmp->msg_controllen = msg_out->msg_controllen;
6421 *msg_out = *msg_tmp;
6423 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6424 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6425 msg_out->msg_controllen = cm_data_space;
6427 SAFE_FREE(*tmp_control);
6429 SWRAP_LOG(SWRAP_LOG_TRACE,
6430 "msg_out->msg_controllen=%zu",
6431 (size_t)msg_out->msg_controllen);
6433 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6434 int saved_errno = errno;
6435 *msg_out = *msg_tmp;
6436 SAFE_FREE(*tmp_control);
6437 errno = saved_errno;
6439 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6442 static ssize_t swrap_sendmsg_before(int fd,
6443 struct socket_info *si,
6445 struct iovec *tmp_iov,
6446 struct sockaddr_un *tmp_un,
6447 const struct sockaddr_un **to_un,
6448 const struct sockaddr **to,
6453 struct swrap_sockaddr_buf buf = {};
6471 if (!si->connected) {
6476 if (msg->msg_iovlen == 0) {
6480 mtu = socket_wrapper_mtu();
6481 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6483 nlen = len + msg->msg_iov[i].iov_len;
6493 msg->msg_iovlen = i;
6494 if (msg->msg_iovlen == 0) {
6495 *tmp_iov = msg->msg_iov[0];
6496 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6498 msg->msg_iov = tmp_iov;
6499 msg->msg_iovlen = 1;
6504 if (si->connected) {
6505 if (msg->msg_name != NULL) {
6507 * We are dealing with unix sockets and if we
6508 * are connected, we should only talk to the
6509 * connected unix path. Using the fd to send
6510 * to another server would be hard to achieve.
6512 msg->msg_name = NULL;
6513 msg->msg_namelen = 0;
6515 SWRAP_LOG(SWRAP_LOG_TRACE,
6516 "connected(%s) fd=%d",
6517 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6520 const struct sockaddr *msg_name;
6521 msg_name = (const struct sockaddr *)msg->msg_name;
6523 if (msg_name == NULL) {
6529 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6541 msg->msg_name = tmp_un;
6542 msg->msg_namelen = sizeof(*tmp_un);
6545 if (si->bound == 0) {
6546 ret = swrap_auto_bind(fd, si, si->family);
6548 SWRAP_UNLOCK_SI(si);
6549 if (errno == ENOTSOCK) {
6550 swrap_remove_stale(fd);
6553 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6559 if (!si->defer_connect) {
6563 ret = sockaddr_convert_to_un(si,
6565 si->peername.sa_socklen,
6573 SWRAP_LOG(SWRAP_LOG_TRACE,
6574 "deferred connect(%s) path=%s, fd=%d",
6575 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6576 tmp_un->sun_path, fd);
6578 ret = libc_connect(fd,
6579 (struct sockaddr *)(void *)tmp_un,
6582 /* to give better errors */
6583 if (ret == -1 && errno == ENOENT) {
6584 errno = EHOSTUNREACH;
6591 si->defer_connect = 0;
6594 errno = EHOSTUNREACH;
6600 SWRAP_UNLOCK_SI(si);
6605 static void swrap_sendmsg_after(int fd,
6606 struct socket_info *si,
6608 const struct sockaddr *to,
6611 int saved_errno = errno;
6618 /* to give better errors */
6620 if (saved_errno == ENOENT) {
6621 saved_errno = EHOSTUNREACH;
6622 } else if (saved_errno == ENOTSOCK) {
6623 /* If the fd is not a socket, remove it */
6624 swrap_remove_stale(fd);
6628 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6629 avail += msg->msg_iov[i].iov_len;
6633 remain = MIN(80, avail);
6638 /* we capture it as one single packet */
6639 buf = (uint8_t *)malloc(remain);
6641 /* we just not capture the packet */
6642 errno = saved_errno;
6646 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6647 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6648 if (this_time > 0) {
6650 msg->msg_iov[i].iov_base,
6654 remain -= this_time;
6663 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6664 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6666 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6671 if (si->connected) {
6672 to = &si->peername.sa.s;
6675 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6676 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6678 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6683 SWRAP_UNLOCK_SI(si);
6686 errno = saved_errno;
6689 static int swrap_recvmsg_before(int fd,
6690 struct socket_info *si,
6692 struct iovec *tmp_iov)
6699 (void)fd; /* unused */
6704 if (!si->connected) {
6709 if (msg->msg_iovlen == 0) {
6713 mtu = socket_wrapper_mtu();
6714 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6716 nlen = len + msg->msg_iov[i].iov_len;
6721 msg->msg_iovlen = i;
6722 if (msg->msg_iovlen == 0) {
6723 *tmp_iov = msg->msg_iov[0];
6724 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6726 msg->msg_iov = tmp_iov;
6727 msg->msg_iovlen = 1;
6732 if (msg->msg_name == NULL) {
6737 if (msg->msg_iovlen == 0) {
6741 if (si->bound == 0) {
6742 ret = swrap_auto_bind(fd, si, si->family);
6744 SWRAP_UNLOCK_SI(si);
6746 * When attempting to read or write to a
6747 * descriptor, if an underlying autobind fails
6748 * because it's not a socket, stop intercepting
6749 * uses of that descriptor.
6751 if (errno == ENOTSOCK) {
6752 swrap_remove_stale(fd);
6755 SWRAP_LOG(SWRAP_LOG_ERROR,
6756 "swrap_recvmsg_before failed");
6763 errno = EHOSTUNREACH;
6769 SWRAP_UNLOCK_SI(si);
6774 static int swrap_recvmsg_after(int fd,
6775 struct socket_info *si,
6777 const struct sockaddr_un *un_addr,
6778 socklen_t un_addrlen,
6781 int saved_errno = errno;
6783 uint8_t *buf = NULL;
6789 /* to give better errors */
6791 if (saved_errno == ENOENT) {
6792 saved_errno = EHOSTUNREACH;
6793 } else if (saved_errno == ENOTSOCK) {
6794 /* If the fd is not a socket, remove it */
6795 swrap_remove_stale(fd);
6799 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6800 avail += msg->msg_iov[i].iov_len;
6805 /* Convert the socket address before we leave */
6806 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6807 rc = sockaddr_convert_from_un(si,
6824 remain = MIN(80, avail);
6829 /* we capture it as one single packet */
6830 buf = (uint8_t *)malloc(remain);
6832 /* we just not capture the packet */
6833 SWRAP_UNLOCK_SI(si);
6834 errno = saved_errno;
6838 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6839 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6841 msg->msg_iov[i].iov_base,
6844 remain -= this_time;
6849 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6850 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6851 } else if (ret == 0) { /* END OF FILE */
6852 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6853 } else if (ret > 0) {
6854 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6863 if (un_addr != NULL) {
6864 swrap_pcap_dump_packet(si,
6870 swrap_pcap_dump_packet(si,
6883 errno = saved_errno;
6885 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6887 msg->msg_controllen > 0 &&
6888 msg->msg_control != NULL) {
6889 rc = swrap_msghdr_add_socket_info(si, msg);
6891 SWRAP_UNLOCK_SI(si);
6897 SWRAP_UNLOCK_SI(si);
6901 /****************************************************************************
6903 ***************************************************************************/
6905 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6906 struct sockaddr *from, socklen_t *fromlen)
6908 struct swrap_address from_addr = {
6909 .sa_socklen = sizeof(struct sockaddr_un),
6912 struct socket_info *si = find_socket_info(s);
6913 struct swrap_address saddr = {
6914 .sa_socklen = sizeof(struct sockaddr_storage),
6921 return libc_recvfrom(s,
6933 if (from != NULL && fromlen != NULL) {
6934 msg.msg_name = from; /* optional address */
6935 msg.msg_namelen = *fromlen; /* size of address */
6937 msg.msg_name = &saddr.sa.s; /* optional address */
6938 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6940 msg.msg_iov = &tmp; /* scatter/gather array */
6941 msg.msg_iovlen = 1; /* # elements in msg_iov */
6942 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6943 msg.msg_control = NULL; /* ancillary data, see below */
6944 msg.msg_controllen = 0; /* ancillary data buffer len */
6945 msg.msg_flags = 0; /* flags on received message */
6948 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6953 buf = msg.msg_iov[0].iov_base;
6954 len = msg.msg_iov[0].iov_len;
6956 ret = libc_recvfrom(s,
6961 &from_addr.sa_socklen);
6966 tret = swrap_recvmsg_after(s,
6970 from_addr.sa_socklen,
6976 if (from != NULL && fromlen != NULL) {
6977 *fromlen = msg.msg_namelen;
6983 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6984 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6985 struct sockaddr *from, Psocklen_t fromlen)
6987 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6988 struct sockaddr *from, socklen_t *fromlen)
6991 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6994 /****************************************************************************
6996 ***************************************************************************/
6998 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6999 const struct sockaddr *to, socklen_t tolen)
7003 struct swrap_address un_addr = {
7004 .sa_socklen = sizeof(struct sockaddr_un),
7006 const struct sockaddr_un *to_un = NULL;
7009 struct socket_info *si = find_socket_info(s);
7013 return libc_sendto(s, buf, len, flags, to, tolen);
7016 tmp.iov_base = discard_const_p(char, buf);
7020 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
7021 msg.msg_namelen = tolen; /* size of address */
7022 msg.msg_iov = &tmp; /* scatter/gather array */
7023 msg.msg_iovlen = 1; /* # elements in msg_iov */
7024 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7025 msg.msg_control = NULL; /* ancillary data, see below */
7026 msg.msg_controllen = 0; /* ancillary data buffer len */
7027 msg.msg_flags = 0; /* flags on received message */
7030 rc = swrap_sendmsg_before(s,
7042 buf = msg.msg_iov[0].iov_base;
7043 len = msg.msg_iov[0].iov_len;
7048 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7050 char *swrap_dir = NULL;
7052 type = SOCKET_TYPE_CHAR_UDP;
7054 swrap_dir = socket_wrapper_dir();
7055 if (swrap_dir == NULL) {
7059 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7060 swrap_un_path(&un_addr.sa.un,
7065 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
7067 /* ignore the any errors in broadcast sends */
7073 un_addr.sa_socklen);
7076 SAFE_FREE(swrap_dir);
7080 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7082 SWRAP_UNLOCK_SI(si);
7089 * If it is a dgram socket and we are connected, don't include the
7092 if (si->type == SOCK_DGRAM && si->connected) {
7093 ret = libc_sendto(s,
7100 ret = libc_sendto(s,
7104 (struct sockaddr *)msg.msg_name,
7108 SWRAP_UNLOCK_SI(si);
7110 swrap_sendmsg_after(s, si, &msg, to, ret);
7115 ssize_t sendto(int s, const void *buf, size_t len, int flags,
7116 const struct sockaddr *to, socklen_t tolen)
7118 return swrap_sendto(s, buf, len, flags, to, tolen);
7121 /****************************************************************************
7123 ***************************************************************************/
7125 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
7127 struct socket_info *si;
7129 struct swrap_address saddr = {
7130 .sa_socklen = sizeof(struct sockaddr_storage),
7136 si = find_socket_info(s);
7138 return libc_recv(s, buf, len, flags);
7145 msg.msg_name = &saddr.sa.s; /* optional address */
7146 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7147 msg.msg_iov = &tmp; /* scatter/gather array */
7148 msg.msg_iovlen = 1; /* # elements in msg_iov */
7149 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7150 msg.msg_control = NULL; /* ancillary data, see below */
7151 msg.msg_controllen = 0; /* ancillary data buffer len */
7152 msg.msg_flags = 0; /* flags on received message */
7155 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7160 buf = msg.msg_iov[0].iov_base;
7161 len = msg.msg_iov[0].iov_len;
7163 ret = libc_recv(s, buf, len, flags);
7165 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7173 ssize_t recv(int s, void *buf, size_t len, int flags)
7175 return swrap_recv(s, buf, len, flags);
7178 /****************************************************************************
7180 ***************************************************************************/
7182 static ssize_t swrap_read(int s, void *buf, size_t len)
7184 struct socket_info *si;
7187 struct swrap_address saddr = {
7188 .sa_socklen = sizeof(struct sockaddr_storage),
7193 si = find_socket_info(s);
7195 return libc_read(s, buf, len);
7202 msg.msg_name = &saddr.sa.ss; /* optional address */
7203 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7204 msg.msg_iov = &tmp; /* scatter/gather array */
7205 msg.msg_iovlen = 1; /* # elements in msg_iov */
7206 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7207 msg.msg_control = NULL; /* ancillary data, see below */
7208 msg.msg_controllen = 0; /* ancillary data buffer len */
7209 msg.msg_flags = 0; /* flags on received message */
7212 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7214 if (tret == -ENOTSOCK) {
7215 return libc_read(s, buf, len);
7220 buf = msg.msg_iov[0].iov_base;
7221 len = msg.msg_iov[0].iov_len;
7223 ret = libc_read(s, buf, len);
7225 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7233 ssize_t read(int s, void *buf, size_t len)
7235 return swrap_read(s, buf, len);
7238 /****************************************************************************
7240 ***************************************************************************/
7242 static ssize_t swrap_write(int s, const void *buf, size_t len)
7246 struct sockaddr_un un_addr;
7249 struct socket_info *si;
7251 si = find_socket_info(s);
7253 return libc_write(s, buf, len);
7256 tmp.iov_base = discard_const_p(char, buf);
7260 msg.msg_name = NULL; /* optional address */
7261 msg.msg_namelen = 0; /* size of address */
7262 msg.msg_iov = &tmp; /* scatter/gather array */
7263 msg.msg_iovlen = 1; /* # elements in msg_iov */
7264 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7265 msg.msg_control = NULL; /* ancillary data, see below */
7266 msg.msg_controllen = 0; /* ancillary data buffer len */
7267 msg.msg_flags = 0; /* flags on received message */
7270 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7275 buf = msg.msg_iov[0].iov_base;
7276 len = msg.msg_iov[0].iov_len;
7278 ret = libc_write(s, buf, len);
7280 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7285 ssize_t write(int s, const void *buf, size_t len)
7287 return swrap_write(s, buf, len);
7290 /****************************************************************************
7292 ***************************************************************************/
7294 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7298 struct sockaddr_un un_addr;
7301 struct socket_info *si = find_socket_info(s);
7304 return libc_send(s, buf, len, flags);
7307 tmp.iov_base = discard_const_p(char, buf);
7311 msg.msg_name = NULL; /* optional address */
7312 msg.msg_namelen = 0; /* size of address */
7313 msg.msg_iov = &tmp; /* scatter/gather array */
7314 msg.msg_iovlen = 1; /* # elements in msg_iov */
7315 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7316 msg.msg_control = NULL; /* ancillary data, see below */
7317 msg.msg_controllen = 0; /* ancillary data buffer len */
7318 msg.msg_flags = 0; /* flags on received message */
7321 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7326 buf = msg.msg_iov[0].iov_base;
7327 len = msg.msg_iov[0].iov_len;
7329 ret = libc_send(s, buf, len, flags);
7331 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7336 ssize_t send(int s, const void *buf, size_t len, int flags)
7338 return swrap_send(s, buf, len, flags);
7341 /****************************************************************************
7343 ***************************************************************************/
7345 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7347 struct swrap_address from_addr = {
7348 .sa_socklen = sizeof(struct sockaddr_un),
7350 struct swrap_address convert_addr = {
7351 .sa_socklen = sizeof(struct sockaddr_storage),
7353 struct socket_info *si;
7356 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7357 size_t msg_ctrllen_filled;
7358 size_t msg_ctrllen_left;
7364 si = find_socket_info(s);
7366 uint8_t *tmp_control = NULL;
7367 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7371 ret = libc_recvmsg(s, &msg, flags);
7372 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7375 tmp.iov_base = NULL;
7379 msg.msg_name = &from_addr.sa; /* optional address */
7380 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7381 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7382 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7383 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7384 msg_ctrllen_filled = 0;
7385 msg_ctrllen_left = omsg->msg_controllen;
7387 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7388 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7389 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7392 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7397 ret = libc_recvmsg(s, &msg, flags);
7399 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7400 msg_ctrllen_filled += msg.msg_controllen;
7401 msg_ctrllen_left -= msg.msg_controllen;
7403 if (omsg->msg_control != NULL) {
7406 p = omsg->msg_control;
7407 p += msg_ctrllen_filled;
7409 msg.msg_control = p;
7410 msg.msg_controllen = msg_ctrllen_left;
7412 msg.msg_control = NULL;
7413 msg.msg_controllen = 0;
7418 * We convert the unix address to a IP address so we need a buffer
7419 * which can store the address in case of SOCK_DGRAM, see below.
7421 msg.msg_name = &convert_addr.sa;
7422 msg.msg_namelen = convert_addr.sa_socklen;
7424 rc = swrap_recvmsg_after(s,
7428 from_addr.sa_socklen,
7434 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7435 if (omsg->msg_control != NULL) {
7436 /* msg.msg_controllen = space left */
7437 msg_ctrllen_left = msg.msg_controllen;
7438 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7441 /* Update the original message length */
7442 omsg->msg_controllen = msg_ctrllen_filled;
7443 omsg->msg_flags = msg.msg_flags;
7445 omsg->msg_iovlen = msg.msg_iovlen;
7452 * The msg_name field points to a caller-allocated buffer that is
7453 * used to return the source address if the socket is unconnected. The
7454 * caller should set msg_namelen to the size of this buffer before this
7455 * call; upon return from a successful call, msg_name will contain the
7456 * length of the returned address. If the application does not need
7457 * to know the source address, msg_name can be specified as NULL.
7459 if (si->type == SOCK_STREAM) {
7460 omsg->msg_namelen = 0;
7461 } else if (omsg->msg_name != NULL &&
7462 omsg->msg_namelen != 0 &&
7463 omsg->msg_namelen >= msg.msg_namelen) {
7464 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7465 omsg->msg_namelen = msg.msg_namelen;
7468 SWRAP_UNLOCK_SI(si);
7473 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7475 return swrap_recvmsg(sockfd, msg, flags);
7478 /****************************************************************************
7480 ***************************************************************************/
7482 #ifdef HAVE_RECVMMSG
7483 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7485 static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7486 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7487 /* Linux legacy glibc < 2.21 */
7488 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7490 /* Linux glibc >= 2.21 */
7491 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7494 struct socket_info *si = find_socket_info(s);
7495 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7496 struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7499 struct swrap_address from_addr;
7500 struct swrap_address convert_addr;
7501 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7502 size_t msg_ctrllen_filled;
7503 size_t msg_ctrllen_left;
7505 } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7512 if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7513 vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7519 uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7521 for (i = 0; i < vlen; i++) {
7522 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7523 struct msghdr *msg = &msgvec[i].msg_hdr;
7525 rc = swrap_recvmsg_before_unix(omsg, msg,
7533 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7538 for (i = 0; i < ret; i++) {
7539 omsgvec[i].msg_len = msgvec[i].msg_len;
7543 saved_errno = errno;
7544 for (i = 0; i < vlen; i++) {
7545 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7546 struct msghdr *msg = &msgvec[i].msg_hdr;
7548 if (i == 0 || i < ret) {
7549 swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7551 SAFE_FREE(tmp_control[i]);
7553 errno = saved_errno;
7558 for (i = 0; i < vlen; i++) {
7559 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7560 struct msghdr *msg = &msgvec[i].msg_hdr;
7562 tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7563 tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7565 msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7566 msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7567 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7568 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7569 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7570 tmp[i].msg_ctrllen_filled = 0;
7571 tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7573 msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7574 msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7575 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7578 rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7585 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7590 for (i = 0; i < ret; i++) {
7591 omsgvec[i].msg_len = msgvec[i].msg_len;
7596 saved_errno = errno;
7597 for (i = 0; i < vlen; i++) {
7598 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7599 struct msghdr *msg = &msgvec[i].msg_hdr;
7601 if (!(i == 0 || i < ret)) {
7605 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7606 tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7607 tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7609 if (omsg->msg_control != NULL) {
7612 p = omsg->msg_control;
7613 p += tmp[i].msg_ctrllen_filled;
7615 msg->msg_control = p;
7616 msg->msg_controllen = tmp[i].msg_ctrllen_left;
7618 msg->msg_control = NULL;
7619 msg->msg_controllen = 0;
7624 * We convert the unix address to a IP address so we need a buffer
7625 * which can store the address in case of SOCK_DGRAM, see below.
7627 msg->msg_name = &tmp[i].convert_addr.sa;
7628 msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7630 swrap_recvmsg_after(s, si, msg,
7631 &tmp[i].from_addr.sa.un,
7632 tmp[i].from_addr.sa_socklen,
7635 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7636 if (omsg->msg_control != NULL) {
7637 /* msg->msg_controllen = space left */
7638 tmp[i].msg_ctrllen_left = msg->msg_controllen;
7639 tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7642 /* Update the original message length */
7643 omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7644 omsg->msg_flags = msg->msg_flags;
7646 omsg->msg_iovlen = msg->msg_iovlen;
7653 * The msg_name field points to a caller-allocated buffer that is
7654 * used to return the source address if the socket is unconnected. The
7655 * caller should set msg_namelen to the size of this buffer before this
7656 * call; upon return from a successful call, msg_name will contain the
7657 * length of the returned address. If the application does not need
7658 * to know the source address, msg_name can be specified as NULL.
7660 if (si->type == SOCK_STREAM) {
7661 omsg->msg_namelen = 0;
7662 } else if (omsg->msg_name != NULL &&
7663 omsg->msg_namelen != 0 &&
7664 omsg->msg_namelen >= msg->msg_namelen) {
7665 memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7666 omsg->msg_namelen = msg->msg_namelen;
7669 SWRAP_UNLOCK_SI(si);
7671 errno = saved_errno;
7676 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7678 ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7679 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7680 /* Linux legacy glibc < 2.21 */
7681 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7683 /* Linux glibc >= 2.21 */
7684 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7687 return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7689 #endif /* HAVE_RECVMMSG */
7691 /****************************************************************************
7693 ***************************************************************************/
7695 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7699 struct sockaddr_un un_addr;
7700 const struct sockaddr_un *to_un = NULL;
7701 const struct sockaddr *to = NULL;
7704 struct socket_info *si = find_socket_info(s);
7708 int scm_rights_pipe_fd = -1;
7710 rc = swrap_sendmsg_before_unix(omsg, &msg,
7711 &scm_rights_pipe_fd);
7715 ret = libc_sendmsg(s, &msg, flags);
7716 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7719 ZERO_STRUCT(un_addr);
7721 tmp.iov_base = NULL;
7728 if (si->connected == 0) {
7729 msg.msg_name = omsg->msg_name; /* optional address */
7730 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7732 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7733 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7735 SWRAP_UNLOCK_SI(si);
7737 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7738 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7739 uint8_t *cmbuf = NULL;
7742 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7748 msg.msg_controllen = 0;
7749 msg.msg_control = NULL;
7751 msg.msg_control = cmbuf;
7752 msg.msg_controllen = cmlen;
7755 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7757 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7759 int saved_errno = errno;
7760 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7761 SAFE_FREE(msg.msg_control);
7763 errno = saved_errno;
7770 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7777 char *swrap_dir = NULL;
7779 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7780 avail += msg.msg_iov[i].iov_len;
7786 /* we capture it as one single packet */
7787 buf = (uint8_t *)malloc(remain);
7789 int saved_errno = errno;
7790 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7791 SAFE_FREE(msg.msg_control);
7793 errno = saved_errno;
7797 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7798 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7800 msg.msg_iov[i].iov_base,
7803 remain -= this_time;
7806 type = SOCKET_TYPE_CHAR_UDP;
7808 swrap_dir = socket_wrapper_dir();
7809 if (swrap_dir == NULL) {
7810 int saved_errno = errno;
7811 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7812 SAFE_FREE(msg.msg_control);
7815 errno = saved_errno;
7819 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7820 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7821 if (stat(un_addr.sun_path, &st) != 0) continue;
7823 msg.msg_name = &un_addr; /* optional address */
7824 msg.msg_namelen = sizeof(un_addr); /* size of address */
7826 /* ignore the any errors in broadcast sends */
7827 libc_sendmsg(s, &msg, flags);
7830 SAFE_FREE(swrap_dir);
7834 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7837 SWRAP_UNLOCK_SI(si);
7842 ret = libc_sendmsg(s, &msg, flags);
7844 swrap_sendmsg_after(s, si, &msg, to, ret);
7846 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7848 int saved_errno = errno;
7849 SAFE_FREE(msg.msg_control);
7850 errno = saved_errno;
7857 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7859 return swrap_sendmsg(s, omsg, flags);
7862 /****************************************************************************
7864 ***************************************************************************/
7866 #ifdef HAVE_SENDMMSG
7867 #if defined(HAVE_SENDMMSG_SSIZE_T)
7869 static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7872 static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7875 struct socket_info *si = find_socket_info(s);
7876 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7877 struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7880 struct sockaddr_un un_addr;
7881 const struct sockaddr_un *to_un;
7882 const struct sockaddr *to;
7884 } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7887 char *swrap_dir = NULL;
7889 int found_bcast = 0;
7894 if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7895 vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7901 int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7903 for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7904 scm_rights_pipe_fd[i] = -1;
7907 for (i = 0; i < vlen; i++) {
7908 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7909 struct msghdr *msg = &msgvec[i].msg_hdr;
7911 rc = swrap_sendmsg_before_unix(omsg, msg,
7912 &scm_rights_pipe_fd[i]);
7919 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7924 for (i = 0; i < ret; i++) {
7925 omsgvec[i].msg_len = msgvec[i].msg_len;
7929 saved_errno = errno;
7930 for (i = 0; i < vlen; i++) {
7931 struct msghdr *msg = &msgvec[i].msg_hdr;
7933 swrap_sendmsg_after_unix(msg, ret,
7934 scm_rights_pipe_fd[i]);
7936 errno = saved_errno;
7942 connected = si->connected;
7943 SWRAP_UNLOCK_SI(si);
7945 for (i = 0; i < vlen; i++) {
7946 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7947 struct msghdr *msg = &msgvec[i].msg_hdr;
7949 if (connected == 0) {
7950 msg->msg_name = omsg->msg_name; /* optional address */
7951 msg->msg_namelen = omsg->msg_namelen; /* size of address */
7953 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7954 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7956 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7957 if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7958 uint8_t *cmbuf = NULL;
7961 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7968 msg->msg_control = cmbuf;
7969 msg->msg_controllen = cmlen;
7972 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7975 rc = swrap_sendmsg_before(s, si, msg,
7993 swrap_dir = socket_wrapper_dir();
7994 if (swrap_dir == NULL) {
7999 for (i = 0; i < vlen; i++) {
8000 struct msghdr *msg = &msgvec[i].msg_hdr;
8001 struct sockaddr_un *un_addr = &tmp[i].un_addr;
8002 const struct sockaddr *to = tmp[i].to;
8005 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
8013 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
8014 avail += msg->msg_iov[l].iov_len;
8020 /* we capture it as one single packet */
8021 buf = (uint8_t *)malloc(remain);
8027 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
8028 size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
8030 msg->msg_iov[l].iov_base,
8033 remain -= this_time;
8036 type = SOCKET_TYPE_CHAR_UDP;
8038 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
8039 swrap_un_path(un_addr, swrap_dir, type, iface, prt);
8040 if (stat(un_addr->sun_path, &st) != 0) continue;
8042 msg->msg_name = un_addr; /* optional address */
8043 msg->msg_namelen = sizeof(*un_addr); /* size of address */
8046 * ignore the any errors in broadcast sends and
8047 * do a single sendmsg instead of sendmmsg
8049 libc_sendmsg(s, msg, flags);
8053 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
8054 SWRAP_UNLOCK_SI(si);
8058 msgvec[i].msg_len = len;
8065 ret = libc_sendmmsg(s, msgvec, vlen, flags);
8071 for (i = 0; i < ret; i++) {
8072 omsgvec[i].msg_len = msgvec[i].msg_len;
8076 saved_errno = errno;
8077 for (i = 0; i < vlen; i++) {
8078 struct msghdr *msg = &msgvec[i].msg_hdr;
8080 if (i == 0 || i < ret) {
8081 swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
8083 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8084 SAFE_FREE(msg->msg_control);
8087 SAFE_FREE(swrap_dir);
8088 errno = saved_errno;
8093 #if defined(HAVE_SENDMMSG_SSIZE_T)
8095 ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
8098 int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
8101 return swrap_sendmmsg(s, msgvec, vlen, flags);
8103 #endif /* HAVE_SENDMMSG */
8105 /****************************************************************************
8107 ***************************************************************************/
8109 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
8111 struct socket_info *si;
8114 struct swrap_address saddr = {
8115 .sa_socklen = sizeof(struct sockaddr_storage)
8120 si = find_socket_info(s);
8122 return libc_readv(s, vector, count);
8125 tmp.iov_base = NULL;
8129 msg.msg_name = &saddr.sa.s; /* optional address */
8130 msg.msg_namelen = saddr.sa_socklen; /* size of address */
8131 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8132 msg.msg_iovlen = count; /* # elements in msg_iov */
8133 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8134 msg.msg_control = NULL; /* ancillary data, see below */
8135 msg.msg_controllen = 0; /* ancillary data buffer len */
8136 msg.msg_flags = 0; /* flags on received message */
8139 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
8141 if (rc == -ENOTSOCK) {
8142 return libc_readv(s, vector, count);
8147 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
8149 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
8157 ssize_t readv(int s, const struct iovec *vector, int count)
8159 return swrap_readv(s, vector, count);
8162 /****************************************************************************
8164 ***************************************************************************/
8166 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
8170 struct sockaddr_un un_addr;
8173 struct socket_info *si = find_socket_info(s);
8176 return libc_writev(s, vector, count);
8179 tmp.iov_base = NULL;
8183 msg.msg_name = NULL; /* optional address */
8184 msg.msg_namelen = 0; /* size of address */
8185 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8186 msg.msg_iovlen = count; /* # elements in msg_iov */
8187 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8188 msg.msg_control = NULL; /* ancillary data, see below */
8189 msg.msg_controllen = 0; /* ancillary data buffer len */
8190 msg.msg_flags = 0; /* flags on received message */
8193 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
8195 if (rc == -ENOTSOCK) {
8196 return libc_readv(s, vector, count);
8201 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
8203 swrap_sendmsg_after(s, si, &msg, NULL, ret);
8208 ssize_t writev(int s, const struct iovec *vector, int count)
8210 return swrap_writev(s, vector, count);
8213 /****************************
8215 ***************************/
8217 static int swrap_remove_wrapper(const char *__func_name,
8218 int (*__close_fd_fn)(int fd),
8221 struct socket_info *si = NULL;
8223 int ret_errno = errno;
8226 swrap_mutex_lock(&socket_reset_mutex);
8228 si_index = find_socket_info_index(fd);
8229 if (si_index == -1) {
8230 swrap_mutex_unlock(&socket_reset_mutex);
8231 return __close_fd_fn(fd);
8234 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8235 reset_socket_info_index(fd);
8237 si = swrap_get_socket_info(si_index);
8239 swrap_mutex_lock(&first_free_mutex);
8242 ret = __close_fd_fn(fd);
8247 swrap_dec_refcount(si);
8249 if (swrap_get_refcount(si) > 0) {
8250 /* there are still references left */
8254 if (si->fd_passed) {
8258 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8259 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8262 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8263 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8264 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8267 if (si->un_addr.sun_path[0] != '\0') {
8268 unlink(si->un_addr.sun_path);
8272 swrap_set_next_free(si, first_free);
8273 first_free = si_index;
8276 SWRAP_UNLOCK_SI(si);
8277 swrap_mutex_unlock(&first_free_mutex);
8278 swrap_mutex_unlock(&socket_reset_mutex);
8284 static int swrap_noop_close(int fd)
8286 (void)fd; /* unused */
8290 static void swrap_remove_stale(int fd)
8292 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8296 * This allows socket_wrapper aware applications to
8297 * indicate that the given fd does not belong to
8300 * We already overload a lot of unrelated functions
8301 * like eventfd(), timerfd_create(), ... in order to
8302 * call swrap_remove_stale() on the returned fd, but
8303 * we'll never be able to handle all possible syscalls.
8305 * socket_wrapper_indicate_no_inet_fd() gives them a way
8308 * We don't export swrap_remove_stale() in order to
8309 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8312 void socket_wrapper_indicate_no_inet_fd(int fd)
8314 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8317 static int swrap_close(int fd)
8319 return swrap_remove_wrapper(__func__, libc_close, fd);
8324 return swrap_close(fd);
8327 #ifdef HAVE___CLOSE_NOCANCEL
8329 static int swrap___close_nocancel(int fd)
8331 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8334 int __close_nocancel(int fd);
8335 int __close_nocancel(int fd)
8337 return swrap___close_nocancel(fd);
8340 #endif /* HAVE___CLOSE_NOCANCEL */
8342 /****************************
8344 ***************************/
8346 static int swrap_dup(int fd)
8348 struct socket_info *si;
8351 idx = find_socket_info_index(fd);
8353 return libc_dup(fd);
8356 si = swrap_get_socket_info(idx);
8358 dup_fd = libc_dup(fd);
8360 int saved_errno = errno;
8361 errno = saved_errno;
8365 if ((size_t)dup_fd >= socket_fds_max) {
8366 SWRAP_LOG(SWRAP_LOG_ERROR,
8367 "The max socket index limit of %zu has been reached, "
8378 swrap_inc_refcount(si);
8380 SWRAP_UNLOCK_SI(si);
8382 /* Make sure we don't have an entry for the fd */
8383 swrap_remove_stale(dup_fd);
8385 set_socket_info_index(dup_fd, idx);
8392 return swrap_dup(fd);
8395 /****************************
8397 ***************************/
8399 static int swrap_dup2(int fd, int newfd)
8401 struct socket_info *si;
8404 idx = find_socket_info_index(fd);
8406 return libc_dup2(fd, newfd);
8409 si = swrap_get_socket_info(idx);
8413 * According to the manpage:
8415 * "If oldfd is a valid file descriptor, and newfd has the same
8416 * value as oldfd, then dup2() does nothing, and returns newfd."
8421 if ((size_t)newfd >= socket_fds_max) {
8422 SWRAP_LOG(SWRAP_LOG_ERROR,
8423 "The max socket index limit of %zu has been reached, "
8431 if (find_socket_info(newfd)) {
8432 /* dup2() does an implicit close of newfd, which we
8433 * need to emulate */
8437 dup_fd = libc_dup2(fd, newfd);
8439 int saved_errno = errno;
8440 errno = saved_errno;
8446 swrap_inc_refcount(si);
8448 SWRAP_UNLOCK_SI(si);
8450 /* Make sure we don't have an entry for the fd */
8451 swrap_remove_stale(dup_fd);
8453 set_socket_info_index(dup_fd, idx);
8458 int dup2(int fd, int newfd)
8460 return swrap_dup2(fd, newfd);
8463 /****************************
8465 ***************************/
8467 static int swrap_vfcntl(int fd, int cmd, va_list va)
8469 struct socket_info *si;
8470 int rc, dup_fd, idx;
8472 idx = find_socket_info_index(fd);
8474 return libc_vfcntl(fd, cmd, va);
8477 si = swrap_get_socket_info(idx);
8481 dup_fd = libc_vfcntl(fd, cmd, va);
8483 int saved_errno = errno;
8484 errno = saved_errno;
8488 /* Make sure we don't have an entry for the fd */
8489 swrap_remove_stale(dup_fd);
8491 if ((size_t)dup_fd >= socket_fds_max) {
8492 SWRAP_LOG(SWRAP_LOG_ERROR,
8493 "The max socket index limit of %zu has been reached, "
8504 swrap_inc_refcount(si);
8506 SWRAP_UNLOCK_SI(si);
8509 set_socket_info_index(dup_fd, idx);
8514 rc = libc_vfcntl(fd, cmd, va);
8521 #undef fcntl /* Needed for LFS handling */
8522 int fcntl(int fd, int cmd, ...)
8529 rc = swrap_vfcntl(fd, cmd, va);
8536 /****************************
8538 ***************************/
8541 static int swrap_eventfd(int count, int flags)
8545 fd = libc_eventfd(count, flags);
8547 swrap_remove_stale(fd);
8553 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8554 int eventfd(unsigned int count, int flags)
8556 int eventfd(int count, int flags)
8559 return swrap_eventfd(count, flags);
8564 int pledge(const char *promises, const char *paths[])
8566 (void)promises; /* unused */
8567 (void)paths; /* unused */
8571 #endif /* HAVE_PLEDGE */
8574 static bool swrap_is_swrap_related_syscall(long int sysno)
8580 #endif /* SYS_close */
8585 #endif /* SYS_recvmmsg */
8590 #endif /* SYS_sendmmsg */
8597 static long int swrap_syscall(long int sysno, va_list vp)
8605 int fd = (int)va_arg(vp, int);
8607 SWRAP_LOG(SWRAP_LOG_TRACE,
8608 "calling swrap_close syscall %lu",
8610 rc = swrap_close(fd);
8613 #endif /* SYS_close */
8618 int fd = (int)va_arg(vp, int);
8619 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8620 unsigned int vlen = va_arg(vp, unsigned int);
8621 int flags = va_arg(vp, int);
8622 struct timespec *timeout = va_arg(vp, struct timespec *);
8624 SWRAP_LOG(SWRAP_LOG_TRACE,
8625 "calling swrap_recvmmsg syscall %lu",
8627 rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
8630 #endif /* SYS_recvmmsg */
8635 int fd = (int)va_arg(vp, int);
8636 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8637 unsigned int vlen = va_arg(vp, unsigned int);
8638 int flags = va_arg(vp, int);
8640 SWRAP_LOG(SWRAP_LOG_TRACE,
8641 "calling swrap_sendmmsg syscall %lu",
8643 rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
8646 #endif /* SYS_sendmmsg */
8657 #ifdef HAVE_SYSCALL_INT
8658 int syscall(int sysno, ...)
8660 long int syscall(long int sysno, ...)
8663 #ifdef HAVE_SYSCALL_INT
8670 va_start(va, sysno);
8673 * We should only handle the syscall numbers
8676 if (!swrap_is_swrap_related_syscall(sysno)) {
8678 * We need to give socket_wrapper a
8679 * chance to take over...
8681 if (swrap_uwrap_syscall_valid(sysno)) {
8682 rc = swrap_uwrap_syscall_va(sysno, va);
8687 rc = libc_vsyscall(sysno, va);
8692 if (!socket_wrapper_enabled()) {
8693 rc = libc_vsyscall(sysno, va);
8698 rc = swrap_syscall(sysno, va);
8704 /* used by uid_wrapper */
8705 bool socket_wrapper_syscall_valid(long int sysno);
8706 bool socket_wrapper_syscall_valid(long int sysno)
8708 if (!swrap_is_swrap_related_syscall(sysno)) {
8712 if (!socket_wrapper_enabled()) {
8719 /* used by uid_wrapper */
8720 long int socket_wrapper_syscall_va(long int sysno, va_list va);
8721 long int socket_wrapper_syscall_va(long int sysno, va_list va)
8723 if (!swrap_is_swrap_related_syscall(sysno)) {
8728 if (!socket_wrapper_enabled()) {
8729 return libc_vsyscall(sysno, va);
8732 return swrap_syscall(sysno, va);
8734 #endif /* HAVE_SYSCALL */
8736 static void swrap_thread_prepare(void)
8739 * This function should only be called here!!
8741 * We bind all symobls to avoid deadlocks of the fork is
8742 * interrupted by a signal handler using a symbol of this
8745 swrap_bind_symbol_all();
8750 static void swrap_thread_parent(void)
8755 static void swrap_thread_child(void)
8760 /****************************
8762 ***************************/
8763 void swrap_constructor(void)
8765 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8766 SWRAP_LOG(SWRAP_LOG_ERROR,
8768 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8769 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8770 "sizeof(struct socket_info)=%zu",
8772 sizeof(struct swrap_unix_scm_rights),
8773 sizeof(struct swrap_unix_scm_rights_payload),
8774 sizeof(struct socket_info));
8781 * If we hold a lock and the application forks, then the child
8782 * is not able to unlock the mutex and we are in a deadlock.
8783 * This should prevent such deadlocks.
8785 pthread_atfork(&swrap_thread_prepare,
8786 &swrap_thread_parent,
8787 &swrap_thread_child);
8790 /****************************
8792 ***************************/
8795 * This function is called when the library is unloaded and makes sure that
8796 * sockets get closed and the unix file for the socket are unlinked.
8798 void swrap_destructor(void)
8802 if (socket_fds_idx != NULL) {
8803 for (i = 0; i < socket_fds_max; ++i) {
8804 if (socket_fds_idx[i] != -1) {
8808 SAFE_FREE(socket_fds_idx);
8813 if (swrap.libc.handle != NULL
8815 && swrap.libc.handle != RTLD_NEXT
8818 dlclose(swrap.libc.handle);
8820 if (swrap.libc.socket_handle
8822 && swrap.libc.socket_handle != RTLD_NEXT
8825 dlclose(swrap.libc.socket_handle);
8829 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8831 * On FreeBSD 12 (and maybe other platforms)
8832 * system libraries like libresolv prefix there
8833 * syscalls with '_' in order to always use
8834 * the symbols from libc.
8836 * In the interaction with resolv_wrapper,
8837 * we need to inject socket wrapper into libresolv,
8838 * which means we need to private all socket
8839 * related syscalls also with the '_' prefix.
8841 * This is tested in Samba's 'make test',
8842 * there we noticed that providing '_read',
8843 * '_open' and '_close' would cause errors, which
8844 * means we skip '_read', '_write' and
8845 * all non socket related calls without
8846 * further analyzing the problem.
8848 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8849 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8852 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8854 SWRAP_SYMBOL_ALIAS(accept, _accept);
8855 SWRAP_SYMBOL_ALIAS(bind, _bind);
8856 SWRAP_SYMBOL_ALIAS(connect, _connect);
8857 SWRAP_SYMBOL_ALIAS(dup, _dup);
8858 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8859 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8860 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8861 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8862 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8863 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8864 SWRAP_SYMBOL_ALIAS(listen, _listen);
8865 SWRAP_SYMBOL_ALIAS(readv, _readv);
8866 SWRAP_SYMBOL_ALIAS(recv, _recv);
8867 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8868 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8869 SWRAP_SYMBOL_ALIAS(send, _send);
8870 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8871 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8872 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8873 SWRAP_SYMBOL_ALIAS(socket, _socket);
8874 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8875 SWRAP_SYMBOL_ALIAS(writev, _writev);
8877 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */