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(const 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, "
1861 idx = swrap_add_socket_info(si);
1866 set_socket_info_index(fd, idx);
1871 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1878 p = strrchr(un->sun_path, '/');
1879 if (p) p++; else p = un->sun_path;
1881 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1886 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1889 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1900 case SOCKET_TYPE_CHAR_TCP:
1901 case SOCKET_TYPE_CHAR_UDP: {
1902 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1904 if ((*len) < sizeof(*in2)) {
1909 memset(in2, 0, sizeof(*in2));
1910 in2->sin_family = AF_INET;
1911 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1912 in2->sin_port = htons(prt);
1914 *len = sizeof(*in2);
1918 case SOCKET_TYPE_CHAR_TCP_V6:
1919 case SOCKET_TYPE_CHAR_UDP_V6: {
1920 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1922 if ((*len) < sizeof(*in2)) {
1927 memset(in2, 0, sizeof(*in2));
1928 in2->sin6_family = AF_INET6;
1929 in2->sin6_addr = *swrap_ipv6();
1930 in2->sin6_addr.s6_addr[15] = iface;
1931 in2->sin6_port = htons(prt);
1933 *len = sizeof(*in2);
1945 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1952 char *swrap_dir = NULL;
1954 if (bcast) *bcast = 0;
1956 switch (inaddr->sa_family) {
1958 const struct sockaddr_in *in =
1959 (const struct sockaddr_in *)(const void *)inaddr;
1960 unsigned int addr = ntohl(in->sin_addr.s_addr);
1964 const unsigned int sw_net_addr = swrap_ipv4_net();
1965 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1969 u_type = SOCKET_TYPE_CHAR_TCP;
1972 u_type = SOCKET_TYPE_CHAR_UDP;
1973 a_type = SOCKET_TYPE_CHAR_UDP;
1974 b_type = SOCKET_TYPE_CHAR_UDP;
1977 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1978 errno = ESOCKTNOSUPPORT;
1982 prt = ntohs(in->sin_port);
1983 if (a_type && addr == 0xFFFFFFFF) {
1984 /* 255.255.255.255 only udp */
1987 iface = socket_wrapper_default_iface();
1988 } else if (b_type && addr == sw_bcast_addr) {
1997 iface = socket_wrapper_default_iface();
1998 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
1999 /* 127.0.0.X or 10.53.57.X */
2002 iface = (addr & 0x000000FF);
2004 errno = ENETUNREACH;
2007 if (bcast) *bcast = is_bcast;
2012 const struct sockaddr_in6 *in =
2013 (const struct sockaddr_in6 *)(const void *)inaddr;
2014 struct in6_addr cmp1, cmp2;
2018 type = SOCKET_TYPE_CHAR_TCP_V6;
2021 type = SOCKET_TYPE_CHAR_UDP_V6;
2024 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2025 errno = ESOCKTNOSUPPORT;
2029 /* XXX no multicast/broadcast */
2031 prt = ntohs(in->sin6_port);
2033 cmp1 = *swrap_ipv6();
2034 cmp2 = in->sin6_addr;
2035 cmp2.s6_addr[15] = 0;
2036 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2037 iface = in->sin6_addr.s6_addr[15];
2039 errno = ENETUNREACH;
2047 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2048 errno = ENETUNREACH;
2053 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2058 swrap_dir = socket_wrapper_dir();
2059 if (swrap_dir == NULL) {
2065 swrap_un_path_EINVAL(un, swrap_dir);
2066 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2067 SAFE_FREE(swrap_dir);
2068 /* the caller need to do more processing */
2072 swrap_un_path(un, swrap_dir, type, iface, prt);
2073 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2075 SAFE_FREE(swrap_dir);
2080 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2088 char *swrap_dir = NULL;
2090 if (bcast) *bcast = 0;
2092 switch (si->family) {
2094 const struct sockaddr_in *in =
2095 (const struct sockaddr_in *)(const void *)inaddr;
2096 unsigned int addr = ntohl(in->sin_addr.s_addr);
2101 const unsigned int sw_net_addr = swrap_ipv4_net();
2102 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2104 prt = ntohs(in->sin_port);
2108 u_type = SOCKET_TYPE_CHAR_TCP;
2109 d_type = SOCKET_TYPE_CHAR_TCP;
2112 u_type = SOCKET_TYPE_CHAR_UDP;
2113 d_type = SOCKET_TYPE_CHAR_UDP;
2114 a_type = SOCKET_TYPE_CHAR_UDP;
2115 b_type = SOCKET_TYPE_CHAR_UDP;
2118 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2119 errno = ESOCKTNOSUPPORT;
2127 iface = socket_wrapper_default_iface();
2128 } else if (a_type && addr == 0xFFFFFFFF) {
2129 /* 255.255.255.255 only udp */
2132 iface = socket_wrapper_default_iface();
2133 } else if (b_type && addr == sw_bcast_addr) {
2134 /* 127.255.255.255 only udp */
2137 iface = socket_wrapper_default_iface();
2138 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2142 iface = (addr & 0x000000FF);
2144 errno = EADDRNOTAVAIL;
2148 /* Store the bind address for connect() */
2149 if (si->bindname.sa_socklen == 0) {
2150 struct sockaddr_in bind_in;
2151 socklen_t blen = sizeof(struct sockaddr_in);
2153 ZERO_STRUCT(bind_in);
2154 bind_in.sin_family = in->sin_family;
2155 bind_in.sin_port = in->sin_port;
2156 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2157 si->bindname.sa_socklen = blen;
2158 memcpy(&si->bindname.sa.in, &bind_in, blen);
2165 const struct sockaddr_in6 *in =
2166 (const struct sockaddr_in6 *)(const void *)inaddr;
2167 struct in6_addr cmp1, cmp2;
2171 type = SOCKET_TYPE_CHAR_TCP_V6;
2174 type = SOCKET_TYPE_CHAR_UDP_V6;
2177 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2178 errno = ESOCKTNOSUPPORT;
2182 /* XXX no multicast/broadcast */
2184 prt = ntohs(in->sin6_port);
2186 cmp1 = *swrap_ipv6();
2187 cmp2 = in->sin6_addr;
2188 cmp2.s6_addr[15] = 0;
2189 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2190 iface = socket_wrapper_default_iface();
2191 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2192 iface = in->sin6_addr.s6_addr[15];
2194 errno = EADDRNOTAVAIL;
2198 /* Store the bind address for connect() */
2199 if (si->bindname.sa_socklen == 0) {
2200 struct sockaddr_in6 bind_in;
2201 socklen_t blen = sizeof(struct sockaddr_in6);
2203 ZERO_STRUCT(bind_in);
2204 bind_in.sin6_family = in->sin6_family;
2205 bind_in.sin6_port = in->sin6_port;
2207 bind_in.sin6_addr = *swrap_ipv6();
2208 bind_in.sin6_addr.s6_addr[15] = iface;
2210 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2211 si->bindname.sa_socklen = blen;
2218 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2219 errno = EADDRNOTAVAIL;
2224 if (bcast) *bcast = is_bcast;
2226 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2231 swrap_dir = socket_wrapper_dir();
2232 if (swrap_dir == NULL) {
2238 /* handle auto-allocation of ephemeral ports */
2239 for (prt = 5001; prt < 10000; prt++) {
2240 swrap_un_path(un, swrap_dir, type, iface, prt);
2241 if (stat(un->sun_path, &st) == 0) continue;
2243 set_port(si->family, prt, &si->myname);
2244 set_port(si->family, prt, &si->bindname);
2251 SAFE_FREE(swrap_dir);
2256 swrap_un_path(un, swrap_dir, type, iface, prt);
2257 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2259 SAFE_FREE(swrap_dir);
2264 static struct socket_info *find_socket_info(int fd)
2266 int idx = find_socket_info_index(fd);
2272 return swrap_get_socket_info(idx);
2276 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2278 struct socket_info_fd *f;
2279 const struct socket_info *last_s = NULL;
2281 /* first catch invalid input */
2282 switch (sa->sa_family) {
2284 if (len < sizeof(struct sockaddr_in)) {
2290 if (len < sizeof(struct sockaddr_in6)) {
2300 for (f = socket_fds; f; f = f->next) {
2301 struct socket_info *s = swrap_get_socket_info(f->si_index);
2308 if (s->myname == NULL) {
2311 if (s->myname->sa_family != sa->sa_family) {
2314 switch (s->myname->sa_family) {
2316 struct sockaddr_in *sin1, *sin2;
2318 sin1 = (struct sockaddr_in *)s->myname;
2319 sin2 = (struct sockaddr_in *)sa;
2321 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2324 if (sin1->sin_port != sin2->sin_port) {
2327 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2337 struct sockaddr_in6 *sin1, *sin2;
2339 sin1 = (struct sockaddr_in6 *)s->myname;
2340 sin2 = (struct sockaddr_in6 *)sa;
2342 if (sin1->sin6_port != sin2->sin6_port) {
2345 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2367 static void swrap_remove_stale(int fd)
2369 struct socket_info *si;
2372 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2374 swrap_mutex_lock(&socket_reset_mutex);
2376 si_index = find_socket_info_index(fd);
2377 if (si_index == -1) {
2378 swrap_mutex_unlock(&socket_reset_mutex);
2382 reset_socket_info_index(fd);
2384 si = swrap_get_socket_info(si_index);
2386 swrap_mutex_lock(&first_free_mutex);
2389 swrap_dec_refcount(si);
2391 if (swrap_get_refcount(si) > 0) {
2395 if (si->un_addr.sun_path[0] != '\0') {
2396 unlink(si->un_addr.sun_path);
2399 swrap_set_next_free(si, first_free);
2400 first_free = si_index;
2403 SWRAP_UNLOCK_SI(si);
2404 swrap_mutex_unlock(&first_free_mutex);
2405 swrap_mutex_unlock(&socket_reset_mutex);
2408 static int sockaddr_convert_to_un(struct socket_info *si,
2409 const struct sockaddr *in_addr,
2411 struct sockaddr_un *out_addr,
2415 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2417 (void) in_len; /* unused */
2419 if (out_addr == NULL) {
2423 out->sa_family = AF_UNIX;
2424 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2425 out->sa_len = sizeof(*out_addr);
2428 switch (in_addr->sa_family) {
2430 const struct sockaddr_in *sin;
2431 if (si->family != AF_INET) {
2434 if (in_len < sizeof(struct sockaddr_in)) {
2437 sin = (const struct sockaddr_in *)(const void *)in_addr;
2438 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2443 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2444 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2458 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2459 errno = ESOCKTNOSUPPORT;
2463 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2465 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2471 errno = EAFNOSUPPORT;
2472 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2476 static int sockaddr_convert_from_un(const struct socket_info *si,
2477 const struct sockaddr_un *in_addr,
2478 socklen_t un_addrlen,
2480 struct sockaddr *out_addr,
2481 socklen_t *out_addrlen)
2485 if (out_addr == NULL || out_addrlen == NULL)
2488 if (un_addrlen == 0) {
2503 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2504 errno = ESOCKTNOSUPPORT;
2507 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2508 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2509 out_addr->sa_len = *out_addrlen;
2516 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2517 errno = EAFNOSUPPORT;
2521 enum swrap_packet_type {
2523 SWRAP_CONNECT_UNREACH,
2531 SWRAP_SENDTO_UNREACH,
2542 struct swrap_file_hdr {
2544 uint16_t version_major;
2545 uint16_t version_minor;
2548 uint32_t frame_max_len;
2549 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2552 #define SWRAP_FILE_HDR_SIZE 24
2554 struct swrap_packet_frame {
2556 uint32_t micro_seconds;
2557 uint32_t recorded_length;
2558 uint32_t full_length;
2560 #define SWRAP_PACKET_FRAME_SIZE 16
2562 union swrap_packet_ip {
2566 uint16_t packet_length;
2567 uint16_t identification;
2572 uint16_t hdr_checksum;
2576 #define SWRAP_PACKET_IP_V4_SIZE 20
2579 uint8_t flow_label_high;
2580 uint16_t flow_label_low;
2581 uint16_t payload_length;
2582 uint8_t next_header;
2584 uint8_t src_addr[16];
2585 uint8_t dest_addr[16];
2587 #define SWRAP_PACKET_IP_V6_SIZE 40
2589 #define SWRAP_PACKET_IP_SIZE 40
2591 union swrap_packet_payload {
2593 uint16_t source_port;
2603 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2605 uint16_t source_port;
2610 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2617 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2624 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2626 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2628 #define SWRAP_PACKET_MIN_ALLOC \
2629 (SWRAP_PACKET_FRAME_SIZE + \
2630 SWRAP_PACKET_IP_SIZE + \
2631 SWRAP_PACKET_PAYLOAD_SIZE)
2633 static const char *swrap_pcap_init_file(void)
2635 static int initialized = 0;
2636 static const char *s = NULL;
2637 static const struct swrap_file_hdr h;
2638 static const struct swrap_packet_frame f;
2639 static const union swrap_packet_ip i;
2640 static const union swrap_packet_payload p;
2642 if (initialized == 1) {
2648 * TODO: don't use the structs use plain buffer offsets
2649 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2651 * for now make sure we disable PCAP support
2652 * if the struct has alignment!
2654 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2657 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2660 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2663 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2666 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2669 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2672 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2675 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2678 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2681 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2685 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2689 if (strncmp(s, "./", 2) == 0) {
2692 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2696 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2697 const struct sockaddr *src,
2698 const struct sockaddr *dest,
2700 const uint8_t *payload,
2702 unsigned long tcp_seqno,
2703 unsigned long tcp_ack,
2704 unsigned char tcp_ctl,
2706 size_t *_packet_len)
2708 uint8_t *base = NULL;
2709 uint8_t *buf = NULL;
2712 struct swrap_packet_frame *frame;
2716 union swrap_packet_ip *ip;
2718 union swrap_packet_payload *pay;
2721 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2722 size_t wire_hdr_len = 0;
2723 size_t wire_len = 0;
2724 size_t ip_hdr_len = 0;
2725 size_t icmp_hdr_len = 0;
2726 size_t icmp_truncate_len = 0;
2727 uint8_t protocol = 0, icmp_protocol = 0;
2728 const struct sockaddr_in *src_in = NULL;
2729 const struct sockaddr_in *dest_in = NULL;
2731 const struct sockaddr_in6 *src_in6 = NULL;
2732 const struct sockaddr_in6 *dest_in6 = NULL;
2737 switch (src->sa_family) {
2739 src_in = (const struct sockaddr_in *)(const void *)src;
2740 dest_in = (const struct sockaddr_in *)(const void *)dest;
2741 src_port = src_in->sin_port;
2742 dest_port = dest_in->sin_port;
2743 ip_hdr_len = sizeof(i.ip->v4);
2747 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2748 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2749 src_port = src_in6->sin6_port;
2750 dest_port = dest_in6->sin6_port;
2751 ip_hdr_len = sizeof(i.ip->v6);
2758 switch (socket_type) {
2760 protocol = 0x06; /* TCP */
2761 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2762 wire_len = wire_hdr_len + payload_len;
2766 protocol = 0x11; /* UDP */
2767 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2768 wire_len = wire_hdr_len + payload_len;
2776 icmp_protocol = protocol;
2777 switch (src->sa_family) {
2779 protocol = 0x01; /* ICMPv4 */
2780 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2784 protocol = 0x3A; /* ICMPv6 */
2785 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2789 if (wire_len > 64 ) {
2790 icmp_truncate_len = wire_len - 64;
2792 wire_len += icmp_hdr_len;
2795 packet_len = nonwire_len + wire_len;
2796 alloc_len = packet_len;
2797 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2798 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2801 base = (uint8_t *)calloc(1, alloc_len);
2809 f.frame->seconds = tval->tv_sec;
2810 f.frame->micro_seconds = tval->tv_usec;
2811 f.frame->recorded_length = wire_len - icmp_truncate_len;
2812 f.frame->full_length = wire_len - icmp_truncate_len;
2814 buf += SWRAP_PACKET_FRAME_SIZE;
2817 switch (src->sa_family) {
2819 if (src_in == NULL || dest_in == NULL) {
2824 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2825 i.ip->v4.tos = 0x00;
2826 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2827 i.ip->v4.identification = htons(0xFFFF);
2828 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2829 i.ip->v4.fragment = htons(0x0000);
2830 i.ip->v4.ttl = 0xFF;
2831 i.ip->v4.protocol = protocol;
2832 i.ip->v4.hdr_checksum = htons(0x0000);
2833 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2834 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2835 buf += SWRAP_PACKET_IP_V4_SIZE;
2839 if (src_in6 == NULL || dest_in6 == NULL) {
2844 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2845 i.ip->v6.flow_label_high = 0x00;
2846 i.ip->v6.flow_label_low = 0x0000;
2847 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2848 i.ip->v6.next_header = protocol;
2849 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2850 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2851 buf += SWRAP_PACKET_IP_V6_SIZE;
2857 pay = (union swrap_packet_payload *)(void *)buf;
2858 switch (src->sa_family) {
2860 pay->icmp4.type = 0x03; /* destination unreachable */
2861 pay->icmp4.code = 0x01; /* host unreachable */
2862 pay->icmp4.checksum = htons(0x0000);
2863 pay->icmp4.unused = htonl(0x00000000);
2865 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2867 /* set the ip header in the ICMP payload */
2869 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2870 i.ip->v4.tos = 0x00;
2871 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2872 i.ip->v4.identification = htons(0xFFFF);
2873 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2874 i.ip->v4.fragment = htons(0x0000);
2875 i.ip->v4.ttl = 0xFF;
2876 i.ip->v4.protocol = icmp_protocol;
2877 i.ip->v4.hdr_checksum = htons(0x0000);
2878 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2879 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2881 buf += SWRAP_PACKET_IP_V4_SIZE;
2883 src_port = dest_in->sin_port;
2884 dest_port = src_in->sin_port;
2888 pay->icmp6.type = 0x01; /* destination unreachable */
2889 pay->icmp6.code = 0x03; /* address unreachable */
2890 pay->icmp6.checksum = htons(0x0000);
2891 pay->icmp6.unused = htonl(0x00000000);
2892 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2894 /* set the ip header in the ICMP payload */
2896 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2897 i.ip->v6.flow_label_high = 0x00;
2898 i.ip->v6.flow_label_low = 0x0000;
2899 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2900 i.ip->v6.next_header = protocol;
2901 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2902 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2904 buf += SWRAP_PACKET_IP_V6_SIZE;
2906 src_port = dest_in6->sin6_port;
2907 dest_port = src_in6->sin6_port;
2913 pay = (union swrap_packet_payload *)(void *)buf;
2915 switch (socket_type) {
2917 pay->tcp.source_port = src_port;
2918 pay->tcp.dest_port = dest_port;
2919 pay->tcp.seq_num = htonl(tcp_seqno);
2920 pay->tcp.ack_num = htonl(tcp_ack);
2921 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2922 pay->tcp.control = tcp_ctl;
2923 pay->tcp.window = htons(0x7FFF);
2924 pay->tcp.checksum = htons(0x0000);
2925 pay->tcp.urg = htons(0x0000);
2926 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2931 pay->udp.source_port = src_port;
2932 pay->udp.dest_port = dest_port;
2933 pay->udp.length = htons(8 + payload_len);
2934 pay->udp.checksum = htons(0x0000);
2935 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2940 if (payload && payload_len > 0) {
2941 memcpy(buf, payload, payload_len);
2944 *_packet_len = packet_len - icmp_truncate_len;
2948 static int swrap_pcap_get_fd(const char *fname)
2956 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2958 struct swrap_file_hdr file_hdr;
2959 file_hdr.magic = 0xA1B2C3D4;
2960 file_hdr.version_major = 0x0002;
2961 file_hdr.version_minor = 0x0004;
2962 file_hdr.timezone = 0x00000000;
2963 file_hdr.sigfigs = 0x00000000;
2964 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2965 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2967 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2974 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2979 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2980 const struct sockaddr *addr,
2981 enum swrap_packet_type type,
2982 const void *buf, size_t len,
2985 const struct sockaddr *src_addr;
2986 const struct sockaddr *dest_addr;
2987 unsigned long tcp_seqno = 0;
2988 unsigned long tcp_ack = 0;
2989 unsigned char tcp_ctl = 0;
2990 int unreachable = 0;
2994 switch (si->family) {
3006 case SWRAP_CONNECT_SEND:
3007 if (si->type != SOCK_STREAM) {
3011 src_addr = &si->myname.sa.s;
3014 tcp_seqno = si->io.pck_snd;
3015 tcp_ack = si->io.pck_rcv;
3016 tcp_ctl = 0x02; /* SYN */
3018 si->io.pck_snd += 1;
3022 case SWRAP_CONNECT_RECV:
3023 if (si->type != SOCK_STREAM) {
3027 dest_addr = &si->myname.sa.s;
3030 tcp_seqno = si->io.pck_rcv;
3031 tcp_ack = si->io.pck_snd;
3032 tcp_ctl = 0x12; /** SYN,ACK */
3034 si->io.pck_rcv += 1;
3038 case SWRAP_CONNECT_UNREACH:
3039 if (si->type != SOCK_STREAM) {
3043 dest_addr = &si->myname.sa.s;
3046 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3047 tcp_seqno = si->io.pck_snd - 1;
3048 tcp_ack = si->io.pck_rcv;
3049 tcp_ctl = 0x02; /* SYN */
3054 case SWRAP_CONNECT_ACK:
3055 if (si->type != SOCK_STREAM) {
3059 src_addr = &si->myname.sa.s;
3062 tcp_seqno = si->io.pck_snd;
3063 tcp_ack = si->io.pck_rcv;
3064 tcp_ctl = 0x10; /* ACK */
3068 case SWRAP_ACCEPT_SEND:
3069 if (si->type != SOCK_STREAM) {
3073 dest_addr = &si->myname.sa.s;
3076 tcp_seqno = si->io.pck_rcv;
3077 tcp_ack = si->io.pck_snd;
3078 tcp_ctl = 0x02; /* SYN */
3080 si->io.pck_rcv += 1;
3084 case SWRAP_ACCEPT_RECV:
3085 if (si->type != SOCK_STREAM) {
3089 src_addr = &si->myname.sa.s;
3092 tcp_seqno = si->io.pck_snd;
3093 tcp_ack = si->io.pck_rcv;
3094 tcp_ctl = 0x12; /* SYN,ACK */
3096 si->io.pck_snd += 1;
3100 case SWRAP_ACCEPT_ACK:
3101 if (si->type != SOCK_STREAM) {
3105 dest_addr = &si->myname.sa.s;
3108 tcp_seqno = si->io.pck_rcv;
3109 tcp_ack = si->io.pck_snd;
3110 tcp_ctl = 0x10; /* ACK */
3115 src_addr = &si->myname.sa.s;
3116 dest_addr = &si->peername.sa.s;
3118 tcp_seqno = si->io.pck_snd;
3119 tcp_ack = si->io.pck_rcv;
3120 tcp_ctl = 0x18; /* PSH,ACK */
3122 si->io.pck_snd += len;
3126 case SWRAP_SEND_RST:
3127 dest_addr = &si->myname.sa.s;
3128 src_addr = &si->peername.sa.s;
3130 if (si->type == SOCK_DGRAM) {
3131 return swrap_pcap_marshall_packet(si,
3133 SWRAP_SENDTO_UNREACH,
3139 tcp_seqno = si->io.pck_rcv;
3140 tcp_ack = si->io.pck_snd;
3141 tcp_ctl = 0x14; /** RST,ACK */
3145 case SWRAP_PENDING_RST:
3146 dest_addr = &si->myname.sa.s;
3147 src_addr = &si->peername.sa.s;
3149 if (si->type == SOCK_DGRAM) {
3153 tcp_seqno = si->io.pck_rcv;
3154 tcp_ack = si->io.pck_snd;
3155 tcp_ctl = 0x14; /* RST,ACK */
3160 dest_addr = &si->myname.sa.s;
3161 src_addr = &si->peername.sa.s;
3163 tcp_seqno = si->io.pck_rcv;
3164 tcp_ack = si->io.pck_snd;
3165 tcp_ctl = 0x18; /* PSH,ACK */
3167 si->io.pck_rcv += len;
3171 case SWRAP_RECV_RST:
3172 dest_addr = &si->myname.sa.s;
3173 src_addr = &si->peername.sa.s;
3175 if (si->type == SOCK_DGRAM) {
3179 tcp_seqno = si->io.pck_rcv;
3180 tcp_ack = si->io.pck_snd;
3181 tcp_ctl = 0x14; /* RST,ACK */
3186 src_addr = &si->myname.sa.s;
3189 si->io.pck_snd += len;
3193 case SWRAP_SENDTO_UNREACH:
3194 dest_addr = &si->myname.sa.s;
3201 case SWRAP_RECVFROM:
3202 dest_addr = &si->myname.sa.s;
3205 si->io.pck_rcv += len;
3209 case SWRAP_CLOSE_SEND:
3210 if (si->type != SOCK_STREAM) {
3214 src_addr = &si->myname.sa.s;
3215 dest_addr = &si->peername.sa.s;
3217 tcp_seqno = si->io.pck_snd;
3218 tcp_ack = si->io.pck_rcv;
3219 tcp_ctl = 0x11; /* FIN, ACK */
3221 si->io.pck_snd += 1;
3225 case SWRAP_CLOSE_RECV:
3226 if (si->type != SOCK_STREAM) {
3230 dest_addr = &si->myname.sa.s;
3231 src_addr = &si->peername.sa.s;
3233 tcp_seqno = si->io.pck_rcv;
3234 tcp_ack = si->io.pck_snd;
3235 tcp_ctl = 0x11; /* FIN,ACK */
3237 si->io.pck_rcv += 1;
3241 case SWRAP_CLOSE_ACK:
3242 if (si->type != SOCK_STREAM) {
3246 src_addr = &si->myname.sa.s;
3247 dest_addr = &si->peername.sa.s;
3249 tcp_seqno = si->io.pck_snd;
3250 tcp_ack = si->io.pck_rcv;
3251 tcp_ctl = 0x10; /* ACK */
3258 swrapGetTimeOfDay(&tv);
3260 return swrap_pcap_packet_init(&tv,
3264 (const uint8_t *)buf,
3273 static void swrap_pcap_dump_packet(struct socket_info *si,
3274 const struct sockaddr *addr,
3275 enum swrap_packet_type type,
3276 const void *buf, size_t len)
3278 const char *file_name;
3280 size_t packet_len = 0;
3283 swrap_mutex_lock(&pcap_dump_mutex);
3285 file_name = swrap_pcap_init_file();
3290 packet = swrap_pcap_marshall_packet(si,
3296 if (packet == NULL) {
3300 fd = swrap_pcap_get_fd(file_name);
3302 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3311 swrap_mutex_unlock(&pcap_dump_mutex);
3314 /****************************************************************************
3316 ***************************************************************************/
3318 #ifdef HAVE_SIGNALFD
3319 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3323 rc = libc_signalfd(fd, mask, flags);
3325 swrap_remove_stale(fd);
3331 int signalfd(int fd, const sigset_t *mask, int flags)
3333 return swrap_signalfd(fd, mask, flags);
3337 /****************************************************************************
3339 ***************************************************************************/
3341 static int swrap_socket(int family, int type, int protocol)
3343 struct socket_info *si = NULL;
3344 struct socket_info _si = { 0 };
3347 int real_type = type;
3350 * Remove possible addition flags passed to socket() so
3351 * do not fail checking the type.
3352 * See https://lwn.net/Articles/281965/
3355 real_type &= ~SOCK_CLOEXEC;
3357 #ifdef SOCK_NONBLOCK
3358 real_type &= ~SOCK_NONBLOCK;
3361 if (!socket_wrapper_enabled()) {
3362 return libc_socket(family, type, protocol);
3373 #endif /* AF_NETLINK */
3376 #endif /* AF_PACKET */
3378 fd = libc_socket(family, type, protocol);
3380 /* Check if we have a stale fd and remove it */
3381 swrap_remove_stale(fd);
3382 SWRAP_LOG(SWRAP_LOG_TRACE,
3383 "Unix socket fd=%d",
3388 errno = EAFNOSUPPORT;
3392 switch (real_type) {
3398 errno = EPROTONOSUPPORT;
3406 if (real_type == SOCK_STREAM) {
3411 if (real_type == SOCK_DGRAM) {
3416 errno = EPROTONOSUPPORT;
3421 * We must call libc_socket with type, from the caller, not the version
3422 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3424 fd = libc_socket(AF_UNIX, type, 0);
3430 /* Check if we have a stale fd and remove it */
3431 swrap_remove_stale(fd);
3434 si->family = family;
3436 /* however, the rest of the socket_wrapper code expects just
3437 * the type, not the flags */
3438 si->type = real_type;
3439 si->protocol = protocol;
3442 * Setup myname so getsockname() can succeed to find out the socket
3445 switch(si->family) {
3447 struct sockaddr_in sin = {
3448 .sin_family = AF_INET,
3451 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3452 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3457 struct sockaddr_in6 sin6 = {
3458 .sin6_family = AF_INET6,
3461 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3462 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3471 ret = swrap_create_socket(si, fd);
3473 int saved_errno = errno;
3475 errno = saved_errno;
3479 SWRAP_LOG(SWRAP_LOG_TRACE,
3480 "Created %s socket for protocol %s, fd=%d",
3481 family == AF_INET ? "IPv4" : "IPv6",
3482 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3488 int socket(int family, int type, int protocol)
3490 return swrap_socket(family, type, protocol);
3493 /****************************************************************************
3495 ***************************************************************************/
3497 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3501 rc = libc_socketpair(family, type, protocol, sv);
3503 swrap_remove_stale(sv[0]);
3504 swrap_remove_stale(sv[1]);
3510 int socketpair(int family, int type, int protocol, int sv[2])
3512 return swrap_socketpair(family, type, protocol, sv);
3515 /****************************************************************************
3517 ***************************************************************************/
3519 #ifdef HAVE_TIMERFD_CREATE
3520 static int swrap_timerfd_create(int clockid, int flags)
3524 fd = libc_timerfd_create(clockid, flags);
3526 swrap_remove_stale(fd);
3532 int timerfd_create(int clockid, int flags)
3534 return swrap_timerfd_create(clockid, flags);
3538 /****************************************************************************
3540 ***************************************************************************/
3542 static int swrap_pipe(int pipefd[2])
3546 rc = libc_pipe(pipefd);
3548 swrap_remove_stale(pipefd[0]);
3549 swrap_remove_stale(pipefd[1]);
3555 int pipe(int pipefd[2])
3557 return swrap_pipe(pipefd);
3560 /****************************************************************************
3562 ***************************************************************************/
3564 static int swrap_accept(int s,
3565 struct sockaddr *addr,
3569 struct socket_info *parent_si, *child_si;
3570 struct socket_info new_si = { 0 };
3573 struct swrap_address un_addr = {
3574 .sa_socklen = sizeof(struct sockaddr_un),
3576 struct swrap_address un_my_addr = {
3577 .sa_socklen = sizeof(struct sockaddr_un),
3579 struct swrap_address in_addr = {
3580 .sa_socklen = sizeof(struct sockaddr_storage),
3582 struct swrap_address in_my_addr = {
3583 .sa_socklen = sizeof(struct sockaddr_storage),
3587 parent_si = find_socket_info(s);
3590 return libc_accept4(s, addr, addrlen, flags);
3593 return libc_accept(s, addr, addrlen);
3599 * prevent parent_si from being altered / closed
3602 SWRAP_LOCK_SI(parent_si);
3605 * assume out sockaddr have the same size as the in parent
3608 in_addr.sa_socklen = socket_length(parent_si->family);
3609 if (in_addr.sa_socklen <= 0) {
3610 SWRAP_UNLOCK_SI(parent_si);
3615 SWRAP_UNLOCK_SI(parent_si);
3618 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3621 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3624 if (errno == ENOTSOCK) {
3625 /* Remove stale fds */
3626 swrap_remove_stale(s);
3633 /* Check if we have a stale fd and remove it */
3634 swrap_remove_stale(fd);
3636 SWRAP_LOCK_SI(parent_si);
3638 ret = sockaddr_convert_from_un(parent_si,
3643 &in_addr.sa_socklen);
3645 SWRAP_UNLOCK_SI(parent_si);
3652 child_si->family = parent_si->family;
3653 child_si->type = parent_si->type;
3654 child_si->protocol = parent_si->protocol;
3655 child_si->bound = 1;
3656 child_si->is_server = 1;
3657 child_si->connected = 1;
3659 SWRAP_UNLOCK_SI(parent_si);
3661 child_si->peername = (struct swrap_address) {
3662 .sa_socklen = in_addr.sa_socklen,
3664 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3666 if (addr != NULL && addrlen != NULL) {
3667 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3669 memcpy(addr, &in_addr.sa.ss, copy_len);
3671 *addrlen = in_addr.sa_socklen;
3674 ret = libc_getsockname(fd,
3676 &un_my_addr.sa_socklen);
3682 ret = sockaddr_convert_from_un(child_si,
3684 un_my_addr.sa_socklen,
3687 &in_my_addr.sa_socklen);
3693 SWRAP_LOG(SWRAP_LOG_TRACE,
3694 "accept() path=%s, fd=%d",
3695 un_my_addr.sa.un.sun_path, s);
3697 child_si->myname = (struct swrap_address) {
3698 .sa_socklen = in_my_addr.sa_socklen,
3700 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3702 idx = swrap_create_socket(&new_si, fd);
3704 int saved_errno = errno;
3706 errno = saved_errno;
3711 struct socket_info *si = swrap_get_socket_info(idx);
3714 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3715 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3716 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3717 SWRAP_UNLOCK_SI(si);
3724 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3726 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3730 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3731 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3733 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3736 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3739 static int autobind_start_init;
3740 static int autobind_start;
3742 /* using sendto() or connect() on an unbound socket would give the
3743 recipient no way to reply, as unlike UDP and TCP, a unix domain
3744 socket can't auto-assign ephemeral port numbers, so we need to
3746 Note: this might change the family from ipv6 to ipv4
3748 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3750 struct swrap_address un_addr = {
3751 .sa_socklen = sizeof(struct sockaddr_un),
3758 char *swrap_dir = NULL;
3760 swrap_mutex_lock(&autobind_start_mutex);
3762 if (autobind_start_init != 1) {
3763 autobind_start_init = 1;
3764 autobind_start = getpid();
3765 autobind_start %= 50000;
3766 autobind_start += 10000;
3769 un_addr.sa.un.sun_family = AF_UNIX;
3773 struct sockaddr_in in;
3777 type = SOCKET_TYPE_CHAR_TCP;
3780 type = SOCKET_TYPE_CHAR_UDP;
3783 errno = ESOCKTNOSUPPORT;
3788 memset(&in, 0, sizeof(in));
3789 in.sin_family = AF_INET;
3790 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3791 socket_wrapper_default_iface()));
3793 si->myname = (struct swrap_address) {
3794 .sa_socklen = sizeof(in),
3796 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3801 struct sockaddr_in6 in6;
3803 if (si->family != family) {
3804 errno = ENETUNREACH;
3811 type = SOCKET_TYPE_CHAR_TCP_V6;
3814 type = SOCKET_TYPE_CHAR_UDP_V6;
3817 errno = ESOCKTNOSUPPORT;
3822 memset(&in6, 0, sizeof(in6));
3823 in6.sin6_family = AF_INET6;
3824 in6.sin6_addr = *swrap_ipv6();
3825 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3827 si->myname = (struct swrap_address) {
3828 .sa_socklen = sizeof(in6),
3830 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3835 errno = ESOCKTNOSUPPORT;
3840 if (autobind_start > 60000) {
3841 autobind_start = 10000;
3844 swrap_dir = socket_wrapper_dir();
3845 if (swrap_dir == NULL) {
3851 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3852 port = autobind_start + i;
3853 swrap_un_path(&un_addr.sa.un,
3856 socket_wrapper_default_iface(),
3858 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3860 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3865 si->un_addr = un_addr.sa.un;
3868 autobind_start = port + 1;
3871 if (i == SOCKET_MAX_SOCKETS) {
3872 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3873 "interface "SOCKET_FORMAT,
3876 socket_wrapper_default_iface(),
3883 si->family = family;
3884 set_port(si->family, port, &si->myname);
3889 SAFE_FREE(swrap_dir);
3890 swrap_mutex_unlock(&autobind_start_mutex);
3894 /****************************************************************************
3896 ***************************************************************************/
3898 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3902 struct swrap_address un_addr = {
3903 .sa_socklen = sizeof(struct sockaddr_un),
3905 struct socket_info *si = find_socket_info(s);
3909 return libc_connect(s, serv_addr, addrlen);
3914 if (si->bound == 0) {
3915 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3921 if (si->family != serv_addr->sa_family) {
3922 SWRAP_LOG(SWRAP_LOG_ERROR,
3923 "called for fd=%d (family=%d) called with invalid family=%d",
3924 s, si->family, serv_addr->sa_family);
3930 ret = sockaddr_convert_to_un(si, serv_addr,
3931 addrlen, &un_addr.sa.un, 0, &bcast);
3937 errno = ENETUNREACH;
3942 if (si->type == SOCK_DGRAM) {
3943 si->defer_connect = 1;
3946 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3948 ret = libc_connect(s,
3950 un_addr.sa_socklen);
3953 SWRAP_LOG(SWRAP_LOG_TRACE,
3954 "connect() path=%s, fd=%d",
3955 un_addr.sa.un.sun_path, s);
3958 /* to give better errors */
3959 if (ret == -1 && errno == ENOENT) {
3960 errno = EHOSTUNREACH;
3964 si->peername = (struct swrap_address) {
3965 .sa_socklen = addrlen,
3968 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3972 * When we connect() on a socket than we have to bind the
3973 * outgoing connection on the interface we use for the
3974 * transport. We already bound it on the right interface
3975 * but here we have to update the name so getsockname()
3976 * returns correct information.
3978 if (si->bindname.sa_socklen > 0) {
3979 si->myname = (struct swrap_address) {
3980 .sa_socklen = si->bindname.sa_socklen,
3983 memcpy(&si->myname.sa.ss,
3984 &si->bindname.sa.ss,
3985 si->bindname.sa_socklen);
3987 /* Cleanup bindname */
3988 si->bindname = (struct swrap_address) {
3993 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3994 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3996 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4000 SWRAP_UNLOCK_SI(si);
4004 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4006 return swrap_connect(s, serv_addr, addrlen);
4009 /****************************************************************************
4011 ***************************************************************************/
4013 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4016 struct swrap_address un_addr = {
4017 .sa_socklen = sizeof(struct sockaddr_un),
4019 struct socket_info *si = find_socket_info(s);
4026 return libc_bind(s, myaddr, addrlen);
4031 switch (si->family) {
4033 const struct sockaddr_in *sin;
4034 if (addrlen < sizeof(struct sockaddr_in)) {
4035 bind_error = EINVAL;
4039 sin = (const struct sockaddr_in *)(const void *)myaddr;
4041 if (sin->sin_family != AF_INET) {
4042 bind_error = EAFNOSUPPORT;
4045 /* special case for AF_UNSPEC */
4046 if (sin->sin_family == AF_UNSPEC &&
4047 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4056 const struct sockaddr_in6 *sin6;
4057 if (addrlen < sizeof(struct sockaddr_in6)) {
4058 bind_error = EINVAL;
4062 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4064 if (sin6->sin6_family != AF_INET6) {
4065 bind_error = EAFNOSUPPORT;
4072 bind_error = EINVAL;
4076 if (bind_error != 0) {
4083 in_use = check_addr_port_in_use(myaddr, addrlen);
4091 si->myname.sa_socklen = addrlen;
4092 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4094 ret = sockaddr_convert_to_un(si,
4104 unlink(un_addr.sa.un.sun_path);
4106 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4108 SWRAP_LOG(SWRAP_LOG_TRACE,
4109 "bind() path=%s, fd=%d",
4110 un_addr.sa.un.sun_path, s);
4117 SWRAP_UNLOCK_SI(si);
4122 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4124 return swrap_bind(s, myaddr, addrlen);
4127 /****************************************************************************
4129 ***************************************************************************/
4131 #ifdef HAVE_BINDRESVPORT
4132 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4134 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4136 struct swrap_address myaddr = {
4137 .sa_socklen = sizeof(struct sockaddr_storage),
4140 static uint16_t port;
4145 #define SWRAP_STARTPORT 600
4146 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4147 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4150 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4154 salen = myaddr.sa_socklen;
4157 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4163 memset(&myaddr.sa.ss, 0, salen);
4168 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4171 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4173 salen = sizeof(struct sockaddr_in);
4174 sinp->sin_port = htons(port);
4178 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4180 salen = sizeof(struct sockaddr_in6);
4181 sin6p->sin6_port = htons(port);
4185 errno = EAFNOSUPPORT;
4190 if (port > SWRAP_ENDPORT) {
4191 port = SWRAP_STARTPORT;
4194 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4195 if (rc == 0 || errno != EADDRINUSE) {
4203 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4205 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4209 /****************************************************************************
4211 ***************************************************************************/
4213 static int swrap_listen(int s, int backlog)
4216 struct socket_info *si = find_socket_info(s);
4219 return libc_listen(s, backlog);
4224 if (si->bound == 0) {
4225 ret = swrap_auto_bind(s, si, si->family);
4232 ret = libc_listen(s, backlog);
4238 SWRAP_UNLOCK_SI(si);
4243 int listen(int s, int backlog)
4245 return swrap_listen(s, backlog);
4248 /****************************************************************************
4250 ***************************************************************************/
4252 static FILE *swrap_fopen(const char *name, const char *mode)
4256 fp = libc_fopen(name, mode);
4258 int fd = fileno(fp);
4260 swrap_remove_stale(fd);
4266 FILE *fopen(const char *name, const char *mode)
4268 return swrap_fopen(name, mode);
4271 /****************************************************************************
4273 ***************************************************************************/
4276 static FILE *swrap_fopen64(const char *name, const char *mode)
4280 fp = libc_fopen64(name, mode);
4282 int fd = fileno(fp);
4284 swrap_remove_stale(fd);
4290 FILE *fopen64(const char *name, const char *mode)
4292 return swrap_fopen64(name, mode);
4294 #endif /* HAVE_FOPEN64 */
4296 /****************************************************************************
4298 ***************************************************************************/
4300 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4304 ret = libc_vopen(pathname, flags, ap);
4307 * There are methods for closing descriptors (libc-internal code
4308 * paths, direct syscalls) which close descriptors in ways that
4309 * we can't intercept, so try to recover when we notice that
4312 swrap_remove_stale(ret);
4317 int open(const char *pathname, int flags, ...)
4322 va_start(ap, flags);
4323 fd = swrap_vopen(pathname, flags, ap);
4329 /****************************************************************************
4331 ***************************************************************************/
4334 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4338 ret = libc_vopen64(pathname, flags, ap);
4341 * There are methods for closing descriptors (libc-internal code
4342 * paths, direct syscalls) which close descriptors in ways that
4343 * we can't intercept, so try to recover when we notice that
4346 swrap_remove_stale(ret);
4351 int open64(const char *pathname, int flags, ...)
4356 va_start(ap, flags);
4357 fd = swrap_vopen64(pathname, flags, ap);
4362 #endif /* HAVE_OPEN64 */
4364 /****************************************************************************
4366 ***************************************************************************/
4368 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4372 ret = libc_vopenat(dirfd, path, flags, ap);
4375 * There are methods for closing descriptors (libc-internal code
4376 * paths, direct syscalls) which close descriptors in ways that
4377 * we can't intercept, so try to recover when we notice that
4380 swrap_remove_stale(ret);
4386 int openat(int dirfd, const char *path, int flags, ...)
4391 va_start(ap, flags);
4392 fd = swrap_vopenat(dirfd, path, flags, ap);
4398 /****************************************************************************
4400 ***************************************************************************/
4402 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4404 struct socket_info *si = find_socket_info(s);
4409 return libc_getpeername(s, name, addrlen);
4414 if (si->peername.sa_socklen == 0)
4420 len = MIN(*addrlen, si->peername.sa_socklen);
4426 memcpy(name, &si->peername.sa.ss, len);
4427 *addrlen = si->peername.sa_socklen;
4431 SWRAP_UNLOCK_SI(si);
4436 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4437 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4439 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4442 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4445 /****************************************************************************
4447 ***************************************************************************/
4449 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4451 struct socket_info *si = find_socket_info(s);
4456 return libc_getsockname(s, name, addrlen);
4461 len = MIN(*addrlen, si->myname.sa_socklen);
4467 memcpy(name, &si->myname.sa.ss, len);
4468 *addrlen = si->myname.sa_socklen;
4472 SWRAP_UNLOCK_SI(si);
4477 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4478 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4480 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4483 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4486 /****************************************************************************
4488 ***************************************************************************/
4491 # ifdef SO_PROTOTYPE /* The Solaris name */
4492 # define SO_PROTOCOL SO_PROTOTYPE
4493 # endif /* SO_PROTOTYPE */
4494 #endif /* SO_PROTOCOL */
4496 static int swrap_getsockopt(int s, int level, int optname,
4497 void *optval, socklen_t *optlen)
4499 struct socket_info *si = find_socket_info(s);
4503 return libc_getsockopt(s,
4512 if (level == SOL_SOCKET) {
4516 if (optval == NULL || optlen == NULL ||
4517 *optlen < (socklen_t)sizeof(int)) {
4523 *optlen = sizeof(int);
4524 *(int *)optval = si->family;
4527 #endif /* SO_DOMAIN */
4531 if (optval == NULL || optlen == NULL ||
4532 *optlen < (socklen_t)sizeof(int)) {
4538 *optlen = sizeof(int);
4539 *(int *)optval = si->protocol;
4542 #endif /* SO_PROTOCOL */
4544 if (optval == NULL || optlen == NULL ||
4545 *optlen < (socklen_t)sizeof(int)) {
4551 *optlen = sizeof(int);
4552 *(int *)optval = si->type;
4556 ret = libc_getsockopt(s,
4563 } else if (level == IPPROTO_TCP) {
4568 * This enables sending packets directly out over TCP.
4569 * As a unix socket is doing that any way, report it as
4572 if (optval == NULL || optlen == NULL ||
4573 *optlen < (socklen_t)sizeof(int)) {
4579 *optlen = sizeof(int);
4580 *(int *)optval = si->tcp_nodelay;
4584 #endif /* TCP_NODELAY */
4587 struct tcp_info info;
4588 socklen_t ilen = sizeof(info);
4590 #ifdef HAVE_NETINET_TCP_FSM_H
4591 /* This is FreeBSD */
4592 # define __TCP_LISTEN TCPS_LISTEN
4593 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4594 # define __TCP_CLOSE TCPS_CLOSED
4597 # define __TCP_LISTEN TCP_LISTEN
4598 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4599 # define __TCP_CLOSE TCP_CLOSE
4603 if (si->listening) {
4604 info.tcpi_state = __TCP_LISTEN;
4605 } else if (si->connected) {
4607 * For now we just fake a few values
4608 * supported both by FreeBSD and Linux
4610 info.tcpi_state = __TCP_ESTABLISHED;
4611 info.tcpi_rto = 200000; /* 200 msec */
4612 info.tcpi_rtt = 5000; /* 5 msec */
4613 info.tcpi_rttvar = 5000; /* 5 msec */
4615 info.tcpi_state = __TCP_CLOSE;
4616 info.tcpi_rto = 1000000; /* 1 sec */
4618 info.tcpi_rttvar = 250000; /* 250 msec */
4621 if (optval == NULL || optlen == NULL ||
4622 *optlen < (socklen_t)ilen) {
4629 memcpy(optval, &info, ilen);
4634 #endif /* TCP_INFO */
4640 errno = ENOPROTOOPT;
4644 SWRAP_UNLOCK_SI(si);
4648 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4649 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4651 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4654 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4657 /****************************************************************************
4659 ***************************************************************************/
4661 static int swrap_setsockopt(int s, int level, int optname,
4662 const void *optval, socklen_t optlen)
4664 struct socket_info *si = find_socket_info(s);
4668 return libc_setsockopt(s,
4675 if (level == SOL_SOCKET) {
4676 return libc_setsockopt(s,
4685 if (level == IPPROTO_TCP) {
4692 * This enables sending packets directly out over TCP.
4693 * A unix socket is doing that any way.
4695 if (optval == NULL || optlen == 0 ||
4696 optlen < (socklen_t)sizeof(int)) {
4702 i = *discard_const_p(int, optval);
4703 if (i != 0 && i != 1) {
4708 si->tcp_nodelay = i;
4713 #endif /* TCP_NODELAY */
4719 switch (si->family) {
4721 if (level == IPPROTO_IP) {
4723 if (optname == IP_PKTINFO) {
4724 si->pktinfo = AF_INET;
4726 #endif /* IP_PKTINFO */
4732 if (level == IPPROTO_IPV6) {
4733 #ifdef IPV6_RECVPKTINFO
4734 if (optname == IPV6_RECVPKTINFO) {
4735 si->pktinfo = AF_INET6;
4737 #endif /* IPV6_PKTINFO */
4743 errno = ENOPROTOOPT;
4749 SWRAP_UNLOCK_SI(si);
4753 int setsockopt(int s, int level, int optname,
4754 const void *optval, socklen_t optlen)
4756 return swrap_setsockopt(s, level, optname, optval, optlen);
4759 /****************************************************************************
4761 ***************************************************************************/
4763 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4765 struct socket_info *si = find_socket_info(s);
4767 int *value_ptr = NULL;
4771 return libc_vioctl(s, r, va);
4778 rc = libc_vioctl(s, r, va);
4783 value_ptr = ((int *)va_arg(ap, int *));
4786 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4787 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4788 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4789 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4794 /* this is FreeBSD */
4795 FALL_THROUGH; /* to TIOCOUTQ */
4796 #endif /* FIONWRITE */
4797 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4799 * This may return more bytes then the application
4800 * sent into the socket, for tcp it should
4801 * return the number of unacked bytes.
4803 * On AF_UNIX, all bytes are immediately acked!
4806 value_ptr = ((int *)va_arg(ap, int *));
4814 SWRAP_UNLOCK_SI(si);
4818 #ifdef HAVE_IOCTL_INT
4819 int ioctl(int s, int r, ...)
4821 int ioctl(int s, unsigned long int r, ...)
4829 rc = swrap_vioctl(s, (unsigned long int) r, va);
4840 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4843 # ifdef _ALIGN /* BSD */
4844 #define CMSG_ALIGN _ALIGN
4846 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4847 # endif /* _ALIGN */
4848 #endif /* CMSG_ALIGN */
4851 * @brief Add a cmsghdr to a msghdr.
4853 * This is an function to add any type of cmsghdr. It will operate on the
4854 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4855 * the buffer position after the added cmsg element. Hence, this function is
4856 * intended to be used with an intermediate msghdr and not on the original
4857 * one handed in by the client.
4859 * @param[in] msg The msghdr to which to add the cmsg.
4861 * @param[in] level The cmsg level to set.
4863 * @param[in] type The cmsg type to set.
4865 * @param[in] data The cmsg data to set.
4867 * @param[in] len the length of the data to set.
4869 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4875 size_t cmlen = CMSG_LEN(len);
4876 size_t cmspace = CMSG_SPACE(len);
4877 uint8_t cmbuf[cmspace];
4878 void *cast_ptr = (void *)cmbuf;
4879 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4882 memset(cmbuf, 0, cmspace);
4884 if (msg->msg_controllen < cmlen) {
4885 cmlen = msg->msg_controllen;
4886 msg->msg_flags |= MSG_CTRUNC;
4889 if (msg->msg_controllen < cmspace) {
4890 cmspace = msg->msg_controllen;
4894 * We copy the full input data into an intermediate cmsghdr first
4895 * in order to more easily cope with truncation.
4897 cm->cmsg_len = cmlen;
4898 cm->cmsg_level = level;
4899 cm->cmsg_type = type;
4900 memcpy(CMSG_DATA(cm), data, len);
4903 * We now copy the possibly truncated buffer.
4904 * We copy cmlen bytes, but consume cmspace bytes,
4905 * leaving the possible padding uninitialiazed.
4907 p = (uint8_t *)msg->msg_control;
4908 memcpy(p, cm, cmlen);
4910 msg->msg_control = p;
4911 msg->msg_controllen -= cmspace;
4916 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4919 /* Add packet info */
4920 switch (si->pktinfo) {
4921 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4923 struct sockaddr_in *sin;
4924 #if defined(HAVE_STRUCT_IN_PKTINFO)
4925 struct in_pktinfo pkt;
4926 #elif defined(IP_RECVDSTADDR)
4930 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4931 sin = &si->bindname.sa.in;
4933 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4936 sin = &si->myname.sa.in;
4941 #if defined(HAVE_STRUCT_IN_PKTINFO)
4942 pkt.ipi_ifindex = socket_wrapper_default_iface();
4943 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4944 #elif defined(IP_RECVDSTADDR)
4945 pkt = sin->sin_addr;
4948 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4953 #endif /* IP_PKTINFO */
4954 #if defined(HAVE_IPV6)
4956 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4957 struct sockaddr_in6 *sin6;
4958 struct in6_pktinfo pkt6;
4960 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4961 sin6 = &si->bindname.sa.in6;
4963 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4966 sin6 = &si->myname.sa.in6;
4971 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4972 pkt6.ipi6_addr = sin6->sin6_addr;
4974 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4975 &pkt6, sizeof(pkt6));
4976 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4980 #endif /* IPV6_PKTINFO */
4988 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4989 struct msghdr *omsg)
4993 if (si->pktinfo > 0) {
4994 rc = swrap_msghdr_add_pktinfo(si, omsg);
5000 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5002 size_t *cm_data_space);
5003 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5005 size_t *cm_data_space);
5006 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5008 size_t *cm_data_space);
5010 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5012 size_t *cm_data_space)
5014 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5015 struct cmsghdr *cmsg;
5019 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5023 for (cmsg = CMSG_FIRSTHDR(msg);
5025 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5026 switch (cmsg->cmsg_level) {
5028 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5033 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5038 rc = swrap_sendmsg_copy_cmsg(cmsg,
5044 int saved_errno = errno;
5045 SAFE_FREE(*cm_data);
5047 errno = saved_errno;
5055 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5057 size_t *cm_data_space)
5062 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5064 p = realloc((*cm_data), cmspace);
5070 p = (*cm_data) + (*cm_data_space);
5071 *cm_data_space = cmspace;
5073 memcpy(p, cmsg, cmsg->cmsg_len);
5078 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5080 size_t *cm_data_space);
5083 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5085 size_t *cm_data_space)
5089 switch(cmsg->cmsg_type) {
5092 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5099 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5111 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5113 size_t *cm_data_space)
5115 (void)cmsg; /* unused */
5116 (void)cm_data; /* unused */
5117 (void)cm_data_space; /* unused */
5120 * Passing a IP pktinfo to a unix socket might be rejected by the
5121 * Kernel, at least on FreeBSD. So skip this cmsg.
5126 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5128 size_t *cm_data_space)
5132 switch (cmsg->cmsg_type) {
5134 SWRAP_LOG(SWRAP_LOG_TRACE,
5135 "Ignoring SCM_RIGHTS on inet socket!");
5138 #ifdef SCM_CREDENTIALS
5139 case SCM_CREDENTIALS:
5140 SWRAP_LOG(SWRAP_LOG_TRACE,
5141 "Ignoring SCM_CREDENTIALS on inet socket!");
5144 #endif /* SCM_CREDENTIALS */
5146 rc = swrap_sendmsg_copy_cmsg(cmsg,
5155 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5157 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5158 struct msghdr *msg_tmp)
5160 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5161 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5162 struct cmsghdr *cmsg = NULL;
5163 uint8_t *cm_data = NULL;
5164 size_t cm_data_space = 0;
5170 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5174 for (cmsg = CMSG_FIRSTHDR(msg_in);
5176 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5177 switch (cmsg->cmsg_level) {
5179 rc = swrap_sendmsg_copy_cmsg(cmsg,
5185 int saved_errno = errno;
5187 errno = saved_errno;
5192 msg_tmp->msg_controllen = cm_data_space;
5193 msg_tmp->msg_control = cm_data;
5196 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5197 *msg_tmp = *_msg_in;
5199 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5202 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5205 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5206 int saved_errno = errno;
5207 SAFE_FREE(msg_tmp->msg_control);
5208 errno = saved_errno;
5209 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5213 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5214 struct msghdr *msg_tmp)
5220 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5221 struct msghdr *msg_out,
5224 *msg_out = *msg_tmp;
5228 static ssize_t swrap_sendmsg_before(int fd,
5229 struct socket_info *si,
5231 struct iovec *tmp_iov,
5232 struct sockaddr_un *tmp_un,
5233 const struct sockaddr_un **to_un,
5234 const struct sockaddr **to,
5256 if (!si->connected) {
5261 if (msg->msg_iovlen == 0) {
5265 mtu = socket_wrapper_mtu();
5266 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5268 nlen = len + msg->msg_iov[i].iov_len;
5278 msg->msg_iovlen = i;
5279 if (msg->msg_iovlen == 0) {
5280 *tmp_iov = msg->msg_iov[0];
5281 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5283 msg->msg_iov = tmp_iov;
5284 msg->msg_iovlen = 1;
5289 if (si->connected) {
5290 if (msg->msg_name != NULL) {
5292 * We are dealing with unix sockets and if we
5293 * are connected, we should only talk to the
5294 * connected unix path. Using the fd to send
5295 * to another server would be hard to achieve.
5297 msg->msg_name = NULL;
5298 msg->msg_namelen = 0;
5301 const struct sockaddr *msg_name;
5302 msg_name = (const struct sockaddr *)msg->msg_name;
5304 if (msg_name == NULL) {
5310 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
5322 msg->msg_name = tmp_un;
5323 msg->msg_namelen = sizeof(*tmp_un);
5326 if (si->bound == 0) {
5327 ret = swrap_auto_bind(fd, si, si->family);
5329 SWRAP_UNLOCK_SI(si);
5330 if (errno == ENOTSOCK) {
5331 swrap_remove_stale(fd);
5334 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
5340 if (!si->defer_connect) {
5344 ret = sockaddr_convert_to_un(si,
5346 si->peername.sa_socklen,
5354 ret = libc_connect(fd,
5355 (struct sockaddr *)(void *)tmp_un,
5358 /* to give better errors */
5359 if (ret == -1 && errno == ENOENT) {
5360 errno = EHOSTUNREACH;
5367 si->defer_connect = 0;
5370 errno = EHOSTUNREACH;
5376 SWRAP_UNLOCK_SI(si);
5381 static void swrap_sendmsg_after(int fd,
5382 struct socket_info *si,
5384 const struct sockaddr *to,
5387 int saved_errno = errno;
5394 /* to give better errors */
5396 if (saved_errno == ENOENT) {
5397 saved_errno = EHOSTUNREACH;
5398 } else if (saved_errno == ENOTSOCK) {
5399 /* If the fd is not a socket, remove it */
5400 swrap_remove_stale(fd);
5404 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5405 avail += msg->msg_iov[i].iov_len;
5409 remain = MIN(80, avail);
5414 /* we capture it as one single packet */
5415 buf = (uint8_t *)malloc(remain);
5417 /* we just not capture the packet */
5418 errno = saved_errno;
5422 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5423 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5425 msg->msg_iov[i].iov_base,
5428 remain -= this_time;
5437 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5438 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5440 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5445 if (si->connected) {
5446 to = &si->peername.sa.s;
5449 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5450 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5452 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5457 SWRAP_UNLOCK_SI(si);
5460 errno = saved_errno;
5463 static int swrap_recvmsg_before(int fd,
5464 struct socket_info *si,
5466 struct iovec *tmp_iov)
5473 (void)fd; /* unused */
5478 if (!si->connected) {
5483 if (msg->msg_iovlen == 0) {
5487 mtu = socket_wrapper_mtu();
5488 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5490 nlen = len + msg->msg_iov[i].iov_len;
5495 msg->msg_iovlen = i;
5496 if (msg->msg_iovlen == 0) {
5497 *tmp_iov = msg->msg_iov[0];
5498 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5500 msg->msg_iov = tmp_iov;
5501 msg->msg_iovlen = 1;
5506 if (msg->msg_name == NULL) {
5511 if (msg->msg_iovlen == 0) {
5515 if (si->bound == 0) {
5516 ret = swrap_auto_bind(fd, si, si->family);
5518 SWRAP_UNLOCK_SI(si);
5520 * When attempting to read or write to a
5521 * descriptor, if an underlying autobind fails
5522 * because it's not a socket, stop intercepting
5523 * uses of that descriptor.
5525 if (errno == ENOTSOCK) {
5526 swrap_remove_stale(fd);
5529 SWRAP_LOG(SWRAP_LOG_ERROR,
5530 "swrap_recvmsg_before failed");
5537 errno = EHOSTUNREACH;
5543 SWRAP_UNLOCK_SI(si);
5548 static int swrap_recvmsg_after(int fd,
5549 struct socket_info *si,
5551 const struct sockaddr_un *un_addr,
5552 socklen_t un_addrlen,
5555 int saved_errno = errno;
5557 uint8_t *buf = NULL;
5563 /* to give better errors */
5565 if (saved_errno == ENOENT) {
5566 saved_errno = EHOSTUNREACH;
5567 } else if (saved_errno == ENOTSOCK) {
5568 /* If the fd is not a socket, remove it */
5569 swrap_remove_stale(fd);
5573 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5574 avail += msg->msg_iov[i].iov_len;
5579 /* Convert the socket address before we leave */
5580 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5581 rc = sockaddr_convert_from_un(si,
5598 remain = MIN(80, avail);
5603 /* we capture it as one single packet */
5604 buf = (uint8_t *)malloc(remain);
5606 /* we just not capture the packet */
5607 SWRAP_UNLOCK_SI(si);
5608 errno = saved_errno;
5612 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5613 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5615 msg->msg_iov[i].iov_base,
5618 remain -= this_time;
5623 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5624 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5625 } else if (ret == 0) { /* END OF FILE */
5626 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5627 } else if (ret > 0) {
5628 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5637 if (un_addr != NULL) {
5638 swrap_pcap_dump_packet(si,
5644 swrap_pcap_dump_packet(si,
5657 errno = saved_errno;
5659 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5661 msg->msg_controllen > 0 &&
5662 msg->msg_control != NULL) {
5663 rc = swrap_msghdr_add_socket_info(si, msg);
5665 SWRAP_UNLOCK_SI(si);
5671 SWRAP_UNLOCK_SI(si);
5675 /****************************************************************************
5677 ***************************************************************************/
5679 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5680 struct sockaddr *from, socklen_t *fromlen)
5682 struct swrap_address from_addr = {
5683 .sa_socklen = sizeof(struct sockaddr_un),
5686 struct socket_info *si = find_socket_info(s);
5687 struct swrap_address saddr = {
5688 .sa_socklen = sizeof(struct sockaddr_storage),
5695 return libc_recvfrom(s,
5707 if (from != NULL && fromlen != NULL) {
5708 msg.msg_name = from; /* optional address */
5709 msg.msg_namelen = *fromlen; /* size of address */
5711 msg.msg_name = &saddr.sa.s; /* optional address */
5712 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5714 msg.msg_iov = &tmp; /* scatter/gather array */
5715 msg.msg_iovlen = 1; /* # elements in msg_iov */
5716 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5717 msg.msg_control = NULL; /* ancillary data, see below */
5718 msg.msg_controllen = 0; /* ancillary data buffer len */
5719 msg.msg_flags = 0; /* flags on received message */
5722 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5727 buf = msg.msg_iov[0].iov_base;
5728 len = msg.msg_iov[0].iov_len;
5730 ret = libc_recvfrom(s,
5735 &from_addr.sa_socklen);
5740 tret = swrap_recvmsg_after(s,
5744 from_addr.sa_socklen,
5750 if (from != NULL && fromlen != NULL) {
5751 *fromlen = msg.msg_namelen;
5757 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5758 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5759 struct sockaddr *from, Psocklen_t fromlen)
5761 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5762 struct sockaddr *from, socklen_t *fromlen)
5765 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5768 /****************************************************************************
5770 ***************************************************************************/
5772 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5773 const struct sockaddr *to, socklen_t tolen)
5777 struct swrap_address un_addr = {
5778 .sa_socklen = sizeof(struct sockaddr_un),
5780 const struct sockaddr_un *to_un = NULL;
5783 struct socket_info *si = find_socket_info(s);
5787 return libc_sendto(s, buf, len, flags, to, tolen);
5790 tmp.iov_base = discard_const_p(char, buf);
5794 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5795 msg.msg_namelen = tolen; /* size of address */
5796 msg.msg_iov = &tmp; /* scatter/gather array */
5797 msg.msg_iovlen = 1; /* # elements in msg_iov */
5798 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5799 msg.msg_control = NULL; /* ancillary data, see below */
5800 msg.msg_controllen = 0; /* ancillary data buffer len */
5801 msg.msg_flags = 0; /* flags on received message */
5804 rc = swrap_sendmsg_before(s,
5816 buf = msg.msg_iov[0].iov_base;
5817 len = msg.msg_iov[0].iov_len;
5822 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5824 char *swrap_dir = NULL;
5826 type = SOCKET_TYPE_CHAR_UDP;
5828 swrap_dir = socket_wrapper_dir();
5829 if (swrap_dir == NULL) {
5833 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5834 swrap_un_path(&un_addr.sa.un,
5839 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5841 /* ignore the any errors in broadcast sends */
5847 un_addr.sa_socklen);
5850 SAFE_FREE(swrap_dir);
5854 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5856 SWRAP_UNLOCK_SI(si);
5863 * If it is a dgram socket and we are connected, don't include the
5866 if (si->type == SOCK_DGRAM && si->connected) {
5867 ret = libc_sendto(s,
5874 ret = libc_sendto(s,
5878 (struct sockaddr *)msg.msg_name,
5882 SWRAP_UNLOCK_SI(si);
5884 swrap_sendmsg_after(s, si, &msg, to, ret);
5889 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5890 const struct sockaddr *to, socklen_t tolen)
5892 return swrap_sendto(s, buf, len, flags, to, tolen);
5895 /****************************************************************************
5897 ***************************************************************************/
5899 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5901 struct socket_info *si;
5903 struct swrap_address saddr = {
5904 .sa_socklen = sizeof(struct sockaddr_storage),
5910 si = find_socket_info(s);
5912 return libc_recv(s, buf, len, flags);
5919 msg.msg_name = &saddr.sa.s; /* optional address */
5920 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5921 msg.msg_iov = &tmp; /* scatter/gather array */
5922 msg.msg_iovlen = 1; /* # elements in msg_iov */
5923 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5924 msg.msg_control = NULL; /* ancillary data, see below */
5925 msg.msg_controllen = 0; /* ancillary data buffer len */
5926 msg.msg_flags = 0; /* flags on received message */
5929 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5934 buf = msg.msg_iov[0].iov_base;
5935 len = msg.msg_iov[0].iov_len;
5937 ret = libc_recv(s, buf, len, flags);
5939 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5947 ssize_t recv(int s, void *buf, size_t len, int flags)
5949 return swrap_recv(s, buf, len, flags);
5952 /****************************************************************************
5954 ***************************************************************************/
5956 static ssize_t swrap_read(int s, void *buf, size_t len)
5958 struct socket_info *si;
5961 struct swrap_address saddr = {
5962 .sa_socklen = sizeof(struct sockaddr_storage),
5967 si = find_socket_info(s);
5969 return libc_read(s, buf, len);
5976 msg.msg_name = &saddr.sa.ss; /* optional address */
5977 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5978 msg.msg_iov = &tmp; /* scatter/gather array */
5979 msg.msg_iovlen = 1; /* # elements in msg_iov */
5980 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5981 msg.msg_control = NULL; /* ancillary data, see below */
5982 msg.msg_controllen = 0; /* ancillary data buffer len */
5983 msg.msg_flags = 0; /* flags on received message */
5986 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5988 if (tret == -ENOTSOCK) {
5989 return libc_read(s, buf, len);
5994 buf = msg.msg_iov[0].iov_base;
5995 len = msg.msg_iov[0].iov_len;
5997 ret = libc_read(s, buf, len);
5999 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6007 ssize_t read(int s, void *buf, size_t len)
6009 return swrap_read(s, buf, len);
6012 /****************************************************************************
6014 ***************************************************************************/
6016 static ssize_t swrap_write(int s, const void *buf, size_t len)
6020 struct sockaddr_un un_addr;
6023 struct socket_info *si;
6025 si = find_socket_info(s);
6027 return libc_write(s, buf, len);
6030 tmp.iov_base = discard_const_p(char, buf);
6034 msg.msg_name = NULL; /* optional address */
6035 msg.msg_namelen = 0; /* size of address */
6036 msg.msg_iov = &tmp; /* scatter/gather array */
6037 msg.msg_iovlen = 1; /* # elements in msg_iov */
6038 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6039 msg.msg_control = NULL; /* ancillary data, see below */
6040 msg.msg_controllen = 0; /* ancillary data buffer len */
6041 msg.msg_flags = 0; /* flags on received message */
6044 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6049 buf = msg.msg_iov[0].iov_base;
6050 len = msg.msg_iov[0].iov_len;
6052 ret = libc_write(s, buf, len);
6054 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6059 ssize_t write(int s, const void *buf, size_t len)
6061 return swrap_write(s, buf, len);
6064 /****************************************************************************
6066 ***************************************************************************/
6068 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6072 struct sockaddr_un un_addr;
6075 struct socket_info *si = find_socket_info(s);
6078 return libc_send(s, buf, len, flags);
6081 tmp.iov_base = discard_const_p(char, buf);
6085 msg.msg_name = NULL; /* optional address */
6086 msg.msg_namelen = 0; /* size of address */
6087 msg.msg_iov = &tmp; /* scatter/gather array */
6088 msg.msg_iovlen = 1; /* # elements in msg_iov */
6089 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6090 msg.msg_control = NULL; /* ancillary data, see below */
6091 msg.msg_controllen = 0; /* ancillary data buffer len */
6092 msg.msg_flags = 0; /* flags on received message */
6095 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6100 buf = msg.msg_iov[0].iov_base;
6101 len = msg.msg_iov[0].iov_len;
6103 ret = libc_send(s, buf, len, flags);
6105 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6110 ssize_t send(int s, const void *buf, size_t len, int flags)
6112 return swrap_send(s, buf, len, flags);
6115 /****************************************************************************
6117 ***************************************************************************/
6119 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6121 struct swrap_address from_addr = {
6122 .sa_socklen = sizeof(struct sockaddr_un),
6124 struct swrap_address convert_addr = {
6125 .sa_socklen = sizeof(struct sockaddr_storage),
6127 struct socket_info *si;
6130 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6131 size_t msg_ctrllen_filled;
6132 size_t msg_ctrllen_left;
6138 si = find_socket_info(s);
6140 rc = swrap_recvmsg_before_unix(omsg, &msg);
6144 ret = libc_recvmsg(s, &msg, flags);
6145 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6148 tmp.iov_base = NULL;
6152 msg.msg_name = &from_addr.sa; /* optional address */
6153 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6154 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6155 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6156 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6157 msg_ctrllen_filled = 0;
6158 msg_ctrllen_left = omsg->msg_controllen;
6160 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6161 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6162 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6165 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6170 ret = libc_recvmsg(s, &msg, flags);
6172 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6173 msg_ctrllen_filled += msg.msg_controllen;
6174 msg_ctrllen_left -= msg.msg_controllen;
6176 if (omsg->msg_control != NULL) {
6179 p = omsg->msg_control;
6180 p += msg_ctrllen_filled;
6182 msg.msg_control = p;
6183 msg.msg_controllen = msg_ctrllen_left;
6185 msg.msg_control = NULL;
6186 msg.msg_controllen = 0;
6191 * We convert the unix address to a IP address so we need a buffer
6192 * which can store the address in case of SOCK_DGRAM, see below.
6194 msg.msg_name = &convert_addr.sa;
6195 msg.msg_namelen = convert_addr.sa_socklen;
6197 rc = swrap_recvmsg_after(s,
6201 from_addr.sa_socklen,
6207 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6208 if (omsg->msg_control != NULL) {
6209 /* msg.msg_controllen = space left */
6210 msg_ctrllen_left = msg.msg_controllen;
6211 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6214 /* Update the original message length */
6215 omsg->msg_controllen = msg_ctrllen_filled;
6216 omsg->msg_flags = msg.msg_flags;
6218 omsg->msg_iovlen = msg.msg_iovlen;
6225 * The msg_name field points to a caller-allocated buffer that is
6226 * used to return the source address if the socket is unconnected. The
6227 * caller should set msg_namelen to the size of this buffer before this
6228 * call; upon return from a successful call, msg_name will contain the
6229 * length of the returned address. If the application does not need
6230 * to know the source address, msg_name can be specified as NULL.
6232 if (si->type == SOCK_STREAM) {
6233 omsg->msg_namelen = 0;
6234 } else if (omsg->msg_name != NULL &&
6235 omsg->msg_namelen != 0 &&
6236 omsg->msg_namelen >= msg.msg_namelen) {
6237 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6238 omsg->msg_namelen = msg.msg_namelen;
6241 SWRAP_UNLOCK_SI(si);
6246 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6248 return swrap_recvmsg(sockfd, msg, flags);
6251 /****************************************************************************
6253 ***************************************************************************/
6255 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
6259 struct sockaddr_un un_addr;
6260 const struct sockaddr_un *to_un = NULL;
6261 const struct sockaddr *to = NULL;
6264 struct socket_info *si = find_socket_info(s);
6268 rc = swrap_sendmsg_before_unix(omsg, &msg);
6272 ret = libc_sendmsg(s, &msg, flags);
6273 return swrap_sendmsg_after_unix(&msg, ret);
6276 ZERO_STRUCT(un_addr);
6278 tmp.iov_base = NULL;
6285 if (si->connected == 0) {
6286 msg.msg_name = omsg->msg_name; /* optional address */
6287 msg.msg_namelen = omsg->msg_namelen; /* size of address */
6289 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6290 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6292 SWRAP_UNLOCK_SI(si);
6294 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6295 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
6296 uint8_t *cmbuf = NULL;
6299 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
6305 msg.msg_controllen = 0;
6306 msg.msg_control = NULL;
6308 msg.msg_control = cmbuf;
6309 msg.msg_controllen = cmlen;
6312 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6314 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
6316 int saved_errno = errno;
6317 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6318 SAFE_FREE(msg.msg_control);
6320 errno = saved_errno;
6327 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6334 char *swrap_dir = NULL;
6336 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6337 avail += msg.msg_iov[i].iov_len;
6343 /* we capture it as one single packet */
6344 buf = (uint8_t *)malloc(remain);
6346 int saved_errno = errno;
6347 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6348 SAFE_FREE(msg.msg_control);
6350 errno = saved_errno;
6354 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6355 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
6357 msg.msg_iov[i].iov_base,
6360 remain -= this_time;
6363 type = SOCKET_TYPE_CHAR_UDP;
6365 swrap_dir = socket_wrapper_dir();
6366 if (swrap_dir == NULL) {
6367 int saved_errno = errno;
6368 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6369 SAFE_FREE(msg.msg_control);
6372 errno = saved_errno;
6376 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6377 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
6378 if (stat(un_addr.sun_path, &st) != 0) continue;
6380 msg.msg_name = &un_addr; /* optional address */
6381 msg.msg_namelen = sizeof(un_addr); /* size of address */
6383 /* ignore the any errors in broadcast sends */
6384 libc_sendmsg(s, &msg, flags);
6387 SAFE_FREE(swrap_dir);
6391 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6394 SWRAP_UNLOCK_SI(si);
6399 ret = libc_sendmsg(s, &msg, flags);
6401 swrap_sendmsg_after(s, si, &msg, to, ret);
6403 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6405 int saved_errno = errno;
6406 SAFE_FREE(msg.msg_control);
6407 errno = saved_errno;
6414 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
6416 return swrap_sendmsg(s, omsg, flags);
6419 /****************************************************************************
6421 ***************************************************************************/
6423 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
6425 struct socket_info *si;
6428 struct swrap_address saddr = {
6429 .sa_socklen = sizeof(struct sockaddr_storage)
6434 si = find_socket_info(s);
6436 return libc_readv(s, vector, count);
6439 tmp.iov_base = NULL;
6443 msg.msg_name = &saddr.sa.s; /* optional address */
6444 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6445 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6446 msg.msg_iovlen = count; /* # elements in msg_iov */
6447 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6448 msg.msg_control = NULL; /* ancillary data, see below */
6449 msg.msg_controllen = 0; /* ancillary data buffer len */
6450 msg.msg_flags = 0; /* flags on received message */
6453 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6455 if (rc == -ENOTSOCK) {
6456 return libc_readv(s, vector, count);
6461 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
6463 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6471 ssize_t readv(int s, const struct iovec *vector, int count)
6473 return swrap_readv(s, vector, count);
6476 /****************************************************************************
6478 ***************************************************************************/
6480 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6484 struct sockaddr_un un_addr;
6487 struct socket_info *si = find_socket_info(s);
6490 return libc_writev(s, vector, count);
6493 tmp.iov_base = NULL;
6497 msg.msg_name = NULL; /* optional address */
6498 msg.msg_namelen = 0; /* size of address */
6499 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6500 msg.msg_iovlen = count; /* # elements in msg_iov */
6501 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6502 msg.msg_control = NULL; /* ancillary data, see below */
6503 msg.msg_controllen = 0; /* ancillary data buffer len */
6504 msg.msg_flags = 0; /* flags on received message */
6507 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6509 if (rc == -ENOTSOCK) {
6510 return libc_readv(s, vector, count);
6515 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6517 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6522 ssize_t writev(int s, const struct iovec *vector, int count)
6524 return swrap_writev(s, vector, count);
6527 /****************************
6529 ***************************/
6531 static int swrap_close(int fd)
6533 struct socket_info *si = NULL;
6537 swrap_mutex_lock(&socket_reset_mutex);
6539 si_index = find_socket_info_index(fd);
6540 if (si_index == -1) {
6541 swrap_mutex_unlock(&socket_reset_mutex);
6542 return libc_close(fd);
6545 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
6546 reset_socket_info_index(fd);
6548 si = swrap_get_socket_info(si_index);
6550 swrap_mutex_lock(&first_free_mutex);
6553 ret = libc_close(fd);
6555 swrap_dec_refcount(si);
6557 if (swrap_get_refcount(si) > 0) {
6558 /* there are still references left */
6562 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6563 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6566 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6567 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6568 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6571 if (si->un_addr.sun_path[0] != '\0') {
6572 unlink(si->un_addr.sun_path);
6575 swrap_set_next_free(si, first_free);
6576 first_free = si_index;
6579 SWRAP_UNLOCK_SI(si);
6580 swrap_mutex_unlock(&first_free_mutex);
6581 swrap_mutex_unlock(&socket_reset_mutex);
6588 return swrap_close(fd);
6591 /****************************
6593 ***************************/
6595 static int swrap_dup(int fd)
6597 struct socket_info *si;
6600 idx = find_socket_info_index(fd);
6602 return libc_dup(fd);
6605 si = swrap_get_socket_info(idx);
6607 dup_fd = libc_dup(fd);
6609 int saved_errno = errno;
6610 errno = saved_errno;
6614 if ((size_t)dup_fd >= socket_fds_max) {
6615 SWRAP_LOG(SWRAP_LOG_ERROR,
6616 "The max socket index limit of %zu has been reached, "
6627 swrap_inc_refcount(si);
6629 SWRAP_UNLOCK_SI(si);
6631 /* Make sure we don't have an entry for the fd */
6632 swrap_remove_stale(dup_fd);
6634 set_socket_info_index(dup_fd, idx);
6641 return swrap_dup(fd);
6644 /****************************
6646 ***************************/
6648 static int swrap_dup2(int fd, int newfd)
6650 struct socket_info *si;
6653 idx = find_socket_info_index(fd);
6655 return libc_dup2(fd, newfd);
6658 si = swrap_get_socket_info(idx);
6662 * According to the manpage:
6664 * "If oldfd is a valid file descriptor, and newfd has the same
6665 * value as oldfd, then dup2() does nothing, and returns newfd."
6670 if ((size_t)newfd >= socket_fds_max) {
6671 SWRAP_LOG(SWRAP_LOG_ERROR,
6672 "The max socket index limit of %zu has been reached, "
6680 if (find_socket_info(newfd)) {
6681 /* dup2() does an implicit close of newfd, which we
6682 * need to emulate */
6686 dup_fd = libc_dup2(fd, newfd);
6688 int saved_errno = errno;
6689 errno = saved_errno;
6695 swrap_inc_refcount(si);
6697 SWRAP_UNLOCK_SI(si);
6699 /* Make sure we don't have an entry for the fd */
6700 swrap_remove_stale(dup_fd);
6702 set_socket_info_index(dup_fd, idx);
6707 int dup2(int fd, int newfd)
6709 return swrap_dup2(fd, newfd);
6712 /****************************
6714 ***************************/
6716 static int swrap_vfcntl(int fd, int cmd, va_list va)
6718 struct socket_info *si;
6719 int rc, dup_fd, idx;
6721 idx = find_socket_info_index(fd);
6723 return libc_vfcntl(fd, cmd, va);
6726 si = swrap_get_socket_info(idx);
6730 dup_fd = libc_vfcntl(fd, cmd, va);
6732 int saved_errno = errno;
6733 errno = saved_errno;
6737 /* Make sure we don't have an entry for the fd */
6738 swrap_remove_stale(dup_fd);
6740 if ((size_t)dup_fd >= socket_fds_max) {
6741 SWRAP_LOG(SWRAP_LOG_ERROR,
6742 "The max socket index limit of %zu has been reached, "
6753 swrap_inc_refcount(si);
6755 SWRAP_UNLOCK_SI(si);
6758 set_socket_info_index(dup_fd, idx);
6763 rc = libc_vfcntl(fd, cmd, va);
6770 int fcntl(int fd, int cmd, ...)
6777 rc = swrap_vfcntl(fd, cmd, va);
6784 /****************************
6786 ***************************/
6789 static int swrap_eventfd(int count, int flags)
6793 fd = libc_eventfd(count, flags);
6795 swrap_remove_stale(fd);
6801 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6802 int eventfd(unsigned int count, int flags)
6804 int eventfd(int count, int flags)
6807 return swrap_eventfd(count, flags);
6812 int pledge(const char *promises, const char *paths[])
6814 (void)promises; /* unused */
6815 (void)paths; /* unused */
6819 #endif /* HAVE_PLEDGE */
6821 static void swrap_thread_prepare(void)
6824 * This function should only be called here!!
6826 * We bind all symobls to avoid deadlocks of the fork is
6827 * interrupted by a signal handler using a symbol of this
6830 swrap_bind_symbol_all();
6835 static void swrap_thread_parent(void)
6840 static void swrap_thread_child(void)
6845 /****************************
6847 ***************************/
6848 void swrap_constructor(void)
6853 * If we hold a lock and the application forks, then the child
6854 * is not able to unlock the mutex and we are in a deadlock.
6855 * This should prevent such deadlocks.
6857 pthread_atfork(&swrap_thread_prepare,
6858 &swrap_thread_parent,
6859 &swrap_thread_child);
6862 /****************************
6864 ***************************/
6867 * This function is called when the library is unloaded and makes sure that
6868 * sockets get closed and the unix file for the socket are unlinked.
6870 void swrap_destructor(void)
6874 if (socket_fds_idx != NULL) {
6875 for (i = 0; i < socket_fds_max; ++i) {
6876 if (socket_fds_idx[i] != -1) {
6880 SAFE_FREE(socket_fds_idx);
6885 if (swrap.libc.handle != NULL) {
6886 dlclose(swrap.libc.handle);
6888 if (swrap.libc.socket_handle) {
6889 dlclose(swrap.libc.socket_handle);
6893 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
6895 * On FreeBSD 12 (and maybe other platforms)
6896 * system libraries like libresolv prefix there
6897 * syscalls with '_' in order to always use
6898 * the symbols from libc.
6900 * In the interaction with resolv_wrapper,
6901 * we need to inject socket wrapper into libresolv,
6902 * which means we need to private all socket
6903 * related syscalls also with the '_' prefix.
6905 * This is tested in Samba's 'make test',
6906 * there we noticed that providing '_read'
6907 * and '_open' would cause errors, which
6908 * means we skip '_read', '_write' and
6909 * all non socket related calls without
6910 * further analyzing the problem.
6912 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
6913 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
6916 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
6918 SWRAP_SYMBOL_ALIAS(accept, _accept);
6919 SWRAP_SYMBOL_ALIAS(bind, _bind);
6920 SWRAP_SYMBOL_ALIAS(close, _close);
6921 SWRAP_SYMBOL_ALIAS(connect, _connect);
6922 SWRAP_SYMBOL_ALIAS(dup, _dup);
6923 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
6924 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
6925 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
6926 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
6927 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
6928 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
6929 SWRAP_SYMBOL_ALIAS(listen, _listen);
6930 SWRAP_SYMBOL_ALIAS(readv, _readv);
6931 SWRAP_SYMBOL_ALIAS(recv, _recv);
6932 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
6933 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
6934 SWRAP_SYMBOL_ALIAS(send, _send);
6935 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
6936 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
6937 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
6938 SWRAP_SYMBOL_ALIAS(socket, _socket);
6939 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
6940 SWRAP_SYMBOL_ALIAS(writev, _writev);
6942 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */