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 int libc_vopen(const char *pathname, int flags, va_list ap)
992 swrap_bind_symbol_all();
994 if (flags & O_CREAT) {
995 mode = va_arg(ap, int);
997 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
1002 static int libc_open(const char *pathname, int flags, ...)
1007 va_start(ap, flags);
1008 fd = libc_vopen(pathname, flags, ap);
1015 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1020 swrap_bind_symbol_all();
1022 if (flags & O_CREAT) {
1023 mode = va_arg(ap, int);
1025 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1029 #endif /* HAVE_OPEN64 */
1031 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1036 swrap_bind_symbol_all();
1038 if (flags & O_CREAT) {
1039 mode = va_arg(ap, int);
1041 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1050 static int libc_openat(int dirfd, const char *path, int flags, ...)
1055 va_start(ap, flags);
1056 fd = libc_vopenat(dirfd, path, flags, ap);
1063 static int libc_pipe(int pipefd[2])
1065 swrap_bind_symbol_all();
1067 return swrap.libc.symbols._libc_pipe.f(pipefd);
1070 static int libc_read(int fd, void *buf, size_t count)
1072 swrap_bind_symbol_all();
1074 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1077 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1079 swrap_bind_symbol_all();
1081 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1084 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1086 swrap_bind_symbol_all();
1088 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1091 static int libc_recvfrom(int sockfd,
1095 struct sockaddr *src_addr,
1098 swrap_bind_symbol_all();
1100 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1108 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1110 swrap_bind_symbol_all();
1112 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1115 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1117 swrap_bind_symbol_all();
1119 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1122 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1124 swrap_bind_symbol_all();
1126 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1129 static int libc_sendto(int sockfd,
1133 const struct sockaddr *dst_addr,
1136 swrap_bind_symbol_all();
1138 return swrap.libc.symbols._libc_sendto.f(sockfd,
1146 static int libc_setsockopt(int sockfd,
1152 swrap_bind_symbol_all();
1154 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1161 #ifdef HAVE_SIGNALFD
1162 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1164 swrap_bind_symbol_all();
1166 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1170 static int libc_socket(int domain, int type, int protocol)
1172 swrap_bind_symbol_all();
1174 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1177 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1179 swrap_bind_symbol_all();
1181 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1184 #ifdef HAVE_TIMERFD_CREATE
1185 static int libc_timerfd_create(int clockid, int flags)
1187 swrap_bind_symbol_all();
1189 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1193 static ssize_t libc_write(int fd, const void *buf, size_t count)
1195 swrap_bind_symbol_all();
1197 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1200 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1202 swrap_bind_symbol_all();
1204 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1207 /* DO NOT call this function during library initialization! */
1208 static void __swrap_bind_symbol_all_once(void)
1211 swrap_bind_symbol_libsocket(accept4);
1213 swrap_bind_symbol_libsocket(accept);
1215 swrap_bind_symbol_libsocket(bind);
1216 swrap_bind_symbol_libc(close);
1217 #ifdef HAVE___CLOSE_NOCANCEL
1218 swrap_bind_symbol_libc(__close_nocancel);
1220 swrap_bind_symbol_libsocket(connect);
1221 swrap_bind_symbol_libc(dup);
1222 swrap_bind_symbol_libc(dup2);
1223 swrap_bind_symbol_libc(fcntl);
1224 swrap_bind_symbol_libc(fopen);
1226 swrap_bind_symbol_libc(fopen64);
1229 swrap_bind_symbol_libc(eventfd);
1231 swrap_bind_symbol_libsocket(getpeername);
1232 swrap_bind_symbol_libsocket(getsockname);
1233 swrap_bind_symbol_libsocket(getsockopt);
1234 swrap_bind_symbol_libc(ioctl);
1235 swrap_bind_symbol_libsocket(listen);
1236 swrap_bind_symbol_libc(open);
1238 swrap_bind_symbol_libc(open64);
1240 swrap_bind_symbol_libc(openat);
1241 swrap_bind_symbol_libsocket(pipe);
1242 swrap_bind_symbol_libc(read);
1243 swrap_bind_symbol_libsocket(readv);
1244 swrap_bind_symbol_libsocket(recv);
1245 swrap_bind_symbol_libsocket(recvfrom);
1246 swrap_bind_symbol_libsocket(recvmsg);
1247 swrap_bind_symbol_libsocket(send);
1248 swrap_bind_symbol_libsocket(sendmsg);
1249 swrap_bind_symbol_libsocket(sendto);
1250 swrap_bind_symbol_libsocket(setsockopt);
1251 #ifdef HAVE_SIGNALFD
1252 swrap_bind_symbol_libsocket(signalfd);
1254 swrap_bind_symbol_libsocket(socket);
1255 swrap_bind_symbol_libsocket(socketpair);
1256 #ifdef HAVE_TIMERFD_CREATE
1257 swrap_bind_symbol_libc(timerfd_create);
1259 swrap_bind_symbol_libc(write);
1260 swrap_bind_symbol_libsocket(writev);
1263 static void swrap_bind_symbol_all(void)
1265 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1267 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1270 /*********************************************************
1271 * SWRAP HELPER FUNCTIONS
1272 *********************************************************/
1275 * We return 127.0.0.0 (default) or 10.53.57.0.
1277 * This can be controlled by:
1278 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1280 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1282 static in_addr_t swrap_ipv4_net(void)
1284 static int initialized;
1285 static in_addr_t hv;
1286 const char *net_str = NULL;
1295 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1296 if (net_str == NULL) {
1297 net_str = "127.0.0.0";
1300 ret = inet_pton(AF_INET, net_str, &nv);
1302 SWRAP_LOG(SWRAP_LOG_ERROR,
1303 "INVALID IPv4 Network [%s]",
1308 hv = ntohl(nv.s_addr);
1318 SWRAP_LOG(SWRAP_LOG_ERROR,
1319 "INVALID IPv4 Network [%s][0x%x] should be "
1320 "127.0.0.0 or 10.53.57.0",
1321 net_str, (unsigned)hv);
1329 * This returns 127.255.255.255 or 10.255.255.255
1331 static in_addr_t swrap_ipv4_bcast(void)
1335 hv = swrap_ipv4_net();
1336 hv |= IN_CLASSA_HOST;
1342 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1344 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1348 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1349 SWRAP_LOG(SWRAP_LOG_ERROR,
1350 "swrap_ipv4_iface(%u) invalid!",
1356 hv = swrap_ipv4_net();
1366 static const struct in6_addr *swrap_ipv6(void)
1368 static struct in6_addr v;
1369 static int initialized;
1377 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1386 static void set_port(int family, int prt, struct swrap_address *addr)
1390 addr->sa.in.sin_port = htons(prt);
1394 addr->sa.in6.sin6_port = htons(prt);
1400 static size_t socket_length(int family)
1404 return sizeof(struct sockaddr_in);
1407 return sizeof(struct sockaddr_in6);
1413 static struct socket_info *swrap_get_socket_info(int si_index)
1415 return (struct socket_info *)(&(sockets[si_index].info));
1418 static int swrap_get_refcount(struct socket_info *si)
1420 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1421 return sic->meta.refcount;
1424 static void swrap_inc_refcount(struct socket_info *si)
1426 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1428 sic->meta.refcount += 1;
1431 static void swrap_dec_refcount(struct socket_info *si)
1433 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1435 sic->meta.refcount -= 1;
1438 static int swrap_get_next_free(struct socket_info *si)
1440 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1442 return sic->meta.next_free;
1445 static void swrap_set_next_free(struct socket_info *si, int next_free)
1447 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1449 sic->meta.next_free = next_free;
1452 static int swrap_un_path(struct sockaddr_un *un,
1453 const char *swrap_dir,
1460 ret = snprintf(un->sun_path,
1461 sizeof(un->sun_path),
1467 if ((size_t)ret >= sizeof(un->sun_path)) {
1468 return ENAMETOOLONG;
1474 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1475 const char *swrap_dir)
1479 ret = snprintf(un->sun_path,
1480 sizeof(un->sun_path),
1484 if ((size_t)ret >= sizeof(un->sun_path)) {
1485 return ENAMETOOLONG;
1491 static bool swrap_dir_usable(const char *swrap_dir)
1493 struct sockaddr_un un;
1496 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1501 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1509 static char *socket_wrapper_dir(void)
1511 char *swrap_dir = NULL;
1512 char *s = getenv("SOCKET_WRAPPER_DIR");
1516 if (s == NULL || s[0] == '\0') {
1517 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1521 swrap_dir = realpath(s, NULL);
1522 if (swrap_dir == NULL) {
1523 SWRAP_LOG(SWRAP_LOG_ERROR,
1524 "Unable to resolve socket_wrapper dir path: %s - %s",
1530 ok = swrap_dir_usable(swrap_dir);
1537 ok = swrap_dir_usable(s);
1539 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1543 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1545 SWRAP_LOG(SWRAP_LOG_ERROR,
1546 "realpath(SOCKET_WRAPPER_DIR) too long and "
1547 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1552 swrap_dir = strdup(s);
1553 if (swrap_dir == NULL) {
1554 SWRAP_LOG(SWRAP_LOG_ERROR,
1555 "Unable to duplicate socket_wrapper dir path");
1559 SWRAP_LOG(SWRAP_LOG_WARN,
1560 "realpath(SOCKET_WRAPPER_DIR) too long, "
1561 "using original SOCKET_WRAPPER_DIR\n");
1564 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1568 static unsigned int socket_wrapper_mtu(void)
1570 static unsigned int max_mtu = 0;
1575 swrap_mutex_lock(&mtu_update_mutex);
1581 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1583 s = getenv("SOCKET_WRAPPER_MTU");
1588 tmp = strtol(s, &endp, 10);
1593 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1599 swrap_mutex_unlock(&mtu_update_mutex);
1603 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1605 pthread_mutexattr_t ma;
1606 bool need_destroy = false;
1609 #define __CHECK(cmd) do { \
1612 SWRAP_LOG(SWRAP_LOG_ERROR, \
1613 "%s: %s - failed %d", \
1619 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1620 __CHECK(pthread_mutexattr_init(&ma));
1621 need_destroy = true;
1622 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1623 __CHECK(pthread_mutex_init(m, &ma));
1626 pthread_mutexattr_destroy(&ma);
1631 static size_t socket_wrapper_max_sockets(void)
1637 if (socket_info_max != 0) {
1638 return socket_info_max;
1641 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1643 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1644 if (s == NULL || s[0] == '\0') {
1648 tmp = strtoul(s, &endp, 10);
1653 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1654 SWRAP_LOG(SWRAP_LOG_ERROR,
1655 "Invalid number of sockets specified, "
1656 "using default (%zu)",
1660 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1661 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1662 SWRAP_LOG(SWRAP_LOG_ERROR,
1663 "Invalid number of sockets specified, "
1664 "using maximum (%zu).",
1668 socket_info_max = tmp;
1671 return socket_info_max;
1674 static void socket_wrapper_init_fds_idx(void)
1679 if (socket_fds_idx != NULL) {
1683 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1685 SWRAP_LOG(SWRAP_LOG_ERROR,
1686 "Failed to allocate socket fds index array: %s",
1691 for (i = 0; i < socket_fds_max; i++) {
1695 socket_fds_idx = tmp;
1698 static void socket_wrapper_init_sockets(void)
1704 swrap_bind_symbol_all();
1706 swrap_mutex_lock(&sockets_mutex);
1708 if (sockets != NULL) {
1709 swrap_mutex_unlock(&sockets_mutex);
1713 SWRAP_LOG(SWRAP_LOG_DEBUG,
1714 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1715 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1718 * Intialize the static cache early before
1719 * any thread is able to start.
1721 (void)swrap_ipv4_net();
1723 socket_wrapper_init_fds_idx();
1725 /* Needs to be called inside the sockets_mutex lock here. */
1726 max_sockets = socket_wrapper_max_sockets();
1728 sockets = (struct socket_info_container *)calloc(max_sockets,
1729 sizeof(struct socket_info_container));
1731 if (sockets == NULL) {
1732 SWRAP_LOG(SWRAP_LOG_ERROR,
1733 "Failed to allocate sockets array: %s",
1735 swrap_mutex_unlock(&sockets_mutex);
1739 swrap_mutex_lock(&first_free_mutex);
1740 swrap_mutex_lock(&sockets_si_global);
1744 for (i = 0; i < max_sockets; i++) {
1745 swrap_set_next_free(&sockets[i].info, i+1);
1748 /* mark the end of the free list */
1749 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1751 swrap_mutex_unlock(&sockets_si_global);
1752 swrap_mutex_unlock(&first_free_mutex);
1753 swrap_mutex_unlock(&sockets_mutex);
1759 bool socket_wrapper_enabled(void)
1761 char *s = socket_wrapper_dir();
1769 socket_wrapper_init_sockets();
1774 static unsigned int socket_wrapper_default_iface(void)
1776 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1779 if (sscanf(s, "%u", &iface) == 1) {
1780 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1786 return 1;/* 127.0.0.1 */
1789 static void set_socket_info_index(int fd, int idx)
1791 SWRAP_LOG(SWRAP_LOG_TRACE,
1794 socket_fds_idx[fd] = idx;
1795 /* This builtin issues a full memory barrier. */
1796 __sync_synchronize();
1799 static void reset_socket_info_index(int fd)
1801 SWRAP_LOG(SWRAP_LOG_TRACE,
1804 set_socket_info_index(fd, -1);
1807 static int find_socket_info_index(int fd)
1813 if (socket_fds_idx == NULL) {
1817 if ((size_t)fd >= socket_fds_max) {
1819 * Do not add a log here as some applications do stupid things
1822 * for (fd = 0; fd <= getdtablesize(); fd++) {
1826 * This would produce millions of lines of debug messages.
1829 SWRAP_LOG(SWRAP_LOG_ERROR,
1830 "Looking for a socket info for the fd %d is over the "
1831 "max socket index limit of %zu.",
1838 /* This builtin issues a full memory barrier. */
1839 __sync_synchronize();
1840 return socket_fds_idx[fd];
1843 static int swrap_add_socket_info(const struct socket_info *si_input)
1845 struct socket_info *si = NULL;
1848 if (si_input == NULL) {
1853 swrap_mutex_lock(&first_free_mutex);
1854 if (first_free == -1) {
1859 si_index = first_free;
1860 si = swrap_get_socket_info(si_index);
1864 first_free = swrap_get_next_free(si);
1866 swrap_inc_refcount(si);
1868 SWRAP_UNLOCK_SI(si);
1871 swrap_mutex_unlock(&first_free_mutex);
1876 static int swrap_create_socket(struct socket_info *si, int fd)
1880 if ((size_t)fd >= socket_fds_max) {
1881 SWRAP_LOG(SWRAP_LOG_ERROR,
1882 "The max socket index limit of %zu has been reached, "
1890 idx = swrap_add_socket_info(si);
1895 set_socket_info_index(fd, idx);
1900 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1907 p = strrchr(un->sun_path, '/');
1908 if (p) p++; else p = un->sun_path;
1910 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1911 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1917 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1918 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1925 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1931 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1935 case SOCKET_TYPE_CHAR_TCP:
1936 case SOCKET_TYPE_CHAR_UDP: {
1937 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1939 if ((*len) < sizeof(*in2)) {
1940 SWRAP_LOG(SWRAP_LOG_ERROR,
1941 "V4: *len(%zu) < sizeof(*in2)=%zu",
1942 (size_t)*len, sizeof(*in2));
1947 memset(in2, 0, sizeof(*in2));
1948 in2->sin_family = AF_INET;
1949 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1950 in2->sin_port = htons(prt);
1952 *len = sizeof(*in2);
1956 case SOCKET_TYPE_CHAR_TCP_V6:
1957 case SOCKET_TYPE_CHAR_UDP_V6: {
1958 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1960 if ((*len) < sizeof(*in2)) {
1961 SWRAP_LOG(SWRAP_LOG_ERROR,
1962 "V6: *len(%zu) < sizeof(*in2)=%zu",
1963 (size_t)*len, sizeof(*in2));
1964 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1969 memset(in2, 0, sizeof(*in2));
1970 in2->sin6_family = AF_INET6;
1971 in2->sin6_addr = *swrap_ipv6();
1972 in2->sin6_addr.s6_addr[15] = iface;
1973 in2->sin6_port = htons(prt);
1975 *len = sizeof(*in2);
1980 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1989 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1996 char *swrap_dir = NULL;
1998 if (bcast) *bcast = 0;
2000 switch (inaddr->sa_family) {
2002 const struct sockaddr_in *in =
2003 (const struct sockaddr_in *)(const void *)inaddr;
2004 unsigned int addr = ntohl(in->sin_addr.s_addr);
2008 const unsigned int sw_net_addr = swrap_ipv4_net();
2009 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2013 u_type = SOCKET_TYPE_CHAR_TCP;
2016 u_type = SOCKET_TYPE_CHAR_UDP;
2017 a_type = SOCKET_TYPE_CHAR_UDP;
2018 b_type = SOCKET_TYPE_CHAR_UDP;
2021 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2022 errno = ESOCKTNOSUPPORT;
2026 prt = ntohs(in->sin_port);
2027 if (a_type && addr == 0xFFFFFFFF) {
2028 /* 255.255.255.255 only udp */
2031 iface = socket_wrapper_default_iface();
2032 } else if (b_type && addr == sw_bcast_addr) {
2041 iface = socket_wrapper_default_iface();
2042 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2043 /* 127.0.0.X or 10.53.57.X */
2046 iface = (addr & 0x000000FF);
2048 char str[256] = {0,};
2049 inet_ntop(inaddr->sa_family,
2052 SWRAP_LOG(SWRAP_LOG_WARN,
2054 str, (unsigned)prt);
2055 errno = ENETUNREACH;
2058 if (bcast) *bcast = is_bcast;
2063 const struct sockaddr_in6 *in =
2064 (const struct sockaddr_in6 *)(const void *)inaddr;
2065 struct in6_addr cmp1, cmp2;
2069 type = SOCKET_TYPE_CHAR_TCP_V6;
2072 type = SOCKET_TYPE_CHAR_UDP_V6;
2075 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2076 errno = ESOCKTNOSUPPORT;
2080 /* XXX no multicast/broadcast */
2082 prt = ntohs(in->sin6_port);
2084 cmp1 = *swrap_ipv6();
2085 cmp2 = in->sin6_addr;
2086 cmp2.s6_addr[15] = 0;
2087 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2088 iface = in->sin6_addr.s6_addr[15];
2090 char str[256] = {0,};
2091 inet_ntop(inaddr->sa_family,
2094 SWRAP_LOG(SWRAP_LOG_WARN,
2096 str, (unsigned)prt);
2097 errno = ENETUNREACH;
2105 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2106 errno = ENETUNREACH;
2111 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2116 swrap_dir = socket_wrapper_dir();
2117 if (swrap_dir == NULL) {
2123 swrap_un_path_EINVAL(un, swrap_dir);
2124 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2125 SAFE_FREE(swrap_dir);
2126 /* the caller need to do more processing */
2130 swrap_un_path(un, swrap_dir, type, iface, prt);
2131 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2133 SAFE_FREE(swrap_dir);
2138 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2146 char *swrap_dir = NULL;
2148 if (bcast) *bcast = 0;
2150 switch (si->family) {
2152 const struct sockaddr_in *in =
2153 (const struct sockaddr_in *)(const void *)inaddr;
2154 unsigned int addr = ntohl(in->sin_addr.s_addr);
2159 const unsigned int sw_net_addr = swrap_ipv4_net();
2160 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2162 prt = ntohs(in->sin_port);
2166 u_type = SOCKET_TYPE_CHAR_TCP;
2167 d_type = SOCKET_TYPE_CHAR_TCP;
2170 u_type = SOCKET_TYPE_CHAR_UDP;
2171 d_type = SOCKET_TYPE_CHAR_UDP;
2172 a_type = SOCKET_TYPE_CHAR_UDP;
2173 b_type = SOCKET_TYPE_CHAR_UDP;
2176 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2177 errno = ESOCKTNOSUPPORT;
2185 iface = socket_wrapper_default_iface();
2186 } else if (a_type && addr == 0xFFFFFFFF) {
2187 /* 255.255.255.255 only udp */
2190 iface = socket_wrapper_default_iface();
2191 } else if (b_type && addr == sw_bcast_addr) {
2192 /* 127.255.255.255 only udp */
2195 iface = socket_wrapper_default_iface();
2196 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2200 iface = (addr & 0x000000FF);
2202 errno = EADDRNOTAVAIL;
2206 /* Store the bind address for connect() */
2207 if (si->bindname.sa_socklen == 0) {
2208 struct sockaddr_in bind_in;
2209 socklen_t blen = sizeof(struct sockaddr_in);
2211 ZERO_STRUCT(bind_in);
2212 bind_in.sin_family = in->sin_family;
2213 bind_in.sin_port = in->sin_port;
2214 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2215 si->bindname.sa_socklen = blen;
2216 memcpy(&si->bindname.sa.in, &bind_in, blen);
2223 const struct sockaddr_in6 *in =
2224 (const struct sockaddr_in6 *)(const void *)inaddr;
2225 struct in6_addr cmp1, cmp2;
2229 type = SOCKET_TYPE_CHAR_TCP_V6;
2232 type = SOCKET_TYPE_CHAR_UDP_V6;
2235 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2236 errno = ESOCKTNOSUPPORT;
2240 /* XXX no multicast/broadcast */
2242 prt = ntohs(in->sin6_port);
2244 cmp1 = *swrap_ipv6();
2245 cmp2 = in->sin6_addr;
2246 cmp2.s6_addr[15] = 0;
2247 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2248 iface = socket_wrapper_default_iface();
2249 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2250 iface = in->sin6_addr.s6_addr[15];
2252 errno = EADDRNOTAVAIL;
2256 /* Store the bind address for connect() */
2257 if (si->bindname.sa_socklen == 0) {
2258 struct sockaddr_in6 bind_in;
2259 socklen_t blen = sizeof(struct sockaddr_in6);
2261 ZERO_STRUCT(bind_in);
2262 bind_in.sin6_family = in->sin6_family;
2263 bind_in.sin6_port = in->sin6_port;
2265 bind_in.sin6_addr = *swrap_ipv6();
2266 bind_in.sin6_addr.s6_addr[15] = iface;
2268 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2269 si->bindname.sa_socklen = blen;
2276 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2277 errno = EADDRNOTAVAIL;
2282 if (bcast) *bcast = is_bcast;
2284 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2289 swrap_dir = socket_wrapper_dir();
2290 if (swrap_dir == NULL) {
2296 /* handle auto-allocation of ephemeral ports */
2297 for (prt = 5001; prt < 10000; prt++) {
2298 swrap_un_path(un, swrap_dir, type, iface, prt);
2299 if (stat(un->sun_path, &st) == 0) continue;
2301 set_port(si->family, prt, &si->myname);
2302 set_port(si->family, prt, &si->bindname);
2309 SAFE_FREE(swrap_dir);
2314 swrap_un_path(un, swrap_dir, type, iface, prt);
2315 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2317 SAFE_FREE(swrap_dir);
2322 static struct socket_info *find_socket_info(int fd)
2324 int idx = find_socket_info_index(fd);
2330 return swrap_get_socket_info(idx);
2334 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2336 struct socket_info_fd *f;
2337 const struct socket_info *last_s = NULL;
2339 /* first catch invalid input */
2340 switch (sa->sa_family) {
2342 if (len < sizeof(struct sockaddr_in)) {
2348 if (len < sizeof(struct sockaddr_in6)) {
2358 for (f = socket_fds; f; f = f->next) {
2359 struct socket_info *s = swrap_get_socket_info(f->si_index);
2366 if (s->myname == NULL) {
2369 if (s->myname->sa_family != sa->sa_family) {
2372 switch (s->myname->sa_family) {
2374 struct sockaddr_in *sin1, *sin2;
2376 sin1 = (struct sockaddr_in *)s->myname;
2377 sin2 = (struct sockaddr_in *)sa;
2379 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2382 if (sin1->sin_port != sin2->sin_port) {
2385 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2395 struct sockaddr_in6 *sin1, *sin2;
2397 sin1 = (struct sockaddr_in6 *)s->myname;
2398 sin2 = (struct sockaddr_in6 *)sa;
2400 if (sin1->sin6_port != sin2->sin6_port) {
2403 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2425 static void swrap_remove_stale(int fd);
2427 static int sockaddr_convert_to_un(struct socket_info *si,
2428 const struct sockaddr *in_addr,
2430 struct sockaddr_un *out_addr,
2434 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2436 (void) in_len; /* unused */
2438 if (out_addr == NULL) {
2442 out->sa_family = AF_UNIX;
2443 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2444 out->sa_len = sizeof(*out_addr);
2447 switch (in_addr->sa_family) {
2449 const struct sockaddr_in *sin;
2450 if (si->family != AF_INET) {
2453 if (in_len < sizeof(struct sockaddr_in)) {
2456 sin = (const struct sockaddr_in *)(const void *)in_addr;
2457 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2462 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2463 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2477 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2478 errno = ESOCKTNOSUPPORT;
2482 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2484 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2490 errno = EAFNOSUPPORT;
2491 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2495 static int sockaddr_convert_from_un(const struct socket_info *si,
2496 const struct sockaddr_un *in_addr,
2497 socklen_t un_addrlen,
2499 struct sockaddr *out_addr,
2500 socklen_t *out_addrlen)
2504 if (out_addr == NULL || out_addrlen == NULL)
2507 if (un_addrlen == 0) {
2522 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2523 errno = ESOCKTNOSUPPORT;
2526 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2527 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2528 out_addr->sa_len = *out_addrlen;
2535 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2536 errno = EAFNOSUPPORT;
2540 enum swrap_packet_type {
2542 SWRAP_CONNECT_UNREACH,
2550 SWRAP_SENDTO_UNREACH,
2561 struct swrap_file_hdr {
2563 uint16_t version_major;
2564 uint16_t version_minor;
2567 uint32_t frame_max_len;
2568 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2571 #define SWRAP_FILE_HDR_SIZE 24
2573 struct swrap_packet_frame {
2575 uint32_t micro_seconds;
2576 uint32_t recorded_length;
2577 uint32_t full_length;
2579 #define SWRAP_PACKET_FRAME_SIZE 16
2581 union swrap_packet_ip {
2585 uint16_t packet_length;
2586 uint16_t identification;
2591 uint16_t hdr_checksum;
2595 #define SWRAP_PACKET_IP_V4_SIZE 20
2598 uint8_t flow_label_high;
2599 uint16_t flow_label_low;
2600 uint16_t payload_length;
2601 uint8_t next_header;
2603 uint8_t src_addr[16];
2604 uint8_t dest_addr[16];
2606 #define SWRAP_PACKET_IP_V6_SIZE 40
2608 #define SWRAP_PACKET_IP_SIZE 40
2610 union swrap_packet_payload {
2612 uint16_t source_port;
2622 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2624 uint16_t source_port;
2629 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2636 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2643 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2645 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2647 #define SWRAP_PACKET_MIN_ALLOC \
2648 (SWRAP_PACKET_FRAME_SIZE + \
2649 SWRAP_PACKET_IP_SIZE + \
2650 SWRAP_PACKET_PAYLOAD_SIZE)
2652 static const char *swrap_pcap_init_file(void)
2654 static int initialized = 0;
2655 static const char *s = NULL;
2656 static const struct swrap_file_hdr h;
2657 static const struct swrap_packet_frame f;
2658 static const union swrap_packet_ip i;
2659 static const union swrap_packet_payload p;
2661 if (initialized == 1) {
2667 * TODO: don't use the structs use plain buffer offsets
2668 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2670 * for now make sure we disable PCAP support
2671 * if the struct has alignment!
2673 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2676 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2679 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2682 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2685 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2688 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2691 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2694 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2697 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2700 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2704 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2708 if (strncmp(s, "./", 2) == 0) {
2711 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2715 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2716 const struct sockaddr *src,
2717 const struct sockaddr *dest,
2719 const uint8_t *payload,
2721 unsigned long tcp_seqno,
2722 unsigned long tcp_ack,
2723 unsigned char tcp_ctl,
2725 size_t *_packet_len)
2727 uint8_t *base = NULL;
2728 uint8_t *buf = NULL;
2731 struct swrap_packet_frame *frame;
2735 union swrap_packet_ip *ip;
2737 union swrap_packet_payload *pay;
2740 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2741 size_t wire_hdr_len = 0;
2742 size_t wire_len = 0;
2743 size_t ip_hdr_len = 0;
2744 size_t icmp_hdr_len = 0;
2745 size_t icmp_truncate_len = 0;
2746 uint8_t protocol = 0, icmp_protocol = 0;
2747 const struct sockaddr_in *src_in = NULL;
2748 const struct sockaddr_in *dest_in = NULL;
2750 const struct sockaddr_in6 *src_in6 = NULL;
2751 const struct sockaddr_in6 *dest_in6 = NULL;
2756 switch (src->sa_family) {
2758 src_in = (const struct sockaddr_in *)(const void *)src;
2759 dest_in = (const struct sockaddr_in *)(const void *)dest;
2760 src_port = src_in->sin_port;
2761 dest_port = dest_in->sin_port;
2762 ip_hdr_len = sizeof(i.ip->v4);
2766 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2767 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2768 src_port = src_in6->sin6_port;
2769 dest_port = dest_in6->sin6_port;
2770 ip_hdr_len = sizeof(i.ip->v6);
2777 switch (socket_type) {
2779 protocol = 0x06; /* TCP */
2780 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2781 wire_len = wire_hdr_len + payload_len;
2785 protocol = 0x11; /* UDP */
2786 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2787 wire_len = wire_hdr_len + payload_len;
2795 icmp_protocol = protocol;
2796 switch (src->sa_family) {
2798 protocol = 0x01; /* ICMPv4 */
2799 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2803 protocol = 0x3A; /* ICMPv6 */
2804 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2808 if (wire_len > 64 ) {
2809 icmp_truncate_len = wire_len - 64;
2811 wire_len += icmp_hdr_len;
2814 packet_len = nonwire_len + wire_len;
2815 alloc_len = packet_len;
2816 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2817 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2820 base = (uint8_t *)calloc(1, alloc_len);
2828 f.frame->seconds = tval->tv_sec;
2829 f.frame->micro_seconds = tval->tv_usec;
2830 f.frame->recorded_length = wire_len - icmp_truncate_len;
2831 f.frame->full_length = wire_len - icmp_truncate_len;
2833 buf += SWRAP_PACKET_FRAME_SIZE;
2836 switch (src->sa_family) {
2838 if (src_in == NULL || dest_in == NULL) {
2843 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2844 i.ip->v4.tos = 0x00;
2845 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2846 i.ip->v4.identification = htons(0xFFFF);
2847 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2848 i.ip->v4.fragment = htons(0x0000);
2849 i.ip->v4.ttl = 0xFF;
2850 i.ip->v4.protocol = protocol;
2851 i.ip->v4.hdr_checksum = htons(0x0000);
2852 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2853 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2854 buf += SWRAP_PACKET_IP_V4_SIZE;
2858 if (src_in6 == NULL || dest_in6 == NULL) {
2863 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2864 i.ip->v6.flow_label_high = 0x00;
2865 i.ip->v6.flow_label_low = 0x0000;
2866 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2867 i.ip->v6.next_header = protocol;
2868 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2869 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2870 buf += SWRAP_PACKET_IP_V6_SIZE;
2876 pay = (union swrap_packet_payload *)(void *)buf;
2877 switch (src->sa_family) {
2879 pay->icmp4.type = 0x03; /* destination unreachable */
2880 pay->icmp4.code = 0x01; /* host unreachable */
2881 pay->icmp4.checksum = htons(0x0000);
2882 pay->icmp4.unused = htonl(0x00000000);
2884 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2886 /* set the ip header in the ICMP payload */
2888 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2889 i.ip->v4.tos = 0x00;
2890 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2891 i.ip->v4.identification = htons(0xFFFF);
2892 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2893 i.ip->v4.fragment = htons(0x0000);
2894 i.ip->v4.ttl = 0xFF;
2895 i.ip->v4.protocol = icmp_protocol;
2896 i.ip->v4.hdr_checksum = htons(0x0000);
2897 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2898 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2900 buf += SWRAP_PACKET_IP_V4_SIZE;
2902 src_port = dest_in->sin_port;
2903 dest_port = src_in->sin_port;
2907 pay->icmp6.type = 0x01; /* destination unreachable */
2908 pay->icmp6.code = 0x03; /* address unreachable */
2909 pay->icmp6.checksum = htons(0x0000);
2910 pay->icmp6.unused = htonl(0x00000000);
2911 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2913 /* set the ip header in the ICMP payload */
2915 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2916 i.ip->v6.flow_label_high = 0x00;
2917 i.ip->v6.flow_label_low = 0x0000;
2918 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2919 i.ip->v6.next_header = protocol;
2920 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2921 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2923 buf += SWRAP_PACKET_IP_V6_SIZE;
2925 src_port = dest_in6->sin6_port;
2926 dest_port = src_in6->sin6_port;
2932 pay = (union swrap_packet_payload *)(void *)buf;
2934 switch (socket_type) {
2936 pay->tcp.source_port = src_port;
2937 pay->tcp.dest_port = dest_port;
2938 pay->tcp.seq_num = htonl(tcp_seqno);
2939 pay->tcp.ack_num = htonl(tcp_ack);
2940 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2941 pay->tcp.control = tcp_ctl;
2942 pay->tcp.window = htons(0x7FFF);
2943 pay->tcp.checksum = htons(0x0000);
2944 pay->tcp.urg = htons(0x0000);
2945 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2950 pay->udp.source_port = src_port;
2951 pay->udp.dest_port = dest_port;
2952 pay->udp.length = htons(8 + payload_len);
2953 pay->udp.checksum = htons(0x0000);
2954 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2959 if (payload && payload_len > 0) {
2960 memcpy(buf, payload, payload_len);
2963 *_packet_len = packet_len - icmp_truncate_len;
2967 static int swrap_pcap_get_fd(const char *fname)
2975 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2977 struct swrap_file_hdr file_hdr;
2978 file_hdr.magic = 0xA1B2C3D4;
2979 file_hdr.version_major = 0x0002;
2980 file_hdr.version_minor = 0x0004;
2981 file_hdr.timezone = 0x00000000;
2982 file_hdr.sigfigs = 0x00000000;
2983 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2984 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2986 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2993 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2998 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2999 const struct sockaddr *addr,
3000 enum swrap_packet_type type,
3001 const void *buf, size_t len,
3004 const struct sockaddr *src_addr;
3005 const struct sockaddr *dest_addr;
3006 unsigned long tcp_seqno = 0;
3007 unsigned long tcp_ack = 0;
3008 unsigned char tcp_ctl = 0;
3009 int unreachable = 0;
3013 switch (si->family) {
3025 case SWRAP_CONNECT_SEND:
3026 if (si->type != SOCK_STREAM) {
3030 src_addr = &si->myname.sa.s;
3033 tcp_seqno = si->io.pck_snd;
3034 tcp_ack = si->io.pck_rcv;
3035 tcp_ctl = 0x02; /* SYN */
3037 si->io.pck_snd += 1;
3041 case SWRAP_CONNECT_RECV:
3042 if (si->type != SOCK_STREAM) {
3046 dest_addr = &si->myname.sa.s;
3049 tcp_seqno = si->io.pck_rcv;
3050 tcp_ack = si->io.pck_snd;
3051 tcp_ctl = 0x12; /** SYN,ACK */
3053 si->io.pck_rcv += 1;
3057 case SWRAP_CONNECT_UNREACH:
3058 if (si->type != SOCK_STREAM) {
3062 dest_addr = &si->myname.sa.s;
3065 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3066 tcp_seqno = si->io.pck_snd - 1;
3067 tcp_ack = si->io.pck_rcv;
3068 tcp_ctl = 0x02; /* SYN */
3073 case SWRAP_CONNECT_ACK:
3074 if (si->type != SOCK_STREAM) {
3078 src_addr = &si->myname.sa.s;
3081 tcp_seqno = si->io.pck_snd;
3082 tcp_ack = si->io.pck_rcv;
3083 tcp_ctl = 0x10; /* ACK */
3087 case SWRAP_ACCEPT_SEND:
3088 if (si->type != SOCK_STREAM) {
3092 dest_addr = &si->myname.sa.s;
3095 tcp_seqno = si->io.pck_rcv;
3096 tcp_ack = si->io.pck_snd;
3097 tcp_ctl = 0x02; /* SYN */
3099 si->io.pck_rcv += 1;
3103 case SWRAP_ACCEPT_RECV:
3104 if (si->type != SOCK_STREAM) {
3108 src_addr = &si->myname.sa.s;
3111 tcp_seqno = si->io.pck_snd;
3112 tcp_ack = si->io.pck_rcv;
3113 tcp_ctl = 0x12; /* SYN,ACK */
3115 si->io.pck_snd += 1;
3119 case SWRAP_ACCEPT_ACK:
3120 if (si->type != SOCK_STREAM) {
3124 dest_addr = &si->myname.sa.s;
3127 tcp_seqno = si->io.pck_rcv;
3128 tcp_ack = si->io.pck_snd;
3129 tcp_ctl = 0x10; /* ACK */
3134 src_addr = &si->myname.sa.s;
3135 dest_addr = &si->peername.sa.s;
3137 tcp_seqno = si->io.pck_snd;
3138 tcp_ack = si->io.pck_rcv;
3139 tcp_ctl = 0x18; /* PSH,ACK */
3141 si->io.pck_snd += len;
3145 case SWRAP_SEND_RST:
3146 dest_addr = &si->myname.sa.s;
3147 src_addr = &si->peername.sa.s;
3149 if (si->type == SOCK_DGRAM) {
3150 return swrap_pcap_marshall_packet(si,
3152 SWRAP_SENDTO_UNREACH,
3158 tcp_seqno = si->io.pck_rcv;
3159 tcp_ack = si->io.pck_snd;
3160 tcp_ctl = 0x14; /** RST,ACK */
3164 case SWRAP_PENDING_RST:
3165 dest_addr = &si->myname.sa.s;
3166 src_addr = &si->peername.sa.s;
3168 if (si->type == SOCK_DGRAM) {
3172 tcp_seqno = si->io.pck_rcv;
3173 tcp_ack = si->io.pck_snd;
3174 tcp_ctl = 0x14; /* RST,ACK */
3179 dest_addr = &si->myname.sa.s;
3180 src_addr = &si->peername.sa.s;
3182 tcp_seqno = si->io.pck_rcv;
3183 tcp_ack = si->io.pck_snd;
3184 tcp_ctl = 0x18; /* PSH,ACK */
3186 si->io.pck_rcv += len;
3190 case SWRAP_RECV_RST:
3191 dest_addr = &si->myname.sa.s;
3192 src_addr = &si->peername.sa.s;
3194 if (si->type == SOCK_DGRAM) {
3198 tcp_seqno = si->io.pck_rcv;
3199 tcp_ack = si->io.pck_snd;
3200 tcp_ctl = 0x14; /* RST,ACK */
3205 src_addr = &si->myname.sa.s;
3208 si->io.pck_snd += len;
3212 case SWRAP_SENDTO_UNREACH:
3213 dest_addr = &si->myname.sa.s;
3220 case SWRAP_RECVFROM:
3221 dest_addr = &si->myname.sa.s;
3224 si->io.pck_rcv += len;
3228 case SWRAP_CLOSE_SEND:
3229 if (si->type != SOCK_STREAM) {
3233 src_addr = &si->myname.sa.s;
3234 dest_addr = &si->peername.sa.s;
3236 tcp_seqno = si->io.pck_snd;
3237 tcp_ack = si->io.pck_rcv;
3238 tcp_ctl = 0x11; /* FIN, ACK */
3240 si->io.pck_snd += 1;
3244 case SWRAP_CLOSE_RECV:
3245 if (si->type != SOCK_STREAM) {
3249 dest_addr = &si->myname.sa.s;
3250 src_addr = &si->peername.sa.s;
3252 tcp_seqno = si->io.pck_rcv;
3253 tcp_ack = si->io.pck_snd;
3254 tcp_ctl = 0x11; /* FIN,ACK */
3256 si->io.pck_rcv += 1;
3260 case SWRAP_CLOSE_ACK:
3261 if (si->type != SOCK_STREAM) {
3265 src_addr = &si->myname.sa.s;
3266 dest_addr = &si->peername.sa.s;
3268 tcp_seqno = si->io.pck_snd;
3269 tcp_ack = si->io.pck_rcv;
3270 tcp_ctl = 0x10; /* ACK */
3277 swrapGetTimeOfDay(&tv);
3279 return swrap_pcap_packet_init(&tv,
3283 (const uint8_t *)buf,
3292 static void swrap_pcap_dump_packet(struct socket_info *si,
3293 const struct sockaddr *addr,
3294 enum swrap_packet_type type,
3295 const void *buf, size_t len)
3297 const char *file_name;
3299 size_t packet_len = 0;
3302 swrap_mutex_lock(&pcap_dump_mutex);
3304 file_name = swrap_pcap_init_file();
3309 packet = swrap_pcap_marshall_packet(si,
3315 if (packet == NULL) {
3319 fd = swrap_pcap_get_fd(file_name);
3321 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3330 swrap_mutex_unlock(&pcap_dump_mutex);
3333 /****************************************************************************
3335 ***************************************************************************/
3337 #ifdef HAVE_SIGNALFD
3338 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3342 rc = libc_signalfd(fd, mask, flags);
3344 swrap_remove_stale(fd);
3350 int signalfd(int fd, const sigset_t *mask, int flags)
3352 return swrap_signalfd(fd, mask, flags);
3356 /****************************************************************************
3358 ***************************************************************************/
3360 static int swrap_socket(int family, int type, int protocol)
3362 struct socket_info *si = NULL;
3363 struct socket_info _si = { 0 };
3366 int real_type = type;
3369 * Remove possible addition flags passed to socket() so
3370 * do not fail checking the type.
3371 * See https://lwn.net/Articles/281965/
3374 real_type &= ~SOCK_CLOEXEC;
3376 #ifdef SOCK_NONBLOCK
3377 real_type &= ~SOCK_NONBLOCK;
3380 if (!socket_wrapper_enabled()) {
3381 return libc_socket(family, type, protocol);
3392 #endif /* AF_NETLINK */
3395 #endif /* AF_PACKET */
3397 fd = libc_socket(family, type, protocol);
3399 /* Check if we have a stale fd and remove it */
3400 swrap_remove_stale(fd);
3401 SWRAP_LOG(SWRAP_LOG_TRACE,
3402 "Unix socket fd=%d",
3407 errno = EAFNOSUPPORT;
3411 switch (real_type) {
3417 errno = EPROTONOSUPPORT;
3425 if (real_type == SOCK_STREAM) {
3430 if (real_type == SOCK_DGRAM) {
3435 errno = EPROTONOSUPPORT;
3440 * We must call libc_socket with type, from the caller, not the version
3441 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3443 fd = libc_socket(AF_UNIX, type, 0);
3449 /* Check if we have a stale fd and remove it */
3450 swrap_remove_stale(fd);
3453 si->family = family;
3455 /* however, the rest of the socket_wrapper code expects just
3456 * the type, not the flags */
3457 si->type = real_type;
3458 si->protocol = protocol;
3461 * Setup myname so getsockname() can succeed to find out the socket
3464 switch(si->family) {
3466 struct sockaddr_in sin = {
3467 .sin_family = AF_INET,
3470 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3471 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3476 struct sockaddr_in6 sin6 = {
3477 .sin6_family = AF_INET6,
3480 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3481 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3490 ret = swrap_create_socket(si, fd);
3492 int saved_errno = errno;
3494 errno = saved_errno;
3498 SWRAP_LOG(SWRAP_LOG_TRACE,
3499 "Created %s socket for protocol %s, fd=%d",
3500 family == AF_INET ? "IPv4" : "IPv6",
3501 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3507 int socket(int family, int type, int protocol)
3509 return swrap_socket(family, type, protocol);
3512 /****************************************************************************
3514 ***************************************************************************/
3516 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3520 rc = libc_socketpair(family, type, protocol, sv);
3522 swrap_remove_stale(sv[0]);
3523 swrap_remove_stale(sv[1]);
3529 int socketpair(int family, int type, int protocol, int sv[2])
3531 return swrap_socketpair(family, type, protocol, sv);
3534 /****************************************************************************
3536 ***************************************************************************/
3538 #ifdef HAVE_TIMERFD_CREATE
3539 static int swrap_timerfd_create(int clockid, int flags)
3543 fd = libc_timerfd_create(clockid, flags);
3545 swrap_remove_stale(fd);
3551 int timerfd_create(int clockid, int flags)
3553 return swrap_timerfd_create(clockid, flags);
3557 /****************************************************************************
3559 ***************************************************************************/
3561 static int swrap_pipe(int pipefd[2])
3565 rc = libc_pipe(pipefd);
3567 swrap_remove_stale(pipefd[0]);
3568 swrap_remove_stale(pipefd[1]);
3574 int pipe(int pipefd[2])
3576 return swrap_pipe(pipefd);
3579 /****************************************************************************
3581 ***************************************************************************/
3583 static int swrap_accept(int s,
3584 struct sockaddr *addr,
3588 struct socket_info *parent_si, *child_si;
3589 struct socket_info new_si = { 0 };
3592 struct swrap_address un_addr = {
3593 .sa_socklen = sizeof(struct sockaddr_un),
3595 struct swrap_address un_my_addr = {
3596 .sa_socklen = sizeof(struct sockaddr_un),
3598 struct swrap_address in_addr = {
3599 .sa_socklen = sizeof(struct sockaddr_storage),
3601 struct swrap_address in_my_addr = {
3602 .sa_socklen = sizeof(struct sockaddr_storage),
3606 parent_si = find_socket_info(s);
3609 return libc_accept4(s, addr, addrlen, flags);
3612 return libc_accept(s, addr, addrlen);
3618 * prevent parent_si from being altered / closed
3621 SWRAP_LOCK_SI(parent_si);
3624 * assume out sockaddr have the same size as the in parent
3627 in_addr.sa_socklen = socket_length(parent_si->family);
3628 if (in_addr.sa_socklen <= 0) {
3629 SWRAP_UNLOCK_SI(parent_si);
3634 SWRAP_UNLOCK_SI(parent_si);
3637 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3640 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3643 int saved_errno = errno;
3644 if (saved_errno == ENOTSOCK) {
3645 /* Remove stale fds */
3646 swrap_remove_stale(s);
3648 errno = saved_errno;
3654 /* Check if we have a stale fd and remove it */
3655 swrap_remove_stale(fd);
3657 if (un_addr.sa.un.sun_path[0] == '\0') {
3659 * FreeBSD seems to have a problem where
3660 * accept4() on the unix socket doesn't
3661 * ECONNABORTED for already disconnected connections.
3663 * Let's try libc_getpeername() to get the peer address
3664 * as a fallback, but it'll likely return ENOTCONN,
3665 * which we have to map to ECONNABORTED.
3667 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3668 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3670 int saved_errno = errno;
3672 if (saved_errno == ENOTCONN) {
3674 * If the connection is already disconnected
3675 * we should return ECONNABORTED.
3677 saved_errno = ECONNABORTED;
3679 errno = saved_errno;
3684 ret = libc_getsockname(fd,
3686 &un_my_addr.sa_socklen);
3688 int saved_errno = errno;
3690 if (saved_errno == ENOTCONN) {
3692 * If the connection is already disconnected
3693 * we should return ECONNABORTED.
3695 saved_errno = ECONNABORTED;
3697 errno = saved_errno;
3701 SWRAP_LOCK_SI(parent_si);
3703 ret = sockaddr_convert_from_un(parent_si,
3708 &in_addr.sa_socklen);
3710 int saved_errno = errno;
3711 SWRAP_UNLOCK_SI(parent_si);
3713 errno = saved_errno;
3719 child_si->family = parent_si->family;
3720 child_si->type = parent_si->type;
3721 child_si->protocol = parent_si->protocol;
3722 child_si->bound = 1;
3723 child_si->is_server = 1;
3724 child_si->connected = 1;
3726 SWRAP_UNLOCK_SI(parent_si);
3728 child_si->peername = (struct swrap_address) {
3729 .sa_socklen = in_addr.sa_socklen,
3731 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3733 if (addr != NULL && addrlen != NULL) {
3734 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3736 memcpy(addr, &in_addr.sa.ss, copy_len);
3738 *addrlen = in_addr.sa_socklen;
3741 ret = sockaddr_convert_from_un(child_si,
3743 un_my_addr.sa_socklen,
3746 &in_my_addr.sa_socklen);
3748 int saved_errno = errno;
3750 errno = saved_errno;
3754 SWRAP_LOG(SWRAP_LOG_TRACE,
3755 "accept() path=%s, fd=%d",
3756 un_my_addr.sa.un.sun_path, s);
3758 child_si->myname = (struct swrap_address) {
3759 .sa_socklen = in_my_addr.sa_socklen,
3761 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3763 idx = swrap_create_socket(&new_si, fd);
3765 int saved_errno = errno;
3767 errno = saved_errno;
3772 struct socket_info *si = swrap_get_socket_info(idx);
3775 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3776 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3777 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3778 SWRAP_UNLOCK_SI(si);
3785 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3787 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3791 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3792 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3794 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3797 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3800 static int autobind_start_init;
3801 static int autobind_start;
3803 /* using sendto() or connect() on an unbound socket would give the
3804 recipient no way to reply, as unlike UDP and TCP, a unix domain
3805 socket can't auto-assign ephemeral port numbers, so we need to
3807 Note: this might change the family from ipv6 to ipv4
3809 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3811 struct swrap_address un_addr = {
3812 .sa_socklen = sizeof(struct sockaddr_un),
3818 char *swrap_dir = NULL;
3820 swrap_mutex_lock(&autobind_start_mutex);
3822 if (autobind_start_init != 1) {
3823 autobind_start_init = 1;
3824 autobind_start = getpid();
3825 autobind_start %= 50000;
3826 autobind_start += 10000;
3829 un_addr.sa.un.sun_family = AF_UNIX;
3833 struct sockaddr_in in;
3837 type = SOCKET_TYPE_CHAR_TCP;
3840 type = SOCKET_TYPE_CHAR_UDP;
3843 errno = ESOCKTNOSUPPORT;
3848 memset(&in, 0, sizeof(in));
3849 in.sin_family = AF_INET;
3850 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3851 socket_wrapper_default_iface()));
3853 si->myname = (struct swrap_address) {
3854 .sa_socklen = sizeof(in),
3856 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3861 struct sockaddr_in6 in6;
3863 if (si->family != family) {
3864 errno = ENETUNREACH;
3871 type = SOCKET_TYPE_CHAR_TCP_V6;
3874 type = SOCKET_TYPE_CHAR_UDP_V6;
3877 errno = ESOCKTNOSUPPORT;
3882 memset(&in6, 0, sizeof(in6));
3883 in6.sin6_family = AF_INET6;
3884 in6.sin6_addr = *swrap_ipv6();
3885 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3887 si->myname = (struct swrap_address) {
3888 .sa_socklen = sizeof(in6),
3890 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3895 errno = ESOCKTNOSUPPORT;
3900 if (autobind_start > 60000) {
3901 autobind_start = 10000;
3904 swrap_dir = socket_wrapper_dir();
3905 if (swrap_dir == NULL) {
3911 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3912 port = autobind_start + i;
3913 swrap_un_path(&un_addr.sa.un,
3916 socket_wrapper_default_iface(),
3919 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3921 if (errno == EALREADY || errno == EADDRINUSE) {
3927 si->un_addr = un_addr.sa.un;
3930 autobind_start = port + 1;
3933 if (i == SOCKET_MAX_SOCKETS) {
3934 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3935 "interface "SOCKET_FORMAT,
3938 socket_wrapper_default_iface(),
3945 si->family = family;
3946 set_port(si->family, port, &si->myname);
3951 SAFE_FREE(swrap_dir);
3952 swrap_mutex_unlock(&autobind_start_mutex);
3956 /****************************************************************************
3958 ***************************************************************************/
3960 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3964 struct swrap_address un_addr = {
3965 .sa_socklen = sizeof(struct sockaddr_un),
3967 struct socket_info *si = find_socket_info(s);
3971 return libc_connect(s, serv_addr, addrlen);
3976 if (si->bound == 0) {
3977 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3983 if (si->family != serv_addr->sa_family) {
3984 SWRAP_LOG(SWRAP_LOG_ERROR,
3985 "called for fd=%d (family=%d) called with invalid family=%d",
3986 s, si->family, serv_addr->sa_family);
3992 ret = sockaddr_convert_to_un(si, serv_addr,
3993 addrlen, &un_addr.sa.un, 0, &bcast);
3999 errno = ENETUNREACH;
4004 if (si->type == SOCK_DGRAM) {
4005 si->defer_connect = 1;
4008 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4010 ret = libc_connect(s,
4012 un_addr.sa_socklen);
4015 SWRAP_LOG(SWRAP_LOG_TRACE,
4016 "connect() path=%s, fd=%d",
4017 un_addr.sa.un.sun_path, s);
4020 /* to give better errors */
4021 if (ret == -1 && errno == ENOENT) {
4022 errno = EHOSTUNREACH;
4026 si->peername = (struct swrap_address) {
4027 .sa_socklen = addrlen,
4030 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4034 * When we connect() on a socket than we have to bind the
4035 * outgoing connection on the interface we use for the
4036 * transport. We already bound it on the right interface
4037 * but here we have to update the name so getsockname()
4038 * returns correct information.
4040 if (si->bindname.sa_socklen > 0) {
4041 si->myname = (struct swrap_address) {
4042 .sa_socklen = si->bindname.sa_socklen,
4045 memcpy(&si->myname.sa.ss,
4046 &si->bindname.sa.ss,
4047 si->bindname.sa_socklen);
4049 /* Cleanup bindname */
4050 si->bindname = (struct swrap_address) {
4055 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4056 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4058 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4062 SWRAP_UNLOCK_SI(si);
4066 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4068 return swrap_connect(s, serv_addr, addrlen);
4071 /****************************************************************************
4073 ***************************************************************************/
4075 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4078 struct swrap_address un_addr = {
4079 .sa_socklen = sizeof(struct sockaddr_un),
4081 struct socket_info *si = find_socket_info(s);
4088 return libc_bind(s, myaddr, addrlen);
4093 switch (si->family) {
4095 const struct sockaddr_in *sin;
4096 if (addrlen < sizeof(struct sockaddr_in)) {
4097 bind_error = EINVAL;
4101 sin = (const struct sockaddr_in *)(const void *)myaddr;
4103 if (sin->sin_family != AF_INET) {
4104 bind_error = EAFNOSUPPORT;
4107 /* special case for AF_UNSPEC */
4108 if (sin->sin_family == AF_UNSPEC &&
4109 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4118 const struct sockaddr_in6 *sin6;
4119 if (addrlen < sizeof(struct sockaddr_in6)) {
4120 bind_error = EINVAL;
4124 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4126 if (sin6->sin6_family != AF_INET6) {
4127 bind_error = EAFNOSUPPORT;
4134 bind_error = EINVAL;
4138 if (bind_error != 0) {
4145 in_use = check_addr_port_in_use(myaddr, addrlen);
4153 si->myname.sa_socklen = addrlen;
4154 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4156 ret = sockaddr_convert_to_un(si,
4166 unlink(un_addr.sa.un.sun_path);
4168 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4170 SWRAP_LOG(SWRAP_LOG_TRACE,
4171 "bind() path=%s, fd=%d",
4172 un_addr.sa.un.sun_path, s);
4179 SWRAP_UNLOCK_SI(si);
4184 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4186 return swrap_bind(s, myaddr, addrlen);
4189 /****************************************************************************
4191 ***************************************************************************/
4193 #ifdef HAVE_BINDRESVPORT
4194 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4196 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4198 struct swrap_address myaddr = {
4199 .sa_socklen = sizeof(struct sockaddr_storage),
4202 static uint16_t port;
4207 #define SWRAP_STARTPORT 600
4208 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4209 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4212 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4216 salen = myaddr.sa_socklen;
4219 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4225 memset(&myaddr.sa.ss, 0, salen);
4230 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4233 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4235 salen = sizeof(struct sockaddr_in);
4236 sinp->sin_port = htons(port);
4240 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4242 salen = sizeof(struct sockaddr_in6);
4243 sin6p->sin6_port = htons(port);
4247 errno = EAFNOSUPPORT;
4252 if (port > SWRAP_ENDPORT) {
4253 port = SWRAP_STARTPORT;
4256 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4257 if (rc == 0 || errno != EADDRINUSE) {
4265 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4267 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4271 /****************************************************************************
4273 ***************************************************************************/
4275 static int swrap_listen(int s, int backlog)
4278 struct socket_info *si = find_socket_info(s);
4281 return libc_listen(s, backlog);
4286 if (si->bound == 0) {
4287 ret = swrap_auto_bind(s, si, si->family);
4294 ret = libc_listen(s, backlog);
4300 SWRAP_UNLOCK_SI(si);
4305 int listen(int s, int backlog)
4307 return swrap_listen(s, backlog);
4310 /****************************************************************************
4312 ***************************************************************************/
4314 static FILE *swrap_fopen(const char *name, const char *mode)
4318 fp = libc_fopen(name, mode);
4320 int fd = fileno(fp);
4322 swrap_remove_stale(fd);
4328 FILE *fopen(const char *name, const char *mode)
4330 return swrap_fopen(name, mode);
4333 /****************************************************************************
4335 ***************************************************************************/
4338 static FILE *swrap_fopen64(const char *name, const char *mode)
4342 fp = libc_fopen64(name, mode);
4344 int fd = fileno(fp);
4346 swrap_remove_stale(fd);
4352 FILE *fopen64(const char *name, const char *mode)
4354 return swrap_fopen64(name, mode);
4356 #endif /* HAVE_FOPEN64 */
4358 /****************************************************************************
4360 ***************************************************************************/
4362 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4366 ret = libc_vopen(pathname, flags, ap);
4369 * There are methods for closing descriptors (libc-internal code
4370 * paths, direct syscalls) which close descriptors in ways that
4371 * we can't intercept, so try to recover when we notice that
4374 swrap_remove_stale(ret);
4379 int open(const char *pathname, int flags, ...)
4384 va_start(ap, flags);
4385 fd = swrap_vopen(pathname, flags, ap);
4391 /****************************************************************************
4393 ***************************************************************************/
4396 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4400 ret = libc_vopen64(pathname, flags, ap);
4403 * There are methods for closing descriptors (libc-internal code
4404 * paths, direct syscalls) which close descriptors in ways that
4405 * we can't intercept, so try to recover when we notice that
4408 swrap_remove_stale(ret);
4413 int open64(const char *pathname, int flags, ...)
4418 va_start(ap, flags);
4419 fd = swrap_vopen64(pathname, flags, ap);
4424 #endif /* HAVE_OPEN64 */
4426 /****************************************************************************
4428 ***************************************************************************/
4430 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4434 ret = libc_vopenat(dirfd, path, flags, ap);
4437 * There are methods for closing descriptors (libc-internal code
4438 * paths, direct syscalls) which close descriptors in ways that
4439 * we can't intercept, so try to recover when we notice that
4442 swrap_remove_stale(ret);
4448 int openat(int dirfd, const char *path, int flags, ...)
4453 va_start(ap, flags);
4454 fd = swrap_vopenat(dirfd, path, flags, ap);
4460 /****************************************************************************
4462 ***************************************************************************/
4464 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4466 struct socket_info *si = find_socket_info(s);
4471 return libc_getpeername(s, name, addrlen);
4476 if (si->peername.sa_socklen == 0)
4482 len = MIN(*addrlen, si->peername.sa_socklen);
4488 memcpy(name, &si->peername.sa.ss, len);
4489 *addrlen = si->peername.sa_socklen;
4493 SWRAP_UNLOCK_SI(si);
4498 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4499 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4501 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4504 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4507 /****************************************************************************
4509 ***************************************************************************/
4511 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4513 struct socket_info *si = find_socket_info(s);
4518 return libc_getsockname(s, name, addrlen);
4523 len = MIN(*addrlen, si->myname.sa_socklen);
4529 memcpy(name, &si->myname.sa.ss, len);
4530 *addrlen = si->myname.sa_socklen;
4534 SWRAP_UNLOCK_SI(si);
4539 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4540 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4542 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4545 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4548 /****************************************************************************
4550 ***************************************************************************/
4553 # ifdef SO_PROTOTYPE /* The Solaris name */
4554 # define SO_PROTOCOL SO_PROTOTYPE
4555 # endif /* SO_PROTOTYPE */
4556 #endif /* SO_PROTOCOL */
4558 static int swrap_getsockopt(int s, int level, int optname,
4559 void *optval, socklen_t *optlen)
4561 struct socket_info *si = find_socket_info(s);
4565 return libc_getsockopt(s,
4574 if (level == SOL_SOCKET) {
4578 if (optval == NULL || optlen == NULL ||
4579 *optlen < (socklen_t)sizeof(int)) {
4585 *optlen = sizeof(int);
4586 *(int *)optval = si->family;
4589 #endif /* SO_DOMAIN */
4593 if (optval == NULL || optlen == NULL ||
4594 *optlen < (socklen_t)sizeof(int)) {
4600 *optlen = sizeof(int);
4601 *(int *)optval = si->protocol;
4604 #endif /* SO_PROTOCOL */
4606 if (optval == NULL || optlen == NULL ||
4607 *optlen < (socklen_t)sizeof(int)) {
4613 *optlen = sizeof(int);
4614 *(int *)optval = si->type;
4618 ret = libc_getsockopt(s,
4625 } else if (level == IPPROTO_TCP) {
4630 * This enables sending packets directly out over TCP.
4631 * As a unix socket is doing that any way, report it as
4634 if (optval == NULL || optlen == NULL ||
4635 *optlen < (socklen_t)sizeof(int)) {
4641 *optlen = sizeof(int);
4642 *(int *)optval = si->tcp_nodelay;
4646 #endif /* TCP_NODELAY */
4649 struct tcp_info info;
4650 socklen_t ilen = sizeof(info);
4652 #ifdef HAVE_NETINET_TCP_FSM_H
4653 /* This is FreeBSD */
4654 # define __TCP_LISTEN TCPS_LISTEN
4655 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4656 # define __TCP_CLOSE TCPS_CLOSED
4659 # define __TCP_LISTEN TCP_LISTEN
4660 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4661 # define __TCP_CLOSE TCP_CLOSE
4665 if (si->listening) {
4666 info.tcpi_state = __TCP_LISTEN;
4667 } else if (si->connected) {
4669 * For now we just fake a few values
4670 * supported both by FreeBSD and Linux
4672 info.tcpi_state = __TCP_ESTABLISHED;
4673 info.tcpi_rto = 200000; /* 200 msec */
4674 info.tcpi_rtt = 5000; /* 5 msec */
4675 info.tcpi_rttvar = 5000; /* 5 msec */
4677 info.tcpi_state = __TCP_CLOSE;
4678 info.tcpi_rto = 1000000; /* 1 sec */
4680 info.tcpi_rttvar = 250000; /* 250 msec */
4683 if (optval == NULL || optlen == NULL ||
4684 *optlen < (socklen_t)ilen) {
4691 memcpy(optval, &info, ilen);
4696 #endif /* TCP_INFO */
4702 errno = ENOPROTOOPT;
4706 SWRAP_UNLOCK_SI(si);
4710 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4711 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4713 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4716 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4719 /****************************************************************************
4721 ***************************************************************************/
4723 static int swrap_setsockopt(int s, int level, int optname,
4724 const void *optval, socklen_t optlen)
4726 struct socket_info *si = find_socket_info(s);
4730 return libc_setsockopt(s,
4737 if (level == SOL_SOCKET) {
4738 return libc_setsockopt(s,
4747 if (level == IPPROTO_TCP) {
4754 * This enables sending packets directly out over TCP.
4755 * A unix socket is doing that any way.
4757 if (optval == NULL || optlen == 0 ||
4758 optlen < (socklen_t)sizeof(int)) {
4764 i = *discard_const_p(int, optval);
4765 if (i != 0 && i != 1) {
4770 si->tcp_nodelay = i;
4775 #endif /* TCP_NODELAY */
4781 switch (si->family) {
4783 if (level == IPPROTO_IP) {
4785 if (optname == IP_PKTINFO) {
4786 si->pktinfo = AF_INET;
4788 #endif /* IP_PKTINFO */
4794 if (level == IPPROTO_IPV6) {
4795 #ifdef IPV6_RECVPKTINFO
4796 if (optname == IPV6_RECVPKTINFO) {
4797 si->pktinfo = AF_INET6;
4799 #endif /* IPV6_PKTINFO */
4805 errno = ENOPROTOOPT;
4811 SWRAP_UNLOCK_SI(si);
4815 int setsockopt(int s, int level, int optname,
4816 const void *optval, socklen_t optlen)
4818 return swrap_setsockopt(s, level, optname, optval, optlen);
4821 /****************************************************************************
4823 ***************************************************************************/
4825 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4827 struct socket_info *si = find_socket_info(s);
4829 int *value_ptr = NULL;
4833 return libc_vioctl(s, r, va);
4840 rc = libc_vioctl(s, r, va);
4845 value_ptr = ((int *)va_arg(ap, int *));
4848 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4849 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4850 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4851 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4856 /* this is FreeBSD */
4857 FALL_THROUGH; /* to TIOCOUTQ */
4858 #endif /* FIONWRITE */
4859 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4861 * This may return more bytes then the application
4862 * sent into the socket, for tcp it should
4863 * return the number of unacked bytes.
4865 * On AF_UNIX, all bytes are immediately acked!
4868 value_ptr = ((int *)va_arg(ap, int *));
4876 SWRAP_UNLOCK_SI(si);
4880 #ifdef HAVE_IOCTL_INT
4881 int ioctl(int s, int r, ...)
4883 int ioctl(int s, unsigned long int r, ...)
4891 rc = swrap_vioctl(s, (unsigned long int) r, va);
4902 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4905 # ifdef _ALIGN /* BSD */
4906 #define CMSG_ALIGN _ALIGN
4908 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4909 # endif /* _ALIGN */
4910 #endif /* CMSG_ALIGN */
4913 * @brief Add a cmsghdr to a msghdr.
4915 * This is an function to add any type of cmsghdr. It will operate on the
4916 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4917 * the buffer position after the added cmsg element. Hence, this function is
4918 * intended to be used with an intermediate msghdr and not on the original
4919 * one handed in by the client.
4921 * @param[in] msg The msghdr to which to add the cmsg.
4923 * @param[in] level The cmsg level to set.
4925 * @param[in] type The cmsg type to set.
4927 * @param[in] data The cmsg data to set.
4929 * @param[in] len the length of the data to set.
4931 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4937 size_t cmlen = CMSG_LEN(len);
4938 size_t cmspace = CMSG_SPACE(len);
4939 uint8_t cmbuf[cmspace];
4940 void *cast_ptr = (void *)cmbuf;
4941 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4944 memset(cmbuf, 0, cmspace);
4946 if (msg->msg_controllen < cmlen) {
4947 cmlen = msg->msg_controllen;
4948 msg->msg_flags |= MSG_CTRUNC;
4951 if (msg->msg_controllen < cmspace) {
4952 cmspace = msg->msg_controllen;
4956 * We copy the full input data into an intermediate cmsghdr first
4957 * in order to more easily cope with truncation.
4959 cm->cmsg_len = cmlen;
4960 cm->cmsg_level = level;
4961 cm->cmsg_type = type;
4962 memcpy(CMSG_DATA(cm), data, len);
4965 * We now copy the possibly truncated buffer.
4966 * We copy cmlen bytes, but consume cmspace bytes,
4967 * leaving the possible padding uninitialiazed.
4969 p = (uint8_t *)msg->msg_control;
4970 memcpy(p, cm, cmlen);
4972 msg->msg_control = p;
4973 msg->msg_controllen -= cmspace;
4978 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4981 /* Add packet info */
4982 switch (si->pktinfo) {
4983 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4985 struct sockaddr_in *sin;
4986 #if defined(HAVE_STRUCT_IN_PKTINFO)
4987 struct in_pktinfo pkt;
4988 #elif defined(IP_RECVDSTADDR)
4992 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4993 sin = &si->bindname.sa.in;
4995 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4998 sin = &si->myname.sa.in;
5003 #if defined(HAVE_STRUCT_IN_PKTINFO)
5004 pkt.ipi_ifindex = socket_wrapper_default_iface();
5005 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5006 #elif defined(IP_RECVDSTADDR)
5007 pkt = sin->sin_addr;
5010 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5015 #endif /* IP_PKTINFO */
5016 #if defined(HAVE_IPV6)
5018 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5019 struct sockaddr_in6 *sin6;
5020 struct in6_pktinfo pkt6;
5022 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5023 sin6 = &si->bindname.sa.in6;
5025 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5028 sin6 = &si->myname.sa.in6;
5033 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5034 pkt6.ipi6_addr = sin6->sin6_addr;
5036 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5037 &pkt6, sizeof(pkt6));
5038 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5042 #endif /* IPV6_PKTINFO */
5050 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5051 struct msghdr *omsg)
5055 if (si->pktinfo > 0) {
5056 rc = swrap_msghdr_add_pktinfo(si, omsg);
5062 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5064 size_t *cm_data_space);
5065 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5067 size_t *cm_data_space);
5068 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5070 size_t *cm_data_space);
5072 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5074 size_t *cm_data_space)
5076 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5077 struct cmsghdr *cmsg;
5081 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5085 for (cmsg = CMSG_FIRSTHDR(msg);
5087 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5088 switch (cmsg->cmsg_level) {
5090 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5095 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5100 rc = swrap_sendmsg_copy_cmsg(cmsg,
5106 int saved_errno = errno;
5107 SAFE_FREE(*cm_data);
5109 errno = saved_errno;
5117 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5119 size_t *cm_data_space)
5124 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5126 p = realloc((*cm_data), cmspace);
5132 p = (*cm_data) + (*cm_data_space);
5133 *cm_data_space = cmspace;
5135 memcpy(p, cmsg, cmsg->cmsg_len);
5140 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5142 size_t *cm_data_space);
5145 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5147 size_t *cm_data_space)
5151 switch(cmsg->cmsg_type) {
5154 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5161 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5173 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5175 size_t *cm_data_space)
5177 (void)cmsg; /* unused */
5178 (void)cm_data; /* unused */
5179 (void)cm_data_space; /* unused */
5182 * Passing a IP pktinfo to a unix socket might be rejected by the
5183 * Kernel, at least on FreeBSD. So skip this cmsg.
5188 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5190 size_t *cm_data_space)
5194 switch (cmsg->cmsg_type) {
5196 SWRAP_LOG(SWRAP_LOG_TRACE,
5197 "Ignoring SCM_RIGHTS on inet socket!");
5200 #ifdef SCM_CREDENTIALS
5201 case SCM_CREDENTIALS:
5202 SWRAP_LOG(SWRAP_LOG_TRACE,
5203 "Ignoring SCM_CREDENTIALS on inet socket!");
5206 #endif /* SCM_CREDENTIALS */
5208 rc = swrap_sendmsg_copy_cmsg(cmsg,
5217 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5220 * We only allow up to 6 fds at a time
5221 * as that's more than enough for Samba
5222 * and it means we can keep the logic simple
5223 * and work with fixed size arrays.
5225 * We also keep sizeof(struct swrap_unix_scm_rights)
5226 * under PIPE_BUF (4096) in order to allow a non-blocking
5227 * write into the pipe.
5230 #define PIPE_BUF 4096
5232 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5233 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5234 struct swrap_unix_scm_rights_payload {
5236 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5237 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5239 struct swrap_unix_scm_rights {
5241 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5242 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5244 uint32_t payload_size;
5245 struct swrap_unix_scm_rights_payload payload;
5248 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5250 int saved_errno = errno;
5253 for (i = 0; i < num; i++) {
5254 struct socket_info *si = array[i];
5260 swrap_dec_refcount(si);
5261 if (si->fd_passed > 0) {
5264 SWRAP_UNLOCK_SI(si);
5268 errno = saved_errno;
5271 static void swrap_undo_si_idx_array(size_t num, int *array)
5273 int saved_errno = errno;
5276 swrap_mutex_lock(&first_free_mutex);
5278 for (i = 0; i < num; i++) {
5279 struct socket_info *si = NULL;
5281 if (array[i] == -1) {
5285 si = swrap_get_socket_info(array[i]);
5291 swrap_dec_refcount(si);
5292 SWRAP_UNLOCK_SI(si);
5294 swrap_set_next_free(si, first_free);
5295 first_free = array[i];
5299 swrap_mutex_unlock(&first_free_mutex);
5300 errno = saved_errno;
5303 static void swrap_close_fd_array(size_t num, const int *array)
5305 int saved_errno = errno;
5308 for (i = 0; i < num; i++) {
5309 if (array[i] == -1) {
5312 libc_close(array[i]);
5315 errno = saved_errno;
5323 union __swrap_cmsghdr {
5325 struct cmsghdr *cmsg;
5328 static int swrap_sendmsg_unix_scm_rights(struct cmsghdr *cmsg,
5330 size_t *cm_data_space,
5331 int *scm_rights_pipe_fd)
5333 struct swrap_unix_scm_rights info;
5334 struct swrap_unix_scm_rights_payload *payload = NULL;
5335 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5336 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5337 size_t info_idx = 0;
5340 union __swrap_fds __fds_in = { .p = NULL, };
5341 const int *fds_in = NULL;
5343 size_t size_fds_out;
5344 union __swrap_fds __fds_out = { .p = NULL, };
5345 int *fds_out = NULL;
5348 size_t new_cm_data_space;
5349 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5350 struct cmsghdr *new_cmsg = NULL;
5353 int pipefd[2] = { -1, -1 };
5358 * We pass this a buffer to the kernel make sure any padding
5362 info.magic = swrap_unix_scm_right_magic;
5363 memcpy(info.package_name,
5364 SOCKET_WRAPPER_PACKAGE,
5365 sizeof(info.package_name));
5366 memcpy(info.package_version,
5367 SOCKET_WRAPPER_VERSION,
5368 sizeof(info.package_version));
5369 info.full_size = sizeof(info);
5370 info.payload_size = sizeof(info.payload);
5371 payload = &info.payload;
5373 if (*scm_rights_pipe_fd != -1) {
5374 SWRAP_LOG(SWRAP_LOG_ERROR,
5375 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5380 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5381 SWRAP_LOG(SWRAP_LOG_ERROR,
5382 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5383 (size_t)cmsg->cmsg_len,
5388 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5389 if ((size_fds_in % sizeof(int)) != 0) {
5390 SWRAP_LOG(SWRAP_LOG_ERROR,
5391 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5392 (size_t)cmsg->cmsg_len,
5398 num_fds_in = size_fds_in / sizeof(int);
5399 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5400 SWRAP_LOG(SWRAP_LOG_ERROR,
5401 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5403 "SWRAP_MAX_PASSED_FDS(%zu)",
5404 (size_t)cmsg->cmsg_len,
5407 SWRAP_MAX_PASSED_FDS);
5411 if (num_fds_in == 0) {
5412 SWRAP_LOG(SWRAP_LOG_ERROR,
5413 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5415 (size_t)cmsg->cmsg_len,
5421 __fds_in.p = CMSG_DATA(cmsg);
5422 fds_in = __fds_in.fds;
5423 num_fds_out = num_fds_in + 1;
5425 SWRAP_LOG(SWRAP_LOG_TRACE,
5426 "num_fds_in=%zu num_fds_out=%zu",
5427 num_fds_in, num_fds_out);
5429 size_fds_out = sizeof(int) * num_fds_out;
5430 cmsg_len = CMSG_LEN(size_fds_out);
5431 cmsg_space = CMSG_SPACE(size_fds_out);
5433 new_cm_data_space = *cm_data_space + cmsg_space;
5435 p = realloc((*cm_data), new_cm_data_space);
5440 p = (*cm_data) + (*cm_data_space);
5441 memset(p, 0, cmsg_space);
5443 new_cmsg = __new_cmsg.cmsg;
5445 __fds_out.p = CMSG_DATA(new_cmsg);
5446 fds_out = __fds_out.fds;
5447 memcpy(fds_out, fds_in, size_fds_in);
5448 new_cmsg->cmsg_len = cmsg->cmsg_len;
5450 for (i = 0; i < num_fds_in; i++) {
5453 payload->idxs[i] = -1;
5454 payload->num_idxs++;
5456 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5457 if (si_idx_array[i] == -1) {
5461 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5462 if (si_array[i] == NULL) {
5463 SWRAP_LOG(SWRAP_LOG_ERROR,
5464 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5465 i, fds_in[i], i, si_idx_array[i]);
5470 for (j = 0; j < i; j++) {
5471 if (si_array[j] == si_array[i]) {
5472 payload->idxs[i] = payload->idxs[j];
5476 if (payload->idxs[i] == -1) {
5477 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5478 SWRAP_LOG(SWRAP_LOG_ERROR,
5479 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5480 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5481 i, fds_in[i], i, si_idx_array[i],
5483 SWRAP_MAX_PASSED_SOCKET_INFO);
5487 payload->idxs[i] = info_idx;
5493 for (i = 0; i < num_fds_in; i++) {
5494 struct socket_info *si = si_array[i];
5497 SWRAP_LOG(SWRAP_LOG_TRACE,
5498 "fds_in[%zu]=%d not an inet socket",
5503 SWRAP_LOG(SWRAP_LOG_TRACE,
5504 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5505 "passing as info.idxs[%zu]=%d!",
5508 i, payload->idxs[i]);
5512 payload->infos[payload->idxs[i]] = *si;
5513 payload->infos[payload->idxs[i]].fd_passed = 0;
5514 SWRAP_UNLOCK_SI(si);
5519 int saved_errno = errno;
5520 SWRAP_LOG(SWRAP_LOG_ERROR,
5521 "pipe() failed - %d %s",
5523 strerror(saved_errno));
5524 swrap_dec_fd_passed_array(num_fds_in, si_array);
5525 errno = saved_errno;
5529 sret = libc_write(pipefd[1], &info, sizeof(info));
5530 if (sret != sizeof(info)) {
5531 int saved_errno = errno;
5533 saved_errno = EINVAL;
5535 SWRAP_LOG(SWRAP_LOG_ERROR,
5536 "write() failed - sret=%zd - %d %s",
5538 strerror(saved_errno));
5539 swrap_dec_fd_passed_array(num_fds_in, si_array);
5540 libc_close(pipefd[1]);
5541 libc_close(pipefd[0]);
5542 errno = saved_errno;
5545 libc_close(pipefd[1]);
5548 * Add the pipe read end to the end of the passed fd array
5550 fds_out[num_fds_in] = pipefd[0];
5551 new_cmsg->cmsg_len = cmsg_len;
5553 /* we're done ... */
5554 *scm_rights_pipe_fd = pipefd[0];
5555 *cm_data_space = new_cm_data_space;
5560 static int swrap_sendmsg_unix_sol_socket(struct cmsghdr *cmsg,
5562 size_t *cm_data_space,
5563 int *scm_rights_pipe_fd)
5567 switch (cmsg->cmsg_type) {
5569 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5572 scm_rights_pipe_fd);
5575 rc = swrap_sendmsg_copy_cmsg(cmsg,
5584 static int swrap_recvmsg_unix_scm_rights(struct cmsghdr *cmsg,
5586 size_t *cm_data_space)
5588 int scm_rights_pipe_fd = -1;
5589 struct swrap_unix_scm_rights info;
5590 struct swrap_unix_scm_rights_payload *payload = NULL;
5591 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5594 union __swrap_fds __fds_in = { .p = NULL, };
5595 const int *fds_in = NULL;
5597 size_t size_fds_out;
5598 union __swrap_fds __fds_out = { .p = NULL, };
5599 int *fds_out = NULL;
5602 size_t new_cm_data_space;
5603 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5604 struct cmsghdr *new_cmsg = NULL;
5610 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5611 SWRAP_LOG(SWRAP_LOG_ERROR,
5612 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5613 (size_t)cmsg->cmsg_len,
5618 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5619 if ((size_fds_in % sizeof(int)) != 0) {
5620 SWRAP_LOG(SWRAP_LOG_ERROR,
5621 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5622 (size_t)cmsg->cmsg_len,
5628 num_fds_in = size_fds_in / sizeof(int);
5629 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5630 SWRAP_LOG(SWRAP_LOG_ERROR,
5631 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5632 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5633 (size_t)cmsg->cmsg_len,
5636 SWRAP_MAX_PASSED_FDS+1);
5640 if (num_fds_in <= 1) {
5641 SWRAP_LOG(SWRAP_LOG_ERROR,
5642 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5644 (size_t)cmsg->cmsg_len,
5650 __fds_in.p = CMSG_DATA(cmsg);
5651 fds_in = __fds_in.fds;
5652 num_fds_out = num_fds_in - 1;
5654 SWRAP_LOG(SWRAP_LOG_TRACE,
5655 "num_fds_in=%zu num_fds_out=%zu",
5656 num_fds_in, num_fds_out);
5658 for (i = 0; i < num_fds_in; i++) {
5659 /* Check if we have a stale fd and remove it */
5660 swrap_remove_stale(fds_in[i]);
5663 scm_rights_pipe_fd = fds_in[num_fds_out];
5664 size_fds_out = sizeof(int) * num_fds_out;
5665 cmsg_len = CMSG_LEN(size_fds_out);
5666 cmsg_space = CMSG_SPACE(size_fds_out);
5668 new_cm_data_space = *cm_data_space + cmsg_space;
5670 p = realloc((*cm_data), new_cm_data_space);
5672 swrap_close_fd_array(num_fds_in, fds_in);
5676 p = (*cm_data) + (*cm_data_space);
5677 memset(p, 0, cmsg_space);
5679 new_cmsg = __new_cmsg.cmsg;
5681 __fds_out.p = CMSG_DATA(new_cmsg);
5682 fds_out = __fds_out.fds;
5683 memcpy(fds_out, fds_in, size_fds_out);
5684 new_cmsg->cmsg_len = cmsg_len;
5686 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5687 if (sret != sizeof(info)) {
5688 int saved_errno = errno;
5690 saved_errno = EINVAL;
5692 SWRAP_LOG(SWRAP_LOG_ERROR,
5693 "read() failed - sret=%zd - %d %s",
5695 strerror(saved_errno));
5696 swrap_close_fd_array(num_fds_in, fds_in);
5697 errno = saved_errno;
5700 libc_close(scm_rights_pipe_fd);
5701 payload = &info.payload;
5703 if (info.magic != swrap_unix_scm_right_magic) {
5704 SWRAP_LOG(SWRAP_LOG_ERROR,
5705 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5706 (unsigned long long)info.magic,
5707 (unsigned long long)swrap_unix_scm_right_magic);
5708 swrap_close_fd_array(num_fds_out, fds_out);
5713 cmp = memcmp(info.package_name,
5714 SOCKET_WRAPPER_PACKAGE,
5715 sizeof(info.package_name));
5717 SWRAP_LOG(SWRAP_LOG_ERROR,
5718 "info.package_name='%.*s' != '%s'",
5719 (int)sizeof(info.package_name),
5721 SOCKET_WRAPPER_PACKAGE);
5722 swrap_close_fd_array(num_fds_out, fds_out);
5727 cmp = memcmp(info.package_version,
5728 SOCKET_WRAPPER_VERSION,
5729 sizeof(info.package_version));
5731 SWRAP_LOG(SWRAP_LOG_ERROR,
5732 "info.package_version='%.*s' != '%s'",
5733 (int)sizeof(info.package_version),
5734 info.package_version,
5735 SOCKET_WRAPPER_VERSION);
5736 swrap_close_fd_array(num_fds_out, fds_out);
5741 if (info.full_size != sizeof(info)) {
5742 SWRAP_LOG(SWRAP_LOG_ERROR,
5743 "info.full_size=%zu != sizeof(info)=%zu",
5744 (size_t)info.full_size,
5746 swrap_close_fd_array(num_fds_out, fds_out);
5751 if (info.payload_size != sizeof(info.payload)) {
5752 SWRAP_LOG(SWRAP_LOG_ERROR,
5753 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5754 (size_t)info.payload_size,
5755 sizeof(info.payload));
5756 swrap_close_fd_array(num_fds_out, fds_out);
5761 if (payload->num_idxs != num_fds_out) {
5762 SWRAP_LOG(SWRAP_LOG_ERROR,
5763 "info.num_idxs=%u != num_fds_out=%zu",
5764 payload->num_idxs, num_fds_out);
5765 swrap_close_fd_array(num_fds_out, fds_out);
5770 for (i = 0; i < num_fds_out; i++) {
5773 si_idx_array[i] = -1;
5775 if (payload->idxs[i] == -1) {
5776 SWRAP_LOG(SWRAP_LOG_TRACE,
5777 "fds_out[%zu]=%d not an inet socket",
5782 if (payload->idxs[i] < 0) {
5783 SWRAP_LOG(SWRAP_LOG_ERROR,
5784 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5785 i, fds_out[i], i, payload->idxs[i]);
5786 swrap_close_fd_array(num_fds_out, fds_out);
5791 if (payload->idxs[i] >= payload->num_idxs) {
5792 SWRAP_LOG(SWRAP_LOG_ERROR,
5793 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5794 i, fds_out[i], i, payload->idxs[i],
5796 swrap_close_fd_array(num_fds_out, fds_out);
5801 if ((size_t)fds_out[i] >= socket_fds_max) {
5802 SWRAP_LOG(SWRAP_LOG_ERROR,
5803 "The max socket index limit of %zu has been reached, "
5807 swrap_close_fd_array(num_fds_out, fds_out);
5812 SWRAP_LOG(SWRAP_LOG_TRACE,
5814 "received as info.idxs[%zu]=%d!",
5816 i, payload->idxs[i]);
5818 for (j = 0; j < i; j++) {
5819 if (payload->idxs[j] == -1) {
5822 if (payload->idxs[j] == payload->idxs[i]) {
5823 si_idx_array[i] = si_idx_array[j];
5826 if (si_idx_array[i] == -1) {
5827 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5829 si_idx_array[i] = swrap_add_socket_info(si);
5830 if (si_idx_array[i] == -1) {
5831 int saved_errno = errno;
5832 SWRAP_LOG(SWRAP_LOG_ERROR,
5833 "The max socket index limit of %zu has been reached, "
5837 swrap_undo_si_idx_array(i, si_idx_array);
5838 swrap_close_fd_array(num_fds_out, fds_out);
5839 errno = saved_errno;
5842 SWRAP_LOG(SWRAP_LOG_TRACE,
5843 "Imported %s socket for protocol %s, fd=%d",
5844 si->family == AF_INET ? "IPv4" : "IPv6",
5845 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5850 for (i = 0; i < num_fds_out; i++) {
5851 if (si_idx_array[i] == -1) {
5854 set_socket_info_index(fds_out[i], si_idx_array[i]);
5857 /* we're done ... */
5858 *cm_data_space = new_cm_data_space;
5863 static int swrap_recvmsg_unix_sol_socket(struct cmsghdr *cmsg,
5865 size_t *cm_data_space)
5869 switch (cmsg->cmsg_type) {
5871 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5876 rc = swrap_sendmsg_copy_cmsg(cmsg,
5885 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5887 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5888 struct msghdr *msg_tmp,
5889 int *scm_rights_pipe_fd)
5891 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5892 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5893 struct cmsghdr *cmsg = NULL;
5894 uint8_t *cm_data = NULL;
5895 size_t cm_data_space = 0;
5899 *scm_rights_pipe_fd = -1;
5902 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5906 for (cmsg = CMSG_FIRSTHDR(msg_in);
5908 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5909 switch (cmsg->cmsg_level) {
5911 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5914 scm_rights_pipe_fd);
5918 rc = swrap_sendmsg_copy_cmsg(cmsg,
5924 int saved_errno = errno;
5926 errno = saved_errno;
5931 msg_tmp->msg_controllen = cm_data_space;
5932 msg_tmp->msg_control = cm_data;
5935 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5936 *msg_tmp = *_msg_in;
5938 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5941 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5943 int scm_rights_pipe_fd)
5945 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5946 int saved_errno = errno;
5947 SAFE_FREE(msg_tmp->msg_control);
5948 if (scm_rights_pipe_fd != -1) {
5949 libc_close(scm_rights_pipe_fd);
5951 errno = saved_errno;
5952 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5956 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5957 struct msghdr *msg_tmp,
5958 uint8_t **tmp_control)
5960 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5961 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
5962 uint8_t *cm_data = NULL;
5963 size_t cm_data_space = 0;
5966 *tmp_control = NULL;
5968 SWRAP_LOG(SWRAP_LOG_TRACE,
5969 "msg_in->msg_controllen=%zu",
5970 (size_t)msg_in->msg_controllen);
5973 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5978 * We need to give the kernel a bit more space in order
5979 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
5980 * swrap_recvmsg_after_unix() will hide it again.
5982 cm_data_space = msg_in->msg_controllen;
5983 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
5984 cm_data_space += cm_extra_space;
5986 cm_data = calloc(1, cm_data_space);
5987 if (cm_data == NULL) {
5991 msg_tmp->msg_controllen = cm_data_space;
5992 msg_tmp->msg_control = cm_data;
5993 *tmp_control = cm_data;
5995 SWRAP_LOG(SWRAP_LOG_TRACE,
5996 "msg_tmp->msg_controllen=%zu",
5997 (size_t)msg_tmp->msg_controllen);
5999 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6001 *tmp_control = NULL;
6003 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6006 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6007 uint8_t **tmp_control,
6008 struct msghdr *msg_out,
6011 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6012 struct cmsghdr *cmsg = NULL;
6013 uint8_t *cm_data = NULL;
6014 size_t cm_data_space = 0;
6018 int saved_errno = errno;
6019 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6020 saved_errno, strerror(saved_errno));
6021 SAFE_FREE(*tmp_control);
6022 /* msg_out should not be touched on error */
6023 errno = saved_errno;
6027 SWRAP_LOG(SWRAP_LOG_TRACE,
6028 "msg_tmp->msg_controllen=%zu",
6029 (size_t)msg_tmp->msg_controllen);
6032 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6033 int saved_errno = errno;
6034 *msg_out = *msg_tmp;
6035 SAFE_FREE(*tmp_control);
6036 errno = saved_errno;
6040 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6042 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6043 switch (cmsg->cmsg_level) {
6045 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6051 rc = swrap_sendmsg_copy_cmsg(cmsg,
6057 int saved_errno = errno;
6059 SAFE_FREE(*tmp_control);
6060 errno = saved_errno;
6066 * msg_tmp->msg_control (*tmp_control) was created by
6067 * swrap_recvmsg_before_unix() and msg_out->msg_control
6068 * is still the buffer of the caller.
6070 msg_tmp->msg_control = msg_out->msg_control;
6071 msg_tmp->msg_controllen = msg_out->msg_controllen;
6072 *msg_out = *msg_tmp;
6074 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6075 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6076 msg_out->msg_controllen = cm_data_space;
6078 SAFE_FREE(*tmp_control);
6080 SWRAP_LOG(SWRAP_LOG_TRACE,
6081 "msg_out->msg_controllen=%zu",
6082 (size_t)msg_out->msg_controllen);
6084 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6085 int saved_errno = errno;
6086 *msg_out = *msg_tmp;
6087 SAFE_FREE(*tmp_control);
6088 errno = saved_errno;
6090 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6093 static ssize_t swrap_sendmsg_before(int fd,
6094 struct socket_info *si,
6096 struct iovec *tmp_iov,
6097 struct sockaddr_un *tmp_un,
6098 const struct sockaddr_un **to_un,
6099 const struct sockaddr **to,
6121 if (!si->connected) {
6126 if (msg->msg_iovlen == 0) {
6130 mtu = socket_wrapper_mtu();
6131 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6133 nlen = len + msg->msg_iov[i].iov_len;
6143 msg->msg_iovlen = i;
6144 if (msg->msg_iovlen == 0) {
6145 *tmp_iov = msg->msg_iov[0];
6146 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6148 msg->msg_iov = tmp_iov;
6149 msg->msg_iovlen = 1;
6154 if (si->connected) {
6155 if (msg->msg_name != NULL) {
6157 * We are dealing with unix sockets and if we
6158 * are connected, we should only talk to the
6159 * connected unix path. Using the fd to send
6160 * to another server would be hard to achieve.
6162 msg->msg_name = NULL;
6163 msg->msg_namelen = 0;
6166 const struct sockaddr *msg_name;
6167 msg_name = (const struct sockaddr *)msg->msg_name;
6169 if (msg_name == NULL) {
6175 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6187 msg->msg_name = tmp_un;
6188 msg->msg_namelen = sizeof(*tmp_un);
6191 if (si->bound == 0) {
6192 ret = swrap_auto_bind(fd, si, si->family);
6194 SWRAP_UNLOCK_SI(si);
6195 if (errno == ENOTSOCK) {
6196 swrap_remove_stale(fd);
6199 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6205 if (!si->defer_connect) {
6209 ret = sockaddr_convert_to_un(si,
6211 si->peername.sa_socklen,
6219 ret = libc_connect(fd,
6220 (struct sockaddr *)(void *)tmp_un,
6223 /* to give better errors */
6224 if (ret == -1 && errno == ENOENT) {
6225 errno = EHOSTUNREACH;
6232 si->defer_connect = 0;
6235 errno = EHOSTUNREACH;
6241 SWRAP_UNLOCK_SI(si);
6246 static void swrap_sendmsg_after(int fd,
6247 struct socket_info *si,
6249 const struct sockaddr *to,
6252 int saved_errno = errno;
6259 /* to give better errors */
6261 if (saved_errno == ENOENT) {
6262 saved_errno = EHOSTUNREACH;
6263 } else if (saved_errno == ENOTSOCK) {
6264 /* If the fd is not a socket, remove it */
6265 swrap_remove_stale(fd);
6269 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6270 avail += msg->msg_iov[i].iov_len;
6274 remain = MIN(80, avail);
6279 /* we capture it as one single packet */
6280 buf = (uint8_t *)malloc(remain);
6282 /* we just not capture the packet */
6283 errno = saved_errno;
6287 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6288 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6289 if (this_time > 0) {
6291 msg->msg_iov[i].iov_base,
6295 remain -= this_time;
6304 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6305 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6307 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6312 if (si->connected) {
6313 to = &si->peername.sa.s;
6316 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6317 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6319 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6324 SWRAP_UNLOCK_SI(si);
6327 errno = saved_errno;
6330 static int swrap_recvmsg_before(int fd,
6331 struct socket_info *si,
6333 struct iovec *tmp_iov)
6340 (void)fd; /* unused */
6345 if (!si->connected) {
6350 if (msg->msg_iovlen == 0) {
6354 mtu = socket_wrapper_mtu();
6355 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6357 nlen = len + msg->msg_iov[i].iov_len;
6362 msg->msg_iovlen = i;
6363 if (msg->msg_iovlen == 0) {
6364 *tmp_iov = msg->msg_iov[0];
6365 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6367 msg->msg_iov = tmp_iov;
6368 msg->msg_iovlen = 1;
6373 if (msg->msg_name == NULL) {
6378 if (msg->msg_iovlen == 0) {
6382 if (si->bound == 0) {
6383 ret = swrap_auto_bind(fd, si, si->family);
6385 SWRAP_UNLOCK_SI(si);
6387 * When attempting to read or write to a
6388 * descriptor, if an underlying autobind fails
6389 * because it's not a socket, stop intercepting
6390 * uses of that descriptor.
6392 if (errno == ENOTSOCK) {
6393 swrap_remove_stale(fd);
6396 SWRAP_LOG(SWRAP_LOG_ERROR,
6397 "swrap_recvmsg_before failed");
6404 errno = EHOSTUNREACH;
6410 SWRAP_UNLOCK_SI(si);
6415 static int swrap_recvmsg_after(int fd,
6416 struct socket_info *si,
6418 const struct sockaddr_un *un_addr,
6419 socklen_t un_addrlen,
6422 int saved_errno = errno;
6424 uint8_t *buf = NULL;
6430 /* to give better errors */
6432 if (saved_errno == ENOENT) {
6433 saved_errno = EHOSTUNREACH;
6434 } else if (saved_errno == ENOTSOCK) {
6435 /* If the fd is not a socket, remove it */
6436 swrap_remove_stale(fd);
6440 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6441 avail += msg->msg_iov[i].iov_len;
6446 /* Convert the socket address before we leave */
6447 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6448 rc = sockaddr_convert_from_un(si,
6465 remain = MIN(80, avail);
6470 /* we capture it as one single packet */
6471 buf = (uint8_t *)malloc(remain);
6473 /* we just not capture the packet */
6474 SWRAP_UNLOCK_SI(si);
6475 errno = saved_errno;
6479 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6480 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6482 msg->msg_iov[i].iov_base,
6485 remain -= this_time;
6490 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6491 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6492 } else if (ret == 0) { /* END OF FILE */
6493 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6494 } else if (ret > 0) {
6495 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6504 if (un_addr != NULL) {
6505 swrap_pcap_dump_packet(si,
6511 swrap_pcap_dump_packet(si,
6524 errno = saved_errno;
6526 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6528 msg->msg_controllen > 0 &&
6529 msg->msg_control != NULL) {
6530 rc = swrap_msghdr_add_socket_info(si, msg);
6532 SWRAP_UNLOCK_SI(si);
6538 SWRAP_UNLOCK_SI(si);
6542 /****************************************************************************
6544 ***************************************************************************/
6546 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6547 struct sockaddr *from, socklen_t *fromlen)
6549 struct swrap_address from_addr = {
6550 .sa_socklen = sizeof(struct sockaddr_un),
6553 struct socket_info *si = find_socket_info(s);
6554 struct swrap_address saddr = {
6555 .sa_socklen = sizeof(struct sockaddr_storage),
6562 return libc_recvfrom(s,
6574 if (from != NULL && fromlen != NULL) {
6575 msg.msg_name = from; /* optional address */
6576 msg.msg_namelen = *fromlen; /* size of address */
6578 msg.msg_name = &saddr.sa.s; /* optional address */
6579 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6581 msg.msg_iov = &tmp; /* scatter/gather array */
6582 msg.msg_iovlen = 1; /* # elements in msg_iov */
6583 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6584 msg.msg_control = NULL; /* ancillary data, see below */
6585 msg.msg_controllen = 0; /* ancillary data buffer len */
6586 msg.msg_flags = 0; /* flags on received message */
6589 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6594 buf = msg.msg_iov[0].iov_base;
6595 len = msg.msg_iov[0].iov_len;
6597 ret = libc_recvfrom(s,
6602 &from_addr.sa_socklen);
6607 tret = swrap_recvmsg_after(s,
6611 from_addr.sa_socklen,
6617 if (from != NULL && fromlen != NULL) {
6618 *fromlen = msg.msg_namelen;
6624 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6625 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6626 struct sockaddr *from, Psocklen_t fromlen)
6628 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6629 struct sockaddr *from, socklen_t *fromlen)
6632 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6635 /****************************************************************************
6637 ***************************************************************************/
6639 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6640 const struct sockaddr *to, socklen_t tolen)
6644 struct swrap_address un_addr = {
6645 .sa_socklen = sizeof(struct sockaddr_un),
6647 const struct sockaddr_un *to_un = NULL;
6650 struct socket_info *si = find_socket_info(s);
6654 return libc_sendto(s, buf, len, flags, to, tolen);
6657 tmp.iov_base = discard_const_p(char, buf);
6661 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6662 msg.msg_namelen = tolen; /* size of address */
6663 msg.msg_iov = &tmp; /* scatter/gather array */
6664 msg.msg_iovlen = 1; /* # elements in msg_iov */
6665 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6666 msg.msg_control = NULL; /* ancillary data, see below */
6667 msg.msg_controllen = 0; /* ancillary data buffer len */
6668 msg.msg_flags = 0; /* flags on received message */
6671 rc = swrap_sendmsg_before(s,
6683 buf = msg.msg_iov[0].iov_base;
6684 len = msg.msg_iov[0].iov_len;
6689 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6691 char *swrap_dir = NULL;
6693 type = SOCKET_TYPE_CHAR_UDP;
6695 swrap_dir = socket_wrapper_dir();
6696 if (swrap_dir == NULL) {
6700 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6701 swrap_un_path(&un_addr.sa.un,
6706 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6708 /* ignore the any errors in broadcast sends */
6714 un_addr.sa_socklen);
6717 SAFE_FREE(swrap_dir);
6721 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6723 SWRAP_UNLOCK_SI(si);
6730 * If it is a dgram socket and we are connected, don't include the
6733 if (si->type == SOCK_DGRAM && si->connected) {
6734 ret = libc_sendto(s,
6741 ret = libc_sendto(s,
6745 (struct sockaddr *)msg.msg_name,
6749 SWRAP_UNLOCK_SI(si);
6751 swrap_sendmsg_after(s, si, &msg, to, ret);
6756 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6757 const struct sockaddr *to, socklen_t tolen)
6759 return swrap_sendto(s, buf, len, flags, to, tolen);
6762 /****************************************************************************
6764 ***************************************************************************/
6766 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6768 struct socket_info *si;
6770 struct swrap_address saddr = {
6771 .sa_socklen = sizeof(struct sockaddr_storage),
6777 si = find_socket_info(s);
6779 return libc_recv(s, buf, len, flags);
6786 msg.msg_name = &saddr.sa.s; /* optional address */
6787 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6788 msg.msg_iov = &tmp; /* scatter/gather array */
6789 msg.msg_iovlen = 1; /* # elements in msg_iov */
6790 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6791 msg.msg_control = NULL; /* ancillary data, see below */
6792 msg.msg_controllen = 0; /* ancillary data buffer len */
6793 msg.msg_flags = 0; /* flags on received message */
6796 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6801 buf = msg.msg_iov[0].iov_base;
6802 len = msg.msg_iov[0].iov_len;
6804 ret = libc_recv(s, buf, len, flags);
6806 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6814 ssize_t recv(int s, void *buf, size_t len, int flags)
6816 return swrap_recv(s, buf, len, flags);
6819 /****************************************************************************
6821 ***************************************************************************/
6823 static ssize_t swrap_read(int s, void *buf, size_t len)
6825 struct socket_info *si;
6828 struct swrap_address saddr = {
6829 .sa_socklen = sizeof(struct sockaddr_storage),
6834 si = find_socket_info(s);
6836 return libc_read(s, buf, len);
6843 msg.msg_name = &saddr.sa.ss; /* optional address */
6844 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6845 msg.msg_iov = &tmp; /* scatter/gather array */
6846 msg.msg_iovlen = 1; /* # elements in msg_iov */
6847 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6848 msg.msg_control = NULL; /* ancillary data, see below */
6849 msg.msg_controllen = 0; /* ancillary data buffer len */
6850 msg.msg_flags = 0; /* flags on received message */
6853 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6855 if (tret == -ENOTSOCK) {
6856 return libc_read(s, buf, len);
6861 buf = msg.msg_iov[0].iov_base;
6862 len = msg.msg_iov[0].iov_len;
6864 ret = libc_read(s, buf, len);
6866 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6874 ssize_t read(int s, void *buf, size_t len)
6876 return swrap_read(s, buf, len);
6879 /****************************************************************************
6881 ***************************************************************************/
6883 static ssize_t swrap_write(int s, const void *buf, size_t len)
6887 struct sockaddr_un un_addr;
6890 struct socket_info *si;
6892 si = find_socket_info(s);
6894 return libc_write(s, buf, len);
6897 tmp.iov_base = discard_const_p(char, buf);
6901 msg.msg_name = NULL; /* optional address */
6902 msg.msg_namelen = 0; /* size of address */
6903 msg.msg_iov = &tmp; /* scatter/gather array */
6904 msg.msg_iovlen = 1; /* # elements in msg_iov */
6905 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6906 msg.msg_control = NULL; /* ancillary data, see below */
6907 msg.msg_controllen = 0; /* ancillary data buffer len */
6908 msg.msg_flags = 0; /* flags on received message */
6911 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6916 buf = msg.msg_iov[0].iov_base;
6917 len = msg.msg_iov[0].iov_len;
6919 ret = libc_write(s, buf, len);
6921 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6926 ssize_t write(int s, const void *buf, size_t len)
6928 return swrap_write(s, buf, len);
6931 /****************************************************************************
6933 ***************************************************************************/
6935 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6939 struct sockaddr_un un_addr;
6942 struct socket_info *si = find_socket_info(s);
6945 return libc_send(s, buf, len, flags);
6948 tmp.iov_base = discard_const_p(char, buf);
6952 msg.msg_name = NULL; /* optional address */
6953 msg.msg_namelen = 0; /* size of address */
6954 msg.msg_iov = &tmp; /* scatter/gather array */
6955 msg.msg_iovlen = 1; /* # elements in msg_iov */
6956 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6957 msg.msg_control = NULL; /* ancillary data, see below */
6958 msg.msg_controllen = 0; /* ancillary data buffer len */
6959 msg.msg_flags = 0; /* flags on received message */
6962 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6967 buf = msg.msg_iov[0].iov_base;
6968 len = msg.msg_iov[0].iov_len;
6970 ret = libc_send(s, buf, len, flags);
6972 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6977 ssize_t send(int s, const void *buf, size_t len, int flags)
6979 return swrap_send(s, buf, len, flags);
6982 /****************************************************************************
6984 ***************************************************************************/
6986 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6988 struct swrap_address from_addr = {
6989 .sa_socklen = sizeof(struct sockaddr_un),
6991 struct swrap_address convert_addr = {
6992 .sa_socklen = sizeof(struct sockaddr_storage),
6994 struct socket_info *si;
6997 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6998 size_t msg_ctrllen_filled;
6999 size_t msg_ctrllen_left;
7005 si = find_socket_info(s);
7007 uint8_t *tmp_control = NULL;
7008 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7012 ret = libc_recvmsg(s, &msg, flags);
7013 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7016 tmp.iov_base = NULL;
7020 msg.msg_name = &from_addr.sa; /* optional address */
7021 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7022 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7023 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7024 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7025 msg_ctrllen_filled = 0;
7026 msg_ctrllen_left = omsg->msg_controllen;
7028 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7029 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7030 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7033 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7038 ret = libc_recvmsg(s, &msg, flags);
7040 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7041 msg_ctrllen_filled += msg.msg_controllen;
7042 msg_ctrllen_left -= msg.msg_controllen;
7044 if (omsg->msg_control != NULL) {
7047 p = omsg->msg_control;
7048 p += msg_ctrllen_filled;
7050 msg.msg_control = p;
7051 msg.msg_controllen = msg_ctrllen_left;
7053 msg.msg_control = NULL;
7054 msg.msg_controllen = 0;
7059 * We convert the unix address to a IP address so we need a buffer
7060 * which can store the address in case of SOCK_DGRAM, see below.
7062 msg.msg_name = &convert_addr.sa;
7063 msg.msg_namelen = convert_addr.sa_socklen;
7065 rc = swrap_recvmsg_after(s,
7069 from_addr.sa_socklen,
7075 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7076 if (omsg->msg_control != NULL) {
7077 /* msg.msg_controllen = space left */
7078 msg_ctrllen_left = msg.msg_controllen;
7079 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7082 /* Update the original message length */
7083 omsg->msg_controllen = msg_ctrllen_filled;
7084 omsg->msg_flags = msg.msg_flags;
7086 omsg->msg_iovlen = msg.msg_iovlen;
7093 * The msg_name field points to a caller-allocated buffer that is
7094 * used to return the source address if the socket is unconnected. The
7095 * caller should set msg_namelen to the size of this buffer before this
7096 * call; upon return from a successful call, msg_name will contain the
7097 * length of the returned address. If the application does not need
7098 * to know the source address, msg_name can be specified as NULL.
7100 if (si->type == SOCK_STREAM) {
7101 omsg->msg_namelen = 0;
7102 } else if (omsg->msg_name != NULL &&
7103 omsg->msg_namelen != 0 &&
7104 omsg->msg_namelen >= msg.msg_namelen) {
7105 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7106 omsg->msg_namelen = msg.msg_namelen;
7109 SWRAP_UNLOCK_SI(si);
7114 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7116 return swrap_recvmsg(sockfd, msg, flags);
7119 /****************************************************************************
7121 ***************************************************************************/
7123 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7127 struct sockaddr_un un_addr;
7128 const struct sockaddr_un *to_un = NULL;
7129 const struct sockaddr *to = NULL;
7132 struct socket_info *si = find_socket_info(s);
7136 int scm_rights_pipe_fd = -1;
7138 rc = swrap_sendmsg_before_unix(omsg, &msg,
7139 &scm_rights_pipe_fd);
7143 ret = libc_sendmsg(s, &msg, flags);
7144 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7147 ZERO_STRUCT(un_addr);
7149 tmp.iov_base = NULL;
7156 if (si->connected == 0) {
7157 msg.msg_name = omsg->msg_name; /* optional address */
7158 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7160 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7161 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7163 SWRAP_UNLOCK_SI(si);
7165 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7166 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7167 uint8_t *cmbuf = NULL;
7170 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7176 msg.msg_controllen = 0;
7177 msg.msg_control = NULL;
7179 msg.msg_control = cmbuf;
7180 msg.msg_controllen = cmlen;
7183 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7185 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7187 int saved_errno = errno;
7188 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7189 SAFE_FREE(msg.msg_control);
7191 errno = saved_errno;
7198 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7205 char *swrap_dir = NULL;
7207 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7208 avail += msg.msg_iov[i].iov_len;
7214 /* we capture it as one single packet */
7215 buf = (uint8_t *)malloc(remain);
7217 int saved_errno = errno;
7218 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7219 SAFE_FREE(msg.msg_control);
7221 errno = saved_errno;
7225 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7226 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7228 msg.msg_iov[i].iov_base,
7231 remain -= this_time;
7234 type = SOCKET_TYPE_CHAR_UDP;
7236 swrap_dir = socket_wrapper_dir();
7237 if (swrap_dir == NULL) {
7238 int saved_errno = errno;
7239 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7240 SAFE_FREE(msg.msg_control);
7243 errno = saved_errno;
7247 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7248 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7249 if (stat(un_addr.sun_path, &st) != 0) continue;
7251 msg.msg_name = &un_addr; /* optional address */
7252 msg.msg_namelen = sizeof(un_addr); /* size of address */
7254 /* ignore the any errors in broadcast sends */
7255 libc_sendmsg(s, &msg, flags);
7258 SAFE_FREE(swrap_dir);
7262 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7265 SWRAP_UNLOCK_SI(si);
7270 ret = libc_sendmsg(s, &msg, flags);
7272 swrap_sendmsg_after(s, si, &msg, to, ret);
7274 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7276 int saved_errno = errno;
7277 SAFE_FREE(msg.msg_control);
7278 errno = saved_errno;
7285 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7287 return swrap_sendmsg(s, omsg, flags);
7290 /****************************************************************************
7292 ***************************************************************************/
7294 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7296 struct socket_info *si;
7299 struct swrap_address saddr = {
7300 .sa_socklen = sizeof(struct sockaddr_storage)
7305 si = find_socket_info(s);
7307 return libc_readv(s, vector, count);
7310 tmp.iov_base = NULL;
7314 msg.msg_name = &saddr.sa.s; /* optional address */
7315 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7316 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7317 msg.msg_iovlen = count; /* # elements in msg_iov */
7318 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7319 msg.msg_control = NULL; /* ancillary data, see below */
7320 msg.msg_controllen = 0; /* ancillary data buffer len */
7321 msg.msg_flags = 0; /* flags on received message */
7324 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7326 if (rc == -ENOTSOCK) {
7327 return libc_readv(s, vector, count);
7332 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7334 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7342 ssize_t readv(int s, const struct iovec *vector, int count)
7344 return swrap_readv(s, vector, count);
7347 /****************************************************************************
7349 ***************************************************************************/
7351 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7355 struct sockaddr_un un_addr;
7358 struct socket_info *si = find_socket_info(s);
7361 return libc_writev(s, vector, count);
7364 tmp.iov_base = NULL;
7368 msg.msg_name = NULL; /* optional address */
7369 msg.msg_namelen = 0; /* size of address */
7370 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7371 msg.msg_iovlen = count; /* # elements in msg_iov */
7372 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7373 msg.msg_control = NULL; /* ancillary data, see below */
7374 msg.msg_controllen = 0; /* ancillary data buffer len */
7375 msg.msg_flags = 0; /* flags on received message */
7378 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7380 if (rc == -ENOTSOCK) {
7381 return libc_readv(s, vector, count);
7386 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7388 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7393 ssize_t writev(int s, const struct iovec *vector, int count)
7395 return swrap_writev(s, vector, count);
7398 /****************************
7400 ***************************/
7402 static int swrap_remove_wrapper(const char *__func_name,
7403 int (*__close_fd_fn)(int fd),
7406 struct socket_info *si = NULL;
7408 int ret_errno = errno;
7411 swrap_mutex_lock(&socket_reset_mutex);
7413 si_index = find_socket_info_index(fd);
7414 if (si_index == -1) {
7415 swrap_mutex_unlock(&socket_reset_mutex);
7416 return __close_fd_fn(fd);
7419 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
7420 reset_socket_info_index(fd);
7422 si = swrap_get_socket_info(si_index);
7424 swrap_mutex_lock(&first_free_mutex);
7427 ret = __close_fd_fn(fd);
7432 swrap_dec_refcount(si);
7434 if (swrap_get_refcount(si) > 0) {
7435 /* there are still references left */
7439 if (si->fd_passed) {
7443 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7444 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7447 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7448 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7449 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7452 if (si->un_addr.sun_path[0] != '\0') {
7453 unlink(si->un_addr.sun_path);
7457 swrap_set_next_free(si, first_free);
7458 first_free = si_index;
7461 SWRAP_UNLOCK_SI(si);
7462 swrap_mutex_unlock(&first_free_mutex);
7463 swrap_mutex_unlock(&socket_reset_mutex);
7469 static int swrap_noop_close(int fd)
7471 (void)fd; /* unused */
7475 static void swrap_remove_stale(int fd)
7477 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7481 * This allows socket_wrapper aware applications to
7482 * indicate that the given fd does not belong to
7485 * We already overload a lot of unrelated functions
7486 * like eventfd(), timerfd_create(), ... in order to
7487 * call swrap_remove_stale() on the returned fd, but
7488 * we'll never be able to handle all possible syscalls.
7490 * socket_wrapper_indicate_no_inet_fd() gives them a way
7493 * We don't export swrap_remove_stale() in order to
7494 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
7497 void socket_wrapper_indicate_no_inet_fd(int fd)
7499 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7502 static int swrap_close(int fd)
7504 return swrap_remove_wrapper(__func__, libc_close, fd);
7509 return swrap_close(fd);
7512 #ifdef HAVE___CLOSE_NOCANCEL
7514 static int swrap___close_nocancel(int fd)
7516 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
7519 int __close_nocancel(int fd);
7520 int __close_nocancel(int fd)
7522 return swrap___close_nocancel(fd);
7525 #endif /* HAVE___CLOSE_NOCANCEL */
7527 /****************************
7529 ***************************/
7531 static int swrap_dup(int fd)
7533 struct socket_info *si;
7536 idx = find_socket_info_index(fd);
7538 return libc_dup(fd);
7541 si = swrap_get_socket_info(idx);
7543 dup_fd = libc_dup(fd);
7545 int saved_errno = errno;
7546 errno = saved_errno;
7550 if ((size_t)dup_fd >= socket_fds_max) {
7551 SWRAP_LOG(SWRAP_LOG_ERROR,
7552 "The max socket index limit of %zu has been reached, "
7563 swrap_inc_refcount(si);
7565 SWRAP_UNLOCK_SI(si);
7567 /* Make sure we don't have an entry for the fd */
7568 swrap_remove_stale(dup_fd);
7570 set_socket_info_index(dup_fd, idx);
7577 return swrap_dup(fd);
7580 /****************************
7582 ***************************/
7584 static int swrap_dup2(int fd, int newfd)
7586 struct socket_info *si;
7589 idx = find_socket_info_index(fd);
7591 return libc_dup2(fd, newfd);
7594 si = swrap_get_socket_info(idx);
7598 * According to the manpage:
7600 * "If oldfd is a valid file descriptor, and newfd has the same
7601 * value as oldfd, then dup2() does nothing, and returns newfd."
7606 if ((size_t)newfd >= socket_fds_max) {
7607 SWRAP_LOG(SWRAP_LOG_ERROR,
7608 "The max socket index limit of %zu has been reached, "
7616 if (find_socket_info(newfd)) {
7617 /* dup2() does an implicit close of newfd, which we
7618 * need to emulate */
7622 dup_fd = libc_dup2(fd, newfd);
7624 int saved_errno = errno;
7625 errno = saved_errno;
7631 swrap_inc_refcount(si);
7633 SWRAP_UNLOCK_SI(si);
7635 /* Make sure we don't have an entry for the fd */
7636 swrap_remove_stale(dup_fd);
7638 set_socket_info_index(dup_fd, idx);
7643 int dup2(int fd, int newfd)
7645 return swrap_dup2(fd, newfd);
7648 /****************************
7650 ***************************/
7652 static int swrap_vfcntl(int fd, int cmd, va_list va)
7654 struct socket_info *si;
7655 int rc, dup_fd, idx;
7657 idx = find_socket_info_index(fd);
7659 return libc_vfcntl(fd, cmd, va);
7662 si = swrap_get_socket_info(idx);
7666 dup_fd = libc_vfcntl(fd, cmd, va);
7668 int saved_errno = errno;
7669 errno = saved_errno;
7673 /* Make sure we don't have an entry for the fd */
7674 swrap_remove_stale(dup_fd);
7676 if ((size_t)dup_fd >= socket_fds_max) {
7677 SWRAP_LOG(SWRAP_LOG_ERROR,
7678 "The max socket index limit of %zu has been reached, "
7689 swrap_inc_refcount(si);
7691 SWRAP_UNLOCK_SI(si);
7694 set_socket_info_index(dup_fd, idx);
7699 rc = libc_vfcntl(fd, cmd, va);
7706 int fcntl(int fd, int cmd, ...)
7713 rc = swrap_vfcntl(fd, cmd, va);
7720 /****************************
7722 ***************************/
7725 static int swrap_eventfd(int count, int flags)
7729 fd = libc_eventfd(count, flags);
7731 swrap_remove_stale(fd);
7737 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7738 int eventfd(unsigned int count, int flags)
7740 int eventfd(int count, int flags)
7743 return swrap_eventfd(count, flags);
7748 int pledge(const char *promises, const char *paths[])
7750 (void)promises; /* unused */
7751 (void)paths; /* unused */
7755 #endif /* HAVE_PLEDGE */
7757 static void swrap_thread_prepare(void)
7760 * This function should only be called here!!
7762 * We bind all symobls to avoid deadlocks of the fork is
7763 * interrupted by a signal handler using a symbol of this
7766 swrap_bind_symbol_all();
7771 static void swrap_thread_parent(void)
7776 static void swrap_thread_child(void)
7781 /****************************
7783 ***************************/
7784 void swrap_constructor(void)
7786 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7787 SWRAP_LOG(SWRAP_LOG_ERROR,
7789 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7790 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7791 "sizeof(struct socket_info)=%zu",
7793 sizeof(struct swrap_unix_scm_rights),
7794 sizeof(struct swrap_unix_scm_rights_payload),
7795 sizeof(struct socket_info));
7802 * If we hold a lock and the application forks, then the child
7803 * is not able to unlock the mutex and we are in a deadlock.
7804 * This should prevent such deadlocks.
7806 pthread_atfork(&swrap_thread_prepare,
7807 &swrap_thread_parent,
7808 &swrap_thread_child);
7811 /****************************
7813 ***************************/
7816 * This function is called when the library is unloaded and makes sure that
7817 * sockets get closed and the unix file for the socket are unlinked.
7819 void swrap_destructor(void)
7823 if (socket_fds_idx != NULL) {
7824 for (i = 0; i < socket_fds_max; ++i) {
7825 if (socket_fds_idx[i] != -1) {
7829 SAFE_FREE(socket_fds_idx);
7834 if (swrap.libc.handle != NULL
7836 && swrap.libc.handle != RTLD_NEXT
7839 dlclose(swrap.libc.handle);
7841 if (swrap.libc.socket_handle
7843 && swrap.libc.socket_handle != RTLD_NEXT
7846 dlclose(swrap.libc.socket_handle);
7850 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7852 * On FreeBSD 12 (and maybe other platforms)
7853 * system libraries like libresolv prefix there
7854 * syscalls with '_' in order to always use
7855 * the symbols from libc.
7857 * In the interaction with resolv_wrapper,
7858 * we need to inject socket wrapper into libresolv,
7859 * which means we need to private all socket
7860 * related syscalls also with the '_' prefix.
7862 * This is tested in Samba's 'make test',
7863 * there we noticed that providing '_read',
7864 * '_open' and '_close' would cause errors, which
7865 * means we skip '_read', '_write' and
7866 * all non socket related calls without
7867 * further analyzing the problem.
7869 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7870 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7873 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7875 SWRAP_SYMBOL_ALIAS(accept, _accept);
7876 SWRAP_SYMBOL_ALIAS(bind, _bind);
7877 SWRAP_SYMBOL_ALIAS(connect, _connect);
7878 SWRAP_SYMBOL_ALIAS(dup, _dup);
7879 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7880 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7881 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7882 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7883 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7884 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7885 SWRAP_SYMBOL_ALIAS(listen, _listen);
7886 SWRAP_SYMBOL_ALIAS(readv, _readv);
7887 SWRAP_SYMBOL_ALIAS(recv, _recv);
7888 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7889 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7890 SWRAP_SYMBOL_ALIAS(send, _send);
7891 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7892 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7893 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7894 SWRAP_SYMBOL_ALIAS(socket, _socket);
7895 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7896 SWRAP_SYMBOL_ALIAS(writev, _writev);
7898 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */