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 /* Add new global locks here please */
182 # define SWRAP_LOCK_ALL do { \
185 # define SWRAP_UNLOCK_ALL do { \
188 #define SOCKET_INFO_CONTAINER(si) \
189 (struct socket_info_container *)(si)
191 #define SWRAP_LOCK_SI(si) do { \
192 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
193 swrap_mutex_lock(&sic->meta.mutex); \
196 #define SWRAP_UNLOCK_SI(si) do { \
197 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
198 swrap_mutex_unlock(&sic->meta.mutex); \
201 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
202 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
204 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
207 /* we need to use a very terse format here as IRIX 6.4 silently
208 truncates names to 16 chars, so if we use a longer name then we
209 can't tell which port a packet came from with recvfrom()
211 with this format we have 8 chars left for the directory name
213 #define SOCKET_FORMAT "%c%02X%04X"
214 #define SOCKET_TYPE_CHAR_TCP 'T'
215 #define SOCKET_TYPE_CHAR_UDP 'U'
216 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
217 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
220 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
221 * format PCAP capture files (as the caller will simply continue from here).
223 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
224 #define SOCKET_WRAPPER_MTU_MIN 512
225 #define SOCKET_WRAPPER_MTU_MAX 32768
227 #define SOCKET_MAX_SOCKETS 1024
230 * Maximum number of socket_info structures that can
231 * be used. Can be overriden by the environment variable
232 * SOCKET_WRAPPER_MAX_SOCKETS.
234 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
236 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
238 /* This limit is to avoid broadcast sendto() needing to stat too many
239 * files. It may be raised (with a performance cost) to up to 254
240 * without changing the format above */
241 #define MAX_WRAPPED_INTERFACES 64
243 struct swrap_address {
244 socklen_t sa_socklen;
247 struct sockaddr_in in;
249 struct sockaddr_in6 in6;
251 struct sockaddr_un un;
252 struct sockaddr_storage ss;
272 /* The unix path so we can unlink it on close() */
273 struct sockaddr_un un_addr;
275 struct swrap_address bindname;
276 struct swrap_address myname;
277 struct swrap_address peername;
280 unsigned long pck_snd;
281 unsigned long pck_rcv;
285 struct socket_info_meta
287 unsigned int refcount;
289 pthread_mutex_t mutex;
292 struct socket_info_container
294 struct socket_info info;
295 struct socket_info_meta meta;
298 static struct socket_info_container *sockets;
300 static size_t socket_info_max = 0;
303 * Allocate the socket array always on the limit value. We want it to be
304 * at least bigger than the default so if we reach the limit we can
305 * still deal with duplicate fds pointing to the same socket_info.
307 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
309 /* Hash table to map fds to corresponding socket_info index */
310 static int *socket_fds_idx;
312 /* Mutex for syncronizing port selection during swrap_auto_bind() */
313 static pthread_mutex_t autobind_start_mutex;
315 /* Mutex to guard the initialization of array of socket_info structures */
316 static pthread_mutex_t sockets_mutex;
318 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
319 static pthread_mutex_t socket_reset_mutex;
321 /* Mutex to synchronize access to first free index in socket_info array */
322 static pthread_mutex_t first_free_mutex;
324 /* Mutex to synchronize access to packet capture dump file */
325 static pthread_mutex_t pcap_dump_mutex;
327 /* Mutex for synchronizing mtu value fetch*/
328 static pthread_mutex_t mtu_update_mutex;
330 /* Function prototypes */
332 bool socket_wrapper_enabled(void);
334 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
335 /* xlC and other oldschool compilers support (only) this */
336 #pragma init (swrap_constructor)
338 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
339 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
340 #pragma fini (swrap_destructor)
342 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
344 #ifndef HAVE_GETPROGNAME
345 static const char *getprogname(void)
347 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
348 return program_invocation_short_name;
349 #elif defined(HAVE_GETEXECNAME)
350 return getexecname();
353 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
355 #endif /* HAVE_GETPROGNAME */
357 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
358 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
360 static void swrap_log(enum swrap_dbglvl_e dbglvl,
362 const char *format, ...)
367 unsigned int lvl = 0;
368 const char *prefix = "SWRAP";
369 const char *progname = getprogname();
371 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
380 va_start(va, format);
381 vsnprintf(buffer, sizeof(buffer), format, va);
385 case SWRAP_LOG_ERROR:
386 prefix = "SWRAP_ERROR";
389 prefix = "SWRAP_WARN";
391 case SWRAP_LOG_DEBUG:
392 prefix = "SWRAP_DEBUG";
394 case SWRAP_LOG_TRACE:
395 prefix = "SWRAP_TRACE";
399 if (progname == NULL) {
400 progname = "<unknown>";
404 "%s[%s (%u)] - %s: %s\n",
407 (unsigned int)getpid(),
412 /*********************************************************
413 * SWRAP LOADING LIBC FUNCTIONS
414 *********************************************************/
419 typedef int (*__libc_accept4)(int sockfd,
420 struct sockaddr *addr,
424 typedef int (*__libc_accept)(int sockfd,
425 struct sockaddr *addr,
428 typedef int (*__libc_bind)(int sockfd,
429 const struct sockaddr *addr,
431 typedef int (*__libc_close)(int fd);
432 typedef int (*__libc_connect)(int sockfd,
433 const struct sockaddr *addr,
435 typedef int (*__libc_dup)(int fd);
436 typedef int (*__libc_dup2)(int oldfd, int newfd);
437 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
438 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
440 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
443 typedef int (*__libc_eventfd)(int count, int flags);
445 typedef int (*__libc_getpeername)(int sockfd,
446 struct sockaddr *addr,
448 typedef int (*__libc_getsockname)(int sockfd,
449 struct sockaddr *addr,
451 typedef int (*__libc_getsockopt)(int sockfd,
456 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
457 typedef int (*__libc_listen)(int sockfd, int backlog);
458 typedef int (*__libc_open)(const char *pathname, int flags, ...);
460 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
461 #endif /* HAVE_OPEN64 */
462 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
463 typedef int (*__libc_pipe)(int pipefd[2]);
464 typedef int (*__libc_read)(int fd, void *buf, size_t count);
465 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
466 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
467 typedef int (*__libc_recvfrom)(int sockfd,
471 struct sockaddr *src_addr,
473 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
474 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
475 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
476 typedef int (*__libc_sendto)(int sockfd,
480 const struct sockaddr *dst_addr,
482 typedef int (*__libc_setsockopt)(int sockfd,
488 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
490 typedef int (*__libc_socket)(int domain, int type, int protocol);
491 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
492 #ifdef HAVE_TIMERFD_CREATE
493 typedef int (*__libc_timerfd_create)(int clockid, int flags);
495 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
496 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
498 #define SWRAP_SYMBOL_ENTRY(i) \
504 struct swrap_libc_symbols {
506 SWRAP_SYMBOL_ENTRY(accept4);
508 SWRAP_SYMBOL_ENTRY(accept);
510 SWRAP_SYMBOL_ENTRY(bind);
511 SWRAP_SYMBOL_ENTRY(close);
512 SWRAP_SYMBOL_ENTRY(connect);
513 SWRAP_SYMBOL_ENTRY(dup);
514 SWRAP_SYMBOL_ENTRY(dup2);
515 SWRAP_SYMBOL_ENTRY(fcntl);
516 SWRAP_SYMBOL_ENTRY(fopen);
518 SWRAP_SYMBOL_ENTRY(fopen64);
521 SWRAP_SYMBOL_ENTRY(eventfd);
523 SWRAP_SYMBOL_ENTRY(getpeername);
524 SWRAP_SYMBOL_ENTRY(getsockname);
525 SWRAP_SYMBOL_ENTRY(getsockopt);
526 SWRAP_SYMBOL_ENTRY(ioctl);
527 SWRAP_SYMBOL_ENTRY(listen);
528 SWRAP_SYMBOL_ENTRY(open);
530 SWRAP_SYMBOL_ENTRY(open64);
532 SWRAP_SYMBOL_ENTRY(openat);
533 SWRAP_SYMBOL_ENTRY(pipe);
534 SWRAP_SYMBOL_ENTRY(read);
535 SWRAP_SYMBOL_ENTRY(readv);
536 SWRAP_SYMBOL_ENTRY(recv);
537 SWRAP_SYMBOL_ENTRY(recvfrom);
538 SWRAP_SYMBOL_ENTRY(recvmsg);
539 SWRAP_SYMBOL_ENTRY(send);
540 SWRAP_SYMBOL_ENTRY(sendmsg);
541 SWRAP_SYMBOL_ENTRY(sendto);
542 SWRAP_SYMBOL_ENTRY(setsockopt);
544 SWRAP_SYMBOL_ENTRY(signalfd);
546 SWRAP_SYMBOL_ENTRY(socket);
547 SWRAP_SYMBOL_ENTRY(socketpair);
548 #ifdef HAVE_TIMERFD_CREATE
549 SWRAP_SYMBOL_ENTRY(timerfd_create);
551 SWRAP_SYMBOL_ENTRY(write);
552 SWRAP_SYMBOL_ENTRY(writev);
559 struct swrap_libc_symbols symbols;
563 static struct swrap swrap;
566 static char *socket_wrapper_dir(void);
568 #define LIBC_NAME "libc.so"
575 static const char *swrap_str_lib(enum swrap_lib lib)
580 case SWRAP_LIBSOCKET:
584 /* Compiler would warn us about unhandled enum value if we get here */
588 static void *swrap_load_lib_handle(enum swrap_lib lib)
590 int flags = RTLD_LAZY;
595 const char *env_preload = getenv("LD_PRELOAD");
596 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
597 bool enable_deepbind = true;
599 /* Don't do a deepbind if we run with libasan */
600 if (env_preload != NULL && strlen(env_preload) < 1024) {
601 const char *p = strstr(env_preload, "libasan.so");
603 enable_deepbind = false;
607 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
608 enable_deepbind = false;
611 if (enable_deepbind) {
612 flags |= RTLD_DEEPBIND;
617 case SWRAP_LIBSOCKET:
618 #ifdef HAVE_LIBSOCKET
619 handle = swrap.libc.socket_handle;
620 if (handle == NULL) {
621 for (i = 10; i >= 0; i--) {
622 char soname[256] = {0};
624 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
625 handle = dlopen(soname, flags);
626 if (handle != NULL) {
631 swrap.libc.socket_handle = handle;
636 handle = swrap.libc.handle;
638 if (handle == NULL) {
639 handle = dlopen(LIBC_SO, flags);
641 swrap.libc.handle = handle;
644 if (handle == NULL) {
645 for (i = 10; i >= 0; i--) {
646 char soname[256] = {0};
648 snprintf(soname, sizeof(soname), "libc.so.%d", i);
649 handle = dlopen(soname, flags);
650 if (handle != NULL) {
655 swrap.libc.handle = handle;
660 if (handle == NULL) {
662 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
664 SWRAP_LOG(SWRAP_LOG_ERROR,
665 "Failed to dlopen library: %s",
674 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
679 handle = swrap_load_lib_handle(lib);
681 func = dlsym(handle, fn_name);
683 SWRAP_LOG(SWRAP_LOG_ERROR,
684 "Failed to find %s: %s",
690 SWRAP_LOG(SWRAP_LOG_TRACE,
698 static void swrap_mutex_lock(pthread_mutex_t *mutex)
702 ret = pthread_mutex_lock(mutex);
704 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
709 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
713 ret = pthread_mutex_unlock(mutex);
715 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
721 * These macros have a thread race condition on purpose!
723 * This is an optimization to avoid locking each time we check if the symbol is
726 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
727 swrap.libc.symbols._libc_##sym_name.obj = \
728 _swrap_bind_symbol(lib, #sym_name); \
731 #define swrap_bind_symbol_libc(sym_name) \
732 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
734 #define swrap_bind_symbol_libsocket(sym_name) \
735 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
737 static void swrap_bind_symbol_all(void);
739 /****************************************************************************
741 ****************************************************************************
743 * Functions especially from libc need to be loaded individually, you can't
744 * load all at once or gdb will segfault at startup. The same applies to
745 * valgrind and has probably something todo with with the linker. So we need
746 * load each function at the point it is called the first time.
748 ****************************************************************************/
751 static int libc_accept4(int sockfd,
752 struct sockaddr *addr,
756 swrap_bind_symbol_all();
758 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
761 #else /* HAVE_ACCEPT4 */
763 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
765 swrap_bind_symbol_all();
767 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
769 #endif /* HAVE_ACCEPT4 */
771 static int libc_bind(int sockfd,
772 const struct sockaddr *addr,
775 swrap_bind_symbol_all();
777 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
780 static int libc_close(int fd)
782 swrap_bind_symbol_all();
784 return swrap.libc.symbols._libc_close.f(fd);
787 static int libc_connect(int sockfd,
788 const struct sockaddr *addr,
791 swrap_bind_symbol_all();
793 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
796 static int libc_dup(int fd)
798 swrap_bind_symbol_all();
800 return swrap.libc.symbols._libc_dup.f(fd);
803 static int libc_dup2(int oldfd, int newfd)
805 swrap_bind_symbol_all();
807 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
811 static int libc_eventfd(int count, int flags)
813 swrap_bind_symbol_all();
815 return swrap.libc.symbols._libc_eventfd.f(count, flags);
819 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
820 static int libc_vfcntl(int fd, int cmd, va_list ap)
825 swrap_bind_symbol_all();
827 arg = va_arg(ap, void *);
829 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
834 static int libc_getpeername(int sockfd,
835 struct sockaddr *addr,
838 swrap_bind_symbol_all();
840 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
843 static int libc_getsockname(int sockfd,
844 struct sockaddr *addr,
847 swrap_bind_symbol_all();
849 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
852 static int libc_getsockopt(int sockfd,
858 swrap_bind_symbol_all();
860 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
867 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
868 static int libc_vioctl(int d, unsigned long int request, va_list ap)
873 swrap_bind_symbol_all();
875 arg = va_arg(ap, void *);
877 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
882 static int libc_listen(int sockfd, int backlog)
884 swrap_bind_symbol_all();
886 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
889 static FILE *libc_fopen(const char *name, const char *mode)
891 swrap_bind_symbol_all();
893 return swrap.libc.symbols._libc_fopen.f(name, mode);
897 static FILE *libc_fopen64(const char *name, const char *mode)
899 swrap_bind_symbol_all();
901 return swrap.libc.symbols._libc_fopen64.f(name, mode);
903 #endif /* HAVE_FOPEN64 */
905 static int libc_vopen(const char *pathname, int flags, va_list ap)
910 swrap_bind_symbol_all();
912 if (flags & O_CREAT) {
913 mode = va_arg(ap, int);
915 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
920 static int libc_open(const char *pathname, int flags, ...)
926 fd = libc_vopen(pathname, flags, ap);
933 static int libc_vopen64(const char *pathname, int flags, va_list ap)
938 swrap_bind_symbol_all();
940 if (flags & O_CREAT) {
941 mode = va_arg(ap, int);
943 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
947 #endif /* HAVE_OPEN64 */
949 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
954 swrap_bind_symbol_all();
956 if (flags & O_CREAT) {
957 mode = va_arg(ap, int);
959 fd = swrap.libc.symbols._libc_openat.f(dirfd,
968 static int libc_openat(int dirfd, const char *path, int flags, ...)
974 fd = libc_vopenat(dirfd, path, flags, ap);
981 static int libc_pipe(int pipefd[2])
983 swrap_bind_symbol_all();
985 return swrap.libc.symbols._libc_pipe.f(pipefd);
988 static int libc_read(int fd, void *buf, size_t count)
990 swrap_bind_symbol_all();
992 return swrap.libc.symbols._libc_read.f(fd, buf, count);
995 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
997 swrap_bind_symbol_all();
999 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1002 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1004 swrap_bind_symbol_all();
1006 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1009 static int libc_recvfrom(int sockfd,
1013 struct sockaddr *src_addr,
1016 swrap_bind_symbol_all();
1018 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1026 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1028 swrap_bind_symbol_all();
1030 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1033 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1035 swrap_bind_symbol_all();
1037 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1040 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1042 swrap_bind_symbol_all();
1044 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1047 static int libc_sendto(int sockfd,
1051 const struct sockaddr *dst_addr,
1054 swrap_bind_symbol_all();
1056 return swrap.libc.symbols._libc_sendto.f(sockfd,
1064 static int libc_setsockopt(int sockfd,
1070 swrap_bind_symbol_all();
1072 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1079 #ifdef HAVE_SIGNALFD
1080 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1082 swrap_bind_symbol_all();
1084 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1088 static int libc_socket(int domain, int type, int protocol)
1090 swrap_bind_symbol_all();
1092 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1095 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1097 swrap_bind_symbol_all();
1099 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1102 #ifdef HAVE_TIMERFD_CREATE
1103 static int libc_timerfd_create(int clockid, int flags)
1105 swrap_bind_symbol_all();
1107 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1111 static ssize_t libc_write(int fd, const void *buf, size_t count)
1113 swrap_bind_symbol_all();
1115 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1118 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1120 swrap_bind_symbol_all();
1122 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1125 /* DO NOT call this function during library initialization! */
1126 static void __swrap_bind_symbol_all_once(void)
1129 swrap_bind_symbol_libsocket(accept4);
1131 swrap_bind_symbol_libsocket(accept);
1133 swrap_bind_symbol_libsocket(bind);
1134 swrap_bind_symbol_libc(close);
1135 swrap_bind_symbol_libsocket(connect);
1136 swrap_bind_symbol_libc(dup);
1137 swrap_bind_symbol_libc(dup2);
1138 swrap_bind_symbol_libc(fcntl);
1139 swrap_bind_symbol_libc(fopen);
1141 swrap_bind_symbol_libc(fopen64);
1144 swrap_bind_symbol_libc(eventfd);
1146 swrap_bind_symbol_libsocket(getpeername);
1147 swrap_bind_symbol_libsocket(getsockname);
1148 swrap_bind_symbol_libsocket(getsockopt);
1149 swrap_bind_symbol_libc(ioctl);
1150 swrap_bind_symbol_libsocket(listen);
1151 swrap_bind_symbol_libc(open);
1153 swrap_bind_symbol_libc(open64);
1155 swrap_bind_symbol_libc(openat);
1156 swrap_bind_symbol_libsocket(pipe);
1157 swrap_bind_symbol_libc(read);
1158 swrap_bind_symbol_libsocket(readv);
1159 swrap_bind_symbol_libsocket(recv);
1160 swrap_bind_symbol_libsocket(recvfrom);
1161 swrap_bind_symbol_libsocket(recvmsg);
1162 swrap_bind_symbol_libsocket(send);
1163 swrap_bind_symbol_libsocket(sendmsg);
1164 swrap_bind_symbol_libsocket(sendto);
1165 swrap_bind_symbol_libsocket(setsockopt);
1166 #ifdef HAVE_SIGNALFD
1167 swrap_bind_symbol_libsocket(signalfd);
1169 swrap_bind_symbol_libsocket(socket);
1170 swrap_bind_symbol_libsocket(socketpair);
1171 #ifdef HAVE_TIMERFD_CREATE
1172 swrap_bind_symbol_libc(timerfd_create);
1174 swrap_bind_symbol_libc(write);
1175 swrap_bind_symbol_libsocket(writev);
1178 static void swrap_bind_symbol_all(void)
1180 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1182 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1185 /*********************************************************
1186 * SWRAP HELPER FUNCTIONS
1187 *********************************************************/
1190 * We return 127.0.0.0 (default) or 10.53.57.0.
1192 * This can be controlled by:
1193 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1195 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1197 static in_addr_t swrap_ipv4_net(void)
1199 static int initialized;
1200 static in_addr_t hv;
1201 const char *net_str = NULL;
1210 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1211 if (net_str == NULL) {
1212 net_str = "127.0.0.0";
1215 ret = inet_pton(AF_INET, net_str, &nv);
1217 SWRAP_LOG(SWRAP_LOG_ERROR,
1218 "INVALID IPv4 Network [%s]",
1223 hv = ntohl(nv.s_addr);
1233 SWRAP_LOG(SWRAP_LOG_ERROR,
1234 "INVALID IPv4 Network [%s][0x%x] should be "
1235 "127.0.0.0 or 10.53.57.0",
1236 net_str, (unsigned)hv);
1244 * This returns 127.255.255.255 or 10.255.255.255
1246 static in_addr_t swrap_ipv4_bcast(void)
1250 hv = swrap_ipv4_net();
1251 hv |= IN_CLASSA_HOST;
1257 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1259 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1263 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1264 SWRAP_LOG(SWRAP_LOG_ERROR,
1265 "swrap_ipv4_iface(%u) invalid!",
1271 hv = swrap_ipv4_net();
1281 static const struct in6_addr *swrap_ipv6(void)
1283 static struct in6_addr v;
1284 static int initialized;
1292 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1301 static void set_port(int family, int prt, struct swrap_address *addr)
1305 addr->sa.in.sin_port = htons(prt);
1309 addr->sa.in6.sin6_port = htons(prt);
1315 static size_t socket_length(int family)
1319 return sizeof(struct sockaddr_in);
1322 return sizeof(struct sockaddr_in6);
1328 static struct socket_info *swrap_get_socket_info(int si_index)
1330 return (struct socket_info *)(&(sockets[si_index].info));
1333 static int swrap_get_refcount(struct socket_info *si)
1335 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1336 return sic->meta.refcount;
1339 static void swrap_inc_refcount(struct socket_info *si)
1341 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1343 sic->meta.refcount += 1;
1346 static void swrap_dec_refcount(struct socket_info *si)
1348 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1350 sic->meta.refcount -= 1;
1353 static int swrap_get_next_free(struct socket_info *si)
1355 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1357 return sic->meta.next_free;
1360 static void swrap_set_next_free(struct socket_info *si, int next_free)
1362 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1364 sic->meta.next_free = next_free;
1367 static int swrap_un_path(struct sockaddr_un *un,
1368 const char *swrap_dir,
1375 ret = snprintf(un->sun_path,
1376 sizeof(un->sun_path),
1382 if ((size_t)ret >= sizeof(un->sun_path)) {
1383 return ENAMETOOLONG;
1389 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1390 const char *swrap_dir)
1394 ret = snprintf(un->sun_path,
1395 sizeof(un->sun_path),
1399 if ((size_t)ret >= sizeof(un->sun_path)) {
1400 return ENAMETOOLONG;
1406 static bool swrap_dir_usable(const char *swrap_dir)
1408 struct sockaddr_un un;
1411 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1416 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1424 static char *socket_wrapper_dir(void)
1426 char *swrap_dir = NULL;
1427 char *s = getenv("SOCKET_WRAPPER_DIR");
1432 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1436 swrap_dir = realpath(s, NULL);
1437 if (swrap_dir == NULL) {
1438 SWRAP_LOG(SWRAP_LOG_ERROR,
1439 "Unable to resolve socket_wrapper dir path: %s",
1444 ok = swrap_dir_usable(swrap_dir);
1451 ok = swrap_dir_usable(s);
1453 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1457 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1459 SWRAP_LOG(SWRAP_LOG_ERROR,
1460 "realpath(SOCKET_WRAPPER_DIR) too long and "
1461 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1466 swrap_dir = strdup(s);
1467 if (swrap_dir == NULL) {
1468 SWRAP_LOG(SWRAP_LOG_ERROR,
1469 "Unable to duplicate socket_wrapper dir path");
1473 SWRAP_LOG(SWRAP_LOG_WARN,
1474 "realpath(SOCKET_WRAPPER_DIR) too long, "
1475 "using original SOCKET_WRAPPER_DIR\n");
1478 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1482 static unsigned int socket_wrapper_mtu(void)
1484 static unsigned int max_mtu = 0;
1489 swrap_mutex_lock(&mtu_update_mutex);
1495 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1497 s = getenv("SOCKET_WRAPPER_MTU");
1502 tmp = strtol(s, &endp, 10);
1507 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1513 swrap_mutex_unlock(&mtu_update_mutex);
1517 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1519 pthread_mutexattr_t ma;
1522 ret = pthread_mutexattr_init(&ma);
1527 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1532 ret = pthread_mutex_init(m, &ma);
1535 pthread_mutexattr_destroy(&ma);
1540 static size_t socket_wrapper_max_sockets(void)
1546 if (socket_info_max != 0) {
1547 return socket_info_max;
1550 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1552 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1553 if (s == NULL || s[0] == '\0') {
1557 tmp = strtoul(s, &endp, 10);
1562 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1563 SWRAP_LOG(SWRAP_LOG_ERROR,
1564 "Invalid number of sockets specified, "
1565 "using default (%zu)",
1569 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1570 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1571 SWRAP_LOG(SWRAP_LOG_ERROR,
1572 "Invalid number of sockets specified, "
1573 "using maximum (%zu).",
1577 socket_info_max = tmp;
1580 return socket_info_max;
1583 static void socket_wrapper_init_fds_idx(void)
1588 if (socket_fds_idx != NULL) {
1592 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1594 SWRAP_LOG(SWRAP_LOG_ERROR,
1595 "Failed to allocate socket fds index array: %s",
1600 for (i = 0; i < socket_fds_max; i++) {
1604 socket_fds_idx = tmp;
1607 static void socket_wrapper_init_sockets(void)
1613 swrap_bind_symbol_all();
1615 swrap_mutex_lock(&sockets_mutex);
1617 if (sockets != NULL) {
1618 swrap_mutex_unlock(&sockets_mutex);
1623 * Intialize the static cache early before
1624 * any thread is able to start.
1626 (void)swrap_ipv4_net();
1628 socket_wrapper_init_fds_idx();
1630 /* Needs to be called inside the sockets_mutex lock here. */
1631 max_sockets = socket_wrapper_max_sockets();
1633 sockets = (struct socket_info_container *)calloc(max_sockets,
1634 sizeof(struct socket_info_container));
1636 if (sockets == NULL) {
1637 SWRAP_LOG(SWRAP_LOG_ERROR,
1638 "Failed to allocate sockets array: %s",
1640 swrap_mutex_unlock(&sockets_mutex);
1644 swrap_mutex_lock(&first_free_mutex);
1648 for (i = 0; i < max_sockets; i++) {
1649 swrap_set_next_free(&sockets[i].info, i+1);
1650 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1652 SWRAP_LOG(SWRAP_LOG_ERROR,
1653 "Failed to initialize pthread mutex");
1658 /* mark the end of the free list */
1659 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1661 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1663 SWRAP_LOG(SWRAP_LOG_ERROR,
1664 "Failed to initialize pthread mutex");
1668 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1670 SWRAP_LOG(SWRAP_LOG_ERROR,
1671 "Failed to initialize pthread mutex");
1675 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1677 SWRAP_LOG(SWRAP_LOG_ERROR,
1678 "Failed to initialize pthread mutex");
1683 swrap_mutex_unlock(&first_free_mutex);
1684 swrap_mutex_unlock(&sockets_mutex);
1690 bool socket_wrapper_enabled(void)
1692 char *s = socket_wrapper_dir();
1700 socket_wrapper_init_sockets();
1705 static unsigned int socket_wrapper_default_iface(void)
1707 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1710 if (sscanf(s, "%u", &iface) == 1) {
1711 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1717 return 1;/* 127.0.0.1 */
1720 static void set_socket_info_index(int fd, int idx)
1722 SWRAP_LOG(SWRAP_LOG_TRACE,
1725 socket_fds_idx[fd] = idx;
1726 /* This builtin issues a full memory barrier. */
1727 __sync_synchronize();
1730 static void reset_socket_info_index(int fd)
1732 SWRAP_LOG(SWRAP_LOG_TRACE,
1735 set_socket_info_index(fd, -1);
1738 static int find_socket_info_index(int fd)
1744 if (socket_fds_idx == NULL) {
1748 if ((size_t)fd >= socket_fds_max) {
1750 * Do not add a log here as some applications do stupid things
1753 * for (fd = 0; fd <= getdtablesize(); fd++) {
1757 * This would produce millions of lines of debug messages.
1760 SWRAP_LOG(SWRAP_LOG_ERROR,
1761 "Looking for a socket info for the fd %d is over the "
1762 "max socket index limit of %zu.",
1769 /* This builtin issues a full memory barrier. */
1770 __sync_synchronize();
1771 return socket_fds_idx[fd];
1774 static int swrap_add_socket_info(struct socket_info *si_input)
1776 struct socket_info *si = NULL;
1779 if (si_input == NULL) {
1784 swrap_mutex_lock(&first_free_mutex);
1785 if (first_free == -1) {
1790 si_index = first_free;
1791 si = swrap_get_socket_info(si_index);
1795 first_free = swrap_get_next_free(si);
1797 swrap_inc_refcount(si);
1799 SWRAP_UNLOCK_SI(si);
1802 swrap_mutex_unlock(&first_free_mutex);
1807 static int swrap_create_socket(struct socket_info *si, int fd)
1811 if ((size_t)fd >= socket_fds_max) {
1812 SWRAP_LOG(SWRAP_LOG_ERROR,
1813 "The max socket index limit of %zu has been reached, "
1820 idx = swrap_add_socket_info(si);
1825 set_socket_info_index(fd, idx);
1830 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1837 p = strrchr(un->sun_path, '/');
1838 if (p) p++; else p = un->sun_path;
1840 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1845 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1848 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1859 case SOCKET_TYPE_CHAR_TCP:
1860 case SOCKET_TYPE_CHAR_UDP: {
1861 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1863 if ((*len) < sizeof(*in2)) {
1868 memset(in2, 0, sizeof(*in2));
1869 in2->sin_family = AF_INET;
1870 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1871 in2->sin_port = htons(prt);
1873 *len = sizeof(*in2);
1877 case SOCKET_TYPE_CHAR_TCP_V6:
1878 case SOCKET_TYPE_CHAR_UDP_V6: {
1879 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1881 if ((*len) < sizeof(*in2)) {
1886 memset(in2, 0, sizeof(*in2));
1887 in2->sin6_family = AF_INET6;
1888 in2->sin6_addr = *swrap_ipv6();
1889 in2->sin6_addr.s6_addr[15] = iface;
1890 in2->sin6_port = htons(prt);
1892 *len = sizeof(*in2);
1904 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1911 char *swrap_dir = NULL;
1913 if (bcast) *bcast = 0;
1915 switch (inaddr->sa_family) {
1917 const struct sockaddr_in *in =
1918 (const struct sockaddr_in *)(const void *)inaddr;
1919 unsigned int addr = ntohl(in->sin_addr.s_addr);
1923 const unsigned int sw_net_addr = swrap_ipv4_net();
1924 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1928 u_type = SOCKET_TYPE_CHAR_TCP;
1931 u_type = SOCKET_TYPE_CHAR_UDP;
1932 a_type = SOCKET_TYPE_CHAR_UDP;
1933 b_type = SOCKET_TYPE_CHAR_UDP;
1936 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1937 errno = ESOCKTNOSUPPORT;
1941 prt = ntohs(in->sin_port);
1942 if (a_type && addr == 0xFFFFFFFF) {
1943 /* 255.255.255.255 only udp */
1946 iface = socket_wrapper_default_iface();
1947 } else if (b_type && addr == sw_bcast_addr) {
1956 iface = socket_wrapper_default_iface();
1957 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
1958 /* 127.0.0.X or 10.53.57.X */
1961 iface = (addr & 0x000000FF);
1963 errno = ENETUNREACH;
1966 if (bcast) *bcast = is_bcast;
1971 const struct sockaddr_in6 *in =
1972 (const struct sockaddr_in6 *)(const void *)inaddr;
1973 struct in6_addr cmp1, cmp2;
1977 type = SOCKET_TYPE_CHAR_TCP_V6;
1980 type = SOCKET_TYPE_CHAR_UDP_V6;
1983 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1984 errno = ESOCKTNOSUPPORT;
1988 /* XXX no multicast/broadcast */
1990 prt = ntohs(in->sin6_port);
1992 cmp1 = *swrap_ipv6();
1993 cmp2 = in->sin6_addr;
1994 cmp2.s6_addr[15] = 0;
1995 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1996 iface = in->sin6_addr.s6_addr[15];
1998 errno = ENETUNREACH;
2006 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2007 errno = ENETUNREACH;
2012 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2017 swrap_dir = socket_wrapper_dir();
2018 if (swrap_dir == NULL) {
2024 swrap_un_path_EINVAL(un, swrap_dir);
2025 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2026 SAFE_FREE(swrap_dir);
2027 /* the caller need to do more processing */
2031 swrap_un_path(un, swrap_dir, type, iface, prt);
2032 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2034 SAFE_FREE(swrap_dir);
2039 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2047 char *swrap_dir = NULL;
2049 if (bcast) *bcast = 0;
2051 switch (si->family) {
2053 const struct sockaddr_in *in =
2054 (const struct sockaddr_in *)(const void *)inaddr;
2055 unsigned int addr = ntohl(in->sin_addr.s_addr);
2060 const unsigned int sw_net_addr = swrap_ipv4_net();
2061 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2063 prt = ntohs(in->sin_port);
2067 u_type = SOCKET_TYPE_CHAR_TCP;
2068 d_type = SOCKET_TYPE_CHAR_TCP;
2071 u_type = SOCKET_TYPE_CHAR_UDP;
2072 d_type = SOCKET_TYPE_CHAR_UDP;
2073 a_type = SOCKET_TYPE_CHAR_UDP;
2074 b_type = SOCKET_TYPE_CHAR_UDP;
2077 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2078 errno = ESOCKTNOSUPPORT;
2086 iface = socket_wrapper_default_iface();
2087 } else if (a_type && addr == 0xFFFFFFFF) {
2088 /* 255.255.255.255 only udp */
2091 iface = socket_wrapper_default_iface();
2092 } else if (b_type && addr == sw_bcast_addr) {
2093 /* 127.255.255.255 only udp */
2096 iface = socket_wrapper_default_iface();
2097 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2101 iface = (addr & 0x000000FF);
2103 errno = EADDRNOTAVAIL;
2107 /* Store the bind address for connect() */
2108 if (si->bindname.sa_socklen == 0) {
2109 struct sockaddr_in bind_in;
2110 socklen_t blen = sizeof(struct sockaddr_in);
2112 ZERO_STRUCT(bind_in);
2113 bind_in.sin_family = in->sin_family;
2114 bind_in.sin_port = in->sin_port;
2115 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2116 si->bindname.sa_socklen = blen;
2117 memcpy(&si->bindname.sa.in, &bind_in, blen);
2124 const struct sockaddr_in6 *in =
2125 (const struct sockaddr_in6 *)(const void *)inaddr;
2126 struct in6_addr cmp1, cmp2;
2130 type = SOCKET_TYPE_CHAR_TCP_V6;
2133 type = SOCKET_TYPE_CHAR_UDP_V6;
2136 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2137 errno = ESOCKTNOSUPPORT;
2141 /* XXX no multicast/broadcast */
2143 prt = ntohs(in->sin6_port);
2145 cmp1 = *swrap_ipv6();
2146 cmp2 = in->sin6_addr;
2147 cmp2.s6_addr[15] = 0;
2148 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2149 iface = socket_wrapper_default_iface();
2150 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2151 iface = in->sin6_addr.s6_addr[15];
2153 errno = EADDRNOTAVAIL;
2157 /* Store the bind address for connect() */
2158 if (si->bindname.sa_socklen == 0) {
2159 struct sockaddr_in6 bind_in;
2160 socklen_t blen = sizeof(struct sockaddr_in6);
2162 ZERO_STRUCT(bind_in);
2163 bind_in.sin6_family = in->sin6_family;
2164 bind_in.sin6_port = in->sin6_port;
2166 bind_in.sin6_addr = *swrap_ipv6();
2167 bind_in.sin6_addr.s6_addr[15] = iface;
2169 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2170 si->bindname.sa_socklen = blen;
2177 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2178 errno = EADDRNOTAVAIL;
2183 if (bcast) *bcast = is_bcast;
2185 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2190 swrap_dir = socket_wrapper_dir();
2191 if (swrap_dir == NULL) {
2197 /* handle auto-allocation of ephemeral ports */
2198 for (prt = 5001; prt < 10000; prt++) {
2199 swrap_un_path(un, swrap_dir, type, iface, prt);
2200 if (stat(un->sun_path, &st) == 0) continue;
2202 set_port(si->family, prt, &si->myname);
2203 set_port(si->family, prt, &si->bindname);
2210 SAFE_FREE(swrap_dir);
2215 swrap_un_path(un, swrap_dir, type, iface, prt);
2216 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2218 SAFE_FREE(swrap_dir);
2223 static struct socket_info *find_socket_info(int fd)
2225 int idx = find_socket_info_index(fd);
2231 return swrap_get_socket_info(idx);
2235 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2237 struct socket_info_fd *f;
2238 const struct socket_info *last_s = NULL;
2240 /* first catch invalid input */
2241 switch (sa->sa_family) {
2243 if (len < sizeof(struct sockaddr_in)) {
2249 if (len < sizeof(struct sockaddr_in6)) {
2259 for (f = socket_fds; f; f = f->next) {
2260 struct socket_info *s = swrap_get_socket_info(f->si_index);
2267 if (s->myname == NULL) {
2270 if (s->myname->sa_family != sa->sa_family) {
2273 switch (s->myname->sa_family) {
2275 struct sockaddr_in *sin1, *sin2;
2277 sin1 = (struct sockaddr_in *)s->myname;
2278 sin2 = (struct sockaddr_in *)sa;
2280 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2283 if (sin1->sin_port != sin2->sin_port) {
2286 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2296 struct sockaddr_in6 *sin1, *sin2;
2298 sin1 = (struct sockaddr_in6 *)s->myname;
2299 sin2 = (struct sockaddr_in6 *)sa;
2301 if (sin1->sin6_port != sin2->sin6_port) {
2304 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2326 static void swrap_remove_stale(int fd)
2328 struct socket_info *si;
2331 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2333 swrap_mutex_lock(&socket_reset_mutex);
2335 si_index = find_socket_info_index(fd);
2336 if (si_index == -1) {
2337 swrap_mutex_unlock(&socket_reset_mutex);
2341 reset_socket_info_index(fd);
2343 si = swrap_get_socket_info(si_index);
2345 swrap_mutex_lock(&first_free_mutex);
2348 swrap_dec_refcount(si);
2350 if (swrap_get_refcount(si) > 0) {
2354 if (si->un_addr.sun_path[0] != '\0') {
2355 unlink(si->un_addr.sun_path);
2358 swrap_set_next_free(si, first_free);
2359 first_free = si_index;
2362 SWRAP_UNLOCK_SI(si);
2363 swrap_mutex_unlock(&first_free_mutex);
2364 swrap_mutex_unlock(&socket_reset_mutex);
2367 static int sockaddr_convert_to_un(struct socket_info *si,
2368 const struct sockaddr *in_addr,
2370 struct sockaddr_un *out_addr,
2374 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2376 (void) in_len; /* unused */
2378 if (out_addr == NULL) {
2382 out->sa_family = AF_UNIX;
2383 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2384 out->sa_len = sizeof(*out_addr);
2387 switch (in_addr->sa_family) {
2389 const struct sockaddr_in *sin;
2390 if (si->family != AF_INET) {
2393 if (in_len < sizeof(struct sockaddr_in)) {
2396 sin = (const struct sockaddr_in *)(const void *)in_addr;
2397 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2402 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2403 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2417 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2418 errno = ESOCKTNOSUPPORT;
2422 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2424 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2430 errno = EAFNOSUPPORT;
2431 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2435 static int sockaddr_convert_from_un(const struct socket_info *si,
2436 const struct sockaddr_un *in_addr,
2437 socklen_t un_addrlen,
2439 struct sockaddr *out_addr,
2440 socklen_t *out_addrlen)
2444 if (out_addr == NULL || out_addrlen == NULL)
2447 if (un_addrlen == 0) {
2462 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2463 errno = ESOCKTNOSUPPORT;
2466 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2467 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2468 out_addr->sa_len = *out_addrlen;
2475 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2476 errno = EAFNOSUPPORT;
2480 enum swrap_packet_type {
2482 SWRAP_CONNECT_UNREACH,
2490 SWRAP_SENDTO_UNREACH,
2501 struct swrap_file_hdr {
2503 uint16_t version_major;
2504 uint16_t version_minor;
2507 uint32_t frame_max_len;
2508 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2511 #define SWRAP_FILE_HDR_SIZE 24
2513 struct swrap_packet_frame {
2515 uint32_t micro_seconds;
2516 uint32_t recorded_length;
2517 uint32_t full_length;
2519 #define SWRAP_PACKET_FRAME_SIZE 16
2521 union swrap_packet_ip {
2525 uint16_t packet_length;
2526 uint16_t identification;
2531 uint16_t hdr_checksum;
2535 #define SWRAP_PACKET_IP_V4_SIZE 20
2538 uint8_t flow_label_high;
2539 uint16_t flow_label_low;
2540 uint16_t payload_length;
2541 uint8_t next_header;
2543 uint8_t src_addr[16];
2544 uint8_t dest_addr[16];
2546 #define SWRAP_PACKET_IP_V6_SIZE 40
2548 #define SWRAP_PACKET_IP_SIZE 40
2550 union swrap_packet_payload {
2552 uint16_t source_port;
2562 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2564 uint16_t source_port;
2569 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2576 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2583 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2585 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2587 #define SWRAP_PACKET_MIN_ALLOC \
2588 (SWRAP_PACKET_FRAME_SIZE + \
2589 SWRAP_PACKET_IP_SIZE + \
2590 SWRAP_PACKET_PAYLOAD_SIZE)
2592 static const char *swrap_pcap_init_file(void)
2594 static int initialized = 0;
2595 static const char *s = NULL;
2596 static const struct swrap_file_hdr h;
2597 static const struct swrap_packet_frame f;
2598 static const union swrap_packet_ip i;
2599 static const union swrap_packet_payload p;
2601 if (initialized == 1) {
2607 * TODO: don't use the structs use plain buffer offsets
2608 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2610 * for now make sure we disable PCAP support
2611 * if the struct has alignment!
2613 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2616 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2619 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2622 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2625 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2628 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2631 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2634 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2637 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2640 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2644 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2648 if (strncmp(s, "./", 2) == 0) {
2651 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2655 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2656 const struct sockaddr *src,
2657 const struct sockaddr *dest,
2659 const uint8_t *payload,
2661 unsigned long tcp_seqno,
2662 unsigned long tcp_ack,
2663 unsigned char tcp_ctl,
2665 size_t *_packet_len)
2667 uint8_t *base = NULL;
2668 uint8_t *buf = NULL;
2671 struct swrap_packet_frame *frame;
2675 union swrap_packet_ip *ip;
2677 union swrap_packet_payload *pay;
2680 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2681 size_t wire_hdr_len = 0;
2682 size_t wire_len = 0;
2683 size_t ip_hdr_len = 0;
2684 size_t icmp_hdr_len = 0;
2685 size_t icmp_truncate_len = 0;
2686 uint8_t protocol = 0, icmp_protocol = 0;
2687 const struct sockaddr_in *src_in = NULL;
2688 const struct sockaddr_in *dest_in = NULL;
2690 const struct sockaddr_in6 *src_in6 = NULL;
2691 const struct sockaddr_in6 *dest_in6 = NULL;
2696 switch (src->sa_family) {
2698 src_in = (const struct sockaddr_in *)(const void *)src;
2699 dest_in = (const struct sockaddr_in *)(const void *)dest;
2700 src_port = src_in->sin_port;
2701 dest_port = dest_in->sin_port;
2702 ip_hdr_len = sizeof(i.ip->v4);
2706 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2707 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2708 src_port = src_in6->sin6_port;
2709 dest_port = dest_in6->sin6_port;
2710 ip_hdr_len = sizeof(i.ip->v6);
2717 switch (socket_type) {
2719 protocol = 0x06; /* TCP */
2720 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2721 wire_len = wire_hdr_len + payload_len;
2725 protocol = 0x11; /* UDP */
2726 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2727 wire_len = wire_hdr_len + payload_len;
2735 icmp_protocol = protocol;
2736 switch (src->sa_family) {
2738 protocol = 0x01; /* ICMPv4 */
2739 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2743 protocol = 0x3A; /* ICMPv6 */
2744 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2748 if (wire_len > 64 ) {
2749 icmp_truncate_len = wire_len - 64;
2751 wire_len += icmp_hdr_len;
2754 packet_len = nonwire_len + wire_len;
2755 alloc_len = packet_len;
2756 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2757 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2760 base = (uint8_t *)calloc(1, alloc_len);
2768 f.frame->seconds = tval->tv_sec;
2769 f.frame->micro_seconds = tval->tv_usec;
2770 f.frame->recorded_length = wire_len - icmp_truncate_len;
2771 f.frame->full_length = wire_len - icmp_truncate_len;
2773 buf += SWRAP_PACKET_FRAME_SIZE;
2776 switch (src->sa_family) {
2778 if (src_in == NULL || dest_in == NULL) {
2783 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2784 i.ip->v4.tos = 0x00;
2785 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2786 i.ip->v4.identification = htons(0xFFFF);
2787 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2788 i.ip->v4.fragment = htons(0x0000);
2789 i.ip->v4.ttl = 0xFF;
2790 i.ip->v4.protocol = protocol;
2791 i.ip->v4.hdr_checksum = htons(0x0000);
2792 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2793 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2794 buf += SWRAP_PACKET_IP_V4_SIZE;
2798 if (src_in6 == NULL || dest_in6 == NULL) {
2803 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2804 i.ip->v6.flow_label_high = 0x00;
2805 i.ip->v6.flow_label_low = 0x0000;
2806 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2807 i.ip->v6.next_header = protocol;
2808 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2809 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2810 buf += SWRAP_PACKET_IP_V6_SIZE;
2816 pay = (union swrap_packet_payload *)(void *)buf;
2817 switch (src->sa_family) {
2819 pay->icmp4.type = 0x03; /* destination unreachable */
2820 pay->icmp4.code = 0x01; /* host unreachable */
2821 pay->icmp4.checksum = htons(0x0000);
2822 pay->icmp4.unused = htonl(0x00000000);
2824 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2826 /* set the ip header in the ICMP payload */
2828 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2829 i.ip->v4.tos = 0x00;
2830 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2831 i.ip->v4.identification = htons(0xFFFF);
2832 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2833 i.ip->v4.fragment = htons(0x0000);
2834 i.ip->v4.ttl = 0xFF;
2835 i.ip->v4.protocol = icmp_protocol;
2836 i.ip->v4.hdr_checksum = htons(0x0000);
2837 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2838 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2840 buf += SWRAP_PACKET_IP_V4_SIZE;
2842 src_port = dest_in->sin_port;
2843 dest_port = src_in->sin_port;
2847 pay->icmp6.type = 0x01; /* destination unreachable */
2848 pay->icmp6.code = 0x03; /* address unreachable */
2849 pay->icmp6.checksum = htons(0x0000);
2850 pay->icmp6.unused = htonl(0x00000000);
2851 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2853 /* set the ip header in the ICMP payload */
2855 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2856 i.ip->v6.flow_label_high = 0x00;
2857 i.ip->v6.flow_label_low = 0x0000;
2858 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2859 i.ip->v6.next_header = protocol;
2860 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2861 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2863 buf += SWRAP_PACKET_IP_V6_SIZE;
2865 src_port = dest_in6->sin6_port;
2866 dest_port = src_in6->sin6_port;
2872 pay = (union swrap_packet_payload *)(void *)buf;
2874 switch (socket_type) {
2876 pay->tcp.source_port = src_port;
2877 pay->tcp.dest_port = dest_port;
2878 pay->tcp.seq_num = htonl(tcp_seqno);
2879 pay->tcp.ack_num = htonl(tcp_ack);
2880 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2881 pay->tcp.control = tcp_ctl;
2882 pay->tcp.window = htons(0x7FFF);
2883 pay->tcp.checksum = htons(0x0000);
2884 pay->tcp.urg = htons(0x0000);
2885 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2890 pay->udp.source_port = src_port;
2891 pay->udp.dest_port = dest_port;
2892 pay->udp.length = htons(8 + payload_len);
2893 pay->udp.checksum = htons(0x0000);
2894 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2899 if (payload && payload_len > 0) {
2900 memcpy(buf, payload, payload_len);
2903 *_packet_len = packet_len - icmp_truncate_len;
2907 static int swrap_pcap_get_fd(const char *fname)
2915 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2917 struct swrap_file_hdr file_hdr;
2918 file_hdr.magic = 0xA1B2C3D4;
2919 file_hdr.version_major = 0x0002;
2920 file_hdr.version_minor = 0x0004;
2921 file_hdr.timezone = 0x00000000;
2922 file_hdr.sigfigs = 0x00000000;
2923 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2924 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2926 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2933 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2938 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2939 const struct sockaddr *addr,
2940 enum swrap_packet_type type,
2941 const void *buf, size_t len,
2944 const struct sockaddr *src_addr;
2945 const struct sockaddr *dest_addr;
2946 unsigned long tcp_seqno = 0;
2947 unsigned long tcp_ack = 0;
2948 unsigned char tcp_ctl = 0;
2949 int unreachable = 0;
2953 switch (si->family) {
2965 case SWRAP_CONNECT_SEND:
2966 if (si->type != SOCK_STREAM) {
2970 src_addr = &si->myname.sa.s;
2973 tcp_seqno = si->io.pck_snd;
2974 tcp_ack = si->io.pck_rcv;
2975 tcp_ctl = 0x02; /* SYN */
2977 si->io.pck_snd += 1;
2981 case SWRAP_CONNECT_RECV:
2982 if (si->type != SOCK_STREAM) {
2986 dest_addr = &si->myname.sa.s;
2989 tcp_seqno = si->io.pck_rcv;
2990 tcp_ack = si->io.pck_snd;
2991 tcp_ctl = 0x12; /** SYN,ACK */
2993 si->io.pck_rcv += 1;
2997 case SWRAP_CONNECT_UNREACH:
2998 if (si->type != SOCK_STREAM) {
3002 dest_addr = &si->myname.sa.s;
3005 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3006 tcp_seqno = si->io.pck_snd - 1;
3007 tcp_ack = si->io.pck_rcv;
3008 tcp_ctl = 0x02; /* SYN */
3013 case SWRAP_CONNECT_ACK:
3014 if (si->type != SOCK_STREAM) {
3018 src_addr = &si->myname.sa.s;
3021 tcp_seqno = si->io.pck_snd;
3022 tcp_ack = si->io.pck_rcv;
3023 tcp_ctl = 0x10; /* ACK */
3027 case SWRAP_ACCEPT_SEND:
3028 if (si->type != SOCK_STREAM) {
3032 dest_addr = &si->myname.sa.s;
3035 tcp_seqno = si->io.pck_rcv;
3036 tcp_ack = si->io.pck_snd;
3037 tcp_ctl = 0x02; /* SYN */
3039 si->io.pck_rcv += 1;
3043 case SWRAP_ACCEPT_RECV:
3044 if (si->type != SOCK_STREAM) {
3048 src_addr = &si->myname.sa.s;
3051 tcp_seqno = si->io.pck_snd;
3052 tcp_ack = si->io.pck_rcv;
3053 tcp_ctl = 0x12; /* SYN,ACK */
3055 si->io.pck_snd += 1;
3059 case SWRAP_ACCEPT_ACK:
3060 if (si->type != SOCK_STREAM) {
3064 dest_addr = &si->myname.sa.s;
3067 tcp_seqno = si->io.pck_rcv;
3068 tcp_ack = si->io.pck_snd;
3069 tcp_ctl = 0x10; /* ACK */
3074 src_addr = &si->myname.sa.s;
3075 dest_addr = &si->peername.sa.s;
3077 tcp_seqno = si->io.pck_snd;
3078 tcp_ack = si->io.pck_rcv;
3079 tcp_ctl = 0x18; /* PSH,ACK */
3081 si->io.pck_snd += len;
3085 case SWRAP_SEND_RST:
3086 dest_addr = &si->myname.sa.s;
3087 src_addr = &si->peername.sa.s;
3089 if (si->type == SOCK_DGRAM) {
3090 return swrap_pcap_marshall_packet(si,
3092 SWRAP_SENDTO_UNREACH,
3098 tcp_seqno = si->io.pck_rcv;
3099 tcp_ack = si->io.pck_snd;
3100 tcp_ctl = 0x14; /** RST,ACK */
3104 case SWRAP_PENDING_RST:
3105 dest_addr = &si->myname.sa.s;
3106 src_addr = &si->peername.sa.s;
3108 if (si->type == SOCK_DGRAM) {
3112 tcp_seqno = si->io.pck_rcv;
3113 tcp_ack = si->io.pck_snd;
3114 tcp_ctl = 0x14; /* RST,ACK */
3119 dest_addr = &si->myname.sa.s;
3120 src_addr = &si->peername.sa.s;
3122 tcp_seqno = si->io.pck_rcv;
3123 tcp_ack = si->io.pck_snd;
3124 tcp_ctl = 0x18; /* PSH,ACK */
3126 si->io.pck_rcv += len;
3130 case SWRAP_RECV_RST:
3131 dest_addr = &si->myname.sa.s;
3132 src_addr = &si->peername.sa.s;
3134 if (si->type == SOCK_DGRAM) {
3138 tcp_seqno = si->io.pck_rcv;
3139 tcp_ack = si->io.pck_snd;
3140 tcp_ctl = 0x14; /* RST,ACK */
3145 src_addr = &si->myname.sa.s;
3148 si->io.pck_snd += len;
3152 case SWRAP_SENDTO_UNREACH:
3153 dest_addr = &si->myname.sa.s;
3160 case SWRAP_RECVFROM:
3161 dest_addr = &si->myname.sa.s;
3164 si->io.pck_rcv += len;
3168 case SWRAP_CLOSE_SEND:
3169 if (si->type != SOCK_STREAM) {
3173 src_addr = &si->myname.sa.s;
3174 dest_addr = &si->peername.sa.s;
3176 tcp_seqno = si->io.pck_snd;
3177 tcp_ack = si->io.pck_rcv;
3178 tcp_ctl = 0x11; /* FIN, ACK */
3180 si->io.pck_snd += 1;
3184 case SWRAP_CLOSE_RECV:
3185 if (si->type != SOCK_STREAM) {
3189 dest_addr = &si->myname.sa.s;
3190 src_addr = &si->peername.sa.s;
3192 tcp_seqno = si->io.pck_rcv;
3193 tcp_ack = si->io.pck_snd;
3194 tcp_ctl = 0x11; /* FIN,ACK */
3196 si->io.pck_rcv += 1;
3200 case SWRAP_CLOSE_ACK:
3201 if (si->type != SOCK_STREAM) {
3205 src_addr = &si->myname.sa.s;
3206 dest_addr = &si->peername.sa.s;
3208 tcp_seqno = si->io.pck_snd;
3209 tcp_ack = si->io.pck_rcv;
3210 tcp_ctl = 0x10; /* ACK */
3217 swrapGetTimeOfDay(&tv);
3219 return swrap_pcap_packet_init(&tv,
3223 (const uint8_t *)buf,
3232 static void swrap_pcap_dump_packet(struct socket_info *si,
3233 const struct sockaddr *addr,
3234 enum swrap_packet_type type,
3235 const void *buf, size_t len)
3237 const char *file_name;
3239 size_t packet_len = 0;
3242 swrap_mutex_lock(&pcap_dump_mutex);
3244 file_name = swrap_pcap_init_file();
3249 packet = swrap_pcap_marshall_packet(si,
3255 if (packet == NULL) {
3259 fd = swrap_pcap_get_fd(file_name);
3261 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3270 swrap_mutex_unlock(&pcap_dump_mutex);
3273 /****************************************************************************
3275 ***************************************************************************/
3277 #ifdef HAVE_SIGNALFD
3278 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3282 rc = libc_signalfd(fd, mask, flags);
3284 swrap_remove_stale(fd);
3290 int signalfd(int fd, const sigset_t *mask, int flags)
3292 return swrap_signalfd(fd, mask, flags);
3296 /****************************************************************************
3298 ***************************************************************************/
3300 static int swrap_socket(int family, int type, int protocol)
3302 struct socket_info *si = NULL;
3303 struct socket_info _si = { 0 };
3306 int real_type = type;
3309 * Remove possible addition flags passed to socket() so
3310 * do not fail checking the type.
3311 * See https://lwn.net/Articles/281965/
3314 real_type &= ~SOCK_CLOEXEC;
3316 #ifdef SOCK_NONBLOCK
3317 real_type &= ~SOCK_NONBLOCK;
3320 if (!socket_wrapper_enabled()) {
3321 return libc_socket(family, type, protocol);
3332 #endif /* AF_NETLINK */
3335 #endif /* AF_PACKET */
3337 fd = libc_socket(family, type, protocol);
3339 /* Check if we have a stale fd and remove it */
3340 swrap_remove_stale(fd);
3341 SWRAP_LOG(SWRAP_LOG_TRACE,
3342 "Unix socket fd=%d",
3347 errno = EAFNOSUPPORT;
3351 switch (real_type) {
3357 errno = EPROTONOSUPPORT;
3365 if (real_type == SOCK_STREAM) {
3370 if (real_type == SOCK_DGRAM) {
3375 errno = EPROTONOSUPPORT;
3380 * We must call libc_socket with type, from the caller, not the version
3381 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3383 fd = libc_socket(AF_UNIX, type, 0);
3389 /* Check if we have a stale fd and remove it */
3390 swrap_remove_stale(fd);
3393 si->family = family;
3395 /* however, the rest of the socket_wrapper code expects just
3396 * the type, not the flags */
3397 si->type = real_type;
3398 si->protocol = protocol;
3401 * Setup myname so getsockname() can succeed to find out the socket
3404 switch(si->family) {
3406 struct sockaddr_in sin = {
3407 .sin_family = AF_INET,
3410 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3411 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3416 struct sockaddr_in6 sin6 = {
3417 .sin6_family = AF_INET6,
3420 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3421 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3430 ret = swrap_create_socket(si, fd);
3435 SWRAP_LOG(SWRAP_LOG_TRACE,
3436 "Created %s socket for protocol %s, fd=%d",
3437 family == AF_INET ? "IPv4" : "IPv6",
3438 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3444 int socket(int family, int type, int protocol)
3446 return swrap_socket(family, type, protocol);
3449 /****************************************************************************
3451 ***************************************************************************/
3453 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3457 rc = libc_socketpair(family, type, protocol, sv);
3459 swrap_remove_stale(sv[0]);
3460 swrap_remove_stale(sv[1]);
3466 int socketpair(int family, int type, int protocol, int sv[2])
3468 return swrap_socketpair(family, type, protocol, sv);
3471 /****************************************************************************
3473 ***************************************************************************/
3475 #ifdef HAVE_TIMERFD_CREATE
3476 static int swrap_timerfd_create(int clockid, int flags)
3480 fd = libc_timerfd_create(clockid, flags);
3482 swrap_remove_stale(fd);
3488 int timerfd_create(int clockid, int flags)
3490 return swrap_timerfd_create(clockid, flags);
3494 /****************************************************************************
3496 ***************************************************************************/
3498 static int swrap_pipe(int pipefd[2])
3502 rc = libc_pipe(pipefd);
3504 swrap_remove_stale(pipefd[0]);
3505 swrap_remove_stale(pipefd[1]);
3511 int pipe(int pipefd[2])
3513 return swrap_pipe(pipefd);
3516 /****************************************************************************
3518 ***************************************************************************/
3520 static int swrap_accept(int s,
3521 struct sockaddr *addr,
3525 struct socket_info *parent_si, *child_si;
3526 struct socket_info new_si = { 0 };
3529 struct swrap_address un_addr = {
3530 .sa_socklen = sizeof(struct sockaddr_un),
3532 struct swrap_address un_my_addr = {
3533 .sa_socklen = sizeof(struct sockaddr_un),
3535 struct swrap_address in_addr = {
3536 .sa_socklen = sizeof(struct sockaddr_storage),
3538 struct swrap_address in_my_addr = {
3539 .sa_socklen = sizeof(struct sockaddr_storage),
3543 parent_si = find_socket_info(s);
3546 return libc_accept4(s, addr, addrlen, flags);
3549 return libc_accept(s, addr, addrlen);
3555 * prevent parent_si from being altered / closed
3558 SWRAP_LOCK_SI(parent_si);
3561 * assume out sockaddr have the same size as the in parent
3564 in_addr.sa_socklen = socket_length(parent_si->family);
3565 if (in_addr.sa_socklen <= 0) {
3566 SWRAP_UNLOCK_SI(parent_si);
3571 SWRAP_UNLOCK_SI(parent_si);
3574 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3577 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3580 if (errno == ENOTSOCK) {
3581 /* Remove stale fds */
3582 swrap_remove_stale(s);
3589 /* Check if we have a stale fd and remove it */
3590 swrap_remove_stale(fd);
3592 SWRAP_LOCK_SI(parent_si);
3594 ret = sockaddr_convert_from_un(parent_si,
3599 &in_addr.sa_socklen);
3601 SWRAP_UNLOCK_SI(parent_si);
3608 child_si->family = parent_si->family;
3609 child_si->type = parent_si->type;
3610 child_si->protocol = parent_si->protocol;
3611 child_si->bound = 1;
3612 child_si->is_server = 1;
3613 child_si->connected = 1;
3615 SWRAP_UNLOCK_SI(parent_si);
3617 child_si->peername = (struct swrap_address) {
3618 .sa_socklen = in_addr.sa_socklen,
3620 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3622 if (addr != NULL && addrlen != NULL) {
3623 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3625 memcpy(addr, &in_addr.sa.ss, copy_len);
3627 *addrlen = in_addr.sa_socklen;
3630 ret = libc_getsockname(fd,
3632 &un_my_addr.sa_socklen);
3638 ret = sockaddr_convert_from_un(child_si,
3640 un_my_addr.sa_socklen,
3643 &in_my_addr.sa_socklen);
3649 SWRAP_LOG(SWRAP_LOG_TRACE,
3650 "accept() path=%s, fd=%d",
3651 un_my_addr.sa.un.sun_path, s);
3653 child_si->myname = (struct swrap_address) {
3654 .sa_socklen = in_my_addr.sa_socklen,
3656 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3658 idx = swrap_create_socket(&new_si, fd);
3665 struct socket_info *si = swrap_get_socket_info(idx);
3668 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3669 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3670 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3671 SWRAP_UNLOCK_SI(si);
3678 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3680 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3684 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3685 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3687 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3690 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3693 static int autobind_start_init;
3694 static int autobind_start;
3696 /* using sendto() or connect() on an unbound socket would give the
3697 recipient no way to reply, as unlike UDP and TCP, a unix domain
3698 socket can't auto-assign ephemeral port numbers, so we need to
3700 Note: this might change the family from ipv6 to ipv4
3702 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3704 struct swrap_address un_addr = {
3705 .sa_socklen = sizeof(struct sockaddr_un),
3712 char *swrap_dir = NULL;
3714 swrap_mutex_lock(&autobind_start_mutex);
3716 if (autobind_start_init != 1) {
3717 autobind_start_init = 1;
3718 autobind_start = getpid();
3719 autobind_start %= 50000;
3720 autobind_start += 10000;
3723 un_addr.sa.un.sun_family = AF_UNIX;
3727 struct sockaddr_in in;
3731 type = SOCKET_TYPE_CHAR_TCP;
3734 type = SOCKET_TYPE_CHAR_UDP;
3737 errno = ESOCKTNOSUPPORT;
3742 memset(&in, 0, sizeof(in));
3743 in.sin_family = AF_INET;
3744 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3745 socket_wrapper_default_iface()));
3747 si->myname = (struct swrap_address) {
3748 .sa_socklen = sizeof(in),
3750 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3755 struct sockaddr_in6 in6;
3757 if (si->family != family) {
3758 errno = ENETUNREACH;
3765 type = SOCKET_TYPE_CHAR_TCP_V6;
3768 type = SOCKET_TYPE_CHAR_UDP_V6;
3771 errno = ESOCKTNOSUPPORT;
3776 memset(&in6, 0, sizeof(in6));
3777 in6.sin6_family = AF_INET6;
3778 in6.sin6_addr = *swrap_ipv6();
3779 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3781 si->myname = (struct swrap_address) {
3782 .sa_socklen = sizeof(in6),
3784 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3789 errno = ESOCKTNOSUPPORT;
3794 if (autobind_start > 60000) {
3795 autobind_start = 10000;
3798 swrap_dir = socket_wrapper_dir();
3799 if (swrap_dir == NULL) {
3805 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3806 port = autobind_start + i;
3807 swrap_un_path(&un_addr.sa.un,
3810 socket_wrapper_default_iface(),
3812 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3814 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3819 si->un_addr = un_addr.sa.un;
3822 autobind_start = port + 1;
3825 if (i == SOCKET_MAX_SOCKETS) {
3826 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3827 "interface "SOCKET_FORMAT,
3830 socket_wrapper_default_iface(),
3837 si->family = family;
3838 set_port(si->family, port, &si->myname);
3843 SAFE_FREE(swrap_dir);
3844 swrap_mutex_unlock(&autobind_start_mutex);
3848 /****************************************************************************
3850 ***************************************************************************/
3852 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3856 struct swrap_address un_addr = {
3857 .sa_socklen = sizeof(struct sockaddr_un),
3859 struct socket_info *si = find_socket_info(s);
3863 return libc_connect(s, serv_addr, addrlen);
3868 if (si->bound == 0) {
3869 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3875 if (si->family != serv_addr->sa_family) {
3876 SWRAP_LOG(SWRAP_LOG_ERROR,
3877 "called for fd=%d (family=%d) called with invalid family=%d",
3878 s, si->family, serv_addr->sa_family);
3884 ret = sockaddr_convert_to_un(si, serv_addr,
3885 addrlen, &un_addr.sa.un, 0, &bcast);
3891 errno = ENETUNREACH;
3896 if (si->type == SOCK_DGRAM) {
3897 si->defer_connect = 1;
3900 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3902 ret = libc_connect(s,
3904 un_addr.sa_socklen);
3907 SWRAP_LOG(SWRAP_LOG_TRACE,
3908 "connect() path=%s, fd=%d",
3909 un_addr.sa.un.sun_path, s);
3912 /* to give better errors */
3913 if (ret == -1 && errno == ENOENT) {
3914 errno = EHOSTUNREACH;
3918 si->peername = (struct swrap_address) {
3919 .sa_socklen = addrlen,
3922 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3926 * When we connect() on a socket than we have to bind the
3927 * outgoing connection on the interface we use for the
3928 * transport. We already bound it on the right interface
3929 * but here we have to update the name so getsockname()
3930 * returns correct information.
3932 if (si->bindname.sa_socklen > 0) {
3933 si->myname = (struct swrap_address) {
3934 .sa_socklen = si->bindname.sa_socklen,
3937 memcpy(&si->myname.sa.ss,
3938 &si->bindname.sa.ss,
3939 si->bindname.sa_socklen);
3941 /* Cleanup bindname */
3942 si->bindname = (struct swrap_address) {
3947 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3948 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3950 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3954 SWRAP_UNLOCK_SI(si);
3958 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3960 return swrap_connect(s, serv_addr, addrlen);
3963 /****************************************************************************
3965 ***************************************************************************/
3967 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3970 struct swrap_address un_addr = {
3971 .sa_socklen = sizeof(struct sockaddr_un),
3973 struct socket_info *si = find_socket_info(s);
3980 return libc_bind(s, myaddr, addrlen);
3985 switch (si->family) {
3987 const struct sockaddr_in *sin;
3988 if (addrlen < sizeof(struct sockaddr_in)) {
3989 bind_error = EINVAL;
3993 sin = (const struct sockaddr_in *)(const void *)myaddr;
3995 if (sin->sin_family != AF_INET) {
3996 bind_error = EAFNOSUPPORT;
3999 /* special case for AF_UNSPEC */
4000 if (sin->sin_family == AF_UNSPEC &&
4001 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4010 const struct sockaddr_in6 *sin6;
4011 if (addrlen < sizeof(struct sockaddr_in6)) {
4012 bind_error = EINVAL;
4016 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4018 if (sin6->sin6_family != AF_INET6) {
4019 bind_error = EAFNOSUPPORT;
4026 bind_error = EINVAL;
4030 if (bind_error != 0) {
4037 in_use = check_addr_port_in_use(myaddr, addrlen);
4045 si->myname.sa_socklen = addrlen;
4046 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4048 ret = sockaddr_convert_to_un(si,
4058 unlink(un_addr.sa.un.sun_path);
4060 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4062 SWRAP_LOG(SWRAP_LOG_TRACE,
4063 "bind() path=%s, fd=%d",
4064 un_addr.sa.un.sun_path, s);
4071 SWRAP_UNLOCK_SI(si);
4076 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4078 return swrap_bind(s, myaddr, addrlen);
4081 /****************************************************************************
4083 ***************************************************************************/
4085 #ifdef HAVE_BINDRESVPORT
4086 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4088 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4090 struct swrap_address myaddr = {
4091 .sa_socklen = sizeof(struct sockaddr_storage),
4094 static uint16_t port;
4099 #define SWRAP_STARTPORT 600
4100 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4101 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4104 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4108 salen = myaddr.sa_socklen;
4111 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4117 memset(&myaddr.sa.ss, 0, salen);
4122 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4125 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4127 salen = sizeof(struct sockaddr_in);
4128 sinp->sin_port = htons(port);
4132 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4134 salen = sizeof(struct sockaddr_in6);
4135 sin6p->sin6_port = htons(port);
4139 errno = EAFNOSUPPORT;
4144 if (port > SWRAP_ENDPORT) {
4145 port = SWRAP_STARTPORT;
4148 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4149 if (rc == 0 || errno != EADDRINUSE) {
4157 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4159 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4163 /****************************************************************************
4165 ***************************************************************************/
4167 static int swrap_listen(int s, int backlog)
4170 struct socket_info *si = find_socket_info(s);
4173 return libc_listen(s, backlog);
4178 if (si->bound == 0) {
4179 ret = swrap_auto_bind(s, si, si->family);
4186 ret = libc_listen(s, backlog);
4192 SWRAP_UNLOCK_SI(si);
4197 int listen(int s, int backlog)
4199 return swrap_listen(s, backlog);
4202 /****************************************************************************
4204 ***************************************************************************/
4206 static FILE *swrap_fopen(const char *name, const char *mode)
4210 fp = libc_fopen(name, mode);
4212 int fd = fileno(fp);
4214 swrap_remove_stale(fd);
4220 FILE *fopen(const char *name, const char *mode)
4222 return swrap_fopen(name, mode);
4225 /****************************************************************************
4227 ***************************************************************************/
4230 static FILE *swrap_fopen64(const char *name, const char *mode)
4234 fp = libc_fopen64(name, mode);
4236 int fd = fileno(fp);
4238 swrap_remove_stale(fd);
4244 FILE *fopen64(const char *name, const char *mode)
4246 return swrap_fopen64(name, mode);
4248 #endif /* HAVE_FOPEN64 */
4250 /****************************************************************************
4252 ***************************************************************************/
4254 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4258 ret = libc_vopen(pathname, flags, ap);
4261 * There are methods for closing descriptors (libc-internal code
4262 * paths, direct syscalls) which close descriptors in ways that
4263 * we can't intercept, so try to recover when we notice that
4266 swrap_remove_stale(ret);
4271 int open(const char *pathname, int flags, ...)
4276 va_start(ap, flags);
4277 fd = swrap_vopen(pathname, flags, ap);
4283 /****************************************************************************
4285 ***************************************************************************/
4288 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4292 ret = libc_vopen64(pathname, flags, ap);
4295 * There are methods for closing descriptors (libc-internal code
4296 * paths, direct syscalls) which close descriptors in ways that
4297 * we can't intercept, so try to recover when we notice that
4300 swrap_remove_stale(ret);
4305 int open64(const char *pathname, int flags, ...)
4310 va_start(ap, flags);
4311 fd = swrap_vopen64(pathname, flags, ap);
4316 #endif /* HAVE_OPEN64 */
4318 /****************************************************************************
4320 ***************************************************************************/
4322 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4326 ret = libc_vopenat(dirfd, path, flags, ap);
4329 * There are methods for closing descriptors (libc-internal code
4330 * paths, direct syscalls) which close descriptors in ways that
4331 * we can't intercept, so try to recover when we notice that
4334 swrap_remove_stale(ret);
4340 int openat(int dirfd, const char *path, int flags, ...)
4345 va_start(ap, flags);
4346 fd = swrap_vopenat(dirfd, path, flags, ap);
4352 /****************************************************************************
4354 ***************************************************************************/
4356 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4358 struct socket_info *si = find_socket_info(s);
4363 return libc_getpeername(s, name, addrlen);
4368 if (si->peername.sa_socklen == 0)
4374 len = MIN(*addrlen, si->peername.sa_socklen);
4380 memcpy(name, &si->peername.sa.ss, len);
4381 *addrlen = si->peername.sa_socklen;
4385 SWRAP_UNLOCK_SI(si);
4390 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4391 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4393 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4396 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4399 /****************************************************************************
4401 ***************************************************************************/
4403 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4405 struct socket_info *si = find_socket_info(s);
4410 return libc_getsockname(s, name, addrlen);
4415 len = MIN(*addrlen, si->myname.sa_socklen);
4421 memcpy(name, &si->myname.sa.ss, len);
4422 *addrlen = si->myname.sa_socklen;
4426 SWRAP_UNLOCK_SI(si);
4431 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4432 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4434 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4437 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4440 /****************************************************************************
4442 ***************************************************************************/
4445 # ifdef SO_PROTOTYPE /* The Solaris name */
4446 # define SO_PROTOCOL SO_PROTOTYPE
4447 # endif /* SO_PROTOTYPE */
4448 #endif /* SO_PROTOCOL */
4450 static int swrap_getsockopt(int s, int level, int optname,
4451 void *optval, socklen_t *optlen)
4453 struct socket_info *si = find_socket_info(s);
4457 return libc_getsockopt(s,
4466 if (level == SOL_SOCKET) {
4470 if (optval == NULL || optlen == NULL ||
4471 *optlen < (socklen_t)sizeof(int)) {
4477 *optlen = sizeof(int);
4478 *(int *)optval = si->family;
4481 #endif /* SO_DOMAIN */
4485 if (optval == NULL || optlen == NULL ||
4486 *optlen < (socklen_t)sizeof(int)) {
4492 *optlen = sizeof(int);
4493 *(int *)optval = si->protocol;
4496 #endif /* SO_PROTOCOL */
4498 if (optval == NULL || optlen == NULL ||
4499 *optlen < (socklen_t)sizeof(int)) {
4505 *optlen = sizeof(int);
4506 *(int *)optval = si->type;
4510 ret = libc_getsockopt(s,
4517 } else if (level == IPPROTO_TCP) {
4522 * This enables sending packets directly out over TCP.
4523 * As a unix socket is doing that any way, report it as
4526 if (optval == NULL || optlen == NULL ||
4527 *optlen < (socklen_t)sizeof(int)) {
4533 *optlen = sizeof(int);
4534 *(int *)optval = si->tcp_nodelay;
4538 #endif /* TCP_NODELAY */
4541 struct tcp_info info;
4542 socklen_t ilen = sizeof(info);
4544 #ifdef HAVE_NETINET_TCP_FSM_H
4545 /* This is FreeBSD */
4546 # define __TCP_LISTEN TCPS_LISTEN
4547 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4548 # define __TCP_CLOSE TCPS_CLOSED
4551 # define __TCP_LISTEN TCP_LISTEN
4552 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4553 # define __TCP_CLOSE TCP_CLOSE
4557 if (si->listening) {
4558 info.tcpi_state = __TCP_LISTEN;
4559 } else if (si->connected) {
4561 * For now we just fake a few values
4562 * supported both by FreeBSD and Linux
4564 info.tcpi_state = __TCP_ESTABLISHED;
4565 info.tcpi_rto = 200000; /* 200 msec */
4566 info.tcpi_rtt = 5000; /* 5 msec */
4567 info.tcpi_rttvar = 5000; /* 5 msec */
4569 info.tcpi_state = __TCP_CLOSE;
4570 info.tcpi_rto = 1000000; /* 1 sec */
4572 info.tcpi_rttvar = 250000; /* 250 msec */
4575 if (optval == NULL || optlen == NULL ||
4576 *optlen < (socklen_t)ilen) {
4583 memcpy(optval, &info, ilen);
4588 #endif /* TCP_INFO */
4594 errno = ENOPROTOOPT;
4598 SWRAP_UNLOCK_SI(si);
4602 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4603 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4605 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4608 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4611 /****************************************************************************
4613 ***************************************************************************/
4615 static int swrap_setsockopt(int s, int level, int optname,
4616 const void *optval, socklen_t optlen)
4618 struct socket_info *si = find_socket_info(s);
4622 return libc_setsockopt(s,
4629 if (level == SOL_SOCKET) {
4630 return libc_setsockopt(s,
4639 if (level == IPPROTO_TCP) {
4646 * This enables sending packets directly out over TCP.
4647 * A unix socket is doing that any way.
4649 if (optval == NULL || optlen == 0 ||
4650 optlen < (socklen_t)sizeof(int)) {
4656 i = *discard_const_p(int, optval);
4657 if (i != 0 && i != 1) {
4662 si->tcp_nodelay = i;
4667 #endif /* TCP_NODELAY */
4673 switch (si->family) {
4675 if (level == IPPROTO_IP) {
4677 if (optname == IP_PKTINFO) {
4678 si->pktinfo = AF_INET;
4680 #endif /* IP_PKTINFO */
4686 if (level == IPPROTO_IPV6) {
4687 #ifdef IPV6_RECVPKTINFO
4688 if (optname == IPV6_RECVPKTINFO) {
4689 si->pktinfo = AF_INET6;
4691 #endif /* IPV6_PKTINFO */
4697 errno = ENOPROTOOPT;
4703 SWRAP_UNLOCK_SI(si);
4707 int setsockopt(int s, int level, int optname,
4708 const void *optval, socklen_t optlen)
4710 return swrap_setsockopt(s, level, optname, optval, optlen);
4713 /****************************************************************************
4715 ***************************************************************************/
4717 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4719 struct socket_info *si = find_socket_info(s);
4721 int *value_ptr = NULL;
4725 return libc_vioctl(s, r, va);
4732 rc = libc_vioctl(s, r, va);
4737 value_ptr = ((int *)va_arg(ap, int *));
4740 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4741 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4742 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4743 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4748 /* this is FreeBSD */
4749 FALL_THROUGH; /* to TIOCOUTQ */
4750 #endif /* FIONWRITE */
4751 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4753 * This may return more bytes then the application
4754 * sent into the socket, for tcp it should
4755 * return the number of unacked bytes.
4757 * On AF_UNIX, all bytes are immediately acked!
4760 value_ptr = ((int *)va_arg(ap, int *));
4768 SWRAP_UNLOCK_SI(si);
4772 #ifdef HAVE_IOCTL_INT
4773 int ioctl(int s, int r, ...)
4775 int ioctl(int s, unsigned long int r, ...)
4783 rc = swrap_vioctl(s, (unsigned long int) r, va);
4794 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4797 # ifdef _ALIGN /* BSD */
4798 #define CMSG_ALIGN _ALIGN
4800 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4801 # endif /* _ALIGN */
4802 #endif /* CMSG_ALIGN */
4805 * @brief Add a cmsghdr to a msghdr.
4807 * This is an function to add any type of cmsghdr. It will operate on the
4808 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4809 * the buffer position after the added cmsg element. Hence, this function is
4810 * intended to be used with an intermediate msghdr and not on the original
4811 * one handed in by the client.
4813 * @param[in] msg The msghdr to which to add the cmsg.
4815 * @param[in] level The cmsg level to set.
4817 * @param[in] type The cmsg type to set.
4819 * @param[in] data The cmsg data to set.
4821 * @param[in] len the length of the data to set.
4823 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4829 size_t cmlen = CMSG_LEN(len);
4830 size_t cmspace = CMSG_SPACE(len);
4831 uint8_t cmbuf[cmspace];
4832 void *cast_ptr = (void *)cmbuf;
4833 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4836 memset(cmbuf, 0, cmspace);
4838 if (msg->msg_controllen < cmlen) {
4839 cmlen = msg->msg_controllen;
4840 msg->msg_flags |= MSG_CTRUNC;
4843 if (msg->msg_controllen < cmspace) {
4844 cmspace = msg->msg_controllen;
4848 * We copy the full input data into an intermediate cmsghdr first
4849 * in order to more easily cope with truncation.
4851 cm->cmsg_len = cmlen;
4852 cm->cmsg_level = level;
4853 cm->cmsg_type = type;
4854 memcpy(CMSG_DATA(cm), data, len);
4857 * We now copy the possibly truncated buffer.
4858 * We copy cmlen bytes, but consume cmspace bytes,
4859 * leaving the possible padding uninitialiazed.
4861 p = (uint8_t *)msg->msg_control;
4862 memcpy(p, cm, cmlen);
4864 msg->msg_control = p;
4865 msg->msg_controllen -= cmspace;
4870 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4873 /* Add packet info */
4874 switch (si->pktinfo) {
4875 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4877 struct sockaddr_in *sin;
4878 #if defined(HAVE_STRUCT_IN_PKTINFO)
4879 struct in_pktinfo pkt;
4880 #elif defined(IP_RECVDSTADDR)
4884 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4885 sin = &si->bindname.sa.in;
4887 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4890 sin = &si->myname.sa.in;
4895 #if defined(HAVE_STRUCT_IN_PKTINFO)
4896 pkt.ipi_ifindex = socket_wrapper_default_iface();
4897 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4898 #elif defined(IP_RECVDSTADDR)
4899 pkt = sin->sin_addr;
4902 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4907 #endif /* IP_PKTINFO */
4908 #if defined(HAVE_IPV6)
4910 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4911 struct sockaddr_in6 *sin6;
4912 struct in6_pktinfo pkt6;
4914 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4915 sin6 = &si->bindname.sa.in6;
4917 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4920 sin6 = &si->myname.sa.in6;
4925 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4926 pkt6.ipi6_addr = sin6->sin6_addr;
4928 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4929 &pkt6, sizeof(pkt6));
4930 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4934 #endif /* IPV6_PKTINFO */
4942 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4943 struct msghdr *omsg)
4947 if (si->pktinfo > 0) {
4948 rc = swrap_msghdr_add_pktinfo(si, omsg);
4954 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4956 size_t *cm_data_space);
4957 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4959 size_t *cm_data_space);
4961 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4963 size_t *cm_data_space) {
4964 struct cmsghdr *cmsg;
4968 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4972 for (cmsg = CMSG_FIRSTHDR(msg);
4974 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4975 switch (cmsg->cmsg_level) {
4977 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4982 rc = swrap_sendmsg_copy_cmsg(cmsg,
4992 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4994 size_t *cm_data_space)
4999 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5001 p = realloc((*cm_data), cmspace);
5007 p = (*cm_data) + (*cm_data_space);
5008 *cm_data_space = cmspace;
5010 memcpy(p, cmsg, cmsg->cmsg_len);
5015 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
5017 size_t *cm_data_space);
5020 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
5022 size_t *cm_data_space)
5026 switch(cmsg->cmsg_type) {
5029 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5036 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5048 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
5050 size_t *cm_data_space)
5052 (void)cmsg; /* unused */
5053 (void)cm_data; /* unused */
5054 (void)cm_data_space; /* unused */
5057 * Passing a IP pktinfo to a unix socket might be rejected by the
5058 * Kernel, at least on FreeBSD. So skip this cmsg.
5062 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5064 static ssize_t swrap_sendmsg_before(int fd,
5065 struct socket_info *si,
5067 struct iovec *tmp_iov,
5068 struct sockaddr_un *tmp_un,
5069 const struct sockaddr_un **to_un,
5070 const struct sockaddr **to,
5092 if (!si->connected) {
5097 if (msg->msg_iovlen == 0) {
5101 mtu = socket_wrapper_mtu();
5102 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5104 nlen = len + msg->msg_iov[i].iov_len;
5114 msg->msg_iovlen = i;
5115 if (msg->msg_iovlen == 0) {
5116 *tmp_iov = msg->msg_iov[0];
5117 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5119 msg->msg_iov = tmp_iov;
5120 msg->msg_iovlen = 1;
5125 if (si->connected) {
5126 if (msg->msg_name != NULL) {
5128 * We are dealing with unix sockets and if we
5129 * are connected, we should only talk to the
5130 * connected unix path. Using the fd to send
5131 * to another server would be hard to achieve.
5133 msg->msg_name = NULL;
5134 msg->msg_namelen = 0;
5137 const struct sockaddr *msg_name;
5138 msg_name = (const struct sockaddr *)msg->msg_name;
5140 if (msg_name == NULL) {
5146 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
5158 msg->msg_name = tmp_un;
5159 msg->msg_namelen = sizeof(*tmp_un);
5162 if (si->bound == 0) {
5163 ret = swrap_auto_bind(fd, si, si->family);
5165 SWRAP_UNLOCK_SI(si);
5166 if (errno == ENOTSOCK) {
5167 swrap_remove_stale(fd);
5170 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
5176 if (!si->defer_connect) {
5180 ret = sockaddr_convert_to_un(si,
5182 si->peername.sa_socklen,
5190 ret = libc_connect(fd,
5191 (struct sockaddr *)(void *)tmp_un,
5194 /* to give better errors */
5195 if (ret == -1 && errno == ENOENT) {
5196 errno = EHOSTUNREACH;
5203 si->defer_connect = 0;
5206 errno = EHOSTUNREACH;
5210 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5211 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
5212 uint8_t *cmbuf = NULL;
5215 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
5222 msg->msg_controllen = 0;
5223 msg->msg_control = NULL;
5224 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
5225 memcpy(msg->msg_control, cmbuf, cmlen);
5226 msg->msg_controllen = cmlen;
5234 SWRAP_UNLOCK_SI(si);
5239 static void swrap_sendmsg_after(int fd,
5240 struct socket_info *si,
5242 const struct sockaddr *to,
5245 int saved_errno = errno;
5252 /* to give better errors */
5254 if (saved_errno == ENOENT) {
5255 saved_errno = EHOSTUNREACH;
5256 } else if (saved_errno == ENOTSOCK) {
5257 /* If the fd is not a socket, remove it */
5258 swrap_remove_stale(fd);
5262 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5263 avail += msg->msg_iov[i].iov_len;
5267 remain = MIN(80, avail);
5272 /* we capture it as one single packet */
5273 buf = (uint8_t *)malloc(remain);
5275 /* we just not capture the packet */
5276 errno = saved_errno;
5280 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5281 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5283 msg->msg_iov[i].iov_base,
5286 remain -= this_time;
5295 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5296 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5298 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5303 if (si->connected) {
5304 to = &si->peername.sa.s;
5307 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5308 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5310 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5315 SWRAP_UNLOCK_SI(si);
5318 errno = saved_errno;
5321 static int swrap_recvmsg_before(int fd,
5322 struct socket_info *si,
5324 struct iovec *tmp_iov)
5331 (void)fd; /* unused */
5336 if (!si->connected) {
5341 if (msg->msg_iovlen == 0) {
5345 mtu = socket_wrapper_mtu();
5346 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5348 nlen = len + msg->msg_iov[i].iov_len;
5353 msg->msg_iovlen = i;
5354 if (msg->msg_iovlen == 0) {
5355 *tmp_iov = msg->msg_iov[0];
5356 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5358 msg->msg_iov = tmp_iov;
5359 msg->msg_iovlen = 1;
5364 if (msg->msg_name == NULL) {
5369 if (msg->msg_iovlen == 0) {
5373 if (si->bound == 0) {
5374 ret = swrap_auto_bind(fd, si, si->family);
5376 SWRAP_UNLOCK_SI(si);
5378 * When attempting to read or write to a
5379 * descriptor, if an underlying autobind fails
5380 * because it's not a socket, stop intercepting
5381 * uses of that descriptor.
5383 if (errno == ENOTSOCK) {
5384 swrap_remove_stale(fd);
5387 SWRAP_LOG(SWRAP_LOG_ERROR,
5388 "swrap_recvmsg_before failed");
5395 errno = EHOSTUNREACH;
5401 SWRAP_UNLOCK_SI(si);
5406 static int swrap_recvmsg_after(int fd,
5407 struct socket_info *si,
5409 const struct sockaddr_un *un_addr,
5410 socklen_t un_addrlen,
5413 int saved_errno = errno;
5415 uint8_t *buf = NULL;
5421 /* to give better errors */
5423 if (saved_errno == ENOENT) {
5424 saved_errno = EHOSTUNREACH;
5425 } else if (saved_errno == ENOTSOCK) {
5426 /* If the fd is not a socket, remove it */
5427 swrap_remove_stale(fd);
5431 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5432 avail += msg->msg_iov[i].iov_len;
5437 /* Convert the socket address before we leave */
5438 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5439 rc = sockaddr_convert_from_un(si,
5456 remain = MIN(80, avail);
5461 /* we capture it as one single packet */
5462 buf = (uint8_t *)malloc(remain);
5464 /* we just not capture the packet */
5465 SWRAP_UNLOCK_SI(si);
5466 errno = saved_errno;
5470 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5471 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5473 msg->msg_iov[i].iov_base,
5476 remain -= this_time;
5481 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5482 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5483 } else if (ret == 0) { /* END OF FILE */
5484 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5485 } else if (ret > 0) {
5486 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5495 if (un_addr != NULL) {
5496 swrap_pcap_dump_packet(si,
5502 swrap_pcap_dump_packet(si,
5515 errno = saved_errno;
5517 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5519 msg->msg_controllen > 0 &&
5520 msg->msg_control != NULL) {
5521 rc = swrap_msghdr_add_socket_info(si, msg);
5523 SWRAP_UNLOCK_SI(si);
5529 SWRAP_UNLOCK_SI(si);
5533 /****************************************************************************
5535 ***************************************************************************/
5537 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5538 struct sockaddr *from, socklen_t *fromlen)
5540 struct swrap_address from_addr = {
5541 .sa_socklen = sizeof(struct sockaddr_un),
5544 struct socket_info *si = find_socket_info(s);
5545 struct swrap_address saddr = {
5546 .sa_socklen = sizeof(struct sockaddr_storage),
5553 return libc_recvfrom(s,
5565 if (from != NULL && fromlen != NULL) {
5566 msg.msg_name = from; /* optional address */
5567 msg.msg_namelen = *fromlen; /* size of address */
5569 msg.msg_name = &saddr.sa.s; /* optional address */
5570 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5572 msg.msg_iov = &tmp; /* scatter/gather array */
5573 msg.msg_iovlen = 1; /* # elements in msg_iov */
5574 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5575 msg.msg_control = NULL; /* ancillary data, see below */
5576 msg.msg_controllen = 0; /* ancillary data buffer len */
5577 msg.msg_flags = 0; /* flags on received message */
5580 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5585 buf = msg.msg_iov[0].iov_base;
5586 len = msg.msg_iov[0].iov_len;
5588 ret = libc_recvfrom(s,
5593 &from_addr.sa_socklen);
5598 tret = swrap_recvmsg_after(s,
5602 from_addr.sa_socklen,
5608 if (from != NULL && fromlen != NULL) {
5609 *fromlen = msg.msg_namelen;
5615 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5616 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5617 struct sockaddr *from, Psocklen_t fromlen)
5619 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5620 struct sockaddr *from, socklen_t *fromlen)
5623 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5626 /****************************************************************************
5628 ***************************************************************************/
5630 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5631 const struct sockaddr *to, socklen_t tolen)
5635 struct swrap_address un_addr = {
5636 .sa_socklen = sizeof(struct sockaddr_un),
5638 const struct sockaddr_un *to_un = NULL;
5641 struct socket_info *si = find_socket_info(s);
5645 return libc_sendto(s, buf, len, flags, to, tolen);
5648 tmp.iov_base = discard_const_p(char, buf);
5652 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5653 msg.msg_namelen = tolen; /* size of address */
5654 msg.msg_iov = &tmp; /* scatter/gather array */
5655 msg.msg_iovlen = 1; /* # elements in msg_iov */
5656 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5657 msg.msg_control = NULL; /* ancillary data, see below */
5658 msg.msg_controllen = 0; /* ancillary data buffer len */
5659 msg.msg_flags = 0; /* flags on received message */
5662 rc = swrap_sendmsg_before(s,
5674 buf = msg.msg_iov[0].iov_base;
5675 len = msg.msg_iov[0].iov_len;
5680 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5682 char *swrap_dir = NULL;
5684 type = SOCKET_TYPE_CHAR_UDP;
5686 swrap_dir = socket_wrapper_dir();
5687 if (swrap_dir == NULL) {
5691 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5692 swrap_un_path(&un_addr.sa.un,
5697 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5699 /* ignore the any errors in broadcast sends */
5705 un_addr.sa_socklen);
5708 SAFE_FREE(swrap_dir);
5712 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5714 SWRAP_UNLOCK_SI(si);
5721 * If it is a dgram socket and we are connected, don't include the
5724 if (si->type == SOCK_DGRAM && si->connected) {
5725 ret = libc_sendto(s,
5732 ret = libc_sendto(s,
5736 (struct sockaddr *)msg.msg_name,
5740 SWRAP_UNLOCK_SI(si);
5742 swrap_sendmsg_after(s, si, &msg, to, ret);
5747 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5748 const struct sockaddr *to, socklen_t tolen)
5750 return swrap_sendto(s, buf, len, flags, to, tolen);
5753 /****************************************************************************
5755 ***************************************************************************/
5757 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5759 struct socket_info *si;
5761 struct swrap_address saddr = {
5762 .sa_socklen = sizeof(struct sockaddr_storage),
5768 si = find_socket_info(s);
5770 return libc_recv(s, buf, len, flags);
5777 msg.msg_name = &saddr.sa.s; /* optional address */
5778 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5779 msg.msg_iov = &tmp; /* scatter/gather array */
5780 msg.msg_iovlen = 1; /* # elements in msg_iov */
5781 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5782 msg.msg_control = NULL; /* ancillary data, see below */
5783 msg.msg_controllen = 0; /* ancillary data buffer len */
5784 msg.msg_flags = 0; /* flags on received message */
5787 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5792 buf = msg.msg_iov[0].iov_base;
5793 len = msg.msg_iov[0].iov_len;
5795 ret = libc_recv(s, buf, len, flags);
5797 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5805 ssize_t recv(int s, void *buf, size_t len, int flags)
5807 return swrap_recv(s, buf, len, flags);
5810 /****************************************************************************
5812 ***************************************************************************/
5814 static ssize_t swrap_read(int s, void *buf, size_t len)
5816 struct socket_info *si;
5819 struct swrap_address saddr = {
5820 .sa_socklen = sizeof(struct sockaddr_storage),
5825 si = find_socket_info(s);
5827 return libc_read(s, buf, len);
5834 msg.msg_name = &saddr.sa.ss; /* optional address */
5835 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5836 msg.msg_iov = &tmp; /* scatter/gather array */
5837 msg.msg_iovlen = 1; /* # elements in msg_iov */
5838 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5839 msg.msg_control = NULL; /* ancillary data, see below */
5840 msg.msg_controllen = 0; /* ancillary data buffer len */
5841 msg.msg_flags = 0; /* flags on received message */
5844 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5846 if (tret == -ENOTSOCK) {
5847 return libc_read(s, buf, len);
5852 buf = msg.msg_iov[0].iov_base;
5853 len = msg.msg_iov[0].iov_len;
5855 ret = libc_read(s, buf, len);
5857 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5865 ssize_t read(int s, void *buf, size_t len)
5867 return swrap_read(s, buf, len);
5870 /****************************************************************************
5872 ***************************************************************************/
5874 static ssize_t swrap_write(int s, const void *buf, size_t len)
5878 struct sockaddr_un un_addr;
5881 struct socket_info *si;
5883 si = find_socket_info(s);
5885 return libc_write(s, buf, len);
5888 tmp.iov_base = discard_const_p(char, buf);
5892 msg.msg_name = NULL; /* optional address */
5893 msg.msg_namelen = 0; /* size of address */
5894 msg.msg_iov = &tmp; /* scatter/gather array */
5895 msg.msg_iovlen = 1; /* # elements in msg_iov */
5896 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5897 msg.msg_control = NULL; /* ancillary data, see below */
5898 msg.msg_controllen = 0; /* ancillary data buffer len */
5899 msg.msg_flags = 0; /* flags on received message */
5902 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5907 buf = msg.msg_iov[0].iov_base;
5908 len = msg.msg_iov[0].iov_len;
5910 ret = libc_write(s, buf, len);
5912 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5917 ssize_t write(int s, const void *buf, size_t len)
5919 return swrap_write(s, buf, len);
5922 /****************************************************************************
5924 ***************************************************************************/
5926 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5930 struct sockaddr_un un_addr;
5933 struct socket_info *si = find_socket_info(s);
5936 return libc_send(s, buf, len, flags);
5939 tmp.iov_base = discard_const_p(char, buf);
5943 msg.msg_name = NULL; /* optional address */
5944 msg.msg_namelen = 0; /* size of address */
5945 msg.msg_iov = &tmp; /* scatter/gather array */
5946 msg.msg_iovlen = 1; /* # elements in msg_iov */
5947 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5948 msg.msg_control = NULL; /* ancillary data, see below */
5949 msg.msg_controllen = 0; /* ancillary data buffer len */
5950 msg.msg_flags = 0; /* flags on received message */
5953 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5958 buf = msg.msg_iov[0].iov_base;
5959 len = msg.msg_iov[0].iov_len;
5961 ret = libc_send(s, buf, len, flags);
5963 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5968 ssize_t send(int s, const void *buf, size_t len, int flags)
5970 return swrap_send(s, buf, len, flags);
5973 /****************************************************************************
5975 ***************************************************************************/
5977 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5979 struct swrap_address from_addr = {
5980 .sa_socklen = sizeof(struct sockaddr_un),
5982 struct swrap_address convert_addr = {
5983 .sa_socklen = sizeof(struct sockaddr_storage),
5985 struct socket_info *si;
5988 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5989 size_t msg_ctrllen_filled;
5990 size_t msg_ctrllen_left;
5996 si = find_socket_info(s);
5998 return libc_recvmsg(s, omsg, flags);
6001 tmp.iov_base = NULL;
6005 msg.msg_name = &from_addr.sa; /* optional address */
6006 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6007 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6008 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6009 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6010 msg_ctrllen_filled = 0;
6011 msg_ctrllen_left = omsg->msg_controllen;
6013 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6014 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6015 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6018 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6023 ret = libc_recvmsg(s, &msg, flags);
6025 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6026 msg_ctrllen_filled += msg.msg_controllen;
6027 msg_ctrllen_left -= msg.msg_controllen;
6029 if (omsg->msg_control != NULL) {
6032 p = omsg->msg_control;
6033 p += msg_ctrllen_filled;
6035 msg.msg_control = p;
6036 msg.msg_controllen = msg_ctrllen_left;
6038 msg.msg_control = NULL;
6039 msg.msg_controllen = 0;
6044 * We convert the unix address to a IP address so we need a buffer
6045 * which can store the address in case of SOCK_DGRAM, see below.
6047 msg.msg_name = &convert_addr.sa;
6048 msg.msg_namelen = convert_addr.sa_socklen;
6050 rc = swrap_recvmsg_after(s,
6054 from_addr.sa_socklen,
6060 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6061 if (omsg->msg_control != NULL) {
6062 /* msg.msg_controllen = space left */
6063 msg_ctrllen_left = msg.msg_controllen;
6064 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6067 /* Update the original message length */
6068 omsg->msg_controllen = msg_ctrllen_filled;
6069 omsg->msg_flags = msg.msg_flags;
6071 omsg->msg_iovlen = msg.msg_iovlen;
6078 * The msg_name field points to a caller-allocated buffer that is
6079 * used to return the source address if the socket is unconnected. The
6080 * caller should set msg_namelen to the size of this buffer before this
6081 * call; upon return from a successful call, msg_name will contain the
6082 * length of the returned address. If the application does not need
6083 * to know the source address, msg_name can be specified as NULL.
6085 if (si->type == SOCK_STREAM) {
6086 omsg->msg_namelen = 0;
6087 } else if (omsg->msg_name != NULL &&
6088 omsg->msg_namelen != 0 &&
6089 omsg->msg_namelen >= msg.msg_namelen) {
6090 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6091 omsg->msg_namelen = msg.msg_namelen;
6094 SWRAP_UNLOCK_SI(si);
6099 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6101 return swrap_recvmsg(sockfd, msg, flags);
6104 /****************************************************************************
6106 ***************************************************************************/
6108 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
6112 struct sockaddr_un un_addr;
6113 const struct sockaddr_un *to_un = NULL;
6114 const struct sockaddr *to = NULL;
6117 struct socket_info *si = find_socket_info(s);
6121 return libc_sendmsg(s, omsg, flags);
6124 ZERO_STRUCT(un_addr);
6126 tmp.iov_base = NULL;
6133 if (si->connected == 0) {
6134 msg.msg_name = omsg->msg_name; /* optional address */
6135 msg.msg_namelen = omsg->msg_namelen; /* size of address */
6137 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6138 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6140 SWRAP_UNLOCK_SI(si);
6142 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6143 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
6144 /* omsg is a const so use a local buffer for modifications */
6145 uint8_t cmbuf[omsg->msg_controllen];
6147 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
6149 msg.msg_control = cmbuf; /* ancillary data, see below */
6150 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6152 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6155 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
6163 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6170 char *swrap_dir = NULL;
6172 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6173 avail += msg.msg_iov[i].iov_len;
6179 /* we capture it as one single packet */
6180 buf = (uint8_t *)malloc(remain);
6185 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6186 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
6188 msg.msg_iov[i].iov_base,
6191 remain -= this_time;
6194 type = SOCKET_TYPE_CHAR_UDP;
6196 swrap_dir = socket_wrapper_dir();
6197 if (swrap_dir == NULL) {
6202 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6203 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
6204 if (stat(un_addr.sun_path, &st) != 0) continue;
6206 msg.msg_name = &un_addr; /* optional address */
6207 msg.msg_namelen = sizeof(un_addr); /* size of address */
6209 /* ignore the any errors in broadcast sends */
6210 libc_sendmsg(s, &msg, flags);
6213 SAFE_FREE(swrap_dir);
6217 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6220 SWRAP_UNLOCK_SI(si);
6225 ret = libc_sendmsg(s, &msg, flags);
6227 swrap_sendmsg_after(s, si, &msg, to, ret);
6232 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
6234 return swrap_sendmsg(s, omsg, flags);
6237 /****************************************************************************
6239 ***************************************************************************/
6241 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
6243 struct socket_info *si;
6246 struct swrap_address saddr = {
6247 .sa_socklen = sizeof(struct sockaddr_storage)
6252 si = find_socket_info(s);
6254 return libc_readv(s, vector, count);
6257 tmp.iov_base = NULL;
6261 msg.msg_name = &saddr.sa.s; /* optional address */
6262 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6263 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6264 msg.msg_iovlen = count; /* # elements in msg_iov */
6265 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6266 msg.msg_control = NULL; /* ancillary data, see below */
6267 msg.msg_controllen = 0; /* ancillary data buffer len */
6268 msg.msg_flags = 0; /* flags on received message */
6271 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6273 if (rc == -ENOTSOCK) {
6274 return libc_readv(s, vector, count);
6279 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
6281 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6289 ssize_t readv(int s, const struct iovec *vector, int count)
6291 return swrap_readv(s, vector, count);
6294 /****************************************************************************
6296 ***************************************************************************/
6298 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6302 struct sockaddr_un un_addr;
6305 struct socket_info *si = find_socket_info(s);
6308 return libc_writev(s, vector, count);
6311 tmp.iov_base = NULL;
6315 msg.msg_name = NULL; /* optional address */
6316 msg.msg_namelen = 0; /* size of address */
6317 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6318 msg.msg_iovlen = count; /* # elements in msg_iov */
6319 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6320 msg.msg_control = NULL; /* ancillary data, see below */
6321 msg.msg_controllen = 0; /* ancillary data buffer len */
6322 msg.msg_flags = 0; /* flags on received message */
6325 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6327 if (rc == -ENOTSOCK) {
6328 return libc_readv(s, vector, count);
6333 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6335 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6340 ssize_t writev(int s, const struct iovec *vector, int count)
6342 return swrap_writev(s, vector, count);
6345 /****************************
6347 ***************************/
6349 static int swrap_close(int fd)
6351 struct socket_info *si = NULL;
6355 swrap_mutex_lock(&socket_reset_mutex);
6357 si_index = find_socket_info_index(fd);
6358 if (si_index == -1) {
6359 swrap_mutex_unlock(&socket_reset_mutex);
6360 return libc_close(fd);
6363 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
6364 reset_socket_info_index(fd);
6366 si = swrap_get_socket_info(si_index);
6368 swrap_mutex_lock(&first_free_mutex);
6371 ret = libc_close(fd);
6373 swrap_dec_refcount(si);
6375 if (swrap_get_refcount(si) > 0) {
6376 /* there are still references left */
6380 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6381 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6384 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6385 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6386 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6389 if (si->un_addr.sun_path[0] != '\0') {
6390 unlink(si->un_addr.sun_path);
6393 swrap_set_next_free(si, first_free);
6394 first_free = si_index;
6397 SWRAP_UNLOCK_SI(si);
6398 swrap_mutex_unlock(&first_free_mutex);
6399 swrap_mutex_unlock(&socket_reset_mutex);
6406 return swrap_close(fd);
6409 /****************************
6411 ***************************/
6413 static int swrap_dup(int fd)
6415 struct socket_info *si;
6418 idx = find_socket_info_index(fd);
6420 return libc_dup(fd);
6423 si = swrap_get_socket_info(idx);
6425 dup_fd = libc_dup(fd);
6427 int saved_errno = errno;
6428 errno = saved_errno;
6434 swrap_inc_refcount(si);
6436 SWRAP_UNLOCK_SI(si);
6438 /* Make sure we don't have an entry for the fd */
6439 swrap_remove_stale(dup_fd);
6441 set_socket_info_index(dup_fd, idx);
6448 return swrap_dup(fd);
6451 /****************************
6453 ***************************/
6455 static int swrap_dup2(int fd, int newfd)
6457 struct socket_info *si;
6460 idx = find_socket_info_index(fd);
6462 return libc_dup2(fd, newfd);
6465 si = swrap_get_socket_info(idx);
6469 * According to the manpage:
6471 * "If oldfd is a valid file descriptor, and newfd has the same
6472 * value as oldfd, then dup2() does nothing, and returns newfd."
6477 if (find_socket_info(newfd)) {
6478 /* dup2() does an implicit close of newfd, which we
6479 * need to emulate */
6483 dup_fd = libc_dup2(fd, newfd);
6485 int saved_errno = errno;
6486 errno = saved_errno;
6492 swrap_inc_refcount(si);
6494 SWRAP_UNLOCK_SI(si);
6496 /* Make sure we don't have an entry for the fd */
6497 swrap_remove_stale(dup_fd);
6499 set_socket_info_index(dup_fd, idx);
6504 int dup2(int fd, int newfd)
6506 return swrap_dup2(fd, newfd);
6509 /****************************
6511 ***************************/
6513 static int swrap_vfcntl(int fd, int cmd, va_list va)
6515 struct socket_info *si;
6516 int rc, dup_fd, idx;
6518 idx = find_socket_info_index(fd);
6520 return libc_vfcntl(fd, cmd, va);
6523 si = swrap_get_socket_info(idx);
6527 dup_fd = libc_vfcntl(fd, cmd, va);
6529 int saved_errno = errno;
6530 errno = saved_errno;
6536 swrap_inc_refcount(si);
6538 SWRAP_UNLOCK_SI(si);
6540 /* Make sure we don't have an entry for the fd */
6541 swrap_remove_stale(dup_fd);
6543 set_socket_info_index(dup_fd, idx);
6548 rc = libc_vfcntl(fd, cmd, va);
6555 int fcntl(int fd, int cmd, ...)
6562 rc = swrap_vfcntl(fd, cmd, va);
6569 /****************************
6571 ***************************/
6574 static int swrap_eventfd(int count, int flags)
6578 fd = libc_eventfd(count, flags);
6580 swrap_remove_stale(fd);
6586 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6587 int eventfd(unsigned int count, int flags)
6589 int eventfd(int count, int flags)
6592 return swrap_eventfd(count, flags);
6597 int pledge(const char *promises, const char *paths[])
6599 (void)promises; /* unused */
6600 (void)paths; /* unused */
6604 #endif /* HAVE_PLEDGE */
6606 static void swrap_thread_prepare(void)
6609 * This function should only be called here!!
6611 * We bind all symobls to avoid deadlocks of the fork is
6612 * interrupted by a signal handler using a symbol of this
6615 swrap_bind_symbol_all();
6620 static void swrap_thread_parent(void)
6625 static void swrap_thread_child(void)
6630 /****************************
6632 ***************************/
6633 void swrap_constructor(void)
6638 * If we hold a lock and the application forks, then the child
6639 * is not able to unlock the mutex and we are in a deadlock.
6640 * This should prevent such deadlocks.
6642 pthread_atfork(&swrap_thread_prepare,
6643 &swrap_thread_parent,
6644 &swrap_thread_child);
6646 ret = socket_wrapper_init_mutex(&sockets_mutex);
6648 SWRAP_LOG(SWRAP_LOG_ERROR,
6649 "Failed to initialize pthread mutex");
6653 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6655 SWRAP_LOG(SWRAP_LOG_ERROR,
6656 "Failed to initialize pthread mutex");
6660 ret = socket_wrapper_init_mutex(&first_free_mutex);
6662 SWRAP_LOG(SWRAP_LOG_ERROR,
6663 "Failed to initialize pthread mutex");
6668 /****************************
6670 ***************************/
6673 * This function is called when the library is unloaded and makes sure that
6674 * sockets get closed and the unix file for the socket are unlinked.
6676 void swrap_destructor(void)
6680 if (socket_fds_idx != NULL) {
6681 for (i = 0; i < socket_fds_max; ++i) {
6682 if (socket_fds_idx[i] != -1) {
6686 SAFE_FREE(socket_fds_idx);
6691 if (swrap.libc.handle != NULL) {
6692 dlclose(swrap.libc.handle);
6694 if (swrap.libc.socket_handle) {
6695 dlclose(swrap.libc.socket_handle);
6699 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
6701 * On FreeBSD 12 (and maybe other platforms)
6702 * system libraries like libresolv prefix there
6703 * syscalls with '_' in order to always use
6704 * the symbols from libc.
6706 * In the interaction with resolv_wrapper,
6707 * we need to inject socket wrapper into libresolv,
6708 * which means we need to private all socket
6709 * related syscalls also with the '_' prefix.
6711 * This is tested in Samba's 'make test',
6712 * there we noticed that providing '_read'
6713 * and '_open' would cause errors, which
6714 * means we skip '_read', '_write' and
6715 * all non socket related calls without
6716 * further analyzing the problem.
6718 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
6719 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
6722 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
6724 SWRAP_SYMBOL_ALIAS(accept, _accept);
6725 SWRAP_SYMBOL_ALIAS(bind, _bind);
6726 SWRAP_SYMBOL_ALIAS(close, _close);
6727 SWRAP_SYMBOL_ALIAS(connect, _connect);
6728 SWRAP_SYMBOL_ALIAS(dup, _dup);
6729 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
6730 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
6731 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
6732 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
6733 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
6734 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
6735 SWRAP_SYMBOL_ALIAS(listen, _listen);
6736 SWRAP_SYMBOL_ALIAS(readv, _readv);
6737 SWRAP_SYMBOL_ALIAS(recv, _recv);
6738 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
6739 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
6740 SWRAP_SYMBOL_ALIAS(send, _send);
6741 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
6742 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
6743 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
6744 SWRAP_SYMBOL_ALIAS(socket, _socket);
6745 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
6746 SWRAP_SYMBOL_ALIAS(writev, _writev);
6748 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */