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 #include <arpa/inet.h>
78 #ifdef HAVE_GNU_LIB_NAMES_H
79 #include <gnu/lib-names.h>
93 /* GCC have printf type attribute check. */
94 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
95 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
97 #define PRINTF_ATTRIBUTE(a,b)
98 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
100 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
101 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
103 #define CONSTRUCTOR_ATTRIBUTE
104 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
106 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
107 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
109 #define DESTRUCTOR_ATTRIBUTE
113 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
114 # define FALL_THROUGH __attribute__ ((fallthrough))
115 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
116 # define FALL_THROUGH ((void)0)
117 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
118 #endif /* FALL_THROUGH */
120 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
121 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
123 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
126 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
127 # define SWRAP_THREAD __thread
129 # define SWRAP_THREAD
133 #define MIN(a,b) ((a)<(b)?(a):(b))
137 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
141 #define ZERO_STRUCTP(x) do { \
143 memset((char *)(x), 0, sizeof(*(x))); \
148 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
151 #ifndef discard_const
152 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
155 #ifndef discard_const_p
156 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
159 #define UNUSED(x) (void)(x)
162 # ifndef IPV6_RECVPKTINFO
163 # define IPV6_RECVPKTINFO IPV6_PKTINFO
164 # endif /* IPV6_RECVPKTINFO */
165 #endif /* IPV6_PKTINFO */
168 * On BSD IP_PKTINFO has a different name because during
169 * the time when they implemented it, there was no RFC.
170 * The name for IPv6 is the same as on Linux.
173 # ifdef IP_RECVDSTADDR
174 # define IP_PKTINFO IP_RECVDSTADDR
178 /* Add new global locks here please */
179 # define SWRAP_LOCK_ALL \
180 swrap_mutex_lock(&libc_symbol_binding_mutex); \
182 # define SWRAP_UNLOCK_ALL \
183 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
185 #define SOCKET_INFO_CONTAINER(si) \
186 (struct socket_info_container *)(si)
188 #define SWRAP_LOCK_SI(si) do { \
189 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
190 swrap_mutex_lock(&sic->meta.mutex); \
193 #define SWRAP_UNLOCK_SI(si) do { \
194 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
195 swrap_mutex_unlock(&sic->meta.mutex); \
198 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
199 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
201 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
204 /* we need to use a very terse format here as IRIX 6.4 silently
205 truncates names to 16 chars, so if we use a longer name then we
206 can't tell which port a packet came from with recvfrom()
208 with this format we have 8 chars left for the directory name
210 #define SOCKET_FORMAT "%c%02X%04X"
211 #define SOCKET_TYPE_CHAR_TCP 'T'
212 #define SOCKET_TYPE_CHAR_UDP 'U'
213 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
214 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
217 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
218 * format PCAP capture files (as the caller will simply continue from here).
220 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
221 #define SOCKET_WRAPPER_MTU_MIN 512
222 #define SOCKET_WRAPPER_MTU_MAX 32768
224 #define SOCKET_MAX_SOCKETS 1024
227 * Maximum number of socket_info structures that can
228 * be used. Can be overriden by the environment variable
229 * SOCKET_WRAPPER_MAX_SOCKETS.
231 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
233 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
235 /* This limit is to avoid broadcast sendto() needing to stat too many
236 * files. It may be raised (with a performance cost) to up to 254
237 * without changing the format above */
238 #define MAX_WRAPPED_INTERFACES 64
240 struct swrap_address {
241 socklen_t sa_socklen;
244 struct sockaddr_in in;
246 struct sockaddr_in6 in6;
248 struct sockaddr_un un;
249 struct sockaddr_storage ss;
268 /* The unix path so we can unlink it on close() */
269 struct sockaddr_un un_addr;
271 struct swrap_address bindname;
272 struct swrap_address myname;
273 struct swrap_address peername;
276 unsigned long pck_snd;
277 unsigned long pck_rcv;
281 struct socket_info_meta
283 unsigned int refcount;
285 pthread_mutex_t mutex;
288 struct socket_info_container
290 struct socket_info info;
291 struct socket_info_meta meta;
294 static struct socket_info_container *sockets;
296 static size_t socket_info_max = 0;
299 * Allocate the socket array always on the limit value. We want it to be
300 * at least bigger than the default so if we reach the limit we can
301 * still deal with duplicate fds pointing to the same socket_info.
303 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
305 /* Hash table to map fds to corresponding socket_info index */
306 static int *socket_fds_idx;
308 /* Mutex to synchronize access to global libc.symbols */
309 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
311 /* Mutex for syncronizing port selection during swrap_auto_bind() */
312 static pthread_mutex_t autobind_start_mutex;
314 /* Mutex to guard the initialization of array of socket_info structures */
315 static pthread_mutex_t sockets_mutex;
317 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
318 static pthread_mutex_t socket_reset_mutex;
320 /* Mutex to synchronize access to first free index in socket_info array */
321 static pthread_mutex_t first_free_mutex;
323 /* Mutex to synchronize access to packet capture dump file */
324 static pthread_mutex_t pcap_dump_mutex;
326 /* Mutex for synchronizing mtu value fetch*/
327 static pthread_mutex_t mtu_update_mutex;
329 /* Function prototypes */
331 bool socket_wrapper_enabled(void);
333 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
334 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
336 #ifndef HAVE_GETPROGNAME
337 static const char *getprogname(void)
339 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
340 return program_invocation_short_name;
341 #elif defined(HAVE_GETEXECNAME)
342 return getexecname();
345 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
347 #endif /* HAVE_GETPROGNAME */
349 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
350 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
352 static void swrap_log(enum swrap_dbglvl_e dbglvl,
354 const char *format, ...)
359 unsigned int lvl = 0;
360 const char *prefix = "SWRAP";
361 const char *progname = getprogname();
363 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
372 va_start(va, format);
373 vsnprintf(buffer, sizeof(buffer), format, va);
377 case SWRAP_LOG_ERROR:
378 prefix = "SWRAP_ERROR";
381 prefix = "SWRAP_WARN";
383 case SWRAP_LOG_DEBUG:
384 prefix = "SWRAP_DEBUG";
386 case SWRAP_LOG_TRACE:
387 prefix = "SWRAP_TRACE";
391 if (progname == NULL) {
392 progname = "<unknown>";
396 "%s[%s (%u)] - %s: %s\n",
399 (unsigned int)getpid(),
404 /*********************************************************
405 * SWRAP LOADING LIBC FUNCTIONS
406 *********************************************************/
411 typedef int (*__libc_accept4)(int sockfd,
412 struct sockaddr *addr,
416 typedef int (*__libc_accept)(int sockfd,
417 struct sockaddr *addr,
420 typedef int (*__libc_bind)(int sockfd,
421 const struct sockaddr *addr,
423 typedef int (*__libc_close)(int fd);
424 typedef int (*__libc_connect)(int sockfd,
425 const struct sockaddr *addr,
427 typedef int (*__libc_dup)(int fd);
428 typedef int (*__libc_dup2)(int oldfd, int newfd);
429 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
430 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
432 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
435 typedef int (*__libc_eventfd)(int count, int flags);
437 typedef int (*__libc_getpeername)(int sockfd,
438 struct sockaddr *addr,
440 typedef int (*__libc_getsockname)(int sockfd,
441 struct sockaddr *addr,
443 typedef int (*__libc_getsockopt)(int sockfd,
448 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
449 typedef int (*__libc_listen)(int sockfd, int backlog);
450 typedef int (*__libc_open)(const char *pathname, int flags, ...);
452 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
453 #endif /* HAVE_OPEN64 */
454 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
455 typedef int (*__libc_pipe)(int pipefd[2]);
456 typedef int (*__libc_read)(int fd, void *buf, size_t count);
457 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
458 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
459 typedef int (*__libc_recvfrom)(int sockfd,
463 struct sockaddr *src_addr,
465 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
466 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
467 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
468 typedef int (*__libc_sendto)(int sockfd,
472 const struct sockaddr *dst_addr,
474 typedef int (*__libc_setsockopt)(int sockfd,
480 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
482 typedef int (*__libc_socket)(int domain, int type, int protocol);
483 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
484 #ifdef HAVE_TIMERFD_CREATE
485 typedef int (*__libc_timerfd_create)(int clockid, int flags);
487 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
488 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
490 #define SWRAP_SYMBOL_ENTRY(i) \
496 struct swrap_libc_symbols {
498 SWRAP_SYMBOL_ENTRY(accept4);
500 SWRAP_SYMBOL_ENTRY(accept);
502 SWRAP_SYMBOL_ENTRY(bind);
503 SWRAP_SYMBOL_ENTRY(close);
504 SWRAP_SYMBOL_ENTRY(connect);
505 SWRAP_SYMBOL_ENTRY(dup);
506 SWRAP_SYMBOL_ENTRY(dup2);
507 SWRAP_SYMBOL_ENTRY(fcntl);
508 SWRAP_SYMBOL_ENTRY(fopen);
510 SWRAP_SYMBOL_ENTRY(fopen64);
513 SWRAP_SYMBOL_ENTRY(eventfd);
515 SWRAP_SYMBOL_ENTRY(getpeername);
516 SWRAP_SYMBOL_ENTRY(getsockname);
517 SWRAP_SYMBOL_ENTRY(getsockopt);
518 SWRAP_SYMBOL_ENTRY(ioctl);
519 SWRAP_SYMBOL_ENTRY(listen);
520 SWRAP_SYMBOL_ENTRY(open);
522 SWRAP_SYMBOL_ENTRY(open64);
524 SWRAP_SYMBOL_ENTRY(openat);
525 SWRAP_SYMBOL_ENTRY(pipe);
526 SWRAP_SYMBOL_ENTRY(read);
527 SWRAP_SYMBOL_ENTRY(readv);
528 SWRAP_SYMBOL_ENTRY(recv);
529 SWRAP_SYMBOL_ENTRY(recvfrom);
530 SWRAP_SYMBOL_ENTRY(recvmsg);
531 SWRAP_SYMBOL_ENTRY(send);
532 SWRAP_SYMBOL_ENTRY(sendmsg);
533 SWRAP_SYMBOL_ENTRY(sendto);
534 SWRAP_SYMBOL_ENTRY(setsockopt);
536 SWRAP_SYMBOL_ENTRY(signalfd);
538 SWRAP_SYMBOL_ENTRY(socket);
539 SWRAP_SYMBOL_ENTRY(socketpair);
540 #ifdef HAVE_TIMERFD_CREATE
541 SWRAP_SYMBOL_ENTRY(timerfd_create);
543 SWRAP_SYMBOL_ENTRY(write);
544 SWRAP_SYMBOL_ENTRY(writev);
551 struct swrap_libc_symbols symbols;
555 static struct swrap swrap;
558 static char *socket_wrapper_dir(void);
560 #define LIBC_NAME "libc.so"
568 static const char *swrap_str_lib(enum swrap_lib lib)
575 case SWRAP_LIBSOCKET:
579 /* Compiler would warn us about unhandled enum value if we get here */
583 static void *swrap_load_lib_handle(enum swrap_lib lib)
585 int flags = RTLD_LAZY;
590 const char *env_preload = getenv("LD_PRELOAD");
591 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
592 bool enable_deepbind = true;
594 /* Don't do a deepbind if we run with libasan */
595 if (env_preload != NULL && strlen(env_preload) < 1024) {
596 const char *p = strstr(env_preload, "libasan.so");
598 enable_deepbind = false;
602 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
603 enable_deepbind = false;
606 if (enable_deepbind) {
607 flags |= RTLD_DEEPBIND;
614 case SWRAP_LIBSOCKET:
615 #ifdef HAVE_LIBSOCKET
616 handle = swrap.libc.socket_handle;
617 if (handle == NULL) {
618 for (i = 10; i >= 0; i--) {
619 char soname[256] = {0};
621 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
622 handle = dlopen(soname, flags);
623 if (handle != NULL) {
628 swrap.libc.socket_handle = handle;
634 handle = swrap.libc.handle;
636 if (handle == NULL) {
637 handle = dlopen(LIBC_SO, flags);
639 swrap.libc.handle = handle;
642 if (handle == NULL) {
643 for (i = 10; i >= 0; i--) {
644 char soname[256] = {0};
646 snprintf(soname, sizeof(soname), "libc.so.%d", i);
647 handle = dlopen(soname, flags);
648 if (handle != NULL) {
653 swrap.libc.handle = handle;
658 if (handle == NULL) {
660 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
662 SWRAP_LOG(SWRAP_LOG_ERROR,
663 "Failed to dlopen library: %s\n",
672 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
677 handle = swrap_load_lib_handle(lib);
679 func = dlsym(handle, fn_name);
681 SWRAP_LOG(SWRAP_LOG_ERROR,
682 "Failed to find %s: %s\n",
688 SWRAP_LOG(SWRAP_LOG_TRACE,
696 static void swrap_mutex_lock(pthread_mutex_t *mutex)
700 ret = pthread_mutex_lock(mutex);
702 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
707 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
711 ret = pthread_mutex_unlock(mutex);
713 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
719 * These macros have a thread race condition on purpose!
721 * This is an optimization to avoid locking each time we check if the symbol is
724 #define swrap_bind_symbol_libc(sym_name) \
725 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
726 swrap_mutex_lock(&libc_symbol_binding_mutex); \
727 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
728 swrap.libc.symbols._libc_##sym_name.obj = \
729 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
731 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
734 #define swrap_bind_symbol_libsocket(sym_name) \
735 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
736 swrap_mutex_lock(&libc_symbol_binding_mutex); \
737 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
738 swrap.libc.symbols._libc_##sym_name.obj = \
739 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
741 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
744 #define swrap_bind_symbol_libnsl(sym_name) \
745 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
746 swrap_mutex_lock(&libc_symbol_binding_mutex); \
747 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
748 swrap.libc.symbols._libc_##sym_name.obj = \
749 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
751 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
754 /****************************************************************************
756 ****************************************************************************
758 * Functions especially from libc need to be loaded individually, you can't
759 * load all at once or gdb will segfault at startup. The same applies to
760 * valgrind and has probably something todo with with the linker. So we need
761 * load each function at the point it is called the first time.
763 ****************************************************************************/
766 static int libc_accept4(int sockfd,
767 struct sockaddr *addr,
771 swrap_bind_symbol_libsocket(accept4);
773 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
776 #else /* HAVE_ACCEPT4 */
778 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
780 swrap_bind_symbol_libsocket(accept);
782 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
784 #endif /* HAVE_ACCEPT4 */
786 static int libc_bind(int sockfd,
787 const struct sockaddr *addr,
790 swrap_bind_symbol_libsocket(bind);
792 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
795 static int libc_close(int fd)
797 swrap_bind_symbol_libc(close);
799 return swrap.libc.symbols._libc_close.f(fd);
802 static int libc_connect(int sockfd,
803 const struct sockaddr *addr,
806 swrap_bind_symbol_libsocket(connect);
808 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
811 static int libc_dup(int fd)
813 swrap_bind_symbol_libc(dup);
815 return swrap.libc.symbols._libc_dup.f(fd);
818 static int libc_dup2(int oldfd, int newfd)
820 swrap_bind_symbol_libc(dup2);
822 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
826 static int libc_eventfd(int count, int flags)
828 swrap_bind_symbol_libc(eventfd);
830 return swrap.libc.symbols._libc_eventfd.f(count, flags);
834 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
835 static int libc_vfcntl(int fd, int cmd, va_list ap)
840 swrap_bind_symbol_libc(fcntl);
842 arg = va_arg(ap, void *);
844 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
849 static int libc_getpeername(int sockfd,
850 struct sockaddr *addr,
853 swrap_bind_symbol_libsocket(getpeername);
855 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
858 static int libc_getsockname(int sockfd,
859 struct sockaddr *addr,
862 swrap_bind_symbol_libsocket(getsockname);
864 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
867 static int libc_getsockopt(int sockfd,
873 swrap_bind_symbol_libsocket(getsockopt);
875 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
882 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
883 static int libc_vioctl(int d, unsigned long int request, va_list ap)
888 swrap_bind_symbol_libc(ioctl);
890 arg = va_arg(ap, void *);
892 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
897 static int libc_listen(int sockfd, int backlog)
899 swrap_bind_symbol_libsocket(listen);
901 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
904 static FILE *libc_fopen(const char *name, const char *mode)
906 swrap_bind_symbol_libc(fopen);
908 return swrap.libc.symbols._libc_fopen.f(name, mode);
912 static FILE *libc_fopen64(const char *name, const char *mode)
914 swrap_bind_symbol_libc(fopen64);
916 return swrap.libc.symbols._libc_fopen64.f(name, mode);
918 #endif /* HAVE_FOPEN64 */
920 static int libc_vopen(const char *pathname, int flags, va_list ap)
925 swrap_bind_symbol_libc(open);
927 if (flags & O_CREAT) {
928 mode = va_arg(ap, int);
930 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
935 static int libc_open(const char *pathname, int flags, ...)
941 fd = libc_vopen(pathname, flags, ap);
948 static int libc_vopen64(const char *pathname, int flags, va_list ap)
953 swrap_bind_symbol_libc(open64);
955 if (flags & O_CREAT) {
956 mode = va_arg(ap, int);
958 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
962 #endif /* HAVE_OPEN64 */
964 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
969 swrap_bind_symbol_libc(openat);
971 if (flags & O_CREAT) {
972 mode = va_arg(ap, int);
974 fd = swrap.libc.symbols._libc_openat.f(dirfd,
983 static int libc_openat(int dirfd, const char *path, int flags, ...)
989 fd = libc_vopenat(dirfd, path, flags, ap);
996 static int libc_pipe(int pipefd[2])
998 swrap_bind_symbol_libsocket(pipe);
1000 return swrap.libc.symbols._libc_pipe.f(pipefd);
1003 static int libc_read(int fd, void *buf, size_t count)
1005 swrap_bind_symbol_libc(read);
1007 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1010 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1012 swrap_bind_symbol_libsocket(readv);
1014 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1017 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1019 swrap_bind_symbol_libsocket(recv);
1021 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1024 static int libc_recvfrom(int sockfd,
1028 struct sockaddr *src_addr,
1031 swrap_bind_symbol_libsocket(recvfrom);
1033 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1041 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1043 swrap_bind_symbol_libsocket(recvmsg);
1045 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1048 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1050 swrap_bind_symbol_libsocket(send);
1052 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1055 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1057 swrap_bind_symbol_libsocket(sendmsg);
1059 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1062 static int libc_sendto(int sockfd,
1066 const struct sockaddr *dst_addr,
1069 swrap_bind_symbol_libsocket(sendto);
1071 return swrap.libc.symbols._libc_sendto.f(sockfd,
1079 static int libc_setsockopt(int sockfd,
1085 swrap_bind_symbol_libsocket(setsockopt);
1087 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1094 #ifdef HAVE_SIGNALFD
1095 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1097 swrap_bind_symbol_libsocket(signalfd);
1099 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1103 static int libc_socket(int domain, int type, int protocol)
1105 swrap_bind_symbol_libsocket(socket);
1107 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1110 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1112 swrap_bind_symbol_libsocket(socketpair);
1114 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1117 #ifdef HAVE_TIMERFD_CREATE
1118 static int libc_timerfd_create(int clockid, int flags)
1120 swrap_bind_symbol_libc(timerfd_create);
1122 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1126 static ssize_t libc_write(int fd, const void *buf, size_t count)
1128 swrap_bind_symbol_libc(write);
1130 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1133 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1135 swrap_bind_symbol_libsocket(writev);
1137 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1140 /* DO NOT call this function during library initialization! */
1141 static void swrap_bind_symbol_all(void)
1144 swrap_bind_symbol_libsocket(accept4);
1146 swrap_bind_symbol_libsocket(accept);
1148 swrap_bind_symbol_libsocket(bind);
1149 swrap_bind_symbol_libc(close);
1150 swrap_bind_symbol_libsocket(connect);
1151 swrap_bind_symbol_libc(dup);
1152 swrap_bind_symbol_libc(dup2);
1153 swrap_bind_symbol_libc(fcntl);
1154 swrap_bind_symbol_libc(fopen);
1156 swrap_bind_symbol_libc(fopen64);
1159 swrap_bind_symbol_libc(eventfd);
1161 swrap_bind_symbol_libsocket(getpeername);
1162 swrap_bind_symbol_libsocket(getsockname);
1163 swrap_bind_symbol_libsocket(getsockopt);
1164 swrap_bind_symbol_libc(ioctl);
1165 swrap_bind_symbol_libsocket(listen);
1166 swrap_bind_symbol_libc(open);
1168 swrap_bind_symbol_libc(open64);
1170 swrap_bind_symbol_libc(openat);
1171 swrap_bind_symbol_libsocket(pipe);
1172 swrap_bind_symbol_libc(read);
1173 swrap_bind_symbol_libsocket(readv);
1174 swrap_bind_symbol_libsocket(recv);
1175 swrap_bind_symbol_libsocket(recvfrom);
1176 swrap_bind_symbol_libsocket(recvmsg);
1177 swrap_bind_symbol_libsocket(send);
1178 swrap_bind_symbol_libsocket(sendmsg);
1179 swrap_bind_symbol_libsocket(sendto);
1180 swrap_bind_symbol_libsocket(setsockopt);
1181 #ifdef HAVE_SIGNALFD
1182 swrap_bind_symbol_libsocket(signalfd);
1184 swrap_bind_symbol_libsocket(socket);
1185 swrap_bind_symbol_libsocket(socketpair);
1186 #ifdef HAVE_TIMERFD_CREATE
1187 swrap_bind_symbol_libc(timerfd_create);
1189 swrap_bind_symbol_libc(write);
1190 swrap_bind_symbol_libsocket(writev);
1193 /*********************************************************
1194 * SWRAP HELPER FUNCTIONS
1195 *********************************************************/
1201 static const struct in6_addr *swrap_ipv6(void)
1203 static struct in6_addr v;
1204 static int initialized;
1212 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1221 static void set_port(int family, int prt, struct swrap_address *addr)
1225 addr->sa.in.sin_port = htons(prt);
1229 addr->sa.in6.sin6_port = htons(prt);
1235 static size_t socket_length(int family)
1239 return sizeof(struct sockaddr_in);
1242 return sizeof(struct sockaddr_in6);
1248 static struct socket_info *swrap_get_socket_info(int si_index)
1250 return (struct socket_info *)(&(sockets[si_index].info));
1253 static int swrap_get_refcount(struct socket_info *si)
1255 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1256 return sic->meta.refcount;
1259 static void swrap_inc_refcount(struct socket_info *si)
1261 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1263 sic->meta.refcount += 1;
1266 static void swrap_dec_refcount(struct socket_info *si)
1268 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1270 sic->meta.refcount -= 1;
1273 static int swrap_get_next_free(struct socket_info *si)
1275 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1277 return sic->meta.next_free;
1280 static void swrap_set_next_free(struct socket_info *si, int next_free)
1282 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1284 sic->meta.next_free = next_free;
1287 static char *socket_wrapper_dir(void)
1289 char *swrap_dir = NULL;
1290 char *s = getenv("SOCKET_WRAPPER_DIR");
1296 swrap_dir = realpath(s, NULL);
1297 if (swrap_dir == NULL) {
1298 SWRAP_LOG(SWRAP_LOG_ERROR,
1299 "Unable to resolve socket_wrapper dir path: %s",
1304 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1308 static unsigned int socket_wrapper_mtu(void)
1310 static unsigned int max_mtu = 0;
1315 swrap_mutex_lock(&mtu_update_mutex);
1321 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1323 s = getenv("SOCKET_WRAPPER_MTU");
1328 tmp = strtol(s, &endp, 10);
1333 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1339 swrap_mutex_unlock(&mtu_update_mutex);
1343 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1345 pthread_mutexattr_t ma;
1348 ret = pthread_mutexattr_init(&ma);
1353 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1358 ret = pthread_mutex_init(m, &ma);
1361 pthread_mutexattr_destroy(&ma);
1366 static size_t socket_wrapper_max_sockets(void)
1372 if (socket_info_max != 0) {
1373 return socket_info_max;
1376 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1378 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1379 if (s == NULL || s[0] == '\0') {
1383 tmp = strtoul(s, &endp, 10);
1388 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1389 SWRAP_LOG(SWRAP_LOG_ERROR,
1390 "Invalid number of sockets specified, "
1391 "using default (%zu)",
1395 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1396 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1397 SWRAP_LOG(SWRAP_LOG_ERROR,
1398 "Invalid number of sockets specified, "
1399 "using maximum (%zu).",
1403 socket_info_max = tmp;
1406 return socket_info_max;
1409 static void socket_wrapper_init_fds_idx(void)
1414 if (socket_fds_idx != NULL) {
1418 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1420 SWRAP_LOG(SWRAP_LOG_ERROR,
1421 "Failed to allocate socket fds index array: %s",
1426 for (i = 0; i < socket_fds_max; i++) {
1430 socket_fds_idx = tmp;
1433 static void socket_wrapper_init_sockets(void)
1439 swrap_mutex_lock(&sockets_mutex);
1441 if (sockets != NULL) {
1442 swrap_mutex_unlock(&sockets_mutex);
1446 socket_wrapper_init_fds_idx();
1448 /* Needs to be called inside the sockets_mutex lock here. */
1449 max_sockets = socket_wrapper_max_sockets();
1451 sockets = (struct socket_info_container *)calloc(max_sockets,
1452 sizeof(struct socket_info_container));
1454 if (sockets == NULL) {
1455 SWRAP_LOG(SWRAP_LOG_ERROR,
1456 "Failed to allocate sockets array: %s",
1458 swrap_mutex_unlock(&sockets_mutex);
1462 swrap_mutex_lock(&first_free_mutex);
1466 for (i = 0; i < max_sockets; i++) {
1467 swrap_set_next_free(&sockets[i].info, i+1);
1468 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1470 SWRAP_LOG(SWRAP_LOG_ERROR,
1471 "Failed to initialize pthread mutex");
1476 /* mark the end of the free list */
1477 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1479 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1481 SWRAP_LOG(SWRAP_LOG_ERROR,
1482 "Failed to initialize pthread mutex");
1486 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1488 SWRAP_LOG(SWRAP_LOG_ERROR,
1489 "Failed to initialize pthread mutex");
1493 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1495 SWRAP_LOG(SWRAP_LOG_ERROR,
1496 "Failed to initialize pthread mutex");
1501 swrap_mutex_unlock(&first_free_mutex);
1502 swrap_mutex_unlock(&sockets_mutex);
1508 bool socket_wrapper_enabled(void)
1510 char *s = socket_wrapper_dir();
1518 socket_wrapper_init_sockets();
1523 static unsigned int socket_wrapper_default_iface(void)
1525 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1528 if (sscanf(s, "%u", &iface) == 1) {
1529 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1535 return 1;/* 127.0.0.1 */
1538 static void set_socket_info_index(int fd, int idx)
1540 socket_fds_idx[fd] = idx;
1541 /* This builtin issues a full memory barrier. */
1542 __sync_synchronize();
1545 static void reset_socket_info_index(int fd)
1547 set_socket_info_index(fd, -1);
1550 static int find_socket_info_index(int fd)
1556 if (socket_fds_idx == NULL) {
1560 if ((size_t)fd >= socket_fds_max) {
1562 * Do not add a log here as some applications do stupid things
1565 * for (fd = 0; fd <= getdtablesize(); fd++) {
1569 * This would produce millions of lines of debug messages.
1572 SWRAP_LOG(SWRAP_LOG_ERROR,
1573 "Looking for a socket info for the fd %d is over the "
1574 "max socket index limit of %zu.",
1581 /* This builtin issues a full memory barrier. */
1582 __sync_synchronize();
1583 return socket_fds_idx[fd];
1586 static int swrap_add_socket_info(struct socket_info *si_input)
1588 struct socket_info *si = NULL;
1591 if (si_input == NULL) {
1596 swrap_mutex_lock(&first_free_mutex);
1597 if (first_free == -1) {
1602 si_index = first_free;
1603 si = swrap_get_socket_info(si_index);
1607 first_free = swrap_get_next_free(si);
1609 swrap_inc_refcount(si);
1611 SWRAP_UNLOCK_SI(si);
1614 swrap_mutex_unlock(&first_free_mutex);
1619 static int swrap_create_socket(struct socket_info *si, int fd)
1623 if ((size_t)fd >= socket_fds_max) {
1624 SWRAP_LOG(SWRAP_LOG_ERROR,
1625 "The max socket index limit of %zu has been reached, "
1632 idx = swrap_add_socket_info(si);
1637 set_socket_info_index(fd, idx);
1642 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1649 p = strrchr(un->sun_path, '/');
1650 if (p) p++; else p = un->sun_path;
1652 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1657 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1660 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1671 case SOCKET_TYPE_CHAR_TCP:
1672 case SOCKET_TYPE_CHAR_UDP: {
1673 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1675 if ((*len) < sizeof(*in2)) {
1680 memset(in2, 0, sizeof(*in2));
1681 in2->sin_family = AF_INET;
1682 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1683 in2->sin_port = htons(prt);
1685 *len = sizeof(*in2);
1689 case SOCKET_TYPE_CHAR_TCP_V6:
1690 case SOCKET_TYPE_CHAR_UDP_V6: {
1691 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1693 if ((*len) < sizeof(*in2)) {
1698 memset(in2, 0, sizeof(*in2));
1699 in2->sin6_family = AF_INET6;
1700 in2->sin6_addr = *swrap_ipv6();
1701 in2->sin6_addr.s6_addr[15] = iface;
1702 in2->sin6_port = htons(prt);
1704 *len = sizeof(*in2);
1716 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1723 char *swrap_dir = NULL;
1725 if (bcast) *bcast = 0;
1727 switch (inaddr->sa_family) {
1729 const struct sockaddr_in *in =
1730 (const struct sockaddr_in *)(const void *)inaddr;
1731 unsigned int addr = ntohl(in->sin_addr.s_addr);
1738 u_type = SOCKET_TYPE_CHAR_TCP;
1741 u_type = SOCKET_TYPE_CHAR_UDP;
1742 a_type = SOCKET_TYPE_CHAR_UDP;
1743 b_type = SOCKET_TYPE_CHAR_UDP;
1746 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1747 errno = ESOCKTNOSUPPORT;
1751 prt = ntohs(in->sin_port);
1752 if (a_type && addr == 0xFFFFFFFF) {
1753 /* 255.255.255.255 only udp */
1756 iface = socket_wrapper_default_iface();
1757 } else if (b_type && addr == 0x7FFFFFFF) {
1758 /* 127.255.255.255 only udp */
1761 iface = socket_wrapper_default_iface();
1762 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1766 iface = (addr & 0x000000FF);
1768 errno = ENETUNREACH;
1771 if (bcast) *bcast = is_bcast;
1776 const struct sockaddr_in6 *in =
1777 (const struct sockaddr_in6 *)(const void *)inaddr;
1778 struct in6_addr cmp1, cmp2;
1782 type = SOCKET_TYPE_CHAR_TCP_V6;
1785 type = SOCKET_TYPE_CHAR_UDP_V6;
1788 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1789 errno = ESOCKTNOSUPPORT;
1793 /* XXX no multicast/broadcast */
1795 prt = ntohs(in->sin6_port);
1797 cmp1 = *swrap_ipv6();
1798 cmp2 = in->sin6_addr;
1799 cmp2.s6_addr[15] = 0;
1800 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1801 iface = in->sin6_addr.s6_addr[15];
1803 errno = ENETUNREACH;
1811 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1812 errno = ENETUNREACH;
1817 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1822 swrap_dir = socket_wrapper_dir();
1825 snprintf(un->sun_path, sizeof(un->sun_path),
1826 "%s/EINVAL", swrap_dir);
1827 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1828 SAFE_FREE(swrap_dir);
1829 /* the caller need to do more processing */
1833 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1834 swrap_dir, type, iface, prt);
1835 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1837 SAFE_FREE(swrap_dir);
1842 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1850 char *swrap_dir = NULL;
1852 if (bcast) *bcast = 0;
1854 switch (si->family) {
1856 const struct sockaddr_in *in =
1857 (const struct sockaddr_in *)(const void *)inaddr;
1858 unsigned int addr = ntohl(in->sin_addr.s_addr);
1864 prt = ntohs(in->sin_port);
1868 u_type = SOCKET_TYPE_CHAR_TCP;
1869 d_type = SOCKET_TYPE_CHAR_TCP;
1872 u_type = SOCKET_TYPE_CHAR_UDP;
1873 d_type = SOCKET_TYPE_CHAR_UDP;
1874 a_type = SOCKET_TYPE_CHAR_UDP;
1875 b_type = SOCKET_TYPE_CHAR_UDP;
1878 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1879 errno = ESOCKTNOSUPPORT;
1887 iface = socket_wrapper_default_iface();
1888 } else if (a_type && addr == 0xFFFFFFFF) {
1889 /* 255.255.255.255 only udp */
1892 iface = socket_wrapper_default_iface();
1893 } else if (b_type && addr == 0x7FFFFFFF) {
1894 /* 127.255.255.255 only udp */
1897 iface = socket_wrapper_default_iface();
1898 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1902 iface = (addr & 0x000000FF);
1904 errno = EADDRNOTAVAIL;
1908 /* Store the bind address for connect() */
1909 if (si->bindname.sa_socklen == 0) {
1910 struct sockaddr_in bind_in;
1911 socklen_t blen = sizeof(struct sockaddr_in);
1913 ZERO_STRUCT(bind_in);
1914 bind_in.sin_family = in->sin_family;
1915 bind_in.sin_port = in->sin_port;
1916 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1918 si->bindname.sa_socklen = blen;
1919 memcpy(&si->bindname.sa.in, &bind_in, blen);
1926 const struct sockaddr_in6 *in =
1927 (const struct sockaddr_in6 *)(const void *)inaddr;
1928 struct in6_addr cmp1, cmp2;
1932 type = SOCKET_TYPE_CHAR_TCP_V6;
1935 type = SOCKET_TYPE_CHAR_UDP_V6;
1938 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1939 errno = ESOCKTNOSUPPORT;
1943 /* XXX no multicast/broadcast */
1945 prt = ntohs(in->sin6_port);
1947 cmp1 = *swrap_ipv6();
1948 cmp2 = in->sin6_addr;
1949 cmp2.s6_addr[15] = 0;
1950 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1951 iface = socket_wrapper_default_iface();
1952 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1953 iface = in->sin6_addr.s6_addr[15];
1955 errno = EADDRNOTAVAIL;
1959 /* Store the bind address for connect() */
1960 if (si->bindname.sa_socklen == 0) {
1961 struct sockaddr_in6 bind_in;
1962 socklen_t blen = sizeof(struct sockaddr_in6);
1964 ZERO_STRUCT(bind_in);
1965 bind_in.sin6_family = in->sin6_family;
1966 bind_in.sin6_port = in->sin6_port;
1968 bind_in.sin6_addr = *swrap_ipv6();
1969 bind_in.sin6_addr.s6_addr[15] = iface;
1971 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1972 si->bindname.sa_socklen = blen;
1979 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1980 errno = EADDRNOTAVAIL;
1985 if (bcast) *bcast = is_bcast;
1987 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1992 swrap_dir = socket_wrapper_dir();
1995 /* handle auto-allocation of ephemeral ports */
1996 for (prt = 5001; prt < 10000; prt++) {
1997 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1998 swrap_dir, type, iface, prt);
1999 if (stat(un->sun_path, &st) == 0) continue;
2001 set_port(si->family, prt, &si->myname);
2002 set_port(si->family, prt, &si->bindname);
2009 SAFE_FREE(swrap_dir);
2014 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
2015 swrap_dir, type, iface, prt);
2016 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2018 SAFE_FREE(swrap_dir);
2023 static struct socket_info *find_socket_info(int fd)
2025 int idx = find_socket_info_index(fd);
2031 return swrap_get_socket_info(idx);
2035 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2037 struct socket_info_fd *f;
2038 const struct socket_info *last_s = NULL;
2040 /* first catch invalid input */
2041 switch (sa->sa_family) {
2043 if (len < sizeof(struct sockaddr_in)) {
2049 if (len < sizeof(struct sockaddr_in6)) {
2059 for (f = socket_fds; f; f = f->next) {
2060 struct socket_info *s = swrap_get_socket_info(f->si_index);
2067 if (s->myname == NULL) {
2070 if (s->myname->sa_family != sa->sa_family) {
2073 switch (s->myname->sa_family) {
2075 struct sockaddr_in *sin1, *sin2;
2077 sin1 = (struct sockaddr_in *)s->myname;
2078 sin2 = (struct sockaddr_in *)sa;
2080 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2083 if (sin1->sin_port != sin2->sin_port) {
2086 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2096 struct sockaddr_in6 *sin1, *sin2;
2098 sin1 = (struct sockaddr_in6 *)s->myname;
2099 sin2 = (struct sockaddr_in6 *)sa;
2101 if (sin1->sin6_port != sin2->sin6_port) {
2104 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2126 static void swrap_remove_stale(int fd)
2128 struct socket_info *si;
2131 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2133 swrap_mutex_lock(&socket_reset_mutex);
2135 si_index = find_socket_info_index(fd);
2136 if (si_index == -1) {
2137 swrap_mutex_unlock(&socket_reset_mutex);
2141 reset_socket_info_index(fd);
2143 si = swrap_get_socket_info(si_index);
2145 swrap_mutex_lock(&first_free_mutex);
2148 swrap_dec_refcount(si);
2150 if (swrap_get_refcount(si) > 0) {
2154 if (si->un_addr.sun_path[0] != '\0') {
2155 unlink(si->un_addr.sun_path);
2158 swrap_set_next_free(si, first_free);
2159 first_free = si_index;
2162 SWRAP_UNLOCK_SI(si);
2163 swrap_mutex_unlock(&first_free_mutex);
2164 swrap_mutex_unlock(&socket_reset_mutex);
2167 static int sockaddr_convert_to_un(struct socket_info *si,
2168 const struct sockaddr *in_addr,
2170 struct sockaddr_un *out_addr,
2174 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2176 (void) in_len; /* unused */
2178 if (out_addr == NULL) {
2182 out->sa_family = AF_UNIX;
2183 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2184 out->sa_len = sizeof(*out_addr);
2187 switch (in_addr->sa_family) {
2189 const struct sockaddr_in *sin;
2190 if (si->family != AF_INET) {
2193 if (in_len < sizeof(struct sockaddr_in)) {
2196 sin = (const struct sockaddr_in *)(const void *)in_addr;
2197 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2202 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2203 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2218 errno = ESOCKTNOSUPPORT;
2222 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2224 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2230 errno = EAFNOSUPPORT;
2231 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2235 static int sockaddr_convert_from_un(const struct socket_info *si,
2236 const struct sockaddr_un *in_addr,
2237 socklen_t un_addrlen,
2239 struct sockaddr *out_addr,
2240 socklen_t *out_addrlen)
2244 if (out_addr == NULL || out_addrlen == NULL)
2247 if (un_addrlen == 0) {
2262 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2263 errno = ESOCKTNOSUPPORT;
2266 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2267 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2268 out_addr->sa_len = *out_addrlen;
2275 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2276 errno = EAFNOSUPPORT;
2280 enum swrap_packet_type {
2282 SWRAP_CONNECT_UNREACH,
2290 SWRAP_SENDTO_UNREACH,
2301 struct swrap_file_hdr {
2303 uint16_t version_major;
2304 uint16_t version_minor;
2307 uint32_t frame_max_len;
2308 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2311 #define SWRAP_FILE_HDR_SIZE 24
2313 struct swrap_packet_frame {
2315 uint32_t micro_seconds;
2316 uint32_t recorded_length;
2317 uint32_t full_length;
2319 #define SWRAP_PACKET_FRAME_SIZE 16
2321 union swrap_packet_ip {
2325 uint16_t packet_length;
2326 uint16_t identification;
2331 uint16_t hdr_checksum;
2335 #define SWRAP_PACKET_IP_V4_SIZE 20
2338 uint8_t flow_label_high;
2339 uint16_t flow_label_low;
2340 uint16_t payload_length;
2341 uint8_t next_header;
2343 uint8_t src_addr[16];
2344 uint8_t dest_addr[16];
2346 #define SWRAP_PACKET_IP_V6_SIZE 40
2348 #define SWRAP_PACKET_IP_SIZE 40
2350 union swrap_packet_payload {
2352 uint16_t source_port;
2362 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2364 uint16_t source_port;
2369 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2376 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2383 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2385 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2387 #define SWRAP_PACKET_MIN_ALLOC \
2388 (SWRAP_PACKET_FRAME_SIZE + \
2389 SWRAP_PACKET_IP_SIZE + \
2390 SWRAP_PACKET_PAYLOAD_SIZE)
2392 static const char *swrap_pcap_init_file(void)
2394 static int initialized = 0;
2395 static const char *s = NULL;
2396 static const struct swrap_file_hdr h;
2397 static const struct swrap_packet_frame f;
2398 static const union swrap_packet_ip i;
2399 static const union swrap_packet_payload p;
2401 if (initialized == 1) {
2407 * TODO: don't use the structs use plain buffer offsets
2408 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2410 * for now make sure we disable PCAP support
2411 * if the struct has alignment!
2413 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2416 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2419 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2422 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2425 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2428 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2431 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2434 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2437 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2440 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2444 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2448 if (strncmp(s, "./", 2) == 0) {
2454 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2455 const struct sockaddr *src,
2456 const struct sockaddr *dest,
2458 const uint8_t *payload,
2460 unsigned long tcp_seqno,
2461 unsigned long tcp_ack,
2462 unsigned char tcp_ctl,
2464 size_t *_packet_len)
2468 struct swrap_packet_frame *frame;
2469 union swrap_packet_ip *ip;
2470 union swrap_packet_payload *pay;
2473 size_t nonwire_len = sizeof(*frame);
2474 size_t wire_hdr_len = 0;
2475 size_t wire_len = 0;
2476 size_t ip_hdr_len = 0;
2477 size_t icmp_hdr_len = 0;
2478 size_t icmp_truncate_len = 0;
2479 uint8_t protocol = 0, icmp_protocol = 0;
2480 const struct sockaddr_in *src_in = NULL;
2481 const struct sockaddr_in *dest_in = NULL;
2483 const struct sockaddr_in6 *src_in6 = NULL;
2484 const struct sockaddr_in6 *dest_in6 = NULL;
2489 switch (src->sa_family) {
2491 src_in = (const struct sockaddr_in *)(const void *)src;
2492 dest_in = (const struct sockaddr_in *)(const void *)dest;
2493 src_port = src_in->sin_port;
2494 dest_port = dest_in->sin_port;
2495 ip_hdr_len = sizeof(ip->v4);
2499 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2500 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2501 src_port = src_in6->sin6_port;
2502 dest_port = dest_in6->sin6_port;
2503 ip_hdr_len = sizeof(ip->v6);
2510 switch (socket_type) {
2512 protocol = 0x06; /* TCP */
2513 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2514 wire_len = wire_hdr_len + payload_len;
2518 protocol = 0x11; /* UDP */
2519 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2520 wire_len = wire_hdr_len + payload_len;
2528 icmp_protocol = protocol;
2529 switch (src->sa_family) {
2531 protocol = 0x01; /* ICMPv4 */
2532 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2536 protocol = 0x3A; /* ICMPv6 */
2537 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2541 if (wire_len > 64 ) {
2542 icmp_truncate_len = wire_len - 64;
2544 wire_hdr_len += icmp_hdr_len;
2545 wire_len += icmp_hdr_len;
2548 packet_len = nonwire_len + wire_len;
2549 alloc_len = packet_len;
2550 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2551 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2554 base = (uint8_t *)calloc(1, alloc_len);
2561 frame = (struct swrap_packet_frame *)(void *)buf;
2562 frame->seconds = tval->tv_sec;
2563 frame->micro_seconds = tval->tv_usec;
2564 frame->recorded_length = wire_len - icmp_truncate_len;
2565 frame->full_length = wire_len - icmp_truncate_len;
2566 buf += SWRAP_PACKET_FRAME_SIZE;
2568 ip = (union swrap_packet_ip *)(void *)buf;
2569 switch (src->sa_family) {
2571 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2573 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2574 ip->v4.identification = htons(0xFFFF);
2575 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2576 ip->v4.fragment = htons(0x0000);
2578 ip->v4.protocol = protocol;
2579 ip->v4.hdr_checksum = htons(0x0000);
2580 ip->v4.src_addr = src_in->sin_addr.s_addr;
2581 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2582 buf += SWRAP_PACKET_IP_V4_SIZE;
2586 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2587 ip->v6.flow_label_high = 0x00;
2588 ip->v6.flow_label_low = 0x0000;
2589 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2590 ip->v6.next_header = protocol;
2591 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2592 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2593 buf += SWRAP_PACKET_IP_V6_SIZE;
2599 pay = (union swrap_packet_payload *)(void *)buf;
2600 switch (src->sa_family) {
2602 pay->icmp4.type = 0x03; /* destination unreachable */
2603 pay->icmp4.code = 0x01; /* host unreachable */
2604 pay->icmp4.checksum = htons(0x0000);
2605 pay->icmp4.unused = htonl(0x00000000);
2606 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2608 /* set the ip header in the ICMP payload */
2609 ip = (union swrap_packet_ip *)(void *)buf;
2610 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2612 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2613 ip->v4.identification = htons(0xFFFF);
2614 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2615 ip->v4.fragment = htons(0x0000);
2617 ip->v4.protocol = icmp_protocol;
2618 ip->v4.hdr_checksum = htons(0x0000);
2619 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2620 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2621 buf += SWRAP_PACKET_IP_V4_SIZE;
2623 src_port = dest_in->sin_port;
2624 dest_port = src_in->sin_port;
2628 pay->icmp6.type = 0x01; /* destination unreachable */
2629 pay->icmp6.code = 0x03; /* address unreachable */
2630 pay->icmp6.checksum = htons(0x0000);
2631 pay->icmp6.unused = htonl(0x00000000);
2632 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2634 /* set the ip header in the ICMP payload */
2635 ip = (union swrap_packet_ip *)(void *)buf;
2636 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2637 ip->v6.flow_label_high = 0x00;
2638 ip->v6.flow_label_low = 0x0000;
2639 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2640 ip->v6.next_header = protocol;
2641 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2642 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2643 buf += SWRAP_PACKET_IP_V6_SIZE;
2645 src_port = dest_in6->sin6_port;
2646 dest_port = src_in6->sin6_port;
2652 pay = (union swrap_packet_payload *)(void *)buf;
2654 switch (socket_type) {
2656 pay->tcp.source_port = src_port;
2657 pay->tcp.dest_port = dest_port;
2658 pay->tcp.seq_num = htonl(tcp_seqno);
2659 pay->tcp.ack_num = htonl(tcp_ack);
2660 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2661 pay->tcp.control = tcp_ctl;
2662 pay->tcp.window = htons(0x7FFF);
2663 pay->tcp.checksum = htons(0x0000);
2664 pay->tcp.urg = htons(0x0000);
2665 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2670 pay->udp.source_port = src_port;
2671 pay->udp.dest_port = dest_port;
2672 pay->udp.length = htons(8 + payload_len);
2673 pay->udp.checksum = htons(0x0000);
2674 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2679 if (payload && payload_len > 0) {
2680 memcpy(buf, payload, payload_len);
2683 *_packet_len = packet_len - icmp_truncate_len;
2687 static int swrap_pcap_get_fd(const char *fname)
2695 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2697 struct swrap_file_hdr file_hdr;
2698 file_hdr.magic = 0xA1B2C3D4;
2699 file_hdr.version_major = 0x0002;
2700 file_hdr.version_minor = 0x0004;
2701 file_hdr.timezone = 0x00000000;
2702 file_hdr.sigfigs = 0x00000000;
2703 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2704 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2706 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2713 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2718 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2719 const struct sockaddr *addr,
2720 enum swrap_packet_type type,
2721 const void *buf, size_t len,
2724 const struct sockaddr *src_addr;
2725 const struct sockaddr *dest_addr;
2726 unsigned long tcp_seqno = 0;
2727 unsigned long tcp_ack = 0;
2728 unsigned char tcp_ctl = 0;
2729 int unreachable = 0;
2733 switch (si->family) {
2745 case SWRAP_CONNECT_SEND:
2746 if (si->type != SOCK_STREAM) {
2750 src_addr = &si->myname.sa.s;
2753 tcp_seqno = si->io.pck_snd;
2754 tcp_ack = si->io.pck_rcv;
2755 tcp_ctl = 0x02; /* SYN */
2757 si->io.pck_snd += 1;
2761 case SWRAP_CONNECT_RECV:
2762 if (si->type != SOCK_STREAM) {
2766 dest_addr = &si->myname.sa.s;
2769 tcp_seqno = si->io.pck_rcv;
2770 tcp_ack = si->io.pck_snd;
2771 tcp_ctl = 0x12; /** SYN,ACK */
2773 si->io.pck_rcv += 1;
2777 case SWRAP_CONNECT_UNREACH:
2778 if (si->type != SOCK_STREAM) {
2782 dest_addr = &si->myname.sa.s;
2785 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2786 tcp_seqno = si->io.pck_snd - 1;
2787 tcp_ack = si->io.pck_rcv;
2788 tcp_ctl = 0x02; /* SYN */
2793 case SWRAP_CONNECT_ACK:
2794 if (si->type != SOCK_STREAM) {
2798 src_addr = &si->myname.sa.s;
2801 tcp_seqno = si->io.pck_snd;
2802 tcp_ack = si->io.pck_rcv;
2803 tcp_ctl = 0x10; /* ACK */
2807 case SWRAP_ACCEPT_SEND:
2808 if (si->type != SOCK_STREAM) {
2812 dest_addr = &si->myname.sa.s;
2815 tcp_seqno = si->io.pck_rcv;
2816 tcp_ack = si->io.pck_snd;
2817 tcp_ctl = 0x02; /* SYN */
2819 si->io.pck_rcv += 1;
2823 case SWRAP_ACCEPT_RECV:
2824 if (si->type != SOCK_STREAM) {
2828 src_addr = &si->myname.sa.s;
2831 tcp_seqno = si->io.pck_snd;
2832 tcp_ack = si->io.pck_rcv;
2833 tcp_ctl = 0x12; /* SYN,ACK */
2835 si->io.pck_snd += 1;
2839 case SWRAP_ACCEPT_ACK:
2840 if (si->type != SOCK_STREAM) {
2844 dest_addr = &si->myname.sa.s;
2847 tcp_seqno = si->io.pck_rcv;
2848 tcp_ack = si->io.pck_snd;
2849 tcp_ctl = 0x10; /* ACK */
2854 src_addr = &si->myname.sa.s;
2855 dest_addr = &si->peername.sa.s;
2857 tcp_seqno = si->io.pck_snd;
2858 tcp_ack = si->io.pck_rcv;
2859 tcp_ctl = 0x18; /* PSH,ACK */
2861 si->io.pck_snd += len;
2865 case SWRAP_SEND_RST:
2866 dest_addr = &si->myname.sa.s;
2867 src_addr = &si->peername.sa.s;
2869 if (si->type == SOCK_DGRAM) {
2870 return swrap_pcap_marshall_packet(si,
2872 SWRAP_SENDTO_UNREACH,
2878 tcp_seqno = si->io.pck_rcv;
2879 tcp_ack = si->io.pck_snd;
2880 tcp_ctl = 0x14; /** RST,ACK */
2884 case SWRAP_PENDING_RST:
2885 dest_addr = &si->myname.sa.s;
2886 src_addr = &si->peername.sa.s;
2888 if (si->type == SOCK_DGRAM) {
2892 tcp_seqno = si->io.pck_rcv;
2893 tcp_ack = si->io.pck_snd;
2894 tcp_ctl = 0x14; /* RST,ACK */
2899 dest_addr = &si->myname.sa.s;
2900 src_addr = &si->peername.sa.s;
2902 tcp_seqno = si->io.pck_rcv;
2903 tcp_ack = si->io.pck_snd;
2904 tcp_ctl = 0x18; /* PSH,ACK */
2906 si->io.pck_rcv += len;
2910 case SWRAP_RECV_RST:
2911 dest_addr = &si->myname.sa.s;
2912 src_addr = &si->peername.sa.s;
2914 if (si->type == SOCK_DGRAM) {
2918 tcp_seqno = si->io.pck_rcv;
2919 tcp_ack = si->io.pck_snd;
2920 tcp_ctl = 0x14; /* RST,ACK */
2925 src_addr = &si->myname.sa.s;
2928 si->io.pck_snd += len;
2932 case SWRAP_SENDTO_UNREACH:
2933 dest_addr = &si->myname.sa.s;
2940 case SWRAP_RECVFROM:
2941 dest_addr = &si->myname.sa.s;
2944 si->io.pck_rcv += len;
2948 case SWRAP_CLOSE_SEND:
2949 if (si->type != SOCK_STREAM) {
2953 src_addr = &si->myname.sa.s;
2954 dest_addr = &si->peername.sa.s;
2956 tcp_seqno = si->io.pck_snd;
2957 tcp_ack = si->io.pck_rcv;
2958 tcp_ctl = 0x11; /* FIN, ACK */
2960 si->io.pck_snd += 1;
2964 case SWRAP_CLOSE_RECV:
2965 if (si->type != SOCK_STREAM) {
2969 dest_addr = &si->myname.sa.s;
2970 src_addr = &si->peername.sa.s;
2972 tcp_seqno = si->io.pck_rcv;
2973 tcp_ack = si->io.pck_snd;
2974 tcp_ctl = 0x11; /* FIN,ACK */
2976 si->io.pck_rcv += 1;
2980 case SWRAP_CLOSE_ACK:
2981 if (si->type != SOCK_STREAM) {
2985 src_addr = &si->myname.sa.s;
2986 dest_addr = &si->peername.sa.s;
2988 tcp_seqno = si->io.pck_snd;
2989 tcp_ack = si->io.pck_rcv;
2990 tcp_ctl = 0x10; /* ACK */
2997 swrapGetTimeOfDay(&tv);
2999 return swrap_pcap_packet_init(&tv,
3003 (const uint8_t *)buf,
3012 static void swrap_pcap_dump_packet(struct socket_info *si,
3013 const struct sockaddr *addr,
3014 enum swrap_packet_type type,
3015 const void *buf, size_t len)
3017 const char *file_name;
3019 size_t packet_len = 0;
3022 swrap_mutex_lock(&pcap_dump_mutex);
3024 file_name = swrap_pcap_init_file();
3029 packet = swrap_pcap_marshall_packet(si,
3035 if (packet == NULL) {
3039 fd = swrap_pcap_get_fd(file_name);
3041 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3050 swrap_mutex_unlock(&pcap_dump_mutex);
3053 /****************************************************************************
3055 ***************************************************************************/
3057 #ifdef HAVE_SIGNALFD
3058 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3062 rc = libc_signalfd(fd, mask, flags);
3064 swrap_remove_stale(fd);
3070 int signalfd(int fd, const sigset_t *mask, int flags)
3072 return swrap_signalfd(fd, mask, flags);
3076 /****************************************************************************
3078 ***************************************************************************/
3080 static int swrap_socket(int family, int type, int protocol)
3082 struct socket_info *si = NULL;
3083 struct socket_info _si = { 0 };
3086 int real_type = type;
3089 * Remove possible addition flags passed to socket() so
3090 * do not fail checking the type.
3091 * See https://lwn.net/Articles/281965/
3094 real_type &= ~SOCK_CLOEXEC;
3096 #ifdef SOCK_NONBLOCK
3097 real_type &= ~SOCK_NONBLOCK;
3100 if (!socket_wrapper_enabled()) {
3101 return libc_socket(family, type, protocol);
3112 #endif /* AF_NETLINK */
3115 #endif /* AF_PACKET */
3117 return libc_socket(family, type, protocol);
3119 errno = EAFNOSUPPORT;
3123 switch (real_type) {
3129 errno = EPROTONOSUPPORT;
3137 if (real_type == SOCK_STREAM) {
3142 if (real_type == SOCK_DGRAM) {
3147 errno = EPROTONOSUPPORT;
3152 * We must call libc_socket with type, from the caller, not the version
3153 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3155 fd = libc_socket(AF_UNIX, type, 0);
3161 /* Check if we have a stale fd and remove it */
3162 swrap_remove_stale(fd);
3165 si->family = family;
3167 /* however, the rest of the socket_wrapper code expects just
3168 * the type, not the flags */
3169 si->type = real_type;
3170 si->protocol = protocol;
3173 * Setup myname so getsockname() can succeed to find out the socket
3176 switch(si->family) {
3178 struct sockaddr_in sin = {
3179 .sin_family = AF_INET,
3182 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3183 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3188 struct sockaddr_in6 sin6 = {
3189 .sin6_family = AF_INET6,
3192 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3193 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3202 ret = swrap_create_socket(si, fd);
3207 SWRAP_LOG(SWRAP_LOG_TRACE,
3208 "Created %s socket for protocol %s, fd=%d",
3209 family == AF_INET ? "IPv4" : "IPv6",
3210 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3216 int socket(int family, int type, int protocol)
3218 return swrap_socket(family, type, protocol);
3221 /****************************************************************************
3223 ***************************************************************************/
3225 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3229 rc = libc_socketpair(family, type, protocol, sv);
3231 swrap_remove_stale(sv[0]);
3232 swrap_remove_stale(sv[1]);
3238 int socketpair(int family, int type, int protocol, int sv[2])
3240 return swrap_socketpair(family, type, protocol, sv);
3243 /****************************************************************************
3245 ***************************************************************************/
3247 #ifdef HAVE_TIMERFD_CREATE
3248 static int swrap_timerfd_create(int clockid, int flags)
3252 fd = libc_timerfd_create(clockid, flags);
3254 swrap_remove_stale(fd);
3260 int timerfd_create(int clockid, int flags)
3262 return swrap_timerfd_create(clockid, flags);
3266 /****************************************************************************
3268 ***************************************************************************/
3270 static int swrap_pipe(int pipefd[2])
3274 rc = libc_pipe(pipefd);
3276 swrap_remove_stale(pipefd[0]);
3277 swrap_remove_stale(pipefd[1]);
3283 int pipe(int pipefd[2])
3285 return swrap_pipe(pipefd);
3288 /****************************************************************************
3290 ***************************************************************************/
3292 static int swrap_accept(int s,
3293 struct sockaddr *addr,
3297 struct socket_info *parent_si, *child_si;
3298 struct socket_info new_si = { 0 };
3301 struct swrap_address un_addr = {
3302 .sa_socklen = sizeof(struct sockaddr_un),
3304 struct swrap_address un_my_addr = {
3305 .sa_socklen = sizeof(struct sockaddr_un),
3307 struct swrap_address in_addr = {
3308 .sa_socklen = sizeof(struct sockaddr_storage),
3310 struct swrap_address in_my_addr = {
3311 .sa_socklen = sizeof(struct sockaddr_storage),
3315 parent_si = find_socket_info(s);
3318 return libc_accept4(s, addr, addrlen, flags);
3321 return libc_accept(s, addr, addrlen);
3327 * prevent parent_si from being altered / closed
3330 SWRAP_LOCK_SI(parent_si);
3333 * assume out sockaddr have the same size as the in parent
3336 in_addr.sa_socklen = socket_length(parent_si->family);
3337 if (in_addr.sa_socklen <= 0) {
3338 SWRAP_UNLOCK_SI(parent_si);
3343 SWRAP_UNLOCK_SI(parent_si);
3346 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3349 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3352 if (errno == ENOTSOCK) {
3353 /* Remove stale fds */
3354 swrap_remove_stale(s);
3361 SWRAP_LOCK_SI(parent_si);
3363 ret = sockaddr_convert_from_un(parent_si,
3368 &in_addr.sa_socklen);
3370 SWRAP_UNLOCK_SI(parent_si);
3377 child_si->family = parent_si->family;
3378 child_si->type = parent_si->type;
3379 child_si->protocol = parent_si->protocol;
3380 child_si->bound = 1;
3381 child_si->is_server = 1;
3382 child_si->connected = 1;
3384 SWRAP_UNLOCK_SI(parent_si);
3386 child_si->peername = (struct swrap_address) {
3387 .sa_socklen = in_addr.sa_socklen,
3389 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3391 if (addr != NULL && addrlen != NULL) {
3392 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3394 memcpy(addr, &in_addr.sa.ss, copy_len);
3396 *addrlen = in_addr.sa_socklen;
3399 ret = libc_getsockname(fd,
3401 &un_my_addr.sa_socklen);
3407 ret = sockaddr_convert_from_un(child_si,
3409 un_my_addr.sa_socklen,
3412 &in_my_addr.sa_socklen);
3418 SWRAP_LOG(SWRAP_LOG_TRACE,
3419 "accept() path=%s, fd=%d",
3420 un_my_addr.sa.un.sun_path, s);
3422 child_si->myname = (struct swrap_address) {
3423 .sa_socklen = in_my_addr.sa_socklen,
3425 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3427 idx = swrap_create_socket(&new_si, fd);
3434 struct socket_info *si = swrap_get_socket_info(idx);
3437 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3438 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3439 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3440 SWRAP_UNLOCK_SI(si);
3447 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3449 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3453 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3454 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3456 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3459 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3462 static int autobind_start_init;
3463 static int autobind_start;
3465 /* using sendto() or connect() on an unbound socket would give the
3466 recipient no way to reply, as unlike UDP and TCP, a unix domain
3467 socket can't auto-assign ephemeral port numbers, so we need to
3469 Note: this might change the family from ipv6 to ipv4
3471 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3473 struct swrap_address un_addr = {
3474 .sa_socklen = sizeof(struct sockaddr_un),
3481 char *swrap_dir = NULL;
3483 swrap_mutex_lock(&autobind_start_mutex);
3485 if (autobind_start_init != 1) {
3486 autobind_start_init = 1;
3487 autobind_start = getpid();
3488 autobind_start %= 50000;
3489 autobind_start += 10000;
3492 un_addr.sa.un.sun_family = AF_UNIX;
3496 struct sockaddr_in in;
3500 type = SOCKET_TYPE_CHAR_TCP;
3503 type = SOCKET_TYPE_CHAR_UDP;
3506 errno = ESOCKTNOSUPPORT;
3511 memset(&in, 0, sizeof(in));
3512 in.sin_family = AF_INET;
3513 in.sin_addr.s_addr = htonl(127<<24 |
3514 socket_wrapper_default_iface());
3516 si->myname = (struct swrap_address) {
3517 .sa_socklen = sizeof(in),
3519 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3524 struct sockaddr_in6 in6;
3526 if (si->family != family) {
3527 errno = ENETUNREACH;
3534 type = SOCKET_TYPE_CHAR_TCP_V6;
3537 type = SOCKET_TYPE_CHAR_UDP_V6;
3540 errno = ESOCKTNOSUPPORT;
3545 memset(&in6, 0, sizeof(in6));
3546 in6.sin6_family = AF_INET6;
3547 in6.sin6_addr = *swrap_ipv6();
3548 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3550 si->myname = (struct swrap_address) {
3551 .sa_socklen = sizeof(in6),
3553 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3558 errno = ESOCKTNOSUPPORT;
3563 if (autobind_start > 60000) {
3564 autobind_start = 10000;
3567 swrap_dir = socket_wrapper_dir();
3569 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3570 port = autobind_start + i;
3571 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3572 "%s/"SOCKET_FORMAT, swrap_dir, type,
3573 socket_wrapper_default_iface(), port);
3574 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3576 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3581 si->un_addr = un_addr.sa.un;
3584 autobind_start = port + 1;
3587 if (i == SOCKET_MAX_SOCKETS) {
3588 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3589 "interface "SOCKET_FORMAT,
3592 socket_wrapper_default_iface(),
3599 si->family = family;
3600 set_port(si->family, port, &si->myname);
3605 SAFE_FREE(swrap_dir);
3606 swrap_mutex_unlock(&autobind_start_mutex);
3610 /****************************************************************************
3612 ***************************************************************************/
3614 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3618 struct swrap_address un_addr = {
3619 .sa_socklen = sizeof(struct sockaddr_un),
3621 struct socket_info *si = find_socket_info(s);
3625 return libc_connect(s, serv_addr, addrlen);
3630 if (si->bound == 0) {
3631 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3637 if (si->family != serv_addr->sa_family) {
3643 ret = sockaddr_convert_to_un(si, serv_addr,
3644 addrlen, &un_addr.sa.un, 0, &bcast);
3650 errno = ENETUNREACH;
3655 if (si->type == SOCK_DGRAM) {
3656 si->defer_connect = 1;
3659 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3661 ret = libc_connect(s,
3663 un_addr.sa_socklen);
3666 SWRAP_LOG(SWRAP_LOG_TRACE,
3667 "connect() path=%s, fd=%d",
3668 un_addr.sa.un.sun_path, s);
3671 /* to give better errors */
3672 if (ret == -1 && errno == ENOENT) {
3673 errno = EHOSTUNREACH;
3677 si->peername = (struct swrap_address) {
3678 .sa_socklen = addrlen,
3681 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3685 * When we connect() on a socket than we have to bind the
3686 * outgoing connection on the interface we use for the
3687 * transport. We already bound it on the right interface
3688 * but here we have to update the name so getsockname()
3689 * returns correct information.
3691 if (si->bindname.sa_socklen > 0) {
3692 si->myname = (struct swrap_address) {
3693 .sa_socklen = si->bindname.sa_socklen,
3696 memcpy(&si->myname.sa.ss,
3697 &si->bindname.sa.ss,
3698 si->bindname.sa_socklen);
3700 /* Cleanup bindname */
3701 si->bindname = (struct swrap_address) {
3706 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3707 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3709 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3713 SWRAP_UNLOCK_SI(si);
3717 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3719 return swrap_connect(s, serv_addr, addrlen);
3722 /****************************************************************************
3724 ***************************************************************************/
3726 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3729 struct swrap_address un_addr = {
3730 .sa_socklen = sizeof(struct sockaddr_un),
3732 struct socket_info *si = find_socket_info(s);
3739 return libc_bind(s, myaddr, addrlen);
3744 switch (si->family) {
3746 const struct sockaddr_in *sin;
3747 if (addrlen < sizeof(struct sockaddr_in)) {
3748 bind_error = EINVAL;
3752 sin = (const struct sockaddr_in *)(const void *)myaddr;
3754 if (sin->sin_family != AF_INET) {
3755 bind_error = EAFNOSUPPORT;
3758 /* special case for AF_UNSPEC */
3759 if (sin->sin_family == AF_UNSPEC &&
3760 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3769 const struct sockaddr_in6 *sin6;
3770 if (addrlen < sizeof(struct sockaddr_in6)) {
3771 bind_error = EINVAL;
3775 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3777 if (sin6->sin6_family != AF_INET6) {
3778 bind_error = EAFNOSUPPORT;
3785 bind_error = EINVAL;
3789 if (bind_error != 0) {
3796 in_use = check_addr_port_in_use(myaddr, addrlen);
3804 si->myname.sa_socklen = addrlen;
3805 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3807 ret = sockaddr_convert_to_un(si,
3817 unlink(un_addr.sa.un.sun_path);
3819 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3821 SWRAP_LOG(SWRAP_LOG_TRACE,
3822 "bind() path=%s, fd=%d",
3823 un_addr.sa.un.sun_path, s);
3830 SWRAP_UNLOCK_SI(si);
3835 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3837 return swrap_bind(s, myaddr, addrlen);
3840 /****************************************************************************
3842 ***************************************************************************/
3844 #ifdef HAVE_BINDRESVPORT
3845 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3847 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3849 struct swrap_address myaddr = {
3850 .sa_socklen = sizeof(struct sockaddr_storage),
3853 static uint16_t port;
3858 #define SWRAP_STARTPORT 600
3859 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3860 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3863 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3867 salen = myaddr.sa_socklen;
3870 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3876 memset(&myaddr.sa.ss, 0, salen);
3881 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3884 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3886 salen = sizeof(struct sockaddr_in);
3887 sinp->sin_port = htons(port);
3891 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3893 salen = sizeof(struct sockaddr_in6);
3894 sin6p->sin6_port = htons(port);
3898 errno = EAFNOSUPPORT;
3903 if (port > SWRAP_ENDPORT) {
3904 port = SWRAP_STARTPORT;
3907 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3908 if (rc == 0 || errno != EADDRINUSE) {
3916 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3918 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3922 /****************************************************************************
3924 ***************************************************************************/
3926 static int swrap_listen(int s, int backlog)
3929 struct socket_info *si = find_socket_info(s);
3932 return libc_listen(s, backlog);
3937 if (si->bound == 0) {
3938 ret = swrap_auto_bind(s, si, si->family);
3945 ret = libc_listen(s, backlog);
3948 SWRAP_UNLOCK_SI(si);
3953 int listen(int s, int backlog)
3955 return swrap_listen(s, backlog);
3958 /****************************************************************************
3960 ***************************************************************************/
3962 static FILE *swrap_fopen(const char *name, const char *mode)
3966 fp = libc_fopen(name, mode);
3968 int fd = fileno(fp);
3970 swrap_remove_stale(fd);
3976 FILE *fopen(const char *name, const char *mode)
3978 return swrap_fopen(name, mode);
3981 /****************************************************************************
3983 ***************************************************************************/
3986 static FILE *swrap_fopen64(const char *name, const char *mode)
3990 fp = libc_fopen64(name, mode);
3992 int fd = fileno(fp);
3994 swrap_remove_stale(fd);
4000 FILE *fopen64(const char *name, const char *mode)
4002 return swrap_fopen64(name, mode);
4004 #endif /* HAVE_FOPEN64 */
4006 /****************************************************************************
4008 ***************************************************************************/
4010 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4014 ret = libc_vopen(pathname, flags, ap);
4017 * There are methods for closing descriptors (libc-internal code
4018 * paths, direct syscalls) which close descriptors in ways that
4019 * we can't intercept, so try to recover when we notice that
4022 swrap_remove_stale(ret);
4027 int open(const char *pathname, int flags, ...)
4032 va_start(ap, flags);
4033 fd = swrap_vopen(pathname, flags, ap);
4039 /****************************************************************************
4041 ***************************************************************************/
4044 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4048 ret = libc_vopen64(pathname, flags, ap);
4051 * There are methods for closing descriptors (libc-internal code
4052 * paths, direct syscalls) which close descriptors in ways that
4053 * we can't intercept, so try to recover when we notice that
4056 swrap_remove_stale(ret);
4061 int open64(const char *pathname, int flags, ...)
4066 va_start(ap, flags);
4067 fd = swrap_vopen64(pathname, flags, ap);
4072 #endif /* HAVE_OPEN64 */
4074 /****************************************************************************
4076 ***************************************************************************/
4078 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4082 ret = libc_vopenat(dirfd, path, flags, ap);
4085 * There are methods for closing descriptors (libc-internal code
4086 * paths, direct syscalls) which close descriptors in ways that
4087 * we can't intercept, so try to recover when we notice that
4090 swrap_remove_stale(ret);
4096 int openat(int dirfd, const char *path, int flags, ...)
4101 va_start(ap, flags);
4102 fd = swrap_vopenat(dirfd, path, flags, ap);
4108 /****************************************************************************
4110 ***************************************************************************/
4112 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4114 struct socket_info *si = find_socket_info(s);
4119 return libc_getpeername(s, name, addrlen);
4124 if (si->peername.sa_socklen == 0)
4130 len = MIN(*addrlen, si->peername.sa_socklen);
4136 memcpy(name, &si->peername.sa.ss, len);
4137 *addrlen = si->peername.sa_socklen;
4141 SWRAP_UNLOCK_SI(si);
4146 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4147 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4149 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4152 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4155 /****************************************************************************
4157 ***************************************************************************/
4159 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4161 struct socket_info *si = find_socket_info(s);
4166 return libc_getsockname(s, name, addrlen);
4171 len = MIN(*addrlen, si->myname.sa_socklen);
4177 memcpy(name, &si->myname.sa.ss, len);
4178 *addrlen = si->myname.sa_socklen;
4182 SWRAP_UNLOCK_SI(si);
4187 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4188 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4190 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4193 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4196 /****************************************************************************
4198 ***************************************************************************/
4201 # ifdef SO_PROTOTYPE /* The Solaris name */
4202 # define SO_PROTOCOL SO_PROTOTYPE
4203 # endif /* SO_PROTOTYPE */
4204 #endif /* SO_PROTOCOL */
4206 static int swrap_getsockopt(int s, int level, int optname,
4207 void *optval, socklen_t *optlen)
4209 struct socket_info *si = find_socket_info(s);
4213 return libc_getsockopt(s,
4222 if (level == SOL_SOCKET) {
4226 if (optval == NULL || optlen == NULL ||
4227 *optlen < (socklen_t)sizeof(int)) {
4233 *optlen = sizeof(int);
4234 *(int *)optval = si->family;
4237 #endif /* SO_DOMAIN */
4241 if (optval == NULL || optlen == NULL ||
4242 *optlen < (socklen_t)sizeof(int)) {
4248 *optlen = sizeof(int);
4249 *(int *)optval = si->protocol;
4252 #endif /* SO_PROTOCOL */
4254 if (optval == NULL || optlen == NULL ||
4255 *optlen < (socklen_t)sizeof(int)) {
4261 *optlen = sizeof(int);
4262 *(int *)optval = si->type;
4266 ret = libc_getsockopt(s,
4273 } else if (level == IPPROTO_TCP) {
4278 * This enables sending packets directly out over TCP.
4279 * As a unix socket is doing that any way, report it as
4282 if (optval == NULL || optlen == NULL ||
4283 *optlen < (socklen_t)sizeof(int)) {
4289 *optlen = sizeof(int);
4290 *(int *)optval = si->tcp_nodelay;
4294 #endif /* TCP_NODELAY */
4300 errno = ENOPROTOOPT;
4304 SWRAP_UNLOCK_SI(si);
4308 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4309 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4311 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4314 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4317 /****************************************************************************
4319 ***************************************************************************/
4321 static int swrap_setsockopt(int s, int level, int optname,
4322 const void *optval, socklen_t optlen)
4324 struct socket_info *si = find_socket_info(s);
4328 return libc_setsockopt(s,
4335 if (level == SOL_SOCKET) {
4336 return libc_setsockopt(s,
4345 if (level == IPPROTO_TCP) {
4352 * This enables sending packets directly out over TCP.
4353 * A unix socket is doing that any way.
4355 if (optval == NULL || optlen == 0 ||
4356 optlen < (socklen_t)sizeof(int)) {
4362 i = *discard_const_p(int, optval);
4363 if (i != 0 && i != 1) {
4368 si->tcp_nodelay = i;
4373 #endif /* TCP_NODELAY */
4379 switch (si->family) {
4381 if (level == IPPROTO_IP) {
4383 if (optname == IP_PKTINFO) {
4384 si->pktinfo = AF_INET;
4386 #endif /* IP_PKTINFO */
4392 if (level == IPPROTO_IPV6) {
4393 #ifdef IPV6_RECVPKTINFO
4394 if (optname == IPV6_RECVPKTINFO) {
4395 si->pktinfo = AF_INET6;
4397 #endif /* IPV6_PKTINFO */
4403 errno = ENOPROTOOPT;
4409 SWRAP_UNLOCK_SI(si);
4413 int setsockopt(int s, int level, int optname,
4414 const void *optval, socklen_t optlen)
4416 return swrap_setsockopt(s, level, optname, optval, optlen);
4419 /****************************************************************************
4421 ***************************************************************************/
4423 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4425 struct socket_info *si = find_socket_info(s);
4431 return libc_vioctl(s, r, va);
4438 rc = libc_vioctl(s, r, va);
4442 value = *((int *)va_arg(ap, int *));
4444 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4445 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4446 } else if (value == 0) { /* END OF FILE */
4447 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4454 SWRAP_UNLOCK_SI(si);
4458 #ifdef HAVE_IOCTL_INT
4459 int ioctl(int s, int r, ...)
4461 int ioctl(int s, unsigned long int r, ...)
4469 rc = swrap_vioctl(s, (unsigned long int) r, va);
4480 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4483 # ifdef _ALIGN /* BSD */
4484 #define CMSG_ALIGN _ALIGN
4486 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4487 # endif /* _ALIGN */
4488 #endif /* CMSG_ALIGN */
4491 * @brief Add a cmsghdr to a msghdr.
4493 * This is an function to add any type of cmsghdr. It will operate on the
4494 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4495 * the buffer position after the added cmsg element. Hence, this function is
4496 * intended to be used with an intermediate msghdr and not on the original
4497 * one handed in by the client.
4499 * @param[in] msg The msghdr to which to add the cmsg.
4501 * @param[in] level The cmsg level to set.
4503 * @param[in] type The cmsg type to set.
4505 * @param[in] data The cmsg data to set.
4507 * @param[in] len the length of the data to set.
4509 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4515 size_t cmlen = CMSG_LEN(len);
4516 size_t cmspace = CMSG_SPACE(len);
4517 uint8_t cmbuf[cmspace];
4518 void *cast_ptr = (void *)cmbuf;
4519 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4522 memset(cmbuf, 0, cmspace);
4524 if (msg->msg_controllen < cmlen) {
4525 cmlen = msg->msg_controllen;
4526 msg->msg_flags |= MSG_CTRUNC;
4529 if (msg->msg_controllen < cmspace) {
4530 cmspace = msg->msg_controllen;
4534 * We copy the full input data into an intermediate cmsghdr first
4535 * in order to more easily cope with truncation.
4537 cm->cmsg_len = cmlen;
4538 cm->cmsg_level = level;
4539 cm->cmsg_type = type;
4540 memcpy(CMSG_DATA(cm), data, len);
4543 * We now copy the possibly truncated buffer.
4544 * We copy cmlen bytes, but consume cmspace bytes,
4545 * leaving the possible padding uninitialiazed.
4547 p = (uint8_t *)msg->msg_control;
4548 memcpy(p, cm, cmlen);
4550 msg->msg_control = p;
4551 msg->msg_controllen -= cmspace;
4556 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4559 /* Add packet info */
4560 switch (si->pktinfo) {
4561 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4563 struct sockaddr_in *sin;
4564 #if defined(HAVE_STRUCT_IN_PKTINFO)
4565 struct in_pktinfo pkt;
4566 #elif defined(IP_RECVDSTADDR)
4570 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4571 sin = &si->bindname.sa.in;
4573 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4576 sin = &si->myname.sa.in;
4581 #if defined(HAVE_STRUCT_IN_PKTINFO)
4582 pkt.ipi_ifindex = socket_wrapper_default_iface();
4583 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4584 #elif defined(IP_RECVDSTADDR)
4585 pkt = sin->sin_addr;
4588 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4593 #endif /* IP_PKTINFO */
4594 #if defined(HAVE_IPV6)
4596 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4597 struct sockaddr_in6 *sin6;
4598 struct in6_pktinfo pkt6;
4600 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4601 sin6 = &si->bindname.sa.in6;
4603 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4606 sin6 = &si->myname.sa.in6;
4611 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4612 pkt6.ipi6_addr = sin6->sin6_addr;
4614 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4615 &pkt6, sizeof(pkt6));
4616 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4620 #endif /* IPV6_PKTINFO */
4628 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4629 struct msghdr *omsg)
4633 if (si->pktinfo > 0) {
4634 rc = swrap_msghdr_add_pktinfo(si, omsg);
4640 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4642 size_t *cm_data_space);
4643 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4645 size_t *cm_data_space);
4647 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4649 size_t *cm_data_space) {
4650 struct cmsghdr *cmsg;
4654 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4658 for (cmsg = CMSG_FIRSTHDR(msg);
4660 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4661 switch (cmsg->cmsg_level) {
4663 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4668 rc = swrap_sendmsg_copy_cmsg(cmsg,
4678 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4680 size_t *cm_data_space)
4685 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4687 p = realloc((*cm_data), cmspace);
4693 p = (*cm_data) + (*cm_data_space);
4694 *cm_data_space = cmspace;
4696 memcpy(p, cmsg, cmsg->cmsg_len);
4701 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4703 size_t *cm_data_space);
4706 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4708 size_t *cm_data_space)
4712 switch(cmsg->cmsg_type) {
4715 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4722 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4734 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4736 size_t *cm_data_space)
4738 (void)cmsg; /* unused */
4739 (void)cm_data; /* unused */
4740 (void)cm_data_space; /* unused */
4743 * Passing a IP pktinfo to a unix socket might be rejected by the
4744 * Kernel, at least on FreeBSD. So skip this cmsg.
4748 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4750 static ssize_t swrap_sendmsg_before(int fd,
4751 struct socket_info *si,
4753 struct iovec *tmp_iov,
4754 struct sockaddr_un *tmp_un,
4755 const struct sockaddr_un **to_un,
4756 const struct sockaddr **to,
4778 if (!si->connected) {
4783 if (msg->msg_iovlen == 0) {
4787 mtu = socket_wrapper_mtu();
4788 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4790 nlen = len + msg->msg_iov[i].iov_len;
4800 msg->msg_iovlen = i;
4801 if (msg->msg_iovlen == 0) {
4802 *tmp_iov = msg->msg_iov[0];
4803 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4805 msg->msg_iov = tmp_iov;
4806 msg->msg_iovlen = 1;
4811 if (si->connected) {
4812 if (msg->msg_name != NULL) {
4814 * We are dealing with unix sockets and if we
4815 * are connected, we should only talk to the
4816 * connected unix path. Using the fd to send
4817 * to another server would be hard to achieve.
4819 msg->msg_name = NULL;
4820 msg->msg_namelen = 0;
4823 const struct sockaddr *msg_name;
4824 msg_name = (const struct sockaddr *)msg->msg_name;
4826 if (msg_name == NULL) {
4832 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4844 msg->msg_name = tmp_un;
4845 msg->msg_namelen = sizeof(*tmp_un);
4848 if (si->bound == 0) {
4849 ret = swrap_auto_bind(fd, si, si->family);
4851 SWRAP_UNLOCK_SI(si);
4852 if (errno == ENOTSOCK) {
4853 swrap_remove_stale(fd);
4856 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4862 if (!si->defer_connect) {
4866 ret = sockaddr_convert_to_un(si,
4868 si->peername.sa_socklen,
4876 ret = libc_connect(fd,
4877 (struct sockaddr *)(void *)tmp_un,
4880 /* to give better errors */
4881 if (ret == -1 && errno == ENOENT) {
4882 errno = EHOSTUNREACH;
4889 si->defer_connect = 0;
4892 errno = EHOSTUNREACH;
4896 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4897 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4898 uint8_t *cmbuf = NULL;
4901 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4908 msg->msg_controllen = 0;
4909 msg->msg_control = NULL;
4910 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4911 memcpy(msg->msg_control, cmbuf, cmlen);
4912 msg->msg_controllen = cmlen;
4920 SWRAP_UNLOCK_SI(si);
4925 static void swrap_sendmsg_after(int fd,
4926 struct socket_info *si,
4928 const struct sockaddr *to,
4931 int saved_errno = errno;
4938 /* to give better errors */
4940 if (saved_errno == ENOENT) {
4941 saved_errno = EHOSTUNREACH;
4942 } else if (saved_errno == ENOTSOCK) {
4943 /* If the fd is not a socket, remove it */
4944 swrap_remove_stale(fd);
4948 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4949 avail += msg->msg_iov[i].iov_len;
4953 remain = MIN(80, avail);
4958 /* we capture it as one single packet */
4959 buf = (uint8_t *)malloc(remain);
4961 /* we just not capture the packet */
4962 errno = saved_errno;
4966 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4967 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4969 msg->msg_iov[i].iov_base,
4972 remain -= this_time;
4981 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4982 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4984 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4989 if (si->connected) {
4990 to = &si->peername.sa.s;
4993 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4994 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4996 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5001 SWRAP_UNLOCK_SI(si);
5004 errno = saved_errno;
5007 static int swrap_recvmsg_before(int fd,
5008 struct socket_info *si,
5010 struct iovec *tmp_iov)
5017 (void)fd; /* unused */
5022 if (!si->connected) {
5027 if (msg->msg_iovlen == 0) {
5031 mtu = socket_wrapper_mtu();
5032 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5034 nlen = len + msg->msg_iov[i].iov_len;
5039 msg->msg_iovlen = i;
5040 if (msg->msg_iovlen == 0) {
5041 *tmp_iov = msg->msg_iov[0];
5042 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5044 msg->msg_iov = tmp_iov;
5045 msg->msg_iovlen = 1;
5050 if (msg->msg_name == NULL) {
5055 if (msg->msg_iovlen == 0) {
5059 if (si->bound == 0) {
5060 ret = swrap_auto_bind(fd, si, si->family);
5062 SWRAP_UNLOCK_SI(si);
5064 * When attempting to read or write to a
5065 * descriptor, if an underlying autobind fails
5066 * because it's not a socket, stop intercepting
5067 * uses of that descriptor.
5069 if (errno == ENOTSOCK) {
5070 swrap_remove_stale(fd);
5073 SWRAP_LOG(SWRAP_LOG_ERROR,
5074 "swrap_recvmsg_before failed");
5081 errno = EHOSTUNREACH;
5087 SWRAP_UNLOCK_SI(si);
5092 static int swrap_recvmsg_after(int fd,
5093 struct socket_info *si,
5095 const struct sockaddr_un *un_addr,
5096 socklen_t un_addrlen,
5099 int saved_errno = errno;
5101 uint8_t *buf = NULL;
5107 /* to give better errors */
5109 if (saved_errno == ENOENT) {
5110 saved_errno = EHOSTUNREACH;
5111 } else if (saved_errno == ENOTSOCK) {
5112 /* If the fd is not a socket, remove it */
5113 swrap_remove_stale(fd);
5117 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5118 avail += msg->msg_iov[i].iov_len;
5123 /* Convert the socket address before we leave */
5124 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5125 rc = sockaddr_convert_from_un(si,
5142 remain = MIN(80, avail);
5147 /* we capture it as one single packet */
5148 buf = (uint8_t *)malloc(remain);
5150 /* we just not capture the packet */
5151 SWRAP_UNLOCK_SI(si);
5152 errno = saved_errno;
5156 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5157 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5159 msg->msg_iov[i].iov_base,
5162 remain -= this_time;
5167 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5168 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5169 } else if (ret == 0) { /* END OF FILE */
5170 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5171 } else if (ret > 0) {
5172 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5181 if (un_addr != NULL) {
5182 swrap_pcap_dump_packet(si,
5188 swrap_pcap_dump_packet(si,
5201 errno = saved_errno;
5203 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5205 msg->msg_controllen > 0 &&
5206 msg->msg_control != NULL) {
5207 rc = swrap_msghdr_add_socket_info(si, msg);
5209 SWRAP_UNLOCK_SI(si);
5215 SWRAP_UNLOCK_SI(si);
5219 /****************************************************************************
5221 ***************************************************************************/
5223 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5224 struct sockaddr *from, socklen_t *fromlen)
5226 struct swrap_address from_addr = {
5227 .sa_socklen = sizeof(struct sockaddr_un),
5230 struct socket_info *si = find_socket_info(s);
5231 struct swrap_address saddr = {
5232 .sa_socklen = sizeof(struct sockaddr_storage),
5239 return libc_recvfrom(s,
5251 if (from != NULL && fromlen != NULL) {
5252 msg.msg_name = from; /* optional address */
5253 msg.msg_namelen = *fromlen; /* size of address */
5255 msg.msg_name = &saddr.sa.s; /* optional address */
5256 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5258 msg.msg_iov = &tmp; /* scatter/gather array */
5259 msg.msg_iovlen = 1; /* # elements in msg_iov */
5260 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5261 msg.msg_control = NULL; /* ancillary data, see below */
5262 msg.msg_controllen = 0; /* ancillary data buffer len */
5263 msg.msg_flags = 0; /* flags on received message */
5266 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5271 buf = msg.msg_iov[0].iov_base;
5272 len = msg.msg_iov[0].iov_len;
5274 ret = libc_recvfrom(s,
5279 &from_addr.sa_socklen);
5284 tret = swrap_recvmsg_after(s,
5288 from_addr.sa_socklen,
5294 if (from != NULL && fromlen != NULL) {
5295 *fromlen = msg.msg_namelen;
5301 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5302 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5303 struct sockaddr *from, Psocklen_t fromlen)
5305 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5306 struct sockaddr *from, socklen_t *fromlen)
5309 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5312 /****************************************************************************
5314 ***************************************************************************/
5316 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5317 const struct sockaddr *to, socklen_t tolen)
5321 struct swrap_address un_addr = {
5322 .sa_socklen = sizeof(struct sockaddr_un),
5324 const struct sockaddr_un *to_un = NULL;
5327 struct socket_info *si = find_socket_info(s);
5331 return libc_sendto(s, buf, len, flags, to, tolen);
5334 tmp.iov_base = discard_const_p(char, buf);
5338 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5339 msg.msg_namelen = tolen; /* size of address */
5340 msg.msg_iov = &tmp; /* scatter/gather array */
5341 msg.msg_iovlen = 1; /* # elements in msg_iov */
5342 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5343 msg.msg_control = NULL; /* ancillary data, see below */
5344 msg.msg_controllen = 0; /* ancillary data buffer len */
5345 msg.msg_flags = 0; /* flags on received message */
5348 rc = swrap_sendmsg_before(s,
5360 buf = msg.msg_iov[0].iov_base;
5361 len = msg.msg_iov[0].iov_len;
5366 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5368 char *swrap_dir = NULL;
5370 type = SOCKET_TYPE_CHAR_UDP;
5372 swrap_dir = socket_wrapper_dir();
5374 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5375 snprintf(un_addr.sa.un.sun_path,
5376 sizeof(un_addr.sa.un.sun_path),
5377 "%s/"SOCKET_FORMAT, swrap_dir, type, iface, prt);
5378 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5380 /* ignore the any errors in broadcast sends */
5386 un_addr.sa_socklen);
5389 SAFE_FREE(swrap_dir);
5393 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5395 SWRAP_UNLOCK_SI(si);
5402 * If it is a dgram socket and we are connected, don't include the
5405 if (si->type == SOCK_DGRAM && si->connected) {
5406 ret = libc_sendto(s,
5413 ret = libc_sendto(s,
5417 (struct sockaddr *)msg.msg_name,
5421 SWRAP_UNLOCK_SI(si);
5423 swrap_sendmsg_after(s, si, &msg, to, ret);
5428 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5429 const struct sockaddr *to, socklen_t tolen)
5431 return swrap_sendto(s, buf, len, flags, to, tolen);
5434 /****************************************************************************
5436 ***************************************************************************/
5438 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5440 struct socket_info *si;
5442 struct swrap_address saddr = {
5443 .sa_socklen = sizeof(struct sockaddr_storage),
5449 si = find_socket_info(s);
5451 return libc_recv(s, buf, len, flags);
5458 msg.msg_name = &saddr.sa.s; /* optional address */
5459 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5460 msg.msg_iov = &tmp; /* scatter/gather array */
5461 msg.msg_iovlen = 1; /* # elements in msg_iov */
5462 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5463 msg.msg_control = NULL; /* ancillary data, see below */
5464 msg.msg_controllen = 0; /* ancillary data buffer len */
5465 msg.msg_flags = 0; /* flags on received message */
5468 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5473 buf = msg.msg_iov[0].iov_base;
5474 len = msg.msg_iov[0].iov_len;
5476 ret = libc_recv(s, buf, len, flags);
5478 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5486 ssize_t recv(int s, void *buf, size_t len, int flags)
5488 return swrap_recv(s, buf, len, flags);
5491 /****************************************************************************
5493 ***************************************************************************/
5495 static ssize_t swrap_read(int s, void *buf, size_t len)
5497 struct socket_info *si;
5500 struct swrap_address saddr = {
5501 .sa_socklen = sizeof(struct sockaddr_storage),
5506 si = find_socket_info(s);
5508 return libc_read(s, buf, len);
5515 msg.msg_name = &saddr.sa.ss; /* optional address */
5516 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5517 msg.msg_iov = &tmp; /* scatter/gather array */
5518 msg.msg_iovlen = 1; /* # elements in msg_iov */
5519 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5520 msg.msg_control = NULL; /* ancillary data, see below */
5521 msg.msg_controllen = 0; /* ancillary data buffer len */
5522 msg.msg_flags = 0; /* flags on received message */
5525 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5527 if (tret == -ENOTSOCK) {
5528 return libc_read(s, buf, len);
5533 buf = msg.msg_iov[0].iov_base;
5534 len = msg.msg_iov[0].iov_len;
5536 ret = libc_read(s, buf, len);
5538 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5546 ssize_t read(int s, void *buf, size_t len)
5548 return swrap_read(s, buf, len);
5551 /****************************************************************************
5553 ***************************************************************************/
5555 static ssize_t swrap_write(int s, const void *buf, size_t len)
5559 struct sockaddr_un un_addr;
5562 struct socket_info *si;
5564 si = find_socket_info(s);
5566 return libc_write(s, buf, len);
5569 tmp.iov_base = discard_const_p(char, buf);
5573 msg.msg_name = NULL; /* optional address */
5574 msg.msg_namelen = 0; /* size of address */
5575 msg.msg_iov = &tmp; /* scatter/gather array */
5576 msg.msg_iovlen = 1; /* # elements in msg_iov */
5577 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5578 msg.msg_control = NULL; /* ancillary data, see below */
5579 msg.msg_controllen = 0; /* ancillary data buffer len */
5580 msg.msg_flags = 0; /* flags on received message */
5583 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5588 buf = msg.msg_iov[0].iov_base;
5589 len = msg.msg_iov[0].iov_len;
5591 ret = libc_write(s, buf, len);
5593 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5598 ssize_t write(int s, const void *buf, size_t len)
5600 return swrap_write(s, buf, len);
5603 /****************************************************************************
5605 ***************************************************************************/
5607 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5611 struct sockaddr_un un_addr;
5614 struct socket_info *si = find_socket_info(s);
5617 return libc_send(s, buf, len, flags);
5620 tmp.iov_base = discard_const_p(char, buf);
5624 msg.msg_name = NULL; /* optional address */
5625 msg.msg_namelen = 0; /* size of address */
5626 msg.msg_iov = &tmp; /* scatter/gather array */
5627 msg.msg_iovlen = 1; /* # elements in msg_iov */
5628 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5629 msg.msg_control = NULL; /* ancillary data, see below */
5630 msg.msg_controllen = 0; /* ancillary data buffer len */
5631 msg.msg_flags = 0; /* flags on received message */
5634 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5639 buf = msg.msg_iov[0].iov_base;
5640 len = msg.msg_iov[0].iov_len;
5642 ret = libc_send(s, buf, len, flags);
5644 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5649 ssize_t send(int s, const void *buf, size_t len, int flags)
5651 return swrap_send(s, buf, len, flags);
5654 /****************************************************************************
5656 ***************************************************************************/
5658 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5660 struct swrap_address from_addr = {
5661 .sa_socklen = sizeof(struct sockaddr_un),
5663 struct swrap_address convert_addr = {
5664 .sa_socklen = sizeof(struct sockaddr_storage),
5666 struct socket_info *si;
5669 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5670 size_t msg_ctrllen_filled;
5671 size_t msg_ctrllen_left;
5677 si = find_socket_info(s);
5679 return libc_recvmsg(s, omsg, flags);
5682 tmp.iov_base = NULL;
5686 msg.msg_name = &from_addr.sa; /* optional address */
5687 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5688 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5689 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5690 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5691 msg_ctrllen_filled = 0;
5692 msg_ctrllen_left = omsg->msg_controllen;
5694 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5695 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5696 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5699 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5704 ret = libc_recvmsg(s, &msg, flags);
5706 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5707 msg_ctrllen_filled += msg.msg_controllen;
5708 msg_ctrllen_left -= msg.msg_controllen;
5710 if (omsg->msg_control != NULL) {
5713 p = omsg->msg_control;
5714 p += msg_ctrllen_filled;
5716 msg.msg_control = p;
5717 msg.msg_controllen = msg_ctrllen_left;
5719 msg.msg_control = NULL;
5720 msg.msg_controllen = 0;
5725 * We convert the unix address to a IP address so we need a buffer
5726 * which can store the address in case of SOCK_DGRAM, see below.
5728 msg.msg_name = &convert_addr.sa;
5729 msg.msg_namelen = convert_addr.sa_socklen;
5731 rc = swrap_recvmsg_after(s,
5735 from_addr.sa_socklen,
5741 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5742 if (omsg->msg_control != NULL) {
5743 /* msg.msg_controllen = space left */
5744 msg_ctrllen_left = msg.msg_controllen;
5745 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5748 /* Update the original message length */
5749 omsg->msg_controllen = msg_ctrllen_filled;
5750 omsg->msg_flags = msg.msg_flags;
5752 omsg->msg_iovlen = msg.msg_iovlen;
5759 * The msg_name field points to a caller-allocated buffer that is
5760 * used to return the source address if the socket is unconnected. The
5761 * caller should set msg_namelen to the size of this buffer before this
5762 * call; upon return from a successful call, msg_name will contain the
5763 * length of the returned address. If the application does not need
5764 * to know the source address, msg_name can be specified as NULL.
5766 if (si->type == SOCK_STREAM) {
5767 omsg->msg_namelen = 0;
5768 } else if (omsg->msg_name != NULL &&
5769 omsg->msg_namelen != 0 &&
5770 omsg->msg_namelen >= msg.msg_namelen) {
5771 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5772 omsg->msg_namelen = msg.msg_namelen;
5775 SWRAP_UNLOCK_SI(si);
5780 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5782 return swrap_recvmsg(sockfd, msg, flags);
5785 /****************************************************************************
5787 ***************************************************************************/
5789 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5793 struct sockaddr_un un_addr;
5794 const struct sockaddr_un *to_un = NULL;
5795 const struct sockaddr *to = NULL;
5798 struct socket_info *si = find_socket_info(s);
5802 return libc_sendmsg(s, omsg, flags);
5805 ZERO_STRUCT(un_addr);
5807 tmp.iov_base = NULL;
5814 if (si->connected == 0) {
5815 msg.msg_name = omsg->msg_name; /* optional address */
5816 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5818 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5819 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5821 SWRAP_UNLOCK_SI(si);
5823 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5824 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5825 /* omsg is a const so use a local buffer for modifications */
5826 uint8_t cmbuf[omsg->msg_controllen];
5828 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5830 msg.msg_control = cmbuf; /* ancillary data, see below */
5831 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5833 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5836 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5844 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5851 char *swrap_dir = NULL;
5853 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5854 avail += msg.msg_iov[i].iov_len;
5860 /* we capture it as one single packet */
5861 buf = (uint8_t *)malloc(remain);
5866 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5867 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5869 msg.msg_iov[i].iov_base,
5872 remain -= this_time;
5875 type = SOCKET_TYPE_CHAR_UDP;
5877 swrap_dir = socket_wrapper_dir();
5879 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5880 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5881 swrap_dir, type, iface, prt);
5882 if (stat(un_addr.sun_path, &st) != 0) continue;
5884 msg.msg_name = &un_addr; /* optional address */
5885 msg.msg_namelen = sizeof(un_addr); /* size of address */
5887 /* ignore the any errors in broadcast sends */
5888 libc_sendmsg(s, &msg, flags);
5891 SAFE_FREE(swrap_dir);
5895 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5898 SWRAP_UNLOCK_SI(si);
5903 ret = libc_sendmsg(s, &msg, flags);
5905 swrap_sendmsg_after(s, si, &msg, to, ret);
5910 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5912 return swrap_sendmsg(s, omsg, flags);
5915 /****************************************************************************
5917 ***************************************************************************/
5919 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5921 struct socket_info *si;
5924 struct swrap_address saddr = {
5925 .sa_socklen = sizeof(struct sockaddr_storage)
5930 si = find_socket_info(s);
5932 return libc_readv(s, vector, count);
5935 tmp.iov_base = NULL;
5939 msg.msg_name = &saddr.sa.s; /* optional address */
5940 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5941 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5942 msg.msg_iovlen = count; /* # elements in msg_iov */
5943 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5944 msg.msg_control = NULL; /* ancillary data, see below */
5945 msg.msg_controllen = 0; /* ancillary data buffer len */
5946 msg.msg_flags = 0; /* flags on received message */
5949 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5951 if (rc == -ENOTSOCK) {
5952 return libc_readv(s, vector, count);
5957 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5959 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5967 ssize_t readv(int s, const struct iovec *vector, int count)
5969 return swrap_readv(s, vector, count);
5972 /****************************************************************************
5974 ***************************************************************************/
5976 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5980 struct sockaddr_un un_addr;
5983 struct socket_info *si = find_socket_info(s);
5986 return libc_writev(s, vector, count);
5989 tmp.iov_base = NULL;
5993 msg.msg_name = NULL; /* optional address */
5994 msg.msg_namelen = 0; /* size of address */
5995 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5996 msg.msg_iovlen = count; /* # elements in msg_iov */
5997 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5998 msg.msg_control = NULL; /* ancillary data, see below */
5999 msg.msg_controllen = 0; /* ancillary data buffer len */
6000 msg.msg_flags = 0; /* flags on received message */
6003 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6005 if (rc == -ENOTSOCK) {
6006 return libc_readv(s, vector, count);
6011 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6013 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6018 ssize_t writev(int s, const struct iovec *vector, int count)
6020 return swrap_writev(s, vector, count);
6023 /****************************
6025 ***************************/
6027 static int swrap_close(int fd)
6029 struct socket_info *si = NULL;
6033 swrap_mutex_lock(&socket_reset_mutex);
6035 si_index = find_socket_info_index(fd);
6036 if (si_index == -1) {
6037 swrap_mutex_unlock(&socket_reset_mutex);
6038 return libc_close(fd);
6041 reset_socket_info_index(fd);
6043 si = swrap_get_socket_info(si_index);
6045 swrap_mutex_lock(&first_free_mutex);
6048 ret = libc_close(fd);
6050 swrap_dec_refcount(si);
6052 if (swrap_get_refcount(si) > 0) {
6053 /* there are still references left */
6057 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6058 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6061 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6062 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6063 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6066 if (si->un_addr.sun_path[0] != '\0') {
6067 unlink(si->un_addr.sun_path);
6070 swrap_set_next_free(si, first_free);
6071 first_free = si_index;
6074 SWRAP_UNLOCK_SI(si);
6075 swrap_mutex_unlock(&first_free_mutex);
6076 swrap_mutex_unlock(&socket_reset_mutex);
6083 return swrap_close(fd);
6086 /****************************
6088 ***************************/
6090 static int swrap_dup(int fd)
6092 struct socket_info *si;
6095 idx = find_socket_info_index(fd);
6097 return libc_dup(fd);
6100 si = swrap_get_socket_info(idx);
6102 dup_fd = libc_dup(fd);
6104 int saved_errno = errno;
6105 errno = saved_errno;
6111 swrap_inc_refcount(si);
6113 SWRAP_UNLOCK_SI(si);
6115 /* Make sure we don't have an entry for the fd */
6116 swrap_remove_stale(dup_fd);
6118 set_socket_info_index(dup_fd, idx);
6125 return swrap_dup(fd);
6128 /****************************
6130 ***************************/
6132 static int swrap_dup2(int fd, int newfd)
6134 struct socket_info *si;
6137 idx = find_socket_info_index(fd);
6139 return libc_dup2(fd, newfd);
6142 si = swrap_get_socket_info(idx);
6146 * According to the manpage:
6148 * "If oldfd is a valid file descriptor, and newfd has the same
6149 * value as oldfd, then dup2() does nothing, and returns newfd."
6154 if (find_socket_info(newfd)) {
6155 /* dup2() does an implicit close of newfd, which we
6156 * need to emulate */
6160 dup_fd = libc_dup2(fd, newfd);
6162 int saved_errno = errno;
6163 errno = saved_errno;
6169 swrap_inc_refcount(si);
6171 SWRAP_UNLOCK_SI(si);
6173 /* Make sure we don't have an entry for the fd */
6174 swrap_remove_stale(dup_fd);
6176 set_socket_info_index(dup_fd, idx);
6181 int dup2(int fd, int newfd)
6183 return swrap_dup2(fd, newfd);
6186 /****************************
6188 ***************************/
6190 static int swrap_vfcntl(int fd, int cmd, va_list va)
6192 struct socket_info *si;
6193 int rc, dup_fd, idx;
6195 idx = find_socket_info_index(fd);
6197 return libc_vfcntl(fd, cmd, va);
6200 si = swrap_get_socket_info(idx);
6204 dup_fd = libc_vfcntl(fd, cmd, va);
6206 int saved_errno = errno;
6207 errno = saved_errno;
6213 swrap_inc_refcount(si);
6215 SWRAP_UNLOCK_SI(si);
6217 /* Make sure we don't have an entry for the fd */
6218 swrap_remove_stale(dup_fd);
6220 set_socket_info_index(dup_fd, idx);
6225 rc = libc_vfcntl(fd, cmd, va);
6232 int fcntl(int fd, int cmd, ...)
6239 rc = swrap_vfcntl(fd, cmd, va);
6246 /****************************
6248 ***************************/
6251 static int swrap_eventfd(int count, int flags)
6255 fd = libc_eventfd(count, flags);
6257 swrap_remove_stale(fd);
6263 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6264 int eventfd(unsigned int count, int flags)
6266 int eventfd(int count, int flags)
6269 return swrap_eventfd(count, flags);
6274 int pledge(const char *promises, const char *paths[])
6276 (void)promises; /* unused */
6277 (void)paths; /* unused */
6281 #endif /* HAVE_PLEDGE */
6283 static void swrap_thread_prepare(void)
6286 * This function should only be called here!!
6288 * We bind all symobls to avoid deadlocks of the fork is
6289 * interrupted by a signal handler using a symbol of this
6292 swrap_bind_symbol_all();
6297 static void swrap_thread_parent(void)
6302 static void swrap_thread_child(void)
6307 /****************************
6309 ***************************/
6310 void swrap_constructor(void)
6315 * If we hold a lock and the application forks, then the child
6316 * is not able to unlock the mutex and we are in a deadlock.
6317 * This should prevent such deadlocks.
6319 pthread_atfork(&swrap_thread_prepare,
6320 &swrap_thread_parent,
6321 &swrap_thread_child);
6323 ret = socket_wrapper_init_mutex(&sockets_mutex);
6325 SWRAP_LOG(SWRAP_LOG_ERROR,
6326 "Failed to initialize pthread mutex");
6330 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6332 SWRAP_LOG(SWRAP_LOG_ERROR,
6333 "Failed to initialize pthread mutex");
6337 ret = socket_wrapper_init_mutex(&first_free_mutex);
6339 SWRAP_LOG(SWRAP_LOG_ERROR,
6340 "Failed to initialize pthread mutex");
6345 /****************************
6347 ***************************/
6350 * This function is called when the library is unloaded and makes sure that
6351 * sockets get closed and the unix file for the socket are unlinked.
6353 void swrap_destructor(void)
6357 if (socket_fds_idx != NULL) {
6358 for (i = 0; i < socket_fds_max; ++i) {
6359 if (socket_fds_idx[i] != -1) {
6363 SAFE_FREE(socket_fds_idx);
6368 if (swrap.libc.handle != NULL) {
6369 dlclose(swrap.libc.handle);
6371 if (swrap.libc.socket_handle) {
6372 dlclose(swrap.libc.socket_handle);