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 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
55 #ifdef HAVE_SYS_SIGNALFD_H
56 #include <sys/signalfd.h>
58 #ifdef HAVE_SYS_EVENTFD_H
59 #include <sys/eventfd.h>
61 #ifdef HAVE_SYS_TIMERFD_H
62 #include <sys/timerfd.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #ifdef HAVE_NETINET_TCP_FSM_H
70 #include <netinet/tcp_fsm.h>
72 #include <arpa/inet.h>
81 #ifdef HAVE_GNU_LIB_NAMES_H
82 #include <gnu/lib-names.h>
89 #include "socket_wrapper.h"
98 /* GCC have printf type attribute check. */
99 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
100 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
102 #define PRINTF_ATTRIBUTE(a,b)
103 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
105 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
106 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
108 #define CONSTRUCTOR_ATTRIBUTE
109 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
111 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
112 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
114 #define DESTRUCTOR_ATTRIBUTE
118 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
119 # define FALL_THROUGH __attribute__ ((fallthrough))
120 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
121 # define FALL_THROUGH ((void)0)
122 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
123 #endif /* FALL_THROUGH */
125 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
126 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
128 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
131 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
132 # define SWRAP_THREAD __thread
134 # define SWRAP_THREAD
138 #define MIN(a,b) ((a)<(b)?(a):(b))
142 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
146 #define ZERO_STRUCTP(x) do { \
148 memset((char *)(x), 0, sizeof(*(x))); \
153 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
156 #ifndef discard_const
157 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
160 #ifndef discard_const_p
161 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
164 #define UNUSED(x) (void)(x)
167 # ifndef IPV6_RECVPKTINFO
168 # define IPV6_RECVPKTINFO IPV6_PKTINFO
169 # endif /* IPV6_RECVPKTINFO */
170 #endif /* IPV6_PKTINFO */
173 * On BSD IP_PKTINFO has a different name because during
174 * the time when they implemented it, there was no RFC.
175 * The name for IPv6 is the same as on Linux.
178 # ifdef IP_RECVDSTADDR
179 # define IP_PKTINFO IP_RECVDSTADDR
183 #define socket_wrapper_init_mutex(m) \
184 _socket_wrapper_init_mutex(m, #m)
186 /* Add new global locks here please */
187 # define SWRAP_REINIT_ALL do { \
189 ret = socket_wrapper_init_mutex(&sockets_mutex); \
190 if (ret != 0) exit(-1); \
191 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
192 if (ret != 0) exit(-1); \
193 ret = socket_wrapper_init_mutex(&first_free_mutex); \
194 if (ret != 0) exit(-1); \
195 ret = socket_wrapper_init_mutex(&sockets_si_global); \
196 if (ret != 0) exit(-1); \
197 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
198 if (ret != 0) exit(-1); \
199 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
200 if (ret != 0) exit(-1); \
201 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
202 if (ret != 0) exit(-1); \
205 # define SWRAP_LOCK_ALL do { \
206 swrap_mutex_lock(&sockets_mutex); \
207 swrap_mutex_lock(&socket_reset_mutex); \
208 swrap_mutex_lock(&first_free_mutex); \
209 swrap_mutex_lock(&sockets_si_global); \
210 swrap_mutex_lock(&autobind_start_mutex); \
211 swrap_mutex_lock(&pcap_dump_mutex); \
212 swrap_mutex_lock(&mtu_update_mutex); \
215 # define SWRAP_UNLOCK_ALL do { \
216 swrap_mutex_unlock(&mtu_update_mutex); \
217 swrap_mutex_unlock(&pcap_dump_mutex); \
218 swrap_mutex_unlock(&autobind_start_mutex); \
219 swrap_mutex_unlock(&sockets_si_global); \
220 swrap_mutex_unlock(&first_free_mutex); \
221 swrap_mutex_unlock(&socket_reset_mutex); \
222 swrap_mutex_unlock(&sockets_mutex); \
225 #define SOCKET_INFO_CONTAINER(si) \
226 (struct socket_info_container *)(si)
228 #define SWRAP_LOCK_SI(si) do { \
229 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
231 swrap_mutex_lock(&sockets_si_global); \
237 #define SWRAP_UNLOCK_SI(si) do { \
238 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
240 swrap_mutex_unlock(&sockets_si_global); \
246 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
247 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
249 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
252 /* we need to use a very terse format here as IRIX 6.4 silently
253 truncates names to 16 chars, so if we use a longer name then we
254 can't tell which port a packet came from with recvfrom()
256 with this format we have 8 chars left for the directory name
258 #define SOCKET_FORMAT "%c%02X%04X"
259 #define SOCKET_TYPE_CHAR_TCP 'T'
260 #define SOCKET_TYPE_CHAR_UDP 'U'
261 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
262 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
265 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
266 * format PCAP capture files (as the caller will simply continue from here).
268 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
269 #define SOCKET_WRAPPER_MTU_MIN 512
270 #define SOCKET_WRAPPER_MTU_MAX 32768
272 #define SOCKET_MAX_SOCKETS 1024
275 * Maximum number of socket_info structures that can
276 * be used. Can be overriden by the environment variable
277 * SOCKET_WRAPPER_MAX_SOCKETS.
279 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
281 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
283 /* This limit is to avoid broadcast sendto() needing to stat too many
284 * files. It may be raised (with a performance cost) to up to 254
285 * without changing the format above */
286 #define MAX_WRAPPED_INTERFACES 64
288 struct swrap_address {
289 socklen_t sa_socklen;
292 struct sockaddr_in in;
294 struct sockaddr_in6 in6;
296 struct sockaddr_un un;
297 struct sockaddr_storage ss;
301 static int first_free;
306 * Remember to update swrap_unix_scm_right_magic
323 /* The unix path so we can unlink it on close() */
324 struct sockaddr_un un_addr;
326 struct swrap_address bindname;
327 struct swrap_address myname;
328 struct swrap_address peername;
331 unsigned long pck_snd;
332 unsigned long pck_rcv;
336 struct socket_info_meta
338 unsigned int refcount;
341 * As long as we don't use shared memory
342 * for the sockets array, we use
343 * sockets_si_global as a single mutex.
345 * pthread_mutex_t mutex;
349 struct socket_info_container
351 struct socket_info info;
352 struct socket_info_meta meta;
355 static struct socket_info_container *sockets;
357 static size_t socket_info_max = 0;
360 * Allocate the socket array always on the limit value. We want it to be
361 * at least bigger than the default so if we reach the limit we can
362 * still deal with duplicate fds pointing to the same socket_info.
364 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
366 /* Hash table to map fds to corresponding socket_info index */
367 static int *socket_fds_idx;
369 /* Mutex for syncronizing port selection during swrap_auto_bind() */
370 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
372 /* Mutex to guard the initialization of array of socket_info structures */
373 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
375 /* Mutex to guard the socket reset in swrap_remove_wrapper() */
376 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
378 /* Mutex to synchronize access to first free index in socket_info array */
379 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
382 * Mutex to synchronize access to to socket_info structures
383 * We use a single global mutex in order to avoid leaking
384 * ~ 38M copy on write memory per fork.
385 * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
387 static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER;
389 /* Mutex to synchronize access to packet capture dump file */
390 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
392 /* Mutex for synchronizing mtu value fetch*/
393 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
395 /* Function prototypes */
397 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
398 /* xlC and other oldschool compilers support (only) this */
399 #pragma init (swrap_constructor)
401 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
402 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
403 #pragma fini (swrap_destructor)
405 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
407 #ifndef HAVE_GETPROGNAME
408 static const char *getprogname(void)
410 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
411 return program_invocation_short_name;
412 #elif defined(HAVE_GETEXECNAME)
413 return getexecname();
416 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
418 #endif /* HAVE_GETPROGNAME */
420 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
421 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
423 static void swrap_log(enum swrap_dbglvl_e dbglvl,
425 const char *format, ...)
430 unsigned int lvl = 0;
431 const char *prefix = "SWRAP";
432 const char *progname = getprogname();
434 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
443 va_start(va, format);
444 vsnprintf(buffer, sizeof(buffer), format, va);
448 case SWRAP_LOG_ERROR:
449 prefix = "SWRAP_ERROR";
452 prefix = "SWRAP_WARN";
454 case SWRAP_LOG_DEBUG:
455 prefix = "SWRAP_DEBUG";
457 case SWRAP_LOG_TRACE:
458 prefix = "SWRAP_TRACE";
462 if (progname == NULL) {
463 progname = "<unknown>";
467 "%s[%s (%u)] - %s: %s\n",
470 (unsigned int)getpid(),
475 /*********************************************************
476 * SWRAP LOADING LIBC FUNCTIONS
477 *********************************************************/
482 typedef int (*__libc_accept4)(int sockfd,
483 struct sockaddr *addr,
487 typedef int (*__libc_accept)(int sockfd,
488 struct sockaddr *addr,
491 typedef int (*__libc_bind)(int sockfd,
492 const struct sockaddr *addr,
494 typedef int (*__libc_close)(int fd);
495 #ifdef HAVE___CLOSE_NOCANCEL
496 typedef int (*__libc___close_nocancel)(int fd);
498 typedef int (*__libc_connect)(int sockfd,
499 const struct sockaddr *addr,
501 typedef int (*__libc_dup)(int fd);
502 typedef int (*__libc_dup2)(int oldfd, int newfd);
503 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
504 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
506 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
509 typedef int (*__libc_eventfd)(int count, int flags);
511 typedef int (*__libc_getpeername)(int sockfd,
512 struct sockaddr *addr,
514 typedef int (*__libc_getsockname)(int sockfd,
515 struct sockaddr *addr,
517 typedef int (*__libc_getsockopt)(int sockfd,
522 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
523 typedef int (*__libc_listen)(int sockfd, int backlog);
524 typedef int (*__libc_open)(const char *pathname, int flags, ...);
526 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
527 #endif /* HAVE_OPEN64 */
528 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
529 typedef int (*__libc_pipe)(int pipefd[2]);
530 typedef int (*__libc_read)(int fd, void *buf, size_t count);
531 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
532 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
533 typedef int (*__libc_recvfrom)(int sockfd,
537 struct sockaddr *src_addr,
539 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
541 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
543 typedef ssize_t (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout);
544 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
545 /* Linux legacy glibc < 2.21 */
546 typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout);
548 /* Linux glibc >= 2.21 */
549 typedef int (*__libc_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout);
551 #endif /* HAVE_RECVMMSG */
552 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
553 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
555 #if defined(HAVE_SENDMMSG_SSIZE_T)
557 typedef ssize_t (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags);
560 typedef int (*__libc_sendmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags);
562 #endif /* HAVE_SENDMMSG */
563 typedef int (*__libc_sendto)(int sockfd,
567 const struct sockaddr *dst_addr,
569 typedef int (*__libc_setsockopt)(int sockfd,
575 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
577 typedef int (*__libc_socket)(int domain, int type, int protocol);
578 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
579 #ifdef HAVE_TIMERFD_CREATE
580 typedef int (*__libc_timerfd_create)(int clockid, int flags);
582 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
583 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
585 #define SWRAP_SYMBOL_ENTRY(i) \
591 struct swrap_libc_symbols {
593 SWRAP_SYMBOL_ENTRY(accept4);
595 SWRAP_SYMBOL_ENTRY(accept);
597 SWRAP_SYMBOL_ENTRY(bind);
598 SWRAP_SYMBOL_ENTRY(close);
599 #ifdef HAVE___CLOSE_NOCANCEL
600 SWRAP_SYMBOL_ENTRY(__close_nocancel);
602 SWRAP_SYMBOL_ENTRY(connect);
603 SWRAP_SYMBOL_ENTRY(dup);
604 SWRAP_SYMBOL_ENTRY(dup2);
605 SWRAP_SYMBOL_ENTRY(fcntl);
606 SWRAP_SYMBOL_ENTRY(fopen);
608 SWRAP_SYMBOL_ENTRY(fopen64);
611 SWRAP_SYMBOL_ENTRY(eventfd);
613 SWRAP_SYMBOL_ENTRY(getpeername);
614 SWRAP_SYMBOL_ENTRY(getsockname);
615 SWRAP_SYMBOL_ENTRY(getsockopt);
616 SWRAP_SYMBOL_ENTRY(ioctl);
617 SWRAP_SYMBOL_ENTRY(listen);
618 SWRAP_SYMBOL_ENTRY(open);
620 SWRAP_SYMBOL_ENTRY(open64);
622 SWRAP_SYMBOL_ENTRY(openat);
623 SWRAP_SYMBOL_ENTRY(pipe);
624 SWRAP_SYMBOL_ENTRY(read);
625 SWRAP_SYMBOL_ENTRY(readv);
626 SWRAP_SYMBOL_ENTRY(recv);
627 SWRAP_SYMBOL_ENTRY(recvfrom);
628 SWRAP_SYMBOL_ENTRY(recvmsg);
630 SWRAP_SYMBOL_ENTRY(recvmmsg);
632 SWRAP_SYMBOL_ENTRY(send);
633 SWRAP_SYMBOL_ENTRY(sendmsg);
635 SWRAP_SYMBOL_ENTRY(sendmmsg);
637 SWRAP_SYMBOL_ENTRY(sendto);
638 SWRAP_SYMBOL_ENTRY(setsockopt);
640 SWRAP_SYMBOL_ENTRY(signalfd);
642 SWRAP_SYMBOL_ENTRY(socket);
643 SWRAP_SYMBOL_ENTRY(socketpair);
644 #ifdef HAVE_TIMERFD_CREATE
645 SWRAP_SYMBOL_ENTRY(timerfd_create);
647 SWRAP_SYMBOL_ENTRY(write);
648 SWRAP_SYMBOL_ENTRY(writev);
655 struct swrap_libc_symbols symbols;
659 static struct swrap swrap;
662 static char *socket_wrapper_dir(void);
664 #define LIBC_NAME "libc.so"
671 static const char *swrap_str_lib(enum swrap_lib lib)
676 case SWRAP_LIBSOCKET:
680 /* Compiler would warn us about unhandled enum value if we get here */
684 static void *swrap_load_lib_handle(enum swrap_lib lib)
686 int flags = RTLD_LAZY;
691 const char *env_preload = getenv("LD_PRELOAD");
692 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
693 bool enable_deepbind = true;
695 /* Don't do a deepbind if we run with libasan */
696 if (env_preload != NULL && strlen(env_preload) < 1024) {
697 const char *p = strstr(env_preload, "libasan.so");
699 enable_deepbind = false;
703 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
704 enable_deepbind = false;
707 if (enable_deepbind) {
708 flags |= RTLD_DEEPBIND;
713 case SWRAP_LIBSOCKET:
714 #ifdef HAVE_LIBSOCKET
715 handle = swrap.libc.socket_handle;
716 if (handle == NULL) {
717 for (i = 10; i >= 0; i--) {
718 char soname[256] = {0};
720 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
721 handle = dlopen(soname, flags);
722 if (handle != NULL) {
727 swrap.libc.socket_handle = handle;
732 handle = swrap.libc.handle;
734 if (handle == NULL) {
735 handle = dlopen(LIBC_SO, flags);
737 swrap.libc.handle = handle;
740 if (handle == NULL) {
741 for (i = 10; i >= 0; i--) {
742 char soname[256] = {0};
744 snprintf(soname, sizeof(soname), "libc.so.%d", i);
745 handle = dlopen(soname, flags);
746 if (handle != NULL) {
751 swrap.libc.handle = handle;
756 if (handle == NULL) {
758 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
760 SWRAP_LOG(SWRAP_LOG_ERROR,
761 "Failed to dlopen library: %s",
770 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
775 handle = swrap_load_lib_handle(lib);
777 func = dlsym(handle, fn_name);
779 SWRAP_LOG(SWRAP_LOG_ERROR,
780 "Failed to find %s: %s",
786 SWRAP_LOG(SWRAP_LOG_TRACE,
794 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
795 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
799 ret = pthread_mutex_lock(mutex);
801 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
802 getpid(), getppid(), caller, line, name, strerror(ret));
807 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
808 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
812 ret = pthread_mutex_unlock(mutex);
814 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
815 getpid(), getppid(), caller, line, name, strerror(ret));
821 * These macros have a thread race condition on purpose!
823 * This is an optimization to avoid locking each time we check if the symbol is
826 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
827 swrap.libc.symbols._libc_##sym_name.obj = \
828 _swrap_bind_symbol(lib, #sym_name); \
831 #define swrap_bind_symbol_libc(sym_name) \
832 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
834 #define swrap_bind_symbol_libsocket(sym_name) \
835 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
837 static void swrap_bind_symbol_all(void);
839 /****************************************************************************
841 ****************************************************************************
843 * Functions especially from libc need to be loaded individually, you can't
844 * load all at once or gdb will segfault at startup. The same applies to
845 * valgrind and has probably something todo with with the linker. So we need
846 * load each function at the point it is called the first time.
848 ****************************************************************************/
851 static int libc_accept4(int sockfd,
852 struct sockaddr *addr,
856 swrap_bind_symbol_all();
858 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
861 #else /* HAVE_ACCEPT4 */
863 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
865 swrap_bind_symbol_all();
867 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
869 #endif /* HAVE_ACCEPT4 */
871 static int libc_bind(int sockfd,
872 const struct sockaddr *addr,
875 swrap_bind_symbol_all();
877 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
880 static int libc_close(int fd)
882 swrap_bind_symbol_all();
884 return swrap.libc.symbols._libc_close.f(fd);
887 #ifdef HAVE___CLOSE_NOCANCEL
888 static int libc___close_nocancel(int fd)
890 swrap_bind_symbol_all();
892 return swrap.libc.symbols._libc___close_nocancel.f(fd);
894 #endif /* HAVE___CLOSE_NOCANCEL */
896 static int libc_connect(int sockfd,
897 const struct sockaddr *addr,
900 swrap_bind_symbol_all();
902 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
905 static int libc_dup(int fd)
907 swrap_bind_symbol_all();
909 return swrap.libc.symbols._libc_dup.f(fd);
912 static int libc_dup2(int oldfd, int newfd)
914 swrap_bind_symbol_all();
916 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
920 static int libc_eventfd(int count, int flags)
922 swrap_bind_symbol_all();
924 return swrap.libc.symbols._libc_eventfd.f(count, flags);
928 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
929 static int libc_vfcntl(int fd, int cmd, va_list ap)
934 swrap_bind_symbol_all();
936 arg = va_arg(ap, void *);
938 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
943 static int libc_getpeername(int sockfd,
944 struct sockaddr *addr,
947 swrap_bind_symbol_all();
949 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
952 static int libc_getsockname(int sockfd,
953 struct sockaddr *addr,
956 swrap_bind_symbol_all();
958 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
961 static int libc_getsockopt(int sockfd,
967 swrap_bind_symbol_all();
969 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
976 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
977 static int libc_vioctl(int d, unsigned long int request, va_list ap)
982 swrap_bind_symbol_all();
984 arg = va_arg(ap, void *);
986 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
991 static int libc_listen(int sockfd, int backlog)
993 swrap_bind_symbol_all();
995 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
998 static FILE *libc_fopen(const char *name, const char *mode)
1000 swrap_bind_symbol_all();
1002 return swrap.libc.symbols._libc_fopen.f(name, mode);
1006 static FILE *libc_fopen64(const char *name, const char *mode)
1008 swrap_bind_symbol_all();
1010 return swrap.libc.symbols._libc_fopen64.f(name, mode);
1012 #endif /* HAVE_FOPEN64 */
1014 static void swrap_inject_o_largefile(int *flags)
1016 (void)*flags; /* maybe unused */
1017 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
1019 if (((*flags) & O_PATH) == 0)
1022 *flags |= O_LARGEFILE;
1027 static int libc_vopen(const char *pathname, int flags, va_list ap)
1032 swrap_bind_symbol_all();
1034 swrap_inject_o_largefile(&flags);
1036 if (flags & O_CREAT) {
1037 mode = va_arg(ap, int);
1039 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1044 static int libc_open(const char *pathname, int flags, ...)
1049 va_start(ap, flags);
1050 fd = libc_vopen(pathname, flags, ap);
1057 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1062 swrap_bind_symbol_all();
1064 swrap_inject_o_largefile(&flags);
1066 if (flags & O_CREAT) {
1067 mode = va_arg(ap, int);
1069 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1073 #endif /* HAVE_OPEN64 */
1075 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1080 swrap_bind_symbol_all();
1082 swrap_inject_o_largefile(&flags);
1084 if (flags & O_CREAT) {
1085 mode = va_arg(ap, int);
1087 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1096 static int libc_openat(int dirfd, const char *path, int flags, ...)
1101 va_start(ap, flags);
1102 fd = libc_vopenat(dirfd, path, flags, ap);
1109 static int libc_pipe(int pipefd[2])
1111 swrap_bind_symbol_all();
1113 return swrap.libc.symbols._libc_pipe.f(pipefd);
1116 static int libc_read(int fd, void *buf, size_t count)
1118 swrap_bind_symbol_all();
1120 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1123 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1125 swrap_bind_symbol_all();
1127 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1130 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1132 swrap_bind_symbol_all();
1134 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1137 static int libc_recvfrom(int sockfd,
1141 struct sockaddr *src_addr,
1144 swrap_bind_symbol_all();
1146 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1154 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1156 swrap_bind_symbol_all();
1158 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1161 #ifdef HAVE_RECVMMSG
1162 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
1164 static ssize_t libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
1165 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
1166 /* Linux legacy glibc < 2.21 */
1167 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
1169 /* Linux glibc >= 2.21 */
1170 static int libc_recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
1173 swrap_bind_symbol_all();
1175 return swrap.libc.symbols._libc_recvmmsg.f(sockfd, msgvec, vlen, flags, timeout);
1179 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1181 swrap_bind_symbol_all();
1183 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1186 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1188 swrap_bind_symbol_all();
1190 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1193 #ifdef HAVE_SENDMMSG
1194 #if defined(HAVE_SENDMMSG_SSIZE_T)
1196 static ssize_t libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags)
1199 static int libc_sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
1202 swrap_bind_symbol_all();
1204 return swrap.libc.symbols._libc_sendmmsg.f(sockfd, msgvec, vlen, flags);
1208 static int libc_sendto(int sockfd,
1212 const struct sockaddr *dst_addr,
1215 swrap_bind_symbol_all();
1217 return swrap.libc.symbols._libc_sendto.f(sockfd,
1225 static int libc_setsockopt(int sockfd,
1231 swrap_bind_symbol_all();
1233 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1240 #ifdef HAVE_SIGNALFD
1241 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1243 swrap_bind_symbol_all();
1245 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1249 static int libc_socket(int domain, int type, int protocol)
1251 swrap_bind_symbol_all();
1253 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1256 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1258 swrap_bind_symbol_all();
1260 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1263 #ifdef HAVE_TIMERFD_CREATE
1264 static int libc_timerfd_create(int clockid, int flags)
1266 swrap_bind_symbol_all();
1268 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1272 static ssize_t libc_write(int fd, const void *buf, size_t count)
1274 swrap_bind_symbol_all();
1276 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1279 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1281 swrap_bind_symbol_all();
1283 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1286 /* DO NOT call this function during library initialization! */
1287 static void __swrap_bind_symbol_all_once(void)
1290 swrap_bind_symbol_libsocket(accept4);
1292 swrap_bind_symbol_libsocket(accept);
1294 swrap_bind_symbol_libsocket(bind);
1295 swrap_bind_symbol_libc(close);
1296 #ifdef HAVE___CLOSE_NOCANCEL
1297 swrap_bind_symbol_libc(__close_nocancel);
1299 swrap_bind_symbol_libsocket(connect);
1300 swrap_bind_symbol_libc(dup);
1301 swrap_bind_symbol_libc(dup2);
1302 swrap_bind_symbol_libc(fcntl);
1303 swrap_bind_symbol_libc(fopen);
1305 swrap_bind_symbol_libc(fopen64);
1308 swrap_bind_symbol_libc(eventfd);
1310 swrap_bind_symbol_libsocket(getpeername);
1311 swrap_bind_symbol_libsocket(getsockname);
1312 swrap_bind_symbol_libsocket(getsockopt);
1313 swrap_bind_symbol_libc(ioctl);
1314 swrap_bind_symbol_libsocket(listen);
1315 swrap_bind_symbol_libc(open);
1317 swrap_bind_symbol_libc(open64);
1319 swrap_bind_symbol_libc(openat);
1320 swrap_bind_symbol_libsocket(pipe);
1321 swrap_bind_symbol_libc(read);
1322 swrap_bind_symbol_libsocket(readv);
1323 swrap_bind_symbol_libsocket(recv);
1324 swrap_bind_symbol_libsocket(recvfrom);
1325 swrap_bind_symbol_libsocket(recvmsg);
1326 #ifdef HAVE_RECVMMSG
1327 swrap_bind_symbol_libsocket(recvmmsg);
1329 swrap_bind_symbol_libsocket(send);
1330 swrap_bind_symbol_libsocket(sendmsg);
1331 #ifdef HAVE_SENDMMSG
1332 swrap_bind_symbol_libsocket(sendmmsg);
1334 swrap_bind_symbol_libsocket(sendto);
1335 swrap_bind_symbol_libsocket(setsockopt);
1336 #ifdef HAVE_SIGNALFD
1337 swrap_bind_symbol_libsocket(signalfd);
1339 swrap_bind_symbol_libsocket(socket);
1340 swrap_bind_symbol_libsocket(socketpair);
1341 #ifdef HAVE_TIMERFD_CREATE
1342 swrap_bind_symbol_libc(timerfd_create);
1344 swrap_bind_symbol_libc(write);
1345 swrap_bind_symbol_libsocket(writev);
1348 static void swrap_bind_symbol_all(void)
1350 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1352 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1355 /*********************************************************
1356 * SWRAP HELPER FUNCTIONS
1357 *********************************************************/
1360 * We return 127.0.0.0 (default) or 10.53.57.0.
1362 * This can be controlled by:
1363 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1365 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1367 static in_addr_t swrap_ipv4_net(void)
1369 static int initialized;
1370 static in_addr_t hv;
1371 const char *net_str = NULL;
1380 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1381 if (net_str == NULL) {
1382 net_str = "127.0.0.0";
1385 ret = inet_pton(AF_INET, net_str, &nv);
1387 SWRAP_LOG(SWRAP_LOG_ERROR,
1388 "INVALID IPv4 Network [%s]",
1393 hv = ntohl(nv.s_addr);
1403 SWRAP_LOG(SWRAP_LOG_ERROR,
1404 "INVALID IPv4 Network [%s][0x%x] should be "
1405 "127.0.0.0 or 10.53.57.0",
1406 net_str, (unsigned)hv);
1414 * This returns 127.255.255.255 or 10.255.255.255
1416 static in_addr_t swrap_ipv4_bcast(void)
1420 hv = swrap_ipv4_net();
1421 hv |= IN_CLASSA_HOST;
1427 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1429 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1433 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1434 SWRAP_LOG(SWRAP_LOG_ERROR,
1435 "swrap_ipv4_iface(%u) invalid!",
1441 hv = swrap_ipv4_net();
1451 static const struct in6_addr *swrap_ipv6(void)
1453 static struct in6_addr v;
1454 static int initialized;
1462 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1471 static void set_port(int family, int prt, struct swrap_address *addr)
1475 addr->sa.in.sin_port = htons(prt);
1479 addr->sa.in6.sin6_port = htons(prt);
1485 static size_t socket_length(int family)
1489 return sizeof(struct sockaddr_in);
1492 return sizeof(struct sockaddr_in6);
1498 struct swrap_sockaddr_buf {
1502 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1503 const struct sockaddr *saddr)
1505 unsigned int port = 0;
1506 char addr[64] = {0,};
1508 switch (saddr->sa_family) {
1510 const struct sockaddr_in *in =
1511 (const struct sockaddr_in *)(const void *)saddr;
1513 port = ntohs(in->sin_port);
1515 inet_ntop(saddr->sa_family,
1517 addr, sizeof(addr));
1522 const struct sockaddr_in6 *in6 =
1523 (const struct sockaddr_in6 *)(const void *)saddr;
1525 port = ntohs(in6->sin6_port);
1527 inet_ntop(saddr->sa_family,
1529 addr, sizeof(addr));
1534 snprintf(addr, sizeof(addr),
1535 "<Unknown address family %u>",
1540 snprintf(buf->str, sizeof(buf->str),
1541 "addr[%s]/port[%u]",
1547 static struct socket_info *swrap_get_socket_info(int si_index)
1549 return (struct socket_info *)(&(sockets[si_index].info));
1552 static int swrap_get_refcount(struct socket_info *si)
1554 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1555 return sic->meta.refcount;
1558 static void swrap_inc_refcount(struct socket_info *si)
1560 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1562 sic->meta.refcount += 1;
1565 static void swrap_dec_refcount(struct socket_info *si)
1567 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1569 sic->meta.refcount -= 1;
1572 static int swrap_get_next_free(struct socket_info *si)
1574 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1576 return sic->meta.next_free;
1579 static void swrap_set_next_free(struct socket_info *si, int next_free)
1581 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1583 sic->meta.next_free = next_free;
1586 static int swrap_un_path(struct sockaddr_un *un,
1587 const char *swrap_dir,
1594 ret = snprintf(un->sun_path,
1595 sizeof(un->sun_path),
1601 if ((size_t)ret >= sizeof(un->sun_path)) {
1602 return ENAMETOOLONG;
1608 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1609 const char *swrap_dir)
1613 ret = snprintf(un->sun_path,
1614 sizeof(un->sun_path),
1618 if ((size_t)ret >= sizeof(un->sun_path)) {
1619 return ENAMETOOLONG;
1625 static bool swrap_dir_usable(const char *swrap_dir)
1627 struct sockaddr_un un;
1630 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1635 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1643 static char *socket_wrapper_dir(void)
1645 char *swrap_dir = NULL;
1646 char *s = getenv("SOCKET_WRAPPER_DIR");
1650 if (s == NULL || s[0] == '\0') {
1651 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1655 swrap_dir = realpath(s, NULL);
1656 if (swrap_dir == NULL) {
1657 SWRAP_LOG(SWRAP_LOG_ERROR,
1658 "Unable to resolve socket_wrapper dir path: %s - %s",
1664 ok = swrap_dir_usable(swrap_dir);
1671 ok = swrap_dir_usable(s);
1673 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1677 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1679 SWRAP_LOG(SWRAP_LOG_ERROR,
1680 "realpath(SOCKET_WRAPPER_DIR) too long and "
1681 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1686 swrap_dir = strdup(s);
1687 if (swrap_dir == NULL) {
1688 SWRAP_LOG(SWRAP_LOG_ERROR,
1689 "Unable to duplicate socket_wrapper dir path");
1693 SWRAP_LOG(SWRAP_LOG_WARN,
1694 "realpath(SOCKET_WRAPPER_DIR) too long, "
1695 "using original SOCKET_WRAPPER_DIR\n");
1698 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1702 static unsigned int socket_wrapper_mtu(void)
1704 static unsigned int max_mtu = 0;
1709 swrap_mutex_lock(&mtu_update_mutex);
1715 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1717 s = getenv("SOCKET_WRAPPER_MTU");
1722 tmp = strtol(s, &endp, 10);
1727 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1733 swrap_mutex_unlock(&mtu_update_mutex);
1737 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1739 pthread_mutexattr_t ma;
1740 bool need_destroy = false;
1743 #define __CHECK(cmd) do { \
1746 SWRAP_LOG(SWRAP_LOG_ERROR, \
1747 "%s: %s - failed %d", \
1753 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1754 __CHECK(pthread_mutexattr_init(&ma));
1755 need_destroy = true;
1756 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1757 __CHECK(pthread_mutex_init(m, &ma));
1760 pthread_mutexattr_destroy(&ma);
1765 static size_t socket_wrapper_max_sockets(void)
1771 if (socket_info_max != 0) {
1772 return socket_info_max;
1775 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1777 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1778 if (s == NULL || s[0] == '\0') {
1782 tmp = strtoul(s, &endp, 10);
1787 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1788 SWRAP_LOG(SWRAP_LOG_ERROR,
1789 "Invalid number of sockets specified, "
1790 "using default (%zu)",
1794 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1795 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1796 SWRAP_LOG(SWRAP_LOG_ERROR,
1797 "Invalid number of sockets specified, "
1798 "using maximum (%zu).",
1802 socket_info_max = tmp;
1805 return socket_info_max;
1808 static void socket_wrapper_init_fds_idx(void)
1813 if (socket_fds_idx != NULL) {
1817 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1819 SWRAP_LOG(SWRAP_LOG_ERROR,
1820 "Failed to allocate socket fds index array: %s",
1825 for (i = 0; i < socket_fds_max; i++) {
1829 socket_fds_idx = tmp;
1832 static void socket_wrapper_init_sockets(void)
1838 swrap_bind_symbol_all();
1840 swrap_mutex_lock(&sockets_mutex);
1842 if (sockets != NULL) {
1843 swrap_mutex_unlock(&sockets_mutex);
1847 SWRAP_LOG(SWRAP_LOG_DEBUG,
1848 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1849 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1852 * Intialize the static cache early before
1853 * any thread is able to start.
1855 (void)swrap_ipv4_net();
1857 socket_wrapper_init_fds_idx();
1859 /* Needs to be called inside the sockets_mutex lock here. */
1860 max_sockets = socket_wrapper_max_sockets();
1862 sockets = (struct socket_info_container *)calloc(max_sockets,
1863 sizeof(struct socket_info_container));
1865 if (sockets == NULL) {
1866 SWRAP_LOG(SWRAP_LOG_ERROR,
1867 "Failed to allocate sockets array: %s",
1869 swrap_mutex_unlock(&sockets_mutex);
1873 swrap_mutex_lock(&first_free_mutex);
1874 swrap_mutex_lock(&sockets_si_global);
1878 for (i = 0; i < max_sockets; i++) {
1879 swrap_set_next_free(&sockets[i].info, i+1);
1882 /* mark the end of the free list */
1883 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1885 swrap_mutex_unlock(&sockets_si_global);
1886 swrap_mutex_unlock(&first_free_mutex);
1887 swrap_mutex_unlock(&sockets_mutex);
1893 bool socket_wrapper_enabled(void)
1895 char *s = socket_wrapper_dir();
1903 socket_wrapper_init_sockets();
1908 static unsigned int socket_wrapper_default_iface(void)
1910 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1913 if (sscanf(s, "%u", &iface) == 1) {
1914 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1920 return 1;/* 127.0.0.1 */
1923 static void set_socket_info_index(int fd, int idx)
1925 SWRAP_LOG(SWRAP_LOG_TRACE,
1928 socket_fds_idx[fd] = idx;
1929 /* This builtin issues a full memory barrier. */
1930 __sync_synchronize();
1933 static void reset_socket_info_index(int fd)
1935 SWRAP_LOG(SWRAP_LOG_TRACE,
1938 set_socket_info_index(fd, -1);
1941 static int find_socket_info_index(int fd)
1947 if (socket_fds_idx == NULL) {
1951 if ((size_t)fd >= socket_fds_max) {
1953 * Do not add a log here as some applications do stupid things
1956 * for (fd = 0; fd <= getdtablesize(); fd++) {
1960 * This would produce millions of lines of debug messages.
1963 SWRAP_LOG(SWRAP_LOG_ERROR,
1964 "Looking for a socket info for the fd %d is over the "
1965 "max socket index limit of %zu.",
1972 /* This builtin issues a full memory barrier. */
1973 __sync_synchronize();
1974 return socket_fds_idx[fd];
1977 static int swrap_add_socket_info(const struct socket_info *si_input)
1979 struct socket_info *si = NULL;
1982 if (si_input == NULL) {
1987 swrap_mutex_lock(&first_free_mutex);
1988 if (first_free == -1) {
1993 si_index = first_free;
1994 si = swrap_get_socket_info(si_index);
1998 first_free = swrap_get_next_free(si);
2000 swrap_inc_refcount(si);
2002 SWRAP_UNLOCK_SI(si);
2005 swrap_mutex_unlock(&first_free_mutex);
2010 static int swrap_create_socket(struct socket_info *si, int fd)
2014 if ((size_t)fd >= socket_fds_max) {
2015 SWRAP_LOG(SWRAP_LOG_ERROR,
2016 "The max socket index limit of %zu has been reached, "
2024 idx = swrap_add_socket_info(si);
2029 set_socket_info_index(fd, idx);
2034 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
2041 p = strrchr(un->sun_path, '/');
2042 if (p) p++; else p = un->sun_path;
2044 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
2045 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
2051 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2052 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2059 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2065 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2069 case SOCKET_TYPE_CHAR_TCP:
2070 case SOCKET_TYPE_CHAR_UDP: {
2071 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2073 if ((*len) < sizeof(*in2)) {
2074 SWRAP_LOG(SWRAP_LOG_ERROR,
2075 "V4: *len(%zu) < sizeof(*in2)=%zu",
2076 (size_t)*len, sizeof(*in2));
2081 memset(in2, 0, sizeof(*in2));
2082 in2->sin_family = AF_INET;
2083 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2084 in2->sin_port = htons(prt);
2086 *len = sizeof(*in2);
2090 case SOCKET_TYPE_CHAR_TCP_V6:
2091 case SOCKET_TYPE_CHAR_UDP_V6: {
2092 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2094 if ((*len) < sizeof(*in2)) {
2095 SWRAP_LOG(SWRAP_LOG_ERROR,
2096 "V6: *len(%zu) < sizeof(*in2)=%zu",
2097 (size_t)*len, sizeof(*in2));
2098 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2103 memset(in2, 0, sizeof(*in2));
2104 in2->sin6_family = AF_INET6;
2105 in2->sin6_addr = *swrap_ipv6();
2106 in2->sin6_addr.s6_addr[15] = iface;
2107 in2->sin6_port = htons(prt);
2109 *len = sizeof(*in2);
2114 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2123 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2130 char *swrap_dir = NULL;
2132 if (bcast) *bcast = 0;
2134 switch (inaddr->sa_family) {
2136 const struct sockaddr_in *in =
2137 (const struct sockaddr_in *)(const void *)inaddr;
2138 unsigned int addr = ntohl(in->sin_addr.s_addr);
2142 const unsigned int sw_net_addr = swrap_ipv4_net();
2143 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2147 u_type = SOCKET_TYPE_CHAR_TCP;
2150 u_type = SOCKET_TYPE_CHAR_UDP;
2151 a_type = SOCKET_TYPE_CHAR_UDP;
2152 b_type = SOCKET_TYPE_CHAR_UDP;
2155 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2156 errno = ESOCKTNOSUPPORT;
2160 prt = ntohs(in->sin_port);
2161 if (a_type && addr == 0xFFFFFFFF) {
2162 /* 255.255.255.255 only udp */
2165 iface = socket_wrapper_default_iface();
2166 } else if (b_type && addr == sw_bcast_addr) {
2175 iface = socket_wrapper_default_iface();
2176 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2177 /* 127.0.0.X or 10.53.57.X */
2180 iface = (addr & 0x000000FF);
2182 struct swrap_sockaddr_buf buf = {};
2183 SWRAP_LOG(SWRAP_LOG_WARN,
2185 swrap_sockaddr_string(&buf, inaddr));
2186 errno = ENETUNREACH;
2189 if (bcast) *bcast = is_bcast;
2194 const struct sockaddr_in6 *in =
2195 (const struct sockaddr_in6 *)(const void *)inaddr;
2196 struct in6_addr cmp1, cmp2;
2200 type = SOCKET_TYPE_CHAR_TCP_V6;
2203 type = SOCKET_TYPE_CHAR_UDP_V6;
2206 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2207 errno = ESOCKTNOSUPPORT;
2211 /* XXX no multicast/broadcast */
2213 prt = ntohs(in->sin6_port);
2215 cmp1 = *swrap_ipv6();
2216 cmp2 = in->sin6_addr;
2217 cmp2.s6_addr[15] = 0;
2218 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2219 iface = in->sin6_addr.s6_addr[15];
2221 struct swrap_sockaddr_buf buf = {};
2222 SWRAP_LOG(SWRAP_LOG_WARN,
2224 swrap_sockaddr_string(&buf, inaddr));
2225 errno = ENETUNREACH;
2233 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2234 errno = ENETUNREACH;
2239 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2244 swrap_dir = socket_wrapper_dir();
2245 if (swrap_dir == NULL) {
2251 swrap_un_path_EINVAL(un, swrap_dir);
2252 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2253 SAFE_FREE(swrap_dir);
2254 /* the caller need to do more processing */
2258 swrap_un_path(un, swrap_dir, type, iface, prt);
2259 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2261 SAFE_FREE(swrap_dir);
2266 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2274 char *swrap_dir = NULL;
2276 if (bcast) *bcast = 0;
2278 switch (si->family) {
2280 const struct sockaddr_in *in =
2281 (const struct sockaddr_in *)(const void *)inaddr;
2282 unsigned int addr = ntohl(in->sin_addr.s_addr);
2287 const unsigned int sw_net_addr = swrap_ipv4_net();
2288 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2290 prt = ntohs(in->sin_port);
2294 u_type = SOCKET_TYPE_CHAR_TCP;
2295 d_type = SOCKET_TYPE_CHAR_TCP;
2298 u_type = SOCKET_TYPE_CHAR_UDP;
2299 d_type = SOCKET_TYPE_CHAR_UDP;
2300 a_type = SOCKET_TYPE_CHAR_UDP;
2301 b_type = SOCKET_TYPE_CHAR_UDP;
2304 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2305 errno = ESOCKTNOSUPPORT;
2313 iface = socket_wrapper_default_iface();
2314 } else if (a_type && addr == 0xFFFFFFFF) {
2315 /* 255.255.255.255 only udp */
2318 iface = socket_wrapper_default_iface();
2319 } else if (b_type && addr == sw_bcast_addr) {
2320 /* 127.255.255.255 only udp */
2323 iface = socket_wrapper_default_iface();
2324 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2328 iface = (addr & 0x000000FF);
2330 errno = EADDRNOTAVAIL;
2334 /* Store the bind address for connect() */
2335 if (si->bindname.sa_socklen == 0) {
2336 struct sockaddr_in bind_in;
2337 socklen_t blen = sizeof(struct sockaddr_in);
2339 ZERO_STRUCT(bind_in);
2340 bind_in.sin_family = in->sin_family;
2341 bind_in.sin_port = in->sin_port;
2342 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2343 si->bindname.sa_socklen = blen;
2344 memcpy(&si->bindname.sa.in, &bind_in, blen);
2351 const struct sockaddr_in6 *in =
2352 (const struct sockaddr_in6 *)(const void *)inaddr;
2353 struct in6_addr cmp1, cmp2;
2357 type = SOCKET_TYPE_CHAR_TCP_V6;
2360 type = SOCKET_TYPE_CHAR_UDP_V6;
2363 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2364 errno = ESOCKTNOSUPPORT;
2368 /* XXX no multicast/broadcast */
2370 prt = ntohs(in->sin6_port);
2372 cmp1 = *swrap_ipv6();
2373 cmp2 = in->sin6_addr;
2374 cmp2.s6_addr[15] = 0;
2375 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2376 iface = socket_wrapper_default_iface();
2377 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2378 iface = in->sin6_addr.s6_addr[15];
2380 errno = EADDRNOTAVAIL;
2384 /* Store the bind address for connect() */
2385 if (si->bindname.sa_socklen == 0) {
2386 struct sockaddr_in6 bind_in;
2387 socklen_t blen = sizeof(struct sockaddr_in6);
2389 ZERO_STRUCT(bind_in);
2390 bind_in.sin6_family = in->sin6_family;
2391 bind_in.sin6_port = in->sin6_port;
2393 bind_in.sin6_addr = *swrap_ipv6();
2394 bind_in.sin6_addr.s6_addr[15] = iface;
2396 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2397 si->bindname.sa_socklen = blen;
2404 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2405 errno = EADDRNOTAVAIL;
2410 if (bcast) *bcast = is_bcast;
2412 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2417 swrap_dir = socket_wrapper_dir();
2418 if (swrap_dir == NULL) {
2424 /* handle auto-allocation of ephemeral ports */
2425 for (prt = 5001; prt < 10000; prt++) {
2426 swrap_un_path(un, swrap_dir, type, iface, prt);
2427 if (stat(un->sun_path, &st) == 0) continue;
2429 set_port(si->family, prt, &si->myname);
2430 set_port(si->family, prt, &si->bindname);
2437 SAFE_FREE(swrap_dir);
2442 swrap_un_path(un, swrap_dir, type, iface, prt);
2443 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2445 SAFE_FREE(swrap_dir);
2450 static struct socket_info *find_socket_info(int fd)
2452 int idx = find_socket_info_index(fd);
2458 return swrap_get_socket_info(idx);
2462 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2464 struct socket_info_fd *f;
2465 const struct socket_info *last_s = NULL;
2467 /* first catch invalid input */
2468 switch (sa->sa_family) {
2470 if (len < sizeof(struct sockaddr_in)) {
2476 if (len < sizeof(struct sockaddr_in6)) {
2486 for (f = socket_fds; f; f = f->next) {
2487 struct socket_info *s = swrap_get_socket_info(f->si_index);
2494 if (s->myname == NULL) {
2497 if (s->myname->sa_family != sa->sa_family) {
2500 switch (s->myname->sa_family) {
2502 struct sockaddr_in *sin1, *sin2;
2504 sin1 = (struct sockaddr_in *)s->myname;
2505 sin2 = (struct sockaddr_in *)sa;
2507 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2510 if (sin1->sin_port != sin2->sin_port) {
2513 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2523 struct sockaddr_in6 *sin1, *sin2;
2525 sin1 = (struct sockaddr_in6 *)s->myname;
2526 sin2 = (struct sockaddr_in6 *)sa;
2528 if (sin1->sin6_port != sin2->sin6_port) {
2531 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2553 static void swrap_remove_stale(int fd);
2555 static int sockaddr_convert_to_un(struct socket_info *si,
2556 const struct sockaddr *in_addr,
2558 struct sockaddr_un *out_addr,
2562 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2564 (void) in_len; /* unused */
2566 if (out_addr == NULL) {
2570 out->sa_family = AF_UNIX;
2571 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2572 out->sa_len = sizeof(*out_addr);
2575 switch (in_addr->sa_family) {
2577 const struct sockaddr_in *sin;
2578 if (si->family != AF_INET) {
2581 if (in_len < sizeof(struct sockaddr_in)) {
2584 sin = (const struct sockaddr_in *)(const void *)in_addr;
2585 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2590 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2591 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2605 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2606 errno = ESOCKTNOSUPPORT;
2610 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2612 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2618 errno = EAFNOSUPPORT;
2619 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2623 static int sockaddr_convert_from_un(const struct socket_info *si,
2624 const struct sockaddr_un *in_addr,
2625 socklen_t un_addrlen,
2627 struct sockaddr *out_addr,
2628 socklen_t *out_addrlen)
2632 if (out_addr == NULL || out_addrlen == NULL)
2635 if (un_addrlen == 0) {
2650 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2651 errno = ESOCKTNOSUPPORT;
2654 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2655 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2656 out_addr->sa_len = *out_addrlen;
2663 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2664 errno = EAFNOSUPPORT;
2668 enum swrap_packet_type {
2670 SWRAP_CONNECT_UNREACH,
2678 SWRAP_SENDTO_UNREACH,
2689 struct swrap_file_hdr {
2691 uint16_t version_major;
2692 uint16_t version_minor;
2695 uint32_t frame_max_len;
2696 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2699 #define SWRAP_FILE_HDR_SIZE 24
2701 struct swrap_packet_frame {
2703 uint32_t micro_seconds;
2704 uint32_t recorded_length;
2705 uint32_t full_length;
2707 #define SWRAP_PACKET_FRAME_SIZE 16
2709 union swrap_packet_ip {
2713 uint16_t packet_length;
2714 uint16_t identification;
2719 uint16_t hdr_checksum;
2723 #define SWRAP_PACKET_IP_V4_SIZE 20
2726 uint8_t flow_label_high;
2727 uint16_t flow_label_low;
2728 uint16_t payload_length;
2729 uint8_t next_header;
2731 uint8_t src_addr[16];
2732 uint8_t dest_addr[16];
2734 #define SWRAP_PACKET_IP_V6_SIZE 40
2736 #define SWRAP_PACKET_IP_SIZE 40
2738 union swrap_packet_payload {
2740 uint16_t source_port;
2750 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2752 uint16_t source_port;
2757 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2764 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2771 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2773 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2775 #define SWRAP_PACKET_MIN_ALLOC \
2776 (SWRAP_PACKET_FRAME_SIZE + \
2777 SWRAP_PACKET_IP_SIZE + \
2778 SWRAP_PACKET_PAYLOAD_SIZE)
2780 static const char *swrap_pcap_init_file(void)
2782 static int initialized = 0;
2783 static const char *s = NULL;
2784 static const struct swrap_file_hdr h;
2785 static const struct swrap_packet_frame f;
2786 static const union swrap_packet_ip i;
2787 static const union swrap_packet_payload p;
2789 if (initialized == 1) {
2795 * TODO: don't use the structs use plain buffer offsets
2796 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2798 * for now make sure we disable PCAP support
2799 * if the struct has alignment!
2801 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2804 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2807 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2810 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2813 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2816 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2819 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2822 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2825 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2828 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2832 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2836 if (strncmp(s, "./", 2) == 0) {
2839 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2843 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2844 const struct sockaddr *src,
2845 const struct sockaddr *dest,
2847 const uint8_t *payload,
2849 unsigned long tcp_seqno,
2850 unsigned long tcp_ack,
2851 unsigned char tcp_ctl,
2853 size_t *_packet_len)
2855 uint8_t *base = NULL;
2856 uint8_t *buf = NULL;
2859 struct swrap_packet_frame *frame;
2863 union swrap_packet_ip *ip;
2865 union swrap_packet_payload *pay;
2868 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2869 size_t wire_hdr_len = 0;
2870 size_t wire_len = 0;
2871 size_t ip_hdr_len = 0;
2872 size_t icmp_hdr_len = 0;
2873 size_t icmp_truncate_len = 0;
2874 uint8_t protocol = 0, icmp_protocol = 0;
2875 const struct sockaddr_in *src_in = NULL;
2876 const struct sockaddr_in *dest_in = NULL;
2878 const struct sockaddr_in6 *src_in6 = NULL;
2879 const struct sockaddr_in6 *dest_in6 = NULL;
2884 switch (src->sa_family) {
2886 src_in = (const struct sockaddr_in *)(const void *)src;
2887 dest_in = (const struct sockaddr_in *)(const void *)dest;
2888 src_port = src_in->sin_port;
2889 dest_port = dest_in->sin_port;
2890 ip_hdr_len = sizeof(i.ip->v4);
2894 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2895 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2896 src_port = src_in6->sin6_port;
2897 dest_port = dest_in6->sin6_port;
2898 ip_hdr_len = sizeof(i.ip->v6);
2905 switch (socket_type) {
2907 protocol = 0x06; /* TCP */
2908 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2909 wire_len = wire_hdr_len + payload_len;
2913 protocol = 0x11; /* UDP */
2914 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2915 wire_len = wire_hdr_len + payload_len;
2923 icmp_protocol = protocol;
2924 switch (src->sa_family) {
2926 protocol = 0x01; /* ICMPv4 */
2927 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2931 protocol = 0x3A; /* ICMPv6 */
2932 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2936 if (wire_len > 64 ) {
2937 icmp_truncate_len = wire_len - 64;
2939 wire_len += icmp_hdr_len;
2942 packet_len = nonwire_len + wire_len;
2943 alloc_len = packet_len;
2944 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2945 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2948 base = (uint8_t *)calloc(1, alloc_len);
2956 f.frame->seconds = tval->tv_sec;
2957 f.frame->micro_seconds = tval->tv_usec;
2958 f.frame->recorded_length = wire_len - icmp_truncate_len;
2959 f.frame->full_length = wire_len - icmp_truncate_len;
2961 buf += SWRAP_PACKET_FRAME_SIZE;
2964 switch (src->sa_family) {
2966 if (src_in == NULL || dest_in == NULL) {
2971 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2972 i.ip->v4.tos = 0x00;
2973 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2974 i.ip->v4.identification = htons(0xFFFF);
2975 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2976 i.ip->v4.fragment = htons(0x0000);
2977 i.ip->v4.ttl = 0xFF;
2978 i.ip->v4.protocol = protocol;
2979 i.ip->v4.hdr_checksum = htons(0x0000);
2980 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2981 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2982 buf += SWRAP_PACKET_IP_V4_SIZE;
2986 if (src_in6 == NULL || dest_in6 == NULL) {
2991 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2992 i.ip->v6.flow_label_high = 0x00;
2993 i.ip->v6.flow_label_low = 0x0000;
2994 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2995 i.ip->v6.next_header = protocol;
2996 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2997 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2998 buf += SWRAP_PACKET_IP_V6_SIZE;
3004 pay = (union swrap_packet_payload *)(void *)buf;
3005 switch (src->sa_family) {
3007 pay->icmp4.type = 0x03; /* destination unreachable */
3008 pay->icmp4.code = 0x01; /* host unreachable */
3009 pay->icmp4.checksum = htons(0x0000);
3010 pay->icmp4.unused = htonl(0x00000000);
3012 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
3014 /* set the ip header in the ICMP payload */
3016 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
3017 i.ip->v4.tos = 0x00;
3018 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
3019 i.ip->v4.identification = htons(0xFFFF);
3020 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
3021 i.ip->v4.fragment = htons(0x0000);
3022 i.ip->v4.ttl = 0xFF;
3023 i.ip->v4.protocol = icmp_protocol;
3024 i.ip->v4.hdr_checksum = htons(0x0000);
3025 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
3026 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
3028 buf += SWRAP_PACKET_IP_V4_SIZE;
3030 src_port = dest_in->sin_port;
3031 dest_port = src_in->sin_port;
3035 pay->icmp6.type = 0x01; /* destination unreachable */
3036 pay->icmp6.code = 0x03; /* address unreachable */
3037 pay->icmp6.checksum = htons(0x0000);
3038 pay->icmp6.unused = htonl(0x00000000);
3039 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
3041 /* set the ip header in the ICMP payload */
3043 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
3044 i.ip->v6.flow_label_high = 0x00;
3045 i.ip->v6.flow_label_low = 0x0000;
3046 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
3047 i.ip->v6.next_header = protocol;
3048 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
3049 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
3051 buf += SWRAP_PACKET_IP_V6_SIZE;
3053 src_port = dest_in6->sin6_port;
3054 dest_port = src_in6->sin6_port;
3060 pay = (union swrap_packet_payload *)(void *)buf;
3062 switch (socket_type) {
3064 pay->tcp.source_port = src_port;
3065 pay->tcp.dest_port = dest_port;
3066 pay->tcp.seq_num = htonl(tcp_seqno);
3067 pay->tcp.ack_num = htonl(tcp_ack);
3068 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3069 pay->tcp.control = tcp_ctl;
3070 pay->tcp.window = htons(0x7FFF);
3071 pay->tcp.checksum = htons(0x0000);
3072 pay->tcp.urg = htons(0x0000);
3073 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3078 pay->udp.source_port = src_port;
3079 pay->udp.dest_port = dest_port;
3080 pay->udp.length = htons(8 + payload_len);
3081 pay->udp.checksum = htons(0x0000);
3082 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3087 if (payload && payload_len > 0) {
3088 memcpy(buf, payload, payload_len);
3091 *_packet_len = packet_len - icmp_truncate_len;
3095 static int swrap_pcap_get_fd(const char *fname)
3103 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3105 struct swrap_file_hdr file_hdr;
3106 file_hdr.magic = 0xA1B2C3D4;
3107 file_hdr.version_major = 0x0002;
3108 file_hdr.version_minor = 0x0004;
3109 file_hdr.timezone = 0x00000000;
3110 file_hdr.sigfigs = 0x00000000;
3111 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3112 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3114 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3121 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3126 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3127 const struct sockaddr *addr,
3128 enum swrap_packet_type type,
3129 const void *buf, size_t len,
3132 const struct sockaddr *src_addr;
3133 const struct sockaddr *dest_addr;
3134 unsigned long tcp_seqno = 0;
3135 unsigned long tcp_ack = 0;
3136 unsigned char tcp_ctl = 0;
3137 int unreachable = 0;
3141 switch (si->family) {
3153 case SWRAP_CONNECT_SEND:
3154 if (si->type != SOCK_STREAM) {
3158 src_addr = &si->myname.sa.s;
3161 tcp_seqno = si->io.pck_snd;
3162 tcp_ack = si->io.pck_rcv;
3163 tcp_ctl = 0x02; /* SYN */
3165 si->io.pck_snd += 1;
3169 case SWRAP_CONNECT_RECV:
3170 if (si->type != SOCK_STREAM) {
3174 dest_addr = &si->myname.sa.s;
3177 tcp_seqno = si->io.pck_rcv;
3178 tcp_ack = si->io.pck_snd;
3179 tcp_ctl = 0x12; /** SYN,ACK */
3181 si->io.pck_rcv += 1;
3185 case SWRAP_CONNECT_UNREACH:
3186 if (si->type != SOCK_STREAM) {
3190 dest_addr = &si->myname.sa.s;
3193 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3194 tcp_seqno = si->io.pck_snd - 1;
3195 tcp_ack = si->io.pck_rcv;
3196 tcp_ctl = 0x02; /* SYN */
3201 case SWRAP_CONNECT_ACK:
3202 if (si->type != SOCK_STREAM) {
3206 src_addr = &si->myname.sa.s;
3209 tcp_seqno = si->io.pck_snd;
3210 tcp_ack = si->io.pck_rcv;
3211 tcp_ctl = 0x10; /* ACK */
3215 case SWRAP_ACCEPT_SEND:
3216 if (si->type != SOCK_STREAM) {
3220 dest_addr = &si->myname.sa.s;
3223 tcp_seqno = si->io.pck_rcv;
3224 tcp_ack = si->io.pck_snd;
3225 tcp_ctl = 0x02; /* SYN */
3227 si->io.pck_rcv += 1;
3231 case SWRAP_ACCEPT_RECV:
3232 if (si->type != SOCK_STREAM) {
3236 src_addr = &si->myname.sa.s;
3239 tcp_seqno = si->io.pck_snd;
3240 tcp_ack = si->io.pck_rcv;
3241 tcp_ctl = 0x12; /* SYN,ACK */
3243 si->io.pck_snd += 1;
3247 case SWRAP_ACCEPT_ACK:
3248 if (si->type != SOCK_STREAM) {
3252 dest_addr = &si->myname.sa.s;
3255 tcp_seqno = si->io.pck_rcv;
3256 tcp_ack = si->io.pck_snd;
3257 tcp_ctl = 0x10; /* ACK */
3262 src_addr = &si->myname.sa.s;
3263 dest_addr = &si->peername.sa.s;
3265 tcp_seqno = si->io.pck_snd;
3266 tcp_ack = si->io.pck_rcv;
3267 tcp_ctl = 0x18; /* PSH,ACK */
3269 si->io.pck_snd += len;
3273 case SWRAP_SEND_RST:
3274 dest_addr = &si->myname.sa.s;
3275 src_addr = &si->peername.sa.s;
3277 if (si->type == SOCK_DGRAM) {
3278 return swrap_pcap_marshall_packet(si,
3280 SWRAP_SENDTO_UNREACH,
3286 tcp_seqno = si->io.pck_rcv;
3287 tcp_ack = si->io.pck_snd;
3288 tcp_ctl = 0x14; /** RST,ACK */
3292 case SWRAP_PENDING_RST:
3293 dest_addr = &si->myname.sa.s;
3294 src_addr = &si->peername.sa.s;
3296 if (si->type == SOCK_DGRAM) {
3300 tcp_seqno = si->io.pck_rcv;
3301 tcp_ack = si->io.pck_snd;
3302 tcp_ctl = 0x14; /* RST,ACK */
3307 dest_addr = &si->myname.sa.s;
3308 src_addr = &si->peername.sa.s;
3310 tcp_seqno = si->io.pck_rcv;
3311 tcp_ack = si->io.pck_snd;
3312 tcp_ctl = 0x18; /* PSH,ACK */
3314 si->io.pck_rcv += len;
3318 case SWRAP_RECV_RST:
3319 dest_addr = &si->myname.sa.s;
3320 src_addr = &si->peername.sa.s;
3322 if (si->type == SOCK_DGRAM) {
3326 tcp_seqno = si->io.pck_rcv;
3327 tcp_ack = si->io.pck_snd;
3328 tcp_ctl = 0x14; /* RST,ACK */
3333 src_addr = &si->myname.sa.s;
3336 si->io.pck_snd += len;
3340 case SWRAP_SENDTO_UNREACH:
3341 dest_addr = &si->myname.sa.s;
3348 case SWRAP_RECVFROM:
3349 dest_addr = &si->myname.sa.s;
3352 si->io.pck_rcv += len;
3356 case SWRAP_CLOSE_SEND:
3357 if (si->type != SOCK_STREAM) {
3361 src_addr = &si->myname.sa.s;
3362 dest_addr = &si->peername.sa.s;
3364 tcp_seqno = si->io.pck_snd;
3365 tcp_ack = si->io.pck_rcv;
3366 tcp_ctl = 0x11; /* FIN, ACK */
3368 si->io.pck_snd += 1;
3372 case SWRAP_CLOSE_RECV:
3373 if (si->type != SOCK_STREAM) {
3377 dest_addr = &si->myname.sa.s;
3378 src_addr = &si->peername.sa.s;
3380 tcp_seqno = si->io.pck_rcv;
3381 tcp_ack = si->io.pck_snd;
3382 tcp_ctl = 0x11; /* FIN,ACK */
3384 si->io.pck_rcv += 1;
3388 case SWRAP_CLOSE_ACK:
3389 if (si->type != SOCK_STREAM) {
3393 src_addr = &si->myname.sa.s;
3394 dest_addr = &si->peername.sa.s;
3396 tcp_seqno = si->io.pck_snd;
3397 tcp_ack = si->io.pck_rcv;
3398 tcp_ctl = 0x10; /* ACK */
3405 swrapGetTimeOfDay(&tv);
3407 return swrap_pcap_packet_init(&tv,
3411 (const uint8_t *)buf,
3420 static void swrap_pcap_dump_packet(struct socket_info *si,
3421 const struct sockaddr *addr,
3422 enum swrap_packet_type type,
3423 const void *buf, size_t len)
3425 const char *file_name;
3427 size_t packet_len = 0;
3430 swrap_mutex_lock(&pcap_dump_mutex);
3432 file_name = swrap_pcap_init_file();
3437 packet = swrap_pcap_marshall_packet(si,
3443 if (packet == NULL) {
3447 fd = swrap_pcap_get_fd(file_name);
3449 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3458 swrap_mutex_unlock(&pcap_dump_mutex);
3461 /****************************************************************************
3463 ***************************************************************************/
3465 #ifdef HAVE_SIGNALFD
3466 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3470 rc = libc_signalfd(fd, mask, flags);
3472 swrap_remove_stale(fd);
3478 int signalfd(int fd, const sigset_t *mask, int flags)
3480 return swrap_signalfd(fd, mask, flags);
3484 /****************************************************************************
3486 ***************************************************************************/
3488 static int swrap_socket(int family, int type, int protocol)
3490 struct socket_info *si = NULL;
3491 struct socket_info _si = { 0 };
3494 int real_type = type;
3497 * Remove possible addition flags passed to socket() so
3498 * do not fail checking the type.
3499 * See https://lwn.net/Articles/281965/
3502 real_type &= ~SOCK_CLOEXEC;
3504 #ifdef SOCK_NONBLOCK
3505 real_type &= ~SOCK_NONBLOCK;
3508 if (!socket_wrapper_enabled()) {
3509 return libc_socket(family, type, protocol);
3520 #endif /* AF_NETLINK */
3523 #endif /* AF_PACKET */
3525 fd = libc_socket(family, type, protocol);
3527 /* Check if we have a stale fd and remove it */
3528 swrap_remove_stale(fd);
3529 SWRAP_LOG(SWRAP_LOG_TRACE,
3530 "Unix socket fd=%d",
3535 errno = EAFNOSUPPORT;
3539 switch (real_type) {
3545 errno = EPROTONOSUPPORT;
3553 if (real_type == SOCK_STREAM) {
3558 if (real_type == SOCK_DGRAM) {
3563 errno = EPROTONOSUPPORT;
3568 * We must call libc_socket with type, from the caller, not the version
3569 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3571 fd = libc_socket(AF_UNIX, type, 0);
3577 /* Check if we have a stale fd and remove it */
3578 swrap_remove_stale(fd);
3581 si->family = family;
3583 /* however, the rest of the socket_wrapper code expects just
3584 * the type, not the flags */
3585 si->type = real_type;
3586 si->protocol = protocol;
3589 * Setup myname so getsockname() can succeed to find out the socket
3592 switch(si->family) {
3594 struct sockaddr_in sin = {
3595 .sin_family = AF_INET,
3598 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3599 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3604 struct sockaddr_in6 sin6 = {
3605 .sin6_family = AF_INET6,
3608 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3609 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3618 ret = swrap_create_socket(si, fd);
3620 int saved_errno = errno;
3622 errno = saved_errno;
3626 SWRAP_LOG(SWRAP_LOG_TRACE,
3627 "Created %s socket for protocol %s, fd=%d",
3628 family == AF_INET ? "IPv4" : "IPv6",
3629 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3635 int socket(int family, int type, int protocol)
3637 return swrap_socket(family, type, protocol);
3640 /****************************************************************************
3642 ***************************************************************************/
3644 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3648 rc = libc_socketpair(family, type, protocol, sv);
3650 swrap_remove_stale(sv[0]);
3651 swrap_remove_stale(sv[1]);
3657 int socketpair(int family, int type, int protocol, int sv[2])
3659 return swrap_socketpair(family, type, protocol, sv);
3662 /****************************************************************************
3664 ***************************************************************************/
3666 #ifdef HAVE_TIMERFD_CREATE
3667 static int swrap_timerfd_create(int clockid, int flags)
3671 fd = libc_timerfd_create(clockid, flags);
3673 swrap_remove_stale(fd);
3679 int timerfd_create(int clockid, int flags)
3681 return swrap_timerfd_create(clockid, flags);
3685 /****************************************************************************
3687 ***************************************************************************/
3689 static int swrap_pipe(int pipefd[2])
3693 rc = libc_pipe(pipefd);
3695 swrap_remove_stale(pipefd[0]);
3696 swrap_remove_stale(pipefd[1]);
3702 int pipe(int pipefd[2])
3704 return swrap_pipe(pipefd);
3707 /****************************************************************************
3709 ***************************************************************************/
3711 static int swrap_accept(int s,
3712 struct sockaddr *addr,
3716 struct socket_info *parent_si, *child_si;
3717 struct socket_info new_si = { 0 };
3720 struct swrap_address un_addr = {
3721 .sa_socklen = sizeof(struct sockaddr_un),
3723 struct swrap_address un_my_addr = {
3724 .sa_socklen = sizeof(struct sockaddr_un),
3726 struct swrap_address in_addr = {
3727 .sa_socklen = sizeof(struct sockaddr_storage),
3729 struct swrap_address in_my_addr = {
3730 .sa_socklen = sizeof(struct sockaddr_storage),
3734 parent_si = find_socket_info(s);
3737 return libc_accept4(s, addr, addrlen, flags);
3740 return libc_accept(s, addr, addrlen);
3746 * prevent parent_si from being altered / closed
3749 SWRAP_LOCK_SI(parent_si);
3752 * assume out sockaddr have the same size as the in parent
3755 in_addr.sa_socklen = socket_length(parent_si->family);
3756 if (in_addr.sa_socklen <= 0) {
3757 SWRAP_UNLOCK_SI(parent_si);
3762 SWRAP_UNLOCK_SI(parent_si);
3765 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3768 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3771 int saved_errno = errno;
3772 if (saved_errno == ENOTSOCK) {
3773 /* Remove stale fds */
3774 swrap_remove_stale(s);
3776 errno = saved_errno;
3782 /* Check if we have a stale fd and remove it */
3783 swrap_remove_stale(fd);
3785 if (un_addr.sa.un.sun_path[0] == '\0') {
3787 * FreeBSD seems to have a problem where
3788 * accept4() on the unix socket doesn't
3789 * ECONNABORTED for already disconnected connections.
3791 * Let's try libc_getpeername() to get the peer address
3792 * as a fallback, but it'll likely return ENOTCONN,
3793 * which we have to map to ECONNABORTED.
3795 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3796 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3798 int saved_errno = errno;
3800 if (saved_errno == ENOTCONN) {
3802 * If the connection is already disconnected
3803 * we should return ECONNABORTED.
3805 saved_errno = ECONNABORTED;
3807 errno = saved_errno;
3812 ret = libc_getsockname(fd,
3814 &un_my_addr.sa_socklen);
3816 int saved_errno = errno;
3818 if (saved_errno == ENOTCONN) {
3820 * If the connection is already disconnected
3821 * we should return ECONNABORTED.
3823 saved_errno = ECONNABORTED;
3825 errno = saved_errno;
3829 SWRAP_LOCK_SI(parent_si);
3831 ret = sockaddr_convert_from_un(parent_si,
3836 &in_addr.sa_socklen);
3838 int saved_errno = errno;
3839 SWRAP_UNLOCK_SI(parent_si);
3841 errno = saved_errno;
3847 child_si->family = parent_si->family;
3848 child_si->type = parent_si->type;
3849 child_si->protocol = parent_si->protocol;
3850 child_si->bound = 1;
3851 child_si->is_server = 1;
3852 child_si->connected = 1;
3854 SWRAP_UNLOCK_SI(parent_si);
3856 child_si->peername = (struct swrap_address) {
3857 .sa_socklen = in_addr.sa_socklen,
3859 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3861 if (addr != NULL && addrlen != NULL) {
3862 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3864 memcpy(addr, &in_addr.sa.ss, copy_len);
3866 *addrlen = in_addr.sa_socklen;
3869 ret = sockaddr_convert_from_un(child_si,
3871 un_my_addr.sa_socklen,
3874 &in_my_addr.sa_socklen);
3876 int saved_errno = errno;
3878 errno = saved_errno;
3882 SWRAP_LOG(SWRAP_LOG_TRACE,
3883 "accept() path=%s, fd=%d",
3884 un_my_addr.sa.un.sun_path, s);
3886 child_si->myname = (struct swrap_address) {
3887 .sa_socklen = in_my_addr.sa_socklen,
3889 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3891 idx = swrap_create_socket(&new_si, fd);
3893 int saved_errno = errno;
3895 errno = saved_errno;
3900 struct socket_info *si = swrap_get_socket_info(idx);
3903 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3904 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3905 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3906 SWRAP_UNLOCK_SI(si);
3913 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3915 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3919 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3920 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3922 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3925 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3928 static int autobind_start_init;
3929 static int autobind_start;
3931 /* using sendto() or connect() on an unbound socket would give the
3932 recipient no way to reply, as unlike UDP and TCP, a unix domain
3933 socket can't auto-assign ephemeral port numbers, so we need to
3935 Note: this might change the family from ipv6 to ipv4
3937 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3939 struct swrap_address un_addr = {
3940 .sa_socklen = sizeof(struct sockaddr_un),
3946 char *swrap_dir = NULL;
3948 swrap_mutex_lock(&autobind_start_mutex);
3950 if (autobind_start_init != 1) {
3951 autobind_start_init = 1;
3952 autobind_start = getpid();
3953 autobind_start %= 50000;
3954 autobind_start += 10000;
3957 un_addr.sa.un.sun_family = AF_UNIX;
3961 struct sockaddr_in in;
3965 type = SOCKET_TYPE_CHAR_TCP;
3968 type = SOCKET_TYPE_CHAR_UDP;
3971 errno = ESOCKTNOSUPPORT;
3976 memset(&in, 0, sizeof(in));
3977 in.sin_family = AF_INET;
3978 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3979 socket_wrapper_default_iface()));
3981 si->myname = (struct swrap_address) {
3982 .sa_socklen = sizeof(in),
3984 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3989 struct sockaddr_in6 in6;
3991 if (si->family != family) {
3992 errno = ENETUNREACH;
3999 type = SOCKET_TYPE_CHAR_TCP_V6;
4002 type = SOCKET_TYPE_CHAR_UDP_V6;
4005 errno = ESOCKTNOSUPPORT;
4010 memset(&in6, 0, sizeof(in6));
4011 in6.sin6_family = AF_INET6;
4012 in6.sin6_addr = *swrap_ipv6();
4013 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
4015 si->myname = (struct swrap_address) {
4016 .sa_socklen = sizeof(in6),
4018 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
4023 errno = ESOCKTNOSUPPORT;
4028 if (autobind_start > 60000) {
4029 autobind_start = 10000;
4032 swrap_dir = socket_wrapper_dir();
4033 if (swrap_dir == NULL) {
4039 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
4040 port = autobind_start + i;
4041 swrap_un_path(&un_addr.sa.un,
4044 socket_wrapper_default_iface(),
4047 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
4049 if (errno == EALREADY || errno == EADDRINUSE) {
4055 si->un_addr = un_addr.sa.un;
4058 autobind_start = port + 1;
4061 if (i == SOCKET_MAX_SOCKETS) {
4062 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
4063 "interface "SOCKET_FORMAT,
4066 socket_wrapper_default_iface(),
4073 si->family = family;
4074 set_port(si->family, port, &si->myname);
4079 SAFE_FREE(swrap_dir);
4080 swrap_mutex_unlock(&autobind_start_mutex);
4084 /****************************************************************************
4086 ***************************************************************************/
4088 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4092 struct swrap_address un_addr = {
4093 .sa_socklen = sizeof(struct sockaddr_un),
4095 struct socket_info *si = find_socket_info(s);
4096 struct swrap_sockaddr_buf buf = {};
4100 return libc_connect(s, serv_addr, addrlen);
4105 if (si->bound == 0) {
4106 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4112 if (si->family != serv_addr->sa_family) {
4113 SWRAP_LOG(SWRAP_LOG_ERROR,
4114 "called for fd=%d (family=%d) called with invalid family=%d",
4115 s, si->family, serv_addr->sa_family);
4121 ret = sockaddr_convert_to_un(si, serv_addr,
4122 addrlen, &un_addr.sa.un, 0, &bcast);
4128 errno = ENETUNREACH;
4133 if (si->type == SOCK_DGRAM) {
4134 si->defer_connect = 1;
4137 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4139 ret = libc_connect(s,
4141 un_addr.sa_socklen);
4144 SWRAP_LOG(SWRAP_LOG_TRACE,
4145 "connect(%s) path=%s, fd=%d",
4146 swrap_sockaddr_string(&buf, serv_addr),
4147 un_addr.sa.un.sun_path, s);
4150 /* to give better errors */
4151 if (ret == -1 && errno == ENOENT) {
4152 errno = EHOSTUNREACH;
4156 si->peername = (struct swrap_address) {
4157 .sa_socklen = addrlen,
4160 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4164 * When we connect() on a socket than we have to bind the
4165 * outgoing connection on the interface we use for the
4166 * transport. We already bound it on the right interface
4167 * but here we have to update the name so getsockname()
4168 * returns correct information.
4170 if (si->bindname.sa_socklen > 0) {
4171 si->myname = (struct swrap_address) {
4172 .sa_socklen = si->bindname.sa_socklen,
4175 memcpy(&si->myname.sa.ss,
4176 &si->bindname.sa.ss,
4177 si->bindname.sa_socklen);
4179 /* Cleanup bindname */
4180 si->bindname = (struct swrap_address) {
4185 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4186 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4188 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4192 SWRAP_UNLOCK_SI(si);
4196 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4198 return swrap_connect(s, serv_addr, addrlen);
4201 /****************************************************************************
4203 ***************************************************************************/
4205 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4208 struct swrap_address un_addr = {
4209 .sa_socklen = sizeof(struct sockaddr_un),
4211 struct socket_info *si = find_socket_info(s);
4212 struct swrap_sockaddr_buf buf = {};
4213 int ret_errno = errno;
4220 return libc_bind(s, myaddr, addrlen);
4225 switch (si->family) {
4227 const struct sockaddr_in *sin;
4228 if (addrlen < sizeof(struct sockaddr_in)) {
4229 bind_error = EINVAL;
4233 sin = (const struct sockaddr_in *)(const void *)myaddr;
4235 if (sin->sin_family != AF_INET) {
4236 bind_error = EAFNOSUPPORT;
4239 /* special case for AF_UNSPEC */
4240 if (sin->sin_family == AF_UNSPEC &&
4241 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4250 const struct sockaddr_in6 *sin6;
4251 if (addrlen < sizeof(struct sockaddr_in6)) {
4252 bind_error = EINVAL;
4256 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4258 if (sin6->sin6_family != AF_INET6) {
4259 bind_error = EAFNOSUPPORT;
4266 bind_error = EINVAL;
4270 if (bind_error != 0) {
4271 ret_errno = bind_error;
4277 in_use = check_addr_port_in_use(myaddr, addrlen);
4285 si->myname.sa_socklen = addrlen;
4286 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4288 ret = sockaddr_convert_to_un(si,
4299 unlink(un_addr.sa.un.sun_path);
4301 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4306 SWRAP_LOG(SWRAP_LOG_TRACE,
4307 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4308 swrap_sockaddr_string(&buf, myaddr),
4309 un_addr.sa.un.sun_path, s, ret, ret_errno);
4316 SWRAP_UNLOCK_SI(si);
4321 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4323 return swrap_bind(s, myaddr, addrlen);
4326 /****************************************************************************
4328 ***************************************************************************/
4330 #ifdef HAVE_BINDRESVPORT
4331 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4333 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4335 struct swrap_address myaddr = {
4336 .sa_socklen = sizeof(struct sockaddr_storage),
4339 static uint16_t port;
4344 #define SWRAP_STARTPORT 600
4345 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4346 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4349 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4353 salen = myaddr.sa_socklen;
4356 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4362 memset(&myaddr.sa.ss, 0, salen);
4367 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4370 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4372 salen = sizeof(struct sockaddr_in);
4373 sinp->sin_port = htons(port);
4377 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4379 salen = sizeof(struct sockaddr_in6);
4380 sin6p->sin6_port = htons(port);
4384 errno = EAFNOSUPPORT;
4389 if (port > SWRAP_ENDPORT) {
4390 port = SWRAP_STARTPORT;
4393 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4394 if (rc == 0 || errno != EADDRINUSE) {
4402 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4404 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4408 /****************************************************************************
4410 ***************************************************************************/
4412 static int swrap_listen(int s, int backlog)
4415 struct socket_info *si = find_socket_info(s);
4418 return libc_listen(s, backlog);
4423 if (si->bound == 0) {
4424 ret = swrap_auto_bind(s, si, si->family);
4431 ret = libc_listen(s, backlog);
4437 SWRAP_UNLOCK_SI(si);
4442 int listen(int s, int backlog)
4444 return swrap_listen(s, backlog);
4447 /****************************************************************************
4449 ***************************************************************************/
4451 static FILE *swrap_fopen(const char *name, const char *mode)
4455 fp = libc_fopen(name, mode);
4457 int fd = fileno(fp);
4459 swrap_remove_stale(fd);
4465 FILE *fopen(const char *name, const char *mode)
4467 return swrap_fopen(name, mode);
4470 /****************************************************************************
4472 ***************************************************************************/
4475 static FILE *swrap_fopen64(const char *name, const char *mode)
4479 fp = libc_fopen64(name, mode);
4481 int fd = fileno(fp);
4483 swrap_remove_stale(fd);
4489 FILE *fopen64(const char *name, const char *mode)
4491 return swrap_fopen64(name, mode);
4493 #endif /* HAVE_FOPEN64 */
4495 /****************************************************************************
4497 ***************************************************************************/
4499 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4503 ret = libc_vopen(pathname, flags, ap);
4506 * There are methods for closing descriptors (libc-internal code
4507 * paths, direct syscalls) which close descriptors in ways that
4508 * we can't intercept, so try to recover when we notice that
4511 swrap_remove_stale(ret);
4516 int open(const char *pathname, int flags, ...)
4521 va_start(ap, flags);
4522 fd = swrap_vopen(pathname, flags, ap);
4528 /****************************************************************************
4530 ***************************************************************************/
4533 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4537 ret = libc_vopen64(pathname, flags, ap);
4540 * There are methods for closing descriptors (libc-internal code
4541 * paths, direct syscalls) which close descriptors in ways that
4542 * we can't intercept, so try to recover when we notice that
4545 swrap_remove_stale(ret);
4550 int open64(const char *pathname, int flags, ...)
4555 va_start(ap, flags);
4556 fd = swrap_vopen64(pathname, flags, ap);
4561 #endif /* HAVE_OPEN64 */
4563 /****************************************************************************
4565 ***************************************************************************/
4567 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4571 ret = libc_vopenat(dirfd, path, flags, ap);
4574 * There are methods for closing descriptors (libc-internal code
4575 * paths, direct syscalls) which close descriptors in ways that
4576 * we can't intercept, so try to recover when we notice that
4579 swrap_remove_stale(ret);
4585 int openat(int dirfd, const char *path, int flags, ...)
4590 va_start(ap, flags);
4591 fd = swrap_vopenat(dirfd, path, flags, ap);
4597 /****************************************************************************
4599 ***************************************************************************/
4601 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4603 struct socket_info *si = find_socket_info(s);
4608 return libc_getpeername(s, name, addrlen);
4613 if (si->peername.sa_socklen == 0)
4619 len = MIN(*addrlen, si->peername.sa_socklen);
4625 memcpy(name, &si->peername.sa.ss, len);
4626 *addrlen = si->peername.sa_socklen;
4630 SWRAP_UNLOCK_SI(si);
4635 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4636 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4638 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4641 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4644 /****************************************************************************
4646 ***************************************************************************/
4648 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4650 struct socket_info *si = find_socket_info(s);
4655 return libc_getsockname(s, name, addrlen);
4660 len = MIN(*addrlen, si->myname.sa_socklen);
4666 memcpy(name, &si->myname.sa.ss, len);
4667 *addrlen = si->myname.sa_socklen;
4671 SWRAP_UNLOCK_SI(si);
4676 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4677 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4679 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4682 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4685 /****************************************************************************
4687 ***************************************************************************/
4690 # ifdef SO_PROTOTYPE /* The Solaris name */
4691 # define SO_PROTOCOL SO_PROTOTYPE
4692 # endif /* SO_PROTOTYPE */
4693 #endif /* SO_PROTOCOL */
4695 static int swrap_getsockopt(int s, int level, int optname,
4696 void *optval, socklen_t *optlen)
4698 struct socket_info *si = find_socket_info(s);
4702 return libc_getsockopt(s,
4711 if (level == SOL_SOCKET) {
4715 if (optval == NULL || optlen == NULL ||
4716 *optlen < (socklen_t)sizeof(int)) {
4722 *optlen = sizeof(int);
4723 *(int *)optval = si->family;
4726 #endif /* SO_DOMAIN */
4730 if (optval == NULL || optlen == NULL ||
4731 *optlen < (socklen_t)sizeof(int)) {
4737 *optlen = sizeof(int);
4738 *(int *)optval = si->protocol;
4741 #endif /* SO_PROTOCOL */
4743 if (optval == NULL || optlen == NULL ||
4744 *optlen < (socklen_t)sizeof(int)) {
4750 *optlen = sizeof(int);
4751 *(int *)optval = si->type;
4755 ret = libc_getsockopt(s,
4762 } else if (level == IPPROTO_TCP) {
4767 * This enables sending packets directly out over TCP.
4768 * As a unix socket is doing that any way, report it as
4771 if (optval == NULL || optlen == NULL ||
4772 *optlen < (socklen_t)sizeof(int)) {
4778 *optlen = sizeof(int);
4779 *(int *)optval = si->tcp_nodelay;
4783 #endif /* TCP_NODELAY */
4786 struct tcp_info info;
4787 socklen_t ilen = sizeof(info);
4789 #ifdef HAVE_NETINET_TCP_FSM_H
4790 /* This is FreeBSD */
4791 # define __TCP_LISTEN TCPS_LISTEN
4792 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4793 # define __TCP_CLOSE TCPS_CLOSED
4796 # define __TCP_LISTEN TCP_LISTEN
4797 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4798 # define __TCP_CLOSE TCP_CLOSE
4802 if (si->listening) {
4803 info.tcpi_state = __TCP_LISTEN;
4804 } else if (si->connected) {
4806 * For now we just fake a few values
4807 * supported both by FreeBSD and Linux
4809 info.tcpi_state = __TCP_ESTABLISHED;
4810 info.tcpi_rto = 200000; /* 200 msec */
4811 info.tcpi_rtt = 5000; /* 5 msec */
4812 info.tcpi_rttvar = 5000; /* 5 msec */
4814 info.tcpi_state = __TCP_CLOSE;
4815 info.tcpi_rto = 1000000; /* 1 sec */
4817 info.tcpi_rttvar = 250000; /* 250 msec */
4820 if (optval == NULL || optlen == NULL ||
4821 *optlen < (socklen_t)ilen) {
4828 memcpy(optval, &info, ilen);
4833 #endif /* TCP_INFO */
4839 errno = ENOPROTOOPT;
4843 SWRAP_UNLOCK_SI(si);
4847 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4848 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4850 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4853 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4856 /****************************************************************************
4858 ***************************************************************************/
4860 static int swrap_setsockopt(int s, int level, int optname,
4861 const void *optval, socklen_t optlen)
4863 struct socket_info *si = find_socket_info(s);
4867 return libc_setsockopt(s,
4874 if (level == SOL_SOCKET) {
4875 return libc_setsockopt(s,
4884 if (level == IPPROTO_TCP) {
4891 * This enables sending packets directly out over TCP.
4892 * A unix socket is doing that any way.
4894 if (optval == NULL || optlen == 0 ||
4895 optlen < (socklen_t)sizeof(int)) {
4901 i = *discard_const_p(int, optval);
4902 if (i != 0 && i != 1) {
4907 si->tcp_nodelay = i;
4912 #endif /* TCP_NODELAY */
4918 switch (si->family) {
4920 if (level == IPPROTO_IP) {
4922 if (optname == IP_PKTINFO) {
4923 si->pktinfo = AF_INET;
4925 #endif /* IP_PKTINFO */
4931 if (level == IPPROTO_IPV6) {
4932 #ifdef IPV6_RECVPKTINFO
4933 if (optname == IPV6_RECVPKTINFO) {
4934 si->pktinfo = AF_INET6;
4936 #endif /* IPV6_PKTINFO */
4942 errno = ENOPROTOOPT;
4948 SWRAP_UNLOCK_SI(si);
4952 int setsockopt(int s, int level, int optname,
4953 const void *optval, socklen_t optlen)
4955 return swrap_setsockopt(s, level, optname, optval, optlen);
4958 /****************************************************************************
4960 ***************************************************************************/
4962 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4964 struct socket_info *si = find_socket_info(s);
4966 int *value_ptr = NULL;
4970 return libc_vioctl(s, r, va);
4977 rc = libc_vioctl(s, r, va);
4982 value_ptr = ((int *)va_arg(ap, int *));
4985 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4986 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4987 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4988 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4993 /* this is FreeBSD */
4994 FALL_THROUGH; /* to TIOCOUTQ */
4995 #endif /* FIONWRITE */
4996 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4998 * This may return more bytes then the application
4999 * sent into the socket, for tcp it should
5000 * return the number of unacked bytes.
5002 * On AF_UNIX, all bytes are immediately acked!
5005 value_ptr = ((int *)va_arg(ap, int *));
5013 SWRAP_UNLOCK_SI(si);
5017 #ifdef HAVE_IOCTL_INT
5018 int ioctl(int s, int r, ...)
5020 int ioctl(int s, unsigned long int r, ...)
5028 rc = swrap_vioctl(s, (unsigned long int) r, va);
5039 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5042 # ifdef _ALIGN /* BSD */
5043 #define CMSG_ALIGN _ALIGN
5045 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
5046 # endif /* _ALIGN */
5047 #endif /* CMSG_ALIGN */
5050 * @brief Add a cmsghdr to a msghdr.
5052 * This is an function to add any type of cmsghdr. It will operate on the
5053 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
5054 * the buffer position after the added cmsg element. Hence, this function is
5055 * intended to be used with an intermediate msghdr and not on the original
5056 * one handed in by the client.
5058 * @param[in] msg The msghdr to which to add the cmsg.
5060 * @param[in] level The cmsg level to set.
5062 * @param[in] type The cmsg type to set.
5064 * @param[in] data The cmsg data to set.
5066 * @param[in] len the length of the data to set.
5068 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5074 size_t cmlen = CMSG_LEN(len);
5075 size_t cmspace = CMSG_SPACE(len);
5076 uint8_t cmbuf[cmspace];
5077 void *cast_ptr = (void *)cmbuf;
5078 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5081 memset(cmbuf, 0, cmspace);
5083 if (msg->msg_controllen < cmlen) {
5084 cmlen = msg->msg_controllen;
5085 msg->msg_flags |= MSG_CTRUNC;
5088 if (msg->msg_controllen < cmspace) {
5089 cmspace = msg->msg_controllen;
5093 * We copy the full input data into an intermediate cmsghdr first
5094 * in order to more easily cope with truncation.
5096 cm->cmsg_len = cmlen;
5097 cm->cmsg_level = level;
5098 cm->cmsg_type = type;
5099 memcpy(CMSG_DATA(cm), data, len);
5102 * We now copy the possibly truncated buffer.
5103 * We copy cmlen bytes, but consume cmspace bytes,
5104 * leaving the possible padding uninitialiazed.
5106 p = (uint8_t *)msg->msg_control;
5107 memcpy(p, cm, cmlen);
5109 msg->msg_control = p;
5110 msg->msg_controllen -= cmspace;
5115 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5118 /* Add packet info */
5119 switch (si->pktinfo) {
5120 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5122 struct sockaddr_in *sin;
5123 #if defined(HAVE_STRUCT_IN_PKTINFO)
5124 struct in_pktinfo pkt;
5125 #elif defined(IP_RECVDSTADDR)
5129 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5130 sin = &si->bindname.sa.in;
5132 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5135 sin = &si->myname.sa.in;
5140 #if defined(HAVE_STRUCT_IN_PKTINFO)
5141 pkt.ipi_ifindex = socket_wrapper_default_iface();
5142 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5143 #elif defined(IP_RECVDSTADDR)
5144 pkt = sin->sin_addr;
5147 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5152 #endif /* IP_PKTINFO */
5153 #if defined(HAVE_IPV6)
5155 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5156 struct sockaddr_in6 *sin6;
5157 struct in6_pktinfo pkt6;
5159 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5160 sin6 = &si->bindname.sa.in6;
5162 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5165 sin6 = &si->myname.sa.in6;
5170 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5171 pkt6.ipi6_addr = sin6->sin6_addr;
5173 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5174 &pkt6, sizeof(pkt6));
5175 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5179 #endif /* IPV6_PKTINFO */
5187 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5188 struct msghdr *omsg)
5192 if (si->pktinfo > 0) {
5193 rc = swrap_msghdr_add_pktinfo(si, omsg);
5199 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5201 size_t *cm_data_space);
5202 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5204 size_t *cm_data_space);
5205 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5207 size_t *cm_data_space);
5209 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5211 size_t *cm_data_space)
5213 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5214 struct cmsghdr *cmsg;
5218 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5222 for (cmsg = CMSG_FIRSTHDR(msg);
5224 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5225 switch (cmsg->cmsg_level) {
5227 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5232 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5237 rc = swrap_sendmsg_copy_cmsg(cmsg,
5243 int saved_errno = errno;
5244 SAFE_FREE(*cm_data);
5246 errno = saved_errno;
5254 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5256 size_t *cm_data_space)
5261 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5263 p = realloc((*cm_data), cmspace);
5269 p = (*cm_data) + (*cm_data_space);
5270 *cm_data_space = cmspace;
5272 memcpy(p, cmsg, cmsg->cmsg_len);
5277 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5279 size_t *cm_data_space);
5282 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5284 size_t *cm_data_space)
5288 switch(cmsg->cmsg_type) {
5291 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5298 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5310 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5312 size_t *cm_data_space)
5314 (void)cmsg; /* unused */
5315 (void)cm_data; /* unused */
5316 (void)cm_data_space; /* unused */
5319 * Passing a IP pktinfo to a unix socket might be rejected by the
5320 * Kernel, at least on FreeBSD. So skip this cmsg.
5325 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5327 size_t *cm_data_space)
5331 switch (cmsg->cmsg_type) {
5333 SWRAP_LOG(SWRAP_LOG_TRACE,
5334 "Ignoring SCM_RIGHTS on inet socket!");
5337 #ifdef SCM_CREDENTIALS
5338 case SCM_CREDENTIALS:
5339 SWRAP_LOG(SWRAP_LOG_TRACE,
5340 "Ignoring SCM_CREDENTIALS on inet socket!");
5343 #endif /* SCM_CREDENTIALS */
5345 rc = swrap_sendmsg_copy_cmsg(cmsg,
5354 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5357 * We only allow up to 6 fds at a time
5358 * as that's more than enough for Samba
5359 * and it means we can keep the logic simple
5360 * and work with fixed size arrays.
5362 * We also keep sizeof(struct swrap_unix_scm_rights)
5363 * under PIPE_BUF (4096) in order to allow a non-blocking
5364 * write into the pipe.
5367 #define PIPE_BUF 4096
5369 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5370 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5371 struct swrap_unix_scm_rights_payload {
5373 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5374 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5376 struct swrap_unix_scm_rights {
5378 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5379 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5381 uint32_t payload_size;
5382 struct swrap_unix_scm_rights_payload payload;
5385 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5387 int saved_errno = errno;
5390 for (i = 0; i < num; i++) {
5391 struct socket_info *si = array[i];
5397 swrap_dec_refcount(si);
5398 if (si->fd_passed > 0) {
5401 SWRAP_UNLOCK_SI(si);
5405 errno = saved_errno;
5408 static void swrap_undo_si_idx_array(size_t num, int *array)
5410 int saved_errno = errno;
5413 swrap_mutex_lock(&first_free_mutex);
5415 for (i = 0; i < num; i++) {
5416 struct socket_info *si = NULL;
5418 if (array[i] == -1) {
5422 si = swrap_get_socket_info(array[i]);
5428 swrap_dec_refcount(si);
5429 SWRAP_UNLOCK_SI(si);
5431 swrap_set_next_free(si, first_free);
5432 first_free = array[i];
5436 swrap_mutex_unlock(&first_free_mutex);
5437 errno = saved_errno;
5440 static void swrap_close_fd_array(size_t num, const int *array)
5442 int saved_errno = errno;
5445 for (i = 0; i < num; i++) {
5446 if (array[i] == -1) {
5449 libc_close(array[i]);
5452 errno = saved_errno;
5460 union __swrap_cmsghdr {
5462 struct cmsghdr *cmsg;
5465 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5467 size_t *cm_data_space,
5468 int *scm_rights_pipe_fd)
5470 struct swrap_unix_scm_rights info;
5471 struct swrap_unix_scm_rights_payload *payload = NULL;
5472 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5473 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5474 size_t info_idx = 0;
5477 union __swrap_fds __fds_in = { .p = NULL, };
5478 const int *fds_in = NULL;
5480 size_t size_fds_out;
5481 union __swrap_fds __fds_out = { .p = NULL, };
5482 int *fds_out = NULL;
5485 size_t new_cm_data_space;
5486 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5487 struct cmsghdr *new_cmsg = NULL;
5490 int pipefd[2] = { -1, -1 };
5495 * We pass this a buffer to the kernel make sure any padding
5499 info.magic = swrap_unix_scm_right_magic;
5500 memcpy(info.package_name,
5501 SOCKET_WRAPPER_PACKAGE,
5502 sizeof(info.package_name));
5503 memcpy(info.package_version,
5504 SOCKET_WRAPPER_VERSION,
5505 sizeof(info.package_version));
5506 info.full_size = sizeof(info);
5507 info.payload_size = sizeof(info.payload);
5508 payload = &info.payload;
5510 if (*scm_rights_pipe_fd != -1) {
5511 SWRAP_LOG(SWRAP_LOG_ERROR,
5512 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5517 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5518 SWRAP_LOG(SWRAP_LOG_ERROR,
5519 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5520 (size_t)cmsg->cmsg_len,
5525 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5526 if ((size_fds_in % sizeof(int)) != 0) {
5527 SWRAP_LOG(SWRAP_LOG_ERROR,
5528 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5529 (size_t)cmsg->cmsg_len,
5535 num_fds_in = size_fds_in / sizeof(int);
5536 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5537 SWRAP_LOG(SWRAP_LOG_ERROR,
5538 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5540 "SWRAP_MAX_PASSED_FDS(%zu)",
5541 (size_t)cmsg->cmsg_len,
5544 SWRAP_MAX_PASSED_FDS);
5548 if (num_fds_in == 0) {
5549 SWRAP_LOG(SWRAP_LOG_ERROR,
5550 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5552 (size_t)cmsg->cmsg_len,
5558 __fds_in.p = CMSG_DATA(cmsg);
5559 fds_in = __fds_in.fds;
5560 num_fds_out = num_fds_in + 1;
5562 SWRAP_LOG(SWRAP_LOG_TRACE,
5563 "num_fds_in=%zu num_fds_out=%zu",
5564 num_fds_in, num_fds_out);
5566 size_fds_out = sizeof(int) * num_fds_out;
5567 cmsg_len = CMSG_LEN(size_fds_out);
5568 cmsg_space = CMSG_SPACE(size_fds_out);
5570 new_cm_data_space = *cm_data_space + cmsg_space;
5572 p = realloc((*cm_data), new_cm_data_space);
5577 p = (*cm_data) + (*cm_data_space);
5578 memset(p, 0, cmsg_space);
5580 new_cmsg = __new_cmsg.cmsg;
5582 __fds_out.p = CMSG_DATA(new_cmsg);
5583 fds_out = __fds_out.fds;
5584 memcpy(fds_out, fds_in, size_fds_in);
5585 new_cmsg->cmsg_len = cmsg->cmsg_len;
5587 for (i = 0; i < num_fds_in; i++) {
5590 payload->idxs[i] = -1;
5591 payload->num_idxs++;
5593 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5594 if (si_idx_array[i] == -1) {
5598 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5599 if (si_array[i] == NULL) {
5600 SWRAP_LOG(SWRAP_LOG_ERROR,
5601 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5602 i, fds_in[i], i, si_idx_array[i]);
5607 for (j = 0; j < i; j++) {
5608 if (si_array[j] == si_array[i]) {
5609 payload->idxs[i] = payload->idxs[j];
5613 if (payload->idxs[i] == -1) {
5614 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5615 SWRAP_LOG(SWRAP_LOG_ERROR,
5616 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5617 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5618 i, fds_in[i], i, si_idx_array[i],
5620 SWRAP_MAX_PASSED_SOCKET_INFO);
5624 payload->idxs[i] = info_idx;
5630 for (i = 0; i < num_fds_in; i++) {
5631 struct socket_info *si = si_array[i];
5634 SWRAP_LOG(SWRAP_LOG_TRACE,
5635 "fds_in[%zu]=%d not an inet socket",
5640 SWRAP_LOG(SWRAP_LOG_TRACE,
5641 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5642 "passing as info.idxs[%zu]=%d!",
5645 i, payload->idxs[i]);
5649 payload->infos[payload->idxs[i]] = *si;
5650 payload->infos[payload->idxs[i]].fd_passed = 0;
5651 SWRAP_UNLOCK_SI(si);
5656 int saved_errno = errno;
5657 SWRAP_LOG(SWRAP_LOG_ERROR,
5658 "pipe() failed - %d %s",
5660 strerror(saved_errno));
5661 swrap_dec_fd_passed_array(num_fds_in, si_array);
5662 errno = saved_errno;
5666 sret = libc_write(pipefd[1], &info, sizeof(info));
5667 if (sret != sizeof(info)) {
5668 int saved_errno = errno;
5670 saved_errno = EINVAL;
5672 SWRAP_LOG(SWRAP_LOG_ERROR,
5673 "write() failed - sret=%zd - %d %s",
5675 strerror(saved_errno));
5676 swrap_dec_fd_passed_array(num_fds_in, si_array);
5677 libc_close(pipefd[1]);
5678 libc_close(pipefd[0]);
5679 errno = saved_errno;
5682 libc_close(pipefd[1]);
5685 * Add the pipe read end to the end of the passed fd array
5687 fds_out[num_fds_in] = pipefd[0];
5688 new_cmsg->cmsg_len = cmsg_len;
5690 /* we're done ... */
5691 *scm_rights_pipe_fd = pipefd[0];
5692 *cm_data_space = new_cm_data_space;
5697 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5699 size_t *cm_data_space,
5700 int *scm_rights_pipe_fd)
5704 switch (cmsg->cmsg_type) {
5706 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5709 scm_rights_pipe_fd);
5712 rc = swrap_sendmsg_copy_cmsg(cmsg,
5721 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5723 size_t *cm_data_space)
5725 int scm_rights_pipe_fd = -1;
5726 struct swrap_unix_scm_rights info;
5727 struct swrap_unix_scm_rights_payload *payload = NULL;
5728 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5731 union __swrap_fds __fds_in = { .p = NULL, };
5732 const int *fds_in = NULL;
5734 size_t size_fds_out;
5735 union __swrap_fds __fds_out = { .p = NULL, };
5736 int *fds_out = NULL;
5739 size_t new_cm_data_space;
5740 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5741 struct cmsghdr *new_cmsg = NULL;
5747 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5748 SWRAP_LOG(SWRAP_LOG_ERROR,
5749 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5750 (size_t)cmsg->cmsg_len,
5755 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5756 if ((size_fds_in % sizeof(int)) != 0) {
5757 SWRAP_LOG(SWRAP_LOG_ERROR,
5758 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5759 (size_t)cmsg->cmsg_len,
5765 num_fds_in = size_fds_in / sizeof(int);
5766 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5767 SWRAP_LOG(SWRAP_LOG_ERROR,
5768 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5769 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5770 (size_t)cmsg->cmsg_len,
5773 SWRAP_MAX_PASSED_FDS+1);
5777 if (num_fds_in <= 1) {
5778 SWRAP_LOG(SWRAP_LOG_ERROR,
5779 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5781 (size_t)cmsg->cmsg_len,
5787 __fds_in.p = CMSG_DATA(cmsg);
5788 fds_in = __fds_in.fds;
5789 num_fds_out = num_fds_in - 1;
5791 SWRAP_LOG(SWRAP_LOG_TRACE,
5792 "num_fds_in=%zu num_fds_out=%zu",
5793 num_fds_in, num_fds_out);
5795 for (i = 0; i < num_fds_in; i++) {
5796 /* Check if we have a stale fd and remove it */
5797 swrap_remove_stale(fds_in[i]);
5800 scm_rights_pipe_fd = fds_in[num_fds_out];
5801 size_fds_out = sizeof(int) * num_fds_out;
5802 cmsg_len = CMSG_LEN(size_fds_out);
5803 cmsg_space = CMSG_SPACE(size_fds_out);
5805 new_cm_data_space = *cm_data_space + cmsg_space;
5807 p = realloc((*cm_data), new_cm_data_space);
5809 swrap_close_fd_array(num_fds_in, fds_in);
5813 p = (*cm_data) + (*cm_data_space);
5814 memset(p, 0, cmsg_space);
5816 new_cmsg = __new_cmsg.cmsg;
5818 __fds_out.p = CMSG_DATA(new_cmsg);
5819 fds_out = __fds_out.fds;
5820 memcpy(fds_out, fds_in, size_fds_out);
5821 new_cmsg->cmsg_len = cmsg_len;
5823 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5824 if (sret != sizeof(info)) {
5825 int saved_errno = errno;
5827 saved_errno = EINVAL;
5829 SWRAP_LOG(SWRAP_LOG_ERROR,
5830 "read() failed - sret=%zd - %d %s",
5832 strerror(saved_errno));
5833 swrap_close_fd_array(num_fds_in, fds_in);
5834 errno = saved_errno;
5837 libc_close(scm_rights_pipe_fd);
5838 payload = &info.payload;
5840 if (info.magic != swrap_unix_scm_right_magic) {
5841 SWRAP_LOG(SWRAP_LOG_ERROR,
5842 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5843 (unsigned long long)info.magic,
5844 (unsigned long long)swrap_unix_scm_right_magic);
5845 swrap_close_fd_array(num_fds_out, fds_out);
5850 cmp = memcmp(info.package_name,
5851 SOCKET_WRAPPER_PACKAGE,
5852 sizeof(info.package_name));
5854 SWRAP_LOG(SWRAP_LOG_ERROR,
5855 "info.package_name='%.*s' != '%s'",
5856 (int)sizeof(info.package_name),
5858 SOCKET_WRAPPER_PACKAGE);
5859 swrap_close_fd_array(num_fds_out, fds_out);
5864 cmp = memcmp(info.package_version,
5865 SOCKET_WRAPPER_VERSION,
5866 sizeof(info.package_version));
5868 SWRAP_LOG(SWRAP_LOG_ERROR,
5869 "info.package_version='%.*s' != '%s'",
5870 (int)sizeof(info.package_version),
5871 info.package_version,
5872 SOCKET_WRAPPER_VERSION);
5873 swrap_close_fd_array(num_fds_out, fds_out);
5878 if (info.full_size != sizeof(info)) {
5879 SWRAP_LOG(SWRAP_LOG_ERROR,
5880 "info.full_size=%zu != sizeof(info)=%zu",
5881 (size_t)info.full_size,
5883 swrap_close_fd_array(num_fds_out, fds_out);
5888 if (info.payload_size != sizeof(info.payload)) {
5889 SWRAP_LOG(SWRAP_LOG_ERROR,
5890 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5891 (size_t)info.payload_size,
5892 sizeof(info.payload));
5893 swrap_close_fd_array(num_fds_out, fds_out);
5898 if (payload->num_idxs != num_fds_out) {
5899 SWRAP_LOG(SWRAP_LOG_ERROR,
5900 "info.num_idxs=%u != num_fds_out=%zu",
5901 payload->num_idxs, num_fds_out);
5902 swrap_close_fd_array(num_fds_out, fds_out);
5907 for (i = 0; i < num_fds_out; i++) {
5910 si_idx_array[i] = -1;
5912 if (payload->idxs[i] == -1) {
5913 SWRAP_LOG(SWRAP_LOG_TRACE,
5914 "fds_out[%zu]=%d not an inet socket",
5919 if (payload->idxs[i] < 0) {
5920 SWRAP_LOG(SWRAP_LOG_ERROR,
5921 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5922 i, fds_out[i], i, payload->idxs[i]);
5923 swrap_close_fd_array(num_fds_out, fds_out);
5928 if (payload->idxs[i] >= payload->num_idxs) {
5929 SWRAP_LOG(SWRAP_LOG_ERROR,
5930 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5931 i, fds_out[i], i, payload->idxs[i],
5933 swrap_close_fd_array(num_fds_out, fds_out);
5938 if ((size_t)fds_out[i] >= socket_fds_max) {
5939 SWRAP_LOG(SWRAP_LOG_ERROR,
5940 "The max socket index limit of %zu has been reached, "
5944 swrap_close_fd_array(num_fds_out, fds_out);
5949 SWRAP_LOG(SWRAP_LOG_TRACE,
5951 "received as info.idxs[%zu]=%d!",
5953 i, payload->idxs[i]);
5955 for (j = 0; j < i; j++) {
5956 if (payload->idxs[j] == -1) {
5959 if (payload->idxs[j] == payload->idxs[i]) {
5960 si_idx_array[i] = si_idx_array[j];
5963 if (si_idx_array[i] == -1) {
5964 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5966 si_idx_array[i] = swrap_add_socket_info(si);
5967 if (si_idx_array[i] == -1) {
5968 int saved_errno = errno;
5969 SWRAP_LOG(SWRAP_LOG_ERROR,
5970 "The max socket index limit of %zu has been reached, "
5974 swrap_undo_si_idx_array(i, si_idx_array);
5975 swrap_close_fd_array(num_fds_out, fds_out);
5976 errno = saved_errno;
5979 SWRAP_LOG(SWRAP_LOG_TRACE,
5980 "Imported %s socket for protocol %s, fd=%d",
5981 si->family == AF_INET ? "IPv4" : "IPv6",
5982 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5987 for (i = 0; i < num_fds_out; i++) {
5988 if (si_idx_array[i] == -1) {
5991 set_socket_info_index(fds_out[i], si_idx_array[i]);
5994 /* we're done ... */
5995 *cm_data_space = new_cm_data_space;
6000 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
6002 size_t *cm_data_space)
6006 switch (cmsg->cmsg_type) {
6008 rc = swrap_recvmsg_unix_scm_rights(cmsg,
6013 rc = swrap_sendmsg_copy_cmsg(cmsg,
6022 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6024 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
6025 struct msghdr *msg_tmp,
6026 int *scm_rights_pipe_fd)
6028 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6029 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
6030 struct cmsghdr *cmsg = NULL;
6031 uint8_t *cm_data = NULL;
6032 size_t cm_data_space = 0;
6036 *scm_rights_pipe_fd = -1;
6039 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6043 for (cmsg = CMSG_FIRSTHDR(msg_in);
6045 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
6046 switch (cmsg->cmsg_level) {
6048 rc = swrap_sendmsg_unix_sol_socket(cmsg,
6051 scm_rights_pipe_fd);
6055 rc = swrap_sendmsg_copy_cmsg(cmsg,
6061 int saved_errno = errno;
6063 errno = saved_errno;
6068 msg_tmp->msg_controllen = cm_data_space;
6069 msg_tmp->msg_control = cm_data;
6072 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6073 *msg_tmp = *_msg_in;
6075 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6078 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6080 int scm_rights_pipe_fd)
6082 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6083 int saved_errno = errno;
6084 SAFE_FREE(msg_tmp->msg_control);
6085 if (scm_rights_pipe_fd != -1) {
6086 libc_close(scm_rights_pipe_fd);
6088 errno = saved_errno;
6089 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6093 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6094 struct msghdr *msg_tmp,
6095 uint8_t **tmp_control)
6097 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6098 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6099 uint8_t *cm_data = NULL;
6100 size_t cm_data_space = 0;
6103 *tmp_control = NULL;
6105 SWRAP_LOG(SWRAP_LOG_TRACE,
6106 "msg_in->msg_controllen=%zu",
6107 (size_t)msg_in->msg_controllen);
6110 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6115 * We need to give the kernel a bit more space in order
6116 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6117 * swrap_recvmsg_after_unix() will hide it again.
6119 cm_data_space = msg_in->msg_controllen;
6120 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6121 cm_data_space += cm_extra_space;
6123 cm_data = calloc(1, cm_data_space);
6124 if (cm_data == NULL) {
6128 msg_tmp->msg_controllen = cm_data_space;
6129 msg_tmp->msg_control = cm_data;
6130 *tmp_control = cm_data;
6132 SWRAP_LOG(SWRAP_LOG_TRACE,
6133 "msg_tmp->msg_controllen=%zu",
6134 (size_t)msg_tmp->msg_controllen);
6136 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6138 *tmp_control = NULL;
6140 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6143 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6144 uint8_t **tmp_control,
6145 struct msghdr *msg_out,
6148 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6149 struct cmsghdr *cmsg = NULL;
6150 uint8_t *cm_data = NULL;
6151 size_t cm_data_space = 0;
6155 int saved_errno = errno;
6156 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6157 saved_errno, strerror(saved_errno));
6158 SAFE_FREE(*tmp_control);
6159 /* msg_out should not be touched on error */
6160 errno = saved_errno;
6164 SWRAP_LOG(SWRAP_LOG_TRACE,
6165 "msg_tmp->msg_controllen=%zu",
6166 (size_t)msg_tmp->msg_controllen);
6169 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6170 int saved_errno = errno;
6171 *msg_out = *msg_tmp;
6172 SAFE_FREE(*tmp_control);
6173 errno = saved_errno;
6177 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6179 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6180 switch (cmsg->cmsg_level) {
6182 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6188 rc = swrap_sendmsg_copy_cmsg(cmsg,
6194 int saved_errno = errno;
6196 SAFE_FREE(*tmp_control);
6197 errno = saved_errno;
6203 * msg_tmp->msg_control (*tmp_control) was created by
6204 * swrap_recvmsg_before_unix() and msg_out->msg_control
6205 * is still the buffer of the caller.
6207 msg_tmp->msg_control = msg_out->msg_control;
6208 msg_tmp->msg_controllen = msg_out->msg_controllen;
6209 *msg_out = *msg_tmp;
6211 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6212 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6213 msg_out->msg_controllen = cm_data_space;
6215 SAFE_FREE(*tmp_control);
6217 SWRAP_LOG(SWRAP_LOG_TRACE,
6218 "msg_out->msg_controllen=%zu",
6219 (size_t)msg_out->msg_controllen);
6221 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6222 int saved_errno = errno;
6223 *msg_out = *msg_tmp;
6224 SAFE_FREE(*tmp_control);
6225 errno = saved_errno;
6227 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6230 static ssize_t swrap_sendmsg_before(int fd,
6231 struct socket_info *si,
6233 struct iovec *tmp_iov,
6234 struct sockaddr_un *tmp_un,
6235 const struct sockaddr_un **to_un,
6236 const struct sockaddr **to,
6241 struct swrap_sockaddr_buf buf = {};
6259 if (!si->connected) {
6264 if (msg->msg_iovlen == 0) {
6268 mtu = socket_wrapper_mtu();
6269 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6271 nlen = len + msg->msg_iov[i].iov_len;
6281 msg->msg_iovlen = i;
6282 if (msg->msg_iovlen == 0) {
6283 *tmp_iov = msg->msg_iov[0];
6284 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6286 msg->msg_iov = tmp_iov;
6287 msg->msg_iovlen = 1;
6292 if (si->connected) {
6293 if (msg->msg_name != NULL) {
6295 * We are dealing with unix sockets and if we
6296 * are connected, we should only talk to the
6297 * connected unix path. Using the fd to send
6298 * to another server would be hard to achieve.
6300 msg->msg_name = NULL;
6301 msg->msg_namelen = 0;
6303 SWRAP_LOG(SWRAP_LOG_TRACE,
6304 "connected(%s) fd=%d",
6305 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6308 const struct sockaddr *msg_name;
6309 msg_name = (const struct sockaddr *)msg->msg_name;
6311 if (msg_name == NULL) {
6317 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6329 msg->msg_name = tmp_un;
6330 msg->msg_namelen = sizeof(*tmp_un);
6333 if (si->bound == 0) {
6334 ret = swrap_auto_bind(fd, si, si->family);
6336 SWRAP_UNLOCK_SI(si);
6337 if (errno == ENOTSOCK) {
6338 swrap_remove_stale(fd);
6341 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6347 if (!si->defer_connect) {
6351 ret = sockaddr_convert_to_un(si,
6353 si->peername.sa_socklen,
6361 SWRAP_LOG(SWRAP_LOG_TRACE,
6362 "deferred connect(%s) path=%s, fd=%d",
6363 swrap_sockaddr_string(&buf, &si->peername.sa.s),
6364 tmp_un->sun_path, fd);
6366 ret = libc_connect(fd,
6367 (struct sockaddr *)(void *)tmp_un,
6370 /* to give better errors */
6371 if (ret == -1 && errno == ENOENT) {
6372 errno = EHOSTUNREACH;
6379 si->defer_connect = 0;
6382 errno = EHOSTUNREACH;
6388 SWRAP_UNLOCK_SI(si);
6393 static void swrap_sendmsg_after(int fd,
6394 struct socket_info *si,
6396 const struct sockaddr *to,
6399 int saved_errno = errno;
6406 /* to give better errors */
6408 if (saved_errno == ENOENT) {
6409 saved_errno = EHOSTUNREACH;
6410 } else if (saved_errno == ENOTSOCK) {
6411 /* If the fd is not a socket, remove it */
6412 swrap_remove_stale(fd);
6416 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6417 avail += msg->msg_iov[i].iov_len;
6421 remain = MIN(80, avail);
6426 /* we capture it as one single packet */
6427 buf = (uint8_t *)malloc(remain);
6429 /* we just not capture the packet */
6430 errno = saved_errno;
6434 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6435 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6436 if (this_time > 0) {
6438 msg->msg_iov[i].iov_base,
6442 remain -= this_time;
6451 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6452 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6454 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6459 if (si->connected) {
6460 to = &si->peername.sa.s;
6463 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6464 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6466 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6471 SWRAP_UNLOCK_SI(si);
6474 errno = saved_errno;
6477 static int swrap_recvmsg_before(int fd,
6478 struct socket_info *si,
6480 struct iovec *tmp_iov)
6487 (void)fd; /* unused */
6492 if (!si->connected) {
6497 if (msg->msg_iovlen == 0) {
6501 mtu = socket_wrapper_mtu();
6502 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6504 nlen = len + msg->msg_iov[i].iov_len;
6509 msg->msg_iovlen = i;
6510 if (msg->msg_iovlen == 0) {
6511 *tmp_iov = msg->msg_iov[0];
6512 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6514 msg->msg_iov = tmp_iov;
6515 msg->msg_iovlen = 1;
6520 if (msg->msg_name == NULL) {
6525 if (msg->msg_iovlen == 0) {
6529 if (si->bound == 0) {
6530 ret = swrap_auto_bind(fd, si, si->family);
6532 SWRAP_UNLOCK_SI(si);
6534 * When attempting to read or write to a
6535 * descriptor, if an underlying autobind fails
6536 * because it's not a socket, stop intercepting
6537 * uses of that descriptor.
6539 if (errno == ENOTSOCK) {
6540 swrap_remove_stale(fd);
6543 SWRAP_LOG(SWRAP_LOG_ERROR,
6544 "swrap_recvmsg_before failed");
6551 errno = EHOSTUNREACH;
6557 SWRAP_UNLOCK_SI(si);
6562 static int swrap_recvmsg_after(int fd,
6563 struct socket_info *si,
6565 const struct sockaddr_un *un_addr,
6566 socklen_t un_addrlen,
6569 int saved_errno = errno;
6571 uint8_t *buf = NULL;
6577 /* to give better errors */
6579 if (saved_errno == ENOENT) {
6580 saved_errno = EHOSTUNREACH;
6581 } else if (saved_errno == ENOTSOCK) {
6582 /* If the fd is not a socket, remove it */
6583 swrap_remove_stale(fd);
6587 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6588 avail += msg->msg_iov[i].iov_len;
6593 /* Convert the socket address before we leave */
6594 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6595 rc = sockaddr_convert_from_un(si,
6612 remain = MIN(80, avail);
6617 /* we capture it as one single packet */
6618 buf = (uint8_t *)malloc(remain);
6620 /* we just not capture the packet */
6621 SWRAP_UNLOCK_SI(si);
6622 errno = saved_errno;
6626 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6627 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6629 msg->msg_iov[i].iov_base,
6632 remain -= this_time;
6637 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6638 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6639 } else if (ret == 0) { /* END OF FILE */
6640 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6641 } else if (ret > 0) {
6642 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6651 if (un_addr != NULL) {
6652 swrap_pcap_dump_packet(si,
6658 swrap_pcap_dump_packet(si,
6671 errno = saved_errno;
6673 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6675 msg->msg_controllen > 0 &&
6676 msg->msg_control != NULL) {
6677 rc = swrap_msghdr_add_socket_info(si, msg);
6679 SWRAP_UNLOCK_SI(si);
6685 SWRAP_UNLOCK_SI(si);
6689 /****************************************************************************
6691 ***************************************************************************/
6693 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6694 struct sockaddr *from, socklen_t *fromlen)
6696 struct swrap_address from_addr = {
6697 .sa_socklen = sizeof(struct sockaddr_un),
6700 struct socket_info *si = find_socket_info(s);
6701 struct swrap_address saddr = {
6702 .sa_socklen = sizeof(struct sockaddr_storage),
6709 return libc_recvfrom(s,
6721 if (from != NULL && fromlen != NULL) {
6722 msg.msg_name = from; /* optional address */
6723 msg.msg_namelen = *fromlen; /* size of address */
6725 msg.msg_name = &saddr.sa.s; /* optional address */
6726 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6728 msg.msg_iov = &tmp; /* scatter/gather array */
6729 msg.msg_iovlen = 1; /* # elements in msg_iov */
6730 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6731 msg.msg_control = NULL; /* ancillary data, see below */
6732 msg.msg_controllen = 0; /* ancillary data buffer len */
6733 msg.msg_flags = 0; /* flags on received message */
6736 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6741 buf = msg.msg_iov[0].iov_base;
6742 len = msg.msg_iov[0].iov_len;
6744 ret = libc_recvfrom(s,
6749 &from_addr.sa_socklen);
6754 tret = swrap_recvmsg_after(s,
6758 from_addr.sa_socklen,
6764 if (from != NULL && fromlen != NULL) {
6765 *fromlen = msg.msg_namelen;
6771 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6772 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6773 struct sockaddr *from, Psocklen_t fromlen)
6775 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6776 struct sockaddr *from, socklen_t *fromlen)
6779 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6782 /****************************************************************************
6784 ***************************************************************************/
6786 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6787 const struct sockaddr *to, socklen_t tolen)
6791 struct swrap_address un_addr = {
6792 .sa_socklen = sizeof(struct sockaddr_un),
6794 const struct sockaddr_un *to_un = NULL;
6797 struct socket_info *si = find_socket_info(s);
6801 return libc_sendto(s, buf, len, flags, to, tolen);
6804 tmp.iov_base = discard_const_p(char, buf);
6808 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6809 msg.msg_namelen = tolen; /* size of address */
6810 msg.msg_iov = &tmp; /* scatter/gather array */
6811 msg.msg_iovlen = 1; /* # elements in msg_iov */
6812 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6813 msg.msg_control = NULL; /* ancillary data, see below */
6814 msg.msg_controllen = 0; /* ancillary data buffer len */
6815 msg.msg_flags = 0; /* flags on received message */
6818 rc = swrap_sendmsg_before(s,
6830 buf = msg.msg_iov[0].iov_base;
6831 len = msg.msg_iov[0].iov_len;
6836 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6838 char *swrap_dir = NULL;
6840 type = SOCKET_TYPE_CHAR_UDP;
6842 swrap_dir = socket_wrapper_dir();
6843 if (swrap_dir == NULL) {
6847 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6848 swrap_un_path(&un_addr.sa.un,
6853 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6855 /* ignore the any errors in broadcast sends */
6861 un_addr.sa_socklen);
6864 SAFE_FREE(swrap_dir);
6868 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6870 SWRAP_UNLOCK_SI(si);
6877 * If it is a dgram socket and we are connected, don't include the
6880 if (si->type == SOCK_DGRAM && si->connected) {
6881 ret = libc_sendto(s,
6888 ret = libc_sendto(s,
6892 (struct sockaddr *)msg.msg_name,
6896 SWRAP_UNLOCK_SI(si);
6898 swrap_sendmsg_after(s, si, &msg, to, ret);
6903 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6904 const struct sockaddr *to, socklen_t tolen)
6906 return swrap_sendto(s, buf, len, flags, to, tolen);
6909 /****************************************************************************
6911 ***************************************************************************/
6913 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6915 struct socket_info *si;
6917 struct swrap_address saddr = {
6918 .sa_socklen = sizeof(struct sockaddr_storage),
6924 si = find_socket_info(s);
6926 return libc_recv(s, buf, len, flags);
6933 msg.msg_name = &saddr.sa.s; /* optional address */
6934 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6935 msg.msg_iov = &tmp; /* scatter/gather array */
6936 msg.msg_iovlen = 1; /* # elements in msg_iov */
6937 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6938 msg.msg_control = NULL; /* ancillary data, see below */
6939 msg.msg_controllen = 0; /* ancillary data buffer len */
6940 msg.msg_flags = 0; /* flags on received message */
6943 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6948 buf = msg.msg_iov[0].iov_base;
6949 len = msg.msg_iov[0].iov_len;
6951 ret = libc_recv(s, buf, len, flags);
6953 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6961 ssize_t recv(int s, void *buf, size_t len, int flags)
6963 return swrap_recv(s, buf, len, flags);
6966 /****************************************************************************
6968 ***************************************************************************/
6970 static ssize_t swrap_read(int s, void *buf, size_t len)
6972 struct socket_info *si;
6975 struct swrap_address saddr = {
6976 .sa_socklen = sizeof(struct sockaddr_storage),
6981 si = find_socket_info(s);
6983 return libc_read(s, buf, len);
6990 msg.msg_name = &saddr.sa.ss; /* optional address */
6991 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6992 msg.msg_iov = &tmp; /* scatter/gather array */
6993 msg.msg_iovlen = 1; /* # elements in msg_iov */
6994 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6995 msg.msg_control = NULL; /* ancillary data, see below */
6996 msg.msg_controllen = 0; /* ancillary data buffer len */
6997 msg.msg_flags = 0; /* flags on received message */
7000 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
7002 if (tret == -ENOTSOCK) {
7003 return libc_read(s, buf, len);
7008 buf = msg.msg_iov[0].iov_base;
7009 len = msg.msg_iov[0].iov_len;
7011 ret = libc_read(s, buf, len);
7013 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7021 ssize_t read(int s, void *buf, size_t len)
7023 return swrap_read(s, buf, len);
7026 /****************************************************************************
7028 ***************************************************************************/
7030 static ssize_t swrap_write(int s, const void *buf, size_t len)
7034 struct sockaddr_un un_addr;
7037 struct socket_info *si;
7039 si = find_socket_info(s);
7041 return libc_write(s, buf, len);
7044 tmp.iov_base = discard_const_p(char, buf);
7048 msg.msg_name = NULL; /* optional address */
7049 msg.msg_namelen = 0; /* size of address */
7050 msg.msg_iov = &tmp; /* scatter/gather array */
7051 msg.msg_iovlen = 1; /* # elements in msg_iov */
7052 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7053 msg.msg_control = NULL; /* ancillary data, see below */
7054 msg.msg_controllen = 0; /* ancillary data buffer len */
7055 msg.msg_flags = 0; /* flags on received message */
7058 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7063 buf = msg.msg_iov[0].iov_base;
7064 len = msg.msg_iov[0].iov_len;
7066 ret = libc_write(s, buf, len);
7068 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7073 ssize_t write(int s, const void *buf, size_t len)
7075 return swrap_write(s, buf, len);
7078 /****************************************************************************
7080 ***************************************************************************/
7082 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7086 struct sockaddr_un un_addr;
7089 struct socket_info *si = find_socket_info(s);
7092 return libc_send(s, buf, len, flags);
7095 tmp.iov_base = discard_const_p(char, buf);
7099 msg.msg_name = NULL; /* optional address */
7100 msg.msg_namelen = 0; /* size of address */
7101 msg.msg_iov = &tmp; /* scatter/gather array */
7102 msg.msg_iovlen = 1; /* # elements in msg_iov */
7103 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7104 msg.msg_control = NULL; /* ancillary data, see below */
7105 msg.msg_controllen = 0; /* ancillary data buffer len */
7106 msg.msg_flags = 0; /* flags on received message */
7109 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7114 buf = msg.msg_iov[0].iov_base;
7115 len = msg.msg_iov[0].iov_len;
7117 ret = libc_send(s, buf, len, flags);
7119 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7124 ssize_t send(int s, const void *buf, size_t len, int flags)
7126 return swrap_send(s, buf, len, flags);
7129 /****************************************************************************
7131 ***************************************************************************/
7133 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7135 struct swrap_address from_addr = {
7136 .sa_socklen = sizeof(struct sockaddr_un),
7138 struct swrap_address convert_addr = {
7139 .sa_socklen = sizeof(struct sockaddr_storage),
7141 struct socket_info *si;
7144 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7145 size_t msg_ctrllen_filled;
7146 size_t msg_ctrllen_left;
7152 si = find_socket_info(s);
7154 uint8_t *tmp_control = NULL;
7155 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7159 ret = libc_recvmsg(s, &msg, flags);
7160 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7163 tmp.iov_base = NULL;
7167 msg.msg_name = &from_addr.sa; /* optional address */
7168 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7169 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7170 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7171 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7172 msg_ctrllen_filled = 0;
7173 msg_ctrllen_left = omsg->msg_controllen;
7175 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7176 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7177 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7180 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7185 ret = libc_recvmsg(s, &msg, flags);
7187 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7188 msg_ctrllen_filled += msg.msg_controllen;
7189 msg_ctrllen_left -= msg.msg_controllen;
7191 if (omsg->msg_control != NULL) {
7194 p = omsg->msg_control;
7195 p += msg_ctrllen_filled;
7197 msg.msg_control = p;
7198 msg.msg_controllen = msg_ctrllen_left;
7200 msg.msg_control = NULL;
7201 msg.msg_controllen = 0;
7206 * We convert the unix address to a IP address so we need a buffer
7207 * which can store the address in case of SOCK_DGRAM, see below.
7209 msg.msg_name = &convert_addr.sa;
7210 msg.msg_namelen = convert_addr.sa_socklen;
7212 rc = swrap_recvmsg_after(s,
7216 from_addr.sa_socklen,
7222 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7223 if (omsg->msg_control != NULL) {
7224 /* msg.msg_controllen = space left */
7225 msg_ctrllen_left = msg.msg_controllen;
7226 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7229 /* Update the original message length */
7230 omsg->msg_controllen = msg_ctrllen_filled;
7231 omsg->msg_flags = msg.msg_flags;
7233 omsg->msg_iovlen = msg.msg_iovlen;
7240 * The msg_name field points to a caller-allocated buffer that is
7241 * used to return the source address if the socket is unconnected. The
7242 * caller should set msg_namelen to the size of this buffer before this
7243 * call; upon return from a successful call, msg_name will contain the
7244 * length of the returned address. If the application does not need
7245 * to know the source address, msg_name can be specified as NULL.
7247 if (si->type == SOCK_STREAM) {
7248 omsg->msg_namelen = 0;
7249 } else if (omsg->msg_name != NULL &&
7250 omsg->msg_namelen != 0 &&
7251 omsg->msg_namelen >= msg.msg_namelen) {
7252 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7253 omsg->msg_namelen = msg.msg_namelen;
7256 SWRAP_UNLOCK_SI(si);
7261 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7263 return swrap_recvmsg(sockfd, msg, flags);
7266 /****************************************************************************
7268 ***************************************************************************/
7270 #ifdef HAVE_RECVMMSG
7271 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7273 static ssize_t swrap_recvmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags, const struct timespec *timeout)
7274 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7275 /* Linux legacy glibc < 2.21 */
7276 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, const struct timespec *timeout)
7278 /* Linux glibc >= 2.21 */
7279 static int swrap_recvmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags, struct timespec *timeout)
7282 struct socket_info *si = find_socket_info(s);
7283 #define __SWRAP_RECVMMSG_MAX_VLEN 16
7284 struct mmsghdr msgvec[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7287 struct swrap_address from_addr;
7288 struct swrap_address convert_addr;
7289 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7290 size_t msg_ctrllen_filled;
7291 size_t msg_ctrllen_left;
7293 } tmp[__SWRAP_RECVMMSG_MAX_VLEN] = {};
7300 if (_vlen > __SWRAP_RECVMMSG_MAX_VLEN) {
7301 vlen = __SWRAP_RECVMMSG_MAX_VLEN;
7307 uint8_t *tmp_control[__SWRAP_RECVMMSG_MAX_VLEN] = { NULL, };
7309 for (i = 0; i < vlen; i++) {
7310 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7311 struct msghdr *msg = &msgvec[i].msg_hdr;
7313 rc = swrap_recvmsg_before_unix(omsg, msg,
7321 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7326 for (i = 0; i < ret; i++) {
7327 omsgvec[i].msg_len = msgvec[i].msg_len;
7331 saved_errno = errno;
7332 for (i = 0; i < vlen; i++) {
7333 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7334 struct msghdr *msg = &msgvec[i].msg_hdr;
7336 if (i == 0 || i < ret) {
7337 swrap_recvmsg_after_unix(msg, &tmp_control[i], omsg, ret);
7339 SAFE_FREE(tmp_control[i]);
7341 errno = saved_errno;
7346 for (i = 0; i < vlen; i++) {
7347 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7348 struct msghdr *msg = &msgvec[i].msg_hdr;
7350 tmp[i].from_addr.sa_socklen = sizeof(struct sockaddr_un);
7351 tmp[i].convert_addr.sa_socklen = sizeof(struct sockaddr_storage);
7353 msg->msg_name = &tmp[i].from_addr.sa; /* optional address */
7354 msg->msg_namelen = tmp[i].from_addr.sa_socklen; /* size of address */
7355 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7356 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7357 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7358 tmp[i].msg_ctrllen_filled = 0;
7359 tmp[i].msg_ctrllen_left = omsg->msg_controllen;
7361 msg->msg_control = omsg->msg_control; /* ancillary data, see below */
7362 msg->msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7363 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7366 rc = swrap_recvmsg_before(s, si, msg, &tmp[i].iov);
7373 ret = libc_recvmmsg(s, msgvec, vlen, flags, timeout);
7378 for (i = 0; i < ret; i++) {
7379 omsgvec[i].msg_len = msgvec[i].msg_len;
7384 saved_errno = errno;
7385 for (i = 0; i < vlen; i++) {
7386 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7387 struct msghdr *msg = &msgvec[i].msg_hdr;
7389 if (!(i == 0 || i < ret)) {
7393 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7394 tmp[i].msg_ctrllen_filled += msg->msg_controllen;
7395 tmp[i].msg_ctrllen_left -= msg->msg_controllen;
7397 if (omsg->msg_control != NULL) {
7400 p = omsg->msg_control;
7401 p += tmp[i].msg_ctrllen_filled;
7403 msg->msg_control = p;
7404 msg->msg_controllen = tmp[i].msg_ctrllen_left;
7406 msg->msg_control = NULL;
7407 msg->msg_controllen = 0;
7412 * We convert the unix address to a IP address so we need a buffer
7413 * which can store the address in case of SOCK_DGRAM, see below.
7415 msg->msg_name = &tmp[i].convert_addr.sa;
7416 msg->msg_namelen = tmp[i].convert_addr.sa_socklen;
7418 swrap_recvmsg_after(s, si, msg,
7419 &tmp[i].from_addr.sa.un,
7420 tmp[i].from_addr.sa_socklen,
7423 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7424 if (omsg->msg_control != NULL) {
7425 /* msg->msg_controllen = space left */
7426 tmp[i].msg_ctrllen_left = msg->msg_controllen;
7427 tmp[i].msg_ctrllen_filled = omsg->msg_controllen - tmp[i].msg_ctrllen_left;
7430 /* Update the original message length */
7431 omsg->msg_controllen = tmp[i].msg_ctrllen_filled;
7432 omsg->msg_flags = msg->msg_flags;
7434 omsg->msg_iovlen = msg->msg_iovlen;
7441 * The msg_name field points to a caller-allocated buffer that is
7442 * used to return the source address if the socket is unconnected. The
7443 * caller should set msg_namelen to the size of this buffer before this
7444 * call; upon return from a successful call, msg_name will contain the
7445 * length of the returned address. If the application does not need
7446 * to know the source address, msg_name can be specified as NULL.
7448 if (si->type == SOCK_STREAM) {
7449 omsg->msg_namelen = 0;
7450 } else if (omsg->msg_name != NULL &&
7451 omsg->msg_namelen != 0 &&
7452 omsg->msg_namelen >= msg->msg_namelen) {
7453 memcpy(omsg->msg_name, msg->msg_name, msg->msg_namelen);
7454 omsg->msg_namelen = msg->msg_namelen;
7457 SWRAP_UNLOCK_SI(si);
7459 errno = saved_errno;
7464 #if defined(HAVE_RECVMMSG_SSIZE_T_CONST_TIMEOUT)
7466 ssize_t recvmmsg(int sockfd, struct mmsghdr *msgvec, size_t vlen, int flags, const struct timespec *timeout)
7467 #elif defined(HAVE_RECVMMSG_CONST_TIMEOUT)
7468 /* Linux legacy glibc < 2.21 */
7469 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, const struct timespec *timeout)
7471 /* Linux glibc >= 2.21 */
7472 int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout)
7475 return swrap_recvmmsg(sockfd, msgvec, vlen, flags, timeout);
7477 #endif /* HAVE_RECVMMSG */
7479 /****************************************************************************
7481 ***************************************************************************/
7483 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7487 struct sockaddr_un un_addr;
7488 const struct sockaddr_un *to_un = NULL;
7489 const struct sockaddr *to = NULL;
7492 struct socket_info *si = find_socket_info(s);
7496 int scm_rights_pipe_fd = -1;
7498 rc = swrap_sendmsg_before_unix(omsg, &msg,
7499 &scm_rights_pipe_fd);
7503 ret = libc_sendmsg(s, &msg, flags);
7504 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7507 ZERO_STRUCT(un_addr);
7509 tmp.iov_base = NULL;
7516 if (si->connected == 0) {
7517 msg.msg_name = omsg->msg_name; /* optional address */
7518 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7520 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7521 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7523 SWRAP_UNLOCK_SI(si);
7525 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7526 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7527 uint8_t *cmbuf = NULL;
7530 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7536 msg.msg_controllen = 0;
7537 msg.msg_control = NULL;
7539 msg.msg_control = cmbuf;
7540 msg.msg_controllen = cmlen;
7543 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7545 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7547 int saved_errno = errno;
7548 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7549 SAFE_FREE(msg.msg_control);
7551 errno = saved_errno;
7558 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7565 char *swrap_dir = NULL;
7567 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7568 avail += msg.msg_iov[i].iov_len;
7574 /* we capture it as one single packet */
7575 buf = (uint8_t *)malloc(remain);
7577 int saved_errno = errno;
7578 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7579 SAFE_FREE(msg.msg_control);
7581 errno = saved_errno;
7585 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7586 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7588 msg.msg_iov[i].iov_base,
7591 remain -= this_time;
7594 type = SOCKET_TYPE_CHAR_UDP;
7596 swrap_dir = socket_wrapper_dir();
7597 if (swrap_dir == NULL) {
7598 int saved_errno = errno;
7599 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7600 SAFE_FREE(msg.msg_control);
7603 errno = saved_errno;
7607 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7608 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7609 if (stat(un_addr.sun_path, &st) != 0) continue;
7611 msg.msg_name = &un_addr; /* optional address */
7612 msg.msg_namelen = sizeof(un_addr); /* size of address */
7614 /* ignore the any errors in broadcast sends */
7615 libc_sendmsg(s, &msg, flags);
7618 SAFE_FREE(swrap_dir);
7622 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7625 SWRAP_UNLOCK_SI(si);
7630 ret = libc_sendmsg(s, &msg, flags);
7632 swrap_sendmsg_after(s, si, &msg, to, ret);
7634 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7636 int saved_errno = errno;
7637 SAFE_FREE(msg.msg_control);
7638 errno = saved_errno;
7645 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7647 return swrap_sendmsg(s, omsg, flags);
7650 /****************************************************************************
7652 ***************************************************************************/
7654 #ifdef HAVE_SENDMMSG
7655 #if defined(HAVE_SENDMMSG_SSIZE_T)
7657 static ssize_t swrap_sendmmsg(int s, struct mmsghdr *omsgvec, size_t _vlen, int flags)
7660 static int swrap_sendmmsg(int s, struct mmsghdr *omsgvec, unsigned int _vlen, int flags)
7663 struct socket_info *si = find_socket_info(s);
7664 #define __SWRAP_SENDMMSG_MAX_VLEN 16
7665 struct mmsghdr msgvec[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7668 struct sockaddr_un un_addr;
7669 const struct sockaddr_un *to_un;
7670 const struct sockaddr *to;
7672 } tmp[__SWRAP_SENDMMSG_MAX_VLEN] = {};
7675 char *swrap_dir = NULL;
7677 int found_bcast = 0;
7682 if (_vlen > __SWRAP_SENDMMSG_MAX_VLEN) {
7683 vlen = __SWRAP_SENDMMSG_MAX_VLEN;
7689 int scm_rights_pipe_fd[__SWRAP_SENDMMSG_MAX_VLEN];
7691 for (i = 0; i < __SWRAP_SENDMMSG_MAX_VLEN; i++) {
7692 scm_rights_pipe_fd[i] = -1;
7695 for (i = 0; i < vlen; i++) {
7696 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7697 struct msghdr *msg = &msgvec[i].msg_hdr;
7699 rc = swrap_sendmsg_before_unix(omsg, msg,
7700 &scm_rights_pipe_fd[i]);
7707 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7712 for (i = 0; i < ret; i++) {
7713 omsgvec[i].msg_len = msgvec[i].msg_len;
7717 saved_errno = errno;
7718 for (i = 0; i < vlen; i++) {
7719 struct msghdr *msg = &msgvec[i].msg_hdr;
7721 swrap_sendmsg_after_unix(msg, ret,
7722 scm_rights_pipe_fd[i]);
7724 errno = saved_errno;
7730 connected = si->connected;
7731 SWRAP_UNLOCK_SI(si);
7733 for (i = 0; i < vlen; i++) {
7734 struct msghdr *omsg = &omsgvec[i].msg_hdr;
7735 struct msghdr *msg = &msgvec[i].msg_hdr;
7737 if (connected == 0) {
7738 msg->msg_name = omsg->msg_name; /* optional address */
7739 msg->msg_namelen = omsg->msg_namelen; /* size of address */
7741 msg->msg_iov = omsg->msg_iov; /* scatter/gather array */
7742 msg->msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7744 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7745 if (omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7746 uint8_t *cmbuf = NULL;
7749 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7756 msg->msg_control = cmbuf;
7757 msg->msg_controllen = cmlen;
7760 msg->msg_flags = omsg->msg_flags; /* flags on received message */
7763 rc = swrap_sendmsg_before(s, si, msg,
7781 swrap_dir = socket_wrapper_dir();
7782 if (swrap_dir == NULL) {
7787 for (i = 0; i < vlen; i++) {
7788 struct msghdr *msg = &msgvec[i].msg_hdr;
7789 struct sockaddr_un *un_addr = &tmp[i].un_addr;
7790 const struct sockaddr *to = tmp[i].to;
7793 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7801 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7802 avail += msg->msg_iov[l].iov_len;
7808 /* we capture it as one single packet */
7809 buf = (uint8_t *)malloc(remain);
7815 for (l = 0; l < (size_t)msg->msg_iovlen; l++) {
7816 size_t this_time = MIN(remain, (size_t)msg->msg_iov[l].iov_len);
7818 msg->msg_iov[l].iov_base,
7821 remain -= this_time;
7824 type = SOCKET_TYPE_CHAR_UDP;
7826 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7827 swrap_un_path(un_addr, swrap_dir, type, iface, prt);
7828 if (stat(un_addr->sun_path, &st) != 0) continue;
7830 msg->msg_name = un_addr; /* optional address */
7831 msg->msg_namelen = sizeof(*un_addr); /* size of address */
7834 * ignore the any errors in broadcast sends and
7835 * do a single sendmsg instead of sendmmsg
7837 libc_sendmsg(s, msg, flags);
7841 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7842 SWRAP_UNLOCK_SI(si);
7846 msgvec[i].msg_len = len;
7853 ret = libc_sendmmsg(s, msgvec, vlen, flags);
7859 for (i = 0; i < ret; i++) {
7860 omsgvec[i].msg_len = msgvec[i].msg_len;
7864 saved_errno = errno;
7865 for (i = 0; i < vlen; i++) {
7866 struct msghdr *msg = &msgvec[i].msg_hdr;
7868 if (i == 0 || i < ret) {
7869 swrap_sendmsg_after(s, si, msg, tmp[i].to, ret);
7871 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7872 SAFE_FREE(msg->msg_control);
7875 SAFE_FREE(swrap_dir);
7876 errno = saved_errno;
7881 #if defined(HAVE_SENDMMSG_SSIZE_T)
7883 ssize_t sendmmsg(int s, struct mmsghdr *msgvec, size_t vlen, int flags)
7886 int sendmmsg(int s, struct mmsghdr *msgvec, unsigned int vlen, int flags)
7889 return swrap_sendmmsg(s, msgvec, vlen, flags);
7891 #endif /* HAVE_SENDMMSG */
7893 /****************************************************************************
7895 ***************************************************************************/
7897 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7899 struct socket_info *si;
7902 struct swrap_address saddr = {
7903 .sa_socklen = sizeof(struct sockaddr_storage)
7908 si = find_socket_info(s);
7910 return libc_readv(s, vector, count);
7913 tmp.iov_base = NULL;
7917 msg.msg_name = &saddr.sa.s; /* optional address */
7918 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7919 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7920 msg.msg_iovlen = count; /* # elements in msg_iov */
7921 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7922 msg.msg_control = NULL; /* ancillary data, see below */
7923 msg.msg_controllen = 0; /* ancillary data buffer len */
7924 msg.msg_flags = 0; /* flags on received message */
7927 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7929 if (rc == -ENOTSOCK) {
7930 return libc_readv(s, vector, count);
7935 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7937 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7945 ssize_t readv(int s, const struct iovec *vector, int count)
7947 return swrap_readv(s, vector, count);
7950 /****************************************************************************
7952 ***************************************************************************/
7954 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7958 struct sockaddr_un un_addr;
7961 struct socket_info *si = find_socket_info(s);
7964 return libc_writev(s, vector, count);
7967 tmp.iov_base = NULL;
7971 msg.msg_name = NULL; /* optional address */
7972 msg.msg_namelen = 0; /* size of address */
7973 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7974 msg.msg_iovlen = count; /* # elements in msg_iov */
7975 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7976 msg.msg_control = NULL; /* ancillary data, see below */
7977 msg.msg_controllen = 0; /* ancillary data buffer len */
7978 msg.msg_flags = 0; /* flags on received message */
7981 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7983 if (rc == -ENOTSOCK) {
7984 return libc_readv(s, vector, count);
7989 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7991 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7996 ssize_t writev(int s, const struct iovec *vector, int count)
7998 return swrap_writev(s, vector, count);
8001 /****************************
8003 ***************************/
8005 static int swrap_remove_wrapper(const char *__func_name,
8006 int (*__close_fd_fn)(int fd),
8009 struct socket_info *si = NULL;
8011 int ret_errno = errno;
8014 swrap_mutex_lock(&socket_reset_mutex);
8016 si_index = find_socket_info_index(fd);
8017 if (si_index == -1) {
8018 swrap_mutex_unlock(&socket_reset_mutex);
8019 return __close_fd_fn(fd);
8022 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
8023 reset_socket_info_index(fd);
8025 si = swrap_get_socket_info(si_index);
8027 swrap_mutex_lock(&first_free_mutex);
8030 ret = __close_fd_fn(fd);
8035 swrap_dec_refcount(si);
8037 if (swrap_get_refcount(si) > 0) {
8038 /* there are still references left */
8042 if (si->fd_passed) {
8046 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8047 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
8050 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
8051 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
8052 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
8055 if (si->un_addr.sun_path[0] != '\0') {
8056 unlink(si->un_addr.sun_path);
8060 swrap_set_next_free(si, first_free);
8061 first_free = si_index;
8064 SWRAP_UNLOCK_SI(si);
8065 swrap_mutex_unlock(&first_free_mutex);
8066 swrap_mutex_unlock(&socket_reset_mutex);
8072 static int swrap_noop_close(int fd)
8074 (void)fd; /* unused */
8078 static void swrap_remove_stale(int fd)
8080 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8084 * This allows socket_wrapper aware applications to
8085 * indicate that the given fd does not belong to
8088 * We already overload a lot of unrelated functions
8089 * like eventfd(), timerfd_create(), ... in order to
8090 * call swrap_remove_stale() on the returned fd, but
8091 * we'll never be able to handle all possible syscalls.
8093 * socket_wrapper_indicate_no_inet_fd() gives them a way
8096 * We don't export swrap_remove_stale() in order to
8097 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
8100 void socket_wrapper_indicate_no_inet_fd(int fd)
8102 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
8105 static int swrap_close(int fd)
8107 return swrap_remove_wrapper(__func__, libc_close, fd);
8112 return swrap_close(fd);
8115 #ifdef HAVE___CLOSE_NOCANCEL
8117 static int swrap___close_nocancel(int fd)
8119 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
8122 int __close_nocancel(int fd);
8123 int __close_nocancel(int fd)
8125 return swrap___close_nocancel(fd);
8128 #endif /* HAVE___CLOSE_NOCANCEL */
8130 /****************************
8132 ***************************/
8134 static int swrap_dup(int fd)
8136 struct socket_info *si;
8139 idx = find_socket_info_index(fd);
8141 return libc_dup(fd);
8144 si = swrap_get_socket_info(idx);
8146 dup_fd = libc_dup(fd);
8148 int saved_errno = errno;
8149 errno = saved_errno;
8153 if ((size_t)dup_fd >= socket_fds_max) {
8154 SWRAP_LOG(SWRAP_LOG_ERROR,
8155 "The max socket index limit of %zu has been reached, "
8166 swrap_inc_refcount(si);
8168 SWRAP_UNLOCK_SI(si);
8170 /* Make sure we don't have an entry for the fd */
8171 swrap_remove_stale(dup_fd);
8173 set_socket_info_index(dup_fd, idx);
8180 return swrap_dup(fd);
8183 /****************************
8185 ***************************/
8187 static int swrap_dup2(int fd, int newfd)
8189 struct socket_info *si;
8192 idx = find_socket_info_index(fd);
8194 return libc_dup2(fd, newfd);
8197 si = swrap_get_socket_info(idx);
8201 * According to the manpage:
8203 * "If oldfd is a valid file descriptor, and newfd has the same
8204 * value as oldfd, then dup2() does nothing, and returns newfd."
8209 if ((size_t)newfd >= socket_fds_max) {
8210 SWRAP_LOG(SWRAP_LOG_ERROR,
8211 "The max socket index limit of %zu has been reached, "
8219 if (find_socket_info(newfd)) {
8220 /* dup2() does an implicit close of newfd, which we
8221 * need to emulate */
8225 dup_fd = libc_dup2(fd, newfd);
8227 int saved_errno = errno;
8228 errno = saved_errno;
8234 swrap_inc_refcount(si);
8236 SWRAP_UNLOCK_SI(si);
8238 /* Make sure we don't have an entry for the fd */
8239 swrap_remove_stale(dup_fd);
8241 set_socket_info_index(dup_fd, idx);
8246 int dup2(int fd, int newfd)
8248 return swrap_dup2(fd, newfd);
8251 /****************************
8253 ***************************/
8255 static int swrap_vfcntl(int fd, int cmd, va_list va)
8257 struct socket_info *si;
8258 int rc, dup_fd, idx;
8260 idx = find_socket_info_index(fd);
8262 return libc_vfcntl(fd, cmd, va);
8265 si = swrap_get_socket_info(idx);
8269 dup_fd = libc_vfcntl(fd, cmd, va);
8271 int saved_errno = errno;
8272 errno = saved_errno;
8276 /* Make sure we don't have an entry for the fd */
8277 swrap_remove_stale(dup_fd);
8279 if ((size_t)dup_fd >= socket_fds_max) {
8280 SWRAP_LOG(SWRAP_LOG_ERROR,
8281 "The max socket index limit of %zu has been reached, "
8292 swrap_inc_refcount(si);
8294 SWRAP_UNLOCK_SI(si);
8297 set_socket_info_index(dup_fd, idx);
8302 rc = libc_vfcntl(fd, cmd, va);
8309 int fcntl(int fd, int cmd, ...)
8316 rc = swrap_vfcntl(fd, cmd, va);
8323 /****************************
8325 ***************************/
8328 static int swrap_eventfd(int count, int flags)
8332 fd = libc_eventfd(count, flags);
8334 swrap_remove_stale(fd);
8340 #ifdef HAVE_EVENTFD_UNSIGNED_INT
8341 int eventfd(unsigned int count, int flags)
8343 int eventfd(int count, int flags)
8346 return swrap_eventfd(count, flags);
8351 int pledge(const char *promises, const char *paths[])
8353 (void)promises; /* unused */
8354 (void)paths; /* unused */
8358 #endif /* HAVE_PLEDGE */
8360 static void swrap_thread_prepare(void)
8363 * This function should only be called here!!
8365 * We bind all symobls to avoid deadlocks of the fork is
8366 * interrupted by a signal handler using a symbol of this
8369 swrap_bind_symbol_all();
8374 static void swrap_thread_parent(void)
8379 static void swrap_thread_child(void)
8384 /****************************
8386 ***************************/
8387 void swrap_constructor(void)
8389 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
8390 SWRAP_LOG(SWRAP_LOG_ERROR,
8392 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
8393 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
8394 "sizeof(struct socket_info)=%zu",
8396 sizeof(struct swrap_unix_scm_rights),
8397 sizeof(struct swrap_unix_scm_rights_payload),
8398 sizeof(struct socket_info));
8405 * If we hold a lock and the application forks, then the child
8406 * is not able to unlock the mutex and we are in a deadlock.
8407 * This should prevent such deadlocks.
8409 pthread_atfork(&swrap_thread_prepare,
8410 &swrap_thread_parent,
8411 &swrap_thread_child);
8414 /****************************
8416 ***************************/
8419 * This function is called when the library is unloaded and makes sure that
8420 * sockets get closed and the unix file for the socket are unlinked.
8422 void swrap_destructor(void)
8426 if (socket_fds_idx != NULL) {
8427 for (i = 0; i < socket_fds_max; ++i) {
8428 if (socket_fds_idx[i] != -1) {
8432 SAFE_FREE(socket_fds_idx);
8437 if (swrap.libc.handle != NULL
8439 && swrap.libc.handle != RTLD_NEXT
8442 dlclose(swrap.libc.handle);
8444 if (swrap.libc.socket_handle
8446 && swrap.libc.socket_handle != RTLD_NEXT
8449 dlclose(swrap.libc.socket_handle);
8453 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
8455 * On FreeBSD 12 (and maybe other platforms)
8456 * system libraries like libresolv prefix there
8457 * syscalls with '_' in order to always use
8458 * the symbols from libc.
8460 * In the interaction with resolv_wrapper,
8461 * we need to inject socket wrapper into libresolv,
8462 * which means we need to private all socket
8463 * related syscalls also with the '_' prefix.
8465 * This is tested in Samba's 'make test',
8466 * there we noticed that providing '_read',
8467 * '_open' and '_close' would cause errors, which
8468 * means we skip '_read', '_write' and
8469 * all non socket related calls without
8470 * further analyzing the problem.
8472 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
8473 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
8476 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
8478 SWRAP_SYMBOL_ALIAS(accept, _accept);
8479 SWRAP_SYMBOL_ALIAS(bind, _bind);
8480 SWRAP_SYMBOL_ALIAS(connect, _connect);
8481 SWRAP_SYMBOL_ALIAS(dup, _dup);
8482 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
8483 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
8484 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
8485 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
8486 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
8487 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
8488 SWRAP_SYMBOL_ALIAS(listen, _listen);
8489 SWRAP_SYMBOL_ALIAS(readv, _readv);
8490 SWRAP_SYMBOL_ALIAS(recv, _recv);
8491 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
8492 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
8493 SWRAP_SYMBOL_ALIAS(send, _send);
8494 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
8495 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
8496 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
8497 SWRAP_SYMBOL_ALIAS(socket, _socket);
8498 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
8499 SWRAP_SYMBOL_ALIAS(writev, _writev);
8501 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */