4 * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 * Copyright (c) 2006-2018, Stefan Metzmacher <metze@samba.org>
6 * Copyright (c) 2013-2018, 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>
96 /* GCC have printf type attribute check. */
97 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
98 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
100 #define PRINTF_ATTRIBUTE(a,b)
101 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
103 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
104 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
106 #define CONSTRUCTOR_ATTRIBUTE
107 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
109 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
110 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
112 #define DESTRUCTOR_ATTRIBUTE
116 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
117 # define FALL_THROUGH __attribute__ ((fallthrough))
118 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
119 # define FALL_THROUGH ((void)0)
120 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
121 #endif /* FALL_THROUGH */
123 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
124 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
126 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
129 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
130 # define SWRAP_THREAD __thread
132 # define SWRAP_THREAD
136 #define MIN(a,b) ((a)<(b)?(a):(b))
140 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
144 #define ZERO_STRUCTP(x) do { \
146 memset((char *)(x), 0, sizeof(*(x))); \
151 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
154 #ifndef discard_const
155 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
158 #ifndef discard_const_p
159 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
162 #define UNUSED(x) (void)(x)
165 # ifndef IPV6_RECVPKTINFO
166 # define IPV6_RECVPKTINFO IPV6_PKTINFO
167 # endif /* IPV6_RECVPKTINFO */
168 #endif /* IPV6_PKTINFO */
171 * On BSD IP_PKTINFO has a different name because during
172 * the time when they implemented it, there was no RFC.
173 * The name for IPv6 is the same as on Linux.
176 # ifdef IP_RECVDSTADDR
177 # define IP_PKTINFO IP_RECVDSTADDR
181 #define socket_wrapper_init_mutex(m) \
182 _socket_wrapper_init_mutex(m, #m)
184 /* Add new global locks here please */
185 # define SWRAP_REINIT_ALL do { \
188 ret = socket_wrapper_init_mutex(&sockets_mutex); \
189 if (ret != 0) exit(-1); \
190 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
191 if (ret != 0) exit(-1); \
192 ret = socket_wrapper_init_mutex(&first_free_mutex); \
193 if (ret != 0) exit(-1); \
194 for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \
195 ret = socket_wrapper_init_mutex(&sockets[__i].meta.mutex); \
196 if (ret != 0) exit(-1); \
198 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
199 if (ret != 0) exit(-1); \
200 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
201 if (ret != 0) exit(-1); \
202 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
203 if (ret != 0) exit(-1); \
206 # define SWRAP_LOCK_ALL do { \
208 swrap_mutex_lock(&sockets_mutex); \
209 swrap_mutex_lock(&socket_reset_mutex); \
210 swrap_mutex_lock(&first_free_mutex); \
211 for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \
212 swrap_mutex_lock(&sockets[__i].meta.mutex); \
214 swrap_mutex_lock(&autobind_start_mutex); \
215 swrap_mutex_lock(&pcap_dump_mutex); \
216 swrap_mutex_lock(&mtu_update_mutex); \
219 # define SWRAP_UNLOCK_ALL do { \
221 swrap_mutex_unlock(&mtu_update_mutex); \
222 swrap_mutex_unlock(&pcap_dump_mutex); \
223 swrap_mutex_unlock(&autobind_start_mutex); \
224 for (__s = 0; (sockets != NULL) && __s < socket_info_max; __s++) { \
225 size_t __i = (socket_info_max - 1) - __s; \
226 swrap_mutex_unlock(&sockets[__i].meta.mutex); \
228 swrap_mutex_unlock(&first_free_mutex); \
229 swrap_mutex_unlock(&socket_reset_mutex); \
230 swrap_mutex_unlock(&sockets_mutex); \
233 #define SOCKET_INFO_CONTAINER(si) \
234 (struct socket_info_container *)(si)
236 #define SWRAP_LOCK_SI(si) do { \
237 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
238 swrap_mutex_lock(&sic->meta.mutex); \
241 #define SWRAP_UNLOCK_SI(si) do { \
242 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
243 swrap_mutex_unlock(&sic->meta.mutex); \
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;
317 /* The unix path so we can unlink it on close() */
318 struct sockaddr_un un_addr;
320 struct swrap_address bindname;
321 struct swrap_address myname;
322 struct swrap_address peername;
325 unsigned long pck_snd;
326 unsigned long pck_rcv;
330 struct socket_info_meta
332 unsigned int refcount;
334 pthread_mutex_t mutex;
337 struct socket_info_container
339 struct socket_info info;
340 struct socket_info_meta meta;
343 static struct socket_info_container *sockets;
345 static size_t socket_info_max = 0;
348 * Allocate the socket array always on the limit value. We want it to be
349 * at least bigger than the default so if we reach the limit we can
350 * still deal with duplicate fds pointing to the same socket_info.
352 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
354 /* Hash table to map fds to corresponding socket_info index */
355 static int *socket_fds_idx;
357 /* Mutex for syncronizing port selection during swrap_auto_bind() */
358 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
360 /* Mutex to guard the initialization of array of socket_info structures */
361 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
363 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
364 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
366 /* Mutex to synchronize access to first free index in socket_info array */
367 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
369 /* Mutex to synchronize access to packet capture dump file */
370 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
372 /* Mutex for synchronizing mtu value fetch*/
373 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
375 /* Function prototypes */
377 bool socket_wrapper_enabled(void);
379 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
380 /* xlC and other oldschool compilers support (only) this */
381 #pragma init (swrap_constructor)
383 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
384 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
385 #pragma fini (swrap_destructor)
387 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
389 #ifndef HAVE_GETPROGNAME
390 static const char *getprogname(void)
392 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
393 return program_invocation_short_name;
394 #elif defined(HAVE_GETEXECNAME)
395 return getexecname();
398 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
400 #endif /* HAVE_GETPROGNAME */
402 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
403 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
405 static void swrap_log(enum swrap_dbglvl_e dbglvl,
407 const char *format, ...)
412 unsigned int lvl = 0;
413 const char *prefix = "SWRAP";
414 const char *progname = getprogname();
416 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
425 va_start(va, format);
426 vsnprintf(buffer, sizeof(buffer), format, va);
430 case SWRAP_LOG_ERROR:
431 prefix = "SWRAP_ERROR";
434 prefix = "SWRAP_WARN";
436 case SWRAP_LOG_DEBUG:
437 prefix = "SWRAP_DEBUG";
439 case SWRAP_LOG_TRACE:
440 prefix = "SWRAP_TRACE";
444 if (progname == NULL) {
445 progname = "<unknown>";
449 "%s[%s (%u)] - %s: %s\n",
452 (unsigned int)getpid(),
457 /*********************************************************
458 * SWRAP LOADING LIBC FUNCTIONS
459 *********************************************************/
464 typedef int (*__libc_accept4)(int sockfd,
465 struct sockaddr *addr,
469 typedef int (*__libc_accept)(int sockfd,
470 struct sockaddr *addr,
473 typedef int (*__libc_bind)(int sockfd,
474 const struct sockaddr *addr,
476 typedef int (*__libc_close)(int fd);
477 typedef int (*__libc_connect)(int sockfd,
478 const struct sockaddr *addr,
480 typedef int (*__libc_dup)(int fd);
481 typedef int (*__libc_dup2)(int oldfd, int newfd);
482 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
483 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
485 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
488 typedef int (*__libc_eventfd)(int count, int flags);
490 typedef int (*__libc_getpeername)(int sockfd,
491 struct sockaddr *addr,
493 typedef int (*__libc_getsockname)(int sockfd,
494 struct sockaddr *addr,
496 typedef int (*__libc_getsockopt)(int sockfd,
501 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
502 typedef int (*__libc_listen)(int sockfd, int backlog);
503 typedef int (*__libc_open)(const char *pathname, int flags, ...);
505 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
506 #endif /* HAVE_OPEN64 */
507 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
508 typedef int (*__libc_pipe)(int pipefd[2]);
509 typedef int (*__libc_read)(int fd, void *buf, size_t count);
510 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
511 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
512 typedef int (*__libc_recvfrom)(int sockfd,
516 struct sockaddr *src_addr,
518 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
519 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
520 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
521 typedef int (*__libc_sendto)(int sockfd,
525 const struct sockaddr *dst_addr,
527 typedef int (*__libc_setsockopt)(int sockfd,
533 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
535 typedef int (*__libc_socket)(int domain, int type, int protocol);
536 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
537 #ifdef HAVE_TIMERFD_CREATE
538 typedef int (*__libc_timerfd_create)(int clockid, int flags);
540 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
541 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
543 #define SWRAP_SYMBOL_ENTRY(i) \
549 struct swrap_libc_symbols {
551 SWRAP_SYMBOL_ENTRY(accept4);
553 SWRAP_SYMBOL_ENTRY(accept);
555 SWRAP_SYMBOL_ENTRY(bind);
556 SWRAP_SYMBOL_ENTRY(close);
557 SWRAP_SYMBOL_ENTRY(connect);
558 SWRAP_SYMBOL_ENTRY(dup);
559 SWRAP_SYMBOL_ENTRY(dup2);
560 SWRAP_SYMBOL_ENTRY(fcntl);
561 SWRAP_SYMBOL_ENTRY(fopen);
563 SWRAP_SYMBOL_ENTRY(fopen64);
566 SWRAP_SYMBOL_ENTRY(eventfd);
568 SWRAP_SYMBOL_ENTRY(getpeername);
569 SWRAP_SYMBOL_ENTRY(getsockname);
570 SWRAP_SYMBOL_ENTRY(getsockopt);
571 SWRAP_SYMBOL_ENTRY(ioctl);
572 SWRAP_SYMBOL_ENTRY(listen);
573 SWRAP_SYMBOL_ENTRY(open);
575 SWRAP_SYMBOL_ENTRY(open64);
577 SWRAP_SYMBOL_ENTRY(openat);
578 SWRAP_SYMBOL_ENTRY(pipe);
579 SWRAP_SYMBOL_ENTRY(read);
580 SWRAP_SYMBOL_ENTRY(readv);
581 SWRAP_SYMBOL_ENTRY(recv);
582 SWRAP_SYMBOL_ENTRY(recvfrom);
583 SWRAP_SYMBOL_ENTRY(recvmsg);
584 SWRAP_SYMBOL_ENTRY(send);
585 SWRAP_SYMBOL_ENTRY(sendmsg);
586 SWRAP_SYMBOL_ENTRY(sendto);
587 SWRAP_SYMBOL_ENTRY(setsockopt);
589 SWRAP_SYMBOL_ENTRY(signalfd);
591 SWRAP_SYMBOL_ENTRY(socket);
592 SWRAP_SYMBOL_ENTRY(socketpair);
593 #ifdef HAVE_TIMERFD_CREATE
594 SWRAP_SYMBOL_ENTRY(timerfd_create);
596 SWRAP_SYMBOL_ENTRY(write);
597 SWRAP_SYMBOL_ENTRY(writev);
604 struct swrap_libc_symbols symbols;
608 static struct swrap swrap;
611 static char *socket_wrapper_dir(void);
613 #define LIBC_NAME "libc.so"
620 static const char *swrap_str_lib(enum swrap_lib lib)
625 case SWRAP_LIBSOCKET:
629 /* Compiler would warn us about unhandled enum value if we get here */
633 static void *swrap_load_lib_handle(enum swrap_lib lib)
635 int flags = RTLD_LAZY;
640 const char *env_preload = getenv("LD_PRELOAD");
641 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
642 bool enable_deepbind = true;
644 /* Don't do a deepbind if we run with libasan */
645 if (env_preload != NULL && strlen(env_preload) < 1024) {
646 const char *p = strstr(env_preload, "libasan.so");
648 enable_deepbind = false;
652 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
653 enable_deepbind = false;
656 if (enable_deepbind) {
657 flags |= RTLD_DEEPBIND;
662 case SWRAP_LIBSOCKET:
663 #ifdef HAVE_LIBSOCKET
664 handle = swrap.libc.socket_handle;
665 if (handle == NULL) {
666 for (i = 10; i >= 0; i--) {
667 char soname[256] = {0};
669 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
670 handle = dlopen(soname, flags);
671 if (handle != NULL) {
676 swrap.libc.socket_handle = handle;
681 handle = swrap.libc.handle;
683 if (handle == NULL) {
684 handle = dlopen(LIBC_SO, flags);
686 swrap.libc.handle = handle;
689 if (handle == NULL) {
690 for (i = 10; i >= 0; i--) {
691 char soname[256] = {0};
693 snprintf(soname, sizeof(soname), "libc.so.%d", i);
694 handle = dlopen(soname, flags);
695 if (handle != NULL) {
700 swrap.libc.handle = handle;
705 if (handle == NULL) {
707 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
709 SWRAP_LOG(SWRAP_LOG_ERROR,
710 "Failed to dlopen library: %s",
719 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
724 handle = swrap_load_lib_handle(lib);
726 func = dlsym(handle, fn_name);
728 SWRAP_LOG(SWRAP_LOG_ERROR,
729 "Failed to find %s: %s",
735 SWRAP_LOG(SWRAP_LOG_TRACE,
743 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
744 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
748 ret = pthread_mutex_lock(mutex);
750 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
751 getpid(), getppid(), caller, line, name, strerror(ret));
755 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
756 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
760 ret = pthread_mutex_unlock(mutex);
762 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
763 getpid(), getppid(), caller, line, name, strerror(ret));
768 * These macros have a thread race condition on purpose!
770 * This is an optimization to avoid locking each time we check if the symbol is
773 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
774 swrap.libc.symbols._libc_##sym_name.obj = \
775 _swrap_bind_symbol(lib, #sym_name); \
778 #define swrap_bind_symbol_libc(sym_name) \
779 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
781 #define swrap_bind_symbol_libsocket(sym_name) \
782 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
784 static void swrap_bind_symbol_all(void);
786 /****************************************************************************
788 ****************************************************************************
790 * Functions especially from libc need to be loaded individually, you can't
791 * load all at once or gdb will segfault at startup. The same applies to
792 * valgrind and has probably something todo with with the linker. So we need
793 * load each function at the point it is called the first time.
795 ****************************************************************************/
798 static int libc_accept4(int sockfd,
799 struct sockaddr *addr,
803 swrap_bind_symbol_all();
805 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
808 #else /* HAVE_ACCEPT4 */
810 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
812 swrap_bind_symbol_all();
814 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
816 #endif /* HAVE_ACCEPT4 */
818 static int libc_bind(int sockfd,
819 const struct sockaddr *addr,
822 swrap_bind_symbol_all();
824 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
827 static int libc_close(int fd)
829 swrap_bind_symbol_all();
831 return swrap.libc.symbols._libc_close.f(fd);
834 static int libc_connect(int sockfd,
835 const struct sockaddr *addr,
838 swrap_bind_symbol_all();
840 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
843 static int libc_dup(int fd)
845 swrap_bind_symbol_all();
847 return swrap.libc.symbols._libc_dup.f(fd);
850 static int libc_dup2(int oldfd, int newfd)
852 swrap_bind_symbol_all();
854 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
858 static int libc_eventfd(int count, int flags)
860 swrap_bind_symbol_all();
862 return swrap.libc.symbols._libc_eventfd.f(count, flags);
866 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
867 static int libc_vfcntl(int fd, int cmd, va_list ap)
872 swrap_bind_symbol_all();
874 arg = va_arg(ap, void *);
876 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
881 static int libc_getpeername(int sockfd,
882 struct sockaddr *addr,
885 swrap_bind_symbol_all();
887 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
890 static int libc_getsockname(int sockfd,
891 struct sockaddr *addr,
894 swrap_bind_symbol_all();
896 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
899 static int libc_getsockopt(int sockfd,
905 swrap_bind_symbol_all();
907 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
914 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
915 static int libc_vioctl(int d, unsigned long int request, va_list ap)
920 swrap_bind_symbol_all();
922 arg = va_arg(ap, void *);
924 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
929 static int libc_listen(int sockfd, int backlog)
931 swrap_bind_symbol_all();
933 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
936 static FILE *libc_fopen(const char *name, const char *mode)
938 swrap_bind_symbol_all();
940 return swrap.libc.symbols._libc_fopen.f(name, mode);
944 static FILE *libc_fopen64(const char *name, const char *mode)
946 swrap_bind_symbol_all();
948 return swrap.libc.symbols._libc_fopen64.f(name, mode);
950 #endif /* HAVE_FOPEN64 */
952 static int libc_vopen(const char *pathname, int flags, va_list ap)
957 swrap_bind_symbol_all();
959 if (flags & O_CREAT) {
960 mode = va_arg(ap, int);
962 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
967 static int libc_open(const char *pathname, int flags, ...)
973 fd = libc_vopen(pathname, flags, ap);
980 static int libc_vopen64(const char *pathname, int flags, va_list ap)
985 swrap_bind_symbol_all();
987 if (flags & O_CREAT) {
988 mode = va_arg(ap, int);
990 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
994 #endif /* HAVE_OPEN64 */
996 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1001 swrap_bind_symbol_all();
1003 if (flags & O_CREAT) {
1004 mode = va_arg(ap, int);
1006 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1015 static int libc_openat(int dirfd, const char *path, int flags, ...)
1020 va_start(ap, flags);
1021 fd = libc_vopenat(dirfd, path, flags, ap);
1028 static int libc_pipe(int pipefd[2])
1030 swrap_bind_symbol_all();
1032 return swrap.libc.symbols._libc_pipe.f(pipefd);
1035 static int libc_read(int fd, void *buf, size_t count)
1037 swrap_bind_symbol_all();
1039 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1042 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1044 swrap_bind_symbol_all();
1046 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1049 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1051 swrap_bind_symbol_all();
1053 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1056 static int libc_recvfrom(int sockfd,
1060 struct sockaddr *src_addr,
1063 swrap_bind_symbol_all();
1065 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1073 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1075 swrap_bind_symbol_all();
1077 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1080 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1082 swrap_bind_symbol_all();
1084 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1087 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1089 swrap_bind_symbol_all();
1091 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1094 static int libc_sendto(int sockfd,
1098 const struct sockaddr *dst_addr,
1101 swrap_bind_symbol_all();
1103 return swrap.libc.symbols._libc_sendto.f(sockfd,
1111 static int libc_setsockopt(int sockfd,
1117 swrap_bind_symbol_all();
1119 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1126 #ifdef HAVE_SIGNALFD
1127 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1129 swrap_bind_symbol_all();
1131 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1135 static int libc_socket(int domain, int type, int protocol)
1137 swrap_bind_symbol_all();
1139 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1142 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1144 swrap_bind_symbol_all();
1146 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1149 #ifdef HAVE_TIMERFD_CREATE
1150 static int libc_timerfd_create(int clockid, int flags)
1152 swrap_bind_symbol_all();
1154 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1158 static ssize_t libc_write(int fd, const void *buf, size_t count)
1160 swrap_bind_symbol_all();
1162 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1165 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1167 swrap_bind_symbol_all();
1169 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1172 /* DO NOT call this function during library initialization! */
1173 static void __swrap_bind_symbol_all_once(void)
1176 swrap_bind_symbol_libsocket(accept4);
1178 swrap_bind_symbol_libsocket(accept);
1180 swrap_bind_symbol_libsocket(bind);
1181 swrap_bind_symbol_libc(close);
1182 swrap_bind_symbol_libsocket(connect);
1183 swrap_bind_symbol_libc(dup);
1184 swrap_bind_symbol_libc(dup2);
1185 swrap_bind_symbol_libc(fcntl);
1186 swrap_bind_symbol_libc(fopen);
1188 swrap_bind_symbol_libc(fopen64);
1191 swrap_bind_symbol_libc(eventfd);
1193 swrap_bind_symbol_libsocket(getpeername);
1194 swrap_bind_symbol_libsocket(getsockname);
1195 swrap_bind_symbol_libsocket(getsockopt);
1196 swrap_bind_symbol_libc(ioctl);
1197 swrap_bind_symbol_libsocket(listen);
1198 swrap_bind_symbol_libc(open);
1200 swrap_bind_symbol_libc(open64);
1202 swrap_bind_symbol_libc(openat);
1203 swrap_bind_symbol_libsocket(pipe);
1204 swrap_bind_symbol_libc(read);
1205 swrap_bind_symbol_libsocket(readv);
1206 swrap_bind_symbol_libsocket(recv);
1207 swrap_bind_symbol_libsocket(recvfrom);
1208 swrap_bind_symbol_libsocket(recvmsg);
1209 swrap_bind_symbol_libsocket(send);
1210 swrap_bind_symbol_libsocket(sendmsg);
1211 swrap_bind_symbol_libsocket(sendto);
1212 swrap_bind_symbol_libsocket(setsockopt);
1213 #ifdef HAVE_SIGNALFD
1214 swrap_bind_symbol_libsocket(signalfd);
1216 swrap_bind_symbol_libsocket(socket);
1217 swrap_bind_symbol_libsocket(socketpair);
1218 #ifdef HAVE_TIMERFD_CREATE
1219 swrap_bind_symbol_libc(timerfd_create);
1221 swrap_bind_symbol_libc(write);
1222 swrap_bind_symbol_libsocket(writev);
1225 static void swrap_bind_symbol_all(void)
1227 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1229 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1232 /*********************************************************
1233 * SWRAP HELPER FUNCTIONS
1234 *********************************************************/
1237 * We return 127.0.0.0 (default) or 10.53.57.0.
1239 * This can be controlled by:
1240 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1242 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1244 static in_addr_t swrap_ipv4_net(void)
1246 static int initialized;
1247 static in_addr_t hv;
1248 const char *net_str = NULL;
1257 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1258 if (net_str == NULL) {
1259 net_str = "127.0.0.0";
1262 ret = inet_pton(AF_INET, net_str, &nv);
1264 SWRAP_LOG(SWRAP_LOG_ERROR,
1265 "INVALID IPv4 Network [%s]",
1270 hv = ntohl(nv.s_addr);
1280 SWRAP_LOG(SWRAP_LOG_ERROR,
1281 "INVALID IPv4 Network [%s][0x%x] should be "
1282 "127.0.0.0 or 10.53.57.0",
1283 net_str, (unsigned)hv);
1291 * This returns 127.255.255.255 or 10.255.255.255
1293 static in_addr_t swrap_ipv4_bcast(void)
1297 hv = swrap_ipv4_net();
1298 hv |= IN_CLASSA_HOST;
1304 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1306 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1310 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1311 SWRAP_LOG(SWRAP_LOG_ERROR,
1312 "swrap_ipv4_iface(%u) invalid!",
1318 hv = swrap_ipv4_net();
1328 static const struct in6_addr *swrap_ipv6(void)
1330 static struct in6_addr v;
1331 static int initialized;
1339 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1348 static void set_port(int family, int prt, struct swrap_address *addr)
1352 addr->sa.in.sin_port = htons(prt);
1356 addr->sa.in6.sin6_port = htons(prt);
1362 static size_t socket_length(int family)
1366 return sizeof(struct sockaddr_in);
1369 return sizeof(struct sockaddr_in6);
1375 static struct socket_info *swrap_get_socket_info(int si_index)
1377 return (struct socket_info *)(&(sockets[si_index].info));
1380 static int swrap_get_refcount(struct socket_info *si)
1382 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1383 return sic->meta.refcount;
1386 static void swrap_inc_refcount(struct socket_info *si)
1388 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1390 sic->meta.refcount += 1;
1393 static void swrap_dec_refcount(struct socket_info *si)
1395 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1397 sic->meta.refcount -= 1;
1400 static int swrap_get_next_free(struct socket_info *si)
1402 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1404 return sic->meta.next_free;
1407 static void swrap_set_next_free(struct socket_info *si, int next_free)
1409 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1411 sic->meta.next_free = next_free;
1414 static int swrap_un_path(struct sockaddr_un *un,
1415 const char *swrap_dir,
1422 ret = snprintf(un->sun_path,
1423 sizeof(un->sun_path),
1429 if ((size_t)ret >= sizeof(un->sun_path)) {
1430 return ENAMETOOLONG;
1436 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1437 const char *swrap_dir)
1441 ret = snprintf(un->sun_path,
1442 sizeof(un->sun_path),
1446 if ((size_t)ret >= sizeof(un->sun_path)) {
1447 return ENAMETOOLONG;
1453 static bool swrap_dir_usable(const char *swrap_dir)
1455 struct sockaddr_un un;
1458 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1463 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1471 static char *socket_wrapper_dir(void)
1473 char *swrap_dir = NULL;
1474 char *s = getenv("SOCKET_WRAPPER_DIR");
1478 if (s == NULL || s[0] == '\0') {
1479 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1483 swrap_dir = realpath(s, NULL);
1484 if (swrap_dir == NULL) {
1485 SWRAP_LOG(SWRAP_LOG_ERROR,
1486 "Unable to resolve socket_wrapper dir path: %s - %s",
1492 ok = swrap_dir_usable(swrap_dir);
1499 ok = swrap_dir_usable(s);
1501 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1505 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1507 SWRAP_LOG(SWRAP_LOG_ERROR,
1508 "realpath(SOCKET_WRAPPER_DIR) too long and "
1509 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1514 swrap_dir = strdup(s);
1515 if (swrap_dir == NULL) {
1516 SWRAP_LOG(SWRAP_LOG_ERROR,
1517 "Unable to duplicate socket_wrapper dir path");
1521 SWRAP_LOG(SWRAP_LOG_WARN,
1522 "realpath(SOCKET_WRAPPER_DIR) too long, "
1523 "using original SOCKET_WRAPPER_DIR\n");
1526 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1530 static unsigned int socket_wrapper_mtu(void)
1532 static unsigned int max_mtu = 0;
1537 swrap_mutex_lock(&mtu_update_mutex);
1543 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1545 s = getenv("SOCKET_WRAPPER_MTU");
1550 tmp = strtol(s, &endp, 10);
1555 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1561 swrap_mutex_unlock(&mtu_update_mutex);
1565 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1567 pthread_mutexattr_t ma;
1568 bool need_destroy = false;
1571 #define __CHECK(cmd) do { \
1574 SWRAP_LOG(SWRAP_LOG_ERROR, \
1575 "%s: %s - failed %d", \
1581 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1582 __CHECK(pthread_mutexattr_init(&ma));
1583 need_destroy = true;
1584 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1585 __CHECK(pthread_mutex_init(m, &ma));
1588 pthread_mutexattr_destroy(&ma);
1593 static size_t socket_wrapper_max_sockets(void)
1599 if (socket_info_max != 0) {
1600 return socket_info_max;
1603 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1605 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1606 if (s == NULL || s[0] == '\0') {
1610 tmp = strtoul(s, &endp, 10);
1615 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1616 SWRAP_LOG(SWRAP_LOG_ERROR,
1617 "Invalid number of sockets specified, "
1618 "using default (%zu)",
1622 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1623 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1624 SWRAP_LOG(SWRAP_LOG_ERROR,
1625 "Invalid number of sockets specified, "
1626 "using maximum (%zu).",
1630 socket_info_max = tmp;
1633 return socket_info_max;
1636 static void socket_wrapper_init_fds_idx(void)
1641 if (socket_fds_idx != NULL) {
1645 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1647 SWRAP_LOG(SWRAP_LOG_ERROR,
1648 "Failed to allocate socket fds index array: %s",
1653 for (i = 0; i < socket_fds_max; i++) {
1657 socket_fds_idx = tmp;
1660 static void socket_wrapper_init_sockets(void)
1666 swrap_bind_symbol_all();
1668 swrap_mutex_lock(&sockets_mutex);
1670 if (sockets != NULL) {
1671 swrap_mutex_unlock(&sockets_mutex);
1675 SWRAP_LOG(SWRAP_LOG_DEBUG,
1676 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1677 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1680 * Intialize the static cache early before
1681 * any thread is able to start.
1683 (void)swrap_ipv4_net();
1685 socket_wrapper_init_fds_idx();
1687 /* Needs to be called inside the sockets_mutex lock here. */
1688 max_sockets = socket_wrapper_max_sockets();
1690 sockets = (struct socket_info_container *)calloc(max_sockets,
1691 sizeof(struct socket_info_container));
1693 if (sockets == NULL) {
1694 SWRAP_LOG(SWRAP_LOG_ERROR,
1695 "Failed to allocate sockets array: %s",
1697 swrap_mutex_unlock(&sockets_mutex);
1701 swrap_mutex_lock(&first_free_mutex);
1705 for (i = 0; i < max_sockets; i++) {
1706 swrap_set_next_free(&sockets[i].info, i+1);
1707 sockets[i].meta.mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1710 for (i = 0; i < max_sockets; i++) {
1711 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1713 SWRAP_LOG(SWRAP_LOG_ERROR,
1714 "Failed to initialize pthread mutex i=%zu", i);
1719 /* mark the end of the free list */
1720 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1723 swrap_mutex_unlock(&first_free_mutex);
1724 swrap_mutex_unlock(&sockets_mutex);
1730 bool socket_wrapper_enabled(void)
1732 char *s = socket_wrapper_dir();
1740 socket_wrapper_init_sockets();
1745 static unsigned int socket_wrapper_default_iface(void)
1747 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1750 if (sscanf(s, "%u", &iface) == 1) {
1751 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1757 return 1;/* 127.0.0.1 */
1760 static void set_socket_info_index(int fd, int idx)
1762 SWRAP_LOG(SWRAP_LOG_TRACE,
1765 socket_fds_idx[fd] = idx;
1766 /* This builtin issues a full memory barrier. */
1767 __sync_synchronize();
1770 static void reset_socket_info_index(int fd)
1772 SWRAP_LOG(SWRAP_LOG_TRACE,
1775 set_socket_info_index(fd, -1);
1778 static int find_socket_info_index(int fd)
1784 if (socket_fds_idx == NULL) {
1788 if ((size_t)fd >= socket_fds_max) {
1790 * Do not add a log here as some applications do stupid things
1793 * for (fd = 0; fd <= getdtablesize(); fd++) {
1797 * This would produce millions of lines of debug messages.
1800 SWRAP_LOG(SWRAP_LOG_ERROR,
1801 "Looking for a socket info for the fd %d is over the "
1802 "max socket index limit of %zu.",
1809 /* This builtin issues a full memory barrier. */
1810 __sync_synchronize();
1811 return socket_fds_idx[fd];
1814 static int swrap_add_socket_info(struct socket_info *si_input)
1816 struct socket_info *si = NULL;
1819 if (si_input == NULL) {
1824 swrap_mutex_lock(&first_free_mutex);
1825 if (first_free == -1) {
1830 si_index = first_free;
1831 si = swrap_get_socket_info(si_index);
1835 first_free = swrap_get_next_free(si);
1837 swrap_inc_refcount(si);
1839 SWRAP_UNLOCK_SI(si);
1842 swrap_mutex_unlock(&first_free_mutex);
1847 static int swrap_create_socket(struct socket_info *si, int fd)
1851 if ((size_t)fd >= socket_fds_max) {
1852 SWRAP_LOG(SWRAP_LOG_ERROR,
1853 "The max socket index limit of %zu has been reached, "
1860 idx = swrap_add_socket_info(si);
1865 set_socket_info_index(fd, idx);
1870 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1877 p = strrchr(un->sun_path, '/');
1878 if (p) p++; else p = un->sun_path;
1880 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1885 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1888 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1899 case SOCKET_TYPE_CHAR_TCP:
1900 case SOCKET_TYPE_CHAR_UDP: {
1901 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1903 if ((*len) < sizeof(*in2)) {
1908 memset(in2, 0, sizeof(*in2));
1909 in2->sin_family = AF_INET;
1910 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1911 in2->sin_port = htons(prt);
1913 *len = sizeof(*in2);
1917 case SOCKET_TYPE_CHAR_TCP_V6:
1918 case SOCKET_TYPE_CHAR_UDP_V6: {
1919 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1921 if ((*len) < sizeof(*in2)) {
1926 memset(in2, 0, sizeof(*in2));
1927 in2->sin6_family = AF_INET6;
1928 in2->sin6_addr = *swrap_ipv6();
1929 in2->sin6_addr.s6_addr[15] = iface;
1930 in2->sin6_port = htons(prt);
1932 *len = sizeof(*in2);
1944 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1951 char *swrap_dir = NULL;
1953 if (bcast) *bcast = 0;
1955 switch (inaddr->sa_family) {
1957 const struct sockaddr_in *in =
1958 (const struct sockaddr_in *)(const void *)inaddr;
1959 unsigned int addr = ntohl(in->sin_addr.s_addr);
1963 const unsigned int sw_net_addr = swrap_ipv4_net();
1964 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1968 u_type = SOCKET_TYPE_CHAR_TCP;
1971 u_type = SOCKET_TYPE_CHAR_UDP;
1972 a_type = SOCKET_TYPE_CHAR_UDP;
1973 b_type = SOCKET_TYPE_CHAR_UDP;
1976 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1977 errno = ESOCKTNOSUPPORT;
1981 prt = ntohs(in->sin_port);
1982 if (a_type && addr == 0xFFFFFFFF) {
1983 /* 255.255.255.255 only udp */
1986 iface = socket_wrapper_default_iface();
1987 } else if (b_type && addr == sw_bcast_addr) {
1996 iface = socket_wrapper_default_iface();
1997 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
1998 /* 127.0.0.X or 10.53.57.X */
2001 iface = (addr & 0x000000FF);
2003 errno = ENETUNREACH;
2006 if (bcast) *bcast = is_bcast;
2011 const struct sockaddr_in6 *in =
2012 (const struct sockaddr_in6 *)(const void *)inaddr;
2013 struct in6_addr cmp1, cmp2;
2017 type = SOCKET_TYPE_CHAR_TCP_V6;
2020 type = SOCKET_TYPE_CHAR_UDP_V6;
2023 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2024 errno = ESOCKTNOSUPPORT;
2028 /* XXX no multicast/broadcast */
2030 prt = ntohs(in->sin6_port);
2032 cmp1 = *swrap_ipv6();
2033 cmp2 = in->sin6_addr;
2034 cmp2.s6_addr[15] = 0;
2035 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2036 iface = in->sin6_addr.s6_addr[15];
2038 errno = ENETUNREACH;
2046 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2047 errno = ENETUNREACH;
2052 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2057 swrap_dir = socket_wrapper_dir();
2058 if (swrap_dir == NULL) {
2064 swrap_un_path_EINVAL(un, swrap_dir);
2065 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2066 SAFE_FREE(swrap_dir);
2067 /* the caller need to do more processing */
2071 swrap_un_path(un, swrap_dir, type, iface, prt);
2072 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2074 SAFE_FREE(swrap_dir);
2079 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2087 char *swrap_dir = NULL;
2089 if (bcast) *bcast = 0;
2091 switch (si->family) {
2093 const struct sockaddr_in *in =
2094 (const struct sockaddr_in *)(const void *)inaddr;
2095 unsigned int addr = ntohl(in->sin_addr.s_addr);
2100 const unsigned int sw_net_addr = swrap_ipv4_net();
2101 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2103 prt = ntohs(in->sin_port);
2107 u_type = SOCKET_TYPE_CHAR_TCP;
2108 d_type = SOCKET_TYPE_CHAR_TCP;
2111 u_type = SOCKET_TYPE_CHAR_UDP;
2112 d_type = SOCKET_TYPE_CHAR_UDP;
2113 a_type = SOCKET_TYPE_CHAR_UDP;
2114 b_type = SOCKET_TYPE_CHAR_UDP;
2117 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2118 errno = ESOCKTNOSUPPORT;
2126 iface = socket_wrapper_default_iface();
2127 } else if (a_type && addr == 0xFFFFFFFF) {
2128 /* 255.255.255.255 only udp */
2131 iface = socket_wrapper_default_iface();
2132 } else if (b_type && addr == sw_bcast_addr) {
2133 /* 127.255.255.255 only udp */
2136 iface = socket_wrapper_default_iface();
2137 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2141 iface = (addr & 0x000000FF);
2143 errno = EADDRNOTAVAIL;
2147 /* Store the bind address for connect() */
2148 if (si->bindname.sa_socklen == 0) {
2149 struct sockaddr_in bind_in;
2150 socklen_t blen = sizeof(struct sockaddr_in);
2152 ZERO_STRUCT(bind_in);
2153 bind_in.sin_family = in->sin_family;
2154 bind_in.sin_port = in->sin_port;
2155 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2156 si->bindname.sa_socklen = blen;
2157 memcpy(&si->bindname.sa.in, &bind_in, blen);
2164 const struct sockaddr_in6 *in =
2165 (const struct sockaddr_in6 *)(const void *)inaddr;
2166 struct in6_addr cmp1, cmp2;
2170 type = SOCKET_TYPE_CHAR_TCP_V6;
2173 type = SOCKET_TYPE_CHAR_UDP_V6;
2176 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2177 errno = ESOCKTNOSUPPORT;
2181 /* XXX no multicast/broadcast */
2183 prt = ntohs(in->sin6_port);
2185 cmp1 = *swrap_ipv6();
2186 cmp2 = in->sin6_addr;
2187 cmp2.s6_addr[15] = 0;
2188 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2189 iface = socket_wrapper_default_iface();
2190 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2191 iface = in->sin6_addr.s6_addr[15];
2193 errno = EADDRNOTAVAIL;
2197 /* Store the bind address for connect() */
2198 if (si->bindname.sa_socklen == 0) {
2199 struct sockaddr_in6 bind_in;
2200 socklen_t blen = sizeof(struct sockaddr_in6);
2202 ZERO_STRUCT(bind_in);
2203 bind_in.sin6_family = in->sin6_family;
2204 bind_in.sin6_port = in->sin6_port;
2206 bind_in.sin6_addr = *swrap_ipv6();
2207 bind_in.sin6_addr.s6_addr[15] = iface;
2209 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2210 si->bindname.sa_socklen = blen;
2217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2218 errno = EADDRNOTAVAIL;
2223 if (bcast) *bcast = is_bcast;
2225 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2230 swrap_dir = socket_wrapper_dir();
2231 if (swrap_dir == NULL) {
2237 /* handle auto-allocation of ephemeral ports */
2238 for (prt = 5001; prt < 10000; prt++) {
2239 swrap_un_path(un, swrap_dir, type, iface, prt);
2240 if (stat(un->sun_path, &st) == 0) continue;
2242 set_port(si->family, prt, &si->myname);
2243 set_port(si->family, prt, &si->bindname);
2250 SAFE_FREE(swrap_dir);
2255 swrap_un_path(un, swrap_dir, type, iface, prt);
2256 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2258 SAFE_FREE(swrap_dir);
2263 static struct socket_info *find_socket_info(int fd)
2265 int idx = find_socket_info_index(fd);
2271 return swrap_get_socket_info(idx);
2275 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2277 struct socket_info_fd *f;
2278 const struct socket_info *last_s = NULL;
2280 /* first catch invalid input */
2281 switch (sa->sa_family) {
2283 if (len < sizeof(struct sockaddr_in)) {
2289 if (len < sizeof(struct sockaddr_in6)) {
2299 for (f = socket_fds; f; f = f->next) {
2300 struct socket_info *s = swrap_get_socket_info(f->si_index);
2307 if (s->myname == NULL) {
2310 if (s->myname->sa_family != sa->sa_family) {
2313 switch (s->myname->sa_family) {
2315 struct sockaddr_in *sin1, *sin2;
2317 sin1 = (struct sockaddr_in *)s->myname;
2318 sin2 = (struct sockaddr_in *)sa;
2320 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2323 if (sin1->sin_port != sin2->sin_port) {
2326 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2336 struct sockaddr_in6 *sin1, *sin2;
2338 sin1 = (struct sockaddr_in6 *)s->myname;
2339 sin2 = (struct sockaddr_in6 *)sa;
2341 if (sin1->sin6_port != sin2->sin6_port) {
2344 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2366 static void swrap_remove_stale(int fd)
2368 struct socket_info *si;
2371 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2373 swrap_mutex_lock(&socket_reset_mutex);
2375 si_index = find_socket_info_index(fd);
2376 if (si_index == -1) {
2377 swrap_mutex_unlock(&socket_reset_mutex);
2381 reset_socket_info_index(fd);
2383 si = swrap_get_socket_info(si_index);
2385 swrap_mutex_lock(&first_free_mutex);
2388 swrap_dec_refcount(si);
2390 if (swrap_get_refcount(si) > 0) {
2394 if (si->un_addr.sun_path[0] != '\0') {
2395 unlink(si->un_addr.sun_path);
2398 swrap_set_next_free(si, first_free);
2399 first_free = si_index;
2402 SWRAP_UNLOCK_SI(si);
2403 swrap_mutex_unlock(&first_free_mutex);
2404 swrap_mutex_unlock(&socket_reset_mutex);
2407 static int sockaddr_convert_to_un(struct socket_info *si,
2408 const struct sockaddr *in_addr,
2410 struct sockaddr_un *out_addr,
2414 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2416 (void) in_len; /* unused */
2418 if (out_addr == NULL) {
2422 out->sa_family = AF_UNIX;
2423 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2424 out->sa_len = sizeof(*out_addr);
2427 switch (in_addr->sa_family) {
2429 const struct sockaddr_in *sin;
2430 if (si->family != AF_INET) {
2433 if (in_len < sizeof(struct sockaddr_in)) {
2436 sin = (const struct sockaddr_in *)(const void *)in_addr;
2437 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2442 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2443 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2457 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2458 errno = ESOCKTNOSUPPORT;
2462 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2464 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2470 errno = EAFNOSUPPORT;
2471 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2475 static int sockaddr_convert_from_un(const struct socket_info *si,
2476 const struct sockaddr_un *in_addr,
2477 socklen_t un_addrlen,
2479 struct sockaddr *out_addr,
2480 socklen_t *out_addrlen)
2484 if (out_addr == NULL || out_addrlen == NULL)
2487 if (un_addrlen == 0) {
2502 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2503 errno = ESOCKTNOSUPPORT;
2506 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2507 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2508 out_addr->sa_len = *out_addrlen;
2515 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2516 errno = EAFNOSUPPORT;
2520 enum swrap_packet_type {
2522 SWRAP_CONNECT_UNREACH,
2530 SWRAP_SENDTO_UNREACH,
2541 struct swrap_file_hdr {
2543 uint16_t version_major;
2544 uint16_t version_minor;
2547 uint32_t frame_max_len;
2548 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2551 #define SWRAP_FILE_HDR_SIZE 24
2553 struct swrap_packet_frame {
2555 uint32_t micro_seconds;
2556 uint32_t recorded_length;
2557 uint32_t full_length;
2559 #define SWRAP_PACKET_FRAME_SIZE 16
2561 union swrap_packet_ip {
2565 uint16_t packet_length;
2566 uint16_t identification;
2571 uint16_t hdr_checksum;
2575 #define SWRAP_PACKET_IP_V4_SIZE 20
2578 uint8_t flow_label_high;
2579 uint16_t flow_label_low;
2580 uint16_t payload_length;
2581 uint8_t next_header;
2583 uint8_t src_addr[16];
2584 uint8_t dest_addr[16];
2586 #define SWRAP_PACKET_IP_V6_SIZE 40
2588 #define SWRAP_PACKET_IP_SIZE 40
2590 union swrap_packet_payload {
2592 uint16_t source_port;
2602 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2604 uint16_t source_port;
2609 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2616 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2623 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2625 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2627 #define SWRAP_PACKET_MIN_ALLOC \
2628 (SWRAP_PACKET_FRAME_SIZE + \
2629 SWRAP_PACKET_IP_SIZE + \
2630 SWRAP_PACKET_PAYLOAD_SIZE)
2632 static const char *swrap_pcap_init_file(void)
2634 static int initialized = 0;
2635 static const char *s = NULL;
2636 static const struct swrap_file_hdr h;
2637 static const struct swrap_packet_frame f;
2638 static const union swrap_packet_ip i;
2639 static const union swrap_packet_payload p;
2641 if (initialized == 1) {
2647 * TODO: don't use the structs use plain buffer offsets
2648 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2650 * for now make sure we disable PCAP support
2651 * if the struct has alignment!
2653 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2656 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2659 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2662 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2665 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2668 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2671 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2674 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2677 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2680 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2684 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2688 if (strncmp(s, "./", 2) == 0) {
2691 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2695 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2696 const struct sockaddr *src,
2697 const struct sockaddr *dest,
2699 const uint8_t *payload,
2701 unsigned long tcp_seqno,
2702 unsigned long tcp_ack,
2703 unsigned char tcp_ctl,
2705 size_t *_packet_len)
2707 uint8_t *base = NULL;
2708 uint8_t *buf = NULL;
2711 struct swrap_packet_frame *frame;
2715 union swrap_packet_ip *ip;
2717 union swrap_packet_payload *pay;
2720 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2721 size_t wire_hdr_len = 0;
2722 size_t wire_len = 0;
2723 size_t ip_hdr_len = 0;
2724 size_t icmp_hdr_len = 0;
2725 size_t icmp_truncate_len = 0;
2726 uint8_t protocol = 0, icmp_protocol = 0;
2727 const struct sockaddr_in *src_in = NULL;
2728 const struct sockaddr_in *dest_in = NULL;
2730 const struct sockaddr_in6 *src_in6 = NULL;
2731 const struct sockaddr_in6 *dest_in6 = NULL;
2736 switch (src->sa_family) {
2738 src_in = (const struct sockaddr_in *)(const void *)src;
2739 dest_in = (const struct sockaddr_in *)(const void *)dest;
2740 src_port = src_in->sin_port;
2741 dest_port = dest_in->sin_port;
2742 ip_hdr_len = sizeof(i.ip->v4);
2746 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2747 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2748 src_port = src_in6->sin6_port;
2749 dest_port = dest_in6->sin6_port;
2750 ip_hdr_len = sizeof(i.ip->v6);
2757 switch (socket_type) {
2759 protocol = 0x06; /* TCP */
2760 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2761 wire_len = wire_hdr_len + payload_len;
2765 protocol = 0x11; /* UDP */
2766 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2767 wire_len = wire_hdr_len + payload_len;
2775 icmp_protocol = protocol;
2776 switch (src->sa_family) {
2778 protocol = 0x01; /* ICMPv4 */
2779 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2783 protocol = 0x3A; /* ICMPv6 */
2784 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2788 if (wire_len > 64 ) {
2789 icmp_truncate_len = wire_len - 64;
2791 wire_len += icmp_hdr_len;
2794 packet_len = nonwire_len + wire_len;
2795 alloc_len = packet_len;
2796 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2797 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2800 base = (uint8_t *)calloc(1, alloc_len);
2808 f.frame->seconds = tval->tv_sec;
2809 f.frame->micro_seconds = tval->tv_usec;
2810 f.frame->recorded_length = wire_len - icmp_truncate_len;
2811 f.frame->full_length = wire_len - icmp_truncate_len;
2813 buf += SWRAP_PACKET_FRAME_SIZE;
2816 switch (src->sa_family) {
2818 if (src_in == NULL || dest_in == NULL) {
2823 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2824 i.ip->v4.tos = 0x00;
2825 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2826 i.ip->v4.identification = htons(0xFFFF);
2827 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2828 i.ip->v4.fragment = htons(0x0000);
2829 i.ip->v4.ttl = 0xFF;
2830 i.ip->v4.protocol = protocol;
2831 i.ip->v4.hdr_checksum = htons(0x0000);
2832 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2833 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2834 buf += SWRAP_PACKET_IP_V4_SIZE;
2838 if (src_in6 == NULL || dest_in6 == NULL) {
2843 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2844 i.ip->v6.flow_label_high = 0x00;
2845 i.ip->v6.flow_label_low = 0x0000;
2846 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2847 i.ip->v6.next_header = protocol;
2848 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2849 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2850 buf += SWRAP_PACKET_IP_V6_SIZE;
2856 pay = (union swrap_packet_payload *)(void *)buf;
2857 switch (src->sa_family) {
2859 pay->icmp4.type = 0x03; /* destination unreachable */
2860 pay->icmp4.code = 0x01; /* host unreachable */
2861 pay->icmp4.checksum = htons(0x0000);
2862 pay->icmp4.unused = htonl(0x00000000);
2864 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2866 /* set the ip header in the ICMP payload */
2868 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2869 i.ip->v4.tos = 0x00;
2870 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2871 i.ip->v4.identification = htons(0xFFFF);
2872 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2873 i.ip->v4.fragment = htons(0x0000);
2874 i.ip->v4.ttl = 0xFF;
2875 i.ip->v4.protocol = icmp_protocol;
2876 i.ip->v4.hdr_checksum = htons(0x0000);
2877 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2878 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2880 buf += SWRAP_PACKET_IP_V4_SIZE;
2882 src_port = dest_in->sin_port;
2883 dest_port = src_in->sin_port;
2887 pay->icmp6.type = 0x01; /* destination unreachable */
2888 pay->icmp6.code = 0x03; /* address unreachable */
2889 pay->icmp6.checksum = htons(0x0000);
2890 pay->icmp6.unused = htonl(0x00000000);
2891 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2893 /* set the ip header in the ICMP payload */
2895 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2896 i.ip->v6.flow_label_high = 0x00;
2897 i.ip->v6.flow_label_low = 0x0000;
2898 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2899 i.ip->v6.next_header = protocol;
2900 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2901 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2903 buf += SWRAP_PACKET_IP_V6_SIZE;
2905 src_port = dest_in6->sin6_port;
2906 dest_port = src_in6->sin6_port;
2912 pay = (union swrap_packet_payload *)(void *)buf;
2914 switch (socket_type) {
2916 pay->tcp.source_port = src_port;
2917 pay->tcp.dest_port = dest_port;
2918 pay->tcp.seq_num = htonl(tcp_seqno);
2919 pay->tcp.ack_num = htonl(tcp_ack);
2920 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2921 pay->tcp.control = tcp_ctl;
2922 pay->tcp.window = htons(0x7FFF);
2923 pay->tcp.checksum = htons(0x0000);
2924 pay->tcp.urg = htons(0x0000);
2925 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2930 pay->udp.source_port = src_port;
2931 pay->udp.dest_port = dest_port;
2932 pay->udp.length = htons(8 + payload_len);
2933 pay->udp.checksum = htons(0x0000);
2934 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2939 if (payload && payload_len > 0) {
2940 memcpy(buf, payload, payload_len);
2943 *_packet_len = packet_len - icmp_truncate_len;
2947 static int swrap_pcap_get_fd(const char *fname)
2955 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2957 struct swrap_file_hdr file_hdr;
2958 file_hdr.magic = 0xA1B2C3D4;
2959 file_hdr.version_major = 0x0002;
2960 file_hdr.version_minor = 0x0004;
2961 file_hdr.timezone = 0x00000000;
2962 file_hdr.sigfigs = 0x00000000;
2963 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2964 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2966 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2973 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2978 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2979 const struct sockaddr *addr,
2980 enum swrap_packet_type type,
2981 const void *buf, size_t len,
2984 const struct sockaddr *src_addr;
2985 const struct sockaddr *dest_addr;
2986 unsigned long tcp_seqno = 0;
2987 unsigned long tcp_ack = 0;
2988 unsigned char tcp_ctl = 0;
2989 int unreachable = 0;
2993 switch (si->family) {
3005 case SWRAP_CONNECT_SEND:
3006 if (si->type != SOCK_STREAM) {
3010 src_addr = &si->myname.sa.s;
3013 tcp_seqno = si->io.pck_snd;
3014 tcp_ack = si->io.pck_rcv;
3015 tcp_ctl = 0x02; /* SYN */
3017 si->io.pck_snd += 1;
3021 case SWRAP_CONNECT_RECV:
3022 if (si->type != SOCK_STREAM) {
3026 dest_addr = &si->myname.sa.s;
3029 tcp_seqno = si->io.pck_rcv;
3030 tcp_ack = si->io.pck_snd;
3031 tcp_ctl = 0x12; /** SYN,ACK */
3033 si->io.pck_rcv += 1;
3037 case SWRAP_CONNECT_UNREACH:
3038 if (si->type != SOCK_STREAM) {
3042 dest_addr = &si->myname.sa.s;
3045 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3046 tcp_seqno = si->io.pck_snd - 1;
3047 tcp_ack = si->io.pck_rcv;
3048 tcp_ctl = 0x02; /* SYN */
3053 case SWRAP_CONNECT_ACK:
3054 if (si->type != SOCK_STREAM) {
3058 src_addr = &si->myname.sa.s;
3061 tcp_seqno = si->io.pck_snd;
3062 tcp_ack = si->io.pck_rcv;
3063 tcp_ctl = 0x10; /* ACK */
3067 case SWRAP_ACCEPT_SEND:
3068 if (si->type != SOCK_STREAM) {
3072 dest_addr = &si->myname.sa.s;
3075 tcp_seqno = si->io.pck_rcv;
3076 tcp_ack = si->io.pck_snd;
3077 tcp_ctl = 0x02; /* SYN */
3079 si->io.pck_rcv += 1;
3083 case SWRAP_ACCEPT_RECV:
3084 if (si->type != SOCK_STREAM) {
3088 src_addr = &si->myname.sa.s;
3091 tcp_seqno = si->io.pck_snd;
3092 tcp_ack = si->io.pck_rcv;
3093 tcp_ctl = 0x12; /* SYN,ACK */
3095 si->io.pck_snd += 1;
3099 case SWRAP_ACCEPT_ACK:
3100 if (si->type != SOCK_STREAM) {
3104 dest_addr = &si->myname.sa.s;
3107 tcp_seqno = si->io.pck_rcv;
3108 tcp_ack = si->io.pck_snd;
3109 tcp_ctl = 0x10; /* ACK */
3114 src_addr = &si->myname.sa.s;
3115 dest_addr = &si->peername.sa.s;
3117 tcp_seqno = si->io.pck_snd;
3118 tcp_ack = si->io.pck_rcv;
3119 tcp_ctl = 0x18; /* PSH,ACK */
3121 si->io.pck_snd += len;
3125 case SWRAP_SEND_RST:
3126 dest_addr = &si->myname.sa.s;
3127 src_addr = &si->peername.sa.s;
3129 if (si->type == SOCK_DGRAM) {
3130 return swrap_pcap_marshall_packet(si,
3132 SWRAP_SENDTO_UNREACH,
3138 tcp_seqno = si->io.pck_rcv;
3139 tcp_ack = si->io.pck_snd;
3140 tcp_ctl = 0x14; /** RST,ACK */
3144 case SWRAP_PENDING_RST:
3145 dest_addr = &si->myname.sa.s;
3146 src_addr = &si->peername.sa.s;
3148 if (si->type == SOCK_DGRAM) {
3152 tcp_seqno = si->io.pck_rcv;
3153 tcp_ack = si->io.pck_snd;
3154 tcp_ctl = 0x14; /* RST,ACK */
3159 dest_addr = &si->myname.sa.s;
3160 src_addr = &si->peername.sa.s;
3162 tcp_seqno = si->io.pck_rcv;
3163 tcp_ack = si->io.pck_snd;
3164 tcp_ctl = 0x18; /* PSH,ACK */
3166 si->io.pck_rcv += len;
3170 case SWRAP_RECV_RST:
3171 dest_addr = &si->myname.sa.s;
3172 src_addr = &si->peername.sa.s;
3174 if (si->type == SOCK_DGRAM) {
3178 tcp_seqno = si->io.pck_rcv;
3179 tcp_ack = si->io.pck_snd;
3180 tcp_ctl = 0x14; /* RST,ACK */
3185 src_addr = &si->myname.sa.s;
3188 si->io.pck_snd += len;
3192 case SWRAP_SENDTO_UNREACH:
3193 dest_addr = &si->myname.sa.s;
3200 case SWRAP_RECVFROM:
3201 dest_addr = &si->myname.sa.s;
3204 si->io.pck_rcv += len;
3208 case SWRAP_CLOSE_SEND:
3209 if (si->type != SOCK_STREAM) {
3213 src_addr = &si->myname.sa.s;
3214 dest_addr = &si->peername.sa.s;
3216 tcp_seqno = si->io.pck_snd;
3217 tcp_ack = si->io.pck_rcv;
3218 tcp_ctl = 0x11; /* FIN, ACK */
3220 si->io.pck_snd += 1;
3224 case SWRAP_CLOSE_RECV:
3225 if (si->type != SOCK_STREAM) {
3229 dest_addr = &si->myname.sa.s;
3230 src_addr = &si->peername.sa.s;
3232 tcp_seqno = si->io.pck_rcv;
3233 tcp_ack = si->io.pck_snd;
3234 tcp_ctl = 0x11; /* FIN,ACK */
3236 si->io.pck_rcv += 1;
3240 case SWRAP_CLOSE_ACK:
3241 if (si->type != SOCK_STREAM) {
3245 src_addr = &si->myname.sa.s;
3246 dest_addr = &si->peername.sa.s;
3248 tcp_seqno = si->io.pck_snd;
3249 tcp_ack = si->io.pck_rcv;
3250 tcp_ctl = 0x10; /* ACK */
3257 swrapGetTimeOfDay(&tv);
3259 return swrap_pcap_packet_init(&tv,
3263 (const uint8_t *)buf,
3272 static void swrap_pcap_dump_packet(struct socket_info *si,
3273 const struct sockaddr *addr,
3274 enum swrap_packet_type type,
3275 const void *buf, size_t len)
3277 const char *file_name;
3279 size_t packet_len = 0;
3282 swrap_mutex_lock(&pcap_dump_mutex);
3284 file_name = swrap_pcap_init_file();
3289 packet = swrap_pcap_marshall_packet(si,
3295 if (packet == NULL) {
3299 fd = swrap_pcap_get_fd(file_name);
3301 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3310 swrap_mutex_unlock(&pcap_dump_mutex);
3313 /****************************************************************************
3315 ***************************************************************************/
3317 #ifdef HAVE_SIGNALFD
3318 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3322 rc = libc_signalfd(fd, mask, flags);
3324 swrap_remove_stale(fd);
3330 int signalfd(int fd, const sigset_t *mask, int flags)
3332 return swrap_signalfd(fd, mask, flags);
3336 /****************************************************************************
3338 ***************************************************************************/
3340 static int swrap_socket(int family, int type, int protocol)
3342 struct socket_info *si = NULL;
3343 struct socket_info _si = { 0 };
3346 int real_type = type;
3349 * Remove possible addition flags passed to socket() so
3350 * do not fail checking the type.
3351 * See https://lwn.net/Articles/281965/
3354 real_type &= ~SOCK_CLOEXEC;
3356 #ifdef SOCK_NONBLOCK
3357 real_type &= ~SOCK_NONBLOCK;
3360 if (!socket_wrapper_enabled()) {
3361 return libc_socket(family, type, protocol);
3372 #endif /* AF_NETLINK */
3375 #endif /* AF_PACKET */
3377 fd = libc_socket(family, type, protocol);
3379 /* Check if we have a stale fd and remove it */
3380 swrap_remove_stale(fd);
3381 SWRAP_LOG(SWRAP_LOG_TRACE,
3382 "Unix socket fd=%d",
3387 errno = EAFNOSUPPORT;
3391 switch (real_type) {
3397 errno = EPROTONOSUPPORT;
3405 if (real_type == SOCK_STREAM) {
3410 if (real_type == SOCK_DGRAM) {
3415 errno = EPROTONOSUPPORT;
3420 * We must call libc_socket with type, from the caller, not the version
3421 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3423 fd = libc_socket(AF_UNIX, type, 0);
3429 /* Check if we have a stale fd and remove it */
3430 swrap_remove_stale(fd);
3433 si->family = family;
3435 /* however, the rest of the socket_wrapper code expects just
3436 * the type, not the flags */
3437 si->type = real_type;
3438 si->protocol = protocol;
3441 * Setup myname so getsockname() can succeed to find out the socket
3444 switch(si->family) {
3446 struct sockaddr_in sin = {
3447 .sin_family = AF_INET,
3450 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3451 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3456 struct sockaddr_in6 sin6 = {
3457 .sin6_family = AF_INET6,
3460 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3461 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3470 ret = swrap_create_socket(si, fd);
3475 SWRAP_LOG(SWRAP_LOG_TRACE,
3476 "Created %s socket for protocol %s, fd=%d",
3477 family == AF_INET ? "IPv4" : "IPv6",
3478 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3484 int socket(int family, int type, int protocol)
3486 return swrap_socket(family, type, protocol);
3489 /****************************************************************************
3491 ***************************************************************************/
3493 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3497 rc = libc_socketpair(family, type, protocol, sv);
3499 swrap_remove_stale(sv[0]);
3500 swrap_remove_stale(sv[1]);
3506 int socketpair(int family, int type, int protocol, int sv[2])
3508 return swrap_socketpair(family, type, protocol, sv);
3511 /****************************************************************************
3513 ***************************************************************************/
3515 #ifdef HAVE_TIMERFD_CREATE
3516 static int swrap_timerfd_create(int clockid, int flags)
3520 fd = libc_timerfd_create(clockid, flags);
3522 swrap_remove_stale(fd);
3528 int timerfd_create(int clockid, int flags)
3530 return swrap_timerfd_create(clockid, flags);
3534 /****************************************************************************
3536 ***************************************************************************/
3538 static int swrap_pipe(int pipefd[2])
3542 rc = libc_pipe(pipefd);
3544 swrap_remove_stale(pipefd[0]);
3545 swrap_remove_stale(pipefd[1]);
3551 int pipe(int pipefd[2])
3553 return swrap_pipe(pipefd);
3556 /****************************************************************************
3558 ***************************************************************************/
3560 static int swrap_accept(int s,
3561 struct sockaddr *addr,
3565 struct socket_info *parent_si, *child_si;
3566 struct socket_info new_si = { 0 };
3569 struct swrap_address un_addr = {
3570 .sa_socklen = sizeof(struct sockaddr_un),
3572 struct swrap_address un_my_addr = {
3573 .sa_socklen = sizeof(struct sockaddr_un),
3575 struct swrap_address in_addr = {
3576 .sa_socklen = sizeof(struct sockaddr_storage),
3578 struct swrap_address in_my_addr = {
3579 .sa_socklen = sizeof(struct sockaddr_storage),
3583 parent_si = find_socket_info(s);
3586 return libc_accept4(s, addr, addrlen, flags);
3589 return libc_accept(s, addr, addrlen);
3595 * prevent parent_si from being altered / closed
3598 SWRAP_LOCK_SI(parent_si);
3601 * assume out sockaddr have the same size as the in parent
3604 in_addr.sa_socklen = socket_length(parent_si->family);
3605 if (in_addr.sa_socklen <= 0) {
3606 SWRAP_UNLOCK_SI(parent_si);
3611 SWRAP_UNLOCK_SI(parent_si);
3614 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3617 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3620 if (errno == ENOTSOCK) {
3621 /* Remove stale fds */
3622 swrap_remove_stale(s);
3629 /* Check if we have a stale fd and remove it */
3630 swrap_remove_stale(fd);
3632 SWRAP_LOCK_SI(parent_si);
3634 ret = sockaddr_convert_from_un(parent_si,
3639 &in_addr.sa_socklen);
3641 SWRAP_UNLOCK_SI(parent_si);
3648 child_si->family = parent_si->family;
3649 child_si->type = parent_si->type;
3650 child_si->protocol = parent_si->protocol;
3651 child_si->bound = 1;
3652 child_si->is_server = 1;
3653 child_si->connected = 1;
3655 SWRAP_UNLOCK_SI(parent_si);
3657 child_si->peername = (struct swrap_address) {
3658 .sa_socklen = in_addr.sa_socklen,
3660 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3662 if (addr != NULL && addrlen != NULL) {
3663 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3665 memcpy(addr, &in_addr.sa.ss, copy_len);
3667 *addrlen = in_addr.sa_socklen;
3670 ret = libc_getsockname(fd,
3672 &un_my_addr.sa_socklen);
3678 ret = sockaddr_convert_from_un(child_si,
3680 un_my_addr.sa_socklen,
3683 &in_my_addr.sa_socklen);
3689 SWRAP_LOG(SWRAP_LOG_TRACE,
3690 "accept() path=%s, fd=%d",
3691 un_my_addr.sa.un.sun_path, s);
3693 child_si->myname = (struct swrap_address) {
3694 .sa_socklen = in_my_addr.sa_socklen,
3696 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3698 idx = swrap_create_socket(&new_si, fd);
3705 struct socket_info *si = swrap_get_socket_info(idx);
3708 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3709 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3710 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3711 SWRAP_UNLOCK_SI(si);
3718 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3720 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3724 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3725 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3727 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3730 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3733 static int autobind_start_init;
3734 static int autobind_start;
3736 /* using sendto() or connect() on an unbound socket would give the
3737 recipient no way to reply, as unlike UDP and TCP, a unix domain
3738 socket can't auto-assign ephemeral port numbers, so we need to
3740 Note: this might change the family from ipv6 to ipv4
3742 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3744 struct swrap_address un_addr = {
3745 .sa_socklen = sizeof(struct sockaddr_un),
3752 char *swrap_dir = NULL;
3754 swrap_mutex_lock(&autobind_start_mutex);
3756 if (autobind_start_init != 1) {
3757 autobind_start_init = 1;
3758 autobind_start = getpid();
3759 autobind_start %= 50000;
3760 autobind_start += 10000;
3763 un_addr.sa.un.sun_family = AF_UNIX;
3767 struct sockaddr_in in;
3771 type = SOCKET_TYPE_CHAR_TCP;
3774 type = SOCKET_TYPE_CHAR_UDP;
3777 errno = ESOCKTNOSUPPORT;
3782 memset(&in, 0, sizeof(in));
3783 in.sin_family = AF_INET;
3784 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3785 socket_wrapper_default_iface()));
3787 si->myname = (struct swrap_address) {
3788 .sa_socklen = sizeof(in),
3790 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3795 struct sockaddr_in6 in6;
3797 if (si->family != family) {
3798 errno = ENETUNREACH;
3805 type = SOCKET_TYPE_CHAR_TCP_V6;
3808 type = SOCKET_TYPE_CHAR_UDP_V6;
3811 errno = ESOCKTNOSUPPORT;
3816 memset(&in6, 0, sizeof(in6));
3817 in6.sin6_family = AF_INET6;
3818 in6.sin6_addr = *swrap_ipv6();
3819 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3821 si->myname = (struct swrap_address) {
3822 .sa_socklen = sizeof(in6),
3824 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3829 errno = ESOCKTNOSUPPORT;
3834 if (autobind_start > 60000) {
3835 autobind_start = 10000;
3838 swrap_dir = socket_wrapper_dir();
3839 if (swrap_dir == NULL) {
3845 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3846 port = autobind_start + i;
3847 swrap_un_path(&un_addr.sa.un,
3850 socket_wrapper_default_iface(),
3852 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3854 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3859 si->un_addr = un_addr.sa.un;
3862 autobind_start = port + 1;
3865 if (i == SOCKET_MAX_SOCKETS) {
3866 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3867 "interface "SOCKET_FORMAT,
3870 socket_wrapper_default_iface(),
3877 si->family = family;
3878 set_port(si->family, port, &si->myname);
3883 SAFE_FREE(swrap_dir);
3884 swrap_mutex_unlock(&autobind_start_mutex);
3888 /****************************************************************************
3890 ***************************************************************************/
3892 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3896 struct swrap_address un_addr = {
3897 .sa_socklen = sizeof(struct sockaddr_un),
3899 struct socket_info *si = find_socket_info(s);
3903 return libc_connect(s, serv_addr, addrlen);
3908 if (si->bound == 0) {
3909 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3915 if (si->family != serv_addr->sa_family) {
3916 SWRAP_LOG(SWRAP_LOG_ERROR,
3917 "called for fd=%d (family=%d) called with invalid family=%d",
3918 s, si->family, serv_addr->sa_family);
3924 ret = sockaddr_convert_to_un(si, serv_addr,
3925 addrlen, &un_addr.sa.un, 0, &bcast);
3931 errno = ENETUNREACH;
3936 if (si->type == SOCK_DGRAM) {
3937 si->defer_connect = 1;
3940 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3942 ret = libc_connect(s,
3944 un_addr.sa_socklen);
3947 SWRAP_LOG(SWRAP_LOG_TRACE,
3948 "connect() path=%s, fd=%d",
3949 un_addr.sa.un.sun_path, s);
3952 /* to give better errors */
3953 if (ret == -1 && errno == ENOENT) {
3954 errno = EHOSTUNREACH;
3958 si->peername = (struct swrap_address) {
3959 .sa_socklen = addrlen,
3962 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3966 * When we connect() on a socket than we have to bind the
3967 * outgoing connection on the interface we use for the
3968 * transport. We already bound it on the right interface
3969 * but here we have to update the name so getsockname()
3970 * returns correct information.
3972 if (si->bindname.sa_socklen > 0) {
3973 si->myname = (struct swrap_address) {
3974 .sa_socklen = si->bindname.sa_socklen,
3977 memcpy(&si->myname.sa.ss,
3978 &si->bindname.sa.ss,
3979 si->bindname.sa_socklen);
3981 /* Cleanup bindname */
3982 si->bindname = (struct swrap_address) {
3987 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3988 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3990 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3994 SWRAP_UNLOCK_SI(si);
3998 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4000 return swrap_connect(s, serv_addr, addrlen);
4003 /****************************************************************************
4005 ***************************************************************************/
4007 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4010 struct swrap_address un_addr = {
4011 .sa_socklen = sizeof(struct sockaddr_un),
4013 struct socket_info *si = find_socket_info(s);
4020 return libc_bind(s, myaddr, addrlen);
4025 switch (si->family) {
4027 const struct sockaddr_in *sin;
4028 if (addrlen < sizeof(struct sockaddr_in)) {
4029 bind_error = EINVAL;
4033 sin = (const struct sockaddr_in *)(const void *)myaddr;
4035 if (sin->sin_family != AF_INET) {
4036 bind_error = EAFNOSUPPORT;
4039 /* special case for AF_UNSPEC */
4040 if (sin->sin_family == AF_UNSPEC &&
4041 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4050 const struct sockaddr_in6 *sin6;
4051 if (addrlen < sizeof(struct sockaddr_in6)) {
4052 bind_error = EINVAL;
4056 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4058 if (sin6->sin6_family != AF_INET6) {
4059 bind_error = EAFNOSUPPORT;
4066 bind_error = EINVAL;
4070 if (bind_error != 0) {
4077 in_use = check_addr_port_in_use(myaddr, addrlen);
4085 si->myname.sa_socklen = addrlen;
4086 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4088 ret = sockaddr_convert_to_un(si,
4098 unlink(un_addr.sa.un.sun_path);
4100 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4102 SWRAP_LOG(SWRAP_LOG_TRACE,
4103 "bind() path=%s, fd=%d",
4104 un_addr.sa.un.sun_path, s);
4111 SWRAP_UNLOCK_SI(si);
4116 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4118 return swrap_bind(s, myaddr, addrlen);
4121 /****************************************************************************
4123 ***************************************************************************/
4125 #ifdef HAVE_BINDRESVPORT
4126 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4128 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4130 struct swrap_address myaddr = {
4131 .sa_socklen = sizeof(struct sockaddr_storage),
4134 static uint16_t port;
4139 #define SWRAP_STARTPORT 600
4140 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4141 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4144 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4148 salen = myaddr.sa_socklen;
4151 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4157 memset(&myaddr.sa.ss, 0, salen);
4162 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4165 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4167 salen = sizeof(struct sockaddr_in);
4168 sinp->sin_port = htons(port);
4172 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4174 salen = sizeof(struct sockaddr_in6);
4175 sin6p->sin6_port = htons(port);
4179 errno = EAFNOSUPPORT;
4184 if (port > SWRAP_ENDPORT) {
4185 port = SWRAP_STARTPORT;
4188 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4189 if (rc == 0 || errno != EADDRINUSE) {
4197 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4199 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4203 /****************************************************************************
4205 ***************************************************************************/
4207 static int swrap_listen(int s, int backlog)
4210 struct socket_info *si = find_socket_info(s);
4213 return libc_listen(s, backlog);
4218 if (si->bound == 0) {
4219 ret = swrap_auto_bind(s, si, si->family);
4226 ret = libc_listen(s, backlog);
4232 SWRAP_UNLOCK_SI(si);
4237 int listen(int s, int backlog)
4239 return swrap_listen(s, backlog);
4242 /****************************************************************************
4244 ***************************************************************************/
4246 static FILE *swrap_fopen(const char *name, const char *mode)
4250 fp = libc_fopen(name, mode);
4252 int fd = fileno(fp);
4254 swrap_remove_stale(fd);
4260 FILE *fopen(const char *name, const char *mode)
4262 return swrap_fopen(name, mode);
4265 /****************************************************************************
4267 ***************************************************************************/
4270 static FILE *swrap_fopen64(const char *name, const char *mode)
4274 fp = libc_fopen64(name, mode);
4276 int fd = fileno(fp);
4278 swrap_remove_stale(fd);
4284 FILE *fopen64(const char *name, const char *mode)
4286 return swrap_fopen64(name, mode);
4288 #endif /* HAVE_FOPEN64 */
4290 /****************************************************************************
4292 ***************************************************************************/
4294 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4298 ret = libc_vopen(pathname, flags, ap);
4301 * There are methods for closing descriptors (libc-internal code
4302 * paths, direct syscalls) which close descriptors in ways that
4303 * we can't intercept, so try to recover when we notice that
4306 swrap_remove_stale(ret);
4311 int open(const char *pathname, int flags, ...)
4316 va_start(ap, flags);
4317 fd = swrap_vopen(pathname, flags, ap);
4323 /****************************************************************************
4325 ***************************************************************************/
4328 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4332 ret = libc_vopen64(pathname, flags, ap);
4335 * There are methods for closing descriptors (libc-internal code
4336 * paths, direct syscalls) which close descriptors in ways that
4337 * we can't intercept, so try to recover when we notice that
4340 swrap_remove_stale(ret);
4345 int open64(const char *pathname, int flags, ...)
4350 va_start(ap, flags);
4351 fd = swrap_vopen64(pathname, flags, ap);
4356 #endif /* HAVE_OPEN64 */
4358 /****************************************************************************
4360 ***************************************************************************/
4362 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4366 ret = libc_vopenat(dirfd, path, flags, ap);
4369 * There are methods for closing descriptors (libc-internal code
4370 * paths, direct syscalls) which close descriptors in ways that
4371 * we can't intercept, so try to recover when we notice that
4374 swrap_remove_stale(ret);
4380 int openat(int dirfd, const char *path, int flags, ...)
4385 va_start(ap, flags);
4386 fd = swrap_vopenat(dirfd, path, flags, ap);
4392 /****************************************************************************
4394 ***************************************************************************/
4396 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4398 struct socket_info *si = find_socket_info(s);
4403 return libc_getpeername(s, name, addrlen);
4408 if (si->peername.sa_socklen == 0)
4414 len = MIN(*addrlen, si->peername.sa_socklen);
4420 memcpy(name, &si->peername.sa.ss, len);
4421 *addrlen = si->peername.sa_socklen;
4425 SWRAP_UNLOCK_SI(si);
4430 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4431 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4433 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4436 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4439 /****************************************************************************
4441 ***************************************************************************/
4443 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4445 struct socket_info *si = find_socket_info(s);
4450 return libc_getsockname(s, name, addrlen);
4455 len = MIN(*addrlen, si->myname.sa_socklen);
4461 memcpy(name, &si->myname.sa.ss, len);
4462 *addrlen = si->myname.sa_socklen;
4466 SWRAP_UNLOCK_SI(si);
4471 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4472 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4474 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4477 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4480 /****************************************************************************
4482 ***************************************************************************/
4485 # ifdef SO_PROTOTYPE /* The Solaris name */
4486 # define SO_PROTOCOL SO_PROTOTYPE
4487 # endif /* SO_PROTOTYPE */
4488 #endif /* SO_PROTOCOL */
4490 static int swrap_getsockopt(int s, int level, int optname,
4491 void *optval, socklen_t *optlen)
4493 struct socket_info *si = find_socket_info(s);
4497 return libc_getsockopt(s,
4506 if (level == SOL_SOCKET) {
4510 if (optval == NULL || optlen == NULL ||
4511 *optlen < (socklen_t)sizeof(int)) {
4517 *optlen = sizeof(int);
4518 *(int *)optval = si->family;
4521 #endif /* SO_DOMAIN */
4525 if (optval == NULL || optlen == NULL ||
4526 *optlen < (socklen_t)sizeof(int)) {
4532 *optlen = sizeof(int);
4533 *(int *)optval = si->protocol;
4536 #endif /* SO_PROTOCOL */
4538 if (optval == NULL || optlen == NULL ||
4539 *optlen < (socklen_t)sizeof(int)) {
4545 *optlen = sizeof(int);
4546 *(int *)optval = si->type;
4550 ret = libc_getsockopt(s,
4557 } else if (level == IPPROTO_TCP) {
4562 * This enables sending packets directly out over TCP.
4563 * As a unix socket is doing that any way, report it as
4566 if (optval == NULL || optlen == NULL ||
4567 *optlen < (socklen_t)sizeof(int)) {
4573 *optlen = sizeof(int);
4574 *(int *)optval = si->tcp_nodelay;
4578 #endif /* TCP_NODELAY */
4581 struct tcp_info info;
4582 socklen_t ilen = sizeof(info);
4584 #ifdef HAVE_NETINET_TCP_FSM_H
4585 /* This is FreeBSD */
4586 # define __TCP_LISTEN TCPS_LISTEN
4587 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4588 # define __TCP_CLOSE TCPS_CLOSED
4591 # define __TCP_LISTEN TCP_LISTEN
4592 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4593 # define __TCP_CLOSE TCP_CLOSE
4597 if (si->listening) {
4598 info.tcpi_state = __TCP_LISTEN;
4599 } else if (si->connected) {
4601 * For now we just fake a few values
4602 * supported both by FreeBSD and Linux
4604 info.tcpi_state = __TCP_ESTABLISHED;
4605 info.tcpi_rto = 200000; /* 200 msec */
4606 info.tcpi_rtt = 5000; /* 5 msec */
4607 info.tcpi_rttvar = 5000; /* 5 msec */
4609 info.tcpi_state = __TCP_CLOSE;
4610 info.tcpi_rto = 1000000; /* 1 sec */
4612 info.tcpi_rttvar = 250000; /* 250 msec */
4615 if (optval == NULL || optlen == NULL ||
4616 *optlen < (socklen_t)ilen) {
4623 memcpy(optval, &info, ilen);
4628 #endif /* TCP_INFO */
4634 errno = ENOPROTOOPT;
4638 SWRAP_UNLOCK_SI(si);
4642 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4643 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4645 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4648 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4651 /****************************************************************************
4653 ***************************************************************************/
4655 static int swrap_setsockopt(int s, int level, int optname,
4656 const void *optval, socklen_t optlen)
4658 struct socket_info *si = find_socket_info(s);
4662 return libc_setsockopt(s,
4669 if (level == SOL_SOCKET) {
4670 return libc_setsockopt(s,
4679 if (level == IPPROTO_TCP) {
4686 * This enables sending packets directly out over TCP.
4687 * A unix socket is doing that any way.
4689 if (optval == NULL || optlen == 0 ||
4690 optlen < (socklen_t)sizeof(int)) {
4696 i = *discard_const_p(int, optval);
4697 if (i != 0 && i != 1) {
4702 si->tcp_nodelay = i;
4707 #endif /* TCP_NODELAY */
4713 switch (si->family) {
4715 if (level == IPPROTO_IP) {
4717 if (optname == IP_PKTINFO) {
4718 si->pktinfo = AF_INET;
4720 #endif /* IP_PKTINFO */
4726 if (level == IPPROTO_IPV6) {
4727 #ifdef IPV6_RECVPKTINFO
4728 if (optname == IPV6_RECVPKTINFO) {
4729 si->pktinfo = AF_INET6;
4731 #endif /* IPV6_PKTINFO */
4737 errno = ENOPROTOOPT;
4743 SWRAP_UNLOCK_SI(si);
4747 int setsockopt(int s, int level, int optname,
4748 const void *optval, socklen_t optlen)
4750 return swrap_setsockopt(s, level, optname, optval, optlen);
4753 /****************************************************************************
4755 ***************************************************************************/
4757 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4759 struct socket_info *si = find_socket_info(s);
4761 int *value_ptr = NULL;
4765 return libc_vioctl(s, r, va);
4772 rc = libc_vioctl(s, r, va);
4777 value_ptr = ((int *)va_arg(ap, int *));
4780 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4781 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4782 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4783 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4788 /* this is FreeBSD */
4789 FALL_THROUGH; /* to TIOCOUTQ */
4790 #endif /* FIONWRITE */
4791 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4793 * This may return more bytes then the application
4794 * sent into the socket, for tcp it should
4795 * return the number of unacked bytes.
4797 * On AF_UNIX, all bytes are immediately acked!
4800 value_ptr = ((int *)va_arg(ap, int *));
4808 SWRAP_UNLOCK_SI(si);
4812 #ifdef HAVE_IOCTL_INT
4813 int ioctl(int s, int r, ...)
4815 int ioctl(int s, unsigned long int r, ...)
4823 rc = swrap_vioctl(s, (unsigned long int) r, va);
4834 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4837 # ifdef _ALIGN /* BSD */
4838 #define CMSG_ALIGN _ALIGN
4840 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4841 # endif /* _ALIGN */
4842 #endif /* CMSG_ALIGN */
4845 * @brief Add a cmsghdr to a msghdr.
4847 * This is an function to add any type of cmsghdr. It will operate on the
4848 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4849 * the buffer position after the added cmsg element. Hence, this function is
4850 * intended to be used with an intermediate msghdr and not on the original
4851 * one handed in by the client.
4853 * @param[in] msg The msghdr to which to add the cmsg.
4855 * @param[in] level The cmsg level to set.
4857 * @param[in] type The cmsg type to set.
4859 * @param[in] data The cmsg data to set.
4861 * @param[in] len the length of the data to set.
4863 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4869 size_t cmlen = CMSG_LEN(len);
4870 size_t cmspace = CMSG_SPACE(len);
4871 uint8_t cmbuf[cmspace];
4872 void *cast_ptr = (void *)cmbuf;
4873 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4876 memset(cmbuf, 0, cmspace);
4878 if (msg->msg_controllen < cmlen) {
4879 cmlen = msg->msg_controllen;
4880 msg->msg_flags |= MSG_CTRUNC;
4883 if (msg->msg_controllen < cmspace) {
4884 cmspace = msg->msg_controllen;
4888 * We copy the full input data into an intermediate cmsghdr first
4889 * in order to more easily cope with truncation.
4891 cm->cmsg_len = cmlen;
4892 cm->cmsg_level = level;
4893 cm->cmsg_type = type;
4894 memcpy(CMSG_DATA(cm), data, len);
4897 * We now copy the possibly truncated buffer.
4898 * We copy cmlen bytes, but consume cmspace bytes,
4899 * leaving the possible padding uninitialiazed.
4901 p = (uint8_t *)msg->msg_control;
4902 memcpy(p, cm, cmlen);
4904 msg->msg_control = p;
4905 msg->msg_controllen -= cmspace;
4910 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4913 /* Add packet info */
4914 switch (si->pktinfo) {
4915 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4917 struct sockaddr_in *sin;
4918 #if defined(HAVE_STRUCT_IN_PKTINFO)
4919 struct in_pktinfo pkt;
4920 #elif defined(IP_RECVDSTADDR)
4924 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4925 sin = &si->bindname.sa.in;
4927 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4930 sin = &si->myname.sa.in;
4935 #if defined(HAVE_STRUCT_IN_PKTINFO)
4936 pkt.ipi_ifindex = socket_wrapper_default_iface();
4937 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4938 #elif defined(IP_RECVDSTADDR)
4939 pkt = sin->sin_addr;
4942 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4947 #endif /* IP_PKTINFO */
4948 #if defined(HAVE_IPV6)
4950 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4951 struct sockaddr_in6 *sin6;
4952 struct in6_pktinfo pkt6;
4954 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4955 sin6 = &si->bindname.sa.in6;
4957 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4960 sin6 = &si->myname.sa.in6;
4965 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4966 pkt6.ipi6_addr = sin6->sin6_addr;
4968 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4969 &pkt6, sizeof(pkt6));
4970 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4974 #endif /* IPV6_PKTINFO */
4982 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4983 struct msghdr *omsg)
4987 if (si->pktinfo > 0) {
4988 rc = swrap_msghdr_add_pktinfo(si, omsg);
4994 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
4996 size_t *cm_data_space);
4997 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
4999 size_t *cm_data_space);
5000 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5002 size_t *cm_data_space);
5004 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5006 size_t *cm_data_space)
5008 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5009 struct cmsghdr *cmsg;
5013 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5017 for (cmsg = CMSG_FIRSTHDR(msg);
5019 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5020 switch (cmsg->cmsg_level) {
5022 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5027 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5032 rc = swrap_sendmsg_copy_cmsg(cmsg,
5038 int saved_errno = errno;
5039 SAFE_FREE(*cm_data);
5041 errno = saved_errno;
5049 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5051 size_t *cm_data_space)
5056 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5058 p = realloc((*cm_data), cmspace);
5064 p = (*cm_data) + (*cm_data_space);
5065 *cm_data_space = cmspace;
5067 memcpy(p, cmsg, cmsg->cmsg_len);
5072 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5074 size_t *cm_data_space);
5077 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5079 size_t *cm_data_space)
5083 switch(cmsg->cmsg_type) {
5086 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5093 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5105 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5107 size_t *cm_data_space)
5109 (void)cmsg; /* unused */
5110 (void)cm_data; /* unused */
5111 (void)cm_data_space; /* unused */
5114 * Passing a IP pktinfo to a unix socket might be rejected by the
5115 * Kernel, at least on FreeBSD. So skip this cmsg.
5120 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5122 size_t *cm_data_space)
5126 switch (cmsg->cmsg_type) {
5128 SWRAP_LOG(SWRAP_LOG_TRACE,
5129 "Ignoring SCM_RIGHTS on inet socket!");
5132 #ifdef SCM_CREDENTIALS
5133 case SCM_CREDENTIALS:
5134 SWRAP_LOG(SWRAP_LOG_TRACE,
5135 "Ignoring SCM_CREDENTIALS on inet socket!");
5138 #endif /* SCM_CREDENTIALS */
5140 rc = swrap_sendmsg_copy_cmsg(cmsg,
5149 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5151 static ssize_t swrap_sendmsg_before(int fd,
5152 struct socket_info *si,
5154 struct iovec *tmp_iov,
5155 struct sockaddr_un *tmp_un,
5156 const struct sockaddr_un **to_un,
5157 const struct sockaddr **to,
5179 if (!si->connected) {
5184 if (msg->msg_iovlen == 0) {
5188 mtu = socket_wrapper_mtu();
5189 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5191 nlen = len + msg->msg_iov[i].iov_len;
5201 msg->msg_iovlen = i;
5202 if (msg->msg_iovlen == 0) {
5203 *tmp_iov = msg->msg_iov[0];
5204 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5206 msg->msg_iov = tmp_iov;
5207 msg->msg_iovlen = 1;
5212 if (si->connected) {
5213 if (msg->msg_name != NULL) {
5215 * We are dealing with unix sockets and if we
5216 * are connected, we should only talk to the
5217 * connected unix path. Using the fd to send
5218 * to another server would be hard to achieve.
5220 msg->msg_name = NULL;
5221 msg->msg_namelen = 0;
5224 const struct sockaddr *msg_name;
5225 msg_name = (const struct sockaddr *)msg->msg_name;
5227 if (msg_name == NULL) {
5233 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
5245 msg->msg_name = tmp_un;
5246 msg->msg_namelen = sizeof(*tmp_un);
5249 if (si->bound == 0) {
5250 ret = swrap_auto_bind(fd, si, si->family);
5252 SWRAP_UNLOCK_SI(si);
5253 if (errno == ENOTSOCK) {
5254 swrap_remove_stale(fd);
5257 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
5263 if (!si->defer_connect) {
5267 ret = sockaddr_convert_to_un(si,
5269 si->peername.sa_socklen,
5277 ret = libc_connect(fd,
5278 (struct sockaddr *)(void *)tmp_un,
5281 /* to give better errors */
5282 if (ret == -1 && errno == ENOENT) {
5283 errno = EHOSTUNREACH;
5290 si->defer_connect = 0;
5293 errno = EHOSTUNREACH;
5299 SWRAP_UNLOCK_SI(si);
5304 static void swrap_sendmsg_after(int fd,
5305 struct socket_info *si,
5307 const struct sockaddr *to,
5310 int saved_errno = errno;
5317 /* to give better errors */
5319 if (saved_errno == ENOENT) {
5320 saved_errno = EHOSTUNREACH;
5321 } else if (saved_errno == ENOTSOCK) {
5322 /* If the fd is not a socket, remove it */
5323 swrap_remove_stale(fd);
5327 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5328 avail += msg->msg_iov[i].iov_len;
5332 remain = MIN(80, avail);
5337 /* we capture it as one single packet */
5338 buf = (uint8_t *)malloc(remain);
5340 /* we just not capture the packet */
5341 errno = saved_errno;
5345 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5346 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5348 msg->msg_iov[i].iov_base,
5351 remain -= this_time;
5360 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5361 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5363 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5368 if (si->connected) {
5369 to = &si->peername.sa.s;
5372 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5373 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5375 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5380 SWRAP_UNLOCK_SI(si);
5383 errno = saved_errno;
5386 static int swrap_recvmsg_before(int fd,
5387 struct socket_info *si,
5389 struct iovec *tmp_iov)
5396 (void)fd; /* unused */
5401 if (!si->connected) {
5406 if (msg->msg_iovlen == 0) {
5410 mtu = socket_wrapper_mtu();
5411 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5413 nlen = len + msg->msg_iov[i].iov_len;
5418 msg->msg_iovlen = i;
5419 if (msg->msg_iovlen == 0) {
5420 *tmp_iov = msg->msg_iov[0];
5421 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5423 msg->msg_iov = tmp_iov;
5424 msg->msg_iovlen = 1;
5429 if (msg->msg_name == NULL) {
5434 if (msg->msg_iovlen == 0) {
5438 if (si->bound == 0) {
5439 ret = swrap_auto_bind(fd, si, si->family);
5441 SWRAP_UNLOCK_SI(si);
5443 * When attempting to read or write to a
5444 * descriptor, if an underlying autobind fails
5445 * because it's not a socket, stop intercepting
5446 * uses of that descriptor.
5448 if (errno == ENOTSOCK) {
5449 swrap_remove_stale(fd);
5452 SWRAP_LOG(SWRAP_LOG_ERROR,
5453 "swrap_recvmsg_before failed");
5460 errno = EHOSTUNREACH;
5466 SWRAP_UNLOCK_SI(si);
5471 static int swrap_recvmsg_after(int fd,
5472 struct socket_info *si,
5474 const struct sockaddr_un *un_addr,
5475 socklen_t un_addrlen,
5478 int saved_errno = errno;
5480 uint8_t *buf = NULL;
5486 /* to give better errors */
5488 if (saved_errno == ENOENT) {
5489 saved_errno = EHOSTUNREACH;
5490 } else if (saved_errno == ENOTSOCK) {
5491 /* If the fd is not a socket, remove it */
5492 swrap_remove_stale(fd);
5496 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5497 avail += msg->msg_iov[i].iov_len;
5502 /* Convert the socket address before we leave */
5503 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5504 rc = sockaddr_convert_from_un(si,
5521 remain = MIN(80, avail);
5526 /* we capture it as one single packet */
5527 buf = (uint8_t *)malloc(remain);
5529 /* we just not capture the packet */
5530 SWRAP_UNLOCK_SI(si);
5531 errno = saved_errno;
5535 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5536 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5538 msg->msg_iov[i].iov_base,
5541 remain -= this_time;
5546 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5547 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5548 } else if (ret == 0) { /* END OF FILE */
5549 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5550 } else if (ret > 0) {
5551 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5560 if (un_addr != NULL) {
5561 swrap_pcap_dump_packet(si,
5567 swrap_pcap_dump_packet(si,
5580 errno = saved_errno;
5582 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5584 msg->msg_controllen > 0 &&
5585 msg->msg_control != NULL) {
5586 rc = swrap_msghdr_add_socket_info(si, msg);
5588 SWRAP_UNLOCK_SI(si);
5594 SWRAP_UNLOCK_SI(si);
5598 /****************************************************************************
5600 ***************************************************************************/
5602 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5603 struct sockaddr *from, socklen_t *fromlen)
5605 struct swrap_address from_addr = {
5606 .sa_socklen = sizeof(struct sockaddr_un),
5609 struct socket_info *si = find_socket_info(s);
5610 struct swrap_address saddr = {
5611 .sa_socklen = sizeof(struct sockaddr_storage),
5618 return libc_recvfrom(s,
5630 if (from != NULL && fromlen != NULL) {
5631 msg.msg_name = from; /* optional address */
5632 msg.msg_namelen = *fromlen; /* size of address */
5634 msg.msg_name = &saddr.sa.s; /* optional address */
5635 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5637 msg.msg_iov = &tmp; /* scatter/gather array */
5638 msg.msg_iovlen = 1; /* # elements in msg_iov */
5639 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5640 msg.msg_control = NULL; /* ancillary data, see below */
5641 msg.msg_controllen = 0; /* ancillary data buffer len */
5642 msg.msg_flags = 0; /* flags on received message */
5645 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5650 buf = msg.msg_iov[0].iov_base;
5651 len = msg.msg_iov[0].iov_len;
5653 ret = libc_recvfrom(s,
5658 &from_addr.sa_socklen);
5663 tret = swrap_recvmsg_after(s,
5667 from_addr.sa_socklen,
5673 if (from != NULL && fromlen != NULL) {
5674 *fromlen = msg.msg_namelen;
5680 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5681 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5682 struct sockaddr *from, Psocklen_t fromlen)
5684 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5685 struct sockaddr *from, socklen_t *fromlen)
5688 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5691 /****************************************************************************
5693 ***************************************************************************/
5695 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5696 const struct sockaddr *to, socklen_t tolen)
5700 struct swrap_address un_addr = {
5701 .sa_socklen = sizeof(struct sockaddr_un),
5703 const struct sockaddr_un *to_un = NULL;
5706 struct socket_info *si = find_socket_info(s);
5710 return libc_sendto(s, buf, len, flags, to, tolen);
5713 tmp.iov_base = discard_const_p(char, buf);
5717 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5718 msg.msg_namelen = tolen; /* size of address */
5719 msg.msg_iov = &tmp; /* scatter/gather array */
5720 msg.msg_iovlen = 1; /* # elements in msg_iov */
5721 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5722 msg.msg_control = NULL; /* ancillary data, see below */
5723 msg.msg_controllen = 0; /* ancillary data buffer len */
5724 msg.msg_flags = 0; /* flags on received message */
5727 rc = swrap_sendmsg_before(s,
5739 buf = msg.msg_iov[0].iov_base;
5740 len = msg.msg_iov[0].iov_len;
5745 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5747 char *swrap_dir = NULL;
5749 type = SOCKET_TYPE_CHAR_UDP;
5751 swrap_dir = socket_wrapper_dir();
5752 if (swrap_dir == NULL) {
5756 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5757 swrap_un_path(&un_addr.sa.un,
5762 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5764 /* ignore the any errors in broadcast sends */
5770 un_addr.sa_socklen);
5773 SAFE_FREE(swrap_dir);
5777 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5779 SWRAP_UNLOCK_SI(si);
5786 * If it is a dgram socket and we are connected, don't include the
5789 if (si->type == SOCK_DGRAM && si->connected) {
5790 ret = libc_sendto(s,
5797 ret = libc_sendto(s,
5801 (struct sockaddr *)msg.msg_name,
5805 SWRAP_UNLOCK_SI(si);
5807 swrap_sendmsg_after(s, si, &msg, to, ret);
5812 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5813 const struct sockaddr *to, socklen_t tolen)
5815 return swrap_sendto(s, buf, len, flags, to, tolen);
5818 /****************************************************************************
5820 ***************************************************************************/
5822 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5824 struct socket_info *si;
5826 struct swrap_address saddr = {
5827 .sa_socklen = sizeof(struct sockaddr_storage),
5833 si = find_socket_info(s);
5835 return libc_recv(s, buf, len, flags);
5842 msg.msg_name = &saddr.sa.s; /* optional address */
5843 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5844 msg.msg_iov = &tmp; /* scatter/gather array */
5845 msg.msg_iovlen = 1; /* # elements in msg_iov */
5846 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5847 msg.msg_control = NULL; /* ancillary data, see below */
5848 msg.msg_controllen = 0; /* ancillary data buffer len */
5849 msg.msg_flags = 0; /* flags on received message */
5852 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5857 buf = msg.msg_iov[0].iov_base;
5858 len = msg.msg_iov[0].iov_len;
5860 ret = libc_recv(s, buf, len, flags);
5862 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5870 ssize_t recv(int s, void *buf, size_t len, int flags)
5872 return swrap_recv(s, buf, len, flags);
5875 /****************************************************************************
5877 ***************************************************************************/
5879 static ssize_t swrap_read(int s, void *buf, size_t len)
5881 struct socket_info *si;
5884 struct swrap_address saddr = {
5885 .sa_socklen = sizeof(struct sockaddr_storage),
5890 si = find_socket_info(s);
5892 return libc_read(s, buf, len);
5899 msg.msg_name = &saddr.sa.ss; /* optional address */
5900 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5901 msg.msg_iov = &tmp; /* scatter/gather array */
5902 msg.msg_iovlen = 1; /* # elements in msg_iov */
5903 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5904 msg.msg_control = NULL; /* ancillary data, see below */
5905 msg.msg_controllen = 0; /* ancillary data buffer len */
5906 msg.msg_flags = 0; /* flags on received message */
5909 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5911 if (tret == -ENOTSOCK) {
5912 return libc_read(s, buf, len);
5917 buf = msg.msg_iov[0].iov_base;
5918 len = msg.msg_iov[0].iov_len;
5920 ret = libc_read(s, buf, len);
5922 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5930 ssize_t read(int s, void *buf, size_t len)
5932 return swrap_read(s, buf, len);
5935 /****************************************************************************
5937 ***************************************************************************/
5939 static ssize_t swrap_write(int s, const void *buf, size_t len)
5943 struct sockaddr_un un_addr;
5946 struct socket_info *si;
5948 si = find_socket_info(s);
5950 return libc_write(s, buf, len);
5953 tmp.iov_base = discard_const_p(char, buf);
5957 msg.msg_name = NULL; /* optional address */
5958 msg.msg_namelen = 0; /* size of address */
5959 msg.msg_iov = &tmp; /* scatter/gather array */
5960 msg.msg_iovlen = 1; /* # elements in msg_iov */
5961 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5962 msg.msg_control = NULL; /* ancillary data, see below */
5963 msg.msg_controllen = 0; /* ancillary data buffer len */
5964 msg.msg_flags = 0; /* flags on received message */
5967 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5972 buf = msg.msg_iov[0].iov_base;
5973 len = msg.msg_iov[0].iov_len;
5975 ret = libc_write(s, buf, len);
5977 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5982 ssize_t write(int s, const void *buf, size_t len)
5984 return swrap_write(s, buf, len);
5987 /****************************************************************************
5989 ***************************************************************************/
5991 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5995 struct sockaddr_un un_addr;
5998 struct socket_info *si = find_socket_info(s);
6001 return libc_send(s, buf, len, flags);
6004 tmp.iov_base = discard_const_p(char, buf);
6008 msg.msg_name = NULL; /* optional address */
6009 msg.msg_namelen = 0; /* size of address */
6010 msg.msg_iov = &tmp; /* scatter/gather array */
6011 msg.msg_iovlen = 1; /* # elements in msg_iov */
6012 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6013 msg.msg_control = NULL; /* ancillary data, see below */
6014 msg.msg_controllen = 0; /* ancillary data buffer len */
6015 msg.msg_flags = 0; /* flags on received message */
6018 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6023 buf = msg.msg_iov[0].iov_base;
6024 len = msg.msg_iov[0].iov_len;
6026 ret = libc_send(s, buf, len, flags);
6028 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6033 ssize_t send(int s, const void *buf, size_t len, int flags)
6035 return swrap_send(s, buf, len, flags);
6038 /****************************************************************************
6040 ***************************************************************************/
6042 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6044 struct swrap_address from_addr = {
6045 .sa_socklen = sizeof(struct sockaddr_un),
6047 struct swrap_address convert_addr = {
6048 .sa_socklen = sizeof(struct sockaddr_storage),
6050 struct socket_info *si;
6053 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6054 size_t msg_ctrllen_filled;
6055 size_t msg_ctrllen_left;
6061 si = find_socket_info(s);
6063 return libc_recvmsg(s, omsg, flags);
6066 tmp.iov_base = NULL;
6070 msg.msg_name = &from_addr.sa; /* optional address */
6071 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6072 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6073 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6074 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6075 msg_ctrllen_filled = 0;
6076 msg_ctrllen_left = omsg->msg_controllen;
6078 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6079 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6080 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6083 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6088 ret = libc_recvmsg(s, &msg, flags);
6090 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6091 msg_ctrllen_filled += msg.msg_controllen;
6092 msg_ctrllen_left -= msg.msg_controllen;
6094 if (omsg->msg_control != NULL) {
6097 p = omsg->msg_control;
6098 p += msg_ctrllen_filled;
6100 msg.msg_control = p;
6101 msg.msg_controllen = msg_ctrllen_left;
6103 msg.msg_control = NULL;
6104 msg.msg_controllen = 0;
6109 * We convert the unix address to a IP address so we need a buffer
6110 * which can store the address in case of SOCK_DGRAM, see below.
6112 msg.msg_name = &convert_addr.sa;
6113 msg.msg_namelen = convert_addr.sa_socklen;
6115 rc = swrap_recvmsg_after(s,
6119 from_addr.sa_socklen,
6125 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6126 if (omsg->msg_control != NULL) {
6127 /* msg.msg_controllen = space left */
6128 msg_ctrllen_left = msg.msg_controllen;
6129 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6132 /* Update the original message length */
6133 omsg->msg_controllen = msg_ctrllen_filled;
6134 omsg->msg_flags = msg.msg_flags;
6136 omsg->msg_iovlen = msg.msg_iovlen;
6143 * The msg_name field points to a caller-allocated buffer that is
6144 * used to return the source address if the socket is unconnected. The
6145 * caller should set msg_namelen to the size of this buffer before this
6146 * call; upon return from a successful call, msg_name will contain the
6147 * length of the returned address. If the application does not need
6148 * to know the source address, msg_name can be specified as NULL.
6150 if (si->type == SOCK_STREAM) {
6151 omsg->msg_namelen = 0;
6152 } else if (omsg->msg_name != NULL &&
6153 omsg->msg_namelen != 0 &&
6154 omsg->msg_namelen >= msg.msg_namelen) {
6155 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6156 omsg->msg_namelen = msg.msg_namelen;
6159 SWRAP_UNLOCK_SI(si);
6164 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6166 return swrap_recvmsg(sockfd, msg, flags);
6169 /****************************************************************************
6171 ***************************************************************************/
6173 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
6177 struct sockaddr_un un_addr;
6178 const struct sockaddr_un *to_un = NULL;
6179 const struct sockaddr *to = NULL;
6182 struct socket_info *si = find_socket_info(s);
6186 return libc_sendmsg(s, omsg, flags);
6189 ZERO_STRUCT(un_addr);
6191 tmp.iov_base = NULL;
6198 if (si->connected == 0) {
6199 msg.msg_name = omsg->msg_name; /* optional address */
6200 msg.msg_namelen = omsg->msg_namelen; /* size of address */
6202 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6203 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6205 SWRAP_UNLOCK_SI(si);
6207 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6208 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
6209 uint8_t *cmbuf = NULL;
6212 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
6218 msg.msg_controllen = 0;
6219 msg.msg_control = NULL;
6221 msg.msg_control = cmbuf;
6222 msg.msg_controllen = cmlen;
6225 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6227 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
6229 int saved_errno = errno;
6230 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6231 SAFE_FREE(msg.msg_control);
6233 errno = saved_errno;
6240 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6247 char *swrap_dir = NULL;
6249 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6250 avail += msg.msg_iov[i].iov_len;
6256 /* we capture it as one single packet */
6257 buf = (uint8_t *)malloc(remain);
6259 int saved_errno = errno;
6260 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6261 SAFE_FREE(msg.msg_control);
6263 errno = saved_errno;
6267 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6268 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
6270 msg.msg_iov[i].iov_base,
6273 remain -= this_time;
6276 type = SOCKET_TYPE_CHAR_UDP;
6278 swrap_dir = socket_wrapper_dir();
6279 if (swrap_dir == NULL) {
6280 int saved_errno = errno;
6281 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6282 SAFE_FREE(msg.msg_control);
6285 errno = saved_errno;
6289 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6290 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
6291 if (stat(un_addr.sun_path, &st) != 0) continue;
6293 msg.msg_name = &un_addr; /* optional address */
6294 msg.msg_namelen = sizeof(un_addr); /* size of address */
6296 /* ignore the any errors in broadcast sends */
6297 libc_sendmsg(s, &msg, flags);
6300 SAFE_FREE(swrap_dir);
6304 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6307 SWRAP_UNLOCK_SI(si);
6312 ret = libc_sendmsg(s, &msg, flags);
6314 swrap_sendmsg_after(s, si, &msg, to, ret);
6316 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6318 int saved_errno = errno;
6319 SAFE_FREE(msg.msg_control);
6320 errno = saved_errno;
6327 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
6329 return swrap_sendmsg(s, omsg, flags);
6332 /****************************************************************************
6334 ***************************************************************************/
6336 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
6338 struct socket_info *si;
6341 struct swrap_address saddr = {
6342 .sa_socklen = sizeof(struct sockaddr_storage)
6347 si = find_socket_info(s);
6349 return libc_readv(s, vector, count);
6352 tmp.iov_base = NULL;
6356 msg.msg_name = &saddr.sa.s; /* optional address */
6357 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6358 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6359 msg.msg_iovlen = count; /* # elements in msg_iov */
6360 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6361 msg.msg_control = NULL; /* ancillary data, see below */
6362 msg.msg_controllen = 0; /* ancillary data buffer len */
6363 msg.msg_flags = 0; /* flags on received message */
6366 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6368 if (rc == -ENOTSOCK) {
6369 return libc_readv(s, vector, count);
6374 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
6376 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6384 ssize_t readv(int s, const struct iovec *vector, int count)
6386 return swrap_readv(s, vector, count);
6389 /****************************************************************************
6391 ***************************************************************************/
6393 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6397 struct sockaddr_un un_addr;
6400 struct socket_info *si = find_socket_info(s);
6403 return libc_writev(s, vector, count);
6406 tmp.iov_base = NULL;
6410 msg.msg_name = NULL; /* optional address */
6411 msg.msg_namelen = 0; /* size of address */
6412 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6413 msg.msg_iovlen = count; /* # elements in msg_iov */
6414 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6415 msg.msg_control = NULL; /* ancillary data, see below */
6416 msg.msg_controllen = 0; /* ancillary data buffer len */
6417 msg.msg_flags = 0; /* flags on received message */
6420 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6422 if (rc == -ENOTSOCK) {
6423 return libc_readv(s, vector, count);
6428 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6430 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6435 ssize_t writev(int s, const struct iovec *vector, int count)
6437 return swrap_writev(s, vector, count);
6440 /****************************
6442 ***************************/
6444 static int swrap_close(int fd)
6446 struct socket_info *si = NULL;
6450 swrap_mutex_lock(&socket_reset_mutex);
6452 si_index = find_socket_info_index(fd);
6453 if (si_index == -1) {
6454 swrap_mutex_unlock(&socket_reset_mutex);
6455 return libc_close(fd);
6458 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
6459 reset_socket_info_index(fd);
6461 si = swrap_get_socket_info(si_index);
6463 swrap_mutex_lock(&first_free_mutex);
6466 ret = libc_close(fd);
6468 swrap_dec_refcount(si);
6470 if (swrap_get_refcount(si) > 0) {
6471 /* there are still references left */
6475 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6476 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6479 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6480 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6481 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6484 if (si->un_addr.sun_path[0] != '\0') {
6485 unlink(si->un_addr.sun_path);
6488 swrap_set_next_free(si, first_free);
6489 first_free = si_index;
6492 SWRAP_UNLOCK_SI(si);
6493 swrap_mutex_unlock(&first_free_mutex);
6494 swrap_mutex_unlock(&socket_reset_mutex);
6501 return swrap_close(fd);
6504 /****************************
6506 ***************************/
6508 static int swrap_dup(int fd)
6510 struct socket_info *si;
6513 idx = find_socket_info_index(fd);
6515 return libc_dup(fd);
6518 si = swrap_get_socket_info(idx);
6520 dup_fd = libc_dup(fd);
6522 int saved_errno = errno;
6523 errno = saved_errno;
6529 swrap_inc_refcount(si);
6531 SWRAP_UNLOCK_SI(si);
6533 /* Make sure we don't have an entry for the fd */
6534 swrap_remove_stale(dup_fd);
6536 set_socket_info_index(dup_fd, idx);
6543 return swrap_dup(fd);
6546 /****************************
6548 ***************************/
6550 static int swrap_dup2(int fd, int newfd)
6552 struct socket_info *si;
6555 idx = find_socket_info_index(fd);
6557 return libc_dup2(fd, newfd);
6560 si = swrap_get_socket_info(idx);
6564 * According to the manpage:
6566 * "If oldfd is a valid file descriptor, and newfd has the same
6567 * value as oldfd, then dup2() does nothing, and returns newfd."
6572 if (find_socket_info(newfd)) {
6573 /* dup2() does an implicit close of newfd, which we
6574 * need to emulate */
6578 dup_fd = libc_dup2(fd, newfd);
6580 int saved_errno = errno;
6581 errno = saved_errno;
6587 swrap_inc_refcount(si);
6589 SWRAP_UNLOCK_SI(si);
6591 /* Make sure we don't have an entry for the fd */
6592 swrap_remove_stale(dup_fd);
6594 set_socket_info_index(dup_fd, idx);
6599 int dup2(int fd, int newfd)
6601 return swrap_dup2(fd, newfd);
6604 /****************************
6606 ***************************/
6608 static int swrap_vfcntl(int fd, int cmd, va_list va)
6610 struct socket_info *si;
6611 int rc, dup_fd, idx;
6613 idx = find_socket_info_index(fd);
6615 return libc_vfcntl(fd, cmd, va);
6618 si = swrap_get_socket_info(idx);
6622 dup_fd = libc_vfcntl(fd, cmd, va);
6624 int saved_errno = errno;
6625 errno = saved_errno;
6631 swrap_inc_refcount(si);
6633 SWRAP_UNLOCK_SI(si);
6635 /* Make sure we don't have an entry for the fd */
6636 swrap_remove_stale(dup_fd);
6638 set_socket_info_index(dup_fd, idx);
6643 rc = libc_vfcntl(fd, cmd, va);
6650 int fcntl(int fd, int cmd, ...)
6657 rc = swrap_vfcntl(fd, cmd, va);
6664 /****************************
6666 ***************************/
6669 static int swrap_eventfd(int count, int flags)
6673 fd = libc_eventfd(count, flags);
6675 swrap_remove_stale(fd);
6681 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6682 int eventfd(unsigned int count, int flags)
6684 int eventfd(int count, int flags)
6687 return swrap_eventfd(count, flags);
6692 int pledge(const char *promises, const char *paths[])
6694 (void)promises; /* unused */
6695 (void)paths; /* unused */
6699 #endif /* HAVE_PLEDGE */
6701 static void swrap_thread_prepare(void)
6704 * This function should only be called here!!
6706 * We bind all symobls to avoid deadlocks of the fork is
6707 * interrupted by a signal handler using a symbol of this
6710 swrap_bind_symbol_all();
6715 static void swrap_thread_parent(void)
6720 static void swrap_thread_child(void)
6725 /****************************
6727 ***************************/
6728 void swrap_constructor(void)
6733 * If we hold a lock and the application forks, then the child
6734 * is not able to unlock the mutex and we are in a deadlock.
6735 * This should prevent such deadlocks.
6737 pthread_atfork(&swrap_thread_prepare,
6738 &swrap_thread_parent,
6739 &swrap_thread_child);
6742 /****************************
6744 ***************************/
6747 * This function is called when the library is unloaded and makes sure that
6748 * sockets get closed and the unix file for the socket are unlinked.
6750 void swrap_destructor(void)
6754 if (socket_fds_idx != NULL) {
6755 for (i = 0; i < socket_fds_max; ++i) {
6756 if (socket_fds_idx[i] != -1) {
6760 SAFE_FREE(socket_fds_idx);
6765 if (swrap.libc.handle != NULL) {
6766 dlclose(swrap.libc.handle);
6768 if (swrap.libc.socket_handle) {
6769 dlclose(swrap.libc.socket_handle);
6773 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
6775 * On FreeBSD 12 (and maybe other platforms)
6776 * system libraries like libresolv prefix there
6777 * syscalls with '_' in order to always use
6778 * the symbols from libc.
6780 * In the interaction with resolv_wrapper,
6781 * we need to inject socket wrapper into libresolv,
6782 * which means we need to private all socket
6783 * related syscalls also with the '_' prefix.
6785 * This is tested in Samba's 'make test',
6786 * there we noticed that providing '_read'
6787 * and '_open' would cause errors, which
6788 * means we skip '_read', '_write' and
6789 * all non socket related calls without
6790 * further analyzing the problem.
6792 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
6793 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
6796 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
6798 SWRAP_SYMBOL_ALIAS(accept, _accept);
6799 SWRAP_SYMBOL_ALIAS(bind, _bind);
6800 SWRAP_SYMBOL_ALIAS(close, _close);
6801 SWRAP_SYMBOL_ALIAS(connect, _connect);
6802 SWRAP_SYMBOL_ALIAS(dup, _dup);
6803 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
6804 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
6805 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
6806 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
6807 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
6808 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
6809 SWRAP_SYMBOL_ALIAS(listen, _listen);
6810 SWRAP_SYMBOL_ALIAS(readv, _readv);
6811 SWRAP_SYMBOL_ALIAS(recv, _recv);
6812 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
6813 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
6814 SWRAP_SYMBOL_ALIAS(send, _send);
6815 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
6816 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
6817 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
6818 SWRAP_SYMBOL_ALIAS(socket, _socket);
6819 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
6820 SWRAP_SYMBOL_ALIAS(writev, _writev);
6822 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */