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);
540 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
541 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
542 typedef int (*__libc_sendto)(int sockfd,
546 const struct sockaddr *dst_addr,
548 typedef int (*__libc_setsockopt)(int sockfd,
554 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
556 typedef int (*__libc_socket)(int domain, int type, int protocol);
557 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
558 #ifdef HAVE_TIMERFD_CREATE
559 typedef int (*__libc_timerfd_create)(int clockid, int flags);
561 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
562 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
564 #define SWRAP_SYMBOL_ENTRY(i) \
570 struct swrap_libc_symbols {
572 SWRAP_SYMBOL_ENTRY(accept4);
574 SWRAP_SYMBOL_ENTRY(accept);
576 SWRAP_SYMBOL_ENTRY(bind);
577 SWRAP_SYMBOL_ENTRY(close);
578 #ifdef HAVE___CLOSE_NOCANCEL
579 SWRAP_SYMBOL_ENTRY(__close_nocancel);
581 SWRAP_SYMBOL_ENTRY(connect);
582 SWRAP_SYMBOL_ENTRY(dup);
583 SWRAP_SYMBOL_ENTRY(dup2);
584 SWRAP_SYMBOL_ENTRY(fcntl);
585 SWRAP_SYMBOL_ENTRY(fopen);
587 SWRAP_SYMBOL_ENTRY(fopen64);
590 SWRAP_SYMBOL_ENTRY(eventfd);
592 SWRAP_SYMBOL_ENTRY(getpeername);
593 SWRAP_SYMBOL_ENTRY(getsockname);
594 SWRAP_SYMBOL_ENTRY(getsockopt);
595 SWRAP_SYMBOL_ENTRY(ioctl);
596 SWRAP_SYMBOL_ENTRY(listen);
597 SWRAP_SYMBOL_ENTRY(open);
599 SWRAP_SYMBOL_ENTRY(open64);
601 SWRAP_SYMBOL_ENTRY(openat);
602 SWRAP_SYMBOL_ENTRY(pipe);
603 SWRAP_SYMBOL_ENTRY(read);
604 SWRAP_SYMBOL_ENTRY(readv);
605 SWRAP_SYMBOL_ENTRY(recv);
606 SWRAP_SYMBOL_ENTRY(recvfrom);
607 SWRAP_SYMBOL_ENTRY(recvmsg);
608 SWRAP_SYMBOL_ENTRY(send);
609 SWRAP_SYMBOL_ENTRY(sendmsg);
610 SWRAP_SYMBOL_ENTRY(sendto);
611 SWRAP_SYMBOL_ENTRY(setsockopt);
613 SWRAP_SYMBOL_ENTRY(signalfd);
615 SWRAP_SYMBOL_ENTRY(socket);
616 SWRAP_SYMBOL_ENTRY(socketpair);
617 #ifdef HAVE_TIMERFD_CREATE
618 SWRAP_SYMBOL_ENTRY(timerfd_create);
620 SWRAP_SYMBOL_ENTRY(write);
621 SWRAP_SYMBOL_ENTRY(writev);
628 struct swrap_libc_symbols symbols;
632 static struct swrap swrap;
635 static char *socket_wrapper_dir(void);
637 #define LIBC_NAME "libc.so"
644 static const char *swrap_str_lib(enum swrap_lib lib)
649 case SWRAP_LIBSOCKET:
653 /* Compiler would warn us about unhandled enum value if we get here */
657 static void *swrap_load_lib_handle(enum swrap_lib lib)
659 int flags = RTLD_LAZY;
664 const char *env_preload = getenv("LD_PRELOAD");
665 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
666 bool enable_deepbind = true;
668 /* Don't do a deepbind if we run with libasan */
669 if (env_preload != NULL && strlen(env_preload) < 1024) {
670 const char *p = strstr(env_preload, "libasan.so");
672 enable_deepbind = false;
676 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
677 enable_deepbind = false;
680 if (enable_deepbind) {
681 flags |= RTLD_DEEPBIND;
686 case SWRAP_LIBSOCKET:
687 #ifdef HAVE_LIBSOCKET
688 handle = swrap.libc.socket_handle;
689 if (handle == NULL) {
690 for (i = 10; i >= 0; i--) {
691 char soname[256] = {0};
693 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
694 handle = dlopen(soname, flags);
695 if (handle != NULL) {
700 swrap.libc.socket_handle = handle;
705 handle = swrap.libc.handle;
707 if (handle == NULL) {
708 handle = dlopen(LIBC_SO, flags);
710 swrap.libc.handle = handle;
713 if (handle == NULL) {
714 for (i = 10; i >= 0; i--) {
715 char soname[256] = {0};
717 snprintf(soname, sizeof(soname), "libc.so.%d", i);
718 handle = dlopen(soname, flags);
719 if (handle != NULL) {
724 swrap.libc.handle = handle;
729 if (handle == NULL) {
731 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
733 SWRAP_LOG(SWRAP_LOG_ERROR,
734 "Failed to dlopen library: %s",
743 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
748 handle = swrap_load_lib_handle(lib);
750 func = dlsym(handle, fn_name);
752 SWRAP_LOG(SWRAP_LOG_ERROR,
753 "Failed to find %s: %s",
759 SWRAP_LOG(SWRAP_LOG_TRACE,
767 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
768 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
772 ret = pthread_mutex_lock(mutex);
774 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
775 getpid(), getppid(), caller, line, name, strerror(ret));
780 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
781 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
785 ret = pthread_mutex_unlock(mutex);
787 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
788 getpid(), getppid(), caller, line, name, strerror(ret));
794 * These macros have a thread race condition on purpose!
796 * This is an optimization to avoid locking each time we check if the symbol is
799 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
800 swrap.libc.symbols._libc_##sym_name.obj = \
801 _swrap_bind_symbol(lib, #sym_name); \
804 #define swrap_bind_symbol_libc(sym_name) \
805 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
807 #define swrap_bind_symbol_libsocket(sym_name) \
808 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
810 static void swrap_bind_symbol_all(void);
812 /****************************************************************************
814 ****************************************************************************
816 * Functions especially from libc need to be loaded individually, you can't
817 * load all at once or gdb will segfault at startup. The same applies to
818 * valgrind and has probably something todo with with the linker. So we need
819 * load each function at the point it is called the first time.
821 ****************************************************************************/
824 static int libc_accept4(int sockfd,
825 struct sockaddr *addr,
829 swrap_bind_symbol_all();
831 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
834 #else /* HAVE_ACCEPT4 */
836 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
838 swrap_bind_symbol_all();
840 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
842 #endif /* HAVE_ACCEPT4 */
844 static int libc_bind(int sockfd,
845 const struct sockaddr *addr,
848 swrap_bind_symbol_all();
850 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
853 static int libc_close(int fd)
855 swrap_bind_symbol_all();
857 return swrap.libc.symbols._libc_close.f(fd);
860 #ifdef HAVE___CLOSE_NOCANCEL
861 static int libc___close_nocancel(int fd)
863 swrap_bind_symbol_all();
865 return swrap.libc.symbols._libc___close_nocancel.f(fd);
867 #endif /* HAVE___CLOSE_NOCANCEL */
869 static int libc_connect(int sockfd,
870 const struct sockaddr *addr,
873 swrap_bind_symbol_all();
875 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
878 static int libc_dup(int fd)
880 swrap_bind_symbol_all();
882 return swrap.libc.symbols._libc_dup.f(fd);
885 static int libc_dup2(int oldfd, int newfd)
887 swrap_bind_symbol_all();
889 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
893 static int libc_eventfd(int count, int flags)
895 swrap_bind_symbol_all();
897 return swrap.libc.symbols._libc_eventfd.f(count, flags);
901 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
902 static int libc_vfcntl(int fd, int cmd, va_list ap)
907 swrap_bind_symbol_all();
909 arg = va_arg(ap, void *);
911 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
916 static int libc_getpeername(int sockfd,
917 struct sockaddr *addr,
920 swrap_bind_symbol_all();
922 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
925 static int libc_getsockname(int sockfd,
926 struct sockaddr *addr,
929 swrap_bind_symbol_all();
931 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
934 static int libc_getsockopt(int sockfd,
940 swrap_bind_symbol_all();
942 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
949 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
950 static int libc_vioctl(int d, unsigned long int request, va_list ap)
955 swrap_bind_symbol_all();
957 arg = va_arg(ap, void *);
959 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
964 static int libc_listen(int sockfd, int backlog)
966 swrap_bind_symbol_all();
968 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
971 static FILE *libc_fopen(const char *name, const char *mode)
973 swrap_bind_symbol_all();
975 return swrap.libc.symbols._libc_fopen.f(name, mode);
979 static FILE *libc_fopen64(const char *name, const char *mode)
981 swrap_bind_symbol_all();
983 return swrap.libc.symbols._libc_fopen64.f(name, mode);
985 #endif /* HAVE_FOPEN64 */
987 static void swrap_inject_o_largefile(int *flags)
989 (void)*flags; /* maybe unused */
990 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
992 if (((*flags) & O_PATH) == 0)
995 *flags |= O_LARGEFILE;
1000 static int libc_vopen(const char *pathname, int flags, va_list ap)
1005 swrap_bind_symbol_all();
1007 swrap_inject_o_largefile(&flags);
1009 if (flags & O_CREAT) {
1010 mode = va_arg(ap, int);
1012 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1017 static int libc_open(const char *pathname, int flags, ...)
1022 va_start(ap, flags);
1023 fd = libc_vopen(pathname, flags, ap);
1030 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1035 swrap_bind_symbol_all();
1037 swrap_inject_o_largefile(&flags);
1039 if (flags & O_CREAT) {
1040 mode = va_arg(ap, int);
1042 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1046 #endif /* HAVE_OPEN64 */
1048 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1053 swrap_bind_symbol_all();
1055 swrap_inject_o_largefile(&flags);
1057 if (flags & O_CREAT) {
1058 mode = va_arg(ap, int);
1060 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1069 static int libc_openat(int dirfd, const char *path, int flags, ...)
1074 va_start(ap, flags);
1075 fd = libc_vopenat(dirfd, path, flags, ap);
1082 static int libc_pipe(int pipefd[2])
1084 swrap_bind_symbol_all();
1086 return swrap.libc.symbols._libc_pipe.f(pipefd);
1089 static int libc_read(int fd, void *buf, size_t count)
1091 swrap_bind_symbol_all();
1093 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1096 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1098 swrap_bind_symbol_all();
1100 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1103 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1105 swrap_bind_symbol_all();
1107 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1110 static int libc_recvfrom(int sockfd,
1114 struct sockaddr *src_addr,
1117 swrap_bind_symbol_all();
1119 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1127 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1129 swrap_bind_symbol_all();
1131 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1134 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1136 swrap_bind_symbol_all();
1138 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1141 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1143 swrap_bind_symbol_all();
1145 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1148 static int libc_sendto(int sockfd,
1152 const struct sockaddr *dst_addr,
1155 swrap_bind_symbol_all();
1157 return swrap.libc.symbols._libc_sendto.f(sockfd,
1165 static int libc_setsockopt(int sockfd,
1171 swrap_bind_symbol_all();
1173 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1180 #ifdef HAVE_SIGNALFD
1181 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1183 swrap_bind_symbol_all();
1185 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1189 static int libc_socket(int domain, int type, int protocol)
1191 swrap_bind_symbol_all();
1193 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1196 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1198 swrap_bind_symbol_all();
1200 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1203 #ifdef HAVE_TIMERFD_CREATE
1204 static int libc_timerfd_create(int clockid, int flags)
1206 swrap_bind_symbol_all();
1208 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1212 static ssize_t libc_write(int fd, const void *buf, size_t count)
1214 swrap_bind_symbol_all();
1216 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1219 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1221 swrap_bind_symbol_all();
1223 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1226 /* DO NOT call this function during library initialization! */
1227 static void __swrap_bind_symbol_all_once(void)
1230 swrap_bind_symbol_libsocket(accept4);
1232 swrap_bind_symbol_libsocket(accept);
1234 swrap_bind_symbol_libsocket(bind);
1235 swrap_bind_symbol_libc(close);
1236 #ifdef HAVE___CLOSE_NOCANCEL
1237 swrap_bind_symbol_libc(__close_nocancel);
1239 swrap_bind_symbol_libsocket(connect);
1240 swrap_bind_symbol_libc(dup);
1241 swrap_bind_symbol_libc(dup2);
1242 swrap_bind_symbol_libc(fcntl);
1243 swrap_bind_symbol_libc(fopen);
1245 swrap_bind_symbol_libc(fopen64);
1248 swrap_bind_symbol_libc(eventfd);
1250 swrap_bind_symbol_libsocket(getpeername);
1251 swrap_bind_symbol_libsocket(getsockname);
1252 swrap_bind_symbol_libsocket(getsockopt);
1253 swrap_bind_symbol_libc(ioctl);
1254 swrap_bind_symbol_libsocket(listen);
1255 swrap_bind_symbol_libc(open);
1257 swrap_bind_symbol_libc(open64);
1259 swrap_bind_symbol_libc(openat);
1260 swrap_bind_symbol_libsocket(pipe);
1261 swrap_bind_symbol_libc(read);
1262 swrap_bind_symbol_libsocket(readv);
1263 swrap_bind_symbol_libsocket(recv);
1264 swrap_bind_symbol_libsocket(recvfrom);
1265 swrap_bind_symbol_libsocket(recvmsg);
1266 swrap_bind_symbol_libsocket(send);
1267 swrap_bind_symbol_libsocket(sendmsg);
1268 swrap_bind_symbol_libsocket(sendto);
1269 swrap_bind_symbol_libsocket(setsockopt);
1270 #ifdef HAVE_SIGNALFD
1271 swrap_bind_symbol_libsocket(signalfd);
1273 swrap_bind_symbol_libsocket(socket);
1274 swrap_bind_symbol_libsocket(socketpair);
1275 #ifdef HAVE_TIMERFD_CREATE
1276 swrap_bind_symbol_libc(timerfd_create);
1278 swrap_bind_symbol_libc(write);
1279 swrap_bind_symbol_libsocket(writev);
1282 static void swrap_bind_symbol_all(void)
1284 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1286 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1289 /*********************************************************
1290 * SWRAP HELPER FUNCTIONS
1291 *********************************************************/
1294 * We return 127.0.0.0 (default) or 10.53.57.0.
1296 * This can be controlled by:
1297 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1299 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1301 static in_addr_t swrap_ipv4_net(void)
1303 static int initialized;
1304 static in_addr_t hv;
1305 const char *net_str = NULL;
1314 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1315 if (net_str == NULL) {
1316 net_str = "127.0.0.0";
1319 ret = inet_pton(AF_INET, net_str, &nv);
1321 SWRAP_LOG(SWRAP_LOG_ERROR,
1322 "INVALID IPv4 Network [%s]",
1327 hv = ntohl(nv.s_addr);
1337 SWRAP_LOG(SWRAP_LOG_ERROR,
1338 "INVALID IPv4 Network [%s][0x%x] should be "
1339 "127.0.0.0 or 10.53.57.0",
1340 net_str, (unsigned)hv);
1348 * This returns 127.255.255.255 or 10.255.255.255
1350 static in_addr_t swrap_ipv4_bcast(void)
1354 hv = swrap_ipv4_net();
1355 hv |= IN_CLASSA_HOST;
1361 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1363 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1367 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1368 SWRAP_LOG(SWRAP_LOG_ERROR,
1369 "swrap_ipv4_iface(%u) invalid!",
1375 hv = swrap_ipv4_net();
1385 static const struct in6_addr *swrap_ipv6(void)
1387 static struct in6_addr v;
1388 static int initialized;
1396 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1405 static void set_port(int family, int prt, struct swrap_address *addr)
1409 addr->sa.in.sin_port = htons(prt);
1413 addr->sa.in6.sin6_port = htons(prt);
1419 static size_t socket_length(int family)
1423 return sizeof(struct sockaddr_in);
1426 return sizeof(struct sockaddr_in6);
1432 struct swrap_sockaddr_buf {
1436 static const char *swrap_sockaddr_string(struct swrap_sockaddr_buf *buf,
1437 const struct sockaddr *saddr)
1439 unsigned int port = 0;
1440 char addr[64] = {0,};
1442 switch (saddr->sa_family) {
1444 const struct sockaddr_in *in =
1445 (const struct sockaddr_in *)(const void *)saddr;
1447 port = ntohs(in->sin_port);
1449 inet_ntop(saddr->sa_family,
1451 addr, sizeof(addr));
1456 const struct sockaddr_in6 *in6 =
1457 (const struct sockaddr_in6 *)(const void *)saddr;
1459 port = ntohs(in6->sin6_port);
1461 inet_ntop(saddr->sa_family,
1463 addr, sizeof(addr));
1468 snprintf(addr, sizeof(addr),
1469 "<Unknown address family %u>",
1474 snprintf(buf->str, sizeof(buf->str),
1475 "addr[%s]/port[%u]",
1481 static struct socket_info *swrap_get_socket_info(int si_index)
1483 return (struct socket_info *)(&(sockets[si_index].info));
1486 static int swrap_get_refcount(struct socket_info *si)
1488 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1489 return sic->meta.refcount;
1492 static void swrap_inc_refcount(struct socket_info *si)
1494 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1496 sic->meta.refcount += 1;
1499 static void swrap_dec_refcount(struct socket_info *si)
1501 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1503 sic->meta.refcount -= 1;
1506 static int swrap_get_next_free(struct socket_info *si)
1508 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1510 return sic->meta.next_free;
1513 static void swrap_set_next_free(struct socket_info *si, int next_free)
1515 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1517 sic->meta.next_free = next_free;
1520 static int swrap_un_path(struct sockaddr_un *un,
1521 const char *swrap_dir,
1528 ret = snprintf(un->sun_path,
1529 sizeof(un->sun_path),
1535 if ((size_t)ret >= sizeof(un->sun_path)) {
1536 return ENAMETOOLONG;
1542 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1543 const char *swrap_dir)
1547 ret = snprintf(un->sun_path,
1548 sizeof(un->sun_path),
1552 if ((size_t)ret >= sizeof(un->sun_path)) {
1553 return ENAMETOOLONG;
1559 static bool swrap_dir_usable(const char *swrap_dir)
1561 struct sockaddr_un un;
1564 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1569 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1577 static char *socket_wrapper_dir(void)
1579 char *swrap_dir = NULL;
1580 char *s = getenv("SOCKET_WRAPPER_DIR");
1584 if (s == NULL || s[0] == '\0') {
1585 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1589 swrap_dir = realpath(s, NULL);
1590 if (swrap_dir == NULL) {
1591 SWRAP_LOG(SWRAP_LOG_ERROR,
1592 "Unable to resolve socket_wrapper dir path: %s - %s",
1598 ok = swrap_dir_usable(swrap_dir);
1605 ok = swrap_dir_usable(s);
1607 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1611 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1613 SWRAP_LOG(SWRAP_LOG_ERROR,
1614 "realpath(SOCKET_WRAPPER_DIR) too long and "
1615 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1620 swrap_dir = strdup(s);
1621 if (swrap_dir == NULL) {
1622 SWRAP_LOG(SWRAP_LOG_ERROR,
1623 "Unable to duplicate socket_wrapper dir path");
1627 SWRAP_LOG(SWRAP_LOG_WARN,
1628 "realpath(SOCKET_WRAPPER_DIR) too long, "
1629 "using original SOCKET_WRAPPER_DIR\n");
1632 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1636 static unsigned int socket_wrapper_mtu(void)
1638 static unsigned int max_mtu = 0;
1643 swrap_mutex_lock(&mtu_update_mutex);
1649 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1651 s = getenv("SOCKET_WRAPPER_MTU");
1656 tmp = strtol(s, &endp, 10);
1661 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1667 swrap_mutex_unlock(&mtu_update_mutex);
1671 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1673 pthread_mutexattr_t ma;
1674 bool need_destroy = false;
1677 #define __CHECK(cmd) do { \
1680 SWRAP_LOG(SWRAP_LOG_ERROR, \
1681 "%s: %s - failed %d", \
1687 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1688 __CHECK(pthread_mutexattr_init(&ma));
1689 need_destroy = true;
1690 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1691 __CHECK(pthread_mutex_init(m, &ma));
1694 pthread_mutexattr_destroy(&ma);
1699 static size_t socket_wrapper_max_sockets(void)
1705 if (socket_info_max != 0) {
1706 return socket_info_max;
1709 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1711 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1712 if (s == NULL || s[0] == '\0') {
1716 tmp = strtoul(s, &endp, 10);
1721 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1722 SWRAP_LOG(SWRAP_LOG_ERROR,
1723 "Invalid number of sockets specified, "
1724 "using default (%zu)",
1728 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1729 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1730 SWRAP_LOG(SWRAP_LOG_ERROR,
1731 "Invalid number of sockets specified, "
1732 "using maximum (%zu).",
1736 socket_info_max = tmp;
1739 return socket_info_max;
1742 static void socket_wrapper_init_fds_idx(void)
1747 if (socket_fds_idx != NULL) {
1751 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1753 SWRAP_LOG(SWRAP_LOG_ERROR,
1754 "Failed to allocate socket fds index array: %s",
1759 for (i = 0; i < socket_fds_max; i++) {
1763 socket_fds_idx = tmp;
1766 static void socket_wrapper_init_sockets(void)
1772 swrap_bind_symbol_all();
1774 swrap_mutex_lock(&sockets_mutex);
1776 if (sockets != NULL) {
1777 swrap_mutex_unlock(&sockets_mutex);
1781 SWRAP_LOG(SWRAP_LOG_DEBUG,
1782 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1783 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1786 * Intialize the static cache early before
1787 * any thread is able to start.
1789 (void)swrap_ipv4_net();
1791 socket_wrapper_init_fds_idx();
1793 /* Needs to be called inside the sockets_mutex lock here. */
1794 max_sockets = socket_wrapper_max_sockets();
1796 sockets = (struct socket_info_container *)calloc(max_sockets,
1797 sizeof(struct socket_info_container));
1799 if (sockets == NULL) {
1800 SWRAP_LOG(SWRAP_LOG_ERROR,
1801 "Failed to allocate sockets array: %s",
1803 swrap_mutex_unlock(&sockets_mutex);
1807 swrap_mutex_lock(&first_free_mutex);
1808 swrap_mutex_lock(&sockets_si_global);
1812 for (i = 0; i < max_sockets; i++) {
1813 swrap_set_next_free(&sockets[i].info, i+1);
1816 /* mark the end of the free list */
1817 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1819 swrap_mutex_unlock(&sockets_si_global);
1820 swrap_mutex_unlock(&first_free_mutex);
1821 swrap_mutex_unlock(&sockets_mutex);
1827 bool socket_wrapper_enabled(void)
1829 char *s = socket_wrapper_dir();
1837 socket_wrapper_init_sockets();
1842 static unsigned int socket_wrapper_default_iface(void)
1844 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1847 if (sscanf(s, "%u", &iface) == 1) {
1848 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1854 return 1;/* 127.0.0.1 */
1857 static void set_socket_info_index(int fd, int idx)
1859 SWRAP_LOG(SWRAP_LOG_TRACE,
1862 socket_fds_idx[fd] = idx;
1863 /* This builtin issues a full memory barrier. */
1864 __sync_synchronize();
1867 static void reset_socket_info_index(int fd)
1869 SWRAP_LOG(SWRAP_LOG_TRACE,
1872 set_socket_info_index(fd, -1);
1875 static int find_socket_info_index(int fd)
1881 if (socket_fds_idx == NULL) {
1885 if ((size_t)fd >= socket_fds_max) {
1887 * Do not add a log here as some applications do stupid things
1890 * for (fd = 0; fd <= getdtablesize(); fd++) {
1894 * This would produce millions of lines of debug messages.
1897 SWRAP_LOG(SWRAP_LOG_ERROR,
1898 "Looking for a socket info for the fd %d is over the "
1899 "max socket index limit of %zu.",
1906 /* This builtin issues a full memory barrier. */
1907 __sync_synchronize();
1908 return socket_fds_idx[fd];
1911 static int swrap_add_socket_info(const struct socket_info *si_input)
1913 struct socket_info *si = NULL;
1916 if (si_input == NULL) {
1921 swrap_mutex_lock(&first_free_mutex);
1922 if (first_free == -1) {
1927 si_index = first_free;
1928 si = swrap_get_socket_info(si_index);
1932 first_free = swrap_get_next_free(si);
1934 swrap_inc_refcount(si);
1936 SWRAP_UNLOCK_SI(si);
1939 swrap_mutex_unlock(&first_free_mutex);
1944 static int swrap_create_socket(struct socket_info *si, int fd)
1948 if ((size_t)fd >= socket_fds_max) {
1949 SWRAP_LOG(SWRAP_LOG_ERROR,
1950 "The max socket index limit of %zu has been reached, "
1958 idx = swrap_add_socket_info(si);
1963 set_socket_info_index(fd, idx);
1968 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1975 p = strrchr(un->sun_path, '/');
1976 if (p) p++; else p = un->sun_path;
1978 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1979 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1985 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1986 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1993 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1999 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
2003 case SOCKET_TYPE_CHAR_TCP:
2004 case SOCKET_TYPE_CHAR_UDP: {
2005 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
2007 if ((*len) < sizeof(*in2)) {
2008 SWRAP_LOG(SWRAP_LOG_ERROR,
2009 "V4: *len(%zu) < sizeof(*in2)=%zu",
2010 (size_t)*len, sizeof(*in2));
2015 memset(in2, 0, sizeof(*in2));
2016 in2->sin_family = AF_INET;
2017 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2018 in2->sin_port = htons(prt);
2020 *len = sizeof(*in2);
2024 case SOCKET_TYPE_CHAR_TCP_V6:
2025 case SOCKET_TYPE_CHAR_UDP_V6: {
2026 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
2028 if ((*len) < sizeof(*in2)) {
2029 SWRAP_LOG(SWRAP_LOG_ERROR,
2030 "V6: *len(%zu) < sizeof(*in2)=%zu",
2031 (size_t)*len, sizeof(*in2));
2032 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
2037 memset(in2, 0, sizeof(*in2));
2038 in2->sin6_family = AF_INET6;
2039 in2->sin6_addr = *swrap_ipv6();
2040 in2->sin6_addr.s6_addr[15] = iface;
2041 in2->sin6_port = htons(prt);
2043 *len = sizeof(*in2);
2048 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2057 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2064 char *swrap_dir = NULL;
2066 if (bcast) *bcast = 0;
2068 switch (inaddr->sa_family) {
2070 const struct sockaddr_in *in =
2071 (const struct sockaddr_in *)(const void *)inaddr;
2072 unsigned int addr = ntohl(in->sin_addr.s_addr);
2076 const unsigned int sw_net_addr = swrap_ipv4_net();
2077 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2081 u_type = SOCKET_TYPE_CHAR_TCP;
2084 u_type = SOCKET_TYPE_CHAR_UDP;
2085 a_type = SOCKET_TYPE_CHAR_UDP;
2086 b_type = SOCKET_TYPE_CHAR_UDP;
2089 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2090 errno = ESOCKTNOSUPPORT;
2094 prt = ntohs(in->sin_port);
2095 if (a_type && addr == 0xFFFFFFFF) {
2096 /* 255.255.255.255 only udp */
2099 iface = socket_wrapper_default_iface();
2100 } else if (b_type && addr == sw_bcast_addr) {
2109 iface = socket_wrapper_default_iface();
2110 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2111 /* 127.0.0.X or 10.53.57.X */
2114 iface = (addr & 0x000000FF);
2116 struct swrap_sockaddr_buf buf = {};
2117 SWRAP_LOG(SWRAP_LOG_WARN,
2119 swrap_sockaddr_string(&buf, inaddr));
2120 errno = ENETUNREACH;
2123 if (bcast) *bcast = is_bcast;
2128 const struct sockaddr_in6 *in =
2129 (const struct sockaddr_in6 *)(const void *)inaddr;
2130 struct in6_addr cmp1, cmp2;
2134 type = SOCKET_TYPE_CHAR_TCP_V6;
2137 type = SOCKET_TYPE_CHAR_UDP_V6;
2140 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2141 errno = ESOCKTNOSUPPORT;
2145 /* XXX no multicast/broadcast */
2147 prt = ntohs(in->sin6_port);
2149 cmp1 = *swrap_ipv6();
2150 cmp2 = in->sin6_addr;
2151 cmp2.s6_addr[15] = 0;
2152 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2153 iface = in->sin6_addr.s6_addr[15];
2155 struct swrap_sockaddr_buf buf = {};
2156 SWRAP_LOG(SWRAP_LOG_WARN,
2158 swrap_sockaddr_string(&buf, inaddr));
2159 errno = ENETUNREACH;
2167 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2168 errno = ENETUNREACH;
2173 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2178 swrap_dir = socket_wrapper_dir();
2179 if (swrap_dir == NULL) {
2185 swrap_un_path_EINVAL(un, swrap_dir);
2186 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2187 SAFE_FREE(swrap_dir);
2188 /* the caller need to do more processing */
2192 swrap_un_path(un, swrap_dir, type, iface, prt);
2193 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2195 SAFE_FREE(swrap_dir);
2200 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2208 char *swrap_dir = NULL;
2210 if (bcast) *bcast = 0;
2212 switch (si->family) {
2214 const struct sockaddr_in *in =
2215 (const struct sockaddr_in *)(const void *)inaddr;
2216 unsigned int addr = ntohl(in->sin_addr.s_addr);
2221 const unsigned int sw_net_addr = swrap_ipv4_net();
2222 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2224 prt = ntohs(in->sin_port);
2228 u_type = SOCKET_TYPE_CHAR_TCP;
2229 d_type = SOCKET_TYPE_CHAR_TCP;
2232 u_type = SOCKET_TYPE_CHAR_UDP;
2233 d_type = SOCKET_TYPE_CHAR_UDP;
2234 a_type = SOCKET_TYPE_CHAR_UDP;
2235 b_type = SOCKET_TYPE_CHAR_UDP;
2238 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2239 errno = ESOCKTNOSUPPORT;
2247 iface = socket_wrapper_default_iface();
2248 } else if (a_type && addr == 0xFFFFFFFF) {
2249 /* 255.255.255.255 only udp */
2252 iface = socket_wrapper_default_iface();
2253 } else if (b_type && addr == sw_bcast_addr) {
2254 /* 127.255.255.255 only udp */
2257 iface = socket_wrapper_default_iface();
2258 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2262 iface = (addr & 0x000000FF);
2264 errno = EADDRNOTAVAIL;
2268 /* Store the bind address for connect() */
2269 if (si->bindname.sa_socklen == 0) {
2270 struct sockaddr_in bind_in;
2271 socklen_t blen = sizeof(struct sockaddr_in);
2273 ZERO_STRUCT(bind_in);
2274 bind_in.sin_family = in->sin_family;
2275 bind_in.sin_port = in->sin_port;
2276 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2277 si->bindname.sa_socklen = blen;
2278 memcpy(&si->bindname.sa.in, &bind_in, blen);
2285 const struct sockaddr_in6 *in =
2286 (const struct sockaddr_in6 *)(const void *)inaddr;
2287 struct in6_addr cmp1, cmp2;
2291 type = SOCKET_TYPE_CHAR_TCP_V6;
2294 type = SOCKET_TYPE_CHAR_UDP_V6;
2297 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2298 errno = ESOCKTNOSUPPORT;
2302 /* XXX no multicast/broadcast */
2304 prt = ntohs(in->sin6_port);
2306 cmp1 = *swrap_ipv6();
2307 cmp2 = in->sin6_addr;
2308 cmp2.s6_addr[15] = 0;
2309 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2310 iface = socket_wrapper_default_iface();
2311 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2312 iface = in->sin6_addr.s6_addr[15];
2314 errno = EADDRNOTAVAIL;
2318 /* Store the bind address for connect() */
2319 if (si->bindname.sa_socklen == 0) {
2320 struct sockaddr_in6 bind_in;
2321 socklen_t blen = sizeof(struct sockaddr_in6);
2323 ZERO_STRUCT(bind_in);
2324 bind_in.sin6_family = in->sin6_family;
2325 bind_in.sin6_port = in->sin6_port;
2327 bind_in.sin6_addr = *swrap_ipv6();
2328 bind_in.sin6_addr.s6_addr[15] = iface;
2330 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2331 si->bindname.sa_socklen = blen;
2338 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2339 errno = EADDRNOTAVAIL;
2344 if (bcast) *bcast = is_bcast;
2346 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2351 swrap_dir = socket_wrapper_dir();
2352 if (swrap_dir == NULL) {
2358 /* handle auto-allocation of ephemeral ports */
2359 for (prt = 5001; prt < 10000; prt++) {
2360 swrap_un_path(un, swrap_dir, type, iface, prt);
2361 if (stat(un->sun_path, &st) == 0) continue;
2363 set_port(si->family, prt, &si->myname);
2364 set_port(si->family, prt, &si->bindname);
2371 SAFE_FREE(swrap_dir);
2376 swrap_un_path(un, swrap_dir, type, iface, prt);
2377 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2379 SAFE_FREE(swrap_dir);
2384 static struct socket_info *find_socket_info(int fd)
2386 int idx = find_socket_info_index(fd);
2392 return swrap_get_socket_info(idx);
2396 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2398 struct socket_info_fd *f;
2399 const struct socket_info *last_s = NULL;
2401 /* first catch invalid input */
2402 switch (sa->sa_family) {
2404 if (len < sizeof(struct sockaddr_in)) {
2410 if (len < sizeof(struct sockaddr_in6)) {
2420 for (f = socket_fds; f; f = f->next) {
2421 struct socket_info *s = swrap_get_socket_info(f->si_index);
2428 if (s->myname == NULL) {
2431 if (s->myname->sa_family != sa->sa_family) {
2434 switch (s->myname->sa_family) {
2436 struct sockaddr_in *sin1, *sin2;
2438 sin1 = (struct sockaddr_in *)s->myname;
2439 sin2 = (struct sockaddr_in *)sa;
2441 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2444 if (sin1->sin_port != sin2->sin_port) {
2447 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2457 struct sockaddr_in6 *sin1, *sin2;
2459 sin1 = (struct sockaddr_in6 *)s->myname;
2460 sin2 = (struct sockaddr_in6 *)sa;
2462 if (sin1->sin6_port != sin2->sin6_port) {
2465 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2487 static void swrap_remove_stale(int fd);
2489 static int sockaddr_convert_to_un(struct socket_info *si,
2490 const struct sockaddr *in_addr,
2492 struct sockaddr_un *out_addr,
2496 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2498 (void) in_len; /* unused */
2500 if (out_addr == NULL) {
2504 out->sa_family = AF_UNIX;
2505 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2506 out->sa_len = sizeof(*out_addr);
2509 switch (in_addr->sa_family) {
2511 const struct sockaddr_in *sin;
2512 if (si->family != AF_INET) {
2515 if (in_len < sizeof(struct sockaddr_in)) {
2518 sin = (const struct sockaddr_in *)(const void *)in_addr;
2519 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2524 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2525 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2539 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2540 errno = ESOCKTNOSUPPORT;
2544 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2546 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2552 errno = EAFNOSUPPORT;
2553 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2557 static int sockaddr_convert_from_un(const struct socket_info *si,
2558 const struct sockaddr_un *in_addr,
2559 socklen_t un_addrlen,
2561 struct sockaddr *out_addr,
2562 socklen_t *out_addrlen)
2566 if (out_addr == NULL || out_addrlen == NULL)
2569 if (un_addrlen == 0) {
2584 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2585 errno = ESOCKTNOSUPPORT;
2588 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2589 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2590 out_addr->sa_len = *out_addrlen;
2597 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2598 errno = EAFNOSUPPORT;
2602 enum swrap_packet_type {
2604 SWRAP_CONNECT_UNREACH,
2612 SWRAP_SENDTO_UNREACH,
2623 struct swrap_file_hdr {
2625 uint16_t version_major;
2626 uint16_t version_minor;
2629 uint32_t frame_max_len;
2630 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2633 #define SWRAP_FILE_HDR_SIZE 24
2635 struct swrap_packet_frame {
2637 uint32_t micro_seconds;
2638 uint32_t recorded_length;
2639 uint32_t full_length;
2641 #define SWRAP_PACKET_FRAME_SIZE 16
2643 union swrap_packet_ip {
2647 uint16_t packet_length;
2648 uint16_t identification;
2653 uint16_t hdr_checksum;
2657 #define SWRAP_PACKET_IP_V4_SIZE 20
2660 uint8_t flow_label_high;
2661 uint16_t flow_label_low;
2662 uint16_t payload_length;
2663 uint8_t next_header;
2665 uint8_t src_addr[16];
2666 uint8_t dest_addr[16];
2668 #define SWRAP_PACKET_IP_V6_SIZE 40
2670 #define SWRAP_PACKET_IP_SIZE 40
2672 union swrap_packet_payload {
2674 uint16_t source_port;
2684 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2686 uint16_t source_port;
2691 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2698 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2705 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2707 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2709 #define SWRAP_PACKET_MIN_ALLOC \
2710 (SWRAP_PACKET_FRAME_SIZE + \
2711 SWRAP_PACKET_IP_SIZE + \
2712 SWRAP_PACKET_PAYLOAD_SIZE)
2714 static const char *swrap_pcap_init_file(void)
2716 static int initialized = 0;
2717 static const char *s = NULL;
2718 static const struct swrap_file_hdr h;
2719 static const struct swrap_packet_frame f;
2720 static const union swrap_packet_ip i;
2721 static const union swrap_packet_payload p;
2723 if (initialized == 1) {
2729 * TODO: don't use the structs use plain buffer offsets
2730 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2732 * for now make sure we disable PCAP support
2733 * if the struct has alignment!
2735 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2738 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2741 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2744 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2747 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2750 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2753 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2756 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2759 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2762 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2766 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2770 if (strncmp(s, "./", 2) == 0) {
2773 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2777 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2778 const struct sockaddr *src,
2779 const struct sockaddr *dest,
2781 const uint8_t *payload,
2783 unsigned long tcp_seqno,
2784 unsigned long tcp_ack,
2785 unsigned char tcp_ctl,
2787 size_t *_packet_len)
2789 uint8_t *base = NULL;
2790 uint8_t *buf = NULL;
2793 struct swrap_packet_frame *frame;
2797 union swrap_packet_ip *ip;
2799 union swrap_packet_payload *pay;
2802 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2803 size_t wire_hdr_len = 0;
2804 size_t wire_len = 0;
2805 size_t ip_hdr_len = 0;
2806 size_t icmp_hdr_len = 0;
2807 size_t icmp_truncate_len = 0;
2808 uint8_t protocol = 0, icmp_protocol = 0;
2809 const struct sockaddr_in *src_in = NULL;
2810 const struct sockaddr_in *dest_in = NULL;
2812 const struct sockaddr_in6 *src_in6 = NULL;
2813 const struct sockaddr_in6 *dest_in6 = NULL;
2818 switch (src->sa_family) {
2820 src_in = (const struct sockaddr_in *)(const void *)src;
2821 dest_in = (const struct sockaddr_in *)(const void *)dest;
2822 src_port = src_in->sin_port;
2823 dest_port = dest_in->sin_port;
2824 ip_hdr_len = sizeof(i.ip->v4);
2828 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2829 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2830 src_port = src_in6->sin6_port;
2831 dest_port = dest_in6->sin6_port;
2832 ip_hdr_len = sizeof(i.ip->v6);
2839 switch (socket_type) {
2841 protocol = 0x06; /* TCP */
2842 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2843 wire_len = wire_hdr_len + payload_len;
2847 protocol = 0x11; /* UDP */
2848 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2849 wire_len = wire_hdr_len + payload_len;
2857 icmp_protocol = protocol;
2858 switch (src->sa_family) {
2860 protocol = 0x01; /* ICMPv4 */
2861 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2865 protocol = 0x3A; /* ICMPv6 */
2866 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2870 if (wire_len > 64 ) {
2871 icmp_truncate_len = wire_len - 64;
2873 wire_len += icmp_hdr_len;
2876 packet_len = nonwire_len + wire_len;
2877 alloc_len = packet_len;
2878 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2879 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2882 base = (uint8_t *)calloc(1, alloc_len);
2890 f.frame->seconds = tval->tv_sec;
2891 f.frame->micro_seconds = tval->tv_usec;
2892 f.frame->recorded_length = wire_len - icmp_truncate_len;
2893 f.frame->full_length = wire_len - icmp_truncate_len;
2895 buf += SWRAP_PACKET_FRAME_SIZE;
2898 switch (src->sa_family) {
2900 if (src_in == NULL || dest_in == NULL) {
2905 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2906 i.ip->v4.tos = 0x00;
2907 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2908 i.ip->v4.identification = htons(0xFFFF);
2909 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2910 i.ip->v4.fragment = htons(0x0000);
2911 i.ip->v4.ttl = 0xFF;
2912 i.ip->v4.protocol = protocol;
2913 i.ip->v4.hdr_checksum = htons(0x0000);
2914 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2915 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2916 buf += SWRAP_PACKET_IP_V4_SIZE;
2920 if (src_in6 == NULL || dest_in6 == NULL) {
2925 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2926 i.ip->v6.flow_label_high = 0x00;
2927 i.ip->v6.flow_label_low = 0x0000;
2928 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2929 i.ip->v6.next_header = protocol;
2930 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2931 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2932 buf += SWRAP_PACKET_IP_V6_SIZE;
2938 pay = (union swrap_packet_payload *)(void *)buf;
2939 switch (src->sa_family) {
2941 pay->icmp4.type = 0x03; /* destination unreachable */
2942 pay->icmp4.code = 0x01; /* host unreachable */
2943 pay->icmp4.checksum = htons(0x0000);
2944 pay->icmp4.unused = htonl(0x00000000);
2946 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2948 /* set the ip header in the ICMP payload */
2950 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2951 i.ip->v4.tos = 0x00;
2952 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2953 i.ip->v4.identification = htons(0xFFFF);
2954 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2955 i.ip->v4.fragment = htons(0x0000);
2956 i.ip->v4.ttl = 0xFF;
2957 i.ip->v4.protocol = icmp_protocol;
2958 i.ip->v4.hdr_checksum = htons(0x0000);
2959 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2960 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2962 buf += SWRAP_PACKET_IP_V4_SIZE;
2964 src_port = dest_in->sin_port;
2965 dest_port = src_in->sin_port;
2969 pay->icmp6.type = 0x01; /* destination unreachable */
2970 pay->icmp6.code = 0x03; /* address unreachable */
2971 pay->icmp6.checksum = htons(0x0000);
2972 pay->icmp6.unused = htonl(0x00000000);
2973 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2975 /* set the ip header in the ICMP payload */
2977 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2978 i.ip->v6.flow_label_high = 0x00;
2979 i.ip->v6.flow_label_low = 0x0000;
2980 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2981 i.ip->v6.next_header = protocol;
2982 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2983 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2985 buf += SWRAP_PACKET_IP_V6_SIZE;
2987 src_port = dest_in6->sin6_port;
2988 dest_port = src_in6->sin6_port;
2994 pay = (union swrap_packet_payload *)(void *)buf;
2996 switch (socket_type) {
2998 pay->tcp.source_port = src_port;
2999 pay->tcp.dest_port = dest_port;
3000 pay->tcp.seq_num = htonl(tcp_seqno);
3001 pay->tcp.ack_num = htonl(tcp_ack);
3002 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
3003 pay->tcp.control = tcp_ctl;
3004 pay->tcp.window = htons(0x7FFF);
3005 pay->tcp.checksum = htons(0x0000);
3006 pay->tcp.urg = htons(0x0000);
3007 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
3012 pay->udp.source_port = src_port;
3013 pay->udp.dest_port = dest_port;
3014 pay->udp.length = htons(8 + payload_len);
3015 pay->udp.checksum = htons(0x0000);
3016 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
3021 if (payload && payload_len > 0) {
3022 memcpy(buf, payload, payload_len);
3025 *_packet_len = packet_len - icmp_truncate_len;
3029 static int swrap_pcap_get_fd(const char *fname)
3037 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
3039 struct swrap_file_hdr file_hdr;
3040 file_hdr.magic = 0xA1B2C3D4;
3041 file_hdr.version_major = 0x0002;
3042 file_hdr.version_minor = 0x0004;
3043 file_hdr.timezone = 0x00000000;
3044 file_hdr.sigfigs = 0x00000000;
3045 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3046 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3048 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3055 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3060 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3061 const struct sockaddr *addr,
3062 enum swrap_packet_type type,
3063 const void *buf, size_t len,
3066 const struct sockaddr *src_addr;
3067 const struct sockaddr *dest_addr;
3068 unsigned long tcp_seqno = 0;
3069 unsigned long tcp_ack = 0;
3070 unsigned char tcp_ctl = 0;
3071 int unreachable = 0;
3075 switch (si->family) {
3087 case SWRAP_CONNECT_SEND:
3088 if (si->type != SOCK_STREAM) {
3092 src_addr = &si->myname.sa.s;
3095 tcp_seqno = si->io.pck_snd;
3096 tcp_ack = si->io.pck_rcv;
3097 tcp_ctl = 0x02; /* SYN */
3099 si->io.pck_snd += 1;
3103 case SWRAP_CONNECT_RECV:
3104 if (si->type != SOCK_STREAM) {
3108 dest_addr = &si->myname.sa.s;
3111 tcp_seqno = si->io.pck_rcv;
3112 tcp_ack = si->io.pck_snd;
3113 tcp_ctl = 0x12; /** SYN,ACK */
3115 si->io.pck_rcv += 1;
3119 case SWRAP_CONNECT_UNREACH:
3120 if (si->type != SOCK_STREAM) {
3124 dest_addr = &si->myname.sa.s;
3127 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3128 tcp_seqno = si->io.pck_snd - 1;
3129 tcp_ack = si->io.pck_rcv;
3130 tcp_ctl = 0x02; /* SYN */
3135 case SWRAP_CONNECT_ACK:
3136 if (si->type != SOCK_STREAM) {
3140 src_addr = &si->myname.sa.s;
3143 tcp_seqno = si->io.pck_snd;
3144 tcp_ack = si->io.pck_rcv;
3145 tcp_ctl = 0x10; /* ACK */
3149 case SWRAP_ACCEPT_SEND:
3150 if (si->type != SOCK_STREAM) {
3154 dest_addr = &si->myname.sa.s;
3157 tcp_seqno = si->io.pck_rcv;
3158 tcp_ack = si->io.pck_snd;
3159 tcp_ctl = 0x02; /* SYN */
3161 si->io.pck_rcv += 1;
3165 case SWRAP_ACCEPT_RECV:
3166 if (si->type != SOCK_STREAM) {
3170 src_addr = &si->myname.sa.s;
3173 tcp_seqno = si->io.pck_snd;
3174 tcp_ack = si->io.pck_rcv;
3175 tcp_ctl = 0x12; /* SYN,ACK */
3177 si->io.pck_snd += 1;
3181 case SWRAP_ACCEPT_ACK:
3182 if (si->type != SOCK_STREAM) {
3186 dest_addr = &si->myname.sa.s;
3189 tcp_seqno = si->io.pck_rcv;
3190 tcp_ack = si->io.pck_snd;
3191 tcp_ctl = 0x10; /* ACK */
3196 src_addr = &si->myname.sa.s;
3197 dest_addr = &si->peername.sa.s;
3199 tcp_seqno = si->io.pck_snd;
3200 tcp_ack = si->io.pck_rcv;
3201 tcp_ctl = 0x18; /* PSH,ACK */
3203 si->io.pck_snd += len;
3207 case SWRAP_SEND_RST:
3208 dest_addr = &si->myname.sa.s;
3209 src_addr = &si->peername.sa.s;
3211 if (si->type == SOCK_DGRAM) {
3212 return swrap_pcap_marshall_packet(si,
3214 SWRAP_SENDTO_UNREACH,
3220 tcp_seqno = si->io.pck_rcv;
3221 tcp_ack = si->io.pck_snd;
3222 tcp_ctl = 0x14; /** RST,ACK */
3226 case SWRAP_PENDING_RST:
3227 dest_addr = &si->myname.sa.s;
3228 src_addr = &si->peername.sa.s;
3230 if (si->type == SOCK_DGRAM) {
3234 tcp_seqno = si->io.pck_rcv;
3235 tcp_ack = si->io.pck_snd;
3236 tcp_ctl = 0x14; /* RST,ACK */
3241 dest_addr = &si->myname.sa.s;
3242 src_addr = &si->peername.sa.s;
3244 tcp_seqno = si->io.pck_rcv;
3245 tcp_ack = si->io.pck_snd;
3246 tcp_ctl = 0x18; /* PSH,ACK */
3248 si->io.pck_rcv += len;
3252 case SWRAP_RECV_RST:
3253 dest_addr = &si->myname.sa.s;
3254 src_addr = &si->peername.sa.s;
3256 if (si->type == SOCK_DGRAM) {
3260 tcp_seqno = si->io.pck_rcv;
3261 tcp_ack = si->io.pck_snd;
3262 tcp_ctl = 0x14; /* RST,ACK */
3267 src_addr = &si->myname.sa.s;
3270 si->io.pck_snd += len;
3274 case SWRAP_SENDTO_UNREACH:
3275 dest_addr = &si->myname.sa.s;
3282 case SWRAP_RECVFROM:
3283 dest_addr = &si->myname.sa.s;
3286 si->io.pck_rcv += len;
3290 case SWRAP_CLOSE_SEND:
3291 if (si->type != SOCK_STREAM) {
3295 src_addr = &si->myname.sa.s;
3296 dest_addr = &si->peername.sa.s;
3298 tcp_seqno = si->io.pck_snd;
3299 tcp_ack = si->io.pck_rcv;
3300 tcp_ctl = 0x11; /* FIN, ACK */
3302 si->io.pck_snd += 1;
3306 case SWRAP_CLOSE_RECV:
3307 if (si->type != SOCK_STREAM) {
3311 dest_addr = &si->myname.sa.s;
3312 src_addr = &si->peername.sa.s;
3314 tcp_seqno = si->io.pck_rcv;
3315 tcp_ack = si->io.pck_snd;
3316 tcp_ctl = 0x11; /* FIN,ACK */
3318 si->io.pck_rcv += 1;
3322 case SWRAP_CLOSE_ACK:
3323 if (si->type != SOCK_STREAM) {
3327 src_addr = &si->myname.sa.s;
3328 dest_addr = &si->peername.sa.s;
3330 tcp_seqno = si->io.pck_snd;
3331 tcp_ack = si->io.pck_rcv;
3332 tcp_ctl = 0x10; /* ACK */
3339 swrapGetTimeOfDay(&tv);
3341 return swrap_pcap_packet_init(&tv,
3345 (const uint8_t *)buf,
3354 static void swrap_pcap_dump_packet(struct socket_info *si,
3355 const struct sockaddr *addr,
3356 enum swrap_packet_type type,
3357 const void *buf, size_t len)
3359 const char *file_name;
3361 size_t packet_len = 0;
3364 swrap_mutex_lock(&pcap_dump_mutex);
3366 file_name = swrap_pcap_init_file();
3371 packet = swrap_pcap_marshall_packet(si,
3377 if (packet == NULL) {
3381 fd = swrap_pcap_get_fd(file_name);
3383 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3392 swrap_mutex_unlock(&pcap_dump_mutex);
3395 /****************************************************************************
3397 ***************************************************************************/
3399 #ifdef HAVE_SIGNALFD
3400 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3404 rc = libc_signalfd(fd, mask, flags);
3406 swrap_remove_stale(fd);
3412 int signalfd(int fd, const sigset_t *mask, int flags)
3414 return swrap_signalfd(fd, mask, flags);
3418 /****************************************************************************
3420 ***************************************************************************/
3422 static int swrap_socket(int family, int type, int protocol)
3424 struct socket_info *si = NULL;
3425 struct socket_info _si = { 0 };
3428 int real_type = type;
3431 * Remove possible addition flags passed to socket() so
3432 * do not fail checking the type.
3433 * See https://lwn.net/Articles/281965/
3436 real_type &= ~SOCK_CLOEXEC;
3438 #ifdef SOCK_NONBLOCK
3439 real_type &= ~SOCK_NONBLOCK;
3442 if (!socket_wrapper_enabled()) {
3443 return libc_socket(family, type, protocol);
3454 #endif /* AF_NETLINK */
3457 #endif /* AF_PACKET */
3459 fd = libc_socket(family, type, protocol);
3461 /* Check if we have a stale fd and remove it */
3462 swrap_remove_stale(fd);
3463 SWRAP_LOG(SWRAP_LOG_TRACE,
3464 "Unix socket fd=%d",
3469 errno = EAFNOSUPPORT;
3473 switch (real_type) {
3479 errno = EPROTONOSUPPORT;
3487 if (real_type == SOCK_STREAM) {
3492 if (real_type == SOCK_DGRAM) {
3497 errno = EPROTONOSUPPORT;
3502 * We must call libc_socket with type, from the caller, not the version
3503 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3505 fd = libc_socket(AF_UNIX, type, 0);
3511 /* Check if we have a stale fd and remove it */
3512 swrap_remove_stale(fd);
3515 si->family = family;
3517 /* however, the rest of the socket_wrapper code expects just
3518 * the type, not the flags */
3519 si->type = real_type;
3520 si->protocol = protocol;
3523 * Setup myname so getsockname() can succeed to find out the socket
3526 switch(si->family) {
3528 struct sockaddr_in sin = {
3529 .sin_family = AF_INET,
3532 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3533 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3538 struct sockaddr_in6 sin6 = {
3539 .sin6_family = AF_INET6,
3542 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3543 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3552 ret = swrap_create_socket(si, fd);
3554 int saved_errno = errno;
3556 errno = saved_errno;
3560 SWRAP_LOG(SWRAP_LOG_TRACE,
3561 "Created %s socket for protocol %s, fd=%d",
3562 family == AF_INET ? "IPv4" : "IPv6",
3563 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3569 int socket(int family, int type, int protocol)
3571 return swrap_socket(family, type, protocol);
3574 /****************************************************************************
3576 ***************************************************************************/
3578 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3582 rc = libc_socketpair(family, type, protocol, sv);
3584 swrap_remove_stale(sv[0]);
3585 swrap_remove_stale(sv[1]);
3591 int socketpair(int family, int type, int protocol, int sv[2])
3593 return swrap_socketpair(family, type, protocol, sv);
3596 /****************************************************************************
3598 ***************************************************************************/
3600 #ifdef HAVE_TIMERFD_CREATE
3601 static int swrap_timerfd_create(int clockid, int flags)
3605 fd = libc_timerfd_create(clockid, flags);
3607 swrap_remove_stale(fd);
3613 int timerfd_create(int clockid, int flags)
3615 return swrap_timerfd_create(clockid, flags);
3619 /****************************************************************************
3621 ***************************************************************************/
3623 static int swrap_pipe(int pipefd[2])
3627 rc = libc_pipe(pipefd);
3629 swrap_remove_stale(pipefd[0]);
3630 swrap_remove_stale(pipefd[1]);
3636 int pipe(int pipefd[2])
3638 return swrap_pipe(pipefd);
3641 /****************************************************************************
3643 ***************************************************************************/
3645 static int swrap_accept(int s,
3646 struct sockaddr *addr,
3650 struct socket_info *parent_si, *child_si;
3651 struct socket_info new_si = { 0 };
3654 struct swrap_address un_addr = {
3655 .sa_socklen = sizeof(struct sockaddr_un),
3657 struct swrap_address un_my_addr = {
3658 .sa_socklen = sizeof(struct sockaddr_un),
3660 struct swrap_address in_addr = {
3661 .sa_socklen = sizeof(struct sockaddr_storage),
3663 struct swrap_address in_my_addr = {
3664 .sa_socklen = sizeof(struct sockaddr_storage),
3668 parent_si = find_socket_info(s);
3671 return libc_accept4(s, addr, addrlen, flags);
3674 return libc_accept(s, addr, addrlen);
3680 * prevent parent_si from being altered / closed
3683 SWRAP_LOCK_SI(parent_si);
3686 * assume out sockaddr have the same size as the in parent
3689 in_addr.sa_socklen = socket_length(parent_si->family);
3690 if (in_addr.sa_socklen <= 0) {
3691 SWRAP_UNLOCK_SI(parent_si);
3696 SWRAP_UNLOCK_SI(parent_si);
3699 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3702 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3705 int saved_errno = errno;
3706 if (saved_errno == ENOTSOCK) {
3707 /* Remove stale fds */
3708 swrap_remove_stale(s);
3710 errno = saved_errno;
3716 /* Check if we have a stale fd and remove it */
3717 swrap_remove_stale(fd);
3719 if (un_addr.sa.un.sun_path[0] == '\0') {
3721 * FreeBSD seems to have a problem where
3722 * accept4() on the unix socket doesn't
3723 * ECONNABORTED for already disconnected connections.
3725 * Let's try libc_getpeername() to get the peer address
3726 * as a fallback, but it'll likely return ENOTCONN,
3727 * which we have to map to ECONNABORTED.
3729 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3730 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3732 int saved_errno = errno;
3734 if (saved_errno == ENOTCONN) {
3736 * If the connection is already disconnected
3737 * we should return ECONNABORTED.
3739 saved_errno = ECONNABORTED;
3741 errno = saved_errno;
3746 ret = libc_getsockname(fd,
3748 &un_my_addr.sa_socklen);
3750 int saved_errno = errno;
3752 if (saved_errno == ENOTCONN) {
3754 * If the connection is already disconnected
3755 * we should return ECONNABORTED.
3757 saved_errno = ECONNABORTED;
3759 errno = saved_errno;
3763 SWRAP_LOCK_SI(parent_si);
3765 ret = sockaddr_convert_from_un(parent_si,
3770 &in_addr.sa_socklen);
3772 int saved_errno = errno;
3773 SWRAP_UNLOCK_SI(parent_si);
3775 errno = saved_errno;
3781 child_si->family = parent_si->family;
3782 child_si->type = parent_si->type;
3783 child_si->protocol = parent_si->protocol;
3784 child_si->bound = 1;
3785 child_si->is_server = 1;
3786 child_si->connected = 1;
3788 SWRAP_UNLOCK_SI(parent_si);
3790 child_si->peername = (struct swrap_address) {
3791 .sa_socklen = in_addr.sa_socklen,
3793 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3795 if (addr != NULL && addrlen != NULL) {
3796 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3798 memcpy(addr, &in_addr.sa.ss, copy_len);
3800 *addrlen = in_addr.sa_socklen;
3803 ret = sockaddr_convert_from_un(child_si,
3805 un_my_addr.sa_socklen,
3808 &in_my_addr.sa_socklen);
3810 int saved_errno = errno;
3812 errno = saved_errno;
3816 SWRAP_LOG(SWRAP_LOG_TRACE,
3817 "accept() path=%s, fd=%d",
3818 un_my_addr.sa.un.sun_path, s);
3820 child_si->myname = (struct swrap_address) {
3821 .sa_socklen = in_my_addr.sa_socklen,
3823 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3825 idx = swrap_create_socket(&new_si, fd);
3827 int saved_errno = errno;
3829 errno = saved_errno;
3834 struct socket_info *si = swrap_get_socket_info(idx);
3837 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3838 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3839 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3840 SWRAP_UNLOCK_SI(si);
3847 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3849 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3853 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3854 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3856 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3859 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3862 static int autobind_start_init;
3863 static int autobind_start;
3865 /* using sendto() or connect() on an unbound socket would give the
3866 recipient no way to reply, as unlike UDP and TCP, a unix domain
3867 socket can't auto-assign ephemeral port numbers, so we need to
3869 Note: this might change the family from ipv6 to ipv4
3871 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3873 struct swrap_address un_addr = {
3874 .sa_socklen = sizeof(struct sockaddr_un),
3880 char *swrap_dir = NULL;
3882 swrap_mutex_lock(&autobind_start_mutex);
3884 if (autobind_start_init != 1) {
3885 autobind_start_init = 1;
3886 autobind_start = getpid();
3887 autobind_start %= 50000;
3888 autobind_start += 10000;
3891 un_addr.sa.un.sun_family = AF_UNIX;
3895 struct sockaddr_in in;
3899 type = SOCKET_TYPE_CHAR_TCP;
3902 type = SOCKET_TYPE_CHAR_UDP;
3905 errno = ESOCKTNOSUPPORT;
3910 memset(&in, 0, sizeof(in));
3911 in.sin_family = AF_INET;
3912 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3913 socket_wrapper_default_iface()));
3915 si->myname = (struct swrap_address) {
3916 .sa_socklen = sizeof(in),
3918 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3923 struct sockaddr_in6 in6;
3925 if (si->family != family) {
3926 errno = ENETUNREACH;
3933 type = SOCKET_TYPE_CHAR_TCP_V6;
3936 type = SOCKET_TYPE_CHAR_UDP_V6;
3939 errno = ESOCKTNOSUPPORT;
3944 memset(&in6, 0, sizeof(in6));
3945 in6.sin6_family = AF_INET6;
3946 in6.sin6_addr = *swrap_ipv6();
3947 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3949 si->myname = (struct swrap_address) {
3950 .sa_socklen = sizeof(in6),
3952 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3957 errno = ESOCKTNOSUPPORT;
3962 if (autobind_start > 60000) {
3963 autobind_start = 10000;
3966 swrap_dir = socket_wrapper_dir();
3967 if (swrap_dir == NULL) {
3973 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3974 port = autobind_start + i;
3975 swrap_un_path(&un_addr.sa.un,
3978 socket_wrapper_default_iface(),
3981 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3983 if (errno == EALREADY || errno == EADDRINUSE) {
3989 si->un_addr = un_addr.sa.un;
3992 autobind_start = port + 1;
3995 if (i == SOCKET_MAX_SOCKETS) {
3996 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3997 "interface "SOCKET_FORMAT,
4000 socket_wrapper_default_iface(),
4007 si->family = family;
4008 set_port(si->family, port, &si->myname);
4013 SAFE_FREE(swrap_dir);
4014 swrap_mutex_unlock(&autobind_start_mutex);
4018 /****************************************************************************
4020 ***************************************************************************/
4022 static int swrap_connect(int s, const struct sockaddr *serv_addr,
4026 struct swrap_address un_addr = {
4027 .sa_socklen = sizeof(struct sockaddr_un),
4029 struct socket_info *si = find_socket_info(s);
4030 struct swrap_sockaddr_buf buf = {};
4034 return libc_connect(s, serv_addr, addrlen);
4039 if (si->bound == 0) {
4040 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4046 if (si->family != serv_addr->sa_family) {
4047 SWRAP_LOG(SWRAP_LOG_ERROR,
4048 "called for fd=%d (family=%d) called with invalid family=%d",
4049 s, si->family, serv_addr->sa_family);
4055 ret = sockaddr_convert_to_un(si, serv_addr,
4056 addrlen, &un_addr.sa.un, 0, &bcast);
4062 errno = ENETUNREACH;
4067 if (si->type == SOCK_DGRAM) {
4068 si->defer_connect = 1;
4071 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4073 ret = libc_connect(s,
4075 un_addr.sa_socklen);
4078 SWRAP_LOG(SWRAP_LOG_TRACE,
4079 "connect(%s) path=%s, fd=%d",
4080 swrap_sockaddr_string(&buf, serv_addr),
4081 un_addr.sa.un.sun_path, s);
4084 /* to give better errors */
4085 if (ret == -1 && errno == ENOENT) {
4086 errno = EHOSTUNREACH;
4090 si->peername = (struct swrap_address) {
4091 .sa_socklen = addrlen,
4094 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4098 * When we connect() on a socket than we have to bind the
4099 * outgoing connection on the interface we use for the
4100 * transport. We already bound it on the right interface
4101 * but here we have to update the name so getsockname()
4102 * returns correct information.
4104 if (si->bindname.sa_socklen > 0) {
4105 si->myname = (struct swrap_address) {
4106 .sa_socklen = si->bindname.sa_socklen,
4109 memcpy(&si->myname.sa.ss,
4110 &si->bindname.sa.ss,
4111 si->bindname.sa_socklen);
4113 /* Cleanup bindname */
4114 si->bindname = (struct swrap_address) {
4119 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4120 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4122 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4126 SWRAP_UNLOCK_SI(si);
4130 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4132 return swrap_connect(s, serv_addr, addrlen);
4135 /****************************************************************************
4137 ***************************************************************************/
4139 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4142 struct swrap_address un_addr = {
4143 .sa_socklen = sizeof(struct sockaddr_un),
4145 struct socket_info *si = find_socket_info(s);
4146 struct swrap_sockaddr_buf buf = {};
4147 int ret_errno = errno;
4154 return libc_bind(s, myaddr, addrlen);
4159 switch (si->family) {
4161 const struct sockaddr_in *sin;
4162 if (addrlen < sizeof(struct sockaddr_in)) {
4163 bind_error = EINVAL;
4167 sin = (const struct sockaddr_in *)(const void *)myaddr;
4169 if (sin->sin_family != AF_INET) {
4170 bind_error = EAFNOSUPPORT;
4173 /* special case for AF_UNSPEC */
4174 if (sin->sin_family == AF_UNSPEC &&
4175 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4184 const struct sockaddr_in6 *sin6;
4185 if (addrlen < sizeof(struct sockaddr_in6)) {
4186 bind_error = EINVAL;
4190 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4192 if (sin6->sin6_family != AF_INET6) {
4193 bind_error = EAFNOSUPPORT;
4200 bind_error = EINVAL;
4204 if (bind_error != 0) {
4205 ret_errno = bind_error;
4211 in_use = check_addr_port_in_use(myaddr, addrlen);
4219 si->myname.sa_socklen = addrlen;
4220 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4222 ret = sockaddr_convert_to_un(si,
4233 unlink(un_addr.sa.un.sun_path);
4235 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4240 SWRAP_LOG(SWRAP_LOG_TRACE,
4241 "bind(%s) path=%s, fd=%d ret=%d ret_errno=%d",
4242 swrap_sockaddr_string(&buf, myaddr),
4243 un_addr.sa.un.sun_path, s, ret, ret_errno);
4250 SWRAP_UNLOCK_SI(si);
4255 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4257 return swrap_bind(s, myaddr, addrlen);
4260 /****************************************************************************
4262 ***************************************************************************/
4264 #ifdef HAVE_BINDRESVPORT
4265 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4267 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4269 struct swrap_address myaddr = {
4270 .sa_socklen = sizeof(struct sockaddr_storage),
4273 static uint16_t port;
4278 #define SWRAP_STARTPORT 600
4279 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4280 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4283 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4287 salen = myaddr.sa_socklen;
4290 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4296 memset(&myaddr.sa.ss, 0, salen);
4301 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4304 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4306 salen = sizeof(struct sockaddr_in);
4307 sinp->sin_port = htons(port);
4311 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4313 salen = sizeof(struct sockaddr_in6);
4314 sin6p->sin6_port = htons(port);
4318 errno = EAFNOSUPPORT;
4323 if (port > SWRAP_ENDPORT) {
4324 port = SWRAP_STARTPORT;
4327 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4328 if (rc == 0 || errno != EADDRINUSE) {
4336 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4338 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4342 /****************************************************************************
4344 ***************************************************************************/
4346 static int swrap_listen(int s, int backlog)
4349 struct socket_info *si = find_socket_info(s);
4352 return libc_listen(s, backlog);
4357 if (si->bound == 0) {
4358 ret = swrap_auto_bind(s, si, si->family);
4365 ret = libc_listen(s, backlog);
4371 SWRAP_UNLOCK_SI(si);
4376 int listen(int s, int backlog)
4378 return swrap_listen(s, backlog);
4381 /****************************************************************************
4383 ***************************************************************************/
4385 static FILE *swrap_fopen(const char *name, const char *mode)
4389 fp = libc_fopen(name, mode);
4391 int fd = fileno(fp);
4393 swrap_remove_stale(fd);
4399 FILE *fopen(const char *name, const char *mode)
4401 return swrap_fopen(name, mode);
4404 /****************************************************************************
4406 ***************************************************************************/
4409 static FILE *swrap_fopen64(const char *name, const char *mode)
4413 fp = libc_fopen64(name, mode);
4415 int fd = fileno(fp);
4417 swrap_remove_stale(fd);
4423 FILE *fopen64(const char *name, const char *mode)
4425 return swrap_fopen64(name, mode);
4427 #endif /* HAVE_FOPEN64 */
4429 /****************************************************************************
4431 ***************************************************************************/
4433 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4437 ret = libc_vopen(pathname, flags, ap);
4440 * There are methods for closing descriptors (libc-internal code
4441 * paths, direct syscalls) which close descriptors in ways that
4442 * we can't intercept, so try to recover when we notice that
4445 swrap_remove_stale(ret);
4450 int open(const char *pathname, int flags, ...)
4455 va_start(ap, flags);
4456 fd = swrap_vopen(pathname, flags, ap);
4462 /****************************************************************************
4464 ***************************************************************************/
4467 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4471 ret = libc_vopen64(pathname, flags, ap);
4474 * There are methods for closing descriptors (libc-internal code
4475 * paths, direct syscalls) which close descriptors in ways that
4476 * we can't intercept, so try to recover when we notice that
4479 swrap_remove_stale(ret);
4484 int open64(const char *pathname, int flags, ...)
4489 va_start(ap, flags);
4490 fd = swrap_vopen64(pathname, flags, ap);
4495 #endif /* HAVE_OPEN64 */
4497 /****************************************************************************
4499 ***************************************************************************/
4501 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4505 ret = libc_vopenat(dirfd, path, flags, ap);
4508 * There are methods for closing descriptors (libc-internal code
4509 * paths, direct syscalls) which close descriptors in ways that
4510 * we can't intercept, so try to recover when we notice that
4513 swrap_remove_stale(ret);
4519 int openat(int dirfd, const char *path, int flags, ...)
4524 va_start(ap, flags);
4525 fd = swrap_vopenat(dirfd, path, flags, ap);
4531 /****************************************************************************
4533 ***************************************************************************/
4535 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4537 struct socket_info *si = find_socket_info(s);
4542 return libc_getpeername(s, name, addrlen);
4547 if (si->peername.sa_socklen == 0)
4553 len = MIN(*addrlen, si->peername.sa_socklen);
4559 memcpy(name, &si->peername.sa.ss, len);
4560 *addrlen = si->peername.sa_socklen;
4564 SWRAP_UNLOCK_SI(si);
4569 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4570 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4572 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4575 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4578 /****************************************************************************
4580 ***************************************************************************/
4582 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4584 struct socket_info *si = find_socket_info(s);
4589 return libc_getsockname(s, name, addrlen);
4594 len = MIN(*addrlen, si->myname.sa_socklen);
4600 memcpy(name, &si->myname.sa.ss, len);
4601 *addrlen = si->myname.sa_socklen;
4605 SWRAP_UNLOCK_SI(si);
4610 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4611 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4613 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4616 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4619 /****************************************************************************
4621 ***************************************************************************/
4624 # ifdef SO_PROTOTYPE /* The Solaris name */
4625 # define SO_PROTOCOL SO_PROTOTYPE
4626 # endif /* SO_PROTOTYPE */
4627 #endif /* SO_PROTOCOL */
4629 static int swrap_getsockopt(int s, int level, int optname,
4630 void *optval, socklen_t *optlen)
4632 struct socket_info *si = find_socket_info(s);
4636 return libc_getsockopt(s,
4645 if (level == SOL_SOCKET) {
4649 if (optval == NULL || optlen == NULL ||
4650 *optlen < (socklen_t)sizeof(int)) {
4656 *optlen = sizeof(int);
4657 *(int *)optval = si->family;
4660 #endif /* SO_DOMAIN */
4664 if (optval == NULL || optlen == NULL ||
4665 *optlen < (socklen_t)sizeof(int)) {
4671 *optlen = sizeof(int);
4672 *(int *)optval = si->protocol;
4675 #endif /* SO_PROTOCOL */
4677 if (optval == NULL || optlen == NULL ||
4678 *optlen < (socklen_t)sizeof(int)) {
4684 *optlen = sizeof(int);
4685 *(int *)optval = si->type;
4689 ret = libc_getsockopt(s,
4696 } else if (level == IPPROTO_TCP) {
4701 * This enables sending packets directly out over TCP.
4702 * As a unix socket is doing that any way, report it as
4705 if (optval == NULL || optlen == NULL ||
4706 *optlen < (socklen_t)sizeof(int)) {
4712 *optlen = sizeof(int);
4713 *(int *)optval = si->tcp_nodelay;
4717 #endif /* TCP_NODELAY */
4720 struct tcp_info info;
4721 socklen_t ilen = sizeof(info);
4723 #ifdef HAVE_NETINET_TCP_FSM_H
4724 /* This is FreeBSD */
4725 # define __TCP_LISTEN TCPS_LISTEN
4726 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4727 # define __TCP_CLOSE TCPS_CLOSED
4730 # define __TCP_LISTEN TCP_LISTEN
4731 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4732 # define __TCP_CLOSE TCP_CLOSE
4736 if (si->listening) {
4737 info.tcpi_state = __TCP_LISTEN;
4738 } else if (si->connected) {
4740 * For now we just fake a few values
4741 * supported both by FreeBSD and Linux
4743 info.tcpi_state = __TCP_ESTABLISHED;
4744 info.tcpi_rto = 200000; /* 200 msec */
4745 info.tcpi_rtt = 5000; /* 5 msec */
4746 info.tcpi_rttvar = 5000; /* 5 msec */
4748 info.tcpi_state = __TCP_CLOSE;
4749 info.tcpi_rto = 1000000; /* 1 sec */
4751 info.tcpi_rttvar = 250000; /* 250 msec */
4754 if (optval == NULL || optlen == NULL ||
4755 *optlen < (socklen_t)ilen) {
4762 memcpy(optval, &info, ilen);
4767 #endif /* TCP_INFO */
4773 errno = ENOPROTOOPT;
4777 SWRAP_UNLOCK_SI(si);
4781 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4782 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4784 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4787 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4790 /****************************************************************************
4792 ***************************************************************************/
4794 static int swrap_setsockopt(int s, int level, int optname,
4795 const void *optval, socklen_t optlen)
4797 struct socket_info *si = find_socket_info(s);
4801 return libc_setsockopt(s,
4808 if (level == SOL_SOCKET) {
4809 return libc_setsockopt(s,
4818 if (level == IPPROTO_TCP) {
4825 * This enables sending packets directly out over TCP.
4826 * A unix socket is doing that any way.
4828 if (optval == NULL || optlen == 0 ||
4829 optlen < (socklen_t)sizeof(int)) {
4835 i = *discard_const_p(int, optval);
4836 if (i != 0 && i != 1) {
4841 si->tcp_nodelay = i;
4846 #endif /* TCP_NODELAY */
4852 switch (si->family) {
4854 if (level == IPPROTO_IP) {
4856 if (optname == IP_PKTINFO) {
4857 si->pktinfo = AF_INET;
4859 #endif /* IP_PKTINFO */
4865 if (level == IPPROTO_IPV6) {
4866 #ifdef IPV6_RECVPKTINFO
4867 if (optname == IPV6_RECVPKTINFO) {
4868 si->pktinfo = AF_INET6;
4870 #endif /* IPV6_PKTINFO */
4876 errno = ENOPROTOOPT;
4882 SWRAP_UNLOCK_SI(si);
4886 int setsockopt(int s, int level, int optname,
4887 const void *optval, socklen_t optlen)
4889 return swrap_setsockopt(s, level, optname, optval, optlen);
4892 /****************************************************************************
4894 ***************************************************************************/
4896 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4898 struct socket_info *si = find_socket_info(s);
4900 int *value_ptr = NULL;
4904 return libc_vioctl(s, r, va);
4911 rc = libc_vioctl(s, r, va);
4916 value_ptr = ((int *)va_arg(ap, int *));
4919 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4920 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4921 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4922 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4927 /* this is FreeBSD */
4928 FALL_THROUGH; /* to TIOCOUTQ */
4929 #endif /* FIONWRITE */
4930 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4932 * This may return more bytes then the application
4933 * sent into the socket, for tcp it should
4934 * return the number of unacked bytes.
4936 * On AF_UNIX, all bytes are immediately acked!
4939 value_ptr = ((int *)va_arg(ap, int *));
4947 SWRAP_UNLOCK_SI(si);
4951 #ifdef HAVE_IOCTL_INT
4952 int ioctl(int s, int r, ...)
4954 int ioctl(int s, unsigned long int r, ...)
4962 rc = swrap_vioctl(s, (unsigned long int) r, va);
4973 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4976 # ifdef _ALIGN /* BSD */
4977 #define CMSG_ALIGN _ALIGN
4979 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4980 # endif /* _ALIGN */
4981 #endif /* CMSG_ALIGN */
4984 * @brief Add a cmsghdr to a msghdr.
4986 * This is an function to add any type of cmsghdr. It will operate on the
4987 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4988 * the buffer position after the added cmsg element. Hence, this function is
4989 * intended to be used with an intermediate msghdr and not on the original
4990 * one handed in by the client.
4992 * @param[in] msg The msghdr to which to add the cmsg.
4994 * @param[in] level The cmsg level to set.
4996 * @param[in] type The cmsg type to set.
4998 * @param[in] data The cmsg data to set.
5000 * @param[in] len the length of the data to set.
5002 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
5008 size_t cmlen = CMSG_LEN(len);
5009 size_t cmspace = CMSG_SPACE(len);
5010 uint8_t cmbuf[cmspace];
5011 void *cast_ptr = (void *)cmbuf;
5012 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
5015 memset(cmbuf, 0, cmspace);
5017 if (msg->msg_controllen < cmlen) {
5018 cmlen = msg->msg_controllen;
5019 msg->msg_flags |= MSG_CTRUNC;
5022 if (msg->msg_controllen < cmspace) {
5023 cmspace = msg->msg_controllen;
5027 * We copy the full input data into an intermediate cmsghdr first
5028 * in order to more easily cope with truncation.
5030 cm->cmsg_len = cmlen;
5031 cm->cmsg_level = level;
5032 cm->cmsg_type = type;
5033 memcpy(CMSG_DATA(cm), data, len);
5036 * We now copy the possibly truncated buffer.
5037 * We copy cmlen bytes, but consume cmspace bytes,
5038 * leaving the possible padding uninitialiazed.
5040 p = (uint8_t *)msg->msg_control;
5041 memcpy(p, cm, cmlen);
5043 msg->msg_control = p;
5044 msg->msg_controllen -= cmspace;
5049 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5052 /* Add packet info */
5053 switch (si->pktinfo) {
5054 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5056 struct sockaddr_in *sin;
5057 #if defined(HAVE_STRUCT_IN_PKTINFO)
5058 struct in_pktinfo pkt;
5059 #elif defined(IP_RECVDSTADDR)
5063 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5064 sin = &si->bindname.sa.in;
5066 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5069 sin = &si->myname.sa.in;
5074 #if defined(HAVE_STRUCT_IN_PKTINFO)
5075 pkt.ipi_ifindex = socket_wrapper_default_iface();
5076 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5077 #elif defined(IP_RECVDSTADDR)
5078 pkt = sin->sin_addr;
5081 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5086 #endif /* IP_PKTINFO */
5087 #if defined(HAVE_IPV6)
5089 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5090 struct sockaddr_in6 *sin6;
5091 struct in6_pktinfo pkt6;
5093 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5094 sin6 = &si->bindname.sa.in6;
5096 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5099 sin6 = &si->myname.sa.in6;
5104 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5105 pkt6.ipi6_addr = sin6->sin6_addr;
5107 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5108 &pkt6, sizeof(pkt6));
5109 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5113 #endif /* IPV6_PKTINFO */
5121 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5122 struct msghdr *omsg)
5126 if (si->pktinfo > 0) {
5127 rc = swrap_msghdr_add_pktinfo(si, omsg);
5133 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5135 size_t *cm_data_space);
5136 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5138 size_t *cm_data_space);
5139 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5141 size_t *cm_data_space);
5143 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5145 size_t *cm_data_space)
5147 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5148 struct cmsghdr *cmsg;
5152 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5156 for (cmsg = CMSG_FIRSTHDR(msg);
5158 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5159 switch (cmsg->cmsg_level) {
5161 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5166 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5171 rc = swrap_sendmsg_copy_cmsg(cmsg,
5177 int saved_errno = errno;
5178 SAFE_FREE(*cm_data);
5180 errno = saved_errno;
5188 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5190 size_t *cm_data_space)
5195 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5197 p = realloc((*cm_data), cmspace);
5203 p = (*cm_data) + (*cm_data_space);
5204 *cm_data_space = cmspace;
5206 memcpy(p, cmsg, cmsg->cmsg_len);
5211 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5213 size_t *cm_data_space);
5216 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5218 size_t *cm_data_space)
5222 switch(cmsg->cmsg_type) {
5225 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5232 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5244 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5246 size_t *cm_data_space)
5248 (void)cmsg; /* unused */
5249 (void)cm_data; /* unused */
5250 (void)cm_data_space; /* unused */
5253 * Passing a IP pktinfo to a unix socket might be rejected by the
5254 * Kernel, at least on FreeBSD. So skip this cmsg.
5259 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5261 size_t *cm_data_space)
5265 switch (cmsg->cmsg_type) {
5267 SWRAP_LOG(SWRAP_LOG_TRACE,
5268 "Ignoring SCM_RIGHTS on inet socket!");
5271 #ifdef SCM_CREDENTIALS
5272 case SCM_CREDENTIALS:
5273 SWRAP_LOG(SWRAP_LOG_TRACE,
5274 "Ignoring SCM_CREDENTIALS on inet socket!");
5277 #endif /* SCM_CREDENTIALS */
5279 rc = swrap_sendmsg_copy_cmsg(cmsg,
5288 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5291 * We only allow up to 6 fds at a time
5292 * as that's more than enough for Samba
5293 * and it means we can keep the logic simple
5294 * and work with fixed size arrays.
5296 * We also keep sizeof(struct swrap_unix_scm_rights)
5297 * under PIPE_BUF (4096) in order to allow a non-blocking
5298 * write into the pipe.
5301 #define PIPE_BUF 4096
5303 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5304 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5305 struct swrap_unix_scm_rights_payload {
5307 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5308 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5310 struct swrap_unix_scm_rights {
5312 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5313 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5315 uint32_t payload_size;
5316 struct swrap_unix_scm_rights_payload payload;
5319 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5321 int saved_errno = errno;
5324 for (i = 0; i < num; i++) {
5325 struct socket_info *si = array[i];
5331 swrap_dec_refcount(si);
5332 if (si->fd_passed > 0) {
5335 SWRAP_UNLOCK_SI(si);
5339 errno = saved_errno;
5342 static void swrap_undo_si_idx_array(size_t num, int *array)
5344 int saved_errno = errno;
5347 swrap_mutex_lock(&first_free_mutex);
5349 for (i = 0; i < num; i++) {
5350 struct socket_info *si = NULL;
5352 if (array[i] == -1) {
5356 si = swrap_get_socket_info(array[i]);
5362 swrap_dec_refcount(si);
5363 SWRAP_UNLOCK_SI(si);
5365 swrap_set_next_free(si, first_free);
5366 first_free = array[i];
5370 swrap_mutex_unlock(&first_free_mutex);
5371 errno = saved_errno;
5374 static void swrap_close_fd_array(size_t num, const int *array)
5376 int saved_errno = errno;
5379 for (i = 0; i < num; i++) {
5380 if (array[i] == -1) {
5383 libc_close(array[i]);
5386 errno = saved_errno;
5394 union __swrap_cmsghdr {
5396 struct cmsghdr *cmsg;
5399 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5401 size_t *cm_data_space,
5402 int *scm_rights_pipe_fd)
5404 struct swrap_unix_scm_rights info;
5405 struct swrap_unix_scm_rights_payload *payload = NULL;
5406 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5407 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5408 size_t info_idx = 0;
5411 union __swrap_fds __fds_in = { .p = NULL, };
5412 const int *fds_in = NULL;
5414 size_t size_fds_out;
5415 union __swrap_fds __fds_out = { .p = NULL, };
5416 int *fds_out = NULL;
5419 size_t new_cm_data_space;
5420 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5421 struct cmsghdr *new_cmsg = NULL;
5424 int pipefd[2] = { -1, -1 };
5429 * We pass this a buffer to the kernel make sure any padding
5433 info.magic = swrap_unix_scm_right_magic;
5434 memcpy(info.package_name,
5435 SOCKET_WRAPPER_PACKAGE,
5436 sizeof(info.package_name));
5437 memcpy(info.package_version,
5438 SOCKET_WRAPPER_VERSION,
5439 sizeof(info.package_version));
5440 info.full_size = sizeof(info);
5441 info.payload_size = sizeof(info.payload);
5442 payload = &info.payload;
5444 if (*scm_rights_pipe_fd != -1) {
5445 SWRAP_LOG(SWRAP_LOG_ERROR,
5446 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5451 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5452 SWRAP_LOG(SWRAP_LOG_ERROR,
5453 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5454 (size_t)cmsg->cmsg_len,
5459 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5460 if ((size_fds_in % sizeof(int)) != 0) {
5461 SWRAP_LOG(SWRAP_LOG_ERROR,
5462 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5463 (size_t)cmsg->cmsg_len,
5469 num_fds_in = size_fds_in / sizeof(int);
5470 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5471 SWRAP_LOG(SWRAP_LOG_ERROR,
5472 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5474 "SWRAP_MAX_PASSED_FDS(%zu)",
5475 (size_t)cmsg->cmsg_len,
5478 SWRAP_MAX_PASSED_FDS);
5482 if (num_fds_in == 0) {
5483 SWRAP_LOG(SWRAP_LOG_ERROR,
5484 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5486 (size_t)cmsg->cmsg_len,
5492 __fds_in.p = CMSG_DATA(cmsg);
5493 fds_in = __fds_in.fds;
5494 num_fds_out = num_fds_in + 1;
5496 SWRAP_LOG(SWRAP_LOG_TRACE,
5497 "num_fds_in=%zu num_fds_out=%zu",
5498 num_fds_in, num_fds_out);
5500 size_fds_out = sizeof(int) * num_fds_out;
5501 cmsg_len = CMSG_LEN(size_fds_out);
5502 cmsg_space = CMSG_SPACE(size_fds_out);
5504 new_cm_data_space = *cm_data_space + cmsg_space;
5506 p = realloc((*cm_data), new_cm_data_space);
5511 p = (*cm_data) + (*cm_data_space);
5512 memset(p, 0, cmsg_space);
5514 new_cmsg = __new_cmsg.cmsg;
5516 __fds_out.p = CMSG_DATA(new_cmsg);
5517 fds_out = __fds_out.fds;
5518 memcpy(fds_out, fds_in, size_fds_in);
5519 new_cmsg->cmsg_len = cmsg->cmsg_len;
5521 for (i = 0; i < num_fds_in; i++) {
5524 payload->idxs[i] = -1;
5525 payload->num_idxs++;
5527 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5528 if (si_idx_array[i] == -1) {
5532 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5533 if (si_array[i] == NULL) {
5534 SWRAP_LOG(SWRAP_LOG_ERROR,
5535 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5536 i, fds_in[i], i, si_idx_array[i]);
5541 for (j = 0; j < i; j++) {
5542 if (si_array[j] == si_array[i]) {
5543 payload->idxs[i] = payload->idxs[j];
5547 if (payload->idxs[i] == -1) {
5548 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5549 SWRAP_LOG(SWRAP_LOG_ERROR,
5550 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5551 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5552 i, fds_in[i], i, si_idx_array[i],
5554 SWRAP_MAX_PASSED_SOCKET_INFO);
5558 payload->idxs[i] = info_idx;
5564 for (i = 0; i < num_fds_in; i++) {
5565 struct socket_info *si = si_array[i];
5568 SWRAP_LOG(SWRAP_LOG_TRACE,
5569 "fds_in[%zu]=%d not an inet socket",
5574 SWRAP_LOG(SWRAP_LOG_TRACE,
5575 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5576 "passing as info.idxs[%zu]=%d!",
5579 i, payload->idxs[i]);
5583 payload->infos[payload->idxs[i]] = *si;
5584 payload->infos[payload->idxs[i]].fd_passed = 0;
5585 SWRAP_UNLOCK_SI(si);
5590 int saved_errno = errno;
5591 SWRAP_LOG(SWRAP_LOG_ERROR,
5592 "pipe() failed - %d %s",
5594 strerror(saved_errno));
5595 swrap_dec_fd_passed_array(num_fds_in, si_array);
5596 errno = saved_errno;
5600 sret = libc_write(pipefd[1], &info, sizeof(info));
5601 if (sret != sizeof(info)) {
5602 int saved_errno = errno;
5604 saved_errno = EINVAL;
5606 SWRAP_LOG(SWRAP_LOG_ERROR,
5607 "write() failed - sret=%zd - %d %s",
5609 strerror(saved_errno));
5610 swrap_dec_fd_passed_array(num_fds_in, si_array);
5611 libc_close(pipefd[1]);
5612 libc_close(pipefd[0]);
5613 errno = saved_errno;
5616 libc_close(pipefd[1]);
5619 * Add the pipe read end to the end of the passed fd array
5621 fds_out[num_fds_in] = pipefd[0];
5622 new_cmsg->cmsg_len = cmsg_len;
5624 /* we're done ... */
5625 *scm_rights_pipe_fd = pipefd[0];
5626 *cm_data_space = new_cm_data_space;
5631 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5633 size_t *cm_data_space,
5634 int *scm_rights_pipe_fd)
5638 switch (cmsg->cmsg_type) {
5640 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5643 scm_rights_pipe_fd);
5646 rc = swrap_sendmsg_copy_cmsg(cmsg,
5655 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5657 size_t *cm_data_space)
5659 int scm_rights_pipe_fd = -1;
5660 struct swrap_unix_scm_rights info;
5661 struct swrap_unix_scm_rights_payload *payload = NULL;
5662 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5665 union __swrap_fds __fds_in = { .p = NULL, };
5666 const int *fds_in = NULL;
5668 size_t size_fds_out;
5669 union __swrap_fds __fds_out = { .p = NULL, };
5670 int *fds_out = NULL;
5673 size_t new_cm_data_space;
5674 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5675 struct cmsghdr *new_cmsg = NULL;
5681 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5682 SWRAP_LOG(SWRAP_LOG_ERROR,
5683 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5684 (size_t)cmsg->cmsg_len,
5689 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5690 if ((size_fds_in % sizeof(int)) != 0) {
5691 SWRAP_LOG(SWRAP_LOG_ERROR,
5692 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5693 (size_t)cmsg->cmsg_len,
5699 num_fds_in = size_fds_in / sizeof(int);
5700 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5701 SWRAP_LOG(SWRAP_LOG_ERROR,
5702 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5703 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5704 (size_t)cmsg->cmsg_len,
5707 SWRAP_MAX_PASSED_FDS+1);
5711 if (num_fds_in <= 1) {
5712 SWRAP_LOG(SWRAP_LOG_ERROR,
5713 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5715 (size_t)cmsg->cmsg_len,
5721 __fds_in.p = CMSG_DATA(cmsg);
5722 fds_in = __fds_in.fds;
5723 num_fds_out = num_fds_in - 1;
5725 SWRAP_LOG(SWRAP_LOG_TRACE,
5726 "num_fds_in=%zu num_fds_out=%zu",
5727 num_fds_in, num_fds_out);
5729 for (i = 0; i < num_fds_in; i++) {
5730 /* Check if we have a stale fd and remove it */
5731 swrap_remove_stale(fds_in[i]);
5734 scm_rights_pipe_fd = fds_in[num_fds_out];
5735 size_fds_out = sizeof(int) * num_fds_out;
5736 cmsg_len = CMSG_LEN(size_fds_out);
5737 cmsg_space = CMSG_SPACE(size_fds_out);
5739 new_cm_data_space = *cm_data_space + cmsg_space;
5741 p = realloc((*cm_data), new_cm_data_space);
5743 swrap_close_fd_array(num_fds_in, fds_in);
5747 p = (*cm_data) + (*cm_data_space);
5748 memset(p, 0, cmsg_space);
5750 new_cmsg = __new_cmsg.cmsg;
5752 __fds_out.p = CMSG_DATA(new_cmsg);
5753 fds_out = __fds_out.fds;
5754 memcpy(fds_out, fds_in, size_fds_out);
5755 new_cmsg->cmsg_len = cmsg_len;
5757 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5758 if (sret != sizeof(info)) {
5759 int saved_errno = errno;
5761 saved_errno = EINVAL;
5763 SWRAP_LOG(SWRAP_LOG_ERROR,
5764 "read() failed - sret=%zd - %d %s",
5766 strerror(saved_errno));
5767 swrap_close_fd_array(num_fds_in, fds_in);
5768 errno = saved_errno;
5771 libc_close(scm_rights_pipe_fd);
5772 payload = &info.payload;
5774 if (info.magic != swrap_unix_scm_right_magic) {
5775 SWRAP_LOG(SWRAP_LOG_ERROR,
5776 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5777 (unsigned long long)info.magic,
5778 (unsigned long long)swrap_unix_scm_right_magic);
5779 swrap_close_fd_array(num_fds_out, fds_out);
5784 cmp = memcmp(info.package_name,
5785 SOCKET_WRAPPER_PACKAGE,
5786 sizeof(info.package_name));
5788 SWRAP_LOG(SWRAP_LOG_ERROR,
5789 "info.package_name='%.*s' != '%s'",
5790 (int)sizeof(info.package_name),
5792 SOCKET_WRAPPER_PACKAGE);
5793 swrap_close_fd_array(num_fds_out, fds_out);
5798 cmp = memcmp(info.package_version,
5799 SOCKET_WRAPPER_VERSION,
5800 sizeof(info.package_version));
5802 SWRAP_LOG(SWRAP_LOG_ERROR,
5803 "info.package_version='%.*s' != '%s'",
5804 (int)sizeof(info.package_version),
5805 info.package_version,
5806 SOCKET_WRAPPER_VERSION);
5807 swrap_close_fd_array(num_fds_out, fds_out);
5812 if (info.full_size != sizeof(info)) {
5813 SWRAP_LOG(SWRAP_LOG_ERROR,
5814 "info.full_size=%zu != sizeof(info)=%zu",
5815 (size_t)info.full_size,
5817 swrap_close_fd_array(num_fds_out, fds_out);
5822 if (info.payload_size != sizeof(info.payload)) {
5823 SWRAP_LOG(SWRAP_LOG_ERROR,
5824 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5825 (size_t)info.payload_size,
5826 sizeof(info.payload));
5827 swrap_close_fd_array(num_fds_out, fds_out);
5832 if (payload->num_idxs != num_fds_out) {
5833 SWRAP_LOG(SWRAP_LOG_ERROR,
5834 "info.num_idxs=%u != num_fds_out=%zu",
5835 payload->num_idxs, num_fds_out);
5836 swrap_close_fd_array(num_fds_out, fds_out);
5841 for (i = 0; i < num_fds_out; i++) {
5844 si_idx_array[i] = -1;
5846 if (payload->idxs[i] == -1) {
5847 SWRAP_LOG(SWRAP_LOG_TRACE,
5848 "fds_out[%zu]=%d not an inet socket",
5853 if (payload->idxs[i] < 0) {
5854 SWRAP_LOG(SWRAP_LOG_ERROR,
5855 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5856 i, fds_out[i], i, payload->idxs[i]);
5857 swrap_close_fd_array(num_fds_out, fds_out);
5862 if (payload->idxs[i] >= payload->num_idxs) {
5863 SWRAP_LOG(SWRAP_LOG_ERROR,
5864 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5865 i, fds_out[i], i, payload->idxs[i],
5867 swrap_close_fd_array(num_fds_out, fds_out);
5872 if ((size_t)fds_out[i] >= socket_fds_max) {
5873 SWRAP_LOG(SWRAP_LOG_ERROR,
5874 "The max socket index limit of %zu has been reached, "
5878 swrap_close_fd_array(num_fds_out, fds_out);
5883 SWRAP_LOG(SWRAP_LOG_TRACE,
5885 "received as info.idxs[%zu]=%d!",
5887 i, payload->idxs[i]);
5889 for (j = 0; j < i; j++) {
5890 if (payload->idxs[j] == -1) {
5893 if (payload->idxs[j] == payload->idxs[i]) {
5894 si_idx_array[i] = si_idx_array[j];
5897 if (si_idx_array[i] == -1) {
5898 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5900 si_idx_array[i] = swrap_add_socket_info(si);
5901 if (si_idx_array[i] == -1) {
5902 int saved_errno = errno;
5903 SWRAP_LOG(SWRAP_LOG_ERROR,
5904 "The max socket index limit of %zu has been reached, "
5908 swrap_undo_si_idx_array(i, si_idx_array);
5909 swrap_close_fd_array(num_fds_out, fds_out);
5910 errno = saved_errno;
5913 SWRAP_LOG(SWRAP_LOG_TRACE,
5914 "Imported %s socket for protocol %s, fd=%d",
5915 si->family == AF_INET ? "IPv4" : "IPv6",
5916 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5921 for (i = 0; i < num_fds_out; i++) {
5922 if (si_idx_array[i] == -1) {
5925 set_socket_info_index(fds_out[i], si_idx_array[i]);
5928 /* we're done ... */
5929 *cm_data_space = new_cm_data_space;
5934 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
5936 size_t *cm_data_space)
5940 switch (cmsg->cmsg_type) {
5942 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5947 rc = swrap_sendmsg_copy_cmsg(cmsg,
5956 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5958 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5959 struct msghdr *msg_tmp,
5960 int *scm_rights_pipe_fd)
5962 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5963 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5964 struct cmsghdr *cmsg = NULL;
5965 uint8_t *cm_data = NULL;
5966 size_t cm_data_space = 0;
5970 *scm_rights_pipe_fd = -1;
5973 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5977 for (cmsg = CMSG_FIRSTHDR(msg_in);
5979 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5980 switch (cmsg->cmsg_level) {
5982 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5985 scm_rights_pipe_fd);
5989 rc = swrap_sendmsg_copy_cmsg(cmsg,
5995 int saved_errno = errno;
5997 errno = saved_errno;
6002 msg_tmp->msg_controllen = cm_data_space;
6003 msg_tmp->msg_control = cm_data;
6006 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6007 *msg_tmp = *_msg_in;
6009 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6012 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
6014 int scm_rights_pipe_fd)
6016 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6017 int saved_errno = errno;
6018 SAFE_FREE(msg_tmp->msg_control);
6019 if (scm_rights_pipe_fd != -1) {
6020 libc_close(scm_rights_pipe_fd);
6022 errno = saved_errno;
6023 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6027 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
6028 struct msghdr *msg_tmp,
6029 uint8_t **tmp_control)
6031 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6032 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
6033 uint8_t *cm_data = NULL;
6034 size_t cm_data_space = 0;
6037 *tmp_control = NULL;
6039 SWRAP_LOG(SWRAP_LOG_TRACE,
6040 "msg_in->msg_controllen=%zu",
6041 (size_t)msg_in->msg_controllen);
6044 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
6049 * We need to give the kernel a bit more space in order
6050 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6051 * swrap_recvmsg_after_unix() will hide it again.
6053 cm_data_space = msg_in->msg_controllen;
6054 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6055 cm_data_space += cm_extra_space;
6057 cm_data = calloc(1, cm_data_space);
6058 if (cm_data == NULL) {
6062 msg_tmp->msg_controllen = cm_data_space;
6063 msg_tmp->msg_control = cm_data;
6064 *tmp_control = cm_data;
6066 SWRAP_LOG(SWRAP_LOG_TRACE,
6067 "msg_tmp->msg_controllen=%zu",
6068 (size_t)msg_tmp->msg_controllen);
6070 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6072 *tmp_control = NULL;
6074 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6077 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6078 uint8_t **tmp_control,
6079 struct msghdr *msg_out,
6082 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6083 struct cmsghdr *cmsg = NULL;
6084 uint8_t *cm_data = NULL;
6085 size_t cm_data_space = 0;
6089 int saved_errno = errno;
6090 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6091 saved_errno, strerror(saved_errno));
6092 SAFE_FREE(*tmp_control);
6093 /* msg_out should not be touched on error */
6094 errno = saved_errno;
6098 SWRAP_LOG(SWRAP_LOG_TRACE,
6099 "msg_tmp->msg_controllen=%zu",
6100 (size_t)msg_tmp->msg_controllen);
6103 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6104 int saved_errno = errno;
6105 *msg_out = *msg_tmp;
6106 SAFE_FREE(*tmp_control);
6107 errno = saved_errno;
6111 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6113 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6114 switch (cmsg->cmsg_level) {
6116 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6122 rc = swrap_sendmsg_copy_cmsg(cmsg,
6128 int saved_errno = errno;
6130 SAFE_FREE(*tmp_control);
6131 errno = saved_errno;
6137 * msg_tmp->msg_control (*tmp_control) was created by
6138 * swrap_recvmsg_before_unix() and msg_out->msg_control
6139 * is still the buffer of the caller.
6141 msg_tmp->msg_control = msg_out->msg_control;
6142 msg_tmp->msg_controllen = msg_out->msg_controllen;
6143 *msg_out = *msg_tmp;
6145 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6146 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6147 msg_out->msg_controllen = cm_data_space;
6149 SAFE_FREE(*tmp_control);
6151 SWRAP_LOG(SWRAP_LOG_TRACE,
6152 "msg_out->msg_controllen=%zu",
6153 (size_t)msg_out->msg_controllen);
6155 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6156 int saved_errno = errno;
6157 *msg_out = *msg_tmp;
6158 SAFE_FREE(*tmp_control);
6159 errno = saved_errno;
6161 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6164 static ssize_t swrap_sendmsg_before(int fd,
6165 struct socket_info *si,
6167 struct iovec *tmp_iov,
6168 struct sockaddr_un *tmp_un,
6169 const struct sockaddr_un **to_un,
6170 const struct sockaddr **to,
6192 if (!si->connected) {
6197 if (msg->msg_iovlen == 0) {
6201 mtu = socket_wrapper_mtu();
6202 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6204 nlen = len + msg->msg_iov[i].iov_len;
6214 msg->msg_iovlen = i;
6215 if (msg->msg_iovlen == 0) {
6216 *tmp_iov = msg->msg_iov[0];
6217 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6219 msg->msg_iov = tmp_iov;
6220 msg->msg_iovlen = 1;
6225 if (si->connected) {
6226 if (msg->msg_name != NULL) {
6228 * We are dealing with unix sockets and if we
6229 * are connected, we should only talk to the
6230 * connected unix path. Using the fd to send
6231 * to another server would be hard to achieve.
6233 msg->msg_name = NULL;
6234 msg->msg_namelen = 0;
6237 const struct sockaddr *msg_name;
6238 msg_name = (const struct sockaddr *)msg->msg_name;
6240 if (msg_name == NULL) {
6246 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6258 msg->msg_name = tmp_un;
6259 msg->msg_namelen = sizeof(*tmp_un);
6262 if (si->bound == 0) {
6263 ret = swrap_auto_bind(fd, si, si->family);
6265 SWRAP_UNLOCK_SI(si);
6266 if (errno == ENOTSOCK) {
6267 swrap_remove_stale(fd);
6270 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6276 if (!si->defer_connect) {
6280 ret = sockaddr_convert_to_un(si,
6282 si->peername.sa_socklen,
6290 ret = libc_connect(fd,
6291 (struct sockaddr *)(void *)tmp_un,
6294 /* to give better errors */
6295 if (ret == -1 && errno == ENOENT) {
6296 errno = EHOSTUNREACH;
6303 si->defer_connect = 0;
6306 errno = EHOSTUNREACH;
6312 SWRAP_UNLOCK_SI(si);
6317 static void swrap_sendmsg_after(int fd,
6318 struct socket_info *si,
6320 const struct sockaddr *to,
6323 int saved_errno = errno;
6330 /* to give better errors */
6332 if (saved_errno == ENOENT) {
6333 saved_errno = EHOSTUNREACH;
6334 } else if (saved_errno == ENOTSOCK) {
6335 /* If the fd is not a socket, remove it */
6336 swrap_remove_stale(fd);
6340 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6341 avail += msg->msg_iov[i].iov_len;
6345 remain = MIN(80, avail);
6350 /* we capture it as one single packet */
6351 buf = (uint8_t *)malloc(remain);
6353 /* we just not capture the packet */
6354 errno = saved_errno;
6358 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6359 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6360 if (this_time > 0) {
6362 msg->msg_iov[i].iov_base,
6366 remain -= this_time;
6375 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6376 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6378 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6383 if (si->connected) {
6384 to = &si->peername.sa.s;
6387 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6388 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6390 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6395 SWRAP_UNLOCK_SI(si);
6398 errno = saved_errno;
6401 static int swrap_recvmsg_before(int fd,
6402 struct socket_info *si,
6404 struct iovec *tmp_iov)
6411 (void)fd; /* unused */
6416 if (!si->connected) {
6421 if (msg->msg_iovlen == 0) {
6425 mtu = socket_wrapper_mtu();
6426 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6428 nlen = len + msg->msg_iov[i].iov_len;
6433 msg->msg_iovlen = i;
6434 if (msg->msg_iovlen == 0) {
6435 *tmp_iov = msg->msg_iov[0];
6436 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6438 msg->msg_iov = tmp_iov;
6439 msg->msg_iovlen = 1;
6444 if (msg->msg_name == NULL) {
6449 if (msg->msg_iovlen == 0) {
6453 if (si->bound == 0) {
6454 ret = swrap_auto_bind(fd, si, si->family);
6456 SWRAP_UNLOCK_SI(si);
6458 * When attempting to read or write to a
6459 * descriptor, if an underlying autobind fails
6460 * because it's not a socket, stop intercepting
6461 * uses of that descriptor.
6463 if (errno == ENOTSOCK) {
6464 swrap_remove_stale(fd);
6467 SWRAP_LOG(SWRAP_LOG_ERROR,
6468 "swrap_recvmsg_before failed");
6475 errno = EHOSTUNREACH;
6481 SWRAP_UNLOCK_SI(si);
6486 static int swrap_recvmsg_after(int fd,
6487 struct socket_info *si,
6489 const struct sockaddr_un *un_addr,
6490 socklen_t un_addrlen,
6493 int saved_errno = errno;
6495 uint8_t *buf = NULL;
6501 /* to give better errors */
6503 if (saved_errno == ENOENT) {
6504 saved_errno = EHOSTUNREACH;
6505 } else if (saved_errno == ENOTSOCK) {
6506 /* If the fd is not a socket, remove it */
6507 swrap_remove_stale(fd);
6511 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6512 avail += msg->msg_iov[i].iov_len;
6517 /* Convert the socket address before we leave */
6518 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6519 rc = sockaddr_convert_from_un(si,
6536 remain = MIN(80, avail);
6541 /* we capture it as one single packet */
6542 buf = (uint8_t *)malloc(remain);
6544 /* we just not capture the packet */
6545 SWRAP_UNLOCK_SI(si);
6546 errno = saved_errno;
6550 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6551 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6553 msg->msg_iov[i].iov_base,
6556 remain -= this_time;
6561 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6562 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6563 } else if (ret == 0) { /* END OF FILE */
6564 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6565 } else if (ret > 0) {
6566 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6575 if (un_addr != NULL) {
6576 swrap_pcap_dump_packet(si,
6582 swrap_pcap_dump_packet(si,
6595 errno = saved_errno;
6597 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6599 msg->msg_controllen > 0 &&
6600 msg->msg_control != NULL) {
6601 rc = swrap_msghdr_add_socket_info(si, msg);
6603 SWRAP_UNLOCK_SI(si);
6609 SWRAP_UNLOCK_SI(si);
6613 /****************************************************************************
6615 ***************************************************************************/
6617 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6618 struct sockaddr *from, socklen_t *fromlen)
6620 struct swrap_address from_addr = {
6621 .sa_socklen = sizeof(struct sockaddr_un),
6624 struct socket_info *si = find_socket_info(s);
6625 struct swrap_address saddr = {
6626 .sa_socklen = sizeof(struct sockaddr_storage),
6633 return libc_recvfrom(s,
6645 if (from != NULL && fromlen != NULL) {
6646 msg.msg_name = from; /* optional address */
6647 msg.msg_namelen = *fromlen; /* size of address */
6649 msg.msg_name = &saddr.sa.s; /* optional address */
6650 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6652 msg.msg_iov = &tmp; /* scatter/gather array */
6653 msg.msg_iovlen = 1; /* # elements in msg_iov */
6654 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6655 msg.msg_control = NULL; /* ancillary data, see below */
6656 msg.msg_controllen = 0; /* ancillary data buffer len */
6657 msg.msg_flags = 0; /* flags on received message */
6660 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6665 buf = msg.msg_iov[0].iov_base;
6666 len = msg.msg_iov[0].iov_len;
6668 ret = libc_recvfrom(s,
6673 &from_addr.sa_socklen);
6678 tret = swrap_recvmsg_after(s,
6682 from_addr.sa_socklen,
6688 if (from != NULL && fromlen != NULL) {
6689 *fromlen = msg.msg_namelen;
6695 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6696 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6697 struct sockaddr *from, Psocklen_t fromlen)
6699 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6700 struct sockaddr *from, socklen_t *fromlen)
6703 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6706 /****************************************************************************
6708 ***************************************************************************/
6710 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6711 const struct sockaddr *to, socklen_t tolen)
6715 struct swrap_address un_addr = {
6716 .sa_socklen = sizeof(struct sockaddr_un),
6718 const struct sockaddr_un *to_un = NULL;
6721 struct socket_info *si = find_socket_info(s);
6725 return libc_sendto(s, buf, len, flags, to, tolen);
6728 tmp.iov_base = discard_const_p(char, buf);
6732 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6733 msg.msg_namelen = tolen; /* size of address */
6734 msg.msg_iov = &tmp; /* scatter/gather array */
6735 msg.msg_iovlen = 1; /* # elements in msg_iov */
6736 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6737 msg.msg_control = NULL; /* ancillary data, see below */
6738 msg.msg_controllen = 0; /* ancillary data buffer len */
6739 msg.msg_flags = 0; /* flags on received message */
6742 rc = swrap_sendmsg_before(s,
6754 buf = msg.msg_iov[0].iov_base;
6755 len = msg.msg_iov[0].iov_len;
6760 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6762 char *swrap_dir = NULL;
6764 type = SOCKET_TYPE_CHAR_UDP;
6766 swrap_dir = socket_wrapper_dir();
6767 if (swrap_dir == NULL) {
6771 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6772 swrap_un_path(&un_addr.sa.un,
6777 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6779 /* ignore the any errors in broadcast sends */
6785 un_addr.sa_socklen);
6788 SAFE_FREE(swrap_dir);
6792 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6794 SWRAP_UNLOCK_SI(si);
6801 * If it is a dgram socket and we are connected, don't include the
6804 if (si->type == SOCK_DGRAM && si->connected) {
6805 ret = libc_sendto(s,
6812 ret = libc_sendto(s,
6816 (struct sockaddr *)msg.msg_name,
6820 SWRAP_UNLOCK_SI(si);
6822 swrap_sendmsg_after(s, si, &msg, to, ret);
6827 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6828 const struct sockaddr *to, socklen_t tolen)
6830 return swrap_sendto(s, buf, len, flags, to, tolen);
6833 /****************************************************************************
6835 ***************************************************************************/
6837 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6839 struct socket_info *si;
6841 struct swrap_address saddr = {
6842 .sa_socklen = sizeof(struct sockaddr_storage),
6848 si = find_socket_info(s);
6850 return libc_recv(s, buf, len, flags);
6857 msg.msg_name = &saddr.sa.s; /* optional address */
6858 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6859 msg.msg_iov = &tmp; /* scatter/gather array */
6860 msg.msg_iovlen = 1; /* # elements in msg_iov */
6861 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6862 msg.msg_control = NULL; /* ancillary data, see below */
6863 msg.msg_controllen = 0; /* ancillary data buffer len */
6864 msg.msg_flags = 0; /* flags on received message */
6867 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6872 buf = msg.msg_iov[0].iov_base;
6873 len = msg.msg_iov[0].iov_len;
6875 ret = libc_recv(s, buf, len, flags);
6877 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6885 ssize_t recv(int s, void *buf, size_t len, int flags)
6887 return swrap_recv(s, buf, len, flags);
6890 /****************************************************************************
6892 ***************************************************************************/
6894 static ssize_t swrap_read(int s, void *buf, size_t len)
6896 struct socket_info *si;
6899 struct swrap_address saddr = {
6900 .sa_socklen = sizeof(struct sockaddr_storage),
6905 si = find_socket_info(s);
6907 return libc_read(s, buf, len);
6914 msg.msg_name = &saddr.sa.ss; /* optional address */
6915 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6916 msg.msg_iov = &tmp; /* scatter/gather array */
6917 msg.msg_iovlen = 1; /* # elements in msg_iov */
6918 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6919 msg.msg_control = NULL; /* ancillary data, see below */
6920 msg.msg_controllen = 0; /* ancillary data buffer len */
6921 msg.msg_flags = 0; /* flags on received message */
6924 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6926 if (tret == -ENOTSOCK) {
6927 return libc_read(s, buf, len);
6932 buf = msg.msg_iov[0].iov_base;
6933 len = msg.msg_iov[0].iov_len;
6935 ret = libc_read(s, buf, len);
6937 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6945 ssize_t read(int s, void *buf, size_t len)
6947 return swrap_read(s, buf, len);
6950 /****************************************************************************
6952 ***************************************************************************/
6954 static ssize_t swrap_write(int s, const void *buf, size_t len)
6958 struct sockaddr_un un_addr;
6961 struct socket_info *si;
6963 si = find_socket_info(s);
6965 return libc_write(s, buf, len);
6968 tmp.iov_base = discard_const_p(char, buf);
6972 msg.msg_name = NULL; /* optional address */
6973 msg.msg_namelen = 0; /* size of address */
6974 msg.msg_iov = &tmp; /* scatter/gather array */
6975 msg.msg_iovlen = 1; /* # elements in msg_iov */
6976 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6977 msg.msg_control = NULL; /* ancillary data, see below */
6978 msg.msg_controllen = 0; /* ancillary data buffer len */
6979 msg.msg_flags = 0; /* flags on received message */
6982 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6987 buf = msg.msg_iov[0].iov_base;
6988 len = msg.msg_iov[0].iov_len;
6990 ret = libc_write(s, buf, len);
6992 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6997 ssize_t write(int s, const void *buf, size_t len)
6999 return swrap_write(s, buf, len);
7002 /****************************************************************************
7004 ***************************************************************************/
7006 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
7010 struct sockaddr_un un_addr;
7013 struct socket_info *si = find_socket_info(s);
7016 return libc_send(s, buf, len, flags);
7019 tmp.iov_base = discard_const_p(char, buf);
7023 msg.msg_name = NULL; /* optional address */
7024 msg.msg_namelen = 0; /* size of address */
7025 msg.msg_iov = &tmp; /* scatter/gather array */
7026 msg.msg_iovlen = 1; /* # elements in msg_iov */
7027 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7028 msg.msg_control = NULL; /* ancillary data, see below */
7029 msg.msg_controllen = 0; /* ancillary data buffer len */
7030 msg.msg_flags = 0; /* flags on received message */
7033 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7038 buf = msg.msg_iov[0].iov_base;
7039 len = msg.msg_iov[0].iov_len;
7041 ret = libc_send(s, buf, len, flags);
7043 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7048 ssize_t send(int s, const void *buf, size_t len, int flags)
7050 return swrap_send(s, buf, len, flags);
7053 /****************************************************************************
7055 ***************************************************************************/
7057 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7059 struct swrap_address from_addr = {
7060 .sa_socklen = sizeof(struct sockaddr_un),
7062 struct swrap_address convert_addr = {
7063 .sa_socklen = sizeof(struct sockaddr_storage),
7065 struct socket_info *si;
7068 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7069 size_t msg_ctrllen_filled;
7070 size_t msg_ctrllen_left;
7076 si = find_socket_info(s);
7078 uint8_t *tmp_control = NULL;
7079 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7083 ret = libc_recvmsg(s, &msg, flags);
7084 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7087 tmp.iov_base = NULL;
7091 msg.msg_name = &from_addr.sa; /* optional address */
7092 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7093 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7094 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7095 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7096 msg_ctrllen_filled = 0;
7097 msg_ctrllen_left = omsg->msg_controllen;
7099 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7100 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7101 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7104 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7109 ret = libc_recvmsg(s, &msg, flags);
7111 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7112 msg_ctrllen_filled += msg.msg_controllen;
7113 msg_ctrllen_left -= msg.msg_controllen;
7115 if (omsg->msg_control != NULL) {
7118 p = omsg->msg_control;
7119 p += msg_ctrllen_filled;
7121 msg.msg_control = p;
7122 msg.msg_controllen = msg_ctrllen_left;
7124 msg.msg_control = NULL;
7125 msg.msg_controllen = 0;
7130 * We convert the unix address to a IP address so we need a buffer
7131 * which can store the address in case of SOCK_DGRAM, see below.
7133 msg.msg_name = &convert_addr.sa;
7134 msg.msg_namelen = convert_addr.sa_socklen;
7136 rc = swrap_recvmsg_after(s,
7140 from_addr.sa_socklen,
7146 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7147 if (omsg->msg_control != NULL) {
7148 /* msg.msg_controllen = space left */
7149 msg_ctrllen_left = msg.msg_controllen;
7150 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7153 /* Update the original message length */
7154 omsg->msg_controllen = msg_ctrllen_filled;
7155 omsg->msg_flags = msg.msg_flags;
7157 omsg->msg_iovlen = msg.msg_iovlen;
7164 * The msg_name field points to a caller-allocated buffer that is
7165 * used to return the source address if the socket is unconnected. The
7166 * caller should set msg_namelen to the size of this buffer before this
7167 * call; upon return from a successful call, msg_name will contain the
7168 * length of the returned address. If the application does not need
7169 * to know the source address, msg_name can be specified as NULL.
7171 if (si->type == SOCK_STREAM) {
7172 omsg->msg_namelen = 0;
7173 } else if (omsg->msg_name != NULL &&
7174 omsg->msg_namelen != 0 &&
7175 omsg->msg_namelen >= msg.msg_namelen) {
7176 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7177 omsg->msg_namelen = msg.msg_namelen;
7180 SWRAP_UNLOCK_SI(si);
7185 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7187 return swrap_recvmsg(sockfd, msg, flags);
7190 /****************************************************************************
7192 ***************************************************************************/
7194 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7198 struct sockaddr_un un_addr;
7199 const struct sockaddr_un *to_un = NULL;
7200 const struct sockaddr *to = NULL;
7203 struct socket_info *si = find_socket_info(s);
7207 int scm_rights_pipe_fd = -1;
7209 rc = swrap_sendmsg_before_unix(omsg, &msg,
7210 &scm_rights_pipe_fd);
7214 ret = libc_sendmsg(s, &msg, flags);
7215 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7218 ZERO_STRUCT(un_addr);
7220 tmp.iov_base = NULL;
7227 if (si->connected == 0) {
7228 msg.msg_name = omsg->msg_name; /* optional address */
7229 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7231 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7232 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7234 SWRAP_UNLOCK_SI(si);
7236 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7237 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7238 uint8_t *cmbuf = NULL;
7241 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7247 msg.msg_controllen = 0;
7248 msg.msg_control = NULL;
7250 msg.msg_control = cmbuf;
7251 msg.msg_controllen = cmlen;
7254 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7256 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7258 int saved_errno = errno;
7259 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7260 SAFE_FREE(msg.msg_control);
7262 errno = saved_errno;
7269 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7276 char *swrap_dir = NULL;
7278 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7279 avail += msg.msg_iov[i].iov_len;
7285 /* we capture it as one single packet */
7286 buf = (uint8_t *)malloc(remain);
7288 int saved_errno = errno;
7289 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7290 SAFE_FREE(msg.msg_control);
7292 errno = saved_errno;
7296 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7297 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7299 msg.msg_iov[i].iov_base,
7302 remain -= this_time;
7305 type = SOCKET_TYPE_CHAR_UDP;
7307 swrap_dir = socket_wrapper_dir();
7308 if (swrap_dir == NULL) {
7309 int saved_errno = errno;
7310 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7311 SAFE_FREE(msg.msg_control);
7314 errno = saved_errno;
7318 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7319 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7320 if (stat(un_addr.sun_path, &st) != 0) continue;
7322 msg.msg_name = &un_addr; /* optional address */
7323 msg.msg_namelen = sizeof(un_addr); /* size of address */
7325 /* ignore the any errors in broadcast sends */
7326 libc_sendmsg(s, &msg, flags);
7329 SAFE_FREE(swrap_dir);
7333 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7336 SWRAP_UNLOCK_SI(si);
7341 ret = libc_sendmsg(s, &msg, flags);
7343 swrap_sendmsg_after(s, si, &msg, to, ret);
7345 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7347 int saved_errno = errno;
7348 SAFE_FREE(msg.msg_control);
7349 errno = saved_errno;
7356 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7358 return swrap_sendmsg(s, omsg, flags);
7361 /****************************************************************************
7363 ***************************************************************************/
7365 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7367 struct socket_info *si;
7370 struct swrap_address saddr = {
7371 .sa_socklen = sizeof(struct sockaddr_storage)
7376 si = find_socket_info(s);
7378 return libc_readv(s, vector, count);
7381 tmp.iov_base = NULL;
7385 msg.msg_name = &saddr.sa.s; /* optional address */
7386 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7387 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7388 msg.msg_iovlen = count; /* # elements in msg_iov */
7389 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7390 msg.msg_control = NULL; /* ancillary data, see below */
7391 msg.msg_controllen = 0; /* ancillary data buffer len */
7392 msg.msg_flags = 0; /* flags on received message */
7395 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7397 if (rc == -ENOTSOCK) {
7398 return libc_readv(s, vector, count);
7403 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7405 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7413 ssize_t readv(int s, const struct iovec *vector, int count)
7415 return swrap_readv(s, vector, count);
7418 /****************************************************************************
7420 ***************************************************************************/
7422 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7426 struct sockaddr_un un_addr;
7429 struct socket_info *si = find_socket_info(s);
7432 return libc_writev(s, vector, count);
7435 tmp.iov_base = NULL;
7439 msg.msg_name = NULL; /* optional address */
7440 msg.msg_namelen = 0; /* size of address */
7441 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7442 msg.msg_iovlen = count; /* # elements in msg_iov */
7443 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7444 msg.msg_control = NULL; /* ancillary data, see below */
7445 msg.msg_controllen = 0; /* ancillary data buffer len */
7446 msg.msg_flags = 0; /* flags on received message */
7449 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7451 if (rc == -ENOTSOCK) {
7452 return libc_readv(s, vector, count);
7457 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7459 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7464 ssize_t writev(int s, const struct iovec *vector, int count)
7466 return swrap_writev(s, vector, count);
7469 /****************************
7471 ***************************/
7473 static int swrap_remove_wrapper(const char *__func_name,
7474 int (*__close_fd_fn)(int fd),
7477 struct socket_info *si = NULL;
7479 int ret_errno = errno;
7482 swrap_mutex_lock(&socket_reset_mutex);
7484 si_index = find_socket_info_index(fd);
7485 if (si_index == -1) {
7486 swrap_mutex_unlock(&socket_reset_mutex);
7487 return __close_fd_fn(fd);
7490 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
7491 reset_socket_info_index(fd);
7493 si = swrap_get_socket_info(si_index);
7495 swrap_mutex_lock(&first_free_mutex);
7498 ret = __close_fd_fn(fd);
7503 swrap_dec_refcount(si);
7505 if (swrap_get_refcount(si) > 0) {
7506 /* there are still references left */
7510 if (si->fd_passed) {
7514 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7515 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7518 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7519 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7520 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7523 if (si->un_addr.sun_path[0] != '\0') {
7524 unlink(si->un_addr.sun_path);
7528 swrap_set_next_free(si, first_free);
7529 first_free = si_index;
7532 SWRAP_UNLOCK_SI(si);
7533 swrap_mutex_unlock(&first_free_mutex);
7534 swrap_mutex_unlock(&socket_reset_mutex);
7540 static int swrap_noop_close(int fd)
7542 (void)fd; /* unused */
7546 static void swrap_remove_stale(int fd)
7548 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7552 * This allows socket_wrapper aware applications to
7553 * indicate that the given fd does not belong to
7556 * We already overload a lot of unrelated functions
7557 * like eventfd(), timerfd_create(), ... in order to
7558 * call swrap_remove_stale() on the returned fd, but
7559 * we'll never be able to handle all possible syscalls.
7561 * socket_wrapper_indicate_no_inet_fd() gives them a way
7564 * We don't export swrap_remove_stale() in order to
7565 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
7568 void socket_wrapper_indicate_no_inet_fd(int fd)
7570 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7573 static int swrap_close(int fd)
7575 return swrap_remove_wrapper(__func__, libc_close, fd);
7580 return swrap_close(fd);
7583 #ifdef HAVE___CLOSE_NOCANCEL
7585 static int swrap___close_nocancel(int fd)
7587 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
7590 int __close_nocancel(int fd);
7591 int __close_nocancel(int fd)
7593 return swrap___close_nocancel(fd);
7596 #endif /* HAVE___CLOSE_NOCANCEL */
7598 /****************************
7600 ***************************/
7602 static int swrap_dup(int fd)
7604 struct socket_info *si;
7607 idx = find_socket_info_index(fd);
7609 return libc_dup(fd);
7612 si = swrap_get_socket_info(idx);
7614 dup_fd = libc_dup(fd);
7616 int saved_errno = errno;
7617 errno = saved_errno;
7621 if ((size_t)dup_fd >= socket_fds_max) {
7622 SWRAP_LOG(SWRAP_LOG_ERROR,
7623 "The max socket index limit of %zu has been reached, "
7634 swrap_inc_refcount(si);
7636 SWRAP_UNLOCK_SI(si);
7638 /* Make sure we don't have an entry for the fd */
7639 swrap_remove_stale(dup_fd);
7641 set_socket_info_index(dup_fd, idx);
7648 return swrap_dup(fd);
7651 /****************************
7653 ***************************/
7655 static int swrap_dup2(int fd, int newfd)
7657 struct socket_info *si;
7660 idx = find_socket_info_index(fd);
7662 return libc_dup2(fd, newfd);
7665 si = swrap_get_socket_info(idx);
7669 * According to the manpage:
7671 * "If oldfd is a valid file descriptor, and newfd has the same
7672 * value as oldfd, then dup2() does nothing, and returns newfd."
7677 if ((size_t)newfd >= socket_fds_max) {
7678 SWRAP_LOG(SWRAP_LOG_ERROR,
7679 "The max socket index limit of %zu has been reached, "
7687 if (find_socket_info(newfd)) {
7688 /* dup2() does an implicit close of newfd, which we
7689 * need to emulate */
7693 dup_fd = libc_dup2(fd, newfd);
7695 int saved_errno = errno;
7696 errno = saved_errno;
7702 swrap_inc_refcount(si);
7704 SWRAP_UNLOCK_SI(si);
7706 /* Make sure we don't have an entry for the fd */
7707 swrap_remove_stale(dup_fd);
7709 set_socket_info_index(dup_fd, idx);
7714 int dup2(int fd, int newfd)
7716 return swrap_dup2(fd, newfd);
7719 /****************************
7721 ***************************/
7723 static int swrap_vfcntl(int fd, int cmd, va_list va)
7725 struct socket_info *si;
7726 int rc, dup_fd, idx;
7728 idx = find_socket_info_index(fd);
7730 return libc_vfcntl(fd, cmd, va);
7733 si = swrap_get_socket_info(idx);
7737 dup_fd = libc_vfcntl(fd, cmd, va);
7739 int saved_errno = errno;
7740 errno = saved_errno;
7744 /* Make sure we don't have an entry for the fd */
7745 swrap_remove_stale(dup_fd);
7747 if ((size_t)dup_fd >= socket_fds_max) {
7748 SWRAP_LOG(SWRAP_LOG_ERROR,
7749 "The max socket index limit of %zu has been reached, "
7760 swrap_inc_refcount(si);
7762 SWRAP_UNLOCK_SI(si);
7765 set_socket_info_index(dup_fd, idx);
7770 rc = libc_vfcntl(fd, cmd, va);
7777 int fcntl(int fd, int cmd, ...)
7784 rc = swrap_vfcntl(fd, cmd, va);
7791 /****************************
7793 ***************************/
7796 static int swrap_eventfd(int count, int flags)
7800 fd = libc_eventfd(count, flags);
7802 swrap_remove_stale(fd);
7808 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7809 int eventfd(unsigned int count, int flags)
7811 int eventfd(int count, int flags)
7814 return swrap_eventfd(count, flags);
7819 int pledge(const char *promises, const char *paths[])
7821 (void)promises; /* unused */
7822 (void)paths; /* unused */
7826 #endif /* HAVE_PLEDGE */
7828 static void swrap_thread_prepare(void)
7831 * This function should only be called here!!
7833 * We bind all symobls to avoid deadlocks of the fork is
7834 * interrupted by a signal handler using a symbol of this
7837 swrap_bind_symbol_all();
7842 static void swrap_thread_parent(void)
7847 static void swrap_thread_child(void)
7852 /****************************
7854 ***************************/
7855 void swrap_constructor(void)
7857 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7858 SWRAP_LOG(SWRAP_LOG_ERROR,
7860 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7861 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7862 "sizeof(struct socket_info)=%zu",
7864 sizeof(struct swrap_unix_scm_rights),
7865 sizeof(struct swrap_unix_scm_rights_payload),
7866 sizeof(struct socket_info));
7873 * If we hold a lock and the application forks, then the child
7874 * is not able to unlock the mutex and we are in a deadlock.
7875 * This should prevent such deadlocks.
7877 pthread_atfork(&swrap_thread_prepare,
7878 &swrap_thread_parent,
7879 &swrap_thread_child);
7882 /****************************
7884 ***************************/
7887 * This function is called when the library is unloaded and makes sure that
7888 * sockets get closed and the unix file for the socket are unlinked.
7890 void swrap_destructor(void)
7894 if (socket_fds_idx != NULL) {
7895 for (i = 0; i < socket_fds_max; ++i) {
7896 if (socket_fds_idx[i] != -1) {
7900 SAFE_FREE(socket_fds_idx);
7905 if (swrap.libc.handle != NULL
7907 && swrap.libc.handle != RTLD_NEXT
7910 dlclose(swrap.libc.handle);
7912 if (swrap.libc.socket_handle
7914 && swrap.libc.socket_handle != RTLD_NEXT
7917 dlclose(swrap.libc.socket_handle);
7921 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7923 * On FreeBSD 12 (and maybe other platforms)
7924 * system libraries like libresolv prefix there
7925 * syscalls with '_' in order to always use
7926 * the symbols from libc.
7928 * In the interaction with resolv_wrapper,
7929 * we need to inject socket wrapper into libresolv,
7930 * which means we need to private all socket
7931 * related syscalls also with the '_' prefix.
7933 * This is tested in Samba's 'make test',
7934 * there we noticed that providing '_read',
7935 * '_open' and '_close' would cause errors, which
7936 * means we skip '_read', '_write' and
7937 * all non socket related calls without
7938 * further analyzing the problem.
7940 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7941 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7944 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7946 SWRAP_SYMBOL_ALIAS(accept, _accept);
7947 SWRAP_SYMBOL_ALIAS(bind, _bind);
7948 SWRAP_SYMBOL_ALIAS(connect, _connect);
7949 SWRAP_SYMBOL_ALIAS(dup, _dup);
7950 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7951 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7952 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7953 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7954 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7955 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7956 SWRAP_SYMBOL_ALIAS(listen, _listen);
7957 SWRAP_SYMBOL_ALIAS(readv, _readv);
7958 SWRAP_SYMBOL_ALIAS(recv, _recv);
7959 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7960 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7961 SWRAP_SYMBOL_ALIAS(send, _send);
7962 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7963 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7964 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7965 SWRAP_SYMBOL_ALIAS(socket, _socket);
7966 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7967 SWRAP_SYMBOL_ALIAS(writev, _writev);
7969 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */