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 if (errno == ENOTSOCK) {
3646 /* Remove stale fds */
3647 swrap_remove_stale(s);
3654 /* Check if we have a stale fd and remove it */
3655 swrap_remove_stale(fd);
3657 SWRAP_LOCK_SI(parent_si);
3659 ret = sockaddr_convert_from_un(parent_si,
3664 &in_addr.sa_socklen);
3666 SWRAP_UNLOCK_SI(parent_si);
3673 child_si->family = parent_si->family;
3674 child_si->type = parent_si->type;
3675 child_si->protocol = parent_si->protocol;
3676 child_si->bound = 1;
3677 child_si->is_server = 1;
3678 child_si->connected = 1;
3680 SWRAP_UNLOCK_SI(parent_si);
3682 child_si->peername = (struct swrap_address) {
3683 .sa_socklen = in_addr.sa_socklen,
3685 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3687 if (addr != NULL && addrlen != NULL) {
3688 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3690 memcpy(addr, &in_addr.sa.ss, copy_len);
3692 *addrlen = in_addr.sa_socklen;
3695 ret = libc_getsockname(fd,
3697 &un_my_addr.sa_socklen);
3703 ret = sockaddr_convert_from_un(child_si,
3705 un_my_addr.sa_socklen,
3708 &in_my_addr.sa_socklen);
3714 SWRAP_LOG(SWRAP_LOG_TRACE,
3715 "accept() path=%s, fd=%d",
3716 un_my_addr.sa.un.sun_path, s);
3718 child_si->myname = (struct swrap_address) {
3719 .sa_socklen = in_my_addr.sa_socklen,
3721 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3723 idx = swrap_create_socket(&new_si, fd);
3725 int saved_errno = errno;
3727 errno = saved_errno;
3732 struct socket_info *si = swrap_get_socket_info(idx);
3735 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3736 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3737 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3738 SWRAP_UNLOCK_SI(si);
3745 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3747 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3751 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3752 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3754 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3757 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3760 static int autobind_start_init;
3761 static int autobind_start;
3763 /* using sendto() or connect() on an unbound socket would give the
3764 recipient no way to reply, as unlike UDP and TCP, a unix domain
3765 socket can't auto-assign ephemeral port numbers, so we need to
3767 Note: this might change the family from ipv6 to ipv4
3769 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3771 struct swrap_address un_addr = {
3772 .sa_socklen = sizeof(struct sockaddr_un),
3779 char *swrap_dir = NULL;
3781 swrap_mutex_lock(&autobind_start_mutex);
3783 if (autobind_start_init != 1) {
3784 autobind_start_init = 1;
3785 autobind_start = getpid();
3786 autobind_start %= 50000;
3787 autobind_start += 10000;
3790 un_addr.sa.un.sun_family = AF_UNIX;
3794 struct sockaddr_in in;
3798 type = SOCKET_TYPE_CHAR_TCP;
3801 type = SOCKET_TYPE_CHAR_UDP;
3804 errno = ESOCKTNOSUPPORT;
3809 memset(&in, 0, sizeof(in));
3810 in.sin_family = AF_INET;
3811 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3812 socket_wrapper_default_iface()));
3814 si->myname = (struct swrap_address) {
3815 .sa_socklen = sizeof(in),
3817 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3822 struct sockaddr_in6 in6;
3824 if (si->family != family) {
3825 errno = ENETUNREACH;
3832 type = SOCKET_TYPE_CHAR_TCP_V6;
3835 type = SOCKET_TYPE_CHAR_UDP_V6;
3838 errno = ESOCKTNOSUPPORT;
3843 memset(&in6, 0, sizeof(in6));
3844 in6.sin6_family = AF_INET6;
3845 in6.sin6_addr = *swrap_ipv6();
3846 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3848 si->myname = (struct swrap_address) {
3849 .sa_socklen = sizeof(in6),
3851 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3856 errno = ESOCKTNOSUPPORT;
3861 if (autobind_start > 60000) {
3862 autobind_start = 10000;
3865 swrap_dir = socket_wrapper_dir();
3866 if (swrap_dir == NULL) {
3872 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3873 port = autobind_start + i;
3874 swrap_un_path(&un_addr.sa.un,
3877 socket_wrapper_default_iface(),
3879 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3881 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3886 si->un_addr = un_addr.sa.un;
3889 autobind_start = port + 1;
3892 if (i == SOCKET_MAX_SOCKETS) {
3893 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3894 "interface "SOCKET_FORMAT,
3897 socket_wrapper_default_iface(),
3904 si->family = family;
3905 set_port(si->family, port, &si->myname);
3910 SAFE_FREE(swrap_dir);
3911 swrap_mutex_unlock(&autobind_start_mutex);
3915 /****************************************************************************
3917 ***************************************************************************/
3919 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3923 struct swrap_address un_addr = {
3924 .sa_socklen = sizeof(struct sockaddr_un),
3926 struct socket_info *si = find_socket_info(s);
3930 return libc_connect(s, serv_addr, addrlen);
3935 if (si->bound == 0) {
3936 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3942 if (si->family != serv_addr->sa_family) {
3943 SWRAP_LOG(SWRAP_LOG_ERROR,
3944 "called for fd=%d (family=%d) called with invalid family=%d",
3945 s, si->family, serv_addr->sa_family);
3951 ret = sockaddr_convert_to_un(si, serv_addr,
3952 addrlen, &un_addr.sa.un, 0, &bcast);
3958 errno = ENETUNREACH;
3963 if (si->type == SOCK_DGRAM) {
3964 si->defer_connect = 1;
3967 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3969 ret = libc_connect(s,
3971 un_addr.sa_socklen);
3974 SWRAP_LOG(SWRAP_LOG_TRACE,
3975 "connect() path=%s, fd=%d",
3976 un_addr.sa.un.sun_path, s);
3979 /* to give better errors */
3980 if (ret == -1 && errno == ENOENT) {
3981 errno = EHOSTUNREACH;
3985 si->peername = (struct swrap_address) {
3986 .sa_socklen = addrlen,
3989 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3993 * When we connect() on a socket than we have to bind the
3994 * outgoing connection on the interface we use for the
3995 * transport. We already bound it on the right interface
3996 * but here we have to update the name so getsockname()
3997 * returns correct information.
3999 if (si->bindname.sa_socklen > 0) {
4000 si->myname = (struct swrap_address) {
4001 .sa_socklen = si->bindname.sa_socklen,
4004 memcpy(&si->myname.sa.ss,
4005 &si->bindname.sa.ss,
4006 si->bindname.sa_socklen);
4008 /* Cleanup bindname */
4009 si->bindname = (struct swrap_address) {
4014 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4015 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4017 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4021 SWRAP_UNLOCK_SI(si);
4025 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4027 return swrap_connect(s, serv_addr, addrlen);
4030 /****************************************************************************
4032 ***************************************************************************/
4034 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4037 struct swrap_address un_addr = {
4038 .sa_socklen = sizeof(struct sockaddr_un),
4040 struct socket_info *si = find_socket_info(s);
4047 return libc_bind(s, myaddr, addrlen);
4052 switch (si->family) {
4054 const struct sockaddr_in *sin;
4055 if (addrlen < sizeof(struct sockaddr_in)) {
4056 bind_error = EINVAL;
4060 sin = (const struct sockaddr_in *)(const void *)myaddr;
4062 if (sin->sin_family != AF_INET) {
4063 bind_error = EAFNOSUPPORT;
4066 /* special case for AF_UNSPEC */
4067 if (sin->sin_family == AF_UNSPEC &&
4068 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4077 const struct sockaddr_in6 *sin6;
4078 if (addrlen < sizeof(struct sockaddr_in6)) {
4079 bind_error = EINVAL;
4083 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4085 if (sin6->sin6_family != AF_INET6) {
4086 bind_error = EAFNOSUPPORT;
4093 bind_error = EINVAL;
4097 if (bind_error != 0) {
4104 in_use = check_addr_port_in_use(myaddr, addrlen);
4112 si->myname.sa_socklen = addrlen;
4113 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4115 ret = sockaddr_convert_to_un(si,
4125 unlink(un_addr.sa.un.sun_path);
4127 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4129 SWRAP_LOG(SWRAP_LOG_TRACE,
4130 "bind() path=%s, fd=%d",
4131 un_addr.sa.un.sun_path, s);
4138 SWRAP_UNLOCK_SI(si);
4143 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4145 return swrap_bind(s, myaddr, addrlen);
4148 /****************************************************************************
4150 ***************************************************************************/
4152 #ifdef HAVE_BINDRESVPORT
4153 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4155 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4157 struct swrap_address myaddr = {
4158 .sa_socklen = sizeof(struct sockaddr_storage),
4161 static uint16_t port;
4166 #define SWRAP_STARTPORT 600
4167 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4168 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4171 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4175 salen = myaddr.sa_socklen;
4178 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4184 memset(&myaddr.sa.ss, 0, salen);
4189 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4192 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4194 salen = sizeof(struct sockaddr_in);
4195 sinp->sin_port = htons(port);
4199 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4201 salen = sizeof(struct sockaddr_in6);
4202 sin6p->sin6_port = htons(port);
4206 errno = EAFNOSUPPORT;
4211 if (port > SWRAP_ENDPORT) {
4212 port = SWRAP_STARTPORT;
4215 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4216 if (rc == 0 || errno != EADDRINUSE) {
4224 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4226 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4230 /****************************************************************************
4232 ***************************************************************************/
4234 static int swrap_listen(int s, int backlog)
4237 struct socket_info *si = find_socket_info(s);
4240 return libc_listen(s, backlog);
4245 if (si->bound == 0) {
4246 ret = swrap_auto_bind(s, si, si->family);
4253 ret = libc_listen(s, backlog);
4259 SWRAP_UNLOCK_SI(si);
4264 int listen(int s, int backlog)
4266 return swrap_listen(s, backlog);
4269 /****************************************************************************
4271 ***************************************************************************/
4273 static FILE *swrap_fopen(const char *name, const char *mode)
4277 fp = libc_fopen(name, mode);
4279 int fd = fileno(fp);
4281 swrap_remove_stale(fd);
4287 FILE *fopen(const char *name, const char *mode)
4289 return swrap_fopen(name, mode);
4292 /****************************************************************************
4294 ***************************************************************************/
4297 static FILE *swrap_fopen64(const char *name, const char *mode)
4301 fp = libc_fopen64(name, mode);
4303 int fd = fileno(fp);
4305 swrap_remove_stale(fd);
4311 FILE *fopen64(const char *name, const char *mode)
4313 return swrap_fopen64(name, mode);
4315 #endif /* HAVE_FOPEN64 */
4317 /****************************************************************************
4319 ***************************************************************************/
4321 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4325 ret = libc_vopen(pathname, flags, ap);
4328 * There are methods for closing descriptors (libc-internal code
4329 * paths, direct syscalls) which close descriptors in ways that
4330 * we can't intercept, so try to recover when we notice that
4333 swrap_remove_stale(ret);
4338 int open(const char *pathname, int flags, ...)
4343 va_start(ap, flags);
4344 fd = swrap_vopen(pathname, flags, ap);
4350 /****************************************************************************
4352 ***************************************************************************/
4355 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4359 ret = libc_vopen64(pathname, flags, ap);
4362 * There are methods for closing descriptors (libc-internal code
4363 * paths, direct syscalls) which close descriptors in ways that
4364 * we can't intercept, so try to recover when we notice that
4367 swrap_remove_stale(ret);
4372 int open64(const char *pathname, int flags, ...)
4377 va_start(ap, flags);
4378 fd = swrap_vopen64(pathname, flags, ap);
4383 #endif /* HAVE_OPEN64 */
4385 /****************************************************************************
4387 ***************************************************************************/
4389 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4393 ret = libc_vopenat(dirfd, path, flags, ap);
4396 * There are methods for closing descriptors (libc-internal code
4397 * paths, direct syscalls) which close descriptors in ways that
4398 * we can't intercept, so try to recover when we notice that
4401 swrap_remove_stale(ret);
4407 int openat(int dirfd, const char *path, int flags, ...)
4412 va_start(ap, flags);
4413 fd = swrap_vopenat(dirfd, path, flags, ap);
4419 /****************************************************************************
4421 ***************************************************************************/
4423 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4425 struct socket_info *si = find_socket_info(s);
4430 return libc_getpeername(s, name, addrlen);
4435 if (si->peername.sa_socklen == 0)
4441 len = MIN(*addrlen, si->peername.sa_socklen);
4447 memcpy(name, &si->peername.sa.ss, len);
4448 *addrlen = si->peername.sa_socklen;
4452 SWRAP_UNLOCK_SI(si);
4457 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4458 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4460 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4463 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4466 /****************************************************************************
4468 ***************************************************************************/
4470 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4472 struct socket_info *si = find_socket_info(s);
4477 return libc_getsockname(s, name, addrlen);
4482 len = MIN(*addrlen, si->myname.sa_socklen);
4488 memcpy(name, &si->myname.sa.ss, len);
4489 *addrlen = si->myname.sa_socklen;
4493 SWRAP_UNLOCK_SI(si);
4498 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4499 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4501 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4504 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4507 /****************************************************************************
4509 ***************************************************************************/
4512 # ifdef SO_PROTOTYPE /* The Solaris name */
4513 # define SO_PROTOCOL SO_PROTOTYPE
4514 # endif /* SO_PROTOTYPE */
4515 #endif /* SO_PROTOCOL */
4517 static int swrap_getsockopt(int s, int level, int optname,
4518 void *optval, socklen_t *optlen)
4520 struct socket_info *si = find_socket_info(s);
4524 return libc_getsockopt(s,
4533 if (level == SOL_SOCKET) {
4537 if (optval == NULL || optlen == NULL ||
4538 *optlen < (socklen_t)sizeof(int)) {
4544 *optlen = sizeof(int);
4545 *(int *)optval = si->family;
4548 #endif /* SO_DOMAIN */
4552 if (optval == NULL || optlen == NULL ||
4553 *optlen < (socklen_t)sizeof(int)) {
4559 *optlen = sizeof(int);
4560 *(int *)optval = si->protocol;
4563 #endif /* SO_PROTOCOL */
4565 if (optval == NULL || optlen == NULL ||
4566 *optlen < (socklen_t)sizeof(int)) {
4572 *optlen = sizeof(int);
4573 *(int *)optval = si->type;
4577 ret = libc_getsockopt(s,
4584 } else if (level == IPPROTO_TCP) {
4589 * This enables sending packets directly out over TCP.
4590 * As a unix socket is doing that any way, report it as
4593 if (optval == NULL || optlen == NULL ||
4594 *optlen < (socklen_t)sizeof(int)) {
4600 *optlen = sizeof(int);
4601 *(int *)optval = si->tcp_nodelay;
4605 #endif /* TCP_NODELAY */
4608 struct tcp_info info;
4609 socklen_t ilen = sizeof(info);
4611 #ifdef HAVE_NETINET_TCP_FSM_H
4612 /* This is FreeBSD */
4613 # define __TCP_LISTEN TCPS_LISTEN
4614 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4615 # define __TCP_CLOSE TCPS_CLOSED
4618 # define __TCP_LISTEN TCP_LISTEN
4619 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4620 # define __TCP_CLOSE TCP_CLOSE
4624 if (si->listening) {
4625 info.tcpi_state = __TCP_LISTEN;
4626 } else if (si->connected) {
4628 * For now we just fake a few values
4629 * supported both by FreeBSD and Linux
4631 info.tcpi_state = __TCP_ESTABLISHED;
4632 info.tcpi_rto = 200000; /* 200 msec */
4633 info.tcpi_rtt = 5000; /* 5 msec */
4634 info.tcpi_rttvar = 5000; /* 5 msec */
4636 info.tcpi_state = __TCP_CLOSE;
4637 info.tcpi_rto = 1000000; /* 1 sec */
4639 info.tcpi_rttvar = 250000; /* 250 msec */
4642 if (optval == NULL || optlen == NULL ||
4643 *optlen < (socklen_t)ilen) {
4650 memcpy(optval, &info, ilen);
4655 #endif /* TCP_INFO */
4661 errno = ENOPROTOOPT;
4665 SWRAP_UNLOCK_SI(si);
4669 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4670 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4672 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4675 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4678 /****************************************************************************
4680 ***************************************************************************/
4682 static int swrap_setsockopt(int s, int level, int optname,
4683 const void *optval, socklen_t optlen)
4685 struct socket_info *si = find_socket_info(s);
4689 return libc_setsockopt(s,
4696 if (level == SOL_SOCKET) {
4697 return libc_setsockopt(s,
4706 if (level == IPPROTO_TCP) {
4713 * This enables sending packets directly out over TCP.
4714 * A unix socket is doing that any way.
4716 if (optval == NULL || optlen == 0 ||
4717 optlen < (socklen_t)sizeof(int)) {
4723 i = *discard_const_p(int, optval);
4724 if (i != 0 && i != 1) {
4729 si->tcp_nodelay = i;
4734 #endif /* TCP_NODELAY */
4740 switch (si->family) {
4742 if (level == IPPROTO_IP) {
4744 if (optname == IP_PKTINFO) {
4745 si->pktinfo = AF_INET;
4747 #endif /* IP_PKTINFO */
4753 if (level == IPPROTO_IPV6) {
4754 #ifdef IPV6_RECVPKTINFO
4755 if (optname == IPV6_RECVPKTINFO) {
4756 si->pktinfo = AF_INET6;
4758 #endif /* IPV6_PKTINFO */
4764 errno = ENOPROTOOPT;
4770 SWRAP_UNLOCK_SI(si);
4774 int setsockopt(int s, int level, int optname,
4775 const void *optval, socklen_t optlen)
4777 return swrap_setsockopt(s, level, optname, optval, optlen);
4780 /****************************************************************************
4782 ***************************************************************************/
4784 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4786 struct socket_info *si = find_socket_info(s);
4788 int *value_ptr = NULL;
4792 return libc_vioctl(s, r, va);
4799 rc = libc_vioctl(s, r, va);
4804 value_ptr = ((int *)va_arg(ap, int *));
4807 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4808 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4809 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4810 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4815 /* this is FreeBSD */
4816 FALL_THROUGH; /* to TIOCOUTQ */
4817 #endif /* FIONWRITE */
4818 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4820 * This may return more bytes then the application
4821 * sent into the socket, for tcp it should
4822 * return the number of unacked bytes.
4824 * On AF_UNIX, all bytes are immediately acked!
4827 value_ptr = ((int *)va_arg(ap, int *));
4835 SWRAP_UNLOCK_SI(si);
4839 #ifdef HAVE_IOCTL_INT
4840 int ioctl(int s, int r, ...)
4842 int ioctl(int s, unsigned long int r, ...)
4850 rc = swrap_vioctl(s, (unsigned long int) r, va);
4861 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4864 # ifdef _ALIGN /* BSD */
4865 #define CMSG_ALIGN _ALIGN
4867 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4868 # endif /* _ALIGN */
4869 #endif /* CMSG_ALIGN */
4872 * @brief Add a cmsghdr to a msghdr.
4874 * This is an function to add any type of cmsghdr. It will operate on the
4875 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4876 * the buffer position after the added cmsg element. Hence, this function is
4877 * intended to be used with an intermediate msghdr and not on the original
4878 * one handed in by the client.
4880 * @param[in] msg The msghdr to which to add the cmsg.
4882 * @param[in] level The cmsg level to set.
4884 * @param[in] type The cmsg type to set.
4886 * @param[in] data The cmsg data to set.
4888 * @param[in] len the length of the data to set.
4890 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4896 size_t cmlen = CMSG_LEN(len);
4897 size_t cmspace = CMSG_SPACE(len);
4898 uint8_t cmbuf[cmspace];
4899 void *cast_ptr = (void *)cmbuf;
4900 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4903 memset(cmbuf, 0, cmspace);
4905 if (msg->msg_controllen < cmlen) {
4906 cmlen = msg->msg_controllen;
4907 msg->msg_flags |= MSG_CTRUNC;
4910 if (msg->msg_controllen < cmspace) {
4911 cmspace = msg->msg_controllen;
4915 * We copy the full input data into an intermediate cmsghdr first
4916 * in order to more easily cope with truncation.
4918 cm->cmsg_len = cmlen;
4919 cm->cmsg_level = level;
4920 cm->cmsg_type = type;
4921 memcpy(CMSG_DATA(cm), data, len);
4924 * We now copy the possibly truncated buffer.
4925 * We copy cmlen bytes, but consume cmspace bytes,
4926 * leaving the possible padding uninitialiazed.
4928 p = (uint8_t *)msg->msg_control;
4929 memcpy(p, cm, cmlen);
4931 msg->msg_control = p;
4932 msg->msg_controllen -= cmspace;
4937 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4940 /* Add packet info */
4941 switch (si->pktinfo) {
4942 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4944 struct sockaddr_in *sin;
4945 #if defined(HAVE_STRUCT_IN_PKTINFO)
4946 struct in_pktinfo pkt;
4947 #elif defined(IP_RECVDSTADDR)
4951 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4952 sin = &si->bindname.sa.in;
4954 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4957 sin = &si->myname.sa.in;
4962 #if defined(HAVE_STRUCT_IN_PKTINFO)
4963 pkt.ipi_ifindex = socket_wrapper_default_iface();
4964 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4965 #elif defined(IP_RECVDSTADDR)
4966 pkt = sin->sin_addr;
4969 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4974 #endif /* IP_PKTINFO */
4975 #if defined(HAVE_IPV6)
4977 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4978 struct sockaddr_in6 *sin6;
4979 struct in6_pktinfo pkt6;
4981 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4982 sin6 = &si->bindname.sa.in6;
4984 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4987 sin6 = &si->myname.sa.in6;
4992 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4993 pkt6.ipi6_addr = sin6->sin6_addr;
4995 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4996 &pkt6, sizeof(pkt6));
4997 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5001 #endif /* IPV6_PKTINFO */
5009 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5010 struct msghdr *omsg)
5014 if (si->pktinfo > 0) {
5015 rc = swrap_msghdr_add_pktinfo(si, omsg);
5021 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5023 size_t *cm_data_space);
5024 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5026 size_t *cm_data_space);
5027 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5029 size_t *cm_data_space);
5031 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5033 size_t *cm_data_space)
5035 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5036 struct cmsghdr *cmsg;
5040 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5044 for (cmsg = CMSG_FIRSTHDR(msg);
5046 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5047 switch (cmsg->cmsg_level) {
5049 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5054 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5059 rc = swrap_sendmsg_copy_cmsg(cmsg,
5065 int saved_errno = errno;
5066 SAFE_FREE(*cm_data);
5068 errno = saved_errno;
5076 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5078 size_t *cm_data_space)
5083 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5085 p = realloc((*cm_data), cmspace);
5091 p = (*cm_data) + (*cm_data_space);
5092 *cm_data_space = cmspace;
5094 memcpy(p, cmsg, cmsg->cmsg_len);
5099 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5101 size_t *cm_data_space);
5104 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5106 size_t *cm_data_space)
5110 switch(cmsg->cmsg_type) {
5113 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5120 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5132 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5134 size_t *cm_data_space)
5136 (void)cmsg; /* unused */
5137 (void)cm_data; /* unused */
5138 (void)cm_data_space; /* unused */
5141 * Passing a IP pktinfo to a unix socket might be rejected by the
5142 * Kernel, at least on FreeBSD. So skip this cmsg.
5147 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5149 size_t *cm_data_space)
5153 switch (cmsg->cmsg_type) {
5155 SWRAP_LOG(SWRAP_LOG_TRACE,
5156 "Ignoring SCM_RIGHTS on inet socket!");
5159 #ifdef SCM_CREDENTIALS
5160 case SCM_CREDENTIALS:
5161 SWRAP_LOG(SWRAP_LOG_TRACE,
5162 "Ignoring SCM_CREDENTIALS on inet socket!");
5165 #endif /* SCM_CREDENTIALS */
5167 rc = swrap_sendmsg_copy_cmsg(cmsg,
5176 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5179 * We only allow up to 6 fds at a time
5180 * as that's more than enough for Samba
5181 * and it means we can keep the logic simple
5182 * and work with fixed size arrays.
5184 * We also keep sizeof(struct swrap_unix_scm_rights)
5185 * under PIPE_BUF (4096) in order to allow a non-blocking
5186 * write into the pipe.
5189 #define PIPE_BUF 4096
5191 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5192 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5193 struct swrap_unix_scm_rights_payload {
5195 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5196 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5198 struct swrap_unix_scm_rights {
5200 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5201 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5203 uint32_t payload_size;
5204 struct swrap_unix_scm_rights_payload payload;
5207 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5209 int saved_errno = errno;
5212 for (i = 0; i < num; i++) {
5213 struct socket_info *si = array[i];
5219 swrap_dec_refcount(si);
5220 if (si->fd_passed > 0) {
5223 SWRAP_UNLOCK_SI(si);
5227 errno = saved_errno;
5230 static void swrap_undo_si_idx_array(size_t num, int *array)
5232 int saved_errno = errno;
5235 swrap_mutex_lock(&first_free_mutex);
5237 for (i = 0; i < num; i++) {
5238 struct socket_info *si = NULL;
5240 if (array[i] == -1) {
5244 si = swrap_get_socket_info(array[i]);
5250 swrap_dec_refcount(si);
5251 SWRAP_UNLOCK_SI(si);
5253 swrap_set_next_free(si, first_free);
5254 first_free = array[i];
5258 swrap_mutex_unlock(&first_free_mutex);
5259 errno = saved_errno;
5262 static void swrap_close_fd_array(size_t num, const int *array)
5264 int saved_errno = errno;
5267 for (i = 0; i < num; i++) {
5268 if (array[i] == -1) {
5271 libc_close(array[i]);
5274 errno = saved_errno;
5282 union __swrap_cmsghdr {
5284 struct cmsghdr *cmsg;
5287 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5289 size_t *cm_data_space,
5290 int *scm_rights_pipe_fd)
5292 struct swrap_unix_scm_rights info;
5293 struct swrap_unix_scm_rights_payload *payload = NULL;
5294 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5295 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5296 size_t info_idx = 0;
5299 union __swrap_fds __fds_in = { .p = NULL, };
5300 const int *fds_in = NULL;
5302 size_t size_fds_out;
5303 union __swrap_fds __fds_out = { .p = NULL, };
5304 int *fds_out = NULL;
5307 size_t new_cm_data_space;
5308 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5309 struct cmsghdr *new_cmsg = NULL;
5312 int pipefd[2] = { -1, -1 };
5317 * We pass this a buffer to the kernel make sure any padding
5321 info.magic = swrap_unix_scm_right_magic;
5322 memcpy(info.package_name,
5323 SOCKET_WRAPPER_PACKAGE,
5324 sizeof(info.package_name));
5325 memcpy(info.package_version,
5326 SOCKET_WRAPPER_VERSION,
5327 sizeof(info.package_version));
5328 info.full_size = sizeof(info);
5329 info.payload_size = sizeof(info.payload);
5330 payload = &info.payload;
5332 if (*scm_rights_pipe_fd != -1) {
5333 SWRAP_LOG(SWRAP_LOG_ERROR,
5334 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5339 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5340 SWRAP_LOG(SWRAP_LOG_ERROR,
5341 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5342 (size_t)cmsg->cmsg_len,
5347 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5348 if ((size_fds_in % sizeof(int)) != 0) {
5349 SWRAP_LOG(SWRAP_LOG_ERROR,
5350 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5351 (size_t)cmsg->cmsg_len,
5357 num_fds_in = size_fds_in / sizeof(int);
5358 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5359 SWRAP_LOG(SWRAP_LOG_ERROR,
5360 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5362 "SWRAP_MAX_PASSED_FDS(%zu)",
5363 (size_t)cmsg->cmsg_len,
5366 SWRAP_MAX_PASSED_FDS);
5370 if (num_fds_in == 0) {
5371 SWRAP_LOG(SWRAP_LOG_ERROR,
5372 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5374 (size_t)cmsg->cmsg_len,
5380 __fds_in.p = CMSG_DATA(cmsg);
5381 fds_in = __fds_in.fds;
5382 num_fds_out = num_fds_in + 1;
5384 SWRAP_LOG(SWRAP_LOG_TRACE,
5385 "num_fds_in=%zu num_fds_out=%zu",
5386 num_fds_in, num_fds_out);
5388 size_fds_out = sizeof(int) * num_fds_out;
5389 cmsg_len = CMSG_LEN(size_fds_out);
5390 cmsg_space = CMSG_SPACE(size_fds_out);
5392 new_cm_data_space = *cm_data_space + cmsg_space;
5394 p = realloc((*cm_data), new_cm_data_space);
5399 p = (*cm_data) + (*cm_data_space);
5400 memset(p, 0, cmsg_space);
5402 new_cmsg = __new_cmsg.cmsg;
5404 __fds_out.p = CMSG_DATA(new_cmsg);
5405 fds_out = __fds_out.fds;
5406 memcpy(fds_out, fds_in, size_fds_out);
5407 new_cmsg->cmsg_len = cmsg->cmsg_len;
5409 for (i = 0; i < num_fds_in; i++) {
5412 payload->idxs[i] = -1;
5413 payload->num_idxs++;
5415 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5416 if (si_idx_array[i] == -1) {
5420 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5421 if (si_array[i] == NULL) {
5422 SWRAP_LOG(SWRAP_LOG_ERROR,
5423 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5424 i, fds_in[i], i, si_idx_array[i]);
5429 for (j = 0; j < i; j++) {
5430 if (si_array[j] == si_array[i]) {
5431 payload->idxs[i] = payload->idxs[j];
5435 if (payload->idxs[i] == -1) {
5436 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5437 SWRAP_LOG(SWRAP_LOG_ERROR,
5438 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5439 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5440 i, fds_in[i], i, si_idx_array[i],
5442 SWRAP_MAX_PASSED_SOCKET_INFO);
5446 payload->idxs[i] = info_idx;
5452 for (i = 0; i < num_fds_in; i++) {
5453 struct socket_info *si = si_array[i];
5456 SWRAP_LOG(SWRAP_LOG_TRACE,
5457 "fds_in[%zu]=%d not an inet socket",
5462 SWRAP_LOG(SWRAP_LOG_TRACE,
5463 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5464 "passing as info.idxs[%zu]=%d!",
5467 i, payload->idxs[i]);
5471 payload->infos[payload->idxs[i]] = *si;
5472 payload->infos[payload->idxs[i]].fd_passed = 0;
5473 SWRAP_UNLOCK_SI(si);
5478 int saved_errno = errno;
5479 SWRAP_LOG(SWRAP_LOG_ERROR,
5480 "pipe() failed - %d %s",
5482 strerror(saved_errno));
5483 swrap_dec_fd_passed_array(num_fds_in, si_array);
5484 errno = saved_errno;
5488 sret = write(pipefd[1], &info, sizeof(info));
5489 if (sret != sizeof(info)) {
5490 int saved_errno = errno;
5492 saved_errno = EINVAL;
5494 SWRAP_LOG(SWRAP_LOG_ERROR,
5495 "write() failed - sret=%zd - %d %s",
5497 strerror(saved_errno));
5498 swrap_dec_fd_passed_array(num_fds_in, si_array);
5499 libc_close(pipefd[1]);
5500 libc_close(pipefd[0]);
5501 errno = saved_errno;
5504 libc_close(pipefd[1]);
5507 * Add the pipe read end to the end of the passed fd array
5509 fds_out[num_fds_in] = pipefd[0];
5510 new_cmsg->cmsg_len = cmsg_len;
5512 /* we're done ... */
5513 *scm_rights_pipe_fd = pipefd[0];
5514 *cm_data_space = new_cm_data_space;
5519 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5521 size_t *cm_data_space,
5522 int *scm_rights_pipe_fd)
5526 switch (cmsg->cmsg_type) {
5528 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5531 scm_rights_pipe_fd);
5534 rc = swrap_sendmsg_copy_cmsg(cmsg,
5543 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5545 size_t *cm_data_space)
5547 int scm_rights_pipe_fd = -1;
5548 struct swrap_unix_scm_rights info;
5549 struct swrap_unix_scm_rights_payload *payload = NULL;
5550 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5553 union __swrap_fds __fds_in = { .p = NULL, };
5554 const int *fds_in = NULL;
5556 size_t size_fds_out;
5557 union __swrap_fds __fds_out = { .p = NULL, };
5558 int *fds_out = NULL;
5561 size_t new_cm_data_space;
5562 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5563 struct cmsghdr *new_cmsg = NULL;
5569 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5570 SWRAP_LOG(SWRAP_LOG_ERROR,
5571 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5572 (size_t)cmsg->cmsg_len,
5577 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5578 if ((size_fds_in % sizeof(int)) != 0) {
5579 SWRAP_LOG(SWRAP_LOG_ERROR,
5580 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5581 (size_t)cmsg->cmsg_len,
5587 num_fds_in = size_fds_in / sizeof(int);
5588 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5589 SWRAP_LOG(SWRAP_LOG_ERROR,
5590 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5591 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5592 (size_t)cmsg->cmsg_len,
5595 SWRAP_MAX_PASSED_FDS+1);
5599 if (num_fds_in <= 1) {
5600 SWRAP_LOG(SWRAP_LOG_ERROR,
5601 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5603 (size_t)cmsg->cmsg_len,
5609 __fds_in.p = CMSG_DATA(cmsg);
5610 fds_in = __fds_in.fds;
5611 num_fds_out = num_fds_in - 1;
5613 SWRAP_LOG(SWRAP_LOG_TRACE,
5614 "num_fds_in=%zu num_fds_out=%zu",
5615 num_fds_in, num_fds_out);
5617 for (i = 0; i < num_fds_in; i++) {
5618 /* Check if we have a stale fd and remove it */
5619 swrap_remove_stale(fds_in[i]);
5622 scm_rights_pipe_fd = fds_in[num_fds_out];
5623 size_fds_out = sizeof(int) * num_fds_out;
5624 cmsg_len = CMSG_LEN(size_fds_out);
5625 cmsg_space = CMSG_SPACE(size_fds_out);
5627 new_cm_data_space = *cm_data_space + cmsg_space;
5629 p = realloc((*cm_data), new_cm_data_space);
5631 swrap_close_fd_array(num_fds_in, fds_in);
5635 p = (*cm_data) + (*cm_data_space);
5636 memset(p, 0, cmsg_space);
5638 new_cmsg = __new_cmsg.cmsg;
5640 __fds_out.p = CMSG_DATA(new_cmsg);
5641 fds_out = __fds_out.fds;
5642 memcpy(fds_out, fds_in, size_fds_out);
5643 new_cmsg->cmsg_len = cmsg_len;
5645 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5646 if (sret != sizeof(info)) {
5647 int saved_errno = errno;
5649 saved_errno = EINVAL;
5651 SWRAP_LOG(SWRAP_LOG_ERROR,
5652 "read() failed - sret=%zd - %d %s",
5654 strerror(saved_errno));
5655 swrap_close_fd_array(num_fds_in, fds_in);
5656 errno = saved_errno;
5659 libc_close(scm_rights_pipe_fd);
5660 payload = &info.payload;
5662 if (info.magic != swrap_unix_scm_right_magic) {
5663 SWRAP_LOG(SWRAP_LOG_ERROR,
5664 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5665 (unsigned long long)info.magic,
5666 (unsigned long long)swrap_unix_scm_right_magic);
5667 swrap_close_fd_array(num_fds_out, fds_out);
5672 cmp = memcmp(info.package_name,
5673 SOCKET_WRAPPER_PACKAGE,
5674 sizeof(info.package_name));
5676 SWRAP_LOG(SWRAP_LOG_ERROR,
5677 "info.package_name='%.*s' != '%s'",
5678 (int)sizeof(info.package_name),
5680 SOCKET_WRAPPER_PACKAGE);
5681 swrap_close_fd_array(num_fds_out, fds_out);
5686 cmp = memcmp(info.package_version,
5687 SOCKET_WRAPPER_VERSION,
5688 sizeof(info.package_version));
5690 SWRAP_LOG(SWRAP_LOG_ERROR,
5691 "info.package_version='%.*s' != '%s'",
5692 (int)sizeof(info.package_version),
5693 info.package_version,
5694 SOCKET_WRAPPER_VERSION);
5695 swrap_close_fd_array(num_fds_out, fds_out);
5700 if (info.full_size != sizeof(info)) {
5701 SWRAP_LOG(SWRAP_LOG_ERROR,
5702 "info.full_size=%zu != sizeof(info)=%zu",
5703 (size_t)info.full_size,
5705 swrap_close_fd_array(num_fds_out, fds_out);
5710 if (info.payload_size != sizeof(info.payload)) {
5711 SWRAP_LOG(SWRAP_LOG_ERROR,
5712 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5713 (size_t)info.payload_size,
5714 sizeof(info.payload));
5715 swrap_close_fd_array(num_fds_out, fds_out);
5720 if (payload->num_idxs != num_fds_out) {
5721 SWRAP_LOG(SWRAP_LOG_ERROR,
5722 "info.num_idxs=%u != num_fds_out=%zu",
5723 payload->num_idxs, num_fds_out);
5724 swrap_close_fd_array(num_fds_out, fds_out);
5729 for (i = 0; i < num_fds_out; i++) {
5732 si_idx_array[i] = -1;
5734 if (payload->idxs[i] == -1) {
5735 SWRAP_LOG(SWRAP_LOG_TRACE,
5736 "fds_out[%zu]=%d not an inet socket",
5741 if (payload->idxs[i] < 0) {
5742 SWRAP_LOG(SWRAP_LOG_ERROR,
5743 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5744 i, fds_out[i], i, payload->idxs[i]);
5745 swrap_close_fd_array(num_fds_out, fds_out);
5750 if (payload->idxs[i] >= payload->num_idxs) {
5751 SWRAP_LOG(SWRAP_LOG_ERROR,
5752 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5753 i, fds_out[i], i, payload->idxs[i],
5755 swrap_close_fd_array(num_fds_out, fds_out);
5760 if ((size_t)fds_out[i] >= socket_fds_max) {
5761 SWRAP_LOG(SWRAP_LOG_ERROR,
5762 "The max socket index limit of %zu has been reached, "
5766 swrap_close_fd_array(num_fds_out, fds_out);
5771 SWRAP_LOG(SWRAP_LOG_TRACE,
5773 "received as info.idxs[%zu]=%d!",
5775 i, payload->idxs[i]);
5777 for (j = 0; j < i; j++) {
5778 if (payload->idxs[j] == -1) {
5781 if (payload->idxs[j] == payload->idxs[i]) {
5782 si_idx_array[i] = si_idx_array[j];
5785 if (si_idx_array[i] == -1) {
5786 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5788 si_idx_array[i] = swrap_add_socket_info(si);
5789 if (si_idx_array[i] == -1) {
5790 int saved_errno = errno;
5791 SWRAP_LOG(SWRAP_LOG_ERROR,
5792 "The max socket index limit of %zu has been reached, "
5796 swrap_undo_si_idx_array(i, si_idx_array);
5797 swrap_close_fd_array(num_fds_out, fds_out);
5798 errno = saved_errno;
5801 SWRAP_LOG(SWRAP_LOG_TRACE,
5802 "Imported %s socket for protocol %s, fd=%d",
5803 si->family == AF_INET ? "IPv4" : "IPv6",
5804 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5809 for (i = 0; i < num_fds_out; i++) {
5810 if (si_idx_array[i] == -1) {
5813 set_socket_info_index(fds_out[i], si_idx_array[i]);
5816 /* we're done ... */
5817 *cm_data_space = new_cm_data_space;
5822 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5824 size_t *cm_data_space)
5828 switch (cmsg->cmsg_type) {
5830 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5835 rc = swrap_sendmsg_copy_cmsg(cmsg,
5844 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5846 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5847 struct msghdr *msg_tmp,
5848 int *scm_rights_pipe_fd)
5850 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5851 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5852 struct cmsghdr *cmsg = NULL;
5853 uint8_t *cm_data = NULL;
5854 size_t cm_data_space = 0;
5858 *scm_rights_pipe_fd = -1;
5861 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5865 for (cmsg = CMSG_FIRSTHDR(msg_in);
5867 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5868 switch (cmsg->cmsg_level) {
5870 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5873 scm_rights_pipe_fd);
5877 rc = swrap_sendmsg_copy_cmsg(cmsg,
5883 int saved_errno = errno;
5885 errno = saved_errno;
5890 msg_tmp->msg_controllen = cm_data_space;
5891 msg_tmp->msg_control = cm_data;
5894 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5895 *msg_tmp = *_msg_in;
5897 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5900 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5902 int scm_rights_pipe_fd)
5904 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5905 int saved_errno = errno;
5906 SAFE_FREE(msg_tmp->msg_control);
5907 if (scm_rights_pipe_fd != -1) {
5908 libc_close(scm_rights_pipe_fd);
5910 errno = saved_errno;
5911 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5915 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5916 struct msghdr *msg_tmp)
5922 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5923 struct msghdr *msg_out,
5926 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5927 struct cmsghdr *cmsg = NULL;
5928 uint8_t *cm_data = NULL;
5929 size_t cm_data_space = 0;
5933 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
5937 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
5939 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
5940 switch (cmsg->cmsg_level) {
5942 rc = swrap_recvmsg_unix_sol_socket(cmsg,
5948 rc = swrap_sendmsg_copy_cmsg(cmsg,
5954 int saved_errno = errno;
5956 errno = saved_errno;
5962 * msg_tmp->msg_control is still the buffer of the caller.
5964 memcpy(msg_tmp->msg_control, cm_data, cm_data_space);
5965 msg_tmp->msg_controllen = cm_data_space;
5968 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5969 *msg_out = *msg_tmp;
5973 static ssize_t swrap_sendmsg_before(int fd,
5974 struct socket_info *si,
5976 struct iovec *tmp_iov,
5977 struct sockaddr_un *tmp_un,
5978 const struct sockaddr_un **to_un,
5979 const struct sockaddr **to,
6001 if (!si->connected) {
6006 if (msg->msg_iovlen == 0) {
6010 mtu = socket_wrapper_mtu();
6011 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6013 nlen = len + msg->msg_iov[i].iov_len;
6023 msg->msg_iovlen = i;
6024 if (msg->msg_iovlen == 0) {
6025 *tmp_iov = msg->msg_iov[0];
6026 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6028 msg->msg_iov = tmp_iov;
6029 msg->msg_iovlen = 1;
6034 if (si->connected) {
6035 if (msg->msg_name != NULL) {
6037 * We are dealing with unix sockets and if we
6038 * are connected, we should only talk to the
6039 * connected unix path. Using the fd to send
6040 * to another server would be hard to achieve.
6042 msg->msg_name = NULL;
6043 msg->msg_namelen = 0;
6046 const struct sockaddr *msg_name;
6047 msg_name = (const struct sockaddr *)msg->msg_name;
6049 if (msg_name == NULL) {
6055 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6067 msg->msg_name = tmp_un;
6068 msg->msg_namelen = sizeof(*tmp_un);
6071 if (si->bound == 0) {
6072 ret = swrap_auto_bind(fd, si, si->family);
6074 SWRAP_UNLOCK_SI(si);
6075 if (errno == ENOTSOCK) {
6076 swrap_remove_stale(fd);
6079 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6085 if (!si->defer_connect) {
6089 ret = sockaddr_convert_to_un(si,
6091 si->peername.sa_socklen,
6099 ret = libc_connect(fd,
6100 (struct sockaddr *)(void *)tmp_un,
6103 /* to give better errors */
6104 if (ret == -1 && errno == ENOENT) {
6105 errno = EHOSTUNREACH;
6112 si->defer_connect = 0;
6115 errno = EHOSTUNREACH;
6121 SWRAP_UNLOCK_SI(si);
6126 static void swrap_sendmsg_after(int fd,
6127 struct socket_info *si,
6129 const struct sockaddr *to,
6132 int saved_errno = errno;
6139 /* to give better errors */
6141 if (saved_errno == ENOENT) {
6142 saved_errno = EHOSTUNREACH;
6143 } else if (saved_errno == ENOTSOCK) {
6144 /* If the fd is not a socket, remove it */
6145 swrap_remove_stale(fd);
6149 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6150 avail += msg->msg_iov[i].iov_len;
6154 remain = MIN(80, avail);
6159 /* we capture it as one single packet */
6160 buf = (uint8_t *)malloc(remain);
6162 /* we just not capture the packet */
6163 errno = saved_errno;
6167 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6168 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6170 msg->msg_iov[i].iov_base,
6173 remain -= this_time;
6182 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6183 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6185 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6190 if (si->connected) {
6191 to = &si->peername.sa.s;
6194 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6195 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6197 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6202 SWRAP_UNLOCK_SI(si);
6205 errno = saved_errno;
6208 static int swrap_recvmsg_before(int fd,
6209 struct socket_info *si,
6211 struct iovec *tmp_iov)
6218 (void)fd; /* unused */
6223 if (!si->connected) {
6228 if (msg->msg_iovlen == 0) {
6232 mtu = socket_wrapper_mtu();
6233 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6235 nlen = len + msg->msg_iov[i].iov_len;
6240 msg->msg_iovlen = i;
6241 if (msg->msg_iovlen == 0) {
6242 *tmp_iov = msg->msg_iov[0];
6243 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6245 msg->msg_iov = tmp_iov;
6246 msg->msg_iovlen = 1;
6251 if (msg->msg_name == NULL) {
6256 if (msg->msg_iovlen == 0) {
6260 if (si->bound == 0) {
6261 ret = swrap_auto_bind(fd, si, si->family);
6263 SWRAP_UNLOCK_SI(si);
6265 * When attempting to read or write to a
6266 * descriptor, if an underlying autobind fails
6267 * because it's not a socket, stop intercepting
6268 * uses of that descriptor.
6270 if (errno == ENOTSOCK) {
6271 swrap_remove_stale(fd);
6274 SWRAP_LOG(SWRAP_LOG_ERROR,
6275 "swrap_recvmsg_before failed");
6282 errno = EHOSTUNREACH;
6288 SWRAP_UNLOCK_SI(si);
6293 static int swrap_recvmsg_after(int fd,
6294 struct socket_info *si,
6296 const struct sockaddr_un *un_addr,
6297 socklen_t un_addrlen,
6300 int saved_errno = errno;
6302 uint8_t *buf = NULL;
6308 /* to give better errors */
6310 if (saved_errno == ENOENT) {
6311 saved_errno = EHOSTUNREACH;
6312 } else if (saved_errno == ENOTSOCK) {
6313 /* If the fd is not a socket, remove it */
6314 swrap_remove_stale(fd);
6318 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6319 avail += msg->msg_iov[i].iov_len;
6324 /* Convert the socket address before we leave */
6325 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6326 rc = sockaddr_convert_from_un(si,
6343 remain = MIN(80, avail);
6348 /* we capture it as one single packet */
6349 buf = (uint8_t *)malloc(remain);
6351 /* we just not capture the packet */
6352 SWRAP_UNLOCK_SI(si);
6353 errno = saved_errno;
6357 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6358 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6360 msg->msg_iov[i].iov_base,
6363 remain -= this_time;
6368 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6369 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6370 } else if (ret == 0) { /* END OF FILE */
6371 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6372 } else if (ret > 0) {
6373 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6382 if (un_addr != NULL) {
6383 swrap_pcap_dump_packet(si,
6389 swrap_pcap_dump_packet(si,
6402 errno = saved_errno;
6404 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6406 msg->msg_controllen > 0 &&
6407 msg->msg_control != NULL) {
6408 rc = swrap_msghdr_add_socket_info(si, msg);
6410 SWRAP_UNLOCK_SI(si);
6416 SWRAP_UNLOCK_SI(si);
6420 /****************************************************************************
6422 ***************************************************************************/
6424 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6425 struct sockaddr *from, socklen_t *fromlen)
6427 struct swrap_address from_addr = {
6428 .sa_socklen = sizeof(struct sockaddr_un),
6431 struct socket_info *si = find_socket_info(s);
6432 struct swrap_address saddr = {
6433 .sa_socklen = sizeof(struct sockaddr_storage),
6440 return libc_recvfrom(s,
6452 if (from != NULL && fromlen != NULL) {
6453 msg.msg_name = from; /* optional address */
6454 msg.msg_namelen = *fromlen; /* size of address */
6456 msg.msg_name = &saddr.sa.s; /* optional address */
6457 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6459 msg.msg_iov = &tmp; /* scatter/gather array */
6460 msg.msg_iovlen = 1; /* # elements in msg_iov */
6461 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6462 msg.msg_control = NULL; /* ancillary data, see below */
6463 msg.msg_controllen = 0; /* ancillary data buffer len */
6464 msg.msg_flags = 0; /* flags on received message */
6467 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6472 buf = msg.msg_iov[0].iov_base;
6473 len = msg.msg_iov[0].iov_len;
6475 ret = libc_recvfrom(s,
6480 &from_addr.sa_socklen);
6485 tret = swrap_recvmsg_after(s,
6489 from_addr.sa_socklen,
6495 if (from != NULL && fromlen != NULL) {
6496 *fromlen = msg.msg_namelen;
6502 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6503 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6504 struct sockaddr *from, Psocklen_t fromlen)
6506 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6507 struct sockaddr *from, socklen_t *fromlen)
6510 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6513 /****************************************************************************
6515 ***************************************************************************/
6517 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6518 const struct sockaddr *to, socklen_t tolen)
6522 struct swrap_address un_addr = {
6523 .sa_socklen = sizeof(struct sockaddr_un),
6525 const struct sockaddr_un *to_un = NULL;
6528 struct socket_info *si = find_socket_info(s);
6532 return libc_sendto(s, buf, len, flags, to, tolen);
6535 tmp.iov_base = discard_const_p(char, buf);
6539 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6540 msg.msg_namelen = tolen; /* size of address */
6541 msg.msg_iov = &tmp; /* scatter/gather array */
6542 msg.msg_iovlen = 1; /* # elements in msg_iov */
6543 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6544 msg.msg_control = NULL; /* ancillary data, see below */
6545 msg.msg_controllen = 0; /* ancillary data buffer len */
6546 msg.msg_flags = 0; /* flags on received message */
6549 rc = swrap_sendmsg_before(s,
6561 buf = msg.msg_iov[0].iov_base;
6562 len = msg.msg_iov[0].iov_len;
6567 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6569 char *swrap_dir = NULL;
6571 type = SOCKET_TYPE_CHAR_UDP;
6573 swrap_dir = socket_wrapper_dir();
6574 if (swrap_dir == NULL) {
6578 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6579 swrap_un_path(&un_addr.sa.un,
6584 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6586 /* ignore the any errors in broadcast sends */
6592 un_addr.sa_socklen);
6595 SAFE_FREE(swrap_dir);
6599 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6601 SWRAP_UNLOCK_SI(si);
6608 * If it is a dgram socket and we are connected, don't include the
6611 if (si->type == SOCK_DGRAM && si->connected) {
6612 ret = libc_sendto(s,
6619 ret = libc_sendto(s,
6623 (struct sockaddr *)msg.msg_name,
6627 SWRAP_UNLOCK_SI(si);
6629 swrap_sendmsg_after(s, si, &msg, to, ret);
6634 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6635 const struct sockaddr *to, socklen_t tolen)
6637 return swrap_sendto(s, buf, len, flags, to, tolen);
6640 /****************************************************************************
6642 ***************************************************************************/
6644 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6646 struct socket_info *si;
6648 struct swrap_address saddr = {
6649 .sa_socklen = sizeof(struct sockaddr_storage),
6655 si = find_socket_info(s);
6657 return libc_recv(s, buf, len, flags);
6664 msg.msg_name = &saddr.sa.s; /* optional address */
6665 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6666 msg.msg_iov = &tmp; /* scatter/gather array */
6667 msg.msg_iovlen = 1; /* # elements in msg_iov */
6668 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6669 msg.msg_control = NULL; /* ancillary data, see below */
6670 msg.msg_controllen = 0; /* ancillary data buffer len */
6671 msg.msg_flags = 0; /* flags on received message */
6674 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6679 buf = msg.msg_iov[0].iov_base;
6680 len = msg.msg_iov[0].iov_len;
6682 ret = libc_recv(s, buf, len, flags);
6684 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6692 ssize_t recv(int s, void *buf, size_t len, int flags)
6694 return swrap_recv(s, buf, len, flags);
6697 /****************************************************************************
6699 ***************************************************************************/
6701 static ssize_t swrap_read(int s, void *buf, size_t len)
6703 struct socket_info *si;
6706 struct swrap_address saddr = {
6707 .sa_socklen = sizeof(struct sockaddr_storage),
6712 si = find_socket_info(s);
6714 return libc_read(s, buf, len);
6721 msg.msg_name = &saddr.sa.ss; /* optional address */
6722 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6723 msg.msg_iov = &tmp; /* scatter/gather array */
6724 msg.msg_iovlen = 1; /* # elements in msg_iov */
6725 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6726 msg.msg_control = NULL; /* ancillary data, see below */
6727 msg.msg_controllen = 0; /* ancillary data buffer len */
6728 msg.msg_flags = 0; /* flags on received message */
6731 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6733 if (tret == -ENOTSOCK) {
6734 return libc_read(s, buf, len);
6739 buf = msg.msg_iov[0].iov_base;
6740 len = msg.msg_iov[0].iov_len;
6742 ret = libc_read(s, buf, len);
6744 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6752 ssize_t read(int s, void *buf, size_t len)
6754 return swrap_read(s, buf, len);
6757 /****************************************************************************
6759 ***************************************************************************/
6761 static ssize_t swrap_write(int s, const void *buf, size_t len)
6765 struct sockaddr_un un_addr;
6768 struct socket_info *si;
6770 si = find_socket_info(s);
6772 return libc_write(s, buf, len);
6775 tmp.iov_base = discard_const_p(char, buf);
6779 msg.msg_name = NULL; /* optional address */
6780 msg.msg_namelen = 0; /* size of address */
6781 msg.msg_iov = &tmp; /* scatter/gather array */
6782 msg.msg_iovlen = 1; /* # elements in msg_iov */
6783 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6784 msg.msg_control = NULL; /* ancillary data, see below */
6785 msg.msg_controllen = 0; /* ancillary data buffer len */
6786 msg.msg_flags = 0; /* flags on received message */
6789 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6794 buf = msg.msg_iov[0].iov_base;
6795 len = msg.msg_iov[0].iov_len;
6797 ret = libc_write(s, buf, len);
6799 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6804 ssize_t write(int s, const void *buf, size_t len)
6806 return swrap_write(s, buf, len);
6809 /****************************************************************************
6811 ***************************************************************************/
6813 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6817 struct sockaddr_un un_addr;
6820 struct socket_info *si = find_socket_info(s);
6823 return libc_send(s, buf, len, flags);
6826 tmp.iov_base = discard_const_p(char, buf);
6830 msg.msg_name = NULL; /* optional address */
6831 msg.msg_namelen = 0; /* size of address */
6832 msg.msg_iov = &tmp; /* scatter/gather array */
6833 msg.msg_iovlen = 1; /* # elements in msg_iov */
6834 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6835 msg.msg_control = NULL; /* ancillary data, see below */
6836 msg.msg_controllen = 0; /* ancillary data buffer len */
6837 msg.msg_flags = 0; /* flags on received message */
6840 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6845 buf = msg.msg_iov[0].iov_base;
6846 len = msg.msg_iov[0].iov_len;
6848 ret = libc_send(s, buf, len, flags);
6850 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6855 ssize_t send(int s, const void *buf, size_t len, int flags)
6857 return swrap_send(s, buf, len, flags);
6860 /****************************************************************************
6862 ***************************************************************************/
6864 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6866 struct swrap_address from_addr = {
6867 .sa_socklen = sizeof(struct sockaddr_un),
6869 struct swrap_address convert_addr = {
6870 .sa_socklen = sizeof(struct sockaddr_storage),
6872 struct socket_info *si;
6875 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6876 size_t msg_ctrllen_filled;
6877 size_t msg_ctrllen_left;
6883 si = find_socket_info(s);
6885 rc = swrap_recvmsg_before_unix(omsg, &msg);
6889 ret = libc_recvmsg(s, &msg, flags);
6890 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6893 tmp.iov_base = NULL;
6897 msg.msg_name = &from_addr.sa; /* optional address */
6898 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6899 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6900 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6901 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6902 msg_ctrllen_filled = 0;
6903 msg_ctrllen_left = omsg->msg_controllen;
6905 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6906 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6907 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6910 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6915 ret = libc_recvmsg(s, &msg, flags);
6917 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6918 msg_ctrllen_filled += msg.msg_controllen;
6919 msg_ctrllen_left -= msg.msg_controllen;
6921 if (omsg->msg_control != NULL) {
6924 p = omsg->msg_control;
6925 p += msg_ctrllen_filled;
6927 msg.msg_control = p;
6928 msg.msg_controllen = msg_ctrllen_left;
6930 msg.msg_control = NULL;
6931 msg.msg_controllen = 0;
6936 * We convert the unix address to a IP address so we need a buffer
6937 * which can store the address in case of SOCK_DGRAM, see below.
6939 msg.msg_name = &convert_addr.sa;
6940 msg.msg_namelen = convert_addr.sa_socklen;
6942 rc = swrap_recvmsg_after(s,
6946 from_addr.sa_socklen,
6952 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6953 if (omsg->msg_control != NULL) {
6954 /* msg.msg_controllen = space left */
6955 msg_ctrllen_left = msg.msg_controllen;
6956 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
6959 /* Update the original message length */
6960 omsg->msg_controllen = msg_ctrllen_filled;
6961 omsg->msg_flags = msg.msg_flags;
6963 omsg->msg_iovlen = msg.msg_iovlen;
6970 * The msg_name field points to a caller-allocated buffer that is
6971 * used to return the source address if the socket is unconnected. The
6972 * caller should set msg_namelen to the size of this buffer before this
6973 * call; upon return from a successful call, msg_name will contain the
6974 * length of the returned address. If the application does not need
6975 * to know the source address, msg_name can be specified as NULL.
6977 if (si->type == SOCK_STREAM) {
6978 omsg->msg_namelen = 0;
6979 } else if (omsg->msg_name != NULL &&
6980 omsg->msg_namelen != 0 &&
6981 omsg->msg_namelen >= msg.msg_namelen) {
6982 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
6983 omsg->msg_namelen = msg.msg_namelen;
6986 SWRAP_UNLOCK_SI(si);
6991 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
6993 return swrap_recvmsg(sockfd, msg, flags);
6996 /****************************************************************************
6998 ***************************************************************************/
7000 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7004 struct sockaddr_un un_addr;
7005 const struct sockaddr_un *to_un = NULL;
7006 const struct sockaddr *to = NULL;
7009 struct socket_info *si = find_socket_info(s);
7013 int scm_rights_pipe_fd = -1;
7015 rc = swrap_sendmsg_before_unix(omsg, &msg,
7016 &scm_rights_pipe_fd);
7020 ret = libc_sendmsg(s, &msg, flags);
7021 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7024 ZERO_STRUCT(un_addr);
7026 tmp.iov_base = NULL;
7033 if (si->connected == 0) {
7034 msg.msg_name = omsg->msg_name; /* optional address */
7035 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7037 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7038 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7040 SWRAP_UNLOCK_SI(si);
7042 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7043 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7044 uint8_t *cmbuf = NULL;
7047 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7053 msg.msg_controllen = 0;
7054 msg.msg_control = NULL;
7056 msg.msg_control = cmbuf;
7057 msg.msg_controllen = cmlen;
7060 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7062 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7064 int saved_errno = errno;
7065 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7066 SAFE_FREE(msg.msg_control);
7068 errno = saved_errno;
7075 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7082 char *swrap_dir = NULL;
7084 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7085 avail += msg.msg_iov[i].iov_len;
7091 /* we capture it as one single packet */
7092 buf = (uint8_t *)malloc(remain);
7094 int saved_errno = errno;
7095 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7096 SAFE_FREE(msg.msg_control);
7098 errno = saved_errno;
7102 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7103 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7105 msg.msg_iov[i].iov_base,
7108 remain -= this_time;
7111 type = SOCKET_TYPE_CHAR_UDP;
7113 swrap_dir = socket_wrapper_dir();
7114 if (swrap_dir == NULL) {
7115 int saved_errno = errno;
7116 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7117 SAFE_FREE(msg.msg_control);
7120 errno = saved_errno;
7124 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7125 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7126 if (stat(un_addr.sun_path, &st) != 0) continue;
7128 msg.msg_name = &un_addr; /* optional address */
7129 msg.msg_namelen = sizeof(un_addr); /* size of address */
7131 /* ignore the any errors in broadcast sends */
7132 libc_sendmsg(s, &msg, flags);
7135 SAFE_FREE(swrap_dir);
7139 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7142 SWRAP_UNLOCK_SI(si);
7147 ret = libc_sendmsg(s, &msg, flags);
7149 swrap_sendmsg_after(s, si, &msg, to, ret);
7151 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7153 int saved_errno = errno;
7154 SAFE_FREE(msg.msg_control);
7155 errno = saved_errno;
7162 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7164 return swrap_sendmsg(s, omsg, flags);
7167 /****************************************************************************
7169 ***************************************************************************/
7171 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7173 struct socket_info *si;
7176 struct swrap_address saddr = {
7177 .sa_socklen = sizeof(struct sockaddr_storage)
7182 si = find_socket_info(s);
7184 return libc_readv(s, vector, count);
7187 tmp.iov_base = NULL;
7191 msg.msg_name = &saddr.sa.s; /* optional address */
7192 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7193 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7194 msg.msg_iovlen = count; /* # elements in msg_iov */
7195 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7196 msg.msg_control = NULL; /* ancillary data, see below */
7197 msg.msg_controllen = 0; /* ancillary data buffer len */
7198 msg.msg_flags = 0; /* flags on received message */
7201 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7203 if (rc == -ENOTSOCK) {
7204 return libc_readv(s, vector, count);
7209 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7211 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7219 ssize_t readv(int s, const struct iovec *vector, int count)
7221 return swrap_readv(s, vector, count);
7224 /****************************************************************************
7226 ***************************************************************************/
7228 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7232 struct sockaddr_un un_addr;
7235 struct socket_info *si = find_socket_info(s);
7238 return libc_writev(s, vector, count);
7241 tmp.iov_base = NULL;
7245 msg.msg_name = NULL; /* optional address */
7246 msg.msg_namelen = 0; /* size of address */
7247 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7248 msg.msg_iovlen = count; /* # elements in msg_iov */
7249 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7250 msg.msg_control = NULL; /* ancillary data, see below */
7251 msg.msg_controllen = 0; /* ancillary data buffer len */
7252 msg.msg_flags = 0; /* flags on received message */
7255 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7257 if (rc == -ENOTSOCK) {
7258 return libc_readv(s, vector, count);
7263 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7265 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7270 ssize_t writev(int s, const struct iovec *vector, int count)
7272 return swrap_writev(s, vector, count);
7275 /****************************
7277 ***************************/
7279 static int swrap_close(int fd)
7281 struct socket_info *si = NULL;
7285 swrap_mutex_lock(&socket_reset_mutex);
7287 si_index = find_socket_info_index(fd);
7288 if (si_index == -1) {
7289 swrap_mutex_unlock(&socket_reset_mutex);
7290 return libc_close(fd);
7293 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7294 reset_socket_info_index(fd);
7296 si = swrap_get_socket_info(si_index);
7298 swrap_mutex_lock(&first_free_mutex);
7301 ret = libc_close(fd);
7303 swrap_dec_refcount(si);
7305 if (swrap_get_refcount(si) > 0) {
7306 /* there are still references left */
7310 if (si->fd_passed) {
7314 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7315 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7318 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7319 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7320 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7323 if (si->un_addr.sun_path[0] != '\0') {
7324 unlink(si->un_addr.sun_path);
7328 swrap_set_next_free(si, first_free);
7329 first_free = si_index;
7332 SWRAP_UNLOCK_SI(si);
7333 swrap_mutex_unlock(&first_free_mutex);
7334 swrap_mutex_unlock(&socket_reset_mutex);
7341 return swrap_close(fd);
7344 /****************************
7346 ***************************/
7348 static int swrap_dup(int fd)
7350 struct socket_info *si;
7353 idx = find_socket_info_index(fd);
7355 return libc_dup(fd);
7358 si = swrap_get_socket_info(idx);
7360 dup_fd = libc_dup(fd);
7362 int saved_errno = errno;
7363 errno = saved_errno;
7367 if ((size_t)dup_fd >= socket_fds_max) {
7368 SWRAP_LOG(SWRAP_LOG_ERROR,
7369 "The max socket index limit of %zu has been reached, "
7380 swrap_inc_refcount(si);
7382 SWRAP_UNLOCK_SI(si);
7384 /* Make sure we don't have an entry for the fd */
7385 swrap_remove_stale(dup_fd);
7387 set_socket_info_index(dup_fd, idx);
7394 return swrap_dup(fd);
7397 /****************************
7399 ***************************/
7401 static int swrap_dup2(int fd, int newfd)
7403 struct socket_info *si;
7406 idx = find_socket_info_index(fd);
7408 return libc_dup2(fd, newfd);
7411 si = swrap_get_socket_info(idx);
7415 * According to the manpage:
7417 * "If oldfd is a valid file descriptor, and newfd has the same
7418 * value as oldfd, then dup2() does nothing, and returns newfd."
7423 if ((size_t)newfd >= socket_fds_max) {
7424 SWRAP_LOG(SWRAP_LOG_ERROR,
7425 "The max socket index limit of %zu has been reached, "
7433 if (find_socket_info(newfd)) {
7434 /* dup2() does an implicit close of newfd, which we
7435 * need to emulate */
7439 dup_fd = libc_dup2(fd, newfd);
7441 int saved_errno = errno;
7442 errno = saved_errno;
7448 swrap_inc_refcount(si);
7450 SWRAP_UNLOCK_SI(si);
7452 /* Make sure we don't have an entry for the fd */
7453 swrap_remove_stale(dup_fd);
7455 set_socket_info_index(dup_fd, idx);
7460 int dup2(int fd, int newfd)
7462 return swrap_dup2(fd, newfd);
7465 /****************************
7467 ***************************/
7469 static int swrap_vfcntl(int fd, int cmd, va_list va)
7471 struct socket_info *si;
7472 int rc, dup_fd, idx;
7474 idx = find_socket_info_index(fd);
7476 return libc_vfcntl(fd, cmd, va);
7479 si = swrap_get_socket_info(idx);
7483 dup_fd = libc_vfcntl(fd, cmd, va);
7485 int saved_errno = errno;
7486 errno = saved_errno;
7490 /* Make sure we don't have an entry for the fd */
7491 swrap_remove_stale(dup_fd);
7493 if ((size_t)dup_fd >= socket_fds_max) {
7494 SWRAP_LOG(SWRAP_LOG_ERROR,
7495 "The max socket index limit of %zu has been reached, "
7506 swrap_inc_refcount(si);
7508 SWRAP_UNLOCK_SI(si);
7511 set_socket_info_index(dup_fd, idx);
7516 rc = libc_vfcntl(fd, cmd, va);
7523 int fcntl(int fd, int cmd, ...)
7530 rc = swrap_vfcntl(fd, cmd, va);
7537 /****************************
7539 ***************************/
7542 static int swrap_eventfd(int count, int flags)
7546 fd = libc_eventfd(count, flags);
7548 swrap_remove_stale(fd);
7554 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7555 int eventfd(unsigned int count, int flags)
7557 int eventfd(int count, int flags)
7560 return swrap_eventfd(count, flags);
7565 int pledge(const char *promises, const char *paths[])
7567 (void)promises; /* unused */
7568 (void)paths; /* unused */
7572 #endif /* HAVE_PLEDGE */
7574 static void swrap_thread_prepare(void)
7577 * This function should only be called here!!
7579 * We bind all symobls to avoid deadlocks of the fork is
7580 * interrupted by a signal handler using a symbol of this
7583 swrap_bind_symbol_all();
7588 static void swrap_thread_parent(void)
7593 static void swrap_thread_child(void)
7598 /****************************
7600 ***************************/
7601 void swrap_constructor(void)
7603 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7604 SWRAP_LOG(SWRAP_LOG_ERROR,
7606 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7607 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7608 "sizeof(struct socket_info)=%zu",
7610 sizeof(struct swrap_unix_scm_rights),
7611 sizeof(struct swrap_unix_scm_rights_payload),
7612 sizeof(struct socket_info));
7619 * If we hold a lock and the application forks, then the child
7620 * is not able to unlock the mutex and we are in a deadlock.
7621 * This should prevent such deadlocks.
7623 pthread_atfork(&swrap_thread_prepare,
7624 &swrap_thread_parent,
7625 &swrap_thread_child);
7628 /****************************
7630 ***************************/
7633 * This function is called when the library is unloaded and makes sure that
7634 * sockets get closed and the unix file for the socket are unlinked.
7636 void swrap_destructor(void)
7640 if (socket_fds_idx != NULL) {
7641 for (i = 0; i < socket_fds_max; ++i) {
7642 if (socket_fds_idx[i] != -1) {
7646 SAFE_FREE(socket_fds_idx);
7651 if (swrap.libc.handle != NULL) {
7652 dlclose(swrap.libc.handle);
7654 if (swrap.libc.socket_handle) {
7655 dlclose(swrap.libc.socket_handle);
7659 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7661 * On FreeBSD 12 (and maybe other platforms)
7662 * system libraries like libresolv prefix there
7663 * syscalls with '_' in order to always use
7664 * the symbols from libc.
7666 * In the interaction with resolv_wrapper,
7667 * we need to inject socket wrapper into libresolv,
7668 * which means we need to private all socket
7669 * related syscalls also with the '_' prefix.
7671 * This is tested in Samba's 'make test',
7672 * there we noticed that providing '_read'
7673 * and '_open' would cause errors, which
7674 * means we skip '_read', '_write' and
7675 * all non socket related calls without
7676 * further analyzing the problem.
7678 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7679 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7682 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7684 SWRAP_SYMBOL_ALIAS(accept, _accept);
7685 SWRAP_SYMBOL_ALIAS(bind, _bind);
7686 SWRAP_SYMBOL_ALIAS(close, _close);
7687 SWRAP_SYMBOL_ALIAS(connect, _connect);
7688 SWRAP_SYMBOL_ALIAS(dup, _dup);
7689 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7690 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7691 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7692 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7693 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7694 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7695 SWRAP_SYMBOL_ALIAS(listen, _listen);
7696 SWRAP_SYMBOL_ALIAS(readv, _readv);
7697 SWRAP_SYMBOL_ALIAS(recv, _recv);
7698 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7699 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7700 SWRAP_SYMBOL_ALIAS(send, _send);
7701 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7702 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7703 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7704 SWRAP_SYMBOL_ALIAS(socket, _socket);
7705 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7706 SWRAP_SYMBOL_ALIAS(writev, _writev);
7708 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */