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),
3819 char *swrap_dir = NULL;
3821 swrap_mutex_lock(&autobind_start_mutex);
3823 if (autobind_start_init != 1) {
3824 autobind_start_init = 1;
3825 autobind_start = getpid();
3826 autobind_start %= 50000;
3827 autobind_start += 10000;
3830 un_addr.sa.un.sun_family = AF_UNIX;
3834 struct sockaddr_in in;
3838 type = SOCKET_TYPE_CHAR_TCP;
3841 type = SOCKET_TYPE_CHAR_UDP;
3844 errno = ESOCKTNOSUPPORT;
3849 memset(&in, 0, sizeof(in));
3850 in.sin_family = AF_INET;
3851 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3852 socket_wrapper_default_iface()));
3854 si->myname = (struct swrap_address) {
3855 .sa_socklen = sizeof(in),
3857 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3862 struct sockaddr_in6 in6;
3864 if (si->family != family) {
3865 errno = ENETUNREACH;
3872 type = SOCKET_TYPE_CHAR_TCP_V6;
3875 type = SOCKET_TYPE_CHAR_UDP_V6;
3878 errno = ESOCKTNOSUPPORT;
3883 memset(&in6, 0, sizeof(in6));
3884 in6.sin6_family = AF_INET6;
3885 in6.sin6_addr = *swrap_ipv6();
3886 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3888 si->myname = (struct swrap_address) {
3889 .sa_socklen = sizeof(in6),
3891 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3896 errno = ESOCKTNOSUPPORT;
3901 if (autobind_start > 60000) {
3902 autobind_start = 10000;
3905 swrap_dir = socket_wrapper_dir();
3906 if (swrap_dir == NULL) {
3912 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3913 port = autobind_start + i;
3914 swrap_un_path(&un_addr.sa.un,
3917 socket_wrapper_default_iface(),
3919 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3921 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3926 si->un_addr = un_addr.sa.un;
3929 autobind_start = port + 1;
3932 if (i == SOCKET_MAX_SOCKETS) {
3933 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3934 "interface "SOCKET_FORMAT,
3937 socket_wrapper_default_iface(),
3944 si->family = family;
3945 set_port(si->family, port, &si->myname);
3950 SAFE_FREE(swrap_dir);
3951 swrap_mutex_unlock(&autobind_start_mutex);
3955 /****************************************************************************
3957 ***************************************************************************/
3959 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3963 struct swrap_address un_addr = {
3964 .sa_socklen = sizeof(struct sockaddr_un),
3966 struct socket_info *si = find_socket_info(s);
3970 return libc_connect(s, serv_addr, addrlen);
3975 if (si->bound == 0) {
3976 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3982 if (si->family != serv_addr->sa_family) {
3983 SWRAP_LOG(SWRAP_LOG_ERROR,
3984 "called for fd=%d (family=%d) called with invalid family=%d",
3985 s, si->family, serv_addr->sa_family);
3991 ret = sockaddr_convert_to_un(si, serv_addr,
3992 addrlen, &un_addr.sa.un, 0, &bcast);
3998 errno = ENETUNREACH;
4003 if (si->type == SOCK_DGRAM) {
4004 si->defer_connect = 1;
4007 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4009 ret = libc_connect(s,
4011 un_addr.sa_socklen);
4014 SWRAP_LOG(SWRAP_LOG_TRACE,
4015 "connect() path=%s, fd=%d",
4016 un_addr.sa.un.sun_path, s);
4019 /* to give better errors */
4020 if (ret == -1 && errno == ENOENT) {
4021 errno = EHOSTUNREACH;
4025 si->peername = (struct swrap_address) {
4026 .sa_socklen = addrlen,
4029 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4033 * When we connect() on a socket than we have to bind the
4034 * outgoing connection on the interface we use for the
4035 * transport. We already bound it on the right interface
4036 * but here we have to update the name so getsockname()
4037 * returns correct information.
4039 if (si->bindname.sa_socklen > 0) {
4040 si->myname = (struct swrap_address) {
4041 .sa_socklen = si->bindname.sa_socklen,
4044 memcpy(&si->myname.sa.ss,
4045 &si->bindname.sa.ss,
4046 si->bindname.sa_socklen);
4048 /* Cleanup bindname */
4049 si->bindname = (struct swrap_address) {
4054 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4055 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4057 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4061 SWRAP_UNLOCK_SI(si);
4065 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4067 return swrap_connect(s, serv_addr, addrlen);
4070 /****************************************************************************
4072 ***************************************************************************/
4074 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4077 struct swrap_address un_addr = {
4078 .sa_socklen = sizeof(struct sockaddr_un),
4080 struct socket_info *si = find_socket_info(s);
4087 return libc_bind(s, myaddr, addrlen);
4092 switch (si->family) {
4094 const struct sockaddr_in *sin;
4095 if (addrlen < sizeof(struct sockaddr_in)) {
4096 bind_error = EINVAL;
4100 sin = (const struct sockaddr_in *)(const void *)myaddr;
4102 if (sin->sin_family != AF_INET) {
4103 bind_error = EAFNOSUPPORT;
4106 /* special case for AF_UNSPEC */
4107 if (sin->sin_family == AF_UNSPEC &&
4108 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4117 const struct sockaddr_in6 *sin6;
4118 if (addrlen < sizeof(struct sockaddr_in6)) {
4119 bind_error = EINVAL;
4123 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4125 if (sin6->sin6_family != AF_INET6) {
4126 bind_error = EAFNOSUPPORT;
4133 bind_error = EINVAL;
4137 if (bind_error != 0) {
4144 in_use = check_addr_port_in_use(myaddr, addrlen);
4152 si->myname.sa_socklen = addrlen;
4153 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4155 ret = sockaddr_convert_to_un(si,
4165 unlink(un_addr.sa.un.sun_path);
4167 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4169 SWRAP_LOG(SWRAP_LOG_TRACE,
4170 "bind() path=%s, fd=%d",
4171 un_addr.sa.un.sun_path, s);
4178 SWRAP_UNLOCK_SI(si);
4183 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4185 return swrap_bind(s, myaddr, addrlen);
4188 /****************************************************************************
4190 ***************************************************************************/
4192 #ifdef HAVE_BINDRESVPORT
4193 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4195 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4197 struct swrap_address myaddr = {
4198 .sa_socklen = sizeof(struct sockaddr_storage),
4201 static uint16_t port;
4206 #define SWRAP_STARTPORT 600
4207 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4208 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4211 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4215 salen = myaddr.sa_socklen;
4218 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4224 memset(&myaddr.sa.ss, 0, salen);
4229 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4232 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4234 salen = sizeof(struct sockaddr_in);
4235 sinp->sin_port = htons(port);
4239 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4241 salen = sizeof(struct sockaddr_in6);
4242 sin6p->sin6_port = htons(port);
4246 errno = EAFNOSUPPORT;
4251 if (port > SWRAP_ENDPORT) {
4252 port = SWRAP_STARTPORT;
4255 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4256 if (rc == 0 || errno != EADDRINUSE) {
4264 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4266 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4270 /****************************************************************************
4272 ***************************************************************************/
4274 static int swrap_listen(int s, int backlog)
4277 struct socket_info *si = find_socket_info(s);
4280 return libc_listen(s, backlog);
4285 if (si->bound == 0) {
4286 ret = swrap_auto_bind(s, si, si->family);
4293 ret = libc_listen(s, backlog);
4299 SWRAP_UNLOCK_SI(si);
4304 int listen(int s, int backlog)
4306 return swrap_listen(s, backlog);
4309 /****************************************************************************
4311 ***************************************************************************/
4313 static FILE *swrap_fopen(const char *name, const char *mode)
4317 fp = libc_fopen(name, mode);
4319 int fd = fileno(fp);
4321 swrap_remove_stale(fd);
4327 FILE *fopen(const char *name, const char *mode)
4329 return swrap_fopen(name, mode);
4332 /****************************************************************************
4334 ***************************************************************************/
4337 static FILE *swrap_fopen64(const char *name, const char *mode)
4341 fp = libc_fopen64(name, mode);
4343 int fd = fileno(fp);
4345 swrap_remove_stale(fd);
4351 FILE *fopen64(const char *name, const char *mode)
4353 return swrap_fopen64(name, mode);
4355 #endif /* HAVE_FOPEN64 */
4357 /****************************************************************************
4359 ***************************************************************************/
4361 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4365 ret = libc_vopen(pathname, flags, ap);
4368 * There are methods for closing descriptors (libc-internal code
4369 * paths, direct syscalls) which close descriptors in ways that
4370 * we can't intercept, so try to recover when we notice that
4373 swrap_remove_stale(ret);
4378 int open(const char *pathname, int flags, ...)
4383 va_start(ap, flags);
4384 fd = swrap_vopen(pathname, flags, ap);
4390 /****************************************************************************
4392 ***************************************************************************/
4395 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4399 ret = libc_vopen64(pathname, flags, ap);
4402 * There are methods for closing descriptors (libc-internal code
4403 * paths, direct syscalls) which close descriptors in ways that
4404 * we can't intercept, so try to recover when we notice that
4407 swrap_remove_stale(ret);
4412 int open64(const char *pathname, int flags, ...)
4417 va_start(ap, flags);
4418 fd = swrap_vopen64(pathname, flags, ap);
4423 #endif /* HAVE_OPEN64 */
4425 /****************************************************************************
4427 ***************************************************************************/
4429 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4433 ret = libc_vopenat(dirfd, path, flags, ap);
4436 * There are methods for closing descriptors (libc-internal code
4437 * paths, direct syscalls) which close descriptors in ways that
4438 * we can't intercept, so try to recover when we notice that
4441 swrap_remove_stale(ret);
4447 int openat(int dirfd, const char *path, int flags, ...)
4452 va_start(ap, flags);
4453 fd = swrap_vopenat(dirfd, path, flags, ap);
4459 /****************************************************************************
4461 ***************************************************************************/
4463 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4465 struct socket_info *si = find_socket_info(s);
4470 return libc_getpeername(s, name, addrlen);
4475 if (si->peername.sa_socklen == 0)
4481 len = MIN(*addrlen, si->peername.sa_socklen);
4487 memcpy(name, &si->peername.sa.ss, len);
4488 *addrlen = si->peername.sa_socklen;
4492 SWRAP_UNLOCK_SI(si);
4497 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4498 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4500 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4503 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4506 /****************************************************************************
4508 ***************************************************************************/
4510 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4512 struct socket_info *si = find_socket_info(s);
4517 return libc_getsockname(s, name, addrlen);
4522 len = MIN(*addrlen, si->myname.sa_socklen);
4528 memcpy(name, &si->myname.sa.ss, len);
4529 *addrlen = si->myname.sa_socklen;
4533 SWRAP_UNLOCK_SI(si);
4538 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4539 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4541 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4544 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4547 /****************************************************************************
4549 ***************************************************************************/
4552 # ifdef SO_PROTOTYPE /* The Solaris name */
4553 # define SO_PROTOCOL SO_PROTOTYPE
4554 # endif /* SO_PROTOTYPE */
4555 #endif /* SO_PROTOCOL */
4557 static int swrap_getsockopt(int s, int level, int optname,
4558 void *optval, socklen_t *optlen)
4560 struct socket_info *si = find_socket_info(s);
4564 return libc_getsockopt(s,
4573 if (level == SOL_SOCKET) {
4577 if (optval == NULL || optlen == NULL ||
4578 *optlen < (socklen_t)sizeof(int)) {
4584 *optlen = sizeof(int);
4585 *(int *)optval = si->family;
4588 #endif /* SO_DOMAIN */
4592 if (optval == NULL || optlen == NULL ||
4593 *optlen < (socklen_t)sizeof(int)) {
4599 *optlen = sizeof(int);
4600 *(int *)optval = si->protocol;
4603 #endif /* SO_PROTOCOL */
4605 if (optval == NULL || optlen == NULL ||
4606 *optlen < (socklen_t)sizeof(int)) {
4612 *optlen = sizeof(int);
4613 *(int *)optval = si->type;
4617 ret = libc_getsockopt(s,
4624 } else if (level == IPPROTO_TCP) {
4629 * This enables sending packets directly out over TCP.
4630 * As a unix socket is doing that any way, report it as
4633 if (optval == NULL || optlen == NULL ||
4634 *optlen < (socklen_t)sizeof(int)) {
4640 *optlen = sizeof(int);
4641 *(int *)optval = si->tcp_nodelay;
4645 #endif /* TCP_NODELAY */
4648 struct tcp_info info;
4649 socklen_t ilen = sizeof(info);
4651 #ifdef HAVE_NETINET_TCP_FSM_H
4652 /* This is FreeBSD */
4653 # define __TCP_LISTEN TCPS_LISTEN
4654 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4655 # define __TCP_CLOSE TCPS_CLOSED
4658 # define __TCP_LISTEN TCP_LISTEN
4659 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4660 # define __TCP_CLOSE TCP_CLOSE
4664 if (si->listening) {
4665 info.tcpi_state = __TCP_LISTEN;
4666 } else if (si->connected) {
4668 * For now we just fake a few values
4669 * supported both by FreeBSD and Linux
4671 info.tcpi_state = __TCP_ESTABLISHED;
4672 info.tcpi_rto = 200000; /* 200 msec */
4673 info.tcpi_rtt = 5000; /* 5 msec */
4674 info.tcpi_rttvar = 5000; /* 5 msec */
4676 info.tcpi_state = __TCP_CLOSE;
4677 info.tcpi_rto = 1000000; /* 1 sec */
4679 info.tcpi_rttvar = 250000; /* 250 msec */
4682 if (optval == NULL || optlen == NULL ||
4683 *optlen < (socklen_t)ilen) {
4690 memcpy(optval, &info, ilen);
4695 #endif /* TCP_INFO */
4701 errno = ENOPROTOOPT;
4705 SWRAP_UNLOCK_SI(si);
4709 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4710 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4712 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4715 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4718 /****************************************************************************
4720 ***************************************************************************/
4722 static int swrap_setsockopt(int s, int level, int optname,
4723 const void *optval, socklen_t optlen)
4725 struct socket_info *si = find_socket_info(s);
4729 return libc_setsockopt(s,
4736 if (level == SOL_SOCKET) {
4737 return libc_setsockopt(s,
4746 if (level == IPPROTO_TCP) {
4753 * This enables sending packets directly out over TCP.
4754 * A unix socket is doing that any way.
4756 if (optval == NULL || optlen == 0 ||
4757 optlen < (socklen_t)sizeof(int)) {
4763 i = *discard_const_p(int, optval);
4764 if (i != 0 && i != 1) {
4769 si->tcp_nodelay = i;
4774 #endif /* TCP_NODELAY */
4780 switch (si->family) {
4782 if (level == IPPROTO_IP) {
4784 if (optname == IP_PKTINFO) {
4785 si->pktinfo = AF_INET;
4787 #endif /* IP_PKTINFO */
4793 if (level == IPPROTO_IPV6) {
4794 #ifdef IPV6_RECVPKTINFO
4795 if (optname == IPV6_RECVPKTINFO) {
4796 si->pktinfo = AF_INET6;
4798 #endif /* IPV6_PKTINFO */
4804 errno = ENOPROTOOPT;
4810 SWRAP_UNLOCK_SI(si);
4814 int setsockopt(int s, int level, int optname,
4815 const void *optval, socklen_t optlen)
4817 return swrap_setsockopt(s, level, optname, optval, optlen);
4820 /****************************************************************************
4822 ***************************************************************************/
4824 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4826 struct socket_info *si = find_socket_info(s);
4828 int *value_ptr = NULL;
4832 return libc_vioctl(s, r, va);
4839 rc = libc_vioctl(s, r, va);
4844 value_ptr = ((int *)va_arg(ap, int *));
4847 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4848 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4849 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4850 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4855 /* this is FreeBSD */
4856 FALL_THROUGH; /* to TIOCOUTQ */
4857 #endif /* FIONWRITE */
4858 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4860 * This may return more bytes then the application
4861 * sent into the socket, for tcp it should
4862 * return the number of unacked bytes.
4864 * On AF_UNIX, all bytes are immediately acked!
4867 value_ptr = ((int *)va_arg(ap, int *));
4875 SWRAP_UNLOCK_SI(si);
4879 #ifdef HAVE_IOCTL_INT
4880 int ioctl(int s, int r, ...)
4882 int ioctl(int s, unsigned long int r, ...)
4890 rc = swrap_vioctl(s, (unsigned long int) r, va);
4901 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4904 # ifdef _ALIGN /* BSD */
4905 #define CMSG_ALIGN _ALIGN
4907 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4908 # endif /* _ALIGN */
4909 #endif /* CMSG_ALIGN */
4912 * @brief Add a cmsghdr to a msghdr.
4914 * This is an function to add any type of cmsghdr. It will operate on the
4915 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4916 * the buffer position after the added cmsg element. Hence, this function is
4917 * intended to be used with an intermediate msghdr and not on the original
4918 * one handed in by the client.
4920 * @param[in] msg The msghdr to which to add the cmsg.
4922 * @param[in] level The cmsg level to set.
4924 * @param[in] type The cmsg type to set.
4926 * @param[in] data The cmsg data to set.
4928 * @param[in] len the length of the data to set.
4930 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4936 size_t cmlen = CMSG_LEN(len);
4937 size_t cmspace = CMSG_SPACE(len);
4938 uint8_t cmbuf[cmspace];
4939 void *cast_ptr = (void *)cmbuf;
4940 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4943 memset(cmbuf, 0, cmspace);
4945 if (msg->msg_controllen < cmlen) {
4946 cmlen = msg->msg_controllen;
4947 msg->msg_flags |= MSG_CTRUNC;
4950 if (msg->msg_controllen < cmspace) {
4951 cmspace = msg->msg_controllen;
4955 * We copy the full input data into an intermediate cmsghdr first
4956 * in order to more easily cope with truncation.
4958 cm->cmsg_len = cmlen;
4959 cm->cmsg_level = level;
4960 cm->cmsg_type = type;
4961 memcpy(CMSG_DATA(cm), data, len);
4964 * We now copy the possibly truncated buffer.
4965 * We copy cmlen bytes, but consume cmspace bytes,
4966 * leaving the possible padding uninitialiazed.
4968 p = (uint8_t *)msg->msg_control;
4969 memcpy(p, cm, cmlen);
4971 msg->msg_control = p;
4972 msg->msg_controllen -= cmspace;
4977 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4980 /* Add packet info */
4981 switch (si->pktinfo) {
4982 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4984 struct sockaddr_in *sin;
4985 #if defined(HAVE_STRUCT_IN_PKTINFO)
4986 struct in_pktinfo pkt;
4987 #elif defined(IP_RECVDSTADDR)
4991 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4992 sin = &si->bindname.sa.in;
4994 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4997 sin = &si->myname.sa.in;
5002 #if defined(HAVE_STRUCT_IN_PKTINFO)
5003 pkt.ipi_ifindex = socket_wrapper_default_iface();
5004 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5005 #elif defined(IP_RECVDSTADDR)
5006 pkt = sin->sin_addr;
5009 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5014 #endif /* IP_PKTINFO */
5015 #if defined(HAVE_IPV6)
5017 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5018 struct sockaddr_in6 *sin6;
5019 struct in6_pktinfo pkt6;
5021 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5022 sin6 = &si->bindname.sa.in6;
5024 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5027 sin6 = &si->myname.sa.in6;
5032 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5033 pkt6.ipi6_addr = sin6->sin6_addr;
5035 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5036 &pkt6, sizeof(pkt6));
5037 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5041 #endif /* IPV6_PKTINFO */
5049 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5050 struct msghdr *omsg)
5054 if (si->pktinfo > 0) {
5055 rc = swrap_msghdr_add_pktinfo(si, omsg);
5061 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5063 size_t *cm_data_space);
5064 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5066 size_t *cm_data_space);
5067 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5069 size_t *cm_data_space);
5071 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5073 size_t *cm_data_space)
5075 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5076 struct cmsghdr *cmsg;
5080 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5084 for (cmsg = CMSG_FIRSTHDR(msg);
5086 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5087 switch (cmsg->cmsg_level) {
5089 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5094 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5099 rc = swrap_sendmsg_copy_cmsg(cmsg,
5105 int saved_errno = errno;
5106 SAFE_FREE(*cm_data);
5108 errno = saved_errno;
5116 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5118 size_t *cm_data_space)
5123 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5125 p = realloc((*cm_data), cmspace);
5131 p = (*cm_data) + (*cm_data_space);
5132 *cm_data_space = cmspace;
5134 memcpy(p, cmsg, cmsg->cmsg_len);
5139 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5141 size_t *cm_data_space);
5144 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5146 size_t *cm_data_space)
5150 switch(cmsg->cmsg_type) {
5153 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5160 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5172 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5174 size_t *cm_data_space)
5176 (void)cmsg; /* unused */
5177 (void)cm_data; /* unused */
5178 (void)cm_data_space; /* unused */
5181 * Passing a IP pktinfo to a unix socket might be rejected by the
5182 * Kernel, at least on FreeBSD. So skip this cmsg.
5187 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5189 size_t *cm_data_space)
5193 switch (cmsg->cmsg_type) {
5195 SWRAP_LOG(SWRAP_LOG_TRACE,
5196 "Ignoring SCM_RIGHTS on inet socket!");
5199 #ifdef SCM_CREDENTIALS
5200 case SCM_CREDENTIALS:
5201 SWRAP_LOG(SWRAP_LOG_TRACE,
5202 "Ignoring SCM_CREDENTIALS on inet socket!");
5205 #endif /* SCM_CREDENTIALS */
5207 rc = swrap_sendmsg_copy_cmsg(cmsg,
5216 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5219 * We only allow up to 6 fds at a time
5220 * as that's more than enough for Samba
5221 * and it means we can keep the logic simple
5222 * and work with fixed size arrays.
5224 * We also keep sizeof(struct swrap_unix_scm_rights)
5225 * under PIPE_BUF (4096) in order to allow a non-blocking
5226 * write into the pipe.
5229 #define PIPE_BUF 4096
5231 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5232 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5233 struct swrap_unix_scm_rights_payload {
5235 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5236 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5238 struct swrap_unix_scm_rights {
5240 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5241 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5243 uint32_t payload_size;
5244 struct swrap_unix_scm_rights_payload payload;
5247 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5249 int saved_errno = errno;
5252 for (i = 0; i < num; i++) {
5253 struct socket_info *si = array[i];
5259 swrap_dec_refcount(si);
5260 if (si->fd_passed > 0) {
5263 SWRAP_UNLOCK_SI(si);
5267 errno = saved_errno;
5270 static void swrap_undo_si_idx_array(size_t num, int *array)
5272 int saved_errno = errno;
5275 swrap_mutex_lock(&first_free_mutex);
5277 for (i = 0; i < num; i++) {
5278 struct socket_info *si = NULL;
5280 if (array[i] == -1) {
5284 si = swrap_get_socket_info(array[i]);
5290 swrap_dec_refcount(si);
5291 SWRAP_UNLOCK_SI(si);
5293 swrap_set_next_free(si, first_free);
5294 first_free = array[i];
5298 swrap_mutex_unlock(&first_free_mutex);
5299 errno = saved_errno;
5302 static void swrap_close_fd_array(size_t num, const int *array)
5304 int saved_errno = errno;
5307 for (i = 0; i < num; i++) {
5308 if (array[i] == -1) {
5311 libc_close(array[i]);
5314 errno = saved_errno;
5322 union __swrap_cmsghdr {
5324 struct cmsghdr *cmsg;
5327 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5329 size_t *cm_data_space,
5330 int *scm_rights_pipe_fd)
5332 struct swrap_unix_scm_rights info;
5333 struct swrap_unix_scm_rights_payload *payload = NULL;
5334 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5335 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5336 size_t info_idx = 0;
5339 union __swrap_fds __fds_in = { .p = NULL, };
5340 const int *fds_in = NULL;
5342 size_t size_fds_out;
5343 union __swrap_fds __fds_out = { .p = NULL, };
5344 int *fds_out = NULL;
5347 size_t new_cm_data_space;
5348 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5349 struct cmsghdr *new_cmsg = NULL;
5352 int pipefd[2] = { -1, -1 };
5357 * We pass this a buffer to the kernel make sure any padding
5361 info.magic = swrap_unix_scm_right_magic;
5362 memcpy(info.package_name,
5363 SOCKET_WRAPPER_PACKAGE,
5364 sizeof(info.package_name));
5365 memcpy(info.package_version,
5366 SOCKET_WRAPPER_VERSION,
5367 sizeof(info.package_version));
5368 info.full_size = sizeof(info);
5369 info.payload_size = sizeof(info.payload);
5370 payload = &info.payload;
5372 if (*scm_rights_pipe_fd != -1) {
5373 SWRAP_LOG(SWRAP_LOG_ERROR,
5374 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5379 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5380 SWRAP_LOG(SWRAP_LOG_ERROR,
5381 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5382 (size_t)cmsg->cmsg_len,
5387 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5388 if ((size_fds_in % sizeof(int)) != 0) {
5389 SWRAP_LOG(SWRAP_LOG_ERROR,
5390 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5391 (size_t)cmsg->cmsg_len,
5397 num_fds_in = size_fds_in / sizeof(int);
5398 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5399 SWRAP_LOG(SWRAP_LOG_ERROR,
5400 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5402 "SWRAP_MAX_PASSED_FDS(%zu)",
5403 (size_t)cmsg->cmsg_len,
5406 SWRAP_MAX_PASSED_FDS);
5410 if (num_fds_in == 0) {
5411 SWRAP_LOG(SWRAP_LOG_ERROR,
5412 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5414 (size_t)cmsg->cmsg_len,
5420 __fds_in.p = CMSG_DATA(cmsg);
5421 fds_in = __fds_in.fds;
5422 num_fds_out = num_fds_in + 1;
5424 SWRAP_LOG(SWRAP_LOG_TRACE,
5425 "num_fds_in=%zu num_fds_out=%zu",
5426 num_fds_in, num_fds_out);
5428 size_fds_out = sizeof(int) * num_fds_out;
5429 cmsg_len = CMSG_LEN(size_fds_out);
5430 cmsg_space = CMSG_SPACE(size_fds_out);
5432 new_cm_data_space = *cm_data_space + cmsg_space;
5434 p = realloc((*cm_data), new_cm_data_space);
5439 p = (*cm_data) + (*cm_data_space);
5440 memset(p, 0, cmsg_space);
5442 new_cmsg = __new_cmsg.cmsg;
5444 __fds_out.p = CMSG_DATA(new_cmsg);
5445 fds_out = __fds_out.fds;
5446 memcpy(fds_out, fds_in, size_fds_in);
5447 new_cmsg->cmsg_len = cmsg->cmsg_len;
5449 for (i = 0; i < num_fds_in; i++) {
5452 payload->idxs[i] = -1;
5453 payload->num_idxs++;
5455 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5456 if (si_idx_array[i] == -1) {
5460 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5461 if (si_array[i] == NULL) {
5462 SWRAP_LOG(SWRAP_LOG_ERROR,
5463 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5464 i, fds_in[i], i, si_idx_array[i]);
5469 for (j = 0; j < i; j++) {
5470 if (si_array[j] == si_array[i]) {
5471 payload->idxs[i] = payload->idxs[j];
5475 if (payload->idxs[i] == -1) {
5476 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5477 SWRAP_LOG(SWRAP_LOG_ERROR,
5478 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5479 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5480 i, fds_in[i], i, si_idx_array[i],
5482 SWRAP_MAX_PASSED_SOCKET_INFO);
5486 payload->idxs[i] = info_idx;
5492 for (i = 0; i < num_fds_in; i++) {
5493 struct socket_info *si = si_array[i];
5496 SWRAP_LOG(SWRAP_LOG_TRACE,
5497 "fds_in[%zu]=%d not an inet socket",
5502 SWRAP_LOG(SWRAP_LOG_TRACE,
5503 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5504 "passing as info.idxs[%zu]=%d!",
5507 i, payload->idxs[i]);
5511 payload->infos[payload->idxs[i]] = *si;
5512 payload->infos[payload->idxs[i]].fd_passed = 0;
5513 SWRAP_UNLOCK_SI(si);
5518 int saved_errno = errno;
5519 SWRAP_LOG(SWRAP_LOG_ERROR,
5520 "pipe() failed - %d %s",
5522 strerror(saved_errno));
5523 swrap_dec_fd_passed_array(num_fds_in, si_array);
5524 errno = saved_errno;
5528 sret = libc_write(pipefd[1], &info, sizeof(info));
5529 if (sret != sizeof(info)) {
5530 int saved_errno = errno;
5532 saved_errno = EINVAL;
5534 SWRAP_LOG(SWRAP_LOG_ERROR,
5535 "write() failed - sret=%zd - %d %s",
5537 strerror(saved_errno));
5538 swrap_dec_fd_passed_array(num_fds_in, si_array);
5539 libc_close(pipefd[1]);
5540 libc_close(pipefd[0]);
5541 errno = saved_errno;
5544 libc_close(pipefd[1]);
5547 * Add the pipe read end to the end of the passed fd array
5549 fds_out[num_fds_in] = pipefd[0];
5550 new_cmsg->cmsg_len = cmsg_len;
5552 /* we're done ... */
5553 *scm_rights_pipe_fd = pipefd[0];
5554 *cm_data_space = new_cm_data_space;
5559 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5561 size_t *cm_data_space,
5562 int *scm_rights_pipe_fd)
5566 switch (cmsg->cmsg_type) {
5568 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5571 scm_rights_pipe_fd);
5574 rc = swrap_sendmsg_copy_cmsg(cmsg,
5583 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5585 size_t *cm_data_space)
5587 int scm_rights_pipe_fd = -1;
5588 struct swrap_unix_scm_rights info;
5589 struct swrap_unix_scm_rights_payload *payload = NULL;
5590 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5593 union __swrap_fds __fds_in = { .p = NULL, };
5594 const int *fds_in = NULL;
5596 size_t size_fds_out;
5597 union __swrap_fds __fds_out = { .p = NULL, };
5598 int *fds_out = NULL;
5601 size_t new_cm_data_space;
5602 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5603 struct cmsghdr *new_cmsg = NULL;
5609 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5610 SWRAP_LOG(SWRAP_LOG_ERROR,
5611 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5612 (size_t)cmsg->cmsg_len,
5617 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5618 if ((size_fds_in % sizeof(int)) != 0) {
5619 SWRAP_LOG(SWRAP_LOG_ERROR,
5620 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5621 (size_t)cmsg->cmsg_len,
5627 num_fds_in = size_fds_in / sizeof(int);
5628 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5629 SWRAP_LOG(SWRAP_LOG_ERROR,
5630 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5631 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5632 (size_t)cmsg->cmsg_len,
5635 SWRAP_MAX_PASSED_FDS+1);
5639 if (num_fds_in <= 1) {
5640 SWRAP_LOG(SWRAP_LOG_ERROR,
5641 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5643 (size_t)cmsg->cmsg_len,
5649 __fds_in.p = CMSG_DATA(cmsg);
5650 fds_in = __fds_in.fds;
5651 num_fds_out = num_fds_in - 1;
5653 SWRAP_LOG(SWRAP_LOG_TRACE,
5654 "num_fds_in=%zu num_fds_out=%zu",
5655 num_fds_in, num_fds_out);
5657 for (i = 0; i < num_fds_in; i++) {
5658 /* Check if we have a stale fd and remove it */
5659 swrap_remove_stale(fds_in[i]);
5662 scm_rights_pipe_fd = fds_in[num_fds_out];
5663 size_fds_out = sizeof(int) * num_fds_out;
5664 cmsg_len = CMSG_LEN(size_fds_out);
5665 cmsg_space = CMSG_SPACE(size_fds_out);
5667 new_cm_data_space = *cm_data_space + cmsg_space;
5669 p = realloc((*cm_data), new_cm_data_space);
5671 swrap_close_fd_array(num_fds_in, fds_in);
5675 p = (*cm_data) + (*cm_data_space);
5676 memset(p, 0, cmsg_space);
5678 new_cmsg = __new_cmsg.cmsg;
5680 __fds_out.p = CMSG_DATA(new_cmsg);
5681 fds_out = __fds_out.fds;
5682 memcpy(fds_out, fds_in, size_fds_out);
5683 new_cmsg->cmsg_len = cmsg_len;
5685 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5686 if (sret != sizeof(info)) {
5687 int saved_errno = errno;
5689 saved_errno = EINVAL;
5691 SWRAP_LOG(SWRAP_LOG_ERROR,
5692 "read() failed - sret=%zd - %d %s",
5694 strerror(saved_errno));
5695 swrap_close_fd_array(num_fds_in, fds_in);
5696 errno = saved_errno;
5699 libc_close(scm_rights_pipe_fd);
5700 payload = &info.payload;
5702 if (info.magic != swrap_unix_scm_right_magic) {
5703 SWRAP_LOG(SWRAP_LOG_ERROR,
5704 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5705 (unsigned long long)info.magic,
5706 (unsigned long long)swrap_unix_scm_right_magic);
5707 swrap_close_fd_array(num_fds_out, fds_out);
5712 cmp = memcmp(info.package_name,
5713 SOCKET_WRAPPER_PACKAGE,
5714 sizeof(info.package_name));
5716 SWRAP_LOG(SWRAP_LOG_ERROR,
5717 "info.package_name='%.*s' != '%s'",
5718 (int)sizeof(info.package_name),
5720 SOCKET_WRAPPER_PACKAGE);
5721 swrap_close_fd_array(num_fds_out, fds_out);
5726 cmp = memcmp(info.package_version,
5727 SOCKET_WRAPPER_VERSION,
5728 sizeof(info.package_version));
5730 SWRAP_LOG(SWRAP_LOG_ERROR,
5731 "info.package_version='%.*s' != '%s'",
5732 (int)sizeof(info.package_version),
5733 info.package_version,
5734 SOCKET_WRAPPER_VERSION);
5735 swrap_close_fd_array(num_fds_out, fds_out);
5740 if (info.full_size != sizeof(info)) {
5741 SWRAP_LOG(SWRAP_LOG_ERROR,
5742 "info.full_size=%zu != sizeof(info)=%zu",
5743 (size_t)info.full_size,
5745 swrap_close_fd_array(num_fds_out, fds_out);
5750 if (info.payload_size != sizeof(info.payload)) {
5751 SWRAP_LOG(SWRAP_LOG_ERROR,
5752 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5753 (size_t)info.payload_size,
5754 sizeof(info.payload));
5755 swrap_close_fd_array(num_fds_out, fds_out);
5760 if (payload->num_idxs != num_fds_out) {
5761 SWRAP_LOG(SWRAP_LOG_ERROR,
5762 "info.num_idxs=%u != num_fds_out=%zu",
5763 payload->num_idxs, num_fds_out);
5764 swrap_close_fd_array(num_fds_out, fds_out);
5769 for (i = 0; i < num_fds_out; i++) {
5772 si_idx_array[i] = -1;
5774 if (payload->idxs[i] == -1) {
5775 SWRAP_LOG(SWRAP_LOG_TRACE,
5776 "fds_out[%zu]=%d not an inet socket",
5781 if (payload->idxs[i] < 0) {
5782 SWRAP_LOG(SWRAP_LOG_ERROR,
5783 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5784 i, fds_out[i], i, payload->idxs[i]);
5785 swrap_close_fd_array(num_fds_out, fds_out);
5790 if (payload->idxs[i] >= payload->num_idxs) {
5791 SWRAP_LOG(SWRAP_LOG_ERROR,
5792 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5793 i, fds_out[i], i, payload->idxs[i],
5795 swrap_close_fd_array(num_fds_out, fds_out);
5800 if ((size_t)fds_out[i] >= socket_fds_max) {
5801 SWRAP_LOG(SWRAP_LOG_ERROR,
5802 "The max socket index limit of %zu has been reached, "
5806 swrap_close_fd_array(num_fds_out, fds_out);
5811 SWRAP_LOG(SWRAP_LOG_TRACE,
5813 "received as info.idxs[%zu]=%d!",
5815 i, payload->idxs[i]);
5817 for (j = 0; j < i; j++) {
5818 if (payload->idxs[j] == -1) {
5821 if (payload->idxs[j] == payload->idxs[i]) {
5822 si_idx_array[i] = si_idx_array[j];
5825 if (si_idx_array[i] == -1) {
5826 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5828 si_idx_array[i] = swrap_add_socket_info(si);
5829 if (si_idx_array[i] == -1) {
5830 int saved_errno = errno;
5831 SWRAP_LOG(SWRAP_LOG_ERROR,
5832 "The max socket index limit of %zu has been reached, "
5836 swrap_undo_si_idx_array(i, si_idx_array);
5837 swrap_close_fd_array(num_fds_out, fds_out);
5838 errno = saved_errno;
5841 SWRAP_LOG(SWRAP_LOG_TRACE,
5842 "Imported %s socket for protocol %s, fd=%d",
5843 si->family == AF_INET ? "IPv4" : "IPv6",
5844 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5849 for (i = 0; i < num_fds_out; i++) {
5850 if (si_idx_array[i] == -1) {
5853 set_socket_info_index(fds_out[i], si_idx_array[i]);
5856 /* we're done ... */
5857 *cm_data_space = new_cm_data_space;
5862 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5864 size_t *cm_data_space)
5868 switch (cmsg->cmsg_type) {
5870 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5875 rc = swrap_sendmsg_copy_cmsg(cmsg,
5884 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5886 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5887 struct msghdr *msg_tmp,
5888 int *scm_rights_pipe_fd)
5890 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5891 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5892 struct cmsghdr *cmsg = NULL;
5893 uint8_t *cm_data = NULL;
5894 size_t cm_data_space = 0;
5898 *scm_rights_pipe_fd = -1;
5901 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5905 for (cmsg = CMSG_FIRSTHDR(msg_in);
5907 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5908 switch (cmsg->cmsg_level) {
5910 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5913 scm_rights_pipe_fd);
5917 rc = swrap_sendmsg_copy_cmsg(cmsg,
5923 int saved_errno = errno;
5925 errno = saved_errno;
5930 msg_tmp->msg_controllen = cm_data_space;
5931 msg_tmp->msg_control = cm_data;
5934 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5935 *msg_tmp = *_msg_in;
5937 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5940 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5942 int scm_rights_pipe_fd)
5944 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5945 int saved_errno = errno;
5946 SAFE_FREE(msg_tmp->msg_control);
5947 if (scm_rights_pipe_fd != -1) {
5948 libc_close(scm_rights_pipe_fd);
5950 errno = saved_errno;
5951 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5955 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5956 struct msghdr *msg_tmp,
5957 uint8_t **tmp_control)
5959 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5960 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
5961 uint8_t *cm_data = NULL;
5962 size_t cm_data_space = 0;
5965 *tmp_control = NULL;
5967 SWRAP_LOG(SWRAP_LOG_TRACE,
5968 "msg_in->msg_controllen=%zu",
5969 (size_t)msg_in->msg_controllen);
5972 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5977 * We need to give the kernel a bit more space in order
5978 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
5979 * swrap_recvmsg_after_unix() will hide it again.
5981 cm_data_space = msg_in->msg_controllen;
5982 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
5983 cm_data_space += cm_extra_space;
5985 cm_data = calloc(1, cm_data_space);
5986 if (cm_data == NULL) {
5990 msg_tmp->msg_controllen = cm_data_space;
5991 msg_tmp->msg_control = cm_data;
5992 *tmp_control = cm_data;
5994 SWRAP_LOG(SWRAP_LOG_TRACE,
5995 "msg_tmp->msg_controllen=%zu",
5996 (size_t)msg_tmp->msg_controllen);
5998 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6000 *tmp_control = NULL;
6002 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6005 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6006 uint8_t **tmp_control,
6007 struct msghdr *msg_out,
6010 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6011 struct cmsghdr *cmsg = NULL;
6012 uint8_t *cm_data = NULL;
6013 size_t cm_data_space = 0;
6017 int saved_errno = errno;
6018 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6019 saved_errno, strerror(saved_errno));
6020 SAFE_FREE(*tmp_control);
6021 /* msg_out should not be touched on error */
6022 errno = saved_errno;
6026 SWRAP_LOG(SWRAP_LOG_TRACE,
6027 "msg_tmp->msg_controllen=%zu",
6028 (size_t)msg_tmp->msg_controllen);
6031 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6032 int saved_errno = errno;
6033 *msg_out = *msg_tmp;
6034 SAFE_FREE(*tmp_control);
6035 errno = saved_errno;
6039 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6041 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6042 switch (cmsg->cmsg_level) {
6044 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6050 rc = swrap_sendmsg_copy_cmsg(cmsg,
6056 int saved_errno = errno;
6058 SAFE_FREE(*tmp_control);
6059 errno = saved_errno;
6065 * msg_tmp->msg_control (*tmp_control) was created by
6066 * swrap_recvmsg_before_unix() and msg_out->msg_control
6067 * is still the buffer of the caller.
6069 msg_tmp->msg_control = msg_out->msg_control;
6070 msg_tmp->msg_controllen = msg_out->msg_controllen;
6071 *msg_out = *msg_tmp;
6073 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6074 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6075 msg_out->msg_controllen = cm_data_space;
6077 SAFE_FREE(*tmp_control);
6079 SWRAP_LOG(SWRAP_LOG_TRACE,
6080 "msg_out->msg_controllen=%zu",
6081 (size_t)msg_out->msg_controllen);
6083 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6084 int saved_errno = errno;
6085 *msg_out = *msg_tmp;
6086 SAFE_FREE(*tmp_control);
6087 errno = saved_errno;
6089 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6092 static ssize_t swrap_sendmsg_before(int fd,
6093 struct socket_info *si,
6095 struct iovec *tmp_iov,
6096 struct sockaddr_un *tmp_un,
6097 const struct sockaddr_un **to_un,
6098 const struct sockaddr **to,
6120 if (!si->connected) {
6125 if (msg->msg_iovlen == 0) {
6129 mtu = socket_wrapper_mtu();
6130 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6132 nlen = len + msg->msg_iov[i].iov_len;
6142 msg->msg_iovlen = i;
6143 if (msg->msg_iovlen == 0) {
6144 *tmp_iov = msg->msg_iov[0];
6145 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6147 msg->msg_iov = tmp_iov;
6148 msg->msg_iovlen = 1;
6153 if (si->connected) {
6154 if (msg->msg_name != NULL) {
6156 * We are dealing with unix sockets and if we
6157 * are connected, we should only talk to the
6158 * connected unix path. Using the fd to send
6159 * to another server would be hard to achieve.
6161 msg->msg_name = NULL;
6162 msg->msg_namelen = 0;
6165 const struct sockaddr *msg_name;
6166 msg_name = (const struct sockaddr *)msg->msg_name;
6168 if (msg_name == NULL) {
6174 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6186 msg->msg_name = tmp_un;
6187 msg->msg_namelen = sizeof(*tmp_un);
6190 if (si->bound == 0) {
6191 ret = swrap_auto_bind(fd, si, si->family);
6193 SWRAP_UNLOCK_SI(si);
6194 if (errno == ENOTSOCK) {
6195 swrap_remove_stale(fd);
6198 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6204 if (!si->defer_connect) {
6208 ret = sockaddr_convert_to_un(si,
6210 si->peername.sa_socklen,
6218 ret = libc_connect(fd,
6219 (struct sockaddr *)(void *)tmp_un,
6222 /* to give better errors */
6223 if (ret == -1 && errno == ENOENT) {
6224 errno = EHOSTUNREACH;
6231 si->defer_connect = 0;
6234 errno = EHOSTUNREACH;
6240 SWRAP_UNLOCK_SI(si);
6245 static void swrap_sendmsg_after(int fd,
6246 struct socket_info *si,
6248 const struct sockaddr *to,
6251 int saved_errno = errno;
6258 /* to give better errors */
6260 if (saved_errno == ENOENT) {
6261 saved_errno = EHOSTUNREACH;
6262 } else if (saved_errno == ENOTSOCK) {
6263 /* If the fd is not a socket, remove it */
6264 swrap_remove_stale(fd);
6268 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6269 avail += msg->msg_iov[i].iov_len;
6273 remain = MIN(80, avail);
6278 /* we capture it as one single packet */
6279 buf = (uint8_t *)malloc(remain);
6281 /* we just not capture the packet */
6282 errno = saved_errno;
6286 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6287 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6289 msg->msg_iov[i].iov_base,
6292 remain -= this_time;
6301 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6302 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6304 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6309 if (si->connected) {
6310 to = &si->peername.sa.s;
6313 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6314 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6316 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6321 SWRAP_UNLOCK_SI(si);
6324 errno = saved_errno;
6327 static int swrap_recvmsg_before(int fd,
6328 struct socket_info *si,
6330 struct iovec *tmp_iov)
6337 (void)fd; /* unused */
6342 if (!si->connected) {
6347 if (msg->msg_iovlen == 0) {
6351 mtu = socket_wrapper_mtu();
6352 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6354 nlen = len + msg->msg_iov[i].iov_len;
6359 msg->msg_iovlen = i;
6360 if (msg->msg_iovlen == 0) {
6361 *tmp_iov = msg->msg_iov[0];
6362 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6364 msg->msg_iov = tmp_iov;
6365 msg->msg_iovlen = 1;
6370 if (msg->msg_name == NULL) {
6375 if (msg->msg_iovlen == 0) {
6379 if (si->bound == 0) {
6380 ret = swrap_auto_bind(fd, si, si->family);
6382 SWRAP_UNLOCK_SI(si);
6384 * When attempting to read or write to a
6385 * descriptor, if an underlying autobind fails
6386 * because it's not a socket, stop intercepting
6387 * uses of that descriptor.
6389 if (errno == ENOTSOCK) {
6390 swrap_remove_stale(fd);
6393 SWRAP_LOG(SWRAP_LOG_ERROR,
6394 "swrap_recvmsg_before failed");
6401 errno = EHOSTUNREACH;
6407 SWRAP_UNLOCK_SI(si);
6412 static int swrap_recvmsg_after(int fd,
6413 struct socket_info *si,
6415 const struct sockaddr_un *un_addr,
6416 socklen_t un_addrlen,
6419 int saved_errno = errno;
6421 uint8_t *buf = NULL;
6427 /* to give better errors */
6429 if (saved_errno == ENOENT) {
6430 saved_errno = EHOSTUNREACH;
6431 } else if (saved_errno == ENOTSOCK) {
6432 /* If the fd is not a socket, remove it */
6433 swrap_remove_stale(fd);
6437 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6438 avail += msg->msg_iov[i].iov_len;
6443 /* Convert the socket address before we leave */
6444 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6445 rc = sockaddr_convert_from_un(si,
6462 remain = MIN(80, avail);
6467 /* we capture it as one single packet */
6468 buf = (uint8_t *)malloc(remain);
6470 /* we just not capture the packet */
6471 SWRAP_UNLOCK_SI(si);
6472 errno = saved_errno;
6476 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6477 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6479 msg->msg_iov[i].iov_base,
6482 remain -= this_time;
6487 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6488 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6489 } else if (ret == 0) { /* END OF FILE */
6490 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6491 } else if (ret > 0) {
6492 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6501 if (un_addr != NULL) {
6502 swrap_pcap_dump_packet(si,
6508 swrap_pcap_dump_packet(si,
6521 errno = saved_errno;
6523 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6525 msg->msg_controllen > 0 &&
6526 msg->msg_control != NULL) {
6527 rc = swrap_msghdr_add_socket_info(si, msg);
6529 SWRAP_UNLOCK_SI(si);
6535 SWRAP_UNLOCK_SI(si);
6539 /****************************************************************************
6541 ***************************************************************************/
6543 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6544 struct sockaddr *from, socklen_t *fromlen)
6546 struct swrap_address from_addr = {
6547 .sa_socklen = sizeof(struct sockaddr_un),
6550 struct socket_info *si = find_socket_info(s);
6551 struct swrap_address saddr = {
6552 .sa_socklen = sizeof(struct sockaddr_storage),
6559 return libc_recvfrom(s,
6571 if (from != NULL && fromlen != NULL) {
6572 msg.msg_name = from; /* optional address */
6573 msg.msg_namelen = *fromlen; /* size of address */
6575 msg.msg_name = &saddr.sa.s; /* optional address */
6576 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6578 msg.msg_iov = &tmp; /* scatter/gather array */
6579 msg.msg_iovlen = 1; /* # elements in msg_iov */
6580 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6581 msg.msg_control = NULL; /* ancillary data, see below */
6582 msg.msg_controllen = 0; /* ancillary data buffer len */
6583 msg.msg_flags = 0; /* flags on received message */
6586 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6591 buf = msg.msg_iov[0].iov_base;
6592 len = msg.msg_iov[0].iov_len;
6594 ret = libc_recvfrom(s,
6599 &from_addr.sa_socklen);
6604 tret = swrap_recvmsg_after(s,
6608 from_addr.sa_socklen,
6614 if (from != NULL && fromlen != NULL) {
6615 *fromlen = msg.msg_namelen;
6621 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6622 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6623 struct sockaddr *from, Psocklen_t fromlen)
6625 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6626 struct sockaddr *from, socklen_t *fromlen)
6629 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6632 /****************************************************************************
6634 ***************************************************************************/
6636 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6637 const struct sockaddr *to, socklen_t tolen)
6641 struct swrap_address un_addr = {
6642 .sa_socklen = sizeof(struct sockaddr_un),
6644 const struct sockaddr_un *to_un = NULL;
6647 struct socket_info *si = find_socket_info(s);
6651 return libc_sendto(s, buf, len, flags, to, tolen);
6654 tmp.iov_base = discard_const_p(char, buf);
6658 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6659 msg.msg_namelen = tolen; /* size of address */
6660 msg.msg_iov = &tmp; /* scatter/gather array */
6661 msg.msg_iovlen = 1; /* # elements in msg_iov */
6662 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6663 msg.msg_control = NULL; /* ancillary data, see below */
6664 msg.msg_controllen = 0; /* ancillary data buffer len */
6665 msg.msg_flags = 0; /* flags on received message */
6668 rc = swrap_sendmsg_before(s,
6680 buf = msg.msg_iov[0].iov_base;
6681 len = msg.msg_iov[0].iov_len;
6686 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6688 char *swrap_dir = NULL;
6690 type = SOCKET_TYPE_CHAR_UDP;
6692 swrap_dir = socket_wrapper_dir();
6693 if (swrap_dir == NULL) {
6697 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6698 swrap_un_path(&un_addr.sa.un,
6703 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6705 /* ignore the any errors in broadcast sends */
6711 un_addr.sa_socklen);
6714 SAFE_FREE(swrap_dir);
6718 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6720 SWRAP_UNLOCK_SI(si);
6727 * If it is a dgram socket and we are connected, don't include the
6730 if (si->type == SOCK_DGRAM && si->connected) {
6731 ret = libc_sendto(s,
6738 ret = libc_sendto(s,
6742 (struct sockaddr *)msg.msg_name,
6746 SWRAP_UNLOCK_SI(si);
6748 swrap_sendmsg_after(s, si, &msg, to, ret);
6753 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6754 const struct sockaddr *to, socklen_t tolen)
6756 return swrap_sendto(s, buf, len, flags, to, tolen);
6759 /****************************************************************************
6761 ***************************************************************************/
6763 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6765 struct socket_info *si;
6767 struct swrap_address saddr = {
6768 .sa_socklen = sizeof(struct sockaddr_storage),
6774 si = find_socket_info(s);
6776 return libc_recv(s, buf, len, flags);
6783 msg.msg_name = &saddr.sa.s; /* optional address */
6784 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6785 msg.msg_iov = &tmp; /* scatter/gather array */
6786 msg.msg_iovlen = 1; /* # elements in msg_iov */
6787 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6788 msg.msg_control = NULL; /* ancillary data, see below */
6789 msg.msg_controllen = 0; /* ancillary data buffer len */
6790 msg.msg_flags = 0; /* flags on received message */
6793 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6798 buf = msg.msg_iov[0].iov_base;
6799 len = msg.msg_iov[0].iov_len;
6801 ret = libc_recv(s, buf, len, flags);
6803 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6811 ssize_t recv(int s, void *buf, size_t len, int flags)
6813 return swrap_recv(s, buf, len, flags);
6816 /****************************************************************************
6818 ***************************************************************************/
6820 static ssize_t swrap_read(int s, void *buf, size_t len)
6822 struct socket_info *si;
6825 struct swrap_address saddr = {
6826 .sa_socklen = sizeof(struct sockaddr_storage),
6831 si = find_socket_info(s);
6833 return libc_read(s, buf, len);
6840 msg.msg_name = &saddr.sa.ss; /* optional address */
6841 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6842 msg.msg_iov = &tmp; /* scatter/gather array */
6843 msg.msg_iovlen = 1; /* # elements in msg_iov */
6844 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6845 msg.msg_control = NULL; /* ancillary data, see below */
6846 msg.msg_controllen = 0; /* ancillary data buffer len */
6847 msg.msg_flags = 0; /* flags on received message */
6850 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6852 if (tret == -ENOTSOCK) {
6853 return libc_read(s, buf, len);
6858 buf = msg.msg_iov[0].iov_base;
6859 len = msg.msg_iov[0].iov_len;
6861 ret = libc_read(s, buf, len);
6863 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6871 ssize_t read(int s, void *buf, size_t len)
6873 return swrap_read(s, buf, len);
6876 /****************************************************************************
6878 ***************************************************************************/
6880 static ssize_t swrap_write(int s, const void *buf, size_t len)
6884 struct sockaddr_un un_addr;
6887 struct socket_info *si;
6889 si = find_socket_info(s);
6891 return libc_write(s, buf, len);
6894 tmp.iov_base = discard_const_p(char, buf);
6898 msg.msg_name = NULL; /* optional address */
6899 msg.msg_namelen = 0; /* size of address */
6900 msg.msg_iov = &tmp; /* scatter/gather array */
6901 msg.msg_iovlen = 1; /* # elements in msg_iov */
6902 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6903 msg.msg_control = NULL; /* ancillary data, see below */
6904 msg.msg_controllen = 0; /* ancillary data buffer len */
6905 msg.msg_flags = 0; /* flags on received message */
6908 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6913 buf = msg.msg_iov[0].iov_base;
6914 len = msg.msg_iov[0].iov_len;
6916 ret = libc_write(s, buf, len);
6918 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6923 ssize_t write(int s, const void *buf, size_t len)
6925 return swrap_write(s, buf, len);
6928 /****************************************************************************
6930 ***************************************************************************/
6932 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6936 struct sockaddr_un un_addr;
6939 struct socket_info *si = find_socket_info(s);
6942 return libc_send(s, buf, len, flags);
6945 tmp.iov_base = discard_const_p(char, buf);
6949 msg.msg_name = NULL; /* optional address */
6950 msg.msg_namelen = 0; /* size of address */
6951 msg.msg_iov = &tmp; /* scatter/gather array */
6952 msg.msg_iovlen = 1; /* # elements in msg_iov */
6953 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6954 msg.msg_control = NULL; /* ancillary data, see below */
6955 msg.msg_controllen = 0; /* ancillary data buffer len */
6956 msg.msg_flags = 0; /* flags on received message */
6959 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6964 buf = msg.msg_iov[0].iov_base;
6965 len = msg.msg_iov[0].iov_len;
6967 ret = libc_send(s, buf, len, flags);
6969 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6974 ssize_t send(int s, const void *buf, size_t len, int flags)
6976 return swrap_send(s, buf, len, flags);
6979 /****************************************************************************
6981 ***************************************************************************/
6983 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6985 struct swrap_address from_addr = {
6986 .sa_socklen = sizeof(struct sockaddr_un),
6988 struct swrap_address convert_addr = {
6989 .sa_socklen = sizeof(struct sockaddr_storage),
6991 struct socket_info *si;
6994 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6995 size_t msg_ctrllen_filled;
6996 size_t msg_ctrllen_left;
7002 si = find_socket_info(s);
7004 uint8_t *tmp_control = NULL;
7005 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7009 ret = libc_recvmsg(s, &msg, flags);
7010 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7013 tmp.iov_base = NULL;
7017 msg.msg_name = &from_addr.sa; /* optional address */
7018 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7019 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7020 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7021 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7022 msg_ctrllen_filled = 0;
7023 msg_ctrllen_left = omsg->msg_controllen;
7025 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7026 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7027 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7030 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7035 ret = libc_recvmsg(s, &msg, flags);
7037 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7038 msg_ctrllen_filled += msg.msg_controllen;
7039 msg_ctrllen_left -= msg.msg_controllen;
7041 if (omsg->msg_control != NULL) {
7044 p = omsg->msg_control;
7045 p += msg_ctrllen_filled;
7047 msg.msg_control = p;
7048 msg.msg_controllen = msg_ctrllen_left;
7050 msg.msg_control = NULL;
7051 msg.msg_controllen = 0;
7056 * We convert the unix address to a IP address so we need a buffer
7057 * which can store the address in case of SOCK_DGRAM, see below.
7059 msg.msg_name = &convert_addr.sa;
7060 msg.msg_namelen = convert_addr.sa_socklen;
7062 rc = swrap_recvmsg_after(s,
7066 from_addr.sa_socklen,
7072 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7073 if (omsg->msg_control != NULL) {
7074 /* msg.msg_controllen = space left */
7075 msg_ctrllen_left = msg.msg_controllen;
7076 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7079 /* Update the original message length */
7080 omsg->msg_controllen = msg_ctrllen_filled;
7081 omsg->msg_flags = msg.msg_flags;
7083 omsg->msg_iovlen = msg.msg_iovlen;
7090 * The msg_name field points to a caller-allocated buffer that is
7091 * used to return the source address if the socket is unconnected. The
7092 * caller should set msg_namelen to the size of this buffer before this
7093 * call; upon return from a successful call, msg_name will contain the
7094 * length of the returned address. If the application does not need
7095 * to know the source address, msg_name can be specified as NULL.
7097 if (si->type == SOCK_STREAM) {
7098 omsg->msg_namelen = 0;
7099 } else if (omsg->msg_name != NULL &&
7100 omsg->msg_namelen != 0 &&
7101 omsg->msg_namelen >= msg.msg_namelen) {
7102 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7103 omsg->msg_namelen = msg.msg_namelen;
7106 SWRAP_UNLOCK_SI(si);
7111 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7113 return swrap_recvmsg(sockfd, msg, flags);
7116 /****************************************************************************
7118 ***************************************************************************/
7120 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7124 struct sockaddr_un un_addr;
7125 const struct sockaddr_un *to_un = NULL;
7126 const struct sockaddr *to = NULL;
7129 struct socket_info *si = find_socket_info(s);
7133 int scm_rights_pipe_fd = -1;
7135 rc = swrap_sendmsg_before_unix(omsg, &msg,
7136 &scm_rights_pipe_fd);
7140 ret = libc_sendmsg(s, &msg, flags);
7141 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7144 ZERO_STRUCT(un_addr);
7146 tmp.iov_base = NULL;
7153 if (si->connected == 0) {
7154 msg.msg_name = omsg->msg_name; /* optional address */
7155 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7157 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7158 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7160 SWRAP_UNLOCK_SI(si);
7162 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7163 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7164 uint8_t *cmbuf = NULL;
7167 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7173 msg.msg_controllen = 0;
7174 msg.msg_control = NULL;
7176 msg.msg_control = cmbuf;
7177 msg.msg_controllen = cmlen;
7180 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7182 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7184 int saved_errno = errno;
7185 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7186 SAFE_FREE(msg.msg_control);
7188 errno = saved_errno;
7195 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7202 char *swrap_dir = NULL;
7204 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7205 avail += msg.msg_iov[i].iov_len;
7211 /* we capture it as one single packet */
7212 buf = (uint8_t *)malloc(remain);
7214 int saved_errno = errno;
7215 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7216 SAFE_FREE(msg.msg_control);
7218 errno = saved_errno;
7222 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7223 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7225 msg.msg_iov[i].iov_base,
7228 remain -= this_time;
7231 type = SOCKET_TYPE_CHAR_UDP;
7233 swrap_dir = socket_wrapper_dir();
7234 if (swrap_dir == NULL) {
7235 int saved_errno = errno;
7236 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7237 SAFE_FREE(msg.msg_control);
7240 errno = saved_errno;
7244 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7245 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7246 if (stat(un_addr.sun_path, &st) != 0) continue;
7248 msg.msg_name = &un_addr; /* optional address */
7249 msg.msg_namelen = sizeof(un_addr); /* size of address */
7251 /* ignore the any errors in broadcast sends */
7252 libc_sendmsg(s, &msg, flags);
7255 SAFE_FREE(swrap_dir);
7259 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7262 SWRAP_UNLOCK_SI(si);
7267 ret = libc_sendmsg(s, &msg, flags);
7269 swrap_sendmsg_after(s, si, &msg, to, ret);
7271 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7273 int saved_errno = errno;
7274 SAFE_FREE(msg.msg_control);
7275 errno = saved_errno;
7282 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7284 return swrap_sendmsg(s, omsg, flags);
7287 /****************************************************************************
7289 ***************************************************************************/
7291 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7293 struct socket_info *si;
7296 struct swrap_address saddr = {
7297 .sa_socklen = sizeof(struct sockaddr_storage)
7302 si = find_socket_info(s);
7304 return libc_readv(s, vector, count);
7307 tmp.iov_base = NULL;
7311 msg.msg_name = &saddr.sa.s; /* optional address */
7312 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7313 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7314 msg.msg_iovlen = count; /* # elements in msg_iov */
7315 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7316 msg.msg_control = NULL; /* ancillary data, see below */
7317 msg.msg_controllen = 0; /* ancillary data buffer len */
7318 msg.msg_flags = 0; /* flags on received message */
7321 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7323 if (rc == -ENOTSOCK) {
7324 return libc_readv(s, vector, count);
7329 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7331 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7339 ssize_t readv(int s, const struct iovec *vector, int count)
7341 return swrap_readv(s, vector, count);
7344 /****************************************************************************
7346 ***************************************************************************/
7348 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7352 struct sockaddr_un un_addr;
7355 struct socket_info *si = find_socket_info(s);
7358 return libc_writev(s, vector, count);
7361 tmp.iov_base = NULL;
7365 msg.msg_name = NULL; /* optional address */
7366 msg.msg_namelen = 0; /* size of address */
7367 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7368 msg.msg_iovlen = count; /* # elements in msg_iov */
7369 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7370 msg.msg_control = NULL; /* ancillary data, see below */
7371 msg.msg_controllen = 0; /* ancillary data buffer len */
7372 msg.msg_flags = 0; /* flags on received message */
7375 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7377 if (rc == -ENOTSOCK) {
7378 return libc_readv(s, vector, count);
7383 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7385 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7390 ssize_t writev(int s, const struct iovec *vector, int count)
7392 return swrap_writev(s, vector, count);
7395 /****************************
7397 ***************************/
7399 static int swrap_remove_wrapper(const char *__func_name,
7400 int (*__close_fd_fn)(int fd),
7403 struct socket_info *si = NULL;
7405 int ret_errno = errno;
7408 swrap_mutex_lock(&socket_reset_mutex);
7410 si_index = find_socket_info_index(fd);
7411 if (si_index == -1) {
7412 swrap_mutex_unlock(&socket_reset_mutex);
7413 return __close_fd_fn(fd);
7416 swrap_log(SWRAP_LOG_TRACE, __func_name, "Remove wrapper for fd=%d", fd);
7417 reset_socket_info_index(fd);
7419 si = swrap_get_socket_info(si_index);
7421 swrap_mutex_lock(&first_free_mutex);
7424 ret = __close_fd_fn(fd);
7429 swrap_dec_refcount(si);
7431 if (swrap_get_refcount(si) > 0) {
7432 /* there are still references left */
7436 if (si->fd_passed) {
7440 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7441 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7444 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7445 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7446 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7449 if (si->un_addr.sun_path[0] != '\0') {
7450 unlink(si->un_addr.sun_path);
7454 swrap_set_next_free(si, first_free);
7455 first_free = si_index;
7458 SWRAP_UNLOCK_SI(si);
7459 swrap_mutex_unlock(&first_free_mutex);
7460 swrap_mutex_unlock(&socket_reset_mutex);
7466 static int swrap_noop_close(int fd)
7468 (void)fd; /* unused */
7472 static void swrap_remove_stale(int fd)
7474 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7478 * This allows socket_wrapper aware applications to
7479 * indicate that the given fd does not belong to
7482 * We already overload a lot of unrelated functions
7483 * like eventfd(), timerfd_create(), ... in order to
7484 * call swrap_remove_stale() on the returned fd, but
7485 * we'll never be able to handle all possible syscalls.
7487 * socket_wrapper_indicate_no_inet_fd() gives them a way
7490 * We don't export swrap_remove_stale() in order to
7491 * make it easier to analyze SOCKET_WRAPPER_DEBUGLEVEL=3
7494 void socket_wrapper_indicate_no_inet_fd(int fd)
7496 swrap_remove_wrapper(__func__, swrap_noop_close, fd);
7499 static int swrap_close(int fd)
7501 return swrap_remove_wrapper(__func__, libc_close, fd);
7506 return swrap_close(fd);
7509 #ifdef HAVE___CLOSE_NOCANCEL
7511 static int swrap___close_nocancel(int fd)
7513 return swrap_remove_wrapper(__func__, libc___close_nocancel, fd);
7516 int __close_nocancel(int fd);
7517 int __close_nocancel(int fd)
7519 return swrap___close_nocancel(fd);
7522 #endif /* HAVE___CLOSE_NOCANCEL */
7524 /****************************
7526 ***************************/
7528 static int swrap_dup(int fd)
7530 struct socket_info *si;
7533 idx = find_socket_info_index(fd);
7535 return libc_dup(fd);
7538 si = swrap_get_socket_info(idx);
7540 dup_fd = libc_dup(fd);
7542 int saved_errno = errno;
7543 errno = saved_errno;
7547 if ((size_t)dup_fd >= socket_fds_max) {
7548 SWRAP_LOG(SWRAP_LOG_ERROR,
7549 "The max socket index limit of %zu has been reached, "
7560 swrap_inc_refcount(si);
7562 SWRAP_UNLOCK_SI(si);
7564 /* Make sure we don't have an entry for the fd */
7565 swrap_remove_stale(dup_fd);
7567 set_socket_info_index(dup_fd, idx);
7574 return swrap_dup(fd);
7577 /****************************
7579 ***************************/
7581 static int swrap_dup2(int fd, int newfd)
7583 struct socket_info *si;
7586 idx = find_socket_info_index(fd);
7588 return libc_dup2(fd, newfd);
7591 si = swrap_get_socket_info(idx);
7595 * According to the manpage:
7597 * "If oldfd is a valid file descriptor, and newfd has the same
7598 * value as oldfd, then dup2() does nothing, and returns newfd."
7603 if ((size_t)newfd >= socket_fds_max) {
7604 SWRAP_LOG(SWRAP_LOG_ERROR,
7605 "The max socket index limit of %zu has been reached, "
7613 if (find_socket_info(newfd)) {
7614 /* dup2() does an implicit close of newfd, which we
7615 * need to emulate */
7619 dup_fd = libc_dup2(fd, newfd);
7621 int saved_errno = errno;
7622 errno = saved_errno;
7628 swrap_inc_refcount(si);
7630 SWRAP_UNLOCK_SI(si);
7632 /* Make sure we don't have an entry for the fd */
7633 swrap_remove_stale(dup_fd);
7635 set_socket_info_index(dup_fd, idx);
7640 int dup2(int fd, int newfd)
7642 return swrap_dup2(fd, newfd);
7645 /****************************
7647 ***************************/
7649 static int swrap_vfcntl(int fd, int cmd, va_list va)
7651 struct socket_info *si;
7652 int rc, dup_fd, idx;
7654 idx = find_socket_info_index(fd);
7656 return libc_vfcntl(fd, cmd, va);
7659 si = swrap_get_socket_info(idx);
7663 dup_fd = libc_vfcntl(fd, cmd, va);
7665 int saved_errno = errno;
7666 errno = saved_errno;
7670 /* Make sure we don't have an entry for the fd */
7671 swrap_remove_stale(dup_fd);
7673 if ((size_t)dup_fd >= socket_fds_max) {
7674 SWRAP_LOG(SWRAP_LOG_ERROR,
7675 "The max socket index limit of %zu has been reached, "
7686 swrap_inc_refcount(si);
7688 SWRAP_UNLOCK_SI(si);
7691 set_socket_info_index(dup_fd, idx);
7696 rc = libc_vfcntl(fd, cmd, va);
7703 int fcntl(int fd, int cmd, ...)
7710 rc = swrap_vfcntl(fd, cmd, va);
7717 /****************************
7719 ***************************/
7722 static int swrap_eventfd(int count, int flags)
7726 fd = libc_eventfd(count, flags);
7728 swrap_remove_stale(fd);
7734 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7735 int eventfd(unsigned int count, int flags)
7737 int eventfd(int count, int flags)
7740 return swrap_eventfd(count, flags);
7745 int pledge(const char *promises, const char *paths[])
7747 (void)promises; /* unused */
7748 (void)paths; /* unused */
7752 #endif /* HAVE_PLEDGE */
7754 static void swrap_thread_prepare(void)
7757 * This function should only be called here!!
7759 * We bind all symobls to avoid deadlocks of the fork is
7760 * interrupted by a signal handler using a symbol of this
7763 swrap_bind_symbol_all();
7768 static void swrap_thread_parent(void)
7773 static void swrap_thread_child(void)
7778 /****************************
7780 ***************************/
7781 void swrap_constructor(void)
7783 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7784 SWRAP_LOG(SWRAP_LOG_ERROR,
7786 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7787 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7788 "sizeof(struct socket_info)=%zu",
7790 sizeof(struct swrap_unix_scm_rights),
7791 sizeof(struct swrap_unix_scm_rights_payload),
7792 sizeof(struct socket_info));
7799 * If we hold a lock and the application forks, then the child
7800 * is not able to unlock the mutex and we are in a deadlock.
7801 * This should prevent such deadlocks.
7803 pthread_atfork(&swrap_thread_prepare,
7804 &swrap_thread_parent,
7805 &swrap_thread_child);
7808 /****************************
7810 ***************************/
7813 * This function is called when the library is unloaded and makes sure that
7814 * sockets get closed and the unix file for the socket are unlinked.
7816 void swrap_destructor(void)
7820 if (socket_fds_idx != NULL) {
7821 for (i = 0; i < socket_fds_max; ++i) {
7822 if (socket_fds_idx[i] != -1) {
7826 SAFE_FREE(socket_fds_idx);
7831 if (swrap.libc.handle != NULL) {
7832 dlclose(swrap.libc.handle);
7834 if (swrap.libc.socket_handle) {
7835 dlclose(swrap.libc.socket_handle);
7839 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7841 * On FreeBSD 12 (and maybe other platforms)
7842 * system libraries like libresolv prefix there
7843 * syscalls with '_' in order to always use
7844 * the symbols from libc.
7846 * In the interaction with resolv_wrapper,
7847 * we need to inject socket wrapper into libresolv,
7848 * which means we need to private all socket
7849 * related syscalls also with the '_' prefix.
7851 * This is tested in Samba's 'make test',
7852 * there we noticed that providing '_read'
7853 * and '_open' would cause errors, which
7854 * means we skip '_read', '_write' and
7855 * all non socket related calls without
7856 * further analyzing the problem.
7858 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7859 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7862 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7864 SWRAP_SYMBOL_ALIAS(accept, _accept);
7865 SWRAP_SYMBOL_ALIAS(bind, _bind);
7866 SWRAP_SYMBOL_ALIAS(close, _close);
7867 SWRAP_SYMBOL_ALIAS(connect, _connect);
7868 SWRAP_SYMBOL_ALIAS(dup, _dup);
7869 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7870 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7871 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7872 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7873 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7874 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7875 SWRAP_SYMBOL_ALIAS(listen, _listen);
7876 SWRAP_SYMBOL_ALIAS(readv, _readv);
7877 SWRAP_SYMBOL_ALIAS(recv, _recv);
7878 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7879 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7880 SWRAP_SYMBOL_ALIAS(send, _send);
7881 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7882 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7883 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7884 SWRAP_SYMBOL_ALIAS(socket, _socket);
7885 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7886 SWRAP_SYMBOL_ALIAS(writev, _writev);
7888 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */