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 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
338 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
340 #ifndef HAVE_GETPROGNAME
341 static const char *getprogname(void)
343 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
344 return program_invocation_short_name;
345 #elif defined(HAVE_GETEXECNAME)
346 return getexecname();
349 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
351 #endif /* HAVE_GETPROGNAME */
353 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
354 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
356 static void swrap_log(enum swrap_dbglvl_e dbglvl,
358 const char *format, ...)
363 unsigned int lvl = 0;
364 const char *prefix = "SWRAP";
365 const char *progname = getprogname();
367 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
376 va_start(va, format);
377 vsnprintf(buffer, sizeof(buffer), format, va);
381 case SWRAP_LOG_ERROR:
382 prefix = "SWRAP_ERROR";
385 prefix = "SWRAP_WARN";
387 case SWRAP_LOG_DEBUG:
388 prefix = "SWRAP_DEBUG";
390 case SWRAP_LOG_TRACE:
391 prefix = "SWRAP_TRACE";
395 if (progname == NULL) {
396 progname = "<unknown>";
400 "%s[%s (%u)] - %s: %s\n",
403 (unsigned int)getpid(),
408 /*********************************************************
409 * SWRAP LOADING LIBC FUNCTIONS
410 *********************************************************/
415 typedef int (*__libc_accept4)(int sockfd,
416 struct sockaddr *addr,
420 typedef int (*__libc_accept)(int sockfd,
421 struct sockaddr *addr,
424 typedef int (*__libc_bind)(int sockfd,
425 const struct sockaddr *addr,
427 typedef int (*__libc_close)(int fd);
428 typedef int (*__libc_connect)(int sockfd,
429 const struct sockaddr *addr,
431 typedef int (*__libc_dup)(int fd);
432 typedef int (*__libc_dup2)(int oldfd, int newfd);
433 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
434 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
436 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
439 typedef int (*__libc_eventfd)(int count, int flags);
441 typedef int (*__libc_getpeername)(int sockfd,
442 struct sockaddr *addr,
444 typedef int (*__libc_getsockname)(int sockfd,
445 struct sockaddr *addr,
447 typedef int (*__libc_getsockopt)(int sockfd,
452 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
453 typedef int (*__libc_listen)(int sockfd, int backlog);
454 typedef int (*__libc_open)(const char *pathname, int flags, ...);
456 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
457 #endif /* HAVE_OPEN64 */
458 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
459 typedef int (*__libc_pipe)(int pipefd[2]);
460 typedef int (*__libc_read)(int fd, void *buf, size_t count);
461 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
462 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
463 typedef int (*__libc_recvfrom)(int sockfd,
467 struct sockaddr *src_addr,
469 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
470 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
471 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
472 typedef int (*__libc_sendto)(int sockfd,
476 const struct sockaddr *dst_addr,
478 typedef int (*__libc_setsockopt)(int sockfd,
484 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
486 typedef int (*__libc_socket)(int domain, int type, int protocol);
487 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
488 #ifdef HAVE_TIMERFD_CREATE
489 typedef int (*__libc_timerfd_create)(int clockid, int flags);
491 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
492 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
494 #define SWRAP_SYMBOL_ENTRY(i) \
500 struct swrap_libc_symbols {
502 SWRAP_SYMBOL_ENTRY(accept4);
504 SWRAP_SYMBOL_ENTRY(accept);
506 SWRAP_SYMBOL_ENTRY(bind);
507 SWRAP_SYMBOL_ENTRY(close);
508 SWRAP_SYMBOL_ENTRY(connect);
509 SWRAP_SYMBOL_ENTRY(dup);
510 SWRAP_SYMBOL_ENTRY(dup2);
511 SWRAP_SYMBOL_ENTRY(fcntl);
512 SWRAP_SYMBOL_ENTRY(fopen);
514 SWRAP_SYMBOL_ENTRY(fopen64);
517 SWRAP_SYMBOL_ENTRY(eventfd);
519 SWRAP_SYMBOL_ENTRY(getpeername);
520 SWRAP_SYMBOL_ENTRY(getsockname);
521 SWRAP_SYMBOL_ENTRY(getsockopt);
522 SWRAP_SYMBOL_ENTRY(ioctl);
523 SWRAP_SYMBOL_ENTRY(listen);
524 SWRAP_SYMBOL_ENTRY(open);
526 SWRAP_SYMBOL_ENTRY(open64);
528 SWRAP_SYMBOL_ENTRY(openat);
529 SWRAP_SYMBOL_ENTRY(pipe);
530 SWRAP_SYMBOL_ENTRY(read);
531 SWRAP_SYMBOL_ENTRY(readv);
532 SWRAP_SYMBOL_ENTRY(recv);
533 SWRAP_SYMBOL_ENTRY(recvfrom);
534 SWRAP_SYMBOL_ENTRY(recvmsg);
535 SWRAP_SYMBOL_ENTRY(send);
536 SWRAP_SYMBOL_ENTRY(sendmsg);
537 SWRAP_SYMBOL_ENTRY(sendto);
538 SWRAP_SYMBOL_ENTRY(setsockopt);
540 SWRAP_SYMBOL_ENTRY(signalfd);
542 SWRAP_SYMBOL_ENTRY(socket);
543 SWRAP_SYMBOL_ENTRY(socketpair);
544 #ifdef HAVE_TIMERFD_CREATE
545 SWRAP_SYMBOL_ENTRY(timerfd_create);
547 SWRAP_SYMBOL_ENTRY(write);
548 SWRAP_SYMBOL_ENTRY(writev);
555 struct swrap_libc_symbols symbols;
559 static struct swrap swrap;
562 static char *socket_wrapper_dir(void);
564 #define LIBC_NAME "libc.so"
572 static const char *swrap_str_lib(enum swrap_lib lib)
579 case SWRAP_LIBSOCKET:
583 /* Compiler would warn us about unhandled enum value if we get here */
587 static void *swrap_load_lib_handle(enum swrap_lib lib)
589 int flags = RTLD_LAZY;
594 const char *env_preload = getenv("LD_PRELOAD");
595 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
596 bool enable_deepbind = true;
598 /* Don't do a deepbind if we run with libasan */
599 if (env_preload != NULL && strlen(env_preload) < 1024) {
600 const char *p = strstr(env_preload, "libasan.so");
602 enable_deepbind = false;
606 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
607 enable_deepbind = false;
610 if (enable_deepbind) {
611 flags |= RTLD_DEEPBIND;
617 case SWRAP_LIBSOCKET:
618 #ifdef HAVE_LIBSOCKET
619 handle = swrap.libc.socket_handle;
620 if (handle == NULL) {
621 for (i = 10; i >= 0; i--) {
622 char soname[256] = {0};
624 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
625 handle = dlopen(soname, flags);
626 if (handle != NULL) {
631 swrap.libc.socket_handle = handle;
636 handle = swrap.libc.handle;
638 if (handle == NULL) {
639 handle = dlopen(LIBC_SO, flags);
641 swrap.libc.handle = handle;
644 if (handle == NULL) {
645 for (i = 10; i >= 0; i--) {
646 char soname[256] = {0};
648 snprintf(soname, sizeof(soname), "libc.so.%d", i);
649 handle = dlopen(soname, flags);
650 if (handle != NULL) {
655 swrap.libc.handle = handle;
660 if (handle == NULL) {
662 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
664 SWRAP_LOG(SWRAP_LOG_ERROR,
665 "Failed to dlopen library: %s",
674 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
679 handle = swrap_load_lib_handle(lib);
681 func = dlsym(handle, fn_name);
683 SWRAP_LOG(SWRAP_LOG_ERROR,
684 "Failed to find %s: %s",
690 SWRAP_LOG(SWRAP_LOG_TRACE,
698 static void swrap_mutex_lock(pthread_mutex_t *mutex)
702 ret = pthread_mutex_lock(mutex);
704 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
709 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
713 ret = pthread_mutex_unlock(mutex);
715 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
721 * These macros have a thread race condition on purpose!
723 * This is an optimization to avoid locking each time we check if the symbol is
726 #define swrap_bind_symbol_libc(sym_name) \
727 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
728 swrap_mutex_lock(&libc_symbol_binding_mutex); \
729 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
730 swrap.libc.symbols._libc_##sym_name.obj = \
731 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
733 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
736 #define swrap_bind_symbol_libsocket(sym_name) \
737 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
738 swrap_mutex_lock(&libc_symbol_binding_mutex); \
739 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
740 swrap.libc.symbols._libc_##sym_name.obj = \
741 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
743 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
746 #define swrap_bind_symbol_libnsl(sym_name) \
747 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
748 swrap_mutex_lock(&libc_symbol_binding_mutex); \
749 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
750 swrap.libc.symbols._libc_##sym_name.obj = \
751 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
753 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
756 /****************************************************************************
758 ****************************************************************************
760 * Functions especially from libc need to be loaded individually, you can't
761 * load all at once or gdb will segfault at startup. The same applies to
762 * valgrind and has probably something todo with with the linker. So we need
763 * load each function at the point it is called the first time.
765 ****************************************************************************/
768 static int libc_accept4(int sockfd,
769 struct sockaddr *addr,
773 swrap_bind_symbol_libsocket(accept4);
775 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
778 #else /* HAVE_ACCEPT4 */
780 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
782 swrap_bind_symbol_libsocket(accept);
784 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
786 #endif /* HAVE_ACCEPT4 */
788 static int libc_bind(int sockfd,
789 const struct sockaddr *addr,
792 swrap_bind_symbol_libsocket(bind);
794 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
797 static int libc_close(int fd)
799 swrap_bind_symbol_libc(close);
801 return swrap.libc.symbols._libc_close.f(fd);
804 static int libc_connect(int sockfd,
805 const struct sockaddr *addr,
808 swrap_bind_symbol_libsocket(connect);
810 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
813 static int libc_dup(int fd)
815 swrap_bind_symbol_libc(dup);
817 return swrap.libc.symbols._libc_dup.f(fd);
820 static int libc_dup2(int oldfd, int newfd)
822 swrap_bind_symbol_libc(dup2);
824 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
828 static int libc_eventfd(int count, int flags)
830 swrap_bind_symbol_libc(eventfd);
832 return swrap.libc.symbols._libc_eventfd.f(count, flags);
836 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
837 static int libc_vfcntl(int fd, int cmd, va_list ap)
842 swrap_bind_symbol_libc(fcntl);
844 arg = va_arg(ap, void *);
846 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
851 static int libc_getpeername(int sockfd,
852 struct sockaddr *addr,
855 swrap_bind_symbol_libsocket(getpeername);
857 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
860 static int libc_getsockname(int sockfd,
861 struct sockaddr *addr,
864 swrap_bind_symbol_libsocket(getsockname);
866 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
869 static int libc_getsockopt(int sockfd,
875 swrap_bind_symbol_libsocket(getsockopt);
877 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
884 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
885 static int libc_vioctl(int d, unsigned long int request, va_list ap)
890 swrap_bind_symbol_libc(ioctl);
892 arg = va_arg(ap, void *);
894 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
899 static int libc_listen(int sockfd, int backlog)
901 swrap_bind_symbol_libsocket(listen);
903 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
906 static FILE *libc_fopen(const char *name, const char *mode)
908 swrap_bind_symbol_libc(fopen);
910 return swrap.libc.symbols._libc_fopen.f(name, mode);
914 static FILE *libc_fopen64(const char *name, const char *mode)
916 swrap_bind_symbol_libc(fopen64);
918 return swrap.libc.symbols._libc_fopen64.f(name, mode);
920 #endif /* HAVE_FOPEN64 */
922 static int libc_vopen(const char *pathname, int flags, va_list ap)
927 swrap_bind_symbol_libc(open);
929 if (flags & O_CREAT) {
930 mode = va_arg(ap, int);
932 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
937 static int libc_open(const char *pathname, int flags, ...)
943 fd = libc_vopen(pathname, flags, ap);
950 static int libc_vopen64(const char *pathname, int flags, va_list ap)
955 swrap_bind_symbol_libc(open64);
957 if (flags & O_CREAT) {
958 mode = va_arg(ap, int);
960 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
964 #endif /* HAVE_OPEN64 */
966 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
971 swrap_bind_symbol_libc(openat);
973 if (flags & O_CREAT) {
974 mode = va_arg(ap, int);
976 fd = swrap.libc.symbols._libc_openat.f(dirfd,
985 static int libc_openat(int dirfd, const char *path, int flags, ...)
991 fd = libc_vopenat(dirfd, path, flags, ap);
998 static int libc_pipe(int pipefd[2])
1000 swrap_bind_symbol_libsocket(pipe);
1002 return swrap.libc.symbols._libc_pipe.f(pipefd);
1005 static int libc_read(int fd, void *buf, size_t count)
1007 swrap_bind_symbol_libc(read);
1009 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1012 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1014 swrap_bind_symbol_libsocket(readv);
1016 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1019 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1021 swrap_bind_symbol_libsocket(recv);
1023 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1026 static int libc_recvfrom(int sockfd,
1030 struct sockaddr *src_addr,
1033 swrap_bind_symbol_libsocket(recvfrom);
1035 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1043 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1045 swrap_bind_symbol_libsocket(recvmsg);
1047 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1050 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1052 swrap_bind_symbol_libsocket(send);
1054 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1057 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1059 swrap_bind_symbol_libsocket(sendmsg);
1061 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1064 static int libc_sendto(int sockfd,
1068 const struct sockaddr *dst_addr,
1071 swrap_bind_symbol_libsocket(sendto);
1073 return swrap.libc.symbols._libc_sendto.f(sockfd,
1081 static int libc_setsockopt(int sockfd,
1087 swrap_bind_symbol_libsocket(setsockopt);
1089 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1096 #ifdef HAVE_SIGNALFD
1097 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1099 swrap_bind_symbol_libsocket(signalfd);
1101 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1105 static int libc_socket(int domain, int type, int protocol)
1107 swrap_bind_symbol_libsocket(socket);
1109 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1112 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1114 swrap_bind_symbol_libsocket(socketpair);
1116 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1119 #ifdef HAVE_TIMERFD_CREATE
1120 static int libc_timerfd_create(int clockid, int flags)
1122 swrap_bind_symbol_libc(timerfd_create);
1124 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1128 static ssize_t libc_write(int fd, const void *buf, size_t count)
1130 swrap_bind_symbol_libc(write);
1132 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1135 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1137 swrap_bind_symbol_libsocket(writev);
1139 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1142 /* DO NOT call this function during library initialization! */
1143 static void swrap_bind_symbol_all(void)
1146 swrap_bind_symbol_libsocket(accept4);
1148 swrap_bind_symbol_libsocket(accept);
1150 swrap_bind_symbol_libsocket(bind);
1151 swrap_bind_symbol_libc(close);
1152 swrap_bind_symbol_libsocket(connect);
1153 swrap_bind_symbol_libc(dup);
1154 swrap_bind_symbol_libc(dup2);
1155 swrap_bind_symbol_libc(fcntl);
1156 swrap_bind_symbol_libc(fopen);
1158 swrap_bind_symbol_libc(fopen64);
1161 swrap_bind_symbol_libc(eventfd);
1163 swrap_bind_symbol_libsocket(getpeername);
1164 swrap_bind_symbol_libsocket(getsockname);
1165 swrap_bind_symbol_libsocket(getsockopt);
1166 swrap_bind_symbol_libc(ioctl);
1167 swrap_bind_symbol_libsocket(listen);
1168 swrap_bind_symbol_libc(open);
1170 swrap_bind_symbol_libc(open64);
1172 swrap_bind_symbol_libc(openat);
1173 swrap_bind_symbol_libsocket(pipe);
1174 swrap_bind_symbol_libc(read);
1175 swrap_bind_symbol_libsocket(readv);
1176 swrap_bind_symbol_libsocket(recv);
1177 swrap_bind_symbol_libsocket(recvfrom);
1178 swrap_bind_symbol_libsocket(recvmsg);
1179 swrap_bind_symbol_libsocket(send);
1180 swrap_bind_symbol_libsocket(sendmsg);
1181 swrap_bind_symbol_libsocket(sendto);
1182 swrap_bind_symbol_libsocket(setsockopt);
1183 #ifdef HAVE_SIGNALFD
1184 swrap_bind_symbol_libsocket(signalfd);
1186 swrap_bind_symbol_libsocket(socket);
1187 swrap_bind_symbol_libsocket(socketpair);
1188 #ifdef HAVE_TIMERFD_CREATE
1189 swrap_bind_symbol_libc(timerfd_create);
1191 swrap_bind_symbol_libc(write);
1192 swrap_bind_symbol_libsocket(writev);
1195 /*********************************************************
1196 * SWRAP HELPER FUNCTIONS
1197 *********************************************************/
1200 * We return 127.0.0.0 (default) or 10.53.57.0.
1202 * This can be controlled by:
1203 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1205 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1207 static in_addr_t swrap_ipv4_net(void)
1209 static int initialized;
1210 static in_addr_t hv;
1211 const char *net_str = NULL;
1220 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1221 if (net_str == NULL) {
1222 net_str = "127.0.0.0";
1225 ret = inet_pton(AF_INET, net_str, &nv);
1227 SWRAP_LOG(SWRAP_LOG_ERROR,
1228 "INVALID IPv4 Network [%s]",
1233 hv = ntohl(nv.s_addr);
1243 SWRAP_LOG(SWRAP_LOG_ERROR,
1244 "INVALID IPv4 Network [%s][0x%x] should be "
1245 "127.0.0.0 or 10.53.57.0",
1246 net_str, (unsigned)hv);
1254 * This returns 127.255.255.255 or 10.255.255.255
1256 static in_addr_t swrap_ipv4_bcast(void)
1260 hv = swrap_ipv4_net();
1261 hv |= IN_CLASSA_HOST;
1267 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1269 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1273 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1274 SWRAP_LOG(SWRAP_LOG_ERROR,
1275 "swrap_ipv4_iface(%u) invalid!",
1281 hv = swrap_ipv4_net();
1291 static const struct in6_addr *swrap_ipv6(void)
1293 static struct in6_addr v;
1294 static int initialized;
1302 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1311 static void set_port(int family, int prt, struct swrap_address *addr)
1315 addr->sa.in.sin_port = htons(prt);
1319 addr->sa.in6.sin6_port = htons(prt);
1325 static size_t socket_length(int family)
1329 return sizeof(struct sockaddr_in);
1332 return sizeof(struct sockaddr_in6);
1338 static struct socket_info *swrap_get_socket_info(int si_index)
1340 return (struct socket_info *)(&(sockets[si_index].info));
1343 static int swrap_get_refcount(struct socket_info *si)
1345 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1346 return sic->meta.refcount;
1349 static void swrap_inc_refcount(struct socket_info *si)
1351 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1353 sic->meta.refcount += 1;
1356 static void swrap_dec_refcount(struct socket_info *si)
1358 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1360 sic->meta.refcount -= 1;
1363 static int swrap_get_next_free(struct socket_info *si)
1365 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1367 return sic->meta.next_free;
1370 static void swrap_set_next_free(struct socket_info *si, int next_free)
1372 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1374 sic->meta.next_free = next_free;
1377 static char *socket_wrapper_dir(void)
1379 char *swrap_dir = NULL;
1380 char *s = getenv("SOCKET_WRAPPER_DIR");
1383 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1387 swrap_dir = realpath(s, NULL);
1388 if (swrap_dir == NULL) {
1389 SWRAP_LOG(SWRAP_LOG_ERROR,
1390 "Unable to resolve socket_wrapper dir path: %s",
1395 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1399 static unsigned int socket_wrapper_mtu(void)
1401 static unsigned int max_mtu = 0;
1406 swrap_mutex_lock(&mtu_update_mutex);
1412 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1414 s = getenv("SOCKET_WRAPPER_MTU");
1419 tmp = strtol(s, &endp, 10);
1424 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1430 swrap_mutex_unlock(&mtu_update_mutex);
1434 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1436 pthread_mutexattr_t ma;
1439 ret = pthread_mutexattr_init(&ma);
1444 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1449 ret = pthread_mutex_init(m, &ma);
1452 pthread_mutexattr_destroy(&ma);
1457 static size_t socket_wrapper_max_sockets(void)
1463 if (socket_info_max != 0) {
1464 return socket_info_max;
1467 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1469 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1470 if (s == NULL || s[0] == '\0') {
1474 tmp = strtoul(s, &endp, 10);
1479 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1480 SWRAP_LOG(SWRAP_LOG_ERROR,
1481 "Invalid number of sockets specified, "
1482 "using default (%zu)",
1486 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1487 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1488 SWRAP_LOG(SWRAP_LOG_ERROR,
1489 "Invalid number of sockets specified, "
1490 "using maximum (%zu).",
1494 socket_info_max = tmp;
1497 return socket_info_max;
1500 static void socket_wrapper_init_fds_idx(void)
1505 if (socket_fds_idx != NULL) {
1509 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1511 SWRAP_LOG(SWRAP_LOG_ERROR,
1512 "Failed to allocate socket fds index array: %s",
1517 for (i = 0; i < socket_fds_max; i++) {
1521 socket_fds_idx = tmp;
1524 static void socket_wrapper_init_sockets(void)
1530 swrap_mutex_lock(&sockets_mutex);
1532 if (sockets != NULL) {
1533 swrap_mutex_unlock(&sockets_mutex);
1538 * Intialize the static cache early before
1539 * any thread is able to start.
1541 (void)swrap_ipv4_net();
1543 socket_wrapper_init_fds_idx();
1545 /* Needs to be called inside the sockets_mutex lock here. */
1546 max_sockets = socket_wrapper_max_sockets();
1548 sockets = (struct socket_info_container *)calloc(max_sockets,
1549 sizeof(struct socket_info_container));
1551 if (sockets == NULL) {
1552 SWRAP_LOG(SWRAP_LOG_ERROR,
1553 "Failed to allocate sockets array: %s",
1555 swrap_mutex_unlock(&sockets_mutex);
1559 swrap_mutex_lock(&first_free_mutex);
1563 for (i = 0; i < max_sockets; i++) {
1564 swrap_set_next_free(&sockets[i].info, i+1);
1565 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1567 SWRAP_LOG(SWRAP_LOG_ERROR,
1568 "Failed to initialize pthread mutex");
1573 /* mark the end of the free list */
1574 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1576 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1578 SWRAP_LOG(SWRAP_LOG_ERROR,
1579 "Failed to initialize pthread mutex");
1583 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1585 SWRAP_LOG(SWRAP_LOG_ERROR,
1586 "Failed to initialize pthread mutex");
1590 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1592 SWRAP_LOG(SWRAP_LOG_ERROR,
1593 "Failed to initialize pthread mutex");
1598 swrap_mutex_unlock(&first_free_mutex);
1599 swrap_mutex_unlock(&sockets_mutex);
1605 bool socket_wrapper_enabled(void)
1607 char *s = socket_wrapper_dir();
1615 socket_wrapper_init_sockets();
1620 static unsigned int socket_wrapper_default_iface(void)
1622 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1625 if (sscanf(s, "%u", &iface) == 1) {
1626 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1632 return 1;/* 127.0.0.1 */
1635 static void set_socket_info_index(int fd, int idx)
1637 SWRAP_LOG(SWRAP_LOG_TRACE,
1640 socket_fds_idx[fd] = idx;
1641 /* This builtin issues a full memory barrier. */
1642 __sync_synchronize();
1645 static void reset_socket_info_index(int fd)
1647 SWRAP_LOG(SWRAP_LOG_TRACE,
1650 set_socket_info_index(fd, -1);
1653 static int find_socket_info_index(int fd)
1659 if (socket_fds_idx == NULL) {
1663 if ((size_t)fd >= socket_fds_max) {
1665 * Do not add a log here as some applications do stupid things
1668 * for (fd = 0; fd <= getdtablesize(); fd++) {
1672 * This would produce millions of lines of debug messages.
1675 SWRAP_LOG(SWRAP_LOG_ERROR,
1676 "Looking for a socket info for the fd %d is over the "
1677 "max socket index limit of %zu.",
1684 /* This builtin issues a full memory barrier. */
1685 __sync_synchronize();
1686 return socket_fds_idx[fd];
1689 static int swrap_add_socket_info(struct socket_info *si_input)
1691 struct socket_info *si = NULL;
1694 if (si_input == NULL) {
1699 swrap_mutex_lock(&first_free_mutex);
1700 if (first_free == -1) {
1705 si_index = first_free;
1706 si = swrap_get_socket_info(si_index);
1710 first_free = swrap_get_next_free(si);
1712 swrap_inc_refcount(si);
1714 SWRAP_UNLOCK_SI(si);
1717 swrap_mutex_unlock(&first_free_mutex);
1722 static int swrap_create_socket(struct socket_info *si, int fd)
1726 if ((size_t)fd >= socket_fds_max) {
1727 SWRAP_LOG(SWRAP_LOG_ERROR,
1728 "The max socket index limit of %zu has been reached, "
1735 idx = swrap_add_socket_info(si);
1740 set_socket_info_index(fd, idx);
1745 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1752 p = strrchr(un->sun_path, '/');
1753 if (p) p++; else p = un->sun_path;
1755 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1760 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1763 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1774 case SOCKET_TYPE_CHAR_TCP:
1775 case SOCKET_TYPE_CHAR_UDP: {
1776 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1778 if ((*len) < sizeof(*in2)) {
1783 memset(in2, 0, sizeof(*in2));
1784 in2->sin_family = AF_INET;
1785 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1786 in2->sin_port = htons(prt);
1788 *len = sizeof(*in2);
1792 case SOCKET_TYPE_CHAR_TCP_V6:
1793 case SOCKET_TYPE_CHAR_UDP_V6: {
1794 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1796 if ((*len) < sizeof(*in2)) {
1801 memset(in2, 0, sizeof(*in2));
1802 in2->sin6_family = AF_INET6;
1803 in2->sin6_addr = *swrap_ipv6();
1804 in2->sin6_addr.s6_addr[15] = iface;
1805 in2->sin6_port = htons(prt);
1807 *len = sizeof(*in2);
1819 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1826 char *swrap_dir = NULL;
1828 if (bcast) *bcast = 0;
1830 switch (inaddr->sa_family) {
1832 const struct sockaddr_in *in =
1833 (const struct sockaddr_in *)(const void *)inaddr;
1834 unsigned int addr = ntohl(in->sin_addr.s_addr);
1838 const unsigned int sw_net_addr = swrap_ipv4_net();
1839 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1843 u_type = SOCKET_TYPE_CHAR_TCP;
1846 u_type = SOCKET_TYPE_CHAR_UDP;
1847 a_type = SOCKET_TYPE_CHAR_UDP;
1848 b_type = SOCKET_TYPE_CHAR_UDP;
1851 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1852 errno = ESOCKTNOSUPPORT;
1856 prt = ntohs(in->sin_port);
1857 if (a_type && addr == 0xFFFFFFFF) {
1858 /* 255.255.255.255 only udp */
1861 iface = socket_wrapper_default_iface();
1862 } else if (b_type && addr == sw_bcast_addr) {
1871 iface = socket_wrapper_default_iface();
1872 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
1873 /* 127.0.0.X or 10.53.57.X */
1876 iface = (addr & 0x000000FF);
1878 errno = ENETUNREACH;
1881 if (bcast) *bcast = is_bcast;
1886 const struct sockaddr_in6 *in =
1887 (const struct sockaddr_in6 *)(const void *)inaddr;
1888 struct in6_addr cmp1, cmp2;
1892 type = SOCKET_TYPE_CHAR_TCP_V6;
1895 type = SOCKET_TYPE_CHAR_UDP_V6;
1898 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1899 errno = ESOCKTNOSUPPORT;
1903 /* XXX no multicast/broadcast */
1905 prt = ntohs(in->sin6_port);
1907 cmp1 = *swrap_ipv6();
1908 cmp2 = in->sin6_addr;
1909 cmp2.s6_addr[15] = 0;
1910 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1911 iface = in->sin6_addr.s6_addr[15];
1913 errno = ENETUNREACH;
1921 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
1922 errno = ENETUNREACH;
1927 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
1932 swrap_dir = socket_wrapper_dir();
1933 if (swrap_dir == NULL) {
1939 snprintf(un->sun_path, sizeof(un->sun_path),
1940 "%s/EINVAL", swrap_dir);
1941 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1942 SAFE_FREE(swrap_dir);
1943 /* the caller need to do more processing */
1947 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1948 swrap_dir, type, iface, prt);
1949 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1951 SAFE_FREE(swrap_dir);
1956 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1964 char *swrap_dir = NULL;
1966 if (bcast) *bcast = 0;
1968 switch (si->family) {
1970 const struct sockaddr_in *in =
1971 (const struct sockaddr_in *)(const void *)inaddr;
1972 unsigned int addr = ntohl(in->sin_addr.s_addr);
1977 const unsigned int sw_net_addr = swrap_ipv4_net();
1978 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1980 prt = ntohs(in->sin_port);
1984 u_type = SOCKET_TYPE_CHAR_TCP;
1985 d_type = SOCKET_TYPE_CHAR_TCP;
1988 u_type = SOCKET_TYPE_CHAR_UDP;
1989 d_type = SOCKET_TYPE_CHAR_UDP;
1990 a_type = SOCKET_TYPE_CHAR_UDP;
1991 b_type = SOCKET_TYPE_CHAR_UDP;
1994 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1995 errno = ESOCKTNOSUPPORT;
2003 iface = socket_wrapper_default_iface();
2004 } else if (a_type && addr == 0xFFFFFFFF) {
2005 /* 255.255.255.255 only udp */
2008 iface = socket_wrapper_default_iface();
2009 } else if (b_type && addr == sw_bcast_addr) {
2010 /* 127.255.255.255 only udp */
2013 iface = socket_wrapper_default_iface();
2014 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2018 iface = (addr & 0x000000FF);
2020 errno = EADDRNOTAVAIL;
2024 /* Store the bind address for connect() */
2025 if (si->bindname.sa_socklen == 0) {
2026 struct sockaddr_in bind_in;
2027 socklen_t blen = sizeof(struct sockaddr_in);
2029 ZERO_STRUCT(bind_in);
2030 bind_in.sin_family = in->sin_family;
2031 bind_in.sin_port = in->sin_port;
2032 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2033 si->bindname.sa_socklen = blen;
2034 memcpy(&si->bindname.sa.in, &bind_in, blen);
2041 const struct sockaddr_in6 *in =
2042 (const struct sockaddr_in6 *)(const void *)inaddr;
2043 struct in6_addr cmp1, cmp2;
2047 type = SOCKET_TYPE_CHAR_TCP_V6;
2050 type = SOCKET_TYPE_CHAR_UDP_V6;
2053 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2054 errno = ESOCKTNOSUPPORT;
2058 /* XXX no multicast/broadcast */
2060 prt = ntohs(in->sin6_port);
2062 cmp1 = *swrap_ipv6();
2063 cmp2 = in->sin6_addr;
2064 cmp2.s6_addr[15] = 0;
2065 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2066 iface = socket_wrapper_default_iface();
2067 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2068 iface = in->sin6_addr.s6_addr[15];
2070 errno = EADDRNOTAVAIL;
2074 /* Store the bind address for connect() */
2075 if (si->bindname.sa_socklen == 0) {
2076 struct sockaddr_in6 bind_in;
2077 socklen_t blen = sizeof(struct sockaddr_in6);
2079 ZERO_STRUCT(bind_in);
2080 bind_in.sin6_family = in->sin6_family;
2081 bind_in.sin6_port = in->sin6_port;
2083 bind_in.sin6_addr = *swrap_ipv6();
2084 bind_in.sin6_addr.s6_addr[15] = iface;
2086 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2087 si->bindname.sa_socklen = blen;
2094 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2095 errno = EADDRNOTAVAIL;
2100 if (bcast) *bcast = is_bcast;
2102 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2107 swrap_dir = socket_wrapper_dir();
2108 if (swrap_dir == NULL) {
2114 /* handle auto-allocation of ephemeral ports */
2115 for (prt = 5001; prt < 10000; prt++) {
2116 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
2117 swrap_dir, type, iface, prt);
2118 if (stat(un->sun_path, &st) == 0) continue;
2120 set_port(si->family, prt, &si->myname);
2121 set_port(si->family, prt, &si->bindname);
2128 SAFE_FREE(swrap_dir);
2133 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
2134 swrap_dir, type, iface, prt);
2135 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2137 SAFE_FREE(swrap_dir);
2142 static struct socket_info *find_socket_info(int fd)
2144 int idx = find_socket_info_index(fd);
2150 return swrap_get_socket_info(idx);
2154 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2156 struct socket_info_fd *f;
2157 const struct socket_info *last_s = NULL;
2159 /* first catch invalid input */
2160 switch (sa->sa_family) {
2162 if (len < sizeof(struct sockaddr_in)) {
2168 if (len < sizeof(struct sockaddr_in6)) {
2178 for (f = socket_fds; f; f = f->next) {
2179 struct socket_info *s = swrap_get_socket_info(f->si_index);
2186 if (s->myname == NULL) {
2189 if (s->myname->sa_family != sa->sa_family) {
2192 switch (s->myname->sa_family) {
2194 struct sockaddr_in *sin1, *sin2;
2196 sin1 = (struct sockaddr_in *)s->myname;
2197 sin2 = (struct sockaddr_in *)sa;
2199 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2202 if (sin1->sin_port != sin2->sin_port) {
2205 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2215 struct sockaddr_in6 *sin1, *sin2;
2217 sin1 = (struct sockaddr_in6 *)s->myname;
2218 sin2 = (struct sockaddr_in6 *)sa;
2220 if (sin1->sin6_port != sin2->sin6_port) {
2223 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2245 static void swrap_remove_stale(int fd)
2247 struct socket_info *si;
2250 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2252 swrap_mutex_lock(&socket_reset_mutex);
2254 si_index = find_socket_info_index(fd);
2255 if (si_index == -1) {
2256 swrap_mutex_unlock(&socket_reset_mutex);
2260 reset_socket_info_index(fd);
2262 si = swrap_get_socket_info(si_index);
2264 swrap_mutex_lock(&first_free_mutex);
2267 swrap_dec_refcount(si);
2269 if (swrap_get_refcount(si) > 0) {
2273 if (si->un_addr.sun_path[0] != '\0') {
2274 unlink(si->un_addr.sun_path);
2277 swrap_set_next_free(si, first_free);
2278 first_free = si_index;
2281 SWRAP_UNLOCK_SI(si);
2282 swrap_mutex_unlock(&first_free_mutex);
2283 swrap_mutex_unlock(&socket_reset_mutex);
2286 static int sockaddr_convert_to_un(struct socket_info *si,
2287 const struct sockaddr *in_addr,
2289 struct sockaddr_un *out_addr,
2293 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2295 (void) in_len; /* unused */
2297 if (out_addr == NULL) {
2301 out->sa_family = AF_UNIX;
2302 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2303 out->sa_len = sizeof(*out_addr);
2306 switch (in_addr->sa_family) {
2308 const struct sockaddr_in *sin;
2309 if (si->family != AF_INET) {
2312 if (in_len < sizeof(struct sockaddr_in)) {
2315 sin = (const struct sockaddr_in *)(const void *)in_addr;
2316 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2321 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2322 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2336 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2337 errno = ESOCKTNOSUPPORT;
2341 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2343 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2349 errno = EAFNOSUPPORT;
2350 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2354 static int sockaddr_convert_from_un(const struct socket_info *si,
2355 const struct sockaddr_un *in_addr,
2356 socklen_t un_addrlen,
2358 struct sockaddr *out_addr,
2359 socklen_t *out_addrlen)
2363 if (out_addr == NULL || out_addrlen == NULL)
2366 if (un_addrlen == 0) {
2381 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2382 errno = ESOCKTNOSUPPORT;
2385 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2386 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2387 out_addr->sa_len = *out_addrlen;
2394 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2395 errno = EAFNOSUPPORT;
2399 enum swrap_packet_type {
2401 SWRAP_CONNECT_UNREACH,
2409 SWRAP_SENDTO_UNREACH,
2420 struct swrap_file_hdr {
2422 uint16_t version_major;
2423 uint16_t version_minor;
2426 uint32_t frame_max_len;
2427 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2430 #define SWRAP_FILE_HDR_SIZE 24
2432 struct swrap_packet_frame {
2434 uint32_t micro_seconds;
2435 uint32_t recorded_length;
2436 uint32_t full_length;
2438 #define SWRAP_PACKET_FRAME_SIZE 16
2440 union swrap_packet_ip {
2444 uint16_t packet_length;
2445 uint16_t identification;
2450 uint16_t hdr_checksum;
2454 #define SWRAP_PACKET_IP_V4_SIZE 20
2457 uint8_t flow_label_high;
2458 uint16_t flow_label_low;
2459 uint16_t payload_length;
2460 uint8_t next_header;
2462 uint8_t src_addr[16];
2463 uint8_t dest_addr[16];
2465 #define SWRAP_PACKET_IP_V6_SIZE 40
2467 #define SWRAP_PACKET_IP_SIZE 40
2469 union swrap_packet_payload {
2471 uint16_t source_port;
2481 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2483 uint16_t source_port;
2488 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2495 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2502 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2504 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2506 #define SWRAP_PACKET_MIN_ALLOC \
2507 (SWRAP_PACKET_FRAME_SIZE + \
2508 SWRAP_PACKET_IP_SIZE + \
2509 SWRAP_PACKET_PAYLOAD_SIZE)
2511 static const char *swrap_pcap_init_file(void)
2513 static int initialized = 0;
2514 static const char *s = NULL;
2515 static const struct swrap_file_hdr h;
2516 static const struct swrap_packet_frame f;
2517 static const union swrap_packet_ip i;
2518 static const union swrap_packet_payload p;
2520 if (initialized == 1) {
2526 * TODO: don't use the structs use plain buffer offsets
2527 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2529 * for now make sure we disable PCAP support
2530 * if the struct has alignment!
2532 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2535 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2538 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2541 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2544 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2547 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2550 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2553 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2556 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2559 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2563 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2567 if (strncmp(s, "./", 2) == 0) {
2570 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2574 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2575 const struct sockaddr *src,
2576 const struct sockaddr *dest,
2578 const uint8_t *payload,
2580 unsigned long tcp_seqno,
2581 unsigned long tcp_ack,
2582 unsigned char tcp_ctl,
2584 size_t *_packet_len)
2586 uint8_t *base = NULL;
2587 uint8_t *buf = NULL;
2590 struct swrap_packet_frame *frame;
2594 union swrap_packet_ip *ip;
2596 union swrap_packet_payload *pay;
2599 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2600 size_t wire_hdr_len = 0;
2601 size_t wire_len = 0;
2602 size_t ip_hdr_len = 0;
2603 size_t icmp_hdr_len = 0;
2604 size_t icmp_truncate_len = 0;
2605 uint8_t protocol = 0, icmp_protocol = 0;
2606 const struct sockaddr_in *src_in = NULL;
2607 const struct sockaddr_in *dest_in = NULL;
2609 const struct sockaddr_in6 *src_in6 = NULL;
2610 const struct sockaddr_in6 *dest_in6 = NULL;
2615 switch (src->sa_family) {
2617 src_in = (const struct sockaddr_in *)(const void *)src;
2618 dest_in = (const struct sockaddr_in *)(const void *)dest;
2619 src_port = src_in->sin_port;
2620 dest_port = dest_in->sin_port;
2621 ip_hdr_len = sizeof(i.ip->v4);
2625 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2626 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2627 src_port = src_in6->sin6_port;
2628 dest_port = dest_in6->sin6_port;
2629 ip_hdr_len = sizeof(i.ip->v6);
2636 switch (socket_type) {
2638 protocol = 0x06; /* TCP */
2639 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2640 wire_len = wire_hdr_len + payload_len;
2644 protocol = 0x11; /* UDP */
2645 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2646 wire_len = wire_hdr_len + payload_len;
2654 icmp_protocol = protocol;
2655 switch (src->sa_family) {
2657 protocol = 0x01; /* ICMPv4 */
2658 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2662 protocol = 0x3A; /* ICMPv6 */
2663 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2667 if (wire_len > 64 ) {
2668 icmp_truncate_len = wire_len - 64;
2670 wire_len += icmp_hdr_len;
2673 packet_len = nonwire_len + wire_len;
2674 alloc_len = packet_len;
2675 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2676 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2679 base = (uint8_t *)calloc(1, alloc_len);
2687 f.frame->seconds = tval->tv_sec;
2688 f.frame->micro_seconds = tval->tv_usec;
2689 f.frame->recorded_length = wire_len - icmp_truncate_len;
2690 f.frame->full_length = wire_len - icmp_truncate_len;
2692 buf += SWRAP_PACKET_FRAME_SIZE;
2695 switch (src->sa_family) {
2697 if (src_in == NULL || dest_in == NULL) {
2702 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2703 i.ip->v4.tos = 0x00;
2704 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2705 i.ip->v4.identification = htons(0xFFFF);
2706 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2707 i.ip->v4.fragment = htons(0x0000);
2708 i.ip->v4.ttl = 0xFF;
2709 i.ip->v4.protocol = protocol;
2710 i.ip->v4.hdr_checksum = htons(0x0000);
2711 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2712 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2713 buf += SWRAP_PACKET_IP_V4_SIZE;
2717 if (src_in6 == NULL || dest_in6 == NULL) {
2722 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2723 i.ip->v6.flow_label_high = 0x00;
2724 i.ip->v6.flow_label_low = 0x0000;
2725 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2726 i.ip->v6.next_header = protocol;
2727 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2728 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2729 buf += SWRAP_PACKET_IP_V6_SIZE;
2735 pay = (union swrap_packet_payload *)(void *)buf;
2736 switch (src->sa_family) {
2738 pay->icmp4.type = 0x03; /* destination unreachable */
2739 pay->icmp4.code = 0x01; /* host unreachable */
2740 pay->icmp4.checksum = htons(0x0000);
2741 pay->icmp4.unused = htonl(0x00000000);
2743 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2745 /* set the ip header in the ICMP payload */
2747 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2748 i.ip->v4.tos = 0x00;
2749 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2750 i.ip->v4.identification = htons(0xFFFF);
2751 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2752 i.ip->v4.fragment = htons(0x0000);
2753 i.ip->v4.ttl = 0xFF;
2754 i.ip->v4.protocol = icmp_protocol;
2755 i.ip->v4.hdr_checksum = htons(0x0000);
2756 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2757 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2759 buf += SWRAP_PACKET_IP_V4_SIZE;
2761 src_port = dest_in->sin_port;
2762 dest_port = src_in->sin_port;
2766 pay->icmp6.type = 0x01; /* destination unreachable */
2767 pay->icmp6.code = 0x03; /* address unreachable */
2768 pay->icmp6.checksum = htons(0x0000);
2769 pay->icmp6.unused = htonl(0x00000000);
2770 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2772 /* set the ip header in the ICMP payload */
2774 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2775 i.ip->v6.flow_label_high = 0x00;
2776 i.ip->v6.flow_label_low = 0x0000;
2777 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2778 i.ip->v6.next_header = protocol;
2779 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2780 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2782 buf += SWRAP_PACKET_IP_V6_SIZE;
2784 src_port = dest_in6->sin6_port;
2785 dest_port = src_in6->sin6_port;
2791 pay = (union swrap_packet_payload *)(void *)buf;
2793 switch (socket_type) {
2795 pay->tcp.source_port = src_port;
2796 pay->tcp.dest_port = dest_port;
2797 pay->tcp.seq_num = htonl(tcp_seqno);
2798 pay->tcp.ack_num = htonl(tcp_ack);
2799 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2800 pay->tcp.control = tcp_ctl;
2801 pay->tcp.window = htons(0x7FFF);
2802 pay->tcp.checksum = htons(0x0000);
2803 pay->tcp.urg = htons(0x0000);
2804 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2809 pay->udp.source_port = src_port;
2810 pay->udp.dest_port = dest_port;
2811 pay->udp.length = htons(8 + payload_len);
2812 pay->udp.checksum = htons(0x0000);
2813 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2818 if (payload && payload_len > 0) {
2819 memcpy(buf, payload, payload_len);
2822 *_packet_len = packet_len - icmp_truncate_len;
2826 static int swrap_pcap_get_fd(const char *fname)
2834 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2836 struct swrap_file_hdr file_hdr;
2837 file_hdr.magic = 0xA1B2C3D4;
2838 file_hdr.version_major = 0x0002;
2839 file_hdr.version_minor = 0x0004;
2840 file_hdr.timezone = 0x00000000;
2841 file_hdr.sigfigs = 0x00000000;
2842 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2843 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2845 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2852 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2857 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2858 const struct sockaddr *addr,
2859 enum swrap_packet_type type,
2860 const void *buf, size_t len,
2863 const struct sockaddr *src_addr;
2864 const struct sockaddr *dest_addr;
2865 unsigned long tcp_seqno = 0;
2866 unsigned long tcp_ack = 0;
2867 unsigned char tcp_ctl = 0;
2868 int unreachable = 0;
2872 switch (si->family) {
2884 case SWRAP_CONNECT_SEND:
2885 if (si->type != SOCK_STREAM) {
2889 src_addr = &si->myname.sa.s;
2892 tcp_seqno = si->io.pck_snd;
2893 tcp_ack = si->io.pck_rcv;
2894 tcp_ctl = 0x02; /* SYN */
2896 si->io.pck_snd += 1;
2900 case SWRAP_CONNECT_RECV:
2901 if (si->type != SOCK_STREAM) {
2905 dest_addr = &si->myname.sa.s;
2908 tcp_seqno = si->io.pck_rcv;
2909 tcp_ack = si->io.pck_snd;
2910 tcp_ctl = 0x12; /** SYN,ACK */
2912 si->io.pck_rcv += 1;
2916 case SWRAP_CONNECT_UNREACH:
2917 if (si->type != SOCK_STREAM) {
2921 dest_addr = &si->myname.sa.s;
2924 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2925 tcp_seqno = si->io.pck_snd - 1;
2926 tcp_ack = si->io.pck_rcv;
2927 tcp_ctl = 0x02; /* SYN */
2932 case SWRAP_CONNECT_ACK:
2933 if (si->type != SOCK_STREAM) {
2937 src_addr = &si->myname.sa.s;
2940 tcp_seqno = si->io.pck_snd;
2941 tcp_ack = si->io.pck_rcv;
2942 tcp_ctl = 0x10; /* ACK */
2946 case SWRAP_ACCEPT_SEND:
2947 if (si->type != SOCK_STREAM) {
2951 dest_addr = &si->myname.sa.s;
2954 tcp_seqno = si->io.pck_rcv;
2955 tcp_ack = si->io.pck_snd;
2956 tcp_ctl = 0x02; /* SYN */
2958 si->io.pck_rcv += 1;
2962 case SWRAP_ACCEPT_RECV:
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 = 0x12; /* SYN,ACK */
2974 si->io.pck_snd += 1;
2978 case SWRAP_ACCEPT_ACK:
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 = 0x10; /* ACK */
2993 src_addr = &si->myname.sa.s;
2994 dest_addr = &si->peername.sa.s;
2996 tcp_seqno = si->io.pck_snd;
2997 tcp_ack = si->io.pck_rcv;
2998 tcp_ctl = 0x18; /* PSH,ACK */
3000 si->io.pck_snd += len;
3004 case SWRAP_SEND_RST:
3005 dest_addr = &si->myname.sa.s;
3006 src_addr = &si->peername.sa.s;
3008 if (si->type == SOCK_DGRAM) {
3009 return swrap_pcap_marshall_packet(si,
3011 SWRAP_SENDTO_UNREACH,
3017 tcp_seqno = si->io.pck_rcv;
3018 tcp_ack = si->io.pck_snd;
3019 tcp_ctl = 0x14; /** RST,ACK */
3023 case SWRAP_PENDING_RST:
3024 dest_addr = &si->myname.sa.s;
3025 src_addr = &si->peername.sa.s;
3027 if (si->type == SOCK_DGRAM) {
3031 tcp_seqno = si->io.pck_rcv;
3032 tcp_ack = si->io.pck_snd;
3033 tcp_ctl = 0x14; /* RST,ACK */
3038 dest_addr = &si->myname.sa.s;
3039 src_addr = &si->peername.sa.s;
3041 tcp_seqno = si->io.pck_rcv;
3042 tcp_ack = si->io.pck_snd;
3043 tcp_ctl = 0x18; /* PSH,ACK */
3045 si->io.pck_rcv += len;
3049 case SWRAP_RECV_RST:
3050 dest_addr = &si->myname.sa.s;
3051 src_addr = &si->peername.sa.s;
3053 if (si->type == SOCK_DGRAM) {
3057 tcp_seqno = si->io.pck_rcv;
3058 tcp_ack = si->io.pck_snd;
3059 tcp_ctl = 0x14; /* RST,ACK */
3064 src_addr = &si->myname.sa.s;
3067 si->io.pck_snd += len;
3071 case SWRAP_SENDTO_UNREACH:
3072 dest_addr = &si->myname.sa.s;
3079 case SWRAP_RECVFROM:
3080 dest_addr = &si->myname.sa.s;
3083 si->io.pck_rcv += len;
3087 case SWRAP_CLOSE_SEND:
3088 if (si->type != SOCK_STREAM) {
3092 src_addr = &si->myname.sa.s;
3093 dest_addr = &si->peername.sa.s;
3095 tcp_seqno = si->io.pck_snd;
3096 tcp_ack = si->io.pck_rcv;
3097 tcp_ctl = 0x11; /* FIN, ACK */
3099 si->io.pck_snd += 1;
3103 case SWRAP_CLOSE_RECV:
3104 if (si->type != SOCK_STREAM) {
3108 dest_addr = &si->myname.sa.s;
3109 src_addr = &si->peername.sa.s;
3111 tcp_seqno = si->io.pck_rcv;
3112 tcp_ack = si->io.pck_snd;
3113 tcp_ctl = 0x11; /* FIN,ACK */
3115 si->io.pck_rcv += 1;
3119 case SWRAP_CLOSE_ACK:
3120 if (si->type != SOCK_STREAM) {
3124 src_addr = &si->myname.sa.s;
3125 dest_addr = &si->peername.sa.s;
3127 tcp_seqno = si->io.pck_snd;
3128 tcp_ack = si->io.pck_rcv;
3129 tcp_ctl = 0x10; /* ACK */
3136 swrapGetTimeOfDay(&tv);
3138 return swrap_pcap_packet_init(&tv,
3142 (const uint8_t *)buf,
3151 static void swrap_pcap_dump_packet(struct socket_info *si,
3152 const struct sockaddr *addr,
3153 enum swrap_packet_type type,
3154 const void *buf, size_t len)
3156 const char *file_name;
3158 size_t packet_len = 0;
3161 swrap_mutex_lock(&pcap_dump_mutex);
3163 file_name = swrap_pcap_init_file();
3168 packet = swrap_pcap_marshall_packet(si,
3174 if (packet == NULL) {
3178 fd = swrap_pcap_get_fd(file_name);
3180 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3189 swrap_mutex_unlock(&pcap_dump_mutex);
3192 /****************************************************************************
3194 ***************************************************************************/
3196 #ifdef HAVE_SIGNALFD
3197 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3201 rc = libc_signalfd(fd, mask, flags);
3203 swrap_remove_stale(fd);
3209 int signalfd(int fd, const sigset_t *mask, int flags)
3211 return swrap_signalfd(fd, mask, flags);
3215 /****************************************************************************
3217 ***************************************************************************/
3219 static int swrap_socket(int family, int type, int protocol)
3221 struct socket_info *si = NULL;
3222 struct socket_info _si = { 0 };
3225 int real_type = type;
3228 * Remove possible addition flags passed to socket() so
3229 * do not fail checking the type.
3230 * See https://lwn.net/Articles/281965/
3233 real_type &= ~SOCK_CLOEXEC;
3235 #ifdef SOCK_NONBLOCK
3236 real_type &= ~SOCK_NONBLOCK;
3239 if (!socket_wrapper_enabled()) {
3240 return libc_socket(family, type, protocol);
3251 #endif /* AF_NETLINK */
3254 #endif /* AF_PACKET */
3256 fd = libc_socket(family, type, protocol);
3258 /* Check if we have a stale fd and remove it */
3259 swrap_remove_stale(fd);
3260 SWRAP_LOG(SWRAP_LOG_TRACE,
3261 "Unix socket fd=%d",
3266 errno = EAFNOSUPPORT;
3270 switch (real_type) {
3276 errno = EPROTONOSUPPORT;
3284 if (real_type == SOCK_STREAM) {
3289 if (real_type == SOCK_DGRAM) {
3294 errno = EPROTONOSUPPORT;
3299 * We must call libc_socket with type, from the caller, not the version
3300 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3302 fd = libc_socket(AF_UNIX, type, 0);
3308 /* Check if we have a stale fd and remove it */
3309 swrap_remove_stale(fd);
3312 si->family = family;
3314 /* however, the rest of the socket_wrapper code expects just
3315 * the type, not the flags */
3316 si->type = real_type;
3317 si->protocol = protocol;
3320 * Setup myname so getsockname() can succeed to find out the socket
3323 switch(si->family) {
3325 struct sockaddr_in sin = {
3326 .sin_family = AF_INET,
3329 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3330 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3335 struct sockaddr_in6 sin6 = {
3336 .sin6_family = AF_INET6,
3339 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3340 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3349 ret = swrap_create_socket(si, fd);
3354 SWRAP_LOG(SWRAP_LOG_TRACE,
3355 "Created %s socket for protocol %s, fd=%d",
3356 family == AF_INET ? "IPv4" : "IPv6",
3357 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3363 int socket(int family, int type, int protocol)
3365 return swrap_socket(family, type, protocol);
3368 /****************************************************************************
3370 ***************************************************************************/
3372 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3376 rc = libc_socketpair(family, type, protocol, sv);
3378 swrap_remove_stale(sv[0]);
3379 swrap_remove_stale(sv[1]);
3385 int socketpair(int family, int type, int protocol, int sv[2])
3387 return swrap_socketpair(family, type, protocol, sv);
3390 /****************************************************************************
3392 ***************************************************************************/
3394 #ifdef HAVE_TIMERFD_CREATE
3395 static int swrap_timerfd_create(int clockid, int flags)
3399 fd = libc_timerfd_create(clockid, flags);
3401 swrap_remove_stale(fd);
3407 int timerfd_create(int clockid, int flags)
3409 return swrap_timerfd_create(clockid, flags);
3413 /****************************************************************************
3415 ***************************************************************************/
3417 static int swrap_pipe(int pipefd[2])
3421 rc = libc_pipe(pipefd);
3423 swrap_remove_stale(pipefd[0]);
3424 swrap_remove_stale(pipefd[1]);
3430 int pipe(int pipefd[2])
3432 return swrap_pipe(pipefd);
3435 /****************************************************************************
3437 ***************************************************************************/
3439 static int swrap_accept(int s,
3440 struct sockaddr *addr,
3444 struct socket_info *parent_si, *child_si;
3445 struct socket_info new_si = { 0 };
3448 struct swrap_address un_addr = {
3449 .sa_socklen = sizeof(struct sockaddr_un),
3451 struct swrap_address un_my_addr = {
3452 .sa_socklen = sizeof(struct sockaddr_un),
3454 struct swrap_address in_addr = {
3455 .sa_socklen = sizeof(struct sockaddr_storage),
3457 struct swrap_address in_my_addr = {
3458 .sa_socklen = sizeof(struct sockaddr_storage),
3462 parent_si = find_socket_info(s);
3465 return libc_accept4(s, addr, addrlen, flags);
3468 return libc_accept(s, addr, addrlen);
3474 * prevent parent_si from being altered / closed
3477 SWRAP_LOCK_SI(parent_si);
3480 * assume out sockaddr have the same size as the in parent
3483 in_addr.sa_socklen = socket_length(parent_si->family);
3484 if (in_addr.sa_socklen <= 0) {
3485 SWRAP_UNLOCK_SI(parent_si);
3490 SWRAP_UNLOCK_SI(parent_si);
3493 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3496 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3499 if (errno == ENOTSOCK) {
3500 /* Remove stale fds */
3501 swrap_remove_stale(s);
3508 /* Check if we have a stale fd and remove it */
3509 swrap_remove_stale(fd);
3511 SWRAP_LOCK_SI(parent_si);
3513 ret = sockaddr_convert_from_un(parent_si,
3518 &in_addr.sa_socklen);
3520 SWRAP_UNLOCK_SI(parent_si);
3527 child_si->family = parent_si->family;
3528 child_si->type = parent_si->type;
3529 child_si->protocol = parent_si->protocol;
3530 child_si->bound = 1;
3531 child_si->is_server = 1;
3532 child_si->connected = 1;
3534 SWRAP_UNLOCK_SI(parent_si);
3536 child_si->peername = (struct swrap_address) {
3537 .sa_socklen = in_addr.sa_socklen,
3539 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3541 if (addr != NULL && addrlen != NULL) {
3542 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3544 memcpy(addr, &in_addr.sa.ss, copy_len);
3546 *addrlen = in_addr.sa_socklen;
3549 ret = libc_getsockname(fd,
3551 &un_my_addr.sa_socklen);
3557 ret = sockaddr_convert_from_un(child_si,
3559 un_my_addr.sa_socklen,
3562 &in_my_addr.sa_socklen);
3568 SWRAP_LOG(SWRAP_LOG_TRACE,
3569 "accept() path=%s, fd=%d",
3570 un_my_addr.sa.un.sun_path, s);
3572 child_si->myname = (struct swrap_address) {
3573 .sa_socklen = in_my_addr.sa_socklen,
3575 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3577 idx = swrap_create_socket(&new_si, fd);
3584 struct socket_info *si = swrap_get_socket_info(idx);
3587 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3588 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3589 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3590 SWRAP_UNLOCK_SI(si);
3597 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3599 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3603 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3604 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3606 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3609 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3612 static int autobind_start_init;
3613 static int autobind_start;
3615 /* using sendto() or connect() on an unbound socket would give the
3616 recipient no way to reply, as unlike UDP and TCP, a unix domain
3617 socket can't auto-assign ephemeral port numbers, so we need to
3619 Note: this might change the family from ipv6 to ipv4
3621 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3623 struct swrap_address un_addr = {
3624 .sa_socklen = sizeof(struct sockaddr_un),
3631 char *swrap_dir = NULL;
3633 swrap_mutex_lock(&autobind_start_mutex);
3635 if (autobind_start_init != 1) {
3636 autobind_start_init = 1;
3637 autobind_start = getpid();
3638 autobind_start %= 50000;
3639 autobind_start += 10000;
3642 un_addr.sa.un.sun_family = AF_UNIX;
3646 struct sockaddr_in in;
3650 type = SOCKET_TYPE_CHAR_TCP;
3653 type = SOCKET_TYPE_CHAR_UDP;
3656 errno = ESOCKTNOSUPPORT;
3661 memset(&in, 0, sizeof(in));
3662 in.sin_family = AF_INET;
3663 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3664 socket_wrapper_default_iface()));
3666 si->myname = (struct swrap_address) {
3667 .sa_socklen = sizeof(in),
3669 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3674 struct sockaddr_in6 in6;
3676 if (si->family != family) {
3677 errno = ENETUNREACH;
3684 type = SOCKET_TYPE_CHAR_TCP_V6;
3687 type = SOCKET_TYPE_CHAR_UDP_V6;
3690 errno = ESOCKTNOSUPPORT;
3695 memset(&in6, 0, sizeof(in6));
3696 in6.sin6_family = AF_INET6;
3697 in6.sin6_addr = *swrap_ipv6();
3698 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3700 si->myname = (struct swrap_address) {
3701 .sa_socklen = sizeof(in6),
3703 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3708 errno = ESOCKTNOSUPPORT;
3713 if (autobind_start > 60000) {
3714 autobind_start = 10000;
3717 swrap_dir = socket_wrapper_dir();
3718 if (swrap_dir == NULL) {
3724 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3725 port = autobind_start + i;
3726 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3727 "%s/"SOCKET_FORMAT, swrap_dir, type,
3728 socket_wrapper_default_iface(), port);
3729 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3731 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3736 si->un_addr = un_addr.sa.un;
3739 autobind_start = port + 1;
3742 if (i == SOCKET_MAX_SOCKETS) {
3743 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3744 "interface "SOCKET_FORMAT,
3747 socket_wrapper_default_iface(),
3754 si->family = family;
3755 set_port(si->family, port, &si->myname);
3760 SAFE_FREE(swrap_dir);
3761 swrap_mutex_unlock(&autobind_start_mutex);
3765 /****************************************************************************
3767 ***************************************************************************/
3769 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3773 struct swrap_address un_addr = {
3774 .sa_socklen = sizeof(struct sockaddr_un),
3776 struct socket_info *si = find_socket_info(s);
3780 return libc_connect(s, serv_addr, addrlen);
3785 if (si->bound == 0) {
3786 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3792 if (si->family != serv_addr->sa_family) {
3793 SWRAP_LOG(SWRAP_LOG_ERROR,
3794 "called for fd=%d (family=%d) called with invalid family=%d",
3795 s, si->family, serv_addr->sa_family);
3801 ret = sockaddr_convert_to_un(si, serv_addr,
3802 addrlen, &un_addr.sa.un, 0, &bcast);
3808 errno = ENETUNREACH;
3813 if (si->type == SOCK_DGRAM) {
3814 si->defer_connect = 1;
3817 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3819 ret = libc_connect(s,
3821 un_addr.sa_socklen);
3824 SWRAP_LOG(SWRAP_LOG_TRACE,
3825 "connect() path=%s, fd=%d",
3826 un_addr.sa.un.sun_path, s);
3829 /* to give better errors */
3830 if (ret == -1 && errno == ENOENT) {
3831 errno = EHOSTUNREACH;
3835 si->peername = (struct swrap_address) {
3836 .sa_socklen = addrlen,
3839 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3843 * When we connect() on a socket than we have to bind the
3844 * outgoing connection on the interface we use for the
3845 * transport. We already bound it on the right interface
3846 * but here we have to update the name so getsockname()
3847 * returns correct information.
3849 if (si->bindname.sa_socklen > 0) {
3850 si->myname = (struct swrap_address) {
3851 .sa_socklen = si->bindname.sa_socklen,
3854 memcpy(&si->myname.sa.ss,
3855 &si->bindname.sa.ss,
3856 si->bindname.sa_socklen);
3858 /* Cleanup bindname */
3859 si->bindname = (struct swrap_address) {
3864 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3865 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3867 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3871 SWRAP_UNLOCK_SI(si);
3875 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3877 return swrap_connect(s, serv_addr, addrlen);
3880 /****************************************************************************
3882 ***************************************************************************/
3884 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3887 struct swrap_address un_addr = {
3888 .sa_socklen = sizeof(struct sockaddr_un),
3890 struct socket_info *si = find_socket_info(s);
3897 return libc_bind(s, myaddr, addrlen);
3902 switch (si->family) {
3904 const struct sockaddr_in *sin;
3905 if (addrlen < sizeof(struct sockaddr_in)) {
3906 bind_error = EINVAL;
3910 sin = (const struct sockaddr_in *)(const void *)myaddr;
3912 if (sin->sin_family != AF_INET) {
3913 bind_error = EAFNOSUPPORT;
3916 /* special case for AF_UNSPEC */
3917 if (sin->sin_family == AF_UNSPEC &&
3918 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3927 const struct sockaddr_in6 *sin6;
3928 if (addrlen < sizeof(struct sockaddr_in6)) {
3929 bind_error = EINVAL;
3933 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3935 if (sin6->sin6_family != AF_INET6) {
3936 bind_error = EAFNOSUPPORT;
3943 bind_error = EINVAL;
3947 if (bind_error != 0) {
3954 in_use = check_addr_port_in_use(myaddr, addrlen);
3962 si->myname.sa_socklen = addrlen;
3963 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3965 ret = sockaddr_convert_to_un(si,
3975 unlink(un_addr.sa.un.sun_path);
3977 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3979 SWRAP_LOG(SWRAP_LOG_TRACE,
3980 "bind() path=%s, fd=%d",
3981 un_addr.sa.un.sun_path, s);
3988 SWRAP_UNLOCK_SI(si);
3993 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3995 return swrap_bind(s, myaddr, addrlen);
3998 /****************************************************************************
4000 ***************************************************************************/
4002 #ifdef HAVE_BINDRESVPORT
4003 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4005 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4007 struct swrap_address myaddr = {
4008 .sa_socklen = sizeof(struct sockaddr_storage),
4011 static uint16_t port;
4016 #define SWRAP_STARTPORT 600
4017 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4018 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4021 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4025 salen = myaddr.sa_socklen;
4028 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4034 memset(&myaddr.sa.ss, 0, salen);
4039 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4042 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4044 salen = sizeof(struct sockaddr_in);
4045 sinp->sin_port = htons(port);
4049 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4051 salen = sizeof(struct sockaddr_in6);
4052 sin6p->sin6_port = htons(port);
4056 errno = EAFNOSUPPORT;
4061 if (port > SWRAP_ENDPORT) {
4062 port = SWRAP_STARTPORT;
4065 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4066 if (rc == 0 || errno != EADDRINUSE) {
4074 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4076 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4080 /****************************************************************************
4082 ***************************************************************************/
4084 static int swrap_listen(int s, int backlog)
4087 struct socket_info *si = find_socket_info(s);
4090 return libc_listen(s, backlog);
4095 if (si->bound == 0) {
4096 ret = swrap_auto_bind(s, si, si->family);
4103 ret = libc_listen(s, backlog);
4109 SWRAP_UNLOCK_SI(si);
4114 int listen(int s, int backlog)
4116 return swrap_listen(s, backlog);
4119 /****************************************************************************
4121 ***************************************************************************/
4123 static FILE *swrap_fopen(const char *name, const char *mode)
4127 fp = libc_fopen(name, mode);
4129 int fd = fileno(fp);
4131 swrap_remove_stale(fd);
4137 FILE *fopen(const char *name, const char *mode)
4139 return swrap_fopen(name, mode);
4142 /****************************************************************************
4144 ***************************************************************************/
4147 static FILE *swrap_fopen64(const char *name, const char *mode)
4151 fp = libc_fopen64(name, mode);
4153 int fd = fileno(fp);
4155 swrap_remove_stale(fd);
4161 FILE *fopen64(const char *name, const char *mode)
4163 return swrap_fopen64(name, mode);
4165 #endif /* HAVE_FOPEN64 */
4167 /****************************************************************************
4169 ***************************************************************************/
4171 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4175 ret = libc_vopen(pathname, flags, ap);
4178 * There are methods for closing descriptors (libc-internal code
4179 * paths, direct syscalls) which close descriptors in ways that
4180 * we can't intercept, so try to recover when we notice that
4183 swrap_remove_stale(ret);
4188 int open(const char *pathname, int flags, ...)
4193 va_start(ap, flags);
4194 fd = swrap_vopen(pathname, flags, ap);
4200 /****************************************************************************
4202 ***************************************************************************/
4205 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4209 ret = libc_vopen64(pathname, flags, ap);
4212 * There are methods for closing descriptors (libc-internal code
4213 * paths, direct syscalls) which close descriptors in ways that
4214 * we can't intercept, so try to recover when we notice that
4217 swrap_remove_stale(ret);
4222 int open64(const char *pathname, int flags, ...)
4227 va_start(ap, flags);
4228 fd = swrap_vopen64(pathname, flags, ap);
4233 #endif /* HAVE_OPEN64 */
4235 /****************************************************************************
4237 ***************************************************************************/
4239 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4243 ret = libc_vopenat(dirfd, path, flags, ap);
4246 * There are methods for closing descriptors (libc-internal code
4247 * paths, direct syscalls) which close descriptors in ways that
4248 * we can't intercept, so try to recover when we notice that
4251 swrap_remove_stale(ret);
4257 int openat(int dirfd, const char *path, int flags, ...)
4262 va_start(ap, flags);
4263 fd = swrap_vopenat(dirfd, path, flags, ap);
4269 /****************************************************************************
4271 ***************************************************************************/
4273 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4275 struct socket_info *si = find_socket_info(s);
4280 return libc_getpeername(s, name, addrlen);
4285 if (si->peername.sa_socklen == 0)
4291 len = MIN(*addrlen, si->peername.sa_socklen);
4297 memcpy(name, &si->peername.sa.ss, len);
4298 *addrlen = si->peername.sa_socklen;
4302 SWRAP_UNLOCK_SI(si);
4307 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4308 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4310 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4313 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4316 /****************************************************************************
4318 ***************************************************************************/
4320 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4322 struct socket_info *si = find_socket_info(s);
4327 return libc_getsockname(s, name, addrlen);
4332 len = MIN(*addrlen, si->myname.sa_socklen);
4338 memcpy(name, &si->myname.sa.ss, len);
4339 *addrlen = si->myname.sa_socklen;
4343 SWRAP_UNLOCK_SI(si);
4348 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4349 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4351 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4354 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4357 /****************************************************************************
4359 ***************************************************************************/
4362 # ifdef SO_PROTOTYPE /* The Solaris name */
4363 # define SO_PROTOCOL SO_PROTOTYPE
4364 # endif /* SO_PROTOTYPE */
4365 #endif /* SO_PROTOCOL */
4367 static int swrap_getsockopt(int s, int level, int optname,
4368 void *optval, socklen_t *optlen)
4370 struct socket_info *si = find_socket_info(s);
4374 return libc_getsockopt(s,
4383 if (level == SOL_SOCKET) {
4387 if (optval == NULL || optlen == NULL ||
4388 *optlen < (socklen_t)sizeof(int)) {
4394 *optlen = sizeof(int);
4395 *(int *)optval = si->family;
4398 #endif /* SO_DOMAIN */
4402 if (optval == NULL || optlen == NULL ||
4403 *optlen < (socklen_t)sizeof(int)) {
4409 *optlen = sizeof(int);
4410 *(int *)optval = si->protocol;
4413 #endif /* SO_PROTOCOL */
4415 if (optval == NULL || optlen == NULL ||
4416 *optlen < (socklen_t)sizeof(int)) {
4422 *optlen = sizeof(int);
4423 *(int *)optval = si->type;
4427 ret = libc_getsockopt(s,
4434 } else if (level == IPPROTO_TCP) {
4439 * This enables sending packets directly out over TCP.
4440 * As a unix socket is doing that any way, report it as
4443 if (optval == NULL || optlen == NULL ||
4444 *optlen < (socklen_t)sizeof(int)) {
4450 *optlen = sizeof(int);
4451 *(int *)optval = si->tcp_nodelay;
4455 #endif /* TCP_NODELAY */
4458 struct tcp_info info;
4459 socklen_t ilen = sizeof(info);
4461 #ifdef HAVE_NETINET_TCP_FSM_H
4462 /* This is FreeBSD */
4463 # define __TCP_LISTEN TCPS_LISTEN
4464 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4465 # define __TCP_CLOSE TCPS_CLOSED
4468 # define __TCP_LISTEN TCP_LISTEN
4469 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4470 # define __TCP_CLOSE TCP_CLOSE
4474 if (si->listening) {
4475 info.tcpi_state = __TCP_LISTEN;
4476 } else if (si->connected) {
4478 * For now we just fake a few values
4479 * supported both by FreeBSD and Linux
4481 info.tcpi_state = __TCP_ESTABLISHED;
4482 info.tcpi_rto = 200000; /* 200 msec */
4483 info.tcpi_rtt = 5000; /* 5 msec */
4484 info.tcpi_rttvar = 5000; /* 5 msec */
4486 info.tcpi_state = __TCP_CLOSE;
4487 info.tcpi_rto = 1000000; /* 1 sec */
4489 info.tcpi_rttvar = 250000; /* 250 msec */
4492 if (optval == NULL || optlen == NULL ||
4493 *optlen < (socklen_t)ilen) {
4500 memcpy(optval, &info, ilen);
4505 #endif /* TCP_INFO */
4511 errno = ENOPROTOOPT;
4515 SWRAP_UNLOCK_SI(si);
4519 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4520 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4522 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4525 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4528 /****************************************************************************
4530 ***************************************************************************/
4532 static int swrap_setsockopt(int s, int level, int optname,
4533 const void *optval, socklen_t optlen)
4535 struct socket_info *si = find_socket_info(s);
4539 return libc_setsockopt(s,
4546 if (level == SOL_SOCKET) {
4547 return libc_setsockopt(s,
4556 if (level == IPPROTO_TCP) {
4563 * This enables sending packets directly out over TCP.
4564 * A unix socket is doing that any way.
4566 if (optval == NULL || optlen == 0 ||
4567 optlen < (socklen_t)sizeof(int)) {
4573 i = *discard_const_p(int, optval);
4574 if (i != 0 && i != 1) {
4579 si->tcp_nodelay = i;
4584 #endif /* TCP_NODELAY */
4590 switch (si->family) {
4592 if (level == IPPROTO_IP) {
4594 if (optname == IP_PKTINFO) {
4595 si->pktinfo = AF_INET;
4597 #endif /* IP_PKTINFO */
4603 if (level == IPPROTO_IPV6) {
4604 #ifdef IPV6_RECVPKTINFO
4605 if (optname == IPV6_RECVPKTINFO) {
4606 si->pktinfo = AF_INET6;
4608 #endif /* IPV6_PKTINFO */
4614 errno = ENOPROTOOPT;
4620 SWRAP_UNLOCK_SI(si);
4624 int setsockopt(int s, int level, int optname,
4625 const void *optval, socklen_t optlen)
4627 return swrap_setsockopt(s, level, optname, optval, optlen);
4630 /****************************************************************************
4632 ***************************************************************************/
4634 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4636 struct socket_info *si = find_socket_info(s);
4638 int *value_ptr = NULL;
4642 return libc_vioctl(s, r, va);
4649 rc = libc_vioctl(s, r, va);
4654 value_ptr = ((int *)va_arg(ap, int *));
4657 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4658 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4659 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4660 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4665 /* this is FreeBSD */
4666 FALL_THROUGH; /* to TIOCOUTQ */
4667 #endif /* FIONWRITE */
4668 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4670 * This may return more bytes then the application
4671 * sent into the socket, for tcp it should
4672 * return the number of unacked bytes.
4674 * On AF_UNIX, all bytes are immediately acked!
4677 value_ptr = ((int *)va_arg(ap, int *));
4685 SWRAP_UNLOCK_SI(si);
4689 #ifdef HAVE_IOCTL_INT
4690 int ioctl(int s, int r, ...)
4692 int ioctl(int s, unsigned long int r, ...)
4700 rc = swrap_vioctl(s, (unsigned long int) r, va);
4711 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4714 # ifdef _ALIGN /* BSD */
4715 #define CMSG_ALIGN _ALIGN
4717 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4718 # endif /* _ALIGN */
4719 #endif /* CMSG_ALIGN */
4722 * @brief Add a cmsghdr to a msghdr.
4724 * This is an function to add any type of cmsghdr. It will operate on the
4725 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4726 * the buffer position after the added cmsg element. Hence, this function is
4727 * intended to be used with an intermediate msghdr and not on the original
4728 * one handed in by the client.
4730 * @param[in] msg The msghdr to which to add the cmsg.
4732 * @param[in] level The cmsg level to set.
4734 * @param[in] type The cmsg type to set.
4736 * @param[in] data The cmsg data to set.
4738 * @param[in] len the length of the data to set.
4740 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4746 size_t cmlen = CMSG_LEN(len);
4747 size_t cmspace = CMSG_SPACE(len);
4748 uint8_t cmbuf[cmspace];
4749 void *cast_ptr = (void *)cmbuf;
4750 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4753 memset(cmbuf, 0, cmspace);
4755 if (msg->msg_controllen < cmlen) {
4756 cmlen = msg->msg_controllen;
4757 msg->msg_flags |= MSG_CTRUNC;
4760 if (msg->msg_controllen < cmspace) {
4761 cmspace = msg->msg_controllen;
4765 * We copy the full input data into an intermediate cmsghdr first
4766 * in order to more easily cope with truncation.
4768 cm->cmsg_len = cmlen;
4769 cm->cmsg_level = level;
4770 cm->cmsg_type = type;
4771 memcpy(CMSG_DATA(cm), data, len);
4774 * We now copy the possibly truncated buffer.
4775 * We copy cmlen bytes, but consume cmspace bytes,
4776 * leaving the possible padding uninitialiazed.
4778 p = (uint8_t *)msg->msg_control;
4779 memcpy(p, cm, cmlen);
4781 msg->msg_control = p;
4782 msg->msg_controllen -= cmspace;
4787 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4790 /* Add packet info */
4791 switch (si->pktinfo) {
4792 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4794 struct sockaddr_in *sin;
4795 #if defined(HAVE_STRUCT_IN_PKTINFO)
4796 struct in_pktinfo pkt;
4797 #elif defined(IP_RECVDSTADDR)
4801 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4802 sin = &si->bindname.sa.in;
4804 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4807 sin = &si->myname.sa.in;
4812 #if defined(HAVE_STRUCT_IN_PKTINFO)
4813 pkt.ipi_ifindex = socket_wrapper_default_iface();
4814 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4815 #elif defined(IP_RECVDSTADDR)
4816 pkt = sin->sin_addr;
4819 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4824 #endif /* IP_PKTINFO */
4825 #if defined(HAVE_IPV6)
4827 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4828 struct sockaddr_in6 *sin6;
4829 struct in6_pktinfo pkt6;
4831 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4832 sin6 = &si->bindname.sa.in6;
4834 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4837 sin6 = &si->myname.sa.in6;
4842 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4843 pkt6.ipi6_addr = sin6->sin6_addr;
4845 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4846 &pkt6, sizeof(pkt6));
4847 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4851 #endif /* IPV6_PKTINFO */
4859 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4860 struct msghdr *omsg)
4864 if (si->pktinfo > 0) {
4865 rc = swrap_msghdr_add_pktinfo(si, omsg);
4871 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4873 size_t *cm_data_space);
4874 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4876 size_t *cm_data_space);
4878 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4880 size_t *cm_data_space) {
4881 struct cmsghdr *cmsg;
4885 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4889 for (cmsg = CMSG_FIRSTHDR(msg);
4891 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4892 switch (cmsg->cmsg_level) {
4894 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4899 rc = swrap_sendmsg_copy_cmsg(cmsg,
4909 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4911 size_t *cm_data_space)
4916 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4918 p = realloc((*cm_data), cmspace);
4924 p = (*cm_data) + (*cm_data_space);
4925 *cm_data_space = cmspace;
4927 memcpy(p, cmsg, cmsg->cmsg_len);
4932 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4934 size_t *cm_data_space);
4937 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4939 size_t *cm_data_space)
4943 switch(cmsg->cmsg_type) {
4946 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4953 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4965 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4967 size_t *cm_data_space)
4969 (void)cmsg; /* unused */
4970 (void)cm_data; /* unused */
4971 (void)cm_data_space; /* unused */
4974 * Passing a IP pktinfo to a unix socket might be rejected by the
4975 * Kernel, at least on FreeBSD. So skip this cmsg.
4979 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4981 static ssize_t swrap_sendmsg_before(int fd,
4982 struct socket_info *si,
4984 struct iovec *tmp_iov,
4985 struct sockaddr_un *tmp_un,
4986 const struct sockaddr_un **to_un,
4987 const struct sockaddr **to,
5009 if (!si->connected) {
5014 if (msg->msg_iovlen == 0) {
5018 mtu = socket_wrapper_mtu();
5019 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5021 nlen = len + msg->msg_iov[i].iov_len;
5031 msg->msg_iovlen = i;
5032 if (msg->msg_iovlen == 0) {
5033 *tmp_iov = msg->msg_iov[0];
5034 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5036 msg->msg_iov = tmp_iov;
5037 msg->msg_iovlen = 1;
5042 if (si->connected) {
5043 if (msg->msg_name != NULL) {
5045 * We are dealing with unix sockets and if we
5046 * are connected, we should only talk to the
5047 * connected unix path. Using the fd to send
5048 * to another server would be hard to achieve.
5050 msg->msg_name = NULL;
5051 msg->msg_namelen = 0;
5054 const struct sockaddr *msg_name;
5055 msg_name = (const struct sockaddr *)msg->msg_name;
5057 if (msg_name == NULL) {
5063 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
5075 msg->msg_name = tmp_un;
5076 msg->msg_namelen = sizeof(*tmp_un);
5079 if (si->bound == 0) {
5080 ret = swrap_auto_bind(fd, si, si->family);
5082 SWRAP_UNLOCK_SI(si);
5083 if (errno == ENOTSOCK) {
5084 swrap_remove_stale(fd);
5087 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
5093 if (!si->defer_connect) {
5097 ret = sockaddr_convert_to_un(si,
5099 si->peername.sa_socklen,
5107 ret = libc_connect(fd,
5108 (struct sockaddr *)(void *)tmp_un,
5111 /* to give better errors */
5112 if (ret == -1 && errno == ENOENT) {
5113 errno = EHOSTUNREACH;
5120 si->defer_connect = 0;
5123 errno = EHOSTUNREACH;
5127 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5128 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
5129 uint8_t *cmbuf = NULL;
5132 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
5139 msg->msg_controllen = 0;
5140 msg->msg_control = NULL;
5141 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
5142 memcpy(msg->msg_control, cmbuf, cmlen);
5143 msg->msg_controllen = cmlen;
5151 SWRAP_UNLOCK_SI(si);
5156 static void swrap_sendmsg_after(int fd,
5157 struct socket_info *si,
5159 const struct sockaddr *to,
5162 int saved_errno = errno;
5169 /* to give better errors */
5171 if (saved_errno == ENOENT) {
5172 saved_errno = EHOSTUNREACH;
5173 } else if (saved_errno == ENOTSOCK) {
5174 /* If the fd is not a socket, remove it */
5175 swrap_remove_stale(fd);
5179 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5180 avail += msg->msg_iov[i].iov_len;
5184 remain = MIN(80, avail);
5189 /* we capture it as one single packet */
5190 buf = (uint8_t *)malloc(remain);
5192 /* we just not capture the packet */
5193 errno = saved_errno;
5197 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5198 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5200 msg->msg_iov[i].iov_base,
5203 remain -= this_time;
5212 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5213 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
5215 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
5220 if (si->connected) {
5221 to = &si->peername.sa.s;
5224 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5225 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
5227 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5232 SWRAP_UNLOCK_SI(si);
5235 errno = saved_errno;
5238 static int swrap_recvmsg_before(int fd,
5239 struct socket_info *si,
5241 struct iovec *tmp_iov)
5248 (void)fd; /* unused */
5253 if (!si->connected) {
5258 if (msg->msg_iovlen == 0) {
5262 mtu = socket_wrapper_mtu();
5263 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5265 nlen = len + msg->msg_iov[i].iov_len;
5270 msg->msg_iovlen = i;
5271 if (msg->msg_iovlen == 0) {
5272 *tmp_iov = msg->msg_iov[0];
5273 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5275 msg->msg_iov = tmp_iov;
5276 msg->msg_iovlen = 1;
5281 if (msg->msg_name == NULL) {
5286 if (msg->msg_iovlen == 0) {
5290 if (si->bound == 0) {
5291 ret = swrap_auto_bind(fd, si, si->family);
5293 SWRAP_UNLOCK_SI(si);
5295 * When attempting to read or write to a
5296 * descriptor, if an underlying autobind fails
5297 * because it's not a socket, stop intercepting
5298 * uses of that descriptor.
5300 if (errno == ENOTSOCK) {
5301 swrap_remove_stale(fd);
5304 SWRAP_LOG(SWRAP_LOG_ERROR,
5305 "swrap_recvmsg_before failed");
5312 errno = EHOSTUNREACH;
5318 SWRAP_UNLOCK_SI(si);
5323 static int swrap_recvmsg_after(int fd,
5324 struct socket_info *si,
5326 const struct sockaddr_un *un_addr,
5327 socklen_t un_addrlen,
5330 int saved_errno = errno;
5332 uint8_t *buf = NULL;
5338 /* to give better errors */
5340 if (saved_errno == ENOENT) {
5341 saved_errno = EHOSTUNREACH;
5342 } else if (saved_errno == ENOTSOCK) {
5343 /* If the fd is not a socket, remove it */
5344 swrap_remove_stale(fd);
5348 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5349 avail += msg->msg_iov[i].iov_len;
5354 /* Convert the socket address before we leave */
5355 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5356 rc = sockaddr_convert_from_un(si,
5373 remain = MIN(80, avail);
5378 /* we capture it as one single packet */
5379 buf = (uint8_t *)malloc(remain);
5381 /* we just not capture the packet */
5382 SWRAP_UNLOCK_SI(si);
5383 errno = saved_errno;
5387 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5388 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5390 msg->msg_iov[i].iov_base,
5393 remain -= this_time;
5398 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5399 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5400 } else if (ret == 0) { /* END OF FILE */
5401 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5402 } else if (ret > 0) {
5403 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5412 if (un_addr != NULL) {
5413 swrap_pcap_dump_packet(si,
5419 swrap_pcap_dump_packet(si,
5432 errno = saved_errno;
5434 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5436 msg->msg_controllen > 0 &&
5437 msg->msg_control != NULL) {
5438 rc = swrap_msghdr_add_socket_info(si, msg);
5440 SWRAP_UNLOCK_SI(si);
5446 SWRAP_UNLOCK_SI(si);
5450 /****************************************************************************
5452 ***************************************************************************/
5454 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5455 struct sockaddr *from, socklen_t *fromlen)
5457 struct swrap_address from_addr = {
5458 .sa_socklen = sizeof(struct sockaddr_un),
5461 struct socket_info *si = find_socket_info(s);
5462 struct swrap_address saddr = {
5463 .sa_socklen = sizeof(struct sockaddr_storage),
5470 return libc_recvfrom(s,
5482 if (from != NULL && fromlen != NULL) {
5483 msg.msg_name = from; /* optional address */
5484 msg.msg_namelen = *fromlen; /* size of address */
5486 msg.msg_name = &saddr.sa.s; /* optional address */
5487 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5489 msg.msg_iov = &tmp; /* scatter/gather array */
5490 msg.msg_iovlen = 1; /* # elements in msg_iov */
5491 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5492 msg.msg_control = NULL; /* ancillary data, see below */
5493 msg.msg_controllen = 0; /* ancillary data buffer len */
5494 msg.msg_flags = 0; /* flags on received message */
5497 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5502 buf = msg.msg_iov[0].iov_base;
5503 len = msg.msg_iov[0].iov_len;
5505 ret = libc_recvfrom(s,
5510 &from_addr.sa_socklen);
5515 tret = swrap_recvmsg_after(s,
5519 from_addr.sa_socklen,
5525 if (from != NULL && fromlen != NULL) {
5526 *fromlen = msg.msg_namelen;
5532 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5533 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5534 struct sockaddr *from, Psocklen_t fromlen)
5536 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5537 struct sockaddr *from, socklen_t *fromlen)
5540 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5543 /****************************************************************************
5545 ***************************************************************************/
5547 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5548 const struct sockaddr *to, socklen_t tolen)
5552 struct swrap_address un_addr = {
5553 .sa_socklen = sizeof(struct sockaddr_un),
5555 const struct sockaddr_un *to_un = NULL;
5558 struct socket_info *si = find_socket_info(s);
5562 return libc_sendto(s, buf, len, flags, to, tolen);
5565 tmp.iov_base = discard_const_p(char, buf);
5569 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5570 msg.msg_namelen = tolen; /* size of address */
5571 msg.msg_iov = &tmp; /* scatter/gather array */
5572 msg.msg_iovlen = 1; /* # elements in msg_iov */
5573 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5574 msg.msg_control = NULL; /* ancillary data, see below */
5575 msg.msg_controllen = 0; /* ancillary data buffer len */
5576 msg.msg_flags = 0; /* flags on received message */
5579 rc = swrap_sendmsg_before(s,
5591 buf = msg.msg_iov[0].iov_base;
5592 len = msg.msg_iov[0].iov_len;
5597 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5599 char *swrap_dir = NULL;
5601 type = SOCKET_TYPE_CHAR_UDP;
5603 swrap_dir = socket_wrapper_dir();
5604 if (swrap_dir == NULL) {
5608 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5609 snprintf(un_addr.sa.un.sun_path,
5610 sizeof(un_addr.sa.un.sun_path),
5611 "%s/"SOCKET_FORMAT, swrap_dir, type, iface, prt);
5612 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5614 /* ignore the any errors in broadcast sends */
5620 un_addr.sa_socklen);
5623 SAFE_FREE(swrap_dir);
5627 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5629 SWRAP_UNLOCK_SI(si);
5636 * If it is a dgram socket and we are connected, don't include the
5639 if (si->type == SOCK_DGRAM && si->connected) {
5640 ret = libc_sendto(s,
5647 ret = libc_sendto(s,
5651 (struct sockaddr *)msg.msg_name,
5655 SWRAP_UNLOCK_SI(si);
5657 swrap_sendmsg_after(s, si, &msg, to, ret);
5662 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5663 const struct sockaddr *to, socklen_t tolen)
5665 return swrap_sendto(s, buf, len, flags, to, tolen);
5668 /****************************************************************************
5670 ***************************************************************************/
5672 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5674 struct socket_info *si;
5676 struct swrap_address saddr = {
5677 .sa_socklen = sizeof(struct sockaddr_storage),
5683 si = find_socket_info(s);
5685 return libc_recv(s, buf, len, flags);
5692 msg.msg_name = &saddr.sa.s; /* optional address */
5693 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5694 msg.msg_iov = &tmp; /* scatter/gather array */
5695 msg.msg_iovlen = 1; /* # elements in msg_iov */
5696 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5697 msg.msg_control = NULL; /* ancillary data, see below */
5698 msg.msg_controllen = 0; /* ancillary data buffer len */
5699 msg.msg_flags = 0; /* flags on received message */
5702 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5707 buf = msg.msg_iov[0].iov_base;
5708 len = msg.msg_iov[0].iov_len;
5710 ret = libc_recv(s, buf, len, flags);
5712 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5720 ssize_t recv(int s, void *buf, size_t len, int flags)
5722 return swrap_recv(s, buf, len, flags);
5725 /****************************************************************************
5727 ***************************************************************************/
5729 static ssize_t swrap_read(int s, void *buf, size_t len)
5731 struct socket_info *si;
5734 struct swrap_address saddr = {
5735 .sa_socklen = sizeof(struct sockaddr_storage),
5740 si = find_socket_info(s);
5742 return libc_read(s, buf, len);
5749 msg.msg_name = &saddr.sa.ss; /* optional address */
5750 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5751 msg.msg_iov = &tmp; /* scatter/gather array */
5752 msg.msg_iovlen = 1; /* # elements in msg_iov */
5753 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5754 msg.msg_control = NULL; /* ancillary data, see below */
5755 msg.msg_controllen = 0; /* ancillary data buffer len */
5756 msg.msg_flags = 0; /* flags on received message */
5759 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5761 if (tret == -ENOTSOCK) {
5762 return libc_read(s, buf, len);
5767 buf = msg.msg_iov[0].iov_base;
5768 len = msg.msg_iov[0].iov_len;
5770 ret = libc_read(s, buf, len);
5772 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5780 ssize_t read(int s, void *buf, size_t len)
5782 return swrap_read(s, buf, len);
5785 /****************************************************************************
5787 ***************************************************************************/
5789 static ssize_t swrap_write(int s, const void *buf, size_t len)
5793 struct sockaddr_un un_addr;
5796 struct socket_info *si;
5798 si = find_socket_info(s);
5800 return libc_write(s, buf, len);
5803 tmp.iov_base = discard_const_p(char, buf);
5807 msg.msg_name = NULL; /* optional address */
5808 msg.msg_namelen = 0; /* size of address */
5809 msg.msg_iov = &tmp; /* scatter/gather array */
5810 msg.msg_iovlen = 1; /* # elements in msg_iov */
5811 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5812 msg.msg_control = NULL; /* ancillary data, see below */
5813 msg.msg_controllen = 0; /* ancillary data buffer len */
5814 msg.msg_flags = 0; /* flags on received message */
5817 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5822 buf = msg.msg_iov[0].iov_base;
5823 len = msg.msg_iov[0].iov_len;
5825 ret = libc_write(s, buf, len);
5827 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5832 ssize_t write(int s, const void *buf, size_t len)
5834 return swrap_write(s, buf, len);
5837 /****************************************************************************
5839 ***************************************************************************/
5841 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5845 struct sockaddr_un un_addr;
5848 struct socket_info *si = find_socket_info(s);
5851 return libc_send(s, buf, len, flags);
5854 tmp.iov_base = discard_const_p(char, buf);
5858 msg.msg_name = NULL; /* optional address */
5859 msg.msg_namelen = 0; /* size of address */
5860 msg.msg_iov = &tmp; /* scatter/gather array */
5861 msg.msg_iovlen = 1; /* # elements in msg_iov */
5862 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5863 msg.msg_control = NULL; /* ancillary data, see below */
5864 msg.msg_controllen = 0; /* ancillary data buffer len */
5865 msg.msg_flags = 0; /* flags on received message */
5868 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5873 buf = msg.msg_iov[0].iov_base;
5874 len = msg.msg_iov[0].iov_len;
5876 ret = libc_send(s, buf, len, flags);
5878 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5883 ssize_t send(int s, const void *buf, size_t len, int flags)
5885 return swrap_send(s, buf, len, flags);
5888 /****************************************************************************
5890 ***************************************************************************/
5892 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5894 struct swrap_address from_addr = {
5895 .sa_socklen = sizeof(struct sockaddr_un),
5897 struct swrap_address convert_addr = {
5898 .sa_socklen = sizeof(struct sockaddr_storage),
5900 struct socket_info *si;
5903 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5904 size_t msg_ctrllen_filled;
5905 size_t msg_ctrllen_left;
5911 si = find_socket_info(s);
5913 return libc_recvmsg(s, omsg, flags);
5916 tmp.iov_base = NULL;
5920 msg.msg_name = &from_addr.sa; /* optional address */
5921 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5922 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5923 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5924 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5925 msg_ctrllen_filled = 0;
5926 msg_ctrllen_left = omsg->msg_controllen;
5928 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5929 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5930 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5933 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5938 ret = libc_recvmsg(s, &msg, flags);
5940 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5941 msg_ctrllen_filled += msg.msg_controllen;
5942 msg_ctrllen_left -= msg.msg_controllen;
5944 if (omsg->msg_control != NULL) {
5947 p = omsg->msg_control;
5948 p += msg_ctrllen_filled;
5950 msg.msg_control = p;
5951 msg.msg_controllen = msg_ctrllen_left;
5953 msg.msg_control = NULL;
5954 msg.msg_controllen = 0;
5959 * We convert the unix address to a IP address so we need a buffer
5960 * which can store the address in case of SOCK_DGRAM, see below.
5962 msg.msg_name = &convert_addr.sa;
5963 msg.msg_namelen = convert_addr.sa_socklen;
5965 rc = swrap_recvmsg_after(s,
5969 from_addr.sa_socklen,
5975 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5976 if (omsg->msg_control != NULL) {
5977 /* msg.msg_controllen = space left */
5978 msg_ctrllen_left = msg.msg_controllen;
5979 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5982 /* Update the original message length */
5983 omsg->msg_controllen = msg_ctrllen_filled;
5984 omsg->msg_flags = msg.msg_flags;
5986 omsg->msg_iovlen = msg.msg_iovlen;
5993 * The msg_name field points to a caller-allocated buffer that is
5994 * used to return the source address if the socket is unconnected. The
5995 * caller should set msg_namelen to the size of this buffer before this
5996 * call; upon return from a successful call, msg_name will contain the
5997 * length of the returned address. If the application does not need
5998 * to know the source address, msg_name can be specified as NULL.
6000 if (si->type == SOCK_STREAM) {
6001 omsg->msg_namelen = 0;
6002 } else if (omsg->msg_name != NULL &&
6003 omsg->msg_namelen != 0 &&
6004 omsg->msg_namelen >= msg.msg_namelen) {
6005 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6006 omsg->msg_namelen = msg.msg_namelen;
6009 SWRAP_UNLOCK_SI(si);
6014 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6016 return swrap_recvmsg(sockfd, msg, flags);
6019 /****************************************************************************
6021 ***************************************************************************/
6023 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
6027 struct sockaddr_un un_addr;
6028 const struct sockaddr_un *to_un = NULL;
6029 const struct sockaddr *to = NULL;
6032 struct socket_info *si = find_socket_info(s);
6036 return libc_sendmsg(s, omsg, flags);
6039 ZERO_STRUCT(un_addr);
6041 tmp.iov_base = NULL;
6048 if (si->connected == 0) {
6049 msg.msg_name = omsg->msg_name; /* optional address */
6050 msg.msg_namelen = omsg->msg_namelen; /* size of address */
6052 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6053 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6055 SWRAP_UNLOCK_SI(si);
6057 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6058 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
6059 /* omsg is a const so use a local buffer for modifications */
6060 uint8_t cmbuf[omsg->msg_controllen];
6062 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
6064 msg.msg_control = cmbuf; /* ancillary data, see below */
6065 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6067 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6070 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
6078 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6085 char *swrap_dir = NULL;
6087 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6088 avail += msg.msg_iov[i].iov_len;
6094 /* we capture it as one single packet */
6095 buf = (uint8_t *)malloc(remain);
6100 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
6101 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
6103 msg.msg_iov[i].iov_base,
6106 remain -= this_time;
6109 type = SOCKET_TYPE_CHAR_UDP;
6111 swrap_dir = socket_wrapper_dir();
6112 if (swrap_dir == NULL) {
6117 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6118 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
6119 swrap_dir, type, iface, prt);
6120 if (stat(un_addr.sun_path, &st) != 0) continue;
6122 msg.msg_name = &un_addr; /* optional address */
6123 msg.msg_namelen = sizeof(un_addr); /* size of address */
6125 /* ignore the any errors in broadcast sends */
6126 libc_sendmsg(s, &msg, flags);
6129 SAFE_FREE(swrap_dir);
6133 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6136 SWRAP_UNLOCK_SI(si);
6141 ret = libc_sendmsg(s, &msg, flags);
6143 swrap_sendmsg_after(s, si, &msg, to, ret);
6148 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
6150 return swrap_sendmsg(s, omsg, flags);
6153 /****************************************************************************
6155 ***************************************************************************/
6157 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
6159 struct socket_info *si;
6162 struct swrap_address saddr = {
6163 .sa_socklen = sizeof(struct sockaddr_storage)
6168 si = find_socket_info(s);
6170 return libc_readv(s, vector, count);
6173 tmp.iov_base = NULL;
6177 msg.msg_name = &saddr.sa.s; /* optional address */
6178 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6179 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6180 msg.msg_iovlen = count; /* # elements in msg_iov */
6181 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6182 msg.msg_control = NULL; /* ancillary data, see below */
6183 msg.msg_controllen = 0; /* ancillary data buffer len */
6184 msg.msg_flags = 0; /* flags on received message */
6187 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6189 if (rc == -ENOTSOCK) {
6190 return libc_readv(s, vector, count);
6195 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
6197 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6205 ssize_t readv(int s, const struct iovec *vector, int count)
6207 return swrap_readv(s, vector, count);
6210 /****************************************************************************
6212 ***************************************************************************/
6214 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
6218 struct sockaddr_un un_addr;
6221 struct socket_info *si = find_socket_info(s);
6224 return libc_writev(s, vector, count);
6227 tmp.iov_base = NULL;
6231 msg.msg_name = NULL; /* optional address */
6232 msg.msg_namelen = 0; /* size of address */
6233 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
6234 msg.msg_iovlen = count; /* # elements in msg_iov */
6235 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6236 msg.msg_control = NULL; /* ancillary data, see below */
6237 msg.msg_controllen = 0; /* ancillary data buffer len */
6238 msg.msg_flags = 0; /* flags on received message */
6241 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6243 if (rc == -ENOTSOCK) {
6244 return libc_readv(s, vector, count);
6249 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6251 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6256 ssize_t writev(int s, const struct iovec *vector, int count)
6258 return swrap_writev(s, vector, count);
6261 /****************************
6263 ***************************/
6265 static int swrap_close(int fd)
6267 struct socket_info *si = NULL;
6271 swrap_mutex_lock(&socket_reset_mutex);
6273 si_index = find_socket_info_index(fd);
6274 if (si_index == -1) {
6275 swrap_mutex_unlock(&socket_reset_mutex);
6276 return libc_close(fd);
6279 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
6280 reset_socket_info_index(fd);
6282 si = swrap_get_socket_info(si_index);
6284 swrap_mutex_lock(&first_free_mutex);
6287 ret = libc_close(fd);
6289 swrap_dec_refcount(si);
6291 if (swrap_get_refcount(si) > 0) {
6292 /* there are still references left */
6296 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6297 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6300 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6301 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6302 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6305 if (si->un_addr.sun_path[0] != '\0') {
6306 unlink(si->un_addr.sun_path);
6309 swrap_set_next_free(si, first_free);
6310 first_free = si_index;
6313 SWRAP_UNLOCK_SI(si);
6314 swrap_mutex_unlock(&first_free_mutex);
6315 swrap_mutex_unlock(&socket_reset_mutex);
6322 return swrap_close(fd);
6325 /****************************
6327 ***************************/
6329 static int swrap_dup(int fd)
6331 struct socket_info *si;
6334 idx = find_socket_info_index(fd);
6336 return libc_dup(fd);
6339 si = swrap_get_socket_info(idx);
6341 dup_fd = libc_dup(fd);
6343 int saved_errno = errno;
6344 errno = saved_errno;
6350 swrap_inc_refcount(si);
6352 SWRAP_UNLOCK_SI(si);
6354 /* Make sure we don't have an entry for the fd */
6355 swrap_remove_stale(dup_fd);
6357 set_socket_info_index(dup_fd, idx);
6364 return swrap_dup(fd);
6367 /****************************
6369 ***************************/
6371 static int swrap_dup2(int fd, int newfd)
6373 struct socket_info *si;
6376 idx = find_socket_info_index(fd);
6378 return libc_dup2(fd, newfd);
6381 si = swrap_get_socket_info(idx);
6385 * According to the manpage:
6387 * "If oldfd is a valid file descriptor, and newfd has the same
6388 * value as oldfd, then dup2() does nothing, and returns newfd."
6393 if (find_socket_info(newfd)) {
6394 /* dup2() does an implicit close of newfd, which we
6395 * need to emulate */
6399 dup_fd = libc_dup2(fd, newfd);
6401 int saved_errno = errno;
6402 errno = saved_errno;
6408 swrap_inc_refcount(si);
6410 SWRAP_UNLOCK_SI(si);
6412 /* Make sure we don't have an entry for the fd */
6413 swrap_remove_stale(dup_fd);
6415 set_socket_info_index(dup_fd, idx);
6420 int dup2(int fd, int newfd)
6422 return swrap_dup2(fd, newfd);
6425 /****************************
6427 ***************************/
6429 static int swrap_vfcntl(int fd, int cmd, va_list va)
6431 struct socket_info *si;
6432 int rc, dup_fd, idx;
6434 idx = find_socket_info_index(fd);
6436 return libc_vfcntl(fd, cmd, va);
6439 si = swrap_get_socket_info(idx);
6443 dup_fd = libc_vfcntl(fd, cmd, va);
6445 int saved_errno = errno;
6446 errno = saved_errno;
6452 swrap_inc_refcount(si);
6454 SWRAP_UNLOCK_SI(si);
6456 /* Make sure we don't have an entry for the fd */
6457 swrap_remove_stale(dup_fd);
6459 set_socket_info_index(dup_fd, idx);
6464 rc = libc_vfcntl(fd, cmd, va);
6471 int fcntl(int fd, int cmd, ...)
6478 rc = swrap_vfcntl(fd, cmd, va);
6485 /****************************
6487 ***************************/
6490 static int swrap_eventfd(int count, int flags)
6494 fd = libc_eventfd(count, flags);
6496 swrap_remove_stale(fd);
6502 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6503 int eventfd(unsigned int count, int flags)
6505 int eventfd(int count, int flags)
6508 return swrap_eventfd(count, flags);
6513 int pledge(const char *promises, const char *paths[])
6515 (void)promises; /* unused */
6516 (void)paths; /* unused */
6520 #endif /* HAVE_PLEDGE */
6522 static void swrap_thread_prepare(void)
6525 * This function should only be called here!!
6527 * We bind all symobls to avoid deadlocks of the fork is
6528 * interrupted by a signal handler using a symbol of this
6531 swrap_bind_symbol_all();
6536 static void swrap_thread_parent(void)
6541 static void swrap_thread_child(void)
6546 /****************************
6548 ***************************/
6549 void swrap_constructor(void)
6554 * If we hold a lock and the application forks, then the child
6555 * is not able to unlock the mutex and we are in a deadlock.
6556 * This should prevent such deadlocks.
6558 pthread_atfork(&swrap_thread_prepare,
6559 &swrap_thread_parent,
6560 &swrap_thread_child);
6562 ret = socket_wrapper_init_mutex(&sockets_mutex);
6564 SWRAP_LOG(SWRAP_LOG_ERROR,
6565 "Failed to initialize pthread mutex");
6569 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6571 SWRAP_LOG(SWRAP_LOG_ERROR,
6572 "Failed to initialize pthread mutex");
6576 ret = socket_wrapper_init_mutex(&first_free_mutex);
6578 SWRAP_LOG(SWRAP_LOG_ERROR,
6579 "Failed to initialize pthread mutex");
6584 /****************************
6586 ***************************/
6589 * This function is called when the library is unloaded and makes sure that
6590 * sockets get closed and the unix file for the socket are unlinked.
6592 void swrap_destructor(void)
6596 if (socket_fds_idx != NULL) {
6597 for (i = 0; i < socket_fds_max; ++i) {
6598 if (socket_fds_idx[i] != -1) {
6602 SAFE_FREE(socket_fds_idx);
6607 if (swrap.libc.handle != NULL) {
6608 dlclose(swrap.libc.handle);
6610 if (swrap.libc.socket_handle) {
6611 dlclose(swrap.libc.socket_handle);
6615 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
6617 * On FreeBSD 12 (and maybe other platforms)
6618 * system libraries like libresolv prefix there
6619 * syscalls with '_' in order to always use
6620 * the symbols from libc.
6622 * In the interaction with resolv_wrapper,
6623 * we need to inject socket wrapper into libresolv,
6624 * which means we need to private all socket
6625 * related syscalls also with the '_' prefix.
6627 * This is tested in Samba's 'make test',
6628 * there we noticed that providing '_read'
6629 * and '_open' would cause errors, which
6630 * means we skip '_read', '_write' and
6631 * all non socket related calls without
6632 * further analyzing the problem.
6634 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
6635 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
6638 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
6640 SWRAP_SYMBOL_ALIAS(accept, _accept);
6641 SWRAP_SYMBOL_ALIAS(bind, _bind);
6642 SWRAP_SYMBOL_ALIAS(close, _close);
6643 SWRAP_SYMBOL_ALIAS(connect, _connect);
6644 SWRAP_SYMBOL_ALIAS(dup, _dup);
6645 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
6646 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
6647 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
6648 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
6649 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
6650 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
6651 SWRAP_SYMBOL_ALIAS(listen, _listen);
6652 SWRAP_SYMBOL_ALIAS(readv, _readv);
6653 SWRAP_SYMBOL_ALIAS(recv, _recv);
6654 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
6655 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
6656 SWRAP_SYMBOL_ALIAS(send, _send);
6657 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
6658 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
6659 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
6660 SWRAP_SYMBOL_ALIAS(socket, _socket);
6661 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
6662 SWRAP_SYMBOL_ALIAS(writev, _writev);
6664 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */