4 * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 * Copyright (c) 2006-2018, Stefan Metzmacher <metze@samba.org>
6 * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
7 * Copyright (c) 2014-2017, Michael Adam <obnox@samba.org>
8 * Copyright (c) 2016-2018, Anoop C S <anoopcs@redhat.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the author nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 Socket wrapper library. Passes all socket communication over
41 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
47 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
55 #ifdef HAVE_SYS_SIGNALFD_H
56 #include <sys/signalfd.h>
58 #ifdef HAVE_SYS_EVENTFD_H
59 #include <sys/eventfd.h>
61 #ifdef HAVE_SYS_TIMERFD_H
62 #include <sys/timerfd.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #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>
96 /* GCC have printf type attribute check. */
97 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
98 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
100 #define PRINTF_ATTRIBUTE(a,b)
101 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
103 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
104 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
106 #define CONSTRUCTOR_ATTRIBUTE
107 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
109 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
110 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
112 #define DESTRUCTOR_ATTRIBUTE
116 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
117 # define FALL_THROUGH __attribute__ ((fallthrough))
118 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
119 # define FALL_THROUGH ((void)0)
120 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
121 #endif /* FALL_THROUGH */
123 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
124 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
126 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
129 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
130 # define SWRAP_THREAD __thread
132 # define SWRAP_THREAD
136 #define MIN(a,b) ((a)<(b)?(a):(b))
140 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
144 #define ZERO_STRUCTP(x) do { \
146 memset((char *)(x), 0, sizeof(*(x))); \
151 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
154 #ifndef discard_const
155 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
158 #ifndef discard_const_p
159 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
162 #define UNUSED(x) (void)(x)
165 # ifndef IPV6_RECVPKTINFO
166 # define IPV6_RECVPKTINFO IPV6_PKTINFO
167 # endif /* IPV6_RECVPKTINFO */
168 #endif /* IPV6_PKTINFO */
171 * On BSD IP_PKTINFO has a different name because during
172 * the time when they implemented it, there was no RFC.
173 * The name for IPv6 is the same as on Linux.
176 # ifdef IP_RECVDSTADDR
177 # define IP_PKTINFO IP_RECVDSTADDR
181 #define socket_wrapper_init_mutex(m) \
182 _socket_wrapper_init_mutex(m, #m)
184 /* Add new global locks here please */
185 # define SWRAP_REINIT_ALL do { \
187 ret = socket_wrapper_init_mutex(&sockets_mutex); \
188 if (ret != 0) exit(-1); \
189 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
190 if (ret != 0) exit(-1); \
191 ret = socket_wrapper_init_mutex(&first_free_mutex); \
192 if (ret != 0) exit(-1); \
193 ret = socket_wrapper_init_mutex(&sockets_si_global); \
194 if (ret != 0) exit(-1); \
195 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
196 if (ret != 0) exit(-1); \
197 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
198 if (ret != 0) exit(-1); \
199 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
200 if (ret != 0) exit(-1); \
203 # define SWRAP_LOCK_ALL do { \
204 swrap_mutex_lock(&sockets_mutex); \
205 swrap_mutex_lock(&socket_reset_mutex); \
206 swrap_mutex_lock(&first_free_mutex); \
207 swrap_mutex_lock(&sockets_si_global); \
208 swrap_mutex_lock(&autobind_start_mutex); \
209 swrap_mutex_lock(&pcap_dump_mutex); \
210 swrap_mutex_lock(&mtu_update_mutex); \
213 # define SWRAP_UNLOCK_ALL do { \
214 swrap_mutex_unlock(&mtu_update_mutex); \
215 swrap_mutex_unlock(&pcap_dump_mutex); \
216 swrap_mutex_unlock(&autobind_start_mutex); \
217 swrap_mutex_unlock(&sockets_si_global); \
218 swrap_mutex_unlock(&first_free_mutex); \
219 swrap_mutex_unlock(&socket_reset_mutex); \
220 swrap_mutex_unlock(&sockets_mutex); \
223 #define SOCKET_INFO_CONTAINER(si) \
224 (struct socket_info_container *)(si)
226 #define SWRAP_LOCK_SI(si) do { \
227 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
229 swrap_mutex_lock(&sockets_si_global); \
235 #define SWRAP_UNLOCK_SI(si) do { \
236 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
238 swrap_mutex_unlock(&sockets_si_global); \
244 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
245 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
247 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
250 /* we need to use a very terse format here as IRIX 6.4 silently
251 truncates names to 16 chars, so if we use a longer name then we
252 can't tell which port a packet came from with recvfrom()
254 with this format we have 8 chars left for the directory name
256 #define SOCKET_FORMAT "%c%02X%04X"
257 #define SOCKET_TYPE_CHAR_TCP 'T'
258 #define SOCKET_TYPE_CHAR_UDP 'U'
259 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
260 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
263 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
264 * format PCAP capture files (as the caller will simply continue from here).
266 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
267 #define SOCKET_WRAPPER_MTU_MIN 512
268 #define SOCKET_WRAPPER_MTU_MAX 32768
270 #define SOCKET_MAX_SOCKETS 1024
273 * Maximum number of socket_info structures that can
274 * be used. Can be overriden by the environment variable
275 * SOCKET_WRAPPER_MAX_SOCKETS.
277 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
279 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
281 /* This limit is to avoid broadcast sendto() needing to stat too many
282 * files. It may be raised (with a performance cost) to up to 254
283 * without changing the format above */
284 #define MAX_WRAPPED_INTERFACES 64
286 struct swrap_address {
287 socklen_t sa_socklen;
290 struct sockaddr_in in;
292 struct sockaddr_in6 in6;
294 struct sockaddr_un un;
295 struct sockaddr_storage ss;
299 static int first_free;
304 * Remember to update swrap_unix_scm_right_magic
321 /* The unix path so we can unlink it on close() */
322 struct sockaddr_un un_addr;
324 struct swrap_address bindname;
325 struct swrap_address myname;
326 struct swrap_address peername;
329 unsigned long pck_snd;
330 unsigned long pck_rcv;
334 struct socket_info_meta
336 unsigned int refcount;
339 * As long as we don't use shared memory
340 * for the sockets array, we use
341 * sockets_si_global as a single mutex.
343 * pthread_mutex_t mutex;
347 struct socket_info_container
349 struct socket_info info;
350 struct socket_info_meta meta;
353 static struct socket_info_container *sockets;
355 static size_t socket_info_max = 0;
358 * Allocate the socket array always on the limit value. We want it to be
359 * at least bigger than the default so if we reach the limit we can
360 * still deal with duplicate fds pointing to the same socket_info.
362 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
364 /* Hash table to map fds to corresponding socket_info index */
365 static int *socket_fds_idx;
367 /* Mutex for syncronizing port selection during swrap_auto_bind() */
368 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
370 /* Mutex to guard the initialization of array of socket_info structures */
371 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
373 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
374 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
376 /* Mutex to synchronize access to first free index in socket_info array */
377 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
380 * Mutex to synchronize access to to socket_info structures
381 * We use a single global mutex in order to avoid leaking
382 * ~ 38M copy on write memory per fork.
383 * max_sockets=65535 * sizeof(struct socket_info_container)=592 = 38796720
385 static pthread_mutex_t sockets_si_global = PTHREAD_MUTEX_INITIALIZER;
387 /* Mutex to synchronize access to packet capture dump file */
388 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
390 /* Mutex for synchronizing mtu value fetch*/
391 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
393 /* Function prototypes */
395 bool socket_wrapper_enabled(void);
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 typedef int (*__libc_connect)(int sockfd,
496 const struct sockaddr *addr,
498 typedef int (*__libc_dup)(int fd);
499 typedef int (*__libc_dup2)(int oldfd, int newfd);
500 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
501 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
503 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
506 typedef int (*__libc_eventfd)(int count, int flags);
508 typedef int (*__libc_getpeername)(int sockfd,
509 struct sockaddr *addr,
511 typedef int (*__libc_getsockname)(int sockfd,
512 struct sockaddr *addr,
514 typedef int (*__libc_getsockopt)(int sockfd,
519 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
520 typedef int (*__libc_listen)(int sockfd, int backlog);
521 typedef int (*__libc_open)(const char *pathname, int flags, ...);
523 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
524 #endif /* HAVE_OPEN64 */
525 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
526 typedef int (*__libc_pipe)(int pipefd[2]);
527 typedef int (*__libc_read)(int fd, void *buf, size_t count);
528 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
529 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
530 typedef int (*__libc_recvfrom)(int sockfd,
534 struct sockaddr *src_addr,
536 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
537 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
538 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
539 typedef int (*__libc_sendto)(int sockfd,
543 const struct sockaddr *dst_addr,
545 typedef int (*__libc_setsockopt)(int sockfd,
551 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
553 typedef int (*__libc_socket)(int domain, int type, int protocol);
554 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
555 #ifdef HAVE_TIMERFD_CREATE
556 typedef int (*__libc_timerfd_create)(int clockid, int flags);
558 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
559 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
561 #define SWRAP_SYMBOL_ENTRY(i) \
567 struct swrap_libc_symbols {
569 SWRAP_SYMBOL_ENTRY(accept4);
571 SWRAP_SYMBOL_ENTRY(accept);
573 SWRAP_SYMBOL_ENTRY(bind);
574 SWRAP_SYMBOL_ENTRY(close);
575 SWRAP_SYMBOL_ENTRY(connect);
576 SWRAP_SYMBOL_ENTRY(dup);
577 SWRAP_SYMBOL_ENTRY(dup2);
578 SWRAP_SYMBOL_ENTRY(fcntl);
579 SWRAP_SYMBOL_ENTRY(fopen);
581 SWRAP_SYMBOL_ENTRY(fopen64);
584 SWRAP_SYMBOL_ENTRY(eventfd);
586 SWRAP_SYMBOL_ENTRY(getpeername);
587 SWRAP_SYMBOL_ENTRY(getsockname);
588 SWRAP_SYMBOL_ENTRY(getsockopt);
589 SWRAP_SYMBOL_ENTRY(ioctl);
590 SWRAP_SYMBOL_ENTRY(listen);
591 SWRAP_SYMBOL_ENTRY(open);
593 SWRAP_SYMBOL_ENTRY(open64);
595 SWRAP_SYMBOL_ENTRY(openat);
596 SWRAP_SYMBOL_ENTRY(pipe);
597 SWRAP_SYMBOL_ENTRY(read);
598 SWRAP_SYMBOL_ENTRY(readv);
599 SWRAP_SYMBOL_ENTRY(recv);
600 SWRAP_SYMBOL_ENTRY(recvfrom);
601 SWRAP_SYMBOL_ENTRY(recvmsg);
602 SWRAP_SYMBOL_ENTRY(send);
603 SWRAP_SYMBOL_ENTRY(sendmsg);
604 SWRAP_SYMBOL_ENTRY(sendto);
605 SWRAP_SYMBOL_ENTRY(setsockopt);
607 SWRAP_SYMBOL_ENTRY(signalfd);
609 SWRAP_SYMBOL_ENTRY(socket);
610 SWRAP_SYMBOL_ENTRY(socketpair);
611 #ifdef HAVE_TIMERFD_CREATE
612 SWRAP_SYMBOL_ENTRY(timerfd_create);
614 SWRAP_SYMBOL_ENTRY(write);
615 SWRAP_SYMBOL_ENTRY(writev);
622 struct swrap_libc_symbols symbols;
626 static struct swrap swrap;
629 static char *socket_wrapper_dir(void);
631 #define LIBC_NAME "libc.so"
638 static const char *swrap_str_lib(enum swrap_lib lib)
643 case SWRAP_LIBSOCKET:
647 /* Compiler would warn us about unhandled enum value if we get here */
651 static void *swrap_load_lib_handle(enum swrap_lib lib)
653 int flags = RTLD_LAZY;
658 const char *env_preload = getenv("LD_PRELOAD");
659 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
660 bool enable_deepbind = true;
662 /* Don't do a deepbind if we run with libasan */
663 if (env_preload != NULL && strlen(env_preload) < 1024) {
664 const char *p = strstr(env_preload, "libasan.so");
666 enable_deepbind = false;
670 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
671 enable_deepbind = false;
674 if (enable_deepbind) {
675 flags |= RTLD_DEEPBIND;
680 case SWRAP_LIBSOCKET:
681 #ifdef HAVE_LIBSOCKET
682 handle = swrap.libc.socket_handle;
683 if (handle == NULL) {
684 for (i = 10; i >= 0; i--) {
685 char soname[256] = {0};
687 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
688 handle = dlopen(soname, flags);
689 if (handle != NULL) {
694 swrap.libc.socket_handle = handle;
699 handle = swrap.libc.handle;
701 if (handle == NULL) {
702 handle = dlopen(LIBC_SO, flags);
704 swrap.libc.handle = handle;
707 if (handle == NULL) {
708 for (i = 10; i >= 0; i--) {
709 char soname[256] = {0};
711 snprintf(soname, sizeof(soname), "libc.so.%d", i);
712 handle = dlopen(soname, flags);
713 if (handle != NULL) {
718 swrap.libc.handle = handle;
723 if (handle == NULL) {
725 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
727 SWRAP_LOG(SWRAP_LOG_ERROR,
728 "Failed to dlopen library: %s",
737 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
742 handle = swrap_load_lib_handle(lib);
744 func = dlsym(handle, fn_name);
746 SWRAP_LOG(SWRAP_LOG_ERROR,
747 "Failed to find %s: %s",
753 SWRAP_LOG(SWRAP_LOG_TRACE,
761 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
762 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
766 ret = pthread_mutex_lock(mutex);
768 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
769 getpid(), getppid(), caller, line, name, strerror(ret));
774 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
775 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
779 ret = pthread_mutex_unlock(mutex);
781 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
782 getpid(), getppid(), caller, line, name, strerror(ret));
788 * These macros have a thread race condition on purpose!
790 * This is an optimization to avoid locking each time we check if the symbol is
793 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
794 swrap.libc.symbols._libc_##sym_name.obj = \
795 _swrap_bind_symbol(lib, #sym_name); \
798 #define swrap_bind_symbol_libc(sym_name) \
799 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
801 #define swrap_bind_symbol_libsocket(sym_name) \
802 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
804 static void swrap_bind_symbol_all(void);
806 /****************************************************************************
808 ****************************************************************************
810 * Functions especially from libc need to be loaded individually, you can't
811 * load all at once or gdb will segfault at startup. The same applies to
812 * valgrind and has probably something todo with with the linker. So we need
813 * load each function at the point it is called the first time.
815 ****************************************************************************/
818 static int libc_accept4(int sockfd,
819 struct sockaddr *addr,
823 swrap_bind_symbol_all();
825 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
828 #else /* HAVE_ACCEPT4 */
830 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
832 swrap_bind_symbol_all();
834 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
836 #endif /* HAVE_ACCEPT4 */
838 static int libc_bind(int sockfd,
839 const struct sockaddr *addr,
842 swrap_bind_symbol_all();
844 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
847 static int libc_close(int fd)
849 swrap_bind_symbol_all();
851 return swrap.libc.symbols._libc_close.f(fd);
854 static int libc_connect(int sockfd,
855 const struct sockaddr *addr,
858 swrap_bind_symbol_all();
860 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
863 static int libc_dup(int fd)
865 swrap_bind_symbol_all();
867 return swrap.libc.symbols._libc_dup.f(fd);
870 static int libc_dup2(int oldfd, int newfd)
872 swrap_bind_symbol_all();
874 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
878 static int libc_eventfd(int count, int flags)
880 swrap_bind_symbol_all();
882 return swrap.libc.symbols._libc_eventfd.f(count, flags);
886 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
887 static int libc_vfcntl(int fd, int cmd, va_list ap)
892 swrap_bind_symbol_all();
894 arg = va_arg(ap, void *);
896 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
901 static int libc_getpeername(int sockfd,
902 struct sockaddr *addr,
905 swrap_bind_symbol_all();
907 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
910 static int libc_getsockname(int sockfd,
911 struct sockaddr *addr,
914 swrap_bind_symbol_all();
916 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
919 static int libc_getsockopt(int sockfd,
925 swrap_bind_symbol_all();
927 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
934 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
935 static int libc_vioctl(int d, unsigned long int request, va_list ap)
940 swrap_bind_symbol_all();
942 arg = va_arg(ap, void *);
944 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
949 static int libc_listen(int sockfd, int backlog)
951 swrap_bind_symbol_all();
953 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
956 static FILE *libc_fopen(const char *name, const char *mode)
958 swrap_bind_symbol_all();
960 return swrap.libc.symbols._libc_fopen.f(name, mode);
964 static FILE *libc_fopen64(const char *name, const char *mode)
966 swrap_bind_symbol_all();
968 return swrap.libc.symbols._libc_fopen64.f(name, mode);
970 #endif /* HAVE_FOPEN64 */
972 static int libc_vopen(const char *pathname, int flags, va_list ap)
977 swrap_bind_symbol_all();
979 if (flags & O_CREAT) {
980 mode = va_arg(ap, int);
982 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
987 static int libc_open(const char *pathname, int flags, ...)
993 fd = libc_vopen(pathname, flags, ap);
1000 static int libc_vopen64(const char *pathname, int flags, va_list ap)
1005 swrap_bind_symbol_all();
1007 if (flags & O_CREAT) {
1008 mode = va_arg(ap, int);
1010 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1014 #endif /* HAVE_OPEN64 */
1016 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1021 swrap_bind_symbol_all();
1023 if (flags & O_CREAT) {
1024 mode = va_arg(ap, int);
1026 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1035 static int libc_openat(int dirfd, const char *path, int flags, ...)
1040 va_start(ap, flags);
1041 fd = libc_vopenat(dirfd, path, flags, ap);
1048 static int libc_pipe(int pipefd[2])
1050 swrap_bind_symbol_all();
1052 return swrap.libc.symbols._libc_pipe.f(pipefd);
1055 static int libc_read(int fd, void *buf, size_t count)
1057 swrap_bind_symbol_all();
1059 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1062 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1064 swrap_bind_symbol_all();
1066 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1069 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1071 swrap_bind_symbol_all();
1073 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1076 static int libc_recvfrom(int sockfd,
1080 struct sockaddr *src_addr,
1083 swrap_bind_symbol_all();
1085 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1093 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1095 swrap_bind_symbol_all();
1097 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1100 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1102 swrap_bind_symbol_all();
1104 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1107 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1109 swrap_bind_symbol_all();
1111 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1114 static int libc_sendto(int sockfd,
1118 const struct sockaddr *dst_addr,
1121 swrap_bind_symbol_all();
1123 return swrap.libc.symbols._libc_sendto.f(sockfd,
1131 static int libc_setsockopt(int sockfd,
1137 swrap_bind_symbol_all();
1139 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1146 #ifdef HAVE_SIGNALFD
1147 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1149 swrap_bind_symbol_all();
1151 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1155 static int libc_socket(int domain, int type, int protocol)
1157 swrap_bind_symbol_all();
1159 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1162 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1164 swrap_bind_symbol_all();
1166 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1169 #ifdef HAVE_TIMERFD_CREATE
1170 static int libc_timerfd_create(int clockid, int flags)
1172 swrap_bind_symbol_all();
1174 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1178 static ssize_t libc_write(int fd, const void *buf, size_t count)
1180 swrap_bind_symbol_all();
1182 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1185 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1187 swrap_bind_symbol_all();
1189 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1192 /* DO NOT call this function during library initialization! */
1193 static void __swrap_bind_symbol_all_once(void)
1196 swrap_bind_symbol_libsocket(accept4);
1198 swrap_bind_symbol_libsocket(accept);
1200 swrap_bind_symbol_libsocket(bind);
1201 swrap_bind_symbol_libc(close);
1202 swrap_bind_symbol_libsocket(connect);
1203 swrap_bind_symbol_libc(dup);
1204 swrap_bind_symbol_libc(dup2);
1205 swrap_bind_symbol_libc(fcntl);
1206 swrap_bind_symbol_libc(fopen);
1208 swrap_bind_symbol_libc(fopen64);
1211 swrap_bind_symbol_libc(eventfd);
1213 swrap_bind_symbol_libsocket(getpeername);
1214 swrap_bind_symbol_libsocket(getsockname);
1215 swrap_bind_symbol_libsocket(getsockopt);
1216 swrap_bind_symbol_libc(ioctl);
1217 swrap_bind_symbol_libsocket(listen);
1218 swrap_bind_symbol_libc(open);
1220 swrap_bind_symbol_libc(open64);
1222 swrap_bind_symbol_libc(openat);
1223 swrap_bind_symbol_libsocket(pipe);
1224 swrap_bind_symbol_libc(read);
1225 swrap_bind_symbol_libsocket(readv);
1226 swrap_bind_symbol_libsocket(recv);
1227 swrap_bind_symbol_libsocket(recvfrom);
1228 swrap_bind_symbol_libsocket(recvmsg);
1229 swrap_bind_symbol_libsocket(send);
1230 swrap_bind_symbol_libsocket(sendmsg);
1231 swrap_bind_symbol_libsocket(sendto);
1232 swrap_bind_symbol_libsocket(setsockopt);
1233 #ifdef HAVE_SIGNALFD
1234 swrap_bind_symbol_libsocket(signalfd);
1236 swrap_bind_symbol_libsocket(socket);
1237 swrap_bind_symbol_libsocket(socketpair);
1238 #ifdef HAVE_TIMERFD_CREATE
1239 swrap_bind_symbol_libc(timerfd_create);
1241 swrap_bind_symbol_libc(write);
1242 swrap_bind_symbol_libsocket(writev);
1245 static void swrap_bind_symbol_all(void)
1247 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1249 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1252 /*********************************************************
1253 * SWRAP HELPER FUNCTIONS
1254 *********************************************************/
1257 * We return 127.0.0.0 (default) or 10.53.57.0.
1259 * This can be controlled by:
1260 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1262 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1264 static in_addr_t swrap_ipv4_net(void)
1266 static int initialized;
1267 static in_addr_t hv;
1268 const char *net_str = NULL;
1277 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1278 if (net_str == NULL) {
1279 net_str = "127.0.0.0";
1282 ret = inet_pton(AF_INET, net_str, &nv);
1284 SWRAP_LOG(SWRAP_LOG_ERROR,
1285 "INVALID IPv4 Network [%s]",
1290 hv = ntohl(nv.s_addr);
1300 SWRAP_LOG(SWRAP_LOG_ERROR,
1301 "INVALID IPv4 Network [%s][0x%x] should be "
1302 "127.0.0.0 or 10.53.57.0",
1303 net_str, (unsigned)hv);
1311 * This returns 127.255.255.255 or 10.255.255.255
1313 static in_addr_t swrap_ipv4_bcast(void)
1317 hv = swrap_ipv4_net();
1318 hv |= IN_CLASSA_HOST;
1324 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1326 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1330 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1331 SWRAP_LOG(SWRAP_LOG_ERROR,
1332 "swrap_ipv4_iface(%u) invalid!",
1338 hv = swrap_ipv4_net();
1348 static const struct in6_addr *swrap_ipv6(void)
1350 static struct in6_addr v;
1351 static int initialized;
1359 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1368 static void set_port(int family, int prt, struct swrap_address *addr)
1372 addr->sa.in.sin_port = htons(prt);
1376 addr->sa.in6.sin6_port = htons(prt);
1382 static size_t socket_length(int family)
1386 return sizeof(struct sockaddr_in);
1389 return sizeof(struct sockaddr_in6);
1395 static struct socket_info *swrap_get_socket_info(int si_index)
1397 return (struct socket_info *)(&(sockets[si_index].info));
1400 static int swrap_get_refcount(struct socket_info *si)
1402 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1403 return sic->meta.refcount;
1406 static void swrap_inc_refcount(struct socket_info *si)
1408 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1410 sic->meta.refcount += 1;
1413 static void swrap_dec_refcount(struct socket_info *si)
1415 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1417 sic->meta.refcount -= 1;
1420 static int swrap_get_next_free(struct socket_info *si)
1422 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1424 return sic->meta.next_free;
1427 static void swrap_set_next_free(struct socket_info *si, int next_free)
1429 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1431 sic->meta.next_free = next_free;
1434 static int swrap_un_path(struct sockaddr_un *un,
1435 const char *swrap_dir,
1442 ret = snprintf(un->sun_path,
1443 sizeof(un->sun_path),
1449 if ((size_t)ret >= sizeof(un->sun_path)) {
1450 return ENAMETOOLONG;
1456 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1457 const char *swrap_dir)
1461 ret = snprintf(un->sun_path,
1462 sizeof(un->sun_path),
1466 if ((size_t)ret >= sizeof(un->sun_path)) {
1467 return ENAMETOOLONG;
1473 static bool swrap_dir_usable(const char *swrap_dir)
1475 struct sockaddr_un un;
1478 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1483 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1491 static char *socket_wrapper_dir(void)
1493 char *swrap_dir = NULL;
1494 char *s = getenv("SOCKET_WRAPPER_DIR");
1498 if (s == NULL || s[0] == '\0') {
1499 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1503 swrap_dir = realpath(s, NULL);
1504 if (swrap_dir == NULL) {
1505 SWRAP_LOG(SWRAP_LOG_ERROR,
1506 "Unable to resolve socket_wrapper dir path: %s - %s",
1512 ok = swrap_dir_usable(swrap_dir);
1519 ok = swrap_dir_usable(s);
1521 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1525 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1527 SWRAP_LOG(SWRAP_LOG_ERROR,
1528 "realpath(SOCKET_WRAPPER_DIR) too long and "
1529 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1534 swrap_dir = strdup(s);
1535 if (swrap_dir == NULL) {
1536 SWRAP_LOG(SWRAP_LOG_ERROR,
1537 "Unable to duplicate socket_wrapper dir path");
1541 SWRAP_LOG(SWRAP_LOG_WARN,
1542 "realpath(SOCKET_WRAPPER_DIR) too long, "
1543 "using original SOCKET_WRAPPER_DIR\n");
1546 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1550 static unsigned int socket_wrapper_mtu(void)
1552 static unsigned int max_mtu = 0;
1557 swrap_mutex_lock(&mtu_update_mutex);
1563 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1565 s = getenv("SOCKET_WRAPPER_MTU");
1570 tmp = strtol(s, &endp, 10);
1575 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1581 swrap_mutex_unlock(&mtu_update_mutex);
1585 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1587 pthread_mutexattr_t ma;
1588 bool need_destroy = false;
1591 #define __CHECK(cmd) do { \
1594 SWRAP_LOG(SWRAP_LOG_ERROR, \
1595 "%s: %s - failed %d", \
1601 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1602 __CHECK(pthread_mutexattr_init(&ma));
1603 need_destroy = true;
1604 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1605 __CHECK(pthread_mutex_init(m, &ma));
1608 pthread_mutexattr_destroy(&ma);
1613 static size_t socket_wrapper_max_sockets(void)
1619 if (socket_info_max != 0) {
1620 return socket_info_max;
1623 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1625 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1626 if (s == NULL || s[0] == '\0') {
1630 tmp = strtoul(s, &endp, 10);
1635 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1636 SWRAP_LOG(SWRAP_LOG_ERROR,
1637 "Invalid number of sockets specified, "
1638 "using default (%zu)",
1642 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1643 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1644 SWRAP_LOG(SWRAP_LOG_ERROR,
1645 "Invalid number of sockets specified, "
1646 "using maximum (%zu).",
1650 socket_info_max = tmp;
1653 return socket_info_max;
1656 static void socket_wrapper_init_fds_idx(void)
1661 if (socket_fds_idx != NULL) {
1665 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1667 SWRAP_LOG(SWRAP_LOG_ERROR,
1668 "Failed to allocate socket fds index array: %s",
1673 for (i = 0; i < socket_fds_max; i++) {
1677 socket_fds_idx = tmp;
1680 static void socket_wrapper_init_sockets(void)
1686 swrap_bind_symbol_all();
1688 swrap_mutex_lock(&sockets_mutex);
1690 if (sockets != NULL) {
1691 swrap_mutex_unlock(&sockets_mutex);
1695 SWRAP_LOG(SWRAP_LOG_DEBUG,
1696 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1697 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1700 * Intialize the static cache early before
1701 * any thread is able to start.
1703 (void)swrap_ipv4_net();
1705 socket_wrapper_init_fds_idx();
1707 /* Needs to be called inside the sockets_mutex lock here. */
1708 max_sockets = socket_wrapper_max_sockets();
1710 sockets = (struct socket_info_container *)calloc(max_sockets,
1711 sizeof(struct socket_info_container));
1713 if (sockets == NULL) {
1714 SWRAP_LOG(SWRAP_LOG_ERROR,
1715 "Failed to allocate sockets array: %s",
1717 swrap_mutex_unlock(&sockets_mutex);
1721 swrap_mutex_lock(&first_free_mutex);
1722 swrap_mutex_lock(&sockets_si_global);
1726 for (i = 0; i < max_sockets; i++) {
1727 swrap_set_next_free(&sockets[i].info, i+1);
1730 /* mark the end of the free list */
1731 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1733 swrap_mutex_unlock(&sockets_si_global);
1734 swrap_mutex_unlock(&first_free_mutex);
1735 swrap_mutex_unlock(&sockets_mutex);
1741 bool socket_wrapper_enabled(void)
1743 char *s = socket_wrapper_dir();
1751 socket_wrapper_init_sockets();
1756 static unsigned int socket_wrapper_default_iface(void)
1758 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1761 if (sscanf(s, "%u", &iface) == 1) {
1762 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1768 return 1;/* 127.0.0.1 */
1771 static void set_socket_info_index(int fd, int idx)
1773 SWRAP_LOG(SWRAP_LOG_TRACE,
1776 socket_fds_idx[fd] = idx;
1777 /* This builtin issues a full memory barrier. */
1778 __sync_synchronize();
1781 static void reset_socket_info_index(int fd)
1783 SWRAP_LOG(SWRAP_LOG_TRACE,
1786 set_socket_info_index(fd, -1);
1789 static int find_socket_info_index(int fd)
1795 if (socket_fds_idx == NULL) {
1799 if ((size_t)fd >= socket_fds_max) {
1801 * Do not add a log here as some applications do stupid things
1804 * for (fd = 0; fd <= getdtablesize(); fd++) {
1808 * This would produce millions of lines of debug messages.
1811 SWRAP_LOG(SWRAP_LOG_ERROR,
1812 "Looking for a socket info for the fd %d is over the "
1813 "max socket index limit of %zu.",
1820 /* This builtin issues a full memory barrier. */
1821 __sync_synchronize();
1822 return socket_fds_idx[fd];
1825 static int swrap_add_socket_info(const struct socket_info *si_input)
1827 struct socket_info *si = NULL;
1830 if (si_input == NULL) {
1835 swrap_mutex_lock(&first_free_mutex);
1836 if (first_free == -1) {
1841 si_index = first_free;
1842 si = swrap_get_socket_info(si_index);
1846 first_free = swrap_get_next_free(si);
1848 swrap_inc_refcount(si);
1850 SWRAP_UNLOCK_SI(si);
1853 swrap_mutex_unlock(&first_free_mutex);
1858 static int swrap_create_socket(struct socket_info *si, int fd)
1862 if ((size_t)fd >= socket_fds_max) {
1863 SWRAP_LOG(SWRAP_LOG_ERROR,
1864 "The max socket index limit of %zu has been reached, "
1872 idx = swrap_add_socket_info(si);
1877 set_socket_info_index(fd, idx);
1882 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1889 p = strrchr(un->sun_path, '/');
1890 if (p) p++; else p = un->sun_path;
1892 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1893 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1899 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1900 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1907 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1913 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1917 case SOCKET_TYPE_CHAR_TCP:
1918 case SOCKET_TYPE_CHAR_UDP: {
1919 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1921 if ((*len) < sizeof(*in2)) {
1922 SWRAP_LOG(SWRAP_LOG_ERROR,
1923 "V4: *len(%zu) < sizeof(*in2)=%zu",
1924 (size_t)*len, sizeof(*in2));
1929 memset(in2, 0, sizeof(*in2));
1930 in2->sin_family = AF_INET;
1931 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1932 in2->sin_port = htons(prt);
1934 *len = sizeof(*in2);
1938 case SOCKET_TYPE_CHAR_TCP_V6:
1939 case SOCKET_TYPE_CHAR_UDP_V6: {
1940 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1942 if ((*len) < sizeof(*in2)) {
1943 SWRAP_LOG(SWRAP_LOG_ERROR,
1944 "V6: *len(%zu) < sizeof(*in2)=%zu",
1945 (size_t)*len, sizeof(*in2));
1946 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1951 memset(in2, 0, sizeof(*in2));
1952 in2->sin6_family = AF_INET6;
1953 in2->sin6_addr = *swrap_ipv6();
1954 in2->sin6_addr.s6_addr[15] = iface;
1955 in2->sin6_port = htons(prt);
1957 *len = sizeof(*in2);
1962 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1971 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1978 char *swrap_dir = NULL;
1980 if (bcast) *bcast = 0;
1982 switch (inaddr->sa_family) {
1984 const struct sockaddr_in *in =
1985 (const struct sockaddr_in *)(const void *)inaddr;
1986 unsigned int addr = ntohl(in->sin_addr.s_addr);
1990 const unsigned int sw_net_addr = swrap_ipv4_net();
1991 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1995 u_type = SOCKET_TYPE_CHAR_TCP;
1998 u_type = SOCKET_TYPE_CHAR_UDP;
1999 a_type = SOCKET_TYPE_CHAR_UDP;
2000 b_type = SOCKET_TYPE_CHAR_UDP;
2003 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2004 errno = ESOCKTNOSUPPORT;
2008 prt = ntohs(in->sin_port);
2009 if (a_type && addr == 0xFFFFFFFF) {
2010 /* 255.255.255.255 only udp */
2013 iface = socket_wrapper_default_iface();
2014 } else if (b_type && addr == sw_bcast_addr) {
2023 iface = socket_wrapper_default_iface();
2024 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2025 /* 127.0.0.X or 10.53.57.X */
2028 iface = (addr & 0x000000FF);
2030 char str[256] = {0,};
2031 inet_ntop(inaddr->sa_family,
2034 SWRAP_LOG(SWRAP_LOG_WARN,
2036 str, (unsigned)prt);
2037 errno = ENETUNREACH;
2040 if (bcast) *bcast = is_bcast;
2045 const struct sockaddr_in6 *in =
2046 (const struct sockaddr_in6 *)(const void *)inaddr;
2047 struct in6_addr cmp1, cmp2;
2051 type = SOCKET_TYPE_CHAR_TCP_V6;
2054 type = SOCKET_TYPE_CHAR_UDP_V6;
2057 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2058 errno = ESOCKTNOSUPPORT;
2062 /* XXX no multicast/broadcast */
2064 prt = ntohs(in->sin6_port);
2066 cmp1 = *swrap_ipv6();
2067 cmp2 = in->sin6_addr;
2068 cmp2.s6_addr[15] = 0;
2069 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2070 iface = in->sin6_addr.s6_addr[15];
2072 char str[256] = {0,};
2073 inet_ntop(inaddr->sa_family,
2076 SWRAP_LOG(SWRAP_LOG_WARN,
2078 str, (unsigned)prt);
2079 errno = ENETUNREACH;
2087 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2088 errno = ENETUNREACH;
2093 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2098 swrap_dir = socket_wrapper_dir();
2099 if (swrap_dir == NULL) {
2105 swrap_un_path_EINVAL(un, swrap_dir);
2106 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2107 SAFE_FREE(swrap_dir);
2108 /* the caller need to do more processing */
2112 swrap_un_path(un, swrap_dir, type, iface, prt);
2113 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2115 SAFE_FREE(swrap_dir);
2120 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2128 char *swrap_dir = NULL;
2130 if (bcast) *bcast = 0;
2132 switch (si->family) {
2134 const struct sockaddr_in *in =
2135 (const struct sockaddr_in *)(const void *)inaddr;
2136 unsigned int addr = ntohl(in->sin_addr.s_addr);
2141 const unsigned int sw_net_addr = swrap_ipv4_net();
2142 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2144 prt = ntohs(in->sin_port);
2148 u_type = SOCKET_TYPE_CHAR_TCP;
2149 d_type = SOCKET_TYPE_CHAR_TCP;
2152 u_type = SOCKET_TYPE_CHAR_UDP;
2153 d_type = SOCKET_TYPE_CHAR_UDP;
2154 a_type = SOCKET_TYPE_CHAR_UDP;
2155 b_type = SOCKET_TYPE_CHAR_UDP;
2158 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2159 errno = ESOCKTNOSUPPORT;
2167 iface = socket_wrapper_default_iface();
2168 } else if (a_type && addr == 0xFFFFFFFF) {
2169 /* 255.255.255.255 only udp */
2172 iface = socket_wrapper_default_iface();
2173 } else if (b_type && addr == sw_bcast_addr) {
2174 /* 127.255.255.255 only udp */
2177 iface = socket_wrapper_default_iface();
2178 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2182 iface = (addr & 0x000000FF);
2184 errno = EADDRNOTAVAIL;
2188 /* Store the bind address for connect() */
2189 if (si->bindname.sa_socklen == 0) {
2190 struct sockaddr_in bind_in;
2191 socklen_t blen = sizeof(struct sockaddr_in);
2193 ZERO_STRUCT(bind_in);
2194 bind_in.sin_family = in->sin_family;
2195 bind_in.sin_port = in->sin_port;
2196 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2197 si->bindname.sa_socklen = blen;
2198 memcpy(&si->bindname.sa.in, &bind_in, blen);
2205 const struct sockaddr_in6 *in =
2206 (const struct sockaddr_in6 *)(const void *)inaddr;
2207 struct in6_addr cmp1, cmp2;
2211 type = SOCKET_TYPE_CHAR_TCP_V6;
2214 type = SOCKET_TYPE_CHAR_UDP_V6;
2217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2218 errno = ESOCKTNOSUPPORT;
2222 /* XXX no multicast/broadcast */
2224 prt = ntohs(in->sin6_port);
2226 cmp1 = *swrap_ipv6();
2227 cmp2 = in->sin6_addr;
2228 cmp2.s6_addr[15] = 0;
2229 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2230 iface = socket_wrapper_default_iface();
2231 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2232 iface = in->sin6_addr.s6_addr[15];
2234 errno = EADDRNOTAVAIL;
2238 /* Store the bind address for connect() */
2239 if (si->bindname.sa_socklen == 0) {
2240 struct sockaddr_in6 bind_in;
2241 socklen_t blen = sizeof(struct sockaddr_in6);
2243 ZERO_STRUCT(bind_in);
2244 bind_in.sin6_family = in->sin6_family;
2245 bind_in.sin6_port = in->sin6_port;
2247 bind_in.sin6_addr = *swrap_ipv6();
2248 bind_in.sin6_addr.s6_addr[15] = iface;
2250 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2251 si->bindname.sa_socklen = blen;
2258 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2259 errno = EADDRNOTAVAIL;
2264 if (bcast) *bcast = is_bcast;
2266 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2271 swrap_dir = socket_wrapper_dir();
2272 if (swrap_dir == NULL) {
2278 /* handle auto-allocation of ephemeral ports */
2279 for (prt = 5001; prt < 10000; prt++) {
2280 swrap_un_path(un, swrap_dir, type, iface, prt);
2281 if (stat(un->sun_path, &st) == 0) continue;
2283 set_port(si->family, prt, &si->myname);
2284 set_port(si->family, prt, &si->bindname);
2291 SAFE_FREE(swrap_dir);
2296 swrap_un_path(un, swrap_dir, type, iface, prt);
2297 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2299 SAFE_FREE(swrap_dir);
2304 static struct socket_info *find_socket_info(int fd)
2306 int idx = find_socket_info_index(fd);
2312 return swrap_get_socket_info(idx);
2316 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2318 struct socket_info_fd *f;
2319 const struct socket_info *last_s = NULL;
2321 /* first catch invalid input */
2322 switch (sa->sa_family) {
2324 if (len < sizeof(struct sockaddr_in)) {
2330 if (len < sizeof(struct sockaddr_in6)) {
2340 for (f = socket_fds; f; f = f->next) {
2341 struct socket_info *s = swrap_get_socket_info(f->si_index);
2348 if (s->myname == NULL) {
2351 if (s->myname->sa_family != sa->sa_family) {
2354 switch (s->myname->sa_family) {
2356 struct sockaddr_in *sin1, *sin2;
2358 sin1 = (struct sockaddr_in *)s->myname;
2359 sin2 = (struct sockaddr_in *)sa;
2361 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2364 if (sin1->sin_port != sin2->sin_port) {
2367 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2377 struct sockaddr_in6 *sin1, *sin2;
2379 sin1 = (struct sockaddr_in6 *)s->myname;
2380 sin2 = (struct sockaddr_in6 *)sa;
2382 if (sin1->sin6_port != sin2->sin6_port) {
2385 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2407 static void swrap_remove_stale(int fd)
2409 struct socket_info *si;
2412 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2414 swrap_mutex_lock(&socket_reset_mutex);
2416 si_index = find_socket_info_index(fd);
2417 if (si_index == -1) {
2418 swrap_mutex_unlock(&socket_reset_mutex);
2422 reset_socket_info_index(fd);
2424 si = swrap_get_socket_info(si_index);
2426 swrap_mutex_lock(&first_free_mutex);
2429 swrap_dec_refcount(si);
2431 if (swrap_get_refcount(si) > 0) {
2435 if (si->un_addr.sun_path[0] != '\0') {
2436 unlink(si->un_addr.sun_path);
2439 swrap_set_next_free(si, first_free);
2440 first_free = si_index;
2443 SWRAP_UNLOCK_SI(si);
2444 swrap_mutex_unlock(&first_free_mutex);
2445 swrap_mutex_unlock(&socket_reset_mutex);
2448 static int sockaddr_convert_to_un(struct socket_info *si,
2449 const struct sockaddr *in_addr,
2451 struct sockaddr_un *out_addr,
2455 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2457 (void) in_len; /* unused */
2459 if (out_addr == NULL) {
2463 out->sa_family = AF_UNIX;
2464 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2465 out->sa_len = sizeof(*out_addr);
2468 switch (in_addr->sa_family) {
2470 const struct sockaddr_in *sin;
2471 if (si->family != AF_INET) {
2474 if (in_len < sizeof(struct sockaddr_in)) {
2477 sin = (const struct sockaddr_in *)(const void *)in_addr;
2478 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2483 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2484 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2498 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2499 errno = ESOCKTNOSUPPORT;
2503 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2505 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2511 errno = EAFNOSUPPORT;
2512 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2516 static int sockaddr_convert_from_un(const struct socket_info *si,
2517 const struct sockaddr_un *in_addr,
2518 socklen_t un_addrlen,
2520 struct sockaddr *out_addr,
2521 socklen_t *out_addrlen)
2525 if (out_addr == NULL || out_addrlen == NULL)
2528 if (un_addrlen == 0) {
2543 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2544 errno = ESOCKTNOSUPPORT;
2547 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2548 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2549 out_addr->sa_len = *out_addrlen;
2556 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2557 errno = EAFNOSUPPORT;
2561 enum swrap_packet_type {
2563 SWRAP_CONNECT_UNREACH,
2571 SWRAP_SENDTO_UNREACH,
2582 struct swrap_file_hdr {
2584 uint16_t version_major;
2585 uint16_t version_minor;
2588 uint32_t frame_max_len;
2589 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2592 #define SWRAP_FILE_HDR_SIZE 24
2594 struct swrap_packet_frame {
2596 uint32_t micro_seconds;
2597 uint32_t recorded_length;
2598 uint32_t full_length;
2600 #define SWRAP_PACKET_FRAME_SIZE 16
2602 union swrap_packet_ip {
2606 uint16_t packet_length;
2607 uint16_t identification;
2612 uint16_t hdr_checksum;
2616 #define SWRAP_PACKET_IP_V4_SIZE 20
2619 uint8_t flow_label_high;
2620 uint16_t flow_label_low;
2621 uint16_t payload_length;
2622 uint8_t next_header;
2624 uint8_t src_addr[16];
2625 uint8_t dest_addr[16];
2627 #define SWRAP_PACKET_IP_V6_SIZE 40
2629 #define SWRAP_PACKET_IP_SIZE 40
2631 union swrap_packet_payload {
2633 uint16_t source_port;
2643 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2645 uint16_t source_port;
2650 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2657 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2664 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2666 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2668 #define SWRAP_PACKET_MIN_ALLOC \
2669 (SWRAP_PACKET_FRAME_SIZE + \
2670 SWRAP_PACKET_IP_SIZE + \
2671 SWRAP_PACKET_PAYLOAD_SIZE)
2673 static const char *swrap_pcap_init_file(void)
2675 static int initialized = 0;
2676 static const char *s = NULL;
2677 static const struct swrap_file_hdr h;
2678 static const struct swrap_packet_frame f;
2679 static const union swrap_packet_ip i;
2680 static const union swrap_packet_payload p;
2682 if (initialized == 1) {
2688 * TODO: don't use the structs use plain buffer offsets
2689 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2691 * for now make sure we disable PCAP support
2692 * if the struct has alignment!
2694 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2697 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2700 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2703 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2706 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2709 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2712 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2715 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2718 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2721 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2725 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2729 if (strncmp(s, "./", 2) == 0) {
2732 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2736 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2737 const struct sockaddr *src,
2738 const struct sockaddr *dest,
2740 const uint8_t *payload,
2742 unsigned long tcp_seqno,
2743 unsigned long tcp_ack,
2744 unsigned char tcp_ctl,
2746 size_t *_packet_len)
2748 uint8_t *base = NULL;
2749 uint8_t *buf = NULL;
2752 struct swrap_packet_frame *frame;
2756 union swrap_packet_ip *ip;
2758 union swrap_packet_payload *pay;
2761 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2762 size_t wire_hdr_len = 0;
2763 size_t wire_len = 0;
2764 size_t ip_hdr_len = 0;
2765 size_t icmp_hdr_len = 0;
2766 size_t icmp_truncate_len = 0;
2767 uint8_t protocol = 0, icmp_protocol = 0;
2768 const struct sockaddr_in *src_in = NULL;
2769 const struct sockaddr_in *dest_in = NULL;
2771 const struct sockaddr_in6 *src_in6 = NULL;
2772 const struct sockaddr_in6 *dest_in6 = NULL;
2777 switch (src->sa_family) {
2779 src_in = (const struct sockaddr_in *)(const void *)src;
2780 dest_in = (const struct sockaddr_in *)(const void *)dest;
2781 src_port = src_in->sin_port;
2782 dest_port = dest_in->sin_port;
2783 ip_hdr_len = sizeof(i.ip->v4);
2787 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2788 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2789 src_port = src_in6->sin6_port;
2790 dest_port = dest_in6->sin6_port;
2791 ip_hdr_len = sizeof(i.ip->v6);
2798 switch (socket_type) {
2800 protocol = 0x06; /* TCP */
2801 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2802 wire_len = wire_hdr_len + payload_len;
2806 protocol = 0x11; /* UDP */
2807 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2808 wire_len = wire_hdr_len + payload_len;
2816 icmp_protocol = protocol;
2817 switch (src->sa_family) {
2819 protocol = 0x01; /* ICMPv4 */
2820 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2824 protocol = 0x3A; /* ICMPv6 */
2825 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2829 if (wire_len > 64 ) {
2830 icmp_truncate_len = wire_len - 64;
2832 wire_len += icmp_hdr_len;
2835 packet_len = nonwire_len + wire_len;
2836 alloc_len = packet_len;
2837 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2838 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2841 base = (uint8_t *)calloc(1, alloc_len);
2849 f.frame->seconds = tval->tv_sec;
2850 f.frame->micro_seconds = tval->tv_usec;
2851 f.frame->recorded_length = wire_len - icmp_truncate_len;
2852 f.frame->full_length = wire_len - icmp_truncate_len;
2854 buf += SWRAP_PACKET_FRAME_SIZE;
2857 switch (src->sa_family) {
2859 if (src_in == NULL || dest_in == NULL) {
2864 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2865 i.ip->v4.tos = 0x00;
2866 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2867 i.ip->v4.identification = htons(0xFFFF);
2868 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2869 i.ip->v4.fragment = htons(0x0000);
2870 i.ip->v4.ttl = 0xFF;
2871 i.ip->v4.protocol = protocol;
2872 i.ip->v4.hdr_checksum = htons(0x0000);
2873 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2874 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2875 buf += SWRAP_PACKET_IP_V4_SIZE;
2879 if (src_in6 == NULL || dest_in6 == NULL) {
2884 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2885 i.ip->v6.flow_label_high = 0x00;
2886 i.ip->v6.flow_label_low = 0x0000;
2887 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2888 i.ip->v6.next_header = protocol;
2889 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2890 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2891 buf += SWRAP_PACKET_IP_V6_SIZE;
2897 pay = (union swrap_packet_payload *)(void *)buf;
2898 switch (src->sa_family) {
2900 pay->icmp4.type = 0x03; /* destination unreachable */
2901 pay->icmp4.code = 0x01; /* host unreachable */
2902 pay->icmp4.checksum = htons(0x0000);
2903 pay->icmp4.unused = htonl(0x00000000);
2905 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2907 /* set the ip header in the ICMP payload */
2909 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2910 i.ip->v4.tos = 0x00;
2911 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2912 i.ip->v4.identification = htons(0xFFFF);
2913 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2914 i.ip->v4.fragment = htons(0x0000);
2915 i.ip->v4.ttl = 0xFF;
2916 i.ip->v4.protocol = icmp_protocol;
2917 i.ip->v4.hdr_checksum = htons(0x0000);
2918 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2919 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2921 buf += SWRAP_PACKET_IP_V4_SIZE;
2923 src_port = dest_in->sin_port;
2924 dest_port = src_in->sin_port;
2928 pay->icmp6.type = 0x01; /* destination unreachable */
2929 pay->icmp6.code = 0x03; /* address unreachable */
2930 pay->icmp6.checksum = htons(0x0000);
2931 pay->icmp6.unused = htonl(0x00000000);
2932 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2934 /* set the ip header in the ICMP payload */
2936 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2937 i.ip->v6.flow_label_high = 0x00;
2938 i.ip->v6.flow_label_low = 0x0000;
2939 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2940 i.ip->v6.next_header = protocol;
2941 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2942 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2944 buf += SWRAP_PACKET_IP_V6_SIZE;
2946 src_port = dest_in6->sin6_port;
2947 dest_port = src_in6->sin6_port;
2953 pay = (union swrap_packet_payload *)(void *)buf;
2955 switch (socket_type) {
2957 pay->tcp.source_port = src_port;
2958 pay->tcp.dest_port = dest_port;
2959 pay->tcp.seq_num = htonl(tcp_seqno);
2960 pay->tcp.ack_num = htonl(tcp_ack);
2961 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2962 pay->tcp.control = tcp_ctl;
2963 pay->tcp.window = htons(0x7FFF);
2964 pay->tcp.checksum = htons(0x0000);
2965 pay->tcp.urg = htons(0x0000);
2966 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2971 pay->udp.source_port = src_port;
2972 pay->udp.dest_port = dest_port;
2973 pay->udp.length = htons(8 + payload_len);
2974 pay->udp.checksum = htons(0x0000);
2975 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2980 if (payload && payload_len > 0) {
2981 memcpy(buf, payload, payload_len);
2984 *_packet_len = packet_len - icmp_truncate_len;
2988 static int swrap_pcap_get_fd(const char *fname)
2996 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2998 struct swrap_file_hdr file_hdr;
2999 file_hdr.magic = 0xA1B2C3D4;
3000 file_hdr.version_major = 0x0002;
3001 file_hdr.version_minor = 0x0004;
3002 file_hdr.timezone = 0x00000000;
3003 file_hdr.sigfigs = 0x00000000;
3004 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
3005 file_hdr.link_type = 0x0065; /* 101 RAW IP */
3007 if (libc_write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3014 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3019 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3020 const struct sockaddr *addr,
3021 enum swrap_packet_type type,
3022 const void *buf, size_t len,
3025 const struct sockaddr *src_addr;
3026 const struct sockaddr *dest_addr;
3027 unsigned long tcp_seqno = 0;
3028 unsigned long tcp_ack = 0;
3029 unsigned char tcp_ctl = 0;
3030 int unreachable = 0;
3034 switch (si->family) {
3046 case SWRAP_CONNECT_SEND:
3047 if (si->type != SOCK_STREAM) {
3051 src_addr = &si->myname.sa.s;
3054 tcp_seqno = si->io.pck_snd;
3055 tcp_ack = si->io.pck_rcv;
3056 tcp_ctl = 0x02; /* SYN */
3058 si->io.pck_snd += 1;
3062 case SWRAP_CONNECT_RECV:
3063 if (si->type != SOCK_STREAM) {
3067 dest_addr = &si->myname.sa.s;
3070 tcp_seqno = si->io.pck_rcv;
3071 tcp_ack = si->io.pck_snd;
3072 tcp_ctl = 0x12; /** SYN,ACK */
3074 si->io.pck_rcv += 1;
3078 case SWRAP_CONNECT_UNREACH:
3079 if (si->type != SOCK_STREAM) {
3083 dest_addr = &si->myname.sa.s;
3086 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3087 tcp_seqno = si->io.pck_snd - 1;
3088 tcp_ack = si->io.pck_rcv;
3089 tcp_ctl = 0x02; /* SYN */
3094 case SWRAP_CONNECT_ACK:
3095 if (si->type != SOCK_STREAM) {
3099 src_addr = &si->myname.sa.s;
3102 tcp_seqno = si->io.pck_snd;
3103 tcp_ack = si->io.pck_rcv;
3104 tcp_ctl = 0x10; /* ACK */
3108 case SWRAP_ACCEPT_SEND:
3109 if (si->type != SOCK_STREAM) {
3113 dest_addr = &si->myname.sa.s;
3116 tcp_seqno = si->io.pck_rcv;
3117 tcp_ack = si->io.pck_snd;
3118 tcp_ctl = 0x02; /* SYN */
3120 si->io.pck_rcv += 1;
3124 case SWRAP_ACCEPT_RECV:
3125 if (si->type != SOCK_STREAM) {
3129 src_addr = &si->myname.sa.s;
3132 tcp_seqno = si->io.pck_snd;
3133 tcp_ack = si->io.pck_rcv;
3134 tcp_ctl = 0x12; /* SYN,ACK */
3136 si->io.pck_snd += 1;
3140 case SWRAP_ACCEPT_ACK:
3141 if (si->type != SOCK_STREAM) {
3145 dest_addr = &si->myname.sa.s;
3148 tcp_seqno = si->io.pck_rcv;
3149 tcp_ack = si->io.pck_snd;
3150 tcp_ctl = 0x10; /* ACK */
3155 src_addr = &si->myname.sa.s;
3156 dest_addr = &si->peername.sa.s;
3158 tcp_seqno = si->io.pck_snd;
3159 tcp_ack = si->io.pck_rcv;
3160 tcp_ctl = 0x18; /* PSH,ACK */
3162 si->io.pck_snd += len;
3166 case SWRAP_SEND_RST:
3167 dest_addr = &si->myname.sa.s;
3168 src_addr = &si->peername.sa.s;
3170 if (si->type == SOCK_DGRAM) {
3171 return swrap_pcap_marshall_packet(si,
3173 SWRAP_SENDTO_UNREACH,
3179 tcp_seqno = si->io.pck_rcv;
3180 tcp_ack = si->io.pck_snd;
3181 tcp_ctl = 0x14; /** RST,ACK */
3185 case SWRAP_PENDING_RST:
3186 dest_addr = &si->myname.sa.s;
3187 src_addr = &si->peername.sa.s;
3189 if (si->type == SOCK_DGRAM) {
3193 tcp_seqno = si->io.pck_rcv;
3194 tcp_ack = si->io.pck_snd;
3195 tcp_ctl = 0x14; /* RST,ACK */
3200 dest_addr = &si->myname.sa.s;
3201 src_addr = &si->peername.sa.s;
3203 tcp_seqno = si->io.pck_rcv;
3204 tcp_ack = si->io.pck_snd;
3205 tcp_ctl = 0x18; /* PSH,ACK */
3207 si->io.pck_rcv += len;
3211 case SWRAP_RECV_RST:
3212 dest_addr = &si->myname.sa.s;
3213 src_addr = &si->peername.sa.s;
3215 if (si->type == SOCK_DGRAM) {
3219 tcp_seqno = si->io.pck_rcv;
3220 tcp_ack = si->io.pck_snd;
3221 tcp_ctl = 0x14; /* RST,ACK */
3226 src_addr = &si->myname.sa.s;
3229 si->io.pck_snd += len;
3233 case SWRAP_SENDTO_UNREACH:
3234 dest_addr = &si->myname.sa.s;
3241 case SWRAP_RECVFROM:
3242 dest_addr = &si->myname.sa.s;
3245 si->io.pck_rcv += len;
3249 case SWRAP_CLOSE_SEND:
3250 if (si->type != SOCK_STREAM) {
3254 src_addr = &si->myname.sa.s;
3255 dest_addr = &si->peername.sa.s;
3257 tcp_seqno = si->io.pck_snd;
3258 tcp_ack = si->io.pck_rcv;
3259 tcp_ctl = 0x11; /* FIN, ACK */
3261 si->io.pck_snd += 1;
3265 case SWRAP_CLOSE_RECV:
3266 if (si->type != SOCK_STREAM) {
3270 dest_addr = &si->myname.sa.s;
3271 src_addr = &si->peername.sa.s;
3273 tcp_seqno = si->io.pck_rcv;
3274 tcp_ack = si->io.pck_snd;
3275 tcp_ctl = 0x11; /* FIN,ACK */
3277 si->io.pck_rcv += 1;
3281 case SWRAP_CLOSE_ACK:
3282 if (si->type != SOCK_STREAM) {
3286 src_addr = &si->myname.sa.s;
3287 dest_addr = &si->peername.sa.s;
3289 tcp_seqno = si->io.pck_snd;
3290 tcp_ack = si->io.pck_rcv;
3291 tcp_ctl = 0x10; /* ACK */
3298 swrapGetTimeOfDay(&tv);
3300 return swrap_pcap_packet_init(&tv,
3304 (const uint8_t *)buf,
3313 static void swrap_pcap_dump_packet(struct socket_info *si,
3314 const struct sockaddr *addr,
3315 enum swrap_packet_type type,
3316 const void *buf, size_t len)
3318 const char *file_name;
3320 size_t packet_len = 0;
3323 swrap_mutex_lock(&pcap_dump_mutex);
3325 file_name = swrap_pcap_init_file();
3330 packet = swrap_pcap_marshall_packet(si,
3336 if (packet == NULL) {
3340 fd = swrap_pcap_get_fd(file_name);
3342 if (libc_write(fd, packet, packet_len) != (ssize_t)packet_len) {
3351 swrap_mutex_unlock(&pcap_dump_mutex);
3354 /****************************************************************************
3356 ***************************************************************************/
3358 #ifdef HAVE_SIGNALFD
3359 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3363 rc = libc_signalfd(fd, mask, flags);
3365 swrap_remove_stale(fd);
3371 int signalfd(int fd, const sigset_t *mask, int flags)
3373 return swrap_signalfd(fd, mask, flags);
3377 /****************************************************************************
3379 ***************************************************************************/
3381 static int swrap_socket(int family, int type, int protocol)
3383 struct socket_info *si = NULL;
3384 struct socket_info _si = { 0 };
3387 int real_type = type;
3390 * Remove possible addition flags passed to socket() so
3391 * do not fail checking the type.
3392 * See https://lwn.net/Articles/281965/
3395 real_type &= ~SOCK_CLOEXEC;
3397 #ifdef SOCK_NONBLOCK
3398 real_type &= ~SOCK_NONBLOCK;
3401 if (!socket_wrapper_enabled()) {
3402 return libc_socket(family, type, protocol);
3413 #endif /* AF_NETLINK */
3416 #endif /* AF_PACKET */
3418 fd = libc_socket(family, type, protocol);
3420 /* Check if we have a stale fd and remove it */
3421 swrap_remove_stale(fd);
3422 SWRAP_LOG(SWRAP_LOG_TRACE,
3423 "Unix socket fd=%d",
3428 errno = EAFNOSUPPORT;
3432 switch (real_type) {
3438 errno = EPROTONOSUPPORT;
3446 if (real_type == SOCK_STREAM) {
3451 if (real_type == SOCK_DGRAM) {
3456 errno = EPROTONOSUPPORT;
3461 * We must call libc_socket with type, from the caller, not the version
3462 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3464 fd = libc_socket(AF_UNIX, type, 0);
3470 /* Check if we have a stale fd and remove it */
3471 swrap_remove_stale(fd);
3474 si->family = family;
3476 /* however, the rest of the socket_wrapper code expects just
3477 * the type, not the flags */
3478 si->type = real_type;
3479 si->protocol = protocol;
3482 * Setup myname so getsockname() can succeed to find out the socket
3485 switch(si->family) {
3487 struct sockaddr_in sin = {
3488 .sin_family = AF_INET,
3491 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3492 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3497 struct sockaddr_in6 sin6 = {
3498 .sin6_family = AF_INET6,
3501 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3502 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3511 ret = swrap_create_socket(si, fd);
3513 int saved_errno = errno;
3515 errno = saved_errno;
3519 SWRAP_LOG(SWRAP_LOG_TRACE,
3520 "Created %s socket for protocol %s, fd=%d",
3521 family == AF_INET ? "IPv4" : "IPv6",
3522 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3528 int socket(int family, int type, int protocol)
3530 return swrap_socket(family, type, protocol);
3533 /****************************************************************************
3535 ***************************************************************************/
3537 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3541 rc = libc_socketpair(family, type, protocol, sv);
3543 swrap_remove_stale(sv[0]);
3544 swrap_remove_stale(sv[1]);
3550 int socketpair(int family, int type, int protocol, int sv[2])
3552 return swrap_socketpair(family, type, protocol, sv);
3555 /****************************************************************************
3557 ***************************************************************************/
3559 #ifdef HAVE_TIMERFD_CREATE
3560 static int swrap_timerfd_create(int clockid, int flags)
3564 fd = libc_timerfd_create(clockid, flags);
3566 swrap_remove_stale(fd);
3572 int timerfd_create(int clockid, int flags)
3574 return swrap_timerfd_create(clockid, flags);
3578 /****************************************************************************
3580 ***************************************************************************/
3582 static int swrap_pipe(int pipefd[2])
3586 rc = libc_pipe(pipefd);
3588 swrap_remove_stale(pipefd[0]);
3589 swrap_remove_stale(pipefd[1]);
3595 int pipe(int pipefd[2])
3597 return swrap_pipe(pipefd);
3600 /****************************************************************************
3602 ***************************************************************************/
3604 static int swrap_accept(int s,
3605 struct sockaddr *addr,
3609 struct socket_info *parent_si, *child_si;
3610 struct socket_info new_si = { 0 };
3613 struct swrap_address un_addr = {
3614 .sa_socklen = sizeof(struct sockaddr_un),
3616 struct swrap_address un_my_addr = {
3617 .sa_socklen = sizeof(struct sockaddr_un),
3619 struct swrap_address in_addr = {
3620 .sa_socklen = sizeof(struct sockaddr_storage),
3622 struct swrap_address in_my_addr = {
3623 .sa_socklen = sizeof(struct sockaddr_storage),
3627 parent_si = find_socket_info(s);
3630 return libc_accept4(s, addr, addrlen, flags);
3633 return libc_accept(s, addr, addrlen);
3639 * prevent parent_si from being altered / closed
3642 SWRAP_LOCK_SI(parent_si);
3645 * assume out sockaddr have the same size as the in parent
3648 in_addr.sa_socklen = socket_length(parent_si->family);
3649 if (in_addr.sa_socklen <= 0) {
3650 SWRAP_UNLOCK_SI(parent_si);
3655 SWRAP_UNLOCK_SI(parent_si);
3658 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3661 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3664 int saved_errno = errno;
3665 if (saved_errno == ENOTSOCK) {
3666 /* Remove stale fds */
3667 swrap_remove_stale(s);
3669 errno = saved_errno;
3675 /* Check if we have a stale fd and remove it */
3676 swrap_remove_stale(fd);
3678 if (un_addr.sa.un.sun_path[0] == '\0') {
3680 * FreeBSD seems to have a problem where
3681 * accept4() on the unix socket doesn't
3682 * ECONNABORTED for already disconnected connections.
3684 * Let's try libc_getpeername() to get the peer address
3685 * as a fallback, but it'll likely return ENOTCONN,
3686 * which we have to map to ECONNABORTED.
3688 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3689 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3691 int saved_errno = errno;
3693 if (saved_errno == ENOTCONN) {
3695 * If the connection is already disconnected
3696 * we should return ECONNABORTED.
3698 saved_errno = ECONNABORTED;
3700 errno = saved_errno;
3705 ret = libc_getsockname(fd,
3707 &un_my_addr.sa_socklen);
3709 int saved_errno = errno;
3711 if (saved_errno == ENOTCONN) {
3713 * If the connection is already disconnected
3714 * we should return ECONNABORTED.
3716 saved_errno = ECONNABORTED;
3718 errno = saved_errno;
3722 SWRAP_LOCK_SI(parent_si);
3724 ret = sockaddr_convert_from_un(parent_si,
3729 &in_addr.sa_socklen);
3731 int saved_errno = errno;
3732 SWRAP_UNLOCK_SI(parent_si);
3734 errno = saved_errno;
3740 child_si->family = parent_si->family;
3741 child_si->type = parent_si->type;
3742 child_si->protocol = parent_si->protocol;
3743 child_si->bound = 1;
3744 child_si->is_server = 1;
3745 child_si->connected = 1;
3747 SWRAP_UNLOCK_SI(parent_si);
3749 child_si->peername = (struct swrap_address) {
3750 .sa_socklen = in_addr.sa_socklen,
3752 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3754 if (addr != NULL && addrlen != NULL) {
3755 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3757 memcpy(addr, &in_addr.sa.ss, copy_len);
3759 *addrlen = in_addr.sa_socklen;
3762 ret = sockaddr_convert_from_un(child_si,
3764 un_my_addr.sa_socklen,
3767 &in_my_addr.sa_socklen);
3769 int saved_errno = errno;
3771 errno = saved_errno;
3775 SWRAP_LOG(SWRAP_LOG_TRACE,
3776 "accept() path=%s, fd=%d",
3777 un_my_addr.sa.un.sun_path, s);
3779 child_si->myname = (struct swrap_address) {
3780 .sa_socklen = in_my_addr.sa_socklen,
3782 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3784 idx = swrap_create_socket(&new_si, fd);
3786 int saved_errno = errno;
3788 errno = saved_errno;
3793 struct socket_info *si = swrap_get_socket_info(idx);
3796 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3797 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3798 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3799 SWRAP_UNLOCK_SI(si);
3806 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3808 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3812 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3813 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3815 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3818 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3821 static int autobind_start_init;
3822 static int autobind_start;
3824 /* using sendto() or connect() on an unbound socket would give the
3825 recipient no way to reply, as unlike UDP and TCP, a unix domain
3826 socket can't auto-assign ephemeral port numbers, so we need to
3828 Note: this might change the family from ipv6 to ipv4
3830 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3832 struct swrap_address un_addr = {
3833 .sa_socklen = sizeof(struct sockaddr_un),
3840 char *swrap_dir = NULL;
3842 swrap_mutex_lock(&autobind_start_mutex);
3844 if (autobind_start_init != 1) {
3845 autobind_start_init = 1;
3846 autobind_start = getpid();
3847 autobind_start %= 50000;
3848 autobind_start += 10000;
3851 un_addr.sa.un.sun_family = AF_UNIX;
3855 struct sockaddr_in in;
3859 type = SOCKET_TYPE_CHAR_TCP;
3862 type = SOCKET_TYPE_CHAR_UDP;
3865 errno = ESOCKTNOSUPPORT;
3870 memset(&in, 0, sizeof(in));
3871 in.sin_family = AF_INET;
3872 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3873 socket_wrapper_default_iface()));
3875 si->myname = (struct swrap_address) {
3876 .sa_socklen = sizeof(in),
3878 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3883 struct sockaddr_in6 in6;
3885 if (si->family != family) {
3886 errno = ENETUNREACH;
3893 type = SOCKET_TYPE_CHAR_TCP_V6;
3896 type = SOCKET_TYPE_CHAR_UDP_V6;
3899 errno = ESOCKTNOSUPPORT;
3904 memset(&in6, 0, sizeof(in6));
3905 in6.sin6_family = AF_INET6;
3906 in6.sin6_addr = *swrap_ipv6();
3907 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3909 si->myname = (struct swrap_address) {
3910 .sa_socklen = sizeof(in6),
3912 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3917 errno = ESOCKTNOSUPPORT;
3922 if (autobind_start > 60000) {
3923 autobind_start = 10000;
3926 swrap_dir = socket_wrapper_dir();
3927 if (swrap_dir == NULL) {
3933 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3934 port = autobind_start + i;
3935 swrap_un_path(&un_addr.sa.un,
3938 socket_wrapper_default_iface(),
3940 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3942 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3947 si->un_addr = un_addr.sa.un;
3950 autobind_start = port + 1;
3953 if (i == SOCKET_MAX_SOCKETS) {
3954 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3955 "interface "SOCKET_FORMAT,
3958 socket_wrapper_default_iface(),
3965 si->family = family;
3966 set_port(si->family, port, &si->myname);
3971 SAFE_FREE(swrap_dir);
3972 swrap_mutex_unlock(&autobind_start_mutex);
3976 /****************************************************************************
3978 ***************************************************************************/
3980 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3984 struct swrap_address un_addr = {
3985 .sa_socklen = sizeof(struct sockaddr_un),
3987 struct socket_info *si = find_socket_info(s);
3991 return libc_connect(s, serv_addr, addrlen);
3996 if (si->bound == 0) {
3997 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
4003 if (si->family != serv_addr->sa_family) {
4004 SWRAP_LOG(SWRAP_LOG_ERROR,
4005 "called for fd=%d (family=%d) called with invalid family=%d",
4006 s, si->family, serv_addr->sa_family);
4012 ret = sockaddr_convert_to_un(si, serv_addr,
4013 addrlen, &un_addr.sa.un, 0, &bcast);
4019 errno = ENETUNREACH;
4024 if (si->type == SOCK_DGRAM) {
4025 si->defer_connect = 1;
4028 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4030 ret = libc_connect(s,
4032 un_addr.sa_socklen);
4035 SWRAP_LOG(SWRAP_LOG_TRACE,
4036 "connect() path=%s, fd=%d",
4037 un_addr.sa.un.sun_path, s);
4040 /* to give better errors */
4041 if (ret == -1 && errno == ENOENT) {
4042 errno = EHOSTUNREACH;
4046 si->peername = (struct swrap_address) {
4047 .sa_socklen = addrlen,
4050 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4054 * When we connect() on a socket than we have to bind the
4055 * outgoing connection on the interface we use for the
4056 * transport. We already bound it on the right interface
4057 * but here we have to update the name so getsockname()
4058 * returns correct information.
4060 if (si->bindname.sa_socklen > 0) {
4061 si->myname = (struct swrap_address) {
4062 .sa_socklen = si->bindname.sa_socklen,
4065 memcpy(&si->myname.sa.ss,
4066 &si->bindname.sa.ss,
4067 si->bindname.sa_socklen);
4069 /* Cleanup bindname */
4070 si->bindname = (struct swrap_address) {
4075 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4076 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4078 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4082 SWRAP_UNLOCK_SI(si);
4086 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4088 return swrap_connect(s, serv_addr, addrlen);
4091 /****************************************************************************
4093 ***************************************************************************/
4095 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4098 struct swrap_address un_addr = {
4099 .sa_socklen = sizeof(struct sockaddr_un),
4101 struct socket_info *si = find_socket_info(s);
4108 return libc_bind(s, myaddr, addrlen);
4113 switch (si->family) {
4115 const struct sockaddr_in *sin;
4116 if (addrlen < sizeof(struct sockaddr_in)) {
4117 bind_error = EINVAL;
4121 sin = (const struct sockaddr_in *)(const void *)myaddr;
4123 if (sin->sin_family != AF_INET) {
4124 bind_error = EAFNOSUPPORT;
4127 /* special case for AF_UNSPEC */
4128 if (sin->sin_family == AF_UNSPEC &&
4129 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4138 const struct sockaddr_in6 *sin6;
4139 if (addrlen < sizeof(struct sockaddr_in6)) {
4140 bind_error = EINVAL;
4144 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4146 if (sin6->sin6_family != AF_INET6) {
4147 bind_error = EAFNOSUPPORT;
4154 bind_error = EINVAL;
4158 if (bind_error != 0) {
4165 in_use = check_addr_port_in_use(myaddr, addrlen);
4173 si->myname.sa_socklen = addrlen;
4174 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4176 ret = sockaddr_convert_to_un(si,
4186 unlink(un_addr.sa.un.sun_path);
4188 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4190 SWRAP_LOG(SWRAP_LOG_TRACE,
4191 "bind() path=%s, fd=%d",
4192 un_addr.sa.un.sun_path, s);
4199 SWRAP_UNLOCK_SI(si);
4204 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4206 return swrap_bind(s, myaddr, addrlen);
4209 /****************************************************************************
4211 ***************************************************************************/
4213 #ifdef HAVE_BINDRESVPORT
4214 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4216 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4218 struct swrap_address myaddr = {
4219 .sa_socklen = sizeof(struct sockaddr_storage),
4222 static uint16_t port;
4227 #define SWRAP_STARTPORT 600
4228 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4229 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4232 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4236 salen = myaddr.sa_socklen;
4239 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4245 memset(&myaddr.sa.ss, 0, salen);
4250 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4253 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4255 salen = sizeof(struct sockaddr_in);
4256 sinp->sin_port = htons(port);
4260 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4262 salen = sizeof(struct sockaddr_in6);
4263 sin6p->sin6_port = htons(port);
4267 errno = EAFNOSUPPORT;
4272 if (port > SWRAP_ENDPORT) {
4273 port = SWRAP_STARTPORT;
4276 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4277 if (rc == 0 || errno != EADDRINUSE) {
4285 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4287 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4291 /****************************************************************************
4293 ***************************************************************************/
4295 static int swrap_listen(int s, int backlog)
4298 struct socket_info *si = find_socket_info(s);
4301 return libc_listen(s, backlog);
4306 if (si->bound == 0) {
4307 ret = swrap_auto_bind(s, si, si->family);
4314 ret = libc_listen(s, backlog);
4320 SWRAP_UNLOCK_SI(si);
4325 int listen(int s, int backlog)
4327 return swrap_listen(s, backlog);
4330 /****************************************************************************
4332 ***************************************************************************/
4334 static FILE *swrap_fopen(const char *name, const char *mode)
4338 fp = libc_fopen(name, mode);
4340 int fd = fileno(fp);
4342 swrap_remove_stale(fd);
4348 FILE *fopen(const char *name, const char *mode)
4350 return swrap_fopen(name, mode);
4353 /****************************************************************************
4355 ***************************************************************************/
4358 static FILE *swrap_fopen64(const char *name, const char *mode)
4362 fp = libc_fopen64(name, mode);
4364 int fd = fileno(fp);
4366 swrap_remove_stale(fd);
4372 FILE *fopen64(const char *name, const char *mode)
4374 return swrap_fopen64(name, mode);
4376 #endif /* HAVE_FOPEN64 */
4378 /****************************************************************************
4380 ***************************************************************************/
4382 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4386 ret = libc_vopen(pathname, flags, ap);
4389 * There are methods for closing descriptors (libc-internal code
4390 * paths, direct syscalls) which close descriptors in ways that
4391 * we can't intercept, so try to recover when we notice that
4394 swrap_remove_stale(ret);
4399 int open(const char *pathname, int flags, ...)
4404 va_start(ap, flags);
4405 fd = swrap_vopen(pathname, flags, ap);
4411 /****************************************************************************
4413 ***************************************************************************/
4416 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4420 ret = libc_vopen64(pathname, flags, ap);
4423 * There are methods for closing descriptors (libc-internal code
4424 * paths, direct syscalls) which close descriptors in ways that
4425 * we can't intercept, so try to recover when we notice that
4428 swrap_remove_stale(ret);
4433 int open64(const char *pathname, int flags, ...)
4438 va_start(ap, flags);
4439 fd = swrap_vopen64(pathname, flags, ap);
4444 #endif /* HAVE_OPEN64 */
4446 /****************************************************************************
4448 ***************************************************************************/
4450 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4454 ret = libc_vopenat(dirfd, path, flags, ap);
4457 * There are methods for closing descriptors (libc-internal code
4458 * paths, direct syscalls) which close descriptors in ways that
4459 * we can't intercept, so try to recover when we notice that
4462 swrap_remove_stale(ret);
4468 int openat(int dirfd, const char *path, int flags, ...)
4473 va_start(ap, flags);
4474 fd = swrap_vopenat(dirfd, path, flags, ap);
4480 /****************************************************************************
4482 ***************************************************************************/
4484 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4486 struct socket_info *si = find_socket_info(s);
4491 return libc_getpeername(s, name, addrlen);
4496 if (si->peername.sa_socklen == 0)
4502 len = MIN(*addrlen, si->peername.sa_socklen);
4508 memcpy(name, &si->peername.sa.ss, len);
4509 *addrlen = si->peername.sa_socklen;
4513 SWRAP_UNLOCK_SI(si);
4518 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4519 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4521 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4524 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4527 /****************************************************************************
4529 ***************************************************************************/
4531 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4533 struct socket_info *si = find_socket_info(s);
4538 return libc_getsockname(s, name, addrlen);
4543 len = MIN(*addrlen, si->myname.sa_socklen);
4549 memcpy(name, &si->myname.sa.ss, len);
4550 *addrlen = si->myname.sa_socklen;
4554 SWRAP_UNLOCK_SI(si);
4559 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4560 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4562 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4565 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4568 /****************************************************************************
4570 ***************************************************************************/
4573 # ifdef SO_PROTOTYPE /* The Solaris name */
4574 # define SO_PROTOCOL SO_PROTOTYPE
4575 # endif /* SO_PROTOTYPE */
4576 #endif /* SO_PROTOCOL */
4578 static int swrap_getsockopt(int s, int level, int optname,
4579 void *optval, socklen_t *optlen)
4581 struct socket_info *si = find_socket_info(s);
4585 return libc_getsockopt(s,
4594 if (level == SOL_SOCKET) {
4598 if (optval == NULL || optlen == NULL ||
4599 *optlen < (socklen_t)sizeof(int)) {
4605 *optlen = sizeof(int);
4606 *(int *)optval = si->family;
4609 #endif /* SO_DOMAIN */
4613 if (optval == NULL || optlen == NULL ||
4614 *optlen < (socklen_t)sizeof(int)) {
4620 *optlen = sizeof(int);
4621 *(int *)optval = si->protocol;
4624 #endif /* SO_PROTOCOL */
4626 if (optval == NULL || optlen == NULL ||
4627 *optlen < (socklen_t)sizeof(int)) {
4633 *optlen = sizeof(int);
4634 *(int *)optval = si->type;
4638 ret = libc_getsockopt(s,
4645 } else if (level == IPPROTO_TCP) {
4650 * This enables sending packets directly out over TCP.
4651 * As a unix socket is doing that any way, report it as
4654 if (optval == NULL || optlen == NULL ||
4655 *optlen < (socklen_t)sizeof(int)) {
4661 *optlen = sizeof(int);
4662 *(int *)optval = si->tcp_nodelay;
4666 #endif /* TCP_NODELAY */
4669 struct tcp_info info;
4670 socklen_t ilen = sizeof(info);
4672 #ifdef HAVE_NETINET_TCP_FSM_H
4673 /* This is FreeBSD */
4674 # define __TCP_LISTEN TCPS_LISTEN
4675 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4676 # define __TCP_CLOSE TCPS_CLOSED
4679 # define __TCP_LISTEN TCP_LISTEN
4680 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4681 # define __TCP_CLOSE TCP_CLOSE
4685 if (si->listening) {
4686 info.tcpi_state = __TCP_LISTEN;
4687 } else if (si->connected) {
4689 * For now we just fake a few values
4690 * supported both by FreeBSD and Linux
4692 info.tcpi_state = __TCP_ESTABLISHED;
4693 info.tcpi_rto = 200000; /* 200 msec */
4694 info.tcpi_rtt = 5000; /* 5 msec */
4695 info.tcpi_rttvar = 5000; /* 5 msec */
4697 info.tcpi_state = __TCP_CLOSE;
4698 info.tcpi_rto = 1000000; /* 1 sec */
4700 info.tcpi_rttvar = 250000; /* 250 msec */
4703 if (optval == NULL || optlen == NULL ||
4704 *optlen < (socklen_t)ilen) {
4711 memcpy(optval, &info, ilen);
4716 #endif /* TCP_INFO */
4722 errno = ENOPROTOOPT;
4726 SWRAP_UNLOCK_SI(si);
4730 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4731 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4733 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4736 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4739 /****************************************************************************
4741 ***************************************************************************/
4743 static int swrap_setsockopt(int s, int level, int optname,
4744 const void *optval, socklen_t optlen)
4746 struct socket_info *si = find_socket_info(s);
4750 return libc_setsockopt(s,
4757 if (level == SOL_SOCKET) {
4758 return libc_setsockopt(s,
4767 if (level == IPPROTO_TCP) {
4774 * This enables sending packets directly out over TCP.
4775 * A unix socket is doing that any way.
4777 if (optval == NULL || optlen == 0 ||
4778 optlen < (socklen_t)sizeof(int)) {
4784 i = *discard_const_p(int, optval);
4785 if (i != 0 && i != 1) {
4790 si->tcp_nodelay = i;
4795 #endif /* TCP_NODELAY */
4801 switch (si->family) {
4803 if (level == IPPROTO_IP) {
4805 if (optname == IP_PKTINFO) {
4806 si->pktinfo = AF_INET;
4808 #endif /* IP_PKTINFO */
4814 if (level == IPPROTO_IPV6) {
4815 #ifdef IPV6_RECVPKTINFO
4816 if (optname == IPV6_RECVPKTINFO) {
4817 si->pktinfo = AF_INET6;
4819 #endif /* IPV6_PKTINFO */
4825 errno = ENOPROTOOPT;
4831 SWRAP_UNLOCK_SI(si);
4835 int setsockopt(int s, int level, int optname,
4836 const void *optval, socklen_t optlen)
4838 return swrap_setsockopt(s, level, optname, optval, optlen);
4841 /****************************************************************************
4843 ***************************************************************************/
4845 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4847 struct socket_info *si = find_socket_info(s);
4849 int *value_ptr = NULL;
4853 return libc_vioctl(s, r, va);
4860 rc = libc_vioctl(s, r, va);
4865 value_ptr = ((int *)va_arg(ap, int *));
4868 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4869 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4870 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4871 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4876 /* this is FreeBSD */
4877 FALL_THROUGH; /* to TIOCOUTQ */
4878 #endif /* FIONWRITE */
4879 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4881 * This may return more bytes then the application
4882 * sent into the socket, for tcp it should
4883 * return the number of unacked bytes.
4885 * On AF_UNIX, all bytes are immediately acked!
4888 value_ptr = ((int *)va_arg(ap, int *));
4896 SWRAP_UNLOCK_SI(si);
4900 #ifdef HAVE_IOCTL_INT
4901 int ioctl(int s, int r, ...)
4903 int ioctl(int s, unsigned long int r, ...)
4911 rc = swrap_vioctl(s, (unsigned long int) r, va);
4922 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4925 # ifdef _ALIGN /* BSD */
4926 #define CMSG_ALIGN _ALIGN
4928 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4929 # endif /* _ALIGN */
4930 #endif /* CMSG_ALIGN */
4933 * @brief Add a cmsghdr to a msghdr.
4935 * This is an function to add any type of cmsghdr. It will operate on the
4936 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4937 * the buffer position after the added cmsg element. Hence, this function is
4938 * intended to be used with an intermediate msghdr and not on the original
4939 * one handed in by the client.
4941 * @param[in] msg The msghdr to which to add the cmsg.
4943 * @param[in] level The cmsg level to set.
4945 * @param[in] type The cmsg type to set.
4947 * @param[in] data The cmsg data to set.
4949 * @param[in] len the length of the data to set.
4951 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4957 size_t cmlen = CMSG_LEN(len);
4958 size_t cmspace = CMSG_SPACE(len);
4959 uint8_t cmbuf[cmspace];
4960 void *cast_ptr = (void *)cmbuf;
4961 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4964 memset(cmbuf, 0, cmspace);
4966 if (msg->msg_controllen < cmlen) {
4967 cmlen = msg->msg_controllen;
4968 msg->msg_flags |= MSG_CTRUNC;
4971 if (msg->msg_controllen < cmspace) {
4972 cmspace = msg->msg_controllen;
4976 * We copy the full input data into an intermediate cmsghdr first
4977 * in order to more easily cope with truncation.
4979 cm->cmsg_len = cmlen;
4980 cm->cmsg_level = level;
4981 cm->cmsg_type = type;
4982 memcpy(CMSG_DATA(cm), data, len);
4985 * We now copy the possibly truncated buffer.
4986 * We copy cmlen bytes, but consume cmspace bytes,
4987 * leaving the possible padding uninitialiazed.
4989 p = (uint8_t *)msg->msg_control;
4990 memcpy(p, cm, cmlen);
4992 msg->msg_control = p;
4993 msg->msg_controllen -= cmspace;
4998 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
5001 /* Add packet info */
5002 switch (si->pktinfo) {
5003 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
5005 struct sockaddr_in *sin;
5006 #if defined(HAVE_STRUCT_IN_PKTINFO)
5007 struct in_pktinfo pkt;
5008 #elif defined(IP_RECVDSTADDR)
5012 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
5013 sin = &si->bindname.sa.in;
5015 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5018 sin = &si->myname.sa.in;
5023 #if defined(HAVE_STRUCT_IN_PKTINFO)
5024 pkt.ipi_ifindex = socket_wrapper_default_iface();
5025 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5026 #elif defined(IP_RECVDSTADDR)
5027 pkt = sin->sin_addr;
5030 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5035 #endif /* IP_PKTINFO */
5036 #if defined(HAVE_IPV6)
5038 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5039 struct sockaddr_in6 *sin6;
5040 struct in6_pktinfo pkt6;
5042 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5043 sin6 = &si->bindname.sa.in6;
5045 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5048 sin6 = &si->myname.sa.in6;
5053 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5054 pkt6.ipi6_addr = sin6->sin6_addr;
5056 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5057 &pkt6, sizeof(pkt6));
5058 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5062 #endif /* IPV6_PKTINFO */
5070 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5071 struct msghdr *omsg)
5075 if (si->pktinfo > 0) {
5076 rc = swrap_msghdr_add_pktinfo(si, omsg);
5082 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5084 size_t *cm_data_space);
5085 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5087 size_t *cm_data_space);
5088 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5090 size_t *cm_data_space);
5092 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5094 size_t *cm_data_space)
5096 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5097 struct cmsghdr *cmsg;
5101 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5105 for (cmsg = CMSG_FIRSTHDR(msg);
5107 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5108 switch (cmsg->cmsg_level) {
5110 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5115 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5120 rc = swrap_sendmsg_copy_cmsg(cmsg,
5126 int saved_errno = errno;
5127 SAFE_FREE(*cm_data);
5129 errno = saved_errno;
5137 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5139 size_t *cm_data_space)
5144 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5146 p = realloc((*cm_data), cmspace);
5152 p = (*cm_data) + (*cm_data_space);
5153 *cm_data_space = cmspace;
5155 memcpy(p, cmsg, cmsg->cmsg_len);
5160 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5162 size_t *cm_data_space);
5165 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5167 size_t *cm_data_space)
5171 switch(cmsg->cmsg_type) {
5174 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5181 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5193 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5195 size_t *cm_data_space)
5197 (void)cmsg; /* unused */
5198 (void)cm_data; /* unused */
5199 (void)cm_data_space; /* unused */
5202 * Passing a IP pktinfo to a unix socket might be rejected by the
5203 * Kernel, at least on FreeBSD. So skip this cmsg.
5208 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5210 size_t *cm_data_space)
5214 switch (cmsg->cmsg_type) {
5216 SWRAP_LOG(SWRAP_LOG_TRACE,
5217 "Ignoring SCM_RIGHTS on inet socket!");
5220 #ifdef SCM_CREDENTIALS
5221 case SCM_CREDENTIALS:
5222 SWRAP_LOG(SWRAP_LOG_TRACE,
5223 "Ignoring SCM_CREDENTIALS on inet socket!");
5226 #endif /* SCM_CREDENTIALS */
5228 rc = swrap_sendmsg_copy_cmsg(cmsg,
5237 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5240 * We only allow up to 6 fds at a time
5241 * as that's more than enough for Samba
5242 * and it means we can keep the logic simple
5243 * and work with fixed size arrays.
5245 * We also keep sizeof(struct swrap_unix_scm_rights)
5246 * under PIPE_BUF (4096) in order to allow a non-blocking
5247 * write into the pipe.
5250 #define PIPE_BUF 4096
5252 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5253 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5254 struct swrap_unix_scm_rights_payload {
5256 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5257 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5259 struct swrap_unix_scm_rights {
5261 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5262 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5264 uint32_t payload_size;
5265 struct swrap_unix_scm_rights_payload payload;
5268 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5270 int saved_errno = errno;
5273 for (i = 0; i < num; i++) {
5274 struct socket_info *si = array[i];
5280 swrap_dec_refcount(si);
5281 if (si->fd_passed > 0) {
5284 SWRAP_UNLOCK_SI(si);
5288 errno = saved_errno;
5291 static void swrap_undo_si_idx_array(size_t num, int *array)
5293 int saved_errno = errno;
5296 swrap_mutex_lock(&first_free_mutex);
5298 for (i = 0; i < num; i++) {
5299 struct socket_info *si = NULL;
5301 if (array[i] == -1) {
5305 si = swrap_get_socket_info(array[i]);
5311 swrap_dec_refcount(si);
5312 SWRAP_UNLOCK_SI(si);
5314 swrap_set_next_free(si, first_free);
5315 first_free = array[i];
5319 swrap_mutex_unlock(&first_free_mutex);
5320 errno = saved_errno;
5323 static void swrap_close_fd_array(size_t num, const int *array)
5325 int saved_errno = errno;
5328 for (i = 0; i < num; i++) {
5329 if (array[i] == -1) {
5332 libc_close(array[i]);
5335 errno = saved_errno;
5343 union __swrap_cmsghdr {
5345 struct cmsghdr *cmsg;
5348 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5350 size_t *cm_data_space,
5351 int *scm_rights_pipe_fd)
5353 struct swrap_unix_scm_rights info;
5354 struct swrap_unix_scm_rights_payload *payload = NULL;
5355 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5356 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5357 size_t info_idx = 0;
5360 union __swrap_fds __fds_in = { .p = NULL, };
5361 const int *fds_in = NULL;
5363 size_t size_fds_out;
5364 union __swrap_fds __fds_out = { .p = NULL, };
5365 int *fds_out = NULL;
5368 size_t new_cm_data_space;
5369 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5370 struct cmsghdr *new_cmsg = NULL;
5373 int pipefd[2] = { -1, -1 };
5378 * We pass this a buffer to the kernel make sure any padding
5382 info.magic = swrap_unix_scm_right_magic;
5383 memcpy(info.package_name,
5384 SOCKET_WRAPPER_PACKAGE,
5385 sizeof(info.package_name));
5386 memcpy(info.package_version,
5387 SOCKET_WRAPPER_VERSION,
5388 sizeof(info.package_version));
5389 info.full_size = sizeof(info);
5390 info.payload_size = sizeof(info.payload);
5391 payload = &info.payload;
5393 if (*scm_rights_pipe_fd != -1) {
5394 SWRAP_LOG(SWRAP_LOG_ERROR,
5395 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5400 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5401 SWRAP_LOG(SWRAP_LOG_ERROR,
5402 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5403 (size_t)cmsg->cmsg_len,
5408 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5409 if ((size_fds_in % sizeof(int)) != 0) {
5410 SWRAP_LOG(SWRAP_LOG_ERROR,
5411 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5412 (size_t)cmsg->cmsg_len,
5418 num_fds_in = size_fds_in / sizeof(int);
5419 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5420 SWRAP_LOG(SWRAP_LOG_ERROR,
5421 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5423 "SWRAP_MAX_PASSED_FDS(%zu)",
5424 (size_t)cmsg->cmsg_len,
5427 SWRAP_MAX_PASSED_FDS);
5431 if (num_fds_in == 0) {
5432 SWRAP_LOG(SWRAP_LOG_ERROR,
5433 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5435 (size_t)cmsg->cmsg_len,
5441 __fds_in.p = CMSG_DATA(cmsg);
5442 fds_in = __fds_in.fds;
5443 num_fds_out = num_fds_in + 1;
5445 SWRAP_LOG(SWRAP_LOG_TRACE,
5446 "num_fds_in=%zu num_fds_out=%zu",
5447 num_fds_in, num_fds_out);
5449 size_fds_out = sizeof(int) * num_fds_out;
5450 cmsg_len = CMSG_LEN(size_fds_out);
5451 cmsg_space = CMSG_SPACE(size_fds_out);
5453 new_cm_data_space = *cm_data_space + cmsg_space;
5455 p = realloc((*cm_data), new_cm_data_space);
5460 p = (*cm_data) + (*cm_data_space);
5461 memset(p, 0, cmsg_space);
5463 new_cmsg = __new_cmsg.cmsg;
5465 __fds_out.p = CMSG_DATA(new_cmsg);
5466 fds_out = __fds_out.fds;
5467 memcpy(fds_out, fds_in, size_fds_in);
5468 new_cmsg->cmsg_len = cmsg->cmsg_len;
5470 for (i = 0; i < num_fds_in; i++) {
5473 payload->idxs[i] = -1;
5474 payload->num_idxs++;
5476 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5477 if (si_idx_array[i] == -1) {
5481 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5482 if (si_array[i] == NULL) {
5483 SWRAP_LOG(SWRAP_LOG_ERROR,
5484 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5485 i, fds_in[i], i, si_idx_array[i]);
5490 for (j = 0; j < i; j++) {
5491 if (si_array[j] == si_array[i]) {
5492 payload->idxs[i] = payload->idxs[j];
5496 if (payload->idxs[i] == -1) {
5497 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5498 SWRAP_LOG(SWRAP_LOG_ERROR,
5499 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5500 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5501 i, fds_in[i], i, si_idx_array[i],
5503 SWRAP_MAX_PASSED_SOCKET_INFO);
5507 payload->idxs[i] = info_idx;
5513 for (i = 0; i < num_fds_in; i++) {
5514 struct socket_info *si = si_array[i];
5517 SWRAP_LOG(SWRAP_LOG_TRACE,
5518 "fds_in[%zu]=%d not an inet socket",
5523 SWRAP_LOG(SWRAP_LOG_TRACE,
5524 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5525 "passing as info.idxs[%zu]=%d!",
5528 i, payload->idxs[i]);
5532 payload->infos[payload->idxs[i]] = *si;
5533 payload->infos[payload->idxs[i]].fd_passed = 0;
5534 SWRAP_UNLOCK_SI(si);
5539 int saved_errno = errno;
5540 SWRAP_LOG(SWRAP_LOG_ERROR,
5541 "pipe() failed - %d %s",
5543 strerror(saved_errno));
5544 swrap_dec_fd_passed_array(num_fds_in, si_array);
5545 errno = saved_errno;
5549 sret = libc_write(pipefd[1], &info, sizeof(info));
5550 if (sret != sizeof(info)) {
5551 int saved_errno = errno;
5553 saved_errno = EINVAL;
5555 SWRAP_LOG(SWRAP_LOG_ERROR,
5556 "write() failed - sret=%zd - %d %s",
5558 strerror(saved_errno));
5559 swrap_dec_fd_passed_array(num_fds_in, si_array);
5560 libc_close(pipefd[1]);
5561 libc_close(pipefd[0]);
5562 errno = saved_errno;
5565 libc_close(pipefd[1]);
5568 * Add the pipe read end to the end of the passed fd array
5570 fds_out[num_fds_in] = pipefd[0];
5571 new_cmsg->cmsg_len = cmsg_len;
5573 /* we're done ... */
5574 *scm_rights_pipe_fd = pipefd[0];
5575 *cm_data_space = new_cm_data_space;
5580 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5582 size_t *cm_data_space,
5583 int *scm_rights_pipe_fd)
5587 switch (cmsg->cmsg_type) {
5589 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5592 scm_rights_pipe_fd);
5595 rc = swrap_sendmsg_copy_cmsg(cmsg,
5604 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5606 size_t *cm_data_space)
5608 int scm_rights_pipe_fd = -1;
5609 struct swrap_unix_scm_rights info;
5610 struct swrap_unix_scm_rights_payload *payload = NULL;
5611 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5614 union __swrap_fds __fds_in = { .p = NULL, };
5615 const int *fds_in = NULL;
5617 size_t size_fds_out;
5618 union __swrap_fds __fds_out = { .p = NULL, };
5619 int *fds_out = NULL;
5622 size_t new_cm_data_space;
5623 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5624 struct cmsghdr *new_cmsg = NULL;
5630 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5631 SWRAP_LOG(SWRAP_LOG_ERROR,
5632 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5633 (size_t)cmsg->cmsg_len,
5638 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5639 if ((size_fds_in % sizeof(int)) != 0) {
5640 SWRAP_LOG(SWRAP_LOG_ERROR,
5641 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5642 (size_t)cmsg->cmsg_len,
5648 num_fds_in = size_fds_in / sizeof(int);
5649 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5650 SWRAP_LOG(SWRAP_LOG_ERROR,
5651 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5652 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5653 (size_t)cmsg->cmsg_len,
5656 SWRAP_MAX_PASSED_FDS+1);
5660 if (num_fds_in <= 1) {
5661 SWRAP_LOG(SWRAP_LOG_ERROR,
5662 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5664 (size_t)cmsg->cmsg_len,
5670 __fds_in.p = CMSG_DATA(cmsg);
5671 fds_in = __fds_in.fds;
5672 num_fds_out = num_fds_in - 1;
5674 SWRAP_LOG(SWRAP_LOG_TRACE,
5675 "num_fds_in=%zu num_fds_out=%zu",
5676 num_fds_in, num_fds_out);
5678 for (i = 0; i < num_fds_in; i++) {
5679 /* Check if we have a stale fd and remove it */
5680 swrap_remove_stale(fds_in[i]);
5683 scm_rights_pipe_fd = fds_in[num_fds_out];
5684 size_fds_out = sizeof(int) * num_fds_out;
5685 cmsg_len = CMSG_LEN(size_fds_out);
5686 cmsg_space = CMSG_SPACE(size_fds_out);
5688 new_cm_data_space = *cm_data_space + cmsg_space;
5690 p = realloc((*cm_data), new_cm_data_space);
5692 swrap_close_fd_array(num_fds_in, fds_in);
5696 p = (*cm_data) + (*cm_data_space);
5697 memset(p, 0, cmsg_space);
5699 new_cmsg = __new_cmsg.cmsg;
5701 __fds_out.p = CMSG_DATA(new_cmsg);
5702 fds_out = __fds_out.fds;
5703 memcpy(fds_out, fds_in, size_fds_out);
5704 new_cmsg->cmsg_len = cmsg_len;
5706 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5707 if (sret != sizeof(info)) {
5708 int saved_errno = errno;
5710 saved_errno = EINVAL;
5712 SWRAP_LOG(SWRAP_LOG_ERROR,
5713 "read() failed - sret=%zd - %d %s",
5715 strerror(saved_errno));
5716 swrap_close_fd_array(num_fds_in, fds_in);
5717 errno = saved_errno;
5720 libc_close(scm_rights_pipe_fd);
5721 payload = &info.payload;
5723 if (info.magic != swrap_unix_scm_right_magic) {
5724 SWRAP_LOG(SWRAP_LOG_ERROR,
5725 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5726 (unsigned long long)info.magic,
5727 (unsigned long long)swrap_unix_scm_right_magic);
5728 swrap_close_fd_array(num_fds_out, fds_out);
5733 cmp = memcmp(info.package_name,
5734 SOCKET_WRAPPER_PACKAGE,
5735 sizeof(info.package_name));
5737 SWRAP_LOG(SWRAP_LOG_ERROR,
5738 "info.package_name='%.*s' != '%s'",
5739 (int)sizeof(info.package_name),
5741 SOCKET_WRAPPER_PACKAGE);
5742 swrap_close_fd_array(num_fds_out, fds_out);
5747 cmp = memcmp(info.package_version,
5748 SOCKET_WRAPPER_VERSION,
5749 sizeof(info.package_version));
5751 SWRAP_LOG(SWRAP_LOG_ERROR,
5752 "info.package_version='%.*s' != '%s'",
5753 (int)sizeof(info.package_version),
5754 info.package_version,
5755 SOCKET_WRAPPER_VERSION);
5756 swrap_close_fd_array(num_fds_out, fds_out);
5761 if (info.full_size != sizeof(info)) {
5762 SWRAP_LOG(SWRAP_LOG_ERROR,
5763 "info.full_size=%zu != sizeof(info)=%zu",
5764 (size_t)info.full_size,
5766 swrap_close_fd_array(num_fds_out, fds_out);
5771 if (info.payload_size != sizeof(info.payload)) {
5772 SWRAP_LOG(SWRAP_LOG_ERROR,
5773 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5774 (size_t)info.payload_size,
5775 sizeof(info.payload));
5776 swrap_close_fd_array(num_fds_out, fds_out);
5781 if (payload->num_idxs != num_fds_out) {
5782 SWRAP_LOG(SWRAP_LOG_ERROR,
5783 "info.num_idxs=%u != num_fds_out=%zu",
5784 payload->num_idxs, num_fds_out);
5785 swrap_close_fd_array(num_fds_out, fds_out);
5790 for (i = 0; i < num_fds_out; i++) {
5793 si_idx_array[i] = -1;
5795 if (payload->idxs[i] == -1) {
5796 SWRAP_LOG(SWRAP_LOG_TRACE,
5797 "fds_out[%zu]=%d not an inet socket",
5802 if (payload->idxs[i] < 0) {
5803 SWRAP_LOG(SWRAP_LOG_ERROR,
5804 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5805 i, fds_out[i], i, payload->idxs[i]);
5806 swrap_close_fd_array(num_fds_out, fds_out);
5811 if (payload->idxs[i] >= payload->num_idxs) {
5812 SWRAP_LOG(SWRAP_LOG_ERROR,
5813 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5814 i, fds_out[i], i, payload->idxs[i],
5816 swrap_close_fd_array(num_fds_out, fds_out);
5821 if ((size_t)fds_out[i] >= socket_fds_max) {
5822 SWRAP_LOG(SWRAP_LOG_ERROR,
5823 "The max socket index limit of %zu has been reached, "
5827 swrap_close_fd_array(num_fds_out, fds_out);
5832 SWRAP_LOG(SWRAP_LOG_TRACE,
5834 "received as info.idxs[%zu]=%d!",
5836 i, payload->idxs[i]);
5838 for (j = 0; j < i; j++) {
5839 if (payload->idxs[j] == -1) {
5842 if (payload->idxs[j] == payload->idxs[i]) {
5843 si_idx_array[i] = si_idx_array[j];
5846 if (si_idx_array[i] == -1) {
5847 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5849 si_idx_array[i] = swrap_add_socket_info(si);
5850 if (si_idx_array[i] == -1) {
5851 int saved_errno = errno;
5852 SWRAP_LOG(SWRAP_LOG_ERROR,
5853 "The max socket index limit of %zu has been reached, "
5857 swrap_undo_si_idx_array(i, si_idx_array);
5858 swrap_close_fd_array(num_fds_out, fds_out);
5859 errno = saved_errno;
5862 SWRAP_LOG(SWRAP_LOG_TRACE,
5863 "Imported %s socket for protocol %s, fd=%d",
5864 si->family == AF_INET ? "IPv4" : "IPv6",
5865 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5870 for (i = 0; i < num_fds_out; i++) {
5871 if (si_idx_array[i] == -1) {
5874 set_socket_info_index(fds_out[i], si_idx_array[i]);
5877 /* we're done ... */
5878 *cm_data_space = new_cm_data_space;
5883 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5885 size_t *cm_data_space)
5889 switch (cmsg->cmsg_type) {
5891 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5896 rc = swrap_sendmsg_copy_cmsg(cmsg,
5905 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5907 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5908 struct msghdr *msg_tmp,
5909 int *scm_rights_pipe_fd)
5911 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5912 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5913 struct cmsghdr *cmsg = NULL;
5914 uint8_t *cm_data = NULL;
5915 size_t cm_data_space = 0;
5919 *scm_rights_pipe_fd = -1;
5922 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5926 for (cmsg = CMSG_FIRSTHDR(msg_in);
5928 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5929 switch (cmsg->cmsg_level) {
5931 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5934 scm_rights_pipe_fd);
5938 rc = swrap_sendmsg_copy_cmsg(cmsg,
5944 int saved_errno = errno;
5946 errno = saved_errno;
5951 msg_tmp->msg_controllen = cm_data_space;
5952 msg_tmp->msg_control = cm_data;
5955 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5956 *msg_tmp = *_msg_in;
5958 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5961 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5963 int scm_rights_pipe_fd)
5965 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5966 int saved_errno = errno;
5967 SAFE_FREE(msg_tmp->msg_control);
5968 if (scm_rights_pipe_fd != -1) {
5969 libc_close(scm_rights_pipe_fd);
5971 errno = saved_errno;
5972 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5976 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5977 struct msghdr *msg_tmp,
5978 uint8_t **tmp_control)
5980 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5981 const size_t cm_extra_space = CMSG_SPACE(sizeof(int));
5982 uint8_t *cm_data = NULL;
5983 size_t cm_data_space = 0;
5986 *tmp_control = NULL;
5988 SWRAP_LOG(SWRAP_LOG_TRACE,
5989 "msg_in->msg_controllen=%zu",
5990 (size_t)msg_in->msg_controllen);
5993 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5998 * We need to give the kernel a bit more space in order
5999 * recv the pipe fd, added by swrap_sendmsg_before_unix()).
6000 * swrap_recvmsg_after_unix() will hide it again.
6002 cm_data_space = msg_in->msg_controllen;
6003 if (cm_data_space < (INT32_MAX - cm_extra_space)) {
6004 cm_data_space += cm_extra_space;
6006 cm_data = calloc(1, cm_data_space);
6007 if (cm_data == NULL) {
6011 msg_tmp->msg_controllen = cm_data_space;
6012 msg_tmp->msg_control = cm_data;
6013 *tmp_control = cm_data;
6015 SWRAP_LOG(SWRAP_LOG_TRACE,
6016 "msg_tmp->msg_controllen=%zu",
6017 (size_t)msg_tmp->msg_controllen);
6019 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6021 *tmp_control = NULL;
6023 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6026 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
6027 uint8_t **tmp_control,
6028 struct msghdr *msg_out,
6031 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6032 struct cmsghdr *cmsg = NULL;
6033 uint8_t *cm_data = NULL;
6034 size_t cm_data_space = 0;
6038 int saved_errno = errno;
6039 SWRAP_LOG(SWRAP_LOG_TRACE, "ret=%zd - %d - %s", ret,
6040 saved_errno, strerror(saved_errno));
6041 SAFE_FREE(*tmp_control);
6042 /* msg_out should not be touched on error */
6043 errno = saved_errno;
6047 SWRAP_LOG(SWRAP_LOG_TRACE,
6048 "msg_tmp->msg_controllen=%zu",
6049 (size_t)msg_tmp->msg_controllen);
6052 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
6053 int saved_errno = errno;
6054 *msg_out = *msg_tmp;
6055 SAFE_FREE(*tmp_control);
6056 errno = saved_errno;
6060 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
6062 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
6063 switch (cmsg->cmsg_level) {
6065 rc = swrap_recvmsg_unix_sol_socket(cmsg,
6071 rc = swrap_sendmsg_copy_cmsg(cmsg,
6077 int saved_errno = errno;
6079 SAFE_FREE(*tmp_control);
6080 errno = saved_errno;
6086 * msg_tmp->msg_control (*tmp_control) was created by
6087 * swrap_recvmsg_before_unix() and msg_out->msg_control
6088 * is still the buffer of the caller.
6090 msg_tmp->msg_control = msg_out->msg_control;
6091 msg_tmp->msg_controllen = msg_out->msg_controllen;
6092 *msg_out = *msg_tmp;
6094 cm_data_space = MIN(cm_data_space, msg_out->msg_controllen);
6095 memcpy(msg_out->msg_control, cm_data, cm_data_space);
6096 msg_out->msg_controllen = cm_data_space;
6098 SAFE_FREE(*tmp_control);
6100 SWRAP_LOG(SWRAP_LOG_TRACE,
6101 "msg_out->msg_controllen=%zu",
6102 (size_t)msg_out->msg_controllen);
6104 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6105 int saved_errno = errno;
6106 *msg_out = *msg_tmp;
6107 SAFE_FREE(*tmp_control);
6108 errno = saved_errno;
6110 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6113 static ssize_t swrap_sendmsg_before(int fd,
6114 struct socket_info *si,
6116 struct iovec *tmp_iov,
6117 struct sockaddr_un *tmp_un,
6118 const struct sockaddr_un **to_un,
6119 const struct sockaddr **to,
6141 if (!si->connected) {
6146 if (msg->msg_iovlen == 0) {
6150 mtu = socket_wrapper_mtu();
6151 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6153 nlen = len + msg->msg_iov[i].iov_len;
6163 msg->msg_iovlen = i;
6164 if (msg->msg_iovlen == 0) {
6165 *tmp_iov = msg->msg_iov[0];
6166 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6168 msg->msg_iov = tmp_iov;
6169 msg->msg_iovlen = 1;
6174 if (si->connected) {
6175 if (msg->msg_name != NULL) {
6177 * We are dealing with unix sockets and if we
6178 * are connected, we should only talk to the
6179 * connected unix path. Using the fd to send
6180 * to another server would be hard to achieve.
6182 msg->msg_name = NULL;
6183 msg->msg_namelen = 0;
6186 const struct sockaddr *msg_name;
6187 msg_name = (const struct sockaddr *)msg->msg_name;
6189 if (msg_name == NULL) {
6195 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6207 msg->msg_name = tmp_un;
6208 msg->msg_namelen = sizeof(*tmp_un);
6211 if (si->bound == 0) {
6212 ret = swrap_auto_bind(fd, si, si->family);
6214 SWRAP_UNLOCK_SI(si);
6215 if (errno == ENOTSOCK) {
6216 swrap_remove_stale(fd);
6219 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6225 if (!si->defer_connect) {
6229 ret = sockaddr_convert_to_un(si,
6231 si->peername.sa_socklen,
6239 ret = libc_connect(fd,
6240 (struct sockaddr *)(void *)tmp_un,
6243 /* to give better errors */
6244 if (ret == -1 && errno == ENOENT) {
6245 errno = EHOSTUNREACH;
6252 si->defer_connect = 0;
6255 errno = EHOSTUNREACH;
6261 SWRAP_UNLOCK_SI(si);
6266 static void swrap_sendmsg_after(int fd,
6267 struct socket_info *si,
6269 const struct sockaddr *to,
6272 int saved_errno = errno;
6279 /* to give better errors */
6281 if (saved_errno == ENOENT) {
6282 saved_errno = EHOSTUNREACH;
6283 } else if (saved_errno == ENOTSOCK) {
6284 /* If the fd is not a socket, remove it */
6285 swrap_remove_stale(fd);
6289 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6290 avail += msg->msg_iov[i].iov_len;
6294 remain = MIN(80, avail);
6299 /* we capture it as one single packet */
6300 buf = (uint8_t *)malloc(remain);
6302 /* we just not capture the packet */
6303 errno = saved_errno;
6307 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6308 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6310 msg->msg_iov[i].iov_base,
6313 remain -= this_time;
6322 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6323 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6325 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6330 if (si->connected) {
6331 to = &si->peername.sa.s;
6334 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6335 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6337 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6342 SWRAP_UNLOCK_SI(si);
6345 errno = saved_errno;
6348 static int swrap_recvmsg_before(int fd,
6349 struct socket_info *si,
6351 struct iovec *tmp_iov)
6358 (void)fd; /* unused */
6363 if (!si->connected) {
6368 if (msg->msg_iovlen == 0) {
6372 mtu = socket_wrapper_mtu();
6373 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6375 nlen = len + msg->msg_iov[i].iov_len;
6380 msg->msg_iovlen = i;
6381 if (msg->msg_iovlen == 0) {
6382 *tmp_iov = msg->msg_iov[0];
6383 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6385 msg->msg_iov = tmp_iov;
6386 msg->msg_iovlen = 1;
6391 if (msg->msg_name == NULL) {
6396 if (msg->msg_iovlen == 0) {
6400 if (si->bound == 0) {
6401 ret = swrap_auto_bind(fd, si, si->family);
6403 SWRAP_UNLOCK_SI(si);
6405 * When attempting to read or write to a
6406 * descriptor, if an underlying autobind fails
6407 * because it's not a socket, stop intercepting
6408 * uses of that descriptor.
6410 if (errno == ENOTSOCK) {
6411 swrap_remove_stale(fd);
6414 SWRAP_LOG(SWRAP_LOG_ERROR,
6415 "swrap_recvmsg_before failed");
6422 errno = EHOSTUNREACH;
6428 SWRAP_UNLOCK_SI(si);
6433 static int swrap_recvmsg_after(int fd,
6434 struct socket_info *si,
6436 const struct sockaddr_un *un_addr,
6437 socklen_t un_addrlen,
6440 int saved_errno = errno;
6442 uint8_t *buf = NULL;
6448 /* to give better errors */
6450 if (saved_errno == ENOENT) {
6451 saved_errno = EHOSTUNREACH;
6452 } else if (saved_errno == ENOTSOCK) {
6453 /* If the fd is not a socket, remove it */
6454 swrap_remove_stale(fd);
6458 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6459 avail += msg->msg_iov[i].iov_len;
6464 /* Convert the socket address before we leave */
6465 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6466 rc = sockaddr_convert_from_un(si,
6483 remain = MIN(80, avail);
6488 /* we capture it as one single packet */
6489 buf = (uint8_t *)malloc(remain);
6491 /* we just not capture the packet */
6492 SWRAP_UNLOCK_SI(si);
6493 errno = saved_errno;
6497 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6498 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6500 msg->msg_iov[i].iov_base,
6503 remain -= this_time;
6508 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6509 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6510 } else if (ret == 0) { /* END OF FILE */
6511 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6512 } else if (ret > 0) {
6513 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6522 if (un_addr != NULL) {
6523 swrap_pcap_dump_packet(si,
6529 swrap_pcap_dump_packet(si,
6542 errno = saved_errno;
6544 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6546 msg->msg_controllen > 0 &&
6547 msg->msg_control != NULL) {
6548 rc = swrap_msghdr_add_socket_info(si, msg);
6550 SWRAP_UNLOCK_SI(si);
6556 SWRAP_UNLOCK_SI(si);
6560 /****************************************************************************
6562 ***************************************************************************/
6564 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6565 struct sockaddr *from, socklen_t *fromlen)
6567 struct swrap_address from_addr = {
6568 .sa_socklen = sizeof(struct sockaddr_un),
6571 struct socket_info *si = find_socket_info(s);
6572 struct swrap_address saddr = {
6573 .sa_socklen = sizeof(struct sockaddr_storage),
6580 return libc_recvfrom(s,
6592 if (from != NULL && fromlen != NULL) {
6593 msg.msg_name = from; /* optional address */
6594 msg.msg_namelen = *fromlen; /* size of address */
6596 msg.msg_name = &saddr.sa.s; /* optional address */
6597 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6599 msg.msg_iov = &tmp; /* scatter/gather array */
6600 msg.msg_iovlen = 1; /* # elements in msg_iov */
6601 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6602 msg.msg_control = NULL; /* ancillary data, see below */
6603 msg.msg_controllen = 0; /* ancillary data buffer len */
6604 msg.msg_flags = 0; /* flags on received message */
6607 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6612 buf = msg.msg_iov[0].iov_base;
6613 len = msg.msg_iov[0].iov_len;
6615 ret = libc_recvfrom(s,
6620 &from_addr.sa_socklen);
6625 tret = swrap_recvmsg_after(s,
6629 from_addr.sa_socklen,
6635 if (from != NULL && fromlen != NULL) {
6636 *fromlen = msg.msg_namelen;
6642 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6643 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6644 struct sockaddr *from, Psocklen_t fromlen)
6646 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6647 struct sockaddr *from, socklen_t *fromlen)
6650 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6653 /****************************************************************************
6655 ***************************************************************************/
6657 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6658 const struct sockaddr *to, socklen_t tolen)
6662 struct swrap_address un_addr = {
6663 .sa_socklen = sizeof(struct sockaddr_un),
6665 const struct sockaddr_un *to_un = NULL;
6668 struct socket_info *si = find_socket_info(s);
6672 return libc_sendto(s, buf, len, flags, to, tolen);
6675 tmp.iov_base = discard_const_p(char, buf);
6679 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6680 msg.msg_namelen = tolen; /* size of address */
6681 msg.msg_iov = &tmp; /* scatter/gather array */
6682 msg.msg_iovlen = 1; /* # elements in msg_iov */
6683 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6684 msg.msg_control = NULL; /* ancillary data, see below */
6685 msg.msg_controllen = 0; /* ancillary data buffer len */
6686 msg.msg_flags = 0; /* flags on received message */
6689 rc = swrap_sendmsg_before(s,
6701 buf = msg.msg_iov[0].iov_base;
6702 len = msg.msg_iov[0].iov_len;
6707 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6709 char *swrap_dir = NULL;
6711 type = SOCKET_TYPE_CHAR_UDP;
6713 swrap_dir = socket_wrapper_dir();
6714 if (swrap_dir == NULL) {
6718 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6719 swrap_un_path(&un_addr.sa.un,
6724 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6726 /* ignore the any errors in broadcast sends */
6732 un_addr.sa_socklen);
6735 SAFE_FREE(swrap_dir);
6739 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6741 SWRAP_UNLOCK_SI(si);
6748 * If it is a dgram socket and we are connected, don't include the
6751 if (si->type == SOCK_DGRAM && si->connected) {
6752 ret = libc_sendto(s,
6759 ret = libc_sendto(s,
6763 (struct sockaddr *)msg.msg_name,
6767 SWRAP_UNLOCK_SI(si);
6769 swrap_sendmsg_after(s, si, &msg, to, ret);
6774 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6775 const struct sockaddr *to, socklen_t tolen)
6777 return swrap_sendto(s, buf, len, flags, to, tolen);
6780 /****************************************************************************
6782 ***************************************************************************/
6784 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6786 struct socket_info *si;
6788 struct swrap_address saddr = {
6789 .sa_socklen = sizeof(struct sockaddr_storage),
6795 si = find_socket_info(s);
6797 return libc_recv(s, buf, len, flags);
6804 msg.msg_name = &saddr.sa.s; /* optional address */
6805 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6806 msg.msg_iov = &tmp; /* scatter/gather array */
6807 msg.msg_iovlen = 1; /* # elements in msg_iov */
6808 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6809 msg.msg_control = NULL; /* ancillary data, see below */
6810 msg.msg_controllen = 0; /* ancillary data buffer len */
6811 msg.msg_flags = 0; /* flags on received message */
6814 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6819 buf = msg.msg_iov[0].iov_base;
6820 len = msg.msg_iov[0].iov_len;
6822 ret = libc_recv(s, buf, len, flags);
6824 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6832 ssize_t recv(int s, void *buf, size_t len, int flags)
6834 return swrap_recv(s, buf, len, flags);
6837 /****************************************************************************
6839 ***************************************************************************/
6841 static ssize_t swrap_read(int s, void *buf, size_t len)
6843 struct socket_info *si;
6846 struct swrap_address saddr = {
6847 .sa_socklen = sizeof(struct sockaddr_storage),
6852 si = find_socket_info(s);
6854 return libc_read(s, buf, len);
6861 msg.msg_name = &saddr.sa.ss; /* optional address */
6862 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6863 msg.msg_iov = &tmp; /* scatter/gather array */
6864 msg.msg_iovlen = 1; /* # elements in msg_iov */
6865 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6866 msg.msg_control = NULL; /* ancillary data, see below */
6867 msg.msg_controllen = 0; /* ancillary data buffer len */
6868 msg.msg_flags = 0; /* flags on received message */
6871 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6873 if (tret == -ENOTSOCK) {
6874 return libc_read(s, buf, len);
6879 buf = msg.msg_iov[0].iov_base;
6880 len = msg.msg_iov[0].iov_len;
6882 ret = libc_read(s, buf, len);
6884 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6892 ssize_t read(int s, void *buf, size_t len)
6894 return swrap_read(s, buf, len);
6897 /****************************************************************************
6899 ***************************************************************************/
6901 static ssize_t swrap_write(int s, const void *buf, size_t len)
6905 struct sockaddr_un un_addr;
6908 struct socket_info *si;
6910 si = find_socket_info(s);
6912 return libc_write(s, buf, len);
6915 tmp.iov_base = discard_const_p(char, buf);
6919 msg.msg_name = NULL; /* optional address */
6920 msg.msg_namelen = 0; /* size of address */
6921 msg.msg_iov = &tmp; /* scatter/gather array */
6922 msg.msg_iovlen = 1; /* # elements in msg_iov */
6923 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6924 msg.msg_control = NULL; /* ancillary data, see below */
6925 msg.msg_controllen = 0; /* ancillary data buffer len */
6926 msg.msg_flags = 0; /* flags on received message */
6929 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6934 buf = msg.msg_iov[0].iov_base;
6935 len = msg.msg_iov[0].iov_len;
6937 ret = libc_write(s, buf, len);
6939 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6944 ssize_t write(int s, const void *buf, size_t len)
6946 return swrap_write(s, buf, len);
6949 /****************************************************************************
6951 ***************************************************************************/
6953 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6957 struct sockaddr_un un_addr;
6960 struct socket_info *si = find_socket_info(s);
6963 return libc_send(s, buf, len, flags);
6966 tmp.iov_base = discard_const_p(char, buf);
6970 msg.msg_name = NULL; /* optional address */
6971 msg.msg_namelen = 0; /* size of address */
6972 msg.msg_iov = &tmp; /* scatter/gather array */
6973 msg.msg_iovlen = 1; /* # elements in msg_iov */
6974 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6975 msg.msg_control = NULL; /* ancillary data, see below */
6976 msg.msg_controllen = 0; /* ancillary data buffer len */
6977 msg.msg_flags = 0; /* flags on received message */
6980 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6985 buf = msg.msg_iov[0].iov_base;
6986 len = msg.msg_iov[0].iov_len;
6988 ret = libc_send(s, buf, len, flags);
6990 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6995 ssize_t send(int s, const void *buf, size_t len, int flags)
6997 return swrap_send(s, buf, len, flags);
7000 /****************************************************************************
7002 ***************************************************************************/
7004 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
7006 struct swrap_address from_addr = {
7007 .sa_socklen = sizeof(struct sockaddr_un),
7009 struct swrap_address convert_addr = {
7010 .sa_socklen = sizeof(struct sockaddr_storage),
7012 struct socket_info *si;
7015 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7016 size_t msg_ctrllen_filled;
7017 size_t msg_ctrllen_left;
7023 si = find_socket_info(s);
7025 uint8_t *tmp_control = NULL;
7026 rc = swrap_recvmsg_before_unix(omsg, &msg, &tmp_control);
7030 ret = libc_recvmsg(s, &msg, flags);
7031 return swrap_recvmsg_after_unix(&msg, &tmp_control, omsg, ret);
7034 tmp.iov_base = NULL;
7038 msg.msg_name = &from_addr.sa; /* optional address */
7039 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
7040 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7041 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7042 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7043 msg_ctrllen_filled = 0;
7044 msg_ctrllen_left = omsg->msg_controllen;
7046 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
7047 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
7048 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7051 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7056 ret = libc_recvmsg(s, &msg, flags);
7058 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7059 msg_ctrllen_filled += msg.msg_controllen;
7060 msg_ctrllen_left -= msg.msg_controllen;
7062 if (omsg->msg_control != NULL) {
7065 p = omsg->msg_control;
7066 p += msg_ctrllen_filled;
7068 msg.msg_control = p;
7069 msg.msg_controllen = msg_ctrllen_left;
7071 msg.msg_control = NULL;
7072 msg.msg_controllen = 0;
7077 * We convert the unix address to a IP address so we need a buffer
7078 * which can store the address in case of SOCK_DGRAM, see below.
7080 msg.msg_name = &convert_addr.sa;
7081 msg.msg_namelen = convert_addr.sa_socklen;
7083 rc = swrap_recvmsg_after(s,
7087 from_addr.sa_socklen,
7093 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7094 if (omsg->msg_control != NULL) {
7095 /* msg.msg_controllen = space left */
7096 msg_ctrllen_left = msg.msg_controllen;
7097 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7100 /* Update the original message length */
7101 omsg->msg_controllen = msg_ctrllen_filled;
7102 omsg->msg_flags = msg.msg_flags;
7104 omsg->msg_iovlen = msg.msg_iovlen;
7111 * The msg_name field points to a caller-allocated buffer that is
7112 * used to return the source address if the socket is unconnected. The
7113 * caller should set msg_namelen to the size of this buffer before this
7114 * call; upon return from a successful call, msg_name will contain the
7115 * length of the returned address. If the application does not need
7116 * to know the source address, msg_name can be specified as NULL.
7118 if (si->type == SOCK_STREAM) {
7119 omsg->msg_namelen = 0;
7120 } else if (omsg->msg_name != NULL &&
7121 omsg->msg_namelen != 0 &&
7122 omsg->msg_namelen >= msg.msg_namelen) {
7123 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7124 omsg->msg_namelen = msg.msg_namelen;
7127 SWRAP_UNLOCK_SI(si);
7132 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7134 return swrap_recvmsg(sockfd, msg, flags);
7137 /****************************************************************************
7139 ***************************************************************************/
7141 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7145 struct sockaddr_un un_addr;
7146 const struct sockaddr_un *to_un = NULL;
7147 const struct sockaddr *to = NULL;
7150 struct socket_info *si = find_socket_info(s);
7154 int scm_rights_pipe_fd = -1;
7156 rc = swrap_sendmsg_before_unix(omsg, &msg,
7157 &scm_rights_pipe_fd);
7161 ret = libc_sendmsg(s, &msg, flags);
7162 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7165 ZERO_STRUCT(un_addr);
7167 tmp.iov_base = NULL;
7174 if (si->connected == 0) {
7175 msg.msg_name = omsg->msg_name; /* optional address */
7176 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7178 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7179 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7181 SWRAP_UNLOCK_SI(si);
7183 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7184 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7185 uint8_t *cmbuf = NULL;
7188 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7194 msg.msg_controllen = 0;
7195 msg.msg_control = NULL;
7197 msg.msg_control = cmbuf;
7198 msg.msg_controllen = cmlen;
7201 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7203 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7205 int saved_errno = errno;
7206 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7207 SAFE_FREE(msg.msg_control);
7209 errno = saved_errno;
7216 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7223 char *swrap_dir = NULL;
7225 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7226 avail += msg.msg_iov[i].iov_len;
7232 /* we capture it as one single packet */
7233 buf = (uint8_t *)malloc(remain);
7235 int saved_errno = errno;
7236 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7237 SAFE_FREE(msg.msg_control);
7239 errno = saved_errno;
7243 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7244 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7246 msg.msg_iov[i].iov_base,
7249 remain -= this_time;
7252 type = SOCKET_TYPE_CHAR_UDP;
7254 swrap_dir = socket_wrapper_dir();
7255 if (swrap_dir == NULL) {
7256 int saved_errno = errno;
7257 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7258 SAFE_FREE(msg.msg_control);
7261 errno = saved_errno;
7265 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7266 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7267 if (stat(un_addr.sun_path, &st) != 0) continue;
7269 msg.msg_name = &un_addr; /* optional address */
7270 msg.msg_namelen = sizeof(un_addr); /* size of address */
7272 /* ignore the any errors in broadcast sends */
7273 libc_sendmsg(s, &msg, flags);
7276 SAFE_FREE(swrap_dir);
7280 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7283 SWRAP_UNLOCK_SI(si);
7288 ret = libc_sendmsg(s, &msg, flags);
7290 swrap_sendmsg_after(s, si, &msg, to, ret);
7292 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7294 int saved_errno = errno;
7295 SAFE_FREE(msg.msg_control);
7296 errno = saved_errno;
7303 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7305 return swrap_sendmsg(s, omsg, flags);
7308 /****************************************************************************
7310 ***************************************************************************/
7312 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7314 struct socket_info *si;
7317 struct swrap_address saddr = {
7318 .sa_socklen = sizeof(struct sockaddr_storage)
7323 si = find_socket_info(s);
7325 return libc_readv(s, vector, count);
7328 tmp.iov_base = NULL;
7332 msg.msg_name = &saddr.sa.s; /* optional address */
7333 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7334 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7335 msg.msg_iovlen = count; /* # elements in msg_iov */
7336 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7337 msg.msg_control = NULL; /* ancillary data, see below */
7338 msg.msg_controllen = 0; /* ancillary data buffer len */
7339 msg.msg_flags = 0; /* flags on received message */
7342 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7344 if (rc == -ENOTSOCK) {
7345 return libc_readv(s, vector, count);
7350 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7352 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7360 ssize_t readv(int s, const struct iovec *vector, int count)
7362 return swrap_readv(s, vector, count);
7365 /****************************************************************************
7367 ***************************************************************************/
7369 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7373 struct sockaddr_un un_addr;
7376 struct socket_info *si = find_socket_info(s);
7379 return libc_writev(s, vector, count);
7382 tmp.iov_base = NULL;
7386 msg.msg_name = NULL; /* optional address */
7387 msg.msg_namelen = 0; /* size of address */
7388 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7389 msg.msg_iovlen = count; /* # elements in msg_iov */
7390 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7391 msg.msg_control = NULL; /* ancillary data, see below */
7392 msg.msg_controllen = 0; /* ancillary data buffer len */
7393 msg.msg_flags = 0; /* flags on received message */
7396 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7398 if (rc == -ENOTSOCK) {
7399 return libc_readv(s, vector, count);
7404 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7406 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7411 ssize_t writev(int s, const struct iovec *vector, int count)
7413 return swrap_writev(s, vector, count);
7416 /****************************
7418 ***************************/
7420 static int swrap_close(int fd)
7422 struct socket_info *si = NULL;
7424 int ret_errno = errno;
7427 swrap_mutex_lock(&socket_reset_mutex);
7429 si_index = find_socket_info_index(fd);
7430 if (si_index == -1) {
7431 swrap_mutex_unlock(&socket_reset_mutex);
7432 return libc_close(fd);
7435 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7436 reset_socket_info_index(fd);
7438 si = swrap_get_socket_info(si_index);
7440 swrap_mutex_lock(&first_free_mutex);
7443 ret = libc_close(fd);
7448 swrap_dec_refcount(si);
7450 if (swrap_get_refcount(si) > 0) {
7451 /* there are still references left */
7455 if (si->fd_passed) {
7459 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7460 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7463 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7464 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7465 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7468 if (si->un_addr.sun_path[0] != '\0') {
7469 unlink(si->un_addr.sun_path);
7473 swrap_set_next_free(si, first_free);
7474 first_free = si_index;
7477 SWRAP_UNLOCK_SI(si);
7478 swrap_mutex_unlock(&first_free_mutex);
7479 swrap_mutex_unlock(&socket_reset_mutex);
7487 return swrap_close(fd);
7490 /****************************
7492 ***************************/
7494 static int swrap_dup(int fd)
7496 struct socket_info *si;
7499 idx = find_socket_info_index(fd);
7501 return libc_dup(fd);
7504 si = swrap_get_socket_info(idx);
7506 dup_fd = libc_dup(fd);
7508 int saved_errno = errno;
7509 errno = saved_errno;
7513 if ((size_t)dup_fd >= socket_fds_max) {
7514 SWRAP_LOG(SWRAP_LOG_ERROR,
7515 "The max socket index limit of %zu has been reached, "
7526 swrap_inc_refcount(si);
7528 SWRAP_UNLOCK_SI(si);
7530 /* Make sure we don't have an entry for the fd */
7531 swrap_remove_stale(dup_fd);
7533 set_socket_info_index(dup_fd, idx);
7540 return swrap_dup(fd);
7543 /****************************
7545 ***************************/
7547 static int swrap_dup2(int fd, int newfd)
7549 struct socket_info *si;
7552 idx = find_socket_info_index(fd);
7554 return libc_dup2(fd, newfd);
7557 si = swrap_get_socket_info(idx);
7561 * According to the manpage:
7563 * "If oldfd is a valid file descriptor, and newfd has the same
7564 * value as oldfd, then dup2() does nothing, and returns newfd."
7569 if ((size_t)newfd >= socket_fds_max) {
7570 SWRAP_LOG(SWRAP_LOG_ERROR,
7571 "The max socket index limit of %zu has been reached, "
7579 if (find_socket_info(newfd)) {
7580 /* dup2() does an implicit close of newfd, which we
7581 * need to emulate */
7585 dup_fd = libc_dup2(fd, newfd);
7587 int saved_errno = errno;
7588 errno = saved_errno;
7594 swrap_inc_refcount(si);
7596 SWRAP_UNLOCK_SI(si);
7598 /* Make sure we don't have an entry for the fd */
7599 swrap_remove_stale(dup_fd);
7601 set_socket_info_index(dup_fd, idx);
7606 int dup2(int fd, int newfd)
7608 return swrap_dup2(fd, newfd);
7611 /****************************
7613 ***************************/
7615 static int swrap_vfcntl(int fd, int cmd, va_list va)
7617 struct socket_info *si;
7618 int rc, dup_fd, idx;
7620 idx = find_socket_info_index(fd);
7622 return libc_vfcntl(fd, cmd, va);
7625 si = swrap_get_socket_info(idx);
7629 dup_fd = libc_vfcntl(fd, cmd, va);
7631 int saved_errno = errno;
7632 errno = saved_errno;
7636 /* Make sure we don't have an entry for the fd */
7637 swrap_remove_stale(dup_fd);
7639 if ((size_t)dup_fd >= socket_fds_max) {
7640 SWRAP_LOG(SWRAP_LOG_ERROR,
7641 "The max socket index limit of %zu has been reached, "
7652 swrap_inc_refcount(si);
7654 SWRAP_UNLOCK_SI(si);
7657 set_socket_info_index(dup_fd, idx);
7662 rc = libc_vfcntl(fd, cmd, va);
7669 int fcntl(int fd, int cmd, ...)
7676 rc = swrap_vfcntl(fd, cmd, va);
7683 /****************************
7685 ***************************/
7688 static int swrap_eventfd(int count, int flags)
7692 fd = libc_eventfd(count, flags);
7694 swrap_remove_stale(fd);
7700 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7701 int eventfd(unsigned int count, int flags)
7703 int eventfd(int count, int flags)
7706 return swrap_eventfd(count, flags);
7711 int pledge(const char *promises, const char *paths[])
7713 (void)promises; /* unused */
7714 (void)paths; /* unused */
7718 #endif /* HAVE_PLEDGE */
7720 static void swrap_thread_prepare(void)
7723 * This function should only be called here!!
7725 * We bind all symobls to avoid deadlocks of the fork is
7726 * interrupted by a signal handler using a symbol of this
7729 swrap_bind_symbol_all();
7734 static void swrap_thread_parent(void)
7739 static void swrap_thread_child(void)
7744 /****************************
7746 ***************************/
7747 void swrap_constructor(void)
7749 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7750 SWRAP_LOG(SWRAP_LOG_ERROR,
7752 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7753 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7754 "sizeof(struct socket_info)=%zu",
7756 sizeof(struct swrap_unix_scm_rights),
7757 sizeof(struct swrap_unix_scm_rights_payload),
7758 sizeof(struct socket_info));
7765 * If we hold a lock and the application forks, then the child
7766 * is not able to unlock the mutex and we are in a deadlock.
7767 * This should prevent such deadlocks.
7769 pthread_atfork(&swrap_thread_prepare,
7770 &swrap_thread_parent,
7771 &swrap_thread_child);
7774 /****************************
7776 ***************************/
7779 * This function is called when the library is unloaded and makes sure that
7780 * sockets get closed and the unix file for the socket are unlinked.
7782 void swrap_destructor(void)
7786 if (socket_fds_idx != NULL) {
7787 for (i = 0; i < socket_fds_max; ++i) {
7788 if (socket_fds_idx[i] != -1) {
7792 SAFE_FREE(socket_fds_idx);
7797 if (swrap.libc.handle != NULL) {
7798 dlclose(swrap.libc.handle);
7800 if (swrap.libc.socket_handle) {
7801 dlclose(swrap.libc.socket_handle);
7805 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7807 * On FreeBSD 12 (and maybe other platforms)
7808 * system libraries like libresolv prefix there
7809 * syscalls with '_' in order to always use
7810 * the symbols from libc.
7812 * In the interaction with resolv_wrapper,
7813 * we need to inject socket wrapper into libresolv,
7814 * which means we need to private all socket
7815 * related syscalls also with the '_' prefix.
7817 * This is tested in Samba's 'make test',
7818 * there we noticed that providing '_read'
7819 * and '_open' would cause errors, which
7820 * means we skip '_read', '_write' and
7821 * all non socket related calls without
7822 * further analyzing the problem.
7824 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7825 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7828 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7830 SWRAP_SYMBOL_ALIAS(accept, _accept);
7831 SWRAP_SYMBOL_ALIAS(bind, _bind);
7832 SWRAP_SYMBOL_ALIAS(close, _close);
7833 SWRAP_SYMBOL_ALIAS(connect, _connect);
7834 SWRAP_SYMBOL_ALIAS(dup, _dup);
7835 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7836 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7837 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7838 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7839 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7840 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7841 SWRAP_SYMBOL_ALIAS(listen, _listen);
7842 SWRAP_SYMBOL_ALIAS(readv, _readv);
7843 SWRAP_SYMBOL_ALIAS(recv, _recv);
7844 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7845 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7846 SWRAP_SYMBOL_ALIAS(send, _send);
7847 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7848 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7849 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7850 SWRAP_SYMBOL_ALIAS(socket, _socket);
7851 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7852 SWRAP_SYMBOL_ALIAS(writev, _writev);
7854 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */