4 * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 * Copyright (c) 2006-2021, Stefan Metzmacher <metze@samba.org>
6 * Copyright (c) 2013-2021, Andreas Schneider <asn@samba.org>
7 * Copyright (c) 2014-2017, Michael Adam <obnox@samba.org>
8 * Copyright (c) 2016-2018, Anoop C S <anoopcs@redhat.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the author nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 Socket wrapper library. Passes all socket communication over
41 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
47 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
55 #ifdef HAVE_SYS_SIGNALFD_H
56 #include <sys/signalfd.h>
58 #ifdef HAVE_SYS_EVENTFD_H
59 #include <sys/eventfd.h>
61 #ifdef HAVE_SYS_TIMERFD_H
62 #include <sys/timerfd.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #ifdef HAVE_NETINET_TCP_FSM_H
70 #include <netinet/tcp_fsm.h>
72 #include <arpa/inet.h>
81 #ifdef HAVE_GNU_LIB_NAMES_H
82 #include <gnu/lib-names.h>
89 #include "socket_wrapper.h"
98 /* GCC have printf type attribute check. */
99 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
100 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
102 #define PRINTF_ATTRIBUTE(a,b)
103 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
105 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
106 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
108 #define CONSTRUCTOR_ATTRIBUTE
109 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
111 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
112 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
114 #define DESTRUCTOR_ATTRIBUTE
118 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
119 # define FALL_THROUGH __attribute__ ((fallthrough))
120 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
121 # define FALL_THROUGH ((void)0)
122 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
123 #endif /* FALL_THROUGH */
125 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
126 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
128 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
131 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
132 # define SWRAP_THREAD __thread
134 # define SWRAP_THREAD
138 #define MIN(a,b) ((a)<(b)?(a):(b))
142 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
146 #define ZERO_STRUCTP(x) do { \
148 memset((char *)(x), 0, sizeof(*(x))); \
153 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
156 #ifndef discard_const
157 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
160 #ifndef discard_const_p
161 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
164 #define UNUSED(x) (void)(x)
167 # ifndef IPV6_RECVPKTINFO
168 # define IPV6_RECVPKTINFO IPV6_PKTINFO
169 # endif /* IPV6_RECVPKTINFO */
170 #endif /* IPV6_PKTINFO */
173 * On BSD IP_PKTINFO has a different name because during
174 * the time when they implemented it, there was no RFC.
175 * The name for IPv6 is the same as on Linux.
178 # ifdef IP_RECVDSTADDR
179 # define IP_PKTINFO IP_RECVDSTADDR
183 #define socket_wrapper_init_mutex(m) \
184 _socket_wrapper_init_mutex(m, #m)
186 /* Add new global locks here please */
187 # define SWRAP_REINIT_ALL do { \
189 ret = socket_wrapper_init_mutex(&sockets_mutex); \
190 if (ret != 0) exit(-1); \
191 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
192 if (ret != 0) exit(-1); \
193 ret = socket_wrapper_init_mutex(&first_free_mutex); \
194 if (ret != 0) exit(-1); \
195 ret = socket_wrapper_init_mutex(&sockets_si_global); \
196 if (ret != 0) exit(-1); \
197 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
198 if (ret != 0) exit(-1); \
199 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
200 if (ret != 0) exit(-1); \
201 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
202 if (ret != 0) exit(-1); \
205 # define SWRAP_LOCK_ALL do { \
206 swrap_mutex_lock(&sockets_mutex); \
207 swrap_mutex_lock(&socket_reset_mutex); \
208 swrap_mutex_lock(&first_free_mutex); \
209 swrap_mutex_lock(&sockets_si_global); \
210 swrap_mutex_lock(&autobind_start_mutex); \
211 swrap_mutex_lock(&pcap_dump_mutex); \
212 swrap_mutex_lock(&mtu_update_mutex); \
215 # define SWRAP_UNLOCK_ALL do { \
216 swrap_mutex_unlock(&mtu_update_mutex); \
217 swrap_mutex_unlock(&pcap_dump_mutex); \
218 swrap_mutex_unlock(&autobind_start_mutex); \
219 swrap_mutex_unlock(&sockets_si_global); \
220 swrap_mutex_unlock(&first_free_mutex); \
221 swrap_mutex_unlock(&socket_reset_mutex); \
222 swrap_mutex_unlock(&sockets_mutex); \
225 #define SOCKET_INFO_CONTAINER(si) \
226 (struct socket_info_container *)(si)
228 #define SWRAP_LOCK_SI(si) do { \
229 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
231 swrap_mutex_lock(&sockets_si_global); \
237 #define SWRAP_UNLOCK_SI(si) do { \
238 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
240 swrap_mutex_unlock(&sockets_si_global); \
246 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
247 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
249 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
252 /* we need to use a very terse format here as IRIX 6.4 silently
253 truncates names to 16 chars, so if we use a longer name then we
254 can't tell which port a packet came from with recvfrom()
256 with this format we have 8 chars left for the directory name
258 #define SOCKET_FORMAT "%c%02X%04X"
259 #define SOCKET_TYPE_CHAR_TCP 'T'
260 #define SOCKET_TYPE_CHAR_UDP 'U'
261 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
262 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
265 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
266 * format PCAP capture files (as the caller will simply continue from here).
268 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
269 #define SOCKET_WRAPPER_MTU_MIN 512
270 #define SOCKET_WRAPPER_MTU_MAX 32768
272 #define SOCKET_MAX_SOCKETS 1024
275 * Maximum number of socket_info structures that can
276 * be used. Can be overriden by the environment variable
277 * SOCKET_WRAPPER_MAX_SOCKETS.
279 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
281 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
283 /* This limit is to avoid broadcast sendto() needing to stat too many
284 * files. It may be raised (with a performance cost) to up to 254
285 * without changing the format above */
286 #define MAX_WRAPPED_INTERFACES 64
288 struct swrap_address {
289 socklen_t sa_socklen;
292 struct sockaddr_in in;
294 struct sockaddr_in6 in6;
296 struct sockaddr_un un;
297 struct sockaddr_storage ss;
301 static int first_free;
306 * Remember to update swrap_unix_scm_right_magic
323 /* The unix path so we can unlink it on close() */
324 struct sockaddr_un un_addr;
326 struct swrap_address bindname;
327 struct swrap_address myname;
328 struct swrap_address peername;
331 unsigned long pck_snd;
332 unsigned long pck_rcv;
336 struct socket_info_meta
338 unsigned int refcount;
341 * As long as we don't use shared memory
342 * for the sockets array, we use
343 * sockets_si_global as a single mutex.
345 * pthread_mutex_t mutex;
349 struct socket_info_container
351 struct socket_info info;
352 struct socket_info_meta meta;
355 static struct socket_info_container *sockets;
357 static size_t socket_info_max = 0;
360 * Allocate the socket array always on the limit value. We want it to be
361 * at least bigger than the default so if we reach the limit we can
362 * still deal with duplicate fds pointing to the same socket_info.
364 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
366 /* Hash table to map fds to corresponding socket_info index */
367 static int *socket_fds_idx;
369 /* Mutex for syncronizing port selection during swrap_auto_bind() */
370 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
372 /* Mutex to guard the initialization of array of socket_info structures */
373 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
375 /* Mutex to guard the socket reset in swrap_remove_wrapper() */
376 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
378 /* Mutex to synchronize access to first free index in socket_info array */
379 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
382 * Mutex to synchronize access to to socket_info structures
383 * We use a single global mutex in order to avoid leaking
384 * ~ 38M copy on write memory per fork.
385 * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
387 static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER;
389 /* Mutex to synchronize access to packet capture dump file */
390 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
392 /* Mutex for synchronizing mtu value fetch*/
393 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
395 /* Function prototypes */
397 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
398 /* xlC and other oldschool compilers support (only) this */
399 #pragma init (swrap_constructor)
401 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
402 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
403 #pragma fini (swrap_destructor)
405 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
407 #ifndef HAVE_GETPROGNAME
408 static const char *getprogname(void)
410 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
411 return program_invocation_short_name;
412 #elif defined(HAVE_GETEXECNAME)
413 return getexecname();
416 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
418 #endif /* HAVE_GETPROGNAME */
420 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
421 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
423 static void swrap_log(enum swrap_dbglvl_e dbglvl,
425 const char *format, ...)
430 unsigned int lvl = 0;
431 const char *prefix = "SWRAP";
432 const char *progname = getprogname();
434 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
443 va_start(va, format);
444 vsnprintf(buffer, sizeof(buffer), format, va);
448 case SWRAP_LOG_ERROR:
449 prefix = "SWRAP_ERROR";
452 prefix = "SWRAP_WARN";
454 case SWRAP_LOG_DEBUG:
455 prefix = "SWRAP_DEBUG";
457 case SWRAP_LOG_TRACE:
458 prefix = "SWRAP_TRACE";
462 if (progname == NULL) {
463 progname = "<unknown>";
467 "%s[%s (%u)] - %s: %s\n",
470 (unsigned int)getpid(),
475 /*********************************************************
476 * SWRAP LOADING LIBC FUNCTIONS
477 *********************************************************/
482 typedef int (*__libc_accept4)(int sockfd,
483 struct sockaddr *addr,
487 typedef int (*__libc_accept)(int sockfd,
488 struct sockaddr *addr,
491 typedef int (*__libc_bind)(int sockfd,
492 const struct sockaddr *addr,
494 typedef int (*__libc_close)(int fd);
495 #ifdef HAVE___CLOSE_NOCANCEL
496 typedef int (*__libc___close_nocancel)(int fd);
498 typedef int (*__libc_connect)(int sockfd,
499 const struct sockaddr *addr,
501 typedef int (*__libc_dup)(int fd);
502 typedef int (*__libc_dup2)(int oldfd, int newfd);
503 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
504 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
506 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
509 typedef int (*__libc_eventfd)(int count, int flags);
511 typedef int (*__libc_getpeername)(int sockfd,
512 struct sockaddr *addr,
514 typedef int (*__libc_getsockname)(int sockfd,
515 struct sockaddr *addr,
517 typedef int (*__libc_getsockopt)(int sockfd,
522 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
523 typedef int (*__libc_listen)(int sockfd, int backlog);
524 typedef int (*__libc_open)(const char *pathname, int flags, ...);
526 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
527 #endif /* HAVE_OPEN64 */
528 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
529 typedef int (*__libc_pipe)(int pipefd[2]);
530 typedef int (*__libc_read)(int fd, void *buf, size_t count);
531 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
532 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
533 typedef int (*__libc_recvfrom)(int sockfd,
537 struct sockaddr *src_addr,
539 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
540 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
541 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
542 typedef int (*__libc_sendto)(int sockfd,
546 const struct sockaddr *dst_addr,
548 typedef int (*__libc_setsockopt)(int sockfd,
554 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
556 typedef int (*__libc_socket)(int domain, int type, int protocol);
557 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
558 #ifdef HAVE_TIMERFD_CREATE
559 typedef int (*__libc_timerfd_create)(int clockid, int flags);
561 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
562 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
564 #define SWRAP_SYMBOL_ENTRY(i) \
570 struct swrap_libc_symbols {
572 SWRAP_SYMBOL_ENTRY(accept4);
574 SWRAP_SYMBOL_ENTRY(accept);
576 SWRAP_SYMBOL_ENTRY(bind);
577 SWRAP_SYMBOL_ENTRY(close);
578 #ifdef HAVE___CLOSE_NOCANCEL
579 SWRAP_SYMBOL_ENTRY(__close_nocancel);
581 SWRAP_SYMBOL_ENTRY(connect);
582 SWRAP_SYMBOL_ENTRY(dup);
583 SWRAP_SYMBOL_ENTRY(dup2);
584 SWRAP_SYMBOL_ENTRY(fcntl);
585 SWRAP_SYMBOL_ENTRY(fopen);
587 SWRAP_SYMBOL_ENTRY(fopen64);
590 SWRAP_SYMBOL_ENTRY(eventfd);
592 SWRAP_SYMBOL_ENTRY(getpeername);
593 SWRAP_SYMBOL_ENTRY(getsockname);
594 SWRAP_SYMBOL_ENTRY(getsockopt);
595 SWRAP_SYMBOL_ENTRY(ioctl);
596 SWRAP_SYMBOL_ENTRY(listen);
597 SWRAP_SYMBOL_ENTRY(open);
599 SWRAP_SYMBOL_ENTRY(open64);
601 SWRAP_SYMBOL_ENTRY(openat);
602 SWRAP_SYMBOL_ENTRY(pipe);
603 SWRAP_SYMBOL_ENTRY(read);
604 SWRAP_SYMBOL_ENTRY(readv);
605 SWRAP_SYMBOL_ENTRY(recv);
606 SWRAP_SYMBOL_ENTRY(recvfrom);
607 SWRAP_SYMBOL_ENTRY(recvmsg);
608 SWRAP_SYMBOL_ENTRY(send);
609 SWRAP_SYMBOL_ENTRY(sendmsg);
610 SWRAP_SYMBOL_ENTRY(sendto);
611 SWRAP_SYMBOL_ENTRY(setsockopt);
613 SWRAP_SYMBOL_ENTRY(signalfd);
615 SWRAP_SYMBOL_ENTRY(socket);
616 SWRAP_SYMBOL_ENTRY(socketpair);
617 #ifdef HAVE_TIMERFD_CREATE
618 SWRAP_SYMBOL_ENTRY(timerfd_create);
620 SWRAP_SYMBOL_ENTRY(write);
621 SWRAP_SYMBOL_ENTRY(writev);
628 struct swrap_libc_symbols symbols;
632 static struct swrap swrap;
635 static char *socket_wrapper_dir(void);
637 #define LIBC_NAME "libc.so"
644 static const char *swrap_str_lib(enum swrap_lib lib)
649 case SWRAP_LIBSOCKET:
653 /* Compiler would warn us about unhandled enum value if we get here */
657 static void *swrap_load_lib_handle(enum swrap_lib lib)
659 int flags = RTLD_LAZY;
664 const char *env_preload = getenv("LD_PRELOAD");
665 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
666 bool enable_deepbind = true;
668 /* Don't do a deepbind if we run with libasan */
669 if (env_preload != NULL && strlen(env_preload) < 1024) {
670 const char *p = strstr(env_preload, "libasan.so");
672 enable_deepbind = false;
676 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
677 enable_deepbind = false;
680 if (enable_deepbind) {
681 flags |= RTLD_DEEPBIND;
686 case SWRAP_LIBSOCKET:
687 #ifdef HAVE_LIBSOCKET
688 handle = swrap.libc.socket_handle;
689 if (handle == NULL) {
690 for (i = 10; i >= 0; i--) {
691 char soname[256] = {0};
693 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
694 handle = dlopen(soname, flags);
695 if (handle != NULL) {
700 swrap.libc.socket_handle = handle;
705 handle = swrap.libc.handle;
707 if (handle == NULL) {
708 handle = dlopen(LIBC_SO, flags);
710 swrap.libc.handle = handle;
713 if (handle == NULL) {
714 for (i = 10; i >= 0; i--) {
715 char soname[256] = {0};
717 snprintf(soname, sizeof(soname), "libc.so.%d", i);
718 handle = dlopen(soname, flags);
719 if (handle != NULL) {
724 swrap.libc.handle = handle;
729 if (handle == NULL) {
731 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
733 SWRAP_LOG(SWRAP_LOG_ERROR,
734 "Failed to dlopen library: %s",
743 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
748 handle = swrap_load_lib_handle(lib);
750 func = dlsym(handle, fn_name);
752 SWRAP_LOG(SWRAP_LOG_ERROR,
753 "Failed to find %s: %s",
759 SWRAP_LOG(SWRAP_LOG_TRACE,
767 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
768 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
772 ret = pthread_mutex_lock(mutex);
774 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
775 getpid(), getppid(), caller, line, name, strerror(ret));
780 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
781 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
785 ret = pthread_mutex_unlock(mutex);
787 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
788 getpid(), getppid(), caller, line, name, strerror(ret));
794 * These macros have a thread race condition on purpose!
796 * This is an optimization to avoid locking each time we check if the symbol is
799 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
800 swrap.libc.symbols._libc_##sym_name.obj = \
801 _swrap_bind_symbol(lib, #sym_name); \
804 #define swrap_bind_symbol_libc(sym_name) \
805 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
807 #define swrap_bind_symbol_libsocket(sym_name) \
808 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
810 static void swrap_bind_symbol_all(void);
812 /****************************************************************************
814 ****************************************************************************
816 * Functions especially from libc need to be loaded individually, you can't
817 * load all at once or gdb will segfault at startup. The same applies to
818 * valgrind and has probably something todo with with the linker. So we need
819 * load each function at the point it is called the first time.
821 ****************************************************************************/
824 static int libc_accept4(int sockfd,
825 struct sockaddr *addr,
829 swrap_bind_symbol_all();
831 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
834 #else /* HAVE_ACCEPT4 */
836 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
838 swrap_bind_symbol_all();
840 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
842 #endif /* HAVE_ACCEPT4 */
844 static int libc_bind(int sockfd,
845 const struct sockaddr *addr,
848 swrap_bind_symbol_all();
850 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
853 static int libc_close(int fd)
855 swrap_bind_symbol_all();
857 return swrap.libc.symbols._libc_close.f(fd);
860 #ifdef HAVE___CLOSE_NOCANCEL
861 static int libc___close_nocancel(int fd)
863 swrap_bind_symbol_all();
865 return swrap.libc.symbols._libc___close_nocancel.f(fd);
867 #endif /* HAVE___CLOSE_NOCANCEL */
869 static int libc_connect(int sockfd,
870 const struct sockaddr *addr,
873 swrap_bind_symbol_all();
875 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
878 static int libc_dup(int fd)
880 swrap_bind_symbol_all();
882 return swrap.libc.symbols._libc_dup.f(fd);
885 static int libc_dup2(int oldfd, int newfd)
887 swrap_bind_symbol_all();
889 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
893 static int libc_eventfd(int count, int flags)
895 swrap_bind_symbol_all();
897 return swrap.libc.symbols._libc_eventfd.f(count, flags);
901 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
902 static int libc_vfcntl(int fd, int cmd, va_list ap)
907 swrap_bind_symbol_all();
909 arg = va_arg(ap, void *);
911 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
916 static int libc_getpeername(int sockfd,
917 struct sockaddr *addr,
920 swrap_bind_symbol_all();
922 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
925 static int libc_getsockname(int sockfd,
926 struct sockaddr *addr,
929 swrap_bind_symbol_all();
931 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
934 static int libc_getsockopt(int sockfd,
940 swrap_bind_symbol_all();
942 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
949 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
950 static int libc_vioctl(int d, unsigned long int request, va_list ap)
955 swrap_bind_symbol_all();
957 arg = va_arg(ap, void *);
959 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
964 static int libc_listen(int sockfd, int backlog)
966 swrap_bind_symbol_all();
968 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
971 static FILE *libc_fopen(const char *name, const char *mode)
973 swrap_bind_symbol_all();
975 return swrap.libc.symbols._libc_fopen.f(name, mode);
979 static FILE *libc_fopen64(const char *name, const char *mode)
981 swrap_bind_symbol_all();
983 return swrap.libc.symbols._libc_fopen64.f(name, mode);
985 #endif /* HAVE_FOPEN64 */
987 static void swrap_inject_o_largefile(int *flags)
989 (void)*flags; /* maybe unused */
990 #if SIZE_MAX == 0xffffffffUL && defined(O_LARGEFILE)
992 if (((*flags) & O_PATH) == 0)
995 *flags |= O_LARGEFILE;
1000 static int libc_vopen(const char *pathname, int flags, va_list ap)
1005 swrap_bind_symbol_all();
1007 swrap_inject_o_largefile(&flags);
1009 if (flags & O_CREAT) {
1010 mode = va_arg(ap, int);
1012 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1017 static int libc_open(const char *pathname, int flags, ...)
1022 va_start(ap, flags);
1023 fd = libc_vopen(pathname, flags, ap);
1030 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1035 swrap_bind_symbol_all();
1037 swrap_inject_o_largefile(&flags);
1039 if (flags & O_CREAT) {
1040 mode = va_arg(ap, int);
1042 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1046 #endif /* HAVE_OPEN64 */
1048 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1053 swrap_bind_symbol_all();
1055 swrap_inject_o_largefile(&flags);
1057 if (flags & O_CREAT) {
1058 mode = va_arg(ap, int);
1060 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1069 static int libc_openat(int dirfd, const char *path, int flags, ...)
1074 va_start(ap, flags);
1075 fd = libc_vopenat(dirfd, path, flags, ap);
1082 static int libc_pipe(int pipefd[2])
1084 swrap_bind_symbol_all();
1086 return swrap.libc.symbols._libc_pipe.f(pipefd);
1089 static int libc_read(int fd, void *buf, size_t count)
1091 swrap_bind_symbol_all();
1093 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1096 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1098 swrap_bind_symbol_all();
1100 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1103 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1105 swrap_bind_symbol_all();
1107 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1110 static int libc_recvfrom(int sockfd,
1114 struct sockaddr *src_addr,
1117 swrap_bind_symbol_all();
1119 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1127 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1129 swrap_bind_symbol_all();
1131 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1134 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1136 swrap_bind_symbol_all();
1138 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1141 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1143 swrap_bind_symbol_all();
1145 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1148 static int libc_sendto(int sockfd,
1152 const struct sockaddr *dst_addr,
1155 swrap_bind_symbol_all();
1157 return swrap.libc.symbols._libc_sendto.f(sockfd,
1165 static int libc_setsockopt(int sockfd,
1171 swrap_bind_symbol_all();
1173 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1180 #ifdef HAVE_SIGNALFD
1181 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1183 swrap_bind_symbol_all();
1185 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1189 static int libc_socket(int domain, int type, int protocol)
1191 swrap_bind_symbol_all();
1193 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1196 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1198 swrap_bind_symbol_all();
1200 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1203 #ifdef HAVE_TIMERFD_CREATE
1204 static int libc_timerfd_create(int clockid, int flags)
1206 swrap_bind_symbol_all();
1208 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1212 static ssize_t libc_write(int fd, const void *buf, size_t count)
1214 swrap_bind_symbol_all();
1216 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1219 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1221 swrap_bind_symbol_all();
1223 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1226 /* DO NOT call this function during library initialization! */
1227 static void __swrap_bind_symbol_all_once(void)
1230 swrap_bind_symbol_libsocket(accept4);
1232 swrap_bind_symbol_libsocket(accept);
1234 swrap_bind_symbol_libsocket(bind);
1235 swrap_bind_symbol_libc(close);
1236 #ifdef HAVE___CLOSE_NOCANCEL
1237 swrap_bind_symbol_libc(__close_nocancel);
1239 swrap_bind_symbol_libsocket(connect);
1240 swrap_bind_symbol_libc(dup);
1241 swrap_bind_symbol_libc(dup2);
1242 swrap_bind_symbol_libc(fcntl);
1243 swrap_bind_symbol_libc(fopen);
1245 swrap_bind_symbol_libc(fopen64);
1248 swrap_bind_symbol_libc(eventfd);
1250 swrap_bind_symbol_libsocket(getpeername);
1251 swrap_bind_symbol_libsocket(getsockname);
1252 swrap_bind_symbol_libsocket(getsockopt);
1253 swrap_bind_symbol_libc(ioctl);
1254 swrap_bind_symbol_libsocket(listen);
1255 swrap_bind_symbol_libc(open);
1257 swrap_bind_symbol_libc(open64);
1259 swrap_bind_symbol_libc(openat);
1260 swrap_bind_symbol_libsocket(pipe);
1261 swrap_bind_symbol_libc(read);
1262 swrap_bind_symbol_libsocket(readv);
1263 swrap_bind_symbol_libsocket(recv);
1264 swrap_bind_symbol_libsocket(recvfrom);
1265 swrap_bind_symbol_libsocket(recvmsg);
1266 swrap_bind_symbol_libsocket(send);
1267 swrap_bind_symbol_libsocket(sendmsg);
1268 swrap_bind_symbol_libsocket(sendto);
1269 swrap_bind_symbol_libsocket(setsockopt);
1270 #ifdef HAVE_SIGNALFD
1271 swrap_bind_symbol_libsocket(signalfd);
1273 swrap_bind_symbol_libsocket(socket);
1274 swrap_bind_symbol_libsocket(socketpair);
1275 #ifdef HAVE_TIMERFD_CREATE
1276 swrap_bind_symbol_libc(timerfd_create);
1278 swrap_bind_symbol_libc(write);
1279 swrap_bind_symbol_libsocket(writev);
1282 static void swrap_bind_symbol_all(void)
1284 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1286 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1289 /*********************************************************
1290 * SWRAP HELPER FUNCTIONS
1291 *********************************************************/
1294 * We return 127.0.0.0 (default) or 10.53.57.0.
1296 * This can be controlled by:
1297 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1299 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1301 static in_addr_t swrap_ipv4_net(void)
1303 static int initialized;
1304 static in_addr_t hv;
1305 const char *net_str = NULL;
1314 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1315 if (net_str == NULL) {
1316 net_str = "127.0.0.0";
1319 ret = inet_pton(AF_INET, net_str, &nv);
1321 SWRAP_LOG(SWRAP_LOG_ERROR,
1322 "INVALID IPv4 Network [%s]",
1327 hv = ntohl(nv.s_addr);
1337 SWRAP_LOG(SWRAP_LOG_ERROR,
1338 "INVALID IPv4 Network [%s][0x%x] should be "
1339 "127.0.0.0 or 10.53.57.0",
1340 net_str, (unsigned)hv);
1348 * This returns 127.255.255.255 or 10.255.255.255
1350 static in_addr_t swrap_ipv4_bcast(void)
1354 hv = swrap_ipv4_net();
1355 hv |= IN_CLASSA_HOST;
1361 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1363 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1367 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1368 SWRAP_LOG(SWRAP_LOG_ERROR,
1369 "swrap_ipv4_iface(%u) invalid!",
1375 hv = swrap_ipv4_net();
1385 static const struct in6_addr *swrap_ipv6(void)
1387 static struct in6_addr v;
1388 static int initialized;
1396 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1405 static void set_port(int family, int prt, struct swrap_address *addr)
1409 addr->sa.in.sin_port = htons(prt);
1413 addr->sa.in6.sin6_port = htons(prt);
1419 static size_t socket_length(int family)
1423 return sizeof(struct sockaddr_in);
1426 return sizeof(struct sockaddr_in6);
1432 static struct socket_info *swrap_get_socket_info(int si_index)
1434 return (struct socket_info *)(&(sockets[si_index].info));
1437 static int swrap_get_refcount(struct socket_info *si)
1439 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1440 return sic->meta.refcount;
1443 static void swrap_inc_refcount(struct socket_info *si)
1445 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1447 sic->meta.refcount += 1;
1450 static void swrap_dec_refcount(struct socket_info *si)
1452 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1454 sic->meta.refcount -= 1;
1457 static int swrap_get_next_free(struct socket_info *si)
1459 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1461 return sic->meta.next_free;
1464 static void swrap_set_next_free(struct socket_info *si, int next_free)
1466 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1468 sic->meta.next_free = next_free;
1471 static int swrap_un_path(struct sockaddr_un *un,
1472 const char *swrap_dir,
1479 ret = snprintf(un->sun_path,
1480 sizeof(un->sun_path),
1486 if ((size_t)ret >= sizeof(un->sun_path)) {
1487 return ENAMETOOLONG;
1493 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1494 const char *swrap_dir)
1498 ret = snprintf(un->sun_path,
1499 sizeof(un->sun_path),
1503 if ((size_t)ret >= sizeof(un->sun_path)) {
1504 return ENAMETOOLONG;
1510 static bool swrap_dir_usable(const char *swrap_dir)
1512 struct sockaddr_un un;
1515 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1520 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1528 static char *socket_wrapper_dir(void)
1530 char *swrap_dir = NULL;
1531 char *s = getenv("SOCKET_WRAPPER_DIR");
1535 if (s == NULL || s[0] == '\0') {
1536 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1540 swrap_dir = realpath(s, NULL);
1541 if (swrap_dir == NULL) {
1542 SWRAP_LOG(SWRAP_LOG_ERROR,
1543 "Unable to resolve socket_wrapper dir path: %s - %s",
1549 ok = swrap_dir_usable(swrap_dir);
1556 ok = swrap_dir_usable(s);
1558 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1562 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1564 SWRAP_LOG(SWRAP_LOG_ERROR,
1565 "realpath(SOCKET_WRAPPER_DIR) too long and "
1566 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1571 swrap_dir = strdup(s);
1572 if (swrap_dir == NULL) {
1573 SWRAP_LOG(SWRAP_LOG_ERROR,
1574 "Unable to duplicate socket_wrapper dir path");
1578 SWRAP_LOG(SWRAP_LOG_WARN,
1579 "realpath(SOCKET_WRAPPER_DIR) too long, "
1580 "using original SOCKET_WRAPPER_DIR\n");
1583 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1587 static unsigned int socket_wrapper_mtu(void)
1589 static unsigned int max_mtu = 0;
1594 swrap_mutex_lock(&mtu_update_mutex);
1600 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1602 s = getenv("SOCKET_WRAPPER_MTU");
1607 tmp = strtol(s, &endp, 10);
1612 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1618 swrap_mutex_unlock(&mtu_update_mutex);
1622 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1624 pthread_mutexattr_t ma;
1625 bool need_destroy = false;
1628 #define __CHECK(cmd) do { \
1631 SWRAP_LOG(SWRAP_LOG_ERROR, \
1632 "%s: %s - failed %d", \
1638 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1639 __CHECK(pthread_mutexattr_init(&ma));
1640 need_destroy = true;
1641 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1642 __CHECK(pthread_mutex_init(m, &ma));
1645 pthread_mutexattr_destroy(&ma);
1650 static size_t socket_wrapper_max_sockets(void)
1656 if (socket_info_max != 0) {
1657 return socket_info_max;
1660 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1662 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1663 if (s == NULL || s[0] == '\0') {
1667 tmp = strtoul(s, &endp, 10);
1672 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1673 SWRAP_LOG(SWRAP_LOG_ERROR,
1674 "Invalid number of sockets specified, "
1675 "using default (%zu)",
1679 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1680 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1681 SWRAP_LOG(SWRAP_LOG_ERROR,
1682 "Invalid number of sockets specified, "
1683 "using maximum (%zu).",
1687 socket_info_max = tmp;
1690 return socket_info_max;
1693 static void socket_wrapper_init_fds_idx(void)
1698 if (socket_fds_idx != NULL) {
1702 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1704 SWRAP_LOG(SWRAP_LOG_ERROR,
1705 "Failed to allocate socket fds index array: %s",
1710 for (i = 0; i < socket_fds_max; i++) {
1714 socket_fds_idx = tmp;
1717 static void socket_wrapper_init_sockets(void)
1723 swrap_bind_symbol_all();
1725 swrap_mutex_lock(&sockets_mutex);
1727 if (sockets != NULL) {
1728 swrap_mutex_unlock(&sockets_mutex);
1732 SWRAP_LOG(SWRAP_LOG_DEBUG,
1733 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1734 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1737 * Intialize the static cache early before
1738 * any thread is able to start.
1740 (void)swrap_ipv4_net();
1742 socket_wrapper_init_fds_idx();
1744 /* Needs to be called inside the sockets_mutex lock here. */
1745 max_sockets = socket_wrapper_max_sockets();
1747 sockets = (struct socket_info_container *)calloc(max_sockets,
1748 sizeof(struct socket_info_container));
1750 if (sockets == NULL) {
1751 SWRAP_LOG(SWRAP_LOG_ERROR,
1752 "Failed to allocate sockets array: %s",
1754 swrap_mutex_unlock(&sockets_mutex);
1758 swrap_mutex_lock(&first_free_mutex);
1759 swrap_mutex_lock(&sockets_si_global);
1763 for (i = 0; i < max_sockets; i++) {
1764 swrap_set_next_free(&sockets[i].info, i+1);
1767 /* mark the end of the free list */
1768 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1770 swrap_mutex_unlock(&sockets_si_global);
1771 swrap_mutex_unlock(&first_free_mutex);
1772 swrap_mutex_unlock(&sockets_mutex);
1778 bool socket_wrapper_enabled(void)
1780 char *s = socket_wrapper_dir();
1788 socket_wrapper_init_sockets();
1793 static unsigned int socket_wrapper_default_iface(void)
1795 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1798 if (sscanf(s, "%u", &iface) == 1) {
1799 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1805 return 1;/* 127.0.0.1 */
1808 static void set_socket_info_index(int fd, int idx)
1810 SWRAP_LOG(SWRAP_LOG_TRACE,
1813 socket_fds_idx[fd] = idx;
1814 /* This builtin issues a full memory barrier. */
1815 __sync_synchronize();
1818 static void reset_socket_info_index(int fd)
1820 SWRAP_LOG(SWRAP_LOG_TRACE,
1823 set_socket_info_index(fd, -1);
1826 static int find_socket_info_index(int fd)
1832 if (socket_fds_idx == NULL) {
1836 if ((size_t)fd >= socket_fds_max) {
1838 * Do not add a log here as some applications do stupid things
1841 * for (fd = 0; fd <= getdtablesize(); fd++) {
1845 * This would produce millions of lines of debug messages.
1848 SWRAP_LOG(SWRAP_LOG_ERROR,
1849 "Looking for a socket info for the fd %d is over the "
1850 "max socket index limit of %zu.",
1857 /* This builtin issues a full memory barrier. */
1858 __sync_synchronize();
1859 return socket_fds_idx[fd];
1862 static int swrap_add_socket_info(const struct socket_info *si_input)
1864 struct socket_info *si = NULL;
1867 if (si_input == NULL) {
1872 swrap_mutex_lock(&first_free_mutex);
1873 if (first_free == -1) {
1878 si_index = first_free;
1879 si = swrap_get_socket_info(si_index);
1883 first_free = swrap_get_next_free(si);
1885 swrap_inc_refcount(si);
1887 SWRAP_UNLOCK_SI(si);
1890 swrap_mutex_unlock(&first_free_mutex);
1895 static int swrap_create_socket(struct socket_info *si, int fd)
1899 if ((size_t)fd >= socket_fds_max) {
1900 SWRAP_LOG(SWRAP_LOG_ERROR,
1901 "The max socket index limit of %zu has been reached, "
1909 idx = swrap_add_socket_info(si);
1914 set_socket_info_index(fd, idx);
1919 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1926 p = strrchr(un->sun_path, '/');
1927 if (p) p++; else p = un->sun_path;
1929 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1930 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1936 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1937 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1944 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1950 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1954 case SOCKET_TYPE_CHAR_TCP:
1955 case SOCKET_TYPE_CHAR_UDP: {
1956 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1958 if ((*len) < sizeof(*in2)) {
1959 SWRAP_LOG(SWRAP_LOG_ERROR,
1960 "V4: *len(%zu) < sizeof(*in2)=%zu",
1961 (size_t)*len, sizeof(*in2));
1966 memset(in2, 0, sizeof(*in2));
1967 in2->sin_family = AF_INET;
1968 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1969 in2->sin_port = htons(prt);
1971 *len = sizeof(*in2);
1975 case SOCKET_TYPE_CHAR_TCP_V6:
1976 case SOCKET_TYPE_CHAR_UDP_V6: {
1977 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1979 if ((*len) < sizeof(*in2)) {
1980 SWRAP_LOG(SWRAP_LOG_ERROR,
1981 "V6: *len(%zu) < sizeof(*in2)=%zu",
1982 (size_t)*len, sizeof(*in2));
1983 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1988 memset(in2, 0, sizeof(*in2));
1989 in2->sin6_family = AF_INET6;
1990 in2->sin6_addr = *swrap_ipv6();
1991 in2->sin6_addr.s6_addr[15] = iface;
1992 in2->sin6_port = htons(prt);
1994 *len = sizeof(*in2);
1999 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
2008 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2015 char *swrap_dir = NULL;
2017 if (bcast) *bcast = 0;
2019 switch (inaddr->sa_family) {
2021 const struct sockaddr_in *in =
2022 (const struct sockaddr_in *)(const void *)inaddr;
2023 unsigned int addr = ntohl(in->sin_addr.s_addr);
2027 const unsigned int sw_net_addr = swrap_ipv4_net();
2028 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2032 u_type = SOCKET_TYPE_CHAR_TCP;
2035 u_type = SOCKET_TYPE_CHAR_UDP;
2036 a_type = SOCKET_TYPE_CHAR_UDP;
2037 b_type = SOCKET_TYPE_CHAR_UDP;
2040 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2041 errno = ESOCKTNOSUPPORT;
2045 prt = ntohs(in->sin_port);
2046 if (a_type && addr == 0xFFFFFFFF) {
2047 /* 255.255.255.255 only udp */
2050 iface = socket_wrapper_default_iface();
2051 } else if (b_type && addr == sw_bcast_addr) {
2060 iface = socket_wrapper_default_iface();
2061 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2062 /* 127.0.0.X or 10.53.57.X */
2065 iface = (addr & 0x000000FF);
2067 char str[256] = {0,};
2068 inet_ntop(inaddr->sa_family,
2071 SWRAP_LOG(SWRAP_LOG_WARN,
2073 str, (unsigned)prt);
2074 errno = ENETUNREACH;
2077 if (bcast) *bcast = is_bcast;
2082 const struct sockaddr_in6 *in =
2083 (const struct sockaddr_in6 *)(const void *)inaddr;
2084 struct in6_addr cmp1, cmp2;
2088 type = SOCKET_TYPE_CHAR_TCP_V6;
2091 type = SOCKET_TYPE_CHAR_UDP_V6;
2094 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2095 errno = ESOCKTNOSUPPORT;
2099 /* XXX no multicast/broadcast */
2101 prt = ntohs(in->sin6_port);
2103 cmp1 = *swrap_ipv6();
2104 cmp2 = in->sin6_addr;
2105 cmp2.s6_addr[15] = 0;
2106 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2107 iface = in->sin6_addr.s6_addr[15];
2109 char str[256] = {0,};
2110 inet_ntop(inaddr->sa_family,
2113 SWRAP_LOG(SWRAP_LOG_WARN,
2115 str, (unsigned)prt);
2116 errno = ENETUNREACH;
2124 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2125 errno = ENETUNREACH;
2130 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2135 swrap_dir = socket_wrapper_dir();
2136 if (swrap_dir == NULL) {
2142 swrap_un_path_EINVAL(un, swrap_dir);
2143 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2144 SAFE_FREE(swrap_dir);
2145 /* the caller need to do more processing */
2149 swrap_un_path(un, swrap_dir, type, iface, prt);
2150 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2152 SAFE_FREE(swrap_dir);
2157 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2165 char *swrap_dir = NULL;
2167 if (bcast) *bcast = 0;
2169 switch (si->family) {
2171 const struct sockaddr_in *in =
2172 (const struct sockaddr_in *)(const void *)inaddr;
2173 unsigned int addr = ntohl(in->sin_addr.s_addr);
2178 const unsigned int sw_net_addr = swrap_ipv4_net();
2179 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2181 prt = ntohs(in->sin_port);
2185 u_type = SOCKET_TYPE_CHAR_TCP;
2186 d_type = SOCKET_TYPE_CHAR_TCP;
2189 u_type = SOCKET_TYPE_CHAR_UDP;
2190 d_type = SOCKET_TYPE_CHAR_UDP;
2191 a_type = SOCKET_TYPE_CHAR_UDP;
2192 b_type = SOCKET_TYPE_CHAR_UDP;
2195 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2196 errno = ESOCKTNOSUPPORT;
2204 iface = socket_wrapper_default_iface();
2205 } else if (a_type && addr == 0xFFFFFFFF) {
2206 /* 255.255.255.255 only udp */
2209 iface = socket_wrapper_default_iface();
2210 } else if (b_type && addr == sw_bcast_addr) {
2211 /* 127.255.255.255 only udp */
2214 iface = socket_wrapper_default_iface();
2215 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2219 iface = (addr & 0x000000FF);
2221 errno = EADDRNOTAVAIL;
2225 /* Store the bind address for connect() */
2226 if (si->bindname.sa_socklen == 0) {
2227 struct sockaddr_in bind_in;
2228 socklen_t blen = sizeof(struct sockaddr_in);
2230 ZERO_STRUCT(bind_in);
2231 bind_in.sin_family = in->sin_family;
2232 bind_in.sin_port = in->sin_port;
2233 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2234 si->bindname.sa_socklen = blen;
2235 memcpy(&si->bindname.sa.in, &bind_in, blen);
2242 const struct sockaddr_in6 *in =
2243 (const struct sockaddr_in6 *)(const void *)inaddr;
2244 struct in6_addr cmp1, cmp2;
2248 type = SOCKET_TYPE_CHAR_TCP_V6;
2251 type = SOCKET_TYPE_CHAR_UDP_V6;
2254 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2255 errno = ESOCKTNOSUPPORT;
2259 /* XXX no multicast/broadcast */
2261 prt = ntohs(in->sin6_port);
2263 cmp1 = *swrap_ipv6();
2264 cmp2 = in->sin6_addr;
2265 cmp2.s6_addr[15] = 0;
2266 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2267 iface = socket_wrapper_default_iface();
2268 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2269 iface = in->sin6_addr.s6_addr[15];
2271 errno = EADDRNOTAVAIL;
2275 /* Store the bind address for connect() */
2276 if (si->bindname.sa_socklen == 0) {
2277 struct sockaddr_in6 bind_in;
2278 socklen_t blen = sizeof(struct sockaddr_in6);
2280 ZERO_STRUCT(bind_in);
2281 bind_in.sin6_family = in->sin6_family;
2282 bind_in.sin6_port = in->sin6_port;
2284 bind_in.sin6_addr = *swrap_ipv6();
2285 bind_in.sin6_addr.s6_addr[15] = iface;
2287 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2288 si->bindname.sa_socklen = blen;
2295 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2296 errno = EADDRNOTAVAIL;
2301 if (bcast) *bcast = is_bcast;
2303 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2308 swrap_dir = socket_wrapper_dir();
2309 if (swrap_dir == NULL) {
2315 /* handle auto-allocation of ephemeral ports */
2316 for (prt = 5001; prt < 10000; prt++) {
2317 swrap_un_path(un, swrap_dir, type, iface, prt);
2318 if (stat(un->sun_path, &st) == 0) continue;
2320 set_port(si->family, prt, &si->myname);
2321 set_port(si->family, prt, &si->bindname);
2328 SAFE_FREE(swrap_dir);
2333 swrap_un_path(un, swrap_dir, type, iface, prt);
2334 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2336 SAFE_FREE(swrap_dir);
2341 static struct socket_info *find_socket_info(int fd)
2343 int idx = find_socket_info_index(fd);
2349 return swrap_get_socket_info(idx);
2353 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2355 struct socket_info_fd *f;
2356 const struct socket_info *last_s = NULL;
2358 /* first catch invalid input */
2359 switch (sa->sa_family) {
2361 if (len < sizeof(struct sockaddr_in)) {
2367 if (len < sizeof(struct sockaddr_in6)) {
2377 for (f = socket_fds; f; f = f->next) {
2378 struct socket_info *s = swrap_get_socket_info(f->si_index);
2385 if (s->myname == NULL) {
2388 if (s->myname->sa_family != sa->sa_family) {
2391 switch (s->myname->sa_family) {
2393 struct sockaddr_in *sin1, *sin2;
2395 sin1 = (struct sockaddr_in *)s->myname;
2396 sin2 = (struct sockaddr_in *)sa;
2398 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2401 if (sin1->sin_port != sin2->sin_port) {
2404 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2414 struct sockaddr_in6 *sin1, *sin2;
2416 sin1 = (struct sockaddr_in6 *)s->myname;
2417 sin2 = (struct sockaddr_in6 *)sa;
2419 if (sin1->sin6_port != sin2->sin6_port) {
2422 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2444 static void swrap_remove_stale(int fd);
2446 static int sockaddr_convert_to_un(struct socket_info *si,
2447 const struct sockaddr *in_addr,
2449 struct sockaddr_un *out_addr,
2453 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2455 (void) in_len; /* unused */
2457 if (out_addr == NULL) {
2461 out->sa_family = AF_UNIX;
2462 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2463 out->sa_len = sizeof(*out_addr);
2466 switch (in_addr->sa_family) {
2468 const struct sockaddr_in *sin;
2469 if (si->family != AF_INET) {
2472 if (in_len < sizeof(struct sockaddr_in)) {
2475 sin = (const struct sockaddr_in *)(const void *)in_addr;
2476 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2481 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2482 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2496 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2497 errno = ESOCKTNOSUPPORT;
2501 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2503 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2509 errno = EAFNOSUPPORT;
2510 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2514 static int sockaddr_convert_from_un(const struct socket_info *si,
2515 const struct sockaddr_un *in_addr,
2516 socklen_t un_addrlen,
2518 struct sockaddr *out_addr,
2519 socklen_t *out_addrlen)
2523 if (out_addr == NULL || out_addrlen == NULL)
2526 if (un_addrlen == 0) {
2541 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2542 errno = ESOCKTNOSUPPORT;
2545 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2546 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2547 out_addr->sa_len = *out_addrlen;
2554 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2555 errno = EAFNOSUPPORT;
2559 enum swrap_packet_type {
2561 SWRAP_CONNECT_UNREACH,
2569 SWRAP_SENDTO_UNREACH,
2580 struct swrap_file_hdr {
2582 uint16_t version_major;
2583 uint16_t version_minor;
2586 uint32_t frame_max_len;
2587 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2590 #define SWRAP_FILE_HDR_SIZE 24
2592 struct swrap_packet_frame {
2594 uint32_t micro_seconds;
2595 uint32_t recorded_length;
2596 uint32_t full_length;
2598 #define SWRAP_PACKET_FRAME_SIZE 16
2600 union swrap_packet_ip {
2604 uint16_t packet_length;
2605 uint16_t identification;
2610 uint16_t hdr_checksum;
2614 #define SWRAP_PACKET_IP_V4_SIZE 20
2617 uint8_t flow_label_high;
2618 uint16_t flow_label_low;
2619 uint16_t payload_length;
2620 uint8_t next_header;
2622 uint8_t src_addr[16];
2623 uint8_t dest_addr[16];
2625 #define SWRAP_PACKET_IP_V6_SIZE 40
2627 #define SWRAP_PACKET_IP_SIZE 40
2629 union swrap_packet_payload {
2631 uint16_t source_port;
2641 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2643 uint16_t source_port;
2648 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2655 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2662 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2664 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2666 #define SWRAP_PACKET_MIN_ALLOC \
2667 (SWRAP_PACKET_FRAME_SIZE + \
2668 SWRAP_PACKET_IP_SIZE + \
2669 SWRAP_PACKET_PAYLOAD_SIZE)
2671 static const char *swrap_pcap_init_file(void)
2673 static int initialized = 0;
2674 static const char *s = NULL;
2675 static const struct swrap_file_hdr h;
2676 static const struct swrap_packet_frame f;
2677 static const union swrap_packet_ip i;
2678 static const union swrap_packet_payload p;
2680 if (initialized == 1) {
2686 * TODO: don't use the structs use plain buffer offsets
2687 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2689 * for now make sure we disable PCAP support
2690 * if the struct has alignment!
2692 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2695 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2698 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2701 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2704 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2707 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2710 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2713 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2716 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2719 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2723 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2727 if (strncmp(s, "./", 2) == 0) {
2730 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2734 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2735 const struct sockaddr *src,
2736 const struct sockaddr *dest,
2738 const uint8_t *payload,
2740 unsigned long tcp_seqno,
2741 unsigned long tcp_ack,
2742 unsigned char tcp_ctl,
2744 size_t *_packet_len)
2746 uint8_t *base = NULL;
2747 uint8_t *buf = NULL;
2750 struct swrap_packet_frame *frame;
2754 union swrap_packet_ip *ip;
2756 union swrap_packet_payload *pay;
2759 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2760 size_t wire_hdr_len = 0;
2761 size_t wire_len = 0;
2762 size_t ip_hdr_len = 0;
2763 size_t icmp_hdr_len = 0;
2764 size_t icmp_truncate_len = 0;
2765 uint8_t protocol = 0, icmp_protocol = 0;
2766 const struct sockaddr_in *src_in = NULL;
2767 const struct sockaddr_in *dest_in = NULL;
2769 const struct sockaddr_in6 *src_in6 = NULL;
2770 const struct sockaddr_in6 *dest_in6 = NULL;
2775 switch (src->sa_family) {
2777 src_in = (const struct sockaddr_in *)(const void *)src;
2778 dest_in = (const struct sockaddr_in *)(const void *)dest;
2779 src_port = src_in->sin_port;
2780 dest_port = dest_in->sin_port;
2781 ip_hdr_len = sizeof(i.ip->v4);
2785 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2786 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2787 src_port = src_in6->sin6_port;
2788 dest_port = dest_in6->sin6_port;
2789 ip_hdr_len = sizeof(i.ip->v6);
2796 switch (socket_type) {
2798 protocol = 0x06; /* TCP */
2799 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2800 wire_len = wire_hdr_len + payload_len;
2804 protocol = 0x11; /* UDP */
2805 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2806 wire_len = wire_hdr_len + payload_len;
2814 icmp_protocol = protocol;
2815 switch (src->sa_family) {
2817 protocol = 0x01; /* ICMPv4 */
2818 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2822 protocol = 0x3A; /* ICMPv6 */
2823 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2827 if (wire_len > 64 ) {
2828 icmp_truncate_len = wire_len - 64;
2830 wire_len += icmp_hdr_len;
2833 packet_len = nonwire_len + wire_len;
2834 alloc_len = packet_len;
2835 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2836 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2839 base = (uint8_t *)calloc(1, alloc_len);
2847 f.frame->seconds = tval->tv_sec;
2848 f.frame->micro_seconds = tval->tv_usec;
2849 f.frame->recorded_length = wire_len - icmp_truncate_len;
2850 f.frame->full_length = wire_len - icmp_truncate_len;
2852 buf += SWRAP_PACKET_FRAME_SIZE;
2855 switch (src->sa_family) {
2857 if (src_in == NULL || dest_in == NULL) {
2862 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2863 i.ip->v4.tos = 0x00;
2864 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2865 i.ip->v4.identification = htons(0xFFFF);
2866 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2867 i.ip->v4.fragment = htons(0x0000);
2868 i.ip->v4.ttl = 0xFF;
2869 i.ip->v4.protocol = protocol;
2870 i.ip->v4.hdr_checksum = htons(0x0000);
2871 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2872 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2873 buf += SWRAP_PACKET_IP_V4_SIZE;
2877 if (src_in6 == NULL || dest_in6 == NULL) {
2882 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2883 i.ip->v6.flow_label_high = 0x00;
2884 i.ip->v6.flow_label_low = 0x0000;
2885 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2886 i.ip->v6.next_header = protocol;
2887 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2888 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2889 buf += SWRAP_PACKET_IP_V6_SIZE;
2895 pay = (union swrap_packet_payload *)(void *)buf;
2896 switch (src->sa_family) {
2898 pay->icmp4.type = 0x03; /* destination unreachable */
2899 pay->icmp4.code = 0x01; /* host unreachable */
2900 pay->icmp4.checksum = htons(0x0000);
2901 pay->icmp4.unused = htonl(0x00000000);
2903 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2905 /* set the ip header in the ICMP payload */
2907 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2908 i.ip->v4.tos = 0x00;
2909 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2910 i.ip->v4.identification = htons(0xFFFF);
2911 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2912 i.ip->v4.fragment = htons(0x0000);
2913 i.ip->v4.ttl = 0xFF;
2914 i.ip->v4.protocol = icmp_protocol;
2915 i.ip->v4.hdr_checksum = htons(0x0000);
2916 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2917 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2919 buf += SWRAP_PACKET_IP_V4_SIZE;
2921 src_port = dest_in->sin_port;
2922 dest_port = src_in->sin_port;
2926 pay->icmp6.type = 0x01; /* destination unreachable */
2927 pay->icmp6.code = 0x03; /* address unreachable */
2928 pay->icmp6.checksum = htons(0x0000);
2929 pay->icmp6.unused = htonl(0x00000000);
2930 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2932 /* set the ip header in the ICMP payload */
2934 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2935 i.ip->v6.flow_label_high = 0x00;
2936 i.ip->v6.flow_label_low = 0x0000;
2937 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2938 i.ip->v6.next_header = protocol;
2939 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2940 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2942 buf += SWRAP_PACKET_IP_V6_SIZE;
2944 src_port = dest_in6->sin6_port;
2945 dest_port = src_in6->sin6_port;
2951 pay = (union swrap_packet_payload *)(void *)buf;
2953 switch (socket_type) {
2955 pay->tcp.source_port = src_port;
2956 pay->tcp.dest_port = dest_port;
2957 pay->tcp.seq_num = htonl(tcp_seqno);
2958 pay->tcp.ack_num = htonl(tcp_ack);
2959 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2960 pay->tcp.control = tcp_ctl;
2961 pay->tcp.window = htons(0x7FFF);
2962 pay->tcp.checksum = htons(0x0000);
2963 pay->tcp.urg = htons(0x0000);
2964 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2969 pay->udp.source_port = src_port;
2970 pay->udp.dest_port = dest_port;
2971 pay->udp.length = htons(8 + payload_len);
2972 pay->udp.checksum = htons(0x0000);
2973 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2978 if (payload && payload_len > 0) {
2979 memcpy(buf, payload, payload_len);
2982 *_packet_len = packet_len - icmp_truncate_len;
2986 static int swrap_pcap_get_fd(const char *fname)
2994 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2996 struct swrap_file_hdr file_hdr;
2997 file_hdr.magic = 0xA1B2C3D4;
2998 file_hdr.version_major = 0x0002;
2999 file_hdr.version_minor = 0x0004;
3000 file_hdr.timezone = 0x00000000;
3001 file_hdr.sigfigs = 0x00000000;
3002 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3003 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3005 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3012 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3017 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3018 const struct sockaddr *addr,
3019 enum swrap_packet_type type,
3020 const void *buf, size_t len,
3023 const struct sockaddr *src_addr;
3024 const struct sockaddr *dest_addr;
3025 unsigned long tcp_seqno = 0;
3026 unsigned long tcp_ack = 0;
3027 unsigned char tcp_ctl = 0;
3028 int unreachable = 0;
3032 switch (si->family) {
3044 case SWRAP_CONNECT_SEND:
3045 if (si->type != SOCK_STREAM) {
3049 src_addr = &si->myname.sa.s;
3052 tcp_seqno = si->io.pck_snd;
3053 tcp_ack = si->io.pck_rcv;
3054 tcp_ctl = 0x02; /* SYN */
3056 si->io.pck_snd += 1;
3060 case SWRAP_CONNECT_RECV:
3061 if (si->type != SOCK_STREAM) {
3065 dest_addr = &si->myname.sa.s;
3068 tcp_seqno = si->io.pck_rcv;
3069 tcp_ack = si->io.pck_snd;
3070 tcp_ctl = 0x12; /** SYN,ACK */
3072 si->io.pck_rcv += 1;
3076 case SWRAP_CONNECT_UNREACH:
3077 if (si->type != SOCK_STREAM) {
3081 dest_addr = &si->myname.sa.s;
3084 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3085 tcp_seqno = si->io.pck_snd - 1;
3086 tcp_ack = si->io.pck_rcv;
3087 tcp_ctl = 0x02; /* SYN */
3092 case SWRAP_CONNECT_ACK:
3093 if (si->type != SOCK_STREAM) {
3097 src_addr = &si->myname.sa.s;
3100 tcp_seqno = si->io.pck_snd;
3101 tcp_ack = si->io.pck_rcv;
3102 tcp_ctl = 0x10; /* ACK */
3106 case SWRAP_ACCEPT_SEND:
3107 if (si->type != SOCK_STREAM) {
3111 dest_addr = &si->myname.sa.s;
3114 tcp_seqno = si->io.pck_rcv;
3115 tcp_ack = si->io.pck_snd;
3116 tcp_ctl = 0x02; /* SYN */
3118 si->io.pck_rcv += 1;
3122 case SWRAP_ACCEPT_RECV:
3123 if (si->type != SOCK_STREAM) {
3127 src_addr = &si->myname.sa.s;
3130 tcp_seqno = si->io.pck_snd;
3131 tcp_ack = si->io.pck_rcv;
3132 tcp_ctl = 0x12; /* SYN,ACK */
3134 si->io.pck_snd += 1;
3138 case SWRAP_ACCEPT_ACK:
3139 if (si->type != SOCK_STREAM) {
3143 dest_addr = &si->myname.sa.s;
3146 tcp_seqno = si->io.pck_rcv;
3147 tcp_ack = si->io.pck_snd;
3148 tcp_ctl = 0x10; /* ACK */
3153 src_addr = &si->myname.sa.s;
3154 dest_addr = &si->peername.sa.s;
3156 tcp_seqno = si->io.pck_snd;
3157 tcp_ack = si->io.pck_rcv;
3158 tcp_ctl = 0x18; /* PSH,ACK */
3160 si->io.pck_snd += len;
3164 case SWRAP_SEND_RST:
3165 dest_addr = &si->myname.sa.s;
3166 src_addr = &si->peername.sa.s;
3168 if (si->type == SOCK_DGRAM) {
3169 return swrap_pcap_marshall_packet(si,
3171 SWRAP_SENDTO_UNREACH,
3177 tcp_seqno = si->io.pck_rcv;
3178 tcp_ack = si->io.pck_snd;
3179 tcp_ctl = 0x14; /** RST,ACK */
3183 case SWRAP_PENDING_RST:
3184 dest_addr = &si->myname.sa.s;
3185 src_addr = &si->peername.sa.s;
3187 if (si->type == SOCK_DGRAM) {
3191 tcp_seqno = si->io.pck_rcv;
3192 tcp_ack = si->io.pck_snd;
3193 tcp_ctl = 0x14; /* RST,ACK */
3198 dest_addr = &si->myname.sa.s;
3199 src_addr = &si->peername.sa.s;
3201 tcp_seqno = si->io.pck_rcv;
3202 tcp_ack = si->io.pck_snd;
3203 tcp_ctl = 0x18; /* PSH,ACK */
3205 si->io.pck_rcv += len;
3209 case SWRAP_RECV_RST:
3210 dest_addr = &si->myname.sa.s;
3211 src_addr = &si->peername.sa.s;
3213 if (si->type == SOCK_DGRAM) {
3217 tcp_seqno = si->io.pck_rcv;
3218 tcp_ack = si->io.pck_snd;
3219 tcp_ctl = 0x14; /* RST,ACK */
3224 src_addr = &si->myname.sa.s;
3227 si->io.pck_snd += len;
3231 case SWRAP_SENDTO_UNREACH:
3232 dest_addr = &si->myname.sa.s;
3239 case SWRAP_RECVFROM:
3240 dest_addr = &si->myname.sa.s;
3243 si->io.pck_rcv += len;
3247 case SWRAP_CLOSE_SEND:
3248 if (si->type != SOCK_STREAM) {
3252 src_addr = &si->myname.sa.s;
3253 dest_addr = &si->peername.sa.s;
3255 tcp_seqno = si->io.pck_snd;
3256 tcp_ack = si->io.pck_rcv;
3257 tcp_ctl = 0x11; /* FIN, ACK */
3259 si->io.pck_snd += 1;
3263 case SWRAP_CLOSE_RECV:
3264 if (si->type != SOCK_STREAM) {
3268 dest_addr = &si->myname.sa.s;
3269 src_addr = &si->peername.sa.s;
3271 tcp_seqno = si->io.pck_rcv;
3272 tcp_ack = si->io.pck_snd;
3273 tcp_ctl = 0x11; /* FIN,ACK */
3275 si->io.pck_rcv += 1;
3279 case SWRAP_CLOSE_ACK:
3280 if (si->type != SOCK_STREAM) {
3284 src_addr = &si->myname.sa.s;
3285 dest_addr = &si->peername.sa.s;
3287 tcp_seqno = si->io.pck_snd;
3288 tcp_ack = si->io.pck_rcv;
3289 tcp_ctl = 0x10; /* ACK */
3296 swrapGetTimeOfDay(&tv);
3298 return swrap_pcap_packet_init(&tv,
3302 (const uint8_t *)buf,
3311 static void swrap_pcap_dump_packet(struct socket_info *si,
3312 const struct sockaddr *addr,
3313 enum swrap_packet_type type,
3314 const void *buf, size_t len)
3316 const char *file_name;
3318 size_t packet_len = 0;
3321 swrap_mutex_lock(&pcap_dump_mutex);
3323 file_name = swrap_pcap_init_file();
3328 packet = swrap_pcap_marshall_packet(si,
3334 if (packet == NULL) {
3338 fd = swrap_pcap_get_fd(file_name);
3340 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3349 swrap_mutex_unlock(&pcap_dump_mutex);
3352 /****************************************************************************
3354 ***************************************************************************/
3356 #ifdef HAVE_SIGNALFD
3357 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3361 rc = libc_signalfd(fd, mask, flags);
3363 swrap_remove_stale(fd);
3369 int signalfd(int fd, const sigset_t *mask, int flags)
3371 return swrap_signalfd(fd, mask, flags);
3375 /****************************************************************************
3377 ***************************************************************************/
3379 static int swrap_socket(int family, int type, int protocol)
3381 struct socket_info *si = NULL;
3382 struct socket_info _si = { 0 };
3385 int real_type = type;
3388 * Remove possible addition flags passed to socket() so
3389 * do not fail checking the type.
3390 * See https://lwn.net/Articles/281965/
3393 real_type &= ~SOCK_CLOEXEC;
3395 #ifdef SOCK_NONBLOCK
3396 real_type &= ~SOCK_NONBLOCK;
3399 if (!socket_wrapper_enabled()) {
3400 return libc_socket(family, type, protocol);
3411 #endif /* AF_NETLINK */
3414 #endif /* AF_PACKET */
3416 fd = libc_socket(family, type, protocol);
3418 /* Check if we have a stale fd and remove it */
3419 swrap_remove_stale(fd);
3420 SWRAP_LOG(SWRAP_LOG_TRACE,
3421 "Unix socket fd=%d",
3426 errno = EAFNOSUPPORT;
3430 switch (real_type) {
3436 errno = EPROTONOSUPPORT;
3444 if (real_type == SOCK_STREAM) {
3449 if (real_type == SOCK_DGRAM) {
3454 errno = EPROTONOSUPPORT;
3459 * We must call libc_socket with type, from the caller, not the version
3460 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3462 fd = libc_socket(AF_UNIX, type, 0);
3468 /* Check if we have a stale fd and remove it */
3469 swrap_remove_stale(fd);
3472 si->family = family;
3474 /* however, the rest of the socket_wrapper code expects just
3475 * the type, not the flags */
3476 si->type = real_type;
3477 si->protocol = protocol;
3480 * Setup myname so getsockname() can succeed to find out the socket
3483 switch(si->family) {
3485 struct sockaddr_in sin = {
3486 .sin_family = AF_INET,
3489 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3490 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3495 struct sockaddr_in6 sin6 = {
3496 .sin6_family = AF_INET6,
3499 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3500 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3509 ret = swrap_create_socket(si, fd);
3511 int saved_errno = errno;
3513 errno = saved_errno;
3517 SWRAP_LOG(SWRAP_LOG_TRACE,
3518 "Created %s socket for protocol %s, fd=%d",
3519 family == AF_INET ? "IPv4" : "IPv6",
3520 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3526 int socket(int family, int type, int protocol)
3528 return swrap_socket(family, type, protocol);
3531 /****************************************************************************
3533 ***************************************************************************/
3535 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3539 rc = libc_socketpair(family, type, protocol, sv);
3541 swrap_remove_stale(sv[0]);
3542 swrap_remove_stale(sv[1]);
3548 int socketpair(int family, int type, int protocol, int sv[2])
3550 return swrap_socketpair(family, type, protocol, sv);
3553 /****************************************************************************
3555 ***************************************************************************/
3557 #ifdef HAVE_TIMERFD_CREATE
3558 static int swrap_timerfd_create(int clockid, int flags)
3562 fd = libc_timerfd_create(clockid, flags);
3564 swrap_remove_stale(fd);
3570 int timerfd_create(int clockid, int flags)
3572 return swrap_timerfd_create(clockid, flags);
3576 /****************************************************************************
3578 ***************************************************************************/
3580 static int swrap_pipe(int pipefd[2])
3584 rc = libc_pipe(pipefd);
3586 swrap_remove_stale(pipefd[0]);
3587 swrap_remove_stale(pipefd[1]);
3593 int pipe(int pipefd[2])
3595 return swrap_pipe(pipefd);
3598 /****************************************************************************
3600 ***************************************************************************/
3602 static int swrap_accept(int s,
3603 struct sockaddr *addr,
3607 struct socket_info *parent_si, *child_si;
3608 struct socket_info new_si = { 0 };
3611 struct swrap_address un_addr = {
3612 .sa_socklen = sizeof(struct sockaddr_un),
3614 struct swrap_address un_my_addr = {
3615 .sa_socklen = sizeof(struct sockaddr_un),
3617 struct swrap_address in_addr = {
3618 .sa_socklen = sizeof(struct sockaddr_storage),
3620 struct swrap_address in_my_addr = {
3621 .sa_socklen = sizeof(struct sockaddr_storage),
3625 parent_si = find_socket_info(s);
3628 return libc_accept4(s, addr, addrlen, flags);
3631 return libc_accept(s, addr, addrlen);
3637 * prevent parent_si from being altered / closed
3640 SWRAP_LOCK_SI(parent_si);
3643 * assume out sockaddr have the same size as the in parent
3646 in_addr.sa_socklen = socket_length(parent_si->family);
3647 if (in_addr.sa_socklen <= 0) {
3648 SWRAP_UNLOCK_SI(parent_si);
3653 SWRAP_UNLOCK_SI(parent_si);
3656 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3659 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3662 int saved_errno = errno;
3663 if (saved_errno == ENOTSOCK) {
3664 /* Remove stale fds */
3665 swrap_remove_stale(s);
3667 errno = saved_errno;
3673 /* Check if we have a stale fd and remove it */
3674 swrap_remove_stale(fd);
3676 if (un_addr.sa.un.sun_path[0] == '\0') {
3678 * FreeBSD seems to have a problem where
3679 * accept4() on the unix socket doesn't
3680 * ECONNABORTED for already disconnected connections.
3682 * Let's try libc_getpeername() to get the peer address
3683 * as a fallback, but it'll likely return ENOTCONN,
3684 * which we have to map to ECONNABORTED.
3686 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3687 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3689 int saved_errno = errno;
3691 if (saved_errno == ENOTCONN) {
3693 * If the connection is already disconnected
3694 * we should return ECONNABORTED.
3696 saved_errno = ECONNABORTED;
3698 errno = saved_errno;
3703 ret = libc_getsockname(fd,
3705 &un_my_addr.sa_socklen);
3707 int saved_errno = errno;
3709 if (saved_errno == ENOTCONN) {
3711 * If the connection is already disconnected
3712 * we should return ECONNABORTED.
3714 saved_errno = ECONNABORTED;
3716 errno = saved_errno;
3720 SWRAP_LOCK_SI(parent_si);
3722 ret = sockaddr_convert_from_un(parent_si,
3727 &in_addr.sa_socklen);
3729 int saved_errno = errno;
3730 SWRAP_UNLOCK_SI(parent_si);
3732 errno = saved_errno;
3738 child_si->family = parent_si->family;
3739 child_si->type = parent_si->type;
3740 child_si->protocol = parent_si->protocol;
3741 child_si->bound = 1;
3742 child_si->is_server = 1;
3743 child_si->connected = 1;
3745 SWRAP_UNLOCK_SI(parent_si);
3747 child_si->peername = (struct swrap_address) {
3748 .sa_socklen = in_addr.sa_socklen,
3750 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3752 if (addr != NULL && addrlen != NULL) {
3753 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3755 memcpy(addr, &in_addr.sa.ss, copy_len);
3757 *addrlen = in_addr.sa_socklen;
3760 ret = sockaddr_convert_from_un(child_si,
3762 un_my_addr.sa_socklen,
3765 &in_my_addr.sa_socklen);
3767 int saved_errno = errno;
3769 errno = saved_errno;
3773 SWRAP_LOG(SWRAP_LOG_TRACE,
3774 "accept() path=%s, fd=%d",
3775 un_my_addr.sa.un.sun_path, s);
3777 child_si->myname = (struct swrap_address) {
3778 .sa_socklen = in_my_addr.sa_socklen,
3780 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3782 idx = swrap_create_socket(&new_si, fd);
3784 int saved_errno = errno;
3786 errno = saved_errno;
3791 struct socket_info *si = swrap_get_socket_info(idx);
3794 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3795 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3796 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3797 SWRAP_UNLOCK_SI(si);
3804 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3806 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3810 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3811 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3813 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3816 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3819 static int autobind_start_init;
3820 static int autobind_start;
3822 /* using sendto() or connect() on an unbound socket would give the
3823 recipient no way to reply, as unlike UDP and TCP, a unix domain
3824 socket can't auto-assign ephemeral port numbers, so we need to
3826 Note: this might change the family from ipv6 to ipv4
3828 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3830 struct swrap_address un_addr = {
3831 .sa_socklen = sizeof(struct sockaddr_un),
3837 char *swrap_dir = NULL;
3839 swrap_mutex_lock(&autobind_start_mutex);
3841 if (autobind_start_init != 1) {
3842 autobind_start_init = 1;
3843 autobind_start = getpid();
3844 autobind_start %= 50000;
3845 autobind_start += 10000;
3848 un_addr.sa.un.sun_family = AF_UNIX;
3852 struct sockaddr_in in;
3856 type = SOCKET_TYPE_CHAR_TCP;
3859 type = SOCKET_TYPE_CHAR_UDP;
3862 errno = ESOCKTNOSUPPORT;
3867 memset(&in, 0, sizeof(in));
3868 in.sin_family = AF_INET;
3869 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3870 socket_wrapper_default_iface()));
3872 si->myname = (struct swrap_address) {
3873 .sa_socklen = sizeof(in),
3875 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3880 struct sockaddr_in6 in6;
3882 if (si->family != family) {
3883 errno = ENETUNREACH;
3890 type = SOCKET_TYPE_CHAR_TCP_V6;
3893 type = SOCKET_TYPE_CHAR_UDP_V6;
3896 errno = ESOCKTNOSUPPORT;
3901 memset(&in6, 0, sizeof(in6));
3902 in6.sin6_family = AF_INET6;
3903 in6.sin6_addr = *swrap_ipv6();
3904 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3906 si->myname = (struct swrap_address) {
3907 .sa_socklen = sizeof(in6),
3909 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3914 errno = ESOCKTNOSUPPORT;
3919 if (autobind_start > 60000) {
3920 autobind_start = 10000;
3923 swrap_dir = socket_wrapper_dir();
3924 if (swrap_dir == NULL) {
3930 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3931 port = autobind_start + i;
3932 swrap_un_path(&un_addr.sa.un,
3935 socket_wrapper_default_iface(),
3938 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3940 if (errno == EALREADY || errno == EADDRINUSE) {
3946 si->un_addr = un_addr.sa.un;
3949 autobind_start = port + 1;
3952 if (i == SOCKET_MAX_SOCKETS) {
3953 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3954 "interface "SOCKET_FORMAT,
3957 socket_wrapper_default_iface(),
3964 si->family = family;
3965 set_port(si->family, port, &si->myname);
3970 SAFE_FREE(swrap_dir);
3971 swrap_mutex_unlock(&autobind_start_mutex);
3975 /****************************************************************************
3977 ***************************************************************************/
3979 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3983 struct swrap_address un_addr = {
3984 .sa_socklen = sizeof(struct sockaddr_un),
3986 struct socket_info *si = find_socket_info(s);
3990 return libc_connect(s, serv_addr, addrlen);
3995 if (si->bound == 0) {
3996 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4002 if (si->family != serv_addr->sa_family) {
4003 SWRAP_LOG(SWRAP_LOG_ERROR,
4004 "called for fd=%d (family=%d) called with invalid family=%d",
4005 s, si->family, serv_addr->sa_family);
4011 ret = sockaddr_convert_to_un(si, serv_addr,
4012 addrlen, &un_addr.sa.un, 0, &bcast);
4018 errno = ENETUNREACH;
4023 if (si->type == SOCK_DGRAM) {
4024 si->defer_connect = 1;
4027 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4029 ret = libc_connect(s,
4031 un_addr.sa_socklen);
4034 SWRAP_LOG(SWRAP_LOG_TRACE,
4035 "connect() path=%s, fd=%d",
4036 un_addr.sa.un.sun_path, s);
4039 /* to give better errors */
4040 if (ret == -1 && errno == ENOENT) {
4041 errno = EHOSTUNREACH;
4045 si->peername = (struct swrap_address) {
4046 .sa_socklen = addrlen,
4049 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4053 * When we connect() on a socket than we have to bind the
4054 * outgoing connection on the interface we use for the
4055 * transport. We already bound it on the right interface
4056 * but here we have to update the name so getsockname()
4057 * returns correct information.
4059 if (si->bindname.sa_socklen > 0) {
4060 si->myname = (struct swrap_address) {
4061 .sa_socklen = si->bindname.sa_socklen,
4064 memcpy(&si->myname.sa.ss,
4065 &si->bindname.sa.ss,
4066 si->bindname.sa_socklen);
4068 /* Cleanup bindname */
4069 si->bindname = (struct swrap_address) {
4074 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4075 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4077 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4081 SWRAP_UNLOCK_SI(si);
4085 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4087 return swrap_connect(s, serv_addr, addrlen);
4090 /****************************************************************************
4092 ***************************************************************************/
4094 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4097 struct swrap_address un_addr = {
4098 .sa_socklen = sizeof(struct sockaddr_un),
4100 struct socket_info *si = find_socket_info(s);
4107 return libc_bind(s, myaddr, addrlen);
4112 switch (si->family) {
4114 const struct sockaddr_in *sin;
4115 if (addrlen < sizeof(struct sockaddr_in)) {
4116 bind_error = EINVAL;
4120 sin = (const struct sockaddr_in *)(const void *)myaddr;
4122 if (sin->sin_family != AF_INET) {
4123 bind_error = EAFNOSUPPORT;
4126 /* special case for AF_UNSPEC */
4127 if (sin->sin_family == AF_UNSPEC &&
4128 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4137 const struct sockaddr_in6 *sin6;
4138 if (addrlen < sizeof(struct sockaddr_in6)) {
4139 bind_error = EINVAL;
4143 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4145 if (sin6->sin6_family != AF_INET6) {
4146 bind_error = EAFNOSUPPORT;
4153 bind_error = EINVAL;
4157 if (bind_error != 0) {
4164 in_use = check_addr_port_in_use(myaddr, addrlen);
4172 si->myname.sa_socklen = addrlen;
4173 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4175 ret = sockaddr_convert_to_un(si,
4185 unlink(un_addr.sa.un.sun_path);
4187 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4189 SWRAP_LOG(SWRAP_LOG_TRACE,
4190 "bind() path=%s, fd=%d",
4191 un_addr.sa.un.sun_path, s);
4198 SWRAP_UNLOCK_SI(si);
4203 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4205 return swrap_bind(s, myaddr, addrlen);
4208 /****************************************************************************
4210 ***************************************************************************/
4212 #ifdef HAVE_BINDRESVPORT
4213 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4215 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4217 struct swrap_address myaddr = {
4218 .sa_socklen = sizeof(struct sockaddr_storage),
4221 static uint16_t port;
4226 #define SWRAP_STARTPORT 600
4227 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4228 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4231 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4235 salen = myaddr.sa_socklen;
4238 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4244 memset(&myaddr.sa.ss, 0, salen);
4249 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4252 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4254 salen = sizeof(struct sockaddr_in);
4255 sinp->sin_port = htons(port);
4259 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4261 salen = sizeof(struct sockaddr_in6);
4262 sin6p->sin6_port = htons(port);
4266 errno = EAFNOSUPPORT;
4271 if (port > SWRAP_ENDPORT) {
4272 port = SWRAP_STARTPORT;
4275 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4276 if (rc == 0 || errno != EADDRINUSE) {
4284 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4286 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4290 /****************************************************************************
4292 ***************************************************************************/
4294 static int swrap_listen(int s, int backlog)
4297 struct socket_info *si = find_socket_info(s);
4300 return libc_listen(s, backlog);
4305 if (si->bound == 0) {
4306 ret = swrap_auto_bind(s, si, si->family);
4313 ret = libc_listen(s, backlog);
4319 SWRAP_UNLOCK_SI(si);
4324 int listen(int s, int backlog)
4326 return swrap_listen(s, backlog);
4329 /****************************************************************************
4331 ***************************************************************************/
4333 static FILE *swrap_fopen(const char *name, const char *mode)
4337 fp = libc_fopen(name, mode);
4339 int fd = fileno(fp);
4341 swrap_remove_stale(fd);
4347 FILE *fopen(const char *name, const char *mode)
4349 return swrap_fopen(name, mode);
4352 /****************************************************************************
4354 ***************************************************************************/
4357 static FILE *swrap_fopen64(const char *name, const char *mode)
4361 fp = libc_fopen64(name, mode);
4363 int fd = fileno(fp);
4365 swrap_remove_stale(fd);
4371 FILE *fopen64(const char *name, const char *mode)
4373 return swrap_fopen64(name, mode);
4375 #endif /* HAVE_FOPEN64 */
4377 /****************************************************************************
4379 ***************************************************************************/
4381 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4385 ret = libc_vopen(pathname, flags, ap);
4388 * There are methods for closing descriptors (libc-internal code
4389 * paths, direct syscalls) which close descriptors in ways that
4390 * we can't intercept, so try to recover when we notice that
4393 swrap_remove_stale(ret);
4398 int open(const char *pathname, int flags, ...)
4403 va_start(ap, flags);
4404 fd = swrap_vopen(pathname, flags, ap);
4410 /****************************************************************************
4412 ***************************************************************************/
4415 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4419 ret = libc_vopen64(pathname, flags, ap);
4422 * There are methods for closing descriptors (libc-internal code
4423 * paths, direct syscalls) which close descriptors in ways that
4424 * we can't intercept, so try to recover when we notice that
4427 swrap_remove_stale(ret);
4432 int open64(const char *pathname, int flags, ...)
4437 va_start(ap, flags);
4438 fd = swrap_vopen64(pathname, flags, ap);
4443 #endif /* HAVE_OPEN64 */
4445 /****************************************************************************
4447 ***************************************************************************/
4449 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4453 ret = libc_vopenat(dirfd, path, flags, ap);
4456 * There are methods for closing descriptors (libc-internal code
4457 * paths, direct syscalls) which close descriptors in ways that
4458 * we can't intercept, so try to recover when we notice that
4461 swrap_remove_stale(ret);
4467 int openat(int dirfd, const char *path, int flags, ...)
4472 va_start(ap, flags);
4473 fd = swrap_vopenat(dirfd, path, flags, ap);
4479 /****************************************************************************
4481 ***************************************************************************/
4483 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4485 struct socket_info *si = find_socket_info(s);
4490 return libc_getpeername(s, name, addrlen);
4495 if (si->peername.sa_socklen == 0)
4501 len = MIN(*addrlen, si->peername.sa_socklen);
4507 memcpy(name, &si->peername.sa.ss, len);
4508 *addrlen = si->peername.sa_socklen;
4512 SWRAP_UNLOCK_SI(si);
4517 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4518 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4520 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4523 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4526 /****************************************************************************
4528 ***************************************************************************/
4530 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4532 struct socket_info *si = find_socket_info(s);
4537 return libc_getsockname(s, name, addrlen);
4542 len = MIN(*addrlen, si->myname.sa_socklen);
4548 memcpy(name, &si->myname.sa.ss, len);
4549 *addrlen = si->myname.sa_socklen;
4553 SWRAP_UNLOCK_SI(si);
4558 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4559 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4561 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4564 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4567 /****************************************************************************
4569 ***************************************************************************/
4572 # ifdef SO_PROTOTYPE /* The Solaris name */
4573 # define SO_PROTOCOL SO_PROTOTYPE
4574 # endif /* SO_PROTOTYPE */
4575 #endif /* SO_PROTOCOL */
4577 static int swrap_getsockopt(int s, int level, int optname,
4578 void *optval, socklen_t *optlen)
4580 struct socket_info *si = find_socket_info(s);
4584 return libc_getsockopt(s,
4593 if (level == SOL_SOCKET) {
4597 if (optval == NULL || optlen == NULL ||
4598 *optlen < (socklen_t)sizeof(int)) {
4604 *optlen = sizeof(int);
4605 *(int *)optval = si->family;
4608 #endif /* SO_DOMAIN */
4612 if (optval == NULL || optlen == NULL ||
4613 *optlen < (socklen_t)sizeof(int)) {
4619 *optlen = sizeof(int);
4620 *(int *)optval = si->protocol;
4623 #endif /* SO_PROTOCOL */
4625 if (optval == NULL || optlen == NULL ||
4626 *optlen < (socklen_t)sizeof(int)) {
4632 *optlen = sizeof(int);
4633 *(int *)optval = si->type;
4637 ret = libc_getsockopt(s,
4644 } else if (level == IPPROTO_TCP) {
4649 * This enables sending packets directly out over TCP.
4650 * As a unix socket is doing that any way, report it as
4653 if (optval == NULL || optlen == NULL ||
4654 *optlen < (socklen_t)sizeof(int)) {
4660 *optlen = sizeof(int);
4661 *(int *)optval = si->tcp_nodelay;
4665 #endif /* TCP_NODELAY */
4668 struct tcp_info info;
4669 socklen_t ilen = sizeof(info);
4671 #ifdef HAVE_NETINET_TCP_FSM_H
4672 /* This is FreeBSD */
4673 # define __TCP_LISTEN TCPS_LISTEN
4674 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4675 # define __TCP_CLOSE TCPS_CLOSED
4678 # define __TCP_LISTEN TCP_LISTEN
4679 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4680 # define __TCP_CLOSE TCP_CLOSE
4684 if (si->listening) {
4685 info.tcpi_state = __TCP_LISTEN;
4686 } else if (si->connected) {
4688 * For now we just fake a few values
4689 * supported both by FreeBSD and Linux
4691 info.tcpi_state = __TCP_ESTABLISHED;
4692 info.tcpi_rto = 200000; /* 200 msec */
4693 info.tcpi_rtt = 5000; /* 5 msec */
4694 info.tcpi_rttvar = 5000; /* 5 msec */
4696 info.tcpi_state = __TCP_CLOSE;
4697 info.tcpi_rto = 1000000; /* 1 sec */
4699 info.tcpi_rttvar = 250000; /* 250 msec */
4702 if (optval == NULL || optlen == NULL ||
4703 *optlen < (socklen_t)ilen) {
4710 memcpy(optval, &info, ilen);
4715 #endif /* TCP_INFO */
4721 errno = ENOPROTOOPT;
4725 SWRAP_UNLOCK_SI(si);
4729 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4730 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4732 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4735 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4738 /****************************************************************************
4740 ***************************************************************************/
4742 static int swrap_setsockopt(int s, int level, int optname,
4743 const void *optval, socklen_t optlen)
4745 struct socket_info *si = find_socket_info(s);
4749 return libc_setsockopt(s,
4756 if (level == SOL_SOCKET) {
4757 return libc_setsockopt(s,
4766 if (level == IPPROTO_TCP) {
4773 * This enables sending packets directly out over TCP.
4774 * A unix socket is doing that any way.
4776 if (optval == NULL || optlen == 0 ||
4777 optlen < (socklen_t)sizeof(int)) {
4783 i = *discard_const_p(int, optval);
4784 if (i != 0 && i != 1) {
4789 si->tcp_nodelay = i;
4794 #endif /* TCP_NODELAY */
4800 switch (si->family) {
4802 if (level == IPPROTO_IP) {
4804 if (optname == IP_PKTINFO) {
4805 si->pktinfo = AF_INET;
4807 #endif /* IP_PKTINFO */
4813 if (level == IPPROTO_IPV6) {
4814 #ifdef IPV6_RECVPKTINFO
4815 if (optname == IPV6_RECVPKTINFO) {
4816 si->pktinfo = AF_INET6;
4818 #endif /* IPV6_PKTINFO */
4824 errno = ENOPROTOOPT;
4830 SWRAP_UNLOCK_SI(si);
4834 int setsockopt(int s, int level, int optname,
4835 const void *optval, socklen_t optlen)
4837 return swrap_setsockopt(s, level, optname, optval, optlen);
4840 /****************************************************************************
4842 ***************************************************************************/
4844 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4846 struct socket_info *si = find_socket_info(s);
4848 int *value_ptr = NULL;
4852 return libc_vioctl(s, r, va);
4859 rc = libc_vioctl(s, r, va);
4864 value_ptr = ((int *)va_arg(ap, int *));
4867 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4868 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4869 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4870 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4875 /* this is FreeBSD */
4876 FALL_THROUGH; /* to TIOCOUTQ */
4877 #endif /* FIONWRITE */
4878 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4880 * This may return more bytes then the application
4881 * sent into the socket, for tcp it should
4882 * return the number of unacked bytes.
4884 * On AF_UNIX, all bytes are immediately acked!
4887 value_ptr = ((int *)va_arg(ap, int *));
4895 SWRAP_UNLOCK_SI(si);
4899 #ifdef HAVE_IOCTL_INT
4900 int ioctl(int s, int r, ...)
4902 int ioctl(int s, unsigned long int r, ...)
4910 rc = swrap_vioctl(s, (unsigned long int) r, va);
4921 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4924 # ifdef _ALIGN /* BSD */
4925 #define CMSG_ALIGN _ALIGN
4927 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4928 # endif /* _ALIGN */
4929 #endif /* CMSG_ALIGN */
4932 * @brief Add a cmsghdr to a msghdr.
4934 * This is an function to add any type of cmsghdr. It will operate on the
4935 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4936 * the buffer position after the added cmsg element. Hence, this function is
4937 * intended to be used with an intermediate msghdr and not on the original
4938 * one handed in by the client.
4940 * @param[in] msg The msghdr to which to add the cmsg.
4942 * @param[in] level The cmsg level to set.
4944 * @param[in] type The cmsg type to set.
4946 * @param[in] data The cmsg data to set.
4948 * @param[in] len the length of the data to set.
4950 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4956 size_t cmlen = CMSG_LEN(len);
4957 size_t cmspace = CMSG_SPACE(len);
4958 uint8_t cmbuf[cmspace];
4959 void *cast_ptr = (void *)cmbuf;
4960 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4963 memset(cmbuf, 0, cmspace);
4965 if (msg->msg_controllen < cmlen) {
4966 cmlen = msg->msg_controllen;
4967 msg->msg_flags |= MSG_CTRUNC;
4970 if (msg->msg_controllen < cmspace) {
4971 cmspace = msg->msg_controllen;
4975 * We copy the full input data into an intermediate cmsghdr first
4976 * in order to more easily cope with truncation.
4978 cm->cmsg_len = cmlen;
4979 cm->cmsg_level = level;
4980 cm->cmsg_type = type;
4981 memcpy(CMSG_DATA(cm), data, len);
4984 * We now copy the possibly truncated buffer.
4985 * We copy cmlen bytes, but consume cmspace bytes,
4986 * leaving the possible padding uninitialiazed.
4988 p = (uint8_t *)msg->msg_control;
4989 memcpy(p, cm, cmlen);
4991 msg->msg_control = p;
4992 msg->msg_controllen -= cmspace;
4997 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5000 /* Add packet info */
5001 switch (si->pktinfo) {
5002 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5004 struct sockaddr_in *sin;
5005 #if defined(HAVE_STRUCT_IN_PKTINFO)
5006 struct in_pktinfo pkt;
5007 #elif defined(IP_RECVDSTADDR)
5011 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5012 sin = &si->bindname.sa.in;
5014 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5017 sin = &si->myname.sa.in;
5022 #if defined(HAVE_STRUCT_IN_PKTINFO)
5023 pkt.ipi_ifindex = socket_wrapper_default_iface();
5024 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5025 #elif defined(IP_RECVDSTADDR)
5026 pkt = sin->sin_addr;
5029 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5034 #endif /* IP_PKTINFO */
5035 #if defined(HAVE_IPV6)
5037 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5038 struct sockaddr_in6 *sin6;
5039 struct in6_pktinfo pkt6;
5041 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5042 sin6 = &si->bindname.sa.in6;
5044 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5047 sin6 = &si->myname.sa.in6;
5052 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5053 pkt6.ipi6_addr = sin6->sin6_addr;
5055 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5056 &pkt6, sizeof(pkt6));
5057 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5061 #endif /* IPV6_PKTINFO */
5069 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5070 struct msghdr *omsg)
5074 if (si->pktinfo > 0) {
5075 rc = swrap_msghdr_add_pktinfo(si, omsg);
5081 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5083 size_t *cm_data_space);
5084 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5086 size_t *cm_data_space);
5087 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5089 size_t *cm_data_space);
5091 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5093 size_t *cm_data_space)
5095 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5096 struct cmsghdr *cmsg;
5100 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5104 for (cmsg = CMSG_FIRSTHDR(msg);
5106 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5107 switch (cmsg->cmsg_level) {
5109 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5114 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5119 rc = swrap_sendmsg_copy_cmsg(cmsg,
5125 int saved_errno = errno;
5126 SAFE_FREE(*cm_data);
5128 errno = saved_errno;
5136 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5138 size_t *cm_data_space)
5143 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5145 p = realloc((*cm_data), cmspace);
5151 p = (*cm_data) + (*cm_data_space);
5152 *cm_data_space = cmspace;
5154 memcpy(p, cmsg, cmsg->cmsg_len);
5159 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5161 size_t *cm_data_space);
5164 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5166 size_t *cm_data_space)
5170 switch(cmsg->cmsg_type) {
5173 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5180 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5192 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5194 size_t *cm_data_space)
5196 (void)cmsg; /* unused */
5197 (void)cm_data; /* unused */
5198 (void)cm_data_space; /* unused */
5201 * Passing a IP pktinfo to a unix socket might be rejected by the
5202 * Kernel, at least on FreeBSD. So skip this cmsg.
5207 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5209 size_t *cm_data_space)
5213 switch (cmsg->cmsg_type) {
5215 SWRAP_LOG(SWRAP_LOG_TRACE,
5216 "Ignoring SCM_RIGHTS on inet socket!");
5219 #ifdef SCM_CREDENTIALS
5220 case SCM_CREDENTIALS:
5221 SWRAP_LOG(SWRAP_LOG_TRACE,
5222 "Ignoring SCM_CREDENTIALS on inet socket!");
5225 #endif /* SCM_CREDENTIALS */
5227 rc = swrap_sendmsg_copy_cmsg(cmsg,
5236 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5239 * We only allow up to 6 fds at a time
5240 * as that's more than enough for Samba
5241 * and it means we can keep the logic simple
5242 * and work with fixed size arrays.
5244 * We also keep sizeof(struct swrap_unix_scm_rights)
5245 * under PIPE_BUF (4096) in order to allow a non-blocking
5246 * write into the pipe.
5249 #define PIPE_BUF 4096
5251 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5252 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5253 struct swrap_unix_scm_rights_payload {
5255 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5256 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5258 struct swrap_unix_scm_rights {
5260 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5261 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5263 uint32_t payload_size;
5264 struct swrap_unix_scm_rights_payload payload;
5267 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5269 int saved_errno = errno;
5272 for (i = 0; i < num; i++) {
5273 struct socket_info *si = array[i];
5279 swrap_dec_refcount(si);
5280 if (si->fd_passed > 0) {
5283 SWRAP_UNLOCK_SI(si);
5287 errno = saved_errno;
5290 static void swrap_undo_si_idx_array(size_t num, int *array)
5292 int saved_errno = errno;
5295 swrap_mutex_lock(&first_free_mutex);
5297 for (i = 0; i < num; i++) {
5298 struct socket_info *si = NULL;
5300 if (array[i] == -1) {
5304 si = swrap_get_socket_info(array[i]);
5310 swrap_dec_refcount(si);
5311 SWRAP_UNLOCK_SI(si);
5313 swrap_set_next_free(si, first_free);
5314 first_free = array[i];
5318 swrap_mutex_unlock(&first_free_mutex);
5319 errno = saved_errno;
5322 static void swrap_close_fd_array(size_t num, const int *array)
5324 int saved_errno = errno;
5327 for (i = 0; i < num; i++) {
5328 if (array[i] == -1) {
5331 libc_close(array[i]);
5334 errno = saved_errno;
5342 union __swrap_cmsghdr {
5344 struct cmsghdr *cmsg;
5347 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5349 size_t *cm_data_space,
5350 int *scm_rights_pipe_fd)
5352 struct swrap_unix_scm_rights info;
5353 struct swrap_unix_scm_rights_payload *payload = NULL;
5354 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5355 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5356 size_t info_idx = 0;
5359 union __swrap_fds __fds_in = { .p = NULL, };
5360 const int *fds_in = NULL;
5362 size_t size_fds_out;
5363 union __swrap_fds __fds_out = { .p = NULL, };
5364 int *fds_out = NULL;
5367 size_t new_cm_data_space;
5368 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5369 struct cmsghdr *new_cmsg = NULL;
5372 int pipefd[2] = { -1, -1 };
5377 * We pass this a buffer to the kernel make sure any padding
5381 info.magic = swrap_unix_scm_right_magic;
5382 memcpy(info.package_name,
5383 SOCKET_WRAPPER_PACKAGE,
5384 sizeof(info.package_name));
5385 memcpy(info.package_version,
5386 SOCKET_WRAPPER_VERSION,
5387 sizeof(info.package_version));
5388 info.full_size = sizeof(info);
5389 info.payload_size = sizeof(info.payload);
5390 payload = &info.payload;
5392 if (*scm_rights_pipe_fd != -1) {
5393 SWRAP_LOG(SWRAP_LOG_ERROR,
5394 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5399 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5400 SWRAP_LOG(SWRAP_LOG_ERROR,
5401 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5402 (size_t)cmsg->cmsg_len,
5407 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5408 if ((size_fds_in % sizeof(int)) != 0) {
5409 SWRAP_LOG(SWRAP_LOG_ERROR,
5410 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5411 (size_t)cmsg->cmsg_len,
5417 num_fds_in = size_fds_in / sizeof(int);
5418 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5419 SWRAP_LOG(SWRAP_LOG_ERROR,
5420 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5422 "SWRAP_MAX_PASSED_FDS(%zu)",
5423 (size_t)cmsg->cmsg_len,
5426 SWRAP_MAX_PASSED_FDS);
5430 if (num_fds_in == 0) {
5431 SWRAP_LOG(SWRAP_LOG_ERROR,
5432 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5434 (size_t)cmsg->cmsg_len,
5440 __fds_in.p = CMSG_DATA(cmsg);
5441 fds_in = __fds_in.fds;
5442 num_fds_out = num_fds_in + 1;
5444 SWRAP_LOG(SWRAP_LOG_TRACE,
5445 "num_fds_in=%zu num_fds_out=%zu",
5446 num_fds_in, num_fds_out);
5448 size_fds_out = sizeof(int) * num_fds_out;
5449 cmsg_len = CMSG_LEN(size_fds_out);
5450 cmsg_space = CMSG_SPACE(size_fds_out);
5452 new_cm_data_space = *cm_data_space + cmsg_space;
5454 p = realloc((*cm_data), new_cm_data_space);
5459 p = (*cm_data) + (*cm_data_space);
5460 memset(p, 0, cmsg_space);
5462 new_cmsg = __new_cmsg.cmsg;
5464 __fds_out.p = CMSG_DATA(new_cmsg);
5465 fds_out = __fds_out.fds;
5466 memcpy(fds_out, fds_in, size_fds_in);
5467 new_cmsg->cmsg_len = cmsg->cmsg_len;
5469 for (i = 0; i < num_fds_in; i++) {
5472 payload->idxs[i] = -1;
5473 payload->num_idxs++;
5475 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5476 if (si_idx_array[i] == -1) {
5480 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5481 if (si_array[i] == NULL) {
5482 SWRAP_LOG(SWRAP_LOG_ERROR,
5483 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5484 i, fds_in[i], i, si_idx_array[i]);
5489 for (j = 0; j < i; j++) {
5490 if (si_array[j] == si_array[i]) {
5491 payload->idxs[i] = payload->idxs[j];
5495 if (payload->idxs[i] == -1) {
5496 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5497 SWRAP_LOG(SWRAP_LOG_ERROR,
5498 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5499 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5500 i, fds_in[i], i, si_idx_array[i],
5502 SWRAP_MAX_PASSED_SOCKET_INFO);
5506 payload->idxs[i] = info_idx;
5512 for (i = 0; i < num_fds_in; i++) {
5513 struct socket_info *si = si_array[i];
5516 SWRAP_LOG(SWRAP_LOG_TRACE,
5517 "fds_in[%zu]=%d not an inet socket",
5522 SWRAP_LOG(SWRAP_LOG_TRACE,
5523 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5524 "passing as info.idxs[%zu]=%d!",
5527 i, payload->idxs[i]);
5531 payload->infos[payload->idxs[i]] = *si;
5532 payload->infos[payload->idxs[i]].fd_passed = 0;
5533 SWRAP_UNLOCK_SI(si);
5538 int saved_errno = errno;
5539 SWRAP_LOG(SWRAP_LOG_ERROR,
5540 "pipe() failed - %d %s",
5542 strerror(saved_errno));
5543 swrap_dec_fd_passed_array(num_fds_in, si_array);
5544 errno = saved_errno;
5548 sret = libc_write(pipefd[1], &info, sizeof(info));
5549 if (sret != sizeof(info)) {
5550 int saved_errno = errno;
5552 saved_errno = EINVAL;
5554 SWRAP_LOG(SWRAP_LOG_ERROR,
5555 "write() failed - sret=%zd - %d %s",
5557 strerror(saved_errno));
5558 swrap_dec_fd_passed_array(num_fds_in, si_array);
5559 libc_close(pipefd[1]);
5560 libc_close(pipefd[0]);
5561 errno = saved_errno;
5564 libc_close(pipefd[1]);
5567 * Add the pipe read end to the end of the passed fd array
5569 fds_out[num_fds_in] = pipefd[0];
5570 new_cmsg->cmsg_len = cmsg_len;
5572 /* we're done ... */
5573 *scm_rights_pipe_fd = pipefd[0];
5574 *cm_data_space = new_cm_data_space;
5579 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5581 size_t *cm_data_space,
5582 int *scm_rights_pipe_fd)
5586 switch (cmsg->cmsg_type) {
5588 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5591 scm_rights_pipe_fd);
5594 rc = swrap_sendmsg_copy_cmsg(cmsg,
5603 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5605 size_t *cm_data_space)
5607 int scm_rights_pipe_fd = -1;
5608 struct swrap_unix_scm_rights info;
5609 struct swrap_unix_scm_rights_payload *payload = NULL;
5610 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5613 union __swrap_fds __fds_in = { .p = NULL, };
5614 const int *fds_in = NULL;
5616 size_t size_fds_out;
5617 union __swrap_fds __fds_out = { .p = NULL, };
5618 int *fds_out = NULL;
5621 size_t new_cm_data_space;
5622 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5623 struct cmsghdr *new_cmsg = NULL;
5629 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5630 SWRAP_LOG(SWRAP_LOG_ERROR,
5631 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5632 (size_t)cmsg->cmsg_len,
5637 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5638 if ((size_fds_in % sizeof(int)) != 0) {
5639 SWRAP_LOG(SWRAP_LOG_ERROR,
5640 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5641 (size_t)cmsg->cmsg_len,
5647 num_fds_in = size_fds_in / sizeof(int);
5648 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5649 SWRAP_LOG(SWRAP_LOG_ERROR,
5650 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5651 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5652 (size_t)cmsg->cmsg_len,
5655 SWRAP_MAX_PASSED_FDS+1);
5659 if (num_fds_in <= 1) {
5660 SWRAP_LOG(SWRAP_LOG_ERROR,
5661 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5663 (size_t)cmsg->cmsg_len,
5669 __fds_in.p = CMSG_DATA(cmsg);
5670 fds_in = __fds_in.fds;
5671 num_fds_out = num_fds_in - 1;
5673 SWRAP_LOG(SWRAP_LOG_TRACE,
5674 "num_fds_in=%zu num_fds_out=%zu",
5675 num_fds_in, num_fds_out);
5677 for (i = 0; i < num_fds_in; i++) {
5678 /* Check if we have a stale fd and remove it */
5679 swrap_remove_stale(fds_in[i]);
5682 scm_rights_pipe_fd = fds_in[num_fds_out];
5683 size_fds_out = sizeof(int) * num_fds_out;
5684 cmsg_len = CMSG_LEN(size_fds_out);
5685 cmsg_space = CMSG_SPACE(size_fds_out);
5687 new_cm_data_space = *cm_data_space + cmsg_space;
5689 p = realloc((*cm_data), new_cm_data_space);
5691 swrap_close_fd_array(num_fds_in, fds_in);
5695 p = (*cm_data) + (*cm_data_space);
5696 memset(p, 0, cmsg_space);
5698 new_cmsg = __new_cmsg.cmsg;
5700 __fds_out.p = CMSG_DATA(new_cmsg);
5701 fds_out = __fds_out.fds;
5702 memcpy(fds_out, fds_in, size_fds_out);
5703 new_cmsg->cmsg_len = cmsg_len;
5705 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5706 if (sret != sizeof(info)) {
5707 int saved_errno = errno;
5709 saved_errno = EINVAL;
5711 SWRAP_LOG(SWRAP_LOG_ERROR,
5712 "read() failed - sret=%zd - %d %s",
5714 strerror(saved_errno));
5715 swrap_close_fd_array(num_fds_in, fds_in);
5716 errno = saved_errno;
5719 libc_close(scm_rights_pipe_fd);
5720 payload = &info.payload;
5722 if (info.magic != swrap_unix_scm_right_magic) {
5723 SWRAP_LOG(SWRAP_LOG_ERROR,
5724 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5725 (unsigned long long)info.magic,
5726 (unsigned long long)swrap_unix_scm_right_magic);
5727 swrap_close_fd_array(num_fds_out, fds_out);
5732 cmp = memcmp(info.package_name,
5733 SOCKET_WRAPPER_PACKAGE,
5734 sizeof(info.package_name));
5736 SWRAP_LOG(SWRAP_LOG_ERROR,
5737 "info.package_name='%.*s' != '%s'",
5738 (int)sizeof(info.package_name),
5740 SOCKET_WRAPPER_PACKAGE);
5741 swrap_close_fd_array(num_fds_out, fds_out);
5746 cmp = memcmp(info.package_version,
5747 SOCKET_WRAPPER_VERSION,
5748 sizeof(info.package_version));
5750 SWRAP_LOG(SWRAP_LOG_ERROR,
5751 "info.package_version='%.*s' != '%s'",
5752 (int)sizeof(info.package_version),
5753 info.package_version,
5754 SOCKET_WRAPPER_VERSION);
5755 swrap_close_fd_array(num_fds_out, fds_out);
5760 if (info.full_size != sizeof(info)) {
5761 SWRAP_LOG(SWRAP_LOG_ERROR,
5762 "info.full_size=%zu != sizeof(info)=%zu",
5763 (size_t)info.full_size,
5765 swrap_close_fd_array(num_fds_out, fds_out);
5770 if (info.payload_size != sizeof(info.payload)) {
5771 SWRAP_LOG(SWRAP_LOG_ERROR,
5772 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5773 (size_t)info.payload_size,
5774 sizeof(info.payload));
5775 swrap_close_fd_array(num_fds_out, fds_out);
5780 if (payload->num_idxs != num_fds_out) {
5781 SWRAP_LOG(SWRAP_LOG_ERROR,
5782 "info.num_idxs=%u != num_fds_out=%zu",
5783 payload->num_idxs, num_fds_out);
5784 swrap_close_fd_array(num_fds_out, fds_out);
5789 for (i = 0; i < num_fds_out; i++) {
5792 si_idx_array[i] = -1;
5794 if (payload->idxs[i] == -1) {
5795 SWRAP_LOG(SWRAP_LOG_TRACE,
5796 "fds_out[%zu]=%d not an inet socket",
5801 if (payload->idxs[i] < 0) {
5802 SWRAP_LOG(SWRAP_LOG_ERROR,
5803 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5804 i, fds_out[i], i, payload->idxs[i]);
5805 swrap_close_fd_array(num_fds_out, fds_out);
5810 if (payload->idxs[i] >= payload->num_idxs) {
5811 SWRAP_LOG(SWRAP_LOG_ERROR,
5812 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5813 i, fds_out[i], i, payload->idxs[i],
5815 swrap_close_fd_array(num_fds_out, fds_out);
5820 if ((size_t)fds_out[i] >= socket_fds_max) {
5821 SWRAP_LOG(SWRAP_LOG_ERROR,
5822 "The max socket index limit of %zu has been reached, "
5826 swrap_close_fd_array(num_fds_out, fds_out);
5831 SWRAP_LOG(SWRAP_LOG_TRACE,
5833 "received as info.idxs[%zu]=%d!",
5835 i, payload->idxs[i]);
5837 for (j = 0; j < i; j++) {
5838 if (payload->idxs[j] == -1) {
5841 if (payload->idxs[j] == payload->idxs[i]) {
5842 si_idx_array[i] = si_idx_array[j];
5845 if (si_idx_array[i] == -1) {
5846 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5848 si_idx_array[i] = swrap_add_socket_info(si);
5849 if (si_idx_array[i] == -1) {
5850 int saved_errno = errno;
5851 SWRAP_LOG(SWRAP_LOG_ERROR,
5852 "The max socket index limit of %zu has been reached, "
5856 swrap_undo_si_idx_array(i, si_idx_array);
5857 swrap_close_fd_array(num_fds_out, fds_out);
5858 errno = saved_errno;
5861 SWRAP_LOG(SWRAP_LOG_TRACE,
5862 "Imported %s socket for protocol %s, fd=%d",
5863 si->family == AF_INET ? "IPv4" : "IPv6",
5864 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5869 for (i = 0; i < num_fds_out; i++) {
5870 if (si_idx_array[i] == -1) {
5873 set_socket_info_index(fds_out[i], si_idx_array[i]);
5876 /* we're done ... */
5877 *cm_data_space = new_cm_data_space;
5882 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
5884 size_t *cm_data_space)
5888 switch (cmsg->cmsg_type) {
5890 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5895 rc = swrap_sendmsg_copy_cmsg(cmsg,
5904 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5906 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5907 struct msghdr *msg_tmp,
5908 int *scm_rights_pipe_fd)
5910 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5911 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5912 struct cmsghdr *cmsg = NULL;
5913 uint8_t *cm_data = NULL;
5914 size_t cm_data_space = 0;
5918 *scm_rights_pipe_fd = -1;
5921 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5925 for (cmsg = CMSG_FIRSTHDR(msg_in);
5927 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5928 switch (cmsg->cmsg_level) {
5930 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5933 scm_rights_pipe_fd);
5937 rc = swrap_sendmsg_copy_cmsg(cmsg,
5943 int saved_errno = errno;
5945 errno = saved_errno;
5950 msg_tmp->msg_controllen = cm_data_space;
5951 msg_tmp->msg_control = cm_data;
5954 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5955 *msg_tmp = *_msg_in;
5957 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5960 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5962 int scm_rights_pipe_fd)
5964 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5965 int saved_errno = errno;
5966 SAFE_FREE(msg_tmp->msg_control);
5967 if (scm_rights_pipe_fd != -1) {
5968 libc_close(scm_rights_pipe_fd);
5970 errno = saved_errno;
5971 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5975 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5976 struct msghdr *msg_tmp,
5977 uint8_t **tmp_control)
5979 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5980 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
5981 uint8_t *cm_data = NULL;
5982 size_t cm_data_space = 0;
5985 *tmp_control = NULL;
5987 SWRAP_LOG(SWRAP_LOG_TRACE,
5988 "msg_in->msg_controllen=%zu",
5989 (size_t)msg_in->msg_controllen);
5992 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5997 * We need to give the kernel a bit more space in order
5998 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
5999 * swrap_recvmsg_after_unix() will hide it again.
6001 cm_data_space = msg_in->msg_controllen;
6002 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6003 cm_data_space += cm_extra_space;
6005 cm_data = calloc(1, cm_data_space);
6006 if (cm_data == NULL) {
6010 msg_tmp->msg_controllen = cm_data_space;
6011 msg_tmp->msg_control = cm_data;
6012 *tmp_control = cm_data;
6014 SWRAP_LOG(SWRAP_LOG_TRACE,
6015 "msg_tmp->msg_controllen=%zu",
6016 (size_t)msg_tmp->msg_controllen);
6018 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6020 *tmp_control = NULL;
6022 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6025 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6026 uint8_t **tmp_control,
6027 struct msghdr *msg_out,
6030 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6031 struct cmsghdr *cmsg = NULL;
6032 uint8_t *cm_data = NULL;
6033 size_t cm_data_space = 0;
6037 int saved_errno = errno;
6038 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6039 saved_errno, strerror(saved_errno));
6040 SAFE_FREE(*tmp_control);
6041 /* msg_out should not be touched on error */
6042 errno = saved_errno;
6046 SWRAP_LOG(SWRAP_LOG_TRACE,
6047 "msg_tmp->msg_controllen=%zu",
6048 (size_t)msg_tmp->msg_controllen);
6051 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6052 int saved_errno = errno;
6053 *msg_out = *msg_tmp;
6054 SAFE_FREE(*tmp_control);
6055 errno = saved_errno;
6059 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6061 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6062 switch (cmsg->cmsg_level) {
6064 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6070 rc = swrap_sendmsg_copy_cmsg(cmsg,
6076 int saved_errno = errno;
6078 SAFE_FREE(*tmp_control);
6079 errno = saved_errno;
6085 * msg_tmp->msg_control (*tmp_control) was created by
6086 * swrap_recvmsg_before_unix() and msg_out->msg_control
6087 * is still the buffer of the caller.
6089 msg_tmp->msg_control = msg_out->msg_control;
6090 msg_tmp->msg_controllen = msg_out->msg_controllen;
6091 *msg_out = *msg_tmp;
6093 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6094 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6095 msg_out->msg_controllen = cm_data_space;
6097 SAFE_FREE(*tmp_control);
6099 SWRAP_LOG(SWRAP_LOG_TRACE,
6100 "msg_out->msg_controllen=%zu",
6101 (size_t)msg_out->msg_controllen);
6103 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6104 int saved_errno = errno;
6105 *msg_out = *msg_tmp;
6106 SAFE_FREE(*tmp_control);
6107 errno = saved_errno;
6109 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6112 static ssize_t swrap_sendmsg_before(int fd,
6113 struct socket_info *si,
6115 struct iovec *tmp_iov,
6116 struct sockaddr_un *tmp_un,
6117 const struct sockaddr_un **to_un,
6118 const struct sockaddr **to,
6140 if (!si->connected) {
6145 if (msg->msg_iovlen == 0) {
6149 mtu = socket_wrapper_mtu();
6150 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6152 nlen = len + msg->msg_iov[i].iov_len;
6162 msg->msg_iovlen = i;
6163 if (msg->msg_iovlen == 0) {
6164 *tmp_iov = msg->msg_iov[0];
6165 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6167 msg->msg_iov = tmp_iov;
6168 msg->msg_iovlen = 1;
6173 if (si->connected) {
6174 if (msg->msg_name != NULL) {
6176 * We are dealing with unix sockets and if we
6177 * are connected, we should only talk to the
6178 * connected unix path. Using the fd to send
6179 * to another server would be hard to achieve.
6181 msg->msg_name = NULL;
6182 msg->msg_namelen = 0;
6185 const struct sockaddr *msg_name;
6186 msg_name = (const struct sockaddr *)msg->msg_name;
6188 if (msg_name == NULL) {
6194 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6206 msg->msg_name = tmp_un;
6207 msg->msg_namelen = sizeof(*tmp_un);
6210 if (si->bound == 0) {
6211 ret = swrap_auto_bind(fd, si, si->family);
6213 SWRAP_UNLOCK_SI(si);
6214 if (errno == ENOTSOCK) {
6215 swrap_remove_stale(fd);
6218 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6224 if (!si->defer_connect) {
6228 ret = sockaddr_convert_to_un(si,
6230 si->peername.sa_socklen,
6238 ret = libc_connect(fd,
6239 (struct sockaddr *)(void *)tmp_un,
6242 /* to give better errors */
6243 if (ret == -1 && errno == ENOENT) {
6244 errno = EHOSTUNREACH;
6251 si->defer_connect = 0;
6254 errno = EHOSTUNREACH;
6260 SWRAP_UNLOCK_SI(si);
6265 static void swrap_sendmsg_after(int fd,
6266 struct socket_info *si,
6268 const struct sockaddr *to,
6271 int saved_errno = errno;
6278 /* to give better errors */
6280 if (saved_errno == ENOENT) {
6281 saved_errno = EHOSTUNREACH;
6282 } else if (saved_errno == ENOTSOCK) {
6283 /* If the fd is not a socket, remove it */
6284 swrap_remove_stale(fd);
6288 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6289 avail += msg->msg_iov[i].iov_len;
6293 remain = MIN(80, avail);
6298 /* we capture it as one single packet */
6299 buf = (uint8_t *)malloc(remain);
6301 /* we just not capture the packet */
6302 errno = saved_errno;
6306 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6307 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6308 if (this_time > 0) {
6310 msg->msg_iov[i].iov_base,
6314 remain -= this_time;
6323 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6324 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6326 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6331 if (si->connected) {
6332 to = &si->peername.sa.s;
6335 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6336 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6338 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6343 SWRAP_UNLOCK_SI(si);
6346 errno = saved_errno;
6349 static int swrap_recvmsg_before(int fd,
6350 struct socket_info *si,
6352 struct iovec *tmp_iov)
6359 (void)fd; /* unused */
6364 if (!si->connected) {
6369 if (msg->msg_iovlen == 0) {
6373 mtu = socket_wrapper_mtu();
6374 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6376 nlen = len + msg->msg_iov[i].iov_len;
6381 msg->msg_iovlen = i;
6382 if (msg->msg_iovlen == 0) {
6383 *tmp_iov = msg->msg_iov[0];
6384 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6386 msg->msg_iov = tmp_iov;
6387 msg->msg_iovlen = 1;
6392 if (msg->msg_name == NULL) {
6397 if (msg->msg_iovlen == 0) {
6401 if (si->bound == 0) {
6402 ret = swrap_auto_bind(fd, si, si->family);
6404 SWRAP_UNLOCK_SI(si);
6406 * When attempting to read or write to a
6407 * descriptor, if an underlying autobind fails
6408 * because it's not a socket, stop intercepting
6409 * uses of that descriptor.
6411 if (errno == ENOTSOCK) {
6412 swrap_remove_stale(fd);
6415 SWRAP_LOG(SWRAP_LOG_ERROR,
6416 "swrap_recvmsg_before failed");
6423 errno = EHOSTUNREACH;
6429 SWRAP_UNLOCK_SI(si);
6434 static int swrap_recvmsg_after(int fd,
6435 struct socket_info *si,
6437 const struct sockaddr_un *un_addr,
6438 socklen_t un_addrlen,
6441 int saved_errno = errno;
6443 uint8_t *buf = NULL;
6449 /* to give better errors */
6451 if (saved_errno == ENOENT) {
6452 saved_errno = EHOSTUNREACH;
6453 } else if (saved_errno == ENOTSOCK) {
6454 /* If the fd is not a socket, remove it */
6455 swrap_remove_stale(fd);
6459 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6460 avail += msg->msg_iov[i].iov_len;
6465 /* Convert the socket address before we leave */
6466 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6467 rc = sockaddr_convert_from_un(si,
6484 remain = MIN(80, avail);
6489 /* we capture it as one single packet */
6490 buf = (uint8_t *)malloc(remain);
6492 /* we just not capture the packet */
6493 SWRAP_UNLOCK_SI(si);
6494 errno = saved_errno;
6498 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6499 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6501 msg->msg_iov[i].iov_base,
6504 remain -= this_time;
6509 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6510 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6511 } else if (ret == 0) { /* END OF FILE */
6512 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6513 } else if (ret > 0) {
6514 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6523 if (un_addr != NULL) {
6524 swrap_pcap_dump_packet(si,
6530 swrap_pcap_dump_packet(si,
6543 errno = saved_errno;
6545 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6547 msg->msg_controllen > 0 &&
6548 msg->msg_control != NULL) {
6549 rc = swrap_msghdr_add_socket_info(si, msg);
6551 SWRAP_UNLOCK_SI(si);
6557 SWRAP_UNLOCK_SI(si);
6561 /****************************************************************************
6563 ***************************************************************************/
6565 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6566 struct sockaddr *from, socklen_t *fromlen)
6568 struct swrap_address from_addr = {
6569 .sa_socklen = sizeof(struct sockaddr_un),
6572 struct socket_info *si = find_socket_info(s);
6573 struct swrap_address saddr = {
6574 .sa_socklen = sizeof(struct sockaddr_storage),
6581 return libc_recvfrom(s,
6593 if (from != NULL && fromlen != NULL) {
6594 msg.msg_name = from; /* optional address */
6595 msg.msg_namelen = *fromlen; /* size of address */
6597 msg.msg_name = &saddr.sa.s; /* optional address */
6598 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6600 msg.msg_iov = &tmp; /* scatter/gather array */
6601 msg.msg_iovlen = 1; /* # elements in msg_iov */
6602 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6603 msg.msg_control = NULL; /* ancillary data, see below */
6604 msg.msg_controllen = 0; /* ancillary data buffer len */
6605 msg.msg_flags = 0; /* flags on received message */
6608 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6613 buf = msg.msg_iov[0].iov_base;
6614 len = msg.msg_iov[0].iov_len;
6616 ret = libc_recvfrom(s,
6621 &from_addr.sa_socklen);
6626 tret = swrap_recvmsg_after(s,
6630 from_addr.sa_socklen,
6636 if (from != NULL && fromlen != NULL) {
6637 *fromlen = msg.msg_namelen;
6643 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6644 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6645 struct sockaddr *from, Psocklen_t fromlen)
6647 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6648 struct sockaddr *from, socklen_t *fromlen)
6651 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6654 /****************************************************************************
6656 ***************************************************************************/
6658 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6659 const struct sockaddr *to, socklen_t tolen)
6663 struct swrap_address un_addr = {
6664 .sa_socklen = sizeof(struct sockaddr_un),
6666 const struct sockaddr_un *to_un = NULL;
6669 struct socket_info *si = find_socket_info(s);
6673 return libc_sendto(s, buf, len, flags, to, tolen);
6676 tmp.iov_base = discard_const_p(char, buf);
6680 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6681 msg.msg_namelen = tolen; /* size of address */
6682 msg.msg_iov = &tmp; /* scatter/gather array */
6683 msg.msg_iovlen = 1; /* # elements in msg_iov */
6684 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6685 msg.msg_control = NULL; /* ancillary data, see below */
6686 msg.msg_controllen = 0; /* ancillary data buffer len */
6687 msg.msg_flags = 0; /* flags on received message */
6690 rc = swrap_sendmsg_before(s,
6702 buf = msg.msg_iov[0].iov_base;
6703 len = msg.msg_iov[0].iov_len;
6708 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6710 char *swrap_dir = NULL;
6712 type = SOCKET_TYPE_CHAR_UDP;
6714 swrap_dir = socket_wrapper_dir();
6715 if (swrap_dir == NULL) {
6719 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6720 swrap_un_path(&un_addr.sa.un,
6725 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6727 /* ignore the any errors in broadcast sends */
6733 un_addr.sa_socklen);
6736 SAFE_FREE(swrap_dir);
6740 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6742 SWRAP_UNLOCK_SI(si);
6749 * If it is a dgram socket and we are connected, don't include the
6752 if (si->type == SOCK_DGRAM && si->connected) {
6753 ret = libc_sendto(s,
6760 ret = libc_sendto(s,
6764 (struct sockaddr *)msg.msg_name,
6768 SWRAP_UNLOCK_SI(si);
6770 swrap_sendmsg_after(s, si, &msg, to, ret);
6775 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6776 const struct sockaddr *to, socklen_t tolen)
6778 return swrap_sendto(s, buf, len, flags, to, tolen);
6781 /****************************************************************************
6783 ***************************************************************************/
6785 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6787 struct socket_info *si;
6789 struct swrap_address saddr = {
6790 .sa_socklen = sizeof(struct sockaddr_storage),
6796 si = find_socket_info(s);
6798 return libc_recv(s, buf, len, flags);
6805 msg.msg_name = &saddr.sa.s; /* optional address */
6806 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6807 msg.msg_iov = &tmp; /* scatter/gather array */
6808 msg.msg_iovlen = 1; /* # elements in msg_iov */
6809 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6810 msg.msg_control = NULL; /* ancillary data, see below */
6811 msg.msg_controllen = 0; /* ancillary data buffer len */
6812 msg.msg_flags = 0; /* flags on received message */
6815 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6820 buf = msg.msg_iov[0].iov_base;
6821 len = msg.msg_iov[0].iov_len;
6823 ret = libc_recv(s, buf, len, flags);
6825 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6833 ssize_t recv(int s, void *buf, size_t len, int flags)
6835 return swrap_recv(s, buf, len, flags);
6838 /****************************************************************************
6840 ***************************************************************************/
6842 static ssize_t swrap_read(int s, void *buf, size_t len)
6844 struct socket_info *si;
6847 struct swrap_address saddr = {
6848 .sa_socklen = sizeof(struct sockaddr_storage),
6853 si = find_socket_info(s);
6855 return libc_read(s, buf, len);
6862 msg.msg_name = &saddr.sa.ss; /* optional address */
6863 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6864 msg.msg_iov = &tmp; /* scatter/gather array */
6865 msg.msg_iovlen = 1; /* # elements in msg_iov */
6866 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6867 msg.msg_control = NULL; /* ancillary data, see below */
6868 msg.msg_controllen = 0; /* ancillary data buffer len */
6869 msg.msg_flags = 0; /* flags on received message */
6872 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6874 if (tret == -ENOTSOCK) {
6875 return libc_read(s, buf, len);
6880 buf = msg.msg_iov[0].iov_base;
6881 len = msg.msg_iov[0].iov_len;
6883 ret = libc_read(s, buf, len);
6885 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6893 ssize_t read(int s, void *buf, size_t len)
6895 return swrap_read(s, buf, len);
6898 /****************************************************************************
6900 ***************************************************************************/
6902 static ssize_t swrap_write(int s, const void *buf, size_t len)
6906 struct sockaddr_un un_addr;
6909 struct socket_info *si;
6911 si = find_socket_info(s);
6913 return libc_write(s, buf, len);
6916 tmp.iov_base = discard_const_p(char, buf);
6920 msg.msg_name = NULL; /* optional address */
6921 msg.msg_namelen = 0; /* size of address */
6922 msg.msg_iov = &tmp; /* scatter/gather array */
6923 msg.msg_iovlen = 1; /* # elements in msg_iov */
6924 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6925 msg.msg_control = NULL; /* ancillary data, see below */
6926 msg.msg_controllen = 0; /* ancillary data buffer len */
6927 msg.msg_flags = 0; /* flags on received message */
6930 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6935 buf = msg.msg_iov[0].iov_base;
6936 len = msg.msg_iov[0].iov_len;
6938 ret = libc_write(s, buf, len);
6940 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6945 ssize_t write(int s, const void *buf, size_t len)
6947 return swrap_write(s, buf, len);
6950 /****************************************************************************
6952 ***************************************************************************/
6954 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6958 struct sockaddr_un un_addr;
6961 struct socket_info *si = find_socket_info(s);
6964 return libc_send(s, buf, len, flags);
6967 tmp.iov_base = discard_const_p(char, buf);
6971 msg.msg_name = NULL; /* optional address */
6972 msg.msg_namelen = 0; /* size of address */
6973 msg.msg_iov = &tmp; /* scatter/gather array */
6974 msg.msg_iovlen = 1; /* # elements in msg_iov */
6975 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6976 msg.msg_control = NULL; /* ancillary data, see below */
6977 msg.msg_controllen = 0; /* ancillary data buffer len */
6978 msg.msg_flags = 0; /* flags on received message */
6981 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6986 buf = msg.msg_iov[0].iov_base;
6987 len = msg.msg_iov[0].iov_len;
6989 ret = libc_send(s, buf, len, flags);
6991 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6996 ssize_t send(int s, const void *buf, size_t len, int flags)
6998 return swrap_send(s, buf, len, flags);
7001 /****************************************************************************
7003 ***************************************************************************/
7005 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7007 struct swrap_address from_addr = {
7008 .sa_socklen = sizeof(struct sockaddr_un),
7010 struct swrap_address convert_addr = {
7011 .sa_socklen = sizeof(struct sockaddr_storage),
7013 struct socket_info *si;
7016 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7017 size_t msg_ctrllen_filled;
7018 size_t msg_ctrllen_left;
7024 si = find_socket_info(s);
7026 uint8_t *tmp_control = NULL;
7027 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7031 ret = libc_recvmsg(s, &msg, flags);
7032 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7035 tmp.iov_base = NULL;
7039 msg.msg_name = &from_addr.sa; /* optional address */
7040 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7041 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7042 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7043 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7044 msg_ctrllen_filled = 0;
7045 msg_ctrllen_left = omsg->msg_controllen;
7047 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7048 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7049 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7052 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7057 ret = libc_recvmsg(s, &msg, flags);
7059 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7060 msg_ctrllen_filled += msg.msg_controllen;
7061 msg_ctrllen_left -= msg.msg_controllen;
7063 if (omsg->msg_control != NULL) {
7066 p = omsg->msg_control;
7067 p += msg_ctrllen_filled;
7069 msg.msg_control = p;
7070 msg.msg_controllen = msg_ctrllen_left;
7072 msg.msg_control = NULL;
7073 msg.msg_controllen = 0;
7078 * We convert the unix address to a IP address so we need a buffer
7079 * which can store the address in case of SOCK_DGRAM, see below.
7081 msg.msg_name = &convert_addr.sa;
7082 msg.msg_namelen = convert_addr.sa_socklen;
7084 rc = swrap_recvmsg_after(s,
7088 from_addr.sa_socklen,
7094 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7095 if (omsg->msg_control != NULL) {
7096 /* msg.msg_controllen = space left */
7097 msg_ctrllen_left = msg.msg_controllen;
7098 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7101 /* Update the original message length */
7102 omsg->msg_controllen = msg_ctrllen_filled;
7103 omsg->msg_flags = msg.msg_flags;
7105 omsg->msg_iovlen = msg.msg_iovlen;
7112 * The msg_name field points to a caller-allocated buffer that is
7113 * used to return the source address if the socket is unconnected. The
7114 * caller should set msg_namelen to the size of this buffer before this
7115 * call; upon return from a successful call, msg_name will contain the
7116 * length of the returned address. If the application does not need
7117 * to know the source address, msg_name can be specified as NULL.
7119 if (si->type == SOCK_STREAM) {
7120 omsg->msg_namelen = 0;
7121 } else if (omsg->msg_name != NULL &&
7122 omsg->msg_namelen != 0 &&
7123 omsg->msg_namelen >= msg.msg_namelen) {
7124 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7125 omsg->msg_namelen = msg.msg_namelen;
7128 SWRAP_UNLOCK_SI(si);
7133 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7135 return swrap_recvmsg(sockfd, msg, flags);
7138 /****************************************************************************
7140 ***************************************************************************/
7142 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7146 struct sockaddr_un un_addr;
7147 const struct sockaddr_un *to_un = NULL;
7148 const struct sockaddr *to = NULL;
7151 struct socket_info *si = find_socket_info(s);
7155 int scm_rights_pipe_fd = -1;
7157 rc = swrap_sendmsg_before_unix(omsg, &msg,
7158 &scm_rights_pipe_fd);
7162 ret = libc_sendmsg(s, &msg, flags);
7163 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7166 ZERO_STRUCT(un_addr);
7168 tmp.iov_base = NULL;
7175 if (si->connected == 0) {
7176 msg.msg_name = omsg->msg_name; /* optional address */
7177 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7179 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7180 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7182 SWRAP_UNLOCK_SI(si);
7184 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7185 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7186 uint8_t *cmbuf = NULL;
7189 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7195 msg.msg_controllen = 0;
7196 msg.msg_control = NULL;
7198 msg.msg_control = cmbuf;
7199 msg.msg_controllen = cmlen;
7202 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7204 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7206 int saved_errno = errno;
7207 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7208 SAFE_FREE(msg.msg_control);
7210 errno = saved_errno;
7217 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7224 char *swrap_dir = NULL;
7226 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7227 avail += msg.msg_iov[i].iov_len;
7233 /* we capture it as one single packet */
7234 buf = (uint8_t *)malloc(remain);
7236 int saved_errno = errno;
7237 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7238 SAFE_FREE(msg.msg_control);
7240 errno = saved_errno;
7244 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7245 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7247 msg.msg_iov[i].iov_base,
7250 remain -= this_time;
7253 type = SOCKET_TYPE_CHAR_UDP;
7255 swrap_dir = socket_wrapper_dir();
7256 if (swrap_dir == NULL) {
7257 int saved_errno = errno;
7258 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7259 SAFE_FREE(msg.msg_control);
7262 errno = saved_errno;
7266 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7267 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7268 if (stat(un_addr.sun_path, &st) != 0) continue;
7270 msg.msg_name = &un_addr; /* optional address */
7271 msg.msg_namelen = sizeof(un_addr); /* size of address */
7273 /* ignore the any errors in broadcast sends */
7274 libc_sendmsg(s, &msg, flags);
7277 SAFE_FREE(swrap_dir);
7281 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7284 SWRAP_UNLOCK_SI(si);
7289 ret = libc_sendmsg(s, &msg, flags);
7291 swrap_sendmsg_after(s, si, &msg, to, ret);
7293 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7295 int saved_errno = errno;
7296 SAFE_FREE(msg.msg_control);
7297 errno = saved_errno;
7304 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7306 return swrap_sendmsg(s, omsg, flags);
7309 /****************************************************************************
7311 ***************************************************************************/
7313 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7315 struct socket_info *si;
7318 struct swrap_address saddr = {
7319 .sa_socklen = sizeof(struct sockaddr_storage)
7324 si = find_socket_info(s);
7326 return libc_readv(s, vector, count);
7329 tmp.iov_base = NULL;
7333 msg.msg_name = &saddr.sa.s; /* optional address */
7334 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7335 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7336 msg.msg_iovlen = count; /* # elements in msg_iov */
7337 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7338 msg.msg_control = NULL; /* ancillary data, see below */
7339 msg.msg_controllen = 0; /* ancillary data buffer len */
7340 msg.msg_flags = 0; /* flags on received message */
7343 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7345 if (rc == -ENOTSOCK) {
7346 return libc_readv(s, vector, count);
7351 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7353 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7361 ssize_t readv(int s, const struct iovec *vector, int count)
7363 return swrap_readv(s, vector, count);
7366 /****************************************************************************
7368 ***************************************************************************/
7370 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7374 struct sockaddr_un un_addr;
7377 struct socket_info *si = find_socket_info(s);
7380 return libc_writev(s, vector, count);
7383 tmp.iov_base = NULL;
7387 msg.msg_name = NULL; /* optional address */
7388 msg.msg_namelen = 0; /* size of address */
7389 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7390 msg.msg_iovlen = count; /* # elements in msg_iov */
7391 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7392 msg.msg_control = NULL; /* ancillary data, see below */
7393 msg.msg_controllen = 0; /* ancillary data buffer len */
7394 msg.msg_flags = 0; /* flags on received message */
7397 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7399 if (rc == -ENOTSOCK) {
7400 return libc_readv(s, vector, count);
7405 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7407 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7412 ssize_t writev(int s, const struct iovec *vector, int count)
7414 return swrap_writev(s, vector, count);
7417 /****************************
7419 ***************************/
7421 static int swrap_remove_wrapper(const char *__func_name,
7422 int (*__close_fd_fn)(int fd),
7425 struct socket_info *si = NULL;
7427 int ret_errno = errno;
7430 swrap_mutex_lock(&socket_reset_mutex);
7432 si_index = find_socket_info_index(fd);
7433 if (si_index == -1) {
7434 swrap_mutex_unlock(&socket_reset_mutex);
7435 return __close_fd_fn(fd);
7438 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
7439 reset_socket_info_index(fd);
7441 si = swrap_get_socket_info(si_index);
7443 swrap_mutex_lock(&first_free_mutex);
7446 ret = __close_fd_fn(fd);
7451 swrap_dec_refcount(si);
7453 if (swrap_get_refcount(si) > 0) {
7454 /* there are still references left */
7458 if (si->fd_passed) {
7462 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7463 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7466 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7467 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7468 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7471 if (si->un_addr.sun_path[0] != '\0') {
7472 unlink(si->un_addr.sun_path);
7476 swrap_set_next_free(si, first_free);
7477 first_free = si_index;
7480 SWRAP_UNLOCK_SI(si);
7481 swrap_mutex_unlock(&first_free_mutex);
7482 swrap_mutex_unlock(&socket_reset_mutex);
7488 static int swrap_noop_close(int fd)
7490 (void)fd; /* unused */
7494 static void swrap_remove_stale(int fd)
7496 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7500 * This allows socket_wrapper aware applications to
7501 * indicate that the given fd does not belong to
7504 * We already overload a lot of unrelated functions
7505 * like eventfd(), timerfd_create(), ... in order to
7506 * call swrap_remove_stale() on the returned fd, but
7507 * we'll never be able to handle all possible syscalls.
7509 * socket_wrapper_indicate_no_inet_fd() gives them a way
7512 * We don't export swrap_remove_stale() in order to
7513 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
7516 void socket_wrapper_indicate_no_inet_fd(int fd)
7518 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7521 static int swrap_close(int fd)
7523 return swrap_remove_wrapper(__func__, libc_close, fd);
7528 return swrap_close(fd);
7531 #ifdef HAVE___CLOSE_NOCANCEL
7533 static int swrap___close_nocancel(int fd)
7535 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
7538 int __close_nocancel(int fd);
7539 int __close_nocancel(int fd)
7541 return swrap___close_nocancel(fd);
7544 #endif /* HAVE___CLOSE_NOCANCEL */
7546 /****************************
7548 ***************************/
7550 static int swrap_dup(int fd)
7552 struct socket_info *si;
7555 idx = find_socket_info_index(fd);
7557 return libc_dup(fd);
7560 si = swrap_get_socket_info(idx);
7562 dup_fd = libc_dup(fd);
7564 int saved_errno = errno;
7565 errno = saved_errno;
7569 if ((size_t)dup_fd >= socket_fds_max) {
7570 SWRAP_LOG(SWRAP_LOG_ERROR,
7571 "The max socket index limit of %zu has been reached, "
7582 swrap_inc_refcount(si);
7584 SWRAP_UNLOCK_SI(si);
7586 /* Make sure we don't have an entry for the fd */
7587 swrap_remove_stale(dup_fd);
7589 set_socket_info_index(dup_fd, idx);
7596 return swrap_dup(fd);
7599 /****************************
7601 ***************************/
7603 static int swrap_dup2(int fd, int newfd)
7605 struct socket_info *si;
7608 idx = find_socket_info_index(fd);
7610 return libc_dup2(fd, newfd);
7613 si = swrap_get_socket_info(idx);
7617 * According to the manpage:
7619 * "If oldfd is a valid file descriptor, and newfd has the same
7620 * value as oldfd, then dup2() does nothing, and returns newfd."
7625 if ((size_t)newfd >= socket_fds_max) {
7626 SWRAP_LOG(SWRAP_LOG_ERROR,
7627 "The max socket index limit of %zu has been reached, "
7635 if (find_socket_info(newfd)) {
7636 /* dup2() does an implicit close of newfd, which we
7637 * need to emulate */
7641 dup_fd = libc_dup2(fd, newfd);
7643 int saved_errno = errno;
7644 errno = saved_errno;
7650 swrap_inc_refcount(si);
7652 SWRAP_UNLOCK_SI(si);
7654 /* Make sure we don't have an entry for the fd */
7655 swrap_remove_stale(dup_fd);
7657 set_socket_info_index(dup_fd, idx);
7662 int dup2(int fd, int newfd)
7664 return swrap_dup2(fd, newfd);
7667 /****************************
7669 ***************************/
7671 static int swrap_vfcntl(int fd, int cmd, va_list va)
7673 struct socket_info *si;
7674 int rc, dup_fd, idx;
7676 idx = find_socket_info_index(fd);
7678 return libc_vfcntl(fd, cmd, va);
7681 si = swrap_get_socket_info(idx);
7685 dup_fd = libc_vfcntl(fd, cmd, va);
7687 int saved_errno = errno;
7688 errno = saved_errno;
7692 /* Make sure we don't have an entry for the fd */
7693 swrap_remove_stale(dup_fd);
7695 if ((size_t)dup_fd >= socket_fds_max) {
7696 SWRAP_LOG(SWRAP_LOG_ERROR,
7697 "The max socket index limit of %zu has been reached, "
7708 swrap_inc_refcount(si);
7710 SWRAP_UNLOCK_SI(si);
7713 set_socket_info_index(dup_fd, idx);
7718 rc = libc_vfcntl(fd, cmd, va);
7725 int fcntl(int fd, int cmd, ...)
7732 rc = swrap_vfcntl(fd, cmd, va);
7739 /****************************
7741 ***************************/
7744 static int swrap_eventfd(int count, int flags)
7748 fd = libc_eventfd(count, flags);
7750 swrap_remove_stale(fd);
7756 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7757 int eventfd(unsigned int count, int flags)
7759 int eventfd(int count, int flags)
7762 return swrap_eventfd(count, flags);
7767 int pledge(const char *promises, const char *paths[])
7769 (void)promises; /* unused */
7770 (void)paths; /* unused */
7774 #endif /* HAVE_PLEDGE */
7776 static void swrap_thread_prepare(void)
7779 * This function should only be called here!!
7781 * We bind all symobls to avoid deadlocks of the fork is
7782 * interrupted by a signal handler using a symbol of this
7785 swrap_bind_symbol_all();
7790 static void swrap_thread_parent(void)
7795 static void swrap_thread_child(void)
7800 /****************************
7802 ***************************/
7803 void swrap_constructor(void)
7805 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7806 SWRAP_LOG(SWRAP_LOG_ERROR,
7808 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7809 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7810 "sizeof(struct socket_info)=%zu",
7812 sizeof(struct swrap_unix_scm_rights),
7813 sizeof(struct swrap_unix_scm_rights_payload),
7814 sizeof(struct socket_info));
7821 * If we hold a lock and the application forks, then the child
7822 * is not able to unlock the mutex and we are in a deadlock.
7823 * This should prevent such deadlocks.
7825 pthread_atfork(&swrap_thread_prepare,
7826 &swrap_thread_parent,
7827 &swrap_thread_child);
7830 /****************************
7832 ***************************/
7835 * This function is called when the library is unloaded and makes sure that
7836 * sockets get closed and the unix file for the socket are unlinked.
7838 void swrap_destructor(void)
7842 if (socket_fds_idx != NULL) {
7843 for (i = 0; i < socket_fds_max; ++i) {
7844 if (socket_fds_idx[i] != -1) {
7848 SAFE_FREE(socket_fds_idx);
7853 if (swrap.libc.handle != NULL
7855 && swrap.libc.handle != RTLD_NEXT
7858 dlclose(swrap.libc.handle);
7860 if (swrap.libc.socket_handle
7862 && swrap.libc.socket_handle != RTLD_NEXT
7865 dlclose(swrap.libc.socket_handle);
7869 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7871 * On FreeBSD 12 (and maybe other platforms)
7872 * system libraries like libresolv prefix there
7873 * syscalls with '_' in order to always use
7874 * the symbols from libc.
7876 * In the interaction with resolv_wrapper,
7877 * we need to inject socket wrapper into libresolv,
7878 * which means we need to private all socket
7879 * related syscalls also with the '_' prefix.
7881 * This is tested in Samba's 'make test',
7882 * there we noticed that providing '_read',
7883 * '_open' and '_close' would cause errors, which
7884 * means we skip '_read', '_write' and
7885 * all non socket related calls without
7886 * further analyzing the problem.
7888 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7889 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7892 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7894 SWRAP_SYMBOL_ALIAS(accept, _accept);
7895 SWRAP_SYMBOL_ALIAS(bind, _bind);
7896 SWRAP_SYMBOL_ALIAS(connect, _connect);
7897 SWRAP_SYMBOL_ALIAS(dup, _dup);
7898 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7899 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7900 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7901 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7902 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7903 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7904 SWRAP_SYMBOL_ALIAS(listen, _listen);
7905 SWRAP_SYMBOL_ALIAS(readv, _readv);
7906 SWRAP_SYMBOL_ALIAS(recv, _recv);
7907 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7908 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7909 SWRAP_SYMBOL_ALIAS(send, _send);
7910 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7911 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7912 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7913 SWRAP_SYMBOL_ALIAS(socket, _socket);
7914 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7915 SWRAP_SYMBOL_ALIAS(writev, _writev);
7917 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */