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 errno = ENETUNREACH;
2033 if (bcast) *bcast = is_bcast;
2038 const struct sockaddr_in6 *in =
2039 (const struct sockaddr_in6 *)(const void *)inaddr;
2040 struct in6_addr cmp1, cmp2;
2044 type = SOCKET_TYPE_CHAR_TCP_V6;
2047 type = SOCKET_TYPE_CHAR_UDP_V6;
2050 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2051 errno = ESOCKTNOSUPPORT;
2055 /* XXX no multicast/broadcast */
2057 prt = ntohs(in->sin6_port);
2059 cmp1 = *swrap_ipv6();
2060 cmp2 = in->sin6_addr;
2061 cmp2.s6_addr[15] = 0;
2062 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2063 iface = in->sin6_addr.s6_addr[15];
2065 errno = ENETUNREACH;
2073 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2074 errno = ENETUNREACH;
2079 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2084 swrap_dir = socket_wrapper_dir();
2085 if (swrap_dir == NULL) {
2091 swrap_un_path_EINVAL(un, swrap_dir);
2092 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2093 SAFE_FREE(swrap_dir);
2094 /* the caller need to do more processing */
2098 swrap_un_path(un, swrap_dir, type, iface, prt);
2099 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2101 SAFE_FREE(swrap_dir);
2106 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2114 char *swrap_dir = NULL;
2116 if (bcast) *bcast = 0;
2118 switch (si->family) {
2120 const struct sockaddr_in *in =
2121 (const struct sockaddr_in *)(const void *)inaddr;
2122 unsigned int addr = ntohl(in->sin_addr.s_addr);
2127 const unsigned int sw_net_addr = swrap_ipv4_net();
2128 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2130 prt = ntohs(in->sin_port);
2134 u_type = SOCKET_TYPE_CHAR_TCP;
2135 d_type = SOCKET_TYPE_CHAR_TCP;
2138 u_type = SOCKET_TYPE_CHAR_UDP;
2139 d_type = SOCKET_TYPE_CHAR_UDP;
2140 a_type = SOCKET_TYPE_CHAR_UDP;
2141 b_type = SOCKET_TYPE_CHAR_UDP;
2144 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2145 errno = ESOCKTNOSUPPORT;
2153 iface = socket_wrapper_default_iface();
2154 } else if (a_type && addr == 0xFFFFFFFF) {
2155 /* 255.255.255.255 only udp */
2158 iface = socket_wrapper_default_iface();
2159 } else if (b_type && addr == sw_bcast_addr) {
2160 /* 127.255.255.255 only udp */
2163 iface = socket_wrapper_default_iface();
2164 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2168 iface = (addr & 0x000000FF);
2170 errno = EADDRNOTAVAIL;
2174 /* Store the bind address for connect() */
2175 if (si->bindname.sa_socklen == 0) {
2176 struct sockaddr_in bind_in;
2177 socklen_t blen = sizeof(struct sockaddr_in);
2179 ZERO_STRUCT(bind_in);
2180 bind_in.sin_family = in->sin_family;
2181 bind_in.sin_port = in->sin_port;
2182 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2183 si->bindname.sa_socklen = blen;
2184 memcpy(&si->bindname.sa.in, &bind_in, blen);
2191 const struct sockaddr_in6 *in =
2192 (const struct sockaddr_in6 *)(const void *)inaddr;
2193 struct in6_addr cmp1, cmp2;
2197 type = SOCKET_TYPE_CHAR_TCP_V6;
2200 type = SOCKET_TYPE_CHAR_UDP_V6;
2203 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2204 errno = ESOCKTNOSUPPORT;
2208 /* XXX no multicast/broadcast */
2210 prt = ntohs(in->sin6_port);
2212 cmp1 = *swrap_ipv6();
2213 cmp2 = in->sin6_addr;
2214 cmp2.s6_addr[15] = 0;
2215 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2216 iface = socket_wrapper_default_iface();
2217 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2218 iface = in->sin6_addr.s6_addr[15];
2220 errno = EADDRNOTAVAIL;
2224 /* Store the bind address for connect() */
2225 if (si->bindname.sa_socklen == 0) {
2226 struct sockaddr_in6 bind_in;
2227 socklen_t blen = sizeof(struct sockaddr_in6);
2229 ZERO_STRUCT(bind_in);
2230 bind_in.sin6_family = in->sin6_family;
2231 bind_in.sin6_port = in->sin6_port;
2233 bind_in.sin6_addr = *swrap_ipv6();
2234 bind_in.sin6_addr.s6_addr[15] = iface;
2236 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2237 si->bindname.sa_socklen = blen;
2244 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2245 errno = EADDRNOTAVAIL;
2250 if (bcast) *bcast = is_bcast;
2252 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2257 swrap_dir = socket_wrapper_dir();
2258 if (swrap_dir == NULL) {
2264 /* handle auto-allocation of ephemeral ports */
2265 for (prt = 5001; prt < 10000; prt++) {
2266 swrap_un_path(un, swrap_dir, type, iface, prt);
2267 if (stat(un->sun_path, &st) == 0) continue;
2269 set_port(si->family, prt, &si->myname);
2270 set_port(si->family, prt, &si->bindname);
2277 SAFE_FREE(swrap_dir);
2282 swrap_un_path(un, swrap_dir, type, iface, prt);
2283 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2285 SAFE_FREE(swrap_dir);
2290 static struct socket_info *find_socket_info(int fd)
2292 int idx = find_socket_info_index(fd);
2298 return swrap_get_socket_info(idx);
2302 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2304 struct socket_info_fd *f;
2305 const struct socket_info *last_s = NULL;
2307 /* first catch invalid input */
2308 switch (sa->sa_family) {
2310 if (len < sizeof(struct sockaddr_in)) {
2316 if (len < sizeof(struct sockaddr_in6)) {
2326 for (f = socket_fds; f; f = f->next) {
2327 struct socket_info *s = swrap_get_socket_info(f->si_index);
2334 if (s->myname == NULL) {
2337 if (s->myname->sa_family != sa->sa_family) {
2340 switch (s->myname->sa_family) {
2342 struct sockaddr_in *sin1, *sin2;
2344 sin1 = (struct sockaddr_in *)s->myname;
2345 sin2 = (struct sockaddr_in *)sa;
2347 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2350 if (sin1->sin_port != sin2->sin_port) {
2353 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2363 struct sockaddr_in6 *sin1, *sin2;
2365 sin1 = (struct sockaddr_in6 *)s->myname;
2366 sin2 = (struct sockaddr_in6 *)sa;
2368 if (sin1->sin6_port != sin2->sin6_port) {
2371 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2393 static void swrap_remove_stale(int fd)
2395 struct socket_info *si;
2398 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2400 swrap_mutex_lock(&socket_reset_mutex);
2402 si_index = find_socket_info_index(fd);
2403 if (si_index == -1) {
2404 swrap_mutex_unlock(&socket_reset_mutex);
2408 reset_socket_info_index(fd);
2410 si = swrap_get_socket_info(si_index);
2412 swrap_mutex_lock(&first_free_mutex);
2415 swrap_dec_refcount(si);
2417 if (swrap_get_refcount(si) > 0) {
2421 if (si->un_addr.sun_path[0] != '\0') {
2422 unlink(si->un_addr.sun_path);
2425 swrap_set_next_free(si, first_free);
2426 first_free = si_index;
2429 SWRAP_UNLOCK_SI(si);
2430 swrap_mutex_unlock(&first_free_mutex);
2431 swrap_mutex_unlock(&socket_reset_mutex);
2434 static int sockaddr_convert_to_un(struct socket_info *si,
2435 const struct sockaddr *in_addr,
2437 struct sockaddr_un *out_addr,
2441 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2443 (void) in_len; /* unused */
2445 if (out_addr == NULL) {
2449 out->sa_family = AF_UNIX;
2450 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2451 out->sa_len = sizeof(*out_addr);
2454 switch (in_addr->sa_family) {
2456 const struct sockaddr_in *sin;
2457 if (si->family != AF_INET) {
2460 if (in_len < sizeof(struct sockaddr_in)) {
2463 sin = (const struct sockaddr_in *)(const void *)in_addr;
2464 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2469 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2470 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2484 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2485 errno = ESOCKTNOSUPPORT;
2489 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2491 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2497 errno = EAFNOSUPPORT;
2498 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2502 static int sockaddr_convert_from_un(const struct socket_info *si,
2503 const struct sockaddr_un *in_addr,
2504 socklen_t un_addrlen,
2506 struct sockaddr *out_addr,
2507 socklen_t *out_addrlen)
2511 if (out_addr == NULL || out_addrlen == NULL)
2514 if (un_addrlen == 0) {
2529 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2530 errno = ESOCKTNOSUPPORT;
2533 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2534 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2535 out_addr->sa_len = *out_addrlen;
2542 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2543 errno = EAFNOSUPPORT;
2547 enum swrap_packet_type {
2549 SWRAP_CONNECT_UNREACH,
2557 SWRAP_SENDTO_UNREACH,
2568 struct swrap_file_hdr {
2570 uint16_t version_major;
2571 uint16_t version_minor;
2574 uint32_t frame_max_len;
2575 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2578 #define SWRAP_FILE_HDR_SIZE 24
2580 struct swrap_packet_frame {
2582 uint32_t micro_seconds;
2583 uint32_t recorded_length;
2584 uint32_t full_length;
2586 #define SWRAP_PACKET_FRAME_SIZE 16
2588 union swrap_packet_ip {
2592 uint16_t packet_length;
2593 uint16_t identification;
2598 uint16_t hdr_checksum;
2602 #define SWRAP_PACKET_IP_V4_SIZE 20
2605 uint8_t flow_label_high;
2606 uint16_t flow_label_low;
2607 uint16_t payload_length;
2608 uint8_t next_header;
2610 uint8_t src_addr[16];
2611 uint8_t dest_addr[16];
2613 #define SWRAP_PACKET_IP_V6_SIZE 40
2615 #define SWRAP_PACKET_IP_SIZE 40
2617 union swrap_packet_payload {
2619 uint16_t source_port;
2629 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2631 uint16_t source_port;
2636 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2643 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2650 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2652 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2654 #define SWRAP_PACKET_MIN_ALLOC \
2655 (SWRAP_PACKET_FRAME_SIZE + \
2656 SWRAP_PACKET_IP_SIZE + \
2657 SWRAP_PACKET_PAYLOAD_SIZE)
2659 static const char *swrap_pcap_init_file(void)
2661 static int initialized = 0;
2662 static const char *s = NULL;
2663 static const struct swrap_file_hdr h;
2664 static const struct swrap_packet_frame f;
2665 static const union swrap_packet_ip i;
2666 static const union swrap_packet_payload p;
2668 if (initialized == 1) {
2674 * TODO: don't use the structs use plain buffer offsets
2675 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2677 * for now make sure we disable PCAP support
2678 * if the struct has alignment!
2680 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2683 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2686 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2689 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2692 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2695 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2698 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2701 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2704 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2707 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2711 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2715 if (strncmp(s, "./", 2) == 0) {
2718 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2722 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2723 const struct sockaddr *src,
2724 const struct sockaddr *dest,
2726 const uint8_t *payload,
2728 unsigned long tcp_seqno,
2729 unsigned long tcp_ack,
2730 unsigned char tcp_ctl,
2732 size_t *_packet_len)
2734 uint8_t *base = NULL;
2735 uint8_t *buf = NULL;
2738 struct swrap_packet_frame *frame;
2742 union swrap_packet_ip *ip;
2744 union swrap_packet_payload *pay;
2747 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2748 size_t wire_hdr_len = 0;
2749 size_t wire_len = 0;
2750 size_t ip_hdr_len = 0;
2751 size_t icmp_hdr_len = 0;
2752 size_t icmp_truncate_len = 0;
2753 uint8_t protocol = 0, icmp_protocol = 0;
2754 const struct sockaddr_in *src_in = NULL;
2755 const struct sockaddr_in *dest_in = NULL;
2757 const struct sockaddr_in6 *src_in6 = NULL;
2758 const struct sockaddr_in6 *dest_in6 = NULL;
2763 switch (src->sa_family) {
2765 src_in = (const struct sockaddr_in *)(const void *)src;
2766 dest_in = (const struct sockaddr_in *)(const void *)dest;
2767 src_port = src_in->sin_port;
2768 dest_port = dest_in->sin_port;
2769 ip_hdr_len = sizeof(i.ip->v4);
2773 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2774 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2775 src_port = src_in6->sin6_port;
2776 dest_port = dest_in6->sin6_port;
2777 ip_hdr_len = sizeof(i.ip->v6);
2784 switch (socket_type) {
2786 protocol = 0x06; /* TCP */
2787 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2788 wire_len = wire_hdr_len + payload_len;
2792 protocol = 0x11; /* UDP */
2793 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2794 wire_len = wire_hdr_len + payload_len;
2802 icmp_protocol = protocol;
2803 switch (src->sa_family) {
2805 protocol = 0x01; /* ICMPv4 */
2806 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2810 protocol = 0x3A; /* ICMPv6 */
2811 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2815 if (wire_len > 64 ) {
2816 icmp_truncate_len = wire_len - 64;
2818 wire_len += icmp_hdr_len;
2821 packet_len = nonwire_len + wire_len;
2822 alloc_len = packet_len;
2823 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2824 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2827 base = (uint8_t *)calloc(1, alloc_len);
2835 f.frame->seconds = tval->tv_sec;
2836 f.frame->micro_seconds = tval->tv_usec;
2837 f.frame->recorded_length = wire_len - icmp_truncate_len;
2838 f.frame->full_length = wire_len - icmp_truncate_len;
2840 buf += SWRAP_PACKET_FRAME_SIZE;
2843 switch (src->sa_family) {
2845 if (src_in == NULL || dest_in == NULL) {
2850 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2851 i.ip->v4.tos = 0x00;
2852 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2853 i.ip->v4.identification = htons(0xFFFF);
2854 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2855 i.ip->v4.fragment = htons(0x0000);
2856 i.ip->v4.ttl = 0xFF;
2857 i.ip->v4.protocol = protocol;
2858 i.ip->v4.hdr_checksum = htons(0x0000);
2859 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2860 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2861 buf += SWRAP_PACKET_IP_V4_SIZE;
2865 if (src_in6 == NULL || dest_in6 == NULL) {
2870 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2871 i.ip->v6.flow_label_high = 0x00;
2872 i.ip->v6.flow_label_low = 0x0000;
2873 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2874 i.ip->v6.next_header = protocol;
2875 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2876 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2877 buf += SWRAP_PACKET_IP_V6_SIZE;
2883 pay = (union swrap_packet_payload *)(void *)buf;
2884 switch (src->sa_family) {
2886 pay->icmp4.type = 0x03; /* destination unreachable */
2887 pay->icmp4.code = 0x01; /* host unreachable */
2888 pay->icmp4.checksum = htons(0x0000);
2889 pay->icmp4.unused = htonl(0x00000000);
2891 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2893 /* set the ip header in the ICMP payload */
2895 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2896 i.ip->v4.tos = 0x00;
2897 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2898 i.ip->v4.identification = htons(0xFFFF);
2899 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2900 i.ip->v4.fragment = htons(0x0000);
2901 i.ip->v4.ttl = 0xFF;
2902 i.ip->v4.protocol = icmp_protocol;
2903 i.ip->v4.hdr_checksum = htons(0x0000);
2904 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2905 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2907 buf += SWRAP_PACKET_IP_V4_SIZE;
2909 src_port = dest_in->sin_port;
2910 dest_port = src_in->sin_port;
2914 pay->icmp6.type = 0x01; /* destination unreachable */
2915 pay->icmp6.code = 0x03; /* address unreachable */
2916 pay->icmp6.checksum = htons(0x0000);
2917 pay->icmp6.unused = htonl(0x00000000);
2918 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2920 /* set the ip header in the ICMP payload */
2922 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2923 i.ip->v6.flow_label_high = 0x00;
2924 i.ip->v6.flow_label_low = 0x0000;
2925 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2926 i.ip->v6.next_header = protocol;
2927 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2928 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2930 buf += SWRAP_PACKET_IP_V6_SIZE;
2932 src_port = dest_in6->sin6_port;
2933 dest_port = src_in6->sin6_port;
2939 pay = (union swrap_packet_payload *)(void *)buf;
2941 switch (socket_type) {
2943 pay->tcp.source_port = src_port;
2944 pay->tcp.dest_port = dest_port;
2945 pay->tcp.seq_num = htonl(tcp_seqno);
2946 pay->tcp.ack_num = htonl(tcp_ack);
2947 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2948 pay->tcp.control = tcp_ctl;
2949 pay->tcp.window = htons(0x7FFF);
2950 pay->tcp.checksum = htons(0x0000);
2951 pay->tcp.urg = htons(0x0000);
2952 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2957 pay->udp.source_port = src_port;
2958 pay->udp.dest_port = dest_port;
2959 pay->udp.length = htons(8 + payload_len);
2960 pay->udp.checksum = htons(0x0000);
2961 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2966 if (payload && payload_len > 0) {
2967 memcpy(buf, payload, payload_len);
2970 *_packet_len = packet_len - icmp_truncate_len;
2974 static int swrap_pcap_get_fd(const char *fname)
2982 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2984 struct swrap_file_hdr file_hdr;
2985 file_hdr.magic = 0xA1B2C3D4;
2986 file_hdr.version_major = 0x0002;
2987 file_hdr.version_minor = 0x0004;
2988 file_hdr.timezone = 0x00000000;
2989 file_hdr.sigfigs = 0x00000000;
2990 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2991 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2993 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
3000 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3005 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3006 const struct sockaddr *addr,
3007 enum swrap_packet_type type,
3008 const void *buf, size_t len,
3011 const struct sockaddr *src_addr;
3012 const struct sockaddr *dest_addr;
3013 unsigned long tcp_seqno = 0;
3014 unsigned long tcp_ack = 0;
3015 unsigned char tcp_ctl = 0;
3016 int unreachable = 0;
3020 switch (si->family) {
3032 case SWRAP_CONNECT_SEND:
3033 if (si->type != SOCK_STREAM) {
3037 src_addr = &si->myname.sa.s;
3040 tcp_seqno = si->io.pck_snd;
3041 tcp_ack = si->io.pck_rcv;
3042 tcp_ctl = 0x02; /* SYN */
3044 si->io.pck_snd += 1;
3048 case SWRAP_CONNECT_RECV:
3049 if (si->type != SOCK_STREAM) {
3053 dest_addr = &si->myname.sa.s;
3056 tcp_seqno = si->io.pck_rcv;
3057 tcp_ack = si->io.pck_snd;
3058 tcp_ctl = 0x12; /** SYN,ACK */
3060 si->io.pck_rcv += 1;
3064 case SWRAP_CONNECT_UNREACH:
3065 if (si->type != SOCK_STREAM) {
3069 dest_addr = &si->myname.sa.s;
3072 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3073 tcp_seqno = si->io.pck_snd - 1;
3074 tcp_ack = si->io.pck_rcv;
3075 tcp_ctl = 0x02; /* SYN */
3080 case SWRAP_CONNECT_ACK:
3081 if (si->type != SOCK_STREAM) {
3085 src_addr = &si->myname.sa.s;
3088 tcp_seqno = si->io.pck_snd;
3089 tcp_ack = si->io.pck_rcv;
3090 tcp_ctl = 0x10; /* ACK */
3094 case SWRAP_ACCEPT_SEND:
3095 if (si->type != SOCK_STREAM) {
3099 dest_addr = &si->myname.sa.s;
3102 tcp_seqno = si->io.pck_rcv;
3103 tcp_ack = si->io.pck_snd;
3104 tcp_ctl = 0x02; /* SYN */
3106 si->io.pck_rcv += 1;
3110 case SWRAP_ACCEPT_RECV:
3111 if (si->type != SOCK_STREAM) {
3115 src_addr = &si->myname.sa.s;
3118 tcp_seqno = si->io.pck_snd;
3119 tcp_ack = si->io.pck_rcv;
3120 tcp_ctl = 0x12; /* SYN,ACK */
3122 si->io.pck_snd += 1;
3126 case SWRAP_ACCEPT_ACK:
3127 if (si->type != SOCK_STREAM) {
3131 dest_addr = &si->myname.sa.s;
3134 tcp_seqno = si->io.pck_rcv;
3135 tcp_ack = si->io.pck_snd;
3136 tcp_ctl = 0x10; /* ACK */
3141 src_addr = &si->myname.sa.s;
3142 dest_addr = &si->peername.sa.s;
3144 tcp_seqno = si->io.pck_snd;
3145 tcp_ack = si->io.pck_rcv;
3146 tcp_ctl = 0x18; /* PSH,ACK */
3148 si->io.pck_snd += len;
3152 case SWRAP_SEND_RST:
3153 dest_addr = &si->myname.sa.s;
3154 src_addr = &si->peername.sa.s;
3156 if (si->type == SOCK_DGRAM) {
3157 return swrap_pcap_marshall_packet(si,
3159 SWRAP_SENDTO_UNREACH,
3165 tcp_seqno = si->io.pck_rcv;
3166 tcp_ack = si->io.pck_snd;
3167 tcp_ctl = 0x14; /** RST,ACK */
3171 case SWRAP_PENDING_RST:
3172 dest_addr = &si->myname.sa.s;
3173 src_addr = &si->peername.sa.s;
3175 if (si->type == SOCK_DGRAM) {
3179 tcp_seqno = si->io.pck_rcv;
3180 tcp_ack = si->io.pck_snd;
3181 tcp_ctl = 0x14; /* RST,ACK */
3186 dest_addr = &si->myname.sa.s;
3187 src_addr = &si->peername.sa.s;
3189 tcp_seqno = si->io.pck_rcv;
3190 tcp_ack = si->io.pck_snd;
3191 tcp_ctl = 0x18; /* PSH,ACK */
3193 si->io.pck_rcv += len;
3197 case SWRAP_RECV_RST:
3198 dest_addr = &si->myname.sa.s;
3199 src_addr = &si->peername.sa.s;
3201 if (si->type == SOCK_DGRAM) {
3205 tcp_seqno = si->io.pck_rcv;
3206 tcp_ack = si->io.pck_snd;
3207 tcp_ctl = 0x14; /* RST,ACK */
3212 src_addr = &si->myname.sa.s;
3215 si->io.pck_snd += len;
3219 case SWRAP_SENDTO_UNREACH:
3220 dest_addr = &si->myname.sa.s;
3227 case SWRAP_RECVFROM:
3228 dest_addr = &si->myname.sa.s;
3231 si->io.pck_rcv += len;
3235 case SWRAP_CLOSE_SEND:
3236 if (si->type != SOCK_STREAM) {
3240 src_addr = &si->myname.sa.s;
3241 dest_addr = &si->peername.sa.s;
3243 tcp_seqno = si->io.pck_snd;
3244 tcp_ack = si->io.pck_rcv;
3245 tcp_ctl = 0x11; /* FIN, ACK */
3247 si->io.pck_snd += 1;
3251 case SWRAP_CLOSE_RECV:
3252 if (si->type != SOCK_STREAM) {
3256 dest_addr = &si->myname.sa.s;
3257 src_addr = &si->peername.sa.s;
3259 tcp_seqno = si->io.pck_rcv;
3260 tcp_ack = si->io.pck_snd;
3261 tcp_ctl = 0x11; /* FIN,ACK */
3263 si->io.pck_rcv += 1;
3267 case SWRAP_CLOSE_ACK:
3268 if (si->type != SOCK_STREAM) {
3272 src_addr = &si->myname.sa.s;
3273 dest_addr = &si->peername.sa.s;
3275 tcp_seqno = si->io.pck_snd;
3276 tcp_ack = si->io.pck_rcv;
3277 tcp_ctl = 0x10; /* ACK */
3284 swrapGetTimeOfDay(&tv);
3286 return swrap_pcap_packet_init(&tv,
3290 (const uint8_t *)buf,
3299 static void swrap_pcap_dump_packet(struct socket_info *si,
3300 const struct sockaddr *addr,
3301 enum swrap_packet_type type,
3302 const void *buf, size_t len)
3304 const char *file_name;
3306 size_t packet_len = 0;
3309 swrap_mutex_lock(&pcap_dump_mutex);
3311 file_name = swrap_pcap_init_file();
3316 packet = swrap_pcap_marshall_packet(si,
3322 if (packet == NULL) {
3326 fd = swrap_pcap_get_fd(file_name);
3328 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3337 swrap_mutex_unlock(&pcap_dump_mutex);
3340 /****************************************************************************
3342 ***************************************************************************/
3344 #ifdef HAVE_SIGNALFD
3345 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3349 rc = libc_signalfd(fd, mask, flags);
3351 swrap_remove_stale(fd);
3357 int signalfd(int fd, const sigset_t *mask, int flags)
3359 return swrap_signalfd(fd, mask, flags);
3363 /****************************************************************************
3365 ***************************************************************************/
3367 static int swrap_socket(int family, int type, int protocol)
3369 struct socket_info *si = NULL;
3370 struct socket_info _si = { 0 };
3373 int real_type = type;
3376 * Remove possible addition flags passed to socket() so
3377 * do not fail checking the type.
3378 * See https://lwn.net/Articles/281965/
3381 real_type &= ~SOCK_CLOEXEC;
3383 #ifdef SOCK_NONBLOCK
3384 real_type &= ~SOCK_NONBLOCK;
3387 if (!socket_wrapper_enabled()) {
3388 return libc_socket(family, type, protocol);
3399 #endif /* AF_NETLINK */
3402 #endif /* AF_PACKET */
3404 fd = libc_socket(family, type, protocol);
3406 /* Check if we have a stale fd and remove it */
3407 swrap_remove_stale(fd);
3408 SWRAP_LOG(SWRAP_LOG_TRACE,
3409 "Unix socket fd=%d",
3414 errno = EAFNOSUPPORT;
3418 switch (real_type) {
3424 errno = EPROTONOSUPPORT;
3432 if (real_type == SOCK_STREAM) {
3437 if (real_type == SOCK_DGRAM) {
3442 errno = EPROTONOSUPPORT;
3447 * We must call libc_socket with type, from the caller, not the version
3448 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3450 fd = libc_socket(AF_UNIX, type, 0);
3456 /* Check if we have a stale fd and remove it */
3457 swrap_remove_stale(fd);
3460 si->family = family;
3462 /* however, the rest of the socket_wrapper code expects just
3463 * the type, not the flags */
3464 si->type = real_type;
3465 si->protocol = protocol;
3468 * Setup myname so getsockname() can succeed to find out the socket
3471 switch(si->family) {
3473 struct sockaddr_in sin = {
3474 .sin_family = AF_INET,
3477 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3478 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3483 struct sockaddr_in6 sin6 = {
3484 .sin6_family = AF_INET6,
3487 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3488 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3497 ret = swrap_create_socket(si, fd);
3499 int saved_errno = errno;
3501 errno = saved_errno;
3505 SWRAP_LOG(SWRAP_LOG_TRACE,
3506 "Created %s socket for protocol %s, fd=%d",
3507 family == AF_INET ? "IPv4" : "IPv6",
3508 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3514 int socket(int family, int type, int protocol)
3516 return swrap_socket(family, type, protocol);
3519 /****************************************************************************
3521 ***************************************************************************/
3523 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3527 rc = libc_socketpair(family, type, protocol, sv);
3529 swrap_remove_stale(sv[0]);
3530 swrap_remove_stale(sv[1]);
3536 int socketpair(int family, int type, int protocol, int sv[2])
3538 return swrap_socketpair(family, type, protocol, sv);
3541 /****************************************************************************
3543 ***************************************************************************/
3545 #ifdef HAVE_TIMERFD_CREATE
3546 static int swrap_timerfd_create(int clockid, int flags)
3550 fd = libc_timerfd_create(clockid, flags);
3552 swrap_remove_stale(fd);
3558 int timerfd_create(int clockid, int flags)
3560 return swrap_timerfd_create(clockid, flags);
3564 /****************************************************************************
3566 ***************************************************************************/
3568 static int swrap_pipe(int pipefd[2])
3572 rc = libc_pipe(pipefd);
3574 swrap_remove_stale(pipefd[0]);
3575 swrap_remove_stale(pipefd[1]);
3581 int pipe(int pipefd[2])
3583 return swrap_pipe(pipefd);
3586 /****************************************************************************
3588 ***************************************************************************/
3590 static int swrap_accept(int s,
3591 struct sockaddr *addr,
3595 struct socket_info *parent_si, *child_si;
3596 struct socket_info new_si = { 0 };
3599 struct swrap_address un_addr = {
3600 .sa_socklen = sizeof(struct sockaddr_un),
3602 struct swrap_address un_my_addr = {
3603 .sa_socklen = sizeof(struct sockaddr_un),
3605 struct swrap_address in_addr = {
3606 .sa_socklen = sizeof(struct sockaddr_storage),
3608 struct swrap_address in_my_addr = {
3609 .sa_socklen = sizeof(struct sockaddr_storage),
3613 parent_si = find_socket_info(s);
3616 return libc_accept4(s, addr, addrlen, flags);
3619 return libc_accept(s, addr, addrlen);
3625 * prevent parent_si from being altered / closed
3628 SWRAP_LOCK_SI(parent_si);
3631 * assume out sockaddr have the same size as the in parent
3634 in_addr.sa_socklen = socket_length(parent_si->family);
3635 if (in_addr.sa_socklen <= 0) {
3636 SWRAP_UNLOCK_SI(parent_si);
3641 SWRAP_UNLOCK_SI(parent_si);
3644 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3647 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3650 int saved_errno = errno;
3651 if (saved_errno == ENOTSOCK) {
3652 /* Remove stale fds */
3653 swrap_remove_stale(s);
3655 errno = saved_errno;
3661 /* Check if we have a stale fd and remove it */
3662 swrap_remove_stale(fd);
3664 if (un_addr.sa.un.sun_path[0] == '\0') {
3666 * FreeBSD seems to have a problem where
3667 * accept4() on the unix socket doesn't
3668 * ECONNABORTED for already disconnected connections.
3670 * Let's try libc_getpeername() to get the peer address
3671 * as a fallback, but it'll likely return ENOTCONN,
3672 * which we have to map to ECONNABORTED.
3674 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3675 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3677 int saved_errno = errno;
3679 if (saved_errno == ENOTCONN) {
3681 * If the connection is already disconnected
3682 * we should return ECONNABORTED.
3684 saved_errno = ECONNABORTED;
3686 errno = saved_errno;
3691 ret = libc_getsockname(fd,
3693 &un_my_addr.sa_socklen);
3695 int saved_errno = errno;
3697 if (saved_errno == ENOTCONN) {
3699 * If the connection is already disconnected
3700 * we should return ECONNABORTED.
3702 saved_errno = ECONNABORTED;
3704 errno = saved_errno;
3708 SWRAP_LOCK_SI(parent_si);
3710 ret = sockaddr_convert_from_un(parent_si,
3715 &in_addr.sa_socklen);
3717 int saved_errno = errno;
3718 SWRAP_UNLOCK_SI(parent_si);
3720 errno = saved_errno;
3726 child_si->family = parent_si->family;
3727 child_si->type = parent_si->type;
3728 child_si->protocol = parent_si->protocol;
3729 child_si->bound = 1;
3730 child_si->is_server = 1;
3731 child_si->connected = 1;
3733 SWRAP_UNLOCK_SI(parent_si);
3735 child_si->peername = (struct swrap_address) {
3736 .sa_socklen = in_addr.sa_socklen,
3738 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3740 if (addr != NULL && addrlen != NULL) {
3741 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3743 memcpy(addr, &in_addr.sa.ss, copy_len);
3745 *addrlen = in_addr.sa_socklen;
3748 ret = sockaddr_convert_from_un(child_si,
3750 un_my_addr.sa_socklen,
3753 &in_my_addr.sa_socklen);
3755 int saved_errno = errno;
3757 errno = saved_errno;
3761 SWRAP_LOG(SWRAP_LOG_TRACE,
3762 "accept() path=%s, fd=%d",
3763 un_my_addr.sa.un.sun_path, s);
3765 child_si->myname = (struct swrap_address) {
3766 .sa_socklen = in_my_addr.sa_socklen,
3768 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3770 idx = swrap_create_socket(&new_si, fd);
3772 int saved_errno = errno;
3774 errno = saved_errno;
3779 struct socket_info *si = swrap_get_socket_info(idx);
3782 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3783 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3784 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3785 SWRAP_UNLOCK_SI(si);
3792 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3794 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3798 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3799 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3801 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3804 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3807 static int autobind_start_init;
3808 static int autobind_start;
3810 /* using sendto() or connect() on an unbound socket would give the
3811 recipient no way to reply, as unlike UDP and TCP, a unix domain
3812 socket can't auto-assign ephemeral port numbers, so we need to
3814 Note: this might change the family from ipv6 to ipv4
3816 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3818 struct swrap_address un_addr = {
3819 .sa_socklen = sizeof(struct sockaddr_un),
3826 char *swrap_dir = NULL;
3828 swrap_mutex_lock(&autobind_start_mutex);
3830 if (autobind_start_init != 1) {
3831 autobind_start_init = 1;
3832 autobind_start = getpid();
3833 autobind_start %= 50000;
3834 autobind_start += 10000;
3837 un_addr.sa.un.sun_family = AF_UNIX;
3841 struct sockaddr_in in;
3845 type = SOCKET_TYPE_CHAR_TCP;
3848 type = SOCKET_TYPE_CHAR_UDP;
3851 errno = ESOCKTNOSUPPORT;
3856 memset(&in, 0, sizeof(in));
3857 in.sin_family = AF_INET;
3858 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3859 socket_wrapper_default_iface()));
3861 si->myname = (struct swrap_address) {
3862 .sa_socklen = sizeof(in),
3864 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3869 struct sockaddr_in6 in6;
3871 if (si->family != family) {
3872 errno = ENETUNREACH;
3879 type = SOCKET_TYPE_CHAR_TCP_V6;
3882 type = SOCKET_TYPE_CHAR_UDP_V6;
3885 errno = ESOCKTNOSUPPORT;
3890 memset(&in6, 0, sizeof(in6));
3891 in6.sin6_family = AF_INET6;
3892 in6.sin6_addr = *swrap_ipv6();
3893 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3895 si->myname = (struct swrap_address) {
3896 .sa_socklen = sizeof(in6),
3898 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3903 errno = ESOCKTNOSUPPORT;
3908 if (autobind_start > 60000) {
3909 autobind_start = 10000;
3912 swrap_dir = socket_wrapper_dir();
3913 if (swrap_dir == NULL) {
3919 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3920 port = autobind_start + i;
3921 swrap_un_path(&un_addr.sa.un,
3924 socket_wrapper_default_iface(),
3926 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3928 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3933 si->un_addr = un_addr.sa.un;
3936 autobind_start = port + 1;
3939 if (i == SOCKET_MAX_SOCKETS) {
3940 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3941 "interface "SOCKET_FORMAT,
3944 socket_wrapper_default_iface(),
3951 si->family = family;
3952 set_port(si->family, port, &si->myname);
3957 SAFE_FREE(swrap_dir);
3958 swrap_mutex_unlock(&autobind_start_mutex);
3962 /****************************************************************************
3964 ***************************************************************************/
3966 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3970 struct swrap_address un_addr = {
3971 .sa_socklen = sizeof(struct sockaddr_un),
3973 struct socket_info *si = find_socket_info(s);
3977 return libc_connect(s, serv_addr, addrlen);
3982 if (si->bound == 0) {
3983 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3989 if (si->family != serv_addr->sa_family) {
3990 SWRAP_LOG(SWRAP_LOG_ERROR,
3991 "called for fd=%d (family=%d) called with invalid family=%d",
3992 s, si->family, serv_addr->sa_family);
3998 ret = sockaddr_convert_to_un(si, serv_addr,
3999 addrlen, &un_addr.sa.un, 0, &bcast);
4005 errno = ENETUNREACH;
4010 if (si->type == SOCK_DGRAM) {
4011 si->defer_connect = 1;
4014 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4016 ret = libc_connect(s,
4018 un_addr.sa_socklen);
4021 SWRAP_LOG(SWRAP_LOG_TRACE,
4022 "connect() path=%s, fd=%d",
4023 un_addr.sa.un.sun_path, s);
4026 /* to give better errors */
4027 if (ret == -1 && errno == ENOENT) {
4028 errno = EHOSTUNREACH;
4032 si->peername = (struct swrap_address) {
4033 .sa_socklen = addrlen,
4036 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4040 * When we connect() on a socket than we have to bind the
4041 * outgoing connection on the interface we use for the
4042 * transport. We already bound it on the right interface
4043 * but here we have to update the name so getsockname()
4044 * returns correct information.
4046 if (si->bindname.sa_socklen > 0) {
4047 si->myname = (struct swrap_address) {
4048 .sa_socklen = si->bindname.sa_socklen,
4051 memcpy(&si->myname.sa.ss,
4052 &si->bindname.sa.ss,
4053 si->bindname.sa_socklen);
4055 /* Cleanup bindname */
4056 si->bindname = (struct swrap_address) {
4061 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4062 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4064 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4068 SWRAP_UNLOCK_SI(si);
4072 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4074 return swrap_connect(s, serv_addr, addrlen);
4077 /****************************************************************************
4079 ***************************************************************************/
4081 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4084 struct swrap_address un_addr = {
4085 .sa_socklen = sizeof(struct sockaddr_un),
4087 struct socket_info *si = find_socket_info(s);
4094 return libc_bind(s, myaddr, addrlen);
4099 switch (si->family) {
4101 const struct sockaddr_in *sin;
4102 if (addrlen < sizeof(struct sockaddr_in)) {
4103 bind_error = EINVAL;
4107 sin = (const struct sockaddr_in *)(const void *)myaddr;
4109 if (sin->sin_family != AF_INET) {
4110 bind_error = EAFNOSUPPORT;
4113 /* special case for AF_UNSPEC */
4114 if (sin->sin_family == AF_UNSPEC &&
4115 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4124 const struct sockaddr_in6 *sin6;
4125 if (addrlen < sizeof(struct sockaddr_in6)) {
4126 bind_error = EINVAL;
4130 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4132 if (sin6->sin6_family != AF_INET6) {
4133 bind_error = EAFNOSUPPORT;
4140 bind_error = EINVAL;
4144 if (bind_error != 0) {
4151 in_use = check_addr_port_in_use(myaddr, addrlen);
4159 si->myname.sa_socklen = addrlen;
4160 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4162 ret = sockaddr_convert_to_un(si,
4172 unlink(un_addr.sa.un.sun_path);
4174 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4176 SWRAP_LOG(SWRAP_LOG_TRACE,
4177 "bind() path=%s, fd=%d",
4178 un_addr.sa.un.sun_path, s);
4185 SWRAP_UNLOCK_SI(si);
4190 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4192 return swrap_bind(s, myaddr, addrlen);
4195 /****************************************************************************
4197 ***************************************************************************/
4199 #ifdef HAVE_BINDRESVPORT
4200 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4202 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4204 struct swrap_address myaddr = {
4205 .sa_socklen = sizeof(struct sockaddr_storage),
4208 static uint16_t port;
4213 #define SWRAP_STARTPORT 600
4214 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4215 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4218 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4222 salen = myaddr.sa_socklen;
4225 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4231 memset(&myaddr.sa.ss, 0, salen);
4236 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4239 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4241 salen = sizeof(struct sockaddr_in);
4242 sinp->sin_port = htons(port);
4246 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4248 salen = sizeof(struct sockaddr_in6);
4249 sin6p->sin6_port = htons(port);
4253 errno = EAFNOSUPPORT;
4258 if (port > SWRAP_ENDPORT) {
4259 port = SWRAP_STARTPORT;
4262 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4263 if (rc == 0 || errno != EADDRINUSE) {
4271 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4273 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4277 /****************************************************************************
4279 ***************************************************************************/
4281 static int swrap_listen(int s, int backlog)
4284 struct socket_info *si = find_socket_info(s);
4287 return libc_listen(s, backlog);
4292 if (si->bound == 0) {
4293 ret = swrap_auto_bind(s, si, si->family);
4300 ret = libc_listen(s, backlog);
4306 SWRAP_UNLOCK_SI(si);
4311 int listen(int s, int backlog)
4313 return swrap_listen(s, backlog);
4316 /****************************************************************************
4318 ***************************************************************************/
4320 static FILE *swrap_fopen(const char *name, const char *mode)
4324 fp = libc_fopen(name, mode);
4326 int fd = fileno(fp);
4328 swrap_remove_stale(fd);
4334 FILE *fopen(const char *name, const char *mode)
4336 return swrap_fopen(name, mode);
4339 /****************************************************************************
4341 ***************************************************************************/
4344 static FILE *swrap_fopen64(const char *name, const char *mode)
4348 fp = libc_fopen64(name, mode);
4350 int fd = fileno(fp);
4352 swrap_remove_stale(fd);
4358 FILE *fopen64(const char *name, const char *mode)
4360 return swrap_fopen64(name, mode);
4362 #endif /* HAVE_FOPEN64 */
4364 /****************************************************************************
4366 ***************************************************************************/
4368 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4372 ret = libc_vopen(pathname, flags, ap);
4375 * There are methods for closing descriptors (libc-internal code
4376 * paths, direct syscalls) which close descriptors in ways that
4377 * we can't intercept, so try to recover when we notice that
4380 swrap_remove_stale(ret);
4385 int open(const char *pathname, int flags, ...)
4390 va_start(ap, flags);
4391 fd = swrap_vopen(pathname, flags, ap);
4397 /****************************************************************************
4399 ***************************************************************************/
4402 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4406 ret = libc_vopen64(pathname, flags, ap);
4409 * There are methods for closing descriptors (libc-internal code
4410 * paths, direct syscalls) which close descriptors in ways that
4411 * we can't intercept, so try to recover when we notice that
4414 swrap_remove_stale(ret);
4419 int open64(const char *pathname, int flags, ...)
4424 va_start(ap, flags);
4425 fd = swrap_vopen64(pathname, flags, ap);
4430 #endif /* HAVE_OPEN64 */
4432 /****************************************************************************
4434 ***************************************************************************/
4436 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4440 ret = libc_vopenat(dirfd, path, flags, ap);
4443 * There are methods for closing descriptors (libc-internal code
4444 * paths, direct syscalls) which close descriptors in ways that
4445 * we can't intercept, so try to recover when we notice that
4448 swrap_remove_stale(ret);
4454 int openat(int dirfd, const char *path, int flags, ...)
4459 va_start(ap, flags);
4460 fd = swrap_vopenat(dirfd, path, flags, ap);
4466 /****************************************************************************
4468 ***************************************************************************/
4470 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4472 struct socket_info *si = find_socket_info(s);
4477 return libc_getpeername(s, name, addrlen);
4482 if (si->peername.sa_socklen == 0)
4488 len = MIN(*addrlen, si->peername.sa_socklen);
4494 memcpy(name, &si->peername.sa.ss, len);
4495 *addrlen = si->peername.sa_socklen;
4499 SWRAP_UNLOCK_SI(si);
4504 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4505 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4507 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4510 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4513 /****************************************************************************
4515 ***************************************************************************/
4517 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4519 struct socket_info *si = find_socket_info(s);
4524 return libc_getsockname(s, name, addrlen);
4529 len = MIN(*addrlen, si->myname.sa_socklen);
4535 memcpy(name, &si->myname.sa.ss, len);
4536 *addrlen = si->myname.sa_socklen;
4540 SWRAP_UNLOCK_SI(si);
4545 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4546 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4548 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4551 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4554 /****************************************************************************
4556 ***************************************************************************/
4559 # ifdef SO_PROTOTYPE /* The Solaris name */
4560 # define SO_PROTOCOL SO_PROTOTYPE
4561 # endif /* SO_PROTOTYPE */
4562 #endif /* SO_PROTOCOL */
4564 static int swrap_getsockopt(int s, int level, int optname,
4565 void *optval, socklen_t *optlen)
4567 struct socket_info *si = find_socket_info(s);
4571 return libc_getsockopt(s,
4580 if (level == SOL_SOCKET) {
4584 if (optval == NULL || optlen == NULL ||
4585 *optlen < (socklen_t)sizeof(int)) {
4591 *optlen = sizeof(int);
4592 *(int *)optval = si->family;
4595 #endif /* SO_DOMAIN */
4599 if (optval == NULL || optlen == NULL ||
4600 *optlen < (socklen_t)sizeof(int)) {
4606 *optlen = sizeof(int);
4607 *(int *)optval = si->protocol;
4610 #endif /* SO_PROTOCOL */
4612 if (optval == NULL || optlen == NULL ||
4613 *optlen < (socklen_t)sizeof(int)) {
4619 *optlen = sizeof(int);
4620 *(int *)optval = si->type;
4624 ret = libc_getsockopt(s,
4631 } else if (level == IPPROTO_TCP) {
4636 * This enables sending packets directly out over TCP.
4637 * As a unix socket is doing that any way, report it as
4640 if (optval == NULL || optlen == NULL ||
4641 *optlen < (socklen_t)sizeof(int)) {
4647 *optlen = sizeof(int);
4648 *(int *)optval = si->tcp_nodelay;
4652 #endif /* TCP_NODELAY */
4655 struct tcp_info info;
4656 socklen_t ilen = sizeof(info);
4658 #ifdef HAVE_NETINET_TCP_FSM_H
4659 /* This is FreeBSD */
4660 # define __TCP_LISTEN TCPS_LISTEN
4661 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4662 # define __TCP_CLOSE TCPS_CLOSED
4665 # define __TCP_LISTEN TCP_LISTEN
4666 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4667 # define __TCP_CLOSE TCP_CLOSE
4671 if (si->listening) {
4672 info.tcpi_state = __TCP_LISTEN;
4673 } else if (si->connected) {
4675 * For now we just fake a few values
4676 * supported both by FreeBSD and Linux
4678 info.tcpi_state = __TCP_ESTABLISHED;
4679 info.tcpi_rto = 200000; /* 200 msec */
4680 info.tcpi_rtt = 5000; /* 5 msec */
4681 info.tcpi_rttvar = 5000; /* 5 msec */
4683 info.tcpi_state = __TCP_CLOSE;
4684 info.tcpi_rto = 1000000; /* 1 sec */
4686 info.tcpi_rttvar = 250000; /* 250 msec */
4689 if (optval == NULL || optlen == NULL ||
4690 *optlen < (socklen_t)ilen) {
4697 memcpy(optval, &info, ilen);
4702 #endif /* TCP_INFO */
4708 errno = ENOPROTOOPT;
4712 SWRAP_UNLOCK_SI(si);
4716 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4717 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4719 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4722 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4725 /****************************************************************************
4727 ***************************************************************************/
4729 static int swrap_setsockopt(int s, int level, int optname,
4730 const void *optval, socklen_t optlen)
4732 struct socket_info *si = find_socket_info(s);
4736 return libc_setsockopt(s,
4743 if (level == SOL_SOCKET) {
4744 return libc_setsockopt(s,
4753 if (level == IPPROTO_TCP) {
4760 * This enables sending packets directly out over TCP.
4761 * A unix socket is doing that any way.
4763 if (optval == NULL || optlen == 0 ||
4764 optlen < (socklen_t)sizeof(int)) {
4770 i = *discard_const_p(int, optval);
4771 if (i != 0 && i != 1) {
4776 si->tcp_nodelay = i;
4781 #endif /* TCP_NODELAY */
4787 switch (si->family) {
4789 if (level == IPPROTO_IP) {
4791 if (optname == IP_PKTINFO) {
4792 si->pktinfo = AF_INET;
4794 #endif /* IP_PKTINFO */
4800 if (level == IPPROTO_IPV6) {
4801 #ifdef IPV6_RECVPKTINFO
4802 if (optname == IPV6_RECVPKTINFO) {
4803 si->pktinfo = AF_INET6;
4805 #endif /* IPV6_PKTINFO */
4811 errno = ENOPROTOOPT;
4817 SWRAP_UNLOCK_SI(si);
4821 int setsockopt(int s, int level, int optname,
4822 const void *optval, socklen_t optlen)
4824 return swrap_setsockopt(s, level, optname, optval, optlen);
4827 /****************************************************************************
4829 ***************************************************************************/
4831 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4833 struct socket_info *si = find_socket_info(s);
4835 int *value_ptr = NULL;
4839 return libc_vioctl(s, r, va);
4846 rc = libc_vioctl(s, r, va);
4851 value_ptr = ((int *)va_arg(ap, int *));
4854 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4855 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4856 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4857 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4862 /* this is FreeBSD */
4863 FALL_THROUGH; /* to TIOCOUTQ */
4864 #endif /* FIONWRITE */
4865 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4867 * This may return more bytes then the application
4868 * sent into the socket, for tcp it should
4869 * return the number of unacked bytes.
4871 * On AF_UNIX, all bytes are immediately acked!
4874 value_ptr = ((int *)va_arg(ap, int *));
4882 SWRAP_UNLOCK_SI(si);
4886 #ifdef HAVE_IOCTL_INT
4887 int ioctl(int s, int r, ...)
4889 int ioctl(int s, unsigned long int r, ...)
4897 rc = swrap_vioctl(s, (unsigned long int) r, va);
4908 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4911 # ifdef _ALIGN /* BSD */
4912 #define CMSG_ALIGN _ALIGN
4914 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4915 # endif /* _ALIGN */
4916 #endif /* CMSG_ALIGN */
4919 * @brief Add a cmsghdr to a msghdr.
4921 * This is an function to add any type of cmsghdr. It will operate on the
4922 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4923 * the buffer position after the added cmsg element. Hence, this function is
4924 * intended to be used with an intermediate msghdr and not on the original
4925 * one handed in by the client.
4927 * @param[in] msg The msghdr to which to add the cmsg.
4929 * @param[in] level The cmsg level to set.
4931 * @param[in] type The cmsg type to set.
4933 * @param[in] data The cmsg data to set.
4935 * @param[in] len the length of the data to set.
4937 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4943 size_t cmlen = CMSG_LEN(len);
4944 size_t cmspace = CMSG_SPACE(len);
4945 uint8_t cmbuf[cmspace];
4946 void *cast_ptr = (void *)cmbuf;
4947 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4950 memset(cmbuf, 0, cmspace);
4952 if (msg->msg_controllen < cmlen) {
4953 cmlen = msg->msg_controllen;
4954 msg->msg_flags |= MSG_CTRUNC;
4957 if (msg->msg_controllen < cmspace) {
4958 cmspace = msg->msg_controllen;
4962 * We copy the full input data into an intermediate cmsghdr first
4963 * in order to more easily cope with truncation.
4965 cm->cmsg_len = cmlen;
4966 cm->cmsg_level = level;
4967 cm->cmsg_type = type;
4968 memcpy(CMSG_DATA(cm), data, len);
4971 * We now copy the possibly truncated buffer.
4972 * We copy cmlen bytes, but consume cmspace bytes,
4973 * leaving the possible padding uninitialiazed.
4975 p = (uint8_t *)msg->msg_control;
4976 memcpy(p, cm, cmlen);
4978 msg->msg_control = p;
4979 msg->msg_controllen -= cmspace;
4984 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4987 /* Add packet info */
4988 switch (si->pktinfo) {
4989 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4991 struct sockaddr_in *sin;
4992 #if defined(HAVE_STRUCT_IN_PKTINFO)
4993 struct in_pktinfo pkt;
4994 #elif defined(IP_RECVDSTADDR)
4998 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4999 sin = &si->bindname.sa.in;
5001 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5004 sin = &si->myname.sa.in;
5009 #if defined(HAVE_STRUCT_IN_PKTINFO)
5010 pkt.ipi_ifindex = socket_wrapper_default_iface();
5011 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5012 #elif defined(IP_RECVDSTADDR)
5013 pkt = sin->sin_addr;
5016 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5021 #endif /* IP_PKTINFO */
5022 #if defined(HAVE_IPV6)
5024 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5025 struct sockaddr_in6 *sin6;
5026 struct in6_pktinfo pkt6;
5028 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5029 sin6 = &si->bindname.sa.in6;
5031 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5034 sin6 = &si->myname.sa.in6;
5039 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5040 pkt6.ipi6_addr = sin6->sin6_addr;
5042 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5043 &pkt6, sizeof(pkt6));
5044 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5048 #endif /* IPV6_PKTINFO */
5056 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5057 struct msghdr *omsg)
5061 if (si->pktinfo > 0) {
5062 rc = swrap_msghdr_add_pktinfo(si, omsg);
5068 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5070 size_t *cm_data_space);
5071 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5073 size_t *cm_data_space);
5074 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5076 size_t *cm_data_space);
5078 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5080 size_t *cm_data_space)
5082 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5083 struct cmsghdr *cmsg;
5087 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5091 for (cmsg = CMSG_FIRSTHDR(msg);
5093 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5094 switch (cmsg->cmsg_level) {
5096 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5101 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5106 rc = swrap_sendmsg_copy_cmsg(cmsg,
5112 int saved_errno = errno;
5113 SAFE_FREE(*cm_data);
5115 errno = saved_errno;
5123 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5125 size_t *cm_data_space)
5130 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5132 p = realloc((*cm_data), cmspace);
5138 p = (*cm_data) + (*cm_data_space);
5139 *cm_data_space = cmspace;
5141 memcpy(p, cmsg, cmsg->cmsg_len);
5146 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5148 size_t *cm_data_space);
5151 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5153 size_t *cm_data_space)
5157 switch(cmsg->cmsg_type) {
5160 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5167 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5179 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5181 size_t *cm_data_space)
5183 (void)cmsg; /* unused */
5184 (void)cm_data; /* unused */
5185 (void)cm_data_space; /* unused */
5188 * Passing a IP pktinfo to a unix socket might be rejected by the
5189 * Kernel, at least on FreeBSD. So skip this cmsg.
5194 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5196 size_t *cm_data_space)
5200 switch (cmsg->cmsg_type) {
5202 SWRAP_LOG(SWRAP_LOG_TRACE,
5203 "Ignoring SCM_RIGHTS on inet socket!");
5206 #ifdef SCM_CREDENTIALS
5207 case SCM_CREDENTIALS:
5208 SWRAP_LOG(SWRAP_LOG_TRACE,
5209 "Ignoring SCM_CREDENTIALS on inet socket!");
5212 #endif /* SCM_CREDENTIALS */
5214 rc = swrap_sendmsg_copy_cmsg(cmsg,
5223 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5226 * We only allow up to 6 fds at a time
5227 * as that's more than enough for Samba
5228 * and it means we can keep the logic simple
5229 * and work with fixed size arrays.
5231 * We also keep sizeof(struct swrap_unix_scm_rights)
5232 * under PIPE_BUF (4096) in order to allow a non-blocking
5233 * write into the pipe.
5236 #define PIPE_BUF 4096
5238 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5239 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5240 struct swrap_unix_scm_rights_payload {
5242 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5243 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5245 struct swrap_unix_scm_rights {
5247 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5248 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5250 uint32_t payload_size;
5251 struct swrap_unix_scm_rights_payload payload;
5254 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5256 int saved_errno = errno;
5259 for (i = 0; i < num; i++) {
5260 struct socket_info *si = array[i];
5266 swrap_dec_refcount(si);
5267 if (si->fd_passed > 0) {
5270 SWRAP_UNLOCK_SI(si);
5274 errno = saved_errno;
5277 static void swrap_undo_si_idx_array(size_t num, int *array)
5279 int saved_errno = errno;
5282 swrap_mutex_lock(&first_free_mutex);
5284 for (i = 0; i < num; i++) {
5285 struct socket_info *si = NULL;
5287 if (array[i] == -1) {
5291 si = swrap_get_socket_info(array[i]);
5297 swrap_dec_refcount(si);
5298 SWRAP_UNLOCK_SI(si);
5300 swrap_set_next_free(si, first_free);
5301 first_free = array[i];
5305 swrap_mutex_unlock(&first_free_mutex);
5306 errno = saved_errno;
5309 static void swrap_close_fd_array(size_t num, const int *array)
5311 int saved_errno = errno;
5314 for (i = 0; i < num; i++) {
5315 if (array[i] == -1) {
5318 libc_close(array[i]);
5321 errno = saved_errno;
5329 union __swrap_cmsghdr {
5331 struct cmsghdr *cmsg;
5334 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5336 size_t *cm_data_space,
5337 int *scm_rights_pipe_fd)
5339 struct swrap_unix_scm_rights info;
5340 struct swrap_unix_scm_rights_payload *payload = NULL;
5341 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5342 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5343 size_t info_idx = 0;
5346 union __swrap_fds __fds_in = { .p = NULL, };
5347 const int *fds_in = NULL;
5349 size_t size_fds_out;
5350 union __swrap_fds __fds_out = { .p = NULL, };
5351 int *fds_out = NULL;
5354 size_t new_cm_data_space;
5355 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5356 struct cmsghdr *new_cmsg = NULL;
5359 int pipefd[2] = { -1, -1 };
5364 * We pass this a buffer to the kernel make sure any padding
5368 info.magic = swrap_unix_scm_right_magic;
5369 memcpy(info.package_name,
5370 SOCKET_WRAPPER_PACKAGE,
5371 sizeof(info.package_name));
5372 memcpy(info.package_version,
5373 SOCKET_WRAPPER_VERSION,
5374 sizeof(info.package_version));
5375 info.full_size = sizeof(info);
5376 info.payload_size = sizeof(info.payload);
5377 payload = &info.payload;
5379 if (*scm_rights_pipe_fd != -1) {
5380 SWRAP_LOG(SWRAP_LOG_ERROR,
5381 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5386 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5387 SWRAP_LOG(SWRAP_LOG_ERROR,
5388 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5389 (size_t)cmsg->cmsg_len,
5394 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5395 if ((size_fds_in % sizeof(int)) != 0) {
5396 SWRAP_LOG(SWRAP_LOG_ERROR,
5397 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5398 (size_t)cmsg->cmsg_len,
5404 num_fds_in = size_fds_in / sizeof(int);
5405 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5406 SWRAP_LOG(SWRAP_LOG_ERROR,
5407 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5409 "SWRAP_MAX_PASSED_FDS(%zu)",
5410 (size_t)cmsg->cmsg_len,
5413 SWRAP_MAX_PASSED_FDS);
5417 if (num_fds_in == 0) {
5418 SWRAP_LOG(SWRAP_LOG_ERROR,
5419 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5421 (size_t)cmsg->cmsg_len,
5427 __fds_in.p = CMSG_DATA(cmsg);
5428 fds_in = __fds_in.fds;
5429 num_fds_out = num_fds_in + 1;
5431 SWRAP_LOG(SWRAP_LOG_TRACE,
5432 "num_fds_in=%zu num_fds_out=%zu",
5433 num_fds_in, num_fds_out);
5435 size_fds_out = sizeof(int) * num_fds_out;
5436 cmsg_len = CMSG_LEN(size_fds_out);
5437 cmsg_space = CMSG_SPACE(size_fds_out);
5439 new_cm_data_space = *cm_data_space + cmsg_space;
5441 p = realloc((*cm_data), new_cm_data_space);
5446 p = (*cm_data) + (*cm_data_space);
5447 memset(p, 0, cmsg_space);
5449 new_cmsg = __new_cmsg.cmsg;
5451 __fds_out.p = CMSG_DATA(new_cmsg);
5452 fds_out = __fds_out.fds;
5453 memcpy(fds_out, fds_in, size_fds_in);
5454 new_cmsg->cmsg_len = cmsg->cmsg_len;
5456 for (i = 0; i < num_fds_in; i++) {
5459 payload->idxs[i] = -1;
5460 payload->num_idxs++;
5462 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5463 if (si_idx_array[i] == -1) {
5467 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5468 if (si_array[i] == NULL) {
5469 SWRAP_LOG(SWRAP_LOG_ERROR,
5470 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5471 i, fds_in[i], i, si_idx_array[i]);
5476 for (j = 0; j < i; j++) {
5477 if (si_array[j] == si_array[i]) {
5478 payload->idxs[i] = payload->idxs[j];
5482 if (payload->idxs[i] == -1) {
5483 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5484 SWRAP_LOG(SWRAP_LOG_ERROR,
5485 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5486 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5487 i, fds_in[i], i, si_idx_array[i],
5489 SWRAP_MAX_PASSED_SOCKET_INFO);
5493 payload->idxs[i] = info_idx;
5499 for (i = 0; i < num_fds_in; i++) {
5500 struct socket_info *si = si_array[i];
5503 SWRAP_LOG(SWRAP_LOG_TRACE,
5504 "fds_in[%zu]=%d not an inet socket",
5509 SWRAP_LOG(SWRAP_LOG_TRACE,
5510 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5511 "passing as info.idxs[%zu]=%d!",
5514 i, payload->idxs[i]);
5518 payload->infos[payload->idxs[i]] = *si;
5519 payload->infos[payload->idxs[i]].fd_passed = 0;
5520 SWRAP_UNLOCK_SI(si);
5525 int saved_errno = errno;
5526 SWRAP_LOG(SWRAP_LOG_ERROR,
5527 "pipe() failed - %d %s",
5529 strerror(saved_errno));
5530 swrap_dec_fd_passed_array(num_fds_in, si_array);
5531 errno = saved_errno;
5535 sret = write(pipefd[1], &info, sizeof(info));
5536 if (sret != sizeof(info)) {
5537 int saved_errno = errno;
5539 saved_errno = EINVAL;
5541 SWRAP_LOG(SWRAP_LOG_ERROR,
5542 "write() failed - sret=%zd - %d %s",
5544 strerror(saved_errno));
5545 swrap_dec_fd_passed_array(num_fds_in, si_array);
5546 libc_close(pipefd[1]);
5547 libc_close(pipefd[0]);
5548 errno = saved_errno;
5551 libc_close(pipefd[1]);
5554 * Add the pipe read end to the end of the passed fd array
5556 fds_out[num_fds_in] = pipefd[0];
5557 new_cmsg->cmsg_len = cmsg_len;
5559 /* we're done ... */
5560 *scm_rights_pipe_fd = pipefd[0];
5561 *cm_data_space = new_cm_data_space;
5566 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5568 size_t *cm_data_space,
5569 int *scm_rights_pipe_fd)
5573 switch (cmsg->cmsg_type) {
5575 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5578 scm_rights_pipe_fd);
5581 rc = swrap_sendmsg_copy_cmsg(cmsg,
5590 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5592 size_t *cm_data_space)
5594 int scm_rights_pipe_fd = -1;
5595 struct swrap_unix_scm_rights info;
5596 struct swrap_unix_scm_rights_payload *payload = NULL;
5597 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5600 union __swrap_fds __fds_in = { .p = NULL, };
5601 const int *fds_in = NULL;
5603 size_t size_fds_out;
5604 union __swrap_fds __fds_out = { .p = NULL, };
5605 int *fds_out = NULL;
5608 size_t new_cm_data_space;
5609 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5610 struct cmsghdr *new_cmsg = NULL;
5616 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5617 SWRAP_LOG(SWRAP_LOG_ERROR,
5618 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5619 (size_t)cmsg->cmsg_len,
5624 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5625 if ((size_fds_in % sizeof(int)) != 0) {
5626 SWRAP_LOG(SWRAP_LOG_ERROR,
5627 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5628 (size_t)cmsg->cmsg_len,
5634 num_fds_in = size_fds_in / sizeof(int);
5635 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5636 SWRAP_LOG(SWRAP_LOG_ERROR,
5637 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5638 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5639 (size_t)cmsg->cmsg_len,
5642 SWRAP_MAX_PASSED_FDS+1);
5646 if (num_fds_in <= 1) {
5647 SWRAP_LOG(SWRAP_LOG_ERROR,
5648 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5650 (size_t)cmsg->cmsg_len,
5656 __fds_in.p = CMSG_DATA(cmsg);
5657 fds_in = __fds_in.fds;
5658 num_fds_out = num_fds_in - 1;
5660 SWRAP_LOG(SWRAP_LOG_TRACE,
5661 "num_fds_in=%zu num_fds_out=%zu",
5662 num_fds_in, num_fds_out);
5664 for (i = 0; i < num_fds_in; i++) {
5665 /* Check if we have a stale fd and remove it */
5666 swrap_remove_stale(fds_in[i]);
5669 scm_rights_pipe_fd = fds_in[num_fds_out];
5670 size_fds_out = sizeof(int) * num_fds_out;
5671 cmsg_len = CMSG_LEN(size_fds_out);
5672 cmsg_space = CMSG_SPACE(size_fds_out);
5674 new_cm_data_space = *cm_data_space + cmsg_space;
5676 p = realloc((*cm_data), new_cm_data_space);
5678 swrap_close_fd_array(num_fds_in, fds_in);
5682 p = (*cm_data) + (*cm_data_space);
5683 memset(p, 0, cmsg_space);
5685 new_cmsg = __new_cmsg.cmsg;
5687 __fds_out.p = CMSG_DATA(new_cmsg);
5688 fds_out = __fds_out.fds;
5689 memcpy(fds_out, fds_in, size_fds_out);
5690 new_cmsg->cmsg_len = cmsg_len;
5692 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5693 if (sret != sizeof(info)) {
5694 int saved_errno = errno;
5696 saved_errno = EINVAL;
5698 SWRAP_LOG(SWRAP_LOG_ERROR,
5699 "read() failed - sret=%zd - %d %s",
5701 strerror(saved_errno));
5702 swrap_close_fd_array(num_fds_in, fds_in);
5703 errno = saved_errno;
5706 libc_close(scm_rights_pipe_fd);
5707 payload = &info.payload;
5709 if (info.magic != swrap_unix_scm_right_magic) {
5710 SWRAP_LOG(SWRAP_LOG_ERROR,
5711 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5712 (unsigned long long)info.magic,
5713 (unsigned long long)swrap_unix_scm_right_magic);
5714 swrap_close_fd_array(num_fds_out, fds_out);
5719 cmp = memcmp(info.package_name,
5720 SOCKET_WRAPPER_PACKAGE,
5721 sizeof(info.package_name));
5723 SWRAP_LOG(SWRAP_LOG_ERROR,
5724 "info.package_name='%.*s' != '%s'",
5725 (int)sizeof(info.package_name),
5727 SOCKET_WRAPPER_PACKAGE);
5728 swrap_close_fd_array(num_fds_out, fds_out);
5733 cmp = memcmp(info.package_version,
5734 SOCKET_WRAPPER_VERSION,
5735 sizeof(info.package_version));
5737 SWRAP_LOG(SWRAP_LOG_ERROR,
5738 "info.package_version='%.*s' != '%s'",
5739 (int)sizeof(info.package_version),
5740 info.package_version,
5741 SOCKET_WRAPPER_VERSION);
5742 swrap_close_fd_array(num_fds_out, fds_out);
5747 if (info.full_size != sizeof(info)) {
5748 SWRAP_LOG(SWRAP_LOG_ERROR,
5749 "info.full_size=%zu != sizeof(info)=%zu",
5750 (size_t)info.full_size,
5752 swrap_close_fd_array(num_fds_out, fds_out);
5757 if (info.payload_size != sizeof(info.payload)) {
5758 SWRAP_LOG(SWRAP_LOG_ERROR,
5759 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5760 (size_t)info.payload_size,
5761 sizeof(info.payload));
5762 swrap_close_fd_array(num_fds_out, fds_out);
5767 if (payload->num_idxs != num_fds_out) {
5768 SWRAP_LOG(SWRAP_LOG_ERROR,
5769 "info.num_idxs=%u != num_fds_out=%zu",
5770 payload->num_idxs, num_fds_out);
5771 swrap_close_fd_array(num_fds_out, fds_out);
5776 for (i = 0; i < num_fds_out; i++) {
5779 si_idx_array[i] = -1;
5781 if (payload->idxs[i] == -1) {
5782 SWRAP_LOG(SWRAP_LOG_TRACE,
5783 "fds_out[%zu]=%d not an inet socket",
5788 if (payload->idxs[i] < 0) {
5789 SWRAP_LOG(SWRAP_LOG_ERROR,
5790 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5791 i, fds_out[i], i, payload->idxs[i]);
5792 swrap_close_fd_array(num_fds_out, fds_out);
5797 if (payload->idxs[i] >= payload->num_idxs) {
5798 SWRAP_LOG(SWRAP_LOG_ERROR,
5799 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5800 i, fds_out[i], i, payload->idxs[i],
5802 swrap_close_fd_array(num_fds_out, fds_out);
5807 if ((size_t)fds_out[i] >= socket_fds_max) {
5808 SWRAP_LOG(SWRAP_LOG_ERROR,
5809 "The max socket index limit of %zu has been reached, "
5813 swrap_close_fd_array(num_fds_out, fds_out);
5818 SWRAP_LOG(SWRAP_LOG_TRACE,
5820 "received as info.idxs[%zu]=%d!",
5822 i, payload->idxs[i]);
5824 for (j = 0; j < i; j++) {
5825 if (payload->idxs[j] == -1) {
5828 if (payload->idxs[j] == payload->idxs[i]) {
5829 si_idx_array[i] = si_idx_array[j];
5832 if (si_idx_array[i] == -1) {
5833 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5835 si_idx_array[i] = swrap_add_socket_info(si);
5836 if (si_idx_array[i] == -1) {
5837 int saved_errno = errno;
5838 SWRAP_LOG(SWRAP_LOG_ERROR,
5839 "The max socket index limit of %zu has been reached, "
5843 swrap_undo_si_idx_array(i, si_idx_array);
5844 swrap_close_fd_array(num_fds_out, fds_out);
5845 errno = saved_errno;
5848 SWRAP_LOG(SWRAP_LOG_TRACE,
5849 "Imported %s socket for protocol %s, fd=%d",
5850 si->family == AF_INET ? "IPv4" : "IPv6",
5851 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5856 for (i = 0; i < num_fds_out; i++) {
5857 if (si_idx_array[i] == -1) {
5860 set_socket_info_index(fds_out[i], si_idx_array[i]);
5863 /* we're done ... */
5864 *cm_data_space = new_cm_data_space;
5869 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5871 size_t *cm_data_space)
5875 switch (cmsg->cmsg_type) {
5877 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5882 rc = swrap_sendmsg_copy_cmsg(cmsg,
5891 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5893 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5894 struct msghdr *msg_tmp,
5895 int *scm_rights_pipe_fd)
5897 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5898 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5899 struct cmsghdr *cmsg = NULL;
5900 uint8_t *cm_data = NULL;
5901 size_t cm_data_space = 0;
5905 *scm_rights_pipe_fd = -1;
5908 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5912 for (cmsg = CMSG_FIRSTHDR(msg_in);
5914 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5915 switch (cmsg->cmsg_level) {
5917 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5920 scm_rights_pipe_fd);
5924 rc = swrap_sendmsg_copy_cmsg(cmsg,
5930 int saved_errno = errno;
5932 errno = saved_errno;
5937 msg_tmp->msg_controllen = cm_data_space;
5938 msg_tmp->msg_control = cm_data;
5941 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5942 *msg_tmp = *_msg_in;
5944 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5947 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5949 int scm_rights_pipe_fd)
5951 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5952 int saved_errno = errno;
5953 SAFE_FREE(msg_tmp->msg_control);
5954 if (scm_rights_pipe_fd != -1) {
5955 libc_close(scm_rights_pipe_fd);
5957 errno = saved_errno;
5958 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5962 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5963 struct msghdr *msg_tmp)
5969 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5970 struct msghdr *msg_out,
5973 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5974 struct cmsghdr *cmsg = NULL;
5975 uint8_t *cm_data = NULL;
5976 size_t cm_data_space = 0;
5980 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
5984 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
5986 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
5987 switch (cmsg->cmsg_level) {
5989 rc = swrap_recvmsg_unix_sol_socket(cmsg,
5995 rc = swrap_sendmsg_copy_cmsg(cmsg,
6001 int saved_errno = errno;
6003 errno = saved_errno;
6009 * msg_tmp->msg_control is still the buffer of the caller.
6011 memcpy(msg_tmp->msg_control, cm_data, cm_data_space);
6012 msg_tmp->msg_controllen = cm_data_space;
6015 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6016 *msg_out = *msg_tmp;
6020 static ssize_t swrap_sendmsg_before(int fd,
6021 struct socket_info *si,
6023 struct iovec *tmp_iov,
6024 struct sockaddr_un *tmp_un,
6025 const struct sockaddr_un **to_un,
6026 const struct sockaddr **to,
6048 if (!si->connected) {
6053 if (msg->msg_iovlen == 0) {
6057 mtu = socket_wrapper_mtu();
6058 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6060 nlen = len + msg->msg_iov[i].iov_len;
6070 msg->msg_iovlen = i;
6071 if (msg->msg_iovlen == 0) {
6072 *tmp_iov = msg->msg_iov[0];
6073 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6075 msg->msg_iov = tmp_iov;
6076 msg->msg_iovlen = 1;
6081 if (si->connected) {
6082 if (msg->msg_name != NULL) {
6084 * We are dealing with unix sockets and if we
6085 * are connected, we should only talk to the
6086 * connected unix path. Using the fd to send
6087 * to another server would be hard to achieve.
6089 msg->msg_name = NULL;
6090 msg->msg_namelen = 0;
6093 const struct sockaddr *msg_name;
6094 msg_name = (const struct sockaddr *)msg->msg_name;
6096 if (msg_name == NULL) {
6102 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6114 msg->msg_name = tmp_un;
6115 msg->msg_namelen = sizeof(*tmp_un);
6118 if (si->bound == 0) {
6119 ret = swrap_auto_bind(fd, si, si->family);
6121 SWRAP_UNLOCK_SI(si);
6122 if (errno == ENOTSOCK) {
6123 swrap_remove_stale(fd);
6126 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6132 if (!si->defer_connect) {
6136 ret = sockaddr_convert_to_un(si,
6138 si->peername.sa_socklen,
6146 ret = libc_connect(fd,
6147 (struct sockaddr *)(void *)tmp_un,
6150 /* to give better errors */
6151 if (ret == -1 && errno == ENOENT) {
6152 errno = EHOSTUNREACH;
6159 si->defer_connect = 0;
6162 errno = EHOSTUNREACH;
6168 SWRAP_UNLOCK_SI(si);
6173 static void swrap_sendmsg_after(int fd,
6174 struct socket_info *si,
6176 const struct sockaddr *to,
6179 int saved_errno = errno;
6186 /* to give better errors */
6188 if (saved_errno == ENOENT) {
6189 saved_errno = EHOSTUNREACH;
6190 } else if (saved_errno == ENOTSOCK) {
6191 /* If the fd is not a socket, remove it */
6192 swrap_remove_stale(fd);
6196 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6197 avail += msg->msg_iov[i].iov_len;
6201 remain = MIN(80, avail);
6206 /* we capture it as one single packet */
6207 buf = (uint8_t *)malloc(remain);
6209 /* we just not capture the packet */
6210 errno = saved_errno;
6214 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6215 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6217 msg->msg_iov[i].iov_base,
6220 remain -= this_time;
6229 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6230 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6232 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6237 if (si->connected) {
6238 to = &si->peername.sa.s;
6241 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6242 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6244 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6249 SWRAP_UNLOCK_SI(si);
6252 errno = saved_errno;
6255 static int swrap_recvmsg_before(int fd,
6256 struct socket_info *si,
6258 struct iovec *tmp_iov)
6265 (void)fd; /* unused */
6270 if (!si->connected) {
6275 if (msg->msg_iovlen == 0) {
6279 mtu = socket_wrapper_mtu();
6280 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6282 nlen = len + msg->msg_iov[i].iov_len;
6287 msg->msg_iovlen = i;
6288 if (msg->msg_iovlen == 0) {
6289 *tmp_iov = msg->msg_iov[0];
6290 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6292 msg->msg_iov = tmp_iov;
6293 msg->msg_iovlen = 1;
6298 if (msg->msg_name == NULL) {
6303 if (msg->msg_iovlen == 0) {
6307 if (si->bound == 0) {
6308 ret = swrap_auto_bind(fd, si, si->family);
6310 SWRAP_UNLOCK_SI(si);
6312 * When attempting to read or write to a
6313 * descriptor, if an underlying autobind fails
6314 * because it's not a socket, stop intercepting
6315 * uses of that descriptor.
6317 if (errno == ENOTSOCK) {
6318 swrap_remove_stale(fd);
6321 SWRAP_LOG(SWRAP_LOG_ERROR,
6322 "swrap_recvmsg_before failed");
6329 errno = EHOSTUNREACH;
6335 SWRAP_UNLOCK_SI(si);
6340 static int swrap_recvmsg_after(int fd,
6341 struct socket_info *si,
6343 const struct sockaddr_un *un_addr,
6344 socklen_t un_addrlen,
6347 int saved_errno = errno;
6349 uint8_t *buf = NULL;
6355 /* to give better errors */
6357 if (saved_errno == ENOENT) {
6358 saved_errno = EHOSTUNREACH;
6359 } else if (saved_errno == ENOTSOCK) {
6360 /* If the fd is not a socket, remove it */
6361 swrap_remove_stale(fd);
6365 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6366 avail += msg->msg_iov[i].iov_len;
6371 /* Convert the socket address before we leave */
6372 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6373 rc = sockaddr_convert_from_un(si,
6390 remain = MIN(80, avail);
6395 /* we capture it as one single packet */
6396 buf = (uint8_t *)malloc(remain);
6398 /* we just not capture the packet */
6399 SWRAP_UNLOCK_SI(si);
6400 errno = saved_errno;
6404 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6405 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6407 msg->msg_iov[i].iov_base,
6410 remain -= this_time;
6415 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6416 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6417 } else if (ret == 0) { /* END OF FILE */
6418 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6419 } else if (ret > 0) {
6420 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6429 if (un_addr != NULL) {
6430 swrap_pcap_dump_packet(si,
6436 swrap_pcap_dump_packet(si,
6449 errno = saved_errno;
6451 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6453 msg->msg_controllen > 0 &&
6454 msg->msg_control != NULL) {
6455 rc = swrap_msghdr_add_socket_info(si, msg);
6457 SWRAP_UNLOCK_SI(si);
6463 SWRAP_UNLOCK_SI(si);
6467 /****************************************************************************
6469 ***************************************************************************/
6471 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6472 struct sockaddr *from, socklen_t *fromlen)
6474 struct swrap_address from_addr = {
6475 .sa_socklen = sizeof(struct sockaddr_un),
6478 struct socket_info *si = find_socket_info(s);
6479 struct swrap_address saddr = {
6480 .sa_socklen = sizeof(struct sockaddr_storage),
6487 return libc_recvfrom(s,
6499 if (from != NULL && fromlen != NULL) {
6500 msg.msg_name = from; /* optional address */
6501 msg.msg_namelen = *fromlen; /* size of address */
6503 msg.msg_name = &saddr.sa.s; /* optional address */
6504 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6506 msg.msg_iov = &tmp; /* scatter/gather array */
6507 msg.msg_iovlen = 1; /* # elements in msg_iov */
6508 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6509 msg.msg_control = NULL; /* ancillary data, see below */
6510 msg.msg_controllen = 0; /* ancillary data buffer len */
6511 msg.msg_flags = 0; /* flags on received message */
6514 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6519 buf = msg.msg_iov[0].iov_base;
6520 len = msg.msg_iov[0].iov_len;
6522 ret = libc_recvfrom(s,
6527 &from_addr.sa_socklen);
6532 tret = swrap_recvmsg_after(s,
6536 from_addr.sa_socklen,
6542 if (from != NULL && fromlen != NULL) {
6543 *fromlen = msg.msg_namelen;
6549 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6550 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6551 struct sockaddr *from, Psocklen_t fromlen)
6553 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6554 struct sockaddr *from, socklen_t *fromlen)
6557 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6560 /****************************************************************************
6562 ***************************************************************************/
6564 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6565 const struct sockaddr *to, socklen_t tolen)
6569 struct swrap_address un_addr = {
6570 .sa_socklen = sizeof(struct sockaddr_un),
6572 const struct sockaddr_un *to_un = NULL;
6575 struct socket_info *si = find_socket_info(s);
6579 return libc_sendto(s, buf, len, flags, to, tolen);
6582 tmp.iov_base = discard_const_p(char, buf);
6586 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6587 msg.msg_namelen = tolen; /* size of address */
6588 msg.msg_iov = &tmp; /* scatter/gather array */
6589 msg.msg_iovlen = 1; /* # elements in msg_iov */
6590 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6591 msg.msg_control = NULL; /* ancillary data, see below */
6592 msg.msg_controllen = 0; /* ancillary data buffer len */
6593 msg.msg_flags = 0; /* flags on received message */
6596 rc = swrap_sendmsg_before(s,
6608 buf = msg.msg_iov[0].iov_base;
6609 len = msg.msg_iov[0].iov_len;
6614 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6616 char *swrap_dir = NULL;
6618 type = SOCKET_TYPE_CHAR_UDP;
6620 swrap_dir = socket_wrapper_dir();
6621 if (swrap_dir == NULL) {
6625 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6626 swrap_un_path(&un_addr.sa.un,
6631 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6633 /* ignore the any errors in broadcast sends */
6639 un_addr.sa_socklen);
6642 SAFE_FREE(swrap_dir);
6646 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6648 SWRAP_UNLOCK_SI(si);
6655 * If it is a dgram socket and we are connected, don't include the
6658 if (si->type == SOCK_DGRAM && si->connected) {
6659 ret = libc_sendto(s,
6666 ret = libc_sendto(s,
6670 (struct sockaddr *)msg.msg_name,
6674 SWRAP_UNLOCK_SI(si);
6676 swrap_sendmsg_after(s, si, &msg, to, ret);
6681 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6682 const struct sockaddr *to, socklen_t tolen)
6684 return swrap_sendto(s, buf, len, flags, to, tolen);
6687 /****************************************************************************
6689 ***************************************************************************/
6691 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6693 struct socket_info *si;
6695 struct swrap_address saddr = {
6696 .sa_socklen = sizeof(struct sockaddr_storage),
6702 si = find_socket_info(s);
6704 return libc_recv(s, buf, len, flags);
6711 msg.msg_name = &saddr.sa.s; /* optional address */
6712 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6713 msg.msg_iov = &tmp; /* scatter/gather array */
6714 msg.msg_iovlen = 1; /* # elements in msg_iov */
6715 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6716 msg.msg_control = NULL; /* ancillary data, see below */
6717 msg.msg_controllen = 0; /* ancillary data buffer len */
6718 msg.msg_flags = 0; /* flags on received message */
6721 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6726 buf = msg.msg_iov[0].iov_base;
6727 len = msg.msg_iov[0].iov_len;
6729 ret = libc_recv(s, buf, len, flags);
6731 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6739 ssize_t recv(int s, void *buf, size_t len, int flags)
6741 return swrap_recv(s, buf, len, flags);
6744 /****************************************************************************
6746 ***************************************************************************/
6748 static ssize_t swrap_read(int s, void *buf, size_t len)
6750 struct socket_info *si;
6753 struct swrap_address saddr = {
6754 .sa_socklen = sizeof(struct sockaddr_storage),
6759 si = find_socket_info(s);
6761 return libc_read(s, buf, len);
6768 msg.msg_name = &saddr.sa.ss; /* optional address */
6769 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6770 msg.msg_iov = &tmp; /* scatter/gather array */
6771 msg.msg_iovlen = 1; /* # elements in msg_iov */
6772 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6773 msg.msg_control = NULL; /* ancillary data, see below */
6774 msg.msg_controllen = 0; /* ancillary data buffer len */
6775 msg.msg_flags = 0; /* flags on received message */
6778 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6780 if (tret == -ENOTSOCK) {
6781 return libc_read(s, buf, len);
6786 buf = msg.msg_iov[0].iov_base;
6787 len = msg.msg_iov[0].iov_len;
6789 ret = libc_read(s, buf, len);
6791 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6799 ssize_t read(int s, void *buf, size_t len)
6801 return swrap_read(s, buf, len);
6804 /****************************************************************************
6806 ***************************************************************************/
6808 static ssize_t swrap_write(int s, const void *buf, size_t len)
6812 struct sockaddr_un un_addr;
6815 struct socket_info *si;
6817 si = find_socket_info(s);
6819 return libc_write(s, buf, len);
6822 tmp.iov_base = discard_const_p(char, buf);
6826 msg.msg_name = NULL; /* optional address */
6827 msg.msg_namelen = 0; /* size of address */
6828 msg.msg_iov = &tmp; /* scatter/gather array */
6829 msg.msg_iovlen = 1; /* # elements in msg_iov */
6830 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6831 msg.msg_control = NULL; /* ancillary data, see below */
6832 msg.msg_controllen = 0; /* ancillary data buffer len */
6833 msg.msg_flags = 0; /* flags on received message */
6836 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6841 buf = msg.msg_iov[0].iov_base;
6842 len = msg.msg_iov[0].iov_len;
6844 ret = libc_write(s, buf, len);
6846 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6851 ssize_t write(int s, const void *buf, size_t len)
6853 return swrap_write(s, buf, len);
6856 /****************************************************************************
6858 ***************************************************************************/
6860 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6864 struct sockaddr_un un_addr;
6867 struct socket_info *si = find_socket_info(s);
6870 return libc_send(s, buf, len, flags);
6873 tmp.iov_base = discard_const_p(char, buf);
6877 msg.msg_name = NULL; /* optional address */
6878 msg.msg_namelen = 0; /* size of address */
6879 msg.msg_iov = &tmp; /* scatter/gather array */
6880 msg.msg_iovlen = 1; /* # elements in msg_iov */
6881 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6882 msg.msg_control = NULL; /* ancillary data, see below */
6883 msg.msg_controllen = 0; /* ancillary data buffer len */
6884 msg.msg_flags = 0; /* flags on received message */
6887 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6892 buf = msg.msg_iov[0].iov_base;
6893 len = msg.msg_iov[0].iov_len;
6895 ret = libc_send(s, buf, len, flags);
6897 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6902 ssize_t send(int s, const void *buf, size_t len, int flags)
6904 return swrap_send(s, buf, len, flags);
6907 /****************************************************************************
6909 ***************************************************************************/
6911 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6913 struct swrap_address from_addr = {
6914 .sa_socklen = sizeof(struct sockaddr_un),
6916 struct swrap_address convert_addr = {
6917 .sa_socklen = sizeof(struct sockaddr_storage),
6919 struct socket_info *si;
6922 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6923 size_t msg_ctrllen_filled;
6924 size_t msg_ctrllen_left;
6930 si = find_socket_info(s);
6932 rc = swrap_recvmsg_before_unix(omsg, &msg);
6936 ret = libc_recvmsg(s, &msg, flags);
6937 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6940 tmp.iov_base = NULL;
6944 msg.msg_name = &from_addr.sa; /* optional address */
6945 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6946 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6947 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6948 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6949 msg_ctrllen_filled = 0;
6950 msg_ctrllen_left = omsg->msg_controllen;
6952 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6953 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6954 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6957 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6962 ret = libc_recvmsg(s, &msg, flags);
6964 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6965 msg_ctrllen_filled += msg.msg_controllen;
6966 msg_ctrllen_left -= msg.msg_controllen;
6968 if (omsg->msg_control != NULL) {
6971 p = omsg->msg_control;
6972 p += msg_ctrllen_filled;
6974 msg.msg_control = p;
6975 msg.msg_controllen = msg_ctrllen_left;
6977 msg.msg_control = NULL;
6978 msg.msg_controllen = 0;
6983 * We convert the unix address to a IP address so we need a buffer
6984 * which can store the address in case of SOCK_DGRAM, see below.
6986 msg.msg_name = &convert_addr.sa;
6987 msg.msg_namelen = convert_addr.sa_socklen;
6989 rc = swrap_recvmsg_after(s,
6993 from_addr.sa_socklen,
6999 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7000 if (omsg->msg_control != NULL) {
7001 /* msg.msg_controllen = space left */
7002 msg_ctrllen_left = msg.msg_controllen;
7003 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7006 /* Update the original message length */
7007 omsg->msg_controllen = msg_ctrllen_filled;
7008 omsg->msg_flags = msg.msg_flags;
7010 omsg->msg_iovlen = msg.msg_iovlen;
7017 * The msg_name field points to a caller-allocated buffer that is
7018 * used to return the source address if the socket is unconnected. The
7019 * caller should set msg_namelen to the size of this buffer before this
7020 * call; upon return from a successful call, msg_name will contain the
7021 * length of the returned address. If the application does not need
7022 * to know the source address, msg_name can be specified as NULL.
7024 if (si->type == SOCK_STREAM) {
7025 omsg->msg_namelen = 0;
7026 } else if (omsg->msg_name != NULL &&
7027 omsg->msg_namelen != 0 &&
7028 omsg->msg_namelen >= msg.msg_namelen) {
7029 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7030 omsg->msg_namelen = msg.msg_namelen;
7033 SWRAP_UNLOCK_SI(si);
7038 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7040 return swrap_recvmsg(sockfd, msg, flags);
7043 /****************************************************************************
7045 ***************************************************************************/
7047 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7051 struct sockaddr_un un_addr;
7052 const struct sockaddr_un *to_un = NULL;
7053 const struct sockaddr *to = NULL;
7056 struct socket_info *si = find_socket_info(s);
7060 int scm_rights_pipe_fd = -1;
7062 rc = swrap_sendmsg_before_unix(omsg, &msg,
7063 &scm_rights_pipe_fd);
7067 ret = libc_sendmsg(s, &msg, flags);
7068 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7071 ZERO_STRUCT(un_addr);
7073 tmp.iov_base = NULL;
7080 if (si->connected == 0) {
7081 msg.msg_name = omsg->msg_name; /* optional address */
7082 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7084 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7085 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7087 SWRAP_UNLOCK_SI(si);
7089 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7090 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7091 uint8_t *cmbuf = NULL;
7094 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7100 msg.msg_controllen = 0;
7101 msg.msg_control = NULL;
7103 msg.msg_control = cmbuf;
7104 msg.msg_controllen = cmlen;
7107 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7109 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7111 int saved_errno = errno;
7112 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7113 SAFE_FREE(msg.msg_control);
7115 errno = saved_errno;
7122 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7129 char *swrap_dir = NULL;
7131 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7132 avail += msg.msg_iov[i].iov_len;
7138 /* we capture it as one single packet */
7139 buf = (uint8_t *)malloc(remain);
7141 int saved_errno = errno;
7142 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7143 SAFE_FREE(msg.msg_control);
7145 errno = saved_errno;
7149 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7150 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7152 msg.msg_iov[i].iov_base,
7155 remain -= this_time;
7158 type = SOCKET_TYPE_CHAR_UDP;
7160 swrap_dir = socket_wrapper_dir();
7161 if (swrap_dir == NULL) {
7162 int saved_errno = errno;
7163 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7164 SAFE_FREE(msg.msg_control);
7167 errno = saved_errno;
7171 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7172 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7173 if (stat(un_addr.sun_path, &st) != 0) continue;
7175 msg.msg_name = &un_addr; /* optional address */
7176 msg.msg_namelen = sizeof(un_addr); /* size of address */
7178 /* ignore the any errors in broadcast sends */
7179 libc_sendmsg(s, &msg, flags);
7182 SAFE_FREE(swrap_dir);
7186 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7189 SWRAP_UNLOCK_SI(si);
7194 ret = libc_sendmsg(s, &msg, flags);
7196 swrap_sendmsg_after(s, si, &msg, to, ret);
7198 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7200 int saved_errno = errno;
7201 SAFE_FREE(msg.msg_control);
7202 errno = saved_errno;
7209 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7211 return swrap_sendmsg(s, omsg, flags);
7214 /****************************************************************************
7216 ***************************************************************************/
7218 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7220 struct socket_info *si;
7223 struct swrap_address saddr = {
7224 .sa_socklen = sizeof(struct sockaddr_storage)
7229 si = find_socket_info(s);
7231 return libc_readv(s, vector, count);
7234 tmp.iov_base = NULL;
7238 msg.msg_name = &saddr.sa.s; /* optional address */
7239 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7240 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7241 msg.msg_iovlen = count; /* # elements in msg_iov */
7242 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7243 msg.msg_control = NULL; /* ancillary data, see below */
7244 msg.msg_controllen = 0; /* ancillary data buffer len */
7245 msg.msg_flags = 0; /* flags on received message */
7248 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7250 if (rc == -ENOTSOCK) {
7251 return libc_readv(s, vector, count);
7256 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7258 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7266 ssize_t readv(int s, const struct iovec *vector, int count)
7268 return swrap_readv(s, vector, count);
7271 /****************************************************************************
7273 ***************************************************************************/
7275 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7279 struct sockaddr_un un_addr;
7282 struct socket_info *si = find_socket_info(s);
7285 return libc_writev(s, vector, count);
7288 tmp.iov_base = NULL;
7292 msg.msg_name = NULL; /* optional address */
7293 msg.msg_namelen = 0; /* size of address */
7294 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7295 msg.msg_iovlen = count; /* # elements in msg_iov */
7296 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7297 msg.msg_control = NULL; /* ancillary data, see below */
7298 msg.msg_controllen = 0; /* ancillary data buffer len */
7299 msg.msg_flags = 0; /* flags on received message */
7302 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7304 if (rc == -ENOTSOCK) {
7305 return libc_readv(s, vector, count);
7310 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7312 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7317 ssize_t writev(int s, const struct iovec *vector, int count)
7319 return swrap_writev(s, vector, count);
7322 /****************************
7324 ***************************/
7326 static int swrap_close(int fd)
7328 struct socket_info *si = NULL;
7332 swrap_mutex_lock(&socket_reset_mutex);
7334 si_index = find_socket_info_index(fd);
7335 if (si_index == -1) {
7336 swrap_mutex_unlock(&socket_reset_mutex);
7337 return libc_close(fd);
7340 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7341 reset_socket_info_index(fd);
7343 si = swrap_get_socket_info(si_index);
7345 swrap_mutex_lock(&first_free_mutex);
7348 ret = libc_close(fd);
7350 swrap_dec_refcount(si);
7352 if (swrap_get_refcount(si) > 0) {
7353 /* there are still references left */
7357 if (si->fd_passed) {
7361 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7362 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7365 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7366 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7367 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7370 if (si->un_addr.sun_path[0] != '\0') {
7371 unlink(si->un_addr.sun_path);
7375 swrap_set_next_free(si, first_free);
7376 first_free = si_index;
7379 SWRAP_UNLOCK_SI(si);
7380 swrap_mutex_unlock(&first_free_mutex);
7381 swrap_mutex_unlock(&socket_reset_mutex);
7388 return swrap_close(fd);
7391 /****************************
7393 ***************************/
7395 static int swrap_dup(int fd)
7397 struct socket_info *si;
7400 idx = find_socket_info_index(fd);
7402 return libc_dup(fd);
7405 si = swrap_get_socket_info(idx);
7407 dup_fd = libc_dup(fd);
7409 int saved_errno = errno;
7410 errno = saved_errno;
7414 if ((size_t)dup_fd >= socket_fds_max) {
7415 SWRAP_LOG(SWRAP_LOG_ERROR,
7416 "The max socket index limit of %zu has been reached, "
7427 swrap_inc_refcount(si);
7429 SWRAP_UNLOCK_SI(si);
7431 /* Make sure we don't have an entry for the fd */
7432 swrap_remove_stale(dup_fd);
7434 set_socket_info_index(dup_fd, idx);
7441 return swrap_dup(fd);
7444 /****************************
7446 ***************************/
7448 static int swrap_dup2(int fd, int newfd)
7450 struct socket_info *si;
7453 idx = find_socket_info_index(fd);
7455 return libc_dup2(fd, newfd);
7458 si = swrap_get_socket_info(idx);
7462 * According to the manpage:
7464 * "If oldfd is a valid file descriptor, and newfd has the same
7465 * value as oldfd, then dup2() does nothing, and returns newfd."
7470 if ((size_t)newfd >= socket_fds_max) {
7471 SWRAP_LOG(SWRAP_LOG_ERROR,
7472 "The max socket index limit of %zu has been reached, "
7480 if (find_socket_info(newfd)) {
7481 /* dup2() does an implicit close of newfd, which we
7482 * need to emulate */
7486 dup_fd = libc_dup2(fd, newfd);
7488 int saved_errno = errno;
7489 errno = saved_errno;
7495 swrap_inc_refcount(si);
7497 SWRAP_UNLOCK_SI(si);
7499 /* Make sure we don't have an entry for the fd */
7500 swrap_remove_stale(dup_fd);
7502 set_socket_info_index(dup_fd, idx);
7507 int dup2(int fd, int newfd)
7509 return swrap_dup2(fd, newfd);
7512 /****************************
7514 ***************************/
7516 static int swrap_vfcntl(int fd, int cmd, va_list va)
7518 struct socket_info *si;
7519 int rc, dup_fd, idx;
7521 idx = find_socket_info_index(fd);
7523 return libc_vfcntl(fd, cmd, va);
7526 si = swrap_get_socket_info(idx);
7530 dup_fd = libc_vfcntl(fd, cmd, va);
7532 int saved_errno = errno;
7533 errno = saved_errno;
7537 /* Make sure we don't have an entry for the fd */
7538 swrap_remove_stale(dup_fd);
7540 if ((size_t)dup_fd >= socket_fds_max) {
7541 SWRAP_LOG(SWRAP_LOG_ERROR,
7542 "The max socket index limit of %zu has been reached, "
7553 swrap_inc_refcount(si);
7555 SWRAP_UNLOCK_SI(si);
7558 set_socket_info_index(dup_fd, idx);
7563 rc = libc_vfcntl(fd, cmd, va);
7570 int fcntl(int fd, int cmd, ...)
7577 rc = swrap_vfcntl(fd, cmd, va);
7584 /****************************
7586 ***************************/
7589 static int swrap_eventfd(int count, int flags)
7593 fd = libc_eventfd(count, flags);
7595 swrap_remove_stale(fd);
7601 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7602 int eventfd(unsigned int count, int flags)
7604 int eventfd(int count, int flags)
7607 return swrap_eventfd(count, flags);
7612 int pledge(const char *promises, const char *paths[])
7614 (void)promises; /* unused */
7615 (void)paths; /* unused */
7619 #endif /* HAVE_PLEDGE */
7621 static void swrap_thread_prepare(void)
7624 * This function should only be called here!!
7626 * We bind all symobls to avoid deadlocks of the fork is
7627 * interrupted by a signal handler using a symbol of this
7630 swrap_bind_symbol_all();
7635 static void swrap_thread_parent(void)
7640 static void swrap_thread_child(void)
7645 /****************************
7647 ***************************/
7648 void swrap_constructor(void)
7650 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7651 SWRAP_LOG(SWRAP_LOG_ERROR,
7653 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7654 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7655 "sizeof(struct socket_info)=%zu",
7657 sizeof(struct swrap_unix_scm_rights),
7658 sizeof(struct swrap_unix_scm_rights_payload),
7659 sizeof(struct socket_info));
7666 * If we hold a lock and the application forks, then the child
7667 * is not able to unlock the mutex and we are in a deadlock.
7668 * This should prevent such deadlocks.
7670 pthread_atfork(&swrap_thread_prepare,
7671 &swrap_thread_parent,
7672 &swrap_thread_child);
7675 /****************************
7677 ***************************/
7680 * This function is called when the library is unloaded and makes sure that
7681 * sockets get closed and the unix file for the socket are unlinked.
7683 void swrap_destructor(void)
7687 if (socket_fds_idx != NULL) {
7688 for (i = 0; i < socket_fds_max; ++i) {
7689 if (socket_fds_idx[i] != -1) {
7693 SAFE_FREE(socket_fds_idx);
7698 if (swrap.libc.handle != NULL) {
7699 dlclose(swrap.libc.handle);
7701 if (swrap.libc.socket_handle) {
7702 dlclose(swrap.libc.socket_handle);
7706 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7708 * On FreeBSD 12 (and maybe other platforms)
7709 * system libraries like libresolv prefix there
7710 * syscalls with '_' in order to always use
7711 * the symbols from libc.
7713 * In the interaction with resolv_wrapper,
7714 * we need to inject socket wrapper into libresolv,
7715 * which means we need to private all socket
7716 * related syscalls also with the '_' prefix.
7718 * This is tested in Samba's 'make test',
7719 * there we noticed that providing '_read'
7720 * and '_open' would cause errors, which
7721 * means we skip '_read', '_write' and
7722 * all non socket related calls without
7723 * further analyzing the problem.
7725 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7726 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7729 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7731 SWRAP_SYMBOL_ALIAS(accept, _accept);
7732 SWRAP_SYMBOL_ALIAS(bind, _bind);
7733 SWRAP_SYMBOL_ALIAS(close, _close);
7734 SWRAP_SYMBOL_ALIAS(connect, _connect);
7735 SWRAP_SYMBOL_ALIAS(dup, _dup);
7736 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7737 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7738 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7739 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7740 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7741 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7742 SWRAP_SYMBOL_ALIAS(listen, _listen);
7743 SWRAP_SYMBOL_ALIAS(readv, _readv);
7744 SWRAP_SYMBOL_ALIAS(recv, _recv);
7745 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7746 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7747 SWRAP_SYMBOL_ALIAS(send, _send);
7748 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7749 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7750 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7751 SWRAP_SYMBOL_ALIAS(socket, _socket);
7752 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7753 SWRAP_SYMBOL_ALIAS(writev, _writev);
7755 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */