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 typedef int (*__libc_connect)(int sockfd,
496 const struct sockaddr *addr,
498 typedef int (*__libc_dup)(int fd);
499 typedef int (*__libc_dup2)(int oldfd, int newfd);
500 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
501 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
503 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
506 typedef int (*__libc_eventfd)(int count, int flags);
508 typedef int (*__libc_getpeername)(int sockfd,
509 struct sockaddr *addr,
511 typedef int (*__libc_getsockname)(int sockfd,
512 struct sockaddr *addr,
514 typedef int (*__libc_getsockopt)(int sockfd,
519 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
520 typedef int (*__libc_listen)(int sockfd, int backlog);
521 typedef int (*__libc_open)(const char *pathname, int flags, ...);
523 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
524 #endif /* HAVE_OPEN64 */
525 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
526 typedef int (*__libc_pipe)(int pipefd[2]);
527 typedef int (*__libc_read)(int fd, void *buf, size_t count);
528 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
529 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
530 typedef int (*__libc_recvfrom)(int sockfd,
534 struct sockaddr *src_addr,
536 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
537 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
538 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
539 typedef int (*__libc_sendto)(int sockfd,
543 const struct sockaddr *dst_addr,
545 typedef int (*__libc_setsockopt)(int sockfd,
551 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
553 typedef int (*__libc_socket)(int domain, int type, int protocol);
554 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
555 #ifdef HAVE_TIMERFD_CREATE
556 typedef int (*__libc_timerfd_create)(int clockid, int flags);
558 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
559 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
561 #define SWRAP_SYMBOL_ENTRY(i) \
567 struct swrap_libc_symbols {
569 SWRAP_SYMBOL_ENTRY(accept4);
571 SWRAP_SYMBOL_ENTRY(accept);
573 SWRAP_SYMBOL_ENTRY(bind);
574 SWRAP_SYMBOL_ENTRY(close);
575 SWRAP_SYMBOL_ENTRY(connect);
576 SWRAP_SYMBOL_ENTRY(dup);
577 SWRAP_SYMBOL_ENTRY(dup2);
578 SWRAP_SYMBOL_ENTRY(fcntl);
579 SWRAP_SYMBOL_ENTRY(fopen);
581 SWRAP_SYMBOL_ENTRY(fopen64);
584 SWRAP_SYMBOL_ENTRY(eventfd);
586 SWRAP_SYMBOL_ENTRY(getpeername);
587 SWRAP_SYMBOL_ENTRY(getsockname);
588 SWRAP_SYMBOL_ENTRY(getsockopt);
589 SWRAP_SYMBOL_ENTRY(ioctl);
590 SWRAP_SYMBOL_ENTRY(listen);
591 SWRAP_SYMBOL_ENTRY(open);
593 SWRAP_SYMBOL_ENTRY(open64);
595 SWRAP_SYMBOL_ENTRY(openat);
596 SWRAP_SYMBOL_ENTRY(pipe);
597 SWRAP_SYMBOL_ENTRY(read);
598 SWRAP_SYMBOL_ENTRY(readv);
599 SWRAP_SYMBOL_ENTRY(recv);
600 SWRAP_SYMBOL_ENTRY(recvfrom);
601 SWRAP_SYMBOL_ENTRY(recvmsg);
602 SWRAP_SYMBOL_ENTRY(send);
603 SWRAP_SYMBOL_ENTRY(sendmsg);
604 SWRAP_SYMBOL_ENTRY(sendto);
605 SWRAP_SYMBOL_ENTRY(setsockopt);
607 SWRAP_SYMBOL_ENTRY(signalfd);
609 SWRAP_SYMBOL_ENTRY(socket);
610 SWRAP_SYMBOL_ENTRY(socketpair);
611 #ifdef HAVE_TIMERFD_CREATE
612 SWRAP_SYMBOL_ENTRY(timerfd_create);
614 SWRAP_SYMBOL_ENTRY(write);
615 SWRAP_SYMBOL_ENTRY(writev);
622 struct swrap_libc_symbols symbols;
626 static struct swrap swrap;
629 static char *socket_wrapper_dir(void);
631 #define LIBC_NAME "libc.so"
638 static const char *swrap_str_lib(enum swrap_lib lib)
643 case SWRAP_LIBSOCKET:
647 /* Compiler would warn us about unhandled enum value if we get here */
651 static void *swrap_load_lib_handle(enum swrap_lib lib)
653 int flags = RTLD_LAZY;
658 const char *env_preload = getenv("LD_PRELOAD");
659 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
660 bool enable_deepbind = true;
662 /* Don't do a deepbind if we run with libasan */
663 if (env_preload != NULL && strlen(env_preload) < 1024) {
664 const char *p = strstr(env_preload, "libasan.so");
666 enable_deepbind = false;
670 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
671 enable_deepbind = false;
674 if (enable_deepbind) {
675 flags |= RTLD_DEEPBIND;
680 case SWRAP_LIBSOCKET:
681 #ifdef HAVE_LIBSOCKET
682 handle = swrap.libc.socket_handle;
683 if (handle == NULL) {
684 for (i = 10; i >= 0; i--) {
685 char soname[256] = {0};
687 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
688 handle = dlopen(soname, flags);
689 if (handle != NULL) {
694 swrap.libc.socket_handle = handle;
699 handle = swrap.libc.handle;
701 if (handle == NULL) {
702 handle = dlopen(LIBC_SO, flags);
704 swrap.libc.handle = handle;
707 if (handle == NULL) {
708 for (i = 10; i >= 0; i--) {
709 char soname[256] = {0};
711 snprintf(soname, sizeof(soname), "libc.so.%d", i);
712 handle = dlopen(soname, flags);
713 if (handle != NULL) {
718 swrap.libc.handle = handle;
723 if (handle == NULL) {
725 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
727 SWRAP_LOG(SWRAP_LOG_ERROR,
728 "Failed to dlopen library: %s",
737 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
742 handle = swrap_load_lib_handle(lib);
744 func = dlsym(handle, fn_name);
746 SWRAP_LOG(SWRAP_LOG_ERROR,
747 "Failed to find %s: %s",
753 SWRAP_LOG(SWRAP_LOG_TRACE,
761 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
762 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
766 ret = pthread_mutex_lock(mutex);
768 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
769 getpid(), getppid(), caller, line, name, strerror(ret));
774 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
775 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
779 ret = pthread_mutex_unlock(mutex);
781 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
782 getpid(), getppid(), caller, line, name, strerror(ret));
788 * These macros have a thread race condition on purpose!
790 * This is an optimization to avoid locking each time we check if the symbol is
793 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
794 swrap.libc.symbols._libc_##sym_name.obj = \
795 _swrap_bind_symbol(lib, #sym_name); \
798 #define swrap_bind_symbol_libc(sym_name) \
799 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
801 #define swrap_bind_symbol_libsocket(sym_name) \
802 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
804 static void swrap_bind_symbol_all(void);
806 /****************************************************************************
808 ****************************************************************************
810 * Functions especially from libc need to be loaded individually, you can't
811 * load all at once or gdb will segfault at startup. The same applies to
812 * valgrind and has probably something todo with with the linker. So we need
813 * load each function at the point it is called the first time.
815 ****************************************************************************/
818 static int libc_accept4(int sockfd,
819 struct sockaddr *addr,
823 swrap_bind_symbol_all();
825 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
828 #else /* HAVE_ACCEPT4 */
830 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
832 swrap_bind_symbol_all();
834 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
836 #endif /* HAVE_ACCEPT4 */
838 static int libc_bind(int sockfd,
839 const struct sockaddr *addr,
842 swrap_bind_symbol_all();
844 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
847 static int libc_close(int fd)
849 swrap_bind_symbol_all();
851 return swrap.libc.symbols._libc_close.f(fd);
854 static int libc_connect(int sockfd,
855 const struct sockaddr *addr,
858 swrap_bind_symbol_all();
860 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
863 static int libc_dup(int fd)
865 swrap_bind_symbol_all();
867 return swrap.libc.symbols._libc_dup.f(fd);
870 static int libc_dup2(int oldfd, int newfd)
872 swrap_bind_symbol_all();
874 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
878 static int libc_eventfd(int count, int flags)
880 swrap_bind_symbol_all();
882 return swrap.libc.symbols._libc_eventfd.f(count, flags);
886 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
887 static int libc_vfcntl(int fd, int cmd, va_list ap)
892 swrap_bind_symbol_all();
894 arg = va_arg(ap, void *);
896 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
901 static int libc_getpeername(int sockfd,
902 struct sockaddr *addr,
905 swrap_bind_symbol_all();
907 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
910 static int libc_getsockname(int sockfd,
911 struct sockaddr *addr,
914 swrap_bind_symbol_all();
916 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
919 static int libc_getsockopt(int sockfd,
925 swrap_bind_symbol_all();
927 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
934 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
935 static int libc_vioctl(int d, unsigned long int request, va_list ap)
940 swrap_bind_symbol_all();
942 arg = va_arg(ap, void *);
944 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
949 static int libc_listen(int sockfd, int backlog)
951 swrap_bind_symbol_all();
953 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
956 static FILE *libc_fopen(const char *name, const char *mode)
958 swrap_bind_symbol_all();
960 return swrap.libc.symbols._libc_fopen.f(name, mode);
964 static FILE *libc_fopen64(const char *name, const char *mode)
966 swrap_bind_symbol_all();
968 return swrap.libc.symbols._libc_fopen64.f(name, mode);
970 #endif /* HAVE_FOPEN64 */
972 static int libc_vopen(const char *pathname, int flags, va_list ap)
977 swrap_bind_symbol_all();
979 if (flags & O_CREAT) {
980 mode = va_arg(ap, int);
982 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
987 static int libc_open(const char *pathname, int flags, ...)
993 fd = libc_vopen(pathname, flags, ap);
1000 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1005 swrap_bind_symbol_all();
1007 if (flags & O_CREAT) {
1008 mode = va_arg(ap, int);
1010 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1014 #endif /* HAVE_OPEN64 */
1016 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1021 swrap_bind_symbol_all();
1023 if (flags & O_CREAT) {
1024 mode = va_arg(ap, int);
1026 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1035 static int libc_openat(int dirfd, const char *path, int flags, ...)
1040 va_start(ap, flags);
1041 fd = libc_vopenat(dirfd, path, flags, ap);
1048 static int libc_pipe(int pipefd[2])
1050 swrap_bind_symbol_all();
1052 return swrap.libc.symbols._libc_pipe.f(pipefd);
1055 static int libc_read(int fd, void *buf, size_t count)
1057 swrap_bind_symbol_all();
1059 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1062 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1064 swrap_bind_symbol_all();
1066 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1069 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1071 swrap_bind_symbol_all();
1073 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1076 static int libc_recvfrom(int sockfd,
1080 struct sockaddr *src_addr,
1083 swrap_bind_symbol_all();
1085 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1093 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1095 swrap_bind_symbol_all();
1097 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1100 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1102 swrap_bind_symbol_all();
1104 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1107 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1109 swrap_bind_symbol_all();
1111 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1114 static int libc_sendto(int sockfd,
1118 const struct sockaddr *dst_addr,
1121 swrap_bind_symbol_all();
1123 return swrap.libc.symbols._libc_sendto.f(sockfd,
1131 static int libc_setsockopt(int sockfd,
1137 swrap_bind_symbol_all();
1139 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1146 #ifdef HAVE_SIGNALFD
1147 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1149 swrap_bind_symbol_all();
1151 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1155 static int libc_socket(int domain, int type, int protocol)
1157 swrap_bind_symbol_all();
1159 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1162 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1164 swrap_bind_symbol_all();
1166 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1169 #ifdef HAVE_TIMERFD_CREATE
1170 static int libc_timerfd_create(int clockid, int flags)
1172 swrap_bind_symbol_all();
1174 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1178 static ssize_t libc_write(int fd, const void *buf, size_t count)
1180 swrap_bind_symbol_all();
1182 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1185 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1187 swrap_bind_symbol_all();
1189 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1192 /* DO NOT call this function during library initialization! */
1193 static void __swrap_bind_symbol_all_once(void)
1196 swrap_bind_symbol_libsocket(accept4);
1198 swrap_bind_symbol_libsocket(accept);
1200 swrap_bind_symbol_libsocket(bind);
1201 swrap_bind_symbol_libc(close);
1202 swrap_bind_symbol_libsocket(connect);
1203 swrap_bind_symbol_libc(dup);
1204 swrap_bind_symbol_libc(dup2);
1205 swrap_bind_symbol_libc(fcntl);
1206 swrap_bind_symbol_libc(fopen);
1208 swrap_bind_symbol_libc(fopen64);
1211 swrap_bind_symbol_libc(eventfd);
1213 swrap_bind_symbol_libsocket(getpeername);
1214 swrap_bind_symbol_libsocket(getsockname);
1215 swrap_bind_symbol_libsocket(getsockopt);
1216 swrap_bind_symbol_libc(ioctl);
1217 swrap_bind_symbol_libsocket(listen);
1218 swrap_bind_symbol_libc(open);
1220 swrap_bind_symbol_libc(open64);
1222 swrap_bind_symbol_libc(openat);
1223 swrap_bind_symbol_libsocket(pipe);
1224 swrap_bind_symbol_libc(read);
1225 swrap_bind_symbol_libsocket(readv);
1226 swrap_bind_symbol_libsocket(recv);
1227 swrap_bind_symbol_libsocket(recvfrom);
1228 swrap_bind_symbol_libsocket(recvmsg);
1229 swrap_bind_symbol_libsocket(send);
1230 swrap_bind_symbol_libsocket(sendmsg);
1231 swrap_bind_symbol_libsocket(sendto);
1232 swrap_bind_symbol_libsocket(setsockopt);
1233 #ifdef HAVE_SIGNALFD
1234 swrap_bind_symbol_libsocket(signalfd);
1236 swrap_bind_symbol_libsocket(socket);
1237 swrap_bind_symbol_libsocket(socketpair);
1238 #ifdef HAVE_TIMERFD_CREATE
1239 swrap_bind_symbol_libc(timerfd_create);
1241 swrap_bind_symbol_libc(write);
1242 swrap_bind_symbol_libsocket(writev);
1245 static void swrap_bind_symbol_all(void)
1247 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1249 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1252 /*********************************************************
1253 * SWRAP HELPER FUNCTIONS
1254 *********************************************************/
1257 * We return 127.0.0.0 (default) or 10.53.57.0.
1259 * This can be controlled by:
1260 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1262 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1264 static in_addr_t swrap_ipv4_net(void)
1266 static int initialized;
1267 static in_addr_t hv;
1268 const char *net_str = NULL;
1277 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1278 if (net_str == NULL) {
1279 net_str = "127.0.0.0";
1282 ret = inet_pton(AF_INET, net_str, &nv);
1284 SWRAP_LOG(SWRAP_LOG_ERROR,
1285 "INVALID IPv4 Network [%s]",
1290 hv = ntohl(nv.s_addr);
1300 SWRAP_LOG(SWRAP_LOG_ERROR,
1301 "INVALID IPv4 Network [%s][0x%x] should be "
1302 "127.0.0.0 or 10.53.57.0",
1303 net_str, (unsigned)hv);
1311 * This returns 127.255.255.255 or 10.255.255.255
1313 static in_addr_t swrap_ipv4_bcast(void)
1317 hv = swrap_ipv4_net();
1318 hv |= IN_CLASSA_HOST;
1324 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1326 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1330 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1331 SWRAP_LOG(SWRAP_LOG_ERROR,
1332 "swrap_ipv4_iface(%u) invalid!",
1338 hv = swrap_ipv4_net();
1348 static const struct in6_addr *swrap_ipv6(void)
1350 static struct in6_addr v;
1351 static int initialized;
1359 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1368 static void set_port(int family, int prt, struct swrap_address *addr)
1372 addr->sa.in.sin_port = htons(prt);
1376 addr->sa.in6.sin6_port = htons(prt);
1382 static size_t socket_length(int family)
1386 return sizeof(struct sockaddr_in);
1389 return sizeof(struct sockaddr_in6);
1395 static struct socket_info *swrap_get_socket_info(int si_index)
1397 return (struct socket_info *)(&(sockets[si_index].info));
1400 static int swrap_get_refcount(struct socket_info *si)
1402 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1403 return sic->meta.refcount;
1406 static void swrap_inc_refcount(struct socket_info *si)
1408 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1410 sic->meta.refcount += 1;
1413 static void swrap_dec_refcount(struct socket_info *si)
1415 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1417 sic->meta.refcount -= 1;
1420 static int swrap_get_next_free(struct socket_info *si)
1422 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1424 return sic->meta.next_free;
1427 static void swrap_set_next_free(struct socket_info *si, int next_free)
1429 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1431 sic->meta.next_free = next_free;
1434 static int swrap_un_path(struct sockaddr_un *un,
1435 const char *swrap_dir,
1442 ret = snprintf(un->sun_path,
1443 sizeof(un->sun_path),
1449 if ((size_t)ret >= sizeof(un->sun_path)) {
1450 return ENAMETOOLONG;
1456 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1457 const char *swrap_dir)
1461 ret = snprintf(un->sun_path,
1462 sizeof(un->sun_path),
1466 if ((size_t)ret >= sizeof(un->sun_path)) {
1467 return ENAMETOOLONG;
1473 static bool swrap_dir_usable(const char *swrap_dir)
1475 struct sockaddr_un un;
1478 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1483 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1491 static char *socket_wrapper_dir(void)
1493 char *swrap_dir = NULL;
1494 char *s = getenv("SOCKET_WRAPPER_DIR");
1498 if (s == NULL || s[0] == '\0') {
1499 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1503 swrap_dir = realpath(s, NULL);
1504 if (swrap_dir == NULL) {
1505 SWRAP_LOG(SWRAP_LOG_ERROR,
1506 "Unable to resolve socket_wrapper dir path: %s - %s",
1512 ok = swrap_dir_usable(swrap_dir);
1519 ok = swrap_dir_usable(s);
1521 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1525 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1527 SWRAP_LOG(SWRAP_LOG_ERROR,
1528 "realpath(SOCKET_WRAPPER_DIR) too long and "
1529 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1534 swrap_dir = strdup(s);
1535 if (swrap_dir == NULL) {
1536 SWRAP_LOG(SWRAP_LOG_ERROR,
1537 "Unable to duplicate socket_wrapper dir path");
1541 SWRAP_LOG(SWRAP_LOG_WARN,
1542 "realpath(SOCKET_WRAPPER_DIR) too long, "
1543 "using original SOCKET_WRAPPER_DIR\n");
1546 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1550 static unsigned int socket_wrapper_mtu(void)
1552 static unsigned int max_mtu = 0;
1557 swrap_mutex_lock(&mtu_update_mutex);
1563 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1565 s = getenv("SOCKET_WRAPPER_MTU");
1570 tmp = strtol(s, &endp, 10);
1575 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1581 swrap_mutex_unlock(&mtu_update_mutex);
1585 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1587 pthread_mutexattr_t ma;
1588 bool need_destroy = false;
1591 #define __CHECK(cmd) do { \
1594 SWRAP_LOG(SWRAP_LOG_ERROR, \
1595 "%s: %s - failed %d", \
1601 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1602 __CHECK(pthread_mutexattr_init(&ma));
1603 need_destroy = true;
1604 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1605 __CHECK(pthread_mutex_init(m, &ma));
1608 pthread_mutexattr_destroy(&ma);
1613 static size_t socket_wrapper_max_sockets(void)
1619 if (socket_info_max != 0) {
1620 return socket_info_max;
1623 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1625 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1626 if (s == NULL || s[0] == '\0') {
1630 tmp = strtoul(s, &endp, 10);
1635 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1636 SWRAP_LOG(SWRAP_LOG_ERROR,
1637 "Invalid number of sockets specified, "
1638 "using default (%zu)",
1642 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1643 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1644 SWRAP_LOG(SWRAP_LOG_ERROR,
1645 "Invalid number of sockets specified, "
1646 "using maximum (%zu).",
1650 socket_info_max = tmp;
1653 return socket_info_max;
1656 static void socket_wrapper_init_fds_idx(void)
1661 if (socket_fds_idx != NULL) {
1665 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1667 SWRAP_LOG(SWRAP_LOG_ERROR,
1668 "Failed to allocate socket fds index array: %s",
1673 for (i = 0; i < socket_fds_max; i++) {
1677 socket_fds_idx = tmp;
1680 static void socket_wrapper_init_sockets(void)
1686 swrap_bind_symbol_all();
1688 swrap_mutex_lock(&sockets_mutex);
1690 if (sockets != NULL) {
1691 swrap_mutex_unlock(&sockets_mutex);
1695 SWRAP_LOG(SWRAP_LOG_DEBUG,
1696 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1697 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1700 * Intialize the static cache early before
1701 * any thread is able to start.
1703 (void)swrap_ipv4_net();
1705 socket_wrapper_init_fds_idx();
1707 /* Needs to be called inside the sockets_mutex lock here. */
1708 max_sockets = socket_wrapper_max_sockets();
1710 sockets = (struct socket_info_container *)calloc(max_sockets,
1711 sizeof(struct socket_info_container));
1713 if (sockets == NULL) {
1714 SWRAP_LOG(SWRAP_LOG_ERROR,
1715 "Failed to allocate sockets array: %s",
1717 swrap_mutex_unlock(&sockets_mutex);
1721 swrap_mutex_lock(&first_free_mutex);
1722 swrap_mutex_lock(&sockets_si_global);
1726 for (i = 0; i < max_sockets; i++) {
1727 swrap_set_next_free(&sockets[i].info, i+1);
1730 /* mark the end of the free list */
1731 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1733 swrap_mutex_unlock(&sockets_si_global);
1734 swrap_mutex_unlock(&first_free_mutex);
1735 swrap_mutex_unlock(&sockets_mutex);
1741 bool socket_wrapper_enabled(void)
1743 char *s = socket_wrapper_dir();
1751 socket_wrapper_init_sockets();
1756 static unsigned int socket_wrapper_default_iface(void)
1758 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1761 if (sscanf(s, "%u", &iface) == 1) {
1762 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1768 return 1;/* 127.0.0.1 */
1771 static void set_socket_info_index(int fd, int idx)
1773 SWRAP_LOG(SWRAP_LOG_TRACE,
1776 socket_fds_idx[fd] = idx;
1777 /* This builtin issues a full memory barrier. */
1778 __sync_synchronize();
1781 static void reset_socket_info_index(int fd)
1783 SWRAP_LOG(SWRAP_LOG_TRACE,
1786 set_socket_info_index(fd, -1);
1789 static int find_socket_info_index(int fd)
1795 if (socket_fds_idx == NULL) {
1799 if ((size_t)fd >= socket_fds_max) {
1801 * Do not add a log here as some applications do stupid things
1804 * for (fd = 0; fd <= getdtablesize(); fd++) {
1808 * This would produce millions of lines of debug messages.
1811 SWRAP_LOG(SWRAP_LOG_ERROR,
1812 "Looking for a socket info for the fd %d is over the "
1813 "max socket index limit of %zu.",
1820 /* This builtin issues a full memory barrier. */
1821 __sync_synchronize();
1822 return socket_fds_idx[fd];
1825 static int swrap_add_socket_info(const struct socket_info *si_input)
1827 struct socket_info *si = NULL;
1830 if (si_input == NULL) {
1835 swrap_mutex_lock(&first_free_mutex);
1836 if (first_free == -1) {
1841 si_index = first_free;
1842 si = swrap_get_socket_info(si_index);
1846 first_free = swrap_get_next_free(si);
1848 swrap_inc_refcount(si);
1850 SWRAP_UNLOCK_SI(si);
1853 swrap_mutex_unlock(&first_free_mutex);
1858 static int swrap_create_socket(struct socket_info *si, int fd)
1862 if ((size_t)fd >= socket_fds_max) {
1863 SWRAP_LOG(SWRAP_LOG_ERROR,
1864 "The max socket index limit of %zu has been reached, "
1872 idx = swrap_add_socket_info(si);
1877 set_socket_info_index(fd, idx);
1882 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1889 p = strrchr(un->sun_path, '/');
1890 if (p) p++; else p = un->sun_path;
1892 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1893 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1899 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1900 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1907 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1913 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1917 case SOCKET_TYPE_CHAR_TCP:
1918 case SOCKET_TYPE_CHAR_UDP: {
1919 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1921 if ((*len) < sizeof(*in2)) {
1922 SWRAP_LOG(SWRAP_LOG_ERROR,
1923 "V4: *len(%zu) < sizeof(*in2)=%zu",
1924 (size_t)*len, sizeof(*in2));
1929 memset(in2, 0, sizeof(*in2));
1930 in2->sin_family = AF_INET;
1931 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1932 in2->sin_port = htons(prt);
1934 *len = sizeof(*in2);
1938 case SOCKET_TYPE_CHAR_TCP_V6:
1939 case SOCKET_TYPE_CHAR_UDP_V6: {
1940 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1942 if ((*len) < sizeof(*in2)) {
1943 SWRAP_LOG(SWRAP_LOG_ERROR,
1944 "V6: *len(%zu) < sizeof(*in2)=%zu",
1945 (size_t)*len, sizeof(*in2));
1946 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1951 memset(in2, 0, sizeof(*in2));
1952 in2->sin6_family = AF_INET6;
1953 in2->sin6_addr = *swrap_ipv6();
1954 in2->sin6_addr.s6_addr[15] = iface;
1955 in2->sin6_port = htons(prt);
1957 *len = sizeof(*in2);
1962 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1971 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1978 char *swrap_dir = NULL;
1980 if (bcast) *bcast = 0;
1982 switch (inaddr->sa_family) {
1984 const struct sockaddr_in *in =
1985 (const struct sockaddr_in *)(const void *)inaddr;
1986 unsigned int addr = ntohl(in->sin_addr.s_addr);
1990 const unsigned int sw_net_addr = swrap_ipv4_net();
1991 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1995 u_type = SOCKET_TYPE_CHAR_TCP;
1998 u_type = SOCKET_TYPE_CHAR_UDP;
1999 a_type = SOCKET_TYPE_CHAR_UDP;
2000 b_type = SOCKET_TYPE_CHAR_UDP;
2003 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2004 errno = ESOCKTNOSUPPORT;
2008 prt = ntohs(in->sin_port);
2009 if (a_type && addr == 0xFFFFFFFF) {
2010 /* 255.255.255.255 only udp */
2013 iface = socket_wrapper_default_iface();
2014 } else if (b_type && addr == sw_bcast_addr) {
2023 iface = socket_wrapper_default_iface();
2024 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2025 /* 127.0.0.X or 10.53.57.X */
2028 iface = (addr & 0x000000FF);
2030 char str[256] = {0,};
2031 inet_ntop(inaddr->sa_family,
2034 SWRAP_LOG(SWRAP_LOG_WARN,
2036 str, (unsigned)prt);
2037 errno = ENETUNREACH;
2040 if (bcast) *bcast = is_bcast;
2045 const struct sockaddr_in6 *in =
2046 (const struct sockaddr_in6 *)(const void *)inaddr;
2047 struct in6_addr cmp1, cmp2;
2051 type = SOCKET_TYPE_CHAR_TCP_V6;
2054 type = SOCKET_TYPE_CHAR_UDP_V6;
2057 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2058 errno = ESOCKTNOSUPPORT;
2062 /* XXX no multicast/broadcast */
2064 prt = ntohs(in->sin6_port);
2066 cmp1 = *swrap_ipv6();
2067 cmp2 = in->sin6_addr;
2068 cmp2.s6_addr[15] = 0;
2069 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2070 iface = in->sin6_addr.s6_addr[15];
2072 char str[256] = {0,};
2073 inet_ntop(inaddr->sa_family,
2076 SWRAP_LOG(SWRAP_LOG_WARN,
2078 str, (unsigned)prt);
2079 errno = ENETUNREACH;
2087 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2088 errno = ENETUNREACH;
2093 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2098 swrap_dir = socket_wrapper_dir();
2099 if (swrap_dir == NULL) {
2105 swrap_un_path_EINVAL(un, swrap_dir);
2106 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2107 SAFE_FREE(swrap_dir);
2108 /* the caller need to do more processing */
2112 swrap_un_path(un, swrap_dir, type, iface, prt);
2113 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2115 SAFE_FREE(swrap_dir);
2120 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2128 char *swrap_dir = NULL;
2130 if (bcast) *bcast = 0;
2132 switch (si->family) {
2134 const struct sockaddr_in *in =
2135 (const struct sockaddr_in *)(const void *)inaddr;
2136 unsigned int addr = ntohl(in->sin_addr.s_addr);
2141 const unsigned int sw_net_addr = swrap_ipv4_net();
2142 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2144 prt = ntohs(in->sin_port);
2148 u_type = SOCKET_TYPE_CHAR_TCP;
2149 d_type = SOCKET_TYPE_CHAR_TCP;
2152 u_type = SOCKET_TYPE_CHAR_UDP;
2153 d_type = SOCKET_TYPE_CHAR_UDP;
2154 a_type = SOCKET_TYPE_CHAR_UDP;
2155 b_type = SOCKET_TYPE_CHAR_UDP;
2158 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2159 errno = ESOCKTNOSUPPORT;
2167 iface = socket_wrapper_default_iface();
2168 } else if (a_type && addr == 0xFFFFFFFF) {
2169 /* 255.255.255.255 only udp */
2172 iface = socket_wrapper_default_iface();
2173 } else if (b_type && addr == sw_bcast_addr) {
2174 /* 127.255.255.255 only udp */
2177 iface = socket_wrapper_default_iface();
2178 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2182 iface = (addr & 0x000000FF);
2184 errno = EADDRNOTAVAIL;
2188 /* Store the bind address for connect() */
2189 if (si->bindname.sa_socklen == 0) {
2190 struct sockaddr_in bind_in;
2191 socklen_t blen = sizeof(struct sockaddr_in);
2193 ZERO_STRUCT(bind_in);
2194 bind_in.sin_family = in->sin_family;
2195 bind_in.sin_port = in->sin_port;
2196 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2197 si->bindname.sa_socklen = blen;
2198 memcpy(&si->bindname.sa.in, &bind_in, blen);
2205 const struct sockaddr_in6 *in =
2206 (const struct sockaddr_in6 *)(const void *)inaddr;
2207 struct in6_addr cmp1, cmp2;
2211 type = SOCKET_TYPE_CHAR_TCP_V6;
2214 type = SOCKET_TYPE_CHAR_UDP_V6;
2217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2218 errno = ESOCKTNOSUPPORT;
2222 /* XXX no multicast/broadcast */
2224 prt = ntohs(in->sin6_port);
2226 cmp1 = *swrap_ipv6();
2227 cmp2 = in->sin6_addr;
2228 cmp2.s6_addr[15] = 0;
2229 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2230 iface = socket_wrapper_default_iface();
2231 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2232 iface = in->sin6_addr.s6_addr[15];
2234 errno = EADDRNOTAVAIL;
2238 /* Store the bind address for connect() */
2239 if (si->bindname.sa_socklen == 0) {
2240 struct sockaddr_in6 bind_in;
2241 socklen_t blen = sizeof(struct sockaddr_in6);
2243 ZERO_STRUCT(bind_in);
2244 bind_in.sin6_family = in->sin6_family;
2245 bind_in.sin6_port = in->sin6_port;
2247 bind_in.sin6_addr = *swrap_ipv6();
2248 bind_in.sin6_addr.s6_addr[15] = iface;
2250 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2251 si->bindname.sa_socklen = blen;
2258 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2259 errno = EADDRNOTAVAIL;
2264 if (bcast) *bcast = is_bcast;
2266 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2271 swrap_dir = socket_wrapper_dir();
2272 if (swrap_dir == NULL) {
2278 /* handle auto-allocation of ephemeral ports */
2279 for (prt = 5001; prt < 10000; prt++) {
2280 swrap_un_path(un, swrap_dir, type, iface, prt);
2281 if (stat(un->sun_path, &st) == 0) continue;
2283 set_port(si->family, prt, &si->myname);
2284 set_port(si->family, prt, &si->bindname);
2291 SAFE_FREE(swrap_dir);
2296 swrap_un_path(un, swrap_dir, type, iface, prt);
2297 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2299 SAFE_FREE(swrap_dir);
2304 static struct socket_info *find_socket_info(int fd)
2306 int idx = find_socket_info_index(fd);
2312 return swrap_get_socket_info(idx);
2316 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2318 struct socket_info_fd *f;
2319 const struct socket_info *last_s = NULL;
2321 /* first catch invalid input */
2322 switch (sa->sa_family) {
2324 if (len < sizeof(struct sockaddr_in)) {
2330 if (len < sizeof(struct sockaddr_in6)) {
2340 for (f = socket_fds; f; f = f->next) {
2341 struct socket_info *s = swrap_get_socket_info(f->si_index);
2348 if (s->myname == NULL) {
2351 if (s->myname->sa_family != sa->sa_family) {
2354 switch (s->myname->sa_family) {
2356 struct sockaddr_in *sin1, *sin2;
2358 sin1 = (struct sockaddr_in *)s->myname;
2359 sin2 = (struct sockaddr_in *)sa;
2361 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2364 if (sin1->sin_port != sin2->sin_port) {
2367 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2377 struct sockaddr_in6 *sin1, *sin2;
2379 sin1 = (struct sockaddr_in6 *)s->myname;
2380 sin2 = (struct sockaddr_in6 *)sa;
2382 if (sin1->sin6_port != sin2->sin6_port) {
2385 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2407 static void swrap_remove_stale(int fd);
2409 static int sockaddr_convert_to_un(struct socket_info *si,
2410 const struct sockaddr *in_addr,
2412 struct sockaddr_un *out_addr,
2416 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2418 (void) in_len; /* unused */
2420 if (out_addr == NULL) {
2424 out->sa_family = AF_UNIX;
2425 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2426 out->sa_len = sizeof(*out_addr);
2429 switch (in_addr->sa_family) {
2431 const struct sockaddr_in *sin;
2432 if (si->family != AF_INET) {
2435 if (in_len < sizeof(struct sockaddr_in)) {
2438 sin = (const struct sockaddr_in *)(const void *)in_addr;
2439 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2444 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2445 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2459 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2460 errno = ESOCKTNOSUPPORT;
2464 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2466 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2472 errno = EAFNOSUPPORT;
2473 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2477 static int sockaddr_convert_from_un(const struct socket_info *si,
2478 const struct sockaddr_un *in_addr,
2479 socklen_t un_addrlen,
2481 struct sockaddr *out_addr,
2482 socklen_t *out_addrlen)
2486 if (out_addr == NULL || out_addrlen == NULL)
2489 if (un_addrlen == 0) {
2504 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2505 errno = ESOCKTNOSUPPORT;
2508 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2509 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2510 out_addr->sa_len = *out_addrlen;
2517 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2518 errno = EAFNOSUPPORT;
2522 enum swrap_packet_type {
2524 SWRAP_CONNECT_UNREACH,
2532 SWRAP_SENDTO_UNREACH,
2543 struct swrap_file_hdr {
2545 uint16_t version_major;
2546 uint16_t version_minor;
2549 uint32_t frame_max_len;
2550 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2553 #define SWRAP_FILE_HDR_SIZE 24
2555 struct swrap_packet_frame {
2557 uint32_t micro_seconds;
2558 uint32_t recorded_length;
2559 uint32_t full_length;
2561 #define SWRAP_PACKET_FRAME_SIZE 16
2563 union swrap_packet_ip {
2567 uint16_t packet_length;
2568 uint16_t identification;
2573 uint16_t hdr_checksum;
2577 #define SWRAP_PACKET_IP_V4_SIZE 20
2580 uint8_t flow_label_high;
2581 uint16_t flow_label_low;
2582 uint16_t payload_length;
2583 uint8_t next_header;
2585 uint8_t src_addr[16];
2586 uint8_t dest_addr[16];
2588 #define SWRAP_PACKET_IP_V6_SIZE 40
2590 #define SWRAP_PACKET_IP_SIZE 40
2592 union swrap_packet_payload {
2594 uint16_t source_port;
2604 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2606 uint16_t source_port;
2611 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2618 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2625 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2627 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2629 #define SWRAP_PACKET_MIN_ALLOC \
2630 (SWRAP_PACKET_FRAME_SIZE + \
2631 SWRAP_PACKET_IP_SIZE + \
2632 SWRAP_PACKET_PAYLOAD_SIZE)
2634 static const char *swrap_pcap_init_file(void)
2636 static int initialized = 0;
2637 static const char *s = NULL;
2638 static const struct swrap_file_hdr h;
2639 static const struct swrap_packet_frame f;
2640 static const union swrap_packet_ip i;
2641 static const union swrap_packet_payload p;
2643 if (initialized == 1) {
2649 * TODO: don't use the structs use plain buffer offsets
2650 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2652 * for now make sure we disable PCAP support
2653 * if the struct has alignment!
2655 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2658 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2661 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2664 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2667 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2670 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2673 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2676 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2679 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2682 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2686 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2690 if (strncmp(s, "./", 2) == 0) {
2693 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2697 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2698 const struct sockaddr *src,
2699 const struct sockaddr *dest,
2701 const uint8_t *payload,
2703 unsigned long tcp_seqno,
2704 unsigned long tcp_ack,
2705 unsigned char tcp_ctl,
2707 size_t *_packet_len)
2709 uint8_t *base = NULL;
2710 uint8_t *buf = NULL;
2713 struct swrap_packet_frame *frame;
2717 union swrap_packet_ip *ip;
2719 union swrap_packet_payload *pay;
2722 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2723 size_t wire_hdr_len = 0;
2724 size_t wire_len = 0;
2725 size_t ip_hdr_len = 0;
2726 size_t icmp_hdr_len = 0;
2727 size_t icmp_truncate_len = 0;
2728 uint8_t protocol = 0, icmp_protocol = 0;
2729 const struct sockaddr_in *src_in = NULL;
2730 const struct sockaddr_in *dest_in = NULL;
2732 const struct sockaddr_in6 *src_in6 = NULL;
2733 const struct sockaddr_in6 *dest_in6 = NULL;
2738 switch (src->sa_family) {
2740 src_in = (const struct sockaddr_in *)(const void *)src;
2741 dest_in = (const struct sockaddr_in *)(const void *)dest;
2742 src_port = src_in->sin_port;
2743 dest_port = dest_in->sin_port;
2744 ip_hdr_len = sizeof(i.ip->v4);
2748 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2749 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2750 src_port = src_in6->sin6_port;
2751 dest_port = dest_in6->sin6_port;
2752 ip_hdr_len = sizeof(i.ip->v6);
2759 switch (socket_type) {
2761 protocol = 0x06; /* TCP */
2762 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2763 wire_len = wire_hdr_len + payload_len;
2767 protocol = 0x11; /* UDP */
2768 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2769 wire_len = wire_hdr_len + payload_len;
2777 icmp_protocol = protocol;
2778 switch (src->sa_family) {
2780 protocol = 0x01; /* ICMPv4 */
2781 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2785 protocol = 0x3A; /* ICMPv6 */
2786 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2790 if (wire_len > 64 ) {
2791 icmp_truncate_len = wire_len - 64;
2793 wire_len += icmp_hdr_len;
2796 packet_len = nonwire_len + wire_len;
2797 alloc_len = packet_len;
2798 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2799 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2802 base = (uint8_t *)calloc(1, alloc_len);
2810 f.frame->seconds = tval->tv_sec;
2811 f.frame->micro_seconds = tval->tv_usec;
2812 f.frame->recorded_length = wire_len - icmp_truncate_len;
2813 f.frame->full_length = wire_len - icmp_truncate_len;
2815 buf += SWRAP_PACKET_FRAME_SIZE;
2818 switch (src->sa_family) {
2820 if (src_in == NULL || dest_in == NULL) {
2825 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2826 i.ip->v4.tos = 0x00;
2827 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2828 i.ip->v4.identification = htons(0xFFFF);
2829 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2830 i.ip->v4.fragment = htons(0x0000);
2831 i.ip->v4.ttl = 0xFF;
2832 i.ip->v4.protocol = protocol;
2833 i.ip->v4.hdr_checksum = htons(0x0000);
2834 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2835 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2836 buf += SWRAP_PACKET_IP_V4_SIZE;
2840 if (src_in6 == NULL || dest_in6 == NULL) {
2845 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2846 i.ip->v6.flow_label_high = 0x00;
2847 i.ip->v6.flow_label_low = 0x0000;
2848 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2849 i.ip->v6.next_header = protocol;
2850 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2851 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2852 buf += SWRAP_PACKET_IP_V6_SIZE;
2858 pay = (union swrap_packet_payload *)(void *)buf;
2859 switch (src->sa_family) {
2861 pay->icmp4.type = 0x03; /* destination unreachable */
2862 pay->icmp4.code = 0x01; /* host unreachable */
2863 pay->icmp4.checksum = htons(0x0000);
2864 pay->icmp4.unused = htonl(0x00000000);
2866 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2868 /* set the ip header in the ICMP payload */
2870 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2871 i.ip->v4.tos = 0x00;
2872 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2873 i.ip->v4.identification = htons(0xFFFF);
2874 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2875 i.ip->v4.fragment = htons(0x0000);
2876 i.ip->v4.ttl = 0xFF;
2877 i.ip->v4.protocol = icmp_protocol;
2878 i.ip->v4.hdr_checksum = htons(0x0000);
2879 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2880 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2882 buf += SWRAP_PACKET_IP_V4_SIZE;
2884 src_port = dest_in->sin_port;
2885 dest_port = src_in->sin_port;
2889 pay->icmp6.type = 0x01; /* destination unreachable */
2890 pay->icmp6.code = 0x03; /* address unreachable */
2891 pay->icmp6.checksum = htons(0x0000);
2892 pay->icmp6.unused = htonl(0x00000000);
2893 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2895 /* set the ip header in the ICMP payload */
2897 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2898 i.ip->v6.flow_label_high = 0x00;
2899 i.ip->v6.flow_label_low = 0x0000;
2900 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2901 i.ip->v6.next_header = protocol;
2902 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2903 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2905 buf += SWRAP_PACKET_IP_V6_SIZE;
2907 src_port = dest_in6->sin6_port;
2908 dest_port = src_in6->sin6_port;
2914 pay = (union swrap_packet_payload *)(void *)buf;
2916 switch (socket_type) {
2918 pay->tcp.source_port = src_port;
2919 pay->tcp.dest_port = dest_port;
2920 pay->tcp.seq_num = htonl(tcp_seqno);
2921 pay->tcp.ack_num = htonl(tcp_ack);
2922 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2923 pay->tcp.control = tcp_ctl;
2924 pay->tcp.window = htons(0x7FFF);
2925 pay->tcp.checksum = htons(0x0000);
2926 pay->tcp.urg = htons(0x0000);
2927 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2932 pay->udp.source_port = src_port;
2933 pay->udp.dest_port = dest_port;
2934 pay->udp.length = htons(8 + payload_len);
2935 pay->udp.checksum = htons(0x0000);
2936 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2941 if (payload && payload_len > 0) {
2942 memcpy(buf, payload, payload_len);
2945 *_packet_len = packet_len - icmp_truncate_len;
2949 static int swrap_pcap_get_fd(const char *fname)
2957 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2959 struct swrap_file_hdr file_hdr;
2960 file_hdr.magic = 0xA1B2C3D4;
2961 file_hdr.version_major = 0x0002;
2962 file_hdr.version_minor = 0x0004;
2963 file_hdr.timezone = 0x00000000;
2964 file_hdr.sigfigs = 0x00000000;
2965 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2966 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2968 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2975 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2980 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2981 const struct sockaddr *addr,
2982 enum swrap_packet_type type,
2983 const void *buf, size_t len,
2986 const struct sockaddr *src_addr;
2987 const struct sockaddr *dest_addr;
2988 unsigned long tcp_seqno = 0;
2989 unsigned long tcp_ack = 0;
2990 unsigned char tcp_ctl = 0;
2991 int unreachable = 0;
2995 switch (si->family) {
3007 case SWRAP_CONNECT_SEND:
3008 if (si->type != SOCK_STREAM) {
3012 src_addr = &si->myname.sa.s;
3015 tcp_seqno = si->io.pck_snd;
3016 tcp_ack = si->io.pck_rcv;
3017 tcp_ctl = 0x02; /* SYN */
3019 si->io.pck_snd += 1;
3023 case SWRAP_CONNECT_RECV:
3024 if (si->type != SOCK_STREAM) {
3028 dest_addr = &si->myname.sa.s;
3031 tcp_seqno = si->io.pck_rcv;
3032 tcp_ack = si->io.pck_snd;
3033 tcp_ctl = 0x12; /** SYN,ACK */
3035 si->io.pck_rcv += 1;
3039 case SWRAP_CONNECT_UNREACH:
3040 if (si->type != SOCK_STREAM) {
3044 dest_addr = &si->myname.sa.s;
3047 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3048 tcp_seqno = si->io.pck_snd - 1;
3049 tcp_ack = si->io.pck_rcv;
3050 tcp_ctl = 0x02; /* SYN */
3055 case SWRAP_CONNECT_ACK:
3056 if (si->type != SOCK_STREAM) {
3060 src_addr = &si->myname.sa.s;
3063 tcp_seqno = si->io.pck_snd;
3064 tcp_ack = si->io.pck_rcv;
3065 tcp_ctl = 0x10; /* ACK */
3069 case SWRAP_ACCEPT_SEND:
3070 if (si->type != SOCK_STREAM) {
3074 dest_addr = &si->myname.sa.s;
3077 tcp_seqno = si->io.pck_rcv;
3078 tcp_ack = si->io.pck_snd;
3079 tcp_ctl = 0x02; /* SYN */
3081 si->io.pck_rcv += 1;
3085 case SWRAP_ACCEPT_RECV:
3086 if (si->type != SOCK_STREAM) {
3090 src_addr = &si->myname.sa.s;
3093 tcp_seqno = si->io.pck_snd;
3094 tcp_ack = si->io.pck_rcv;
3095 tcp_ctl = 0x12; /* SYN,ACK */
3097 si->io.pck_snd += 1;
3101 case SWRAP_ACCEPT_ACK:
3102 if (si->type != SOCK_STREAM) {
3106 dest_addr = &si->myname.sa.s;
3109 tcp_seqno = si->io.pck_rcv;
3110 tcp_ack = si->io.pck_snd;
3111 tcp_ctl = 0x10; /* ACK */
3116 src_addr = &si->myname.sa.s;
3117 dest_addr = &si->peername.sa.s;
3119 tcp_seqno = si->io.pck_snd;
3120 tcp_ack = si->io.pck_rcv;
3121 tcp_ctl = 0x18; /* PSH,ACK */
3123 si->io.pck_snd += len;
3127 case SWRAP_SEND_RST:
3128 dest_addr = &si->myname.sa.s;
3129 src_addr = &si->peername.sa.s;
3131 if (si->type == SOCK_DGRAM) {
3132 return swrap_pcap_marshall_packet(si,
3134 SWRAP_SENDTO_UNREACH,
3140 tcp_seqno = si->io.pck_rcv;
3141 tcp_ack = si->io.pck_snd;
3142 tcp_ctl = 0x14; /** RST,ACK */
3146 case SWRAP_PENDING_RST:
3147 dest_addr = &si->myname.sa.s;
3148 src_addr = &si->peername.sa.s;
3150 if (si->type == SOCK_DGRAM) {
3154 tcp_seqno = si->io.pck_rcv;
3155 tcp_ack = si->io.pck_snd;
3156 tcp_ctl = 0x14; /* RST,ACK */
3161 dest_addr = &si->myname.sa.s;
3162 src_addr = &si->peername.sa.s;
3164 tcp_seqno = si->io.pck_rcv;
3165 tcp_ack = si->io.pck_snd;
3166 tcp_ctl = 0x18; /* PSH,ACK */
3168 si->io.pck_rcv += len;
3172 case SWRAP_RECV_RST:
3173 dest_addr = &si->myname.sa.s;
3174 src_addr = &si->peername.sa.s;
3176 if (si->type == SOCK_DGRAM) {
3180 tcp_seqno = si->io.pck_rcv;
3181 tcp_ack = si->io.pck_snd;
3182 tcp_ctl = 0x14; /* RST,ACK */
3187 src_addr = &si->myname.sa.s;
3190 si->io.pck_snd += len;
3194 case SWRAP_SENDTO_UNREACH:
3195 dest_addr = &si->myname.sa.s;
3202 case SWRAP_RECVFROM:
3203 dest_addr = &si->myname.sa.s;
3206 si->io.pck_rcv += len;
3210 case SWRAP_CLOSE_SEND:
3211 if (si->type != SOCK_STREAM) {
3215 src_addr = &si->myname.sa.s;
3216 dest_addr = &si->peername.sa.s;
3218 tcp_seqno = si->io.pck_snd;
3219 tcp_ack = si->io.pck_rcv;
3220 tcp_ctl = 0x11; /* FIN, ACK */
3222 si->io.pck_snd += 1;
3226 case SWRAP_CLOSE_RECV:
3227 if (si->type != SOCK_STREAM) {
3231 dest_addr = &si->myname.sa.s;
3232 src_addr = &si->peername.sa.s;
3234 tcp_seqno = si->io.pck_rcv;
3235 tcp_ack = si->io.pck_snd;
3236 tcp_ctl = 0x11; /* FIN,ACK */
3238 si->io.pck_rcv += 1;
3242 case SWRAP_CLOSE_ACK:
3243 if (si->type != SOCK_STREAM) {
3247 src_addr = &si->myname.sa.s;
3248 dest_addr = &si->peername.sa.s;
3250 tcp_seqno = si->io.pck_snd;
3251 tcp_ack = si->io.pck_rcv;
3252 tcp_ctl = 0x10; /* ACK */
3259 swrapGetTimeOfDay(&tv);
3261 return swrap_pcap_packet_init(&tv,
3265 (const uint8_t *)buf,
3274 static void swrap_pcap_dump_packet(struct socket_info *si,
3275 const struct sockaddr *addr,
3276 enum swrap_packet_type type,
3277 const void *buf, size_t len)
3279 const char *file_name;
3281 size_t packet_len = 0;
3284 swrap_mutex_lock(&pcap_dump_mutex);
3286 file_name = swrap_pcap_init_file();
3291 packet = swrap_pcap_marshall_packet(si,
3297 if (packet == NULL) {
3301 fd = swrap_pcap_get_fd(file_name);
3303 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3312 swrap_mutex_unlock(&pcap_dump_mutex);
3315 /****************************************************************************
3317 ***************************************************************************/
3319 #ifdef HAVE_SIGNALFD
3320 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3324 rc = libc_signalfd(fd, mask, flags);
3326 swrap_remove_stale(fd);
3332 int signalfd(int fd, const sigset_t *mask, int flags)
3334 return swrap_signalfd(fd, mask, flags);
3338 /****************************************************************************
3340 ***************************************************************************/
3342 static int swrap_socket(int family, int type, int protocol)
3344 struct socket_info *si = NULL;
3345 struct socket_info _si = { 0 };
3348 int real_type = type;
3351 * Remove possible addition flags passed to socket() so
3352 * do not fail checking the type.
3353 * See https://lwn.net/Articles/281965/
3356 real_type &= ~SOCK_CLOEXEC;
3358 #ifdef SOCK_NONBLOCK
3359 real_type &= ~SOCK_NONBLOCK;
3362 if (!socket_wrapper_enabled()) {
3363 return libc_socket(family, type, protocol);
3374 #endif /* AF_NETLINK */
3377 #endif /* AF_PACKET */
3379 fd = libc_socket(family, type, protocol);
3381 /* Check if we have a stale fd and remove it */
3382 swrap_remove_stale(fd);
3383 SWRAP_LOG(SWRAP_LOG_TRACE,
3384 "Unix socket fd=%d",
3389 errno = EAFNOSUPPORT;
3393 switch (real_type) {
3399 errno = EPROTONOSUPPORT;
3407 if (real_type == SOCK_STREAM) {
3412 if (real_type == SOCK_DGRAM) {
3417 errno = EPROTONOSUPPORT;
3422 * We must call libc_socket with type, from the caller, not the version
3423 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3425 fd = libc_socket(AF_UNIX, type, 0);
3431 /* Check if we have a stale fd and remove it */
3432 swrap_remove_stale(fd);
3435 si->family = family;
3437 /* however, the rest of the socket_wrapper code expects just
3438 * the type, not the flags */
3439 si->type = real_type;
3440 si->protocol = protocol;
3443 * Setup myname so getsockname() can succeed to find out the socket
3446 switch(si->family) {
3448 struct sockaddr_in sin = {
3449 .sin_family = AF_INET,
3452 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3453 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3458 struct sockaddr_in6 sin6 = {
3459 .sin6_family = AF_INET6,
3462 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3463 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3472 ret = swrap_create_socket(si, fd);
3474 int saved_errno = errno;
3476 errno = saved_errno;
3480 SWRAP_LOG(SWRAP_LOG_TRACE,
3481 "Created %s socket for protocol %s, fd=%d",
3482 family == AF_INET ? "IPv4" : "IPv6",
3483 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3489 int socket(int family, int type, int protocol)
3491 return swrap_socket(family, type, protocol);
3494 /****************************************************************************
3496 ***************************************************************************/
3498 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3502 rc = libc_socketpair(family, type, protocol, sv);
3504 swrap_remove_stale(sv[0]);
3505 swrap_remove_stale(sv[1]);
3511 int socketpair(int family, int type, int protocol, int sv[2])
3513 return swrap_socketpair(family, type, protocol, sv);
3516 /****************************************************************************
3518 ***************************************************************************/
3520 #ifdef HAVE_TIMERFD_CREATE
3521 static int swrap_timerfd_create(int clockid, int flags)
3525 fd = libc_timerfd_create(clockid, flags);
3527 swrap_remove_stale(fd);
3533 int timerfd_create(int clockid, int flags)
3535 return swrap_timerfd_create(clockid, flags);
3539 /****************************************************************************
3541 ***************************************************************************/
3543 static int swrap_pipe(int pipefd[2])
3547 rc = libc_pipe(pipefd);
3549 swrap_remove_stale(pipefd[0]);
3550 swrap_remove_stale(pipefd[1]);
3556 int pipe(int pipefd[2])
3558 return swrap_pipe(pipefd);
3561 /****************************************************************************
3563 ***************************************************************************/
3565 static int swrap_accept(int s,
3566 struct sockaddr *addr,
3570 struct socket_info *parent_si, *child_si;
3571 struct socket_info new_si = { 0 };
3574 struct swrap_address un_addr = {
3575 .sa_socklen = sizeof(struct sockaddr_un),
3577 struct swrap_address un_my_addr = {
3578 .sa_socklen = sizeof(struct sockaddr_un),
3580 struct swrap_address in_addr = {
3581 .sa_socklen = sizeof(struct sockaddr_storage),
3583 struct swrap_address in_my_addr = {
3584 .sa_socklen = sizeof(struct sockaddr_storage),
3588 parent_si = find_socket_info(s);
3591 return libc_accept4(s, addr, addrlen, flags);
3594 return libc_accept(s, addr, addrlen);
3600 * prevent parent_si from being altered / closed
3603 SWRAP_LOCK_SI(parent_si);
3606 * assume out sockaddr have the same size as the in parent
3609 in_addr.sa_socklen = socket_length(parent_si->family);
3610 if (in_addr.sa_socklen <= 0) {
3611 SWRAP_UNLOCK_SI(parent_si);
3616 SWRAP_UNLOCK_SI(parent_si);
3619 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3622 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3625 int saved_errno = errno;
3626 if (saved_errno == ENOTSOCK) {
3627 /* Remove stale fds */
3628 swrap_remove_stale(s);
3630 errno = saved_errno;
3636 /* Check if we have a stale fd and remove it */
3637 swrap_remove_stale(fd);
3639 if (un_addr.sa.un.sun_path[0] == '\0') {
3641 * FreeBSD seems to have a problem where
3642 * accept4() on the unix socket doesn't
3643 * ECONNABORTED for already disconnected connections.
3645 * Let's try libc_getpeername() to get the peer address
3646 * as a fallback, but it'll likely return ENOTCONN,
3647 * which we have to map to ECONNABORTED.
3649 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3650 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3652 int saved_errno = errno;
3654 if (saved_errno == ENOTCONN) {
3656 * If the connection is already disconnected
3657 * we should return ECONNABORTED.
3659 saved_errno = ECONNABORTED;
3661 errno = saved_errno;
3666 ret = libc_getsockname(fd,
3668 &un_my_addr.sa_socklen);
3670 int saved_errno = errno;
3672 if (saved_errno == ENOTCONN) {
3674 * If the connection is already disconnected
3675 * we should return ECONNABORTED.
3677 saved_errno = ECONNABORTED;
3679 errno = saved_errno;
3683 SWRAP_LOCK_SI(parent_si);
3685 ret = sockaddr_convert_from_un(parent_si,
3690 &in_addr.sa_socklen);
3692 int saved_errno = errno;
3693 SWRAP_UNLOCK_SI(parent_si);
3695 errno = saved_errno;
3701 child_si->family = parent_si->family;
3702 child_si->type = parent_si->type;
3703 child_si->protocol = parent_si->protocol;
3704 child_si->bound = 1;
3705 child_si->is_server = 1;
3706 child_si->connected = 1;
3708 SWRAP_UNLOCK_SI(parent_si);
3710 child_si->peername = (struct swrap_address) {
3711 .sa_socklen = in_addr.sa_socklen,
3713 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3715 if (addr != NULL && addrlen != NULL) {
3716 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3718 memcpy(addr, &in_addr.sa.ss, copy_len);
3720 *addrlen = in_addr.sa_socklen;
3723 ret = sockaddr_convert_from_un(child_si,
3725 un_my_addr.sa_socklen,
3728 &in_my_addr.sa_socklen);
3730 int saved_errno = errno;
3732 errno = saved_errno;
3736 SWRAP_LOG(SWRAP_LOG_TRACE,
3737 "accept() path=%s, fd=%d",
3738 un_my_addr.sa.un.sun_path, s);
3740 child_si->myname = (struct swrap_address) {
3741 .sa_socklen = in_my_addr.sa_socklen,
3743 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3745 idx = swrap_create_socket(&new_si, fd);
3747 int saved_errno = errno;
3749 errno = saved_errno;
3754 struct socket_info *si = swrap_get_socket_info(idx);
3757 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3758 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3759 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3760 SWRAP_UNLOCK_SI(si);
3767 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3769 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3773 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3774 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3776 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3779 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3782 static int autobind_start_init;
3783 static int autobind_start;
3785 /* using sendto() or connect() on an unbound socket would give the
3786 recipient no way to reply, as unlike UDP and TCP, a unix domain
3787 socket can't auto-assign ephemeral port numbers, so we need to
3789 Note: this might change the family from ipv6 to ipv4
3791 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3793 struct swrap_address un_addr = {
3794 .sa_socklen = sizeof(struct sockaddr_un),
3801 char *swrap_dir = NULL;
3803 swrap_mutex_lock(&autobind_start_mutex);
3805 if (autobind_start_init != 1) {
3806 autobind_start_init = 1;
3807 autobind_start = getpid();
3808 autobind_start %= 50000;
3809 autobind_start += 10000;
3812 un_addr.sa.un.sun_family = AF_UNIX;
3816 struct sockaddr_in in;
3820 type = SOCKET_TYPE_CHAR_TCP;
3823 type = SOCKET_TYPE_CHAR_UDP;
3826 errno = ESOCKTNOSUPPORT;
3831 memset(&in, 0, sizeof(in));
3832 in.sin_family = AF_INET;
3833 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3834 socket_wrapper_default_iface()));
3836 si->myname = (struct swrap_address) {
3837 .sa_socklen = sizeof(in),
3839 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3844 struct sockaddr_in6 in6;
3846 if (si->family != family) {
3847 errno = ENETUNREACH;
3854 type = SOCKET_TYPE_CHAR_TCP_V6;
3857 type = SOCKET_TYPE_CHAR_UDP_V6;
3860 errno = ESOCKTNOSUPPORT;
3865 memset(&in6, 0, sizeof(in6));
3866 in6.sin6_family = AF_INET6;
3867 in6.sin6_addr = *swrap_ipv6();
3868 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3870 si->myname = (struct swrap_address) {
3871 .sa_socklen = sizeof(in6),
3873 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3878 errno = ESOCKTNOSUPPORT;
3883 if (autobind_start > 60000) {
3884 autobind_start = 10000;
3887 swrap_dir = socket_wrapper_dir();
3888 if (swrap_dir == NULL) {
3894 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3895 port = autobind_start + i;
3896 swrap_un_path(&un_addr.sa.un,
3899 socket_wrapper_default_iface(),
3901 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3903 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3908 si->un_addr = un_addr.sa.un;
3911 autobind_start = port + 1;
3914 if (i == SOCKET_MAX_SOCKETS) {
3915 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3916 "interface "SOCKET_FORMAT,
3919 socket_wrapper_default_iface(),
3926 si->family = family;
3927 set_port(si->family, port, &si->myname);
3932 SAFE_FREE(swrap_dir);
3933 swrap_mutex_unlock(&autobind_start_mutex);
3937 /****************************************************************************
3939 ***************************************************************************/
3941 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3945 struct swrap_address un_addr = {
3946 .sa_socklen = sizeof(struct sockaddr_un),
3948 struct socket_info *si = find_socket_info(s);
3952 return libc_connect(s, serv_addr, addrlen);
3957 if (si->bound == 0) {
3958 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3964 if (si->family != serv_addr->sa_family) {
3965 SWRAP_LOG(SWRAP_LOG_ERROR,
3966 "called for fd=%d (family=%d) called with invalid family=%d",
3967 s, si->family, serv_addr->sa_family);
3973 ret = sockaddr_convert_to_un(si, serv_addr,
3974 addrlen, &un_addr.sa.un, 0, &bcast);
3980 errno = ENETUNREACH;
3985 if (si->type == SOCK_DGRAM) {
3986 si->defer_connect = 1;
3989 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3991 ret = libc_connect(s,
3993 un_addr.sa_socklen);
3996 SWRAP_LOG(SWRAP_LOG_TRACE,
3997 "connect() path=%s, fd=%d",
3998 un_addr.sa.un.sun_path, s);
4001 /* to give better errors */
4002 if (ret == -1 && errno == ENOENT) {
4003 errno = EHOSTUNREACH;
4007 si->peername = (struct swrap_address) {
4008 .sa_socklen = addrlen,
4011 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4015 * When we connect() on a socket than we have to bind the
4016 * outgoing connection on the interface we use for the
4017 * transport. We already bound it on the right interface
4018 * but here we have to update the name so getsockname()
4019 * returns correct information.
4021 if (si->bindname.sa_socklen > 0) {
4022 si->myname = (struct swrap_address) {
4023 .sa_socklen = si->bindname.sa_socklen,
4026 memcpy(&si->myname.sa.ss,
4027 &si->bindname.sa.ss,
4028 si->bindname.sa_socklen);
4030 /* Cleanup bindname */
4031 si->bindname = (struct swrap_address) {
4036 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4037 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4039 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4043 SWRAP_UNLOCK_SI(si);
4047 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4049 return swrap_connect(s, serv_addr, addrlen);
4052 /****************************************************************************
4054 ***************************************************************************/
4056 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4059 struct swrap_address un_addr = {
4060 .sa_socklen = sizeof(struct sockaddr_un),
4062 struct socket_info *si = find_socket_info(s);
4069 return libc_bind(s, myaddr, addrlen);
4074 switch (si->family) {
4076 const struct sockaddr_in *sin;
4077 if (addrlen < sizeof(struct sockaddr_in)) {
4078 bind_error = EINVAL;
4082 sin = (const struct sockaddr_in *)(const void *)myaddr;
4084 if (sin->sin_family != AF_INET) {
4085 bind_error = EAFNOSUPPORT;
4088 /* special case for AF_UNSPEC */
4089 if (sin->sin_family == AF_UNSPEC &&
4090 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4099 const struct sockaddr_in6 *sin6;
4100 if (addrlen < sizeof(struct sockaddr_in6)) {
4101 bind_error = EINVAL;
4105 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4107 if (sin6->sin6_family != AF_INET6) {
4108 bind_error = EAFNOSUPPORT;
4115 bind_error = EINVAL;
4119 if (bind_error != 0) {
4126 in_use = check_addr_port_in_use(myaddr, addrlen);
4134 si->myname.sa_socklen = addrlen;
4135 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4137 ret = sockaddr_convert_to_un(si,
4147 unlink(un_addr.sa.un.sun_path);
4149 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4151 SWRAP_LOG(SWRAP_LOG_TRACE,
4152 "bind() path=%s, fd=%d",
4153 un_addr.sa.un.sun_path, s);
4160 SWRAP_UNLOCK_SI(si);
4165 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4167 return swrap_bind(s, myaddr, addrlen);
4170 /****************************************************************************
4172 ***************************************************************************/
4174 #ifdef HAVE_BINDRESVPORT
4175 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4177 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4179 struct swrap_address myaddr = {
4180 .sa_socklen = sizeof(struct sockaddr_storage),
4183 static uint16_t port;
4188 #define SWRAP_STARTPORT 600
4189 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4190 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4193 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4197 salen = myaddr.sa_socklen;
4200 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4206 memset(&myaddr.sa.ss, 0, salen);
4211 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4214 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4216 salen = sizeof(struct sockaddr_in);
4217 sinp->sin_port = htons(port);
4221 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4223 salen = sizeof(struct sockaddr_in6);
4224 sin6p->sin6_port = htons(port);
4228 errno = EAFNOSUPPORT;
4233 if (port > SWRAP_ENDPORT) {
4234 port = SWRAP_STARTPORT;
4237 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4238 if (rc == 0 || errno != EADDRINUSE) {
4246 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4248 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4252 /****************************************************************************
4254 ***************************************************************************/
4256 static int swrap_listen(int s, int backlog)
4259 struct socket_info *si = find_socket_info(s);
4262 return libc_listen(s, backlog);
4267 if (si->bound == 0) {
4268 ret = swrap_auto_bind(s, si, si->family);
4275 ret = libc_listen(s, backlog);
4281 SWRAP_UNLOCK_SI(si);
4286 int listen(int s, int backlog)
4288 return swrap_listen(s, backlog);
4291 /****************************************************************************
4293 ***************************************************************************/
4295 static FILE *swrap_fopen(const char *name, const char *mode)
4299 fp = libc_fopen(name, mode);
4301 int fd = fileno(fp);
4303 swrap_remove_stale(fd);
4309 FILE *fopen(const char *name, const char *mode)
4311 return swrap_fopen(name, mode);
4314 /****************************************************************************
4316 ***************************************************************************/
4319 static FILE *swrap_fopen64(const char *name, const char *mode)
4323 fp = libc_fopen64(name, mode);
4325 int fd = fileno(fp);
4327 swrap_remove_stale(fd);
4333 FILE *fopen64(const char *name, const char *mode)
4335 return swrap_fopen64(name, mode);
4337 #endif /* HAVE_FOPEN64 */
4339 /****************************************************************************
4341 ***************************************************************************/
4343 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4347 ret = libc_vopen(pathname, flags, ap);
4350 * There are methods for closing descriptors (libc-internal code
4351 * paths, direct syscalls) which close descriptors in ways that
4352 * we can't intercept, so try to recover when we notice that
4355 swrap_remove_stale(ret);
4360 int open(const char *pathname, int flags, ...)
4365 va_start(ap, flags);
4366 fd = swrap_vopen(pathname, flags, ap);
4372 /****************************************************************************
4374 ***************************************************************************/
4377 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4381 ret = libc_vopen64(pathname, flags, ap);
4384 * There are methods for closing descriptors (libc-internal code
4385 * paths, direct syscalls) which close descriptors in ways that
4386 * we can't intercept, so try to recover when we notice that
4389 swrap_remove_stale(ret);
4394 int open64(const char *pathname, int flags, ...)
4399 va_start(ap, flags);
4400 fd = swrap_vopen64(pathname, flags, ap);
4405 #endif /* HAVE_OPEN64 */
4407 /****************************************************************************
4409 ***************************************************************************/
4411 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4415 ret = libc_vopenat(dirfd, path, flags, ap);
4418 * There are methods for closing descriptors (libc-internal code
4419 * paths, direct syscalls) which close descriptors in ways that
4420 * we can't intercept, so try to recover when we notice that
4423 swrap_remove_stale(ret);
4429 int openat(int dirfd, const char *path, int flags, ...)
4434 va_start(ap, flags);
4435 fd = swrap_vopenat(dirfd, path, flags, ap);
4441 /****************************************************************************
4443 ***************************************************************************/
4445 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4447 struct socket_info *si = find_socket_info(s);
4452 return libc_getpeername(s, name, addrlen);
4457 if (si->peername.sa_socklen == 0)
4463 len = MIN(*addrlen, si->peername.sa_socklen);
4469 memcpy(name, &si->peername.sa.ss, len);
4470 *addrlen = si->peername.sa_socklen;
4474 SWRAP_UNLOCK_SI(si);
4479 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4480 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4482 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4485 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4488 /****************************************************************************
4490 ***************************************************************************/
4492 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4494 struct socket_info *si = find_socket_info(s);
4499 return libc_getsockname(s, name, addrlen);
4504 len = MIN(*addrlen, si->myname.sa_socklen);
4510 memcpy(name, &si->myname.sa.ss, len);
4511 *addrlen = si->myname.sa_socklen;
4515 SWRAP_UNLOCK_SI(si);
4520 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4521 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4523 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4526 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4529 /****************************************************************************
4531 ***************************************************************************/
4534 # ifdef SO_PROTOTYPE /* The Solaris name */
4535 # define SO_PROTOCOL SO_PROTOTYPE
4536 # endif /* SO_PROTOTYPE */
4537 #endif /* SO_PROTOCOL */
4539 static int swrap_getsockopt(int s, int level, int optname,
4540 void *optval, socklen_t *optlen)
4542 struct socket_info *si = find_socket_info(s);
4546 return libc_getsockopt(s,
4555 if (level == SOL_SOCKET) {
4559 if (optval == NULL || optlen == NULL ||
4560 *optlen < (socklen_t)sizeof(int)) {
4566 *optlen = sizeof(int);
4567 *(int *)optval = si->family;
4570 #endif /* SO_DOMAIN */
4574 if (optval == NULL || optlen == NULL ||
4575 *optlen < (socklen_t)sizeof(int)) {
4581 *optlen = sizeof(int);
4582 *(int *)optval = si->protocol;
4585 #endif /* SO_PROTOCOL */
4587 if (optval == NULL || optlen == NULL ||
4588 *optlen < (socklen_t)sizeof(int)) {
4594 *optlen = sizeof(int);
4595 *(int *)optval = si->type;
4599 ret = libc_getsockopt(s,
4606 } else if (level == IPPROTO_TCP) {
4611 * This enables sending packets directly out over TCP.
4612 * As a unix socket is doing that any way, report it as
4615 if (optval == NULL || optlen == NULL ||
4616 *optlen < (socklen_t)sizeof(int)) {
4622 *optlen = sizeof(int);
4623 *(int *)optval = si->tcp_nodelay;
4627 #endif /* TCP_NODELAY */
4630 struct tcp_info info;
4631 socklen_t ilen = sizeof(info);
4633 #ifdef HAVE_NETINET_TCP_FSM_H
4634 /* This is FreeBSD */
4635 # define __TCP_LISTEN TCPS_LISTEN
4636 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4637 # define __TCP_CLOSE TCPS_CLOSED
4640 # define __TCP_LISTEN TCP_LISTEN
4641 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4642 # define __TCP_CLOSE TCP_CLOSE
4646 if (si->listening) {
4647 info.tcpi_state = __TCP_LISTEN;
4648 } else if (si->connected) {
4650 * For now we just fake a few values
4651 * supported both by FreeBSD and Linux
4653 info.tcpi_state = __TCP_ESTABLISHED;
4654 info.tcpi_rto = 200000; /* 200 msec */
4655 info.tcpi_rtt = 5000; /* 5 msec */
4656 info.tcpi_rttvar = 5000; /* 5 msec */
4658 info.tcpi_state = __TCP_CLOSE;
4659 info.tcpi_rto = 1000000; /* 1 sec */
4661 info.tcpi_rttvar = 250000; /* 250 msec */
4664 if (optval == NULL || optlen == NULL ||
4665 *optlen < (socklen_t)ilen) {
4672 memcpy(optval, &info, ilen);
4677 #endif /* TCP_INFO */
4683 errno = ENOPROTOOPT;
4687 SWRAP_UNLOCK_SI(si);
4691 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4692 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4694 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4697 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4700 /****************************************************************************
4702 ***************************************************************************/
4704 static int swrap_setsockopt(int s, int level, int optname,
4705 const void *optval, socklen_t optlen)
4707 struct socket_info *si = find_socket_info(s);
4711 return libc_setsockopt(s,
4718 if (level == SOL_SOCKET) {
4719 return libc_setsockopt(s,
4728 if (level == IPPROTO_TCP) {
4735 * This enables sending packets directly out over TCP.
4736 * A unix socket is doing that any way.
4738 if (optval == NULL || optlen == 0 ||
4739 optlen < (socklen_t)sizeof(int)) {
4745 i = *discard_const_p(int, optval);
4746 if (i != 0 && i != 1) {
4751 si->tcp_nodelay = i;
4756 #endif /* TCP_NODELAY */
4762 switch (si->family) {
4764 if (level == IPPROTO_IP) {
4766 if (optname == IP_PKTINFO) {
4767 si->pktinfo = AF_INET;
4769 #endif /* IP_PKTINFO */
4775 if (level == IPPROTO_IPV6) {
4776 #ifdef IPV6_RECVPKTINFO
4777 if (optname == IPV6_RECVPKTINFO) {
4778 si->pktinfo = AF_INET6;
4780 #endif /* IPV6_PKTINFO */
4786 errno = ENOPROTOOPT;
4792 SWRAP_UNLOCK_SI(si);
4796 int setsockopt(int s, int level, int optname,
4797 const void *optval, socklen_t optlen)
4799 return swrap_setsockopt(s, level, optname, optval, optlen);
4802 /****************************************************************************
4804 ***************************************************************************/
4806 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4808 struct socket_info *si = find_socket_info(s);
4810 int *value_ptr = NULL;
4814 return libc_vioctl(s, r, va);
4821 rc = libc_vioctl(s, r, va);
4826 value_ptr = ((int *)va_arg(ap, int *));
4829 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4830 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4831 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4832 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4837 /* this is FreeBSD */
4838 FALL_THROUGH; /* to TIOCOUTQ */
4839 #endif /* FIONWRITE */
4840 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4842 * This may return more bytes then the application
4843 * sent into the socket, for tcp it should
4844 * return the number of unacked bytes.
4846 * On AF_UNIX, all bytes are immediately acked!
4849 value_ptr = ((int *)va_arg(ap, int *));
4857 SWRAP_UNLOCK_SI(si);
4861 #ifdef HAVE_IOCTL_INT
4862 int ioctl(int s, int r, ...)
4864 int ioctl(int s, unsigned long int r, ...)
4872 rc = swrap_vioctl(s, (unsigned long int) r, va);
4883 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4886 # ifdef _ALIGN /* BSD */
4887 #define CMSG_ALIGN _ALIGN
4889 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4890 # endif /* _ALIGN */
4891 #endif /* CMSG_ALIGN */
4894 * @brief Add a cmsghdr to a msghdr.
4896 * This is an function to add any type of cmsghdr. It will operate on the
4897 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4898 * the buffer position after the added cmsg element. Hence, this function is
4899 * intended to be used with an intermediate msghdr and not on the original
4900 * one handed in by the client.
4902 * @param[in] msg The msghdr to which to add the cmsg.
4904 * @param[in] level The cmsg level to set.
4906 * @param[in] type The cmsg type to set.
4908 * @param[in] data The cmsg data to set.
4910 * @param[in] len the length of the data to set.
4912 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4918 size_t cmlen = CMSG_LEN(len);
4919 size_t cmspace = CMSG_SPACE(len);
4920 uint8_t cmbuf[cmspace];
4921 void *cast_ptr = (void *)cmbuf;
4922 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4925 memset(cmbuf, 0, cmspace);
4927 if (msg->msg_controllen < cmlen) {
4928 cmlen = msg->msg_controllen;
4929 msg->msg_flags |= MSG_CTRUNC;
4932 if (msg->msg_controllen < cmspace) {
4933 cmspace = msg->msg_controllen;
4937 * We copy the full input data into an intermediate cmsghdr first
4938 * in order to more easily cope with truncation.
4940 cm->cmsg_len = cmlen;
4941 cm->cmsg_level = level;
4942 cm->cmsg_type = type;
4943 memcpy(CMSG_DATA(cm), data, len);
4946 * We now copy the possibly truncated buffer.
4947 * We copy cmlen bytes, but consume cmspace bytes,
4948 * leaving the possible padding uninitialiazed.
4950 p = (uint8_t *)msg->msg_control;
4951 memcpy(p, cm, cmlen);
4953 msg->msg_control = p;
4954 msg->msg_controllen -= cmspace;
4959 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4962 /* Add packet info */
4963 switch (si->pktinfo) {
4964 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4966 struct sockaddr_in *sin;
4967 #if defined(HAVE_STRUCT_IN_PKTINFO)
4968 struct in_pktinfo pkt;
4969 #elif defined(IP_RECVDSTADDR)
4973 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4974 sin = &si->bindname.sa.in;
4976 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4979 sin = &si->myname.sa.in;
4984 #if defined(HAVE_STRUCT_IN_PKTINFO)
4985 pkt.ipi_ifindex = socket_wrapper_default_iface();
4986 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4987 #elif defined(IP_RECVDSTADDR)
4988 pkt = sin->sin_addr;
4991 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4996 #endif /* IP_PKTINFO */
4997 #if defined(HAVE_IPV6)
4999 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5000 struct sockaddr_in6 *sin6;
5001 struct in6_pktinfo pkt6;
5003 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5004 sin6 = &si->bindname.sa.in6;
5006 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5009 sin6 = &si->myname.sa.in6;
5014 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5015 pkt6.ipi6_addr = sin6->sin6_addr;
5017 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5018 &pkt6, sizeof(pkt6));
5019 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5023 #endif /* IPV6_PKTINFO */
5031 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5032 struct msghdr *omsg)
5036 if (si->pktinfo > 0) {
5037 rc = swrap_msghdr_add_pktinfo(si, omsg);
5043 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5045 size_t *cm_data_space);
5046 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5048 size_t *cm_data_space);
5049 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5051 size_t *cm_data_space);
5053 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5055 size_t *cm_data_space)
5057 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5058 struct cmsghdr *cmsg;
5062 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5066 for (cmsg = CMSG_FIRSTHDR(msg);
5068 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5069 switch (cmsg->cmsg_level) {
5071 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5076 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5081 rc = swrap_sendmsg_copy_cmsg(cmsg,
5087 int saved_errno = errno;
5088 SAFE_FREE(*cm_data);
5090 errno = saved_errno;
5098 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5100 size_t *cm_data_space)
5105 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5107 p = realloc((*cm_data), cmspace);
5113 p = (*cm_data) + (*cm_data_space);
5114 *cm_data_space = cmspace;
5116 memcpy(p, cmsg, cmsg->cmsg_len);
5121 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5123 size_t *cm_data_space);
5126 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5128 size_t *cm_data_space)
5132 switch(cmsg->cmsg_type) {
5135 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5142 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5154 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5156 size_t *cm_data_space)
5158 (void)cmsg; /* unused */
5159 (void)cm_data; /* unused */
5160 (void)cm_data_space; /* unused */
5163 * Passing a IP pktinfo to a unix socket might be rejected by the
5164 * Kernel, at least on FreeBSD. So skip this cmsg.
5169 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5171 size_t *cm_data_space)
5175 switch (cmsg->cmsg_type) {
5177 SWRAP_LOG(SWRAP_LOG_TRACE,
5178 "Ignoring SCM_RIGHTS on inet socket!");
5181 #ifdef SCM_CREDENTIALS
5182 case SCM_CREDENTIALS:
5183 SWRAP_LOG(SWRAP_LOG_TRACE,
5184 "Ignoring SCM_CREDENTIALS on inet socket!");
5187 #endif /* SCM_CREDENTIALS */
5189 rc = swrap_sendmsg_copy_cmsg(cmsg,
5198 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5201 * We only allow up to 6 fds at a time
5202 * as that's more than enough for Samba
5203 * and it means we can keep the logic simple
5204 * and work with fixed size arrays.
5206 * We also keep sizeof(struct swrap_unix_scm_rights)
5207 * under PIPE_BUF (4096) in order to allow a non-blocking
5208 * write into the pipe.
5211 #define PIPE_BUF 4096
5213 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5214 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5215 struct swrap_unix_scm_rights_payload {
5217 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5218 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5220 struct swrap_unix_scm_rights {
5222 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5223 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5225 uint32_t payload_size;
5226 struct swrap_unix_scm_rights_payload payload;
5229 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5231 int saved_errno = errno;
5234 for (i = 0; i < num; i++) {
5235 struct socket_info *si = array[i];
5241 swrap_dec_refcount(si);
5242 if (si->fd_passed > 0) {
5245 SWRAP_UNLOCK_SI(si);
5249 errno = saved_errno;
5252 static void swrap_undo_si_idx_array(size_t num, int *array)
5254 int saved_errno = errno;
5257 swrap_mutex_lock(&first_free_mutex);
5259 for (i = 0; i < num; i++) {
5260 struct socket_info *si = NULL;
5262 if (array[i] == -1) {
5266 si = swrap_get_socket_info(array[i]);
5272 swrap_dec_refcount(si);
5273 SWRAP_UNLOCK_SI(si);
5275 swrap_set_next_free(si, first_free);
5276 first_free = array[i];
5280 swrap_mutex_unlock(&first_free_mutex);
5281 errno = saved_errno;
5284 static void swrap_close_fd_array(size_t num, const int *array)
5286 int saved_errno = errno;
5289 for (i = 0; i < num; i++) {
5290 if (array[i] == -1) {
5293 libc_close(array[i]);
5296 errno = saved_errno;
5304 union __swrap_cmsghdr {
5306 struct cmsghdr *cmsg;
5309 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5311 size_t *cm_data_space,
5312 int *scm_rights_pipe_fd)
5314 struct swrap_unix_scm_rights info;
5315 struct swrap_unix_scm_rights_payload *payload = NULL;
5316 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5317 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5318 size_t info_idx = 0;
5321 union __swrap_fds __fds_in = { .p = NULL, };
5322 const int *fds_in = NULL;
5324 size_t size_fds_out;
5325 union __swrap_fds __fds_out = { .p = NULL, };
5326 int *fds_out = NULL;
5329 size_t new_cm_data_space;
5330 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5331 struct cmsghdr *new_cmsg = NULL;
5334 int pipefd[2] = { -1, -1 };
5339 * We pass this a buffer to the kernel make sure any padding
5343 info.magic = swrap_unix_scm_right_magic;
5344 memcpy(info.package_name,
5345 SOCKET_WRAPPER_PACKAGE,
5346 sizeof(info.package_name));
5347 memcpy(info.package_version,
5348 SOCKET_WRAPPER_VERSION,
5349 sizeof(info.package_version));
5350 info.full_size = sizeof(info);
5351 info.payload_size = sizeof(info.payload);
5352 payload = &info.payload;
5354 if (*scm_rights_pipe_fd != -1) {
5355 SWRAP_LOG(SWRAP_LOG_ERROR,
5356 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5361 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5362 SWRAP_LOG(SWRAP_LOG_ERROR,
5363 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5364 (size_t)cmsg->cmsg_len,
5369 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5370 if ((size_fds_in % sizeof(int)) != 0) {
5371 SWRAP_LOG(SWRAP_LOG_ERROR,
5372 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5373 (size_t)cmsg->cmsg_len,
5379 num_fds_in = size_fds_in / sizeof(int);
5380 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5381 SWRAP_LOG(SWRAP_LOG_ERROR,
5382 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5384 "SWRAP_MAX_PASSED_FDS(%zu)",
5385 (size_t)cmsg->cmsg_len,
5388 SWRAP_MAX_PASSED_FDS);
5392 if (num_fds_in == 0) {
5393 SWRAP_LOG(SWRAP_LOG_ERROR,
5394 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5396 (size_t)cmsg->cmsg_len,
5402 __fds_in.p = CMSG_DATA(cmsg);
5403 fds_in = __fds_in.fds;
5404 num_fds_out = num_fds_in + 1;
5406 SWRAP_LOG(SWRAP_LOG_TRACE,
5407 "num_fds_in=%zu num_fds_out=%zu",
5408 num_fds_in, num_fds_out);
5410 size_fds_out = sizeof(int) * num_fds_out;
5411 cmsg_len = CMSG_LEN(size_fds_out);
5412 cmsg_space = CMSG_SPACE(size_fds_out);
5414 new_cm_data_space = *cm_data_space + cmsg_space;
5416 p = realloc((*cm_data), new_cm_data_space);
5421 p = (*cm_data) + (*cm_data_space);
5422 memset(p, 0, cmsg_space);
5424 new_cmsg = __new_cmsg.cmsg;
5426 __fds_out.p = CMSG_DATA(new_cmsg);
5427 fds_out = __fds_out.fds;
5428 memcpy(fds_out, fds_in, size_fds_in);
5429 new_cmsg->cmsg_len = cmsg->cmsg_len;
5431 for (i = 0; i < num_fds_in; i++) {
5434 payload->idxs[i] = -1;
5435 payload->num_idxs++;
5437 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5438 if (si_idx_array[i] == -1) {
5442 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5443 if (si_array[i] == NULL) {
5444 SWRAP_LOG(SWRAP_LOG_ERROR,
5445 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5446 i, fds_in[i], i, si_idx_array[i]);
5451 for (j = 0; j < i; j++) {
5452 if (si_array[j] == si_array[i]) {
5453 payload->idxs[i] = payload->idxs[j];
5457 if (payload->idxs[i] == -1) {
5458 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5459 SWRAP_LOG(SWRAP_LOG_ERROR,
5460 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5461 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5462 i, fds_in[i], i, si_idx_array[i],
5464 SWRAP_MAX_PASSED_SOCKET_INFO);
5468 payload->idxs[i] = info_idx;
5474 for (i = 0; i < num_fds_in; i++) {
5475 struct socket_info *si = si_array[i];
5478 SWRAP_LOG(SWRAP_LOG_TRACE,
5479 "fds_in[%zu]=%d not an inet socket",
5484 SWRAP_LOG(SWRAP_LOG_TRACE,
5485 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5486 "passing as info.idxs[%zu]=%d!",
5489 i, payload->idxs[i]);
5493 payload->infos[payload->idxs[i]] = *si;
5494 payload->infos[payload->idxs[i]].fd_passed = 0;
5495 SWRAP_UNLOCK_SI(si);
5500 int saved_errno = errno;
5501 SWRAP_LOG(SWRAP_LOG_ERROR,
5502 "pipe() failed - %d %s",
5504 strerror(saved_errno));
5505 swrap_dec_fd_passed_array(num_fds_in, si_array);
5506 errno = saved_errno;
5510 sret = libc_write(pipefd[1], &info, sizeof(info));
5511 if (sret != sizeof(info)) {
5512 int saved_errno = errno;
5514 saved_errno = EINVAL;
5516 SWRAP_LOG(SWRAP_LOG_ERROR,
5517 "write() failed - sret=%zd - %d %s",
5519 strerror(saved_errno));
5520 swrap_dec_fd_passed_array(num_fds_in, si_array);
5521 libc_close(pipefd[1]);
5522 libc_close(pipefd[0]);
5523 errno = saved_errno;
5526 libc_close(pipefd[1]);
5529 * Add the pipe read end to the end of the passed fd array
5531 fds_out[num_fds_in] = pipefd[0];
5532 new_cmsg->cmsg_len = cmsg_len;
5534 /* we're done ... */
5535 *scm_rights_pipe_fd = pipefd[0];
5536 *cm_data_space = new_cm_data_space;
5541 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5543 size_t *cm_data_space,
5544 int *scm_rights_pipe_fd)
5548 switch (cmsg->cmsg_type) {
5550 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5553 scm_rights_pipe_fd);
5556 rc = swrap_sendmsg_copy_cmsg(cmsg,
5565 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5567 size_t *cm_data_space)
5569 int scm_rights_pipe_fd = -1;
5570 struct swrap_unix_scm_rights info;
5571 struct swrap_unix_scm_rights_payload *payload = NULL;
5572 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5575 union __swrap_fds __fds_in = { .p = NULL, };
5576 const int *fds_in = NULL;
5578 size_t size_fds_out;
5579 union __swrap_fds __fds_out = { .p = NULL, };
5580 int *fds_out = NULL;
5583 size_t new_cm_data_space;
5584 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5585 struct cmsghdr *new_cmsg = NULL;
5591 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5592 SWRAP_LOG(SWRAP_LOG_ERROR,
5593 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5594 (size_t)cmsg->cmsg_len,
5599 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5600 if ((size_fds_in % sizeof(int)) != 0) {
5601 SWRAP_LOG(SWRAP_LOG_ERROR,
5602 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5603 (size_t)cmsg->cmsg_len,
5609 num_fds_in = size_fds_in / sizeof(int);
5610 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5611 SWRAP_LOG(SWRAP_LOG_ERROR,
5612 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5613 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5614 (size_t)cmsg->cmsg_len,
5617 SWRAP_MAX_PASSED_FDS+1);
5621 if (num_fds_in <= 1) {
5622 SWRAP_LOG(SWRAP_LOG_ERROR,
5623 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5625 (size_t)cmsg->cmsg_len,
5631 __fds_in.p = CMSG_DATA(cmsg);
5632 fds_in = __fds_in.fds;
5633 num_fds_out = num_fds_in - 1;
5635 SWRAP_LOG(SWRAP_LOG_TRACE,
5636 "num_fds_in=%zu num_fds_out=%zu",
5637 num_fds_in, num_fds_out);
5639 for (i = 0; i < num_fds_in; i++) {
5640 /* Check if we have a stale fd and remove it */
5641 swrap_remove_stale(fds_in[i]);
5644 scm_rights_pipe_fd = fds_in[num_fds_out];
5645 size_fds_out = sizeof(int) * num_fds_out;
5646 cmsg_len = CMSG_LEN(size_fds_out);
5647 cmsg_space = CMSG_SPACE(size_fds_out);
5649 new_cm_data_space = *cm_data_space + cmsg_space;
5651 p = realloc((*cm_data), new_cm_data_space);
5653 swrap_close_fd_array(num_fds_in, fds_in);
5657 p = (*cm_data) + (*cm_data_space);
5658 memset(p, 0, cmsg_space);
5660 new_cmsg = __new_cmsg.cmsg;
5662 __fds_out.p = CMSG_DATA(new_cmsg);
5663 fds_out = __fds_out.fds;
5664 memcpy(fds_out, fds_in, size_fds_out);
5665 new_cmsg->cmsg_len = cmsg_len;
5667 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5668 if (sret != sizeof(info)) {
5669 int saved_errno = errno;
5671 saved_errno = EINVAL;
5673 SWRAP_LOG(SWRAP_LOG_ERROR,
5674 "read() failed - sret=%zd - %d %s",
5676 strerror(saved_errno));
5677 swrap_close_fd_array(num_fds_in, fds_in);
5678 errno = saved_errno;
5681 libc_close(scm_rights_pipe_fd);
5682 payload = &info.payload;
5684 if (info.magic != swrap_unix_scm_right_magic) {
5685 SWRAP_LOG(SWRAP_LOG_ERROR,
5686 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5687 (unsigned long long)info.magic,
5688 (unsigned long long)swrap_unix_scm_right_magic);
5689 swrap_close_fd_array(num_fds_out, fds_out);
5694 cmp = memcmp(info.package_name,
5695 SOCKET_WRAPPER_PACKAGE,
5696 sizeof(info.package_name));
5698 SWRAP_LOG(SWRAP_LOG_ERROR,
5699 "info.package_name='%.*s' != '%s'",
5700 (int)sizeof(info.package_name),
5702 SOCKET_WRAPPER_PACKAGE);
5703 swrap_close_fd_array(num_fds_out, fds_out);
5708 cmp = memcmp(info.package_version,
5709 SOCKET_WRAPPER_VERSION,
5710 sizeof(info.package_version));
5712 SWRAP_LOG(SWRAP_LOG_ERROR,
5713 "info.package_version='%.*s' != '%s'",
5714 (int)sizeof(info.package_version),
5715 info.package_version,
5716 SOCKET_WRAPPER_VERSION);
5717 swrap_close_fd_array(num_fds_out, fds_out);
5722 if (info.full_size != sizeof(info)) {
5723 SWRAP_LOG(SWRAP_LOG_ERROR,
5724 "info.full_size=%zu != sizeof(info)=%zu",
5725 (size_t)info.full_size,
5727 swrap_close_fd_array(num_fds_out, fds_out);
5732 if (info.payload_size != sizeof(info.payload)) {
5733 SWRAP_LOG(SWRAP_LOG_ERROR,
5734 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5735 (size_t)info.payload_size,
5736 sizeof(info.payload));
5737 swrap_close_fd_array(num_fds_out, fds_out);
5742 if (payload->num_idxs != num_fds_out) {
5743 SWRAP_LOG(SWRAP_LOG_ERROR,
5744 "info.num_idxs=%u != num_fds_out=%zu",
5745 payload->num_idxs, num_fds_out);
5746 swrap_close_fd_array(num_fds_out, fds_out);
5751 for (i = 0; i < num_fds_out; i++) {
5754 si_idx_array[i] = -1;
5756 if (payload->idxs[i] == -1) {
5757 SWRAP_LOG(SWRAP_LOG_TRACE,
5758 "fds_out[%zu]=%d not an inet socket",
5763 if (payload->idxs[i] < 0) {
5764 SWRAP_LOG(SWRAP_LOG_ERROR,
5765 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5766 i, fds_out[i], i, payload->idxs[i]);
5767 swrap_close_fd_array(num_fds_out, fds_out);
5772 if (payload->idxs[i] >= payload->num_idxs) {
5773 SWRAP_LOG(SWRAP_LOG_ERROR,
5774 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5775 i, fds_out[i], i, payload->idxs[i],
5777 swrap_close_fd_array(num_fds_out, fds_out);
5782 if ((size_t)fds_out[i] >= socket_fds_max) {
5783 SWRAP_LOG(SWRAP_LOG_ERROR,
5784 "The max socket index limit of %zu has been reached, "
5788 swrap_close_fd_array(num_fds_out, fds_out);
5793 SWRAP_LOG(SWRAP_LOG_TRACE,
5795 "received as info.idxs[%zu]=%d!",
5797 i, payload->idxs[i]);
5799 for (j = 0; j < i; j++) {
5800 if (payload->idxs[j] == -1) {
5803 if (payload->idxs[j] == payload->idxs[i]) {
5804 si_idx_array[i] = si_idx_array[j];
5807 if (si_idx_array[i] == -1) {
5808 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5810 si_idx_array[i] = swrap_add_socket_info(si);
5811 if (si_idx_array[i] == -1) {
5812 int saved_errno = errno;
5813 SWRAP_LOG(SWRAP_LOG_ERROR,
5814 "The max socket index limit of %zu has been reached, "
5818 swrap_undo_si_idx_array(i, si_idx_array);
5819 swrap_close_fd_array(num_fds_out, fds_out);
5820 errno = saved_errno;
5823 SWRAP_LOG(SWRAP_LOG_TRACE,
5824 "Imported %s socket for protocol %s, fd=%d",
5825 si->family == AF_INET ? "IPv4" : "IPv6",
5826 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5831 for (i = 0; i < num_fds_out; i++) {
5832 if (si_idx_array[i] == -1) {
5835 set_socket_info_index(fds_out[i], si_idx_array[i]);
5838 /* we're done ... */
5839 *cm_data_space = new_cm_data_space;
5844 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5846 size_t *cm_data_space)
5850 switch (cmsg->cmsg_type) {
5852 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5857 rc = swrap_sendmsg_copy_cmsg(cmsg,
5866 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5868 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5869 struct msghdr *msg_tmp,
5870 int *scm_rights_pipe_fd)
5872 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5873 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5874 struct cmsghdr *cmsg = NULL;
5875 uint8_t *cm_data = NULL;
5876 size_t cm_data_space = 0;
5880 *scm_rights_pipe_fd = -1;
5883 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5887 for (cmsg = CMSG_FIRSTHDR(msg_in);
5889 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5890 switch (cmsg->cmsg_level) {
5892 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5895 scm_rights_pipe_fd);
5899 rc = swrap_sendmsg_copy_cmsg(cmsg,
5905 int saved_errno = errno;
5907 errno = saved_errno;
5912 msg_tmp->msg_controllen = cm_data_space;
5913 msg_tmp->msg_control = cm_data;
5916 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5917 *msg_tmp = *_msg_in;
5919 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5922 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5924 int scm_rights_pipe_fd)
5926 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5927 int saved_errno = errno;
5928 SAFE_FREE(msg_tmp->msg_control);
5929 if (scm_rights_pipe_fd != -1) {
5930 libc_close(scm_rights_pipe_fd);
5932 errno = saved_errno;
5933 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5937 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5938 struct msghdr *msg_tmp,
5939 uint8_t **tmp_control)
5941 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5942 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
5943 uint8_t *cm_data = NULL;
5944 size_t cm_data_space = 0;
5947 *tmp_control = NULL;
5949 SWRAP_LOG(SWRAP_LOG_TRACE,
5950 "msg_in->msg_controllen=%zu",
5951 (size_t)msg_in->msg_controllen);
5954 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5959 * We need to give the kernel a bit more space in order
5960 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
5961 * swrap_recvmsg_after_unix() will hide it again.
5963 cm_data_space = msg_in->msg_controllen;
5964 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
5965 cm_data_space += cm_extra_space;
5967 cm_data = calloc(1, cm_data_space);
5968 if (cm_data == NULL) {
5972 msg_tmp->msg_controllen = cm_data_space;
5973 msg_tmp->msg_control = cm_data;
5974 *tmp_control = cm_data;
5976 SWRAP_LOG(SWRAP_LOG_TRACE,
5977 "msg_tmp->msg_controllen=%zu",
5978 (size_t)msg_tmp->msg_controllen);
5980 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5982 *tmp_control = NULL;
5984 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5987 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5988 uint8_t **tmp_control,
5989 struct msghdr *msg_out,
5992 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5993 struct cmsghdr *cmsg = NULL;
5994 uint8_t *cm_data = NULL;
5995 size_t cm_data_space = 0;
5999 int saved_errno = errno;
6000 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6001 saved_errno, strerror(saved_errno));
6002 SAFE_FREE(*tmp_control);
6003 /* msg_out should not be touched on error */
6004 errno = saved_errno;
6008 SWRAP_LOG(SWRAP_LOG_TRACE,
6009 "msg_tmp->msg_controllen=%zu",
6010 (size_t)msg_tmp->msg_controllen);
6013 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6014 int saved_errno = errno;
6015 *msg_out = *msg_tmp;
6016 SAFE_FREE(*tmp_control);
6017 errno = saved_errno;
6021 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6023 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6024 switch (cmsg->cmsg_level) {
6026 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6032 rc = swrap_sendmsg_copy_cmsg(cmsg,
6038 int saved_errno = errno;
6040 SAFE_FREE(*tmp_control);
6041 errno = saved_errno;
6047 * msg_tmp->msg_control (*tmp_control) was created by
6048 * swrap_recvmsg_before_unix() and msg_out->msg_control
6049 * is still the buffer of the caller.
6051 msg_tmp->msg_control = msg_out->msg_control;
6052 msg_tmp->msg_controllen = msg_out->msg_controllen;
6053 *msg_out = *msg_tmp;
6055 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6056 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6057 msg_out->msg_controllen = cm_data_space;
6059 SAFE_FREE(*tmp_control);
6061 SWRAP_LOG(SWRAP_LOG_TRACE,
6062 "msg_out->msg_controllen=%zu",
6063 (size_t)msg_out->msg_controllen);
6065 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6066 int saved_errno = errno;
6067 *msg_out = *msg_tmp;
6068 SAFE_FREE(*tmp_control);
6069 errno = saved_errno;
6071 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6074 static ssize_t swrap_sendmsg_before(int fd,
6075 struct socket_info *si,
6077 struct iovec *tmp_iov,
6078 struct sockaddr_un *tmp_un,
6079 const struct sockaddr_un **to_un,
6080 const struct sockaddr **to,
6102 if (!si->connected) {
6107 if (msg->msg_iovlen == 0) {
6111 mtu = socket_wrapper_mtu();
6112 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6114 nlen = len + msg->msg_iov[i].iov_len;
6124 msg->msg_iovlen = i;
6125 if (msg->msg_iovlen == 0) {
6126 *tmp_iov = msg->msg_iov[0];
6127 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6129 msg->msg_iov = tmp_iov;
6130 msg->msg_iovlen = 1;
6135 if (si->connected) {
6136 if (msg->msg_name != NULL) {
6138 * We are dealing with unix sockets and if we
6139 * are connected, we should only talk to the
6140 * connected unix path. Using the fd to send
6141 * to another server would be hard to achieve.
6143 msg->msg_name = NULL;
6144 msg->msg_namelen = 0;
6147 const struct sockaddr *msg_name;
6148 msg_name = (const struct sockaddr *)msg->msg_name;
6150 if (msg_name == NULL) {
6156 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6168 msg->msg_name = tmp_un;
6169 msg->msg_namelen = sizeof(*tmp_un);
6172 if (si->bound == 0) {
6173 ret = swrap_auto_bind(fd, si, si->family);
6175 SWRAP_UNLOCK_SI(si);
6176 if (errno == ENOTSOCK) {
6177 swrap_remove_stale(fd);
6180 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6186 if (!si->defer_connect) {
6190 ret = sockaddr_convert_to_un(si,
6192 si->peername.sa_socklen,
6200 ret = libc_connect(fd,
6201 (struct sockaddr *)(void *)tmp_un,
6204 /* to give better errors */
6205 if (ret == -1 && errno == ENOENT) {
6206 errno = EHOSTUNREACH;
6213 si->defer_connect = 0;
6216 errno = EHOSTUNREACH;
6222 SWRAP_UNLOCK_SI(si);
6227 static void swrap_sendmsg_after(int fd,
6228 struct socket_info *si,
6230 const struct sockaddr *to,
6233 int saved_errno = errno;
6240 /* to give better errors */
6242 if (saved_errno == ENOENT) {
6243 saved_errno = EHOSTUNREACH;
6244 } else if (saved_errno == ENOTSOCK) {
6245 /* If the fd is not a socket, remove it */
6246 swrap_remove_stale(fd);
6250 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6251 avail += msg->msg_iov[i].iov_len;
6255 remain = MIN(80, avail);
6260 /* we capture it as one single packet */
6261 buf = (uint8_t *)malloc(remain);
6263 /* we just not capture the packet */
6264 errno = saved_errno;
6268 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6269 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6271 msg->msg_iov[i].iov_base,
6274 remain -= this_time;
6283 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6284 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6286 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6291 if (si->connected) {
6292 to = &si->peername.sa.s;
6295 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6296 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6298 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6303 SWRAP_UNLOCK_SI(si);
6306 errno = saved_errno;
6309 static int swrap_recvmsg_before(int fd,
6310 struct socket_info *si,
6312 struct iovec *tmp_iov)
6319 (void)fd; /* unused */
6324 if (!si->connected) {
6329 if (msg->msg_iovlen == 0) {
6333 mtu = socket_wrapper_mtu();
6334 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6336 nlen = len + msg->msg_iov[i].iov_len;
6341 msg->msg_iovlen = i;
6342 if (msg->msg_iovlen == 0) {
6343 *tmp_iov = msg->msg_iov[0];
6344 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6346 msg->msg_iov = tmp_iov;
6347 msg->msg_iovlen = 1;
6352 if (msg->msg_name == NULL) {
6357 if (msg->msg_iovlen == 0) {
6361 if (si->bound == 0) {
6362 ret = swrap_auto_bind(fd, si, si->family);
6364 SWRAP_UNLOCK_SI(si);
6366 * When attempting to read or write to a
6367 * descriptor, if an underlying autobind fails
6368 * because it's not a socket, stop intercepting
6369 * uses of that descriptor.
6371 if (errno == ENOTSOCK) {
6372 swrap_remove_stale(fd);
6375 SWRAP_LOG(SWRAP_LOG_ERROR,
6376 "swrap_recvmsg_before failed");
6383 errno = EHOSTUNREACH;
6389 SWRAP_UNLOCK_SI(si);
6394 static int swrap_recvmsg_after(int fd,
6395 struct socket_info *si,
6397 const struct sockaddr_un *un_addr,
6398 socklen_t un_addrlen,
6401 int saved_errno = errno;
6403 uint8_t *buf = NULL;
6409 /* to give better errors */
6411 if (saved_errno == ENOENT) {
6412 saved_errno = EHOSTUNREACH;
6413 } else if (saved_errno == ENOTSOCK) {
6414 /* If the fd is not a socket, remove it */
6415 swrap_remove_stale(fd);
6419 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6420 avail += msg->msg_iov[i].iov_len;
6425 /* Convert the socket address before we leave */
6426 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6427 rc = sockaddr_convert_from_un(si,
6444 remain = MIN(80, avail);
6449 /* we capture it as one single packet */
6450 buf = (uint8_t *)malloc(remain);
6452 /* we just not capture the packet */
6453 SWRAP_UNLOCK_SI(si);
6454 errno = saved_errno;
6458 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6459 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6461 msg->msg_iov[i].iov_base,
6464 remain -= this_time;
6469 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6470 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6471 } else if (ret == 0) { /* END OF FILE */
6472 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6473 } else if (ret > 0) {
6474 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6483 if (un_addr != NULL) {
6484 swrap_pcap_dump_packet(si,
6490 swrap_pcap_dump_packet(si,
6503 errno = saved_errno;
6505 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6507 msg->msg_controllen > 0 &&
6508 msg->msg_control != NULL) {
6509 rc = swrap_msghdr_add_socket_info(si, msg);
6511 SWRAP_UNLOCK_SI(si);
6517 SWRAP_UNLOCK_SI(si);
6521 /****************************************************************************
6523 ***************************************************************************/
6525 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6526 struct sockaddr *from, socklen_t *fromlen)
6528 struct swrap_address from_addr = {
6529 .sa_socklen = sizeof(struct sockaddr_un),
6532 struct socket_info *si = find_socket_info(s);
6533 struct swrap_address saddr = {
6534 .sa_socklen = sizeof(struct sockaddr_storage),
6541 return libc_recvfrom(s,
6553 if (from != NULL && fromlen != NULL) {
6554 msg.msg_name = from; /* optional address */
6555 msg.msg_namelen = *fromlen; /* size of address */
6557 msg.msg_name = &saddr.sa.s; /* optional address */
6558 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6560 msg.msg_iov = &tmp; /* scatter/gather array */
6561 msg.msg_iovlen = 1; /* # elements in msg_iov */
6562 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6563 msg.msg_control = NULL; /* ancillary data, see below */
6564 msg.msg_controllen = 0; /* ancillary data buffer len */
6565 msg.msg_flags = 0; /* flags on received message */
6568 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6573 buf = msg.msg_iov[0].iov_base;
6574 len = msg.msg_iov[0].iov_len;
6576 ret = libc_recvfrom(s,
6581 &from_addr.sa_socklen);
6586 tret = swrap_recvmsg_after(s,
6590 from_addr.sa_socklen,
6596 if (from != NULL && fromlen != NULL) {
6597 *fromlen = msg.msg_namelen;
6603 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6604 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6605 struct sockaddr *from, Psocklen_t fromlen)
6607 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6608 struct sockaddr *from, socklen_t *fromlen)
6611 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6614 /****************************************************************************
6616 ***************************************************************************/
6618 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6619 const struct sockaddr *to, socklen_t tolen)
6623 struct swrap_address un_addr = {
6624 .sa_socklen = sizeof(struct sockaddr_un),
6626 const struct sockaddr_un *to_un = NULL;
6629 struct socket_info *si = find_socket_info(s);
6633 return libc_sendto(s, buf, len, flags, to, tolen);
6636 tmp.iov_base = discard_const_p(char, buf);
6640 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6641 msg.msg_namelen = tolen; /* size of address */
6642 msg.msg_iov = &tmp; /* scatter/gather array */
6643 msg.msg_iovlen = 1; /* # elements in msg_iov */
6644 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6645 msg.msg_control = NULL; /* ancillary data, see below */
6646 msg.msg_controllen = 0; /* ancillary data buffer len */
6647 msg.msg_flags = 0; /* flags on received message */
6650 rc = swrap_sendmsg_before(s,
6662 buf = msg.msg_iov[0].iov_base;
6663 len = msg.msg_iov[0].iov_len;
6668 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6670 char *swrap_dir = NULL;
6672 type = SOCKET_TYPE_CHAR_UDP;
6674 swrap_dir = socket_wrapper_dir();
6675 if (swrap_dir == NULL) {
6679 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6680 swrap_un_path(&un_addr.sa.un,
6685 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6687 /* ignore the any errors in broadcast sends */
6693 un_addr.sa_socklen);
6696 SAFE_FREE(swrap_dir);
6700 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6702 SWRAP_UNLOCK_SI(si);
6709 * If it is a dgram socket and we are connected, don't include the
6712 if (si->type == SOCK_DGRAM && si->connected) {
6713 ret = libc_sendto(s,
6720 ret = libc_sendto(s,
6724 (struct sockaddr *)msg.msg_name,
6728 SWRAP_UNLOCK_SI(si);
6730 swrap_sendmsg_after(s, si, &msg, to, ret);
6735 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6736 const struct sockaddr *to, socklen_t tolen)
6738 return swrap_sendto(s, buf, len, flags, to, tolen);
6741 /****************************************************************************
6743 ***************************************************************************/
6745 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6747 struct socket_info *si;
6749 struct swrap_address saddr = {
6750 .sa_socklen = sizeof(struct sockaddr_storage),
6756 si = find_socket_info(s);
6758 return libc_recv(s, buf, len, flags);
6765 msg.msg_name = &saddr.sa.s; /* optional address */
6766 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6767 msg.msg_iov = &tmp; /* scatter/gather array */
6768 msg.msg_iovlen = 1; /* # elements in msg_iov */
6769 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6770 msg.msg_control = NULL; /* ancillary data, see below */
6771 msg.msg_controllen = 0; /* ancillary data buffer len */
6772 msg.msg_flags = 0; /* flags on received message */
6775 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6780 buf = msg.msg_iov[0].iov_base;
6781 len = msg.msg_iov[0].iov_len;
6783 ret = libc_recv(s, buf, len, flags);
6785 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6793 ssize_t recv(int s, void *buf, size_t len, int flags)
6795 return swrap_recv(s, buf, len, flags);
6798 /****************************************************************************
6800 ***************************************************************************/
6802 static ssize_t swrap_read(int s, void *buf, size_t len)
6804 struct socket_info *si;
6807 struct swrap_address saddr = {
6808 .sa_socklen = sizeof(struct sockaddr_storage),
6813 si = find_socket_info(s);
6815 return libc_read(s, buf, len);
6822 msg.msg_name = &saddr.sa.ss; /* optional address */
6823 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6824 msg.msg_iov = &tmp; /* scatter/gather array */
6825 msg.msg_iovlen = 1; /* # elements in msg_iov */
6826 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6827 msg.msg_control = NULL; /* ancillary data, see below */
6828 msg.msg_controllen = 0; /* ancillary data buffer len */
6829 msg.msg_flags = 0; /* flags on received message */
6832 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6834 if (tret == -ENOTSOCK) {
6835 return libc_read(s, buf, len);
6840 buf = msg.msg_iov[0].iov_base;
6841 len = msg.msg_iov[0].iov_len;
6843 ret = libc_read(s, buf, len);
6845 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6853 ssize_t read(int s, void *buf, size_t len)
6855 return swrap_read(s, buf, len);
6858 /****************************************************************************
6860 ***************************************************************************/
6862 static ssize_t swrap_write(int s, const void *buf, size_t len)
6866 struct sockaddr_un un_addr;
6869 struct socket_info *si;
6871 si = find_socket_info(s);
6873 return libc_write(s, buf, len);
6876 tmp.iov_base = discard_const_p(char, buf);
6880 msg.msg_name = NULL; /* optional address */
6881 msg.msg_namelen = 0; /* size of address */
6882 msg.msg_iov = &tmp; /* scatter/gather array */
6883 msg.msg_iovlen = 1; /* # elements in msg_iov */
6884 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6885 msg.msg_control = NULL; /* ancillary data, see below */
6886 msg.msg_controllen = 0; /* ancillary data buffer len */
6887 msg.msg_flags = 0; /* flags on received message */
6890 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6895 buf = msg.msg_iov[0].iov_base;
6896 len = msg.msg_iov[0].iov_len;
6898 ret = libc_write(s, buf, len);
6900 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6905 ssize_t write(int s, const void *buf, size_t len)
6907 return swrap_write(s, buf, len);
6910 /****************************************************************************
6912 ***************************************************************************/
6914 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6918 struct sockaddr_un un_addr;
6921 struct socket_info *si = find_socket_info(s);
6924 return libc_send(s, buf, len, flags);
6927 tmp.iov_base = discard_const_p(char, buf);
6931 msg.msg_name = NULL; /* optional address */
6932 msg.msg_namelen = 0; /* size of address */
6933 msg.msg_iov = &tmp; /* scatter/gather array */
6934 msg.msg_iovlen = 1; /* # elements in msg_iov */
6935 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6936 msg.msg_control = NULL; /* ancillary data, see below */
6937 msg.msg_controllen = 0; /* ancillary data buffer len */
6938 msg.msg_flags = 0; /* flags on received message */
6941 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6946 buf = msg.msg_iov[0].iov_base;
6947 len = msg.msg_iov[0].iov_len;
6949 ret = libc_send(s, buf, len, flags);
6951 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6956 ssize_t send(int s, const void *buf, size_t len, int flags)
6958 return swrap_send(s, buf, len, flags);
6961 /****************************************************************************
6963 ***************************************************************************/
6965 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6967 struct swrap_address from_addr = {
6968 .sa_socklen = sizeof(struct sockaddr_un),
6970 struct swrap_address convert_addr = {
6971 .sa_socklen = sizeof(struct sockaddr_storage),
6973 struct socket_info *si;
6976 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6977 size_t msg_ctrllen_filled;
6978 size_t msg_ctrllen_left;
6984 si = find_socket_info(s);
6986 uint8_t *tmp_control = NULL;
6987 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
6991 ret = libc_recvmsg(s, &msg, flags);
6992 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
6995 tmp.iov_base = NULL;
6999 msg.msg_name = &from_addr.sa; /* optional address */
7000 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7001 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7002 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7003 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7004 msg_ctrllen_filled = 0;
7005 msg_ctrllen_left = omsg->msg_controllen;
7007 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7008 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7009 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7012 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7017 ret = libc_recvmsg(s, &msg, flags);
7019 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7020 msg_ctrllen_filled += msg.msg_controllen;
7021 msg_ctrllen_left -= msg.msg_controllen;
7023 if (omsg->msg_control != NULL) {
7026 p = omsg->msg_control;
7027 p += msg_ctrllen_filled;
7029 msg.msg_control = p;
7030 msg.msg_controllen = msg_ctrllen_left;
7032 msg.msg_control = NULL;
7033 msg.msg_controllen = 0;
7038 * We convert the unix address to a IP address so we need a buffer
7039 * which can store the address in case of SOCK_DGRAM, see below.
7041 msg.msg_name = &convert_addr.sa;
7042 msg.msg_namelen = convert_addr.sa_socklen;
7044 rc = swrap_recvmsg_after(s,
7048 from_addr.sa_socklen,
7054 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7055 if (omsg->msg_control != NULL) {
7056 /* msg.msg_controllen = space left */
7057 msg_ctrllen_left = msg.msg_controllen;
7058 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7061 /* Update the original message length */
7062 omsg->msg_controllen = msg_ctrllen_filled;
7063 omsg->msg_flags = msg.msg_flags;
7065 omsg->msg_iovlen = msg.msg_iovlen;
7072 * The msg_name field points to a caller-allocated buffer that is
7073 * used to return the source address if the socket is unconnected. The
7074 * caller should set msg_namelen to the size of this buffer before this
7075 * call; upon return from a successful call, msg_name will contain the
7076 * length of the returned address. If the application does not need
7077 * to know the source address, msg_name can be specified as NULL.
7079 if (si->type == SOCK_STREAM) {
7080 omsg->msg_namelen = 0;
7081 } else if (omsg->msg_name != NULL &&
7082 omsg->msg_namelen != 0 &&
7083 omsg->msg_namelen >= msg.msg_namelen) {
7084 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7085 omsg->msg_namelen = msg.msg_namelen;
7088 SWRAP_UNLOCK_SI(si);
7093 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7095 return swrap_recvmsg(sockfd, msg, flags);
7098 /****************************************************************************
7100 ***************************************************************************/
7102 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7106 struct sockaddr_un un_addr;
7107 const struct sockaddr_un *to_un = NULL;
7108 const struct sockaddr *to = NULL;
7111 struct socket_info *si = find_socket_info(s);
7115 int scm_rights_pipe_fd = -1;
7117 rc = swrap_sendmsg_before_unix(omsg, &msg,
7118 &scm_rights_pipe_fd);
7122 ret = libc_sendmsg(s, &msg, flags);
7123 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7126 ZERO_STRUCT(un_addr);
7128 tmp.iov_base = NULL;
7135 if (si->connected == 0) {
7136 msg.msg_name = omsg->msg_name; /* optional address */
7137 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7139 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7140 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7142 SWRAP_UNLOCK_SI(si);
7144 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7145 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7146 uint8_t *cmbuf = NULL;
7149 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7155 msg.msg_controllen = 0;
7156 msg.msg_control = NULL;
7158 msg.msg_control = cmbuf;
7159 msg.msg_controllen = cmlen;
7162 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7164 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7166 int saved_errno = errno;
7167 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7168 SAFE_FREE(msg.msg_control);
7170 errno = saved_errno;
7177 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7184 char *swrap_dir = NULL;
7186 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7187 avail += msg.msg_iov[i].iov_len;
7193 /* we capture it as one single packet */
7194 buf = (uint8_t *)malloc(remain);
7196 int saved_errno = errno;
7197 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7198 SAFE_FREE(msg.msg_control);
7200 errno = saved_errno;
7204 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7205 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7207 msg.msg_iov[i].iov_base,
7210 remain -= this_time;
7213 type = SOCKET_TYPE_CHAR_UDP;
7215 swrap_dir = socket_wrapper_dir();
7216 if (swrap_dir == NULL) {
7217 int saved_errno = errno;
7218 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7219 SAFE_FREE(msg.msg_control);
7222 errno = saved_errno;
7226 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7227 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7228 if (stat(un_addr.sun_path, &st) != 0) continue;
7230 msg.msg_name = &un_addr; /* optional address */
7231 msg.msg_namelen = sizeof(un_addr); /* size of address */
7233 /* ignore the any errors in broadcast sends */
7234 libc_sendmsg(s, &msg, flags);
7237 SAFE_FREE(swrap_dir);
7241 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7244 SWRAP_UNLOCK_SI(si);
7249 ret = libc_sendmsg(s, &msg, flags);
7251 swrap_sendmsg_after(s, si, &msg, to, ret);
7253 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7255 int saved_errno = errno;
7256 SAFE_FREE(msg.msg_control);
7257 errno = saved_errno;
7264 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7266 return swrap_sendmsg(s, omsg, flags);
7269 /****************************************************************************
7271 ***************************************************************************/
7273 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7275 struct socket_info *si;
7278 struct swrap_address saddr = {
7279 .sa_socklen = sizeof(struct sockaddr_storage)
7284 si = find_socket_info(s);
7286 return libc_readv(s, vector, count);
7289 tmp.iov_base = NULL;
7293 msg.msg_name = &saddr.sa.s; /* optional address */
7294 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7295 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7296 msg.msg_iovlen = count; /* # elements in msg_iov */
7297 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7298 msg.msg_control = NULL; /* ancillary data, see below */
7299 msg.msg_controllen = 0; /* ancillary data buffer len */
7300 msg.msg_flags = 0; /* flags on received message */
7303 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7305 if (rc == -ENOTSOCK) {
7306 return libc_readv(s, vector, count);
7311 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7313 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7321 ssize_t readv(int s, const struct iovec *vector, int count)
7323 return swrap_readv(s, vector, count);
7326 /****************************************************************************
7328 ***************************************************************************/
7330 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7334 struct sockaddr_un un_addr;
7337 struct socket_info *si = find_socket_info(s);
7340 return libc_writev(s, vector, count);
7343 tmp.iov_base = NULL;
7347 msg.msg_name = NULL; /* optional address */
7348 msg.msg_namelen = 0; /* size of address */
7349 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7350 msg.msg_iovlen = count; /* # elements in msg_iov */
7351 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7352 msg.msg_control = NULL; /* ancillary data, see below */
7353 msg.msg_controllen = 0; /* ancillary data buffer len */
7354 msg.msg_flags = 0; /* flags on received message */
7357 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7359 if (rc == -ENOTSOCK) {
7360 return libc_readv(s, vector, count);
7365 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7367 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7372 ssize_t writev(int s, const struct iovec *vector, int count)
7374 return swrap_writev(s, vector, count);
7377 /****************************
7379 ***************************/
7381 static int swrap_remove_wrapper(const char *__func_name,
7382 int (*__close_fd_fn)(int fd),
7385 struct socket_info *si = NULL;
7387 int ret_errno = errno;
7390 swrap_mutex_lock(&socket_reset_mutex);
7392 si_index = find_socket_info_index(fd);
7393 if (si_index == -1) {
7394 swrap_mutex_unlock(&socket_reset_mutex);
7395 return __close_fd_fn(fd);
7398 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
7399 reset_socket_info_index(fd);
7401 si = swrap_get_socket_info(si_index);
7403 swrap_mutex_lock(&first_free_mutex);
7406 ret = __close_fd_fn(fd);
7411 swrap_dec_refcount(si);
7413 if (swrap_get_refcount(si) > 0) {
7414 /* there are still references left */
7418 if (si->fd_passed) {
7422 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7423 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7426 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7427 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7428 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7431 if (si->un_addr.sun_path[0] != '\0') {
7432 unlink(si->un_addr.sun_path);
7436 swrap_set_next_free(si, first_free);
7437 first_free = si_index;
7440 SWRAP_UNLOCK_SI(si);
7441 swrap_mutex_unlock(&first_free_mutex);
7442 swrap_mutex_unlock(&socket_reset_mutex);
7448 static int swrap_noop_close(int fd)
7450 (void)fd; /* unused */
7454 static void swrap_remove_stale(int fd)
7456 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7460 * This allows socket_wrapper aware applications to
7461 * indicate that the given fd does not belong to
7464 * We already overload a lot of unrelated functions
7465 * like eventfd(), timerfd_create(), ... in order to
7466 * call swrap_remove_stale() on the returned fd, but
7467 * we'll never be able to handle all possible syscalls.
7469 * socket_wrapper_indicate_no_inet_fd() gives them a way
7472 * We don't export swrap_remove_stale() in order to
7473 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
7476 void socket_wrapper_indicate_no_inet_fd(int fd)
7478 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7481 static int swrap_close(int fd)
7483 return swrap_remove_wrapper(__func__, libc_close, fd);
7488 return swrap_close(fd);
7491 /****************************
7493 ***************************/
7495 static int swrap_dup(int fd)
7497 struct socket_info *si;
7500 idx = find_socket_info_index(fd);
7502 return libc_dup(fd);
7505 si = swrap_get_socket_info(idx);
7507 dup_fd = libc_dup(fd);
7509 int saved_errno = errno;
7510 errno = saved_errno;
7514 if ((size_t)dup_fd >= socket_fds_max) {
7515 SWRAP_LOG(SWRAP_LOG_ERROR,
7516 "The max socket index limit of %zu has been reached, "
7527 swrap_inc_refcount(si);
7529 SWRAP_UNLOCK_SI(si);
7531 /* Make sure we don't have an entry for the fd */
7532 swrap_remove_stale(dup_fd);
7534 set_socket_info_index(dup_fd, idx);
7541 return swrap_dup(fd);
7544 /****************************
7546 ***************************/
7548 static int swrap_dup2(int fd, int newfd)
7550 struct socket_info *si;
7553 idx = find_socket_info_index(fd);
7555 return libc_dup2(fd, newfd);
7558 si = swrap_get_socket_info(idx);
7562 * According to the manpage:
7564 * "If oldfd is a valid file descriptor, and newfd has the same
7565 * value as oldfd, then dup2() does nothing, and returns newfd."
7570 if ((size_t)newfd >= socket_fds_max) {
7571 SWRAP_LOG(SWRAP_LOG_ERROR,
7572 "The max socket index limit of %zu has been reached, "
7580 if (find_socket_info(newfd)) {
7581 /* dup2() does an implicit close of newfd, which we
7582 * need to emulate */
7586 dup_fd = libc_dup2(fd, newfd);
7588 int saved_errno = errno;
7589 errno = saved_errno;
7595 swrap_inc_refcount(si);
7597 SWRAP_UNLOCK_SI(si);
7599 /* Make sure we don't have an entry for the fd */
7600 swrap_remove_stale(dup_fd);
7602 set_socket_info_index(dup_fd, idx);
7607 int dup2(int fd, int newfd)
7609 return swrap_dup2(fd, newfd);
7612 /****************************
7614 ***************************/
7616 static int swrap_vfcntl(int fd, int cmd, va_list va)
7618 struct socket_info *si;
7619 int rc, dup_fd, idx;
7621 idx = find_socket_info_index(fd);
7623 return libc_vfcntl(fd, cmd, va);
7626 si = swrap_get_socket_info(idx);
7630 dup_fd = libc_vfcntl(fd, cmd, va);
7632 int saved_errno = errno;
7633 errno = saved_errno;
7637 /* Make sure we don't have an entry for the fd */
7638 swrap_remove_stale(dup_fd);
7640 if ((size_t)dup_fd >= socket_fds_max) {
7641 SWRAP_LOG(SWRAP_LOG_ERROR,
7642 "The max socket index limit of %zu has been reached, "
7653 swrap_inc_refcount(si);
7655 SWRAP_UNLOCK_SI(si);
7658 set_socket_info_index(dup_fd, idx);
7663 rc = libc_vfcntl(fd, cmd, va);
7670 int fcntl(int fd, int cmd, ...)
7677 rc = swrap_vfcntl(fd, cmd, va);
7684 /****************************
7686 ***************************/
7689 static int swrap_eventfd(int count, int flags)
7693 fd = libc_eventfd(count, flags);
7695 swrap_remove_stale(fd);
7701 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7702 int eventfd(unsigned int count, int flags)
7704 int eventfd(int count, int flags)
7707 return swrap_eventfd(count, flags);
7712 int pledge(const char *promises, const char *paths[])
7714 (void)promises; /* unused */
7715 (void)paths; /* unused */
7719 #endif /* HAVE_PLEDGE */
7721 static void swrap_thread_prepare(void)
7724 * This function should only be called here!!
7726 * We bind all symobls to avoid deadlocks of the fork is
7727 * interrupted by a signal handler using a symbol of this
7730 swrap_bind_symbol_all();
7735 static void swrap_thread_parent(void)
7740 static void swrap_thread_child(void)
7745 /****************************
7747 ***************************/
7748 void swrap_constructor(void)
7750 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7751 SWRAP_LOG(SWRAP_LOG_ERROR,
7753 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7754 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7755 "sizeof(struct socket_info)=%zu",
7757 sizeof(struct swrap_unix_scm_rights),
7758 sizeof(struct swrap_unix_scm_rights_payload),
7759 sizeof(struct socket_info));
7766 * If we hold a lock and the application forks, then the child
7767 * is not able to unlock the mutex and we are in a deadlock.
7768 * This should prevent such deadlocks.
7770 pthread_atfork(&swrap_thread_prepare,
7771 &swrap_thread_parent,
7772 &swrap_thread_child);
7775 /****************************
7777 ***************************/
7780 * This function is called when the library is unloaded and makes sure that
7781 * sockets get closed and the unix file for the socket are unlinked.
7783 void swrap_destructor(void)
7787 if (socket_fds_idx != NULL) {
7788 for (i = 0; i < socket_fds_max; ++i) {
7789 if (socket_fds_idx[i] != -1) {
7793 SAFE_FREE(socket_fds_idx);
7798 if (swrap.libc.handle != NULL) {
7799 dlclose(swrap.libc.handle);
7801 if (swrap.libc.socket_handle) {
7802 dlclose(swrap.libc.socket_handle);
7806 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7808 * On FreeBSD 12 (and maybe other platforms)
7809 * system libraries like libresolv prefix there
7810 * syscalls with '_' in order to always use
7811 * the symbols from libc.
7813 * In the interaction with resolv_wrapper,
7814 * we need to inject socket wrapper into libresolv,
7815 * which means we need to private all socket
7816 * related syscalls also with the '_' prefix.
7818 * This is tested in Samba's 'make test',
7819 * there we noticed that providing '_read'
7820 * and '_open' would cause errors, which
7821 * means we skip '_read', '_write' and
7822 * all non socket related calls without
7823 * further analyzing the problem.
7825 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7826 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7829 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7831 SWRAP_SYMBOL_ALIAS(accept, _accept);
7832 SWRAP_SYMBOL_ALIAS(bind, _bind);
7833 SWRAP_SYMBOL_ALIAS(close, _close);
7834 SWRAP_SYMBOL_ALIAS(connect, _connect);
7835 SWRAP_SYMBOL_ALIAS(dup, _dup);
7836 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7837 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7838 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7839 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7840 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7841 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7842 SWRAP_SYMBOL_ALIAS(listen, _listen);
7843 SWRAP_SYMBOL_ALIAS(readv, _readv);
7844 SWRAP_SYMBOL_ALIAS(recv, _recv);
7845 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7846 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7847 SWRAP_SYMBOL_ALIAS(send, _send);
7848 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7849 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7850 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7851 SWRAP_SYMBOL_ALIAS(socket, _socket);
7852 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7853 SWRAP_SYMBOL_ALIAS(writev, _writev);
7855 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */