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
47 #include <sys/types.h>
50 #ifdef HAVE_SYS_SYSCALL_H
51 #include <sys/syscall.h>
56 #include <sys/socket.h>
57 #include <sys/ioctl.h>
58 #ifdef HAVE_SYS_FILIO_H
59 #include <sys/filio.h>
61 #ifdef HAVE_SYS_SIGNALFD_H
62 #include <sys/signalfd.h>
64 #ifdef HAVE_SYS_EVENTFD_H
65 #include <sys/eventfd.h>
67 #ifdef HAVE_SYS_TIMERFD_H
68 #include <sys/timerfd.h>
73 #include <netinet/in.h>
74 #include <netinet/tcp.h>
75 #ifdef HAVE_NETINET_TCP_FSM_H
76 #include <netinet/tcp_fsm.h>
78 #include <arpa/inet.h>
87 #ifdef HAVE_GNU_LIB_NAMES_H
88 #include <gnu/lib-names.h>
95 #include "socket_wrapper.h"
104 /* GCC have printf type attribute check. */
105 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
106 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
108 #define PRINTF_ATTRIBUTE(a,b)
109 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
111 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
112 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
114 #define CONSTRUCTOR_ATTRIBUTE
115 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
117 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
118 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
120 #define DESTRUCTOR_ATTRIBUTE
124 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
125 # define FALL_THROUGH __attribute__ ((fallthrough))
126 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
127 # define FALL_THROUGH ((void)0)
128 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
129 #endif /* FALL_THROUGH */
131 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
132 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
134 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
137 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
138 # define SWRAP_THREAD __thread
140 # define SWRAP_THREAD
144 #define MIN(a,b) ((a)<(b)?(a):(b))
148 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
152 #define ZERO_STRUCTP(x) do { \
154 memset((char *)(x), 0, sizeof(*(x))); \
159 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
162 #ifndef discard_const
163 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
166 #ifndef discard_const_p
167 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
170 #define UNUSED(x) (void)(x)
173 # ifndef IPV6_RECVPKTINFO
174 # define IPV6_RECVPKTINFO IPV6_PKTINFO
175 # endif /* IPV6_RECVPKTINFO */
176 #endif /* IPV6_PKTINFO */
179 * On BSD IP_PKTINFO has a different name because during
180 * the time when they implemented it, there was no RFC.
181 * The name for IPv6 is the same as on Linux.
184 # ifdef IP_RECVDSTADDR
185 # define IP_PKTINFO IP_RECVDSTADDR
189 #define socket_wrapper_init_mutex(m) \
190 _socket_wrapper_init_mutex(m, #m)
192 /* Add new global locks here please */
193 # define SWRAP_REINIT_ALL do { \
195 ret = socket_wrapper_init_mutex(&sockets_mutex); \
196 if (ret != 0) exit(-1); \
197 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
198 if (ret != 0) exit(-1); \
199 ret = socket_wrapper_init_mutex(&first_free_mutex); \
200 if (ret != 0) exit(-1); \
201 ret = socket_wrapper_init_mutex(&sockets_si_global); \
202 if (ret != 0) exit(-1); \
203 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
204 if (ret != 0) exit(-1); \
205 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
206 if (ret != 0) exit(-1); \
207 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
208 if (ret != 0) exit(-1); \
211 # define SWRAP_LOCK_ALL do { \
212 swrap_mutex_lock(&sockets_mutex); \
213 swrap_mutex_lock(&socket_reset_mutex); \
214 swrap_mutex_lock(&first_free_mutex); \
215 swrap_mutex_lock(&sockets_si_global); \
216 swrap_mutex_lock(&autobind_start_mutex); \
217 swrap_mutex_lock(&pcap_dump_mutex); \
218 swrap_mutex_lock(&mtu_update_mutex); \
221 # define SWRAP_UNLOCK_ALL do { \
222 swrap_mutex_unlock(&mtu_update_mutex); \
223 swrap_mutex_unlock(&pcap_dump_mutex); \
224 swrap_mutex_unlock(&autobind_start_mutex); \
225 swrap_mutex_unlock(&sockets_si_global); \
226 swrap_mutex_unlock(&first_free_mutex); \
227 swrap_mutex_unlock(&socket_reset_mutex); \
228 swrap_mutex_unlock(&sockets_mutex); \
231 #define SOCKET_INFO_CONTAINER(si) \
232 (struct socket_info_container *)(si)
234 #define SWRAP_LOCK_SI(si) do { \
235 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
237 swrap_mutex_lock(&sockets_si_global); \
243 #define SWRAP_UNLOCK_SI(si) do { \
244 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
246 swrap_mutex_unlock(&sockets_si_global); \
252 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
253 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
255 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
258 /* we need to use a very terse format here as IRIX 6.4 silently
259 truncates names to 16 chars, so if we use a longer name then we
260 can't tell which port a packet came from with recvfrom()
262 with this format we have 8 chars left for the directory name
264 #define SOCKET_FORMAT "%c%02X%04X"
265 #define SOCKET_TYPE_CHAR_TCP 'T'
266 #define SOCKET_TYPE_CHAR_UDP 'U'
267 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
268 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
271 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
272 * format PCAP capture files (as the caller will simply continue from here).
274 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
275 #define SOCKET_WRAPPER_MTU_MIN 512
276 #define SOCKET_WRAPPER_MTU_MAX 32768
278 #define SOCKET_MAX_SOCKETS 1024
281 * Maximum number of socket_info structures that can
282 * be used. Can be overriden by the environment variable
283 * SOCKET_WRAPPER_MAX_SOCKETS.
285 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
287 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
289 /* This limit is to avoid broadcast sendto() needing to stat too many
290 * files. It may be raised (with a performance cost) to up to 254
291 * without changing the format above */
292 #define MAX_WRAPPED_INTERFACES 64
294 struct swrap_address {
295 socklen_t sa_socklen;
298 struct sockaddr_in in;
300 struct sockaddr_in6 in6;
302 struct sockaddr_un un;
303 struct sockaddr_storage ss;
307 static int first_free;
312 * Remember to update swrap_unix_scm_right_magic
329 /* The unix path so we can unlink it on close() */
330 struct sockaddr_un un_addr;
332 struct swrap_address bindname;
333 struct swrap_address myname;
334 struct swrap_address peername;
337 unsigned long pck_snd;
338 unsigned long pck_rcv;
342 struct socket_info_meta
344 unsigned int refcount;
347 * As long as we don't use shared memory
348 * for the sockets array, we use
349 * sockets_si_global as a single mutex.
351 * pthread_mutex_t mutex;
355 struct socket_info_container
357 struct socket_info info;
358 struct socket_info_meta meta;
361 static struct socket_info_container *sockets;
363 static size_t socket_info_max = 0;
366 * Allocate the socket array always on the limit value. We want it to be
367 * at least bigger than the default so if we reach the limit we can
368 * still deal with duplicate fds pointing to the same socket_info.
370 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
372 /* Hash table to map fds to corresponding socket_info index */
373 static int *socket_fds_idx;
375 /* Mutex for syncronizing port selection during swrap_auto_bind() */
376 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
378 /* Mutex to guard the initialization of array of socket_info structures */
379 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
381 /* Mutex to guard the socket reset in swrap_remove_wrapper() */
382 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
384 /* Mutex to synchronize access to first free index in socket_info array */
385 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
388 * Mutex to synchronize access to to socket_info structures
389 * We use a single global mutex in order to avoid leaking
390 * ~ 38M copy on write memory per fork.
391 * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
393 static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER;
395 /* Mutex to synchronize access to packet capture dump file */
396 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
398 /* Mutex for synchronizing mtu value fetch*/
399 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
401 /* Function prototypes */
403 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
404 /* xlC and other oldschool compilers support (only) this */
405 #pragma init (swrap_constructor)
407 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
408 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
409 #pragma fini (swrap_destructor)
411 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
413 #ifndef HAVE_GETPROGNAME
414 static const char *getprogname(void)
416 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
417 return program_invocation_short_name;
418 #elif defined(HAVE_GETEXECNAME)
419 return getexecname();
422 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
424 #endif /* HAVE_GETPROGNAME */
426 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
427 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
429 static void swrap_log(enum swrap_dbglvl_e dbglvl,
431 const char *format, ...)
436 unsigned int lvl = 0;
437 const char *prefix = "SWRAP";
438 const char *progname = getprogname();
440 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
449 va_start(va, format);
450 vsnprintf(buffer, sizeof(buffer), format, va);
454 case SWRAP_LOG_ERROR:
455 prefix = "SWRAP_ERROR";
458 prefix = "SWRAP_WARN";
460 case SWRAP_LOG_DEBUG:
461 prefix = "SWRAP_DEBUG";
463 case SWRAP_LOG_TRACE:
464 prefix = "SWRAP_TRACE";
468 if (progname == NULL) {
469 progname = "<unknown>";
473 "%s[%s (%u)] - %s: %s\n",
476 (unsigned int)getpid(),
481 /*********************************************************
482 * SWRAP LOADING LIBC FUNCTIONS
483 *********************************************************/
488 typedef int (*__libc_accept4)(int sockfd,
489 struct sockaddr *addr,
493 typedef int (*__libc_accept)(int sockfd,
494 struct sockaddr *addr,
497 typedef int (*__libc_bind)(int sockfd,
498 const struct sockaddr *addr,
500 typedef int (*__libc_close)(int fd);
501 #ifdef HAVE___CLOSE_NOCANCEL
502 typedef int (*__libc___close_nocancel)(int fd);
504 typedef int (*__libc_connect)(int sockfd,
505 const struct sockaddr *addr,
507 typedef int (*__libc_dup)(int fd);
508 typedef int (*__libc_dup2)(int oldfd, int newfd);
509 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
510 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
512 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
515 typedef int (*__libc_eventfd)(int count, int flags);
517 typedef int (*__libc_getpeername)(int sockfd,
518 struct sockaddr *addr,
520 typedef int (*__libc_getsockname)(int sockfd,
521 struct sockaddr *addr,
523 typedef int (*__libc_getsockopt)(int sockfd,
528 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
529 typedef int (*__libc_listen)(int sockfd, int backlog);
530 typedef int (*__libc_open)(const char *pathname, int flags, ...);
532 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
533 #endif /* HAVE_OPEN64 */
534 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
535 typedef int (*__libc_pipe)(int pipefd[2]);
536 typedef int (*__libc_read)(int fd, void *buf, size_t count);
537 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
538 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
539 typedef int (*__libc_recvfrom)(int sockfd,
543 struct sockaddr *src_addr,
545 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
547 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
549 typedef ssize_t (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout);
550 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
551 /* Linux legacy glibc < 2.21 */
552 typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout);
554 /* Linux glibc >= 2.21 */
555 typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);
557 #endif /* HAVE_RECVMMSG */
558 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
559 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
561 #if defined(HAVE_SENDMMSG_SSIZE_T)
563 typedef ssize_t (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags);
566 typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags);
568 #endif /* HAVE_SENDMMSG */
569 typedef int (*__libc_sendto)(int sockfd,
573 const struct sockaddr *dst_addr,
575 typedef int (*__libc_setsockopt)(int sockfd,
581 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
583 typedef int (*__libc_socket)(int domain, int type, int protocol);
584 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
585 #ifdef HAVE_TIMERFD_CREATE
586 typedef int (*__libc_timerfd_create)(int clockid, int flags);
588 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
589 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
591 typedef long int (*__libc_syscall)(long int sysno, ...);
594 #define SWRAP_SYMBOL_ENTRY(i) \
600 struct swrap_libc_symbols {
602 SWRAP_SYMBOL_ENTRY(accept4);
604 SWRAP_SYMBOL_ENTRY(accept);
606 SWRAP_SYMBOL_ENTRY(bind);
607 SWRAP_SYMBOL_ENTRY(close);
608 #ifdef HAVE___CLOSE_NOCANCEL
609 SWRAP_SYMBOL_ENTRY(__close_nocancel);
611 SWRAP_SYMBOL_ENTRY(connect);
612 SWRAP_SYMBOL_ENTRY(dup);
613 SWRAP_SYMBOL_ENTRY(dup2);
614 SWRAP_SYMBOL_ENTRY(fcntl);
615 SWRAP_SYMBOL_ENTRY(fopen);
617 SWRAP_SYMBOL_ENTRY(fopen64);
620 SWRAP_SYMBOL_ENTRY(eventfd);
622 SWRAP_SYMBOL_ENTRY(getpeername);
623 SWRAP_SYMBOL_ENTRY(getsockname);
624 SWRAP_SYMBOL_ENTRY(getsockopt);
625 SWRAP_SYMBOL_ENTRY(ioctl);
626 SWRAP_SYMBOL_ENTRY(listen);
627 SWRAP_SYMBOL_ENTRY(open);
629 SWRAP_SYMBOL_ENTRY(open64);
631 SWRAP_SYMBOL_ENTRY(openat);
632 SWRAP_SYMBOL_ENTRY(pipe);
633 SWRAP_SYMBOL_ENTRY(read);
634 SWRAP_SYMBOL_ENTRY(readv);
635 SWRAP_SYMBOL_ENTRY(recv);
636 SWRAP_SYMBOL_ENTRY(recvfrom);
637 SWRAP_SYMBOL_ENTRY(recvmsg);
639 SWRAP_SYMBOL_ENTRY(recvmmsg);
641 SWRAP_SYMBOL_ENTRY(send);
642 SWRAP_SYMBOL_ENTRY(sendmsg);
644 SWRAP_SYMBOL_ENTRY(sendmmsg);
646 SWRAP_SYMBOL_ENTRY(sendto);
647 SWRAP_SYMBOL_ENTRY(setsockopt);
649 SWRAP_SYMBOL_ENTRY(signalfd);
651 SWRAP_SYMBOL_ENTRY(socket);
652 SWRAP_SYMBOL_ENTRY(socketpair);
653 #ifdef HAVE_TIMERFD_CREATE
654 SWRAP_SYMBOL_ENTRY(timerfd_create);
656 SWRAP_SYMBOL_ENTRY(write);
657 SWRAP_SYMBOL_ENTRY(writev);
659 SWRAP_SYMBOL_ENTRY(syscall);
667 struct swrap_libc_symbols symbols;
671 static struct swrap swrap;
674 static char *socket_wrapper_dir(void);
676 #define LIBC_NAME "libc.so"
683 static const char *swrap_str_lib(enum swrap_lib lib)
688 case SWRAP_LIBSOCKET:
692 /* Compiler would warn us about unhandled enum value if we get here */
696 static void *swrap_load_lib_handle(enum swrap_lib lib)
698 int flags = RTLD_LAZY;
703 const char *env_preload = getenv("LD_PRELOAD");
704 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
705 bool enable_deepbind = true;
707 /* Don't do a deepbind if we run with libasan */
708 if (env_preload != NULL && strlen(env_preload) < 1024) {
709 const char *p = strstr(env_preload, "libasan.so");
711 enable_deepbind = false;
715 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
716 enable_deepbind = false;
719 if (enable_deepbind) {
720 flags |= RTLD_DEEPBIND;
725 case SWRAP_LIBSOCKET:
726 #ifdef HAVE_LIBSOCKET
727 handle = swrap.libc.socket_handle;
728 if (handle == NULL) {
729 for (i = 10; i >= 0; i--) {
730 char soname[256] = {0};
732 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
733 handle = dlopen(soname, flags);
734 if (handle != NULL) {
739 swrap.libc.socket_handle = handle;
744 handle = swrap.libc.handle;
746 if (handle == NULL) {
747 handle = dlopen(LIBC_SO, flags);
749 swrap.libc.handle = handle;
752 if (handle == NULL) {
753 for (i = 10; i >= 0; i--) {
754 char soname[256] = {0};
756 snprintf(soname, sizeof(soname), "libc.so.%d", i);
757 handle = dlopen(soname, flags);
758 if (handle != NULL) {
763 swrap.libc.handle = handle;
768 if (handle == NULL) {
770 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
772 SWRAP_LOG(SWRAP_LOG_ERROR,
773 "Failed to dlopen library: %s",
782 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
787 handle = swrap_load_lib_handle(lib);
789 func = dlsym(handle, fn_name);
791 SWRAP_LOG(SWRAP_LOG_ERROR,
792 "Failed to find %s: %s",
798 SWRAP_LOG(SWRAP_LOG_TRACE,
806 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
807 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
811 ret = pthread_mutex_lock(mutex);
813 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
814 getpid(), getppid(), caller, line, name, strerror(ret));
819 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
820 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
824 ret = pthread_mutex_unlock(mutex);
826 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
827 getpid(), getppid(), caller, line, name, strerror(ret));
833 * These macros have a thread race condition on purpose!
835 * This is an optimization to avoid locking each time we check if the symbol is
838 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
839 swrap.libc.symbols._libc_##sym_name.obj = \
840 _swrap_bind_symbol(lib, #sym_name); \
843 #define swrap_bind_symbol_libc(sym_name) \
844 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
846 #define swrap_bind_symbol_libsocket(sym_name) \
847 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
849 static void swrap_bind_symbol_all(void);
851 /****************************************************************************
853 ****************************************************************************
855 * Functions especially from libc need to be loaded individually, you can't
856 * load all at once or gdb will segfault at startup. The same applies to
857 * valgrind and has probably something todo with with the linker. So we need
858 * load each function at the point it is called the first time.
860 ****************************************************************************/
863 static int libc_accept4(int sockfd,
864 struct sockaddr *addr,
868 swrap_bind_symbol_all();
870 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
873 #else /* HAVE_ACCEPT4 */
875 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
877 swrap_bind_symbol_all();
879 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
881 #endif /* HAVE_ACCEPT4 */
883 static int libc_bind(int sockfd,
884 const struct sockaddr *addr,
887 swrap_bind_symbol_all();
889 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
892 static int libc_close(int fd)
894 swrap_bind_symbol_all();
896 return swrap.libc.symbols._libc_close.f(fd);
899 #ifdef HAVE___CLOSE_NOCANCEL
900 static int libc___close_nocancel(int fd)
902 swrap_bind_symbol_all();
904 return swrap.libc.symbols._libc___close_nocancel.f(fd);
906 #endif /* HAVE___CLOSE_NOCANCEL */
908 static int libc_connect(int sockfd,
909 const struct sockaddr *addr,
912 swrap_bind_symbol_all();
914 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
917 static int libc_dup(int fd)
919 swrap_bind_symbol_all();
921 return swrap.libc.symbols._libc_dup.f(fd);
924 static int libc_dup2(int oldfd, int newfd)
926 swrap_bind_symbol_all();
928 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
932 static int libc_eventfd(int count, int flags)
934 swrap_bind_symbol_all();
936 return swrap.libc.symbols._libc_eventfd.f(count, flags);
940 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
941 static int libc_vfcntl(int fd, int cmd, va_list ap)
946 swrap_bind_symbol_all();
948 arg = va_arg(ap, void *);
950 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
955 static int libc_getpeername(int sockfd,
956 struct sockaddr *addr,
959 swrap_bind_symbol_all();
961 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
964 static int libc_getsockname(int sockfd,
965 struct sockaddr *addr,
968 swrap_bind_symbol_all();
970 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
973 static int libc_getsockopt(int sockfd,
979 swrap_bind_symbol_all();
981 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
988 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
989 static int libc_vioctl(int d, unsigned long int request, va_list ap)
994 swrap_bind_symbol_all();
996 arg = va_arg(ap, void *);
998 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
1003 static int libc_listen(int sockfd, int backlog)
1005 swrap_bind_symbol_all();
1007 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
1010 static FILE *libc_fopen(const char *name, const char *mode)
1012 swrap_bind_symbol_all();
1014 return swrap.libc.symbols._libc_fopen.f(name, mode);
1018 static FILE *libc_fopen64(const char *name, const char *mode)
1020 swrap_bind_symbol_all();
1022 return swrap.libc.symbols._libc_fopen64.f(name, mode);
1024 #endif /* HAVE_FOPEN64 */
1026 static void swrap_inject_o_largefile(int *flags)
1028 (void)*flags; /* maybe unused */
1029 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1031 if (((*flags) & O_PATH) == 0)
1034 *flags |= O_LARGEFILE;
1039 static int libc_vopen(const char *pathname, int flags, va_list ap)
1044 swrap_bind_symbol_all();
1046 swrap_inject_o_largefile(&flags);
1048 if (flags & O_CREAT) {
1049 mode = va_arg(ap, int);
1051 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1056 static int libc_open(const char *pathname, int flags, ...)
1061 va_start(ap, flags);
1062 fd = libc_vopen(pathname, flags, ap);
1069 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1074 swrap_bind_symbol_all();
1076 swrap_inject_o_largefile(&flags);
1078 if (flags & O_CREAT) {
1079 mode = va_arg(ap, int);
1081 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1085 #endif /* HAVE_OPEN64 */
1087 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1092 swrap_bind_symbol_all();
1094 swrap_inject_o_largefile(&flags);
1096 if (flags & O_CREAT) {
1097 mode = va_arg(ap, int);
1099 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1108 static int libc_openat(int dirfd, const char *path, int flags, ...)
1113 va_start(ap, flags);
1114 fd = libc_vopenat(dirfd, path, flags, ap);
1121 static int libc_pipe(int pipefd[2])
1123 swrap_bind_symbol_all();
1125 return swrap.libc.symbols._libc_pipe.f(pipefd);
1128 static int libc_read(int fd, void *buf, size_t count)
1130 swrap_bind_symbol_all();
1132 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1135 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1137 swrap_bind_symbol_all();
1139 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1142 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1144 swrap_bind_symbol_all();
1146 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1149 static int libc_recvfrom(int sockfd,
1153 struct sockaddr *src_addr,
1156 swrap_bind_symbol_all();
1158 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1166 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1168 swrap_bind_symbol_all();
1170 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1173 #ifdef HAVE_RECVMMSG
1174 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1176 static ssize_t libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
1177 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1178 /* Linux legacy glibc < 2.21 */
1179 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
1181 /* Linux glibc >= 2.21 */
1182 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
1185 swrap_bind_symbol_all();
1187 return swrap.libc.symbols._libc_recvmmsg.f(sockfd, msgvec, vlen, flags, timeout);
1191 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1193 swrap_bind_symbol_all();
1195 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1198 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1200 swrap_bind_symbol_all();
1202 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1205 #ifdef HAVE_SENDMMSG
1206 #if defined(HAVE_SENDMMSG_SSIZE_T)
1208 static ssize_t libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags)
1211 static int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
1214 swrap_bind_symbol_all();
1216 return swrap.libc.symbols._libc_sendmmsg.f(sockfd, msgvec, vlen, flags);
1220 static int libc_sendto(int sockfd,
1224 const struct sockaddr *dst_addr,
1227 swrap_bind_symbol_all();
1229 return swrap.libc.symbols._libc_sendto.f(sockfd,
1237 static int libc_setsockopt(int sockfd,
1243 swrap_bind_symbol_all();
1245 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1252 #ifdef HAVE_SIGNALFD
1253 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1255 swrap_bind_symbol_all();
1257 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1261 static int libc_socket(int domain, int type, int protocol)
1263 swrap_bind_symbol_all();
1265 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1268 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1270 swrap_bind_symbol_all();
1272 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1275 #ifdef HAVE_TIMERFD_CREATE
1276 static int libc_timerfd_create(int clockid, int flags)
1278 swrap_bind_symbol_all();
1280 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1284 static ssize_t libc_write(int fd, const void *buf, size_t count)
1286 swrap_bind_symbol_all();
1288 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1291 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1293 swrap_bind_symbol_all();
1295 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1299 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1300 static long int libc_vsyscall(long int sysno, va_list va)
1306 swrap_bind_symbol_all();
1308 for (i = 0; i < 8; i++) {
1309 args[i] = va_arg(va, long int);
1312 rc = swrap.libc.symbols._libc_syscall.f(sysno,
1324 #endif /* HAVE_SYSCALL */
1326 /* DO NOT call this function during library initialization! */
1327 static void __swrap_bind_symbol_all_once(void)
1330 swrap_bind_symbol_libsocket(accept4);
1332 swrap_bind_symbol_libsocket(accept);
1334 swrap_bind_symbol_libsocket(bind);
1335 swrap_bind_symbol_libc(close);
1336 #ifdef HAVE___CLOSE_NOCANCEL
1337 swrap_bind_symbol_libc(__close_nocancel);
1339 swrap_bind_symbol_libsocket(connect);
1340 swrap_bind_symbol_libc(dup);
1341 swrap_bind_symbol_libc(dup2);
1342 swrap_bind_symbol_libc(fcntl);
1343 swrap_bind_symbol_libc(fopen);
1345 swrap_bind_symbol_libc(fopen64);
1348 swrap_bind_symbol_libc(eventfd);
1350 swrap_bind_symbol_libsocket(getpeername);
1351 swrap_bind_symbol_libsocket(getsockname);
1352 swrap_bind_symbol_libsocket(getsockopt);
1353 swrap_bind_symbol_libc(ioctl);
1354 swrap_bind_symbol_libsocket(listen);
1355 swrap_bind_symbol_libc(open);
1357 swrap_bind_symbol_libc(open64);
1359 swrap_bind_symbol_libc(openat);
1360 swrap_bind_symbol_libsocket(pipe);
1361 swrap_bind_symbol_libc(read);
1362 swrap_bind_symbol_libsocket(readv);
1363 swrap_bind_symbol_libsocket(recv);
1364 swrap_bind_symbol_libsocket(recvfrom);
1365 swrap_bind_symbol_libsocket(recvmsg);
1366 #ifdef HAVE_RECVMMSG
1367 swrap_bind_symbol_libsocket(recvmmsg);
1369 swrap_bind_symbol_libsocket(send);
1370 swrap_bind_symbol_libsocket(sendmsg);
1371 #ifdef HAVE_SENDMMSG
1372 swrap_bind_symbol_libsocket(sendmmsg);
1374 swrap_bind_symbol_libsocket(sendto);
1375 swrap_bind_symbol_libsocket(setsockopt);
1376 #ifdef HAVE_SIGNALFD
1377 swrap_bind_symbol_libsocket(signalfd);
1379 swrap_bind_symbol_libsocket(socket);
1380 swrap_bind_symbol_libsocket(socketpair);
1381 #ifdef HAVE_TIMERFD_CREATE
1382 swrap_bind_symbol_libc(timerfd_create);
1384 swrap_bind_symbol_libc(write);
1385 swrap_bind_symbol_libsocket(writev);
1387 swrap_bind_symbol_libc(syscall);
1391 static void swrap_bind_symbol_all(void)
1393 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1395 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1398 /*********************************************************
1399 * SWRAP HELPER FUNCTIONS
1400 *********************************************************/
1403 * We return 127.0.0.0 (default) or 10.53.57.0.
1405 * This can be controlled by:
1406 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1408 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1410 static in_addr_t swrap_ipv4_net(void)
1412 static int initialized;
1413 static in_addr_t hv;
1414 const char *net_str = NULL;
1423 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1424 if (net_str == NULL) {
1425 net_str = "127.0.0.0";
1428 ret = inet_pton(AF_INET, net_str, &nv);
1430 SWRAP_LOG(SWRAP_LOG_ERROR,
1431 "INVALID IPv4 Network [%s]",
1436 hv = ntohl(nv.s_addr);
1446 SWRAP_LOG(SWRAP_LOG_ERROR,
1447 "INVALID IPv4 Network [%s][0x%x] should be "
1448 "127.0.0.0 or 10.53.57.0",
1449 net_str, (unsigned)hv);
1457 * This returns 127.255.255.255 or 10.255.255.255
1459 static in_addr_t swrap_ipv4_bcast(void)
1463 hv = swrap_ipv4_net();
1464 hv |= IN_CLASSA_HOST;
1470 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1472 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1476 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1477 SWRAP_LOG(SWRAP_LOG_ERROR,
1478 "swrap_ipv4_iface(%u) invalid!",
1484 hv = swrap_ipv4_net();
1494 static const struct in6_addr *swrap_ipv6(void)
1496 static struct in6_addr v;
1497 static int initialized;
1505 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1514 static void set_port(int family, int prt, struct swrap_address *addr)
1518 addr->sa.in.sin_port = htons(prt);
1522 addr->sa.in6.sin6_port = htons(prt);
1528 static size_t socket_length(int family)
1532 return sizeof(struct sockaddr_in);
1535 return sizeof(struct sockaddr_in6);
1541 struct swrap_sockaddr_buf {
1545 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1546 const struct sockaddr *saddr)
1548 unsigned int port = 0;
1549 char addr[64] = {0,};
1551 switch (saddr->sa_family) {
1553 const struct sockaddr_in *in =
1554 (const struct sockaddr_in *)(const void *)saddr;
1556 port = ntohs(in->sin_port);
1558 inet_ntop(saddr->sa_family,
1560 addr, sizeof(addr));
1565 const struct sockaddr_in6 *in6 =
1566 (const struct sockaddr_in6 *)(const void *)saddr;
1568 port = ntohs(in6->sin6_port);
1570 inet_ntop(saddr->sa_family,
1572 addr, sizeof(addr));
1577 snprintf(addr, sizeof(addr),
1578 "<Unknown address family %u>",
1583 snprintf(buf->str, sizeof(buf->str),
1584 "addr[%s]/port[%u]",
1590 static struct socket_info *swrap_get_socket_info(int si_index)
1592 return (struct socket_info *)(&(sockets[si_index].info));
1595 static int swrap_get_refcount(struct socket_info *si)
1597 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1598 return sic->meta.refcount;
1601 static void swrap_inc_refcount(struct socket_info *si)
1603 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1605 sic->meta.refcount += 1;
1608 static void swrap_dec_refcount(struct socket_info *si)
1610 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1612 sic->meta.refcount -= 1;
1615 static int swrap_get_next_free(struct socket_info *si)
1617 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1619 return sic->meta.next_free;
1622 static void swrap_set_next_free(struct socket_info *si, int next_free)
1624 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1626 sic->meta.next_free = next_free;
1629 static int swrap_un_path(struct sockaddr_un *un,
1630 const char *swrap_dir,
1637 ret = snprintf(un->sun_path,
1638 sizeof(un->sun_path),
1644 if ((size_t)ret >= sizeof(un->sun_path)) {
1645 return ENAMETOOLONG;
1651 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1652 const char *swrap_dir)
1656 ret = snprintf(un->sun_path,
1657 sizeof(un->sun_path),
1661 if ((size_t)ret >= sizeof(un->sun_path)) {
1662 return ENAMETOOLONG;
1668 static bool swrap_dir_usable(const char *swrap_dir)
1670 struct sockaddr_un un;
1673 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1678 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1686 static char *socket_wrapper_dir(void)
1688 char *swrap_dir = NULL;
1689 char *s = getenv("SOCKET_WRAPPER_DIR");
1693 if (s == NULL || s[0] == '\0') {
1694 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1698 swrap_dir = realpath(s, NULL);
1699 if (swrap_dir == NULL) {
1700 SWRAP_LOG(SWRAP_LOG_ERROR,
1701 "Unable to resolve socket_wrapper dir path: %s - %s",
1707 ok = swrap_dir_usable(swrap_dir);
1714 ok = swrap_dir_usable(s);
1716 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1720 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1722 SWRAP_LOG(SWRAP_LOG_ERROR,
1723 "realpath(SOCKET_WRAPPER_DIR) too long and "
1724 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1729 swrap_dir = strdup(s);
1730 if (swrap_dir == NULL) {
1731 SWRAP_LOG(SWRAP_LOG_ERROR,
1732 "Unable to duplicate socket_wrapper dir path");
1736 SWRAP_LOG(SWRAP_LOG_WARN,
1737 "realpath(SOCKET_WRAPPER_DIR) too long, "
1738 "using original SOCKET_WRAPPER_DIR\n");
1741 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1745 static unsigned int socket_wrapper_mtu(void)
1747 static unsigned int max_mtu = 0;
1752 swrap_mutex_lock(&mtu_update_mutex);
1758 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1760 s = getenv("SOCKET_WRAPPER_MTU");
1765 tmp = strtol(s, &endp, 10);
1770 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1776 swrap_mutex_unlock(&mtu_update_mutex);
1780 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1782 pthread_mutexattr_t ma;
1783 bool need_destroy = false;
1786 #define __CHECK(cmd) do { \
1789 SWRAP_LOG(SWRAP_LOG_ERROR, \
1790 "%s: %s - failed %d", \
1796 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1797 __CHECK(pthread_mutexattr_init(&ma));
1798 need_destroy = true;
1799 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1800 __CHECK(pthread_mutex_init(m, &ma));
1803 pthread_mutexattr_destroy(&ma);
1808 static size_t socket_wrapper_max_sockets(void)
1814 if (socket_info_max != 0) {
1815 return socket_info_max;
1818 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1820 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1821 if (s == NULL || s[0] == '\0') {
1825 tmp = strtoul(s, &endp, 10);
1830 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1831 SWRAP_LOG(SWRAP_LOG_ERROR,
1832 "Invalid number of sockets specified, "
1833 "using default (%zu)",
1837 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1838 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1839 SWRAP_LOG(SWRAP_LOG_ERROR,
1840 "Invalid number of sockets specified, "
1841 "using maximum (%zu).",
1845 socket_info_max = tmp;
1848 return socket_info_max;
1851 static void socket_wrapper_init_fds_idx(void)
1856 if (socket_fds_idx != NULL) {
1860 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1862 SWRAP_LOG(SWRAP_LOG_ERROR,
1863 "Failed to allocate socket fds index array: %s",
1868 for (i = 0; i < socket_fds_max; i++) {
1872 socket_fds_idx = tmp;
1875 static void socket_wrapper_init_sockets(void)
1881 swrap_bind_symbol_all();
1883 swrap_mutex_lock(&sockets_mutex);
1885 if (sockets != NULL) {
1886 swrap_mutex_unlock(&sockets_mutex);
1890 SWRAP_LOG(SWRAP_LOG_DEBUG,
1891 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1892 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1895 * Intialize the static cache early before
1896 * any thread is able to start.
1898 (void)swrap_ipv4_net();
1900 socket_wrapper_init_fds_idx();
1902 /* Needs to be called inside the sockets_mutex lock here. */
1903 max_sockets = socket_wrapper_max_sockets();
1905 sockets = (struct socket_info_container *)calloc(max_sockets,
1906 sizeof(struct socket_info_container));
1908 if (sockets == NULL) {
1909 SWRAP_LOG(SWRAP_LOG_ERROR,
1910 "Failed to allocate sockets array: %s",
1912 swrap_mutex_unlock(&sockets_mutex);
1916 swrap_mutex_lock(&first_free_mutex);
1917 swrap_mutex_lock(&sockets_si_global);
1921 for (i = 0; i < max_sockets; i++) {
1922 swrap_set_next_free(&sockets[i].info, i+1);
1925 /* mark the end of the free list */
1926 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1928 swrap_mutex_unlock(&sockets_si_global);
1929 swrap_mutex_unlock(&first_free_mutex);
1930 swrap_mutex_unlock(&sockets_mutex);
1936 bool socket_wrapper_enabled(void)
1938 char *s = socket_wrapper_dir();
1946 socket_wrapper_init_sockets();
1951 static unsigned int socket_wrapper_default_iface(void)
1953 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1956 if (sscanf(s, "%u", &iface) == 1) {
1957 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1963 return 1;/* 127.0.0.1 */
1966 static void set_socket_info_index(int fd, int idx)
1968 SWRAP_LOG(SWRAP_LOG_TRACE,
1971 socket_fds_idx[fd] = idx;
1972 /* This builtin issues a full memory barrier. */
1973 __sync_synchronize();
1976 static void reset_socket_info_index(int fd)
1978 SWRAP_LOG(SWRAP_LOG_TRACE,
1981 set_socket_info_index(fd, -1);
1984 static int find_socket_info_index(int fd)
1990 if (socket_fds_idx == NULL) {
1994 if ((size_t)fd >= socket_fds_max) {
1996 * Do not add a log here as some applications do stupid things
1999 * for (fd = 0; fd <= getdtablesize(); fd++) {
2003 * This would produce millions of lines of debug messages.
2006 SWRAP_LOG(SWRAP_LOG_ERROR,
2007 "Looking for a socket info for the fd %d is over the "
2008 "max socket index limit of %zu.",
2015 /* This builtin issues a full memory barrier. */
2016 __sync_synchronize();
2017 return socket_fds_idx[fd];
2020 static int swrap_add_socket_info(const struct socket_info *si_input)
2022 struct socket_info *si = NULL;
2025 if (si_input == NULL) {
2030 swrap_mutex_lock(&first_free_mutex);
2031 if (first_free == -1) {
2036 si_index = first_free;
2037 si = swrap_get_socket_info(si_index);
2041 first_free = swrap_get_next_free(si);
2043 swrap_inc_refcount(si);
2045 SWRAP_UNLOCK_SI(si);
2048 swrap_mutex_unlock(&first_free_mutex);
2053 static int swrap_create_socket(struct socket_info *si, int fd)
2057 if ((size_t)fd >= socket_fds_max) {
2058 SWRAP_LOG(SWRAP_LOG_ERROR,
2059 "The max socket index limit of %zu has been reached, "
2067 idx = swrap_add_socket_info(si);
2072 set_socket_info_index(fd, idx);
2077 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2084 p = strrchr(un->sun_path, '/');
2085 if (p) p++; else p = un->sun_path;
2087 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2088 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2094 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2095 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2102 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2108 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2112 case SOCKET_TYPE_CHAR_TCP:
2113 case SOCKET_TYPE_CHAR_UDP: {
2114 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2116 if ((*len) < sizeof(*in2)) {
2117 SWRAP_LOG(SWRAP_LOG_ERROR,
2118 "V4: *len(%zu) < sizeof(*in2)=%zu",
2119 (size_t)*len, sizeof(*in2));
2124 memset(in2, 0, sizeof(*in2));
2125 in2->sin_family = AF_INET;
2126 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2127 in2->sin_port = htons(prt);
2129 *len = sizeof(*in2);
2133 case SOCKET_TYPE_CHAR_TCP_V6:
2134 case SOCKET_TYPE_CHAR_UDP_V6: {
2135 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2137 if ((*len) < sizeof(*in2)) {
2138 SWRAP_LOG(SWRAP_LOG_ERROR,
2139 "V6: *len(%zu) < sizeof(*in2)=%zu",
2140 (size_t)*len, sizeof(*in2));
2141 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2146 memset(in2, 0, sizeof(*in2));
2147 in2->sin6_family = AF_INET6;
2148 in2->sin6_addr = *swrap_ipv6();
2149 in2->sin6_addr.s6_addr[15] = iface;
2150 in2->sin6_port = htons(prt);
2152 *len = sizeof(*in2);
2157 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2166 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2173 char *swrap_dir = NULL;
2175 if (bcast) *bcast = 0;
2177 switch (inaddr->sa_family) {
2179 const struct sockaddr_in *in =
2180 (const struct sockaddr_in *)(const void *)inaddr;
2181 unsigned int addr = ntohl(in->sin_addr.s_addr);
2185 const unsigned int sw_net_addr = swrap_ipv4_net();
2186 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2190 u_type = SOCKET_TYPE_CHAR_TCP;
2193 u_type = SOCKET_TYPE_CHAR_UDP;
2194 a_type = SOCKET_TYPE_CHAR_UDP;
2195 b_type = SOCKET_TYPE_CHAR_UDP;
2198 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2199 errno = ESOCKTNOSUPPORT;
2203 prt = ntohs(in->sin_port);
2204 if (a_type && addr == 0xFFFFFFFF) {
2205 /* 255.255.255.255 only udp */
2208 iface = socket_wrapper_default_iface();
2209 } else if (b_type && addr == sw_bcast_addr) {
2218 iface = socket_wrapper_default_iface();
2219 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2220 /* 127.0.0.X or 10.53.57.X */
2223 iface = (addr & 0x000000FF);
2225 struct swrap_sockaddr_buf buf = {};
2226 SWRAP_LOG(SWRAP_LOG_WARN,
2228 swrap_sockaddr_string(&buf, inaddr));
2229 errno = ENETUNREACH;
2232 if (bcast) *bcast = is_bcast;
2237 const struct sockaddr_in6 *in =
2238 (const struct sockaddr_in6 *)(const void *)inaddr;
2239 struct in6_addr cmp1, cmp2;
2243 type = SOCKET_TYPE_CHAR_TCP_V6;
2246 type = SOCKET_TYPE_CHAR_UDP_V6;
2249 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2250 errno = ESOCKTNOSUPPORT;
2254 /* XXX no multicast/broadcast */
2256 prt = ntohs(in->sin6_port);
2258 cmp1 = *swrap_ipv6();
2259 cmp2 = in->sin6_addr;
2260 cmp2.s6_addr[15] = 0;
2261 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2262 iface = in->sin6_addr.s6_addr[15];
2264 struct swrap_sockaddr_buf buf = {};
2265 SWRAP_LOG(SWRAP_LOG_WARN,
2267 swrap_sockaddr_string(&buf, inaddr));
2268 errno = ENETUNREACH;
2276 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2277 errno = ENETUNREACH;
2282 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2287 swrap_dir = socket_wrapper_dir();
2288 if (swrap_dir == NULL) {
2294 swrap_un_path_EINVAL(un, swrap_dir);
2295 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2296 SAFE_FREE(swrap_dir);
2297 /* the caller need to do more processing */
2301 swrap_un_path(un, swrap_dir, type, iface, prt);
2302 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2304 SAFE_FREE(swrap_dir);
2309 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2317 char *swrap_dir = NULL;
2319 if (bcast) *bcast = 0;
2321 switch (si->family) {
2323 const struct sockaddr_in *in =
2324 (const struct sockaddr_in *)(const void *)inaddr;
2325 unsigned int addr = ntohl(in->sin_addr.s_addr);
2330 const unsigned int sw_net_addr = swrap_ipv4_net();
2331 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2333 prt = ntohs(in->sin_port);
2337 u_type = SOCKET_TYPE_CHAR_TCP;
2338 d_type = SOCKET_TYPE_CHAR_TCP;
2341 u_type = SOCKET_TYPE_CHAR_UDP;
2342 d_type = SOCKET_TYPE_CHAR_UDP;
2343 a_type = SOCKET_TYPE_CHAR_UDP;
2344 b_type = SOCKET_TYPE_CHAR_UDP;
2347 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2348 errno = ESOCKTNOSUPPORT;
2356 iface = socket_wrapper_default_iface();
2357 } else if (a_type && addr == 0xFFFFFFFF) {
2358 /* 255.255.255.255 only udp */
2361 iface = socket_wrapper_default_iface();
2362 } else if (b_type && addr == sw_bcast_addr) {
2363 /* 127.255.255.255 only udp */
2366 iface = socket_wrapper_default_iface();
2367 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2371 iface = (addr & 0x000000FF);
2373 errno = EADDRNOTAVAIL;
2377 /* Store the bind address for connect() */
2378 if (si->bindname.sa_socklen == 0) {
2379 struct sockaddr_in bind_in;
2380 socklen_t blen = sizeof(struct sockaddr_in);
2382 ZERO_STRUCT(bind_in);
2383 bind_in.sin_family = in->sin_family;
2384 bind_in.sin_port = in->sin_port;
2385 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2386 si->bindname.sa_socklen = blen;
2387 memcpy(&si->bindname.sa.in, &bind_in, blen);
2394 const struct sockaddr_in6 *in =
2395 (const struct sockaddr_in6 *)(const void *)inaddr;
2396 struct in6_addr cmp1, cmp2;
2400 type = SOCKET_TYPE_CHAR_TCP_V6;
2403 type = SOCKET_TYPE_CHAR_UDP_V6;
2406 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2407 errno = ESOCKTNOSUPPORT;
2411 /* XXX no multicast/broadcast */
2413 prt = ntohs(in->sin6_port);
2415 cmp1 = *swrap_ipv6();
2416 cmp2 = in->sin6_addr;
2417 cmp2.s6_addr[15] = 0;
2418 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2419 iface = socket_wrapper_default_iface();
2420 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2421 iface = in->sin6_addr.s6_addr[15];
2423 errno = EADDRNOTAVAIL;
2427 /* Store the bind address for connect() */
2428 if (si->bindname.sa_socklen == 0) {
2429 struct sockaddr_in6 bind_in;
2430 socklen_t blen = sizeof(struct sockaddr_in6);
2432 ZERO_STRUCT(bind_in);
2433 bind_in.sin6_family = in->sin6_family;
2434 bind_in.sin6_port = in->sin6_port;
2436 bind_in.sin6_addr = *swrap_ipv6();
2437 bind_in.sin6_addr.s6_addr[15] = iface;
2439 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2440 si->bindname.sa_socklen = blen;
2447 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2448 errno = EADDRNOTAVAIL;
2453 if (bcast) *bcast = is_bcast;
2455 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2460 swrap_dir = socket_wrapper_dir();
2461 if (swrap_dir == NULL) {
2467 /* handle auto-allocation of ephemeral ports */
2468 for (prt = 5001; prt < 10000; prt++) {
2469 swrap_un_path(un, swrap_dir, type, iface, prt);
2470 if (stat(un->sun_path, &st) == 0) continue;
2472 set_port(si->family, prt, &si->myname);
2473 set_port(si->family, prt, &si->bindname);
2480 SAFE_FREE(swrap_dir);
2485 swrap_un_path(un, swrap_dir, type, iface, prt);
2486 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2488 SAFE_FREE(swrap_dir);
2493 static struct socket_info *find_socket_info(int fd)
2495 int idx = find_socket_info_index(fd);
2501 return swrap_get_socket_info(idx);
2505 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2507 struct socket_info_fd *f;
2508 const struct socket_info *last_s = NULL;
2510 /* first catch invalid input */
2511 switch (sa->sa_family) {
2513 if (len < sizeof(struct sockaddr_in)) {
2519 if (len < sizeof(struct sockaddr_in6)) {
2529 for (f = socket_fds; f; f = f->next) {
2530 struct socket_info *s = swrap_get_socket_info(f->si_index);
2537 if (s->myname == NULL) {
2540 if (s->myname->sa_family != sa->sa_family) {
2543 switch (s->myname->sa_family) {
2545 struct sockaddr_in *sin1, *sin2;
2547 sin1 = (struct sockaddr_in *)s->myname;
2548 sin2 = (struct sockaddr_in *)sa;
2550 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2553 if (sin1->sin_port != sin2->sin_port) {
2556 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2566 struct sockaddr_in6 *sin1, *sin2;
2568 sin1 = (struct sockaddr_in6 *)s->myname;
2569 sin2 = (struct sockaddr_in6 *)sa;
2571 if (sin1->sin6_port != sin2->sin6_port) {
2574 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2596 static void swrap_remove_stale(int fd);
2598 static int sockaddr_convert_to_un(struct socket_info *si,
2599 const struct sockaddr *in_addr,
2601 struct sockaddr_un *out_addr,
2605 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2607 (void) in_len; /* unused */
2609 if (out_addr == NULL) {
2613 out->sa_family = AF_UNIX;
2614 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2615 out->sa_len = sizeof(*out_addr);
2618 switch (in_addr->sa_family) {
2620 const struct sockaddr_in *sin;
2621 if (si->family != AF_INET) {
2624 if (in_len < sizeof(struct sockaddr_in)) {
2627 sin = (const struct sockaddr_in *)(const void *)in_addr;
2628 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2633 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2634 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2648 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2649 errno = ESOCKTNOSUPPORT;
2653 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2655 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2661 errno = EAFNOSUPPORT;
2662 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2666 static int sockaddr_convert_from_un(const struct socket_info *si,
2667 const struct sockaddr_un *in_addr,
2668 socklen_t un_addrlen,
2670 struct sockaddr *out_addr,
2671 socklen_t *out_addrlen)
2675 if (out_addr == NULL || out_addrlen == NULL)
2678 if (un_addrlen == 0) {
2693 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2694 errno = ESOCKTNOSUPPORT;
2697 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2698 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2699 out_addr->sa_len = *out_addrlen;
2706 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2707 errno = EAFNOSUPPORT;
2711 enum swrap_packet_type {
2713 SWRAP_CONNECT_UNREACH,
2721 SWRAP_SENDTO_UNREACH,
2732 struct swrap_file_hdr {
2734 uint16_t version_major;
2735 uint16_t version_minor;
2738 uint32_t frame_max_len;
2739 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2742 #define SWRAP_FILE_HDR_SIZE 24
2744 struct swrap_packet_frame {
2746 uint32_t micro_seconds;
2747 uint32_t recorded_length;
2748 uint32_t full_length;
2750 #define SWRAP_PACKET_FRAME_SIZE 16
2752 union swrap_packet_ip {
2756 uint16_t packet_length;
2757 uint16_t identification;
2762 uint16_t hdr_checksum;
2766 #define SWRAP_PACKET_IP_V4_SIZE 20
2769 uint8_t flow_label_high;
2770 uint16_t flow_label_low;
2771 uint16_t payload_length;
2772 uint8_t next_header;
2774 uint8_t src_addr[16];
2775 uint8_t dest_addr[16];
2777 #define SWRAP_PACKET_IP_V6_SIZE 40
2779 #define SWRAP_PACKET_IP_SIZE 40
2781 union swrap_packet_payload {
2783 uint16_t source_port;
2793 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2795 uint16_t source_port;
2800 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2807 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2814 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2816 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2818 #define SWRAP_PACKET_MIN_ALLOC \
2819 (SWRAP_PACKET_FRAME_SIZE + \
2820 SWRAP_PACKET_IP_SIZE + \
2821 SWRAP_PACKET_PAYLOAD_SIZE)
2823 static const char *swrap_pcap_init_file(void)
2825 static int initialized = 0;
2826 static const char *s = NULL;
2827 static const struct swrap_file_hdr h;
2828 static const struct swrap_packet_frame f;
2829 static const union swrap_packet_ip i;
2830 static const union swrap_packet_payload p;
2832 if (initialized == 1) {
2838 * TODO: don't use the structs use plain buffer offsets
2839 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2841 * for now make sure we disable PCAP support
2842 * if the struct has alignment!
2844 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2847 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2850 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2853 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2856 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2859 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2862 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2865 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2868 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2871 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2875 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2879 if (strncmp(s, "./", 2) == 0) {
2882 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2886 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2887 const struct sockaddr *src,
2888 const struct sockaddr *dest,
2890 const uint8_t *payload,
2892 unsigned long tcp_seqno,
2893 unsigned long tcp_ack,
2894 unsigned char tcp_ctl,
2896 size_t *_packet_len)
2898 uint8_t *base = NULL;
2899 uint8_t *buf = NULL;
2902 struct swrap_packet_frame *frame;
2906 union swrap_packet_ip *ip;
2908 union swrap_packet_payload *pay;
2911 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2912 size_t wire_hdr_len = 0;
2913 size_t wire_len = 0;
2914 size_t ip_hdr_len = 0;
2915 size_t icmp_hdr_len = 0;
2916 size_t icmp_truncate_len = 0;
2917 uint8_t protocol = 0, icmp_protocol = 0;
2918 const struct sockaddr_in *src_in = NULL;
2919 const struct sockaddr_in *dest_in = NULL;
2921 const struct sockaddr_in6 *src_in6 = NULL;
2922 const struct sockaddr_in6 *dest_in6 = NULL;
2927 switch (src->sa_family) {
2929 src_in = (const struct sockaddr_in *)(const void *)src;
2930 dest_in = (const struct sockaddr_in *)(const void *)dest;
2931 src_port = src_in->sin_port;
2932 dest_port = dest_in->sin_port;
2933 ip_hdr_len = sizeof(i.ip->v4);
2937 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2938 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2939 src_port = src_in6->sin6_port;
2940 dest_port = dest_in6->sin6_port;
2941 ip_hdr_len = sizeof(i.ip->v6);
2948 switch (socket_type) {
2950 protocol = 0x06; /* TCP */
2951 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2952 wire_len = wire_hdr_len + payload_len;
2956 protocol = 0x11; /* UDP */
2957 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2958 wire_len = wire_hdr_len + payload_len;
2966 icmp_protocol = protocol;
2967 switch (src->sa_family) {
2969 protocol = 0x01; /* ICMPv4 */
2970 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2974 protocol = 0x3A; /* ICMPv6 */
2975 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2979 if (wire_len > 64 ) {
2980 icmp_truncate_len = wire_len - 64;
2982 wire_len += icmp_hdr_len;
2985 packet_len = nonwire_len + wire_len;
2986 alloc_len = packet_len;
2987 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2988 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2991 base = (uint8_t *)calloc(1, alloc_len);
2999 f.frame->seconds = tval->tv_sec;
3000 f.frame->micro_seconds = tval->tv_usec;
3001 f.frame->recorded_length = wire_len - icmp_truncate_len;
3002 f.frame->full_length = wire_len - icmp_truncate_len;
3004 buf += SWRAP_PACKET_FRAME_SIZE;
3007 switch (src->sa_family) {
3009 if (src_in == NULL || dest_in == NULL) {
3014 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3015 i.ip->v4.tos = 0x00;
3016 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
3017 i.ip->v4.identification = htons(0xFFFF);
3018 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3019 i.ip->v4.fragment = htons(0x0000);
3020 i.ip->v4.ttl = 0xFF;
3021 i.ip->v4.protocol = protocol;
3022 i.ip->v4.hdr_checksum = htons(0x0000);
3023 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
3024 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
3025 buf += SWRAP_PACKET_IP_V4_SIZE;
3029 if (src_in6 == NULL || dest_in6 == NULL) {
3034 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3035 i.ip->v6.flow_label_high = 0x00;
3036 i.ip->v6.flow_label_low = 0x0000;
3037 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3038 i.ip->v6.next_header = protocol;
3039 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
3040 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
3041 buf += SWRAP_PACKET_IP_V6_SIZE;
3047 pay = (union swrap_packet_payload *)(void *)buf;
3048 switch (src->sa_family) {
3050 pay->icmp4.type = 0x03; /* destination unreachable */
3051 pay->icmp4.code = 0x01; /* host unreachable */
3052 pay->icmp4.checksum = htons(0x0000);
3053 pay->icmp4.unused = htonl(0x00000000);
3055 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3057 /* set the ip header in the ICMP payload */
3059 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3060 i.ip->v4.tos = 0x00;
3061 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3062 i.ip->v4.identification = htons(0xFFFF);
3063 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3064 i.ip->v4.fragment = htons(0x0000);
3065 i.ip->v4.ttl = 0xFF;
3066 i.ip->v4.protocol = icmp_protocol;
3067 i.ip->v4.hdr_checksum = htons(0x0000);
3068 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3069 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3071 buf += SWRAP_PACKET_IP_V4_SIZE;
3073 src_port = dest_in->sin_port;
3074 dest_port = src_in->sin_port;
3078 pay->icmp6.type = 0x01; /* destination unreachable */
3079 pay->icmp6.code = 0x03; /* address unreachable */
3080 pay->icmp6.checksum = htons(0x0000);
3081 pay->icmp6.unused = htonl(0x00000000);
3082 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3084 /* set the ip header in the ICMP payload */
3086 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3087 i.ip->v6.flow_label_high = 0x00;
3088 i.ip->v6.flow_label_low = 0x0000;
3089 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3090 i.ip->v6.next_header = protocol;
3091 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3092 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3094 buf += SWRAP_PACKET_IP_V6_SIZE;
3096 src_port = dest_in6->sin6_port;
3097 dest_port = src_in6->sin6_port;
3103 pay = (union swrap_packet_payload *)(void *)buf;
3105 switch (socket_type) {
3107 pay->tcp.source_port = src_port;
3108 pay->tcp.dest_port = dest_port;
3109 pay->tcp.seq_num = htonl(tcp_seqno);
3110 pay->tcp.ack_num = htonl(tcp_ack);
3111 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3112 pay->tcp.control = tcp_ctl;
3113 pay->tcp.window = htons(0x7FFF);
3114 pay->tcp.checksum = htons(0x0000);
3115 pay->tcp.urg = htons(0x0000);
3116 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3121 pay->udp.source_port = src_port;
3122 pay->udp.dest_port = dest_port;
3123 pay->udp.length = htons(8 + payload_len);
3124 pay->udp.checksum = htons(0x0000);
3125 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3130 if (payload && payload_len > 0) {
3131 memcpy(buf, payload, payload_len);
3134 *_packet_len = packet_len - icmp_truncate_len;
3138 static int swrap_pcap_get_fd(const char *fname)
3146 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3148 struct swrap_file_hdr file_hdr;
3149 file_hdr.magic = 0xA1B2C3D4;
3150 file_hdr.version_major = 0x0002;
3151 file_hdr.version_minor = 0x0004;
3152 file_hdr.timezone = 0x00000000;
3153 file_hdr.sigfigs = 0x00000000;
3154 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3155 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3157 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3164 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3169 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3170 const struct sockaddr *addr,
3171 enum swrap_packet_type type,
3172 const void *buf, size_t len,
3175 const struct sockaddr *src_addr;
3176 const struct sockaddr *dest_addr;
3177 unsigned long tcp_seqno = 0;
3178 unsigned long tcp_ack = 0;
3179 unsigned char tcp_ctl = 0;
3180 int unreachable = 0;
3184 switch (si->family) {
3196 case SWRAP_CONNECT_SEND:
3197 if (si->type != SOCK_STREAM) {
3201 src_addr = &si->myname.sa.s;
3204 tcp_seqno = si->io.pck_snd;
3205 tcp_ack = si->io.pck_rcv;
3206 tcp_ctl = 0x02; /* SYN */
3208 si->io.pck_snd += 1;
3212 case SWRAP_CONNECT_RECV:
3213 if (si->type != SOCK_STREAM) {
3217 dest_addr = &si->myname.sa.s;
3220 tcp_seqno = si->io.pck_rcv;
3221 tcp_ack = si->io.pck_snd;
3222 tcp_ctl = 0x12; /** SYN,ACK */
3224 si->io.pck_rcv += 1;
3228 case SWRAP_CONNECT_UNREACH:
3229 if (si->type != SOCK_STREAM) {
3233 dest_addr = &si->myname.sa.s;
3236 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3237 tcp_seqno = si->io.pck_snd - 1;
3238 tcp_ack = si->io.pck_rcv;
3239 tcp_ctl = 0x02; /* SYN */
3244 case SWRAP_CONNECT_ACK:
3245 if (si->type != SOCK_STREAM) {
3249 src_addr = &si->myname.sa.s;
3252 tcp_seqno = si->io.pck_snd;
3253 tcp_ack = si->io.pck_rcv;
3254 tcp_ctl = 0x10; /* ACK */
3258 case SWRAP_ACCEPT_SEND:
3259 if (si->type != SOCK_STREAM) {
3263 dest_addr = &si->myname.sa.s;
3266 tcp_seqno = si->io.pck_rcv;
3267 tcp_ack = si->io.pck_snd;
3268 tcp_ctl = 0x02; /* SYN */
3270 si->io.pck_rcv += 1;
3274 case SWRAP_ACCEPT_RECV:
3275 if (si->type != SOCK_STREAM) {
3279 src_addr = &si->myname.sa.s;
3282 tcp_seqno = si->io.pck_snd;
3283 tcp_ack = si->io.pck_rcv;
3284 tcp_ctl = 0x12; /* SYN,ACK */
3286 si->io.pck_snd += 1;
3290 case SWRAP_ACCEPT_ACK:
3291 if (si->type != SOCK_STREAM) {
3295 dest_addr = &si->myname.sa.s;
3298 tcp_seqno = si->io.pck_rcv;
3299 tcp_ack = si->io.pck_snd;
3300 tcp_ctl = 0x10; /* ACK */
3305 src_addr = &si->myname.sa.s;
3306 dest_addr = &si->peername.sa.s;
3308 tcp_seqno = si->io.pck_snd;
3309 tcp_ack = si->io.pck_rcv;
3310 tcp_ctl = 0x18; /* PSH,ACK */
3312 si->io.pck_snd += len;
3316 case SWRAP_SEND_RST:
3317 dest_addr = &si->myname.sa.s;
3318 src_addr = &si->peername.sa.s;
3320 if (si->type == SOCK_DGRAM) {
3321 return swrap_pcap_marshall_packet(si,
3323 SWRAP_SENDTO_UNREACH,
3329 tcp_seqno = si->io.pck_rcv;
3330 tcp_ack = si->io.pck_snd;
3331 tcp_ctl = 0x14; /** RST,ACK */
3335 case SWRAP_PENDING_RST:
3336 dest_addr = &si->myname.sa.s;
3337 src_addr = &si->peername.sa.s;
3339 if (si->type == SOCK_DGRAM) {
3343 tcp_seqno = si->io.pck_rcv;
3344 tcp_ack = si->io.pck_snd;
3345 tcp_ctl = 0x14; /* RST,ACK */
3350 dest_addr = &si->myname.sa.s;
3351 src_addr = &si->peername.sa.s;
3353 tcp_seqno = si->io.pck_rcv;
3354 tcp_ack = si->io.pck_snd;
3355 tcp_ctl = 0x18; /* PSH,ACK */
3357 si->io.pck_rcv += len;
3361 case SWRAP_RECV_RST:
3362 dest_addr = &si->myname.sa.s;
3363 src_addr = &si->peername.sa.s;
3365 if (si->type == SOCK_DGRAM) {
3369 tcp_seqno = si->io.pck_rcv;
3370 tcp_ack = si->io.pck_snd;
3371 tcp_ctl = 0x14; /* RST,ACK */
3376 src_addr = &si->myname.sa.s;
3379 si->io.pck_snd += len;
3383 case SWRAP_SENDTO_UNREACH:
3384 dest_addr = &si->myname.sa.s;
3391 case SWRAP_RECVFROM:
3392 dest_addr = &si->myname.sa.s;
3395 si->io.pck_rcv += len;
3399 case SWRAP_CLOSE_SEND:
3400 if (si->type != SOCK_STREAM) {
3404 src_addr = &si->myname.sa.s;
3405 dest_addr = &si->peername.sa.s;
3407 tcp_seqno = si->io.pck_snd;
3408 tcp_ack = si->io.pck_rcv;
3409 tcp_ctl = 0x11; /* FIN, ACK */
3411 si->io.pck_snd += 1;
3415 case SWRAP_CLOSE_RECV:
3416 if (si->type != SOCK_STREAM) {
3420 dest_addr = &si->myname.sa.s;
3421 src_addr = &si->peername.sa.s;
3423 tcp_seqno = si->io.pck_rcv;
3424 tcp_ack = si->io.pck_snd;
3425 tcp_ctl = 0x11; /* FIN,ACK */
3427 si->io.pck_rcv += 1;
3431 case SWRAP_CLOSE_ACK:
3432 if (si->type != SOCK_STREAM) {
3436 src_addr = &si->myname.sa.s;
3437 dest_addr = &si->peername.sa.s;
3439 tcp_seqno = si->io.pck_snd;
3440 tcp_ack = si->io.pck_rcv;
3441 tcp_ctl = 0x10; /* ACK */
3448 swrapGetTimeOfDay(&tv);
3450 return swrap_pcap_packet_init(&tv,
3454 (const uint8_t *)buf,
3463 static void swrap_pcap_dump_packet(struct socket_info *si,
3464 const struct sockaddr *addr,
3465 enum swrap_packet_type type,
3466 const void *buf, size_t len)
3468 const char *file_name;
3470 size_t packet_len = 0;
3473 swrap_mutex_lock(&pcap_dump_mutex);
3475 file_name = swrap_pcap_init_file();
3480 packet = swrap_pcap_marshall_packet(si,
3486 if (packet == NULL) {
3490 fd = swrap_pcap_get_fd(file_name);
3492 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3501 swrap_mutex_unlock(&pcap_dump_mutex);
3504 /****************************************************************************
3506 ***************************************************************************/
3508 #ifdef HAVE_SIGNALFD
3509 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3513 rc = libc_signalfd(fd, mask, flags);
3515 swrap_remove_stale(fd);
3521 int signalfd(int fd, const sigset_t *mask, int flags)
3523 return swrap_signalfd(fd, mask, flags);
3527 /****************************************************************************
3529 ***************************************************************************/
3531 static int swrap_socket(int family, int type, int protocol)
3533 struct socket_info *si = NULL;
3534 struct socket_info _si = { 0 };
3537 int real_type = type;
3540 * Remove possible addition flags passed to socket() so
3541 * do not fail checking the type.
3542 * See https://lwn.net/Articles/281965/
3545 real_type &= ~SOCK_CLOEXEC;
3547 #ifdef SOCK_NONBLOCK
3548 real_type &= ~SOCK_NONBLOCK;
3551 if (!socket_wrapper_enabled()) {
3552 return libc_socket(family, type, protocol);
3563 #endif /* AF_NETLINK */
3566 #endif /* AF_PACKET */
3568 fd = libc_socket(family, type, protocol);
3570 /* Check if we have a stale fd and remove it */
3571 swrap_remove_stale(fd);
3572 SWRAP_LOG(SWRAP_LOG_TRACE,
3573 "Unix socket fd=%d",
3578 errno = EAFNOSUPPORT;
3582 switch (real_type) {
3588 errno = EPROTONOSUPPORT;
3596 if (real_type == SOCK_STREAM) {
3601 if (real_type == SOCK_DGRAM) {
3606 errno = EPROTONOSUPPORT;
3611 * We must call libc_socket with type, from the caller, not the version
3612 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3614 fd = libc_socket(AF_UNIX, type, 0);
3620 /* Check if we have a stale fd and remove it */
3621 swrap_remove_stale(fd);
3624 si->family = family;
3626 /* however, the rest of the socket_wrapper code expects just
3627 * the type, not the flags */
3628 si->type = real_type;
3629 si->protocol = protocol;
3632 * Setup myname so getsockname() can succeed to find out the socket
3635 switch(si->family) {
3637 struct sockaddr_in sin = {
3638 .sin_family = AF_INET,
3641 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3642 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3647 struct sockaddr_in6 sin6 = {
3648 .sin6_family = AF_INET6,
3651 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3652 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3661 ret = swrap_create_socket(si, fd);
3663 int saved_errno = errno;
3665 errno = saved_errno;
3669 SWRAP_LOG(SWRAP_LOG_TRACE,
3670 "Created %s socket for protocol %s, fd=%d",
3671 family == AF_INET ? "IPv4" : "IPv6",
3672 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3678 int socket(int family, int type, int protocol)
3680 return swrap_socket(family, type, protocol);
3683 /****************************************************************************
3685 ***************************************************************************/
3687 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3691 rc = libc_socketpair(family, type, protocol, sv);
3693 swrap_remove_stale(sv[0]);
3694 swrap_remove_stale(sv[1]);
3700 int socketpair(int family, int type, int protocol, int sv[2])
3702 return swrap_socketpair(family, type, protocol, sv);
3705 /****************************************************************************
3707 ***************************************************************************/
3709 #ifdef HAVE_TIMERFD_CREATE
3710 static int swrap_timerfd_create(int clockid, int flags)
3714 fd = libc_timerfd_create(clockid, flags);
3716 swrap_remove_stale(fd);
3722 int timerfd_create(int clockid, int flags)
3724 return swrap_timerfd_create(clockid, flags);
3728 /****************************************************************************
3730 ***************************************************************************/
3732 static int swrap_pipe(int pipefd[2])
3736 rc = libc_pipe(pipefd);
3738 swrap_remove_stale(pipefd[0]);
3739 swrap_remove_stale(pipefd[1]);
3745 int pipe(int pipefd[2])
3747 return swrap_pipe(pipefd);
3750 /****************************************************************************
3752 ***************************************************************************/
3754 static int swrap_accept(int s,
3755 struct sockaddr *addr,
3759 struct socket_info *parent_si, *child_si;
3760 struct socket_info new_si = { 0 };
3763 struct swrap_address un_addr = {
3764 .sa_socklen = sizeof(struct sockaddr_un),
3766 struct swrap_address un_my_addr = {
3767 .sa_socklen = sizeof(struct sockaddr_un),
3769 struct swrap_address in_addr = {
3770 .sa_socklen = sizeof(struct sockaddr_storage),
3772 struct swrap_address in_my_addr = {
3773 .sa_socklen = sizeof(struct sockaddr_storage),
3777 parent_si = find_socket_info(s);
3780 return libc_accept4(s, addr, addrlen, flags);
3783 return libc_accept(s, addr, addrlen);
3789 * prevent parent_si from being altered / closed
3792 SWRAP_LOCK_SI(parent_si);
3795 * assume out sockaddr have the same size as the in parent
3798 in_addr.sa_socklen = socket_length(parent_si->family);
3799 if (in_addr.sa_socklen <= 0) {
3800 SWRAP_UNLOCK_SI(parent_si);
3805 SWRAP_UNLOCK_SI(parent_si);
3808 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3811 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3814 int saved_errno = errno;
3815 if (saved_errno == ENOTSOCK) {
3816 /* Remove stale fds */
3817 swrap_remove_stale(s);
3819 errno = saved_errno;
3825 /* Check if we have a stale fd and remove it */
3826 swrap_remove_stale(fd);
3828 if (un_addr.sa.un.sun_path[0] == '\0') {
3830 * FreeBSD seems to have a problem where
3831 * accept4() on the unix socket doesn't
3832 * ECONNABORTED for already disconnected connections.
3834 * Let's try libc_getpeername() to get the peer address
3835 * as a fallback, but it'll likely return ENOTCONN,
3836 * which we have to map to ECONNABORTED.
3838 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3839 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3841 int saved_errno = errno;
3843 if (saved_errno == ENOTCONN) {
3845 * If the connection is already disconnected
3846 * we should return ECONNABORTED.
3848 saved_errno = ECONNABORTED;
3850 errno = saved_errno;
3855 ret = libc_getsockname(fd,
3857 &un_my_addr.sa_socklen);
3859 int saved_errno = errno;
3861 if (saved_errno == ENOTCONN) {
3863 * If the connection is already disconnected
3864 * we should return ECONNABORTED.
3866 saved_errno = ECONNABORTED;
3868 errno = saved_errno;
3872 SWRAP_LOCK_SI(parent_si);
3874 ret = sockaddr_convert_from_un(parent_si,
3879 &in_addr.sa_socklen);
3881 int saved_errno = errno;
3882 SWRAP_UNLOCK_SI(parent_si);
3884 errno = saved_errno;
3890 child_si->family = parent_si->family;
3891 child_si->type = parent_si->type;
3892 child_si->protocol = parent_si->protocol;
3893 child_si->bound = 1;
3894 child_si->is_server = 1;
3895 child_si->connected = 1;
3897 SWRAP_UNLOCK_SI(parent_si);
3899 child_si->peername = (struct swrap_address) {
3900 .sa_socklen = in_addr.sa_socklen,
3902 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3904 if (addr != NULL && addrlen != NULL) {
3905 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3907 memcpy(addr, &in_addr.sa.ss, copy_len);
3909 *addrlen = in_addr.sa_socklen;
3912 ret = sockaddr_convert_from_un(child_si,
3914 un_my_addr.sa_socklen,
3917 &in_my_addr.sa_socklen);
3919 int saved_errno = errno;
3921 errno = saved_errno;
3925 SWRAP_LOG(SWRAP_LOG_TRACE,
3926 "accept() path=%s, fd=%d",
3927 un_my_addr.sa.un.sun_path, s);
3929 child_si->myname = (struct swrap_address) {
3930 .sa_socklen = in_my_addr.sa_socklen,
3932 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3934 idx = swrap_create_socket(&new_si, fd);
3936 int saved_errno = errno;
3938 errno = saved_errno;
3943 struct socket_info *si = swrap_get_socket_info(idx);
3946 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3947 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3948 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3949 SWRAP_UNLOCK_SI(si);
3956 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3958 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3962 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3963 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3965 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3968 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3971 static int autobind_start_init;
3972 static int autobind_start;
3974 /* using sendto() or connect() on an unbound socket would give the
3975 recipient no way to reply, as unlike UDP and TCP, a unix domain
3976 socket can't auto-assign ephemeral port numbers, so we need to
3978 Note: this might change the family from ipv6 to ipv4
3980 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3982 struct swrap_address un_addr = {
3983 .sa_socklen = sizeof(struct sockaddr_un),
3989 char *swrap_dir = NULL;
3991 swrap_mutex_lock(&autobind_start_mutex);
3993 if (autobind_start_init != 1) {
3994 autobind_start_init = 1;
3995 autobind_start = getpid();
3996 autobind_start %= 50000;
3997 autobind_start += 10000;
4000 un_addr.sa.un.sun_family = AF_UNIX;
4004 struct sockaddr_in in;
4008 type = SOCKET_TYPE_CHAR_TCP;
4011 type = SOCKET_TYPE_CHAR_UDP;
4014 errno = ESOCKTNOSUPPORT;
4019 memset(&in, 0, sizeof(in));
4020 in.sin_family = AF_INET;
4021 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
4022 socket_wrapper_default_iface()));
4024 si->myname = (struct swrap_address) {
4025 .sa_socklen = sizeof(in),
4027 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
4032 struct sockaddr_in6 in6;
4034 if (si->family != family) {
4035 errno = ENETUNREACH;
4042 type = SOCKET_TYPE_CHAR_TCP_V6;
4045 type = SOCKET_TYPE_CHAR_UDP_V6;
4048 errno = ESOCKTNOSUPPORT;
4053 memset(&in6, 0, sizeof(in6));
4054 in6.sin6_family = AF_INET6;
4055 in6.sin6_addr = *swrap_ipv6();
4056 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4058 si->myname = (struct swrap_address) {
4059 .sa_socklen = sizeof(in6),
4061 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4066 errno = ESOCKTNOSUPPORT;
4071 if (autobind_start > 60000) {
4072 autobind_start = 10000;
4075 swrap_dir = socket_wrapper_dir();
4076 if (swrap_dir == NULL) {
4082 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4083 port = autobind_start + i;
4084 swrap_un_path(&un_addr.sa.un,
4087 socket_wrapper_default_iface(),
4090 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4092 if (errno == EALREADY || errno == EADDRINUSE) {
4098 si->un_addr = un_addr.sa.un;
4101 autobind_start = port + 1;
4104 if (i == SOCKET_MAX_SOCKETS) {
4105 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4106 "interface "SOCKET_FORMAT,
4109 socket_wrapper_default_iface(),
4116 si->family = family;
4117 set_port(si->family, port, &si->myname);
4122 SAFE_FREE(swrap_dir);
4123 swrap_mutex_unlock(&autobind_start_mutex);
4127 /****************************************************************************
4129 ***************************************************************************/
4131 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4135 struct swrap_address un_addr = {
4136 .sa_socklen = sizeof(struct sockaddr_un),
4138 struct socket_info *si = find_socket_info(s);
4139 struct swrap_sockaddr_buf buf = {};
4143 return libc_connect(s, serv_addr, addrlen);
4148 if (si->bound == 0) {
4149 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4155 if (si->family != serv_addr->sa_family) {
4156 SWRAP_LOG(SWRAP_LOG_ERROR,
4157 "called for fd=%d (family=%d) called with invalid family=%d",
4158 s, si->family, serv_addr->sa_family);
4164 ret = sockaddr_convert_to_un(si, serv_addr,
4165 addrlen, &un_addr.sa.un, 0, &bcast);
4171 errno = ENETUNREACH;
4176 if (si->type == SOCK_DGRAM) {
4177 si->defer_connect = 1;
4180 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4182 ret = libc_connect(s,
4184 un_addr.sa_socklen);
4187 SWRAP_LOG(SWRAP_LOG_TRACE,
4188 "connect(%s) path=%s, fd=%d",
4189 swrap_sockaddr_string(&buf, serv_addr),
4190 un_addr.sa.un.sun_path, s);
4193 /* to give better errors */
4194 if (ret == -1 && errno == ENOENT) {
4195 errno = EHOSTUNREACH;
4199 si->peername = (struct swrap_address) {
4200 .sa_socklen = addrlen,
4203 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4207 * When we connect() on a socket than we have to bind the
4208 * outgoing connection on the interface we use for the
4209 * transport. We already bound it on the right interface
4210 * but here we have to update the name so getsockname()
4211 * returns correct information.
4213 if (si->bindname.sa_socklen > 0) {
4214 si->myname = (struct swrap_address) {
4215 .sa_socklen = si->bindname.sa_socklen,
4218 memcpy(&si->myname.sa.ss,
4219 &si->bindname.sa.ss,
4220 si->bindname.sa_socklen);
4222 /* Cleanup bindname */
4223 si->bindname = (struct swrap_address) {
4228 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4229 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4231 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4235 SWRAP_UNLOCK_SI(si);
4239 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4241 return swrap_connect(s, serv_addr, addrlen);
4244 /****************************************************************************
4246 ***************************************************************************/
4248 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4251 struct swrap_address un_addr = {
4252 .sa_socklen = sizeof(struct sockaddr_un),
4254 struct socket_info *si = find_socket_info(s);
4255 struct swrap_sockaddr_buf buf = {};
4256 int ret_errno = errno;
4263 return libc_bind(s, myaddr, addrlen);
4268 switch (si->family) {
4270 const struct sockaddr_in *sin;
4271 if (addrlen < sizeof(struct sockaddr_in)) {
4272 bind_error = EINVAL;
4276 sin = (const struct sockaddr_in *)(const void *)myaddr;
4278 if (sin->sin_family != AF_INET) {
4279 bind_error = EAFNOSUPPORT;
4282 /* special case for AF_UNSPEC */
4283 if (sin->sin_family == AF_UNSPEC &&
4284 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4293 const struct sockaddr_in6 *sin6;
4294 if (addrlen < sizeof(struct sockaddr_in6)) {
4295 bind_error = EINVAL;
4299 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4301 if (sin6->sin6_family != AF_INET6) {
4302 bind_error = EAFNOSUPPORT;
4309 bind_error = EINVAL;
4313 if (bind_error != 0) {
4314 ret_errno = bind_error;
4320 in_use = check_addr_port_in_use(myaddr, addrlen);
4328 si->myname.sa_socklen = addrlen;
4329 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4331 ret = sockaddr_convert_to_un(si,
4342 unlink(un_addr.sa.un.sun_path);
4344 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4349 SWRAP_LOG(SWRAP_LOG_TRACE,
4350 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4351 swrap_sockaddr_string(&buf, myaddr),
4352 un_addr.sa.un.sun_path, s, ret, ret_errno);
4359 SWRAP_UNLOCK_SI(si);
4364 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4366 return swrap_bind(s, myaddr, addrlen);
4369 /****************************************************************************
4371 ***************************************************************************/
4373 #ifdef HAVE_BINDRESVPORT
4374 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4376 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4378 struct swrap_address myaddr = {
4379 .sa_socklen = sizeof(struct sockaddr_storage),
4382 static uint16_t port;
4387 #define SWRAP_STARTPORT 600
4388 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4389 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4392 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4396 salen = myaddr.sa_socklen;
4399 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4405 memset(&myaddr.sa.ss, 0, salen);
4410 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4413 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4415 salen = sizeof(struct sockaddr_in);
4416 sinp->sin_port = htons(port);
4420 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4422 salen = sizeof(struct sockaddr_in6);
4423 sin6p->sin6_port = htons(port);
4427 errno = EAFNOSUPPORT;
4432 if (port > SWRAP_ENDPORT) {
4433 port = SWRAP_STARTPORT;
4436 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4437 if (rc == 0 || errno != EADDRINUSE) {
4445 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4447 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4451 /****************************************************************************
4453 ***************************************************************************/
4455 static int swrap_listen(int s, int backlog)
4458 struct socket_info *si = find_socket_info(s);
4461 return libc_listen(s, backlog);
4466 if (si->bound == 0) {
4467 ret = swrap_auto_bind(s, si, si->family);
4474 ret = libc_listen(s, backlog);
4480 SWRAP_UNLOCK_SI(si);
4485 int listen(int s, int backlog)
4487 return swrap_listen(s, backlog);
4490 /****************************************************************************
4492 ***************************************************************************/
4494 static FILE *swrap_fopen(const char *name, const char *mode)
4498 fp = libc_fopen(name, mode);
4500 int fd = fileno(fp);
4502 swrap_remove_stale(fd);
4508 FILE *fopen(const char *name, const char *mode)
4510 return swrap_fopen(name, mode);
4513 /****************************************************************************
4515 ***************************************************************************/
4518 static FILE *swrap_fopen64(const char *name, const char *mode)
4522 fp = libc_fopen64(name, mode);
4524 int fd = fileno(fp);
4526 swrap_remove_stale(fd);
4532 FILE *fopen64(const char *name, const char *mode)
4534 return swrap_fopen64(name, mode);
4536 #endif /* HAVE_FOPEN64 */
4538 /****************************************************************************
4540 ***************************************************************************/
4542 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4546 ret = libc_vopen(pathname, flags, ap);
4549 * There are methods for closing descriptors (libc-internal code
4550 * paths, direct syscalls) which close descriptors in ways that
4551 * we can't intercept, so try to recover when we notice that
4554 swrap_remove_stale(ret);
4559 int open(const char *pathname, int flags, ...)
4564 va_start(ap, flags);
4565 fd = swrap_vopen(pathname, flags, ap);
4571 /****************************************************************************
4573 ***************************************************************************/
4576 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4580 ret = libc_vopen64(pathname, flags, ap);
4583 * There are methods for closing descriptors (libc-internal code
4584 * paths, direct syscalls) which close descriptors in ways that
4585 * we can't intercept, so try to recover when we notice that
4588 swrap_remove_stale(ret);
4593 int open64(const char *pathname, int flags, ...)
4598 va_start(ap, flags);
4599 fd = swrap_vopen64(pathname, flags, ap);
4604 #endif /* HAVE_OPEN64 */
4606 /****************************************************************************
4608 ***************************************************************************/
4610 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4614 ret = libc_vopenat(dirfd, path, flags, ap);
4617 * There are methods for closing descriptors (libc-internal code
4618 * paths, direct syscalls) which close descriptors in ways that
4619 * we can't intercept, so try to recover when we notice that
4622 swrap_remove_stale(ret);
4628 int openat(int dirfd, const char *path, int flags, ...)
4633 va_start(ap, flags);
4634 fd = swrap_vopenat(dirfd, path, flags, ap);
4640 /****************************************************************************
4642 ***************************************************************************/
4644 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4646 struct socket_info *si = find_socket_info(s);
4651 return libc_getpeername(s, name, addrlen);
4656 if (si->peername.sa_socklen == 0)
4662 len = MIN(*addrlen, si->peername.sa_socklen);
4668 memcpy(name, &si->peername.sa.ss, len);
4669 *addrlen = si->peername.sa_socklen;
4673 SWRAP_UNLOCK_SI(si);
4678 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4679 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4681 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4684 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4687 /****************************************************************************
4689 ***************************************************************************/
4691 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4693 struct socket_info *si = find_socket_info(s);
4698 return libc_getsockname(s, name, addrlen);
4703 len = MIN(*addrlen, si->myname.sa_socklen);
4709 memcpy(name, &si->myname.sa.ss, len);
4710 *addrlen = si->myname.sa_socklen;
4714 SWRAP_UNLOCK_SI(si);
4719 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4720 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4722 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4725 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4728 /****************************************************************************
4730 ***************************************************************************/
4733 # ifdef SO_PROTOTYPE /* The Solaris name */
4734 # define SO_PROTOCOL SO_PROTOTYPE
4735 # endif /* SO_PROTOTYPE */
4736 #endif /* SO_PROTOCOL */
4738 static int swrap_getsockopt(int s, int level, int optname,
4739 void *optval, socklen_t *optlen)
4741 struct socket_info *si = find_socket_info(s);
4745 return libc_getsockopt(s,
4754 if (level == SOL_SOCKET) {
4758 if (optval == NULL || optlen == NULL ||
4759 *optlen < (socklen_t)sizeof(int)) {
4765 *optlen = sizeof(int);
4766 *(int *)optval = si->family;
4769 #endif /* SO_DOMAIN */
4773 if (optval == NULL || optlen == NULL ||
4774 *optlen < (socklen_t)sizeof(int)) {
4780 *optlen = sizeof(int);
4781 *(int *)optval = si->protocol;
4784 #endif /* SO_PROTOCOL */
4786 if (optval == NULL || optlen == NULL ||
4787 *optlen < (socklen_t)sizeof(int)) {
4793 *optlen = sizeof(int);
4794 *(int *)optval = si->type;
4798 ret = libc_getsockopt(s,
4805 } else if (level == IPPROTO_TCP) {
4810 * This enables sending packets directly out over TCP.
4811 * As a unix socket is doing that any way, report it as
4814 if (optval == NULL || optlen == NULL ||
4815 *optlen < (socklen_t)sizeof(int)) {
4821 *optlen = sizeof(int);
4822 *(int *)optval = si->tcp_nodelay;
4826 #endif /* TCP_NODELAY */
4829 struct tcp_info info;
4830 socklen_t ilen = sizeof(info);
4832 #ifdef HAVE_NETINET_TCP_FSM_H
4833 /* This is FreeBSD */
4834 # define __TCP_LISTEN TCPS_LISTEN
4835 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4836 # define __TCP_CLOSE TCPS_CLOSED
4839 # define __TCP_LISTEN TCP_LISTEN
4840 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4841 # define __TCP_CLOSE TCP_CLOSE
4845 if (si->listening) {
4846 info.tcpi_state = __TCP_LISTEN;
4847 } else if (si->connected) {
4849 * For now we just fake a few values
4850 * supported both by FreeBSD and Linux
4852 info.tcpi_state = __TCP_ESTABLISHED;
4853 info.tcpi_rto = 200000; /* 200 msec */
4854 info.tcpi_rtt = 5000; /* 5 msec */
4855 info.tcpi_rttvar = 5000; /* 5 msec */
4857 info.tcpi_state = __TCP_CLOSE;
4858 info.tcpi_rto = 1000000; /* 1 sec */
4860 info.tcpi_rttvar = 250000; /* 250 msec */
4863 if (optval == NULL || optlen == NULL ||
4864 *optlen < (socklen_t)ilen) {
4871 memcpy(optval, &info, ilen);
4876 #endif /* TCP_INFO */
4882 errno = ENOPROTOOPT;
4886 SWRAP_UNLOCK_SI(si);
4890 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4891 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4893 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4896 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4899 /****************************************************************************
4901 ***************************************************************************/
4903 static int swrap_setsockopt(int s, int level, int optname,
4904 const void *optval, socklen_t optlen)
4906 struct socket_info *si = find_socket_info(s);
4910 return libc_setsockopt(s,
4917 if (level == SOL_SOCKET) {
4918 return libc_setsockopt(s,
4927 if (level == IPPROTO_TCP) {
4934 * This enables sending packets directly out over TCP.
4935 * A unix socket is doing that any way.
4937 if (optval == NULL || optlen == 0 ||
4938 optlen < (socklen_t)sizeof(int)) {
4944 i = *discard_const_p(int, optval);
4945 if (i != 0 && i != 1) {
4950 si->tcp_nodelay = i;
4955 #endif /* TCP_NODELAY */
4961 switch (si->family) {
4963 if (level == IPPROTO_IP) {
4965 if (optname == IP_PKTINFO) {
4966 si->pktinfo = AF_INET;
4968 #endif /* IP_PKTINFO */
4974 if (level == IPPROTO_IPV6) {
4975 #ifdef IPV6_RECVPKTINFO
4976 if (optname == IPV6_RECVPKTINFO) {
4977 si->pktinfo = AF_INET6;
4979 #endif /* IPV6_PKTINFO */
4985 errno = ENOPROTOOPT;
4991 SWRAP_UNLOCK_SI(si);
4995 int setsockopt(int s, int level, int optname,
4996 const void *optval, socklen_t optlen)
4998 return swrap_setsockopt(s, level, optname, optval, optlen);
5001 /****************************************************************************
5003 ***************************************************************************/
5005 static int swrap_vioctl(int s, unsigned long int r, va_list va)
5007 struct socket_info *si = find_socket_info(s);
5009 int *value_ptr = NULL;
5013 return libc_vioctl(s, r, va);
5020 rc = libc_vioctl(s, r, va);
5025 value_ptr = ((int *)va_arg(ap, int *));
5028 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
5029 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5030 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
5031 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5036 /* this is FreeBSD */
5037 FALL_THROUGH; /* to TIOCOUTQ */
5038 #endif /* FIONWRITE */
5039 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
5041 * This may return more bytes then the application
5042 * sent into the socket, for tcp it should
5043 * return the number of unacked bytes.
5045 * On AF_UNIX, all bytes are immediately acked!
5048 value_ptr = ((int *)va_arg(ap, int *));
5056 SWRAP_UNLOCK_SI(si);
5060 #ifdef HAVE_IOCTL_INT
5061 int ioctl(int s, int r, ...)
5063 int ioctl(int s, unsigned long int r, ...)
5071 rc = swrap_vioctl(s, (unsigned long int) r, va);
5082 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5085 # ifdef _ALIGN /* BSD */
5086 #define CMSG_ALIGN _ALIGN
5088 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5089 # endif /* _ALIGN */
5090 #endif /* CMSG_ALIGN */
5093 * @brief Add a cmsghdr to a msghdr.
5095 * This is an function to add any type of cmsghdr. It will operate on the
5096 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5097 * the buffer position after the added cmsg element. Hence, this function is
5098 * intended to be used with an intermediate msghdr and not on the original
5099 * one handed in by the client.
5101 * @param[in] msg The msghdr to which to add the cmsg.
5103 * @param[in] level The cmsg level to set.
5105 * @param[in] type The cmsg type to set.
5107 * @param[in] data The cmsg data to set.
5109 * @param[in] len the length of the data to set.
5111 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5117 size_t cmlen = CMSG_LEN(len);
5118 size_t cmspace = CMSG_SPACE(len);
5119 uint8_t cmbuf[cmspace];
5120 void *cast_ptr = (void *)cmbuf;
5121 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5124 memset(cmbuf, 0, cmspace);
5126 if (msg->msg_controllen < cmlen) {
5127 cmlen = msg->msg_controllen;
5128 msg->msg_flags |= MSG_CTRUNC;
5131 if (msg->msg_controllen < cmspace) {
5132 cmspace = msg->msg_controllen;
5136 * We copy the full input data into an intermediate cmsghdr first
5137 * in order to more easily cope with truncation.
5139 cm->cmsg_len = cmlen;
5140 cm->cmsg_level = level;
5141 cm->cmsg_type = type;
5142 memcpy(CMSG_DATA(cm), data, len);
5145 * We now copy the possibly truncated buffer.
5146 * We copy cmlen bytes, but consume cmspace bytes,
5147 * leaving the possible padding uninitialiazed.
5149 p = (uint8_t *)msg->msg_control;
5150 memcpy(p, cm, cmlen);
5152 msg->msg_control = p;
5153 msg->msg_controllen -= cmspace;
5158 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5161 /* Add packet info */
5162 switch (si->pktinfo) {
5163 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5165 struct sockaddr_in *sin;
5166 #if defined(HAVE_STRUCT_IN_PKTINFO)
5167 struct in_pktinfo pkt;
5168 #elif defined(IP_RECVDSTADDR)
5172 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5173 sin = &si->bindname.sa.in;
5175 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5178 sin = &si->myname.sa.in;
5183 #if defined(HAVE_STRUCT_IN_PKTINFO)
5184 pkt.ipi_ifindex = socket_wrapper_default_iface();
5185 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5186 #elif defined(IP_RECVDSTADDR)
5187 pkt = sin->sin_addr;
5190 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5195 #endif /* IP_PKTINFO */
5196 #if defined(HAVE_IPV6)
5198 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5199 struct sockaddr_in6 *sin6;
5200 struct in6_pktinfo pkt6;
5202 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5203 sin6 = &si->bindname.sa.in6;
5205 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5208 sin6 = &si->myname.sa.in6;
5213 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5214 pkt6.ipi6_addr = sin6->sin6_addr;
5216 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5217 &pkt6, sizeof(pkt6));
5218 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5222 #endif /* IPV6_PKTINFO */
5230 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5231 struct msghdr *omsg)
5235 if (si->pktinfo > 0) {
5236 rc = swrap_msghdr_add_pktinfo(si, omsg);
5242 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5244 size_t *cm_data_space);
5245 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5247 size_t *cm_data_space);
5248 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5250 size_t *cm_data_space);
5252 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5254 size_t *cm_data_space)
5256 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5257 struct cmsghdr *cmsg;
5261 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5265 for (cmsg = CMSG_FIRSTHDR(msg);
5267 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5268 switch (cmsg->cmsg_level) {
5270 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5275 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5280 rc = swrap_sendmsg_copy_cmsg(cmsg,
5286 int saved_errno = errno;
5287 SAFE_FREE(*cm_data);
5289 errno = saved_errno;
5297 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5299 size_t *cm_data_space)
5304 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5306 p = realloc((*cm_data), cmspace);
5312 p = (*cm_data) + (*cm_data_space);
5313 *cm_data_space = cmspace;
5315 memcpy(p, cmsg, cmsg->cmsg_len);
5320 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5322 size_t *cm_data_space);
5325 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5327 size_t *cm_data_space)
5331 switch(cmsg->cmsg_type) {
5334 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5341 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5353 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5355 size_t *cm_data_space)
5357 (void)cmsg; /* unused */
5358 (void)cm_data; /* unused */
5359 (void)cm_data_space; /* unused */
5362 * Passing a IP pktinfo to a unix socket might be rejected by the
5363 * Kernel, at least on FreeBSD. So skip this cmsg.
5368 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5370 size_t *cm_data_space)
5374 switch (cmsg->cmsg_type) {
5376 SWRAP_LOG(SWRAP_LOG_TRACE,
5377 "Ignoring SCM_RIGHTS on inet socket!");
5380 #ifdef SCM_CREDENTIALS
5381 case SCM_CREDENTIALS:
5382 SWRAP_LOG(SWRAP_LOG_TRACE,
5383 "Ignoring SCM_CREDENTIALS on inet socket!");
5386 #endif /* SCM_CREDENTIALS */
5388 rc = swrap_sendmsg_copy_cmsg(cmsg,
5397 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5400 * We only allow up to 6 fds at a time
5401 * as that's more than enough for Samba
5402 * and it means we can keep the logic simple
5403 * and work with fixed size arrays.
5405 * We also keep sizeof(struct swrap_unix_scm_rights)
5406 * under PIPE_BUF (4096) in order to allow a non-blocking
5407 * write into the pipe.
5410 #define PIPE_BUF 4096
5412 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5413 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5414 struct swrap_unix_scm_rights_payload {
5416 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5417 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5419 struct swrap_unix_scm_rights {
5421 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5422 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5424 uint32_t payload_size;
5425 struct swrap_unix_scm_rights_payload payload;
5428 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5430 int saved_errno = errno;
5433 for (i = 0; i < num; i++) {
5434 struct socket_info *si = array[i];
5440 swrap_dec_refcount(si);
5441 if (si->fd_passed > 0) {
5444 SWRAP_UNLOCK_SI(si);
5448 errno = saved_errno;
5451 static void swrap_undo_si_idx_array(size_t num, int *array)
5453 int saved_errno = errno;
5456 swrap_mutex_lock(&first_free_mutex);
5458 for (i = 0; i < num; i++) {
5459 struct socket_info *si = NULL;
5461 if (array[i] == -1) {
5465 si = swrap_get_socket_info(array[i]);
5471 swrap_dec_refcount(si);
5472 SWRAP_UNLOCK_SI(si);
5474 swrap_set_next_free(si, first_free);
5475 first_free = array[i];
5479 swrap_mutex_unlock(&first_free_mutex);
5480 errno = saved_errno;
5483 static void swrap_close_fd_array(size_t num, const int *array)
5485 int saved_errno = errno;
5488 for (i = 0; i < num; i++) {
5489 if (array[i] == -1) {
5492 libc_close(array[i]);
5495 errno = saved_errno;
5503 union __swrap_cmsghdr {
5505 struct cmsghdr *cmsg;
5508 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5510 size_t *cm_data_space,
5511 int *scm_rights_pipe_fd)
5513 struct swrap_unix_scm_rights info;
5514 struct swrap_unix_scm_rights_payload *payload = NULL;
5515 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5516 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5517 size_t info_idx = 0;
5520 union __swrap_fds __fds_in = { .p = NULL, };
5521 const int *fds_in = NULL;
5523 size_t size_fds_out;
5524 union __swrap_fds __fds_out = { .p = NULL, };
5525 int *fds_out = NULL;
5528 size_t new_cm_data_space;
5529 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5530 struct cmsghdr *new_cmsg = NULL;
5533 int pipefd[2] = { -1, -1 };
5538 * We pass this a buffer to the kernel make sure any padding
5542 info.magic = swrap_unix_scm_right_magic;
5543 memcpy(info.package_name,
5544 SOCKET_WRAPPER_PACKAGE,
5545 sizeof(info.package_name));
5546 memcpy(info.package_version,
5547 SOCKET_WRAPPER_VERSION,
5548 sizeof(info.package_version));
5549 info.full_size = sizeof(info);
5550 info.payload_size = sizeof(info.payload);
5551 payload = &info.payload;
5553 if (*scm_rights_pipe_fd != -1) {
5554 SWRAP_LOG(SWRAP_LOG_ERROR,
5555 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5560 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5561 SWRAP_LOG(SWRAP_LOG_ERROR,
5562 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5563 (size_t)cmsg->cmsg_len,
5568 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5569 if ((size_fds_in % sizeof(int)) != 0) {
5570 SWRAP_LOG(SWRAP_LOG_ERROR,
5571 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5572 (size_t)cmsg->cmsg_len,
5578 num_fds_in = size_fds_in / sizeof(int);
5579 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5580 SWRAP_LOG(SWRAP_LOG_ERROR,
5581 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5583 "SWRAP_MAX_PASSED_FDS(%zu)",
5584 (size_t)cmsg->cmsg_len,
5587 SWRAP_MAX_PASSED_FDS);
5591 if (num_fds_in == 0) {
5592 SWRAP_LOG(SWRAP_LOG_ERROR,
5593 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5595 (size_t)cmsg->cmsg_len,
5601 __fds_in.p = CMSG_DATA(cmsg);
5602 fds_in = __fds_in.fds;
5603 num_fds_out = num_fds_in + 1;
5605 SWRAP_LOG(SWRAP_LOG_TRACE,
5606 "num_fds_in=%zu num_fds_out=%zu",
5607 num_fds_in, num_fds_out);
5609 size_fds_out = sizeof(int) * num_fds_out;
5610 cmsg_len = CMSG_LEN(size_fds_out);
5611 cmsg_space = CMSG_SPACE(size_fds_out);
5613 new_cm_data_space = *cm_data_space + cmsg_space;
5615 p = realloc((*cm_data), new_cm_data_space);
5620 p = (*cm_data) + (*cm_data_space);
5621 memset(p, 0, cmsg_space);
5623 new_cmsg = __new_cmsg.cmsg;
5625 __fds_out.p = CMSG_DATA(new_cmsg);
5626 fds_out = __fds_out.fds;
5627 memcpy(fds_out, fds_in, size_fds_in);
5628 new_cmsg->cmsg_len = cmsg->cmsg_len;
5630 for (i = 0; i < num_fds_in; i++) {
5633 payload->idxs[i] = -1;
5634 payload->num_idxs++;
5636 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5637 if (si_idx_array[i] == -1) {
5641 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5642 if (si_array[i] == NULL) {
5643 SWRAP_LOG(SWRAP_LOG_ERROR,
5644 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5645 i, fds_in[i], i, si_idx_array[i]);
5650 for (j = 0; j < i; j++) {
5651 if (si_array[j] == si_array[i]) {
5652 payload->idxs[i] = payload->idxs[j];
5656 if (payload->idxs[i] == -1) {
5657 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5658 SWRAP_LOG(SWRAP_LOG_ERROR,
5659 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5660 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5661 i, fds_in[i], i, si_idx_array[i],
5663 SWRAP_MAX_PASSED_SOCKET_INFO);
5667 payload->idxs[i] = info_idx;
5673 for (i = 0; i < num_fds_in; i++) {
5674 struct socket_info *si = si_array[i];
5677 SWRAP_LOG(SWRAP_LOG_TRACE,
5678 "fds_in[%zu]=%d not an inet socket",
5683 SWRAP_LOG(SWRAP_LOG_TRACE,
5684 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5685 "passing as info.idxs[%zu]=%d!",
5688 i, payload->idxs[i]);
5692 payload->infos[payload->idxs[i]] = *si;
5693 payload->infos[payload->idxs[i]].fd_passed = 0;
5694 SWRAP_UNLOCK_SI(si);
5699 int saved_errno = errno;
5700 SWRAP_LOG(SWRAP_LOG_ERROR,
5701 "pipe() failed - %d %s",
5703 strerror(saved_errno));
5704 swrap_dec_fd_passed_array(num_fds_in, si_array);
5705 errno = saved_errno;
5709 sret = libc_write(pipefd[1], &info, sizeof(info));
5710 if (sret != sizeof(info)) {
5711 int saved_errno = errno;
5713 saved_errno = EINVAL;
5715 SWRAP_LOG(SWRAP_LOG_ERROR,
5716 "write() failed - sret=%zd - %d %s",
5718 strerror(saved_errno));
5719 swrap_dec_fd_passed_array(num_fds_in, si_array);
5720 libc_close(pipefd[1]);
5721 libc_close(pipefd[0]);
5722 errno = saved_errno;
5725 libc_close(pipefd[1]);
5728 * Add the pipe read end to the end of the passed fd array
5730 fds_out[num_fds_in] = pipefd[0];
5731 new_cmsg->cmsg_len = cmsg_len;
5733 /* we're done ... */
5734 *scm_rights_pipe_fd = pipefd[0];
5735 *cm_data_space = new_cm_data_space;
5740 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5742 size_t *cm_data_space,
5743 int *scm_rights_pipe_fd)
5747 switch (cmsg->cmsg_type) {
5749 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5752 scm_rights_pipe_fd);
5755 rc = swrap_sendmsg_copy_cmsg(cmsg,
5764 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5766 size_t *cm_data_space)
5768 int scm_rights_pipe_fd = -1;
5769 struct swrap_unix_scm_rights info;
5770 struct swrap_unix_scm_rights_payload *payload = NULL;
5771 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5774 union __swrap_fds __fds_in = { .p = NULL, };
5775 const int *fds_in = NULL;
5777 size_t size_fds_out;
5778 union __swrap_fds __fds_out = { .p = NULL, };
5779 int *fds_out = NULL;
5782 size_t new_cm_data_space;
5783 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5784 struct cmsghdr *new_cmsg = NULL;
5790 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5791 SWRAP_LOG(SWRAP_LOG_ERROR,
5792 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5793 (size_t)cmsg->cmsg_len,
5798 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5799 if ((size_fds_in % sizeof(int)) != 0) {
5800 SWRAP_LOG(SWRAP_LOG_ERROR,
5801 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5802 (size_t)cmsg->cmsg_len,
5808 num_fds_in = size_fds_in / sizeof(int);
5809 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5810 SWRAP_LOG(SWRAP_LOG_ERROR,
5811 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5812 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5813 (size_t)cmsg->cmsg_len,
5816 SWRAP_MAX_PASSED_FDS+1);
5820 if (num_fds_in <= 1) {
5821 SWRAP_LOG(SWRAP_LOG_ERROR,
5822 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5824 (size_t)cmsg->cmsg_len,
5830 __fds_in.p = CMSG_DATA(cmsg);
5831 fds_in = __fds_in.fds;
5832 num_fds_out = num_fds_in - 1;
5834 SWRAP_LOG(SWRAP_LOG_TRACE,
5835 "num_fds_in=%zu num_fds_out=%zu",
5836 num_fds_in, num_fds_out);
5838 for (i = 0; i < num_fds_in; i++) {
5839 /* Check if we have a stale fd and remove it */
5840 swrap_remove_stale(fds_in[i]);
5843 scm_rights_pipe_fd = fds_in[num_fds_out];
5844 size_fds_out = sizeof(int) * num_fds_out;
5845 cmsg_len = CMSG_LEN(size_fds_out);
5846 cmsg_space = CMSG_SPACE(size_fds_out);
5848 new_cm_data_space = *cm_data_space + cmsg_space;
5850 p = realloc((*cm_data), new_cm_data_space);
5852 swrap_close_fd_array(num_fds_in, fds_in);
5856 p = (*cm_data) + (*cm_data_space);
5857 memset(p, 0, cmsg_space);
5859 new_cmsg = __new_cmsg.cmsg;
5861 __fds_out.p = CMSG_DATA(new_cmsg);
5862 fds_out = __fds_out.fds;
5863 memcpy(fds_out, fds_in, size_fds_out);
5864 new_cmsg->cmsg_len = cmsg_len;
5866 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5867 if (sret != sizeof(info)) {
5868 int saved_errno = errno;
5870 saved_errno = EINVAL;
5872 SWRAP_LOG(SWRAP_LOG_ERROR,
5873 "read() failed - sret=%zd - %d %s",
5875 strerror(saved_errno));
5876 swrap_close_fd_array(num_fds_in, fds_in);
5877 errno = saved_errno;
5880 libc_close(scm_rights_pipe_fd);
5881 payload = &info.payload;
5883 if (info.magic != swrap_unix_scm_right_magic) {
5884 SWRAP_LOG(SWRAP_LOG_ERROR,
5885 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5886 (unsigned long long)info.magic,
5887 (unsigned long long)swrap_unix_scm_right_magic);
5888 swrap_close_fd_array(num_fds_out, fds_out);
5893 cmp = memcmp(info.package_name,
5894 SOCKET_WRAPPER_PACKAGE,
5895 sizeof(info.package_name));
5897 SWRAP_LOG(SWRAP_LOG_ERROR,
5898 "info.package_name='%.*s' != '%s'",
5899 (int)sizeof(info.package_name),
5901 SOCKET_WRAPPER_PACKAGE);
5902 swrap_close_fd_array(num_fds_out, fds_out);
5907 cmp = memcmp(info.package_version,
5908 SOCKET_WRAPPER_VERSION,
5909 sizeof(info.package_version));
5911 SWRAP_LOG(SWRAP_LOG_ERROR,
5912 "info.package_version='%.*s' != '%s'",
5913 (int)sizeof(info.package_version),
5914 info.package_version,
5915 SOCKET_WRAPPER_VERSION);
5916 swrap_close_fd_array(num_fds_out, fds_out);
5921 if (info.full_size != sizeof(info)) {
5922 SWRAP_LOG(SWRAP_LOG_ERROR,
5923 "info.full_size=%zu != sizeof(info)=%zu",
5924 (size_t)info.full_size,
5926 swrap_close_fd_array(num_fds_out, fds_out);
5931 if (info.payload_size != sizeof(info.payload)) {
5932 SWRAP_LOG(SWRAP_LOG_ERROR,
5933 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5934 (size_t)info.payload_size,
5935 sizeof(info.payload));
5936 swrap_close_fd_array(num_fds_out, fds_out);
5941 if (payload->num_idxs != num_fds_out) {
5942 SWRAP_LOG(SWRAP_LOG_ERROR,
5943 "info.num_idxs=%u != num_fds_out=%zu",
5944 payload->num_idxs, num_fds_out);
5945 swrap_close_fd_array(num_fds_out, fds_out);
5950 for (i = 0; i < num_fds_out; i++) {
5953 si_idx_array[i] = -1;
5955 if (payload->idxs[i] == -1) {
5956 SWRAP_LOG(SWRAP_LOG_TRACE,
5957 "fds_out[%zu]=%d not an inet socket",
5962 if (payload->idxs[i] < 0) {
5963 SWRAP_LOG(SWRAP_LOG_ERROR,
5964 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5965 i, fds_out[i], i, payload->idxs[i]);
5966 swrap_close_fd_array(num_fds_out, fds_out);
5971 if (payload->idxs[i] >= payload->num_idxs) {
5972 SWRAP_LOG(SWRAP_LOG_ERROR,
5973 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5974 i, fds_out[i], i, payload->idxs[i],
5976 swrap_close_fd_array(num_fds_out, fds_out);
5981 if ((size_t)fds_out[i] >= socket_fds_max) {
5982 SWRAP_LOG(SWRAP_LOG_ERROR,
5983 "The max socket index limit of %zu has been reached, "
5987 swrap_close_fd_array(num_fds_out, fds_out);
5992 SWRAP_LOG(SWRAP_LOG_TRACE,
5994 "received as info.idxs[%zu]=%d!",
5996 i, payload->idxs[i]);
5998 for (j = 0; j < i; j++) {
5999 if (payload->idxs[j] == -1) {
6002 if (payload->idxs[j] == payload->idxs[i]) {
6003 si_idx_array[i] = si_idx_array[j];
6006 if (si_idx_array[i] == -1) {
6007 const struct socket_info *si = &payload->infos[payload->idxs[i]];
6009 si_idx_array[i] = swrap_add_socket_info(si);
6010 if (si_idx_array[i] == -1) {
6011 int saved_errno = errno;
6012 SWRAP_LOG(SWRAP_LOG_ERROR,
6013 "The max socket index limit of %zu has been reached, "
6017 swrap_undo_si_idx_array(i, si_idx_array);
6018 swrap_close_fd_array(num_fds_out, fds_out);
6019 errno = saved_errno;
6022 SWRAP_LOG(SWRAP_LOG_TRACE,
6023 "Imported %s socket for protocol %s, fd=%d",
6024 si->family == AF_INET ? "IPv4" : "IPv6",
6025 si->type == SOCK_DGRAM ? "UDP" : "TCP",
6030 for (i = 0; i < num_fds_out; i++) {
6031 if (si_idx_array[i] == -1) {
6034 set_socket_info_index(fds_out[i], si_idx_array[i]);
6037 /* we're done ... */
6038 *cm_data_space = new_cm_data_space;
6043 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6045 size_t *cm_data_space)
6049 switch (cmsg->cmsg_type) {
6051 rc = swrap_recvmsg_unix_scm_rights(cmsg,
6056 rc = swrap_sendmsg_copy_cmsg(cmsg,
6065 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6067 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6068 struct msghdr *msg_tmp,
6069 int *scm_rights_pipe_fd)
6071 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6072 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6073 struct cmsghdr *cmsg = NULL;
6074 uint8_t *cm_data = NULL;
6075 size_t cm_data_space = 0;
6079 *scm_rights_pipe_fd = -1;
6082 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6086 for (cmsg = CMSG_FIRSTHDR(msg_in);
6088 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6089 switch (cmsg->cmsg_level) {
6091 rc = swrap_sendmsg_unix_sol_socket(cmsg,
6094 scm_rights_pipe_fd);
6098 rc = swrap_sendmsg_copy_cmsg(cmsg,
6104 int saved_errno = errno;
6106 errno = saved_errno;
6111 msg_tmp->msg_controllen = cm_data_space;
6112 msg_tmp->msg_control = cm_data;
6115 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6116 *msg_tmp = *_msg_in;
6118 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6121 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6123 int scm_rights_pipe_fd)
6125 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6126 int saved_errno = errno;
6127 SAFE_FREE(msg_tmp->msg_control);
6128 if (scm_rights_pipe_fd != -1) {
6129 libc_close(scm_rights_pipe_fd);
6131 errno = saved_errno;
6132 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6136 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6137 struct msghdr *msg_tmp,
6138 uint8_t **tmp_control)
6140 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6141 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6142 uint8_t *cm_data = NULL;
6143 size_t cm_data_space = 0;
6146 *tmp_control = NULL;
6148 SWRAP_LOG(SWRAP_LOG_TRACE,
6149 "msg_in->msg_controllen=%zu",
6150 (size_t)msg_in->msg_controllen);
6153 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6158 * We need to give the kernel a bit more space in order
6159 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6160 * swrap_recvmsg_after_unix() will hide it again.
6162 cm_data_space = msg_in->msg_controllen;
6163 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6164 cm_data_space += cm_extra_space;
6166 cm_data = calloc(1, cm_data_space);
6167 if (cm_data == NULL) {
6171 msg_tmp->msg_controllen = cm_data_space;
6172 msg_tmp->msg_control = cm_data;
6173 *tmp_control = cm_data;
6175 SWRAP_LOG(SWRAP_LOG_TRACE,
6176 "msg_tmp->msg_controllen=%zu",
6177 (size_t)msg_tmp->msg_controllen);
6179 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6181 *tmp_control = NULL;
6183 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6186 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6187 uint8_t **tmp_control,
6188 struct msghdr *msg_out,
6191 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6192 struct cmsghdr *cmsg = NULL;
6193 uint8_t *cm_data = NULL;
6194 size_t cm_data_space = 0;
6198 int saved_errno = errno;
6199 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6200 saved_errno, strerror(saved_errno));
6201 SAFE_FREE(*tmp_control);
6202 /* msg_out should not be touched on error */
6203 errno = saved_errno;
6207 SWRAP_LOG(SWRAP_LOG_TRACE,
6208 "msg_tmp->msg_controllen=%zu",
6209 (size_t)msg_tmp->msg_controllen);
6212 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6213 int saved_errno = errno;
6214 *msg_out = *msg_tmp;
6215 SAFE_FREE(*tmp_control);
6216 errno = saved_errno;
6220 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6222 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6223 switch (cmsg->cmsg_level) {
6225 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6231 rc = swrap_sendmsg_copy_cmsg(cmsg,
6237 int saved_errno = errno;
6239 SAFE_FREE(*tmp_control);
6240 errno = saved_errno;
6246 * msg_tmp->msg_control (*tmp_control) was created by
6247 * swrap_recvmsg_before_unix() and msg_out->msg_control
6248 * is still the buffer of the caller.
6250 msg_tmp->msg_control = msg_out->msg_control;
6251 msg_tmp->msg_controllen = msg_out->msg_controllen;
6252 *msg_out = *msg_tmp;
6254 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6255 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6256 msg_out->msg_controllen = cm_data_space;
6258 SAFE_FREE(*tmp_control);
6260 SWRAP_LOG(SWRAP_LOG_TRACE,
6261 "msg_out->msg_controllen=%zu",
6262 (size_t)msg_out->msg_controllen);
6264 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6265 int saved_errno = errno;
6266 *msg_out = *msg_tmp;
6267 SAFE_FREE(*tmp_control);
6268 errno = saved_errno;
6270 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6273 static ssize_t swrap_sendmsg_before(int fd,
6274 struct socket_info *si,
6276 struct iovec *tmp_iov,
6277 struct sockaddr_un *tmp_un,
6278 const struct sockaddr_un **to_un,
6279 const struct sockaddr **to,
6284 struct swrap_sockaddr_buf buf = {};
6302 if (!si->connected) {
6307 if (msg->msg_iovlen == 0) {
6311 mtu = socket_wrapper_mtu();
6312 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6314 nlen = len + msg->msg_iov[i].iov_len;
6324 msg->msg_iovlen = i;
6325 if (msg->msg_iovlen == 0) {
6326 *tmp_iov = msg->msg_iov[0];
6327 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6329 msg->msg_iov = tmp_iov;
6330 msg->msg_iovlen = 1;
6335 if (si->connected) {
6336 if (msg->msg_name != NULL) {
6338 * We are dealing with unix sockets and if we
6339 * are connected, we should only talk to the
6340 * connected unix path. Using the fd to send
6341 * to another server would be hard to achieve.
6343 msg->msg_name = NULL;
6344 msg->msg_namelen = 0;
6346 SWRAP_LOG(SWRAP_LOG_TRACE,
6347 "connected(%s) fd=%d",
6348 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6351 const struct sockaddr *msg_name;
6352 msg_name = (const struct sockaddr *)msg->msg_name;
6354 if (msg_name == NULL) {
6360 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6372 msg->msg_name = tmp_un;
6373 msg->msg_namelen = sizeof(*tmp_un);
6376 if (si->bound == 0) {
6377 ret = swrap_auto_bind(fd, si, si->family);
6379 SWRAP_UNLOCK_SI(si);
6380 if (errno == ENOTSOCK) {
6381 swrap_remove_stale(fd);
6384 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6390 if (!si->defer_connect) {
6394 ret = sockaddr_convert_to_un(si,
6396 si->peername.sa_socklen,
6404 SWRAP_LOG(SWRAP_LOG_TRACE,
6405 "deferred connect(%s) path=%s, fd=%d",
6406 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6407 tmp_un->sun_path, fd);
6409 ret = libc_connect(fd,
6410 (struct sockaddr *)(void *)tmp_un,
6413 /* to give better errors */
6414 if (ret == -1 && errno == ENOENT) {
6415 errno = EHOSTUNREACH;
6422 si->defer_connect = 0;
6425 errno = EHOSTUNREACH;
6431 SWRAP_UNLOCK_SI(si);
6436 static void swrap_sendmsg_after(int fd,
6437 struct socket_info *si,
6439 const struct sockaddr *to,
6442 int saved_errno = errno;
6449 /* to give better errors */
6451 if (saved_errno == ENOENT) {
6452 saved_errno = EHOSTUNREACH;
6453 } else if (saved_errno == ENOTSOCK) {
6454 /* If the fd is not a socket, remove it */
6455 swrap_remove_stale(fd);
6459 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6460 avail += msg->msg_iov[i].iov_len;
6464 remain = MIN(80, avail);
6469 /* we capture it as one single packet */
6470 buf = (uint8_t *)malloc(remain);
6472 /* we just not capture the packet */
6473 errno = saved_errno;
6477 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6478 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6479 if (this_time > 0) {
6481 msg->msg_iov[i].iov_base,
6485 remain -= this_time;
6494 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6495 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6497 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6502 if (si->connected) {
6503 to = &si->peername.sa.s;
6506 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6507 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6509 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6514 SWRAP_UNLOCK_SI(si);
6517 errno = saved_errno;
6520 static int swrap_recvmsg_before(int fd,
6521 struct socket_info *si,
6523 struct iovec *tmp_iov)
6530 (void)fd; /* unused */
6535 if (!si->connected) {
6540 if (msg->msg_iovlen == 0) {
6544 mtu = socket_wrapper_mtu();
6545 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6547 nlen = len + msg->msg_iov[i].iov_len;
6552 msg->msg_iovlen = i;
6553 if (msg->msg_iovlen == 0) {
6554 *tmp_iov = msg->msg_iov[0];
6555 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6557 msg->msg_iov = tmp_iov;
6558 msg->msg_iovlen = 1;
6563 if (msg->msg_name == NULL) {
6568 if (msg->msg_iovlen == 0) {
6572 if (si->bound == 0) {
6573 ret = swrap_auto_bind(fd, si, si->family);
6575 SWRAP_UNLOCK_SI(si);
6577 * When attempting to read or write to a
6578 * descriptor, if an underlying autobind fails
6579 * because it's not a socket, stop intercepting
6580 * uses of that descriptor.
6582 if (errno == ENOTSOCK) {
6583 swrap_remove_stale(fd);
6586 SWRAP_LOG(SWRAP_LOG_ERROR,
6587 "swrap_recvmsg_before failed");
6594 errno = EHOSTUNREACH;
6600 SWRAP_UNLOCK_SI(si);
6605 static int swrap_recvmsg_after(int fd,
6606 struct socket_info *si,
6608 const struct sockaddr_un *un_addr,
6609 socklen_t un_addrlen,
6612 int saved_errno = errno;
6614 uint8_t *buf = NULL;
6620 /* to give better errors */
6622 if (saved_errno == ENOENT) {
6623 saved_errno = EHOSTUNREACH;
6624 } else if (saved_errno == ENOTSOCK) {
6625 /* If the fd is not a socket, remove it */
6626 swrap_remove_stale(fd);
6630 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6631 avail += msg->msg_iov[i].iov_len;
6636 /* Convert the socket address before we leave */
6637 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6638 rc = sockaddr_convert_from_un(si,
6655 remain = MIN(80, avail);
6660 /* we capture it as one single packet */
6661 buf = (uint8_t *)malloc(remain);
6663 /* we just not capture the packet */
6664 SWRAP_UNLOCK_SI(si);
6665 errno = saved_errno;
6669 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6670 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6672 msg->msg_iov[i].iov_base,
6675 remain -= this_time;
6680 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6681 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6682 } else if (ret == 0) { /* END OF FILE */
6683 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6684 } else if (ret > 0) {
6685 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6694 if (un_addr != NULL) {
6695 swrap_pcap_dump_packet(si,
6701 swrap_pcap_dump_packet(si,
6714 errno = saved_errno;
6716 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6718 msg->msg_controllen > 0 &&
6719 msg->msg_control != NULL) {
6720 rc = swrap_msghdr_add_socket_info(si, msg);
6722 SWRAP_UNLOCK_SI(si);
6728 SWRAP_UNLOCK_SI(si);
6732 /****************************************************************************
6734 ***************************************************************************/
6736 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6737 struct sockaddr *from, socklen_t *fromlen)
6739 struct swrap_address from_addr = {
6740 .sa_socklen = sizeof(struct sockaddr_un),
6743 struct socket_info *si = find_socket_info(s);
6744 struct swrap_address saddr = {
6745 .sa_socklen = sizeof(struct sockaddr_storage),
6752 return libc_recvfrom(s,
6764 if (from != NULL && fromlen != NULL) {
6765 msg.msg_name = from; /* optional address */
6766 msg.msg_namelen = *fromlen; /* size of address */
6768 msg.msg_name = &saddr.sa.s; /* optional address */
6769 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6771 msg.msg_iov = &tmp; /* scatter/gather array */
6772 msg.msg_iovlen = 1; /* # elements in msg_iov */
6773 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6774 msg.msg_control = NULL; /* ancillary data, see below */
6775 msg.msg_controllen = 0; /* ancillary data buffer len */
6776 msg.msg_flags = 0; /* flags on received message */
6779 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6784 buf = msg.msg_iov[0].iov_base;
6785 len = msg.msg_iov[0].iov_len;
6787 ret = libc_recvfrom(s,
6792 &from_addr.sa_socklen);
6797 tret = swrap_recvmsg_after(s,
6801 from_addr.sa_socklen,
6807 if (from != NULL && fromlen != NULL) {
6808 *fromlen = msg.msg_namelen;
6814 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6815 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6816 struct sockaddr *from, Psocklen_t fromlen)
6818 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6819 struct sockaddr *from, socklen_t *fromlen)
6822 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6825 /****************************************************************************
6827 ***************************************************************************/
6829 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6830 const struct sockaddr *to, socklen_t tolen)
6834 struct swrap_address un_addr = {
6835 .sa_socklen = sizeof(struct sockaddr_un),
6837 const struct sockaddr_un *to_un = NULL;
6840 struct socket_info *si = find_socket_info(s);
6844 return libc_sendto(s, buf, len, flags, to, tolen);
6847 tmp.iov_base = discard_const_p(char, buf);
6851 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6852 msg.msg_namelen = tolen; /* size of address */
6853 msg.msg_iov = &tmp; /* scatter/gather array */
6854 msg.msg_iovlen = 1; /* # elements in msg_iov */
6855 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6856 msg.msg_control = NULL; /* ancillary data, see below */
6857 msg.msg_controllen = 0; /* ancillary data buffer len */
6858 msg.msg_flags = 0; /* flags on received message */
6861 rc = swrap_sendmsg_before(s,
6873 buf = msg.msg_iov[0].iov_base;
6874 len = msg.msg_iov[0].iov_len;
6879 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6881 char *swrap_dir = NULL;
6883 type = SOCKET_TYPE_CHAR_UDP;
6885 swrap_dir = socket_wrapper_dir();
6886 if (swrap_dir == NULL) {
6890 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6891 swrap_un_path(&un_addr.sa.un,
6896 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6898 /* ignore the any errors in broadcast sends */
6904 un_addr.sa_socklen);
6907 SAFE_FREE(swrap_dir);
6911 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6913 SWRAP_UNLOCK_SI(si);
6920 * If it is a dgram socket and we are connected, don't include the
6923 if (si->type == SOCK_DGRAM && si->connected) {
6924 ret = libc_sendto(s,
6931 ret = libc_sendto(s,
6935 (struct sockaddr *)msg.msg_name,
6939 SWRAP_UNLOCK_SI(si);
6941 swrap_sendmsg_after(s, si, &msg, to, ret);
6946 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6947 const struct sockaddr *to, socklen_t tolen)
6949 return swrap_sendto(s, buf, len, flags, to, tolen);
6952 /****************************************************************************
6954 ***************************************************************************/
6956 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6958 struct socket_info *si;
6960 struct swrap_address saddr = {
6961 .sa_socklen = sizeof(struct sockaddr_storage),
6967 si = find_socket_info(s);
6969 return libc_recv(s, buf, len, flags);
6976 msg.msg_name = &saddr.sa.s; /* optional address */
6977 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6978 msg.msg_iov = &tmp; /* scatter/gather array */
6979 msg.msg_iovlen = 1; /* # elements in msg_iov */
6980 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6981 msg.msg_control = NULL; /* ancillary data, see below */
6982 msg.msg_controllen = 0; /* ancillary data buffer len */
6983 msg.msg_flags = 0; /* flags on received message */
6986 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6991 buf = msg.msg_iov[0].iov_base;
6992 len = msg.msg_iov[0].iov_len;
6994 ret = libc_recv(s, buf, len, flags);
6996 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7004 ssize_t recv(int s, void *buf, size_t len, int flags)
7006 return swrap_recv(s, buf, len, flags);
7009 /****************************************************************************
7011 ***************************************************************************/
7013 static ssize_t swrap_read(int s, void *buf, size_t len)
7015 struct socket_info *si;
7018 struct swrap_address saddr = {
7019 .sa_socklen = sizeof(struct sockaddr_storage),
7024 si = find_socket_info(s);
7026 return libc_read(s, buf, len);
7033 msg.msg_name = &saddr.sa.ss; /* optional address */
7034 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7035 msg.msg_iov = &tmp; /* scatter/gather array */
7036 msg.msg_iovlen = 1; /* # elements in msg_iov */
7037 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7038 msg.msg_control = NULL; /* ancillary data, see below */
7039 msg.msg_controllen = 0; /* ancillary data buffer len */
7040 msg.msg_flags = 0; /* flags on received message */
7043 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7045 if (tret == -ENOTSOCK) {
7046 return libc_read(s, buf, len);
7051 buf = msg.msg_iov[0].iov_base;
7052 len = msg.msg_iov[0].iov_len;
7054 ret = libc_read(s, buf, len);
7056 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7064 ssize_t read(int s, void *buf, size_t len)
7066 return swrap_read(s, buf, len);
7069 /****************************************************************************
7071 ***************************************************************************/
7073 static ssize_t swrap_write(int s, const void *buf, size_t len)
7077 struct sockaddr_un un_addr;
7080 struct socket_info *si;
7082 si = find_socket_info(s);
7084 return libc_write(s, buf, len);
7087 tmp.iov_base = discard_const_p(char, buf);
7091 msg.msg_name = NULL; /* optional address */
7092 msg.msg_namelen = 0; /* size of address */
7093 msg.msg_iov = &tmp; /* scatter/gather array */
7094 msg.msg_iovlen = 1; /* # elements in msg_iov */
7095 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7096 msg.msg_control = NULL; /* ancillary data, see below */
7097 msg.msg_controllen = 0; /* ancillary data buffer len */
7098 msg.msg_flags = 0; /* flags on received message */
7101 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7106 buf = msg.msg_iov[0].iov_base;
7107 len = msg.msg_iov[0].iov_len;
7109 ret = libc_write(s, buf, len);
7111 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7116 ssize_t write(int s, const void *buf, size_t len)
7118 return swrap_write(s, buf, len);
7121 /****************************************************************************
7123 ***************************************************************************/
7125 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7129 struct sockaddr_un un_addr;
7132 struct socket_info *si = find_socket_info(s);
7135 return libc_send(s, buf, len, flags);
7138 tmp.iov_base = discard_const_p(char, buf);
7142 msg.msg_name = NULL; /* optional address */
7143 msg.msg_namelen = 0; /* size of address */
7144 msg.msg_iov = &tmp; /* scatter/gather array */
7145 msg.msg_iovlen = 1; /* # elements in msg_iov */
7146 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7147 msg.msg_control = NULL; /* ancillary data, see below */
7148 msg.msg_controllen = 0; /* ancillary data buffer len */
7149 msg.msg_flags = 0; /* flags on received message */
7152 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7157 buf = msg.msg_iov[0].iov_base;
7158 len = msg.msg_iov[0].iov_len;
7160 ret = libc_send(s, buf, len, flags);
7162 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7167 ssize_t send(int s, const void *buf, size_t len, int flags)
7169 return swrap_send(s, buf, len, flags);
7172 /****************************************************************************
7174 ***************************************************************************/
7176 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7178 struct swrap_address from_addr = {
7179 .sa_socklen = sizeof(struct sockaddr_un),
7181 struct swrap_address convert_addr = {
7182 .sa_socklen = sizeof(struct sockaddr_storage),
7184 struct socket_info *si;
7187 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7188 size_t msg_ctrllen_filled;
7189 size_t msg_ctrllen_left;
7195 si = find_socket_info(s);
7197 uint8_t *tmp_control = NULL;
7198 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7202 ret = libc_recvmsg(s, &msg, flags);
7203 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7206 tmp.iov_base = NULL;
7210 msg.msg_name = &from_addr.sa; /* optional address */
7211 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7212 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7213 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7214 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7215 msg_ctrllen_filled = 0;
7216 msg_ctrllen_left = omsg->msg_controllen;
7218 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7219 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7220 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7223 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7228 ret = libc_recvmsg(s, &msg, flags);
7230 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7231 msg_ctrllen_filled += msg.msg_controllen;
7232 msg_ctrllen_left -= msg.msg_controllen;
7234 if (omsg->msg_control != NULL) {
7237 p = omsg->msg_control;
7238 p += msg_ctrllen_filled;
7240 msg.msg_control = p;
7241 msg.msg_controllen = msg_ctrllen_left;
7243 msg.msg_control = NULL;
7244 msg.msg_controllen = 0;
7249 * We convert the unix address to a IP address so we need a buffer
7250 * which can store the address in case of SOCK_DGRAM, see below.
7252 msg.msg_name = &convert_addr.sa;
7253 msg.msg_namelen = convert_addr.sa_socklen;
7255 rc = swrap_recvmsg_after(s,
7259 from_addr.sa_socklen,
7265 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7266 if (omsg->msg_control != NULL) {
7267 /* msg.msg_controllen = space left */
7268 msg_ctrllen_left = msg.msg_controllen;
7269 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7272 /* Update the original message length */
7273 omsg->msg_controllen = msg_ctrllen_filled;
7274 omsg->msg_flags = msg.msg_flags;
7276 omsg->msg_iovlen = msg.msg_iovlen;
7283 * The msg_name field points to a caller-allocated buffer that is
7284 * used to return the source address if the socket is unconnected. The
7285 * caller should set msg_namelen to the size of this buffer before this
7286 * call; upon return from a successful call, msg_name will contain the
7287 * length of the returned address. If the application does not need
7288 * to know the source address, msg_name can be specified as NULL.
7290 if (si->type == SOCK_STREAM) {
7291 omsg->msg_namelen = 0;
7292 } else if (omsg->msg_name != NULL &&
7293 omsg->msg_namelen != 0 &&
7294 omsg->msg_namelen >= msg.msg_namelen) {
7295 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7296 omsg->msg_namelen = msg.msg_namelen;
7299 SWRAP_UNLOCK_SI(si);
7304 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7306 return swrap_recvmsg(sockfd, msg, flags);
7309 /****************************************************************************
7311 ***************************************************************************/
7313 #ifdef HAVE_RECVMMSG
7314 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7316 static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7317 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7318 /* Linux legacy glibc < 2.21 */
7319 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7321 /* Linux glibc >= 2.21 */
7322 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7325 struct socket_info *si = find_socket_info(s);
7326 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7327 struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7330 struct swrap_address from_addr;
7331 struct swrap_address convert_addr;
7332 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7333 size_t msg_ctrllen_filled;
7334 size_t msg_ctrllen_left;
7336 } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7343 if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7344 vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7350 uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7352 for (i = 0; i < vlen; i++) {
7353 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7354 struct msghdr *msg = &msgvec[i].msg_hdr;
7356 rc = swrap_recvmsg_before_unix(omsg, msg,
7364 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7369 for (i = 0; i < ret; i++) {
7370 omsgvec[i].msg_len = msgvec[i].msg_len;
7374 saved_errno = errno;
7375 for (i = 0; i < vlen; i++) {
7376 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7377 struct msghdr *msg = &msgvec[i].msg_hdr;
7379 if (i == 0 || i < ret) {
7380 swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7382 SAFE_FREE(tmp_control[i]);
7384 errno = saved_errno;
7389 for (i = 0; i < vlen; i++) {
7390 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7391 struct msghdr *msg = &msgvec[i].msg_hdr;
7393 tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7394 tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7396 msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7397 msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7398 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7399 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7400 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7401 tmp[i].msg_ctrllen_filled = 0;
7402 tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7404 msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7405 msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7406 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7409 rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7416 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7421 for (i = 0; i < ret; i++) {
7422 omsgvec[i].msg_len = msgvec[i].msg_len;
7427 saved_errno = errno;
7428 for (i = 0; i < vlen; i++) {
7429 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7430 struct msghdr *msg = &msgvec[i].msg_hdr;
7432 if (!(i == 0 || i < ret)) {
7436 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7437 tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7438 tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7440 if (omsg->msg_control != NULL) {
7443 p = omsg->msg_control;
7444 p += tmp[i].msg_ctrllen_filled;
7446 msg->msg_control = p;
7447 msg->msg_controllen = tmp[i].msg_ctrllen_left;
7449 msg->msg_control = NULL;
7450 msg->msg_controllen = 0;
7455 * We convert the unix address to a IP address so we need a buffer
7456 * which can store the address in case of SOCK_DGRAM, see below.
7458 msg->msg_name = &tmp[i].convert_addr.sa;
7459 msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7461 swrap_recvmsg_after(s, si, msg,
7462 &tmp[i].from_addr.sa.un,
7463 tmp[i].from_addr.sa_socklen,
7466 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7467 if (omsg->msg_control != NULL) {
7468 /* msg->msg_controllen = space left */
7469 tmp[i].msg_ctrllen_left = msg->msg_controllen;
7470 tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7473 /* Update the original message length */
7474 omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7475 omsg->msg_flags = msg->msg_flags;
7477 omsg->msg_iovlen = msg->msg_iovlen;
7484 * The msg_name field points to a caller-allocated buffer that is
7485 * used to return the source address if the socket is unconnected. The
7486 * caller should set msg_namelen to the size of this buffer before this
7487 * call; upon return from a successful call, msg_name will contain the
7488 * length of the returned address. If the application does not need
7489 * to know the source address, msg_name can be specified as NULL.
7491 if (si->type == SOCK_STREAM) {
7492 omsg->msg_namelen = 0;
7493 } else if (omsg->msg_name != NULL &&
7494 omsg->msg_namelen != 0 &&
7495 omsg->msg_namelen >= msg->msg_namelen) {
7496 memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7497 omsg->msg_namelen = msg->msg_namelen;
7500 SWRAP_UNLOCK_SI(si);
7502 errno = saved_errno;
7507 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7509 ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7510 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7511 /* Linux legacy glibc < 2.21 */
7512 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7514 /* Linux glibc >= 2.21 */
7515 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7518 return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7520 #endif /* HAVE_RECVMMSG */
7522 /****************************************************************************
7524 ***************************************************************************/
7526 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7530 struct sockaddr_un un_addr;
7531 const struct sockaddr_un *to_un = NULL;
7532 const struct sockaddr *to = NULL;
7535 struct socket_info *si = find_socket_info(s);
7539 int scm_rights_pipe_fd = -1;
7541 rc = swrap_sendmsg_before_unix(omsg, &msg,
7542 &scm_rights_pipe_fd);
7546 ret = libc_sendmsg(s, &msg, flags);
7547 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7550 ZERO_STRUCT(un_addr);
7552 tmp.iov_base = NULL;
7559 if (si->connected == 0) {
7560 msg.msg_name = omsg->msg_name; /* optional address */
7561 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7563 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7564 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7566 SWRAP_UNLOCK_SI(si);
7568 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7569 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7570 uint8_t *cmbuf = NULL;
7573 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7579 msg.msg_controllen = 0;
7580 msg.msg_control = NULL;
7582 msg.msg_control = cmbuf;
7583 msg.msg_controllen = cmlen;
7586 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7588 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7590 int saved_errno = errno;
7591 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7592 SAFE_FREE(msg.msg_control);
7594 errno = saved_errno;
7601 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7608 char *swrap_dir = NULL;
7610 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7611 avail += msg.msg_iov[i].iov_len;
7617 /* we capture it as one single packet */
7618 buf = (uint8_t *)malloc(remain);
7620 int saved_errno = errno;
7621 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7622 SAFE_FREE(msg.msg_control);
7624 errno = saved_errno;
7628 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7629 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7631 msg.msg_iov[i].iov_base,
7634 remain -= this_time;
7637 type = SOCKET_TYPE_CHAR_UDP;
7639 swrap_dir = socket_wrapper_dir();
7640 if (swrap_dir == NULL) {
7641 int saved_errno = errno;
7642 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7643 SAFE_FREE(msg.msg_control);
7646 errno = saved_errno;
7650 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7651 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7652 if (stat(un_addr.sun_path, &st) != 0) continue;
7654 msg.msg_name = &un_addr; /* optional address */
7655 msg.msg_namelen = sizeof(un_addr); /* size of address */
7657 /* ignore the any errors in broadcast sends */
7658 libc_sendmsg(s, &msg, flags);
7661 SAFE_FREE(swrap_dir);
7665 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7668 SWRAP_UNLOCK_SI(si);
7673 ret = libc_sendmsg(s, &msg, flags);
7675 swrap_sendmsg_after(s, si, &msg, to, ret);
7677 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7679 int saved_errno = errno;
7680 SAFE_FREE(msg.msg_control);
7681 errno = saved_errno;
7688 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7690 return swrap_sendmsg(s, omsg, flags);
7693 /****************************************************************************
7695 ***************************************************************************/
7697 #ifdef HAVE_SENDMMSG
7698 #if defined(HAVE_SENDMMSG_SSIZE_T)
7700 static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7703 static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7706 struct socket_info *si = find_socket_info(s);
7707 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7708 struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7711 struct sockaddr_un un_addr;
7712 const struct sockaddr_un *to_un;
7713 const struct sockaddr *to;
7715 } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7718 char *swrap_dir = NULL;
7720 int found_bcast = 0;
7725 if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7726 vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7732 int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7734 for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7735 scm_rights_pipe_fd[i] = -1;
7738 for (i = 0; i < vlen; i++) {
7739 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7740 struct msghdr *msg = &msgvec[i].msg_hdr;
7742 rc = swrap_sendmsg_before_unix(omsg, msg,
7743 &scm_rights_pipe_fd[i]);
7750 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7755 for (i = 0; i < ret; i++) {
7756 omsgvec[i].msg_len = msgvec[i].msg_len;
7760 saved_errno = errno;
7761 for (i = 0; i < vlen; i++) {
7762 struct msghdr *msg = &msgvec[i].msg_hdr;
7764 swrap_sendmsg_after_unix(msg, ret,
7765 scm_rights_pipe_fd[i]);
7767 errno = saved_errno;
7773 connected = si->connected;
7774 SWRAP_UNLOCK_SI(si);
7776 for (i = 0; i < vlen; i++) {
7777 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7778 struct msghdr *msg = &msgvec[i].msg_hdr;
7780 if (connected == 0) {
7781 msg->msg_name = omsg->msg_name; /* optional address */
7782 msg->msg_namelen = omsg->msg_namelen; /* size of address */
7784 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7785 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7787 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7788 if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7789 uint8_t *cmbuf = NULL;
7792 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7799 msg->msg_control = cmbuf;
7800 msg->msg_controllen = cmlen;
7803 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7806 rc = swrap_sendmsg_before(s, si, msg,
7824 swrap_dir = socket_wrapper_dir();
7825 if (swrap_dir == NULL) {
7830 for (i = 0; i < vlen; i++) {
7831 struct msghdr *msg = &msgvec[i].msg_hdr;
7832 struct sockaddr_un *un_addr = &tmp[i].un_addr;
7833 const struct sockaddr *to = tmp[i].to;
7836 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7844 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7845 avail += msg->msg_iov[l].iov_len;
7851 /* we capture it as one single packet */
7852 buf = (uint8_t *)malloc(remain);
7858 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7859 size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
7861 msg->msg_iov[l].iov_base,
7864 remain -= this_time;
7867 type = SOCKET_TYPE_CHAR_UDP;
7869 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7870 swrap_un_path(un_addr, swrap_dir, type, iface, prt);
7871 if (stat(un_addr->sun_path, &st) != 0) continue;
7873 msg->msg_name = un_addr; /* optional address */
7874 msg->msg_namelen = sizeof(*un_addr); /* size of address */
7877 * ignore the any errors in broadcast sends and
7878 * do a single sendmsg instead of sendmmsg
7880 libc_sendmsg(s, msg, flags);
7884 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7885 SWRAP_UNLOCK_SI(si);
7889 msgvec[i].msg_len = len;
7896 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7902 for (i = 0; i < ret; i++) {
7903 omsgvec[i].msg_len = msgvec[i].msg_len;
7907 saved_errno = errno;
7908 for (i = 0; i < vlen; i++) {
7909 struct msghdr *msg = &msgvec[i].msg_hdr;
7911 if (i == 0 || i < ret) {
7912 swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
7914 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7915 SAFE_FREE(msg->msg_control);
7918 SAFE_FREE(swrap_dir);
7919 errno = saved_errno;
7924 #if defined(HAVE_SENDMMSG_SSIZE_T)
7926 ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
7929 int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
7932 return swrap_sendmmsg(s, msgvec, vlen, flags);
7934 #endif /* HAVE_SENDMMSG */
7936 /****************************************************************************
7938 ***************************************************************************/
7940 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7942 struct socket_info *si;
7945 struct swrap_address saddr = {
7946 .sa_socklen = sizeof(struct sockaddr_storage)
7951 si = find_socket_info(s);
7953 return libc_readv(s, vector, count);
7956 tmp.iov_base = NULL;
7960 msg.msg_name = &saddr.sa.s; /* optional address */
7961 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7962 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7963 msg.msg_iovlen = count; /* # elements in msg_iov */
7964 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7965 msg.msg_control = NULL; /* ancillary data, see below */
7966 msg.msg_controllen = 0; /* ancillary data buffer len */
7967 msg.msg_flags = 0; /* flags on received message */
7970 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7972 if (rc == -ENOTSOCK) {
7973 return libc_readv(s, vector, count);
7978 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7980 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7988 ssize_t readv(int s, const struct iovec *vector, int count)
7990 return swrap_readv(s, vector, count);
7993 /****************************************************************************
7995 ***************************************************************************/
7997 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
8001 struct sockaddr_un un_addr;
8004 struct socket_info *si = find_socket_info(s);
8007 return libc_writev(s, vector, count);
8010 tmp.iov_base = NULL;
8014 msg.msg_name = NULL; /* optional address */
8015 msg.msg_namelen = 0; /* size of address */
8016 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8017 msg.msg_iovlen = count; /* # elements in msg_iov */
8018 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8019 msg.msg_control = NULL; /* ancillary data, see below */
8020 msg.msg_controllen = 0; /* ancillary data buffer len */
8021 msg.msg_flags = 0; /* flags on received message */
8024 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
8026 if (rc == -ENOTSOCK) {
8027 return libc_readv(s, vector, count);
8032 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
8034 swrap_sendmsg_after(s, si, &msg, NULL, ret);
8039 ssize_t writev(int s, const struct iovec *vector, int count)
8041 return swrap_writev(s, vector, count);
8044 /****************************
8046 ***************************/
8048 static int swrap_remove_wrapper(const char *__func_name,
8049 int (*__close_fd_fn)(int fd),
8052 struct socket_info *si = NULL;
8054 int ret_errno = errno;
8057 swrap_mutex_lock(&socket_reset_mutex);
8059 si_index = find_socket_info_index(fd);
8060 if (si_index == -1) {
8061 swrap_mutex_unlock(&socket_reset_mutex);
8062 return __close_fd_fn(fd);
8065 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8066 reset_socket_info_index(fd);
8068 si = swrap_get_socket_info(si_index);
8070 swrap_mutex_lock(&first_free_mutex);
8073 ret = __close_fd_fn(fd);
8078 swrap_dec_refcount(si);
8080 if (swrap_get_refcount(si) > 0) {
8081 /* there are still references left */
8085 if (si->fd_passed) {
8089 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8090 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8093 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8094 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8095 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8098 if (si->un_addr.sun_path[0] != '\0') {
8099 unlink(si->un_addr.sun_path);
8103 swrap_set_next_free(si, first_free);
8104 first_free = si_index;
8107 SWRAP_UNLOCK_SI(si);
8108 swrap_mutex_unlock(&first_free_mutex);
8109 swrap_mutex_unlock(&socket_reset_mutex);
8115 static int swrap_noop_close(int fd)
8117 (void)fd; /* unused */
8121 static void swrap_remove_stale(int fd)
8123 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8127 * This allows socket_wrapper aware applications to
8128 * indicate that the given fd does not belong to
8131 * We already overload a lot of unrelated functions
8132 * like eventfd(), timerfd_create(), ... in order to
8133 * call swrap_remove_stale() on the returned fd, but
8134 * we'll never be able to handle all possible syscalls.
8136 * socket_wrapper_indicate_no_inet_fd() gives them a way
8139 * We don't export swrap_remove_stale() in order to
8140 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8143 void socket_wrapper_indicate_no_inet_fd(int fd)
8145 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8148 static int swrap_close(int fd)
8150 return swrap_remove_wrapper(__func__, libc_close, fd);
8155 return swrap_close(fd);
8158 #ifdef HAVE___CLOSE_NOCANCEL
8160 static int swrap___close_nocancel(int fd)
8162 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8165 int __close_nocancel(int fd);
8166 int __close_nocancel(int fd)
8168 return swrap___close_nocancel(fd);
8171 #endif /* HAVE___CLOSE_NOCANCEL */
8173 /****************************
8175 ***************************/
8177 static int swrap_dup(int fd)
8179 struct socket_info *si;
8182 idx = find_socket_info_index(fd);
8184 return libc_dup(fd);
8187 si = swrap_get_socket_info(idx);
8189 dup_fd = libc_dup(fd);
8191 int saved_errno = errno;
8192 errno = saved_errno;
8196 if ((size_t)dup_fd >= socket_fds_max) {
8197 SWRAP_LOG(SWRAP_LOG_ERROR,
8198 "The max socket index limit of %zu has been reached, "
8209 swrap_inc_refcount(si);
8211 SWRAP_UNLOCK_SI(si);
8213 /* Make sure we don't have an entry for the fd */
8214 swrap_remove_stale(dup_fd);
8216 set_socket_info_index(dup_fd, idx);
8223 return swrap_dup(fd);
8226 /****************************
8228 ***************************/
8230 static int swrap_dup2(int fd, int newfd)
8232 struct socket_info *si;
8235 idx = find_socket_info_index(fd);
8237 return libc_dup2(fd, newfd);
8240 si = swrap_get_socket_info(idx);
8244 * According to the manpage:
8246 * "If oldfd is a valid file descriptor, and newfd has the same
8247 * value as oldfd, then dup2() does nothing, and returns newfd."
8252 if ((size_t)newfd >= socket_fds_max) {
8253 SWRAP_LOG(SWRAP_LOG_ERROR,
8254 "The max socket index limit of %zu has been reached, "
8262 if (find_socket_info(newfd)) {
8263 /* dup2() does an implicit close of newfd, which we
8264 * need to emulate */
8268 dup_fd = libc_dup2(fd, newfd);
8270 int saved_errno = errno;
8271 errno = saved_errno;
8277 swrap_inc_refcount(si);
8279 SWRAP_UNLOCK_SI(si);
8281 /* Make sure we don't have an entry for the fd */
8282 swrap_remove_stale(dup_fd);
8284 set_socket_info_index(dup_fd, idx);
8289 int dup2(int fd, int newfd)
8291 return swrap_dup2(fd, newfd);
8294 /****************************
8296 ***************************/
8298 static int swrap_vfcntl(int fd, int cmd, va_list va)
8300 struct socket_info *si;
8301 int rc, dup_fd, idx;
8303 idx = find_socket_info_index(fd);
8305 return libc_vfcntl(fd, cmd, va);
8308 si = swrap_get_socket_info(idx);
8312 dup_fd = libc_vfcntl(fd, cmd, va);
8314 int saved_errno = errno;
8315 errno = saved_errno;
8319 /* Make sure we don't have an entry for the fd */
8320 swrap_remove_stale(dup_fd);
8322 if ((size_t)dup_fd >= socket_fds_max) {
8323 SWRAP_LOG(SWRAP_LOG_ERROR,
8324 "The max socket index limit of %zu has been reached, "
8335 swrap_inc_refcount(si);
8337 SWRAP_UNLOCK_SI(si);
8340 set_socket_info_index(dup_fd, idx);
8345 rc = libc_vfcntl(fd, cmd, va);
8352 int fcntl(int fd, int cmd, ...)
8359 rc = swrap_vfcntl(fd, cmd, va);
8366 /****************************
8368 ***************************/
8371 static int swrap_eventfd(int count, int flags)
8375 fd = libc_eventfd(count, flags);
8377 swrap_remove_stale(fd);
8383 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8384 int eventfd(unsigned int count, int flags)
8386 int eventfd(int count, int flags)
8389 return swrap_eventfd(count, flags);
8394 int pledge(const char *promises, const char *paths[])
8396 (void)promises; /* unused */
8397 (void)paths; /* unused */
8401 #endif /* HAVE_PLEDGE */
8404 static bool swrap_is_swrap_related_syscall(long int sysno)
8410 #endif /* SYS_close */
8415 #endif /* SYS_recvmmsg */
8420 #endif /* SYS_sendmmsg */
8427 static long int swrap_syscall(long int sysno, va_list vp)
8435 int fd = (int)va_arg(vp, int);
8437 SWRAP_LOG(SWRAP_LOG_TRACE,
8438 "calling swrap_close syscall %lu",
8440 rc = swrap_close(fd);
8443 #endif /* SYS_close */
8448 int fd = (int)va_arg(vp, int);
8449 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8450 unsigned int vlen = va_arg(vp, unsigned int);
8451 int flags = va_arg(vp, int);
8452 struct timespec *timeout = va_arg(vp, struct timespec *);
8454 SWRAP_LOG(SWRAP_LOG_TRACE,
8455 "calling swrap_recvmmsg syscall %lu",
8457 rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
8460 #endif /* SYS_recvmmsg */
8465 int fd = (int)va_arg(vp, int);
8466 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8467 unsigned int vlen = va_arg(vp, unsigned int);
8468 int flags = va_arg(vp, int);
8470 SWRAP_LOG(SWRAP_LOG_TRACE,
8471 "calling swrap_sendmmsg syscall %lu",
8473 rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
8476 #endif /* SYS_sendmmsg */
8487 #ifdef HAVE_SYSCALL_INT
8488 int syscall(int sysno, ...)
8490 long int syscall(long int sysno, ...)
8493 #ifdef HAVE_SYSCALL_INT
8500 va_start(va, sysno);
8503 * We should only handle the syscall numbers
8506 if (!swrap_is_swrap_related_syscall(sysno)) {
8507 rc = libc_vsyscall(sysno, va);
8512 if (!socket_wrapper_enabled()) {
8513 rc = libc_vsyscall(sysno, va);
8518 rc = swrap_syscall(sysno, va);
8523 #endif /* HAVE_SYSCALL */
8525 static void swrap_thread_prepare(void)
8528 * This function should only be called here!!
8530 * We bind all symobls to avoid deadlocks of the fork is
8531 * interrupted by a signal handler using a symbol of this
8534 swrap_bind_symbol_all();
8539 static void swrap_thread_parent(void)
8544 static void swrap_thread_child(void)
8549 /****************************
8551 ***************************/
8552 void swrap_constructor(void)
8554 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8555 SWRAP_LOG(SWRAP_LOG_ERROR,
8557 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8558 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8559 "sizeof(struct socket_info)=%zu",
8561 sizeof(struct swrap_unix_scm_rights),
8562 sizeof(struct swrap_unix_scm_rights_payload),
8563 sizeof(struct socket_info));
8570 * If we hold a lock and the application forks, then the child
8571 * is not able to unlock the mutex and we are in a deadlock.
8572 * This should prevent such deadlocks.
8574 pthread_atfork(&swrap_thread_prepare,
8575 &swrap_thread_parent,
8576 &swrap_thread_child);
8579 /****************************
8581 ***************************/
8584 * This function is called when the library is unloaded and makes sure that
8585 * sockets get closed and the unix file for the socket are unlinked.
8587 void swrap_destructor(void)
8591 if (socket_fds_idx != NULL) {
8592 for (i = 0; i < socket_fds_max; ++i) {
8593 if (socket_fds_idx[i] != -1) {
8597 SAFE_FREE(socket_fds_idx);
8602 if (swrap.libc.handle != NULL
8604 && swrap.libc.handle != RTLD_NEXT
8607 dlclose(swrap.libc.handle);
8609 if (swrap.libc.socket_handle
8611 && swrap.libc.socket_handle != RTLD_NEXT
8614 dlclose(swrap.libc.socket_handle);
8618 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8620 * On FreeBSD 12 (and maybe other platforms)
8621 * system libraries like libresolv prefix there
8622 * syscalls with '_' in order to always use
8623 * the symbols from libc.
8625 * In the interaction with resolv_wrapper,
8626 * we need to inject socket wrapper into libresolv,
8627 * which means we need to private all socket
8628 * related syscalls also with the '_' prefix.
8630 * This is tested in Samba's 'make test',
8631 * there we noticed that providing '_read',
8632 * '_open' and '_close' would cause errors, which
8633 * means we skip '_read', '_write' and
8634 * all non socket related calls without
8635 * further analyzing the problem.
8637 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8638 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8641 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8643 SWRAP_SYMBOL_ALIAS(accept, _accept);
8644 SWRAP_SYMBOL_ALIAS(bind, _bind);
8645 SWRAP_SYMBOL_ALIAS(connect, _connect);
8646 SWRAP_SYMBOL_ALIAS(dup, _dup);
8647 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8648 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8649 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8650 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8651 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8652 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8653 SWRAP_SYMBOL_ALIAS(listen, _listen);
8654 SWRAP_SYMBOL_ALIAS(readv, _readv);
8655 SWRAP_SYMBOL_ALIAS(recv, _recv);
8656 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8657 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8658 SWRAP_SYMBOL_ALIAS(send, _send);
8659 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8660 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8661 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8662 SWRAP_SYMBOL_ALIAS(socket, _socket);
8663 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8664 SWRAP_SYMBOL_ALIAS(writev, _writev);
8666 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */