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 { \
188 ret = socket_wrapper_init_mutex(&sockets_mutex); \
189 if (ret != 0) exit(-1); \
190 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
191 if (ret != 0) exit(-1); \
192 ret = socket_wrapper_init_mutex(&first_free_mutex); \
193 if (ret != 0) exit(-1); \
194 for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \
195 ret = socket_wrapper_init_mutex(&sockets[__i].meta.mutex); \
196 if (ret != 0) exit(-1); \
198 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
199 if (ret != 0) exit(-1); \
200 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
201 if (ret != 0) exit(-1); \
202 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
203 if (ret != 0) exit(-1); \
206 # define SWRAP_LOCK_ALL do { \
208 swrap_mutex_lock(&sockets_mutex); \
209 swrap_mutex_lock(&socket_reset_mutex); \
210 swrap_mutex_lock(&first_free_mutex); \
211 for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \
212 swrap_mutex_lock(&sockets[__i].meta.mutex); \
214 swrap_mutex_lock(&autobind_start_mutex); \
215 swrap_mutex_lock(&pcap_dump_mutex); \
216 swrap_mutex_lock(&mtu_update_mutex); \
219 # define SWRAP_UNLOCK_ALL do { \
221 swrap_mutex_unlock(&mtu_update_mutex); \
222 swrap_mutex_unlock(&pcap_dump_mutex); \
223 swrap_mutex_unlock(&autobind_start_mutex); \
224 for (__s = 0; (sockets != NULL) && __s < socket_info_max; __s++) { \
225 size_t __i = (socket_info_max - 1) - __s; \
226 swrap_mutex_unlock(&sockets[__i].meta.mutex); \
228 swrap_mutex_unlock(&first_free_mutex); \
229 swrap_mutex_unlock(&socket_reset_mutex); \
230 swrap_mutex_unlock(&sockets_mutex); \
233 #define SOCKET_INFO_CONTAINER(si) \
234 (struct socket_info_container *)(si)
236 #define SWRAP_LOCK_SI(si) do { \
237 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
238 swrap_mutex_lock(&sic->meta.mutex); \
241 #define SWRAP_UNLOCK_SI(si) do { \
242 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
243 swrap_mutex_unlock(&sic->meta.mutex); \
246 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
247 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
249 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
252 /* we need to use a very terse format here as IRIX 6.4 silently
253 truncates names to 16 chars, so if we use a longer name then we
254 can't tell which port a packet came from with recvfrom()
256 with this format we have 8 chars left for the directory name
258 #define SOCKET_FORMAT "%c%02X%04X"
259 #define SOCKET_TYPE_CHAR_TCP 'T'
260 #define SOCKET_TYPE_CHAR_UDP 'U'
261 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
262 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
265 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
266 * format PCAP capture files (as the caller will simply continue from here).
268 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
269 #define SOCKET_WRAPPER_MTU_MIN 512
270 #define SOCKET_WRAPPER_MTU_MAX 32768
272 #define SOCKET_MAX_SOCKETS 1024
275 * Maximum number of socket_info structures that can
276 * be used. Can be overriden by the environment variable
277 * SOCKET_WRAPPER_MAX_SOCKETS.
279 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
281 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
283 /* This limit is to avoid broadcast sendto() needing to stat too many
284 * files. It may be raised (with a performance cost) to up to 254
285 * without changing the format above */
286 #define MAX_WRAPPED_INTERFACES 64
288 struct swrap_address {
289 socklen_t sa_socklen;
292 struct sockaddr_in in;
294 struct sockaddr_in6 in6;
296 struct sockaddr_un un;
297 struct sockaddr_storage ss;
301 static int first_free;
306 * Remember to update swrap_unix_scm_right_magic
323 /* The unix path so we can unlink it on close() */
324 struct sockaddr_un un_addr;
326 struct swrap_address bindname;
327 struct swrap_address myname;
328 struct swrap_address peername;
331 unsigned long pck_snd;
332 unsigned long pck_rcv;
336 struct socket_info_meta
338 unsigned int refcount;
340 pthread_mutex_t mutex;
343 struct socket_info_container
345 struct socket_info info;
346 struct socket_info_meta meta;
349 static struct socket_info_container *sockets;
351 static size_t socket_info_max = 0;
354 * Allocate the socket array always on the limit value. We want it to be
355 * at least bigger than the default so if we reach the limit we can
356 * still deal with duplicate fds pointing to the same socket_info.
358 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
360 /* Hash table to map fds to corresponding socket_info index */
361 static int *socket_fds_idx;
363 /* Mutex for syncronizing port selection during swrap_auto_bind() */
364 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
366 /* Mutex to guard the initialization of array of socket_info structures */
367 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
369 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
370 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
372 /* Mutex to synchronize access to first free index in socket_info array */
373 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
375 /* Mutex to synchronize access to packet capture dump file */
376 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
378 /* Mutex for synchronizing mtu value fetch*/
379 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
381 /* Function prototypes */
383 bool socket_wrapper_enabled(void);
385 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
386 /* xlC and other oldschool compilers support (only) this */
387 #pragma init (swrap_constructor)
389 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
390 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
391 #pragma fini (swrap_destructor)
393 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
395 #ifndef HAVE_GETPROGNAME
396 static const char *getprogname(void)
398 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
399 return program_invocation_short_name;
400 #elif defined(HAVE_GETEXECNAME)
401 return getexecname();
404 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
406 #endif /* HAVE_GETPROGNAME */
408 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
409 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
411 static void swrap_log(enum swrap_dbglvl_e dbglvl,
413 const char *format, ...)
418 unsigned int lvl = 0;
419 const char *prefix = "SWRAP";
420 const char *progname = getprogname();
422 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
431 va_start(va, format);
432 vsnprintf(buffer, sizeof(buffer), format, va);
436 case SWRAP_LOG_ERROR:
437 prefix = "SWRAP_ERROR";
440 prefix = "SWRAP_WARN";
442 case SWRAP_LOG_DEBUG:
443 prefix = "SWRAP_DEBUG";
445 case SWRAP_LOG_TRACE:
446 prefix = "SWRAP_TRACE";
450 if (progname == NULL) {
451 progname = "<unknown>";
455 "%s[%s (%u)] - %s: %s\n",
458 (unsigned int)getpid(),
463 /*********************************************************
464 * SWRAP LOADING LIBC FUNCTIONS
465 *********************************************************/
470 typedef int (*__libc_accept4)(int sockfd,
471 struct sockaddr *addr,
475 typedef int (*__libc_accept)(int sockfd,
476 struct sockaddr *addr,
479 typedef int (*__libc_bind)(int sockfd,
480 const struct sockaddr *addr,
482 typedef int (*__libc_close)(int fd);
483 typedef int (*__libc_connect)(int sockfd,
484 const struct sockaddr *addr,
486 typedef int (*__libc_dup)(int fd);
487 typedef int (*__libc_dup2)(int oldfd, int newfd);
488 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
489 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
491 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
494 typedef int (*__libc_eventfd)(int count, int flags);
496 typedef int (*__libc_getpeername)(int sockfd,
497 struct sockaddr *addr,
499 typedef int (*__libc_getsockname)(int sockfd,
500 struct sockaddr *addr,
502 typedef int (*__libc_getsockopt)(int sockfd,
507 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
508 typedef int (*__libc_listen)(int sockfd, int backlog);
509 typedef int (*__libc_open)(const char *pathname, int flags, ...);
511 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
512 #endif /* HAVE_OPEN64 */
513 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
514 typedef int (*__libc_pipe)(int pipefd[2]);
515 typedef int (*__libc_read)(int fd, void *buf, size_t count);
516 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
517 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
518 typedef int (*__libc_recvfrom)(int sockfd,
522 struct sockaddr *src_addr,
524 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
525 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
526 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
527 typedef int (*__libc_sendto)(int sockfd,
531 const struct sockaddr *dst_addr,
533 typedef int (*__libc_setsockopt)(int sockfd,
539 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
541 typedef int (*__libc_socket)(int domain, int type, int protocol);
542 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
543 #ifdef HAVE_TIMERFD_CREATE
544 typedef int (*__libc_timerfd_create)(int clockid, int flags);
546 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
547 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
549 #define SWRAP_SYMBOL_ENTRY(i) \
555 struct swrap_libc_symbols {
557 SWRAP_SYMBOL_ENTRY(accept4);
559 SWRAP_SYMBOL_ENTRY(accept);
561 SWRAP_SYMBOL_ENTRY(bind);
562 SWRAP_SYMBOL_ENTRY(close);
563 SWRAP_SYMBOL_ENTRY(connect);
564 SWRAP_SYMBOL_ENTRY(dup);
565 SWRAP_SYMBOL_ENTRY(dup2);
566 SWRAP_SYMBOL_ENTRY(fcntl);
567 SWRAP_SYMBOL_ENTRY(fopen);
569 SWRAP_SYMBOL_ENTRY(fopen64);
572 SWRAP_SYMBOL_ENTRY(eventfd);
574 SWRAP_SYMBOL_ENTRY(getpeername);
575 SWRAP_SYMBOL_ENTRY(getsockname);
576 SWRAP_SYMBOL_ENTRY(getsockopt);
577 SWRAP_SYMBOL_ENTRY(ioctl);
578 SWRAP_SYMBOL_ENTRY(listen);
579 SWRAP_SYMBOL_ENTRY(open);
581 SWRAP_SYMBOL_ENTRY(open64);
583 SWRAP_SYMBOL_ENTRY(openat);
584 SWRAP_SYMBOL_ENTRY(pipe);
585 SWRAP_SYMBOL_ENTRY(read);
586 SWRAP_SYMBOL_ENTRY(readv);
587 SWRAP_SYMBOL_ENTRY(recv);
588 SWRAP_SYMBOL_ENTRY(recvfrom);
589 SWRAP_SYMBOL_ENTRY(recvmsg);
590 SWRAP_SYMBOL_ENTRY(send);
591 SWRAP_SYMBOL_ENTRY(sendmsg);
592 SWRAP_SYMBOL_ENTRY(sendto);
593 SWRAP_SYMBOL_ENTRY(setsockopt);
595 SWRAP_SYMBOL_ENTRY(signalfd);
597 SWRAP_SYMBOL_ENTRY(socket);
598 SWRAP_SYMBOL_ENTRY(socketpair);
599 #ifdef HAVE_TIMERFD_CREATE
600 SWRAP_SYMBOL_ENTRY(timerfd_create);
602 SWRAP_SYMBOL_ENTRY(write);
603 SWRAP_SYMBOL_ENTRY(writev);
610 struct swrap_libc_symbols symbols;
614 static struct swrap swrap;
617 static char *socket_wrapper_dir(void);
619 #define LIBC_NAME "libc.so"
626 static const char *swrap_str_lib(enum swrap_lib lib)
631 case SWRAP_LIBSOCKET:
635 /* Compiler would warn us about unhandled enum value if we get here */
639 static void *swrap_load_lib_handle(enum swrap_lib lib)
641 int flags = RTLD_LAZY;
646 const char *env_preload = getenv("LD_PRELOAD");
647 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
648 bool enable_deepbind = true;
650 /* Don't do a deepbind if we run with libasan */
651 if (env_preload != NULL && strlen(env_preload) < 1024) {
652 const char *p = strstr(env_preload, "libasan.so");
654 enable_deepbind = false;
658 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
659 enable_deepbind = false;
662 if (enable_deepbind) {
663 flags |= RTLD_DEEPBIND;
668 case SWRAP_LIBSOCKET:
669 #ifdef HAVE_LIBSOCKET
670 handle = swrap.libc.socket_handle;
671 if (handle == NULL) {
672 for (i = 10; i >= 0; i--) {
673 char soname[256] = {0};
675 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
676 handle = dlopen(soname, flags);
677 if (handle != NULL) {
682 swrap.libc.socket_handle = handle;
687 handle = swrap.libc.handle;
689 if (handle == NULL) {
690 handle = dlopen(LIBC_SO, flags);
692 swrap.libc.handle = handle;
695 if (handle == NULL) {
696 for (i = 10; i >= 0; i--) {
697 char soname[256] = {0};
699 snprintf(soname, sizeof(soname), "libc.so.%d", i);
700 handle = dlopen(soname, flags);
701 if (handle != NULL) {
706 swrap.libc.handle = handle;
711 if (handle == NULL) {
713 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
715 SWRAP_LOG(SWRAP_LOG_ERROR,
716 "Failed to dlopen library: %s",
725 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
730 handle = swrap_load_lib_handle(lib);
732 func = dlsym(handle, fn_name);
734 SWRAP_LOG(SWRAP_LOG_ERROR,
735 "Failed to find %s: %s",
741 SWRAP_LOG(SWRAP_LOG_TRACE,
749 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
750 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
754 ret = pthread_mutex_lock(mutex);
756 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
757 getpid(), getppid(), caller, line, name, strerror(ret));
761 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
762 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
766 ret = pthread_mutex_unlock(mutex);
768 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
769 getpid(), getppid(), caller, line, name, strerror(ret));
774 * These macros have a thread race condition on purpose!
776 * This is an optimization to avoid locking each time we check if the symbol is
779 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
780 swrap.libc.symbols._libc_##sym_name.obj = \
781 _swrap_bind_symbol(lib, #sym_name); \
784 #define swrap_bind_symbol_libc(sym_name) \
785 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
787 #define swrap_bind_symbol_libsocket(sym_name) \
788 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
790 static void swrap_bind_symbol_all(void);
792 /****************************************************************************
794 ****************************************************************************
796 * Functions especially from libc need to be loaded individually, you can't
797 * load all at once or gdb will segfault at startup. The same applies to
798 * valgrind and has probably something todo with with the linker. So we need
799 * load each function at the point it is called the first time.
801 ****************************************************************************/
804 static int libc_accept4(int sockfd,
805 struct sockaddr *addr,
809 swrap_bind_symbol_all();
811 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
814 #else /* HAVE_ACCEPT4 */
816 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
818 swrap_bind_symbol_all();
820 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
822 #endif /* HAVE_ACCEPT4 */
824 static int libc_bind(int sockfd,
825 const struct sockaddr *addr,
828 swrap_bind_symbol_all();
830 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
833 static int libc_close(int fd)
835 swrap_bind_symbol_all();
837 return swrap.libc.symbols._libc_close.f(fd);
840 static int libc_connect(int sockfd,
841 const struct sockaddr *addr,
844 swrap_bind_symbol_all();
846 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
849 static int libc_dup(int fd)
851 swrap_bind_symbol_all();
853 return swrap.libc.symbols._libc_dup.f(fd);
856 static int libc_dup2(int oldfd, int newfd)
858 swrap_bind_symbol_all();
860 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
864 static int libc_eventfd(int count, int flags)
866 swrap_bind_symbol_all();
868 return swrap.libc.symbols._libc_eventfd.f(count, flags);
872 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
873 static int libc_vfcntl(int fd, int cmd, va_list ap)
878 swrap_bind_symbol_all();
880 arg = va_arg(ap, void *);
882 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
887 static int libc_getpeername(int sockfd,
888 struct sockaddr *addr,
891 swrap_bind_symbol_all();
893 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
896 static int libc_getsockname(int sockfd,
897 struct sockaddr *addr,
900 swrap_bind_symbol_all();
902 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
905 static int libc_getsockopt(int sockfd,
911 swrap_bind_symbol_all();
913 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
920 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
921 static int libc_vioctl(int d, unsigned long int request, va_list ap)
926 swrap_bind_symbol_all();
928 arg = va_arg(ap, void *);
930 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
935 static int libc_listen(int sockfd, int backlog)
937 swrap_bind_symbol_all();
939 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
942 static FILE *libc_fopen(const char *name, const char *mode)
944 swrap_bind_symbol_all();
946 return swrap.libc.symbols._libc_fopen.f(name, mode);
950 static FILE *libc_fopen64(const char *name, const char *mode)
952 swrap_bind_symbol_all();
954 return swrap.libc.symbols._libc_fopen64.f(name, mode);
956 #endif /* HAVE_FOPEN64 */
958 static int libc_vopen(const char *pathname, int flags, va_list ap)
963 swrap_bind_symbol_all();
965 if (flags & O_CREAT) {
966 mode = va_arg(ap, int);
968 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
973 static int libc_open(const char *pathname, int flags, ...)
979 fd = libc_vopen(pathname, flags, ap);
986 static int libc_vopen64(const char *pathname, int flags, va_list ap)
991 swrap_bind_symbol_all();
993 if (flags & O_CREAT) {
994 mode = va_arg(ap, int);
996 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1000 #endif /* HAVE_OPEN64 */
1002 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1007 swrap_bind_symbol_all();
1009 if (flags & O_CREAT) {
1010 mode = va_arg(ap, int);
1012 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1021 static int libc_openat(int dirfd, const char *path, int flags, ...)
1026 va_start(ap, flags);
1027 fd = libc_vopenat(dirfd, path, flags, ap);
1034 static int libc_pipe(int pipefd[2])
1036 swrap_bind_symbol_all();
1038 return swrap.libc.symbols._libc_pipe.f(pipefd);
1041 static int libc_read(int fd, void *buf, size_t count)
1043 swrap_bind_symbol_all();
1045 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1048 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1050 swrap_bind_symbol_all();
1052 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1055 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1057 swrap_bind_symbol_all();
1059 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1062 static int libc_recvfrom(int sockfd,
1066 struct sockaddr *src_addr,
1069 swrap_bind_symbol_all();
1071 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1079 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1081 swrap_bind_symbol_all();
1083 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1086 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1088 swrap_bind_symbol_all();
1090 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1093 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1095 swrap_bind_symbol_all();
1097 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1100 static int libc_sendto(int sockfd,
1104 const struct sockaddr *dst_addr,
1107 swrap_bind_symbol_all();
1109 return swrap.libc.symbols._libc_sendto.f(sockfd,
1117 static int libc_setsockopt(int sockfd,
1123 swrap_bind_symbol_all();
1125 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1132 #ifdef HAVE_SIGNALFD
1133 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1135 swrap_bind_symbol_all();
1137 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1141 static int libc_socket(int domain, int type, int protocol)
1143 swrap_bind_symbol_all();
1145 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1148 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1150 swrap_bind_symbol_all();
1152 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1155 #ifdef HAVE_TIMERFD_CREATE
1156 static int libc_timerfd_create(int clockid, int flags)
1158 swrap_bind_symbol_all();
1160 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1164 static ssize_t libc_write(int fd, const void *buf, size_t count)
1166 swrap_bind_symbol_all();
1168 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1171 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1173 swrap_bind_symbol_all();
1175 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1178 /* DO NOT call this function during library initialization! */
1179 static void __swrap_bind_symbol_all_once(void)
1182 swrap_bind_symbol_libsocket(accept4);
1184 swrap_bind_symbol_libsocket(accept);
1186 swrap_bind_symbol_libsocket(bind);
1187 swrap_bind_symbol_libc(close);
1188 swrap_bind_symbol_libsocket(connect);
1189 swrap_bind_symbol_libc(dup);
1190 swrap_bind_symbol_libc(dup2);
1191 swrap_bind_symbol_libc(fcntl);
1192 swrap_bind_symbol_libc(fopen);
1194 swrap_bind_symbol_libc(fopen64);
1197 swrap_bind_symbol_libc(eventfd);
1199 swrap_bind_symbol_libsocket(getpeername);
1200 swrap_bind_symbol_libsocket(getsockname);
1201 swrap_bind_symbol_libsocket(getsockopt);
1202 swrap_bind_symbol_libc(ioctl);
1203 swrap_bind_symbol_libsocket(listen);
1204 swrap_bind_symbol_libc(open);
1206 swrap_bind_symbol_libc(open64);
1208 swrap_bind_symbol_libc(openat);
1209 swrap_bind_symbol_libsocket(pipe);
1210 swrap_bind_symbol_libc(read);
1211 swrap_bind_symbol_libsocket(readv);
1212 swrap_bind_symbol_libsocket(recv);
1213 swrap_bind_symbol_libsocket(recvfrom);
1214 swrap_bind_symbol_libsocket(recvmsg);
1215 swrap_bind_symbol_libsocket(send);
1216 swrap_bind_symbol_libsocket(sendmsg);
1217 swrap_bind_symbol_libsocket(sendto);
1218 swrap_bind_symbol_libsocket(setsockopt);
1219 #ifdef HAVE_SIGNALFD
1220 swrap_bind_symbol_libsocket(signalfd);
1222 swrap_bind_symbol_libsocket(socket);
1223 swrap_bind_symbol_libsocket(socketpair);
1224 #ifdef HAVE_TIMERFD_CREATE
1225 swrap_bind_symbol_libc(timerfd_create);
1227 swrap_bind_symbol_libc(write);
1228 swrap_bind_symbol_libsocket(writev);
1231 static void swrap_bind_symbol_all(void)
1233 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1235 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1238 /*********************************************************
1239 * SWRAP HELPER FUNCTIONS
1240 *********************************************************/
1243 * We return 127.0.0.0 (default) or 10.53.57.0.
1245 * This can be controlled by:
1246 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1248 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1250 static in_addr_t swrap_ipv4_net(void)
1252 static int initialized;
1253 static in_addr_t hv;
1254 const char *net_str = NULL;
1263 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1264 if (net_str == NULL) {
1265 net_str = "127.0.0.0";
1268 ret = inet_pton(AF_INET, net_str, &nv);
1270 SWRAP_LOG(SWRAP_LOG_ERROR,
1271 "INVALID IPv4 Network [%s]",
1276 hv = ntohl(nv.s_addr);
1286 SWRAP_LOG(SWRAP_LOG_ERROR,
1287 "INVALID IPv4 Network [%s][0x%x] should be "
1288 "127.0.0.0 or 10.53.57.0",
1289 net_str, (unsigned)hv);
1297 * This returns 127.255.255.255 or 10.255.255.255
1299 static in_addr_t swrap_ipv4_bcast(void)
1303 hv = swrap_ipv4_net();
1304 hv |= IN_CLASSA_HOST;
1310 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1312 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1316 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1317 SWRAP_LOG(SWRAP_LOG_ERROR,
1318 "swrap_ipv4_iface(%u) invalid!",
1324 hv = swrap_ipv4_net();
1334 static const struct in6_addr *swrap_ipv6(void)
1336 static struct in6_addr v;
1337 static int initialized;
1345 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1354 static void set_port(int family, int prt, struct swrap_address *addr)
1358 addr->sa.in.sin_port = htons(prt);
1362 addr->sa.in6.sin6_port = htons(prt);
1368 static size_t socket_length(int family)
1372 return sizeof(struct sockaddr_in);
1375 return sizeof(struct sockaddr_in6);
1381 static struct socket_info *swrap_get_socket_info(int si_index)
1383 return (struct socket_info *)(&(sockets[si_index].info));
1386 static int swrap_get_refcount(struct socket_info *si)
1388 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1389 return sic->meta.refcount;
1392 static void swrap_inc_refcount(struct socket_info *si)
1394 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1396 sic->meta.refcount += 1;
1399 static void swrap_dec_refcount(struct socket_info *si)
1401 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1403 sic->meta.refcount -= 1;
1406 static int swrap_get_next_free(struct socket_info *si)
1408 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1410 return sic->meta.next_free;
1413 static void swrap_set_next_free(struct socket_info *si, int next_free)
1415 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1417 sic->meta.next_free = next_free;
1420 static int swrap_un_path(struct sockaddr_un *un,
1421 const char *swrap_dir,
1428 ret = snprintf(un->sun_path,
1429 sizeof(un->sun_path),
1435 if ((size_t)ret >= sizeof(un->sun_path)) {
1436 return ENAMETOOLONG;
1442 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1443 const char *swrap_dir)
1447 ret = snprintf(un->sun_path,
1448 sizeof(un->sun_path),
1452 if ((size_t)ret >= sizeof(un->sun_path)) {
1453 return ENAMETOOLONG;
1459 static bool swrap_dir_usable(const char *swrap_dir)
1461 struct sockaddr_un un;
1464 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1469 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1477 static char *socket_wrapper_dir(void)
1479 char *swrap_dir = NULL;
1480 char *s = getenv("SOCKET_WRAPPER_DIR");
1484 if (s == NULL || s[0] == '\0') {
1485 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1489 swrap_dir = realpath(s, NULL);
1490 if (swrap_dir == NULL) {
1491 SWRAP_LOG(SWRAP_LOG_ERROR,
1492 "Unable to resolve socket_wrapper dir path: %s - %s",
1498 ok = swrap_dir_usable(swrap_dir);
1505 ok = swrap_dir_usable(s);
1507 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1511 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1513 SWRAP_LOG(SWRAP_LOG_ERROR,
1514 "realpath(SOCKET_WRAPPER_DIR) too long and "
1515 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1520 swrap_dir = strdup(s);
1521 if (swrap_dir == NULL) {
1522 SWRAP_LOG(SWRAP_LOG_ERROR,
1523 "Unable to duplicate socket_wrapper dir path");
1527 SWRAP_LOG(SWRAP_LOG_WARN,
1528 "realpath(SOCKET_WRAPPER_DIR) too long, "
1529 "using original SOCKET_WRAPPER_DIR\n");
1532 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1536 static unsigned int socket_wrapper_mtu(void)
1538 static unsigned int max_mtu = 0;
1543 swrap_mutex_lock(&mtu_update_mutex);
1549 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1551 s = getenv("SOCKET_WRAPPER_MTU");
1556 tmp = strtol(s, &endp, 10);
1561 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1567 swrap_mutex_unlock(&mtu_update_mutex);
1571 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1573 pthread_mutexattr_t ma;
1574 bool need_destroy = false;
1577 #define __CHECK(cmd) do { \
1580 SWRAP_LOG(SWRAP_LOG_ERROR, \
1581 "%s: %s - failed %d", \
1587 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1588 __CHECK(pthread_mutexattr_init(&ma));
1589 need_destroy = true;
1590 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1591 __CHECK(pthread_mutex_init(m, &ma));
1594 pthread_mutexattr_destroy(&ma);
1599 static size_t socket_wrapper_max_sockets(void)
1605 if (socket_info_max != 0) {
1606 return socket_info_max;
1609 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1611 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1612 if (s == NULL || s[0] == '\0') {
1616 tmp = strtoul(s, &endp, 10);
1621 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1622 SWRAP_LOG(SWRAP_LOG_ERROR,
1623 "Invalid number of sockets specified, "
1624 "using default (%zu)",
1628 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1629 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1630 SWRAP_LOG(SWRAP_LOG_ERROR,
1631 "Invalid number of sockets specified, "
1632 "using maximum (%zu).",
1636 socket_info_max = tmp;
1639 return socket_info_max;
1642 static void socket_wrapper_init_fds_idx(void)
1647 if (socket_fds_idx != NULL) {
1651 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1653 SWRAP_LOG(SWRAP_LOG_ERROR,
1654 "Failed to allocate socket fds index array: %s",
1659 for (i = 0; i < socket_fds_max; i++) {
1663 socket_fds_idx = tmp;
1666 static void socket_wrapper_init_sockets(void)
1672 swrap_bind_symbol_all();
1674 swrap_mutex_lock(&sockets_mutex);
1676 if (sockets != NULL) {
1677 swrap_mutex_unlock(&sockets_mutex);
1681 SWRAP_LOG(SWRAP_LOG_DEBUG,
1682 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1683 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1686 * Intialize the static cache early before
1687 * any thread is able to start.
1689 (void)swrap_ipv4_net();
1691 socket_wrapper_init_fds_idx();
1693 /* Needs to be called inside the sockets_mutex lock here. */
1694 max_sockets = socket_wrapper_max_sockets();
1696 sockets = (struct socket_info_container *)calloc(max_sockets,
1697 sizeof(struct socket_info_container));
1699 if (sockets == NULL) {
1700 SWRAP_LOG(SWRAP_LOG_ERROR,
1701 "Failed to allocate sockets array: %s",
1703 swrap_mutex_unlock(&sockets_mutex);
1707 swrap_mutex_lock(&first_free_mutex);
1711 for (i = 0; i < max_sockets; i++) {
1712 swrap_set_next_free(&sockets[i].info, i+1);
1713 sockets[i].meta.mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1716 for (i = 0; i < max_sockets; i++) {
1717 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1719 SWRAP_LOG(SWRAP_LOG_ERROR,
1720 "Failed to initialize pthread mutex i=%zu", i);
1725 /* mark the end of the free list */
1726 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1729 swrap_mutex_unlock(&first_free_mutex);
1730 swrap_mutex_unlock(&sockets_mutex);
1736 bool socket_wrapper_enabled(void)
1738 char *s = socket_wrapper_dir();
1746 socket_wrapper_init_sockets();
1751 static unsigned int socket_wrapper_default_iface(void)
1753 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1756 if (sscanf(s, "%u", &iface) == 1) {
1757 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1763 return 1;/* 127.0.0.1 */
1766 static void set_socket_info_index(int fd, int idx)
1768 SWRAP_LOG(SWRAP_LOG_TRACE,
1771 socket_fds_idx[fd] = idx;
1772 /* This builtin issues a full memory barrier. */
1773 __sync_synchronize();
1776 static void reset_socket_info_index(int fd)
1778 SWRAP_LOG(SWRAP_LOG_TRACE,
1781 set_socket_info_index(fd, -1);
1784 static int find_socket_info_index(int fd)
1790 if (socket_fds_idx == NULL) {
1794 if ((size_t)fd >= socket_fds_max) {
1796 * Do not add a log here as some applications do stupid things
1799 * for (fd = 0; fd <= getdtablesize(); fd++) {
1803 * This would produce millions of lines of debug messages.
1806 SWRAP_LOG(SWRAP_LOG_ERROR,
1807 "Looking for a socket info for the fd %d is over the "
1808 "max socket index limit of %zu.",
1815 /* This builtin issues a full memory barrier. */
1816 __sync_synchronize();
1817 return socket_fds_idx[fd];
1820 static int swrap_add_socket_info(const struct socket_info *si_input)
1822 struct socket_info *si = NULL;
1825 if (si_input == NULL) {
1830 swrap_mutex_lock(&first_free_mutex);
1831 if (first_free == -1) {
1836 si_index = first_free;
1837 si = swrap_get_socket_info(si_index);
1841 first_free = swrap_get_next_free(si);
1843 swrap_inc_refcount(si);
1845 SWRAP_UNLOCK_SI(si);
1848 swrap_mutex_unlock(&first_free_mutex);
1853 static int swrap_create_socket(struct socket_info *si, int fd)
1857 if ((size_t)fd >= socket_fds_max) {
1858 SWRAP_LOG(SWRAP_LOG_ERROR,
1859 "The max socket index limit of %zu has been reached, "
1867 idx = swrap_add_socket_info(si);
1872 set_socket_info_index(fd, idx);
1877 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1884 p = strrchr(un->sun_path, '/');
1885 if (p) p++; else p = un->sun_path;
1887 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1888 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1894 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1895 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1902 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1908 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1912 case SOCKET_TYPE_CHAR_TCP:
1913 case SOCKET_TYPE_CHAR_UDP: {
1914 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1916 if ((*len) < sizeof(*in2)) {
1917 SWRAP_LOG(SWRAP_LOG_ERROR,
1918 "V4: *len(%zu) < sizeof(*in2)=%zu",
1919 (size_t)*len, sizeof(*in2));
1924 memset(in2, 0, sizeof(*in2));
1925 in2->sin_family = AF_INET;
1926 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1927 in2->sin_port = htons(prt);
1929 *len = sizeof(*in2);
1933 case SOCKET_TYPE_CHAR_TCP_V6:
1934 case SOCKET_TYPE_CHAR_UDP_V6: {
1935 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1937 if ((*len) < sizeof(*in2)) {
1938 SWRAP_LOG(SWRAP_LOG_ERROR,
1939 "V6: *len(%zu) < sizeof(*in2)=%zu",
1940 (size_t)*len, sizeof(*in2));
1941 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1946 memset(in2, 0, sizeof(*in2));
1947 in2->sin6_family = AF_INET6;
1948 in2->sin6_addr = *swrap_ipv6();
1949 in2->sin6_addr.s6_addr[15] = iface;
1950 in2->sin6_port = htons(prt);
1952 *len = sizeof(*in2);
1957 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1966 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1973 char *swrap_dir = NULL;
1975 if (bcast) *bcast = 0;
1977 switch (inaddr->sa_family) {
1979 const struct sockaddr_in *in =
1980 (const struct sockaddr_in *)(const void *)inaddr;
1981 unsigned int addr = ntohl(in->sin_addr.s_addr);
1985 const unsigned int sw_net_addr = swrap_ipv4_net();
1986 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1990 u_type = SOCKET_TYPE_CHAR_TCP;
1993 u_type = SOCKET_TYPE_CHAR_UDP;
1994 a_type = SOCKET_TYPE_CHAR_UDP;
1995 b_type = SOCKET_TYPE_CHAR_UDP;
1998 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1999 errno = ESOCKTNOSUPPORT;
2003 prt = ntohs(in->sin_port);
2004 if (a_type && addr == 0xFFFFFFFF) {
2005 /* 255.255.255.255 only udp */
2008 iface = socket_wrapper_default_iface();
2009 } else if (b_type && addr == sw_bcast_addr) {
2018 iface = socket_wrapper_default_iface();
2019 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2020 /* 127.0.0.X or 10.53.57.X */
2023 iface = (addr & 0x000000FF);
2025 errno = ENETUNREACH;
2028 if (bcast) *bcast = is_bcast;
2033 const struct sockaddr_in6 *in =
2034 (const struct sockaddr_in6 *)(const void *)inaddr;
2035 struct in6_addr cmp1, cmp2;
2039 type = SOCKET_TYPE_CHAR_TCP_V6;
2042 type = SOCKET_TYPE_CHAR_UDP_V6;
2045 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2046 errno = ESOCKTNOSUPPORT;
2050 /* XXX no multicast/broadcast */
2052 prt = ntohs(in->sin6_port);
2054 cmp1 = *swrap_ipv6();
2055 cmp2 = in->sin6_addr;
2056 cmp2.s6_addr[15] = 0;
2057 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2058 iface = in->sin6_addr.s6_addr[15];
2060 errno = ENETUNREACH;
2068 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2069 errno = ENETUNREACH;
2074 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2079 swrap_dir = socket_wrapper_dir();
2080 if (swrap_dir == NULL) {
2086 swrap_un_path_EINVAL(un, swrap_dir);
2087 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2088 SAFE_FREE(swrap_dir);
2089 /* the caller need to do more processing */
2093 swrap_un_path(un, swrap_dir, type, iface, prt);
2094 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2096 SAFE_FREE(swrap_dir);
2101 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2109 char *swrap_dir = NULL;
2111 if (bcast) *bcast = 0;
2113 switch (si->family) {
2115 const struct sockaddr_in *in =
2116 (const struct sockaddr_in *)(const void *)inaddr;
2117 unsigned int addr = ntohl(in->sin_addr.s_addr);
2122 const unsigned int sw_net_addr = swrap_ipv4_net();
2123 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2125 prt = ntohs(in->sin_port);
2129 u_type = SOCKET_TYPE_CHAR_TCP;
2130 d_type = SOCKET_TYPE_CHAR_TCP;
2133 u_type = SOCKET_TYPE_CHAR_UDP;
2134 d_type = SOCKET_TYPE_CHAR_UDP;
2135 a_type = SOCKET_TYPE_CHAR_UDP;
2136 b_type = SOCKET_TYPE_CHAR_UDP;
2139 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2140 errno = ESOCKTNOSUPPORT;
2148 iface = socket_wrapper_default_iface();
2149 } else if (a_type && addr == 0xFFFFFFFF) {
2150 /* 255.255.255.255 only udp */
2153 iface = socket_wrapper_default_iface();
2154 } else if (b_type && addr == sw_bcast_addr) {
2155 /* 127.255.255.255 only udp */
2158 iface = socket_wrapper_default_iface();
2159 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2163 iface = (addr & 0x000000FF);
2165 errno = EADDRNOTAVAIL;
2169 /* Store the bind address for connect() */
2170 if (si->bindname.sa_socklen == 0) {
2171 struct sockaddr_in bind_in;
2172 socklen_t blen = sizeof(struct sockaddr_in);
2174 ZERO_STRUCT(bind_in);
2175 bind_in.sin_family = in->sin_family;
2176 bind_in.sin_port = in->sin_port;
2177 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2178 si->bindname.sa_socklen = blen;
2179 memcpy(&si->bindname.sa.in, &bind_in, blen);
2186 const struct sockaddr_in6 *in =
2187 (const struct sockaddr_in6 *)(const void *)inaddr;
2188 struct in6_addr cmp1, cmp2;
2192 type = SOCKET_TYPE_CHAR_TCP_V6;
2195 type = SOCKET_TYPE_CHAR_UDP_V6;
2198 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2199 errno = ESOCKTNOSUPPORT;
2203 /* XXX no multicast/broadcast */
2205 prt = ntohs(in->sin6_port);
2207 cmp1 = *swrap_ipv6();
2208 cmp2 = in->sin6_addr;
2209 cmp2.s6_addr[15] = 0;
2210 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2211 iface = socket_wrapper_default_iface();
2212 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2213 iface = in->sin6_addr.s6_addr[15];
2215 errno = EADDRNOTAVAIL;
2219 /* Store the bind address for connect() */
2220 if (si->bindname.sa_socklen == 0) {
2221 struct sockaddr_in6 bind_in;
2222 socklen_t blen = sizeof(struct sockaddr_in6);
2224 ZERO_STRUCT(bind_in);
2225 bind_in.sin6_family = in->sin6_family;
2226 bind_in.sin6_port = in->sin6_port;
2228 bind_in.sin6_addr = *swrap_ipv6();
2229 bind_in.sin6_addr.s6_addr[15] = iface;
2231 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2232 si->bindname.sa_socklen = blen;
2239 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2240 errno = EADDRNOTAVAIL;
2245 if (bcast) *bcast = is_bcast;
2247 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2252 swrap_dir = socket_wrapper_dir();
2253 if (swrap_dir == NULL) {
2259 /* handle auto-allocation of ephemeral ports */
2260 for (prt = 5001; prt < 10000; prt++) {
2261 swrap_un_path(un, swrap_dir, type, iface, prt);
2262 if (stat(un->sun_path, &st) == 0) continue;
2264 set_port(si->family, prt, &si->myname);
2265 set_port(si->family, prt, &si->bindname);
2272 SAFE_FREE(swrap_dir);
2277 swrap_un_path(un, swrap_dir, type, iface, prt);
2278 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2280 SAFE_FREE(swrap_dir);
2285 static struct socket_info *find_socket_info(int fd)
2287 int idx = find_socket_info_index(fd);
2293 return swrap_get_socket_info(idx);
2297 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2299 struct socket_info_fd *f;
2300 const struct socket_info *last_s = NULL;
2302 /* first catch invalid input */
2303 switch (sa->sa_family) {
2305 if (len < sizeof(struct sockaddr_in)) {
2311 if (len < sizeof(struct sockaddr_in6)) {
2321 for (f = socket_fds; f; f = f->next) {
2322 struct socket_info *s = swrap_get_socket_info(f->si_index);
2329 if (s->myname == NULL) {
2332 if (s->myname->sa_family != sa->sa_family) {
2335 switch (s->myname->sa_family) {
2337 struct sockaddr_in *sin1, *sin2;
2339 sin1 = (struct sockaddr_in *)s->myname;
2340 sin2 = (struct sockaddr_in *)sa;
2342 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2345 if (sin1->sin_port != sin2->sin_port) {
2348 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2358 struct sockaddr_in6 *sin1, *sin2;
2360 sin1 = (struct sockaddr_in6 *)s->myname;
2361 sin2 = (struct sockaddr_in6 *)sa;
2363 if (sin1->sin6_port != sin2->sin6_port) {
2366 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2388 static void swrap_remove_stale(int fd)
2390 struct socket_info *si;
2393 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2395 swrap_mutex_lock(&socket_reset_mutex);
2397 si_index = find_socket_info_index(fd);
2398 if (si_index == -1) {
2399 swrap_mutex_unlock(&socket_reset_mutex);
2403 reset_socket_info_index(fd);
2405 si = swrap_get_socket_info(si_index);
2407 swrap_mutex_lock(&first_free_mutex);
2410 swrap_dec_refcount(si);
2412 if (swrap_get_refcount(si) > 0) {
2416 if (si->un_addr.sun_path[0] != '\0') {
2417 unlink(si->un_addr.sun_path);
2420 swrap_set_next_free(si, first_free);
2421 first_free = si_index;
2424 SWRAP_UNLOCK_SI(si);
2425 swrap_mutex_unlock(&first_free_mutex);
2426 swrap_mutex_unlock(&socket_reset_mutex);
2429 static int sockaddr_convert_to_un(struct socket_info *si,
2430 const struct sockaddr *in_addr,
2432 struct sockaddr_un *out_addr,
2436 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2438 (void) in_len; /* unused */
2440 if (out_addr == NULL) {
2444 out->sa_family = AF_UNIX;
2445 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2446 out->sa_len = sizeof(*out_addr);
2449 switch (in_addr->sa_family) {
2451 const struct sockaddr_in *sin;
2452 if (si->family != AF_INET) {
2455 if (in_len < sizeof(struct sockaddr_in)) {
2458 sin = (const struct sockaddr_in *)(const void *)in_addr;
2459 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2464 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2465 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2479 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2480 errno = ESOCKTNOSUPPORT;
2484 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2486 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2492 errno = EAFNOSUPPORT;
2493 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2497 static int sockaddr_convert_from_un(const struct socket_info *si,
2498 const struct sockaddr_un *in_addr,
2499 socklen_t un_addrlen,
2501 struct sockaddr *out_addr,
2502 socklen_t *out_addrlen)
2506 if (out_addr == NULL || out_addrlen == NULL)
2509 if (un_addrlen == 0) {
2524 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2525 errno = ESOCKTNOSUPPORT;
2528 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2529 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2530 out_addr->sa_len = *out_addrlen;
2537 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2538 errno = EAFNOSUPPORT;
2542 enum swrap_packet_type {
2544 SWRAP_CONNECT_UNREACH,
2552 SWRAP_SENDTO_UNREACH,
2563 struct swrap_file_hdr {
2565 uint16_t version_major;
2566 uint16_t version_minor;
2569 uint32_t frame_max_len;
2570 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2573 #define SWRAP_FILE_HDR_SIZE 24
2575 struct swrap_packet_frame {
2577 uint32_t micro_seconds;
2578 uint32_t recorded_length;
2579 uint32_t full_length;
2581 #define SWRAP_PACKET_FRAME_SIZE 16
2583 union swrap_packet_ip {
2587 uint16_t packet_length;
2588 uint16_t identification;
2593 uint16_t hdr_checksum;
2597 #define SWRAP_PACKET_IP_V4_SIZE 20
2600 uint8_t flow_label_high;
2601 uint16_t flow_label_low;
2602 uint16_t payload_length;
2603 uint8_t next_header;
2605 uint8_t src_addr[16];
2606 uint8_t dest_addr[16];
2608 #define SWRAP_PACKET_IP_V6_SIZE 40
2610 #define SWRAP_PACKET_IP_SIZE 40
2612 union swrap_packet_payload {
2614 uint16_t source_port;
2624 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2626 uint16_t source_port;
2631 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2638 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2645 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2647 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2649 #define SWRAP_PACKET_MIN_ALLOC \
2650 (SWRAP_PACKET_FRAME_SIZE + \
2651 SWRAP_PACKET_IP_SIZE + \
2652 SWRAP_PACKET_PAYLOAD_SIZE)
2654 static const char *swrap_pcap_init_file(void)
2656 static int initialized = 0;
2657 static const char *s = NULL;
2658 static const struct swrap_file_hdr h;
2659 static const struct swrap_packet_frame f;
2660 static const union swrap_packet_ip i;
2661 static const union swrap_packet_payload p;
2663 if (initialized == 1) {
2669 * TODO: don't use the structs use plain buffer offsets
2670 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2672 * for now make sure we disable PCAP support
2673 * if the struct has alignment!
2675 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2678 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2681 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2684 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2687 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2690 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2693 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2696 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2699 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2702 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2706 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2710 if (strncmp(s, "./", 2) == 0) {
2713 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2717 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2718 const struct sockaddr *src,
2719 const struct sockaddr *dest,
2721 const uint8_t *payload,
2723 unsigned long tcp_seqno,
2724 unsigned long tcp_ack,
2725 unsigned char tcp_ctl,
2727 size_t *_packet_len)
2729 uint8_t *base = NULL;
2730 uint8_t *buf = NULL;
2733 struct swrap_packet_frame *frame;
2737 union swrap_packet_ip *ip;
2739 union swrap_packet_payload *pay;
2742 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2743 size_t wire_hdr_len = 0;
2744 size_t wire_len = 0;
2745 size_t ip_hdr_len = 0;
2746 size_t icmp_hdr_len = 0;
2747 size_t icmp_truncate_len = 0;
2748 uint8_t protocol = 0, icmp_protocol = 0;
2749 const struct sockaddr_in *src_in = NULL;
2750 const struct sockaddr_in *dest_in = NULL;
2752 const struct sockaddr_in6 *src_in6 = NULL;
2753 const struct sockaddr_in6 *dest_in6 = NULL;
2758 switch (src->sa_family) {
2760 src_in = (const struct sockaddr_in *)(const void *)src;
2761 dest_in = (const struct sockaddr_in *)(const void *)dest;
2762 src_port = src_in->sin_port;
2763 dest_port = dest_in->sin_port;
2764 ip_hdr_len = sizeof(i.ip->v4);
2768 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2769 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2770 src_port = src_in6->sin6_port;
2771 dest_port = dest_in6->sin6_port;
2772 ip_hdr_len = sizeof(i.ip->v6);
2779 switch (socket_type) {
2781 protocol = 0x06; /* TCP */
2782 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2783 wire_len = wire_hdr_len + payload_len;
2787 protocol = 0x11; /* UDP */
2788 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2789 wire_len = wire_hdr_len + payload_len;
2797 icmp_protocol = protocol;
2798 switch (src->sa_family) {
2800 protocol = 0x01; /* ICMPv4 */
2801 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2805 protocol = 0x3A; /* ICMPv6 */
2806 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2810 if (wire_len > 64 ) {
2811 icmp_truncate_len = wire_len - 64;
2813 wire_len += icmp_hdr_len;
2816 packet_len = nonwire_len + wire_len;
2817 alloc_len = packet_len;
2818 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2819 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2822 base = (uint8_t *)calloc(1, alloc_len);
2830 f.frame->seconds = tval->tv_sec;
2831 f.frame->micro_seconds = tval->tv_usec;
2832 f.frame->recorded_length = wire_len - icmp_truncate_len;
2833 f.frame->full_length = wire_len - icmp_truncate_len;
2835 buf += SWRAP_PACKET_FRAME_SIZE;
2838 switch (src->sa_family) {
2840 if (src_in == NULL || dest_in == NULL) {
2845 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2846 i.ip->v4.tos = 0x00;
2847 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2848 i.ip->v4.identification = htons(0xFFFF);
2849 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2850 i.ip->v4.fragment = htons(0x0000);
2851 i.ip->v4.ttl = 0xFF;
2852 i.ip->v4.protocol = protocol;
2853 i.ip->v4.hdr_checksum = htons(0x0000);
2854 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2855 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2856 buf += SWRAP_PACKET_IP_V4_SIZE;
2860 if (src_in6 == NULL || dest_in6 == NULL) {
2865 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2866 i.ip->v6.flow_label_high = 0x00;
2867 i.ip->v6.flow_label_low = 0x0000;
2868 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2869 i.ip->v6.next_header = protocol;
2870 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2871 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2872 buf += SWRAP_PACKET_IP_V6_SIZE;
2878 pay = (union swrap_packet_payload *)(void *)buf;
2879 switch (src->sa_family) {
2881 pay->icmp4.type = 0x03; /* destination unreachable */
2882 pay->icmp4.code = 0x01; /* host unreachable */
2883 pay->icmp4.checksum = htons(0x0000);
2884 pay->icmp4.unused = htonl(0x00000000);
2886 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2888 /* set the ip header in the ICMP payload */
2890 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2891 i.ip->v4.tos = 0x00;
2892 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2893 i.ip->v4.identification = htons(0xFFFF);
2894 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2895 i.ip->v4.fragment = htons(0x0000);
2896 i.ip->v4.ttl = 0xFF;
2897 i.ip->v4.protocol = icmp_protocol;
2898 i.ip->v4.hdr_checksum = htons(0x0000);
2899 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2900 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2902 buf += SWRAP_PACKET_IP_V4_SIZE;
2904 src_port = dest_in->sin_port;
2905 dest_port = src_in->sin_port;
2909 pay->icmp6.type = 0x01; /* destination unreachable */
2910 pay->icmp6.code = 0x03; /* address unreachable */
2911 pay->icmp6.checksum = htons(0x0000);
2912 pay->icmp6.unused = htonl(0x00000000);
2913 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2915 /* set the ip header in the ICMP payload */
2917 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2918 i.ip->v6.flow_label_high = 0x00;
2919 i.ip->v6.flow_label_low = 0x0000;
2920 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2921 i.ip->v6.next_header = protocol;
2922 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2923 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2925 buf += SWRAP_PACKET_IP_V6_SIZE;
2927 src_port = dest_in6->sin6_port;
2928 dest_port = src_in6->sin6_port;
2934 pay = (union swrap_packet_payload *)(void *)buf;
2936 switch (socket_type) {
2938 pay->tcp.source_port = src_port;
2939 pay->tcp.dest_port = dest_port;
2940 pay->tcp.seq_num = htonl(tcp_seqno);
2941 pay->tcp.ack_num = htonl(tcp_ack);
2942 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2943 pay->tcp.control = tcp_ctl;
2944 pay->tcp.window = htons(0x7FFF);
2945 pay->tcp.checksum = htons(0x0000);
2946 pay->tcp.urg = htons(0x0000);
2947 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2952 pay->udp.source_port = src_port;
2953 pay->udp.dest_port = dest_port;
2954 pay->udp.length = htons(8 + payload_len);
2955 pay->udp.checksum = htons(0x0000);
2956 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2961 if (payload && payload_len > 0) {
2962 memcpy(buf, payload, payload_len);
2965 *_packet_len = packet_len - icmp_truncate_len;
2969 static int swrap_pcap_get_fd(const char *fname)
2977 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2979 struct swrap_file_hdr file_hdr;
2980 file_hdr.magic = 0xA1B2C3D4;
2981 file_hdr.version_major = 0x0002;
2982 file_hdr.version_minor = 0x0004;
2983 file_hdr.timezone = 0x00000000;
2984 file_hdr.sigfigs = 0x00000000;
2985 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2986 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2988 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2995 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3000 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3001 const struct sockaddr *addr,
3002 enum swrap_packet_type type,
3003 const void *buf, size_t len,
3006 const struct sockaddr *src_addr;
3007 const struct sockaddr *dest_addr;
3008 unsigned long tcp_seqno = 0;
3009 unsigned long tcp_ack = 0;
3010 unsigned char tcp_ctl = 0;
3011 int unreachable = 0;
3015 switch (si->family) {
3027 case SWRAP_CONNECT_SEND:
3028 if (si->type != SOCK_STREAM) {
3032 src_addr = &si->myname.sa.s;
3035 tcp_seqno = si->io.pck_snd;
3036 tcp_ack = si->io.pck_rcv;
3037 tcp_ctl = 0x02; /* SYN */
3039 si->io.pck_snd += 1;
3043 case SWRAP_CONNECT_RECV:
3044 if (si->type != SOCK_STREAM) {
3048 dest_addr = &si->myname.sa.s;
3051 tcp_seqno = si->io.pck_rcv;
3052 tcp_ack = si->io.pck_snd;
3053 tcp_ctl = 0x12; /** SYN,ACK */
3055 si->io.pck_rcv += 1;
3059 case SWRAP_CONNECT_UNREACH:
3060 if (si->type != SOCK_STREAM) {
3064 dest_addr = &si->myname.sa.s;
3067 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3068 tcp_seqno = si->io.pck_snd - 1;
3069 tcp_ack = si->io.pck_rcv;
3070 tcp_ctl = 0x02; /* SYN */
3075 case SWRAP_CONNECT_ACK:
3076 if (si->type != SOCK_STREAM) {
3080 src_addr = &si->myname.sa.s;
3083 tcp_seqno = si->io.pck_snd;
3084 tcp_ack = si->io.pck_rcv;
3085 tcp_ctl = 0x10; /* ACK */
3089 case SWRAP_ACCEPT_SEND:
3090 if (si->type != SOCK_STREAM) {
3094 dest_addr = &si->myname.sa.s;
3097 tcp_seqno = si->io.pck_rcv;
3098 tcp_ack = si->io.pck_snd;
3099 tcp_ctl = 0x02; /* SYN */
3101 si->io.pck_rcv += 1;
3105 case SWRAP_ACCEPT_RECV:
3106 if (si->type != SOCK_STREAM) {
3110 src_addr = &si->myname.sa.s;
3113 tcp_seqno = si->io.pck_snd;
3114 tcp_ack = si->io.pck_rcv;
3115 tcp_ctl = 0x12; /* SYN,ACK */
3117 si->io.pck_snd += 1;
3121 case SWRAP_ACCEPT_ACK:
3122 if (si->type != SOCK_STREAM) {
3126 dest_addr = &si->myname.sa.s;
3129 tcp_seqno = si->io.pck_rcv;
3130 tcp_ack = si->io.pck_snd;
3131 tcp_ctl = 0x10; /* ACK */
3136 src_addr = &si->myname.sa.s;
3137 dest_addr = &si->peername.sa.s;
3139 tcp_seqno = si->io.pck_snd;
3140 tcp_ack = si->io.pck_rcv;
3141 tcp_ctl = 0x18; /* PSH,ACK */
3143 si->io.pck_snd += len;
3147 case SWRAP_SEND_RST:
3148 dest_addr = &si->myname.sa.s;
3149 src_addr = &si->peername.sa.s;
3151 if (si->type == SOCK_DGRAM) {
3152 return swrap_pcap_marshall_packet(si,
3154 SWRAP_SENDTO_UNREACH,
3160 tcp_seqno = si->io.pck_rcv;
3161 tcp_ack = si->io.pck_snd;
3162 tcp_ctl = 0x14; /** RST,ACK */
3166 case SWRAP_PENDING_RST:
3167 dest_addr = &si->myname.sa.s;
3168 src_addr = &si->peername.sa.s;
3170 if (si->type == SOCK_DGRAM) {
3174 tcp_seqno = si->io.pck_rcv;
3175 tcp_ack = si->io.pck_snd;
3176 tcp_ctl = 0x14; /* RST,ACK */
3181 dest_addr = &si->myname.sa.s;
3182 src_addr = &si->peername.sa.s;
3184 tcp_seqno = si->io.pck_rcv;
3185 tcp_ack = si->io.pck_snd;
3186 tcp_ctl = 0x18; /* PSH,ACK */
3188 si->io.pck_rcv += len;
3192 case SWRAP_RECV_RST:
3193 dest_addr = &si->myname.sa.s;
3194 src_addr = &si->peername.sa.s;
3196 if (si->type == SOCK_DGRAM) {
3200 tcp_seqno = si->io.pck_rcv;
3201 tcp_ack = si->io.pck_snd;
3202 tcp_ctl = 0x14; /* RST,ACK */
3207 src_addr = &si->myname.sa.s;
3210 si->io.pck_snd += len;
3214 case SWRAP_SENDTO_UNREACH:
3215 dest_addr = &si->myname.sa.s;
3222 case SWRAP_RECVFROM:
3223 dest_addr = &si->myname.sa.s;
3226 si->io.pck_rcv += len;
3230 case SWRAP_CLOSE_SEND:
3231 if (si->type != SOCK_STREAM) {
3235 src_addr = &si->myname.sa.s;
3236 dest_addr = &si->peername.sa.s;
3238 tcp_seqno = si->io.pck_snd;
3239 tcp_ack = si->io.pck_rcv;
3240 tcp_ctl = 0x11; /* FIN, ACK */
3242 si->io.pck_snd += 1;
3246 case SWRAP_CLOSE_RECV:
3247 if (si->type != SOCK_STREAM) {
3251 dest_addr = &si->myname.sa.s;
3252 src_addr = &si->peername.sa.s;
3254 tcp_seqno = si->io.pck_rcv;
3255 tcp_ack = si->io.pck_snd;
3256 tcp_ctl = 0x11; /* FIN,ACK */
3258 si->io.pck_rcv += 1;
3262 case SWRAP_CLOSE_ACK:
3263 if (si->type != SOCK_STREAM) {
3267 src_addr = &si->myname.sa.s;
3268 dest_addr = &si->peername.sa.s;
3270 tcp_seqno = si->io.pck_snd;
3271 tcp_ack = si->io.pck_rcv;
3272 tcp_ctl = 0x10; /* ACK */
3279 swrapGetTimeOfDay(&tv);
3281 return swrap_pcap_packet_init(&tv,
3285 (const uint8_t *)buf,
3294 static void swrap_pcap_dump_packet(struct socket_info *si,
3295 const struct sockaddr *addr,
3296 enum swrap_packet_type type,
3297 const void *buf, size_t len)
3299 const char *file_name;
3301 size_t packet_len = 0;
3304 swrap_mutex_lock(&pcap_dump_mutex);
3306 file_name = swrap_pcap_init_file();
3311 packet = swrap_pcap_marshall_packet(si,
3317 if (packet == NULL) {
3321 fd = swrap_pcap_get_fd(file_name);
3323 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3332 swrap_mutex_unlock(&pcap_dump_mutex);
3335 /****************************************************************************
3337 ***************************************************************************/
3339 #ifdef HAVE_SIGNALFD
3340 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3344 rc = libc_signalfd(fd, mask, flags);
3346 swrap_remove_stale(fd);
3352 int signalfd(int fd, const sigset_t *mask, int flags)
3354 return swrap_signalfd(fd, mask, flags);
3358 /****************************************************************************
3360 ***************************************************************************/
3362 static int swrap_socket(int family, int type, int protocol)
3364 struct socket_info *si = NULL;
3365 struct socket_info _si = { 0 };
3368 int real_type = type;
3371 * Remove possible addition flags passed to socket() so
3372 * do not fail checking the type.
3373 * See https://lwn.net/Articles/281965/
3376 real_type &= ~SOCK_CLOEXEC;
3378 #ifdef SOCK_NONBLOCK
3379 real_type &= ~SOCK_NONBLOCK;
3382 if (!socket_wrapper_enabled()) {
3383 return libc_socket(family, type, protocol);
3394 #endif /* AF_NETLINK */
3397 #endif /* AF_PACKET */
3399 fd = libc_socket(family, type, protocol);
3401 /* Check if we have a stale fd and remove it */
3402 swrap_remove_stale(fd);
3403 SWRAP_LOG(SWRAP_LOG_TRACE,
3404 "Unix socket fd=%d",
3409 errno = EAFNOSUPPORT;
3413 switch (real_type) {
3419 errno = EPROTONOSUPPORT;
3427 if (real_type == SOCK_STREAM) {
3432 if (real_type == SOCK_DGRAM) {
3437 errno = EPROTONOSUPPORT;
3442 * We must call libc_socket with type, from the caller, not the version
3443 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3445 fd = libc_socket(AF_UNIX, type, 0);
3451 /* Check if we have a stale fd and remove it */
3452 swrap_remove_stale(fd);
3455 si->family = family;
3457 /* however, the rest of the socket_wrapper code expects just
3458 * the type, not the flags */
3459 si->type = real_type;
3460 si->protocol = protocol;
3463 * Setup myname so getsockname() can succeed to find out the socket
3466 switch(si->family) {
3468 struct sockaddr_in sin = {
3469 .sin_family = AF_INET,
3472 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3473 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3478 struct sockaddr_in6 sin6 = {
3479 .sin6_family = AF_INET6,
3482 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3483 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3492 ret = swrap_create_socket(si, fd);
3494 int saved_errno = errno;
3496 errno = saved_errno;
3500 SWRAP_LOG(SWRAP_LOG_TRACE,
3501 "Created %s socket for protocol %s, fd=%d",
3502 family == AF_INET ? "IPv4" : "IPv6",
3503 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3509 int socket(int family, int type, int protocol)
3511 return swrap_socket(family, type, protocol);
3514 /****************************************************************************
3516 ***************************************************************************/
3518 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3522 rc = libc_socketpair(family, type, protocol, sv);
3524 swrap_remove_stale(sv[0]);
3525 swrap_remove_stale(sv[1]);
3531 int socketpair(int family, int type, int protocol, int sv[2])
3533 return swrap_socketpair(family, type, protocol, sv);
3536 /****************************************************************************
3538 ***************************************************************************/
3540 #ifdef HAVE_TIMERFD_CREATE
3541 static int swrap_timerfd_create(int clockid, int flags)
3545 fd = libc_timerfd_create(clockid, flags);
3547 swrap_remove_stale(fd);
3553 int timerfd_create(int clockid, int flags)
3555 return swrap_timerfd_create(clockid, flags);
3559 /****************************************************************************
3561 ***************************************************************************/
3563 static int swrap_pipe(int pipefd[2])
3567 rc = libc_pipe(pipefd);
3569 swrap_remove_stale(pipefd[0]);
3570 swrap_remove_stale(pipefd[1]);
3576 int pipe(int pipefd[2])
3578 return swrap_pipe(pipefd);
3581 /****************************************************************************
3583 ***************************************************************************/
3585 static int swrap_accept(int s,
3586 struct sockaddr *addr,
3590 struct socket_info *parent_si, *child_si;
3591 struct socket_info new_si = { 0 };
3594 struct swrap_address un_addr = {
3595 .sa_socklen = sizeof(struct sockaddr_un),
3597 struct swrap_address un_my_addr = {
3598 .sa_socklen = sizeof(struct sockaddr_un),
3600 struct swrap_address in_addr = {
3601 .sa_socklen = sizeof(struct sockaddr_storage),
3603 struct swrap_address in_my_addr = {
3604 .sa_socklen = sizeof(struct sockaddr_storage),
3608 parent_si = find_socket_info(s);
3611 return libc_accept4(s, addr, addrlen, flags);
3614 return libc_accept(s, addr, addrlen);
3620 * prevent parent_si from being altered / closed
3623 SWRAP_LOCK_SI(parent_si);
3626 * assume out sockaddr have the same size as the in parent
3629 in_addr.sa_socklen = socket_length(parent_si->family);
3630 if (in_addr.sa_socklen <= 0) {
3631 SWRAP_UNLOCK_SI(parent_si);
3636 SWRAP_UNLOCK_SI(parent_si);
3639 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3642 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3645 int saved_errno = errno;
3646 if (saved_errno == ENOTSOCK) {
3647 /* Remove stale fds */
3648 swrap_remove_stale(s);
3650 errno = saved_errno;
3656 /* Check if we have a stale fd and remove it */
3657 swrap_remove_stale(fd);
3659 ret = libc_getsockname(fd,
3661 &un_my_addr.sa_socklen);
3663 int saved_errno = errno;
3665 if (saved_errno == ENOTCONN) {
3667 * If the connection is already disconnected
3668 * we should return ECONNABORTED.
3670 saved_errno = ECONNABORTED;
3672 errno = saved_errno;
3676 SWRAP_LOCK_SI(parent_si);
3678 ret = sockaddr_convert_from_un(parent_si,
3683 &in_addr.sa_socklen);
3685 int saved_errno = errno;
3686 SWRAP_UNLOCK_SI(parent_si);
3688 errno = saved_errno;
3694 child_si->family = parent_si->family;
3695 child_si->type = parent_si->type;
3696 child_si->protocol = parent_si->protocol;
3697 child_si->bound = 1;
3698 child_si->is_server = 1;
3699 child_si->connected = 1;
3701 SWRAP_UNLOCK_SI(parent_si);
3703 child_si->peername = (struct swrap_address) {
3704 .sa_socklen = in_addr.sa_socklen,
3706 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3708 if (addr != NULL && addrlen != NULL) {
3709 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3711 memcpy(addr, &in_addr.sa.ss, copy_len);
3713 *addrlen = in_addr.sa_socklen;
3716 ret = sockaddr_convert_from_un(child_si,
3718 un_my_addr.sa_socklen,
3721 &in_my_addr.sa_socklen);
3723 int saved_errno = errno;
3725 errno = saved_errno;
3729 SWRAP_LOG(SWRAP_LOG_TRACE,
3730 "accept() path=%s, fd=%d",
3731 un_my_addr.sa.un.sun_path, s);
3733 child_si->myname = (struct swrap_address) {
3734 .sa_socklen = in_my_addr.sa_socklen,
3736 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3738 idx = swrap_create_socket(&new_si, fd);
3740 int saved_errno = errno;
3742 errno = saved_errno;
3747 struct socket_info *si = swrap_get_socket_info(idx);
3750 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3751 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3752 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3753 SWRAP_UNLOCK_SI(si);
3760 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3762 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3766 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3767 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3769 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3772 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3775 static int autobind_start_init;
3776 static int autobind_start;
3778 /* using sendto() or connect() on an unbound socket would give the
3779 recipient no way to reply, as unlike UDP and TCP, a unix domain
3780 socket can't auto-assign ephemeral port numbers, so we need to
3782 Note: this might change the family from ipv6 to ipv4
3784 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3786 struct swrap_address un_addr = {
3787 .sa_socklen = sizeof(struct sockaddr_un),
3794 char *swrap_dir = NULL;
3796 swrap_mutex_lock(&autobind_start_mutex);
3798 if (autobind_start_init != 1) {
3799 autobind_start_init = 1;
3800 autobind_start = getpid();
3801 autobind_start %= 50000;
3802 autobind_start += 10000;
3805 un_addr.sa.un.sun_family = AF_UNIX;
3809 struct sockaddr_in in;
3813 type = SOCKET_TYPE_CHAR_TCP;
3816 type = SOCKET_TYPE_CHAR_UDP;
3819 errno = ESOCKTNOSUPPORT;
3824 memset(&in, 0, sizeof(in));
3825 in.sin_family = AF_INET;
3826 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3827 socket_wrapper_default_iface()));
3829 si->myname = (struct swrap_address) {
3830 .sa_socklen = sizeof(in),
3832 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3837 struct sockaddr_in6 in6;
3839 if (si->family != family) {
3840 errno = ENETUNREACH;
3847 type = SOCKET_TYPE_CHAR_TCP_V6;
3850 type = SOCKET_TYPE_CHAR_UDP_V6;
3853 errno = ESOCKTNOSUPPORT;
3858 memset(&in6, 0, sizeof(in6));
3859 in6.sin6_family = AF_INET6;
3860 in6.sin6_addr = *swrap_ipv6();
3861 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3863 si->myname = (struct swrap_address) {
3864 .sa_socklen = sizeof(in6),
3866 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3871 errno = ESOCKTNOSUPPORT;
3876 if (autobind_start > 60000) {
3877 autobind_start = 10000;
3880 swrap_dir = socket_wrapper_dir();
3881 if (swrap_dir == NULL) {
3887 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3888 port = autobind_start + i;
3889 swrap_un_path(&un_addr.sa.un,
3892 socket_wrapper_default_iface(),
3894 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3896 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3901 si->un_addr = un_addr.sa.un;
3904 autobind_start = port + 1;
3907 if (i == SOCKET_MAX_SOCKETS) {
3908 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3909 "interface "SOCKET_FORMAT,
3912 socket_wrapper_default_iface(),
3919 si->family = family;
3920 set_port(si->family, port, &si->myname);
3925 SAFE_FREE(swrap_dir);
3926 swrap_mutex_unlock(&autobind_start_mutex);
3930 /****************************************************************************
3932 ***************************************************************************/
3934 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3938 struct swrap_address un_addr = {
3939 .sa_socklen = sizeof(struct sockaddr_un),
3941 struct socket_info *si = find_socket_info(s);
3945 return libc_connect(s, serv_addr, addrlen);
3950 if (si->bound == 0) {
3951 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3957 if (si->family != serv_addr->sa_family) {
3958 SWRAP_LOG(SWRAP_LOG_ERROR,
3959 "called for fd=%d (family=%d) called with invalid family=%d",
3960 s, si->family, serv_addr->sa_family);
3966 ret = sockaddr_convert_to_un(si, serv_addr,
3967 addrlen, &un_addr.sa.un, 0, &bcast);
3973 errno = ENETUNREACH;
3978 if (si->type == SOCK_DGRAM) {
3979 si->defer_connect = 1;
3982 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3984 ret = libc_connect(s,
3986 un_addr.sa_socklen);
3989 SWRAP_LOG(SWRAP_LOG_TRACE,
3990 "connect() path=%s, fd=%d",
3991 un_addr.sa.un.sun_path, s);
3994 /* to give better errors */
3995 if (ret == -1 && errno == ENOENT) {
3996 errno = EHOSTUNREACH;
4000 si->peername = (struct swrap_address) {
4001 .sa_socklen = addrlen,
4004 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4008 * When we connect() on a socket than we have to bind the
4009 * outgoing connection on the interface we use for the
4010 * transport. We already bound it on the right interface
4011 * but here we have to update the name so getsockname()
4012 * returns correct information.
4014 if (si->bindname.sa_socklen > 0) {
4015 si->myname = (struct swrap_address) {
4016 .sa_socklen = si->bindname.sa_socklen,
4019 memcpy(&si->myname.sa.ss,
4020 &si->bindname.sa.ss,
4021 si->bindname.sa_socklen);
4023 /* Cleanup bindname */
4024 si->bindname = (struct swrap_address) {
4029 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4030 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4032 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4036 SWRAP_UNLOCK_SI(si);
4040 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4042 return swrap_connect(s, serv_addr, addrlen);
4045 /****************************************************************************
4047 ***************************************************************************/
4049 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4052 struct swrap_address un_addr = {
4053 .sa_socklen = sizeof(struct sockaddr_un),
4055 struct socket_info *si = find_socket_info(s);
4062 return libc_bind(s, myaddr, addrlen);
4067 switch (si->family) {
4069 const struct sockaddr_in *sin;
4070 if (addrlen < sizeof(struct sockaddr_in)) {
4071 bind_error = EINVAL;
4075 sin = (const struct sockaddr_in *)(const void *)myaddr;
4077 if (sin->sin_family != AF_INET) {
4078 bind_error = EAFNOSUPPORT;
4081 /* special case for AF_UNSPEC */
4082 if (sin->sin_family == AF_UNSPEC &&
4083 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4092 const struct sockaddr_in6 *sin6;
4093 if (addrlen < sizeof(struct sockaddr_in6)) {
4094 bind_error = EINVAL;
4098 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4100 if (sin6->sin6_family != AF_INET6) {
4101 bind_error = EAFNOSUPPORT;
4108 bind_error = EINVAL;
4112 if (bind_error != 0) {
4119 in_use = check_addr_port_in_use(myaddr, addrlen);
4127 si->myname.sa_socklen = addrlen;
4128 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4130 ret = sockaddr_convert_to_un(si,
4140 unlink(un_addr.sa.un.sun_path);
4142 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4144 SWRAP_LOG(SWRAP_LOG_TRACE,
4145 "bind() path=%s, fd=%d",
4146 un_addr.sa.un.sun_path, s);
4153 SWRAP_UNLOCK_SI(si);
4158 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4160 return swrap_bind(s, myaddr, addrlen);
4163 /****************************************************************************
4165 ***************************************************************************/
4167 #ifdef HAVE_BINDRESVPORT
4168 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4170 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4172 struct swrap_address myaddr = {
4173 .sa_socklen = sizeof(struct sockaddr_storage),
4176 static uint16_t port;
4181 #define SWRAP_STARTPORT 600
4182 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4183 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4186 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4190 salen = myaddr.sa_socklen;
4193 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4199 memset(&myaddr.sa.ss, 0, salen);
4204 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4207 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4209 salen = sizeof(struct sockaddr_in);
4210 sinp->sin_port = htons(port);
4214 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4216 salen = sizeof(struct sockaddr_in6);
4217 sin6p->sin6_port = htons(port);
4221 errno = EAFNOSUPPORT;
4226 if (port > SWRAP_ENDPORT) {
4227 port = SWRAP_STARTPORT;
4230 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4231 if (rc == 0 || errno != EADDRINUSE) {
4239 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4241 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4245 /****************************************************************************
4247 ***************************************************************************/
4249 static int swrap_listen(int s, int backlog)
4252 struct socket_info *si = find_socket_info(s);
4255 return libc_listen(s, backlog);
4260 if (si->bound == 0) {
4261 ret = swrap_auto_bind(s, si, si->family);
4268 ret = libc_listen(s, backlog);
4274 SWRAP_UNLOCK_SI(si);
4279 int listen(int s, int backlog)
4281 return swrap_listen(s, backlog);
4284 /****************************************************************************
4286 ***************************************************************************/
4288 static FILE *swrap_fopen(const char *name, const char *mode)
4292 fp = libc_fopen(name, mode);
4294 int fd = fileno(fp);
4296 swrap_remove_stale(fd);
4302 FILE *fopen(const char *name, const char *mode)
4304 return swrap_fopen(name, mode);
4307 /****************************************************************************
4309 ***************************************************************************/
4312 static FILE *swrap_fopen64(const char *name, const char *mode)
4316 fp = libc_fopen64(name, mode);
4318 int fd = fileno(fp);
4320 swrap_remove_stale(fd);
4326 FILE *fopen64(const char *name, const char *mode)
4328 return swrap_fopen64(name, mode);
4330 #endif /* HAVE_FOPEN64 */
4332 /****************************************************************************
4334 ***************************************************************************/
4336 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4340 ret = libc_vopen(pathname, flags, ap);
4343 * There are methods for closing descriptors (libc-internal code
4344 * paths, direct syscalls) which close descriptors in ways that
4345 * we can't intercept, so try to recover when we notice that
4348 swrap_remove_stale(ret);
4353 int open(const char *pathname, int flags, ...)
4358 va_start(ap, flags);
4359 fd = swrap_vopen(pathname, flags, ap);
4365 /****************************************************************************
4367 ***************************************************************************/
4370 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4374 ret = libc_vopen64(pathname, flags, ap);
4377 * There are methods for closing descriptors (libc-internal code
4378 * paths, direct syscalls) which close descriptors in ways that
4379 * we can't intercept, so try to recover when we notice that
4382 swrap_remove_stale(ret);
4387 int open64(const char *pathname, int flags, ...)
4392 va_start(ap, flags);
4393 fd = swrap_vopen64(pathname, flags, ap);
4398 #endif /* HAVE_OPEN64 */
4400 /****************************************************************************
4402 ***************************************************************************/
4404 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4408 ret = libc_vopenat(dirfd, path, flags, ap);
4411 * There are methods for closing descriptors (libc-internal code
4412 * paths, direct syscalls) which close descriptors in ways that
4413 * we can't intercept, so try to recover when we notice that
4416 swrap_remove_stale(ret);
4422 int openat(int dirfd, const char *path, int flags, ...)
4427 va_start(ap, flags);
4428 fd = swrap_vopenat(dirfd, path, flags, ap);
4434 /****************************************************************************
4436 ***************************************************************************/
4438 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4440 struct socket_info *si = find_socket_info(s);
4445 return libc_getpeername(s, name, addrlen);
4450 if (si->peername.sa_socklen == 0)
4456 len = MIN(*addrlen, si->peername.sa_socklen);
4462 memcpy(name, &si->peername.sa.ss, len);
4463 *addrlen = si->peername.sa_socklen;
4467 SWRAP_UNLOCK_SI(si);
4472 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4473 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4475 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4478 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4481 /****************************************************************************
4483 ***************************************************************************/
4485 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4487 struct socket_info *si = find_socket_info(s);
4492 return libc_getsockname(s, name, addrlen);
4497 len = MIN(*addrlen, si->myname.sa_socklen);
4503 memcpy(name, &si->myname.sa.ss, len);
4504 *addrlen = si->myname.sa_socklen;
4508 SWRAP_UNLOCK_SI(si);
4513 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4514 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4516 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4519 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4522 /****************************************************************************
4524 ***************************************************************************/
4527 # ifdef SO_PROTOTYPE /* The Solaris name */
4528 # define SO_PROTOCOL SO_PROTOTYPE
4529 # endif /* SO_PROTOTYPE */
4530 #endif /* SO_PROTOCOL */
4532 static int swrap_getsockopt(int s, int level, int optname,
4533 void *optval, socklen_t *optlen)
4535 struct socket_info *si = find_socket_info(s);
4539 return libc_getsockopt(s,
4548 if (level == SOL_SOCKET) {
4552 if (optval == NULL || optlen == NULL ||
4553 *optlen < (socklen_t)sizeof(int)) {
4559 *optlen = sizeof(int);
4560 *(int *)optval = si->family;
4563 #endif /* SO_DOMAIN */
4567 if (optval == NULL || optlen == NULL ||
4568 *optlen < (socklen_t)sizeof(int)) {
4574 *optlen = sizeof(int);
4575 *(int *)optval = si->protocol;
4578 #endif /* SO_PROTOCOL */
4580 if (optval == NULL || optlen == NULL ||
4581 *optlen < (socklen_t)sizeof(int)) {
4587 *optlen = sizeof(int);
4588 *(int *)optval = si->type;
4592 ret = libc_getsockopt(s,
4599 } else if (level == IPPROTO_TCP) {
4604 * This enables sending packets directly out over TCP.
4605 * As a unix socket is doing that any way, report it as
4608 if (optval == NULL || optlen == NULL ||
4609 *optlen < (socklen_t)sizeof(int)) {
4615 *optlen = sizeof(int);
4616 *(int *)optval = si->tcp_nodelay;
4620 #endif /* TCP_NODELAY */
4623 struct tcp_info info;
4624 socklen_t ilen = sizeof(info);
4626 #ifdef HAVE_NETINET_TCP_FSM_H
4627 /* This is FreeBSD */
4628 # define __TCP_LISTEN TCPS_LISTEN
4629 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4630 # define __TCP_CLOSE TCPS_CLOSED
4633 # define __TCP_LISTEN TCP_LISTEN
4634 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4635 # define __TCP_CLOSE TCP_CLOSE
4639 if (si->listening) {
4640 info.tcpi_state = __TCP_LISTEN;
4641 } else if (si->connected) {
4643 * For now we just fake a few values
4644 * supported both by FreeBSD and Linux
4646 info.tcpi_state = __TCP_ESTABLISHED;
4647 info.tcpi_rto = 200000; /* 200 msec */
4648 info.tcpi_rtt = 5000; /* 5 msec */
4649 info.tcpi_rttvar = 5000; /* 5 msec */
4651 info.tcpi_state = __TCP_CLOSE;
4652 info.tcpi_rto = 1000000; /* 1 sec */
4654 info.tcpi_rttvar = 250000; /* 250 msec */
4657 if (optval == NULL || optlen == NULL ||
4658 *optlen < (socklen_t)ilen) {
4665 memcpy(optval, &info, ilen);
4670 #endif /* TCP_INFO */
4676 errno = ENOPROTOOPT;
4680 SWRAP_UNLOCK_SI(si);
4684 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4685 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4687 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4690 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4693 /****************************************************************************
4695 ***************************************************************************/
4697 static int swrap_setsockopt(int s, int level, int optname,
4698 const void *optval, socklen_t optlen)
4700 struct socket_info *si = find_socket_info(s);
4704 return libc_setsockopt(s,
4711 if (level == SOL_SOCKET) {
4712 return libc_setsockopt(s,
4721 if (level == IPPROTO_TCP) {
4728 * This enables sending packets directly out over TCP.
4729 * A unix socket is doing that any way.
4731 if (optval == NULL || optlen == 0 ||
4732 optlen < (socklen_t)sizeof(int)) {
4738 i = *discard_const_p(int, optval);
4739 if (i != 0 && i != 1) {
4744 si->tcp_nodelay = i;
4749 #endif /* TCP_NODELAY */
4755 switch (si->family) {
4757 if (level == IPPROTO_IP) {
4759 if (optname == IP_PKTINFO) {
4760 si->pktinfo = AF_INET;
4762 #endif /* IP_PKTINFO */
4768 if (level == IPPROTO_IPV6) {
4769 #ifdef IPV6_RECVPKTINFO
4770 if (optname == IPV6_RECVPKTINFO) {
4771 si->pktinfo = AF_INET6;
4773 #endif /* IPV6_PKTINFO */
4779 errno = ENOPROTOOPT;
4785 SWRAP_UNLOCK_SI(si);
4789 int setsockopt(int s, int level, int optname,
4790 const void *optval, socklen_t optlen)
4792 return swrap_setsockopt(s, level, optname, optval, optlen);
4795 /****************************************************************************
4797 ***************************************************************************/
4799 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4801 struct socket_info *si = find_socket_info(s);
4803 int *value_ptr = NULL;
4807 return libc_vioctl(s, r, va);
4814 rc = libc_vioctl(s, r, va);
4819 value_ptr = ((int *)va_arg(ap, int *));
4822 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4823 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4824 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4825 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4830 /* this is FreeBSD */
4831 FALL_THROUGH; /* to TIOCOUTQ */
4832 #endif /* FIONWRITE */
4833 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4835 * This may return more bytes then the application
4836 * sent into the socket, for tcp it should
4837 * return the number of unacked bytes.
4839 * On AF_UNIX, all bytes are immediately acked!
4842 value_ptr = ((int *)va_arg(ap, int *));
4850 SWRAP_UNLOCK_SI(si);
4854 #ifdef HAVE_IOCTL_INT
4855 int ioctl(int s, int r, ...)
4857 int ioctl(int s, unsigned long int r, ...)
4865 rc = swrap_vioctl(s, (unsigned long int) r, va);
4876 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4879 # ifdef _ALIGN /* BSD */
4880 #define CMSG_ALIGN _ALIGN
4882 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4883 # endif /* _ALIGN */
4884 #endif /* CMSG_ALIGN */
4887 * @brief Add a cmsghdr to a msghdr.
4889 * This is an function to add any type of cmsghdr. It will operate on the
4890 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4891 * the buffer position after the added cmsg element. Hence, this function is
4892 * intended to be used with an intermediate msghdr and not on the original
4893 * one handed in by the client.
4895 * @param[in] msg The msghdr to which to add the cmsg.
4897 * @param[in] level The cmsg level to set.
4899 * @param[in] type The cmsg type to set.
4901 * @param[in] data The cmsg data to set.
4903 * @param[in] len the length of the data to set.
4905 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4911 size_t cmlen = CMSG_LEN(len);
4912 size_t cmspace = CMSG_SPACE(len);
4913 uint8_t cmbuf[cmspace];
4914 void *cast_ptr = (void *)cmbuf;
4915 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4918 memset(cmbuf, 0, cmspace);
4920 if (msg->msg_controllen < cmlen) {
4921 cmlen = msg->msg_controllen;
4922 msg->msg_flags |= MSG_CTRUNC;
4925 if (msg->msg_controllen < cmspace) {
4926 cmspace = msg->msg_controllen;
4930 * We copy the full input data into an intermediate cmsghdr first
4931 * in order to more easily cope with truncation.
4933 cm->cmsg_len = cmlen;
4934 cm->cmsg_level = level;
4935 cm->cmsg_type = type;
4936 memcpy(CMSG_DATA(cm), data, len);
4939 * We now copy the possibly truncated buffer.
4940 * We copy cmlen bytes, but consume cmspace bytes,
4941 * leaving the possible padding uninitialiazed.
4943 p = (uint8_t *)msg->msg_control;
4944 memcpy(p, cm, cmlen);
4946 msg->msg_control = p;
4947 msg->msg_controllen -= cmspace;
4952 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4955 /* Add packet info */
4956 switch (si->pktinfo) {
4957 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4959 struct sockaddr_in *sin;
4960 #if defined(HAVE_STRUCT_IN_PKTINFO)
4961 struct in_pktinfo pkt;
4962 #elif defined(IP_RECVDSTADDR)
4966 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4967 sin = &si->bindname.sa.in;
4969 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4972 sin = &si->myname.sa.in;
4977 #if defined(HAVE_STRUCT_IN_PKTINFO)
4978 pkt.ipi_ifindex = socket_wrapper_default_iface();
4979 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4980 #elif defined(IP_RECVDSTADDR)
4981 pkt = sin->sin_addr;
4984 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4989 #endif /* IP_PKTINFO */
4990 #if defined(HAVE_IPV6)
4992 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4993 struct sockaddr_in6 *sin6;
4994 struct in6_pktinfo pkt6;
4996 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4997 sin6 = &si->bindname.sa.in6;
4999 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5002 sin6 = &si->myname.sa.in6;
5007 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5008 pkt6.ipi6_addr = sin6->sin6_addr;
5010 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5011 &pkt6, sizeof(pkt6));
5012 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5016 #endif /* IPV6_PKTINFO */
5024 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5025 struct msghdr *omsg)
5029 if (si->pktinfo > 0) {
5030 rc = swrap_msghdr_add_pktinfo(si, omsg);
5036 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5038 size_t *cm_data_space);
5039 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5041 size_t *cm_data_space);
5042 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5044 size_t *cm_data_space);
5046 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5048 size_t *cm_data_space)
5050 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5051 struct cmsghdr *cmsg;
5055 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5059 for (cmsg = CMSG_FIRSTHDR(msg);
5061 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5062 switch (cmsg->cmsg_level) {
5064 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5069 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5074 rc = swrap_sendmsg_copy_cmsg(cmsg,
5080 int saved_errno = errno;
5081 SAFE_FREE(*cm_data);
5083 errno = saved_errno;
5091 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5093 size_t *cm_data_space)
5098 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5100 p = realloc((*cm_data), cmspace);
5106 p = (*cm_data) + (*cm_data_space);
5107 *cm_data_space = cmspace;
5109 memcpy(p, cmsg, cmsg->cmsg_len);
5114 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5116 size_t *cm_data_space);
5119 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5121 size_t *cm_data_space)
5125 switch(cmsg->cmsg_type) {
5128 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5135 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5147 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5149 size_t *cm_data_space)
5151 (void)cmsg; /* unused */
5152 (void)cm_data; /* unused */
5153 (void)cm_data_space; /* unused */
5156 * Passing a IP pktinfo to a unix socket might be rejected by the
5157 * Kernel, at least on FreeBSD. So skip this cmsg.
5162 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5164 size_t *cm_data_space)
5168 switch (cmsg->cmsg_type) {
5170 SWRAP_LOG(SWRAP_LOG_TRACE,
5171 "Ignoring SCM_RIGHTS on inet socket!");
5174 #ifdef SCM_CREDENTIALS
5175 case SCM_CREDENTIALS:
5176 SWRAP_LOG(SWRAP_LOG_TRACE,
5177 "Ignoring SCM_CREDENTIALS on inet socket!");
5180 #endif /* SCM_CREDENTIALS */
5182 rc = swrap_sendmsg_copy_cmsg(cmsg,
5191 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5194 * We only allow up to 6 fds at a time
5195 * as that's more than enough for Samba
5196 * and it means we can keep the logic simple
5197 * and work with fixed size arrays.
5199 * We also keep sizeof(struct swrap_unix_scm_rights)
5200 * under PIPE_BUF (4096) in order to allow a non-blocking
5201 * write into the pipe.
5204 #define PIPE_BUF 4096
5206 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5207 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5208 struct swrap_unix_scm_rights_payload {
5210 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5211 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5213 struct swrap_unix_scm_rights {
5215 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5216 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5218 uint32_t payload_size;
5219 struct swrap_unix_scm_rights_payload payload;
5222 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5224 int saved_errno = errno;
5227 for (i = 0; i < num; i++) {
5228 struct socket_info *si = array[i];
5234 swrap_dec_refcount(si);
5235 if (si->fd_passed > 0) {
5238 SWRAP_UNLOCK_SI(si);
5242 errno = saved_errno;
5245 static void swrap_undo_si_idx_array(size_t num, int *array)
5247 int saved_errno = errno;
5250 swrap_mutex_lock(&first_free_mutex);
5252 for (i = 0; i < num; i++) {
5253 struct socket_info *si = NULL;
5255 if (array[i] == -1) {
5259 si = swrap_get_socket_info(array[i]);
5265 swrap_dec_refcount(si);
5266 SWRAP_UNLOCK_SI(si);
5268 swrap_set_next_free(si, first_free);
5269 first_free = array[i];
5273 swrap_mutex_unlock(&first_free_mutex);
5274 errno = saved_errno;
5277 static void swrap_close_fd_array(size_t num, const int *array)
5279 int saved_errno = errno;
5282 for (i = 0; i < num; i++) {
5283 if (array[i] == -1) {
5286 libc_close(array[i]);
5289 errno = saved_errno;
5297 union __swrap_cmsghdr {
5299 struct cmsghdr *cmsg;
5302 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5304 size_t *cm_data_space,
5305 int *scm_rights_pipe_fd)
5307 struct swrap_unix_scm_rights info;
5308 struct swrap_unix_scm_rights_payload *payload = NULL;
5309 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5310 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5311 size_t info_idx = 0;
5314 union __swrap_fds __fds_in = { .p = NULL, };
5315 const int *fds_in = NULL;
5317 size_t size_fds_out;
5318 union __swrap_fds __fds_out = { .p = NULL, };
5319 int *fds_out = NULL;
5322 size_t new_cm_data_space;
5323 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5324 struct cmsghdr *new_cmsg = NULL;
5327 int pipefd[2] = { -1, -1 };
5332 * We pass this a buffer to the kernel make sure any padding
5336 info.magic = swrap_unix_scm_right_magic;
5337 memcpy(info.package_name,
5338 SOCKET_WRAPPER_PACKAGE,
5339 sizeof(info.package_name));
5340 memcpy(info.package_version,
5341 SOCKET_WRAPPER_VERSION,
5342 sizeof(info.package_version));
5343 info.full_size = sizeof(info);
5344 info.payload_size = sizeof(info.payload);
5345 payload = &info.payload;
5347 if (*scm_rights_pipe_fd != -1) {
5348 SWRAP_LOG(SWRAP_LOG_ERROR,
5349 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5354 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5355 SWRAP_LOG(SWRAP_LOG_ERROR,
5356 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5357 (size_t)cmsg->cmsg_len,
5362 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5363 if ((size_fds_in % sizeof(int)) != 0) {
5364 SWRAP_LOG(SWRAP_LOG_ERROR,
5365 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5366 (size_t)cmsg->cmsg_len,
5372 num_fds_in = size_fds_in / sizeof(int);
5373 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5374 SWRAP_LOG(SWRAP_LOG_ERROR,
5375 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5377 "SWRAP_MAX_PASSED_FDS(%zu)",
5378 (size_t)cmsg->cmsg_len,
5381 SWRAP_MAX_PASSED_FDS);
5385 if (num_fds_in == 0) {
5386 SWRAP_LOG(SWRAP_LOG_ERROR,
5387 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5389 (size_t)cmsg->cmsg_len,
5395 __fds_in.p = CMSG_DATA(cmsg);
5396 fds_in = __fds_in.fds;
5397 num_fds_out = num_fds_in + 1;
5399 SWRAP_LOG(SWRAP_LOG_TRACE,
5400 "num_fds_in=%zu num_fds_out=%zu",
5401 num_fds_in, num_fds_out);
5403 size_fds_out = sizeof(int) * num_fds_out;
5404 cmsg_len = CMSG_LEN(size_fds_out);
5405 cmsg_space = CMSG_SPACE(size_fds_out);
5407 new_cm_data_space = *cm_data_space + cmsg_space;
5409 p = realloc((*cm_data), new_cm_data_space);
5414 p = (*cm_data) + (*cm_data_space);
5415 memset(p, 0, cmsg_space);
5417 new_cmsg = __new_cmsg.cmsg;
5419 __fds_out.p = CMSG_DATA(new_cmsg);
5420 fds_out = __fds_out.fds;
5421 memcpy(fds_out, fds_in, size_fds_out);
5422 new_cmsg->cmsg_len = cmsg->cmsg_len;
5424 for (i = 0; i < num_fds_in; i++) {
5427 payload->idxs[i] = -1;
5428 payload->num_idxs++;
5430 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5431 if (si_idx_array[i] == -1) {
5435 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5436 if (si_array[i] == NULL) {
5437 SWRAP_LOG(SWRAP_LOG_ERROR,
5438 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5439 i, fds_in[i], i, si_idx_array[i]);
5444 for (j = 0; j < i; j++) {
5445 if (si_array[j] == si_array[i]) {
5446 payload->idxs[i] = payload->idxs[j];
5450 if (payload->idxs[i] == -1) {
5451 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5452 SWRAP_LOG(SWRAP_LOG_ERROR,
5453 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5454 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5455 i, fds_in[i], i, si_idx_array[i],
5457 SWRAP_MAX_PASSED_SOCKET_INFO);
5461 payload->idxs[i] = info_idx;
5467 for (i = 0; i < num_fds_in; i++) {
5468 struct socket_info *si = si_array[i];
5471 SWRAP_LOG(SWRAP_LOG_TRACE,
5472 "fds_in[%zu]=%d not an inet socket",
5477 SWRAP_LOG(SWRAP_LOG_TRACE,
5478 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5479 "passing as info.idxs[%zu]=%d!",
5482 i, payload->idxs[i]);
5486 payload->infos[payload->idxs[i]] = *si;
5487 payload->infos[payload->idxs[i]].fd_passed = 0;
5488 SWRAP_UNLOCK_SI(si);
5493 int saved_errno = errno;
5494 SWRAP_LOG(SWRAP_LOG_ERROR,
5495 "pipe() failed - %d %s",
5497 strerror(saved_errno));
5498 swrap_dec_fd_passed_array(num_fds_in, si_array);
5499 errno = saved_errno;
5503 sret = write(pipefd[1], &info, sizeof(info));
5504 if (sret != sizeof(info)) {
5505 int saved_errno = errno;
5507 saved_errno = EINVAL;
5509 SWRAP_LOG(SWRAP_LOG_ERROR,
5510 "write() failed - sret=%zd - %d %s",
5512 strerror(saved_errno));
5513 swrap_dec_fd_passed_array(num_fds_in, si_array);
5514 libc_close(pipefd[1]);
5515 libc_close(pipefd[0]);
5516 errno = saved_errno;
5519 libc_close(pipefd[1]);
5522 * Add the pipe read end to the end of the passed fd array
5524 fds_out[num_fds_in] = pipefd[0];
5525 new_cmsg->cmsg_len = cmsg_len;
5527 /* we're done ... */
5528 *scm_rights_pipe_fd = pipefd[0];
5529 *cm_data_space = new_cm_data_space;
5534 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5536 size_t *cm_data_space,
5537 int *scm_rights_pipe_fd)
5541 switch (cmsg->cmsg_type) {
5543 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5546 scm_rights_pipe_fd);
5549 rc = swrap_sendmsg_copy_cmsg(cmsg,
5558 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5560 size_t *cm_data_space)
5562 int scm_rights_pipe_fd = -1;
5563 struct swrap_unix_scm_rights info;
5564 struct swrap_unix_scm_rights_payload *payload = NULL;
5565 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5568 union __swrap_fds __fds_in = { .p = NULL, };
5569 const int *fds_in = NULL;
5571 size_t size_fds_out;
5572 union __swrap_fds __fds_out = { .p = NULL, };
5573 int *fds_out = NULL;
5576 size_t new_cm_data_space;
5577 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5578 struct cmsghdr *new_cmsg = NULL;
5584 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5585 SWRAP_LOG(SWRAP_LOG_ERROR,
5586 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5587 (size_t)cmsg->cmsg_len,
5592 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5593 if ((size_fds_in % sizeof(int)) != 0) {
5594 SWRAP_LOG(SWRAP_LOG_ERROR,
5595 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5596 (size_t)cmsg->cmsg_len,
5602 num_fds_in = size_fds_in / sizeof(int);
5603 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5604 SWRAP_LOG(SWRAP_LOG_ERROR,
5605 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5606 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5607 (size_t)cmsg->cmsg_len,
5610 SWRAP_MAX_PASSED_FDS+1);
5614 if (num_fds_in <= 1) {
5615 SWRAP_LOG(SWRAP_LOG_ERROR,
5616 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5618 (size_t)cmsg->cmsg_len,
5624 __fds_in.p = CMSG_DATA(cmsg);
5625 fds_in = __fds_in.fds;
5626 num_fds_out = num_fds_in - 1;
5628 SWRAP_LOG(SWRAP_LOG_TRACE,
5629 "num_fds_in=%zu num_fds_out=%zu",
5630 num_fds_in, num_fds_out);
5632 for (i = 0; i < num_fds_in; i++) {
5633 /* Check if we have a stale fd and remove it */
5634 swrap_remove_stale(fds_in[i]);
5637 scm_rights_pipe_fd = fds_in[num_fds_out];
5638 size_fds_out = sizeof(int) * num_fds_out;
5639 cmsg_len = CMSG_LEN(size_fds_out);
5640 cmsg_space = CMSG_SPACE(size_fds_out);
5642 new_cm_data_space = *cm_data_space + cmsg_space;
5644 p = realloc((*cm_data), new_cm_data_space);
5646 swrap_close_fd_array(num_fds_in, fds_in);
5650 p = (*cm_data) + (*cm_data_space);
5651 memset(p, 0, cmsg_space);
5653 new_cmsg = __new_cmsg.cmsg;
5655 __fds_out.p = CMSG_DATA(new_cmsg);
5656 fds_out = __fds_out.fds;
5657 memcpy(fds_out, fds_in, size_fds_out);
5658 new_cmsg->cmsg_len = cmsg_len;
5660 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5661 if (sret != sizeof(info)) {
5662 int saved_errno = errno;
5664 saved_errno = EINVAL;
5666 SWRAP_LOG(SWRAP_LOG_ERROR,
5667 "read() failed - sret=%zd - %d %s",
5669 strerror(saved_errno));
5670 swrap_close_fd_array(num_fds_in, fds_in);
5671 errno = saved_errno;
5674 libc_close(scm_rights_pipe_fd);
5675 payload = &info.payload;
5677 if (info.magic != swrap_unix_scm_right_magic) {
5678 SWRAP_LOG(SWRAP_LOG_ERROR,
5679 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5680 (unsigned long long)info.magic,
5681 (unsigned long long)swrap_unix_scm_right_magic);
5682 swrap_close_fd_array(num_fds_out, fds_out);
5687 cmp = memcmp(info.package_name,
5688 SOCKET_WRAPPER_PACKAGE,
5689 sizeof(info.package_name));
5691 SWRAP_LOG(SWRAP_LOG_ERROR,
5692 "info.package_name='%.*s' != '%s'",
5693 (int)sizeof(info.package_name),
5695 SOCKET_WRAPPER_PACKAGE);
5696 swrap_close_fd_array(num_fds_out, fds_out);
5701 cmp = memcmp(info.package_version,
5702 SOCKET_WRAPPER_VERSION,
5703 sizeof(info.package_version));
5705 SWRAP_LOG(SWRAP_LOG_ERROR,
5706 "info.package_version='%.*s' != '%s'",
5707 (int)sizeof(info.package_version),
5708 info.package_version,
5709 SOCKET_WRAPPER_VERSION);
5710 swrap_close_fd_array(num_fds_out, fds_out);
5715 if (info.full_size != sizeof(info)) {
5716 SWRAP_LOG(SWRAP_LOG_ERROR,
5717 "info.full_size=%zu != sizeof(info)=%zu",
5718 (size_t)info.full_size,
5720 swrap_close_fd_array(num_fds_out, fds_out);
5725 if (info.payload_size != sizeof(info.payload)) {
5726 SWRAP_LOG(SWRAP_LOG_ERROR,
5727 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5728 (size_t)info.payload_size,
5729 sizeof(info.payload));
5730 swrap_close_fd_array(num_fds_out, fds_out);
5735 if (payload->num_idxs != num_fds_out) {
5736 SWRAP_LOG(SWRAP_LOG_ERROR,
5737 "info.num_idxs=%u != num_fds_out=%zu",
5738 payload->num_idxs, num_fds_out);
5739 swrap_close_fd_array(num_fds_out, fds_out);
5744 for (i = 0; i < num_fds_out; i++) {
5747 si_idx_array[i] = -1;
5749 if (payload->idxs[i] == -1) {
5750 SWRAP_LOG(SWRAP_LOG_TRACE,
5751 "fds_out[%zu]=%d not an inet socket",
5756 if (payload->idxs[i] < 0) {
5757 SWRAP_LOG(SWRAP_LOG_ERROR,
5758 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5759 i, fds_out[i], i, payload->idxs[i]);
5760 swrap_close_fd_array(num_fds_out, fds_out);
5765 if (payload->idxs[i] >= payload->num_idxs) {
5766 SWRAP_LOG(SWRAP_LOG_ERROR,
5767 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5768 i, fds_out[i], i, payload->idxs[i],
5770 swrap_close_fd_array(num_fds_out, fds_out);
5775 if ((size_t)fds_out[i] >= socket_fds_max) {
5776 SWRAP_LOG(SWRAP_LOG_ERROR,
5777 "The max socket index limit of %zu has been reached, "
5781 swrap_close_fd_array(num_fds_out, fds_out);
5786 SWRAP_LOG(SWRAP_LOG_TRACE,
5788 "received as info.idxs[%zu]=%d!",
5790 i, payload->idxs[i]);
5792 for (j = 0; j < i; j++) {
5793 if (payload->idxs[j] == -1) {
5796 if (payload->idxs[j] == payload->idxs[i]) {
5797 si_idx_array[i] = si_idx_array[j];
5800 if (si_idx_array[i] == -1) {
5801 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5803 si_idx_array[i] = swrap_add_socket_info(si);
5804 if (si_idx_array[i] == -1) {
5805 int saved_errno = errno;
5806 SWRAP_LOG(SWRAP_LOG_ERROR,
5807 "The max socket index limit of %zu has been reached, "
5811 swrap_undo_si_idx_array(i, si_idx_array);
5812 swrap_close_fd_array(num_fds_out, fds_out);
5813 errno = saved_errno;
5816 SWRAP_LOG(SWRAP_LOG_TRACE,
5817 "Imported %s socket for protocol %s, fd=%d",
5818 si->family == AF_INET ? "IPv4" : "IPv6",
5819 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5824 for (i = 0; i < num_fds_out; i++) {
5825 if (si_idx_array[i] == -1) {
5828 set_socket_info_index(fds_out[i], si_idx_array[i]);
5831 /* we're done ... */
5832 *cm_data_space = new_cm_data_space;
5837 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5839 size_t *cm_data_space)
5843 switch (cmsg->cmsg_type) {
5845 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5850 rc = swrap_sendmsg_copy_cmsg(cmsg,
5859 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5861 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5862 struct msghdr *msg_tmp,
5863 int *scm_rights_pipe_fd)
5865 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5866 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5867 struct cmsghdr *cmsg = NULL;
5868 uint8_t *cm_data = NULL;
5869 size_t cm_data_space = 0;
5873 *scm_rights_pipe_fd = -1;
5876 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5880 for (cmsg = CMSG_FIRSTHDR(msg_in);
5882 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5883 switch (cmsg->cmsg_level) {
5885 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5888 scm_rights_pipe_fd);
5892 rc = swrap_sendmsg_copy_cmsg(cmsg,
5898 int saved_errno = errno;
5900 errno = saved_errno;
5905 msg_tmp->msg_controllen = cm_data_space;
5906 msg_tmp->msg_control = cm_data;
5909 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5910 *msg_tmp = *_msg_in;
5912 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5915 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5917 int scm_rights_pipe_fd)
5919 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5920 int saved_errno = errno;
5921 SAFE_FREE(msg_tmp->msg_control);
5922 if (scm_rights_pipe_fd != -1) {
5923 libc_close(scm_rights_pipe_fd);
5925 errno = saved_errno;
5926 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5930 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5931 struct msghdr *msg_tmp)
5937 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5938 struct msghdr *msg_out,
5941 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5942 struct cmsghdr *cmsg = NULL;
5943 uint8_t *cm_data = NULL;
5944 size_t cm_data_space = 0;
5948 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
5952 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
5954 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
5955 switch (cmsg->cmsg_level) {
5957 rc = swrap_recvmsg_unix_sol_socket(cmsg,
5963 rc = swrap_sendmsg_copy_cmsg(cmsg,
5969 int saved_errno = errno;
5971 errno = saved_errno;
5977 * msg_tmp->msg_control is still the buffer of the caller.
5979 memcpy(msg_tmp->msg_control, cm_data, cm_data_space);
5980 msg_tmp->msg_controllen = cm_data_space;
5983 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5984 *msg_out = *msg_tmp;
5988 static ssize_t swrap_sendmsg_before(int fd,
5989 struct socket_info *si,
5991 struct iovec *tmp_iov,
5992 struct sockaddr_un *tmp_un,
5993 const struct sockaddr_un **to_un,
5994 const struct sockaddr **to,
6016 if (!si->connected) {
6021 if (msg->msg_iovlen == 0) {
6025 mtu = socket_wrapper_mtu();
6026 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6028 nlen = len + msg->msg_iov[i].iov_len;
6038 msg->msg_iovlen = i;
6039 if (msg->msg_iovlen == 0) {
6040 *tmp_iov = msg->msg_iov[0];
6041 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6043 msg->msg_iov = tmp_iov;
6044 msg->msg_iovlen = 1;
6049 if (si->connected) {
6050 if (msg->msg_name != NULL) {
6052 * We are dealing with unix sockets and if we
6053 * are connected, we should only talk to the
6054 * connected unix path. Using the fd to send
6055 * to another server would be hard to achieve.
6057 msg->msg_name = NULL;
6058 msg->msg_namelen = 0;
6061 const struct sockaddr *msg_name;
6062 msg_name = (const struct sockaddr *)msg->msg_name;
6064 if (msg_name == NULL) {
6070 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6082 msg->msg_name = tmp_un;
6083 msg->msg_namelen = sizeof(*tmp_un);
6086 if (si->bound == 0) {
6087 ret = swrap_auto_bind(fd, si, si->family);
6089 SWRAP_UNLOCK_SI(si);
6090 if (errno == ENOTSOCK) {
6091 swrap_remove_stale(fd);
6094 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6100 if (!si->defer_connect) {
6104 ret = sockaddr_convert_to_un(si,
6106 si->peername.sa_socklen,
6114 ret = libc_connect(fd,
6115 (struct sockaddr *)(void *)tmp_un,
6118 /* to give better errors */
6119 if (ret == -1 && errno == ENOENT) {
6120 errno = EHOSTUNREACH;
6127 si->defer_connect = 0;
6130 errno = EHOSTUNREACH;
6136 SWRAP_UNLOCK_SI(si);
6141 static void swrap_sendmsg_after(int fd,
6142 struct socket_info *si,
6144 const struct sockaddr *to,
6147 int saved_errno = errno;
6154 /* to give better errors */
6156 if (saved_errno == ENOENT) {
6157 saved_errno = EHOSTUNREACH;
6158 } else if (saved_errno == ENOTSOCK) {
6159 /* If the fd is not a socket, remove it */
6160 swrap_remove_stale(fd);
6164 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6165 avail += msg->msg_iov[i].iov_len;
6169 remain = MIN(80, avail);
6174 /* we capture it as one single packet */
6175 buf = (uint8_t *)malloc(remain);
6177 /* we just not capture the packet */
6178 errno = saved_errno;
6182 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6183 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6185 msg->msg_iov[i].iov_base,
6188 remain -= this_time;
6197 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6198 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6200 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6205 if (si->connected) {
6206 to = &si->peername.sa.s;
6209 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6210 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6212 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6217 SWRAP_UNLOCK_SI(si);
6220 errno = saved_errno;
6223 static int swrap_recvmsg_before(int fd,
6224 struct socket_info *si,
6226 struct iovec *tmp_iov)
6233 (void)fd; /* unused */
6238 if (!si->connected) {
6243 if (msg->msg_iovlen == 0) {
6247 mtu = socket_wrapper_mtu();
6248 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6250 nlen = len + msg->msg_iov[i].iov_len;
6255 msg->msg_iovlen = i;
6256 if (msg->msg_iovlen == 0) {
6257 *tmp_iov = msg->msg_iov[0];
6258 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6260 msg->msg_iov = tmp_iov;
6261 msg->msg_iovlen = 1;
6266 if (msg->msg_name == NULL) {
6271 if (msg->msg_iovlen == 0) {
6275 if (si->bound == 0) {
6276 ret = swrap_auto_bind(fd, si, si->family);
6278 SWRAP_UNLOCK_SI(si);
6280 * When attempting to read or write to a
6281 * descriptor, if an underlying autobind fails
6282 * because it's not a socket, stop intercepting
6283 * uses of that descriptor.
6285 if (errno == ENOTSOCK) {
6286 swrap_remove_stale(fd);
6289 SWRAP_LOG(SWRAP_LOG_ERROR,
6290 "swrap_recvmsg_before failed");
6297 errno = EHOSTUNREACH;
6303 SWRAP_UNLOCK_SI(si);
6308 static int swrap_recvmsg_after(int fd,
6309 struct socket_info *si,
6311 const struct sockaddr_un *un_addr,
6312 socklen_t un_addrlen,
6315 int saved_errno = errno;
6317 uint8_t *buf = NULL;
6323 /* to give better errors */
6325 if (saved_errno == ENOENT) {
6326 saved_errno = EHOSTUNREACH;
6327 } else if (saved_errno == ENOTSOCK) {
6328 /* If the fd is not a socket, remove it */
6329 swrap_remove_stale(fd);
6333 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6334 avail += msg->msg_iov[i].iov_len;
6339 /* Convert the socket address before we leave */
6340 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6341 rc = sockaddr_convert_from_un(si,
6358 remain = MIN(80, avail);
6363 /* we capture it as one single packet */
6364 buf = (uint8_t *)malloc(remain);
6366 /* we just not capture the packet */
6367 SWRAP_UNLOCK_SI(si);
6368 errno = saved_errno;
6372 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6373 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6375 msg->msg_iov[i].iov_base,
6378 remain -= this_time;
6383 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6384 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6385 } else if (ret == 0) { /* END OF FILE */
6386 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6387 } else if (ret > 0) {
6388 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6397 if (un_addr != NULL) {
6398 swrap_pcap_dump_packet(si,
6404 swrap_pcap_dump_packet(si,
6417 errno = saved_errno;
6419 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6421 msg->msg_controllen > 0 &&
6422 msg->msg_control != NULL) {
6423 rc = swrap_msghdr_add_socket_info(si, msg);
6425 SWRAP_UNLOCK_SI(si);
6431 SWRAP_UNLOCK_SI(si);
6435 /****************************************************************************
6437 ***************************************************************************/
6439 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6440 struct sockaddr *from, socklen_t *fromlen)
6442 struct swrap_address from_addr = {
6443 .sa_socklen = sizeof(struct sockaddr_un),
6446 struct socket_info *si = find_socket_info(s);
6447 struct swrap_address saddr = {
6448 .sa_socklen = sizeof(struct sockaddr_storage),
6455 return libc_recvfrom(s,
6467 if (from != NULL && fromlen != NULL) {
6468 msg.msg_name = from; /* optional address */
6469 msg.msg_namelen = *fromlen; /* size of address */
6471 msg.msg_name = &saddr.sa.s; /* optional address */
6472 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6474 msg.msg_iov = &tmp; /* scatter/gather array */
6475 msg.msg_iovlen = 1; /* # elements in msg_iov */
6476 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6477 msg.msg_control = NULL; /* ancillary data, see below */
6478 msg.msg_controllen = 0; /* ancillary data buffer len */
6479 msg.msg_flags = 0; /* flags on received message */
6482 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6487 buf = msg.msg_iov[0].iov_base;
6488 len = msg.msg_iov[0].iov_len;
6490 ret = libc_recvfrom(s,
6495 &from_addr.sa_socklen);
6500 tret = swrap_recvmsg_after(s,
6504 from_addr.sa_socklen,
6510 if (from != NULL && fromlen != NULL) {
6511 *fromlen = msg.msg_namelen;
6517 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6518 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6519 struct sockaddr *from, Psocklen_t fromlen)
6521 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6522 struct sockaddr *from, socklen_t *fromlen)
6525 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6528 /****************************************************************************
6530 ***************************************************************************/
6532 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6533 const struct sockaddr *to, socklen_t tolen)
6537 struct swrap_address un_addr = {
6538 .sa_socklen = sizeof(struct sockaddr_un),
6540 const struct sockaddr_un *to_un = NULL;
6543 struct socket_info *si = find_socket_info(s);
6547 return libc_sendto(s, buf, len, flags, to, tolen);
6550 tmp.iov_base = discard_const_p(char, buf);
6554 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6555 msg.msg_namelen = tolen; /* size of address */
6556 msg.msg_iov = &tmp; /* scatter/gather array */
6557 msg.msg_iovlen = 1; /* # elements in msg_iov */
6558 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6559 msg.msg_control = NULL; /* ancillary data, see below */
6560 msg.msg_controllen = 0; /* ancillary data buffer len */
6561 msg.msg_flags = 0; /* flags on received message */
6564 rc = swrap_sendmsg_before(s,
6576 buf = msg.msg_iov[0].iov_base;
6577 len = msg.msg_iov[0].iov_len;
6582 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6584 char *swrap_dir = NULL;
6586 type = SOCKET_TYPE_CHAR_UDP;
6588 swrap_dir = socket_wrapper_dir();
6589 if (swrap_dir == NULL) {
6593 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6594 swrap_un_path(&un_addr.sa.un,
6599 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6601 /* ignore the any errors in broadcast sends */
6607 un_addr.sa_socklen);
6610 SAFE_FREE(swrap_dir);
6614 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6616 SWRAP_UNLOCK_SI(si);
6623 * If it is a dgram socket and we are connected, don't include the
6626 if (si->type == SOCK_DGRAM && si->connected) {
6627 ret = libc_sendto(s,
6634 ret = libc_sendto(s,
6638 (struct sockaddr *)msg.msg_name,
6642 SWRAP_UNLOCK_SI(si);
6644 swrap_sendmsg_after(s, si, &msg, to, ret);
6649 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6650 const struct sockaddr *to, socklen_t tolen)
6652 return swrap_sendto(s, buf, len, flags, to, tolen);
6655 /****************************************************************************
6657 ***************************************************************************/
6659 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6661 struct socket_info *si;
6663 struct swrap_address saddr = {
6664 .sa_socklen = sizeof(struct sockaddr_storage),
6670 si = find_socket_info(s);
6672 return libc_recv(s, buf, len, flags);
6679 msg.msg_name = &saddr.sa.s; /* optional address */
6680 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6681 msg.msg_iov = &tmp; /* scatter/gather array */
6682 msg.msg_iovlen = 1; /* # elements in msg_iov */
6683 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6684 msg.msg_control = NULL; /* ancillary data, see below */
6685 msg.msg_controllen = 0; /* ancillary data buffer len */
6686 msg.msg_flags = 0; /* flags on received message */
6689 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6694 buf = msg.msg_iov[0].iov_base;
6695 len = msg.msg_iov[0].iov_len;
6697 ret = libc_recv(s, buf, len, flags);
6699 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6707 ssize_t recv(int s, void *buf, size_t len, int flags)
6709 return swrap_recv(s, buf, len, flags);
6712 /****************************************************************************
6714 ***************************************************************************/
6716 static ssize_t swrap_read(int s, void *buf, size_t len)
6718 struct socket_info *si;
6721 struct swrap_address saddr = {
6722 .sa_socklen = sizeof(struct sockaddr_storage),
6727 si = find_socket_info(s);
6729 return libc_read(s, buf, len);
6736 msg.msg_name = &saddr.sa.ss; /* optional address */
6737 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6738 msg.msg_iov = &tmp; /* scatter/gather array */
6739 msg.msg_iovlen = 1; /* # elements in msg_iov */
6740 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6741 msg.msg_control = NULL; /* ancillary data, see below */
6742 msg.msg_controllen = 0; /* ancillary data buffer len */
6743 msg.msg_flags = 0; /* flags on received message */
6746 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6748 if (tret == -ENOTSOCK) {
6749 return libc_read(s, buf, len);
6754 buf = msg.msg_iov[0].iov_base;
6755 len = msg.msg_iov[0].iov_len;
6757 ret = libc_read(s, buf, len);
6759 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6767 ssize_t read(int s, void *buf, size_t len)
6769 return swrap_read(s, buf, len);
6772 /****************************************************************************
6774 ***************************************************************************/
6776 static ssize_t swrap_write(int s, const void *buf, size_t len)
6780 struct sockaddr_un un_addr;
6783 struct socket_info *si;
6785 si = find_socket_info(s);
6787 return libc_write(s, buf, len);
6790 tmp.iov_base = discard_const_p(char, buf);
6794 msg.msg_name = NULL; /* optional address */
6795 msg.msg_namelen = 0; /* size of address */
6796 msg.msg_iov = &tmp; /* scatter/gather array */
6797 msg.msg_iovlen = 1; /* # elements in msg_iov */
6798 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6799 msg.msg_control = NULL; /* ancillary data, see below */
6800 msg.msg_controllen = 0; /* ancillary data buffer len */
6801 msg.msg_flags = 0; /* flags on received message */
6804 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6809 buf = msg.msg_iov[0].iov_base;
6810 len = msg.msg_iov[0].iov_len;
6812 ret = libc_write(s, buf, len);
6814 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6819 ssize_t write(int s, const void *buf, size_t len)
6821 return swrap_write(s, buf, len);
6824 /****************************************************************************
6826 ***************************************************************************/
6828 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6832 struct sockaddr_un un_addr;
6835 struct socket_info *si = find_socket_info(s);
6838 return libc_send(s, buf, len, flags);
6841 tmp.iov_base = discard_const_p(char, buf);
6845 msg.msg_name = NULL; /* optional address */
6846 msg.msg_namelen = 0; /* size of address */
6847 msg.msg_iov = &tmp; /* scatter/gather array */
6848 msg.msg_iovlen = 1; /* # elements in msg_iov */
6849 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6850 msg.msg_control = NULL; /* ancillary data, see below */
6851 msg.msg_controllen = 0; /* ancillary data buffer len */
6852 msg.msg_flags = 0; /* flags on received message */
6855 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6860 buf = msg.msg_iov[0].iov_base;
6861 len = msg.msg_iov[0].iov_len;
6863 ret = libc_send(s, buf, len, flags);
6865 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6870 ssize_t send(int s, const void *buf, size_t len, int flags)
6872 return swrap_send(s, buf, len, flags);
6875 /****************************************************************************
6877 ***************************************************************************/
6879 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6881 struct swrap_address from_addr = {
6882 .sa_socklen = sizeof(struct sockaddr_un),
6884 struct swrap_address convert_addr = {
6885 .sa_socklen = sizeof(struct sockaddr_storage),
6887 struct socket_info *si;
6890 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6891 size_t msg_ctrllen_filled;
6892 size_t msg_ctrllen_left;
6898 si = find_socket_info(s);
6900 rc = swrap_recvmsg_before_unix(omsg, &msg);
6904 ret = libc_recvmsg(s, &msg, flags);
6905 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6908 tmp.iov_base = NULL;
6912 msg.msg_name = &from_addr.sa; /* optional address */
6913 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6914 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6915 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6916 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6917 msg_ctrllen_filled = 0;
6918 msg_ctrllen_left = omsg->msg_controllen;
6920 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6921 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6922 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6925 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6930 ret = libc_recvmsg(s, &msg, flags);
6932 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6933 msg_ctrllen_filled += msg.msg_controllen;
6934 msg_ctrllen_left -= msg.msg_controllen;
6936 if (omsg->msg_control != NULL) {
6939 p = omsg->msg_control;
6940 p += msg_ctrllen_filled;
6942 msg.msg_control = p;
6943 msg.msg_controllen = msg_ctrllen_left;
6945 msg.msg_control = NULL;
6946 msg.msg_controllen = 0;
6951 * We convert the unix address to a IP address so we need a buffer
6952 * which can store the address in case of SOCK_DGRAM, see below.
6954 msg.msg_name = &convert_addr.sa;
6955 msg.msg_namelen = convert_addr.sa_socklen;
6957 rc = swrap_recvmsg_after(s,
6961 from_addr.sa_socklen,
6967 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6968 if (omsg->msg_control != NULL) {
6969 /* msg.msg_controllen = space left */
6970 msg_ctrllen_left = msg.msg_controllen;
6971 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6974 /* Update the original message length */
6975 omsg->msg_controllen = msg_ctrllen_filled;
6976 omsg->msg_flags = msg.msg_flags;
6978 omsg->msg_iovlen = msg.msg_iovlen;
6985 * The msg_name field points to a caller-allocated buffer that is
6986 * used to return the source address if the socket is unconnected. The
6987 * caller should set msg_namelen to the size of this buffer before this
6988 * call; upon return from a successful call, msg_name will contain the
6989 * length of the returned address. If the application does not need
6990 * to know the source address, msg_name can be specified as NULL.
6992 if (si->type == SOCK_STREAM) {
6993 omsg->msg_namelen = 0;
6994 } else if (omsg->msg_name != NULL &&
6995 omsg->msg_namelen != 0 &&
6996 omsg->msg_namelen >= msg.msg_namelen) {
6997 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6998 omsg->msg_namelen = msg.msg_namelen;
7001 SWRAP_UNLOCK_SI(si);
7006 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7008 return swrap_recvmsg(sockfd, msg, flags);
7011 /****************************************************************************
7013 ***************************************************************************/
7015 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7019 struct sockaddr_un un_addr;
7020 const struct sockaddr_un *to_un = NULL;
7021 const struct sockaddr *to = NULL;
7024 struct socket_info *si = find_socket_info(s);
7028 int scm_rights_pipe_fd = -1;
7030 rc = swrap_sendmsg_before_unix(omsg, &msg,
7031 &scm_rights_pipe_fd);
7035 ret = libc_sendmsg(s, &msg, flags);
7036 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7039 ZERO_STRUCT(un_addr);
7041 tmp.iov_base = NULL;
7048 if (si->connected == 0) {
7049 msg.msg_name = omsg->msg_name; /* optional address */
7050 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7052 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7053 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7055 SWRAP_UNLOCK_SI(si);
7057 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7058 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7059 uint8_t *cmbuf = NULL;
7062 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7068 msg.msg_controllen = 0;
7069 msg.msg_control = NULL;
7071 msg.msg_control = cmbuf;
7072 msg.msg_controllen = cmlen;
7075 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7077 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7079 int saved_errno = errno;
7080 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7081 SAFE_FREE(msg.msg_control);
7083 errno = saved_errno;
7090 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7097 char *swrap_dir = NULL;
7099 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7100 avail += msg.msg_iov[i].iov_len;
7106 /* we capture it as one single packet */
7107 buf = (uint8_t *)malloc(remain);
7109 int saved_errno = errno;
7110 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7111 SAFE_FREE(msg.msg_control);
7113 errno = saved_errno;
7117 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7118 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7120 msg.msg_iov[i].iov_base,
7123 remain -= this_time;
7126 type = SOCKET_TYPE_CHAR_UDP;
7128 swrap_dir = socket_wrapper_dir();
7129 if (swrap_dir == NULL) {
7130 int saved_errno = errno;
7131 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7132 SAFE_FREE(msg.msg_control);
7135 errno = saved_errno;
7139 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7140 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7141 if (stat(un_addr.sun_path, &st) != 0) continue;
7143 msg.msg_name = &un_addr; /* optional address */
7144 msg.msg_namelen = sizeof(un_addr); /* size of address */
7146 /* ignore the any errors in broadcast sends */
7147 libc_sendmsg(s, &msg, flags);
7150 SAFE_FREE(swrap_dir);
7154 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7157 SWRAP_UNLOCK_SI(si);
7162 ret = libc_sendmsg(s, &msg, flags);
7164 swrap_sendmsg_after(s, si, &msg, to, ret);
7166 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7168 int saved_errno = errno;
7169 SAFE_FREE(msg.msg_control);
7170 errno = saved_errno;
7177 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7179 return swrap_sendmsg(s, omsg, flags);
7182 /****************************************************************************
7184 ***************************************************************************/
7186 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7188 struct socket_info *si;
7191 struct swrap_address saddr = {
7192 .sa_socklen = sizeof(struct sockaddr_storage)
7197 si = find_socket_info(s);
7199 return libc_readv(s, vector, count);
7202 tmp.iov_base = NULL;
7206 msg.msg_name = &saddr.sa.s; /* optional address */
7207 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7208 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7209 msg.msg_iovlen = count; /* # elements in msg_iov */
7210 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7211 msg.msg_control = NULL; /* ancillary data, see below */
7212 msg.msg_controllen = 0; /* ancillary data buffer len */
7213 msg.msg_flags = 0; /* flags on received message */
7216 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7218 if (rc == -ENOTSOCK) {
7219 return libc_readv(s, vector, count);
7224 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7226 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7234 ssize_t readv(int s, const struct iovec *vector, int count)
7236 return swrap_readv(s, vector, count);
7239 /****************************************************************************
7241 ***************************************************************************/
7243 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7247 struct sockaddr_un un_addr;
7250 struct socket_info *si = find_socket_info(s);
7253 return libc_writev(s, vector, count);
7256 tmp.iov_base = NULL;
7260 msg.msg_name = NULL; /* optional address */
7261 msg.msg_namelen = 0; /* size of address */
7262 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7263 msg.msg_iovlen = count; /* # elements in msg_iov */
7264 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7265 msg.msg_control = NULL; /* ancillary data, see below */
7266 msg.msg_controllen = 0; /* ancillary data buffer len */
7267 msg.msg_flags = 0; /* flags on received message */
7270 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7272 if (rc == -ENOTSOCK) {
7273 return libc_readv(s, vector, count);
7278 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7280 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7285 ssize_t writev(int s, const struct iovec *vector, int count)
7287 return swrap_writev(s, vector, count);
7290 /****************************
7292 ***************************/
7294 static int swrap_close(int fd)
7296 struct socket_info *si = NULL;
7300 swrap_mutex_lock(&socket_reset_mutex);
7302 si_index = find_socket_info_index(fd);
7303 if (si_index == -1) {
7304 swrap_mutex_unlock(&socket_reset_mutex);
7305 return libc_close(fd);
7308 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7309 reset_socket_info_index(fd);
7311 si = swrap_get_socket_info(si_index);
7313 swrap_mutex_lock(&first_free_mutex);
7316 ret = libc_close(fd);
7318 swrap_dec_refcount(si);
7320 if (swrap_get_refcount(si) > 0) {
7321 /* there are still references left */
7325 if (si->fd_passed) {
7329 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7330 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7333 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7334 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7335 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7338 if (si->un_addr.sun_path[0] != '\0') {
7339 unlink(si->un_addr.sun_path);
7343 swrap_set_next_free(si, first_free);
7344 first_free = si_index;
7347 SWRAP_UNLOCK_SI(si);
7348 swrap_mutex_unlock(&first_free_mutex);
7349 swrap_mutex_unlock(&socket_reset_mutex);
7356 return swrap_close(fd);
7359 /****************************
7361 ***************************/
7363 static int swrap_dup(int fd)
7365 struct socket_info *si;
7368 idx = find_socket_info_index(fd);
7370 return libc_dup(fd);
7373 si = swrap_get_socket_info(idx);
7375 dup_fd = libc_dup(fd);
7377 int saved_errno = errno;
7378 errno = saved_errno;
7382 if ((size_t)dup_fd >= socket_fds_max) {
7383 SWRAP_LOG(SWRAP_LOG_ERROR,
7384 "The max socket index limit of %zu has been reached, "
7395 swrap_inc_refcount(si);
7397 SWRAP_UNLOCK_SI(si);
7399 /* Make sure we don't have an entry for the fd */
7400 swrap_remove_stale(dup_fd);
7402 set_socket_info_index(dup_fd, idx);
7409 return swrap_dup(fd);
7412 /****************************
7414 ***************************/
7416 static int swrap_dup2(int fd, int newfd)
7418 struct socket_info *si;
7421 idx = find_socket_info_index(fd);
7423 return libc_dup2(fd, newfd);
7426 si = swrap_get_socket_info(idx);
7430 * According to the manpage:
7432 * "If oldfd is a valid file descriptor, and newfd has the same
7433 * value as oldfd, then dup2() does nothing, and returns newfd."
7438 if ((size_t)newfd >= socket_fds_max) {
7439 SWRAP_LOG(SWRAP_LOG_ERROR,
7440 "The max socket index limit of %zu has been reached, "
7448 if (find_socket_info(newfd)) {
7449 /* dup2() does an implicit close of newfd, which we
7450 * need to emulate */
7454 dup_fd = libc_dup2(fd, newfd);
7456 int saved_errno = errno;
7457 errno = saved_errno;
7463 swrap_inc_refcount(si);
7465 SWRAP_UNLOCK_SI(si);
7467 /* Make sure we don't have an entry for the fd */
7468 swrap_remove_stale(dup_fd);
7470 set_socket_info_index(dup_fd, idx);
7475 int dup2(int fd, int newfd)
7477 return swrap_dup2(fd, newfd);
7480 /****************************
7482 ***************************/
7484 static int swrap_vfcntl(int fd, int cmd, va_list va)
7486 struct socket_info *si;
7487 int rc, dup_fd, idx;
7489 idx = find_socket_info_index(fd);
7491 return libc_vfcntl(fd, cmd, va);
7494 si = swrap_get_socket_info(idx);
7498 dup_fd = libc_vfcntl(fd, cmd, va);
7500 int saved_errno = errno;
7501 errno = saved_errno;
7505 /* Make sure we don't have an entry for the fd */
7506 swrap_remove_stale(dup_fd);
7508 if ((size_t)dup_fd >= socket_fds_max) {
7509 SWRAP_LOG(SWRAP_LOG_ERROR,
7510 "The max socket index limit of %zu has been reached, "
7521 swrap_inc_refcount(si);
7523 SWRAP_UNLOCK_SI(si);
7526 set_socket_info_index(dup_fd, idx);
7531 rc = libc_vfcntl(fd, cmd, va);
7538 int fcntl(int fd, int cmd, ...)
7545 rc = swrap_vfcntl(fd, cmd, va);
7552 /****************************
7554 ***************************/
7557 static int swrap_eventfd(int count, int flags)
7561 fd = libc_eventfd(count, flags);
7563 swrap_remove_stale(fd);
7569 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7570 int eventfd(unsigned int count, int flags)
7572 int eventfd(int count, int flags)
7575 return swrap_eventfd(count, flags);
7580 int pledge(const char *promises, const char *paths[])
7582 (void)promises; /* unused */
7583 (void)paths; /* unused */
7587 #endif /* HAVE_PLEDGE */
7589 static void swrap_thread_prepare(void)
7592 * This function should only be called here!!
7594 * We bind all symobls to avoid deadlocks of the fork is
7595 * interrupted by a signal handler using a symbol of this
7598 swrap_bind_symbol_all();
7603 static void swrap_thread_parent(void)
7608 static void swrap_thread_child(void)
7613 /****************************
7615 ***************************/
7616 void swrap_constructor(void)
7618 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7619 SWRAP_LOG(SWRAP_LOG_ERROR,
7621 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7622 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7623 "sizeof(struct socket_info)=%zu",
7625 sizeof(struct swrap_unix_scm_rights),
7626 sizeof(struct swrap_unix_scm_rights_payload),
7627 sizeof(struct socket_info));
7634 * If we hold a lock and the application forks, then the child
7635 * is not able to unlock the mutex and we are in a deadlock.
7636 * This should prevent such deadlocks.
7638 pthread_atfork(&swrap_thread_prepare,
7639 &swrap_thread_parent,
7640 &swrap_thread_child);
7643 /****************************
7645 ***************************/
7648 * This function is called when the library is unloaded and makes sure that
7649 * sockets get closed and the unix file for the socket are unlinked.
7651 void swrap_destructor(void)
7655 if (socket_fds_idx != NULL) {
7656 for (i = 0; i < socket_fds_max; ++i) {
7657 if (socket_fds_idx[i] != -1) {
7661 SAFE_FREE(socket_fds_idx);
7666 if (swrap.libc.handle != NULL) {
7667 dlclose(swrap.libc.handle);
7669 if (swrap.libc.socket_handle) {
7670 dlclose(swrap.libc.socket_handle);
7674 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7676 * On FreeBSD 12 (and maybe other platforms)
7677 * system libraries like libresolv prefix there
7678 * syscalls with '_' in order to always use
7679 * the symbols from libc.
7681 * In the interaction with resolv_wrapper,
7682 * we need to inject socket wrapper into libresolv,
7683 * which means we need to private all socket
7684 * related syscalls also with the '_' prefix.
7686 * This is tested in Samba's 'make test',
7687 * there we noticed that providing '_read'
7688 * and '_open' would cause errors, which
7689 * means we skip '_read', '_write' and
7690 * all non socket related calls without
7691 * further analyzing the problem.
7693 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7694 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7697 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7699 SWRAP_SYMBOL_ALIAS(accept, _accept);
7700 SWRAP_SYMBOL_ALIAS(bind, _bind);
7701 SWRAP_SYMBOL_ALIAS(close, _close);
7702 SWRAP_SYMBOL_ALIAS(connect, _connect);
7703 SWRAP_SYMBOL_ALIAS(dup, _dup);
7704 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7705 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7706 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7707 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7708 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7709 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7710 SWRAP_SYMBOL_ALIAS(listen, _listen);
7711 SWRAP_SYMBOL_ALIAS(readv, _readv);
7712 SWRAP_SYMBOL_ALIAS(recv, _recv);
7713 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7714 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7715 SWRAP_SYMBOL_ALIAS(send, _send);
7716 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7717 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7718 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7719 SWRAP_SYMBOL_ALIAS(socket, _socket);
7720 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7721 SWRAP_SYMBOL_ALIAS(writev, _writev);
7723 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */