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);
662 #undef SWRAP_SYMBOL_ENTRY
664 #define SWRAP_SYMBOL_ENTRY(i) \
666 __rtld_default_##i f; \
671 typedef bool (*__rtld_default_uid_wrapper_syscall_valid)(long int sysno);
672 typedef long int (*__rtld_default_uid_wrapper_syscall_va)(long int sysno, va_list va);
675 struct swrap_rtld_default_symbols {
677 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_valid);
678 SWRAP_SYMBOL_ENTRY(uid_wrapper_syscall_va);
683 #undef SWRAP_SYMBOL_ENTRY
689 struct swrap_libc_symbols symbols;
693 struct swrap_rtld_default_symbols symbols;
697 static struct swrap swrap;
700 static char *socket_wrapper_dir(void);
702 #define LIBC_NAME "libc.so"
709 static const char *swrap_str_lib(enum swrap_lib lib)
714 case SWRAP_LIBSOCKET:
718 /* Compiler would warn us about unhandled enum value if we get here */
722 static void *swrap_load_lib_handle(enum swrap_lib lib)
724 int flags = RTLD_LAZY;
729 const char *env_preload = getenv("LD_PRELOAD");
730 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
731 bool enable_deepbind = true;
733 /* Don't do a deepbind if we run with libasan */
734 if (env_preload != NULL && strlen(env_preload) < 1024) {
735 const char *p = strstr(env_preload, "libasan.so");
737 enable_deepbind = false;
741 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
742 enable_deepbind = false;
745 if (enable_deepbind) {
746 flags |= RTLD_DEEPBIND;
751 case SWRAP_LIBSOCKET:
752 #ifdef HAVE_LIBSOCKET
753 handle = swrap.libc.socket_handle;
754 if (handle == NULL) {
755 for (i = 10; i >= 0; i--) {
756 char soname[256] = {0};
758 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
759 handle = dlopen(soname, flags);
760 if (handle != NULL) {
765 swrap.libc.socket_handle = handle;
770 handle = swrap.libc.handle;
772 if (handle == NULL) {
773 handle = dlopen(LIBC_SO, flags);
775 swrap.libc.handle = handle;
778 if (handle == NULL) {
779 for (i = 10; i >= 0; i--) {
780 char soname[256] = {0};
782 snprintf(soname, sizeof(soname), "libc.so.%d", i);
783 handle = dlopen(soname, flags);
784 if (handle != NULL) {
789 swrap.libc.handle = handle;
794 if (handle == NULL) {
796 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
798 SWRAP_LOG(SWRAP_LOG_ERROR,
799 "Failed to dlopen library: %s",
808 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
813 handle = swrap_load_lib_handle(lib);
815 func = dlsym(handle, fn_name);
817 SWRAP_LOG(SWRAP_LOG_ERROR,
818 "Failed to find %s: %s",
824 SWRAP_LOG(SWRAP_LOG_TRACE,
832 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
833 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
837 ret = pthread_mutex_lock(mutex);
839 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
840 getpid(), getppid(), caller, line, name, strerror(ret));
845 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
846 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
850 ret = pthread_mutex_unlock(mutex);
852 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
853 getpid(), getppid(), caller, line, name, strerror(ret));
859 * These macros have a thread race condition on purpose!
861 * This is an optimization to avoid locking each time we check if the symbol is
864 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
865 swrap.libc.symbols._libc_##sym_name.obj = \
866 _swrap_bind_symbol(lib, #sym_name); \
869 #define swrap_bind_symbol_libc(sym_name) \
870 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
872 #define swrap_bind_symbol_libsocket(sym_name) \
873 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
875 #define swrap_bind_symbol_rtld_default_optional(sym_name) do { \
876 swrap.rtld_default.symbols._rtld_default_##sym_name.obj = \
877 dlsym(RTLD_DEFAULT, #sym_name); \
880 static void swrap_bind_symbol_all(void);
882 /****************************************************************************
884 ****************************************************************************
886 * Functions especially from libc need to be loaded individually, you can't
887 * load all at once or gdb will segfault at startup. The same applies to
888 * valgrind and has probably something todo with with the linker. So we need
889 * load each function at the point it is called the first time.
891 ****************************************************************************/
894 static int libc_accept4(int sockfd,
895 struct sockaddr *addr,
899 swrap_bind_symbol_all();
901 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
904 #else /* HAVE_ACCEPT4 */
906 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
908 swrap_bind_symbol_all();
910 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
912 #endif /* HAVE_ACCEPT4 */
914 static int libc_bind(int sockfd,
915 const struct sockaddr *addr,
918 swrap_bind_symbol_all();
920 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
923 static int libc_close(int fd)
925 swrap_bind_symbol_all();
927 return swrap.libc.symbols._libc_close.f(fd);
930 #ifdef HAVE___CLOSE_NOCANCEL
931 static int libc___close_nocancel(int fd)
933 swrap_bind_symbol_all();
935 return swrap.libc.symbols._libc___close_nocancel.f(fd);
937 #endif /* HAVE___CLOSE_NOCANCEL */
939 static int libc_connect(int sockfd,
940 const struct sockaddr *addr,
943 swrap_bind_symbol_all();
945 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
948 static int libc_dup(int fd)
950 swrap_bind_symbol_all();
952 return swrap.libc.symbols._libc_dup.f(fd);
955 static int libc_dup2(int oldfd, int newfd)
957 swrap_bind_symbol_all();
959 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
963 static int libc_eventfd(int count, int flags)
965 swrap_bind_symbol_all();
967 return swrap.libc.symbols._libc_eventfd.f(count, flags);
971 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
972 static int libc_vfcntl(int fd, int cmd, va_list ap)
977 swrap_bind_symbol_all();
979 arg = va_arg(ap, void *);
981 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
986 static int libc_getpeername(int sockfd,
987 struct sockaddr *addr,
990 swrap_bind_symbol_all();
992 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
995 static int libc_getsockname(int sockfd,
996 struct sockaddr *addr,
999 swrap_bind_symbol_all();
1001 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
1004 static int libc_getsockopt(int sockfd,
1010 swrap_bind_symbol_all();
1012 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
1019 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1020 static int libc_vioctl(int d, unsigned long int request, va_list ap)
1025 swrap_bind_symbol_all();
1027 arg = va_arg(ap, void *);
1029 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
1034 static int libc_listen(int sockfd, int backlog)
1036 swrap_bind_symbol_all();
1038 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
1041 static FILE *libc_fopen(const char *name, const char *mode)
1043 swrap_bind_symbol_all();
1045 return swrap.libc.symbols._libc_fopen.f(name, mode);
1049 static FILE *libc_fopen64(const char *name, const char *mode)
1051 swrap_bind_symbol_all();
1053 return swrap.libc.symbols._libc_fopen64.f(name, mode);
1055 #endif /* HAVE_FOPEN64 */
1057 static void swrap_inject_o_largefile(int *flags)
1059 (void)*flags; /* maybe unused */
1060 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1062 if (((*flags) & O_PATH) == 0)
1065 *flags |= O_LARGEFILE;
1070 static int libc_vopen(const char *pathname, int flags, va_list ap)
1075 swrap_bind_symbol_all();
1077 swrap_inject_o_largefile(&flags);
1079 if (flags & O_CREAT) {
1080 mode = va_arg(ap, int);
1082 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1087 static int libc_open(const char *pathname, int flags, ...)
1092 va_start(ap, flags);
1093 fd = libc_vopen(pathname, flags, ap);
1100 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1105 swrap_bind_symbol_all();
1107 swrap_inject_o_largefile(&flags);
1109 if (flags & O_CREAT) {
1110 mode = va_arg(ap, int);
1112 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1116 #endif /* HAVE_OPEN64 */
1118 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1123 swrap_bind_symbol_all();
1125 swrap_inject_o_largefile(&flags);
1127 if (flags & O_CREAT) {
1128 mode = va_arg(ap, int);
1130 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1139 static int libc_openat(int dirfd, const char *path, int flags, ...)
1144 va_start(ap, flags);
1145 fd = libc_vopenat(dirfd, path, flags, ap);
1152 static int libc_pipe(int pipefd[2])
1154 swrap_bind_symbol_all();
1156 return swrap.libc.symbols._libc_pipe.f(pipefd);
1159 static int libc_read(int fd, void *buf, size_t count)
1161 swrap_bind_symbol_all();
1163 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1166 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1168 swrap_bind_symbol_all();
1170 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1173 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1175 swrap_bind_symbol_all();
1177 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1180 static int libc_recvfrom(int sockfd,
1184 struct sockaddr *src_addr,
1187 swrap_bind_symbol_all();
1189 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1197 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1199 swrap_bind_symbol_all();
1201 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1204 #ifdef HAVE_RECVMMSG
1205 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1207 static ssize_t libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
1208 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1209 /* Linux legacy glibc < 2.21 */
1210 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
1212 /* Linux glibc >= 2.21 */
1213 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
1216 swrap_bind_symbol_all();
1218 return swrap.libc.symbols._libc_recvmmsg.f(sockfd, msgvec, vlen, flags, timeout);
1222 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1224 swrap_bind_symbol_all();
1226 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1229 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1231 swrap_bind_symbol_all();
1233 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1236 #ifdef HAVE_SENDMMSG
1237 #if defined(HAVE_SENDMMSG_SSIZE_T)
1239 static ssize_t libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags)
1242 static int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
1245 swrap_bind_symbol_all();
1247 return swrap.libc.symbols._libc_sendmmsg.f(sockfd, msgvec, vlen, flags);
1251 static int libc_sendto(int sockfd,
1255 const struct sockaddr *dst_addr,
1258 swrap_bind_symbol_all();
1260 return swrap.libc.symbols._libc_sendto.f(sockfd,
1268 static int libc_setsockopt(int sockfd,
1274 swrap_bind_symbol_all();
1276 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1283 #ifdef HAVE_SIGNALFD
1284 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1286 swrap_bind_symbol_all();
1288 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1292 static int libc_socket(int domain, int type, int protocol)
1294 swrap_bind_symbol_all();
1296 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1299 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1301 swrap_bind_symbol_all();
1303 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1306 #ifdef HAVE_TIMERFD_CREATE
1307 static int libc_timerfd_create(int clockid, int flags)
1309 swrap_bind_symbol_all();
1311 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1315 static ssize_t libc_write(int fd, const void *buf, size_t count)
1317 swrap_bind_symbol_all();
1319 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1322 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1324 swrap_bind_symbol_all();
1326 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1330 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1331 static long int libc_vsyscall(long int sysno, va_list va)
1337 swrap_bind_symbol_all();
1339 for (i = 0; i < 8; i++) {
1340 args[i] = va_arg(va, long int);
1343 rc = swrap.libc.symbols._libc_syscall.f(sysno,
1356 static bool swrap_uwrap_syscall_valid(long int sysno)
1358 swrap_bind_symbol_all();
1360 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f == NULL) {
1364 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_valid.f(
1368 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
1369 static long int swrap_uwrap_syscall_va(long int sysno, va_list va)
1371 swrap_bind_symbol_all();
1373 if (swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f == NULL) {
1375 * Fallback to libc, if uid_wrapper_syscall_va is not
1378 return libc_vsyscall(sysno, va);
1381 return swrap.rtld_default.symbols._rtld_default_uid_wrapper_syscall_va.f(
1385 #endif /* HAVE_SYSCALL */
1387 /* DO NOT call this function during library initialization! */
1388 static void __swrap_bind_symbol_all_once(void)
1391 swrap_bind_symbol_libsocket(accept4);
1393 swrap_bind_symbol_libsocket(accept);
1395 swrap_bind_symbol_libsocket(bind);
1396 swrap_bind_symbol_libc(close);
1397 #ifdef HAVE___CLOSE_NOCANCEL
1398 swrap_bind_symbol_libc(__close_nocancel);
1400 swrap_bind_symbol_libsocket(connect);
1401 swrap_bind_symbol_libc(dup);
1402 swrap_bind_symbol_libc(dup2);
1403 swrap_bind_symbol_libc(fcntl);
1404 swrap_bind_symbol_libc(fopen);
1406 swrap_bind_symbol_libc(fopen64);
1409 swrap_bind_symbol_libc(eventfd);
1411 swrap_bind_symbol_libsocket(getpeername);
1412 swrap_bind_symbol_libsocket(getsockname);
1413 swrap_bind_symbol_libsocket(getsockopt);
1414 swrap_bind_symbol_libc(ioctl);
1415 swrap_bind_symbol_libsocket(listen);
1416 swrap_bind_symbol_libc(open);
1418 swrap_bind_symbol_libc(open64);
1420 swrap_bind_symbol_libc(openat);
1421 swrap_bind_symbol_libsocket(pipe);
1422 swrap_bind_symbol_libc(read);
1423 swrap_bind_symbol_libsocket(readv);
1424 swrap_bind_symbol_libsocket(recv);
1425 swrap_bind_symbol_libsocket(recvfrom);
1426 swrap_bind_symbol_libsocket(recvmsg);
1427 #ifdef HAVE_RECVMMSG
1428 swrap_bind_symbol_libsocket(recvmmsg);
1430 swrap_bind_symbol_libsocket(send);
1431 swrap_bind_symbol_libsocket(sendmsg);
1432 #ifdef HAVE_SENDMMSG
1433 swrap_bind_symbol_libsocket(sendmmsg);
1435 swrap_bind_symbol_libsocket(sendto);
1436 swrap_bind_symbol_libsocket(setsockopt);
1437 #ifdef HAVE_SIGNALFD
1438 swrap_bind_symbol_libsocket(signalfd);
1440 swrap_bind_symbol_libsocket(socket);
1441 swrap_bind_symbol_libsocket(socketpair);
1442 #ifdef HAVE_TIMERFD_CREATE
1443 swrap_bind_symbol_libc(timerfd_create);
1445 swrap_bind_symbol_libc(write);
1446 swrap_bind_symbol_libsocket(writev);
1448 swrap_bind_symbol_libc(syscall);
1449 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_valid);
1450 swrap_bind_symbol_rtld_default_optional(uid_wrapper_syscall_va);
1454 static void swrap_bind_symbol_all(void)
1456 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1458 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1461 /*********************************************************
1462 * SWRAP HELPER FUNCTIONS
1463 *********************************************************/
1466 * We return 127.0.0.0 (default) or 10.53.57.0.
1468 * This can be controlled by:
1469 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1471 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1473 static in_addr_t swrap_ipv4_net(void)
1475 static int initialized;
1476 static in_addr_t hv;
1477 const char *net_str = NULL;
1486 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1487 if (net_str == NULL) {
1488 net_str = "127.0.0.0";
1491 ret = inet_pton(AF_INET, net_str, &nv);
1493 SWRAP_LOG(SWRAP_LOG_ERROR,
1494 "INVALID IPv4 Network [%s]",
1499 hv = ntohl(nv.s_addr);
1509 SWRAP_LOG(SWRAP_LOG_ERROR,
1510 "INVALID IPv4 Network [%s][0x%x] should be "
1511 "127.0.0.0 or 10.53.57.0",
1512 net_str, (unsigned)hv);
1520 * This returns 127.255.255.255 or 10.255.255.255
1522 static in_addr_t swrap_ipv4_bcast(void)
1526 hv = swrap_ipv4_net();
1527 hv |= IN_CLASSA_HOST;
1533 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1535 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1539 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1540 SWRAP_LOG(SWRAP_LOG_ERROR,
1541 "swrap_ipv4_iface(%u) invalid!",
1547 hv = swrap_ipv4_net();
1557 static const struct in6_addr *swrap_ipv6(void)
1559 static struct in6_addr v;
1560 static int initialized;
1568 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1577 static void set_port(int family, int prt, struct swrap_address *addr)
1581 addr->sa.in.sin_port = htons(prt);
1585 addr->sa.in6.sin6_port = htons(prt);
1591 static size_t socket_length(int family)
1595 return sizeof(struct sockaddr_in);
1598 return sizeof(struct sockaddr_in6);
1604 struct swrap_sockaddr_buf {
1608 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1609 const struct sockaddr *saddr)
1611 unsigned int port = 0;
1612 char addr[64] = {0,};
1614 switch (saddr->sa_family) {
1616 const struct sockaddr_in *in =
1617 (const struct sockaddr_in *)(const void *)saddr;
1619 port = ntohs(in->sin_port);
1621 inet_ntop(saddr->sa_family,
1623 addr, sizeof(addr));
1628 const struct sockaddr_in6 *in6 =
1629 (const struct sockaddr_in6 *)(const void *)saddr;
1631 port = ntohs(in6->sin6_port);
1633 inet_ntop(saddr->sa_family,
1635 addr, sizeof(addr));
1640 snprintf(addr, sizeof(addr),
1641 "<Unknown address family %u>",
1646 snprintf(buf->str, sizeof(buf->str),
1647 "addr[%s]/port[%u]",
1653 static struct socket_info *swrap_get_socket_info(int si_index)
1655 return (struct socket_info *)(&(sockets[si_index].info));
1658 static int swrap_get_refcount(struct socket_info *si)
1660 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1661 return sic->meta.refcount;
1664 static void swrap_inc_refcount(struct socket_info *si)
1666 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1668 sic->meta.refcount += 1;
1671 static void swrap_dec_refcount(struct socket_info *si)
1673 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1675 sic->meta.refcount -= 1;
1678 static int swrap_get_next_free(struct socket_info *si)
1680 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1682 return sic->meta.next_free;
1685 static void swrap_set_next_free(struct socket_info *si, int next_free)
1687 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1689 sic->meta.next_free = next_free;
1692 static int swrap_un_path(struct sockaddr_un *un,
1693 const char *swrap_dir,
1700 ret = snprintf(un->sun_path,
1701 sizeof(un->sun_path),
1707 if ((size_t)ret >= sizeof(un->sun_path)) {
1708 return ENAMETOOLONG;
1714 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1715 const char *swrap_dir)
1719 ret = snprintf(un->sun_path,
1720 sizeof(un->sun_path),
1724 if ((size_t)ret >= sizeof(un->sun_path)) {
1725 return ENAMETOOLONG;
1731 static bool swrap_dir_usable(const char *swrap_dir)
1733 struct sockaddr_un un;
1736 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1741 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1749 static char *socket_wrapper_dir(void)
1751 char *swrap_dir = NULL;
1752 char *s = getenv("SOCKET_WRAPPER_DIR");
1756 if (s == NULL || s[0] == '\0') {
1757 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1761 swrap_dir = realpath(s, NULL);
1762 if (swrap_dir == NULL) {
1763 SWRAP_LOG(SWRAP_LOG_ERROR,
1764 "Unable to resolve socket_wrapper dir path: %s - %s",
1770 ok = swrap_dir_usable(swrap_dir);
1777 ok = swrap_dir_usable(s);
1779 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1783 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1785 SWRAP_LOG(SWRAP_LOG_ERROR,
1786 "realpath(SOCKET_WRAPPER_DIR) too long and "
1787 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1792 swrap_dir = strdup(s);
1793 if (swrap_dir == NULL) {
1794 SWRAP_LOG(SWRAP_LOG_ERROR,
1795 "Unable to duplicate socket_wrapper dir path");
1799 SWRAP_LOG(SWRAP_LOG_WARN,
1800 "realpath(SOCKET_WRAPPER_DIR) too long, "
1801 "using original SOCKET_WRAPPER_DIR\n");
1804 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1808 static unsigned int socket_wrapper_mtu(void)
1810 static unsigned int max_mtu = 0;
1815 swrap_mutex_lock(&mtu_update_mutex);
1821 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1823 s = getenv("SOCKET_WRAPPER_MTU");
1828 tmp = strtol(s, &endp, 10);
1833 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1839 swrap_mutex_unlock(&mtu_update_mutex);
1843 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1845 pthread_mutexattr_t ma;
1846 bool need_destroy = false;
1849 #define __CHECK(cmd) do { \
1852 SWRAP_LOG(SWRAP_LOG_ERROR, \
1853 "%s: %s - failed %d", \
1859 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1860 __CHECK(pthread_mutexattr_init(&ma));
1861 need_destroy = true;
1862 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1863 __CHECK(pthread_mutex_init(m, &ma));
1866 pthread_mutexattr_destroy(&ma);
1871 static size_t socket_wrapper_max_sockets(void)
1877 if (socket_info_max != 0) {
1878 return socket_info_max;
1881 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1883 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1884 if (s == NULL || s[0] == '\0') {
1888 tmp = strtoul(s, &endp, 10);
1893 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1894 SWRAP_LOG(SWRAP_LOG_ERROR,
1895 "Invalid number of sockets specified, "
1896 "using default (%zu)",
1900 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1901 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1902 SWRAP_LOG(SWRAP_LOG_ERROR,
1903 "Invalid number of sockets specified, "
1904 "using maximum (%zu).",
1908 socket_info_max = tmp;
1911 return socket_info_max;
1914 static void socket_wrapper_init_fds_idx(void)
1919 if (socket_fds_idx != NULL) {
1923 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1925 SWRAP_LOG(SWRAP_LOG_ERROR,
1926 "Failed to allocate socket fds index array: %s",
1931 for (i = 0; i < socket_fds_max; i++) {
1935 socket_fds_idx = tmp;
1938 static void socket_wrapper_init_sockets(void)
1944 swrap_bind_symbol_all();
1946 swrap_mutex_lock(&sockets_mutex);
1948 if (sockets != NULL) {
1949 swrap_mutex_unlock(&sockets_mutex);
1953 SWRAP_LOG(SWRAP_LOG_DEBUG,
1954 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1955 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1958 * Intialize the static cache early before
1959 * any thread is able to start.
1961 (void)swrap_ipv4_net();
1963 socket_wrapper_init_fds_idx();
1965 /* Needs to be called inside the sockets_mutex lock here. */
1966 max_sockets = socket_wrapper_max_sockets();
1968 sockets = (struct socket_info_container *)calloc(max_sockets,
1969 sizeof(struct socket_info_container));
1971 if (sockets == NULL) {
1972 SWRAP_LOG(SWRAP_LOG_ERROR,
1973 "Failed to allocate sockets array: %s",
1975 swrap_mutex_unlock(&sockets_mutex);
1979 swrap_mutex_lock(&first_free_mutex);
1980 swrap_mutex_lock(&sockets_si_global);
1984 for (i = 0; i < max_sockets; i++) {
1985 swrap_set_next_free(&sockets[i].info, i+1);
1988 /* mark the end of the free list */
1989 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1991 swrap_mutex_unlock(&sockets_si_global);
1992 swrap_mutex_unlock(&first_free_mutex);
1993 swrap_mutex_unlock(&sockets_mutex);
1999 bool socket_wrapper_enabled(void)
2001 char *s = socket_wrapper_dir();
2009 socket_wrapper_init_sockets();
2014 static unsigned int socket_wrapper_default_iface(void)
2016 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
2019 if (sscanf(s, "%u", &iface) == 1) {
2020 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
2026 return 1;/* 127.0.0.1 */
2029 static void set_socket_info_index(int fd, int idx)
2031 SWRAP_LOG(SWRAP_LOG_TRACE,
2034 socket_fds_idx[fd] = idx;
2035 /* This builtin issues a full memory barrier. */
2036 __sync_synchronize();
2039 static void reset_socket_info_index(int fd)
2041 SWRAP_LOG(SWRAP_LOG_TRACE,
2044 set_socket_info_index(fd, -1);
2047 static int find_socket_info_index(int fd)
2053 if (socket_fds_idx == NULL) {
2057 if ((size_t)fd >= socket_fds_max) {
2059 * Do not add a log here as some applications do stupid things
2062 * for (fd = 0; fd <= getdtablesize(); fd++) {
2066 * This would produce millions of lines of debug messages.
2069 SWRAP_LOG(SWRAP_LOG_ERROR,
2070 "Looking for a socket info for the fd %d is over the "
2071 "max socket index limit of %zu.",
2078 /* This builtin issues a full memory barrier. */
2079 __sync_synchronize();
2080 return socket_fds_idx[fd];
2083 static int swrap_add_socket_info(const struct socket_info *si_input)
2085 struct socket_info *si = NULL;
2088 if (si_input == NULL) {
2093 swrap_mutex_lock(&first_free_mutex);
2094 if (first_free == -1) {
2099 si_index = first_free;
2100 si = swrap_get_socket_info(si_index);
2104 first_free = swrap_get_next_free(si);
2106 swrap_inc_refcount(si);
2108 SWRAP_UNLOCK_SI(si);
2111 swrap_mutex_unlock(&first_free_mutex);
2116 static int swrap_create_socket(struct socket_info *si, int fd)
2120 if ((size_t)fd >= socket_fds_max) {
2121 SWRAP_LOG(SWRAP_LOG_ERROR,
2122 "The max socket index limit of %zu has been reached, "
2130 idx = swrap_add_socket_info(si);
2135 set_socket_info_index(fd, idx);
2140 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2147 p = strrchr(un->sun_path, '/');
2148 if (p) p++; else p = un->sun_path;
2150 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2151 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2157 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2158 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2165 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2171 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2175 case SOCKET_TYPE_CHAR_TCP:
2176 case SOCKET_TYPE_CHAR_UDP: {
2177 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2179 if ((*len) < sizeof(*in2)) {
2180 SWRAP_LOG(SWRAP_LOG_ERROR,
2181 "V4: *len(%zu) < sizeof(*in2)=%zu",
2182 (size_t)*len, sizeof(*in2));
2187 memset(in2, 0, sizeof(*in2));
2188 in2->sin_family = AF_INET;
2189 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2190 in2->sin_port = htons(prt);
2192 *len = sizeof(*in2);
2196 case SOCKET_TYPE_CHAR_TCP_V6:
2197 case SOCKET_TYPE_CHAR_UDP_V6: {
2198 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2200 if ((*len) < sizeof(*in2)) {
2201 SWRAP_LOG(SWRAP_LOG_ERROR,
2202 "V6: *len(%zu) < sizeof(*in2)=%zu",
2203 (size_t)*len, sizeof(*in2));
2204 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2209 memset(in2, 0, sizeof(*in2));
2210 in2->sin6_family = AF_INET6;
2211 in2->sin6_addr = *swrap_ipv6();
2212 in2->sin6_addr.s6_addr[15] = iface;
2213 in2->sin6_port = htons(prt);
2215 *len = sizeof(*in2);
2220 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2229 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2236 char *swrap_dir = NULL;
2238 if (bcast) *bcast = 0;
2240 switch (inaddr->sa_family) {
2242 const struct sockaddr_in *in =
2243 (const struct sockaddr_in *)(const void *)inaddr;
2244 unsigned int addr = ntohl(in->sin_addr.s_addr);
2248 const unsigned int sw_net_addr = swrap_ipv4_net();
2249 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2253 u_type = SOCKET_TYPE_CHAR_TCP;
2256 u_type = SOCKET_TYPE_CHAR_UDP;
2257 a_type = SOCKET_TYPE_CHAR_UDP;
2258 b_type = SOCKET_TYPE_CHAR_UDP;
2261 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2262 errno = ESOCKTNOSUPPORT;
2266 prt = ntohs(in->sin_port);
2267 if (a_type && addr == 0xFFFFFFFF) {
2268 /* 255.255.255.255 only udp */
2271 iface = socket_wrapper_default_iface();
2272 } else if (b_type && addr == sw_bcast_addr) {
2281 iface = socket_wrapper_default_iface();
2282 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2283 /* 127.0.0.X or 10.53.57.X */
2286 iface = (addr & 0x000000FF);
2288 struct swrap_sockaddr_buf buf = {};
2289 SWRAP_LOG(SWRAP_LOG_WARN,
2291 swrap_sockaddr_string(&buf, inaddr));
2292 errno = ENETUNREACH;
2295 if (bcast) *bcast = is_bcast;
2300 const struct sockaddr_in6 *in =
2301 (const struct sockaddr_in6 *)(const void *)inaddr;
2302 struct in6_addr cmp1, cmp2;
2306 type = SOCKET_TYPE_CHAR_TCP_V6;
2309 type = SOCKET_TYPE_CHAR_UDP_V6;
2312 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2313 errno = ESOCKTNOSUPPORT;
2317 /* XXX no multicast/broadcast */
2319 prt = ntohs(in->sin6_port);
2321 cmp1 = *swrap_ipv6();
2322 cmp2 = in->sin6_addr;
2323 cmp2.s6_addr[15] = 0;
2324 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2325 iface = in->sin6_addr.s6_addr[15];
2327 struct swrap_sockaddr_buf buf = {};
2328 SWRAP_LOG(SWRAP_LOG_WARN,
2330 swrap_sockaddr_string(&buf, inaddr));
2331 errno = ENETUNREACH;
2339 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2340 errno = ENETUNREACH;
2345 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2350 swrap_dir = socket_wrapper_dir();
2351 if (swrap_dir == NULL) {
2357 swrap_un_path_EINVAL(un, swrap_dir);
2358 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2359 SAFE_FREE(swrap_dir);
2360 /* the caller need to do more processing */
2364 swrap_un_path(un, swrap_dir, type, iface, prt);
2365 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2367 SAFE_FREE(swrap_dir);
2372 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2380 char *swrap_dir = NULL;
2382 if (bcast) *bcast = 0;
2384 switch (si->family) {
2386 const struct sockaddr_in *in =
2387 (const struct sockaddr_in *)(const void *)inaddr;
2388 unsigned int addr = ntohl(in->sin_addr.s_addr);
2393 const unsigned int sw_net_addr = swrap_ipv4_net();
2394 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2396 prt = ntohs(in->sin_port);
2400 u_type = SOCKET_TYPE_CHAR_TCP;
2401 d_type = SOCKET_TYPE_CHAR_TCP;
2404 u_type = SOCKET_TYPE_CHAR_UDP;
2405 d_type = SOCKET_TYPE_CHAR_UDP;
2406 a_type = SOCKET_TYPE_CHAR_UDP;
2407 b_type = SOCKET_TYPE_CHAR_UDP;
2410 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2411 errno = ESOCKTNOSUPPORT;
2419 iface = socket_wrapper_default_iface();
2420 } else if (a_type && addr == 0xFFFFFFFF) {
2421 /* 255.255.255.255 only udp */
2424 iface = socket_wrapper_default_iface();
2425 } else if (b_type && addr == sw_bcast_addr) {
2426 /* 127.255.255.255 only udp */
2429 iface = socket_wrapper_default_iface();
2430 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2434 iface = (addr & 0x000000FF);
2436 errno = EADDRNOTAVAIL;
2440 /* Store the bind address for connect() */
2441 if (si->bindname.sa_socklen == 0) {
2442 struct sockaddr_in bind_in;
2443 socklen_t blen = sizeof(struct sockaddr_in);
2445 ZERO_STRUCT(bind_in);
2446 bind_in.sin_family = in->sin_family;
2447 bind_in.sin_port = in->sin_port;
2448 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2449 si->bindname.sa_socklen = blen;
2450 memcpy(&si->bindname.sa.in, &bind_in, blen);
2457 const struct sockaddr_in6 *in =
2458 (const struct sockaddr_in6 *)(const void *)inaddr;
2459 struct in6_addr cmp1, cmp2;
2463 type = SOCKET_TYPE_CHAR_TCP_V6;
2466 type = SOCKET_TYPE_CHAR_UDP_V6;
2469 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2470 errno = ESOCKTNOSUPPORT;
2474 /* XXX no multicast/broadcast */
2476 prt = ntohs(in->sin6_port);
2478 cmp1 = *swrap_ipv6();
2479 cmp2 = in->sin6_addr;
2480 cmp2.s6_addr[15] = 0;
2481 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2482 iface = socket_wrapper_default_iface();
2483 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2484 iface = in->sin6_addr.s6_addr[15];
2486 errno = EADDRNOTAVAIL;
2490 /* Store the bind address for connect() */
2491 if (si->bindname.sa_socklen == 0) {
2492 struct sockaddr_in6 bind_in;
2493 socklen_t blen = sizeof(struct sockaddr_in6);
2495 ZERO_STRUCT(bind_in);
2496 bind_in.sin6_family = in->sin6_family;
2497 bind_in.sin6_port = in->sin6_port;
2499 bind_in.sin6_addr = *swrap_ipv6();
2500 bind_in.sin6_addr.s6_addr[15] = iface;
2502 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2503 si->bindname.sa_socklen = blen;
2510 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2511 errno = EADDRNOTAVAIL;
2516 if (bcast) *bcast = is_bcast;
2518 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2523 swrap_dir = socket_wrapper_dir();
2524 if (swrap_dir == NULL) {
2530 /* handle auto-allocation of ephemeral ports */
2531 for (prt = 5001; prt < 10000; prt++) {
2532 swrap_un_path(un, swrap_dir, type, iface, prt);
2533 if (stat(un->sun_path, &st) == 0) continue;
2535 set_port(si->family, prt, &si->myname);
2536 set_port(si->family, prt, &si->bindname);
2543 SAFE_FREE(swrap_dir);
2548 swrap_un_path(un, swrap_dir, type, iface, prt);
2549 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2551 SAFE_FREE(swrap_dir);
2556 static struct socket_info *find_socket_info(int fd)
2558 int idx = find_socket_info_index(fd);
2564 return swrap_get_socket_info(idx);
2568 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2570 struct socket_info_fd *f;
2571 const struct socket_info *last_s = NULL;
2573 /* first catch invalid input */
2574 switch (sa->sa_family) {
2576 if (len < sizeof(struct sockaddr_in)) {
2582 if (len < sizeof(struct sockaddr_in6)) {
2592 for (f = socket_fds; f; f = f->next) {
2593 struct socket_info *s = swrap_get_socket_info(f->si_index);
2600 if (s->myname == NULL) {
2603 if (s->myname->sa_family != sa->sa_family) {
2606 switch (s->myname->sa_family) {
2608 struct sockaddr_in *sin1, *sin2;
2610 sin1 = (struct sockaddr_in *)s->myname;
2611 sin2 = (struct sockaddr_in *)sa;
2613 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2616 if (sin1->sin_port != sin2->sin_port) {
2619 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2629 struct sockaddr_in6 *sin1, *sin2;
2631 sin1 = (struct sockaddr_in6 *)s->myname;
2632 sin2 = (struct sockaddr_in6 *)sa;
2634 if (sin1->sin6_port != sin2->sin6_port) {
2637 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2659 static void swrap_remove_stale(int fd);
2661 static int sockaddr_convert_to_un(struct socket_info *si,
2662 const struct sockaddr *in_addr,
2664 struct sockaddr_un *out_addr,
2668 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2670 (void) in_len; /* unused */
2672 if (out_addr == NULL) {
2676 out->sa_family = AF_UNIX;
2677 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2678 out->sa_len = sizeof(*out_addr);
2681 switch (in_addr->sa_family) {
2683 const struct sockaddr_in *sin;
2684 if (si->family != AF_INET) {
2687 if (in_len < sizeof(struct sockaddr_in)) {
2690 sin = (const struct sockaddr_in *)(const void *)in_addr;
2691 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2696 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2697 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2711 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2712 errno = ESOCKTNOSUPPORT;
2716 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2718 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2724 errno = EAFNOSUPPORT;
2725 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2729 static int sockaddr_convert_from_un(const struct socket_info *si,
2730 const struct sockaddr_un *in_addr,
2731 socklen_t un_addrlen,
2733 struct sockaddr *out_addr,
2734 socklen_t *out_addrlen)
2738 if (out_addr == NULL || out_addrlen == NULL)
2741 if (un_addrlen == 0) {
2756 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2757 errno = ESOCKTNOSUPPORT;
2760 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2761 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2762 out_addr->sa_len = *out_addrlen;
2769 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2770 errno = EAFNOSUPPORT;
2774 enum swrap_packet_type {
2776 SWRAP_CONNECT_UNREACH,
2784 SWRAP_SENDTO_UNREACH,
2795 struct swrap_file_hdr {
2797 uint16_t version_major;
2798 uint16_t version_minor;
2801 uint32_t frame_max_len;
2802 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2805 #define SWRAP_FILE_HDR_SIZE 24
2807 struct swrap_packet_frame {
2809 uint32_t micro_seconds;
2810 uint32_t recorded_length;
2811 uint32_t full_length;
2813 #define SWRAP_PACKET_FRAME_SIZE 16
2815 union swrap_packet_ip {
2819 uint16_t packet_length;
2820 uint16_t identification;
2825 uint16_t hdr_checksum;
2829 #define SWRAP_PACKET_IP_V4_SIZE 20
2832 uint8_t flow_label_high;
2833 uint16_t flow_label_low;
2834 uint16_t payload_length;
2835 uint8_t next_header;
2837 uint8_t src_addr[16];
2838 uint8_t dest_addr[16];
2840 #define SWRAP_PACKET_IP_V6_SIZE 40
2842 #define SWRAP_PACKET_IP_SIZE 40
2844 union swrap_packet_payload {
2846 uint16_t source_port;
2856 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2858 uint16_t source_port;
2863 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2870 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2877 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2879 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2881 #define SWRAP_PACKET_MIN_ALLOC \
2882 (SWRAP_PACKET_FRAME_SIZE + \
2883 SWRAP_PACKET_IP_SIZE + \
2884 SWRAP_PACKET_PAYLOAD_SIZE)
2886 static const char *swrap_pcap_init_file(void)
2888 static int initialized = 0;
2889 static const char *s = NULL;
2890 static const struct swrap_file_hdr h;
2891 static const struct swrap_packet_frame f;
2892 static const union swrap_packet_ip i;
2893 static const union swrap_packet_payload p;
2895 if (initialized == 1) {
2901 * TODO: don't use the structs use plain buffer offsets
2902 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2904 * for now make sure we disable PCAP support
2905 * if the struct has alignment!
2907 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2910 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2913 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2916 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2919 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2922 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2925 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2928 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2931 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2934 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2938 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2942 if (strncmp(s, "./", 2) == 0) {
2945 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2949 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2950 const struct sockaddr *src,
2951 const struct sockaddr *dest,
2953 const uint8_t *payload,
2955 unsigned long tcp_seqno,
2956 unsigned long tcp_ack,
2957 unsigned char tcp_ctl,
2959 size_t *_packet_len)
2961 uint8_t *base = NULL;
2962 uint8_t *buf = NULL;
2965 struct swrap_packet_frame *frame;
2969 union swrap_packet_ip *ip;
2971 union swrap_packet_payload *pay;
2974 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2975 size_t wire_hdr_len = 0;
2976 size_t wire_len = 0;
2977 size_t ip_hdr_len = 0;
2978 size_t icmp_hdr_len = 0;
2979 size_t icmp_truncate_len = 0;
2980 uint8_t protocol = 0, icmp_protocol = 0;
2981 const struct sockaddr_in *src_in = NULL;
2982 const struct sockaddr_in *dest_in = NULL;
2984 const struct sockaddr_in6 *src_in6 = NULL;
2985 const struct sockaddr_in6 *dest_in6 = NULL;
2990 switch (src->sa_family) {
2992 src_in = (const struct sockaddr_in *)(const void *)src;
2993 dest_in = (const struct sockaddr_in *)(const void *)dest;
2994 src_port = src_in->sin_port;
2995 dest_port = dest_in->sin_port;
2996 ip_hdr_len = sizeof(i.ip->v4);
3000 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
3001 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
3002 src_port = src_in6->sin6_port;
3003 dest_port = dest_in6->sin6_port;
3004 ip_hdr_len = sizeof(i.ip->v6);
3011 switch (socket_type) {
3013 protocol = 0x06; /* TCP */
3014 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
3015 wire_len = wire_hdr_len + payload_len;
3019 protocol = 0x11; /* UDP */
3020 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
3021 wire_len = wire_hdr_len + payload_len;
3029 icmp_protocol = protocol;
3030 switch (src->sa_family) {
3032 protocol = 0x01; /* ICMPv4 */
3033 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
3037 protocol = 0x3A; /* ICMPv6 */
3038 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
3042 if (wire_len > 64 ) {
3043 icmp_truncate_len = wire_len - 64;
3045 wire_len += icmp_hdr_len;
3048 packet_len = nonwire_len + wire_len;
3049 alloc_len = packet_len;
3050 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
3051 alloc_len = SWRAP_PACKET_MIN_ALLOC;
3054 base = (uint8_t *)calloc(1, alloc_len);
3062 f.frame->seconds = tval->tv_sec;
3063 f.frame->micro_seconds = tval->tv_usec;
3064 f.frame->recorded_length = wire_len - icmp_truncate_len;
3065 f.frame->full_length = wire_len - icmp_truncate_len;
3067 buf += SWRAP_PACKET_FRAME_SIZE;
3070 switch (src->sa_family) {
3072 if (src_in == NULL || dest_in == NULL) {
3077 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3078 i.ip->v4.tos = 0x00;
3079 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
3080 i.ip->v4.identification = htons(0xFFFF);
3081 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3082 i.ip->v4.fragment = htons(0x0000);
3083 i.ip->v4.ttl = 0xFF;
3084 i.ip->v4.protocol = protocol;
3085 i.ip->v4.hdr_checksum = htons(0x0000);
3086 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
3087 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
3088 buf += SWRAP_PACKET_IP_V4_SIZE;
3092 if (src_in6 == NULL || dest_in6 == NULL) {
3097 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3098 i.ip->v6.flow_label_high = 0x00;
3099 i.ip->v6.flow_label_low = 0x0000;
3100 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3101 i.ip->v6.next_header = protocol;
3102 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
3103 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
3104 buf += SWRAP_PACKET_IP_V6_SIZE;
3110 pay = (union swrap_packet_payload *)(void *)buf;
3111 switch (src->sa_family) {
3113 pay->icmp4.type = 0x03; /* destination unreachable */
3114 pay->icmp4.code = 0x01; /* host unreachable */
3115 pay->icmp4.checksum = htons(0x0000);
3116 pay->icmp4.unused = htonl(0x00000000);
3118 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3120 /* set the ip header in the ICMP payload */
3122 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3123 i.ip->v4.tos = 0x00;
3124 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3125 i.ip->v4.identification = htons(0xFFFF);
3126 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3127 i.ip->v4.fragment = htons(0x0000);
3128 i.ip->v4.ttl = 0xFF;
3129 i.ip->v4.protocol = icmp_protocol;
3130 i.ip->v4.hdr_checksum = htons(0x0000);
3131 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3132 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3134 buf += SWRAP_PACKET_IP_V4_SIZE;
3136 src_port = dest_in->sin_port;
3137 dest_port = src_in->sin_port;
3141 pay->icmp6.type = 0x01; /* destination unreachable */
3142 pay->icmp6.code = 0x03; /* address unreachable */
3143 pay->icmp6.checksum = htons(0x0000);
3144 pay->icmp6.unused = htonl(0x00000000);
3145 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3147 /* set the ip header in the ICMP payload */
3149 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3150 i.ip->v6.flow_label_high = 0x00;
3151 i.ip->v6.flow_label_low = 0x0000;
3152 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3153 i.ip->v6.next_header = protocol;
3154 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3155 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3157 buf += SWRAP_PACKET_IP_V6_SIZE;
3159 src_port = dest_in6->sin6_port;
3160 dest_port = src_in6->sin6_port;
3166 pay = (union swrap_packet_payload *)(void *)buf;
3168 switch (socket_type) {
3170 pay->tcp.source_port = src_port;
3171 pay->tcp.dest_port = dest_port;
3172 pay->tcp.seq_num = htonl(tcp_seqno);
3173 pay->tcp.ack_num = htonl(tcp_ack);
3174 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3175 pay->tcp.control = tcp_ctl;
3176 pay->tcp.window = htons(0x7FFF);
3177 pay->tcp.checksum = htons(0x0000);
3178 pay->tcp.urg = htons(0x0000);
3179 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3184 pay->udp.source_port = src_port;
3185 pay->udp.dest_port = dest_port;
3186 pay->udp.length = htons(8 + payload_len);
3187 pay->udp.checksum = htons(0x0000);
3188 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3193 if (payload && payload_len > 0) {
3194 memcpy(buf, payload, payload_len);
3197 *_packet_len = packet_len - icmp_truncate_len;
3201 static int swrap_pcap_get_fd(const char *fname)
3209 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3211 struct swrap_file_hdr file_hdr;
3212 file_hdr.magic = 0xA1B2C3D4;
3213 file_hdr.version_major = 0x0002;
3214 file_hdr.version_minor = 0x0004;
3215 file_hdr.timezone = 0x00000000;
3216 file_hdr.sigfigs = 0x00000000;
3217 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3218 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3220 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3227 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3232 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3233 const struct sockaddr *addr,
3234 enum swrap_packet_type type,
3235 const void *buf, size_t len,
3238 const struct sockaddr *src_addr;
3239 const struct sockaddr *dest_addr;
3240 unsigned long tcp_seqno = 0;
3241 unsigned long tcp_ack = 0;
3242 unsigned char tcp_ctl = 0;
3243 int unreachable = 0;
3247 switch (si->family) {
3259 case SWRAP_CONNECT_SEND:
3260 if (si->type != SOCK_STREAM) {
3264 src_addr = &si->myname.sa.s;
3267 tcp_seqno = si->io.pck_snd;
3268 tcp_ack = si->io.pck_rcv;
3269 tcp_ctl = 0x02; /* SYN */
3271 si->io.pck_snd += 1;
3275 case SWRAP_CONNECT_RECV:
3276 if (si->type != SOCK_STREAM) {
3280 dest_addr = &si->myname.sa.s;
3283 tcp_seqno = si->io.pck_rcv;
3284 tcp_ack = si->io.pck_snd;
3285 tcp_ctl = 0x12; /** SYN,ACK */
3287 si->io.pck_rcv += 1;
3291 case SWRAP_CONNECT_UNREACH:
3292 if (si->type != SOCK_STREAM) {
3296 dest_addr = &si->myname.sa.s;
3299 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3300 tcp_seqno = si->io.pck_snd - 1;
3301 tcp_ack = si->io.pck_rcv;
3302 tcp_ctl = 0x02; /* SYN */
3307 case SWRAP_CONNECT_ACK:
3308 if (si->type != SOCK_STREAM) {
3312 src_addr = &si->myname.sa.s;
3315 tcp_seqno = si->io.pck_snd;
3316 tcp_ack = si->io.pck_rcv;
3317 tcp_ctl = 0x10; /* ACK */
3321 case SWRAP_ACCEPT_SEND:
3322 if (si->type != SOCK_STREAM) {
3326 dest_addr = &si->myname.sa.s;
3329 tcp_seqno = si->io.pck_rcv;
3330 tcp_ack = si->io.pck_snd;
3331 tcp_ctl = 0x02; /* SYN */
3333 si->io.pck_rcv += 1;
3337 case SWRAP_ACCEPT_RECV:
3338 if (si->type != SOCK_STREAM) {
3342 src_addr = &si->myname.sa.s;
3345 tcp_seqno = si->io.pck_snd;
3346 tcp_ack = si->io.pck_rcv;
3347 tcp_ctl = 0x12; /* SYN,ACK */
3349 si->io.pck_snd += 1;
3353 case SWRAP_ACCEPT_ACK:
3354 if (si->type != SOCK_STREAM) {
3358 dest_addr = &si->myname.sa.s;
3361 tcp_seqno = si->io.pck_rcv;
3362 tcp_ack = si->io.pck_snd;
3363 tcp_ctl = 0x10; /* ACK */
3368 src_addr = &si->myname.sa.s;
3369 dest_addr = &si->peername.sa.s;
3371 tcp_seqno = si->io.pck_snd;
3372 tcp_ack = si->io.pck_rcv;
3373 tcp_ctl = 0x18; /* PSH,ACK */
3375 si->io.pck_snd += len;
3379 case SWRAP_SEND_RST:
3380 dest_addr = &si->myname.sa.s;
3381 src_addr = &si->peername.sa.s;
3383 if (si->type == SOCK_DGRAM) {
3384 return swrap_pcap_marshall_packet(si,
3386 SWRAP_SENDTO_UNREACH,
3392 tcp_seqno = si->io.pck_rcv;
3393 tcp_ack = si->io.pck_snd;
3394 tcp_ctl = 0x14; /** RST,ACK */
3398 case SWRAP_PENDING_RST:
3399 dest_addr = &si->myname.sa.s;
3400 src_addr = &si->peername.sa.s;
3402 if (si->type == SOCK_DGRAM) {
3406 tcp_seqno = si->io.pck_rcv;
3407 tcp_ack = si->io.pck_snd;
3408 tcp_ctl = 0x14; /* RST,ACK */
3413 dest_addr = &si->myname.sa.s;
3414 src_addr = &si->peername.sa.s;
3416 tcp_seqno = si->io.pck_rcv;
3417 tcp_ack = si->io.pck_snd;
3418 tcp_ctl = 0x18; /* PSH,ACK */
3420 si->io.pck_rcv += len;
3424 case SWRAP_RECV_RST:
3425 dest_addr = &si->myname.sa.s;
3426 src_addr = &si->peername.sa.s;
3428 if (si->type == SOCK_DGRAM) {
3432 tcp_seqno = si->io.pck_rcv;
3433 tcp_ack = si->io.pck_snd;
3434 tcp_ctl = 0x14; /* RST,ACK */
3439 src_addr = &si->myname.sa.s;
3442 si->io.pck_snd += len;
3446 case SWRAP_SENDTO_UNREACH:
3447 dest_addr = &si->myname.sa.s;
3454 case SWRAP_RECVFROM:
3455 dest_addr = &si->myname.sa.s;
3458 si->io.pck_rcv += len;
3462 case SWRAP_CLOSE_SEND:
3463 if (si->type != SOCK_STREAM) {
3467 src_addr = &si->myname.sa.s;
3468 dest_addr = &si->peername.sa.s;
3470 tcp_seqno = si->io.pck_snd;
3471 tcp_ack = si->io.pck_rcv;
3472 tcp_ctl = 0x11; /* FIN, ACK */
3474 si->io.pck_snd += 1;
3478 case SWRAP_CLOSE_RECV:
3479 if (si->type != SOCK_STREAM) {
3483 dest_addr = &si->myname.sa.s;
3484 src_addr = &si->peername.sa.s;
3486 tcp_seqno = si->io.pck_rcv;
3487 tcp_ack = si->io.pck_snd;
3488 tcp_ctl = 0x11; /* FIN,ACK */
3490 si->io.pck_rcv += 1;
3494 case SWRAP_CLOSE_ACK:
3495 if (si->type != SOCK_STREAM) {
3499 src_addr = &si->myname.sa.s;
3500 dest_addr = &si->peername.sa.s;
3502 tcp_seqno = si->io.pck_snd;
3503 tcp_ack = si->io.pck_rcv;
3504 tcp_ctl = 0x10; /* ACK */
3511 swrapGetTimeOfDay(&tv);
3513 return swrap_pcap_packet_init(&tv,
3517 (const uint8_t *)buf,
3526 static void swrap_pcap_dump_packet(struct socket_info *si,
3527 const struct sockaddr *addr,
3528 enum swrap_packet_type type,
3529 const void *buf, size_t len)
3531 const char *file_name;
3533 size_t packet_len = 0;
3536 swrap_mutex_lock(&pcap_dump_mutex);
3538 file_name = swrap_pcap_init_file();
3543 packet = swrap_pcap_marshall_packet(si,
3549 if (packet == NULL) {
3553 fd = swrap_pcap_get_fd(file_name);
3555 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3564 swrap_mutex_unlock(&pcap_dump_mutex);
3567 /****************************************************************************
3569 ***************************************************************************/
3571 #ifdef HAVE_SIGNALFD
3572 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3576 rc = libc_signalfd(fd, mask, flags);
3578 swrap_remove_stale(fd);
3584 int signalfd(int fd, const sigset_t *mask, int flags)
3586 return swrap_signalfd(fd, mask, flags);
3590 /****************************************************************************
3592 ***************************************************************************/
3594 static int swrap_socket(int family, int type, int protocol)
3596 struct socket_info *si = NULL;
3597 struct socket_info _si = { 0 };
3600 int real_type = type;
3603 * Remove possible addition flags passed to socket() so
3604 * do not fail checking the type.
3605 * See https://lwn.net/Articles/281965/
3608 real_type &= ~SOCK_CLOEXEC;
3610 #ifdef SOCK_NONBLOCK
3611 real_type &= ~SOCK_NONBLOCK;
3614 if (!socket_wrapper_enabled()) {
3615 return libc_socket(family, type, protocol);
3626 #endif /* AF_NETLINK */
3629 #endif /* AF_PACKET */
3631 fd = libc_socket(family, type, protocol);
3633 /* Check if we have a stale fd and remove it */
3634 swrap_remove_stale(fd);
3635 SWRAP_LOG(SWRAP_LOG_TRACE,
3636 "Unix socket fd=%d",
3641 errno = EAFNOSUPPORT;
3645 switch (real_type) {
3651 errno = EPROTONOSUPPORT;
3659 if (real_type == SOCK_STREAM) {
3664 if (real_type == SOCK_DGRAM) {
3669 errno = EPROTONOSUPPORT;
3674 * We must call libc_socket with type, from the caller, not the version
3675 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3677 fd = libc_socket(AF_UNIX, type, 0);
3683 /* Check if we have a stale fd and remove it */
3684 swrap_remove_stale(fd);
3687 si->family = family;
3689 /* however, the rest of the socket_wrapper code expects just
3690 * the type, not the flags */
3691 si->type = real_type;
3692 si->protocol = protocol;
3695 * Setup myname so getsockname() can succeed to find out the socket
3698 switch(si->family) {
3700 struct sockaddr_in sin = {
3701 .sin_family = AF_INET,
3704 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3705 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3710 struct sockaddr_in6 sin6 = {
3711 .sin6_family = AF_INET6,
3714 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3715 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3724 ret = swrap_create_socket(si, fd);
3726 int saved_errno = errno;
3728 errno = saved_errno;
3732 SWRAP_LOG(SWRAP_LOG_TRACE,
3733 "Created %s socket for protocol %s, fd=%d",
3734 family == AF_INET ? "IPv4" : "IPv6",
3735 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3741 int socket(int family, int type, int protocol)
3743 return swrap_socket(family, type, protocol);
3746 /****************************************************************************
3748 ***************************************************************************/
3750 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3754 rc = libc_socketpair(family, type, protocol, sv);
3756 swrap_remove_stale(sv[0]);
3757 swrap_remove_stale(sv[1]);
3763 int socketpair(int family, int type, int protocol, int sv[2])
3765 return swrap_socketpair(family, type, protocol, sv);
3768 /****************************************************************************
3770 ***************************************************************************/
3772 #ifdef HAVE_TIMERFD_CREATE
3773 static int swrap_timerfd_create(int clockid, int flags)
3777 fd = libc_timerfd_create(clockid, flags);
3779 swrap_remove_stale(fd);
3785 int timerfd_create(int clockid, int flags)
3787 return swrap_timerfd_create(clockid, flags);
3791 /****************************************************************************
3793 ***************************************************************************/
3795 static int swrap_pipe(int pipefd[2])
3799 rc = libc_pipe(pipefd);
3801 swrap_remove_stale(pipefd[0]);
3802 swrap_remove_stale(pipefd[1]);
3808 int pipe(int pipefd[2])
3810 return swrap_pipe(pipefd);
3813 /****************************************************************************
3815 ***************************************************************************/
3817 static int swrap_accept(int s,
3818 struct sockaddr *addr,
3822 struct socket_info *parent_si, *child_si;
3823 struct socket_info new_si = { 0 };
3826 struct swrap_address un_addr = {
3827 .sa_socklen = sizeof(struct sockaddr_un),
3829 struct swrap_address un_my_addr = {
3830 .sa_socklen = sizeof(struct sockaddr_un),
3832 struct swrap_address in_addr = {
3833 .sa_socklen = sizeof(struct sockaddr_storage),
3835 struct swrap_address in_my_addr = {
3836 .sa_socklen = sizeof(struct sockaddr_storage),
3840 parent_si = find_socket_info(s);
3843 return libc_accept4(s, addr, addrlen, flags);
3846 return libc_accept(s, addr, addrlen);
3852 * prevent parent_si from being altered / closed
3855 SWRAP_LOCK_SI(parent_si);
3858 * assume out sockaddr have the same size as the in parent
3861 in_addr.sa_socklen = socket_length(parent_si->family);
3862 if (in_addr.sa_socklen <= 0) {
3863 SWRAP_UNLOCK_SI(parent_si);
3868 SWRAP_UNLOCK_SI(parent_si);
3871 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3874 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3877 int saved_errno = errno;
3878 if (saved_errno == ENOTSOCK) {
3879 /* Remove stale fds */
3880 swrap_remove_stale(s);
3882 errno = saved_errno;
3888 /* Check if we have a stale fd and remove it */
3889 swrap_remove_stale(fd);
3891 if (un_addr.sa.un.sun_path[0] == '\0') {
3893 * FreeBSD seems to have a problem where
3894 * accept4() on the unix socket doesn't
3895 * ECONNABORTED for already disconnected connections.
3897 * Let's try libc_getpeername() to get the peer address
3898 * as a fallback, but it'll likely return ENOTCONN,
3899 * which we have to map to ECONNABORTED.
3901 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3902 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3904 int saved_errno = errno;
3906 if (saved_errno == ENOTCONN) {
3908 * If the connection is already disconnected
3909 * we should return ECONNABORTED.
3911 saved_errno = ECONNABORTED;
3913 errno = saved_errno;
3918 ret = libc_getsockname(fd,
3920 &un_my_addr.sa_socklen);
3922 int saved_errno = errno;
3924 if (saved_errno == ENOTCONN) {
3926 * If the connection is already disconnected
3927 * we should return ECONNABORTED.
3929 saved_errno = ECONNABORTED;
3931 errno = saved_errno;
3935 SWRAP_LOCK_SI(parent_si);
3937 ret = sockaddr_convert_from_un(parent_si,
3942 &in_addr.sa_socklen);
3944 int saved_errno = errno;
3945 SWRAP_UNLOCK_SI(parent_si);
3947 errno = saved_errno;
3953 child_si->family = parent_si->family;
3954 child_si->type = parent_si->type;
3955 child_si->protocol = parent_si->protocol;
3956 child_si->bound = 1;
3957 child_si->is_server = 1;
3958 child_si->connected = 1;
3960 SWRAP_UNLOCK_SI(parent_si);
3962 child_si->peername = (struct swrap_address) {
3963 .sa_socklen = in_addr.sa_socklen,
3965 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3967 if (addr != NULL && addrlen != NULL) {
3968 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3970 memcpy(addr, &in_addr.sa.ss, copy_len);
3972 *addrlen = in_addr.sa_socklen;
3975 ret = sockaddr_convert_from_un(child_si,
3977 un_my_addr.sa_socklen,
3980 &in_my_addr.sa_socklen);
3982 int saved_errno = errno;
3984 errno = saved_errno;
3988 SWRAP_LOG(SWRAP_LOG_TRACE,
3989 "accept() path=%s, fd=%d",
3990 un_my_addr.sa.un.sun_path, s);
3992 child_si->myname = (struct swrap_address) {
3993 .sa_socklen = in_my_addr.sa_socklen,
3995 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3997 idx = swrap_create_socket(&new_si, fd);
3999 int saved_errno = errno;
4001 errno = saved_errno;
4006 struct socket_info *si = swrap_get_socket_info(idx);
4009 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
4010 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
4011 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
4012 SWRAP_UNLOCK_SI(si);
4019 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
4021 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
4025 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4026 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
4028 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
4031 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
4034 static int autobind_start_init;
4035 static int autobind_start;
4037 /* using sendto() or connect() on an unbound socket would give the
4038 recipient no way to reply, as unlike UDP and TCP, a unix domain
4039 socket can't auto-assign ephemeral port numbers, so we need to
4041 Note: this might change the family from ipv6 to ipv4
4043 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
4045 struct swrap_address un_addr = {
4046 .sa_socklen = sizeof(struct sockaddr_un),
4052 char *swrap_dir = NULL;
4054 swrap_mutex_lock(&autobind_start_mutex);
4056 if (autobind_start_init != 1) {
4057 autobind_start_init = 1;
4058 autobind_start = getpid();
4059 autobind_start %= 50000;
4060 autobind_start += 10000;
4063 un_addr.sa.un.sun_family = AF_UNIX;
4067 struct sockaddr_in in;
4071 type = SOCKET_TYPE_CHAR_TCP;
4074 type = SOCKET_TYPE_CHAR_UDP;
4077 errno = ESOCKTNOSUPPORT;
4082 memset(&in, 0, sizeof(in));
4083 in.sin_family = AF_INET;
4084 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
4085 socket_wrapper_default_iface()));
4087 si->myname = (struct swrap_address) {
4088 .sa_socklen = sizeof(in),
4090 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
4095 struct sockaddr_in6 in6;
4097 if (si->family != family) {
4098 errno = ENETUNREACH;
4105 type = SOCKET_TYPE_CHAR_TCP_V6;
4108 type = SOCKET_TYPE_CHAR_UDP_V6;
4111 errno = ESOCKTNOSUPPORT;
4116 memset(&in6, 0, sizeof(in6));
4117 in6.sin6_family = AF_INET6;
4118 in6.sin6_addr = *swrap_ipv6();
4119 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4121 si->myname = (struct swrap_address) {
4122 .sa_socklen = sizeof(in6),
4124 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4129 errno = ESOCKTNOSUPPORT;
4134 if (autobind_start > 60000) {
4135 autobind_start = 10000;
4138 swrap_dir = socket_wrapper_dir();
4139 if (swrap_dir == NULL) {
4145 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4146 port = autobind_start + i;
4147 swrap_un_path(&un_addr.sa.un,
4150 socket_wrapper_default_iface(),
4153 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4155 if (errno == EALREADY || errno == EADDRINUSE) {
4161 si->un_addr = un_addr.sa.un;
4164 autobind_start = port + 1;
4167 if (i == SOCKET_MAX_SOCKETS) {
4168 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4169 "interface "SOCKET_FORMAT,
4172 socket_wrapper_default_iface(),
4179 si->family = family;
4180 set_port(si->family, port, &si->myname);
4185 SAFE_FREE(swrap_dir);
4186 swrap_mutex_unlock(&autobind_start_mutex);
4190 /****************************************************************************
4192 ***************************************************************************/
4194 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4198 struct swrap_address un_addr = {
4199 .sa_socklen = sizeof(struct sockaddr_un),
4201 struct socket_info *si = find_socket_info(s);
4202 struct swrap_sockaddr_buf buf = {};
4206 return libc_connect(s, serv_addr, addrlen);
4211 if (si->bound == 0) {
4212 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4218 if (si->family != serv_addr->sa_family) {
4219 SWRAP_LOG(SWRAP_LOG_ERROR,
4220 "called for fd=%d (family=%d) called with invalid family=%d",
4221 s, si->family, serv_addr->sa_family);
4227 ret = sockaddr_convert_to_un(si, serv_addr,
4228 addrlen, &un_addr.sa.un, 0, &bcast);
4234 errno = ENETUNREACH;
4239 if (si->type == SOCK_DGRAM) {
4240 si->defer_connect = 1;
4243 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4245 ret = libc_connect(s,
4247 un_addr.sa_socklen);
4250 SWRAP_LOG(SWRAP_LOG_TRACE,
4251 "connect(%s) path=%s, fd=%d",
4252 swrap_sockaddr_string(&buf, serv_addr),
4253 un_addr.sa.un.sun_path, s);
4256 /* to give better errors */
4257 if (ret == -1 && errno == ENOENT) {
4258 errno = EHOSTUNREACH;
4262 si->peername = (struct swrap_address) {
4263 .sa_socklen = addrlen,
4266 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4270 * When we connect() on a socket than we have to bind the
4271 * outgoing connection on the interface we use for the
4272 * transport. We already bound it on the right interface
4273 * but here we have to update the name so getsockname()
4274 * returns correct information.
4276 if (si->bindname.sa_socklen > 0) {
4277 si->myname = (struct swrap_address) {
4278 .sa_socklen = si->bindname.sa_socklen,
4281 memcpy(&si->myname.sa.ss,
4282 &si->bindname.sa.ss,
4283 si->bindname.sa_socklen);
4285 /* Cleanup bindname */
4286 si->bindname = (struct swrap_address) {
4291 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4292 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4294 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4298 SWRAP_UNLOCK_SI(si);
4302 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4304 return swrap_connect(s, serv_addr, addrlen);
4307 /****************************************************************************
4309 ***************************************************************************/
4311 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4314 struct swrap_address un_addr = {
4315 .sa_socklen = sizeof(struct sockaddr_un),
4317 struct socket_info *si = find_socket_info(s);
4318 struct swrap_sockaddr_buf buf = {};
4319 int ret_errno = errno;
4326 return libc_bind(s, myaddr, addrlen);
4331 switch (si->family) {
4333 const struct sockaddr_in *sin;
4334 if (addrlen < sizeof(struct sockaddr_in)) {
4335 bind_error = EINVAL;
4339 sin = (const struct sockaddr_in *)(const void *)myaddr;
4341 if (sin->sin_family != AF_INET) {
4342 bind_error = EAFNOSUPPORT;
4345 /* special case for AF_UNSPEC */
4346 if (sin->sin_family == AF_UNSPEC &&
4347 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4356 const struct sockaddr_in6 *sin6;
4357 if (addrlen < sizeof(struct sockaddr_in6)) {
4358 bind_error = EINVAL;
4362 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4364 if (sin6->sin6_family != AF_INET6) {
4365 bind_error = EAFNOSUPPORT;
4372 bind_error = EINVAL;
4376 if (bind_error != 0) {
4377 ret_errno = bind_error;
4383 in_use = check_addr_port_in_use(myaddr, addrlen);
4391 si->myname.sa_socklen = addrlen;
4392 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4394 ret = sockaddr_convert_to_un(si,
4405 unlink(un_addr.sa.un.sun_path);
4407 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4412 SWRAP_LOG(SWRAP_LOG_TRACE,
4413 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4414 swrap_sockaddr_string(&buf, myaddr),
4415 un_addr.sa.un.sun_path, s, ret, ret_errno);
4422 SWRAP_UNLOCK_SI(si);
4427 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4429 return swrap_bind(s, myaddr, addrlen);
4432 /****************************************************************************
4434 ***************************************************************************/
4436 #ifdef HAVE_BINDRESVPORT
4437 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4439 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4441 struct swrap_address myaddr = {
4442 .sa_socklen = sizeof(struct sockaddr_storage),
4445 static uint16_t port;
4450 #define SWRAP_STARTPORT 600
4451 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4452 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4455 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4459 salen = myaddr.sa_socklen;
4462 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4468 memset(&myaddr.sa.ss, 0, salen);
4473 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4476 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4478 salen = sizeof(struct sockaddr_in);
4479 sinp->sin_port = htons(port);
4483 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4485 salen = sizeof(struct sockaddr_in6);
4486 sin6p->sin6_port = htons(port);
4490 errno = EAFNOSUPPORT;
4495 if (port > SWRAP_ENDPORT) {
4496 port = SWRAP_STARTPORT;
4499 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4500 if (rc == 0 || errno != EADDRINUSE) {
4508 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4510 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4514 /****************************************************************************
4516 ***************************************************************************/
4518 static int swrap_listen(int s, int backlog)
4521 struct socket_info *si = find_socket_info(s);
4524 return libc_listen(s, backlog);
4529 if (si->bound == 0) {
4530 ret = swrap_auto_bind(s, si, si->family);
4537 ret = libc_listen(s, backlog);
4543 SWRAP_UNLOCK_SI(si);
4548 int listen(int s, int backlog)
4550 return swrap_listen(s, backlog);
4553 /****************************************************************************
4555 ***************************************************************************/
4557 static FILE *swrap_fopen(const char *name, const char *mode)
4561 fp = libc_fopen(name, mode);
4563 int fd = fileno(fp);
4565 swrap_remove_stale(fd);
4571 FILE *fopen(const char *name, const char *mode)
4573 return swrap_fopen(name, mode);
4576 /****************************************************************************
4578 ***************************************************************************/
4581 static FILE *swrap_fopen64(const char *name, const char *mode)
4585 fp = libc_fopen64(name, mode);
4587 int fd = fileno(fp);
4589 swrap_remove_stale(fd);
4595 FILE *fopen64(const char *name, const char *mode)
4597 return swrap_fopen64(name, mode);
4599 #endif /* HAVE_FOPEN64 */
4601 /****************************************************************************
4603 ***************************************************************************/
4605 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4609 ret = libc_vopen(pathname, flags, ap);
4612 * There are methods for closing descriptors (libc-internal code
4613 * paths, direct syscalls) which close descriptors in ways that
4614 * we can't intercept, so try to recover when we notice that
4617 swrap_remove_stale(ret);
4622 int open(const char *pathname, int flags, ...)
4627 va_start(ap, flags);
4628 fd = swrap_vopen(pathname, flags, ap);
4634 /****************************************************************************
4636 ***************************************************************************/
4639 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4643 ret = libc_vopen64(pathname, flags, ap);
4646 * There are methods for closing descriptors (libc-internal code
4647 * paths, direct syscalls) which close descriptors in ways that
4648 * we can't intercept, so try to recover when we notice that
4651 swrap_remove_stale(ret);
4656 int open64(const char *pathname, int flags, ...)
4661 va_start(ap, flags);
4662 fd = swrap_vopen64(pathname, flags, ap);
4667 #endif /* HAVE_OPEN64 */
4669 /****************************************************************************
4671 ***************************************************************************/
4673 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4677 ret = libc_vopenat(dirfd, path, flags, ap);
4680 * There are methods for closing descriptors (libc-internal code
4681 * paths, direct syscalls) which close descriptors in ways that
4682 * we can't intercept, so try to recover when we notice that
4685 swrap_remove_stale(ret);
4691 int openat(int dirfd, const char *path, int flags, ...)
4696 va_start(ap, flags);
4697 fd = swrap_vopenat(dirfd, path, flags, ap);
4703 /****************************************************************************
4705 ***************************************************************************/
4707 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4709 struct socket_info *si = find_socket_info(s);
4714 return libc_getpeername(s, name, addrlen);
4719 if (si->peername.sa_socklen == 0)
4725 len = MIN(*addrlen, si->peername.sa_socklen);
4731 memcpy(name, &si->peername.sa.ss, len);
4732 *addrlen = si->peername.sa_socklen;
4736 SWRAP_UNLOCK_SI(si);
4741 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4742 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4744 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4747 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4750 /****************************************************************************
4752 ***************************************************************************/
4754 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4756 struct socket_info *si = find_socket_info(s);
4761 return libc_getsockname(s, name, addrlen);
4766 len = MIN(*addrlen, si->myname.sa_socklen);
4772 memcpy(name, &si->myname.sa.ss, len);
4773 *addrlen = si->myname.sa_socklen;
4777 SWRAP_UNLOCK_SI(si);
4782 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4783 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4785 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4788 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4791 /****************************************************************************
4793 ***************************************************************************/
4796 # ifdef SO_PROTOTYPE /* The Solaris name */
4797 # define SO_PROTOCOL SO_PROTOTYPE
4798 # endif /* SO_PROTOTYPE */
4799 #endif /* SO_PROTOCOL */
4801 static int swrap_getsockopt(int s, int level, int optname,
4802 void *optval, socklen_t *optlen)
4804 struct socket_info *si = find_socket_info(s);
4808 return libc_getsockopt(s,
4817 if (level == SOL_SOCKET) {
4821 if (optval == NULL || optlen == NULL ||
4822 *optlen < (socklen_t)sizeof(int)) {
4828 *optlen = sizeof(int);
4829 *(int *)optval = si->family;
4832 #endif /* SO_DOMAIN */
4836 if (optval == NULL || optlen == NULL ||
4837 *optlen < (socklen_t)sizeof(int)) {
4843 *optlen = sizeof(int);
4844 *(int *)optval = si->protocol;
4847 #endif /* SO_PROTOCOL */
4849 if (optval == NULL || optlen == NULL ||
4850 *optlen < (socklen_t)sizeof(int)) {
4856 *optlen = sizeof(int);
4857 *(int *)optval = si->type;
4861 ret = libc_getsockopt(s,
4868 } else if (level == IPPROTO_TCP) {
4873 * This enables sending packets directly out over TCP.
4874 * As a unix socket is doing that any way, report it as
4877 if (optval == NULL || optlen == NULL ||
4878 *optlen < (socklen_t)sizeof(int)) {
4884 *optlen = sizeof(int);
4885 *(int *)optval = si->tcp_nodelay;
4889 #endif /* TCP_NODELAY */
4892 struct tcp_info info;
4893 socklen_t ilen = sizeof(info);
4895 #ifdef HAVE_NETINET_TCP_FSM_H
4896 /* This is FreeBSD */
4897 # define __TCP_LISTEN TCPS_LISTEN
4898 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4899 # define __TCP_CLOSE TCPS_CLOSED
4902 # define __TCP_LISTEN TCP_LISTEN
4903 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4904 # define __TCP_CLOSE TCP_CLOSE
4908 if (si->listening) {
4909 info.tcpi_state = __TCP_LISTEN;
4910 } else if (si->connected) {
4912 * For now we just fake a few values
4913 * supported both by FreeBSD and Linux
4915 info.tcpi_state = __TCP_ESTABLISHED;
4916 info.tcpi_rto = 200000; /* 200 msec */
4917 info.tcpi_rtt = 5000; /* 5 msec */
4918 info.tcpi_rttvar = 5000; /* 5 msec */
4920 info.tcpi_state = __TCP_CLOSE;
4921 info.tcpi_rto = 1000000; /* 1 sec */
4923 info.tcpi_rttvar = 250000; /* 250 msec */
4926 if (optval == NULL || optlen == NULL ||
4927 *optlen < (socklen_t)ilen) {
4934 memcpy(optval, &info, ilen);
4939 #endif /* TCP_INFO */
4945 errno = ENOPROTOOPT;
4949 SWRAP_UNLOCK_SI(si);
4953 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4954 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4956 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4959 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4962 /****************************************************************************
4964 ***************************************************************************/
4966 static int swrap_setsockopt(int s, int level, int optname,
4967 const void *optval, socklen_t optlen)
4969 struct socket_info *si = find_socket_info(s);
4973 return libc_setsockopt(s,
4980 if (level == SOL_SOCKET) {
4981 return libc_setsockopt(s,
4990 if (level == IPPROTO_TCP) {
4997 * This enables sending packets directly out over TCP.
4998 * A unix socket is doing that any way.
5000 if (optval == NULL || optlen == 0 ||
5001 optlen < (socklen_t)sizeof(int)) {
5007 i = *discard_const_p(int, optval);
5008 if (i != 0 && i != 1) {
5013 si->tcp_nodelay = i;
5018 #endif /* TCP_NODELAY */
5024 switch (si->family) {
5026 if (level == IPPROTO_IP) {
5028 if (optname == IP_PKTINFO) {
5029 si->pktinfo = AF_INET;
5031 #endif /* IP_PKTINFO */
5037 if (level == IPPROTO_IPV6) {
5038 #ifdef IPV6_RECVPKTINFO
5039 if (optname == IPV6_RECVPKTINFO) {
5040 si->pktinfo = AF_INET6;
5042 #endif /* IPV6_PKTINFO */
5048 errno = ENOPROTOOPT;
5054 SWRAP_UNLOCK_SI(si);
5058 int setsockopt(int s, int level, int optname,
5059 const void *optval, socklen_t optlen)
5061 return swrap_setsockopt(s, level, optname, optval, optlen);
5064 /****************************************************************************
5066 ***************************************************************************/
5068 static int swrap_vioctl(int s, unsigned long int r, va_list va)
5070 struct socket_info *si = find_socket_info(s);
5072 int *value_ptr = NULL;
5076 return libc_vioctl(s, r, va);
5083 rc = libc_vioctl(s, r, va);
5088 value_ptr = ((int *)va_arg(ap, int *));
5091 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
5092 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5093 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
5094 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
5099 /* this is FreeBSD */
5100 FALL_THROUGH; /* to TIOCOUTQ */
5101 #endif /* FIONWRITE */
5102 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
5104 * This may return more bytes then the application
5105 * sent into the socket, for tcp it should
5106 * return the number of unacked bytes.
5108 * On AF_UNIX, all bytes are immediately acked!
5111 value_ptr = ((int *)va_arg(ap, int *));
5119 SWRAP_UNLOCK_SI(si);
5123 #ifdef HAVE_IOCTL_INT
5124 int ioctl(int s, int r, ...)
5126 int ioctl(int s, unsigned long int r, ...)
5134 rc = swrap_vioctl(s, (unsigned long int) r, va);
5145 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5148 # ifdef _ALIGN /* BSD */
5149 #define CMSG_ALIGN _ALIGN
5151 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5152 # endif /* _ALIGN */
5153 #endif /* CMSG_ALIGN */
5156 * @brief Add a cmsghdr to a msghdr.
5158 * This is an function to add any type of cmsghdr. It will operate on the
5159 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5160 * the buffer position after the added cmsg element. Hence, this function is
5161 * intended to be used with an intermediate msghdr and not on the original
5162 * one handed in by the client.
5164 * @param[in] msg The msghdr to which to add the cmsg.
5166 * @param[in] level The cmsg level to set.
5168 * @param[in] type The cmsg type to set.
5170 * @param[in] data The cmsg data to set.
5172 * @param[in] len the length of the data to set.
5174 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5180 size_t cmlen = CMSG_LEN(len);
5181 size_t cmspace = CMSG_SPACE(len);
5182 uint8_t cmbuf[cmspace];
5183 void *cast_ptr = (void *)cmbuf;
5184 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5187 memset(cmbuf, 0, cmspace);
5189 if (msg->msg_controllen < cmlen) {
5190 cmlen = msg->msg_controllen;
5191 msg->msg_flags |= MSG_CTRUNC;
5194 if (msg->msg_controllen < cmspace) {
5195 cmspace = msg->msg_controllen;
5199 * We copy the full input data into an intermediate cmsghdr first
5200 * in order to more easily cope with truncation.
5202 cm->cmsg_len = cmlen;
5203 cm->cmsg_level = level;
5204 cm->cmsg_type = type;
5205 memcpy(CMSG_DATA(cm), data, len);
5208 * We now copy the possibly truncated buffer.
5209 * We copy cmlen bytes, but consume cmspace bytes,
5210 * leaving the possible padding uninitialiazed.
5212 p = (uint8_t *)msg->msg_control;
5213 memcpy(p, cm, cmlen);
5215 msg->msg_control = p;
5216 msg->msg_controllen -= cmspace;
5221 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5224 /* Add packet info */
5225 switch (si->pktinfo) {
5226 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5228 struct sockaddr_in *sin;
5229 #if defined(HAVE_STRUCT_IN_PKTINFO)
5230 struct in_pktinfo pkt;
5231 #elif defined(IP_RECVDSTADDR)
5235 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5236 sin = &si->bindname.sa.in;
5238 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5241 sin = &si->myname.sa.in;
5246 #if defined(HAVE_STRUCT_IN_PKTINFO)
5247 pkt.ipi_ifindex = socket_wrapper_default_iface();
5248 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5249 #elif defined(IP_RECVDSTADDR)
5250 pkt = sin->sin_addr;
5253 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5258 #endif /* IP_PKTINFO */
5259 #if defined(HAVE_IPV6)
5261 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5262 struct sockaddr_in6 *sin6;
5263 struct in6_pktinfo pkt6;
5265 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5266 sin6 = &si->bindname.sa.in6;
5268 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5271 sin6 = &si->myname.sa.in6;
5276 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5277 pkt6.ipi6_addr = sin6->sin6_addr;
5279 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5280 &pkt6, sizeof(pkt6));
5281 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5285 #endif /* IPV6_PKTINFO */
5293 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5294 struct msghdr *omsg)
5298 if (si->pktinfo > 0) {
5299 rc = swrap_msghdr_add_pktinfo(si, omsg);
5305 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5307 size_t *cm_data_space);
5308 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5310 size_t *cm_data_space);
5311 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5313 size_t *cm_data_space);
5315 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5317 size_t *cm_data_space)
5319 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5320 struct cmsghdr *cmsg;
5324 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5328 for (cmsg = CMSG_FIRSTHDR(msg);
5330 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5331 switch (cmsg->cmsg_level) {
5333 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5338 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5343 rc = swrap_sendmsg_copy_cmsg(cmsg,
5349 int saved_errno = errno;
5350 SAFE_FREE(*cm_data);
5352 errno = saved_errno;
5360 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5362 size_t *cm_data_space)
5367 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5369 p = realloc((*cm_data), cmspace);
5375 p = (*cm_data) + (*cm_data_space);
5376 *cm_data_space = cmspace;
5378 memcpy(p, cmsg, cmsg->cmsg_len);
5383 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5385 size_t *cm_data_space);
5388 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5390 size_t *cm_data_space)
5394 switch(cmsg->cmsg_type) {
5397 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5404 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5416 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5418 size_t *cm_data_space)
5420 (void)cmsg; /* unused */
5421 (void)cm_data; /* unused */
5422 (void)cm_data_space; /* unused */
5425 * Passing a IP pktinfo to a unix socket might be rejected by the
5426 * Kernel, at least on FreeBSD. So skip this cmsg.
5431 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5433 size_t *cm_data_space)
5437 switch (cmsg->cmsg_type) {
5439 SWRAP_LOG(SWRAP_LOG_TRACE,
5440 "Ignoring SCM_RIGHTS on inet socket!");
5443 #ifdef SCM_CREDENTIALS
5444 case SCM_CREDENTIALS:
5445 SWRAP_LOG(SWRAP_LOG_TRACE,
5446 "Ignoring SCM_CREDENTIALS on inet socket!");
5449 #endif /* SCM_CREDENTIALS */
5451 rc = swrap_sendmsg_copy_cmsg(cmsg,
5460 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5463 * We only allow up to 6 fds at a time
5464 * as that's more than enough for Samba
5465 * and it means we can keep the logic simple
5466 * and work with fixed size arrays.
5468 * We also keep sizeof(struct swrap_unix_scm_rights)
5469 * under PIPE_BUF (4096) in order to allow a non-blocking
5470 * write into the pipe.
5473 #define PIPE_BUF 4096
5475 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5476 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5477 struct swrap_unix_scm_rights_payload {
5479 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5480 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5482 struct swrap_unix_scm_rights {
5484 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5485 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5487 uint32_t payload_size;
5488 struct swrap_unix_scm_rights_payload payload;
5491 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5493 int saved_errno = errno;
5496 for (i = 0; i < num; i++) {
5497 struct socket_info *si = array[i];
5503 swrap_dec_refcount(si);
5504 if (si->fd_passed > 0) {
5507 SWRAP_UNLOCK_SI(si);
5511 errno = saved_errno;
5514 static void swrap_undo_si_idx_array(size_t num, int *array)
5516 int saved_errno = errno;
5519 swrap_mutex_lock(&first_free_mutex);
5521 for (i = 0; i < num; i++) {
5522 struct socket_info *si = NULL;
5524 if (array[i] == -1) {
5528 si = swrap_get_socket_info(array[i]);
5534 swrap_dec_refcount(si);
5535 SWRAP_UNLOCK_SI(si);
5537 swrap_set_next_free(si, first_free);
5538 first_free = array[i];
5542 swrap_mutex_unlock(&first_free_mutex);
5543 errno = saved_errno;
5546 static void swrap_close_fd_array(size_t num, const int *array)
5548 int saved_errno = errno;
5551 for (i = 0; i < num; i++) {
5552 if (array[i] == -1) {
5555 libc_close(array[i]);
5558 errno = saved_errno;
5566 union __swrap_cmsghdr {
5568 struct cmsghdr *cmsg;
5571 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5573 size_t *cm_data_space,
5574 int *scm_rights_pipe_fd)
5576 struct swrap_unix_scm_rights info;
5577 struct swrap_unix_scm_rights_payload *payload = NULL;
5578 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5579 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5580 size_t info_idx = 0;
5583 union __swrap_fds __fds_in = { .p = NULL, };
5584 const int *fds_in = NULL;
5586 size_t size_fds_out;
5587 union __swrap_fds __fds_out = { .p = NULL, };
5588 int *fds_out = NULL;
5591 size_t new_cm_data_space;
5592 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5593 struct cmsghdr *new_cmsg = NULL;
5596 int pipefd[2] = { -1, -1 };
5601 * We pass this a buffer to the kernel make sure any padding
5605 info.magic = swrap_unix_scm_right_magic;
5606 memcpy(info.package_name,
5607 SOCKET_WRAPPER_PACKAGE,
5608 sizeof(info.package_name));
5609 memcpy(info.package_version,
5610 SOCKET_WRAPPER_VERSION,
5611 sizeof(info.package_version));
5612 info.full_size = sizeof(info);
5613 info.payload_size = sizeof(info.payload);
5614 payload = &info.payload;
5616 if (*scm_rights_pipe_fd != -1) {
5617 SWRAP_LOG(SWRAP_LOG_ERROR,
5618 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5623 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5624 SWRAP_LOG(SWRAP_LOG_ERROR,
5625 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5626 (size_t)cmsg->cmsg_len,
5631 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5632 if ((size_fds_in % sizeof(int)) != 0) {
5633 SWRAP_LOG(SWRAP_LOG_ERROR,
5634 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5635 (size_t)cmsg->cmsg_len,
5641 num_fds_in = size_fds_in / sizeof(int);
5642 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5643 SWRAP_LOG(SWRAP_LOG_ERROR,
5644 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5646 "SWRAP_MAX_PASSED_FDS(%zu)",
5647 (size_t)cmsg->cmsg_len,
5650 SWRAP_MAX_PASSED_FDS);
5654 if (num_fds_in == 0) {
5655 SWRAP_LOG(SWRAP_LOG_ERROR,
5656 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5658 (size_t)cmsg->cmsg_len,
5664 __fds_in.p = CMSG_DATA(cmsg);
5665 fds_in = __fds_in.fds;
5666 num_fds_out = num_fds_in + 1;
5668 SWRAP_LOG(SWRAP_LOG_TRACE,
5669 "num_fds_in=%zu num_fds_out=%zu",
5670 num_fds_in, num_fds_out);
5672 size_fds_out = sizeof(int) * num_fds_out;
5673 cmsg_len = CMSG_LEN(size_fds_out);
5674 cmsg_space = CMSG_SPACE(size_fds_out);
5676 new_cm_data_space = *cm_data_space + cmsg_space;
5678 p = realloc((*cm_data), new_cm_data_space);
5683 p = (*cm_data) + (*cm_data_space);
5684 memset(p, 0, cmsg_space);
5686 new_cmsg = __new_cmsg.cmsg;
5688 __fds_out.p = CMSG_DATA(new_cmsg);
5689 fds_out = __fds_out.fds;
5690 memcpy(fds_out, fds_in, size_fds_in);
5691 new_cmsg->cmsg_len = cmsg->cmsg_len;
5693 for (i = 0; i < num_fds_in; i++) {
5696 payload->idxs[i] = -1;
5697 payload->num_idxs++;
5699 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5700 if (si_idx_array[i] == -1) {
5704 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5705 if (si_array[i] == NULL) {
5706 SWRAP_LOG(SWRAP_LOG_ERROR,
5707 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5708 i, fds_in[i], i, si_idx_array[i]);
5713 for (j = 0; j < i; j++) {
5714 if (si_array[j] == si_array[i]) {
5715 payload->idxs[i] = payload->idxs[j];
5719 if (payload->idxs[i] == -1) {
5720 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5721 SWRAP_LOG(SWRAP_LOG_ERROR,
5722 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5723 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5724 i, fds_in[i], i, si_idx_array[i],
5726 SWRAP_MAX_PASSED_SOCKET_INFO);
5730 payload->idxs[i] = info_idx;
5736 for (i = 0; i < num_fds_in; i++) {
5737 struct socket_info *si = si_array[i];
5740 SWRAP_LOG(SWRAP_LOG_TRACE,
5741 "fds_in[%zu]=%d not an inet socket",
5746 SWRAP_LOG(SWRAP_LOG_TRACE,
5747 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5748 "passing as info.idxs[%zu]=%d!",
5751 i, payload->idxs[i]);
5755 payload->infos[payload->idxs[i]] = *si;
5756 payload->infos[payload->idxs[i]].fd_passed = 0;
5757 SWRAP_UNLOCK_SI(si);
5762 int saved_errno = errno;
5763 SWRAP_LOG(SWRAP_LOG_ERROR,
5764 "pipe() failed - %d %s",
5766 strerror(saved_errno));
5767 swrap_dec_fd_passed_array(num_fds_in, si_array);
5768 errno = saved_errno;
5772 sret = libc_write(pipefd[1], &info, sizeof(info));
5773 if (sret != sizeof(info)) {
5774 int saved_errno = errno;
5776 saved_errno = EINVAL;
5778 SWRAP_LOG(SWRAP_LOG_ERROR,
5779 "write() failed - sret=%zd - %d %s",
5781 strerror(saved_errno));
5782 swrap_dec_fd_passed_array(num_fds_in, si_array);
5783 libc_close(pipefd[1]);
5784 libc_close(pipefd[0]);
5785 errno = saved_errno;
5788 libc_close(pipefd[1]);
5791 * Add the pipe read end to the end of the passed fd array
5793 fds_out[num_fds_in] = pipefd[0];
5794 new_cmsg->cmsg_len = cmsg_len;
5796 /* we're done ... */
5797 *scm_rights_pipe_fd = pipefd[0];
5798 *cm_data_space = new_cm_data_space;
5803 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5805 size_t *cm_data_space,
5806 int *scm_rights_pipe_fd)
5810 switch (cmsg->cmsg_type) {
5812 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5815 scm_rights_pipe_fd);
5818 rc = swrap_sendmsg_copy_cmsg(cmsg,
5827 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5829 size_t *cm_data_space)
5831 int scm_rights_pipe_fd = -1;
5832 struct swrap_unix_scm_rights info;
5833 struct swrap_unix_scm_rights_payload *payload = NULL;
5834 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5837 union __swrap_fds __fds_in = { .p = NULL, };
5838 const int *fds_in = NULL;
5840 size_t size_fds_out;
5841 union __swrap_fds __fds_out = { .p = NULL, };
5842 int *fds_out = NULL;
5845 size_t new_cm_data_space;
5846 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5847 struct cmsghdr *new_cmsg = NULL;
5853 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5854 SWRAP_LOG(SWRAP_LOG_ERROR,
5855 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5856 (size_t)cmsg->cmsg_len,
5861 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5862 if ((size_fds_in % sizeof(int)) != 0) {
5863 SWRAP_LOG(SWRAP_LOG_ERROR,
5864 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5865 (size_t)cmsg->cmsg_len,
5871 num_fds_in = size_fds_in / sizeof(int);
5872 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5873 SWRAP_LOG(SWRAP_LOG_ERROR,
5874 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5875 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5876 (size_t)cmsg->cmsg_len,
5879 SWRAP_MAX_PASSED_FDS+1);
5883 if (num_fds_in <= 1) {
5884 SWRAP_LOG(SWRAP_LOG_ERROR,
5885 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5887 (size_t)cmsg->cmsg_len,
5893 __fds_in.p = CMSG_DATA(cmsg);
5894 fds_in = __fds_in.fds;
5895 num_fds_out = num_fds_in - 1;
5897 SWRAP_LOG(SWRAP_LOG_TRACE,
5898 "num_fds_in=%zu num_fds_out=%zu",
5899 num_fds_in, num_fds_out);
5901 for (i = 0; i < num_fds_in; i++) {
5902 /* Check if we have a stale fd and remove it */
5903 swrap_remove_stale(fds_in[i]);
5906 scm_rights_pipe_fd = fds_in[num_fds_out];
5907 size_fds_out = sizeof(int) * num_fds_out;
5908 cmsg_len = CMSG_LEN(size_fds_out);
5909 cmsg_space = CMSG_SPACE(size_fds_out);
5911 new_cm_data_space = *cm_data_space + cmsg_space;
5913 p = realloc((*cm_data), new_cm_data_space);
5915 swrap_close_fd_array(num_fds_in, fds_in);
5919 p = (*cm_data) + (*cm_data_space);
5920 memset(p, 0, cmsg_space);
5922 new_cmsg = __new_cmsg.cmsg;
5924 __fds_out.p = CMSG_DATA(new_cmsg);
5925 fds_out = __fds_out.fds;
5926 memcpy(fds_out, fds_in, size_fds_out);
5927 new_cmsg->cmsg_len = cmsg_len;
5929 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5930 if (sret != sizeof(info)) {
5931 int saved_errno = errno;
5933 saved_errno = EINVAL;
5935 SWRAP_LOG(SWRAP_LOG_ERROR,
5936 "read() failed - sret=%zd - %d %s",
5938 strerror(saved_errno));
5939 swrap_close_fd_array(num_fds_in, fds_in);
5940 errno = saved_errno;
5943 libc_close(scm_rights_pipe_fd);
5944 payload = &info.payload;
5946 if (info.magic != swrap_unix_scm_right_magic) {
5947 SWRAP_LOG(SWRAP_LOG_ERROR,
5948 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5949 (unsigned long long)info.magic,
5950 (unsigned long long)swrap_unix_scm_right_magic);
5951 swrap_close_fd_array(num_fds_out, fds_out);
5956 cmp = memcmp(info.package_name,
5957 SOCKET_WRAPPER_PACKAGE,
5958 sizeof(info.package_name));
5960 SWRAP_LOG(SWRAP_LOG_ERROR,
5961 "info.package_name='%.*s' != '%s'",
5962 (int)sizeof(info.package_name),
5964 SOCKET_WRAPPER_PACKAGE);
5965 swrap_close_fd_array(num_fds_out, fds_out);
5970 cmp = memcmp(info.package_version,
5971 SOCKET_WRAPPER_VERSION,
5972 sizeof(info.package_version));
5974 SWRAP_LOG(SWRAP_LOG_ERROR,
5975 "info.package_version='%.*s' != '%s'",
5976 (int)sizeof(info.package_version),
5977 info.package_version,
5978 SOCKET_WRAPPER_VERSION);
5979 swrap_close_fd_array(num_fds_out, fds_out);
5984 if (info.full_size != sizeof(info)) {
5985 SWRAP_LOG(SWRAP_LOG_ERROR,
5986 "info.full_size=%zu != sizeof(info)=%zu",
5987 (size_t)info.full_size,
5989 swrap_close_fd_array(num_fds_out, fds_out);
5994 if (info.payload_size != sizeof(info.payload)) {
5995 SWRAP_LOG(SWRAP_LOG_ERROR,
5996 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5997 (size_t)info.payload_size,
5998 sizeof(info.payload));
5999 swrap_close_fd_array(num_fds_out, fds_out);
6004 if (payload->num_idxs != num_fds_out) {
6005 SWRAP_LOG(SWRAP_LOG_ERROR,
6006 "info.num_idxs=%u != num_fds_out=%zu",
6007 payload->num_idxs, num_fds_out);
6008 swrap_close_fd_array(num_fds_out, fds_out);
6013 for (i = 0; i < num_fds_out; i++) {
6016 si_idx_array[i] = -1;
6018 if (payload->idxs[i] == -1) {
6019 SWRAP_LOG(SWRAP_LOG_TRACE,
6020 "fds_out[%zu]=%d not an inet socket",
6025 if (payload->idxs[i] < 0) {
6026 SWRAP_LOG(SWRAP_LOG_ERROR,
6027 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
6028 i, fds_out[i], i, payload->idxs[i]);
6029 swrap_close_fd_array(num_fds_out, fds_out);
6034 if (payload->idxs[i] >= payload->num_idxs) {
6035 SWRAP_LOG(SWRAP_LOG_ERROR,
6036 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
6037 i, fds_out[i], i, payload->idxs[i],
6039 swrap_close_fd_array(num_fds_out, fds_out);
6044 if ((size_t)fds_out[i] >= socket_fds_max) {
6045 SWRAP_LOG(SWRAP_LOG_ERROR,
6046 "The max socket index limit of %zu has been reached, "
6050 swrap_close_fd_array(num_fds_out, fds_out);
6055 SWRAP_LOG(SWRAP_LOG_TRACE,
6057 "received as info.idxs[%zu]=%d!",
6059 i, payload->idxs[i]);
6061 for (j = 0; j < i; j++) {
6062 if (payload->idxs[j] == -1) {
6065 if (payload->idxs[j] == payload->idxs[i]) {
6066 si_idx_array[i] = si_idx_array[j];
6069 if (si_idx_array[i] == -1) {
6070 const struct socket_info *si = &payload->infos[payload->idxs[i]];
6072 si_idx_array[i] = swrap_add_socket_info(si);
6073 if (si_idx_array[i] == -1) {
6074 int saved_errno = errno;
6075 SWRAP_LOG(SWRAP_LOG_ERROR,
6076 "The max socket index limit of %zu has been reached, "
6080 swrap_undo_si_idx_array(i, si_idx_array);
6081 swrap_close_fd_array(num_fds_out, fds_out);
6082 errno = saved_errno;
6085 SWRAP_LOG(SWRAP_LOG_TRACE,
6086 "Imported %s socket for protocol %s, fd=%d",
6087 si->family == AF_INET ? "IPv4" : "IPv6",
6088 si->type == SOCK_DGRAM ? "UDP" : "TCP",
6093 for (i = 0; i < num_fds_out; i++) {
6094 if (si_idx_array[i] == -1) {
6097 set_socket_info_index(fds_out[i], si_idx_array[i]);
6100 /* we're done ... */
6101 *cm_data_space = new_cm_data_space;
6106 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6108 size_t *cm_data_space)
6112 switch (cmsg->cmsg_type) {
6114 rc = swrap_recvmsg_unix_scm_rights(cmsg,
6119 rc = swrap_sendmsg_copy_cmsg(cmsg,
6128 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6130 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6131 struct msghdr *msg_tmp,
6132 int *scm_rights_pipe_fd)
6134 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6135 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6136 struct cmsghdr *cmsg = NULL;
6137 uint8_t *cm_data = NULL;
6138 size_t cm_data_space = 0;
6142 *scm_rights_pipe_fd = -1;
6145 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6149 for (cmsg = CMSG_FIRSTHDR(msg_in);
6151 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6152 switch (cmsg->cmsg_level) {
6154 rc = swrap_sendmsg_unix_sol_socket(cmsg,
6157 scm_rights_pipe_fd);
6161 rc = swrap_sendmsg_copy_cmsg(cmsg,
6167 int saved_errno = errno;
6169 errno = saved_errno;
6174 msg_tmp->msg_controllen = cm_data_space;
6175 msg_tmp->msg_control = cm_data;
6178 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6179 *msg_tmp = *_msg_in;
6181 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6184 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6186 int scm_rights_pipe_fd)
6188 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6189 int saved_errno = errno;
6190 SAFE_FREE(msg_tmp->msg_control);
6191 if (scm_rights_pipe_fd != -1) {
6192 libc_close(scm_rights_pipe_fd);
6194 errno = saved_errno;
6195 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6199 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6200 struct msghdr *msg_tmp,
6201 uint8_t **tmp_control)
6203 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6204 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6205 uint8_t *cm_data = NULL;
6206 size_t cm_data_space = 0;
6209 *tmp_control = NULL;
6211 SWRAP_LOG(SWRAP_LOG_TRACE,
6212 "msg_in->msg_controllen=%zu",
6213 (size_t)msg_in->msg_controllen);
6216 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6221 * We need to give the kernel a bit more space in order
6222 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6223 * swrap_recvmsg_after_unix() will hide it again.
6225 cm_data_space = msg_in->msg_controllen;
6226 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6227 cm_data_space += cm_extra_space;
6229 cm_data = calloc(1, cm_data_space);
6230 if (cm_data == NULL) {
6234 msg_tmp->msg_controllen = cm_data_space;
6235 msg_tmp->msg_control = cm_data;
6236 *tmp_control = cm_data;
6238 SWRAP_LOG(SWRAP_LOG_TRACE,
6239 "msg_tmp->msg_controllen=%zu",
6240 (size_t)msg_tmp->msg_controllen);
6242 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6244 *tmp_control = NULL;
6246 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6249 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6250 uint8_t **tmp_control,
6251 struct msghdr *msg_out,
6254 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6255 struct cmsghdr *cmsg = NULL;
6256 uint8_t *cm_data = NULL;
6257 size_t cm_data_space = 0;
6261 int saved_errno = errno;
6262 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6263 saved_errno, strerror(saved_errno));
6264 SAFE_FREE(*tmp_control);
6265 /* msg_out should not be touched on error */
6266 errno = saved_errno;
6270 SWRAP_LOG(SWRAP_LOG_TRACE,
6271 "msg_tmp->msg_controllen=%zu",
6272 (size_t)msg_tmp->msg_controllen);
6275 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6276 int saved_errno = errno;
6277 *msg_out = *msg_tmp;
6278 SAFE_FREE(*tmp_control);
6279 errno = saved_errno;
6283 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6285 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6286 switch (cmsg->cmsg_level) {
6288 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6294 rc = swrap_sendmsg_copy_cmsg(cmsg,
6300 int saved_errno = errno;
6302 SAFE_FREE(*tmp_control);
6303 errno = saved_errno;
6309 * msg_tmp->msg_control (*tmp_control) was created by
6310 * swrap_recvmsg_before_unix() and msg_out->msg_control
6311 * is still the buffer of the caller.
6313 msg_tmp->msg_control = msg_out->msg_control;
6314 msg_tmp->msg_controllen = msg_out->msg_controllen;
6315 *msg_out = *msg_tmp;
6317 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6318 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6319 msg_out->msg_controllen = cm_data_space;
6321 SAFE_FREE(*tmp_control);
6323 SWRAP_LOG(SWRAP_LOG_TRACE,
6324 "msg_out->msg_controllen=%zu",
6325 (size_t)msg_out->msg_controllen);
6327 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6328 int saved_errno = errno;
6329 *msg_out = *msg_tmp;
6330 SAFE_FREE(*tmp_control);
6331 errno = saved_errno;
6333 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6336 static ssize_t swrap_sendmsg_before(int fd,
6337 struct socket_info *si,
6339 struct iovec *tmp_iov,
6340 struct sockaddr_un *tmp_un,
6341 const struct sockaddr_un **to_un,
6342 const struct sockaddr **to,
6347 struct swrap_sockaddr_buf buf = {};
6365 if (!si->connected) {
6370 if (msg->msg_iovlen == 0) {
6374 mtu = socket_wrapper_mtu();
6375 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6377 nlen = len + msg->msg_iov[i].iov_len;
6387 msg->msg_iovlen = i;
6388 if (msg->msg_iovlen == 0) {
6389 *tmp_iov = msg->msg_iov[0];
6390 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6392 msg->msg_iov = tmp_iov;
6393 msg->msg_iovlen = 1;
6398 if (si->connected) {
6399 if (msg->msg_name != NULL) {
6401 * We are dealing with unix sockets and if we
6402 * are connected, we should only talk to the
6403 * connected unix path. Using the fd to send
6404 * to another server would be hard to achieve.
6406 msg->msg_name = NULL;
6407 msg->msg_namelen = 0;
6409 SWRAP_LOG(SWRAP_LOG_TRACE,
6410 "connected(%s) fd=%d",
6411 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6414 const struct sockaddr *msg_name;
6415 msg_name = (const struct sockaddr *)msg->msg_name;
6417 if (msg_name == NULL) {
6423 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6435 msg->msg_name = tmp_un;
6436 msg->msg_namelen = sizeof(*tmp_un);
6439 if (si->bound == 0) {
6440 ret = swrap_auto_bind(fd, si, si->family);
6442 SWRAP_UNLOCK_SI(si);
6443 if (errno == ENOTSOCK) {
6444 swrap_remove_stale(fd);
6447 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6453 if (!si->defer_connect) {
6457 ret = sockaddr_convert_to_un(si,
6459 si->peername.sa_socklen,
6467 SWRAP_LOG(SWRAP_LOG_TRACE,
6468 "deferred connect(%s) path=%s, fd=%d",
6469 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6470 tmp_un->sun_path, fd);
6472 ret = libc_connect(fd,
6473 (struct sockaddr *)(void *)tmp_un,
6476 /* to give better errors */
6477 if (ret == -1 && errno == ENOENT) {
6478 errno = EHOSTUNREACH;
6485 si->defer_connect = 0;
6488 errno = EHOSTUNREACH;
6494 SWRAP_UNLOCK_SI(si);
6499 static void swrap_sendmsg_after(int fd,
6500 struct socket_info *si,
6502 const struct sockaddr *to,
6505 int saved_errno = errno;
6512 /* to give better errors */
6514 if (saved_errno == ENOENT) {
6515 saved_errno = EHOSTUNREACH;
6516 } else if (saved_errno == ENOTSOCK) {
6517 /* If the fd is not a socket, remove it */
6518 swrap_remove_stale(fd);
6522 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6523 avail += msg->msg_iov[i].iov_len;
6527 remain = MIN(80, avail);
6532 /* we capture it as one single packet */
6533 buf = (uint8_t *)malloc(remain);
6535 /* we just not capture the packet */
6536 errno = saved_errno;
6540 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6541 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6542 if (this_time > 0) {
6544 msg->msg_iov[i].iov_base,
6548 remain -= this_time;
6557 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6558 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6560 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6565 if (si->connected) {
6566 to = &si->peername.sa.s;
6569 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6570 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6572 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6577 SWRAP_UNLOCK_SI(si);
6580 errno = saved_errno;
6583 static int swrap_recvmsg_before(int fd,
6584 struct socket_info *si,
6586 struct iovec *tmp_iov)
6593 (void)fd; /* unused */
6598 if (!si->connected) {
6603 if (msg->msg_iovlen == 0) {
6607 mtu = socket_wrapper_mtu();
6608 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6610 nlen = len + msg->msg_iov[i].iov_len;
6615 msg->msg_iovlen = i;
6616 if (msg->msg_iovlen == 0) {
6617 *tmp_iov = msg->msg_iov[0];
6618 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6620 msg->msg_iov = tmp_iov;
6621 msg->msg_iovlen = 1;
6626 if (msg->msg_name == NULL) {
6631 if (msg->msg_iovlen == 0) {
6635 if (si->bound == 0) {
6636 ret = swrap_auto_bind(fd, si, si->family);
6638 SWRAP_UNLOCK_SI(si);
6640 * When attempting to read or write to a
6641 * descriptor, if an underlying autobind fails
6642 * because it's not a socket, stop intercepting
6643 * uses of that descriptor.
6645 if (errno == ENOTSOCK) {
6646 swrap_remove_stale(fd);
6649 SWRAP_LOG(SWRAP_LOG_ERROR,
6650 "swrap_recvmsg_before failed");
6657 errno = EHOSTUNREACH;
6663 SWRAP_UNLOCK_SI(si);
6668 static int swrap_recvmsg_after(int fd,
6669 struct socket_info *si,
6671 const struct sockaddr_un *un_addr,
6672 socklen_t un_addrlen,
6675 int saved_errno = errno;
6677 uint8_t *buf = NULL;
6683 /* to give better errors */
6685 if (saved_errno == ENOENT) {
6686 saved_errno = EHOSTUNREACH;
6687 } else if (saved_errno == ENOTSOCK) {
6688 /* If the fd is not a socket, remove it */
6689 swrap_remove_stale(fd);
6693 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6694 avail += msg->msg_iov[i].iov_len;
6699 /* Convert the socket address before we leave */
6700 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6701 rc = sockaddr_convert_from_un(si,
6718 remain = MIN(80, avail);
6723 /* we capture it as one single packet */
6724 buf = (uint8_t *)malloc(remain);
6726 /* we just not capture the packet */
6727 SWRAP_UNLOCK_SI(si);
6728 errno = saved_errno;
6732 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6733 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6735 msg->msg_iov[i].iov_base,
6738 remain -= this_time;
6743 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6744 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6745 } else if (ret == 0) { /* END OF FILE */
6746 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6747 } else if (ret > 0) {
6748 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6757 if (un_addr != NULL) {
6758 swrap_pcap_dump_packet(si,
6764 swrap_pcap_dump_packet(si,
6777 errno = saved_errno;
6779 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6781 msg->msg_controllen > 0 &&
6782 msg->msg_control != NULL) {
6783 rc = swrap_msghdr_add_socket_info(si, msg);
6785 SWRAP_UNLOCK_SI(si);
6791 SWRAP_UNLOCK_SI(si);
6795 /****************************************************************************
6797 ***************************************************************************/
6799 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6800 struct sockaddr *from, socklen_t *fromlen)
6802 struct swrap_address from_addr = {
6803 .sa_socklen = sizeof(struct sockaddr_un),
6806 struct socket_info *si = find_socket_info(s);
6807 struct swrap_address saddr = {
6808 .sa_socklen = sizeof(struct sockaddr_storage),
6815 return libc_recvfrom(s,
6827 if (from != NULL && fromlen != NULL) {
6828 msg.msg_name = from; /* optional address */
6829 msg.msg_namelen = *fromlen; /* size of address */
6831 msg.msg_name = &saddr.sa.s; /* optional address */
6832 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6834 msg.msg_iov = &tmp; /* scatter/gather array */
6835 msg.msg_iovlen = 1; /* # elements in msg_iov */
6836 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6837 msg.msg_control = NULL; /* ancillary data, see below */
6838 msg.msg_controllen = 0; /* ancillary data buffer len */
6839 msg.msg_flags = 0; /* flags on received message */
6842 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6847 buf = msg.msg_iov[0].iov_base;
6848 len = msg.msg_iov[0].iov_len;
6850 ret = libc_recvfrom(s,
6855 &from_addr.sa_socklen);
6860 tret = swrap_recvmsg_after(s,
6864 from_addr.sa_socklen,
6870 if (from != NULL && fromlen != NULL) {
6871 *fromlen = msg.msg_namelen;
6877 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6878 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6879 struct sockaddr *from, Psocklen_t fromlen)
6881 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6882 struct sockaddr *from, socklen_t *fromlen)
6885 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6888 /****************************************************************************
6890 ***************************************************************************/
6892 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6893 const struct sockaddr *to, socklen_t tolen)
6897 struct swrap_address un_addr = {
6898 .sa_socklen = sizeof(struct sockaddr_un),
6900 const struct sockaddr_un *to_un = NULL;
6903 struct socket_info *si = find_socket_info(s);
6907 return libc_sendto(s, buf, len, flags, to, tolen);
6910 tmp.iov_base = discard_const_p(char, buf);
6914 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6915 msg.msg_namelen = tolen; /* size of address */
6916 msg.msg_iov = &tmp; /* scatter/gather array */
6917 msg.msg_iovlen = 1; /* # elements in msg_iov */
6918 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6919 msg.msg_control = NULL; /* ancillary data, see below */
6920 msg.msg_controllen = 0; /* ancillary data buffer len */
6921 msg.msg_flags = 0; /* flags on received message */
6924 rc = swrap_sendmsg_before(s,
6936 buf = msg.msg_iov[0].iov_base;
6937 len = msg.msg_iov[0].iov_len;
6942 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6944 char *swrap_dir = NULL;
6946 type = SOCKET_TYPE_CHAR_UDP;
6948 swrap_dir = socket_wrapper_dir();
6949 if (swrap_dir == NULL) {
6953 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6954 swrap_un_path(&un_addr.sa.un,
6959 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6961 /* ignore the any errors in broadcast sends */
6967 un_addr.sa_socklen);
6970 SAFE_FREE(swrap_dir);
6974 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6976 SWRAP_UNLOCK_SI(si);
6983 * If it is a dgram socket and we are connected, don't include the
6986 if (si->type == SOCK_DGRAM && si->connected) {
6987 ret = libc_sendto(s,
6994 ret = libc_sendto(s,
6998 (struct sockaddr *)msg.msg_name,
7002 SWRAP_UNLOCK_SI(si);
7004 swrap_sendmsg_after(s, si, &msg, to, ret);
7009 ssize_t sendto(int s, const void *buf, size_t len, int flags,
7010 const struct sockaddr *to, socklen_t tolen)
7012 return swrap_sendto(s, buf, len, flags, to, tolen);
7015 /****************************************************************************
7017 ***************************************************************************/
7019 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
7021 struct socket_info *si;
7023 struct swrap_address saddr = {
7024 .sa_socklen = sizeof(struct sockaddr_storage),
7030 si = find_socket_info(s);
7032 return libc_recv(s, buf, len, flags);
7039 msg.msg_name = &saddr.sa.s; /* optional address */
7040 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7041 msg.msg_iov = &tmp; /* scatter/gather array */
7042 msg.msg_iovlen = 1; /* # elements in msg_iov */
7043 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7044 msg.msg_control = NULL; /* ancillary data, see below */
7045 msg.msg_controllen = 0; /* ancillary data buffer len */
7046 msg.msg_flags = 0; /* flags on received message */
7049 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7054 buf = msg.msg_iov[0].iov_base;
7055 len = msg.msg_iov[0].iov_len;
7057 ret = libc_recv(s, buf, len, flags);
7059 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7067 ssize_t recv(int s, void *buf, size_t len, int flags)
7069 return swrap_recv(s, buf, len, flags);
7072 /****************************************************************************
7074 ***************************************************************************/
7076 static ssize_t swrap_read(int s, void *buf, size_t len)
7078 struct socket_info *si;
7081 struct swrap_address saddr = {
7082 .sa_socklen = sizeof(struct sockaddr_storage),
7087 si = find_socket_info(s);
7089 return libc_read(s, buf, len);
7096 msg.msg_name = &saddr.sa.ss; /* optional address */
7097 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7098 msg.msg_iov = &tmp; /* scatter/gather array */
7099 msg.msg_iovlen = 1; /* # elements in msg_iov */
7100 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7101 msg.msg_control = NULL; /* ancillary data, see below */
7102 msg.msg_controllen = 0; /* ancillary data buffer len */
7103 msg.msg_flags = 0; /* flags on received message */
7106 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7108 if (tret == -ENOTSOCK) {
7109 return libc_read(s, buf, len);
7114 buf = msg.msg_iov[0].iov_base;
7115 len = msg.msg_iov[0].iov_len;
7117 ret = libc_read(s, buf, len);
7119 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7127 ssize_t read(int s, void *buf, size_t len)
7129 return swrap_read(s, buf, len);
7132 /****************************************************************************
7134 ***************************************************************************/
7136 static ssize_t swrap_write(int s, const void *buf, size_t len)
7140 struct sockaddr_un un_addr;
7143 struct socket_info *si;
7145 si = find_socket_info(s);
7147 return libc_write(s, buf, len);
7150 tmp.iov_base = discard_const_p(char, buf);
7154 msg.msg_name = NULL; /* optional address */
7155 msg.msg_namelen = 0; /* size of address */
7156 msg.msg_iov = &tmp; /* scatter/gather array */
7157 msg.msg_iovlen = 1; /* # elements in msg_iov */
7158 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7159 msg.msg_control = NULL; /* ancillary data, see below */
7160 msg.msg_controllen = 0; /* ancillary data buffer len */
7161 msg.msg_flags = 0; /* flags on received message */
7164 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7169 buf = msg.msg_iov[0].iov_base;
7170 len = msg.msg_iov[0].iov_len;
7172 ret = libc_write(s, buf, len);
7174 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7179 ssize_t write(int s, const void *buf, size_t len)
7181 return swrap_write(s, buf, len);
7184 /****************************************************************************
7186 ***************************************************************************/
7188 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7192 struct sockaddr_un un_addr;
7195 struct socket_info *si = find_socket_info(s);
7198 return libc_send(s, buf, len, flags);
7201 tmp.iov_base = discard_const_p(char, buf);
7205 msg.msg_name = NULL; /* optional address */
7206 msg.msg_namelen = 0; /* size of address */
7207 msg.msg_iov = &tmp; /* scatter/gather array */
7208 msg.msg_iovlen = 1; /* # elements in msg_iov */
7209 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7210 msg.msg_control = NULL; /* ancillary data, see below */
7211 msg.msg_controllen = 0; /* ancillary data buffer len */
7212 msg.msg_flags = 0; /* flags on received message */
7215 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7220 buf = msg.msg_iov[0].iov_base;
7221 len = msg.msg_iov[0].iov_len;
7223 ret = libc_send(s, buf, len, flags);
7225 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7230 ssize_t send(int s, const void *buf, size_t len, int flags)
7232 return swrap_send(s, buf, len, flags);
7235 /****************************************************************************
7237 ***************************************************************************/
7239 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7241 struct swrap_address from_addr = {
7242 .sa_socklen = sizeof(struct sockaddr_un),
7244 struct swrap_address convert_addr = {
7245 .sa_socklen = sizeof(struct sockaddr_storage),
7247 struct socket_info *si;
7250 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7251 size_t msg_ctrllen_filled;
7252 size_t msg_ctrllen_left;
7258 si = find_socket_info(s);
7260 uint8_t *tmp_control = NULL;
7261 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7265 ret = libc_recvmsg(s, &msg, flags);
7266 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7269 tmp.iov_base = NULL;
7273 msg.msg_name = &from_addr.sa; /* optional address */
7274 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7275 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7276 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7277 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7278 msg_ctrllen_filled = 0;
7279 msg_ctrllen_left = omsg->msg_controllen;
7281 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7282 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7283 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7286 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7291 ret = libc_recvmsg(s, &msg, flags);
7293 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7294 msg_ctrllen_filled += msg.msg_controllen;
7295 msg_ctrllen_left -= msg.msg_controllen;
7297 if (omsg->msg_control != NULL) {
7300 p = omsg->msg_control;
7301 p += msg_ctrllen_filled;
7303 msg.msg_control = p;
7304 msg.msg_controllen = msg_ctrllen_left;
7306 msg.msg_control = NULL;
7307 msg.msg_controllen = 0;
7312 * We convert the unix address to a IP address so we need a buffer
7313 * which can store the address in case of SOCK_DGRAM, see below.
7315 msg.msg_name = &convert_addr.sa;
7316 msg.msg_namelen = convert_addr.sa_socklen;
7318 rc = swrap_recvmsg_after(s,
7322 from_addr.sa_socklen,
7328 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7329 if (omsg->msg_control != NULL) {
7330 /* msg.msg_controllen = space left */
7331 msg_ctrllen_left = msg.msg_controllen;
7332 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7335 /* Update the original message length */
7336 omsg->msg_controllen = msg_ctrllen_filled;
7337 omsg->msg_flags = msg.msg_flags;
7339 omsg->msg_iovlen = msg.msg_iovlen;
7346 * The msg_name field points to a caller-allocated buffer that is
7347 * used to return the source address if the socket is unconnected. The
7348 * caller should set msg_namelen to the size of this buffer before this
7349 * call; upon return from a successful call, msg_name will contain the
7350 * length of the returned address. If the application does not need
7351 * to know the source address, msg_name can be specified as NULL.
7353 if (si->type == SOCK_STREAM) {
7354 omsg->msg_namelen = 0;
7355 } else if (omsg->msg_name != NULL &&
7356 omsg->msg_namelen != 0 &&
7357 omsg->msg_namelen >= msg.msg_namelen) {
7358 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7359 omsg->msg_namelen = msg.msg_namelen;
7362 SWRAP_UNLOCK_SI(si);
7367 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7369 return swrap_recvmsg(sockfd, msg, flags);
7372 /****************************************************************************
7374 ***************************************************************************/
7376 #ifdef HAVE_RECVMMSG
7377 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7379 static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7380 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7381 /* Linux legacy glibc < 2.21 */
7382 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7384 /* Linux glibc >= 2.21 */
7385 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7388 struct socket_info *si = find_socket_info(s);
7389 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7390 struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7393 struct swrap_address from_addr;
7394 struct swrap_address convert_addr;
7395 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7396 size_t msg_ctrllen_filled;
7397 size_t msg_ctrllen_left;
7399 } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7406 if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7407 vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7413 uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7415 for (i = 0; i < vlen; i++) {
7416 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7417 struct msghdr *msg = &msgvec[i].msg_hdr;
7419 rc = swrap_recvmsg_before_unix(omsg, msg,
7427 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7432 for (i = 0; i < ret; i++) {
7433 omsgvec[i].msg_len = msgvec[i].msg_len;
7437 saved_errno = errno;
7438 for (i = 0; i < vlen; i++) {
7439 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7440 struct msghdr *msg = &msgvec[i].msg_hdr;
7442 if (i == 0 || i < ret) {
7443 swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7445 SAFE_FREE(tmp_control[i]);
7447 errno = saved_errno;
7452 for (i = 0; i < vlen; i++) {
7453 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7454 struct msghdr *msg = &msgvec[i].msg_hdr;
7456 tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7457 tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7459 msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7460 msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7461 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7462 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7463 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7464 tmp[i].msg_ctrllen_filled = 0;
7465 tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7467 msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7468 msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7469 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7472 rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7479 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7484 for (i = 0; i < ret; i++) {
7485 omsgvec[i].msg_len = msgvec[i].msg_len;
7490 saved_errno = errno;
7491 for (i = 0; i < vlen; i++) {
7492 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7493 struct msghdr *msg = &msgvec[i].msg_hdr;
7495 if (!(i == 0 || i < ret)) {
7499 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7500 tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7501 tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7503 if (omsg->msg_control != NULL) {
7506 p = omsg->msg_control;
7507 p += tmp[i].msg_ctrllen_filled;
7509 msg->msg_control = p;
7510 msg->msg_controllen = tmp[i].msg_ctrllen_left;
7512 msg->msg_control = NULL;
7513 msg->msg_controllen = 0;
7518 * We convert the unix address to a IP address so we need a buffer
7519 * which can store the address in case of SOCK_DGRAM, see below.
7521 msg->msg_name = &tmp[i].convert_addr.sa;
7522 msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7524 swrap_recvmsg_after(s, si, msg,
7525 &tmp[i].from_addr.sa.un,
7526 tmp[i].from_addr.sa_socklen,
7529 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7530 if (omsg->msg_control != NULL) {
7531 /* msg->msg_controllen = space left */
7532 tmp[i].msg_ctrllen_left = msg->msg_controllen;
7533 tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7536 /* Update the original message length */
7537 omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7538 omsg->msg_flags = msg->msg_flags;
7540 omsg->msg_iovlen = msg->msg_iovlen;
7547 * The msg_name field points to a caller-allocated buffer that is
7548 * used to return the source address if the socket is unconnected. The
7549 * caller should set msg_namelen to the size of this buffer before this
7550 * call; upon return from a successful call, msg_name will contain the
7551 * length of the returned address. If the application does not need
7552 * to know the source address, msg_name can be specified as NULL.
7554 if (si->type == SOCK_STREAM) {
7555 omsg->msg_namelen = 0;
7556 } else if (omsg->msg_name != NULL &&
7557 omsg->msg_namelen != 0 &&
7558 omsg->msg_namelen >= msg->msg_namelen) {
7559 memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7560 omsg->msg_namelen = msg->msg_namelen;
7563 SWRAP_UNLOCK_SI(si);
7565 errno = saved_errno;
7570 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7572 ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7573 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7574 /* Linux legacy glibc < 2.21 */
7575 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7577 /* Linux glibc >= 2.21 */
7578 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7581 return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7583 #endif /* HAVE_RECVMMSG */
7585 /****************************************************************************
7587 ***************************************************************************/
7589 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7593 struct sockaddr_un un_addr;
7594 const struct sockaddr_un *to_un = NULL;
7595 const struct sockaddr *to = NULL;
7598 struct socket_info *si = find_socket_info(s);
7602 int scm_rights_pipe_fd = -1;
7604 rc = swrap_sendmsg_before_unix(omsg, &msg,
7605 &scm_rights_pipe_fd);
7609 ret = libc_sendmsg(s, &msg, flags);
7610 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7613 ZERO_STRUCT(un_addr);
7615 tmp.iov_base = NULL;
7622 if (si->connected == 0) {
7623 msg.msg_name = omsg->msg_name; /* optional address */
7624 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7626 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7627 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7629 SWRAP_UNLOCK_SI(si);
7631 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7632 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7633 uint8_t *cmbuf = NULL;
7636 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7642 msg.msg_controllen = 0;
7643 msg.msg_control = NULL;
7645 msg.msg_control = cmbuf;
7646 msg.msg_controllen = cmlen;
7649 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7651 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7653 int saved_errno = errno;
7654 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7655 SAFE_FREE(msg.msg_control);
7657 errno = saved_errno;
7664 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7671 char *swrap_dir = NULL;
7673 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7674 avail += msg.msg_iov[i].iov_len;
7680 /* we capture it as one single packet */
7681 buf = (uint8_t *)malloc(remain);
7683 int saved_errno = errno;
7684 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7685 SAFE_FREE(msg.msg_control);
7687 errno = saved_errno;
7691 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7692 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7694 msg.msg_iov[i].iov_base,
7697 remain -= this_time;
7700 type = SOCKET_TYPE_CHAR_UDP;
7702 swrap_dir = socket_wrapper_dir();
7703 if (swrap_dir == NULL) {
7704 int saved_errno = errno;
7705 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7706 SAFE_FREE(msg.msg_control);
7709 errno = saved_errno;
7713 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7714 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7715 if (stat(un_addr.sun_path, &st) != 0) continue;
7717 msg.msg_name = &un_addr; /* optional address */
7718 msg.msg_namelen = sizeof(un_addr); /* size of address */
7720 /* ignore the any errors in broadcast sends */
7721 libc_sendmsg(s, &msg, flags);
7724 SAFE_FREE(swrap_dir);
7728 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7731 SWRAP_UNLOCK_SI(si);
7736 ret = libc_sendmsg(s, &msg, flags);
7738 swrap_sendmsg_after(s, si, &msg, to, ret);
7740 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7742 int saved_errno = errno;
7743 SAFE_FREE(msg.msg_control);
7744 errno = saved_errno;
7751 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7753 return swrap_sendmsg(s, omsg, flags);
7756 /****************************************************************************
7758 ***************************************************************************/
7760 #ifdef HAVE_SENDMMSG
7761 #if defined(HAVE_SENDMMSG_SSIZE_T)
7763 static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7766 static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7769 struct socket_info *si = find_socket_info(s);
7770 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7771 struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7774 struct sockaddr_un un_addr;
7775 const struct sockaddr_un *to_un;
7776 const struct sockaddr *to;
7778 } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7781 char *swrap_dir = NULL;
7783 int found_bcast = 0;
7788 if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7789 vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7795 int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7797 for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7798 scm_rights_pipe_fd[i] = -1;
7801 for (i = 0; i < vlen; i++) {
7802 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7803 struct msghdr *msg = &msgvec[i].msg_hdr;
7805 rc = swrap_sendmsg_before_unix(omsg, msg,
7806 &scm_rights_pipe_fd[i]);
7813 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7818 for (i = 0; i < ret; i++) {
7819 omsgvec[i].msg_len = msgvec[i].msg_len;
7823 saved_errno = errno;
7824 for (i = 0; i < vlen; i++) {
7825 struct msghdr *msg = &msgvec[i].msg_hdr;
7827 swrap_sendmsg_after_unix(msg, ret,
7828 scm_rights_pipe_fd[i]);
7830 errno = saved_errno;
7836 connected = si->connected;
7837 SWRAP_UNLOCK_SI(si);
7839 for (i = 0; i < vlen; i++) {
7840 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7841 struct msghdr *msg = &msgvec[i].msg_hdr;
7843 if (connected == 0) {
7844 msg->msg_name = omsg->msg_name; /* optional address */
7845 msg->msg_namelen = omsg->msg_namelen; /* size of address */
7847 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7848 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7850 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7851 if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7852 uint8_t *cmbuf = NULL;
7855 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7862 msg->msg_control = cmbuf;
7863 msg->msg_controllen = cmlen;
7866 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7869 rc = swrap_sendmsg_before(s, si, msg,
7887 swrap_dir = socket_wrapper_dir();
7888 if (swrap_dir == NULL) {
7893 for (i = 0; i < vlen; i++) {
7894 struct msghdr *msg = &msgvec[i].msg_hdr;
7895 struct sockaddr_un *un_addr = &tmp[i].un_addr;
7896 const struct sockaddr *to = tmp[i].to;
7899 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7907 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7908 avail += msg->msg_iov[l].iov_len;
7914 /* we capture it as one single packet */
7915 buf = (uint8_t *)malloc(remain);
7921 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7922 size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
7924 msg->msg_iov[l].iov_base,
7927 remain -= this_time;
7930 type = SOCKET_TYPE_CHAR_UDP;
7932 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7933 swrap_un_path(un_addr, swrap_dir, type, iface, prt);
7934 if (stat(un_addr->sun_path, &st) != 0) continue;
7936 msg->msg_name = un_addr; /* optional address */
7937 msg->msg_namelen = sizeof(*un_addr); /* size of address */
7940 * ignore the any errors in broadcast sends and
7941 * do a single sendmsg instead of sendmmsg
7943 libc_sendmsg(s, msg, flags);
7947 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7948 SWRAP_UNLOCK_SI(si);
7952 msgvec[i].msg_len = len;
7959 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7965 for (i = 0; i < ret; i++) {
7966 omsgvec[i].msg_len = msgvec[i].msg_len;
7970 saved_errno = errno;
7971 for (i = 0; i < vlen; i++) {
7972 struct msghdr *msg = &msgvec[i].msg_hdr;
7974 if (i == 0 || i < ret) {
7975 swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
7977 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7978 SAFE_FREE(msg->msg_control);
7981 SAFE_FREE(swrap_dir);
7982 errno = saved_errno;
7987 #if defined(HAVE_SENDMMSG_SSIZE_T)
7989 ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
7992 int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
7995 return swrap_sendmmsg(s, msgvec, vlen, flags);
7997 #endif /* HAVE_SENDMMSG */
7999 /****************************************************************************
8001 ***************************************************************************/
8003 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
8005 struct socket_info *si;
8008 struct swrap_address saddr = {
8009 .sa_socklen = sizeof(struct sockaddr_storage)
8014 si = find_socket_info(s);
8016 return libc_readv(s, vector, count);
8019 tmp.iov_base = NULL;
8023 msg.msg_name = &saddr.sa.s; /* optional address */
8024 msg.msg_namelen = saddr.sa_socklen; /* size of address */
8025 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8026 msg.msg_iovlen = count; /* # elements in msg_iov */
8027 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8028 msg.msg_control = NULL; /* ancillary data, see below */
8029 msg.msg_controllen = 0; /* ancillary data buffer len */
8030 msg.msg_flags = 0; /* flags on received message */
8033 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
8035 if (rc == -ENOTSOCK) {
8036 return libc_readv(s, vector, count);
8041 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
8043 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
8051 ssize_t readv(int s, const struct iovec *vector, int count)
8053 return swrap_readv(s, vector, count);
8056 /****************************************************************************
8058 ***************************************************************************/
8060 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
8064 struct sockaddr_un un_addr;
8067 struct socket_info *si = find_socket_info(s);
8070 return libc_writev(s, vector, count);
8073 tmp.iov_base = NULL;
8077 msg.msg_name = NULL; /* optional address */
8078 msg.msg_namelen = 0; /* size of address */
8079 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
8080 msg.msg_iovlen = count; /* # elements in msg_iov */
8081 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
8082 msg.msg_control = NULL; /* ancillary data, see below */
8083 msg.msg_controllen = 0; /* ancillary data buffer len */
8084 msg.msg_flags = 0; /* flags on received message */
8087 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
8089 if (rc == -ENOTSOCK) {
8090 return libc_readv(s, vector, count);
8095 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
8097 swrap_sendmsg_after(s, si, &msg, NULL, ret);
8102 ssize_t writev(int s, const struct iovec *vector, int count)
8104 return swrap_writev(s, vector, count);
8107 /****************************
8109 ***************************/
8111 static int swrap_remove_wrapper(const char *__func_name,
8112 int (*__close_fd_fn)(int fd),
8115 struct socket_info *si = NULL;
8117 int ret_errno = errno;
8120 swrap_mutex_lock(&socket_reset_mutex);
8122 si_index = find_socket_info_index(fd);
8123 if (si_index == -1) {
8124 swrap_mutex_unlock(&socket_reset_mutex);
8125 return __close_fd_fn(fd);
8128 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8129 reset_socket_info_index(fd);
8131 si = swrap_get_socket_info(si_index);
8133 swrap_mutex_lock(&first_free_mutex);
8136 ret = __close_fd_fn(fd);
8141 swrap_dec_refcount(si);
8143 if (swrap_get_refcount(si) > 0) {
8144 /* there are still references left */
8148 if (si->fd_passed) {
8152 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8153 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8156 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8157 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8158 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8161 if (si->un_addr.sun_path[0] != '\0') {
8162 unlink(si->un_addr.sun_path);
8166 swrap_set_next_free(si, first_free);
8167 first_free = si_index;
8170 SWRAP_UNLOCK_SI(si);
8171 swrap_mutex_unlock(&first_free_mutex);
8172 swrap_mutex_unlock(&socket_reset_mutex);
8178 static int swrap_noop_close(int fd)
8180 (void)fd; /* unused */
8184 static void swrap_remove_stale(int fd)
8186 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8190 * This allows socket_wrapper aware applications to
8191 * indicate that the given fd does not belong to
8194 * We already overload a lot of unrelated functions
8195 * like eventfd(), timerfd_create(), ... in order to
8196 * call swrap_remove_stale() on the returned fd, but
8197 * we'll never be able to handle all possible syscalls.
8199 * socket_wrapper_indicate_no_inet_fd() gives them a way
8202 * We don't export swrap_remove_stale() in order to
8203 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8206 void socket_wrapper_indicate_no_inet_fd(int fd)
8208 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8211 static int swrap_close(int fd)
8213 return swrap_remove_wrapper(__func__, libc_close, fd);
8218 return swrap_close(fd);
8221 #ifdef HAVE___CLOSE_NOCANCEL
8223 static int swrap___close_nocancel(int fd)
8225 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8228 int __close_nocancel(int fd);
8229 int __close_nocancel(int fd)
8231 return swrap___close_nocancel(fd);
8234 #endif /* HAVE___CLOSE_NOCANCEL */
8236 /****************************
8238 ***************************/
8240 static int swrap_dup(int fd)
8242 struct socket_info *si;
8245 idx = find_socket_info_index(fd);
8247 return libc_dup(fd);
8250 si = swrap_get_socket_info(idx);
8252 dup_fd = libc_dup(fd);
8254 int saved_errno = errno;
8255 errno = saved_errno;
8259 if ((size_t)dup_fd >= socket_fds_max) {
8260 SWRAP_LOG(SWRAP_LOG_ERROR,
8261 "The max socket index limit of %zu has been reached, "
8272 swrap_inc_refcount(si);
8274 SWRAP_UNLOCK_SI(si);
8276 /* Make sure we don't have an entry for the fd */
8277 swrap_remove_stale(dup_fd);
8279 set_socket_info_index(dup_fd, idx);
8286 return swrap_dup(fd);
8289 /****************************
8291 ***************************/
8293 static int swrap_dup2(int fd, int newfd)
8295 struct socket_info *si;
8298 idx = find_socket_info_index(fd);
8300 return libc_dup2(fd, newfd);
8303 si = swrap_get_socket_info(idx);
8307 * According to the manpage:
8309 * "If oldfd is a valid file descriptor, and newfd has the same
8310 * value as oldfd, then dup2() does nothing, and returns newfd."
8315 if ((size_t)newfd >= socket_fds_max) {
8316 SWRAP_LOG(SWRAP_LOG_ERROR,
8317 "The max socket index limit of %zu has been reached, "
8325 if (find_socket_info(newfd)) {
8326 /* dup2() does an implicit close of newfd, which we
8327 * need to emulate */
8331 dup_fd = libc_dup2(fd, newfd);
8333 int saved_errno = errno;
8334 errno = saved_errno;
8340 swrap_inc_refcount(si);
8342 SWRAP_UNLOCK_SI(si);
8344 /* Make sure we don't have an entry for the fd */
8345 swrap_remove_stale(dup_fd);
8347 set_socket_info_index(dup_fd, idx);
8352 int dup2(int fd, int newfd)
8354 return swrap_dup2(fd, newfd);
8357 /****************************
8359 ***************************/
8361 static int swrap_vfcntl(int fd, int cmd, va_list va)
8363 struct socket_info *si;
8364 int rc, dup_fd, idx;
8366 idx = find_socket_info_index(fd);
8368 return libc_vfcntl(fd, cmd, va);
8371 si = swrap_get_socket_info(idx);
8375 dup_fd = libc_vfcntl(fd, cmd, va);
8377 int saved_errno = errno;
8378 errno = saved_errno;
8382 /* Make sure we don't have an entry for the fd */
8383 swrap_remove_stale(dup_fd);
8385 if ((size_t)dup_fd >= socket_fds_max) {
8386 SWRAP_LOG(SWRAP_LOG_ERROR,
8387 "The max socket index limit of %zu has been reached, "
8398 swrap_inc_refcount(si);
8400 SWRAP_UNLOCK_SI(si);
8403 set_socket_info_index(dup_fd, idx);
8408 rc = libc_vfcntl(fd, cmd, va);
8415 int fcntl(int fd, int cmd, ...)
8422 rc = swrap_vfcntl(fd, cmd, va);
8429 /****************************
8431 ***************************/
8434 static int swrap_eventfd(int count, int flags)
8438 fd = libc_eventfd(count, flags);
8440 swrap_remove_stale(fd);
8446 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8447 int eventfd(unsigned int count, int flags)
8449 int eventfd(int count, int flags)
8452 return swrap_eventfd(count, flags);
8457 int pledge(const char *promises, const char *paths[])
8459 (void)promises; /* unused */
8460 (void)paths; /* unused */
8464 #endif /* HAVE_PLEDGE */
8467 static bool swrap_is_swrap_related_syscall(long int sysno)
8473 #endif /* SYS_close */
8478 #endif /* SYS_recvmmsg */
8483 #endif /* SYS_sendmmsg */
8490 static long int swrap_syscall(long int sysno, va_list vp)
8498 int fd = (int)va_arg(vp, int);
8500 SWRAP_LOG(SWRAP_LOG_TRACE,
8501 "calling swrap_close syscall %lu",
8503 rc = swrap_close(fd);
8506 #endif /* SYS_close */
8511 int fd = (int)va_arg(vp, int);
8512 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8513 unsigned int vlen = va_arg(vp, unsigned int);
8514 int flags = va_arg(vp, int);
8515 struct timespec *timeout = va_arg(vp, struct timespec *);
8517 SWRAP_LOG(SWRAP_LOG_TRACE,
8518 "calling swrap_recvmmsg syscall %lu",
8520 rc = swrap_recvmmsg(fd, msgvec, vlen, flags, timeout);
8523 #endif /* SYS_recvmmsg */
8528 int fd = (int)va_arg(vp, int);
8529 struct mmsghdr *msgvec = va_arg(vp, struct mmsghdr *);
8530 unsigned int vlen = va_arg(vp, unsigned int);
8531 int flags = va_arg(vp, int);
8533 SWRAP_LOG(SWRAP_LOG_TRACE,
8534 "calling swrap_sendmmsg syscall %lu",
8536 rc = swrap_sendmmsg(fd, msgvec, vlen, flags);
8539 #endif /* SYS_sendmmsg */
8550 #ifdef HAVE_SYSCALL_INT
8551 int syscall(int sysno, ...)
8553 long int syscall(long int sysno, ...)
8556 #ifdef HAVE_SYSCALL_INT
8563 va_start(va, sysno);
8566 * We should only handle the syscall numbers
8569 if (!swrap_is_swrap_related_syscall(sysno)) {
8571 * We need to give socket_wrapper a
8572 * chance to take over...
8574 if (swrap_uwrap_syscall_valid(sysno)) {
8575 rc = swrap_uwrap_syscall_va(sysno, va);
8580 rc = libc_vsyscall(sysno, va);
8585 if (!socket_wrapper_enabled()) {
8586 rc = libc_vsyscall(sysno, va);
8591 rc = swrap_syscall(sysno, va);
8597 /* used by uid_wrapper */
8598 bool socket_wrapper_syscall_valid(long int sysno);
8599 bool socket_wrapper_syscall_valid(long int sysno)
8601 if (!swrap_is_swrap_related_syscall(sysno)) {
8605 if (!socket_wrapper_enabled()) {
8612 /* used by uid_wrapper */
8613 long int socket_wrapper_syscall_va(long int sysno, va_list va);
8614 long int socket_wrapper_syscall_va(long int sysno, va_list va)
8616 if (!swrap_is_swrap_related_syscall(sysno)) {
8621 if (!socket_wrapper_enabled()) {
8622 return libc_vsyscall(sysno, va);
8625 return swrap_syscall(sysno, va);
8627 #endif /* HAVE_SYSCALL */
8629 static void swrap_thread_prepare(void)
8632 * This function should only be called here!!
8634 * We bind all symobls to avoid deadlocks of the fork is
8635 * interrupted by a signal handler using a symbol of this
8638 swrap_bind_symbol_all();
8643 static void swrap_thread_parent(void)
8648 static void swrap_thread_child(void)
8653 /****************************
8655 ***************************/
8656 void swrap_constructor(void)
8658 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8659 SWRAP_LOG(SWRAP_LOG_ERROR,
8661 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8662 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8663 "sizeof(struct socket_info)=%zu",
8665 sizeof(struct swrap_unix_scm_rights),
8666 sizeof(struct swrap_unix_scm_rights_payload),
8667 sizeof(struct socket_info));
8674 * If we hold a lock and the application forks, then the child
8675 * is not able to unlock the mutex and we are in a deadlock.
8676 * This should prevent such deadlocks.
8678 pthread_atfork(&swrap_thread_prepare,
8679 &swrap_thread_parent,
8680 &swrap_thread_child);
8683 /****************************
8685 ***************************/
8688 * This function is called when the library is unloaded and makes sure that
8689 * sockets get closed and the unix file for the socket are unlinked.
8691 void swrap_destructor(void)
8695 if (socket_fds_idx != NULL) {
8696 for (i = 0; i < socket_fds_max; ++i) {
8697 if (socket_fds_idx[i] != -1) {
8701 SAFE_FREE(socket_fds_idx);
8706 if (swrap.libc.handle != NULL
8708 && swrap.libc.handle != RTLD_NEXT
8711 dlclose(swrap.libc.handle);
8713 if (swrap.libc.socket_handle
8715 && swrap.libc.socket_handle != RTLD_NEXT
8718 dlclose(swrap.libc.socket_handle);
8722 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8724 * On FreeBSD 12 (and maybe other platforms)
8725 * system libraries like libresolv prefix there
8726 * syscalls with '_' in order to always use
8727 * the symbols from libc.
8729 * In the interaction with resolv_wrapper,
8730 * we need to inject socket wrapper into libresolv,
8731 * which means we need to private all socket
8732 * related syscalls also with the '_' prefix.
8734 * This is tested in Samba's 'make test',
8735 * there we noticed that providing '_read',
8736 * '_open' and '_close' would cause errors, which
8737 * means we skip '_read', '_write' and
8738 * all non socket related calls without
8739 * further analyzing the problem.
8741 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8742 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8745 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8747 SWRAP_SYMBOL_ALIAS(accept, _accept);
8748 SWRAP_SYMBOL_ALIAS(bind, _bind);
8749 SWRAP_SYMBOL_ALIAS(connect, _connect);
8750 SWRAP_SYMBOL_ALIAS(dup, _dup);
8751 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8752 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8753 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8754 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8755 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8756 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8757 SWRAP_SYMBOL_ALIAS(listen, _listen);
8758 SWRAP_SYMBOL_ALIAS(readv, _readv);
8759 SWRAP_SYMBOL_ALIAS(recv, _recv);
8760 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8761 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8762 SWRAP_SYMBOL_ALIAS(send, _send);
8763 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8764 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8765 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8766 SWRAP_SYMBOL_ALIAS(socket, _socket);
8767 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8768 SWRAP_SYMBOL_ALIAS(writev, _writev);
8770 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */