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 \
183 swrap_mutex_lock(&libc_symbol_binding_mutex); \
185 # define SWRAP_UNLOCK_ALL \
186 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
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 to synchronize access to global libc.symbols */
313 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
315 /* Mutex for syncronizing port selection during swrap_auto_bind() */
316 static pthread_mutex_t autobind_start_mutex;
318 /* Mutex to guard the initialization of array of socket_info structures */
319 static pthread_mutex_t sockets_mutex;
321 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
322 static pthread_mutex_t socket_reset_mutex;
324 /* Mutex to synchronize access to first free index in socket_info array */
325 static pthread_mutex_t first_free_mutex;
327 /* Mutex to synchronize access to packet capture dump file */
328 static pthread_mutex_t pcap_dump_mutex;
330 /* Mutex for synchronizing mtu value fetch*/
331 static pthread_mutex_t mtu_update_mutex;
333 /* Function prototypes */
335 bool socket_wrapper_enabled(void);
337 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
338 /* xlC and other oldschool compilers support (only) this */
339 #pragma init (swrap_constructor)
341 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
342 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
343 #pragma fini (swrap_destructor)
345 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
347 #ifndef HAVE_GETPROGNAME
348 static const char *getprogname(void)
350 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
351 return program_invocation_short_name;
352 #elif defined(HAVE_GETEXECNAME)
353 return getexecname();
356 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
358 #endif /* HAVE_GETPROGNAME */
360 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
361 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
363 static void swrap_log(enum swrap_dbglvl_e dbglvl,
365 const char *format, ...)
370 unsigned int lvl = 0;
371 const char *prefix = "SWRAP";
372 const char *progname = getprogname();
374 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
383 va_start(va, format);
384 vsnprintf(buffer, sizeof(buffer), format, va);
388 case SWRAP_LOG_ERROR:
389 prefix = "SWRAP_ERROR";
392 prefix = "SWRAP_WARN";
394 case SWRAP_LOG_DEBUG:
395 prefix = "SWRAP_DEBUG";
397 case SWRAP_LOG_TRACE:
398 prefix = "SWRAP_TRACE";
402 if (progname == NULL) {
403 progname = "<unknown>";
407 "%s[%s (%u)] - %s: %s\n",
410 (unsigned int)getpid(),
415 /*********************************************************
416 * SWRAP LOADING LIBC FUNCTIONS
417 *********************************************************/
422 typedef int (*__libc_accept4)(int sockfd,
423 struct sockaddr *addr,
427 typedef int (*__libc_accept)(int sockfd,
428 struct sockaddr *addr,
431 typedef int (*__libc_bind)(int sockfd,
432 const struct sockaddr *addr,
434 typedef int (*__libc_close)(int fd);
435 typedef int (*__libc_connect)(int sockfd,
436 const struct sockaddr *addr,
438 typedef int (*__libc_dup)(int fd);
439 typedef int (*__libc_dup2)(int oldfd, int newfd);
440 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
441 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
443 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
446 typedef int (*__libc_eventfd)(int count, int flags);
448 typedef int (*__libc_getpeername)(int sockfd,
449 struct sockaddr *addr,
451 typedef int (*__libc_getsockname)(int sockfd,
452 struct sockaddr *addr,
454 typedef int (*__libc_getsockopt)(int sockfd,
459 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
460 typedef int (*__libc_listen)(int sockfd, int backlog);
461 typedef int (*__libc_open)(const char *pathname, int flags, ...);
463 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
464 #endif /* HAVE_OPEN64 */
465 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
466 typedef int (*__libc_pipe)(int pipefd[2]);
467 typedef int (*__libc_read)(int fd, void *buf, size_t count);
468 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
469 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
470 typedef int (*__libc_recvfrom)(int sockfd,
474 struct sockaddr *src_addr,
476 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
477 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
478 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
479 typedef int (*__libc_sendto)(int sockfd,
483 const struct sockaddr *dst_addr,
485 typedef int (*__libc_setsockopt)(int sockfd,
491 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
493 typedef int (*__libc_socket)(int domain, int type, int protocol);
494 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
495 #ifdef HAVE_TIMERFD_CREATE
496 typedef int (*__libc_timerfd_create)(int clockid, int flags);
498 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
499 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
501 #define SWRAP_SYMBOL_ENTRY(i) \
507 struct swrap_libc_symbols {
509 SWRAP_SYMBOL_ENTRY(accept4);
511 SWRAP_SYMBOL_ENTRY(accept);
513 SWRAP_SYMBOL_ENTRY(bind);
514 SWRAP_SYMBOL_ENTRY(close);
515 SWRAP_SYMBOL_ENTRY(connect);
516 SWRAP_SYMBOL_ENTRY(dup);
517 SWRAP_SYMBOL_ENTRY(dup2);
518 SWRAP_SYMBOL_ENTRY(fcntl);
519 SWRAP_SYMBOL_ENTRY(fopen);
521 SWRAP_SYMBOL_ENTRY(fopen64);
524 SWRAP_SYMBOL_ENTRY(eventfd);
526 SWRAP_SYMBOL_ENTRY(getpeername);
527 SWRAP_SYMBOL_ENTRY(getsockname);
528 SWRAP_SYMBOL_ENTRY(getsockopt);
529 SWRAP_SYMBOL_ENTRY(ioctl);
530 SWRAP_SYMBOL_ENTRY(listen);
531 SWRAP_SYMBOL_ENTRY(open);
533 SWRAP_SYMBOL_ENTRY(open64);
535 SWRAP_SYMBOL_ENTRY(openat);
536 SWRAP_SYMBOL_ENTRY(pipe);
537 SWRAP_SYMBOL_ENTRY(read);
538 SWRAP_SYMBOL_ENTRY(readv);
539 SWRAP_SYMBOL_ENTRY(recv);
540 SWRAP_SYMBOL_ENTRY(recvfrom);
541 SWRAP_SYMBOL_ENTRY(recvmsg);
542 SWRAP_SYMBOL_ENTRY(send);
543 SWRAP_SYMBOL_ENTRY(sendmsg);
544 SWRAP_SYMBOL_ENTRY(sendto);
545 SWRAP_SYMBOL_ENTRY(setsockopt);
547 SWRAP_SYMBOL_ENTRY(signalfd);
549 SWRAP_SYMBOL_ENTRY(socket);
550 SWRAP_SYMBOL_ENTRY(socketpair);
551 #ifdef HAVE_TIMERFD_CREATE
552 SWRAP_SYMBOL_ENTRY(timerfd_create);
554 SWRAP_SYMBOL_ENTRY(write);
555 SWRAP_SYMBOL_ENTRY(writev);
562 struct swrap_libc_symbols symbols;
566 static struct swrap swrap;
569 static char *socket_wrapper_dir(void);
571 #define LIBC_NAME "libc.so"
578 static const char *swrap_str_lib(enum swrap_lib lib)
583 case SWRAP_LIBSOCKET:
587 /* Compiler would warn us about unhandled enum value if we get here */
591 static void *swrap_load_lib_handle(enum swrap_lib lib)
593 int flags = RTLD_LAZY;
598 const char *env_preload = getenv("LD_PRELOAD");
599 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
600 bool enable_deepbind = true;
602 /* Don't do a deepbind if we run with libasan */
603 if (env_preload != NULL && strlen(env_preload) < 1024) {
604 const char *p = strstr(env_preload, "libasan.so");
606 enable_deepbind = false;
610 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
611 enable_deepbind = false;
614 if (enable_deepbind) {
615 flags |= RTLD_DEEPBIND;
620 case SWRAP_LIBSOCKET:
621 #ifdef HAVE_LIBSOCKET
622 handle = swrap.libc.socket_handle;
623 if (handle == NULL) {
624 for (i = 10; i >= 0; i--) {
625 char soname[256] = {0};
627 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
628 handle = dlopen(soname, flags);
629 if (handle != NULL) {
634 swrap.libc.socket_handle = handle;
639 handle = swrap.libc.handle;
641 if (handle == NULL) {
642 handle = dlopen(LIBC_SO, flags);
644 swrap.libc.handle = handle;
647 if (handle == NULL) {
648 for (i = 10; i >= 0; i--) {
649 char soname[256] = {0};
651 snprintf(soname, sizeof(soname), "libc.so.%d", i);
652 handle = dlopen(soname, flags);
653 if (handle != NULL) {
658 swrap.libc.handle = handle;
663 if (handle == NULL) {
665 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
667 SWRAP_LOG(SWRAP_LOG_ERROR,
668 "Failed to dlopen library: %s",
677 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
682 handle = swrap_load_lib_handle(lib);
684 func = dlsym(handle, fn_name);
686 SWRAP_LOG(SWRAP_LOG_ERROR,
687 "Failed to find %s: %s",
693 SWRAP_LOG(SWRAP_LOG_TRACE,
701 static void swrap_mutex_lock(pthread_mutex_t *mutex)
705 ret = pthread_mutex_lock(mutex);
707 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
712 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
716 ret = pthread_mutex_unlock(mutex);
718 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
724 * These macros have a thread race condition on purpose!
726 * This is an optimization to avoid locking each time we check if the symbol is
729 #define _swrap_bind_symbol_generic(lib, sym_name) \
730 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
731 swrap_mutex_lock(&libc_symbol_binding_mutex); \
732 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
733 swrap.libc.symbols._libc_##sym_name.obj = \
734 _swrap_bind_symbol(lib, #sym_name); \
736 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
739 #define swrap_bind_symbol_libc(sym_name) \
740 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
742 #define swrap_bind_symbol_libsocket(sym_name) \
743 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
745 /****************************************************************************
747 ****************************************************************************
749 * Functions especially from libc need to be loaded individually, you can't
750 * load all at once or gdb will segfault at startup. The same applies to
751 * valgrind and has probably something todo with with the linker. So we need
752 * load each function at the point it is called the first time.
754 ****************************************************************************/
757 static int libc_accept4(int sockfd,
758 struct sockaddr *addr,
762 swrap_bind_symbol_libsocket(accept4);
764 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
767 #else /* HAVE_ACCEPT4 */
769 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
771 swrap_bind_symbol_libsocket(accept);
773 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
775 #endif /* HAVE_ACCEPT4 */
777 static int libc_bind(int sockfd,
778 const struct sockaddr *addr,
781 swrap_bind_symbol_libsocket(bind);
783 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
786 static int libc_close(int fd)
788 swrap_bind_symbol_libc(close);
790 return swrap.libc.symbols._libc_close.f(fd);
793 static int libc_connect(int sockfd,
794 const struct sockaddr *addr,
797 swrap_bind_symbol_libsocket(connect);
799 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
802 static int libc_dup(int fd)
804 swrap_bind_symbol_libc(dup);
806 return swrap.libc.symbols._libc_dup.f(fd);
809 static int libc_dup2(int oldfd, int newfd)
811 swrap_bind_symbol_libc(dup2);
813 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
817 static int libc_eventfd(int count, int flags)
819 swrap_bind_symbol_libc(eventfd);
821 return swrap.libc.symbols._libc_eventfd.f(count, flags);
825 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
826 static int libc_vfcntl(int fd, int cmd, va_list ap)
831 swrap_bind_symbol_libc(fcntl);
833 arg = va_arg(ap, void *);
835 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
840 static int libc_getpeername(int sockfd,
841 struct sockaddr *addr,
844 swrap_bind_symbol_libsocket(getpeername);
846 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
849 static int libc_getsockname(int sockfd,
850 struct sockaddr *addr,
853 swrap_bind_symbol_libsocket(getsockname);
855 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
858 static int libc_getsockopt(int sockfd,
864 swrap_bind_symbol_libsocket(getsockopt);
866 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
873 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
874 static int libc_vioctl(int d, unsigned long int request, va_list ap)
879 swrap_bind_symbol_libc(ioctl);
881 arg = va_arg(ap, void *);
883 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
888 static int libc_listen(int sockfd, int backlog)
890 swrap_bind_symbol_libsocket(listen);
892 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
895 static FILE *libc_fopen(const char *name, const char *mode)
897 swrap_bind_symbol_libc(fopen);
899 return swrap.libc.symbols._libc_fopen.f(name, mode);
903 static FILE *libc_fopen64(const char *name, const char *mode)
905 swrap_bind_symbol_libc(fopen64);
907 return swrap.libc.symbols._libc_fopen64.f(name, mode);
909 #endif /* HAVE_FOPEN64 */
911 static int libc_vopen(const char *pathname, int flags, va_list ap)
916 swrap_bind_symbol_libc(open);
918 if (flags & O_CREAT) {
919 mode = va_arg(ap, int);
921 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
926 static int libc_open(const char *pathname, int flags, ...)
932 fd = libc_vopen(pathname, flags, ap);
939 static int libc_vopen64(const char *pathname, int flags, va_list ap)
944 swrap_bind_symbol_libc(open64);
946 if (flags & O_CREAT) {
947 mode = va_arg(ap, int);
949 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
953 #endif /* HAVE_OPEN64 */
955 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
960 swrap_bind_symbol_libc(openat);
962 if (flags & O_CREAT) {
963 mode = va_arg(ap, int);
965 fd = swrap.libc.symbols._libc_openat.f(dirfd,
974 static int libc_openat(int dirfd, const char *path, int flags, ...)
980 fd = libc_vopenat(dirfd, path, flags, ap);
987 static int libc_pipe(int pipefd[2])
989 swrap_bind_symbol_libsocket(pipe);
991 return swrap.libc.symbols._libc_pipe.f(pipefd);
994 static int libc_read(int fd, void *buf, size_t count)
996 swrap_bind_symbol_libc(read);
998 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1001 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1003 swrap_bind_symbol_libsocket(readv);
1005 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1008 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1010 swrap_bind_symbol_libsocket(recv);
1012 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1015 static int libc_recvfrom(int sockfd,
1019 struct sockaddr *src_addr,
1022 swrap_bind_symbol_libsocket(recvfrom);
1024 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1032 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1034 swrap_bind_symbol_libsocket(recvmsg);
1036 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1039 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1041 swrap_bind_symbol_libsocket(send);
1043 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1046 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1048 swrap_bind_symbol_libsocket(sendmsg);
1050 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1053 static int libc_sendto(int sockfd,
1057 const struct sockaddr *dst_addr,
1060 swrap_bind_symbol_libsocket(sendto);
1062 return swrap.libc.symbols._libc_sendto.f(sockfd,
1070 static int libc_setsockopt(int sockfd,
1076 swrap_bind_symbol_libsocket(setsockopt);
1078 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1085 #ifdef HAVE_SIGNALFD
1086 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1088 swrap_bind_symbol_libsocket(signalfd);
1090 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1094 static int libc_socket(int domain, int type, int protocol)
1096 swrap_bind_symbol_libsocket(socket);
1098 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1101 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1103 swrap_bind_symbol_libsocket(socketpair);
1105 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1108 #ifdef HAVE_TIMERFD_CREATE
1109 static int libc_timerfd_create(int clockid, int flags)
1111 swrap_bind_symbol_libc(timerfd_create);
1113 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1117 static ssize_t libc_write(int fd, const void *buf, size_t count)
1119 swrap_bind_symbol_libc(write);
1121 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1124 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1126 swrap_bind_symbol_libsocket(writev);
1128 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1131 /* DO NOT call this function during library initialization! */
1132 static void swrap_bind_symbol_all(void)
1135 swrap_bind_symbol_libsocket(accept4);
1137 swrap_bind_symbol_libsocket(accept);
1139 swrap_bind_symbol_libsocket(bind);
1140 swrap_bind_symbol_libc(close);
1141 swrap_bind_symbol_libsocket(connect);
1142 swrap_bind_symbol_libc(dup);
1143 swrap_bind_symbol_libc(dup2);
1144 swrap_bind_symbol_libc(fcntl);
1145 swrap_bind_symbol_libc(fopen);
1147 swrap_bind_symbol_libc(fopen64);
1150 swrap_bind_symbol_libc(eventfd);
1152 swrap_bind_symbol_libsocket(getpeername);
1153 swrap_bind_symbol_libsocket(getsockname);
1154 swrap_bind_symbol_libsocket(getsockopt);
1155 swrap_bind_symbol_libc(ioctl);
1156 swrap_bind_symbol_libsocket(listen);
1157 swrap_bind_symbol_libc(open);
1159 swrap_bind_symbol_libc(open64);
1161 swrap_bind_symbol_libc(openat);
1162 swrap_bind_symbol_libsocket(pipe);
1163 swrap_bind_symbol_libc(read);
1164 swrap_bind_symbol_libsocket(readv);
1165 swrap_bind_symbol_libsocket(recv);
1166 swrap_bind_symbol_libsocket(recvfrom);
1167 swrap_bind_symbol_libsocket(recvmsg);
1168 swrap_bind_symbol_libsocket(send);
1169 swrap_bind_symbol_libsocket(sendmsg);
1170 swrap_bind_symbol_libsocket(sendto);
1171 swrap_bind_symbol_libsocket(setsockopt);
1172 #ifdef HAVE_SIGNALFD
1173 swrap_bind_symbol_libsocket(signalfd);
1175 swrap_bind_symbol_libsocket(socket);
1176 swrap_bind_symbol_libsocket(socketpair);
1177 #ifdef HAVE_TIMERFD_CREATE
1178 swrap_bind_symbol_libc(timerfd_create);
1180 swrap_bind_symbol_libc(write);
1181 swrap_bind_symbol_libsocket(writev);
1184 /*********************************************************
1185 * SWRAP HELPER FUNCTIONS
1186 *********************************************************/
1189 * We return 127.0.0.0 (default) or 10.53.57.0.
1191 * This can be controlled by:
1192 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1194 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1196 static in_addr_t swrap_ipv4_net(void)
1198 static int initialized;
1199 static in_addr_t hv;
1200 const char *net_str = NULL;
1209 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1210 if (net_str == NULL) {
1211 net_str = "127.0.0.0";
1214 ret = inet_pton(AF_INET, net_str, &nv);
1216 SWRAP_LOG(SWRAP_LOG_ERROR,
1217 "INVALID IPv4 Network [%s]",
1222 hv = ntohl(nv.s_addr);
1232 SWRAP_LOG(SWRAP_LOG_ERROR,
1233 "INVALID IPv4 Network [%s][0x%x] should be "
1234 "127.0.0.0 or 10.53.57.0",
1235 net_str, (unsigned)hv);
1243 * This returns 127.255.255.255 or 10.255.255.255
1245 static in_addr_t swrap_ipv4_bcast(void)
1249 hv = swrap_ipv4_net();
1250 hv |= IN_CLASSA_HOST;
1256 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1258 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1262 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1263 SWRAP_LOG(SWRAP_LOG_ERROR,
1264 "swrap_ipv4_iface(%u) invalid!",
1270 hv = swrap_ipv4_net();
1280 static const struct in6_addr *swrap_ipv6(void)
1282 static struct in6_addr v;
1283 static int initialized;
1291 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1300 static void set_port(int family, int prt, struct swrap_address *addr)
1304 addr->sa.in.sin_port = htons(prt);
1308 addr->sa.in6.sin6_port = htons(prt);
1314 static size_t socket_length(int family)
1318 return sizeof(struct sockaddr_in);
1321 return sizeof(struct sockaddr_in6);
1327 static struct socket_info *swrap_get_socket_info(int si_index)
1329 return (struct socket_info *)(&(sockets[si_index].info));
1332 static int swrap_get_refcount(struct socket_info *si)
1334 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1335 return sic->meta.refcount;
1338 static void swrap_inc_refcount(struct socket_info *si)
1340 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1342 sic->meta.refcount += 1;
1345 static void swrap_dec_refcount(struct socket_info *si)
1347 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1349 sic->meta.refcount -= 1;
1352 static int swrap_get_next_free(struct socket_info *si)
1354 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1356 return sic->meta.next_free;
1359 static void swrap_set_next_free(struct socket_info *si, int next_free)
1361 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1363 sic->meta.next_free = next_free;
1366 static int swrap_un_path(struct sockaddr_un *un,
1367 const char *swrap_dir,
1374 ret = snprintf(un->sun_path,
1375 sizeof(un->sun_path),
1381 if ((size_t)ret >= sizeof(un->sun_path)) {
1382 return ENAMETOOLONG;
1388 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1389 const char *swrap_dir)
1393 ret = snprintf(un->sun_path,
1394 sizeof(un->sun_path),
1398 if ((size_t)ret >= sizeof(un->sun_path)) {
1399 return ENAMETOOLONG;
1405 static bool swrap_dir_usable(const char *swrap_dir)
1407 struct sockaddr_un un;
1410 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1415 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1423 static char *socket_wrapper_dir(void)
1425 char *swrap_dir = NULL;
1426 char *s = getenv("SOCKET_WRAPPER_DIR");
1431 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1435 swrap_dir = realpath(s, NULL);
1436 if (swrap_dir == NULL) {
1437 SWRAP_LOG(SWRAP_LOG_ERROR,
1438 "Unable to resolve socket_wrapper dir path: %s",
1443 ok = swrap_dir_usable(swrap_dir);
1450 ok = swrap_dir_usable(s);
1452 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1456 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1458 SWRAP_LOG(SWRAP_LOG_ERROR,
1459 "realpath(SOCKET_WRAPPER_DIR) too long and "
1460 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1465 swrap_dir = strdup(s);
1466 if (swrap_dir == NULL) {
1467 SWRAP_LOG(SWRAP_LOG_ERROR,
1468 "Unable to duplicate socket_wrapper dir path");
1472 SWRAP_LOG(SWRAP_LOG_WARN,
1473 "realpath(SOCKET_WRAPPER_DIR) too long, "
1474 "using original SOCKET_WRAPPER_DIR\n");
1477 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1481 static unsigned int socket_wrapper_mtu(void)
1483 static unsigned int max_mtu = 0;
1488 swrap_mutex_lock(&mtu_update_mutex);
1494 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1496 s = getenv("SOCKET_WRAPPER_MTU");
1501 tmp = strtol(s, &endp, 10);
1506 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1512 swrap_mutex_unlock(&mtu_update_mutex);
1516 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1518 pthread_mutexattr_t ma;
1521 ret = pthread_mutexattr_init(&ma);
1526 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1531 ret = pthread_mutex_init(m, &ma);
1534 pthread_mutexattr_destroy(&ma);
1539 static size_t socket_wrapper_max_sockets(void)
1545 if (socket_info_max != 0) {
1546 return socket_info_max;
1549 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1551 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1552 if (s == NULL || s[0] == '\0') {
1556 tmp = strtoul(s, &endp, 10);
1561 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1562 SWRAP_LOG(SWRAP_LOG_ERROR,
1563 "Invalid number of sockets specified, "
1564 "using default (%zu)",
1568 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1569 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1570 SWRAP_LOG(SWRAP_LOG_ERROR,
1571 "Invalid number of sockets specified, "
1572 "using maximum (%zu).",
1576 socket_info_max = tmp;
1579 return socket_info_max;
1582 static void socket_wrapper_init_fds_idx(void)
1587 if (socket_fds_idx != NULL) {
1591 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1593 SWRAP_LOG(SWRAP_LOG_ERROR,
1594 "Failed to allocate socket fds index array: %s",
1599 for (i = 0; i < socket_fds_max; i++) {
1603 socket_fds_idx = tmp;
1606 static void socket_wrapper_init_sockets(void)
1612 swrap_mutex_lock(&sockets_mutex);
1614 if (sockets != NULL) {
1615 swrap_mutex_unlock(&sockets_mutex);
1620 * Intialize the static cache early before
1621 * any thread is able to start.
1623 (void)swrap_ipv4_net();
1625 socket_wrapper_init_fds_idx();
1627 /* Needs to be called inside the sockets_mutex lock here. */
1628 max_sockets = socket_wrapper_max_sockets();
1630 sockets = (struct socket_info_container *)calloc(max_sockets,
1631 sizeof(struct socket_info_container));
1633 if (sockets == NULL) {
1634 SWRAP_LOG(SWRAP_LOG_ERROR,
1635 "Failed to allocate sockets array: %s",
1637 swrap_mutex_unlock(&sockets_mutex);
1641 swrap_mutex_lock(&first_free_mutex);
1645 for (i = 0; i < max_sockets; i++) {
1646 swrap_set_next_free(&sockets[i].info, i+1);
1647 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1649 SWRAP_LOG(SWRAP_LOG_ERROR,
1650 "Failed to initialize pthread mutex");
1655 /* mark the end of the free list */
1656 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1658 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1660 SWRAP_LOG(SWRAP_LOG_ERROR,
1661 "Failed to initialize pthread mutex");
1665 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1667 SWRAP_LOG(SWRAP_LOG_ERROR,
1668 "Failed to initialize pthread mutex");
1672 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1674 SWRAP_LOG(SWRAP_LOG_ERROR,
1675 "Failed to initialize pthread mutex");
1680 swrap_mutex_unlock(&first_free_mutex);
1681 swrap_mutex_unlock(&sockets_mutex);
1687 bool socket_wrapper_enabled(void)
1689 char *s = socket_wrapper_dir();
1697 socket_wrapper_init_sockets();
1702 static unsigned int socket_wrapper_default_iface(void)
1704 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1707 if (sscanf(s, "%u", &iface) == 1) {
1708 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1714 return 1;/* 127.0.0.1 */
1717 static void set_socket_info_index(int fd, int idx)
1719 SWRAP_LOG(SWRAP_LOG_TRACE,
1722 socket_fds_idx[fd] = idx;
1723 /* This builtin issues a full memory barrier. */
1724 __sync_synchronize();
1727 static void reset_socket_info_index(int fd)
1729 SWRAP_LOG(SWRAP_LOG_TRACE,
1732 set_socket_info_index(fd, -1);
1735 static int find_socket_info_index(int fd)
1741 if (socket_fds_idx == NULL) {
1745 if ((size_t)fd >= socket_fds_max) {
1747 * Do not add a log here as some applications do stupid things
1750 * for (fd = 0; fd <= getdtablesize(); fd++) {
1754 * This would produce millions of lines of debug messages.
1757 SWRAP_LOG(SWRAP_LOG_ERROR,
1758 "Looking for a socket info for the fd %d is over the "
1759 "max socket index limit of %zu.",
1766 /* This builtin issues a full memory barrier. */
1767 __sync_synchronize();
1768 return socket_fds_idx[fd];
1771 static int swrap_add_socket_info(struct socket_info *si_input)
1773 struct socket_info *si = NULL;
1776 if (si_input == NULL) {
1781 swrap_mutex_lock(&first_free_mutex);
1782 if (first_free == -1) {
1787 si_index = first_free;
1788 si = swrap_get_socket_info(si_index);
1792 first_free = swrap_get_next_free(si);
1794 swrap_inc_refcount(si);
1796 SWRAP_UNLOCK_SI(si);
1799 swrap_mutex_unlock(&first_free_mutex);
1804 static int swrap_create_socket(struct socket_info *si, int fd)
1808 if ((size_t)fd >= socket_fds_max) {
1809 SWRAP_LOG(SWRAP_LOG_ERROR,
1810 "The max socket index limit of %zu has been reached, "
1817 idx = swrap_add_socket_info(si);
1822 set_socket_info_index(fd, idx);
1827 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1834 p = strrchr(un->sun_path, '/');
1835 if (p) p++; else p = un->sun_path;
1837 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1842 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1845 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1856 case SOCKET_TYPE_CHAR_TCP:
1857 case SOCKET_TYPE_CHAR_UDP: {
1858 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1860 if ((*len) < sizeof(*in2)) {
1865 memset(in2, 0, sizeof(*in2));
1866 in2->sin_family = AF_INET;
1867 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1868 in2->sin_port = htons(prt);
1870 *len = sizeof(*in2);
1874 case SOCKET_TYPE_CHAR_TCP_V6:
1875 case SOCKET_TYPE_CHAR_UDP_V6: {
1876 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1878 if ((*len) < sizeof(*in2)) {
1883 memset(in2, 0, sizeof(*in2));
1884 in2->sin6_family = AF_INET6;
1885 in2->sin6_addr = *swrap_ipv6();
1886 in2->sin6_addr.s6_addr[15] = iface;
1887 in2->sin6_port = htons(prt);
1889 *len = sizeof(*in2);
1901 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1908 char *swrap_dir = NULL;
1910 if (bcast) *bcast = 0;
1912 switch (inaddr->sa_family) {
1914 const struct sockaddr_in *in =
1915 (const struct sockaddr_in *)(const void *)inaddr;
1916 unsigned int addr = ntohl(in->sin_addr.s_addr);
1920 const unsigned int sw_net_addr = swrap_ipv4_net();
1921 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1925 u_type = SOCKET_TYPE_CHAR_TCP;
1928 u_type = SOCKET_TYPE_CHAR_UDP;
1929 a_type = SOCKET_TYPE_CHAR_UDP;
1930 b_type = SOCKET_TYPE_CHAR_UDP;
1933 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1934 errno = ESOCKTNOSUPPORT;
1938 prt = ntohs(in->sin_port);
1939 if (a_type && addr == 0xFFFFFFFF) {
1940 /* 255.255.255.255 only udp */
1943 iface = socket_wrapper_default_iface();
1944 } else if (b_type && addr == sw_bcast_addr) {
1953 iface = socket_wrapper_default_iface();
1954 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
1955 /* 127.0.0.X or 10.53.57.X */
1958 iface = (addr & 0x000000FF);
1960 errno = ENETUNREACH;
1963 if (bcast) *bcast = is_bcast;
1968 const struct sockaddr_in6 *in =
1969 (const struct sockaddr_in6 *)(const void *)inaddr;
1970 struct in6_addr cmp1, cmp2;
1974 type = SOCKET_TYPE_CHAR_TCP_V6;
1977 type = SOCKET_TYPE_CHAR_UDP_V6;
1980 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1981 errno = ESOCKTNOSUPPORT;
1985 /* XXX no multicast/broadcast */
1987 prt = ntohs(in->sin6_port);
1989 cmp1 = *swrap_ipv6();
1990 cmp2 = in->sin6_addr;
1991 cmp2.s6_addr[15] = 0;
1992 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1993 iface = in->sin6_addr.s6_addr[15];
1995 errno = ENETUNREACH;
2003 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2004 errno = ENETUNREACH;
2009 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2014 swrap_dir = socket_wrapper_dir();
2015 if (swrap_dir == NULL) {
2021 swrap_un_path_EINVAL(un, swrap_dir);
2022 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2023 SAFE_FREE(swrap_dir);
2024 /* the caller need to do more processing */
2028 swrap_un_path(un, swrap_dir, type, iface, prt);
2029 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2031 SAFE_FREE(swrap_dir);
2036 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2044 char *swrap_dir = NULL;
2046 if (bcast) *bcast = 0;
2048 switch (si->family) {
2050 const struct sockaddr_in *in =
2051 (const struct sockaddr_in *)(const void *)inaddr;
2052 unsigned int addr = ntohl(in->sin_addr.s_addr);
2057 const unsigned int sw_net_addr = swrap_ipv4_net();
2058 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2060 prt = ntohs(in->sin_port);
2064 u_type = SOCKET_TYPE_CHAR_TCP;
2065 d_type = SOCKET_TYPE_CHAR_TCP;
2068 u_type = SOCKET_TYPE_CHAR_UDP;
2069 d_type = SOCKET_TYPE_CHAR_UDP;
2070 a_type = SOCKET_TYPE_CHAR_UDP;
2071 b_type = SOCKET_TYPE_CHAR_UDP;
2074 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2075 errno = ESOCKTNOSUPPORT;
2083 iface = socket_wrapper_default_iface();
2084 } else if (a_type && addr == 0xFFFFFFFF) {
2085 /* 255.255.255.255 only udp */
2088 iface = socket_wrapper_default_iface();
2089 } else if (b_type && addr == sw_bcast_addr) {
2090 /* 127.255.255.255 only udp */
2093 iface = socket_wrapper_default_iface();
2094 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2098 iface = (addr & 0x000000FF);
2100 errno = EADDRNOTAVAIL;
2104 /* Store the bind address for connect() */
2105 if (si->bindname.sa_socklen == 0) {
2106 struct sockaddr_in bind_in;
2107 socklen_t blen = sizeof(struct sockaddr_in);
2109 ZERO_STRUCT(bind_in);
2110 bind_in.sin_family = in->sin_family;
2111 bind_in.sin_port = in->sin_port;
2112 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2113 si->bindname.sa_socklen = blen;
2114 memcpy(&si->bindname.sa.in, &bind_in, blen);
2121 const struct sockaddr_in6 *in =
2122 (const struct sockaddr_in6 *)(const void *)inaddr;
2123 struct in6_addr cmp1, cmp2;
2127 type = SOCKET_TYPE_CHAR_TCP_V6;
2130 type = SOCKET_TYPE_CHAR_UDP_V6;
2133 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2134 errno = ESOCKTNOSUPPORT;
2138 /* XXX no multicast/broadcast */
2140 prt = ntohs(in->sin6_port);
2142 cmp1 = *swrap_ipv6();
2143 cmp2 = in->sin6_addr;
2144 cmp2.s6_addr[15] = 0;
2145 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2146 iface = socket_wrapper_default_iface();
2147 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2148 iface = in->sin6_addr.s6_addr[15];
2150 errno = EADDRNOTAVAIL;
2154 /* Store the bind address for connect() */
2155 if (si->bindname.sa_socklen == 0) {
2156 struct sockaddr_in6 bind_in;
2157 socklen_t blen = sizeof(struct sockaddr_in6);
2159 ZERO_STRUCT(bind_in);
2160 bind_in.sin6_family = in->sin6_family;
2161 bind_in.sin6_port = in->sin6_port;
2163 bind_in.sin6_addr = *swrap_ipv6();
2164 bind_in.sin6_addr.s6_addr[15] = iface;
2166 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2167 si->bindname.sa_socklen = blen;
2174 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2175 errno = EADDRNOTAVAIL;
2180 if (bcast) *bcast = is_bcast;
2182 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2187 swrap_dir = socket_wrapper_dir();
2188 if (swrap_dir == NULL) {
2194 /* handle auto-allocation of ephemeral ports */
2195 for (prt = 5001; prt < 10000; prt++) {
2196 swrap_un_path(un, swrap_dir, type, iface, prt);
2197 if (stat(un->sun_path, &st) == 0) continue;
2199 set_port(si->family, prt, &si->myname);
2200 set_port(si->family, prt, &si->bindname);
2207 SAFE_FREE(swrap_dir);
2212 swrap_un_path(un, swrap_dir, type, iface, prt);
2213 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2215 SAFE_FREE(swrap_dir);
2220 static struct socket_info *find_socket_info(int fd)
2222 int idx = find_socket_info_index(fd);
2228 return swrap_get_socket_info(idx);
2232 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2234 struct socket_info_fd *f;
2235 const struct socket_info *last_s = NULL;
2237 /* first catch invalid input */
2238 switch (sa->sa_family) {
2240 if (len < sizeof(struct sockaddr_in)) {
2246 if (len < sizeof(struct sockaddr_in6)) {
2256 for (f = socket_fds; f; f = f->next) {
2257 struct socket_info *s = swrap_get_socket_info(f->si_index);
2264 if (s->myname == NULL) {
2267 if (s->myname->sa_family != sa->sa_family) {
2270 switch (s->myname->sa_family) {
2272 struct sockaddr_in *sin1, *sin2;
2274 sin1 = (struct sockaddr_in *)s->myname;
2275 sin2 = (struct sockaddr_in *)sa;
2277 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2280 if (sin1->sin_port != sin2->sin_port) {
2283 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2293 struct sockaddr_in6 *sin1, *sin2;
2295 sin1 = (struct sockaddr_in6 *)s->myname;
2296 sin2 = (struct sockaddr_in6 *)sa;
2298 if (sin1->sin6_port != sin2->sin6_port) {
2301 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2323 static void swrap_remove_stale(int fd)
2325 struct socket_info *si;
2328 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2330 swrap_mutex_lock(&socket_reset_mutex);
2332 si_index = find_socket_info_index(fd);
2333 if (si_index == -1) {
2334 swrap_mutex_unlock(&socket_reset_mutex);
2338 reset_socket_info_index(fd);
2340 si = swrap_get_socket_info(si_index);
2342 swrap_mutex_lock(&first_free_mutex);
2345 swrap_dec_refcount(si);
2347 if (swrap_get_refcount(si) > 0) {
2351 if (si->un_addr.sun_path[0] != '\0') {
2352 unlink(si->un_addr.sun_path);
2355 swrap_set_next_free(si, first_free);
2356 first_free = si_index;
2359 SWRAP_UNLOCK_SI(si);
2360 swrap_mutex_unlock(&first_free_mutex);
2361 swrap_mutex_unlock(&socket_reset_mutex);
2364 static int sockaddr_convert_to_un(struct socket_info *si,
2365 const struct sockaddr *in_addr,
2367 struct sockaddr_un *out_addr,
2371 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2373 (void) in_len; /* unused */
2375 if (out_addr == NULL) {
2379 out->sa_family = AF_UNIX;
2380 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2381 out->sa_len = sizeof(*out_addr);
2384 switch (in_addr->sa_family) {
2386 const struct sockaddr_in *sin;
2387 if (si->family != AF_INET) {
2390 if (in_len < sizeof(struct sockaddr_in)) {
2393 sin = (const struct sockaddr_in *)(const void *)in_addr;
2394 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2399 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2400 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2414 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2415 errno = ESOCKTNOSUPPORT;
2419 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2421 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2427 errno = EAFNOSUPPORT;
2428 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2432 static int sockaddr_convert_from_un(const struct socket_info *si,
2433 const struct sockaddr_un *in_addr,
2434 socklen_t un_addrlen,
2436 struct sockaddr *out_addr,
2437 socklen_t *out_addrlen)
2441 if (out_addr == NULL || out_addrlen == NULL)
2444 if (un_addrlen == 0) {
2459 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2460 errno = ESOCKTNOSUPPORT;
2463 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2464 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2465 out_addr->sa_len = *out_addrlen;
2472 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2473 errno = EAFNOSUPPORT;
2477 enum swrap_packet_type {
2479 SWRAP_CONNECT_UNREACH,
2487 SWRAP_SENDTO_UNREACH,
2498 struct swrap_file_hdr {
2500 uint16_t version_major;
2501 uint16_t version_minor;
2504 uint32_t frame_max_len;
2505 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2508 #define SWRAP_FILE_HDR_SIZE 24
2510 struct swrap_packet_frame {
2512 uint32_t micro_seconds;
2513 uint32_t recorded_length;
2514 uint32_t full_length;
2516 #define SWRAP_PACKET_FRAME_SIZE 16
2518 union swrap_packet_ip {
2522 uint16_t packet_length;
2523 uint16_t identification;
2528 uint16_t hdr_checksum;
2532 #define SWRAP_PACKET_IP_V4_SIZE 20
2535 uint8_t flow_label_high;
2536 uint16_t flow_label_low;
2537 uint16_t payload_length;
2538 uint8_t next_header;
2540 uint8_t src_addr[16];
2541 uint8_t dest_addr[16];
2543 #define SWRAP_PACKET_IP_V6_SIZE 40
2545 #define SWRAP_PACKET_IP_SIZE 40
2547 union swrap_packet_payload {
2549 uint16_t source_port;
2559 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2561 uint16_t source_port;
2566 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2573 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2580 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2582 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2584 #define SWRAP_PACKET_MIN_ALLOC \
2585 (SWRAP_PACKET_FRAME_SIZE + \
2586 SWRAP_PACKET_IP_SIZE + \
2587 SWRAP_PACKET_PAYLOAD_SIZE)
2589 static const char *swrap_pcap_init_file(void)
2591 static int initialized = 0;
2592 static const char *s = NULL;
2593 static const struct swrap_file_hdr h;
2594 static const struct swrap_packet_frame f;
2595 static const union swrap_packet_ip i;
2596 static const union swrap_packet_payload p;
2598 if (initialized == 1) {
2604 * TODO: don't use the structs use plain buffer offsets
2605 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2607 * for now make sure we disable PCAP support
2608 * if the struct has alignment!
2610 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2613 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2616 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2619 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2622 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2625 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2628 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2631 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2634 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2637 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2641 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2645 if (strncmp(s, "./", 2) == 0) {
2648 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2652 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2653 const struct sockaddr *src,
2654 const struct sockaddr *dest,
2656 const uint8_t *payload,
2658 unsigned long tcp_seqno,
2659 unsigned long tcp_ack,
2660 unsigned char tcp_ctl,
2662 size_t *_packet_len)
2664 uint8_t *base = NULL;
2665 uint8_t *buf = NULL;
2668 struct swrap_packet_frame *frame;
2672 union swrap_packet_ip *ip;
2674 union swrap_packet_payload *pay;
2677 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2678 size_t wire_hdr_len = 0;
2679 size_t wire_len = 0;
2680 size_t ip_hdr_len = 0;
2681 size_t icmp_hdr_len = 0;
2682 size_t icmp_truncate_len = 0;
2683 uint8_t protocol = 0, icmp_protocol = 0;
2684 const struct sockaddr_in *src_in = NULL;
2685 const struct sockaddr_in *dest_in = NULL;
2687 const struct sockaddr_in6 *src_in6 = NULL;
2688 const struct sockaddr_in6 *dest_in6 = NULL;
2693 switch (src->sa_family) {
2695 src_in = (const struct sockaddr_in *)(const void *)src;
2696 dest_in = (const struct sockaddr_in *)(const void *)dest;
2697 src_port = src_in->sin_port;
2698 dest_port = dest_in->sin_port;
2699 ip_hdr_len = sizeof(i.ip->v4);
2703 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2704 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2705 src_port = src_in6->sin6_port;
2706 dest_port = dest_in6->sin6_port;
2707 ip_hdr_len = sizeof(i.ip->v6);
2714 switch (socket_type) {
2716 protocol = 0x06; /* TCP */
2717 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2718 wire_len = wire_hdr_len + payload_len;
2722 protocol = 0x11; /* UDP */
2723 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2724 wire_len = wire_hdr_len + payload_len;
2732 icmp_protocol = protocol;
2733 switch (src->sa_family) {
2735 protocol = 0x01; /* ICMPv4 */
2736 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2740 protocol = 0x3A; /* ICMPv6 */
2741 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2745 if (wire_len > 64 ) {
2746 icmp_truncate_len = wire_len - 64;
2748 wire_len += icmp_hdr_len;
2751 packet_len = nonwire_len + wire_len;
2752 alloc_len = packet_len;
2753 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2754 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2757 base = (uint8_t *)calloc(1, alloc_len);
2765 f.frame->seconds = tval->tv_sec;
2766 f.frame->micro_seconds = tval->tv_usec;
2767 f.frame->recorded_length = wire_len - icmp_truncate_len;
2768 f.frame->full_length = wire_len - icmp_truncate_len;
2770 buf += SWRAP_PACKET_FRAME_SIZE;
2773 switch (src->sa_family) {
2775 if (src_in == NULL || dest_in == NULL) {
2780 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2781 i.ip->v4.tos = 0x00;
2782 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2783 i.ip->v4.identification = htons(0xFFFF);
2784 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2785 i.ip->v4.fragment = htons(0x0000);
2786 i.ip->v4.ttl = 0xFF;
2787 i.ip->v4.protocol = protocol;
2788 i.ip->v4.hdr_checksum = htons(0x0000);
2789 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2790 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2791 buf += SWRAP_PACKET_IP_V4_SIZE;
2795 if (src_in6 == NULL || dest_in6 == NULL) {
2800 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2801 i.ip->v6.flow_label_high = 0x00;
2802 i.ip->v6.flow_label_low = 0x0000;
2803 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2804 i.ip->v6.next_header = protocol;
2805 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2806 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2807 buf += SWRAP_PACKET_IP_V6_SIZE;
2813 pay = (union swrap_packet_payload *)(void *)buf;
2814 switch (src->sa_family) {
2816 pay->icmp4.type = 0x03; /* destination unreachable */
2817 pay->icmp4.code = 0x01; /* host unreachable */
2818 pay->icmp4.checksum = htons(0x0000);
2819 pay->icmp4.unused = htonl(0x00000000);
2821 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2823 /* set the ip header in the ICMP payload */
2825 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2826 i.ip->v4.tos = 0x00;
2827 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2828 i.ip->v4.identification = htons(0xFFFF);
2829 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2830 i.ip->v4.fragment = htons(0x0000);
2831 i.ip->v4.ttl = 0xFF;
2832 i.ip->v4.protocol = icmp_protocol;
2833 i.ip->v4.hdr_checksum = htons(0x0000);
2834 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2835 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2837 buf += SWRAP_PACKET_IP_V4_SIZE;
2839 src_port = dest_in->sin_port;
2840 dest_port = src_in->sin_port;
2844 pay->icmp6.type = 0x01; /* destination unreachable */
2845 pay->icmp6.code = 0x03; /* address unreachable */
2846 pay->icmp6.checksum = htons(0x0000);
2847 pay->icmp6.unused = htonl(0x00000000);
2848 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2850 /* set the ip header in the ICMP payload */
2852 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2853 i.ip->v6.flow_label_high = 0x00;
2854 i.ip->v6.flow_label_low = 0x0000;
2855 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2856 i.ip->v6.next_header = protocol;
2857 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2858 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2860 buf += SWRAP_PACKET_IP_V6_SIZE;
2862 src_port = dest_in6->sin6_port;
2863 dest_port = src_in6->sin6_port;
2869 pay = (union swrap_packet_payload *)(void *)buf;
2871 switch (socket_type) {
2873 pay->tcp.source_port = src_port;
2874 pay->tcp.dest_port = dest_port;
2875 pay->tcp.seq_num = htonl(tcp_seqno);
2876 pay->tcp.ack_num = htonl(tcp_ack);
2877 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2878 pay->tcp.control = tcp_ctl;
2879 pay->tcp.window = htons(0x7FFF);
2880 pay->tcp.checksum = htons(0x0000);
2881 pay->tcp.urg = htons(0x0000);
2882 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2887 pay->udp.source_port = src_port;
2888 pay->udp.dest_port = dest_port;
2889 pay->udp.length = htons(8 + payload_len);
2890 pay->udp.checksum = htons(0x0000);
2891 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2896 if (payload && payload_len > 0) {
2897 memcpy(buf, payload, payload_len);
2900 *_packet_len = packet_len - icmp_truncate_len;
2904 static int swrap_pcap_get_fd(const char *fname)
2912 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2914 struct swrap_file_hdr file_hdr;
2915 file_hdr.magic = 0xA1B2C3D4;
2916 file_hdr.version_major = 0x0002;
2917 file_hdr.version_minor = 0x0004;
2918 file_hdr.timezone = 0x00000000;
2919 file_hdr.sigfigs = 0x00000000;
2920 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2921 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2923 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2930 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2935 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2936 const struct sockaddr *addr,
2937 enum swrap_packet_type type,
2938 const void *buf, size_t len,
2941 const struct sockaddr *src_addr;
2942 const struct sockaddr *dest_addr;
2943 unsigned long tcp_seqno = 0;
2944 unsigned long tcp_ack = 0;
2945 unsigned char tcp_ctl = 0;
2946 int unreachable = 0;
2950 switch (si->family) {
2962 case SWRAP_CONNECT_SEND:
2963 if (si->type != SOCK_STREAM) {
2967 src_addr = &si->myname.sa.s;
2970 tcp_seqno = si->io.pck_snd;
2971 tcp_ack = si->io.pck_rcv;
2972 tcp_ctl = 0x02; /* SYN */
2974 si->io.pck_snd += 1;
2978 case SWRAP_CONNECT_RECV:
2979 if (si->type != SOCK_STREAM) {
2983 dest_addr = &si->myname.sa.s;
2986 tcp_seqno = si->io.pck_rcv;
2987 tcp_ack = si->io.pck_snd;
2988 tcp_ctl = 0x12; /** SYN,ACK */
2990 si->io.pck_rcv += 1;
2994 case SWRAP_CONNECT_UNREACH:
2995 if (si->type != SOCK_STREAM) {
2999 dest_addr = &si->myname.sa.s;
3002 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3003 tcp_seqno = si->io.pck_snd - 1;
3004 tcp_ack = si->io.pck_rcv;
3005 tcp_ctl = 0x02; /* SYN */
3010 case SWRAP_CONNECT_ACK:
3011 if (si->type != SOCK_STREAM) {
3015 src_addr = &si->myname.sa.s;
3018 tcp_seqno = si->io.pck_snd;
3019 tcp_ack = si->io.pck_rcv;
3020 tcp_ctl = 0x10; /* ACK */
3024 case SWRAP_ACCEPT_SEND:
3025 if (si->type != SOCK_STREAM) {
3029 dest_addr = &si->myname.sa.s;
3032 tcp_seqno = si->io.pck_rcv;
3033 tcp_ack = si->io.pck_snd;
3034 tcp_ctl = 0x02; /* SYN */
3036 si->io.pck_rcv += 1;
3040 case SWRAP_ACCEPT_RECV:
3041 if (si->type != SOCK_STREAM) {
3045 src_addr = &si->myname.sa.s;
3048 tcp_seqno = si->io.pck_snd;
3049 tcp_ack = si->io.pck_rcv;
3050 tcp_ctl = 0x12; /* SYN,ACK */
3052 si->io.pck_snd += 1;
3056 case SWRAP_ACCEPT_ACK:
3057 if (si->type != SOCK_STREAM) {
3061 dest_addr = &si->myname.sa.s;
3064 tcp_seqno = si->io.pck_rcv;
3065 tcp_ack = si->io.pck_snd;
3066 tcp_ctl = 0x10; /* ACK */
3071 src_addr = &si->myname.sa.s;
3072 dest_addr = &si->peername.sa.s;
3074 tcp_seqno = si->io.pck_snd;
3075 tcp_ack = si->io.pck_rcv;
3076 tcp_ctl = 0x18; /* PSH,ACK */
3078 si->io.pck_snd += len;
3082 case SWRAP_SEND_RST:
3083 dest_addr = &si->myname.sa.s;
3084 src_addr = &si->peername.sa.s;
3086 if (si->type == SOCK_DGRAM) {
3087 return swrap_pcap_marshall_packet(si,
3089 SWRAP_SENDTO_UNREACH,
3095 tcp_seqno = si->io.pck_rcv;
3096 tcp_ack = si->io.pck_snd;
3097 tcp_ctl = 0x14; /** RST,ACK */
3101 case SWRAP_PENDING_RST:
3102 dest_addr = &si->myname.sa.s;
3103 src_addr = &si->peername.sa.s;
3105 if (si->type == SOCK_DGRAM) {
3109 tcp_seqno = si->io.pck_rcv;
3110 tcp_ack = si->io.pck_snd;
3111 tcp_ctl = 0x14; /* RST,ACK */
3116 dest_addr = &si->myname.sa.s;
3117 src_addr = &si->peername.sa.s;
3119 tcp_seqno = si->io.pck_rcv;
3120 tcp_ack = si->io.pck_snd;
3121 tcp_ctl = 0x18; /* PSH,ACK */
3123 si->io.pck_rcv += len;
3127 case SWRAP_RECV_RST:
3128 dest_addr = &si->myname.sa.s;
3129 src_addr = &si->peername.sa.s;
3131 if (si->type == SOCK_DGRAM) {
3135 tcp_seqno = si->io.pck_rcv;
3136 tcp_ack = si->io.pck_snd;
3137 tcp_ctl = 0x14; /* RST,ACK */
3142 src_addr = &si->myname.sa.s;
3145 si->io.pck_snd += len;
3149 case SWRAP_SENDTO_UNREACH:
3150 dest_addr = &si->myname.sa.s;
3157 case SWRAP_RECVFROM:
3158 dest_addr = &si->myname.sa.s;
3161 si->io.pck_rcv += len;
3165 case SWRAP_CLOSE_SEND:
3166 if (si->type != SOCK_STREAM) {
3170 src_addr = &si->myname.sa.s;
3171 dest_addr = &si->peername.sa.s;
3173 tcp_seqno = si->io.pck_snd;
3174 tcp_ack = si->io.pck_rcv;
3175 tcp_ctl = 0x11; /* FIN, ACK */
3177 si->io.pck_snd += 1;
3181 case SWRAP_CLOSE_RECV:
3182 if (si->type != SOCK_STREAM) {
3186 dest_addr = &si->myname.sa.s;
3187 src_addr = &si->peername.sa.s;
3189 tcp_seqno = si->io.pck_rcv;
3190 tcp_ack = si->io.pck_snd;
3191 tcp_ctl = 0x11; /* FIN,ACK */
3193 si->io.pck_rcv += 1;
3197 case SWRAP_CLOSE_ACK:
3198 if (si->type != SOCK_STREAM) {
3202 src_addr = &si->myname.sa.s;
3203 dest_addr = &si->peername.sa.s;
3205 tcp_seqno = si->io.pck_snd;
3206 tcp_ack = si->io.pck_rcv;
3207 tcp_ctl = 0x10; /* ACK */
3214 swrapGetTimeOfDay(&tv);
3216 return swrap_pcap_packet_init(&tv,
3220 (const uint8_t *)buf,
3229 static void swrap_pcap_dump_packet(struct socket_info *si,
3230 const struct sockaddr *addr,
3231 enum swrap_packet_type type,
3232 const void *buf, size_t len)
3234 const char *file_name;
3236 size_t packet_len = 0;
3239 swrap_mutex_lock(&pcap_dump_mutex);
3241 file_name = swrap_pcap_init_file();
3246 packet = swrap_pcap_marshall_packet(si,
3252 if (packet == NULL) {
3256 fd = swrap_pcap_get_fd(file_name);
3258 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3267 swrap_mutex_unlock(&pcap_dump_mutex);
3270 /****************************************************************************
3272 ***************************************************************************/
3274 #ifdef HAVE_SIGNALFD
3275 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3279 rc = libc_signalfd(fd, mask, flags);
3281 swrap_remove_stale(fd);
3287 int signalfd(int fd, const sigset_t *mask, int flags)
3289 return swrap_signalfd(fd, mask, flags);
3293 /****************************************************************************
3295 ***************************************************************************/
3297 static int swrap_socket(int family, int type, int protocol)
3299 struct socket_info *si = NULL;
3300 struct socket_info _si = { 0 };
3303 int real_type = type;
3306 * Remove possible addition flags passed to socket() so
3307 * do not fail checking the type.
3308 * See https://lwn.net/Articles/281965/
3311 real_type &= ~SOCK_CLOEXEC;
3313 #ifdef SOCK_NONBLOCK
3314 real_type &= ~SOCK_NONBLOCK;
3317 if (!socket_wrapper_enabled()) {
3318 return libc_socket(family, type, protocol);
3329 #endif /* AF_NETLINK */
3332 #endif /* AF_PACKET */
3334 fd = libc_socket(family, type, protocol);
3336 /* Check if we have a stale fd and remove it */
3337 swrap_remove_stale(fd);
3338 SWRAP_LOG(SWRAP_LOG_TRACE,
3339 "Unix socket fd=%d",
3344 errno = EAFNOSUPPORT;
3348 switch (real_type) {
3354 errno = EPROTONOSUPPORT;
3362 if (real_type == SOCK_STREAM) {
3367 if (real_type == SOCK_DGRAM) {
3372 errno = EPROTONOSUPPORT;
3377 * We must call libc_socket with type, from the caller, not the version
3378 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3380 fd = libc_socket(AF_UNIX, type, 0);
3386 /* Check if we have a stale fd and remove it */
3387 swrap_remove_stale(fd);
3390 si->family = family;
3392 /* however, the rest of the socket_wrapper code expects just
3393 * the type, not the flags */
3394 si->type = real_type;
3395 si->protocol = protocol;
3398 * Setup myname so getsockname() can succeed to find out the socket
3401 switch(si->family) {
3403 struct sockaddr_in sin = {
3404 .sin_family = AF_INET,
3407 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3408 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3413 struct sockaddr_in6 sin6 = {
3414 .sin6_family = AF_INET6,
3417 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3418 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3427 ret = swrap_create_socket(si, fd);
3432 SWRAP_LOG(SWRAP_LOG_TRACE,
3433 "Created %s socket for protocol %s, fd=%d",
3434 family == AF_INET ? "IPv4" : "IPv6",
3435 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3441 int socket(int family, int type, int protocol)
3443 return swrap_socket(family, type, protocol);
3446 /****************************************************************************
3448 ***************************************************************************/
3450 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3454 rc = libc_socketpair(family, type, protocol, sv);
3456 swrap_remove_stale(sv[0]);
3457 swrap_remove_stale(sv[1]);
3463 int socketpair(int family, int type, int protocol, int sv[2])
3465 return swrap_socketpair(family, type, protocol, sv);
3468 /****************************************************************************
3470 ***************************************************************************/
3472 #ifdef HAVE_TIMERFD_CREATE
3473 static int swrap_timerfd_create(int clockid, int flags)
3477 fd = libc_timerfd_create(clockid, flags);
3479 swrap_remove_stale(fd);
3485 int timerfd_create(int clockid, int flags)
3487 return swrap_timerfd_create(clockid, flags);
3491 /****************************************************************************
3493 ***************************************************************************/
3495 static int swrap_pipe(int pipefd[2])
3499 rc = libc_pipe(pipefd);
3501 swrap_remove_stale(pipefd[0]);
3502 swrap_remove_stale(pipefd[1]);
3508 int pipe(int pipefd[2])
3510 return swrap_pipe(pipefd);
3513 /****************************************************************************
3515 ***************************************************************************/
3517 static int swrap_accept(int s,
3518 struct sockaddr *addr,
3522 struct socket_info *parent_si, *child_si;
3523 struct socket_info new_si = { 0 };
3526 struct swrap_address un_addr = {
3527 .sa_socklen = sizeof(struct sockaddr_un),
3529 struct swrap_address un_my_addr = {
3530 .sa_socklen = sizeof(struct sockaddr_un),
3532 struct swrap_address in_addr = {
3533 .sa_socklen = sizeof(struct sockaddr_storage),
3535 struct swrap_address in_my_addr = {
3536 .sa_socklen = sizeof(struct sockaddr_storage),
3540 parent_si = find_socket_info(s);
3543 return libc_accept4(s, addr, addrlen, flags);
3546 return libc_accept(s, addr, addrlen);
3552 * prevent parent_si from being altered / closed
3555 SWRAP_LOCK_SI(parent_si);
3558 * assume out sockaddr have the same size as the in parent
3561 in_addr.sa_socklen = socket_length(parent_si->family);
3562 if (in_addr.sa_socklen <= 0) {
3563 SWRAP_UNLOCK_SI(parent_si);
3568 SWRAP_UNLOCK_SI(parent_si);
3571 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3574 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3577 if (errno == ENOTSOCK) {
3578 /* Remove stale fds */
3579 swrap_remove_stale(s);
3586 /* Check if we have a stale fd and remove it */
3587 swrap_remove_stale(fd);
3589 SWRAP_LOCK_SI(parent_si);
3591 ret = sockaddr_convert_from_un(parent_si,
3596 &in_addr.sa_socklen);
3598 SWRAP_UNLOCK_SI(parent_si);
3605 child_si->family = parent_si->family;
3606 child_si->type = parent_si->type;
3607 child_si->protocol = parent_si->protocol;
3608 child_si->bound = 1;
3609 child_si->is_server = 1;
3610 child_si->connected = 1;
3612 SWRAP_UNLOCK_SI(parent_si);
3614 child_si->peername = (struct swrap_address) {
3615 .sa_socklen = in_addr.sa_socklen,
3617 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3619 if (addr != NULL && addrlen != NULL) {
3620 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3622 memcpy(addr, &in_addr.sa.ss, copy_len);
3624 *addrlen = in_addr.sa_socklen;
3627 ret = libc_getsockname(fd,
3629 &un_my_addr.sa_socklen);
3635 ret = sockaddr_convert_from_un(child_si,
3637 un_my_addr.sa_socklen,
3640 &in_my_addr.sa_socklen);
3646 SWRAP_LOG(SWRAP_LOG_TRACE,
3647 "accept() path=%s, fd=%d",
3648 un_my_addr.sa.un.sun_path, s);
3650 child_si->myname = (struct swrap_address) {
3651 .sa_socklen = in_my_addr.sa_socklen,
3653 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3655 idx = swrap_create_socket(&new_si, fd);
3662 struct socket_info *si = swrap_get_socket_info(idx);
3665 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3666 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3667 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3668 SWRAP_UNLOCK_SI(si);
3675 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3677 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3681 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3682 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3684 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3687 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3690 static int autobind_start_init;
3691 static int autobind_start;
3693 /* using sendto() or connect() on an unbound socket would give the
3694 recipient no way to reply, as unlike UDP and TCP, a unix domain
3695 socket can't auto-assign ephemeral port numbers, so we need to
3697 Note: this might change the family from ipv6 to ipv4
3699 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3701 struct swrap_address un_addr = {
3702 .sa_socklen = sizeof(struct sockaddr_un),
3709 char *swrap_dir = NULL;
3711 swrap_mutex_lock(&autobind_start_mutex);
3713 if (autobind_start_init != 1) {
3714 autobind_start_init = 1;
3715 autobind_start = getpid();
3716 autobind_start %= 50000;
3717 autobind_start += 10000;
3720 un_addr.sa.un.sun_family = AF_UNIX;
3724 struct sockaddr_in in;
3728 type = SOCKET_TYPE_CHAR_TCP;
3731 type = SOCKET_TYPE_CHAR_UDP;
3734 errno = ESOCKTNOSUPPORT;
3739 memset(&in, 0, sizeof(in));
3740 in.sin_family = AF_INET;
3741 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3742 socket_wrapper_default_iface()));
3744 si->myname = (struct swrap_address) {
3745 .sa_socklen = sizeof(in),
3747 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3752 struct sockaddr_in6 in6;
3754 if (si->family != family) {
3755 errno = ENETUNREACH;
3762 type = SOCKET_TYPE_CHAR_TCP_V6;
3765 type = SOCKET_TYPE_CHAR_UDP_V6;
3768 errno = ESOCKTNOSUPPORT;
3773 memset(&in6, 0, sizeof(in6));
3774 in6.sin6_family = AF_INET6;
3775 in6.sin6_addr = *swrap_ipv6();
3776 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3778 si->myname = (struct swrap_address) {
3779 .sa_socklen = sizeof(in6),
3781 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3786 errno = ESOCKTNOSUPPORT;
3791 if (autobind_start > 60000) {
3792 autobind_start = 10000;
3795 swrap_dir = socket_wrapper_dir();
3796 if (swrap_dir == NULL) {
3802 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3803 port = autobind_start + i;
3804 swrap_un_path(&un_addr.sa.un,
3807 socket_wrapper_default_iface(),
3809 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3811 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3816 si->un_addr = un_addr.sa.un;
3819 autobind_start = port + 1;
3822 if (i == SOCKET_MAX_SOCKETS) {
3823 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3824 "interface "SOCKET_FORMAT,
3827 socket_wrapper_default_iface(),
3834 si->family = family;
3835 set_port(si->family, port, &si->myname);
3840 SAFE_FREE(swrap_dir);
3841 swrap_mutex_unlock(&autobind_start_mutex);
3845 /****************************************************************************
3847 ***************************************************************************/
3849 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3853 struct swrap_address un_addr = {
3854 .sa_socklen = sizeof(struct sockaddr_un),
3856 struct socket_info *si = find_socket_info(s);
3860 return libc_connect(s, serv_addr, addrlen);
3865 if (si->bound == 0) {
3866 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3872 if (si->family != serv_addr->sa_family) {
3873 SWRAP_LOG(SWRAP_LOG_ERROR,
3874 "called for fd=%d (family=%d) called with invalid family=%d",
3875 s, si->family, serv_addr->sa_family);
3881 ret = sockaddr_convert_to_un(si, serv_addr,
3882 addrlen, &un_addr.sa.un, 0, &bcast);
3888 errno = ENETUNREACH;
3893 if (si->type == SOCK_DGRAM) {
3894 si->defer_connect = 1;
3897 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3899 ret = libc_connect(s,
3901 un_addr.sa_socklen);
3904 SWRAP_LOG(SWRAP_LOG_TRACE,
3905 "connect() path=%s, fd=%d",
3906 un_addr.sa.un.sun_path, s);
3909 /* to give better errors */
3910 if (ret == -1 && errno == ENOENT) {
3911 errno = EHOSTUNREACH;
3915 si->peername = (struct swrap_address) {
3916 .sa_socklen = addrlen,
3919 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3923 * When we connect() on a socket than we have to bind the
3924 * outgoing connection on the interface we use for the
3925 * transport. We already bound it on the right interface
3926 * but here we have to update the name so getsockname()
3927 * returns correct information.
3929 if (si->bindname.sa_socklen > 0) {
3930 si->myname = (struct swrap_address) {
3931 .sa_socklen = si->bindname.sa_socklen,
3934 memcpy(&si->myname.sa.ss,
3935 &si->bindname.sa.ss,
3936 si->bindname.sa_socklen);
3938 /* Cleanup bindname */
3939 si->bindname = (struct swrap_address) {
3944 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3945 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3947 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3951 SWRAP_UNLOCK_SI(si);
3955 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3957 return swrap_connect(s, serv_addr, addrlen);
3960 /****************************************************************************
3962 ***************************************************************************/
3964 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3967 struct swrap_address un_addr = {
3968 .sa_socklen = sizeof(struct sockaddr_un),
3970 struct socket_info *si = find_socket_info(s);
3977 return libc_bind(s, myaddr, addrlen);
3982 switch (si->family) {
3984 const struct sockaddr_in *sin;
3985 if (addrlen < sizeof(struct sockaddr_in)) {
3986 bind_error = EINVAL;
3990 sin = (const struct sockaddr_in *)(const void *)myaddr;
3992 if (sin->sin_family != AF_INET) {
3993 bind_error = EAFNOSUPPORT;
3996 /* special case for AF_UNSPEC */
3997 if (sin->sin_family == AF_UNSPEC &&
3998 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4007 const struct sockaddr_in6 *sin6;
4008 if (addrlen < sizeof(struct sockaddr_in6)) {
4009 bind_error = EINVAL;
4013 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4015 if (sin6->sin6_family != AF_INET6) {
4016 bind_error = EAFNOSUPPORT;
4023 bind_error = EINVAL;
4027 if (bind_error != 0) {
4034 in_use = check_addr_port_in_use(myaddr, addrlen);
4042 si->myname.sa_socklen = addrlen;
4043 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4045 ret = sockaddr_convert_to_un(si,
4055 unlink(un_addr.sa.un.sun_path);
4057 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4059 SWRAP_LOG(SWRAP_LOG_TRACE,
4060 "bind() path=%s, fd=%d",
4061 un_addr.sa.un.sun_path, s);
4068 SWRAP_UNLOCK_SI(si);
4073 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4075 return swrap_bind(s, myaddr, addrlen);
4078 /****************************************************************************
4080 ***************************************************************************/
4082 #ifdef HAVE_BINDRESVPORT
4083 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4085 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4087 struct swrap_address myaddr = {
4088 .sa_socklen = sizeof(struct sockaddr_storage),
4091 static uint16_t port;
4096 #define SWRAP_STARTPORT 600
4097 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4098 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4101 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4105 salen = myaddr.sa_socklen;
4108 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4114 memset(&myaddr.sa.ss, 0, salen);
4119 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4122 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4124 salen = sizeof(struct sockaddr_in);
4125 sinp->sin_port = htons(port);
4129 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4131 salen = sizeof(struct sockaddr_in6);
4132 sin6p->sin6_port = htons(port);
4136 errno = EAFNOSUPPORT;
4141 if (port > SWRAP_ENDPORT) {
4142 port = SWRAP_STARTPORT;
4145 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4146 if (rc == 0 || errno != EADDRINUSE) {
4154 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4156 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4160 /****************************************************************************
4162 ***************************************************************************/
4164 static int swrap_listen(int s, int backlog)
4167 struct socket_info *si = find_socket_info(s);
4170 return libc_listen(s, backlog);
4175 if (si->bound == 0) {
4176 ret = swrap_auto_bind(s, si, si->family);
4183 ret = libc_listen(s, backlog);
4189 SWRAP_UNLOCK_SI(si);
4194 int listen(int s, int backlog)
4196 return swrap_listen(s, backlog);
4199 /****************************************************************************
4201 ***************************************************************************/
4203 static FILE *swrap_fopen(const char *name, const char *mode)
4207 fp = libc_fopen(name, mode);
4209 int fd = fileno(fp);
4211 swrap_remove_stale(fd);
4217 FILE *fopen(const char *name, const char *mode)
4219 return swrap_fopen(name, mode);
4222 /****************************************************************************
4224 ***************************************************************************/
4227 static FILE *swrap_fopen64(const char *name, const char *mode)
4231 fp = libc_fopen64(name, mode);
4233 int fd = fileno(fp);
4235 swrap_remove_stale(fd);
4241 FILE *fopen64(const char *name, const char *mode)
4243 return swrap_fopen64(name, mode);
4245 #endif /* HAVE_FOPEN64 */
4247 /****************************************************************************
4249 ***************************************************************************/
4251 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4255 ret = libc_vopen(pathname, flags, ap);
4258 * There are methods for closing descriptors (libc-internal code
4259 * paths, direct syscalls) which close descriptors in ways that
4260 * we can't intercept, so try to recover when we notice that
4263 swrap_remove_stale(ret);
4268 int open(const char *pathname, int flags, ...)
4273 va_start(ap, flags);
4274 fd = swrap_vopen(pathname, flags, ap);
4280 /****************************************************************************
4282 ***************************************************************************/
4285 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4289 ret = libc_vopen64(pathname, flags, ap);
4292 * There are methods for closing descriptors (libc-internal code
4293 * paths, direct syscalls) which close descriptors in ways that
4294 * we can't intercept, so try to recover when we notice that
4297 swrap_remove_stale(ret);
4302 int open64(const char *pathname, int flags, ...)
4307 va_start(ap, flags);
4308 fd = swrap_vopen64(pathname, flags, ap);
4313 #endif /* HAVE_OPEN64 */
4315 /****************************************************************************
4317 ***************************************************************************/
4319 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4323 ret = libc_vopenat(dirfd, path, flags, ap);
4326 * There are methods for closing descriptors (libc-internal code
4327 * paths, direct syscalls) which close descriptors in ways that
4328 * we can't intercept, so try to recover when we notice that
4331 swrap_remove_stale(ret);
4337 int openat(int dirfd, const char *path, int flags, ...)
4342 va_start(ap, flags);
4343 fd = swrap_vopenat(dirfd, path, flags, ap);
4349 /****************************************************************************
4351 ***************************************************************************/
4353 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4355 struct socket_info *si = find_socket_info(s);
4360 return libc_getpeername(s, name, addrlen);
4365 if (si->peername.sa_socklen == 0)
4371 len = MIN(*addrlen, si->peername.sa_socklen);
4377 memcpy(name, &si->peername.sa.ss, len);
4378 *addrlen = si->peername.sa_socklen;
4382 SWRAP_UNLOCK_SI(si);
4387 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4388 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4390 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4393 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4396 /****************************************************************************
4398 ***************************************************************************/
4400 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4402 struct socket_info *si = find_socket_info(s);
4407 return libc_getsockname(s, name, addrlen);
4412 len = MIN(*addrlen, si->myname.sa_socklen);
4418 memcpy(name, &si->myname.sa.ss, len);
4419 *addrlen = si->myname.sa_socklen;
4423 SWRAP_UNLOCK_SI(si);
4428 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4429 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4431 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4434 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4437 /****************************************************************************
4439 ***************************************************************************/
4442 # ifdef SO_PROTOTYPE /* The Solaris name */
4443 # define SO_PROTOCOL SO_PROTOTYPE
4444 # endif /* SO_PROTOTYPE */
4445 #endif /* SO_PROTOCOL */
4447 static int swrap_getsockopt(int s, int level, int optname,
4448 void *optval, socklen_t *optlen)
4450 struct socket_info *si = find_socket_info(s);
4454 return libc_getsockopt(s,
4463 if (level == SOL_SOCKET) {
4467 if (optval == NULL || optlen == NULL ||
4468 *optlen < (socklen_t)sizeof(int)) {
4474 *optlen = sizeof(int);
4475 *(int *)optval = si->family;
4478 #endif /* SO_DOMAIN */
4482 if (optval == NULL || optlen == NULL ||
4483 *optlen < (socklen_t)sizeof(int)) {
4489 *optlen = sizeof(int);
4490 *(int *)optval = si->protocol;
4493 #endif /* SO_PROTOCOL */
4495 if (optval == NULL || optlen == NULL ||
4496 *optlen < (socklen_t)sizeof(int)) {
4502 *optlen = sizeof(int);
4503 *(int *)optval = si->type;
4507 ret = libc_getsockopt(s,
4514 } else if (level == IPPROTO_TCP) {
4519 * This enables sending packets directly out over TCP.
4520 * As a unix socket is doing that any way, report it as
4523 if (optval == NULL || optlen == NULL ||
4524 *optlen < (socklen_t)sizeof(int)) {
4530 *optlen = sizeof(int);
4531 *(int *)optval = si->tcp_nodelay;
4535 #endif /* TCP_NODELAY */
4538 struct tcp_info info;
4539 socklen_t ilen = sizeof(info);
4541 #ifdef HAVE_NETINET_TCP_FSM_H
4542 /* This is FreeBSD */
4543 # define __TCP_LISTEN TCPS_LISTEN
4544 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4545 # define __TCP_CLOSE TCPS_CLOSED
4548 # define __TCP_LISTEN TCP_LISTEN
4549 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4550 # define __TCP_CLOSE TCP_CLOSE
4554 if (si->listening) {
4555 info.tcpi_state = __TCP_LISTEN;
4556 } else if (si->connected) {
4558 * For now we just fake a few values
4559 * supported both by FreeBSD and Linux
4561 info.tcpi_state = __TCP_ESTABLISHED;
4562 info.tcpi_rto = 200000; /* 200 msec */
4563 info.tcpi_rtt = 5000; /* 5 msec */
4564 info.tcpi_rttvar = 5000; /* 5 msec */
4566 info.tcpi_state = __TCP_CLOSE;
4567 info.tcpi_rto = 1000000; /* 1 sec */
4569 info.tcpi_rttvar = 250000; /* 250 msec */
4572 if (optval == NULL || optlen == NULL ||
4573 *optlen < (socklen_t)ilen) {
4580 memcpy(optval, &info, ilen);
4585 #endif /* TCP_INFO */
4591 errno = ENOPROTOOPT;
4595 SWRAP_UNLOCK_SI(si);
4599 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4600 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4602 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4605 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4608 /****************************************************************************
4610 ***************************************************************************/
4612 static int swrap_setsockopt(int s, int level, int optname,
4613 const void *optval, socklen_t optlen)
4615 struct socket_info *si = find_socket_info(s);
4619 return libc_setsockopt(s,
4626 if (level == SOL_SOCKET) {
4627 return libc_setsockopt(s,
4636 if (level == IPPROTO_TCP) {
4643 * This enables sending packets directly out over TCP.
4644 * A unix socket is doing that any way.
4646 if (optval == NULL || optlen == 0 ||
4647 optlen < (socklen_t)sizeof(int)) {
4653 i = *discard_const_p(int, optval);
4654 if (i != 0 && i != 1) {
4659 si->tcp_nodelay = i;
4664 #endif /* TCP_NODELAY */
4670 switch (si->family) {
4672 if (level == IPPROTO_IP) {
4674 if (optname == IP_PKTINFO) {
4675 si->pktinfo = AF_INET;
4677 #endif /* IP_PKTINFO */
4683 if (level == IPPROTO_IPV6) {
4684 #ifdef IPV6_RECVPKTINFO
4685 if (optname == IPV6_RECVPKTINFO) {
4686 si->pktinfo = AF_INET6;
4688 #endif /* IPV6_PKTINFO */
4694 errno = ENOPROTOOPT;
4700 SWRAP_UNLOCK_SI(si);
4704 int setsockopt(int s, int level, int optname,
4705 const void *optval, socklen_t optlen)
4707 return swrap_setsockopt(s, level, optname, optval, optlen);
4710 /****************************************************************************
4712 ***************************************************************************/
4714 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4716 struct socket_info *si = find_socket_info(s);
4718 int *value_ptr = NULL;
4722 return libc_vioctl(s, r, va);
4729 rc = libc_vioctl(s, r, va);
4734 value_ptr = ((int *)va_arg(ap, int *));
4737 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4738 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4739 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4740 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4745 /* this is FreeBSD */
4746 FALL_THROUGH; /* to TIOCOUTQ */
4747 #endif /* FIONWRITE */
4748 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4750 * This may return more bytes then the application
4751 * sent into the socket, for tcp it should
4752 * return the number of unacked bytes.
4754 * On AF_UNIX, all bytes are immediately acked!
4757 value_ptr = ((int *)va_arg(ap, int *));
4765 SWRAP_UNLOCK_SI(si);
4769 #ifdef HAVE_IOCTL_INT
4770 int ioctl(int s, int r, ...)
4772 int ioctl(int s, unsigned long int r, ...)
4780 rc = swrap_vioctl(s, (unsigned long int) r, va);
4791 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4794 # ifdef _ALIGN /* BSD */
4795 #define CMSG_ALIGN _ALIGN
4797 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4798 # endif /* _ALIGN */
4799 #endif /* CMSG_ALIGN */
4802 * @brief Add a cmsghdr to a msghdr.
4804 * This is an function to add any type of cmsghdr. It will operate on the
4805 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4806 * the buffer position after the added cmsg element. Hence, this function is
4807 * intended to be used with an intermediate msghdr and not on the original
4808 * one handed in by the client.
4810 * @param[in] msg The msghdr to which to add the cmsg.
4812 * @param[in] level The cmsg level to set.
4814 * @param[in] type The cmsg type to set.
4816 * @param[in] data The cmsg data to set.
4818 * @param[in] len the length of the data to set.
4820 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4826 size_t cmlen = CMSG_LEN(len);
4827 size_t cmspace = CMSG_SPACE(len);
4828 uint8_t cmbuf[cmspace];
4829 void *cast_ptr = (void *)cmbuf;
4830 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4833 memset(cmbuf, 0, cmspace);
4835 if (msg->msg_controllen < cmlen) {
4836 cmlen = msg->msg_controllen;
4837 msg->msg_flags |= MSG_CTRUNC;
4840 if (msg->msg_controllen < cmspace) {
4841 cmspace = msg->msg_controllen;
4845 * We copy the full input data into an intermediate cmsghdr first
4846 * in order to more easily cope with truncation.
4848 cm->cmsg_len = cmlen;
4849 cm->cmsg_level = level;
4850 cm->cmsg_type = type;
4851 memcpy(CMSG_DATA(cm), data, len);
4854 * We now copy the possibly truncated buffer.
4855 * We copy cmlen bytes, but consume cmspace bytes,
4856 * leaving the possible padding uninitialiazed.
4858 p = (uint8_t *)msg->msg_control;
4859 memcpy(p, cm, cmlen);
4861 msg->msg_control = p;
4862 msg->msg_controllen -= cmspace;
4867 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4870 /* Add packet info */
4871 switch (si->pktinfo) {
4872 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4874 struct sockaddr_in *sin;
4875 #if defined(HAVE_STRUCT_IN_PKTINFO)
4876 struct in_pktinfo pkt;
4877 #elif defined(IP_RECVDSTADDR)
4881 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4882 sin = &si->bindname.sa.in;
4884 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4887 sin = &si->myname.sa.in;
4892 #if defined(HAVE_STRUCT_IN_PKTINFO)
4893 pkt.ipi_ifindex = socket_wrapper_default_iface();
4894 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4895 #elif defined(IP_RECVDSTADDR)
4896 pkt = sin->sin_addr;
4899 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4904 #endif /* IP_PKTINFO */
4905 #if defined(HAVE_IPV6)
4907 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4908 struct sockaddr_in6 *sin6;
4909 struct in6_pktinfo pkt6;
4911 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4912 sin6 = &si->bindname.sa.in6;
4914 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4917 sin6 = &si->myname.sa.in6;
4922 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4923 pkt6.ipi6_addr = sin6->sin6_addr;
4925 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4926 &pkt6, sizeof(pkt6));
4927 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4931 #endif /* IPV6_PKTINFO */
4939 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4940 struct msghdr *omsg)
4944 if (si->pktinfo > 0) {
4945 rc = swrap_msghdr_add_pktinfo(si, omsg);
4951 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4953 size_t *cm_data_space);
4954 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4956 size_t *cm_data_space);
4958 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4960 size_t *cm_data_space) {
4961 struct cmsghdr *cmsg;
4965 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4969 for (cmsg = CMSG_FIRSTHDR(msg);
4971 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4972 switch (cmsg->cmsg_level) {
4974 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4979 rc = swrap_sendmsg_copy_cmsg(cmsg,
4989 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4991 size_t *cm_data_space)
4996 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4998 p = realloc((*cm_data), cmspace);
5004 p = (*cm_data) + (*cm_data_space);
5005 *cm_data_space = cmspace;
5007 memcpy(p, cmsg, cmsg->cmsg_len);
5012 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
5014 size_t *cm_data_space);
5017 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
5019 size_t *cm_data_space)
5023 switch(cmsg->cmsg_type) {
5026 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5033 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5045 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
5047 size_t *cm_data_space)
5049 (void)cmsg; /* unused */
5050 (void)cm_data; /* unused */
5051 (void)cm_data_space; /* unused */
5054 * Passing a IP pktinfo to a unix socket might be rejected by the
5055 * Kernel, at least on FreeBSD. So skip this cmsg.
5059 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5061 static ssize_t swrap_sendmsg_before(int fd,
5062 struct socket_info *si,
5064 struct iovec *tmp_iov,
5065 struct sockaddr_un *tmp_un,
5066 const struct sockaddr_un **to_un,
5067 const struct sockaddr **to,
5089 if (!si->connected) {
5094 if (msg->msg_iovlen == 0) {
5098 mtu = socket_wrapper_mtu();
5099 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5101 nlen = len + msg->msg_iov[i].iov_len;
5111 msg->msg_iovlen = i;
5112 if (msg->msg_iovlen == 0) {
5113 *tmp_iov = msg->msg_iov[0];
5114 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5116 msg->msg_iov = tmp_iov;
5117 msg->msg_iovlen = 1;
5122 if (si->connected) {
5123 if (msg->msg_name != NULL) {
5125 * We are dealing with unix sockets and if we
5126 * are connected, we should only talk to the
5127 * connected unix path. Using the fd to send
5128 * to another server would be hard to achieve.
5130 msg->msg_name = NULL;
5131 msg->msg_namelen = 0;
5134 const struct sockaddr *msg_name;
5135 msg_name = (const struct sockaddr *)msg->msg_name;
5137 if (msg_name == NULL) {
5143 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
5155 msg->msg_name = tmp_un;
5156 msg->msg_namelen = sizeof(*tmp_un);
5159 if (si->bound == 0) {
5160 ret = swrap_auto_bind(fd, si, si->family);
5162 SWRAP_UNLOCK_SI(si);
5163 if (errno == ENOTSOCK) {
5164 swrap_remove_stale(fd);
5167 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
5173 if (!si->defer_connect) {
5177 ret = sockaddr_convert_to_un(si,
5179 si->peername.sa_socklen,
5187 ret = libc_connect(fd,
5188 (struct sockaddr *)(void *)tmp_un,
5191 /* to give better errors */
5192 if (ret == -1 && errno == ENOENT) {
5193 errno = EHOSTUNREACH;
5200 si->defer_connect = 0;
5203 errno = EHOSTUNREACH;
5207 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5208 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
5209 uint8_t *cmbuf = NULL;
5212 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
5219 msg->msg_controllen = 0;
5220 msg->msg_control = NULL;
5221 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
5222 memcpy(msg->msg_control, cmbuf, cmlen);
5223 msg->msg_controllen = cmlen;
5231 SWRAP_UNLOCK_SI(si);
5236 static void swrap_sendmsg_after(int fd,
5237 struct socket_info *si,
5239 const struct sockaddr *to,
5242 int saved_errno = errno;
5249 /* to give better errors */
5251 if (saved_errno == ENOENT) {
5252 saved_errno = EHOSTUNREACH;
5253 } else if (saved_errno == ENOTSOCK) {
5254 /* If the fd is not a socket, remove it */
5255 swrap_remove_stale(fd);
5259 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5260 avail += msg->msg_iov[i].iov_len;
5264 remain = MIN(80, avail);
5269 /* we capture it as one single packet */
5270 buf = (uint8_t *)malloc(remain);
5272 /* we just not capture the packet */
5273 errno = saved_errno;
5277 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5278 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5280 msg->msg_iov[i].iov_base,
5283 remain -= this_time;
5292 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5293 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5295 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5300 if (si->connected) {
5301 to = &si->peername.sa.s;
5304 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5305 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5307 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5312 SWRAP_UNLOCK_SI(si);
5315 errno = saved_errno;
5318 static int swrap_recvmsg_before(int fd,
5319 struct socket_info *si,
5321 struct iovec *tmp_iov)
5328 (void)fd; /* unused */
5333 if (!si->connected) {
5338 if (msg->msg_iovlen == 0) {
5342 mtu = socket_wrapper_mtu();
5343 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5345 nlen = len + msg->msg_iov[i].iov_len;
5350 msg->msg_iovlen = i;
5351 if (msg->msg_iovlen == 0) {
5352 *tmp_iov = msg->msg_iov[0];
5353 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5355 msg->msg_iov = tmp_iov;
5356 msg->msg_iovlen = 1;
5361 if (msg->msg_name == NULL) {
5366 if (msg->msg_iovlen == 0) {
5370 if (si->bound == 0) {
5371 ret = swrap_auto_bind(fd, si, si->family);
5373 SWRAP_UNLOCK_SI(si);
5375 * When attempting to read or write to a
5376 * descriptor, if an underlying autobind fails
5377 * because it's not a socket, stop intercepting
5378 * uses of that descriptor.
5380 if (errno == ENOTSOCK) {
5381 swrap_remove_stale(fd);
5384 SWRAP_LOG(SWRAP_LOG_ERROR,
5385 "swrap_recvmsg_before failed");
5392 errno = EHOSTUNREACH;
5398 SWRAP_UNLOCK_SI(si);
5403 static int swrap_recvmsg_after(int fd,
5404 struct socket_info *si,
5406 const struct sockaddr_un *un_addr,
5407 socklen_t un_addrlen,
5410 int saved_errno = errno;
5412 uint8_t *buf = NULL;
5418 /* to give better errors */
5420 if (saved_errno == ENOENT) {
5421 saved_errno = EHOSTUNREACH;
5422 } else if (saved_errno == ENOTSOCK) {
5423 /* If the fd is not a socket, remove it */
5424 swrap_remove_stale(fd);
5428 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5429 avail += msg->msg_iov[i].iov_len;
5434 /* Convert the socket address before we leave */
5435 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5436 rc = sockaddr_convert_from_un(si,
5453 remain = MIN(80, avail);
5458 /* we capture it as one single packet */
5459 buf = (uint8_t *)malloc(remain);
5461 /* we just not capture the packet */
5462 SWRAP_UNLOCK_SI(si);
5463 errno = saved_errno;
5467 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5468 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5470 msg->msg_iov[i].iov_base,
5473 remain -= this_time;
5478 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5479 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5480 } else if (ret == 0) { /* END OF FILE */
5481 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5482 } else if (ret > 0) {
5483 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5492 if (un_addr != NULL) {
5493 swrap_pcap_dump_packet(si,
5499 swrap_pcap_dump_packet(si,
5512 errno = saved_errno;
5514 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5516 msg->msg_controllen > 0 &&
5517 msg->msg_control != NULL) {
5518 rc = swrap_msghdr_add_socket_info(si, msg);
5520 SWRAP_UNLOCK_SI(si);
5526 SWRAP_UNLOCK_SI(si);
5530 /****************************************************************************
5532 ***************************************************************************/
5534 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5535 struct sockaddr *from, socklen_t *fromlen)
5537 struct swrap_address from_addr = {
5538 .sa_socklen = sizeof(struct sockaddr_un),
5541 struct socket_info *si = find_socket_info(s);
5542 struct swrap_address saddr = {
5543 .sa_socklen = sizeof(struct sockaddr_storage),
5550 return libc_recvfrom(s,
5562 if (from != NULL && fromlen != NULL) {
5563 msg.msg_name = from; /* optional address */
5564 msg.msg_namelen = *fromlen; /* size of address */
5566 msg.msg_name = &saddr.sa.s; /* optional address */
5567 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5569 msg.msg_iov = &tmp; /* scatter/gather array */
5570 msg.msg_iovlen = 1; /* # elements in msg_iov */
5571 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5572 msg.msg_control = NULL; /* ancillary data, see below */
5573 msg.msg_controllen = 0; /* ancillary data buffer len */
5574 msg.msg_flags = 0; /* flags on received message */
5577 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5582 buf = msg.msg_iov[0].iov_base;
5583 len = msg.msg_iov[0].iov_len;
5585 ret = libc_recvfrom(s,
5590 &from_addr.sa_socklen);
5595 tret = swrap_recvmsg_after(s,
5599 from_addr.sa_socklen,
5605 if (from != NULL && fromlen != NULL) {
5606 *fromlen = msg.msg_namelen;
5612 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5613 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5614 struct sockaddr *from, Psocklen_t fromlen)
5616 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5617 struct sockaddr *from, socklen_t *fromlen)
5620 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5623 /****************************************************************************
5625 ***************************************************************************/
5627 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5628 const struct sockaddr *to, socklen_t tolen)
5632 struct swrap_address un_addr = {
5633 .sa_socklen = sizeof(struct sockaddr_un),
5635 const struct sockaddr_un *to_un = NULL;
5638 struct socket_info *si = find_socket_info(s);
5642 return libc_sendto(s, buf, len, flags, to, tolen);
5645 tmp.iov_base = discard_const_p(char, buf);
5649 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5650 msg.msg_namelen = tolen; /* size of address */
5651 msg.msg_iov = &tmp; /* scatter/gather array */
5652 msg.msg_iovlen = 1; /* # elements in msg_iov */
5653 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5654 msg.msg_control = NULL; /* ancillary data, see below */
5655 msg.msg_controllen = 0; /* ancillary data buffer len */
5656 msg.msg_flags = 0; /* flags on received message */
5659 rc = swrap_sendmsg_before(s,
5671 buf = msg.msg_iov[0].iov_base;
5672 len = msg.msg_iov[0].iov_len;
5677 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5679 char *swrap_dir = NULL;
5681 type = SOCKET_TYPE_CHAR_UDP;
5683 swrap_dir = socket_wrapper_dir();
5684 if (swrap_dir == NULL) {
5688 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5689 swrap_un_path(&un_addr.sa.un,
5694 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5696 /* ignore the any errors in broadcast sends */
5702 un_addr.sa_socklen);
5705 SAFE_FREE(swrap_dir);
5709 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5711 SWRAP_UNLOCK_SI(si);
5718 * If it is a dgram socket and we are connected, don't include the
5721 if (si->type == SOCK_DGRAM && si->connected) {
5722 ret = libc_sendto(s,
5729 ret = libc_sendto(s,
5733 (struct sockaddr *)msg.msg_name,
5737 SWRAP_UNLOCK_SI(si);
5739 swrap_sendmsg_after(s, si, &msg, to, ret);
5744 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5745 const struct sockaddr *to, socklen_t tolen)
5747 return swrap_sendto(s, buf, len, flags, to, tolen);
5750 /****************************************************************************
5752 ***************************************************************************/
5754 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5756 struct socket_info *si;
5758 struct swrap_address saddr = {
5759 .sa_socklen = sizeof(struct sockaddr_storage),
5765 si = find_socket_info(s);
5767 return libc_recv(s, buf, len, flags);
5774 msg.msg_name = &saddr.sa.s; /* optional address */
5775 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5776 msg.msg_iov = &tmp; /* scatter/gather array */
5777 msg.msg_iovlen = 1; /* # elements in msg_iov */
5778 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5779 msg.msg_control = NULL; /* ancillary data, see below */
5780 msg.msg_controllen = 0; /* ancillary data buffer len */
5781 msg.msg_flags = 0; /* flags on received message */
5784 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5789 buf = msg.msg_iov[0].iov_base;
5790 len = msg.msg_iov[0].iov_len;
5792 ret = libc_recv(s, buf, len, flags);
5794 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5802 ssize_t recv(int s, void *buf, size_t len, int flags)
5804 return swrap_recv(s, buf, len, flags);
5807 /****************************************************************************
5809 ***************************************************************************/
5811 static ssize_t swrap_read(int s, void *buf, size_t len)
5813 struct socket_info *si;
5816 struct swrap_address saddr = {
5817 .sa_socklen = sizeof(struct sockaddr_storage),
5822 si = find_socket_info(s);
5824 return libc_read(s, buf, len);
5831 msg.msg_name = &saddr.sa.ss; /* optional address */
5832 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5833 msg.msg_iov = &tmp; /* scatter/gather array */
5834 msg.msg_iovlen = 1; /* # elements in msg_iov */
5835 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5836 msg.msg_control = NULL; /* ancillary data, see below */
5837 msg.msg_controllen = 0; /* ancillary data buffer len */
5838 msg.msg_flags = 0; /* flags on received message */
5841 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5843 if (tret == -ENOTSOCK) {
5844 return libc_read(s, buf, len);
5849 buf = msg.msg_iov[0].iov_base;
5850 len = msg.msg_iov[0].iov_len;
5852 ret = libc_read(s, buf, len);
5854 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5862 ssize_t read(int s, void *buf, size_t len)
5864 return swrap_read(s, buf, len);
5867 /****************************************************************************
5869 ***************************************************************************/
5871 static ssize_t swrap_write(int s, const void *buf, size_t len)
5875 struct sockaddr_un un_addr;
5878 struct socket_info *si;
5880 si = find_socket_info(s);
5882 return libc_write(s, buf, len);
5885 tmp.iov_base = discard_const_p(char, buf);
5889 msg.msg_name = NULL; /* optional address */
5890 msg.msg_namelen = 0; /* size of address */
5891 msg.msg_iov = &tmp; /* scatter/gather array */
5892 msg.msg_iovlen = 1; /* # elements in msg_iov */
5893 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5894 msg.msg_control = NULL; /* ancillary data, see below */
5895 msg.msg_controllen = 0; /* ancillary data buffer len */
5896 msg.msg_flags = 0; /* flags on received message */
5899 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5904 buf = msg.msg_iov[0].iov_base;
5905 len = msg.msg_iov[0].iov_len;
5907 ret = libc_write(s, buf, len);
5909 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5914 ssize_t write(int s, const void *buf, size_t len)
5916 return swrap_write(s, buf, len);
5919 /****************************************************************************
5921 ***************************************************************************/
5923 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5927 struct sockaddr_un un_addr;
5930 struct socket_info *si = find_socket_info(s);
5933 return libc_send(s, buf, len, flags);
5936 tmp.iov_base = discard_const_p(char, buf);
5940 msg.msg_name = NULL; /* optional address */
5941 msg.msg_namelen = 0; /* size of address */
5942 msg.msg_iov = &tmp; /* scatter/gather array */
5943 msg.msg_iovlen = 1; /* # elements in msg_iov */
5944 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5945 msg.msg_control = NULL; /* ancillary data, see below */
5946 msg.msg_controllen = 0; /* ancillary data buffer len */
5947 msg.msg_flags = 0; /* flags on received message */
5950 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5955 buf = msg.msg_iov[0].iov_base;
5956 len = msg.msg_iov[0].iov_len;
5958 ret = libc_send(s, buf, len, flags);
5960 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5965 ssize_t send(int s, const void *buf, size_t len, int flags)
5967 return swrap_send(s, buf, len, flags);
5970 /****************************************************************************
5972 ***************************************************************************/
5974 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5976 struct swrap_address from_addr = {
5977 .sa_socklen = sizeof(struct sockaddr_un),
5979 struct swrap_address convert_addr = {
5980 .sa_socklen = sizeof(struct sockaddr_storage),
5982 struct socket_info *si;
5985 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5986 size_t msg_ctrllen_filled;
5987 size_t msg_ctrllen_left;
5993 si = find_socket_info(s);
5995 return libc_recvmsg(s, omsg, flags);
5998 tmp.iov_base = NULL;
6002 msg.msg_name = &from_addr.sa; /* optional address */
6003 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6004 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6005 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6006 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6007 msg_ctrllen_filled = 0;
6008 msg_ctrllen_left = omsg->msg_controllen;
6010 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6011 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6012 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6015 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6020 ret = libc_recvmsg(s, &msg, flags);
6022 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6023 msg_ctrllen_filled += msg.msg_controllen;
6024 msg_ctrllen_left -= msg.msg_controllen;
6026 if (omsg->msg_control != NULL) {
6029 p = omsg->msg_control;
6030 p += msg_ctrllen_filled;
6032 msg.msg_control = p;
6033 msg.msg_controllen = msg_ctrllen_left;
6035 msg.msg_control = NULL;
6036 msg.msg_controllen = 0;
6041 * We convert the unix address to a IP address so we need a buffer
6042 * which can store the address in case of SOCK_DGRAM, see below.
6044 msg.msg_name = &convert_addr.sa;
6045 msg.msg_namelen = convert_addr.sa_socklen;
6047 rc = swrap_recvmsg_after(s,
6051 from_addr.sa_socklen,
6057 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6058 if (omsg->msg_control != NULL) {
6059 /* msg.msg_controllen = space left */
6060 msg_ctrllen_left = msg.msg_controllen;
6061 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6064 /* Update the original message length */
6065 omsg->msg_controllen = msg_ctrllen_filled;
6066 omsg->msg_flags = msg.msg_flags;
6068 omsg->msg_iovlen = msg.msg_iovlen;
6075 * The msg_name field points to a caller-allocated buffer that is
6076 * used to return the source address if the socket is unconnected. The
6077 * caller should set msg_namelen to the size of this buffer before this
6078 * call; upon return from a successful call, msg_name will contain the
6079 * length of the returned address. If the application does not need
6080 * to know the source address, msg_name can be specified as NULL.
6082 if (si->type == SOCK_STREAM) {
6083 omsg->msg_namelen = 0;
6084 } else if (omsg->msg_name != NULL &&
6085 omsg->msg_namelen != 0 &&
6086 omsg->msg_namelen >= msg.msg_namelen) {
6087 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6088 omsg->msg_namelen = msg.msg_namelen;
6091 SWRAP_UNLOCK_SI(si);
6096 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6098 return swrap_recvmsg(sockfd, msg, flags);
6101 /****************************************************************************
6103 ***************************************************************************/
6105 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
6109 struct sockaddr_un un_addr;
6110 const struct sockaddr_un *to_un = NULL;
6111 const struct sockaddr *to = NULL;
6114 struct socket_info *si = find_socket_info(s);
6118 return libc_sendmsg(s, omsg, flags);
6121 ZERO_STRUCT(un_addr);
6123 tmp.iov_base = NULL;
6130 if (si->connected == 0) {
6131 msg.msg_name = omsg->msg_name; /* optional address */
6132 msg.msg_namelen = omsg->msg_namelen; /* size of address */
6134 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6135 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6137 SWRAP_UNLOCK_SI(si);
6139 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6140 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
6141 /* omsg is a const so use a local buffer for modifications */
6142 uint8_t cmbuf[omsg->msg_controllen];
6144 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
6146 msg.msg_control = cmbuf; /* ancillary data, see below */
6147 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6149 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6152 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
6160 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6167 char *swrap_dir = NULL;
6169 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6170 avail += msg.msg_iov[i].iov_len;
6176 /* we capture it as one single packet */
6177 buf = (uint8_t *)malloc(remain);
6182 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6183 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
6185 msg.msg_iov[i].iov_base,
6188 remain -= this_time;
6191 type = SOCKET_TYPE_CHAR_UDP;
6193 swrap_dir = socket_wrapper_dir();
6194 if (swrap_dir == NULL) {
6199 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6200 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
6201 if (stat(un_addr.sun_path, &st) != 0) continue;
6203 msg.msg_name = &un_addr; /* optional address */
6204 msg.msg_namelen = sizeof(un_addr); /* size of address */
6206 /* ignore the any errors in broadcast sends */
6207 libc_sendmsg(s, &msg, flags);
6210 SAFE_FREE(swrap_dir);
6214 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6217 SWRAP_UNLOCK_SI(si);
6222 ret = libc_sendmsg(s, &msg, flags);
6224 swrap_sendmsg_after(s, si, &msg, to, ret);
6229 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
6231 return swrap_sendmsg(s, omsg, flags);
6234 /****************************************************************************
6236 ***************************************************************************/
6238 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
6240 struct socket_info *si;
6243 struct swrap_address saddr = {
6244 .sa_socklen = sizeof(struct sockaddr_storage)
6249 si = find_socket_info(s);
6251 return libc_readv(s, vector, count);
6254 tmp.iov_base = NULL;
6258 msg.msg_name = &saddr.sa.s; /* optional address */
6259 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6260 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6261 msg.msg_iovlen = count; /* # elements in msg_iov */
6262 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6263 msg.msg_control = NULL; /* ancillary data, see below */
6264 msg.msg_controllen = 0; /* ancillary data buffer len */
6265 msg.msg_flags = 0; /* flags on received message */
6268 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6270 if (rc == -ENOTSOCK) {
6271 return libc_readv(s, vector, count);
6276 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
6278 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6286 ssize_t readv(int s, const struct iovec *vector, int count)
6288 return swrap_readv(s, vector, count);
6291 /****************************************************************************
6293 ***************************************************************************/
6295 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6299 struct sockaddr_un un_addr;
6302 struct socket_info *si = find_socket_info(s);
6305 return libc_writev(s, vector, count);
6308 tmp.iov_base = NULL;
6312 msg.msg_name = NULL; /* optional address */
6313 msg.msg_namelen = 0; /* size of address */
6314 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6315 msg.msg_iovlen = count; /* # elements in msg_iov */
6316 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6317 msg.msg_control = NULL; /* ancillary data, see below */
6318 msg.msg_controllen = 0; /* ancillary data buffer len */
6319 msg.msg_flags = 0; /* flags on received message */
6322 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6324 if (rc == -ENOTSOCK) {
6325 return libc_readv(s, vector, count);
6330 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6332 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6337 ssize_t writev(int s, const struct iovec *vector, int count)
6339 return swrap_writev(s, vector, count);
6342 /****************************
6344 ***************************/
6346 static int swrap_close(int fd)
6348 struct socket_info *si = NULL;
6352 swrap_mutex_lock(&socket_reset_mutex);
6354 si_index = find_socket_info_index(fd);
6355 if (si_index == -1) {
6356 swrap_mutex_unlock(&socket_reset_mutex);
6357 return libc_close(fd);
6360 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
6361 reset_socket_info_index(fd);
6363 si = swrap_get_socket_info(si_index);
6365 swrap_mutex_lock(&first_free_mutex);
6368 ret = libc_close(fd);
6370 swrap_dec_refcount(si);
6372 if (swrap_get_refcount(si) > 0) {
6373 /* there are still references left */
6377 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6378 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6381 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6382 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6383 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6386 if (si->un_addr.sun_path[0] != '\0') {
6387 unlink(si->un_addr.sun_path);
6390 swrap_set_next_free(si, first_free);
6391 first_free = si_index;
6394 SWRAP_UNLOCK_SI(si);
6395 swrap_mutex_unlock(&first_free_mutex);
6396 swrap_mutex_unlock(&socket_reset_mutex);
6403 return swrap_close(fd);
6406 /****************************
6408 ***************************/
6410 static int swrap_dup(int fd)
6412 struct socket_info *si;
6415 idx = find_socket_info_index(fd);
6417 return libc_dup(fd);
6420 si = swrap_get_socket_info(idx);
6422 dup_fd = libc_dup(fd);
6424 int saved_errno = errno;
6425 errno = saved_errno;
6431 swrap_inc_refcount(si);
6433 SWRAP_UNLOCK_SI(si);
6435 /* Make sure we don't have an entry for the fd */
6436 swrap_remove_stale(dup_fd);
6438 set_socket_info_index(dup_fd, idx);
6445 return swrap_dup(fd);
6448 /****************************
6450 ***************************/
6452 static int swrap_dup2(int fd, int newfd)
6454 struct socket_info *si;
6457 idx = find_socket_info_index(fd);
6459 return libc_dup2(fd, newfd);
6462 si = swrap_get_socket_info(idx);
6466 * According to the manpage:
6468 * "If oldfd is a valid file descriptor, and newfd has the same
6469 * value as oldfd, then dup2() does nothing, and returns newfd."
6474 if (find_socket_info(newfd)) {
6475 /* dup2() does an implicit close of newfd, which we
6476 * need to emulate */
6480 dup_fd = libc_dup2(fd, newfd);
6482 int saved_errno = errno;
6483 errno = saved_errno;
6489 swrap_inc_refcount(si);
6491 SWRAP_UNLOCK_SI(si);
6493 /* Make sure we don't have an entry for the fd */
6494 swrap_remove_stale(dup_fd);
6496 set_socket_info_index(dup_fd, idx);
6501 int dup2(int fd, int newfd)
6503 return swrap_dup2(fd, newfd);
6506 /****************************
6508 ***************************/
6510 static int swrap_vfcntl(int fd, int cmd, va_list va)
6512 struct socket_info *si;
6513 int rc, dup_fd, idx;
6515 idx = find_socket_info_index(fd);
6517 return libc_vfcntl(fd, cmd, va);
6520 si = swrap_get_socket_info(idx);
6524 dup_fd = libc_vfcntl(fd, cmd, va);
6526 int saved_errno = errno;
6527 errno = saved_errno;
6533 swrap_inc_refcount(si);
6535 SWRAP_UNLOCK_SI(si);
6537 /* Make sure we don't have an entry for the fd */
6538 swrap_remove_stale(dup_fd);
6540 set_socket_info_index(dup_fd, idx);
6545 rc = libc_vfcntl(fd, cmd, va);
6552 int fcntl(int fd, int cmd, ...)
6559 rc = swrap_vfcntl(fd, cmd, va);
6566 /****************************
6568 ***************************/
6571 static int swrap_eventfd(int count, int flags)
6575 fd = libc_eventfd(count, flags);
6577 swrap_remove_stale(fd);
6583 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6584 int eventfd(unsigned int count, int flags)
6586 int eventfd(int count, int flags)
6589 return swrap_eventfd(count, flags);
6594 int pledge(const char *promises, const char *paths[])
6596 (void)promises; /* unused */
6597 (void)paths; /* unused */
6601 #endif /* HAVE_PLEDGE */
6603 static void swrap_thread_prepare(void)
6606 * This function should only be called here!!
6608 * We bind all symobls to avoid deadlocks of the fork is
6609 * interrupted by a signal handler using a symbol of this
6612 swrap_bind_symbol_all();
6617 static void swrap_thread_parent(void)
6622 static void swrap_thread_child(void)
6627 /****************************
6629 ***************************/
6630 void swrap_constructor(void)
6635 * If we hold a lock and the application forks, then the child
6636 * is not able to unlock the mutex and we are in a deadlock.
6637 * This should prevent such deadlocks.
6639 pthread_atfork(&swrap_thread_prepare,
6640 &swrap_thread_parent,
6641 &swrap_thread_child);
6643 ret = socket_wrapper_init_mutex(&sockets_mutex);
6645 SWRAP_LOG(SWRAP_LOG_ERROR,
6646 "Failed to initialize pthread mutex");
6650 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6652 SWRAP_LOG(SWRAP_LOG_ERROR,
6653 "Failed to initialize pthread mutex");
6657 ret = socket_wrapper_init_mutex(&first_free_mutex);
6659 SWRAP_LOG(SWRAP_LOG_ERROR,
6660 "Failed to initialize pthread mutex");
6665 /****************************
6667 ***************************/
6670 * This function is called when the library is unloaded and makes sure that
6671 * sockets get closed and the unix file for the socket are unlinked.
6673 void swrap_destructor(void)
6677 if (socket_fds_idx != NULL) {
6678 for (i = 0; i < socket_fds_max; ++i) {
6679 if (socket_fds_idx[i] != -1) {
6683 SAFE_FREE(socket_fds_idx);
6688 if (swrap.libc.handle != NULL) {
6689 dlclose(swrap.libc.handle);
6691 if (swrap.libc.socket_handle) {
6692 dlclose(swrap.libc.socket_handle);
6696 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
6698 * On FreeBSD 12 (and maybe other platforms)
6699 * system libraries like libresolv prefix there
6700 * syscalls with '_' in order to always use
6701 * the symbols from libc.
6703 * In the interaction with resolv_wrapper,
6704 * we need to inject socket wrapper into libresolv,
6705 * which means we need to private all socket
6706 * related syscalls also with the '_' prefix.
6708 * This is tested in Samba's 'make test',
6709 * there we noticed that providing '_read'
6710 * and '_open' would cause errors, which
6711 * means we skip '_read', '_write' and
6712 * all non socket related calls without
6713 * further analyzing the problem.
6715 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
6716 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
6719 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
6721 SWRAP_SYMBOL_ALIAS(accept, _accept);
6722 SWRAP_SYMBOL_ALIAS(bind, _bind);
6723 SWRAP_SYMBOL_ALIAS(close, _close);
6724 SWRAP_SYMBOL_ALIAS(connect, _connect);
6725 SWRAP_SYMBOL_ALIAS(dup, _dup);
6726 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
6727 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
6728 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
6729 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
6730 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
6731 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
6732 SWRAP_SYMBOL_ALIAS(listen, _listen);
6733 SWRAP_SYMBOL_ALIAS(readv, _readv);
6734 SWRAP_SYMBOL_ALIAS(recv, _recv);
6735 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
6736 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
6737 SWRAP_SYMBOL_ALIAS(send, _send);
6738 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
6739 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
6740 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
6741 SWRAP_SYMBOL_ALIAS(socket, _socket);
6742 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
6743 SWRAP_SYMBOL_ALIAS(writev, _writev);
6745 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */