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_socket(const struct cmsghdr *cmsg,
4999 size_t *cm_data_space);
5001 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5003 size_t *cm_data_space)
5005 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5006 struct cmsghdr *cmsg;
5010 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5014 for (cmsg = CMSG_FIRSTHDR(msg);
5016 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5017 switch (cmsg->cmsg_level) {
5019 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
5024 rc = swrap_sendmsg_copy_cmsg(cmsg,
5034 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5036 size_t *cm_data_space)
5041 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5043 p = realloc((*cm_data), cmspace);
5049 p = (*cm_data) + (*cm_data_space);
5050 *cm_data_space = cmspace;
5052 memcpy(p, cmsg, cmsg->cmsg_len);
5057 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5059 size_t *cm_data_space);
5062 static int swrap_sendmsg_filter_cmsg_socket(const struct cmsghdr *cmsg,
5064 size_t *cm_data_space)
5068 switch(cmsg->cmsg_type) {
5071 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5078 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5090 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5092 size_t *cm_data_space)
5094 (void)cmsg; /* unused */
5095 (void)cm_data; /* unused */
5096 (void)cm_data_space; /* unused */
5099 * Passing a IP pktinfo to a unix socket might be rejected by the
5100 * Kernel, at least on FreeBSD. So skip this cmsg.
5104 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5106 static ssize_t swrap_sendmsg_before(int fd,
5107 struct socket_info *si,
5109 struct iovec *tmp_iov,
5110 struct sockaddr_un *tmp_un,
5111 const struct sockaddr_un **to_un,
5112 const struct sockaddr **to,
5134 if (!si->connected) {
5139 if (msg->msg_iovlen == 0) {
5143 mtu = socket_wrapper_mtu();
5144 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5146 nlen = len + msg->msg_iov[i].iov_len;
5156 msg->msg_iovlen = i;
5157 if (msg->msg_iovlen == 0) {
5158 *tmp_iov = msg->msg_iov[0];
5159 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5161 msg->msg_iov = tmp_iov;
5162 msg->msg_iovlen = 1;
5167 if (si->connected) {
5168 if (msg->msg_name != NULL) {
5170 * We are dealing with unix sockets and if we
5171 * are connected, we should only talk to the
5172 * connected unix path. Using the fd to send
5173 * to another server would be hard to achieve.
5175 msg->msg_name = NULL;
5176 msg->msg_namelen = 0;
5179 const struct sockaddr *msg_name;
5180 msg_name = (const struct sockaddr *)msg->msg_name;
5182 if (msg_name == NULL) {
5188 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
5200 msg->msg_name = tmp_un;
5201 msg->msg_namelen = sizeof(*tmp_un);
5204 if (si->bound == 0) {
5205 ret = swrap_auto_bind(fd, si, si->family);
5207 SWRAP_UNLOCK_SI(si);
5208 if (errno == ENOTSOCK) {
5209 swrap_remove_stale(fd);
5212 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
5218 if (!si->defer_connect) {
5222 ret = sockaddr_convert_to_un(si,
5224 si->peername.sa_socklen,
5232 ret = libc_connect(fd,
5233 (struct sockaddr *)(void *)tmp_un,
5236 /* to give better errors */
5237 if (ret == -1 && errno == ENOENT) {
5238 errno = EHOSTUNREACH;
5245 si->defer_connect = 0;
5248 errno = EHOSTUNREACH;
5254 SWRAP_UNLOCK_SI(si);
5259 static void swrap_sendmsg_after(int fd,
5260 struct socket_info *si,
5262 const struct sockaddr *to,
5265 int saved_errno = errno;
5272 /* to give better errors */
5274 if (saved_errno == ENOENT) {
5275 saved_errno = EHOSTUNREACH;
5276 } else if (saved_errno == ENOTSOCK) {
5277 /* If the fd is not a socket, remove it */
5278 swrap_remove_stale(fd);
5282 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5283 avail += msg->msg_iov[i].iov_len;
5287 remain = MIN(80, avail);
5292 /* we capture it as one single packet */
5293 buf = (uint8_t *)malloc(remain);
5295 /* we just not capture the packet */
5296 errno = saved_errno;
5300 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5301 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5303 msg->msg_iov[i].iov_base,
5306 remain -= this_time;
5315 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5316 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5318 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5323 if (si->connected) {
5324 to = &si->peername.sa.s;
5327 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5328 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5330 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5335 SWRAP_UNLOCK_SI(si);
5338 errno = saved_errno;
5341 static int swrap_recvmsg_before(int fd,
5342 struct socket_info *si,
5344 struct iovec *tmp_iov)
5351 (void)fd; /* unused */
5356 if (!si->connected) {
5361 if (msg->msg_iovlen == 0) {
5365 mtu = socket_wrapper_mtu();
5366 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5368 nlen = len + msg->msg_iov[i].iov_len;
5373 msg->msg_iovlen = i;
5374 if (msg->msg_iovlen == 0) {
5375 *tmp_iov = msg->msg_iov[0];
5376 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5378 msg->msg_iov = tmp_iov;
5379 msg->msg_iovlen = 1;
5384 if (msg->msg_name == NULL) {
5389 if (msg->msg_iovlen == 0) {
5393 if (si->bound == 0) {
5394 ret = swrap_auto_bind(fd, si, si->family);
5396 SWRAP_UNLOCK_SI(si);
5398 * When attempting to read or write to a
5399 * descriptor, if an underlying autobind fails
5400 * because it's not a socket, stop intercepting
5401 * uses of that descriptor.
5403 if (errno == ENOTSOCK) {
5404 swrap_remove_stale(fd);
5407 SWRAP_LOG(SWRAP_LOG_ERROR,
5408 "swrap_recvmsg_before failed");
5415 errno = EHOSTUNREACH;
5421 SWRAP_UNLOCK_SI(si);
5426 static int swrap_recvmsg_after(int fd,
5427 struct socket_info *si,
5429 const struct sockaddr_un *un_addr,
5430 socklen_t un_addrlen,
5433 int saved_errno = errno;
5435 uint8_t *buf = NULL;
5441 /* to give better errors */
5443 if (saved_errno == ENOENT) {
5444 saved_errno = EHOSTUNREACH;
5445 } else if (saved_errno == ENOTSOCK) {
5446 /* If the fd is not a socket, remove it */
5447 swrap_remove_stale(fd);
5451 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5452 avail += msg->msg_iov[i].iov_len;
5457 /* Convert the socket address before we leave */
5458 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5459 rc = sockaddr_convert_from_un(si,
5476 remain = MIN(80, avail);
5481 /* we capture it as one single packet */
5482 buf = (uint8_t *)malloc(remain);
5484 /* we just not capture the packet */
5485 SWRAP_UNLOCK_SI(si);
5486 errno = saved_errno;
5490 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5491 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5493 msg->msg_iov[i].iov_base,
5496 remain -= this_time;
5501 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5502 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5503 } else if (ret == 0) { /* END OF FILE */
5504 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5505 } else if (ret > 0) {
5506 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5515 if (un_addr != NULL) {
5516 swrap_pcap_dump_packet(si,
5522 swrap_pcap_dump_packet(si,
5535 errno = saved_errno;
5537 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5539 msg->msg_controllen > 0 &&
5540 msg->msg_control != NULL) {
5541 rc = swrap_msghdr_add_socket_info(si, msg);
5543 SWRAP_UNLOCK_SI(si);
5549 SWRAP_UNLOCK_SI(si);
5553 /****************************************************************************
5555 ***************************************************************************/
5557 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5558 struct sockaddr *from, socklen_t *fromlen)
5560 struct swrap_address from_addr = {
5561 .sa_socklen = sizeof(struct sockaddr_un),
5564 struct socket_info *si = find_socket_info(s);
5565 struct swrap_address saddr = {
5566 .sa_socklen = sizeof(struct sockaddr_storage),
5573 return libc_recvfrom(s,
5585 if (from != NULL && fromlen != NULL) {
5586 msg.msg_name = from; /* optional address */
5587 msg.msg_namelen = *fromlen; /* size of address */
5589 msg.msg_name = &saddr.sa.s; /* optional address */
5590 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5592 msg.msg_iov = &tmp; /* scatter/gather array */
5593 msg.msg_iovlen = 1; /* # elements in msg_iov */
5594 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5595 msg.msg_control = NULL; /* ancillary data, see below */
5596 msg.msg_controllen = 0; /* ancillary data buffer len */
5597 msg.msg_flags = 0; /* flags on received message */
5600 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5605 buf = msg.msg_iov[0].iov_base;
5606 len = msg.msg_iov[0].iov_len;
5608 ret = libc_recvfrom(s,
5613 &from_addr.sa_socklen);
5618 tret = swrap_recvmsg_after(s,
5622 from_addr.sa_socklen,
5628 if (from != NULL && fromlen != NULL) {
5629 *fromlen = msg.msg_namelen;
5635 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5636 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5637 struct sockaddr *from, Psocklen_t fromlen)
5639 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5640 struct sockaddr *from, socklen_t *fromlen)
5643 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5646 /****************************************************************************
5648 ***************************************************************************/
5650 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5651 const struct sockaddr *to, socklen_t tolen)
5655 struct swrap_address un_addr = {
5656 .sa_socklen = sizeof(struct sockaddr_un),
5658 const struct sockaddr_un *to_un = NULL;
5661 struct socket_info *si = find_socket_info(s);
5665 return libc_sendto(s, buf, len, flags, to, tolen);
5668 tmp.iov_base = discard_const_p(char, buf);
5672 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5673 msg.msg_namelen = tolen; /* size of address */
5674 msg.msg_iov = &tmp; /* scatter/gather array */
5675 msg.msg_iovlen = 1; /* # elements in msg_iov */
5676 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5677 msg.msg_control = NULL; /* ancillary data, see below */
5678 msg.msg_controllen = 0; /* ancillary data buffer len */
5679 msg.msg_flags = 0; /* flags on received message */
5682 rc = swrap_sendmsg_before(s,
5694 buf = msg.msg_iov[0].iov_base;
5695 len = msg.msg_iov[0].iov_len;
5700 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5702 char *swrap_dir = NULL;
5704 type = SOCKET_TYPE_CHAR_UDP;
5706 swrap_dir = socket_wrapper_dir();
5707 if (swrap_dir == NULL) {
5711 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5712 swrap_un_path(&un_addr.sa.un,
5717 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5719 /* ignore the any errors in broadcast sends */
5725 un_addr.sa_socklen);
5728 SAFE_FREE(swrap_dir);
5732 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5734 SWRAP_UNLOCK_SI(si);
5741 * If it is a dgram socket and we are connected, don't include the
5744 if (si->type == SOCK_DGRAM && si->connected) {
5745 ret = libc_sendto(s,
5752 ret = libc_sendto(s,
5756 (struct sockaddr *)msg.msg_name,
5760 SWRAP_UNLOCK_SI(si);
5762 swrap_sendmsg_after(s, si, &msg, to, ret);
5767 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5768 const struct sockaddr *to, socklen_t tolen)
5770 return swrap_sendto(s, buf, len, flags, to, tolen);
5773 /****************************************************************************
5775 ***************************************************************************/
5777 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5779 struct socket_info *si;
5781 struct swrap_address saddr = {
5782 .sa_socklen = sizeof(struct sockaddr_storage),
5788 si = find_socket_info(s);
5790 return libc_recv(s, buf, len, flags);
5797 msg.msg_name = &saddr.sa.s; /* optional address */
5798 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5799 msg.msg_iov = &tmp; /* scatter/gather array */
5800 msg.msg_iovlen = 1; /* # elements in msg_iov */
5801 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5802 msg.msg_control = NULL; /* ancillary data, see below */
5803 msg.msg_controllen = 0; /* ancillary data buffer len */
5804 msg.msg_flags = 0; /* flags on received message */
5807 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5812 buf = msg.msg_iov[0].iov_base;
5813 len = msg.msg_iov[0].iov_len;
5815 ret = libc_recv(s, buf, len, flags);
5817 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5825 ssize_t recv(int s, void *buf, size_t len, int flags)
5827 return swrap_recv(s, buf, len, flags);
5830 /****************************************************************************
5832 ***************************************************************************/
5834 static ssize_t swrap_read(int s, void *buf, size_t len)
5836 struct socket_info *si;
5839 struct swrap_address saddr = {
5840 .sa_socklen = sizeof(struct sockaddr_storage),
5845 si = find_socket_info(s);
5847 return libc_read(s, buf, len);
5854 msg.msg_name = &saddr.sa.ss; /* optional address */
5855 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5856 msg.msg_iov = &tmp; /* scatter/gather array */
5857 msg.msg_iovlen = 1; /* # elements in msg_iov */
5858 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5859 msg.msg_control = NULL; /* ancillary data, see below */
5860 msg.msg_controllen = 0; /* ancillary data buffer len */
5861 msg.msg_flags = 0; /* flags on received message */
5864 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5866 if (tret == -ENOTSOCK) {
5867 return libc_read(s, buf, len);
5872 buf = msg.msg_iov[0].iov_base;
5873 len = msg.msg_iov[0].iov_len;
5875 ret = libc_read(s, buf, len);
5877 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5885 ssize_t read(int s, void *buf, size_t len)
5887 return swrap_read(s, buf, len);
5890 /****************************************************************************
5892 ***************************************************************************/
5894 static ssize_t swrap_write(int s, const void *buf, size_t len)
5898 struct sockaddr_un un_addr;
5901 struct socket_info *si;
5903 si = find_socket_info(s);
5905 return libc_write(s, buf, len);
5908 tmp.iov_base = discard_const_p(char, buf);
5912 msg.msg_name = NULL; /* optional address */
5913 msg.msg_namelen = 0; /* size of address */
5914 msg.msg_iov = &tmp; /* scatter/gather array */
5915 msg.msg_iovlen = 1; /* # elements in msg_iov */
5916 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5917 msg.msg_control = NULL; /* ancillary data, see below */
5918 msg.msg_controllen = 0; /* ancillary data buffer len */
5919 msg.msg_flags = 0; /* flags on received message */
5922 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5927 buf = msg.msg_iov[0].iov_base;
5928 len = msg.msg_iov[0].iov_len;
5930 ret = libc_write(s, buf, len);
5932 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5937 ssize_t write(int s, const void *buf, size_t len)
5939 return swrap_write(s, buf, len);
5942 /****************************************************************************
5944 ***************************************************************************/
5946 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5950 struct sockaddr_un un_addr;
5953 struct socket_info *si = find_socket_info(s);
5956 return libc_send(s, buf, len, flags);
5959 tmp.iov_base = discard_const_p(char, buf);
5963 msg.msg_name = NULL; /* optional address */
5964 msg.msg_namelen = 0; /* size of address */
5965 msg.msg_iov = &tmp; /* scatter/gather array */
5966 msg.msg_iovlen = 1; /* # elements in msg_iov */
5967 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5968 msg.msg_control = NULL; /* ancillary data, see below */
5969 msg.msg_controllen = 0; /* ancillary data buffer len */
5970 msg.msg_flags = 0; /* flags on received message */
5973 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5978 buf = msg.msg_iov[0].iov_base;
5979 len = msg.msg_iov[0].iov_len;
5981 ret = libc_send(s, buf, len, flags);
5983 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5988 ssize_t send(int s, const void *buf, size_t len, int flags)
5990 return swrap_send(s, buf, len, flags);
5993 /****************************************************************************
5995 ***************************************************************************/
5997 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5999 struct swrap_address from_addr = {
6000 .sa_socklen = sizeof(struct sockaddr_un),
6002 struct swrap_address convert_addr = {
6003 .sa_socklen = sizeof(struct sockaddr_storage),
6005 struct socket_info *si;
6008 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6009 size_t msg_ctrllen_filled;
6010 size_t msg_ctrllen_left;
6016 si = find_socket_info(s);
6018 return libc_recvmsg(s, omsg, flags);
6021 tmp.iov_base = NULL;
6025 msg.msg_name = &from_addr.sa; /* optional address */
6026 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6027 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6028 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6029 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6030 msg_ctrllen_filled = 0;
6031 msg_ctrllen_left = omsg->msg_controllen;
6033 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6034 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6035 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6038 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6043 ret = libc_recvmsg(s, &msg, flags);
6045 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6046 msg_ctrllen_filled += msg.msg_controllen;
6047 msg_ctrllen_left -= msg.msg_controllen;
6049 if (omsg->msg_control != NULL) {
6052 p = omsg->msg_control;
6053 p += msg_ctrllen_filled;
6055 msg.msg_control = p;
6056 msg.msg_controllen = msg_ctrllen_left;
6058 msg.msg_control = NULL;
6059 msg.msg_controllen = 0;
6064 * We convert the unix address to a IP address so we need a buffer
6065 * which can store the address in case of SOCK_DGRAM, see below.
6067 msg.msg_name = &convert_addr.sa;
6068 msg.msg_namelen = convert_addr.sa_socklen;
6070 rc = swrap_recvmsg_after(s,
6074 from_addr.sa_socklen,
6080 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6081 if (omsg->msg_control != NULL) {
6082 /* msg.msg_controllen = space left */
6083 msg_ctrllen_left = msg.msg_controllen;
6084 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6087 /* Update the original message length */
6088 omsg->msg_controllen = msg_ctrllen_filled;
6089 omsg->msg_flags = msg.msg_flags;
6091 omsg->msg_iovlen = msg.msg_iovlen;
6098 * The msg_name field points to a caller-allocated buffer that is
6099 * used to return the source address if the socket is unconnected. The
6100 * caller should set msg_namelen to the size of this buffer before this
6101 * call; upon return from a successful call, msg_name will contain the
6102 * length of the returned address. If the application does not need
6103 * to know the source address, msg_name can be specified as NULL.
6105 if (si->type == SOCK_STREAM) {
6106 omsg->msg_namelen = 0;
6107 } else if (omsg->msg_name != NULL &&
6108 omsg->msg_namelen != 0 &&
6109 omsg->msg_namelen >= msg.msg_namelen) {
6110 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6111 omsg->msg_namelen = msg.msg_namelen;
6114 SWRAP_UNLOCK_SI(si);
6119 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6121 return swrap_recvmsg(sockfd, msg, flags);
6124 /****************************************************************************
6126 ***************************************************************************/
6128 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
6132 struct sockaddr_un un_addr;
6133 const struct sockaddr_un *to_un = NULL;
6134 const struct sockaddr *to = NULL;
6137 struct socket_info *si = find_socket_info(s);
6141 return libc_sendmsg(s, omsg, flags);
6144 ZERO_STRUCT(un_addr);
6146 tmp.iov_base = NULL;
6153 if (si->connected == 0) {
6154 msg.msg_name = omsg->msg_name; /* optional address */
6155 msg.msg_namelen = omsg->msg_namelen; /* size of address */
6157 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6158 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6160 SWRAP_UNLOCK_SI(si);
6162 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6163 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
6164 uint8_t *cmbuf = NULL;
6167 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
6173 msg.msg_controllen = 0;
6174 msg.msg_control = NULL;
6176 msg.msg_control = cmbuf;
6177 msg.msg_controllen = cmlen;
6180 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6182 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
6184 int saved_errno = errno;
6185 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6186 SAFE_FREE(msg.msg_control);
6188 errno = saved_errno;
6195 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6202 char *swrap_dir = NULL;
6204 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6205 avail += msg.msg_iov[i].iov_len;
6211 /* we capture it as one single packet */
6212 buf = (uint8_t *)malloc(remain);
6214 int saved_errno = errno;
6215 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6216 SAFE_FREE(msg.msg_control);
6218 errno = saved_errno;
6222 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6223 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
6225 msg.msg_iov[i].iov_base,
6228 remain -= this_time;
6231 type = SOCKET_TYPE_CHAR_UDP;
6233 swrap_dir = socket_wrapper_dir();
6234 if (swrap_dir == NULL) {
6235 int saved_errno = errno;
6236 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6237 SAFE_FREE(msg.msg_control);
6240 errno = saved_errno;
6244 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6245 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
6246 if (stat(un_addr.sun_path, &st) != 0) continue;
6248 msg.msg_name = &un_addr; /* optional address */
6249 msg.msg_namelen = sizeof(un_addr); /* size of address */
6251 /* ignore the any errors in broadcast sends */
6252 libc_sendmsg(s, &msg, flags);
6255 SAFE_FREE(swrap_dir);
6259 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6262 SWRAP_UNLOCK_SI(si);
6267 ret = libc_sendmsg(s, &msg, flags);
6269 swrap_sendmsg_after(s, si, &msg, to, ret);
6271 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6273 int saved_errno = errno;
6274 SAFE_FREE(msg.msg_control);
6275 errno = saved_errno;
6282 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
6284 return swrap_sendmsg(s, omsg, flags);
6287 /****************************************************************************
6289 ***************************************************************************/
6291 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
6293 struct socket_info *si;
6296 struct swrap_address saddr = {
6297 .sa_socklen = sizeof(struct sockaddr_storage)
6302 si = find_socket_info(s);
6304 return libc_readv(s, vector, count);
6307 tmp.iov_base = NULL;
6311 msg.msg_name = &saddr.sa.s; /* optional address */
6312 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6313 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6314 msg.msg_iovlen = count; /* # elements in msg_iov */
6315 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6316 msg.msg_control = NULL; /* ancillary data, see below */
6317 msg.msg_controllen = 0; /* ancillary data buffer len */
6318 msg.msg_flags = 0; /* flags on received message */
6321 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6323 if (rc == -ENOTSOCK) {
6324 return libc_readv(s, vector, count);
6329 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
6331 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6339 ssize_t readv(int s, const struct iovec *vector, int count)
6341 return swrap_readv(s, vector, count);
6344 /****************************************************************************
6346 ***************************************************************************/
6348 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6352 struct sockaddr_un un_addr;
6355 struct socket_info *si = find_socket_info(s);
6358 return libc_writev(s, vector, count);
6361 tmp.iov_base = NULL;
6365 msg.msg_name = NULL; /* optional address */
6366 msg.msg_namelen = 0; /* size of address */
6367 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6368 msg.msg_iovlen = count; /* # elements in msg_iov */
6369 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6370 msg.msg_control = NULL; /* ancillary data, see below */
6371 msg.msg_controllen = 0; /* ancillary data buffer len */
6372 msg.msg_flags = 0; /* flags on received message */
6375 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6377 if (rc == -ENOTSOCK) {
6378 return libc_readv(s, vector, count);
6383 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6385 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6390 ssize_t writev(int s, const struct iovec *vector, int count)
6392 return swrap_writev(s, vector, count);
6395 /****************************
6397 ***************************/
6399 static int swrap_close(int fd)
6401 struct socket_info *si = NULL;
6405 swrap_mutex_lock(&socket_reset_mutex);
6407 si_index = find_socket_info_index(fd);
6408 if (si_index == -1) {
6409 swrap_mutex_unlock(&socket_reset_mutex);
6410 return libc_close(fd);
6413 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
6414 reset_socket_info_index(fd);
6416 si = swrap_get_socket_info(si_index);
6418 swrap_mutex_lock(&first_free_mutex);
6421 ret = libc_close(fd);
6423 swrap_dec_refcount(si);
6425 if (swrap_get_refcount(si) > 0) {
6426 /* there are still references left */
6430 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6431 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6434 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6435 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6436 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6439 if (si->un_addr.sun_path[0] != '\0') {
6440 unlink(si->un_addr.sun_path);
6443 swrap_set_next_free(si, first_free);
6444 first_free = si_index;
6447 SWRAP_UNLOCK_SI(si);
6448 swrap_mutex_unlock(&first_free_mutex);
6449 swrap_mutex_unlock(&socket_reset_mutex);
6456 return swrap_close(fd);
6459 /****************************
6461 ***************************/
6463 static int swrap_dup(int fd)
6465 struct socket_info *si;
6468 idx = find_socket_info_index(fd);
6470 return libc_dup(fd);
6473 si = swrap_get_socket_info(idx);
6475 dup_fd = libc_dup(fd);
6477 int saved_errno = errno;
6478 errno = saved_errno;
6484 swrap_inc_refcount(si);
6486 SWRAP_UNLOCK_SI(si);
6488 /* Make sure we don't have an entry for the fd */
6489 swrap_remove_stale(dup_fd);
6491 set_socket_info_index(dup_fd, idx);
6498 return swrap_dup(fd);
6501 /****************************
6503 ***************************/
6505 static int swrap_dup2(int fd, int newfd)
6507 struct socket_info *si;
6510 idx = find_socket_info_index(fd);
6512 return libc_dup2(fd, newfd);
6515 si = swrap_get_socket_info(idx);
6519 * According to the manpage:
6521 * "If oldfd is a valid file descriptor, and newfd has the same
6522 * value as oldfd, then dup2() does nothing, and returns newfd."
6527 if (find_socket_info(newfd)) {
6528 /* dup2() does an implicit close of newfd, which we
6529 * need to emulate */
6533 dup_fd = libc_dup2(fd, newfd);
6535 int saved_errno = errno;
6536 errno = saved_errno;
6542 swrap_inc_refcount(si);
6544 SWRAP_UNLOCK_SI(si);
6546 /* Make sure we don't have an entry for the fd */
6547 swrap_remove_stale(dup_fd);
6549 set_socket_info_index(dup_fd, idx);
6554 int dup2(int fd, int newfd)
6556 return swrap_dup2(fd, newfd);
6559 /****************************
6561 ***************************/
6563 static int swrap_vfcntl(int fd, int cmd, va_list va)
6565 struct socket_info *si;
6566 int rc, dup_fd, idx;
6568 idx = find_socket_info_index(fd);
6570 return libc_vfcntl(fd, cmd, va);
6573 si = swrap_get_socket_info(idx);
6577 dup_fd = libc_vfcntl(fd, cmd, va);
6579 int saved_errno = errno;
6580 errno = saved_errno;
6586 swrap_inc_refcount(si);
6588 SWRAP_UNLOCK_SI(si);
6590 /* Make sure we don't have an entry for the fd */
6591 swrap_remove_stale(dup_fd);
6593 set_socket_info_index(dup_fd, idx);
6598 rc = libc_vfcntl(fd, cmd, va);
6605 int fcntl(int fd, int cmd, ...)
6612 rc = swrap_vfcntl(fd, cmd, va);
6619 /****************************
6621 ***************************/
6624 static int swrap_eventfd(int count, int flags)
6628 fd = libc_eventfd(count, flags);
6630 swrap_remove_stale(fd);
6636 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6637 int eventfd(unsigned int count, int flags)
6639 int eventfd(int count, int flags)
6642 return swrap_eventfd(count, flags);
6647 int pledge(const char *promises, const char *paths[])
6649 (void)promises; /* unused */
6650 (void)paths; /* unused */
6654 #endif /* HAVE_PLEDGE */
6656 static void swrap_thread_prepare(void)
6659 * This function should only be called here!!
6661 * We bind all symobls to avoid deadlocks of the fork is
6662 * interrupted by a signal handler using a symbol of this
6665 swrap_bind_symbol_all();
6670 static void swrap_thread_parent(void)
6675 static void swrap_thread_child(void)
6680 /****************************
6682 ***************************/
6683 void swrap_constructor(void)
6688 * If we hold a lock and the application forks, then the child
6689 * is not able to unlock the mutex and we are in a deadlock.
6690 * This should prevent such deadlocks.
6692 pthread_atfork(&swrap_thread_prepare,
6693 &swrap_thread_parent,
6694 &swrap_thread_child);
6697 /****************************
6699 ***************************/
6702 * This function is called when the library is unloaded and makes sure that
6703 * sockets get closed and the unix file for the socket are unlinked.
6705 void swrap_destructor(void)
6709 if (socket_fds_idx != NULL) {
6710 for (i = 0; i < socket_fds_max; ++i) {
6711 if (socket_fds_idx[i] != -1) {
6715 SAFE_FREE(socket_fds_idx);
6720 if (swrap.libc.handle != NULL) {
6721 dlclose(swrap.libc.handle);
6723 if (swrap.libc.socket_handle) {
6724 dlclose(swrap.libc.socket_handle);
6728 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
6730 * On FreeBSD 12 (and maybe other platforms)
6731 * system libraries like libresolv prefix there
6732 * syscalls with '_' in order to always use
6733 * the symbols from libc.
6735 * In the interaction with resolv_wrapper,
6736 * we need to inject socket wrapper into libresolv,
6737 * which means we need to private all socket
6738 * related syscalls also with the '_' prefix.
6740 * This is tested in Samba's 'make test',
6741 * there we noticed that providing '_read'
6742 * and '_open' would cause errors, which
6743 * means we skip '_read', '_write' and
6744 * all non socket related calls without
6745 * further analyzing the problem.
6747 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
6748 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
6751 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
6753 SWRAP_SYMBOL_ALIAS(accept, _accept);
6754 SWRAP_SYMBOL_ALIAS(bind, _bind);
6755 SWRAP_SYMBOL_ALIAS(close, _close);
6756 SWRAP_SYMBOL_ALIAS(connect, _connect);
6757 SWRAP_SYMBOL_ALIAS(dup, _dup);
6758 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
6759 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
6760 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
6761 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
6762 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
6763 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
6764 SWRAP_SYMBOL_ALIAS(listen, _listen);
6765 SWRAP_SYMBOL_ALIAS(readv, _readv);
6766 SWRAP_SYMBOL_ALIAS(recv, _recv);
6767 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
6768 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
6769 SWRAP_SYMBOL_ALIAS(send, _send);
6770 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
6771 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
6772 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
6773 SWRAP_SYMBOL_ALIAS(socket, _socket);
6774 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
6775 SWRAP_SYMBOL_ALIAS(writev, _writev);
6777 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */