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;
613 case SWRAP_LIBSOCKET:
614 #ifdef HAVE_LIBSOCKET
615 handle = swrap.libc.socket_handle;
616 if (handle == NULL) {
617 for (i = 10; i >= 0; i--) {
618 char soname[256] = {0};
620 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
621 handle = dlopen(soname, flags);
622 if (handle != NULL) {
627 swrap.libc.socket_handle = handle;
632 handle = swrap.libc.handle;
634 if (handle == NULL) {
635 handle = dlopen(LIBC_SO, flags);
637 swrap.libc.handle = handle;
640 if (handle == NULL) {
641 for (i = 10; i >= 0; i--) {
642 char soname[256] = {0};
644 snprintf(soname, sizeof(soname), "libc.so.%d", i);
645 handle = dlopen(soname, flags);
646 if (handle != NULL) {
651 swrap.libc.handle = handle;
656 if (handle == NULL) {
658 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
660 SWRAP_LOG(SWRAP_LOG_ERROR,
661 "Failed to dlopen library: %s\n",
670 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
675 handle = swrap_load_lib_handle(lib);
677 func = dlsym(handle, fn_name);
679 SWRAP_LOG(SWRAP_LOG_ERROR,
680 "Failed to find %s: %s\n",
686 SWRAP_LOG(SWRAP_LOG_TRACE,
694 static void swrap_mutex_lock(pthread_mutex_t *mutex)
698 ret = pthread_mutex_lock(mutex);
700 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
705 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
709 ret = pthread_mutex_unlock(mutex);
711 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
717 * These macros have a thread race condition on purpose!
719 * This is an optimization to avoid locking each time we check if the symbol is
722 #define swrap_bind_symbol_libc(sym_name) \
723 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
724 swrap_mutex_lock(&libc_symbol_binding_mutex); \
725 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
726 swrap.libc.symbols._libc_##sym_name.obj = \
727 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
729 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
732 #define swrap_bind_symbol_libsocket(sym_name) \
733 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
734 swrap_mutex_lock(&libc_symbol_binding_mutex); \
735 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
736 swrap.libc.symbols._libc_##sym_name.obj = \
737 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
739 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
742 #define swrap_bind_symbol_libnsl(sym_name) \
743 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
744 swrap_mutex_lock(&libc_symbol_binding_mutex); \
745 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
746 swrap.libc.symbols._libc_##sym_name.obj = \
747 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
749 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
752 /****************************************************************************
754 ****************************************************************************
756 * Functions especially from libc need to be loaded individually, you can't
757 * load all at once or gdb will segfault at startup. The same applies to
758 * valgrind and has probably something todo with with the linker. So we need
759 * load each function at the point it is called the first time.
761 ****************************************************************************/
764 static int libc_accept4(int sockfd,
765 struct sockaddr *addr,
769 swrap_bind_symbol_libsocket(accept4);
771 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
774 #else /* HAVE_ACCEPT4 */
776 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
778 swrap_bind_symbol_libsocket(accept);
780 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
782 #endif /* HAVE_ACCEPT4 */
784 static int libc_bind(int sockfd,
785 const struct sockaddr *addr,
788 swrap_bind_symbol_libsocket(bind);
790 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
793 static int libc_close(int fd)
795 swrap_bind_symbol_libc(close);
797 return swrap.libc.symbols._libc_close.f(fd);
800 static int libc_connect(int sockfd,
801 const struct sockaddr *addr,
804 swrap_bind_symbol_libsocket(connect);
806 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
809 static int libc_dup(int fd)
811 swrap_bind_symbol_libc(dup);
813 return swrap.libc.symbols._libc_dup.f(fd);
816 static int libc_dup2(int oldfd, int newfd)
818 swrap_bind_symbol_libc(dup2);
820 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
824 static int libc_eventfd(int count, int flags)
826 swrap_bind_symbol_libc(eventfd);
828 return swrap.libc.symbols._libc_eventfd.f(count, flags);
832 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
833 static int libc_vfcntl(int fd, int cmd, va_list ap)
838 swrap_bind_symbol_libc(fcntl);
840 arg = va_arg(ap, void *);
842 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
847 static int libc_getpeername(int sockfd,
848 struct sockaddr *addr,
851 swrap_bind_symbol_libsocket(getpeername);
853 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
856 static int libc_getsockname(int sockfd,
857 struct sockaddr *addr,
860 swrap_bind_symbol_libsocket(getsockname);
862 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
865 static int libc_getsockopt(int sockfd,
871 swrap_bind_symbol_libsocket(getsockopt);
873 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
880 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
881 static int libc_vioctl(int d, unsigned long int request, va_list ap)
886 swrap_bind_symbol_libc(ioctl);
888 arg = va_arg(ap, void *);
890 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
895 static int libc_listen(int sockfd, int backlog)
897 swrap_bind_symbol_libsocket(listen);
899 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
902 static FILE *libc_fopen(const char *name, const char *mode)
904 swrap_bind_symbol_libc(fopen);
906 return swrap.libc.symbols._libc_fopen.f(name, mode);
910 static FILE *libc_fopen64(const char *name, const char *mode)
912 swrap_bind_symbol_libc(fopen64);
914 return swrap.libc.symbols._libc_fopen64.f(name, mode);
916 #endif /* HAVE_FOPEN64 */
918 static int libc_vopen(const char *pathname, int flags, va_list ap)
923 swrap_bind_symbol_libc(open);
925 if (flags & O_CREAT) {
926 mode = va_arg(ap, int);
928 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
933 static int libc_open(const char *pathname, int flags, ...)
939 fd = libc_vopen(pathname, flags, ap);
946 static int libc_vopen64(const char *pathname, int flags, va_list ap)
951 swrap_bind_symbol_libc(open64);
953 if (flags & O_CREAT) {
954 mode = va_arg(ap, int);
956 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
960 #endif /* HAVE_OPEN64 */
962 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
967 swrap_bind_symbol_libc(openat);
969 if (flags & O_CREAT) {
970 mode = va_arg(ap, int);
972 fd = swrap.libc.symbols._libc_openat.f(dirfd,
981 static int libc_openat(int dirfd, const char *path, int flags, ...)
987 fd = libc_vopenat(dirfd, path, flags, ap);
994 static int libc_pipe(int pipefd[2])
996 swrap_bind_symbol_libsocket(pipe);
998 return swrap.libc.symbols._libc_pipe.f(pipefd);
1001 static int libc_read(int fd, void *buf, size_t count)
1003 swrap_bind_symbol_libc(read);
1005 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1008 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1010 swrap_bind_symbol_libsocket(readv);
1012 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1015 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1017 swrap_bind_symbol_libsocket(recv);
1019 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1022 static int libc_recvfrom(int sockfd,
1026 struct sockaddr *src_addr,
1029 swrap_bind_symbol_libsocket(recvfrom);
1031 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1039 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1041 swrap_bind_symbol_libsocket(recvmsg);
1043 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1046 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1048 swrap_bind_symbol_libsocket(send);
1050 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1053 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1055 swrap_bind_symbol_libsocket(sendmsg);
1057 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1060 static int libc_sendto(int sockfd,
1064 const struct sockaddr *dst_addr,
1067 swrap_bind_symbol_libsocket(sendto);
1069 return swrap.libc.symbols._libc_sendto.f(sockfd,
1077 static int libc_setsockopt(int sockfd,
1083 swrap_bind_symbol_libsocket(setsockopt);
1085 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1092 #ifdef HAVE_SIGNALFD
1093 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1095 swrap_bind_symbol_libsocket(signalfd);
1097 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1101 static int libc_socket(int domain, int type, int protocol)
1103 swrap_bind_symbol_libsocket(socket);
1105 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1108 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1110 swrap_bind_symbol_libsocket(socketpair);
1112 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1115 #ifdef HAVE_TIMERFD_CREATE
1116 static int libc_timerfd_create(int clockid, int flags)
1118 swrap_bind_symbol_libc(timerfd_create);
1120 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1124 static ssize_t libc_write(int fd, const void *buf, size_t count)
1126 swrap_bind_symbol_libc(write);
1128 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1131 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1133 swrap_bind_symbol_libsocket(writev);
1135 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1138 /* DO NOT call this function during library initialization! */
1139 static void swrap_bind_symbol_all(void)
1142 swrap_bind_symbol_libsocket(accept4);
1144 swrap_bind_symbol_libsocket(accept);
1146 swrap_bind_symbol_libsocket(bind);
1147 swrap_bind_symbol_libc(close);
1148 swrap_bind_symbol_libsocket(connect);
1149 swrap_bind_symbol_libc(dup);
1150 swrap_bind_symbol_libc(dup2);
1151 swrap_bind_symbol_libc(fcntl);
1152 swrap_bind_symbol_libc(fopen);
1154 swrap_bind_symbol_libc(fopen64);
1157 swrap_bind_symbol_libc(eventfd);
1159 swrap_bind_symbol_libsocket(getpeername);
1160 swrap_bind_symbol_libsocket(getsockname);
1161 swrap_bind_symbol_libsocket(getsockopt);
1162 swrap_bind_symbol_libc(ioctl);
1163 swrap_bind_symbol_libsocket(listen);
1164 swrap_bind_symbol_libc(open);
1166 swrap_bind_symbol_libc(open64);
1168 swrap_bind_symbol_libc(openat);
1169 swrap_bind_symbol_libsocket(pipe);
1170 swrap_bind_symbol_libc(read);
1171 swrap_bind_symbol_libsocket(readv);
1172 swrap_bind_symbol_libsocket(recv);
1173 swrap_bind_symbol_libsocket(recvfrom);
1174 swrap_bind_symbol_libsocket(recvmsg);
1175 swrap_bind_symbol_libsocket(send);
1176 swrap_bind_symbol_libsocket(sendmsg);
1177 swrap_bind_symbol_libsocket(sendto);
1178 swrap_bind_symbol_libsocket(setsockopt);
1179 #ifdef HAVE_SIGNALFD
1180 swrap_bind_symbol_libsocket(signalfd);
1182 swrap_bind_symbol_libsocket(socket);
1183 swrap_bind_symbol_libsocket(socketpair);
1184 #ifdef HAVE_TIMERFD_CREATE
1185 swrap_bind_symbol_libc(timerfd_create);
1187 swrap_bind_symbol_libc(write);
1188 swrap_bind_symbol_libsocket(writev);
1191 /*********************************************************
1192 * SWRAP HELPER FUNCTIONS
1193 *********************************************************/
1199 static const struct in6_addr *swrap_ipv6(void)
1201 static struct in6_addr v;
1202 static int initialized;
1210 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1219 static void set_port(int family, int prt, struct swrap_address *addr)
1223 addr->sa.in.sin_port = htons(prt);
1227 addr->sa.in6.sin6_port = htons(prt);
1233 static size_t socket_length(int family)
1237 return sizeof(struct sockaddr_in);
1240 return sizeof(struct sockaddr_in6);
1246 static struct socket_info *swrap_get_socket_info(int si_index)
1248 return (struct socket_info *)(&(sockets[si_index].info));
1251 static int swrap_get_refcount(struct socket_info *si)
1253 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1254 return sic->meta.refcount;
1257 static void swrap_inc_refcount(struct socket_info *si)
1259 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1261 sic->meta.refcount += 1;
1264 static void swrap_dec_refcount(struct socket_info *si)
1266 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1268 sic->meta.refcount -= 1;
1271 static int swrap_get_next_free(struct socket_info *si)
1273 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1275 return sic->meta.next_free;
1278 static void swrap_set_next_free(struct socket_info *si, int next_free)
1280 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1282 sic->meta.next_free = next_free;
1285 static char *socket_wrapper_dir(void)
1287 char *swrap_dir = NULL;
1288 char *s = getenv("SOCKET_WRAPPER_DIR");
1294 swrap_dir = realpath(s, NULL);
1295 if (swrap_dir == NULL) {
1296 SWRAP_LOG(SWRAP_LOG_ERROR,
1297 "Unable to resolve socket_wrapper dir path: %s",
1302 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1306 static unsigned int socket_wrapper_mtu(void)
1308 static unsigned int max_mtu = 0;
1313 swrap_mutex_lock(&mtu_update_mutex);
1319 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1321 s = getenv("SOCKET_WRAPPER_MTU");
1326 tmp = strtol(s, &endp, 10);
1331 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1337 swrap_mutex_unlock(&mtu_update_mutex);
1341 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1343 pthread_mutexattr_t ma;
1346 ret = pthread_mutexattr_init(&ma);
1351 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1356 ret = pthread_mutex_init(m, &ma);
1359 pthread_mutexattr_destroy(&ma);
1364 static size_t socket_wrapper_max_sockets(void)
1370 if (socket_info_max != 0) {
1371 return socket_info_max;
1374 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1376 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1377 if (s == NULL || s[0] == '\0') {
1381 tmp = strtoul(s, &endp, 10);
1386 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1387 SWRAP_LOG(SWRAP_LOG_ERROR,
1388 "Invalid number of sockets specified, "
1389 "using default (%zu)",
1393 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1394 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1395 SWRAP_LOG(SWRAP_LOG_ERROR,
1396 "Invalid number of sockets specified, "
1397 "using maximum (%zu).",
1401 socket_info_max = tmp;
1404 return socket_info_max;
1407 static void socket_wrapper_init_fds_idx(void)
1412 if (socket_fds_idx != NULL) {
1416 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1418 SWRAP_LOG(SWRAP_LOG_ERROR,
1419 "Failed to allocate socket fds index array: %s",
1424 for (i = 0; i < socket_fds_max; i++) {
1428 socket_fds_idx = tmp;
1431 static void socket_wrapper_init_sockets(void)
1437 swrap_mutex_lock(&sockets_mutex);
1439 if (sockets != NULL) {
1440 swrap_mutex_unlock(&sockets_mutex);
1444 socket_wrapper_init_fds_idx();
1446 /* Needs to be called inside the sockets_mutex lock here. */
1447 max_sockets = socket_wrapper_max_sockets();
1449 sockets = (struct socket_info_container *)calloc(max_sockets,
1450 sizeof(struct socket_info_container));
1452 if (sockets == NULL) {
1453 SWRAP_LOG(SWRAP_LOG_ERROR,
1454 "Failed to allocate sockets array: %s",
1456 swrap_mutex_unlock(&sockets_mutex);
1460 swrap_mutex_lock(&first_free_mutex);
1464 for (i = 0; i < max_sockets; i++) {
1465 swrap_set_next_free(&sockets[i].info, i+1);
1466 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1468 SWRAP_LOG(SWRAP_LOG_ERROR,
1469 "Failed to initialize pthread mutex");
1474 /* mark the end of the free list */
1475 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1477 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1479 SWRAP_LOG(SWRAP_LOG_ERROR,
1480 "Failed to initialize pthread mutex");
1484 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1486 SWRAP_LOG(SWRAP_LOG_ERROR,
1487 "Failed to initialize pthread mutex");
1491 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1493 SWRAP_LOG(SWRAP_LOG_ERROR,
1494 "Failed to initialize pthread mutex");
1499 swrap_mutex_unlock(&first_free_mutex);
1500 swrap_mutex_unlock(&sockets_mutex);
1506 bool socket_wrapper_enabled(void)
1508 char *s = socket_wrapper_dir();
1516 socket_wrapper_init_sockets();
1521 static unsigned int socket_wrapper_default_iface(void)
1523 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1526 if (sscanf(s, "%u", &iface) == 1) {
1527 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1533 return 1;/* 127.0.0.1 */
1536 static void set_socket_info_index(int fd, int idx)
1538 socket_fds_idx[fd] = idx;
1539 /* This builtin issues a full memory barrier. */
1540 __sync_synchronize();
1543 static void reset_socket_info_index(int fd)
1545 set_socket_info_index(fd, -1);
1548 static int find_socket_info_index(int fd)
1554 if (socket_fds_idx == NULL) {
1558 if ((size_t)fd >= socket_fds_max) {
1560 * Do not add a log here as some applications do stupid things
1563 * for (fd = 0; fd <= getdtablesize(); fd++) {
1567 * This would produce millions of lines of debug messages.
1570 SWRAP_LOG(SWRAP_LOG_ERROR,
1571 "Looking for a socket info for the fd %d is over the "
1572 "max socket index limit of %zu.",
1579 /* This builtin issues a full memory barrier. */
1580 __sync_synchronize();
1581 return socket_fds_idx[fd];
1584 static int swrap_add_socket_info(struct socket_info *si_input)
1586 struct socket_info *si = NULL;
1589 if (si_input == NULL) {
1594 swrap_mutex_lock(&first_free_mutex);
1595 if (first_free == -1) {
1600 si_index = first_free;
1601 si = swrap_get_socket_info(si_index);
1605 first_free = swrap_get_next_free(si);
1607 swrap_inc_refcount(si);
1609 SWRAP_UNLOCK_SI(si);
1612 swrap_mutex_unlock(&first_free_mutex);
1617 static int swrap_create_socket(struct socket_info *si, int fd)
1621 if ((size_t)fd >= socket_fds_max) {
1622 SWRAP_LOG(SWRAP_LOG_ERROR,
1623 "The max socket index limit of %zu has been reached, "
1630 idx = swrap_add_socket_info(si);
1635 set_socket_info_index(fd, idx);
1640 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1647 p = strrchr(un->sun_path, '/');
1648 if (p) p++; else p = un->sun_path;
1650 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1655 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1658 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1669 case SOCKET_TYPE_CHAR_TCP:
1670 case SOCKET_TYPE_CHAR_UDP: {
1671 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1673 if ((*len) < sizeof(*in2)) {
1678 memset(in2, 0, sizeof(*in2));
1679 in2->sin_family = AF_INET;
1680 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1681 in2->sin_port = htons(prt);
1683 *len = sizeof(*in2);
1687 case SOCKET_TYPE_CHAR_TCP_V6:
1688 case SOCKET_TYPE_CHAR_UDP_V6: {
1689 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1691 if ((*len) < sizeof(*in2)) {
1696 memset(in2, 0, sizeof(*in2));
1697 in2->sin6_family = AF_INET6;
1698 in2->sin6_addr = *swrap_ipv6();
1699 in2->sin6_addr.s6_addr[15] = iface;
1700 in2->sin6_port = htons(prt);
1702 *len = sizeof(*in2);
1714 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1721 char *swrap_dir = NULL;
1723 if (bcast) *bcast = 0;
1725 switch (inaddr->sa_family) {
1727 const struct sockaddr_in *in =
1728 (const struct sockaddr_in *)(const void *)inaddr;
1729 unsigned int addr = ntohl(in->sin_addr.s_addr);
1736 u_type = SOCKET_TYPE_CHAR_TCP;
1739 u_type = SOCKET_TYPE_CHAR_UDP;
1740 a_type = SOCKET_TYPE_CHAR_UDP;
1741 b_type = SOCKET_TYPE_CHAR_UDP;
1744 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1745 errno = ESOCKTNOSUPPORT;
1749 prt = ntohs(in->sin_port);
1750 if (a_type && addr == 0xFFFFFFFF) {
1751 /* 255.255.255.255 only udp */
1754 iface = socket_wrapper_default_iface();
1755 } else if (b_type && addr == 0x7FFFFFFF) {
1756 /* 127.255.255.255 only udp */
1759 iface = socket_wrapper_default_iface();
1760 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1764 iface = (addr & 0x000000FF);
1766 errno = ENETUNREACH;
1769 if (bcast) *bcast = is_bcast;
1774 const struct sockaddr_in6 *in =
1775 (const struct sockaddr_in6 *)(const void *)inaddr;
1776 struct in6_addr cmp1, cmp2;
1780 type = SOCKET_TYPE_CHAR_TCP_V6;
1783 type = SOCKET_TYPE_CHAR_UDP_V6;
1786 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1787 errno = ESOCKTNOSUPPORT;
1791 /* XXX no multicast/broadcast */
1793 prt = ntohs(in->sin6_port);
1795 cmp1 = *swrap_ipv6();
1796 cmp2 = in->sin6_addr;
1797 cmp2.s6_addr[15] = 0;
1798 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1799 iface = in->sin6_addr.s6_addr[15];
1801 errno = ENETUNREACH;
1809 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1810 errno = ENETUNREACH;
1815 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1820 swrap_dir = socket_wrapper_dir();
1823 snprintf(un->sun_path, sizeof(un->sun_path),
1824 "%s/EINVAL", swrap_dir);
1825 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1826 SAFE_FREE(swrap_dir);
1827 /* the caller need to do more processing */
1831 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1832 swrap_dir, type, iface, prt);
1833 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1835 SAFE_FREE(swrap_dir);
1840 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1848 char *swrap_dir = NULL;
1850 if (bcast) *bcast = 0;
1852 switch (si->family) {
1854 const struct sockaddr_in *in =
1855 (const struct sockaddr_in *)(const void *)inaddr;
1856 unsigned int addr = ntohl(in->sin_addr.s_addr);
1862 prt = ntohs(in->sin_port);
1866 u_type = SOCKET_TYPE_CHAR_TCP;
1867 d_type = SOCKET_TYPE_CHAR_TCP;
1870 u_type = SOCKET_TYPE_CHAR_UDP;
1871 d_type = SOCKET_TYPE_CHAR_UDP;
1872 a_type = SOCKET_TYPE_CHAR_UDP;
1873 b_type = SOCKET_TYPE_CHAR_UDP;
1876 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1877 errno = ESOCKTNOSUPPORT;
1885 iface = socket_wrapper_default_iface();
1886 } else if (a_type && addr == 0xFFFFFFFF) {
1887 /* 255.255.255.255 only udp */
1890 iface = socket_wrapper_default_iface();
1891 } else if (b_type && addr == 0x7FFFFFFF) {
1892 /* 127.255.255.255 only udp */
1895 iface = socket_wrapper_default_iface();
1896 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1900 iface = (addr & 0x000000FF);
1902 errno = EADDRNOTAVAIL;
1906 /* Store the bind address for connect() */
1907 if (si->bindname.sa_socklen == 0) {
1908 struct sockaddr_in bind_in;
1909 socklen_t blen = sizeof(struct sockaddr_in);
1911 ZERO_STRUCT(bind_in);
1912 bind_in.sin_family = in->sin_family;
1913 bind_in.sin_port = in->sin_port;
1914 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1916 si->bindname.sa_socklen = blen;
1917 memcpy(&si->bindname.sa.in, &bind_in, blen);
1924 const struct sockaddr_in6 *in =
1925 (const struct sockaddr_in6 *)(const void *)inaddr;
1926 struct in6_addr cmp1, cmp2;
1930 type = SOCKET_TYPE_CHAR_TCP_V6;
1933 type = SOCKET_TYPE_CHAR_UDP_V6;
1936 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1937 errno = ESOCKTNOSUPPORT;
1941 /* XXX no multicast/broadcast */
1943 prt = ntohs(in->sin6_port);
1945 cmp1 = *swrap_ipv6();
1946 cmp2 = in->sin6_addr;
1947 cmp2.s6_addr[15] = 0;
1948 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1949 iface = socket_wrapper_default_iface();
1950 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1951 iface = in->sin6_addr.s6_addr[15];
1953 errno = EADDRNOTAVAIL;
1957 /* Store the bind address for connect() */
1958 if (si->bindname.sa_socklen == 0) {
1959 struct sockaddr_in6 bind_in;
1960 socklen_t blen = sizeof(struct sockaddr_in6);
1962 ZERO_STRUCT(bind_in);
1963 bind_in.sin6_family = in->sin6_family;
1964 bind_in.sin6_port = in->sin6_port;
1966 bind_in.sin6_addr = *swrap_ipv6();
1967 bind_in.sin6_addr.s6_addr[15] = iface;
1969 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1970 si->bindname.sa_socklen = blen;
1977 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1978 errno = EADDRNOTAVAIL;
1983 if (bcast) *bcast = is_bcast;
1985 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1990 swrap_dir = socket_wrapper_dir();
1993 /* handle auto-allocation of ephemeral ports */
1994 for (prt = 5001; prt < 10000; prt++) {
1995 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1996 swrap_dir, type, iface, prt);
1997 if (stat(un->sun_path, &st) == 0) continue;
1999 set_port(si->family, prt, &si->myname);
2000 set_port(si->family, prt, &si->bindname);
2007 SAFE_FREE(swrap_dir);
2012 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
2013 swrap_dir, type, iface, prt);
2014 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2016 SAFE_FREE(swrap_dir);
2021 static struct socket_info *find_socket_info(int fd)
2023 int idx = find_socket_info_index(fd);
2029 return swrap_get_socket_info(idx);
2033 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2035 struct socket_info_fd *f;
2036 const struct socket_info *last_s = NULL;
2038 /* first catch invalid input */
2039 switch (sa->sa_family) {
2041 if (len < sizeof(struct sockaddr_in)) {
2047 if (len < sizeof(struct sockaddr_in6)) {
2057 for (f = socket_fds; f; f = f->next) {
2058 struct socket_info *s = swrap_get_socket_info(f->si_index);
2065 if (s->myname == NULL) {
2068 if (s->myname->sa_family != sa->sa_family) {
2071 switch (s->myname->sa_family) {
2073 struct sockaddr_in *sin1, *sin2;
2075 sin1 = (struct sockaddr_in *)s->myname;
2076 sin2 = (struct sockaddr_in *)sa;
2078 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2081 if (sin1->sin_port != sin2->sin_port) {
2084 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2094 struct sockaddr_in6 *sin1, *sin2;
2096 sin1 = (struct sockaddr_in6 *)s->myname;
2097 sin2 = (struct sockaddr_in6 *)sa;
2099 if (sin1->sin6_port != sin2->sin6_port) {
2102 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2124 static void swrap_remove_stale(int fd)
2126 struct socket_info *si;
2129 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2131 swrap_mutex_lock(&socket_reset_mutex);
2133 si_index = find_socket_info_index(fd);
2134 if (si_index == -1) {
2135 swrap_mutex_unlock(&socket_reset_mutex);
2139 reset_socket_info_index(fd);
2141 si = swrap_get_socket_info(si_index);
2143 swrap_mutex_lock(&first_free_mutex);
2146 swrap_dec_refcount(si);
2148 if (swrap_get_refcount(si) > 0) {
2152 if (si->un_addr.sun_path[0] != '\0') {
2153 unlink(si->un_addr.sun_path);
2156 swrap_set_next_free(si, first_free);
2157 first_free = si_index;
2160 SWRAP_UNLOCK_SI(si);
2161 swrap_mutex_unlock(&first_free_mutex);
2162 swrap_mutex_unlock(&socket_reset_mutex);
2165 static int sockaddr_convert_to_un(struct socket_info *si,
2166 const struct sockaddr *in_addr,
2168 struct sockaddr_un *out_addr,
2172 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2174 (void) in_len; /* unused */
2176 if (out_addr == NULL) {
2180 out->sa_family = AF_UNIX;
2181 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2182 out->sa_len = sizeof(*out_addr);
2185 switch (in_addr->sa_family) {
2187 const struct sockaddr_in *sin;
2188 if (si->family != AF_INET) {
2191 if (in_len < sizeof(struct sockaddr_in)) {
2194 sin = (const struct sockaddr_in *)(const void *)in_addr;
2195 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2200 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2201 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2215 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2216 errno = ESOCKTNOSUPPORT;
2220 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2222 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2228 errno = EAFNOSUPPORT;
2229 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2233 static int sockaddr_convert_from_un(const struct socket_info *si,
2234 const struct sockaddr_un *in_addr,
2235 socklen_t un_addrlen,
2237 struct sockaddr *out_addr,
2238 socklen_t *out_addrlen)
2242 if (out_addr == NULL || out_addrlen == NULL)
2245 if (un_addrlen == 0) {
2260 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2261 errno = ESOCKTNOSUPPORT;
2264 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2265 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2266 out_addr->sa_len = *out_addrlen;
2273 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2274 errno = EAFNOSUPPORT;
2278 enum swrap_packet_type {
2280 SWRAP_CONNECT_UNREACH,
2288 SWRAP_SENDTO_UNREACH,
2299 struct swrap_file_hdr {
2301 uint16_t version_major;
2302 uint16_t version_minor;
2305 uint32_t frame_max_len;
2306 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2309 #define SWRAP_FILE_HDR_SIZE 24
2311 struct swrap_packet_frame {
2313 uint32_t micro_seconds;
2314 uint32_t recorded_length;
2315 uint32_t full_length;
2317 #define SWRAP_PACKET_FRAME_SIZE 16
2319 union swrap_packet_ip {
2323 uint16_t packet_length;
2324 uint16_t identification;
2329 uint16_t hdr_checksum;
2333 #define SWRAP_PACKET_IP_V4_SIZE 20
2336 uint8_t flow_label_high;
2337 uint16_t flow_label_low;
2338 uint16_t payload_length;
2339 uint8_t next_header;
2341 uint8_t src_addr[16];
2342 uint8_t dest_addr[16];
2344 #define SWRAP_PACKET_IP_V6_SIZE 40
2346 #define SWRAP_PACKET_IP_SIZE 40
2348 union swrap_packet_payload {
2350 uint16_t source_port;
2360 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2362 uint16_t source_port;
2367 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2374 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2381 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2383 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2385 #define SWRAP_PACKET_MIN_ALLOC \
2386 (SWRAP_PACKET_FRAME_SIZE + \
2387 SWRAP_PACKET_IP_SIZE + \
2388 SWRAP_PACKET_PAYLOAD_SIZE)
2390 static const char *swrap_pcap_init_file(void)
2392 static int initialized = 0;
2393 static const char *s = NULL;
2394 static const struct swrap_file_hdr h;
2395 static const struct swrap_packet_frame f;
2396 static const union swrap_packet_ip i;
2397 static const union swrap_packet_payload p;
2399 if (initialized == 1) {
2405 * TODO: don't use the structs use plain buffer offsets
2406 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2408 * for now make sure we disable PCAP support
2409 * if the struct has alignment!
2411 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2414 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2417 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2420 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2423 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2426 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2429 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2432 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2435 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2438 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2442 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2446 if (strncmp(s, "./", 2) == 0) {
2452 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2453 const struct sockaddr *src,
2454 const struct sockaddr *dest,
2456 const uint8_t *payload,
2458 unsigned long tcp_seqno,
2459 unsigned long tcp_ack,
2460 unsigned char tcp_ctl,
2462 size_t *_packet_len)
2466 struct swrap_packet_frame *frame;
2467 union swrap_packet_ip *ip;
2468 union swrap_packet_payload *pay;
2471 size_t nonwire_len = sizeof(*frame);
2472 size_t wire_hdr_len = 0;
2473 size_t wire_len = 0;
2474 size_t ip_hdr_len = 0;
2475 size_t icmp_hdr_len = 0;
2476 size_t icmp_truncate_len = 0;
2477 uint8_t protocol = 0, icmp_protocol = 0;
2478 const struct sockaddr_in *src_in = NULL;
2479 const struct sockaddr_in *dest_in = NULL;
2481 const struct sockaddr_in6 *src_in6 = NULL;
2482 const struct sockaddr_in6 *dest_in6 = NULL;
2487 switch (src->sa_family) {
2489 src_in = (const struct sockaddr_in *)(const void *)src;
2490 dest_in = (const struct sockaddr_in *)(const void *)dest;
2491 src_port = src_in->sin_port;
2492 dest_port = dest_in->sin_port;
2493 ip_hdr_len = sizeof(ip->v4);
2497 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2498 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2499 src_port = src_in6->sin6_port;
2500 dest_port = dest_in6->sin6_port;
2501 ip_hdr_len = sizeof(ip->v6);
2508 switch (socket_type) {
2510 protocol = 0x06; /* TCP */
2511 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2512 wire_len = wire_hdr_len + payload_len;
2516 protocol = 0x11; /* UDP */
2517 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2518 wire_len = wire_hdr_len + payload_len;
2526 icmp_protocol = protocol;
2527 switch (src->sa_family) {
2529 protocol = 0x01; /* ICMPv4 */
2530 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2534 protocol = 0x3A; /* ICMPv6 */
2535 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2539 if (wire_len > 64 ) {
2540 icmp_truncate_len = wire_len - 64;
2542 wire_len += icmp_hdr_len;
2545 packet_len = nonwire_len + wire_len;
2546 alloc_len = packet_len;
2547 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2548 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2551 base = (uint8_t *)calloc(1, alloc_len);
2558 frame = (struct swrap_packet_frame *)(void *)buf;
2559 frame->seconds = tval->tv_sec;
2560 frame->micro_seconds = tval->tv_usec;
2561 frame->recorded_length = wire_len - icmp_truncate_len;
2562 frame->full_length = wire_len - icmp_truncate_len;
2563 buf += SWRAP_PACKET_FRAME_SIZE;
2565 ip = (union swrap_packet_ip *)(void *)buf;
2566 switch (src->sa_family) {
2568 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2570 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2571 ip->v4.identification = htons(0xFFFF);
2572 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2573 ip->v4.fragment = htons(0x0000);
2575 ip->v4.protocol = protocol;
2576 ip->v4.hdr_checksum = htons(0x0000);
2577 ip->v4.src_addr = src_in->sin_addr.s_addr;
2578 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2579 buf += SWRAP_PACKET_IP_V4_SIZE;
2583 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2584 ip->v6.flow_label_high = 0x00;
2585 ip->v6.flow_label_low = 0x0000;
2586 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2587 ip->v6.next_header = protocol;
2588 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2589 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2590 buf += SWRAP_PACKET_IP_V6_SIZE;
2596 pay = (union swrap_packet_payload *)(void *)buf;
2597 switch (src->sa_family) {
2599 pay->icmp4.type = 0x03; /* destination unreachable */
2600 pay->icmp4.code = 0x01; /* host unreachable */
2601 pay->icmp4.checksum = htons(0x0000);
2602 pay->icmp4.unused = htonl(0x00000000);
2603 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2605 /* set the ip header in the ICMP payload */
2606 ip = (union swrap_packet_ip *)(void *)buf;
2607 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2609 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2610 ip->v4.identification = htons(0xFFFF);
2611 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2612 ip->v4.fragment = htons(0x0000);
2614 ip->v4.protocol = icmp_protocol;
2615 ip->v4.hdr_checksum = htons(0x0000);
2616 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2617 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2618 buf += SWRAP_PACKET_IP_V4_SIZE;
2620 src_port = dest_in->sin_port;
2621 dest_port = src_in->sin_port;
2625 pay->icmp6.type = 0x01; /* destination unreachable */
2626 pay->icmp6.code = 0x03; /* address unreachable */
2627 pay->icmp6.checksum = htons(0x0000);
2628 pay->icmp6.unused = htonl(0x00000000);
2629 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2631 /* set the ip header in the ICMP payload */
2632 ip = (union swrap_packet_ip *)(void *)buf;
2633 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2634 ip->v6.flow_label_high = 0x00;
2635 ip->v6.flow_label_low = 0x0000;
2636 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2637 ip->v6.next_header = protocol;
2638 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2639 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2640 buf += SWRAP_PACKET_IP_V6_SIZE;
2642 src_port = dest_in6->sin6_port;
2643 dest_port = src_in6->sin6_port;
2649 pay = (union swrap_packet_payload *)(void *)buf;
2651 switch (socket_type) {
2653 pay->tcp.source_port = src_port;
2654 pay->tcp.dest_port = dest_port;
2655 pay->tcp.seq_num = htonl(tcp_seqno);
2656 pay->tcp.ack_num = htonl(tcp_ack);
2657 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2658 pay->tcp.control = tcp_ctl;
2659 pay->tcp.window = htons(0x7FFF);
2660 pay->tcp.checksum = htons(0x0000);
2661 pay->tcp.urg = htons(0x0000);
2662 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2667 pay->udp.source_port = src_port;
2668 pay->udp.dest_port = dest_port;
2669 pay->udp.length = htons(8 + payload_len);
2670 pay->udp.checksum = htons(0x0000);
2671 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2676 if (payload && payload_len > 0) {
2677 memcpy(buf, payload, payload_len);
2680 *_packet_len = packet_len - icmp_truncate_len;
2684 static int swrap_pcap_get_fd(const char *fname)
2692 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2694 struct swrap_file_hdr file_hdr;
2695 file_hdr.magic = 0xA1B2C3D4;
2696 file_hdr.version_major = 0x0002;
2697 file_hdr.version_minor = 0x0004;
2698 file_hdr.timezone = 0x00000000;
2699 file_hdr.sigfigs = 0x00000000;
2700 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2701 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2703 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2710 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2715 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2716 const struct sockaddr *addr,
2717 enum swrap_packet_type type,
2718 const void *buf, size_t len,
2721 const struct sockaddr *src_addr;
2722 const struct sockaddr *dest_addr;
2723 unsigned long tcp_seqno = 0;
2724 unsigned long tcp_ack = 0;
2725 unsigned char tcp_ctl = 0;
2726 int unreachable = 0;
2730 switch (si->family) {
2742 case SWRAP_CONNECT_SEND:
2743 if (si->type != SOCK_STREAM) {
2747 src_addr = &si->myname.sa.s;
2750 tcp_seqno = si->io.pck_snd;
2751 tcp_ack = si->io.pck_rcv;
2752 tcp_ctl = 0x02; /* SYN */
2754 si->io.pck_snd += 1;
2758 case SWRAP_CONNECT_RECV:
2759 if (si->type != SOCK_STREAM) {
2763 dest_addr = &si->myname.sa.s;
2766 tcp_seqno = si->io.pck_rcv;
2767 tcp_ack = si->io.pck_snd;
2768 tcp_ctl = 0x12; /** SYN,ACK */
2770 si->io.pck_rcv += 1;
2774 case SWRAP_CONNECT_UNREACH:
2775 if (si->type != SOCK_STREAM) {
2779 dest_addr = &si->myname.sa.s;
2782 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2783 tcp_seqno = si->io.pck_snd - 1;
2784 tcp_ack = si->io.pck_rcv;
2785 tcp_ctl = 0x02; /* SYN */
2790 case SWRAP_CONNECT_ACK:
2791 if (si->type != SOCK_STREAM) {
2795 src_addr = &si->myname.sa.s;
2798 tcp_seqno = si->io.pck_snd;
2799 tcp_ack = si->io.pck_rcv;
2800 tcp_ctl = 0x10; /* ACK */
2804 case SWRAP_ACCEPT_SEND:
2805 if (si->type != SOCK_STREAM) {
2809 dest_addr = &si->myname.sa.s;
2812 tcp_seqno = si->io.pck_rcv;
2813 tcp_ack = si->io.pck_snd;
2814 tcp_ctl = 0x02; /* SYN */
2816 si->io.pck_rcv += 1;
2820 case SWRAP_ACCEPT_RECV:
2821 if (si->type != SOCK_STREAM) {
2825 src_addr = &si->myname.sa.s;
2828 tcp_seqno = si->io.pck_snd;
2829 tcp_ack = si->io.pck_rcv;
2830 tcp_ctl = 0x12; /* SYN,ACK */
2832 si->io.pck_snd += 1;
2836 case SWRAP_ACCEPT_ACK:
2837 if (si->type != SOCK_STREAM) {
2841 dest_addr = &si->myname.sa.s;
2844 tcp_seqno = si->io.pck_rcv;
2845 tcp_ack = si->io.pck_snd;
2846 tcp_ctl = 0x10; /* ACK */
2851 src_addr = &si->myname.sa.s;
2852 dest_addr = &si->peername.sa.s;
2854 tcp_seqno = si->io.pck_snd;
2855 tcp_ack = si->io.pck_rcv;
2856 tcp_ctl = 0x18; /* PSH,ACK */
2858 si->io.pck_snd += len;
2862 case SWRAP_SEND_RST:
2863 dest_addr = &si->myname.sa.s;
2864 src_addr = &si->peername.sa.s;
2866 if (si->type == SOCK_DGRAM) {
2867 return swrap_pcap_marshall_packet(si,
2869 SWRAP_SENDTO_UNREACH,
2875 tcp_seqno = si->io.pck_rcv;
2876 tcp_ack = si->io.pck_snd;
2877 tcp_ctl = 0x14; /** RST,ACK */
2881 case SWRAP_PENDING_RST:
2882 dest_addr = &si->myname.sa.s;
2883 src_addr = &si->peername.sa.s;
2885 if (si->type == SOCK_DGRAM) {
2889 tcp_seqno = si->io.pck_rcv;
2890 tcp_ack = si->io.pck_snd;
2891 tcp_ctl = 0x14; /* RST,ACK */
2896 dest_addr = &si->myname.sa.s;
2897 src_addr = &si->peername.sa.s;
2899 tcp_seqno = si->io.pck_rcv;
2900 tcp_ack = si->io.pck_snd;
2901 tcp_ctl = 0x18; /* PSH,ACK */
2903 si->io.pck_rcv += len;
2907 case SWRAP_RECV_RST:
2908 dest_addr = &si->myname.sa.s;
2909 src_addr = &si->peername.sa.s;
2911 if (si->type == SOCK_DGRAM) {
2915 tcp_seqno = si->io.pck_rcv;
2916 tcp_ack = si->io.pck_snd;
2917 tcp_ctl = 0x14; /* RST,ACK */
2922 src_addr = &si->myname.sa.s;
2925 si->io.pck_snd += len;
2929 case SWRAP_SENDTO_UNREACH:
2930 dest_addr = &si->myname.sa.s;
2937 case SWRAP_RECVFROM:
2938 dest_addr = &si->myname.sa.s;
2941 si->io.pck_rcv += len;
2945 case SWRAP_CLOSE_SEND:
2946 if (si->type != SOCK_STREAM) {
2950 src_addr = &si->myname.sa.s;
2951 dest_addr = &si->peername.sa.s;
2953 tcp_seqno = si->io.pck_snd;
2954 tcp_ack = si->io.pck_rcv;
2955 tcp_ctl = 0x11; /* FIN, ACK */
2957 si->io.pck_snd += 1;
2961 case SWRAP_CLOSE_RECV:
2962 if (si->type != SOCK_STREAM) {
2966 dest_addr = &si->myname.sa.s;
2967 src_addr = &si->peername.sa.s;
2969 tcp_seqno = si->io.pck_rcv;
2970 tcp_ack = si->io.pck_snd;
2971 tcp_ctl = 0x11; /* FIN,ACK */
2973 si->io.pck_rcv += 1;
2977 case SWRAP_CLOSE_ACK:
2978 if (si->type != SOCK_STREAM) {
2982 src_addr = &si->myname.sa.s;
2983 dest_addr = &si->peername.sa.s;
2985 tcp_seqno = si->io.pck_snd;
2986 tcp_ack = si->io.pck_rcv;
2987 tcp_ctl = 0x10; /* ACK */
2994 swrapGetTimeOfDay(&tv);
2996 return swrap_pcap_packet_init(&tv,
3000 (const uint8_t *)buf,
3009 static void swrap_pcap_dump_packet(struct socket_info *si,
3010 const struct sockaddr *addr,
3011 enum swrap_packet_type type,
3012 const void *buf, size_t len)
3014 const char *file_name;
3016 size_t packet_len = 0;
3019 swrap_mutex_lock(&pcap_dump_mutex);
3021 file_name = swrap_pcap_init_file();
3026 packet = swrap_pcap_marshall_packet(si,
3032 if (packet == NULL) {
3036 fd = swrap_pcap_get_fd(file_name);
3038 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3047 swrap_mutex_unlock(&pcap_dump_mutex);
3050 /****************************************************************************
3052 ***************************************************************************/
3054 #ifdef HAVE_SIGNALFD
3055 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3059 rc = libc_signalfd(fd, mask, flags);
3061 swrap_remove_stale(fd);
3067 int signalfd(int fd, const sigset_t *mask, int flags)
3069 return swrap_signalfd(fd, mask, flags);
3073 /****************************************************************************
3075 ***************************************************************************/
3077 static int swrap_socket(int family, int type, int protocol)
3079 struct socket_info *si = NULL;
3080 struct socket_info _si = { 0 };
3083 int real_type = type;
3086 * Remove possible addition flags passed to socket() so
3087 * do not fail checking the type.
3088 * See https://lwn.net/Articles/281965/
3091 real_type &= ~SOCK_CLOEXEC;
3093 #ifdef SOCK_NONBLOCK
3094 real_type &= ~SOCK_NONBLOCK;
3097 if (!socket_wrapper_enabled()) {
3098 return libc_socket(family, type, protocol);
3109 #endif /* AF_NETLINK */
3112 #endif /* AF_PACKET */
3114 return libc_socket(family, type, protocol);
3116 errno = EAFNOSUPPORT;
3120 switch (real_type) {
3126 errno = EPROTONOSUPPORT;
3134 if (real_type == SOCK_STREAM) {
3139 if (real_type == SOCK_DGRAM) {
3144 errno = EPROTONOSUPPORT;
3149 * We must call libc_socket with type, from the caller, not the version
3150 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3152 fd = libc_socket(AF_UNIX, type, 0);
3158 /* Check if we have a stale fd and remove it */
3159 swrap_remove_stale(fd);
3162 si->family = family;
3164 /* however, the rest of the socket_wrapper code expects just
3165 * the type, not the flags */
3166 si->type = real_type;
3167 si->protocol = protocol;
3170 * Setup myname so getsockname() can succeed to find out the socket
3173 switch(si->family) {
3175 struct sockaddr_in sin = {
3176 .sin_family = AF_INET,
3179 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3180 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3185 struct sockaddr_in6 sin6 = {
3186 .sin6_family = AF_INET6,
3189 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3190 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3199 ret = swrap_create_socket(si, fd);
3204 SWRAP_LOG(SWRAP_LOG_TRACE,
3205 "Created %s socket for protocol %s, fd=%d",
3206 family == AF_INET ? "IPv4" : "IPv6",
3207 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3213 int socket(int family, int type, int protocol)
3215 return swrap_socket(family, type, protocol);
3218 /****************************************************************************
3220 ***************************************************************************/
3222 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3226 rc = libc_socketpair(family, type, protocol, sv);
3228 swrap_remove_stale(sv[0]);
3229 swrap_remove_stale(sv[1]);
3235 int socketpair(int family, int type, int protocol, int sv[2])
3237 return swrap_socketpair(family, type, protocol, sv);
3240 /****************************************************************************
3242 ***************************************************************************/
3244 #ifdef HAVE_TIMERFD_CREATE
3245 static int swrap_timerfd_create(int clockid, int flags)
3249 fd = libc_timerfd_create(clockid, flags);
3251 swrap_remove_stale(fd);
3257 int timerfd_create(int clockid, int flags)
3259 return swrap_timerfd_create(clockid, flags);
3263 /****************************************************************************
3265 ***************************************************************************/
3267 static int swrap_pipe(int pipefd[2])
3271 rc = libc_pipe(pipefd);
3273 swrap_remove_stale(pipefd[0]);
3274 swrap_remove_stale(pipefd[1]);
3280 int pipe(int pipefd[2])
3282 return swrap_pipe(pipefd);
3285 /****************************************************************************
3287 ***************************************************************************/
3289 static int swrap_accept(int s,
3290 struct sockaddr *addr,
3294 struct socket_info *parent_si, *child_si;
3295 struct socket_info new_si = { 0 };
3298 struct swrap_address un_addr = {
3299 .sa_socklen = sizeof(struct sockaddr_un),
3301 struct swrap_address un_my_addr = {
3302 .sa_socklen = sizeof(struct sockaddr_un),
3304 struct swrap_address in_addr = {
3305 .sa_socklen = sizeof(struct sockaddr_storage),
3307 struct swrap_address in_my_addr = {
3308 .sa_socklen = sizeof(struct sockaddr_storage),
3312 parent_si = find_socket_info(s);
3315 return libc_accept4(s, addr, addrlen, flags);
3318 return libc_accept(s, addr, addrlen);
3324 * prevent parent_si from being altered / closed
3327 SWRAP_LOCK_SI(parent_si);
3330 * assume out sockaddr have the same size as the in parent
3333 in_addr.sa_socklen = socket_length(parent_si->family);
3334 if (in_addr.sa_socklen <= 0) {
3335 SWRAP_UNLOCK_SI(parent_si);
3340 SWRAP_UNLOCK_SI(parent_si);
3343 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3346 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3349 if (errno == ENOTSOCK) {
3350 /* Remove stale fds */
3351 swrap_remove_stale(s);
3358 SWRAP_LOCK_SI(parent_si);
3360 ret = sockaddr_convert_from_un(parent_si,
3365 &in_addr.sa_socklen);
3367 SWRAP_UNLOCK_SI(parent_si);
3374 child_si->family = parent_si->family;
3375 child_si->type = parent_si->type;
3376 child_si->protocol = parent_si->protocol;
3377 child_si->bound = 1;
3378 child_si->is_server = 1;
3379 child_si->connected = 1;
3381 SWRAP_UNLOCK_SI(parent_si);
3383 child_si->peername = (struct swrap_address) {
3384 .sa_socklen = in_addr.sa_socklen,
3386 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3388 if (addr != NULL && addrlen != NULL) {
3389 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3391 memcpy(addr, &in_addr.sa.ss, copy_len);
3393 *addrlen = in_addr.sa_socklen;
3396 ret = libc_getsockname(fd,
3398 &un_my_addr.sa_socklen);
3404 ret = sockaddr_convert_from_un(child_si,
3406 un_my_addr.sa_socklen,
3409 &in_my_addr.sa_socklen);
3415 SWRAP_LOG(SWRAP_LOG_TRACE,
3416 "accept() path=%s, fd=%d",
3417 un_my_addr.sa.un.sun_path, s);
3419 child_si->myname = (struct swrap_address) {
3420 .sa_socklen = in_my_addr.sa_socklen,
3422 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3424 idx = swrap_create_socket(&new_si, fd);
3431 struct socket_info *si = swrap_get_socket_info(idx);
3434 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3435 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3436 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3437 SWRAP_UNLOCK_SI(si);
3444 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3446 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3450 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3451 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3453 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3456 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3459 static int autobind_start_init;
3460 static int autobind_start;
3462 /* using sendto() or connect() on an unbound socket would give the
3463 recipient no way to reply, as unlike UDP and TCP, a unix domain
3464 socket can't auto-assign ephemeral port numbers, so we need to
3466 Note: this might change the family from ipv6 to ipv4
3468 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3470 struct swrap_address un_addr = {
3471 .sa_socklen = sizeof(struct sockaddr_un),
3478 char *swrap_dir = NULL;
3480 swrap_mutex_lock(&autobind_start_mutex);
3482 if (autobind_start_init != 1) {
3483 autobind_start_init = 1;
3484 autobind_start = getpid();
3485 autobind_start %= 50000;
3486 autobind_start += 10000;
3489 un_addr.sa.un.sun_family = AF_UNIX;
3493 struct sockaddr_in in;
3497 type = SOCKET_TYPE_CHAR_TCP;
3500 type = SOCKET_TYPE_CHAR_UDP;
3503 errno = ESOCKTNOSUPPORT;
3508 memset(&in, 0, sizeof(in));
3509 in.sin_family = AF_INET;
3510 in.sin_addr.s_addr = htonl(127<<24 |
3511 socket_wrapper_default_iface());
3513 si->myname = (struct swrap_address) {
3514 .sa_socklen = sizeof(in),
3516 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3521 struct sockaddr_in6 in6;
3523 if (si->family != family) {
3524 errno = ENETUNREACH;
3531 type = SOCKET_TYPE_CHAR_TCP_V6;
3534 type = SOCKET_TYPE_CHAR_UDP_V6;
3537 errno = ESOCKTNOSUPPORT;
3542 memset(&in6, 0, sizeof(in6));
3543 in6.sin6_family = AF_INET6;
3544 in6.sin6_addr = *swrap_ipv6();
3545 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3547 si->myname = (struct swrap_address) {
3548 .sa_socklen = sizeof(in6),
3550 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3555 errno = ESOCKTNOSUPPORT;
3560 if (autobind_start > 60000) {
3561 autobind_start = 10000;
3564 swrap_dir = socket_wrapper_dir();
3566 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3567 port = autobind_start + i;
3568 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3569 "%s/"SOCKET_FORMAT, swrap_dir, type,
3570 socket_wrapper_default_iface(), port);
3571 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3573 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3578 si->un_addr = un_addr.sa.un;
3581 autobind_start = port + 1;
3584 if (i == SOCKET_MAX_SOCKETS) {
3585 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3586 "interface "SOCKET_FORMAT,
3589 socket_wrapper_default_iface(),
3596 si->family = family;
3597 set_port(si->family, port, &si->myname);
3602 SAFE_FREE(swrap_dir);
3603 swrap_mutex_unlock(&autobind_start_mutex);
3607 /****************************************************************************
3609 ***************************************************************************/
3611 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3615 struct swrap_address un_addr = {
3616 .sa_socklen = sizeof(struct sockaddr_un),
3618 struct socket_info *si = find_socket_info(s);
3622 return libc_connect(s, serv_addr, addrlen);
3627 if (si->bound == 0) {
3628 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3634 if (si->family != serv_addr->sa_family) {
3640 ret = sockaddr_convert_to_un(si, serv_addr,
3641 addrlen, &un_addr.sa.un, 0, &bcast);
3647 errno = ENETUNREACH;
3652 if (si->type == SOCK_DGRAM) {
3653 si->defer_connect = 1;
3656 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3658 ret = libc_connect(s,
3660 un_addr.sa_socklen);
3663 SWRAP_LOG(SWRAP_LOG_TRACE,
3664 "connect() path=%s, fd=%d",
3665 un_addr.sa.un.sun_path, s);
3668 /* to give better errors */
3669 if (ret == -1 && errno == ENOENT) {
3670 errno = EHOSTUNREACH;
3674 si->peername = (struct swrap_address) {
3675 .sa_socklen = addrlen,
3678 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3682 * When we connect() on a socket than we have to bind the
3683 * outgoing connection on the interface we use for the
3684 * transport. We already bound it on the right interface
3685 * but here we have to update the name so getsockname()
3686 * returns correct information.
3688 if (si->bindname.sa_socklen > 0) {
3689 si->myname = (struct swrap_address) {
3690 .sa_socklen = si->bindname.sa_socklen,
3693 memcpy(&si->myname.sa.ss,
3694 &si->bindname.sa.ss,
3695 si->bindname.sa_socklen);
3697 /* Cleanup bindname */
3698 si->bindname = (struct swrap_address) {
3703 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3704 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3706 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3710 SWRAP_UNLOCK_SI(si);
3714 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3716 return swrap_connect(s, serv_addr, addrlen);
3719 /****************************************************************************
3721 ***************************************************************************/
3723 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3726 struct swrap_address un_addr = {
3727 .sa_socklen = sizeof(struct sockaddr_un),
3729 struct socket_info *si = find_socket_info(s);
3736 return libc_bind(s, myaddr, addrlen);
3741 switch (si->family) {
3743 const struct sockaddr_in *sin;
3744 if (addrlen < sizeof(struct sockaddr_in)) {
3745 bind_error = EINVAL;
3749 sin = (const struct sockaddr_in *)(const void *)myaddr;
3751 if (sin->sin_family != AF_INET) {
3752 bind_error = EAFNOSUPPORT;
3755 /* special case for AF_UNSPEC */
3756 if (sin->sin_family == AF_UNSPEC &&
3757 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3766 const struct sockaddr_in6 *sin6;
3767 if (addrlen < sizeof(struct sockaddr_in6)) {
3768 bind_error = EINVAL;
3772 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3774 if (sin6->sin6_family != AF_INET6) {
3775 bind_error = EAFNOSUPPORT;
3782 bind_error = EINVAL;
3786 if (bind_error != 0) {
3793 in_use = check_addr_port_in_use(myaddr, addrlen);
3801 si->myname.sa_socklen = addrlen;
3802 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3804 ret = sockaddr_convert_to_un(si,
3814 unlink(un_addr.sa.un.sun_path);
3816 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3818 SWRAP_LOG(SWRAP_LOG_TRACE,
3819 "bind() path=%s, fd=%d",
3820 un_addr.sa.un.sun_path, s);
3827 SWRAP_UNLOCK_SI(si);
3832 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3834 return swrap_bind(s, myaddr, addrlen);
3837 /****************************************************************************
3839 ***************************************************************************/
3841 #ifdef HAVE_BINDRESVPORT
3842 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3844 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3846 struct swrap_address myaddr = {
3847 .sa_socklen = sizeof(struct sockaddr_storage),
3850 static uint16_t port;
3855 #define SWRAP_STARTPORT 600
3856 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3857 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3860 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3864 salen = myaddr.sa_socklen;
3867 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3873 memset(&myaddr.sa.ss, 0, salen);
3878 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3881 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3883 salen = sizeof(struct sockaddr_in);
3884 sinp->sin_port = htons(port);
3888 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3890 salen = sizeof(struct sockaddr_in6);
3891 sin6p->sin6_port = htons(port);
3895 errno = EAFNOSUPPORT;
3900 if (port > SWRAP_ENDPORT) {
3901 port = SWRAP_STARTPORT;
3904 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3905 if (rc == 0 || errno != EADDRINUSE) {
3913 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3915 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3919 /****************************************************************************
3921 ***************************************************************************/
3923 static int swrap_listen(int s, int backlog)
3926 struct socket_info *si = find_socket_info(s);
3929 return libc_listen(s, backlog);
3934 if (si->bound == 0) {
3935 ret = swrap_auto_bind(s, si, si->family);
3942 ret = libc_listen(s, backlog);
3945 SWRAP_UNLOCK_SI(si);
3950 int listen(int s, int backlog)
3952 return swrap_listen(s, backlog);
3955 /****************************************************************************
3957 ***************************************************************************/
3959 static FILE *swrap_fopen(const char *name, const char *mode)
3963 fp = libc_fopen(name, mode);
3965 int fd = fileno(fp);
3967 swrap_remove_stale(fd);
3973 FILE *fopen(const char *name, const char *mode)
3975 return swrap_fopen(name, mode);
3978 /****************************************************************************
3980 ***************************************************************************/
3983 static FILE *swrap_fopen64(const char *name, const char *mode)
3987 fp = libc_fopen64(name, mode);
3989 int fd = fileno(fp);
3991 swrap_remove_stale(fd);
3997 FILE *fopen64(const char *name, const char *mode)
3999 return swrap_fopen64(name, mode);
4001 #endif /* HAVE_FOPEN64 */
4003 /****************************************************************************
4005 ***************************************************************************/
4007 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4011 ret = libc_vopen(pathname, flags, ap);
4014 * There are methods for closing descriptors (libc-internal code
4015 * paths, direct syscalls) which close descriptors in ways that
4016 * we can't intercept, so try to recover when we notice that
4019 swrap_remove_stale(ret);
4024 int open(const char *pathname, int flags, ...)
4029 va_start(ap, flags);
4030 fd = swrap_vopen(pathname, flags, ap);
4036 /****************************************************************************
4038 ***************************************************************************/
4041 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4045 ret = libc_vopen64(pathname, flags, ap);
4048 * There are methods for closing descriptors (libc-internal code
4049 * paths, direct syscalls) which close descriptors in ways that
4050 * we can't intercept, so try to recover when we notice that
4053 swrap_remove_stale(ret);
4058 int open64(const char *pathname, int flags, ...)
4063 va_start(ap, flags);
4064 fd = swrap_vopen64(pathname, flags, ap);
4069 #endif /* HAVE_OPEN64 */
4071 /****************************************************************************
4073 ***************************************************************************/
4075 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4079 ret = libc_vopenat(dirfd, path, flags, ap);
4082 * There are methods for closing descriptors (libc-internal code
4083 * paths, direct syscalls) which close descriptors in ways that
4084 * we can't intercept, so try to recover when we notice that
4087 swrap_remove_stale(ret);
4093 int openat(int dirfd, const char *path, int flags, ...)
4098 va_start(ap, flags);
4099 fd = swrap_vopenat(dirfd, path, flags, ap);
4105 /****************************************************************************
4107 ***************************************************************************/
4109 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4111 struct socket_info *si = find_socket_info(s);
4116 return libc_getpeername(s, name, addrlen);
4121 if (si->peername.sa_socklen == 0)
4127 len = MIN(*addrlen, si->peername.sa_socklen);
4133 memcpy(name, &si->peername.sa.ss, len);
4134 *addrlen = si->peername.sa_socklen;
4138 SWRAP_UNLOCK_SI(si);
4143 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4144 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4146 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4149 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4152 /****************************************************************************
4154 ***************************************************************************/
4156 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4158 struct socket_info *si = find_socket_info(s);
4163 return libc_getsockname(s, name, addrlen);
4168 len = MIN(*addrlen, si->myname.sa_socklen);
4174 memcpy(name, &si->myname.sa.ss, len);
4175 *addrlen = si->myname.sa_socklen;
4179 SWRAP_UNLOCK_SI(si);
4184 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4185 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4187 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4190 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4193 /****************************************************************************
4195 ***************************************************************************/
4198 # ifdef SO_PROTOTYPE /* The Solaris name */
4199 # define SO_PROTOCOL SO_PROTOTYPE
4200 # endif /* SO_PROTOTYPE */
4201 #endif /* SO_PROTOCOL */
4203 static int swrap_getsockopt(int s, int level, int optname,
4204 void *optval, socklen_t *optlen)
4206 struct socket_info *si = find_socket_info(s);
4210 return libc_getsockopt(s,
4219 if (level == SOL_SOCKET) {
4223 if (optval == NULL || optlen == NULL ||
4224 *optlen < (socklen_t)sizeof(int)) {
4230 *optlen = sizeof(int);
4231 *(int *)optval = si->family;
4234 #endif /* SO_DOMAIN */
4238 if (optval == NULL || optlen == NULL ||
4239 *optlen < (socklen_t)sizeof(int)) {
4245 *optlen = sizeof(int);
4246 *(int *)optval = si->protocol;
4249 #endif /* SO_PROTOCOL */
4251 if (optval == NULL || optlen == NULL ||
4252 *optlen < (socklen_t)sizeof(int)) {
4258 *optlen = sizeof(int);
4259 *(int *)optval = si->type;
4263 ret = libc_getsockopt(s,
4270 } else if (level == IPPROTO_TCP) {
4275 * This enables sending packets directly out over TCP.
4276 * As a unix socket is doing that any way, report it as
4279 if (optval == NULL || optlen == NULL ||
4280 *optlen < (socklen_t)sizeof(int)) {
4286 *optlen = sizeof(int);
4287 *(int *)optval = si->tcp_nodelay;
4291 #endif /* TCP_NODELAY */
4297 errno = ENOPROTOOPT;
4301 SWRAP_UNLOCK_SI(si);
4305 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4306 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4308 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4311 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4314 /****************************************************************************
4316 ***************************************************************************/
4318 static int swrap_setsockopt(int s, int level, int optname,
4319 const void *optval, socklen_t optlen)
4321 struct socket_info *si = find_socket_info(s);
4325 return libc_setsockopt(s,
4332 if (level == SOL_SOCKET) {
4333 return libc_setsockopt(s,
4342 if (level == IPPROTO_TCP) {
4349 * This enables sending packets directly out over TCP.
4350 * A unix socket is doing that any way.
4352 if (optval == NULL || optlen == 0 ||
4353 optlen < (socklen_t)sizeof(int)) {
4359 i = *discard_const_p(int, optval);
4360 if (i != 0 && i != 1) {
4365 si->tcp_nodelay = i;
4370 #endif /* TCP_NODELAY */
4376 switch (si->family) {
4378 if (level == IPPROTO_IP) {
4380 if (optname == IP_PKTINFO) {
4381 si->pktinfo = AF_INET;
4383 #endif /* IP_PKTINFO */
4389 if (level == IPPROTO_IPV6) {
4390 #ifdef IPV6_RECVPKTINFO
4391 if (optname == IPV6_RECVPKTINFO) {
4392 si->pktinfo = AF_INET6;
4394 #endif /* IPV6_PKTINFO */
4400 errno = ENOPROTOOPT;
4406 SWRAP_UNLOCK_SI(si);
4410 int setsockopt(int s, int level, int optname,
4411 const void *optval, socklen_t optlen)
4413 return swrap_setsockopt(s, level, optname, optval, optlen);
4416 /****************************************************************************
4418 ***************************************************************************/
4420 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4422 struct socket_info *si = find_socket_info(s);
4428 return libc_vioctl(s, r, va);
4435 rc = libc_vioctl(s, r, va);
4439 value = *((int *)va_arg(ap, int *));
4441 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4442 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4443 } else if (value == 0) { /* END OF FILE */
4444 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4451 SWRAP_UNLOCK_SI(si);
4455 #ifdef HAVE_IOCTL_INT
4456 int ioctl(int s, int r, ...)
4458 int ioctl(int s, unsigned long int r, ...)
4466 rc = swrap_vioctl(s, (unsigned long int) r, va);
4477 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4480 # ifdef _ALIGN /* BSD */
4481 #define CMSG_ALIGN _ALIGN
4483 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4484 # endif /* _ALIGN */
4485 #endif /* CMSG_ALIGN */
4488 * @brief Add a cmsghdr to a msghdr.
4490 * This is an function to add any type of cmsghdr. It will operate on the
4491 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4492 * the buffer position after the added cmsg element. Hence, this function is
4493 * intended to be used with an intermediate msghdr and not on the original
4494 * one handed in by the client.
4496 * @param[in] msg The msghdr to which to add the cmsg.
4498 * @param[in] level The cmsg level to set.
4500 * @param[in] type The cmsg type to set.
4502 * @param[in] data The cmsg data to set.
4504 * @param[in] len the length of the data to set.
4506 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4512 size_t cmlen = CMSG_LEN(len);
4513 size_t cmspace = CMSG_SPACE(len);
4514 uint8_t cmbuf[cmspace];
4515 void *cast_ptr = (void *)cmbuf;
4516 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4519 memset(cmbuf, 0, cmspace);
4521 if (msg->msg_controllen < cmlen) {
4522 cmlen = msg->msg_controllen;
4523 msg->msg_flags |= MSG_CTRUNC;
4526 if (msg->msg_controllen < cmspace) {
4527 cmspace = msg->msg_controllen;
4531 * We copy the full input data into an intermediate cmsghdr first
4532 * in order to more easily cope with truncation.
4534 cm->cmsg_len = cmlen;
4535 cm->cmsg_level = level;
4536 cm->cmsg_type = type;
4537 memcpy(CMSG_DATA(cm), data, len);
4540 * We now copy the possibly truncated buffer.
4541 * We copy cmlen bytes, but consume cmspace bytes,
4542 * leaving the possible padding uninitialiazed.
4544 p = (uint8_t *)msg->msg_control;
4545 memcpy(p, cm, cmlen);
4547 msg->msg_control = p;
4548 msg->msg_controllen -= cmspace;
4553 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4556 /* Add packet info */
4557 switch (si->pktinfo) {
4558 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4560 struct sockaddr_in *sin;
4561 #if defined(HAVE_STRUCT_IN_PKTINFO)
4562 struct in_pktinfo pkt;
4563 #elif defined(IP_RECVDSTADDR)
4567 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4568 sin = &si->bindname.sa.in;
4570 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4573 sin = &si->myname.sa.in;
4578 #if defined(HAVE_STRUCT_IN_PKTINFO)
4579 pkt.ipi_ifindex = socket_wrapper_default_iface();
4580 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4581 #elif defined(IP_RECVDSTADDR)
4582 pkt = sin->sin_addr;
4585 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4590 #endif /* IP_PKTINFO */
4591 #if defined(HAVE_IPV6)
4593 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4594 struct sockaddr_in6 *sin6;
4595 struct in6_pktinfo pkt6;
4597 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4598 sin6 = &si->bindname.sa.in6;
4600 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4603 sin6 = &si->myname.sa.in6;
4608 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4609 pkt6.ipi6_addr = sin6->sin6_addr;
4611 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4612 &pkt6, sizeof(pkt6));
4613 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4617 #endif /* IPV6_PKTINFO */
4625 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4626 struct msghdr *omsg)
4630 if (si->pktinfo > 0) {
4631 rc = swrap_msghdr_add_pktinfo(si, omsg);
4637 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4639 size_t *cm_data_space);
4640 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4642 size_t *cm_data_space);
4644 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4646 size_t *cm_data_space) {
4647 struct cmsghdr *cmsg;
4651 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4655 for (cmsg = CMSG_FIRSTHDR(msg);
4657 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4658 switch (cmsg->cmsg_level) {
4660 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4665 rc = swrap_sendmsg_copy_cmsg(cmsg,
4675 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4677 size_t *cm_data_space)
4682 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4684 p = realloc((*cm_data), cmspace);
4690 p = (*cm_data) + (*cm_data_space);
4691 *cm_data_space = cmspace;
4693 memcpy(p, cmsg, cmsg->cmsg_len);
4698 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4700 size_t *cm_data_space);
4703 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4705 size_t *cm_data_space)
4709 switch(cmsg->cmsg_type) {
4712 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4719 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4731 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4733 size_t *cm_data_space)
4735 (void)cmsg; /* unused */
4736 (void)cm_data; /* unused */
4737 (void)cm_data_space; /* unused */
4740 * Passing a IP pktinfo to a unix socket might be rejected by the
4741 * Kernel, at least on FreeBSD. So skip this cmsg.
4745 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4747 static ssize_t swrap_sendmsg_before(int fd,
4748 struct socket_info *si,
4750 struct iovec *tmp_iov,
4751 struct sockaddr_un *tmp_un,
4752 const struct sockaddr_un **to_un,
4753 const struct sockaddr **to,
4775 if (!si->connected) {
4780 if (msg->msg_iovlen == 0) {
4784 mtu = socket_wrapper_mtu();
4785 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4787 nlen = len + msg->msg_iov[i].iov_len;
4797 msg->msg_iovlen = i;
4798 if (msg->msg_iovlen == 0) {
4799 *tmp_iov = msg->msg_iov[0];
4800 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4802 msg->msg_iov = tmp_iov;
4803 msg->msg_iovlen = 1;
4808 if (si->connected) {
4809 if (msg->msg_name != NULL) {
4811 * We are dealing with unix sockets and if we
4812 * are connected, we should only talk to the
4813 * connected unix path. Using the fd to send
4814 * to another server would be hard to achieve.
4816 msg->msg_name = NULL;
4817 msg->msg_namelen = 0;
4820 const struct sockaddr *msg_name;
4821 msg_name = (const struct sockaddr *)msg->msg_name;
4823 if (msg_name == NULL) {
4829 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4841 msg->msg_name = tmp_un;
4842 msg->msg_namelen = sizeof(*tmp_un);
4845 if (si->bound == 0) {
4846 ret = swrap_auto_bind(fd, si, si->family);
4848 SWRAP_UNLOCK_SI(si);
4849 if (errno == ENOTSOCK) {
4850 swrap_remove_stale(fd);
4853 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4859 if (!si->defer_connect) {
4863 ret = sockaddr_convert_to_un(si,
4865 si->peername.sa_socklen,
4873 ret = libc_connect(fd,
4874 (struct sockaddr *)(void *)tmp_un,
4877 /* to give better errors */
4878 if (ret == -1 && errno == ENOENT) {
4879 errno = EHOSTUNREACH;
4886 si->defer_connect = 0;
4889 errno = EHOSTUNREACH;
4893 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4894 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4895 uint8_t *cmbuf = NULL;
4898 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4905 msg->msg_controllen = 0;
4906 msg->msg_control = NULL;
4907 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4908 memcpy(msg->msg_control, cmbuf, cmlen);
4909 msg->msg_controllen = cmlen;
4917 SWRAP_UNLOCK_SI(si);
4922 static void swrap_sendmsg_after(int fd,
4923 struct socket_info *si,
4925 const struct sockaddr *to,
4928 int saved_errno = errno;
4935 /* to give better errors */
4937 if (saved_errno == ENOENT) {
4938 saved_errno = EHOSTUNREACH;
4939 } else if (saved_errno == ENOTSOCK) {
4940 /* If the fd is not a socket, remove it */
4941 swrap_remove_stale(fd);
4945 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4946 avail += msg->msg_iov[i].iov_len;
4950 remain = MIN(80, avail);
4955 /* we capture it as one single packet */
4956 buf = (uint8_t *)malloc(remain);
4958 /* we just not capture the packet */
4959 errno = saved_errno;
4963 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4964 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4966 msg->msg_iov[i].iov_base,
4969 remain -= this_time;
4978 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4979 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4981 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4986 if (si->connected) {
4987 to = &si->peername.sa.s;
4990 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4991 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4993 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4998 SWRAP_UNLOCK_SI(si);
5001 errno = saved_errno;
5004 static int swrap_recvmsg_before(int fd,
5005 struct socket_info *si,
5007 struct iovec *tmp_iov)
5014 (void)fd; /* unused */
5019 if (!si->connected) {
5024 if (msg->msg_iovlen == 0) {
5028 mtu = socket_wrapper_mtu();
5029 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5031 nlen = len + msg->msg_iov[i].iov_len;
5036 msg->msg_iovlen = i;
5037 if (msg->msg_iovlen == 0) {
5038 *tmp_iov = msg->msg_iov[0];
5039 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5041 msg->msg_iov = tmp_iov;
5042 msg->msg_iovlen = 1;
5047 if (msg->msg_name == NULL) {
5052 if (msg->msg_iovlen == 0) {
5056 if (si->bound == 0) {
5057 ret = swrap_auto_bind(fd, si, si->family);
5059 SWRAP_UNLOCK_SI(si);
5061 * When attempting to read or write to a
5062 * descriptor, if an underlying autobind fails
5063 * because it's not a socket, stop intercepting
5064 * uses of that descriptor.
5066 if (errno == ENOTSOCK) {
5067 swrap_remove_stale(fd);
5070 SWRAP_LOG(SWRAP_LOG_ERROR,
5071 "swrap_recvmsg_before failed");
5078 errno = EHOSTUNREACH;
5084 SWRAP_UNLOCK_SI(si);
5089 static int swrap_recvmsg_after(int fd,
5090 struct socket_info *si,
5092 const struct sockaddr_un *un_addr,
5093 socklen_t un_addrlen,
5096 int saved_errno = errno;
5098 uint8_t *buf = NULL;
5104 /* to give better errors */
5106 if (saved_errno == ENOENT) {
5107 saved_errno = EHOSTUNREACH;
5108 } else if (saved_errno == ENOTSOCK) {
5109 /* If the fd is not a socket, remove it */
5110 swrap_remove_stale(fd);
5114 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5115 avail += msg->msg_iov[i].iov_len;
5120 /* Convert the socket address before we leave */
5121 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5122 rc = sockaddr_convert_from_un(si,
5139 remain = MIN(80, avail);
5144 /* we capture it as one single packet */
5145 buf = (uint8_t *)malloc(remain);
5147 /* we just not capture the packet */
5148 SWRAP_UNLOCK_SI(si);
5149 errno = saved_errno;
5153 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5154 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5156 msg->msg_iov[i].iov_base,
5159 remain -= this_time;
5164 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5165 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5166 } else if (ret == 0) { /* END OF FILE */
5167 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5168 } else if (ret > 0) {
5169 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5178 if (un_addr != NULL) {
5179 swrap_pcap_dump_packet(si,
5185 swrap_pcap_dump_packet(si,
5198 errno = saved_errno;
5200 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5202 msg->msg_controllen > 0 &&
5203 msg->msg_control != NULL) {
5204 rc = swrap_msghdr_add_socket_info(si, msg);
5206 SWRAP_UNLOCK_SI(si);
5212 SWRAP_UNLOCK_SI(si);
5216 /****************************************************************************
5218 ***************************************************************************/
5220 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5221 struct sockaddr *from, socklen_t *fromlen)
5223 struct swrap_address from_addr = {
5224 .sa_socklen = sizeof(struct sockaddr_un),
5227 struct socket_info *si = find_socket_info(s);
5228 struct swrap_address saddr = {
5229 .sa_socklen = sizeof(struct sockaddr_storage),
5236 return libc_recvfrom(s,
5248 if (from != NULL && fromlen != NULL) {
5249 msg.msg_name = from; /* optional address */
5250 msg.msg_namelen = *fromlen; /* size of address */
5252 msg.msg_name = &saddr.sa.s; /* optional address */
5253 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5255 msg.msg_iov = &tmp; /* scatter/gather array */
5256 msg.msg_iovlen = 1; /* # elements in msg_iov */
5257 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5258 msg.msg_control = NULL; /* ancillary data, see below */
5259 msg.msg_controllen = 0; /* ancillary data buffer len */
5260 msg.msg_flags = 0; /* flags on received message */
5263 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5268 buf = msg.msg_iov[0].iov_base;
5269 len = msg.msg_iov[0].iov_len;
5271 ret = libc_recvfrom(s,
5276 &from_addr.sa_socklen);
5281 tret = swrap_recvmsg_after(s,
5285 from_addr.sa_socklen,
5291 if (from != NULL && fromlen != NULL) {
5292 *fromlen = msg.msg_namelen;
5298 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5299 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5300 struct sockaddr *from, Psocklen_t fromlen)
5302 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5303 struct sockaddr *from, socklen_t *fromlen)
5306 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5309 /****************************************************************************
5311 ***************************************************************************/
5313 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5314 const struct sockaddr *to, socklen_t tolen)
5318 struct swrap_address un_addr = {
5319 .sa_socklen = sizeof(struct sockaddr_un),
5321 const struct sockaddr_un *to_un = NULL;
5324 struct socket_info *si = find_socket_info(s);
5328 return libc_sendto(s, buf, len, flags, to, tolen);
5331 tmp.iov_base = discard_const_p(char, buf);
5335 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5336 msg.msg_namelen = tolen; /* size of address */
5337 msg.msg_iov = &tmp; /* scatter/gather array */
5338 msg.msg_iovlen = 1; /* # elements in msg_iov */
5339 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5340 msg.msg_control = NULL; /* ancillary data, see below */
5341 msg.msg_controllen = 0; /* ancillary data buffer len */
5342 msg.msg_flags = 0; /* flags on received message */
5345 rc = swrap_sendmsg_before(s,
5357 buf = msg.msg_iov[0].iov_base;
5358 len = msg.msg_iov[0].iov_len;
5363 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5365 char *swrap_dir = NULL;
5367 type = SOCKET_TYPE_CHAR_UDP;
5369 swrap_dir = socket_wrapper_dir();
5371 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5372 snprintf(un_addr.sa.un.sun_path,
5373 sizeof(un_addr.sa.un.sun_path),
5374 "%s/"SOCKET_FORMAT, swrap_dir, type, iface, prt);
5375 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5377 /* ignore the any errors in broadcast sends */
5383 un_addr.sa_socklen);
5386 SAFE_FREE(swrap_dir);
5390 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5392 SWRAP_UNLOCK_SI(si);
5399 * If it is a dgram socket and we are connected, don't include the
5402 if (si->type == SOCK_DGRAM && si->connected) {
5403 ret = libc_sendto(s,
5410 ret = libc_sendto(s,
5414 (struct sockaddr *)msg.msg_name,
5418 SWRAP_UNLOCK_SI(si);
5420 swrap_sendmsg_after(s, si, &msg, to, ret);
5425 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5426 const struct sockaddr *to, socklen_t tolen)
5428 return swrap_sendto(s, buf, len, flags, to, tolen);
5431 /****************************************************************************
5433 ***************************************************************************/
5435 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5437 struct socket_info *si;
5439 struct swrap_address saddr = {
5440 .sa_socklen = sizeof(struct sockaddr_storage),
5446 si = find_socket_info(s);
5448 return libc_recv(s, buf, len, flags);
5455 msg.msg_name = &saddr.sa.s; /* optional address */
5456 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5457 msg.msg_iov = &tmp; /* scatter/gather array */
5458 msg.msg_iovlen = 1; /* # elements in msg_iov */
5459 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5460 msg.msg_control = NULL; /* ancillary data, see below */
5461 msg.msg_controllen = 0; /* ancillary data buffer len */
5462 msg.msg_flags = 0; /* flags on received message */
5465 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5470 buf = msg.msg_iov[0].iov_base;
5471 len = msg.msg_iov[0].iov_len;
5473 ret = libc_recv(s, buf, len, flags);
5475 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5483 ssize_t recv(int s, void *buf, size_t len, int flags)
5485 return swrap_recv(s, buf, len, flags);
5488 /****************************************************************************
5490 ***************************************************************************/
5492 static ssize_t swrap_read(int s, void *buf, size_t len)
5494 struct socket_info *si;
5497 struct swrap_address saddr = {
5498 .sa_socklen = sizeof(struct sockaddr_storage),
5503 si = find_socket_info(s);
5505 return libc_read(s, buf, len);
5512 msg.msg_name = &saddr.sa.ss; /* optional address */
5513 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5514 msg.msg_iov = &tmp; /* scatter/gather array */
5515 msg.msg_iovlen = 1; /* # elements in msg_iov */
5516 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5517 msg.msg_control = NULL; /* ancillary data, see below */
5518 msg.msg_controllen = 0; /* ancillary data buffer len */
5519 msg.msg_flags = 0; /* flags on received message */
5522 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5524 if (tret == -ENOTSOCK) {
5525 return libc_read(s, buf, len);
5530 buf = msg.msg_iov[0].iov_base;
5531 len = msg.msg_iov[0].iov_len;
5533 ret = libc_read(s, buf, len);
5535 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5543 ssize_t read(int s, void *buf, size_t len)
5545 return swrap_read(s, buf, len);
5548 /****************************************************************************
5550 ***************************************************************************/
5552 static ssize_t swrap_write(int s, const void *buf, size_t len)
5556 struct sockaddr_un un_addr;
5559 struct socket_info *si;
5561 si = find_socket_info(s);
5563 return libc_write(s, buf, len);
5566 tmp.iov_base = discard_const_p(char, buf);
5570 msg.msg_name = NULL; /* optional address */
5571 msg.msg_namelen = 0; /* size of address */
5572 msg.msg_iov = &tmp; /* scatter/gather array */
5573 msg.msg_iovlen = 1; /* # elements in msg_iov */
5574 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5575 msg.msg_control = NULL; /* ancillary data, see below */
5576 msg.msg_controllen = 0; /* ancillary data buffer len */
5577 msg.msg_flags = 0; /* flags on received message */
5580 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5585 buf = msg.msg_iov[0].iov_base;
5586 len = msg.msg_iov[0].iov_len;
5588 ret = libc_write(s, buf, len);
5590 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5595 ssize_t write(int s, const void *buf, size_t len)
5597 return swrap_write(s, buf, len);
5600 /****************************************************************************
5602 ***************************************************************************/
5604 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5608 struct sockaddr_un un_addr;
5611 struct socket_info *si = find_socket_info(s);
5614 return libc_send(s, buf, len, flags);
5617 tmp.iov_base = discard_const_p(char, buf);
5621 msg.msg_name = NULL; /* optional address */
5622 msg.msg_namelen = 0; /* size of address */
5623 msg.msg_iov = &tmp; /* scatter/gather array */
5624 msg.msg_iovlen = 1; /* # elements in msg_iov */
5625 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5626 msg.msg_control = NULL; /* ancillary data, see below */
5627 msg.msg_controllen = 0; /* ancillary data buffer len */
5628 msg.msg_flags = 0; /* flags on received message */
5631 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5636 buf = msg.msg_iov[0].iov_base;
5637 len = msg.msg_iov[0].iov_len;
5639 ret = libc_send(s, buf, len, flags);
5641 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5646 ssize_t send(int s, const void *buf, size_t len, int flags)
5648 return swrap_send(s, buf, len, flags);
5651 /****************************************************************************
5653 ***************************************************************************/
5655 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5657 struct swrap_address from_addr = {
5658 .sa_socklen = sizeof(struct sockaddr_un),
5660 struct swrap_address convert_addr = {
5661 .sa_socklen = sizeof(struct sockaddr_storage),
5663 struct socket_info *si;
5666 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5667 size_t msg_ctrllen_filled;
5668 size_t msg_ctrllen_left;
5674 si = find_socket_info(s);
5676 return libc_recvmsg(s, omsg, flags);
5679 tmp.iov_base = NULL;
5683 msg.msg_name = &from_addr.sa; /* optional address */
5684 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5685 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5686 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5687 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5688 msg_ctrllen_filled = 0;
5689 msg_ctrllen_left = omsg->msg_controllen;
5691 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5692 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5693 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5696 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5701 ret = libc_recvmsg(s, &msg, flags);
5703 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5704 msg_ctrllen_filled += msg.msg_controllen;
5705 msg_ctrllen_left -= msg.msg_controllen;
5707 if (omsg->msg_control != NULL) {
5710 p = omsg->msg_control;
5711 p += msg_ctrllen_filled;
5713 msg.msg_control = p;
5714 msg.msg_controllen = msg_ctrllen_left;
5716 msg.msg_control = NULL;
5717 msg.msg_controllen = 0;
5722 * We convert the unix address to a IP address so we need a buffer
5723 * which can store the address in case of SOCK_DGRAM, see below.
5725 msg.msg_name = &convert_addr.sa;
5726 msg.msg_namelen = convert_addr.sa_socklen;
5728 rc = swrap_recvmsg_after(s,
5732 from_addr.sa_socklen,
5738 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5739 if (omsg->msg_control != NULL) {
5740 /* msg.msg_controllen = space left */
5741 msg_ctrllen_left = msg.msg_controllen;
5742 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5745 /* Update the original message length */
5746 omsg->msg_controllen = msg_ctrllen_filled;
5747 omsg->msg_flags = msg.msg_flags;
5749 omsg->msg_iovlen = msg.msg_iovlen;
5756 * The msg_name field points to a caller-allocated buffer that is
5757 * used to return the source address if the socket is unconnected. The
5758 * caller should set msg_namelen to the size of this buffer before this
5759 * call; upon return from a successful call, msg_name will contain the
5760 * length of the returned address. If the application does not need
5761 * to know the source address, msg_name can be specified as NULL.
5763 if (si->type == SOCK_STREAM) {
5764 omsg->msg_namelen = 0;
5765 } else if (omsg->msg_name != NULL &&
5766 omsg->msg_namelen != 0 &&
5767 omsg->msg_namelen >= msg.msg_namelen) {
5768 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5769 omsg->msg_namelen = msg.msg_namelen;
5772 SWRAP_UNLOCK_SI(si);
5777 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5779 return swrap_recvmsg(sockfd, msg, flags);
5782 /****************************************************************************
5784 ***************************************************************************/
5786 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5790 struct sockaddr_un un_addr;
5791 const struct sockaddr_un *to_un = NULL;
5792 const struct sockaddr *to = NULL;
5795 struct socket_info *si = find_socket_info(s);
5799 return libc_sendmsg(s, omsg, flags);
5802 ZERO_STRUCT(un_addr);
5804 tmp.iov_base = NULL;
5811 if (si->connected == 0) {
5812 msg.msg_name = omsg->msg_name; /* optional address */
5813 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5815 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5816 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5818 SWRAP_UNLOCK_SI(si);
5820 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5821 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5822 /* omsg is a const so use a local buffer for modifications */
5823 uint8_t cmbuf[omsg->msg_controllen];
5825 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5827 msg.msg_control = cmbuf; /* ancillary data, see below */
5828 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5830 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5833 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5841 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5848 char *swrap_dir = NULL;
5850 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5851 avail += msg.msg_iov[i].iov_len;
5857 /* we capture it as one single packet */
5858 buf = (uint8_t *)malloc(remain);
5863 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5864 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5866 msg.msg_iov[i].iov_base,
5869 remain -= this_time;
5872 type = SOCKET_TYPE_CHAR_UDP;
5874 swrap_dir = socket_wrapper_dir();
5876 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5877 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5878 swrap_dir, type, iface, prt);
5879 if (stat(un_addr.sun_path, &st) != 0) continue;
5881 msg.msg_name = &un_addr; /* optional address */
5882 msg.msg_namelen = sizeof(un_addr); /* size of address */
5884 /* ignore the any errors in broadcast sends */
5885 libc_sendmsg(s, &msg, flags);
5888 SAFE_FREE(swrap_dir);
5892 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5895 SWRAP_UNLOCK_SI(si);
5900 ret = libc_sendmsg(s, &msg, flags);
5902 swrap_sendmsg_after(s, si, &msg, to, ret);
5907 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5909 return swrap_sendmsg(s, omsg, flags);
5912 /****************************************************************************
5914 ***************************************************************************/
5916 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5918 struct socket_info *si;
5921 struct swrap_address saddr = {
5922 .sa_socklen = sizeof(struct sockaddr_storage)
5927 si = find_socket_info(s);
5929 return libc_readv(s, vector, count);
5932 tmp.iov_base = NULL;
5936 msg.msg_name = &saddr.sa.s; /* optional address */
5937 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5938 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5939 msg.msg_iovlen = count; /* # elements in msg_iov */
5940 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5941 msg.msg_control = NULL; /* ancillary data, see below */
5942 msg.msg_controllen = 0; /* ancillary data buffer len */
5943 msg.msg_flags = 0; /* flags on received message */
5946 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5948 if (rc == -ENOTSOCK) {
5949 return libc_readv(s, vector, count);
5954 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5956 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5964 ssize_t readv(int s, const struct iovec *vector, int count)
5966 return swrap_readv(s, vector, count);
5969 /****************************************************************************
5971 ***************************************************************************/
5973 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5977 struct sockaddr_un un_addr;
5980 struct socket_info *si = find_socket_info(s);
5983 return libc_writev(s, vector, count);
5986 tmp.iov_base = NULL;
5990 msg.msg_name = NULL; /* optional address */
5991 msg.msg_namelen = 0; /* size of address */
5992 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5993 msg.msg_iovlen = count; /* # elements in msg_iov */
5994 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5995 msg.msg_control = NULL; /* ancillary data, see below */
5996 msg.msg_controllen = 0; /* ancillary data buffer len */
5997 msg.msg_flags = 0; /* flags on received message */
6000 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6002 if (rc == -ENOTSOCK) {
6003 return libc_readv(s, vector, count);
6008 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
6010 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6015 ssize_t writev(int s, const struct iovec *vector, int count)
6017 return swrap_writev(s, vector, count);
6020 /****************************
6022 ***************************/
6024 static int swrap_close(int fd)
6026 struct socket_info *si = NULL;
6030 swrap_mutex_lock(&socket_reset_mutex);
6032 si_index = find_socket_info_index(fd);
6033 if (si_index == -1) {
6034 swrap_mutex_unlock(&socket_reset_mutex);
6035 return libc_close(fd);
6038 reset_socket_info_index(fd);
6040 si = swrap_get_socket_info(si_index);
6042 swrap_mutex_lock(&first_free_mutex);
6045 ret = libc_close(fd);
6047 swrap_dec_refcount(si);
6049 if (swrap_get_refcount(si) > 0) {
6050 /* there are still references left */
6054 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6055 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6058 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6059 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6060 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6063 if (si->un_addr.sun_path[0] != '\0') {
6064 unlink(si->un_addr.sun_path);
6067 swrap_set_next_free(si, first_free);
6068 first_free = si_index;
6071 SWRAP_UNLOCK_SI(si);
6072 swrap_mutex_unlock(&first_free_mutex);
6073 swrap_mutex_unlock(&socket_reset_mutex);
6080 return swrap_close(fd);
6083 /****************************
6085 ***************************/
6087 static int swrap_dup(int fd)
6089 struct socket_info *si;
6092 idx = find_socket_info_index(fd);
6094 return libc_dup(fd);
6097 si = swrap_get_socket_info(idx);
6099 dup_fd = libc_dup(fd);
6101 int saved_errno = errno;
6102 errno = saved_errno;
6108 swrap_inc_refcount(si);
6110 SWRAP_UNLOCK_SI(si);
6112 /* Make sure we don't have an entry for the fd */
6113 swrap_remove_stale(dup_fd);
6115 set_socket_info_index(dup_fd, idx);
6122 return swrap_dup(fd);
6125 /****************************
6127 ***************************/
6129 static int swrap_dup2(int fd, int newfd)
6131 struct socket_info *si;
6134 idx = find_socket_info_index(fd);
6136 return libc_dup2(fd, newfd);
6139 si = swrap_get_socket_info(idx);
6143 * According to the manpage:
6145 * "If oldfd is a valid file descriptor, and newfd has the same
6146 * value as oldfd, then dup2() does nothing, and returns newfd."
6151 if (find_socket_info(newfd)) {
6152 /* dup2() does an implicit close of newfd, which we
6153 * need to emulate */
6157 dup_fd = libc_dup2(fd, newfd);
6159 int saved_errno = errno;
6160 errno = saved_errno;
6166 swrap_inc_refcount(si);
6168 SWRAP_UNLOCK_SI(si);
6170 /* Make sure we don't have an entry for the fd */
6171 swrap_remove_stale(dup_fd);
6173 set_socket_info_index(dup_fd, idx);
6178 int dup2(int fd, int newfd)
6180 return swrap_dup2(fd, newfd);
6183 /****************************
6185 ***************************/
6187 static int swrap_vfcntl(int fd, int cmd, va_list va)
6189 struct socket_info *si;
6190 int rc, dup_fd, idx;
6192 idx = find_socket_info_index(fd);
6194 return libc_vfcntl(fd, cmd, va);
6197 si = swrap_get_socket_info(idx);
6201 dup_fd = libc_vfcntl(fd, cmd, va);
6203 int saved_errno = errno;
6204 errno = saved_errno;
6210 swrap_inc_refcount(si);
6212 SWRAP_UNLOCK_SI(si);
6214 /* Make sure we don't have an entry for the fd */
6215 swrap_remove_stale(dup_fd);
6217 set_socket_info_index(dup_fd, idx);
6222 rc = libc_vfcntl(fd, cmd, va);
6229 int fcntl(int fd, int cmd, ...)
6236 rc = swrap_vfcntl(fd, cmd, va);
6243 /****************************
6245 ***************************/
6248 static int swrap_eventfd(int count, int flags)
6252 fd = libc_eventfd(count, flags);
6254 swrap_remove_stale(fd);
6260 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6261 int eventfd(unsigned int count, int flags)
6263 int eventfd(int count, int flags)
6266 return swrap_eventfd(count, flags);
6271 int pledge(const char *promises, const char *paths[])
6273 (void)promises; /* unused */
6274 (void)paths; /* unused */
6278 #endif /* HAVE_PLEDGE */
6280 static void swrap_thread_prepare(void)
6283 * This function should only be called here!!
6285 * We bind all symobls to avoid deadlocks of the fork is
6286 * interrupted by a signal handler using a symbol of this
6289 swrap_bind_symbol_all();
6294 static void swrap_thread_parent(void)
6299 static void swrap_thread_child(void)
6304 /****************************
6306 ***************************/
6307 void swrap_constructor(void)
6312 * If we hold a lock and the application forks, then the child
6313 * is not able to unlock the mutex and we are in a deadlock.
6314 * This should prevent such deadlocks.
6316 pthread_atfork(&swrap_thread_prepare,
6317 &swrap_thread_parent,
6318 &swrap_thread_child);
6320 ret = socket_wrapper_init_mutex(&sockets_mutex);
6322 SWRAP_LOG(SWRAP_LOG_ERROR,
6323 "Failed to initialize pthread mutex");
6327 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6329 SWRAP_LOG(SWRAP_LOG_ERROR,
6330 "Failed to initialize pthread mutex");
6334 ret = socket_wrapper_init_mutex(&first_free_mutex);
6336 SWRAP_LOG(SWRAP_LOG_ERROR,
6337 "Failed to initialize pthread mutex");
6342 /****************************
6344 ***************************/
6347 * This function is called when the library is unloaded and makes sure that
6348 * sockets get closed and the unix file for the socket are unlinked.
6350 void swrap_destructor(void)
6354 if (socket_fds_idx != NULL) {
6355 for (i = 0; i < socket_fds_max; ++i) {
6356 if (socket_fds_idx[i] != -1) {
6360 SAFE_FREE(socket_fds_idx);
6365 if (swrap.libc.handle != NULL) {
6366 dlclose(swrap.libc.handle);
6368 if (swrap.libc.socket_handle) {
6369 dlclose(swrap.libc.socket_handle);