4 * Copyright (c) 2005-2008, Jelmer Vernooij <jelmer@samba.org>
5 * Copyright (c) 2006-2018, Stefan Metzmacher <metze@samba.org>
6 * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
7 * Copyright (c) 2014-2017, Michael Adam <obnox@samba.org>
8 * Copyright (c) 2016-2018, Anoop C S <anoopcs@redhat.com>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the author nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 Socket wrapper library. Passes all socket communication over
41 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
47 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <sys/ioctl.h>
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
55 #ifdef HAVE_SYS_SIGNALFD_H
56 #include <sys/signalfd.h>
58 #ifdef HAVE_SYS_EVENTFD_H
59 #include <sys/eventfd.h>
61 #ifdef HAVE_SYS_TIMERFD_H
62 #include <sys/timerfd.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #ifdef HAVE_NETINET_TCP_FSM_H
70 #include <netinet/tcp_fsm.h>
72 #include <arpa/inet.h>
81 #ifdef HAVE_GNU_LIB_NAMES_H
82 #include <gnu/lib-names.h>
96 /* GCC have printf type attribute check. */
97 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
98 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
100 #define PRINTF_ATTRIBUTE(a,b)
101 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
103 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
104 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
106 #define CONSTRUCTOR_ATTRIBUTE
107 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
109 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
110 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
112 #define DESTRUCTOR_ATTRIBUTE
116 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
117 # define FALL_THROUGH __attribute__ ((fallthrough))
118 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
119 # define FALL_THROUGH ((void)0)
120 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
121 #endif /* FALL_THROUGH */
123 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
124 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
126 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
129 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
130 # define SWRAP_THREAD __thread
132 # define SWRAP_THREAD
136 #define MIN(a,b) ((a)<(b)?(a):(b))
140 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
144 #define ZERO_STRUCTP(x) do { \
146 memset((char *)(x), 0, sizeof(*(x))); \
151 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
154 #ifndef discard_const
155 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
158 #ifndef discard_const_p
159 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
162 #define UNUSED(x) (void)(x)
165 # ifndef IPV6_RECVPKTINFO
166 # define IPV6_RECVPKTINFO IPV6_PKTINFO
167 # endif /* IPV6_RECVPKTINFO */
168 #endif /* IPV6_PKTINFO */
171 * On BSD IP_PKTINFO has a different name because during
172 * the time when they implemented it, there was no RFC.
173 * The name for IPv6 is the same as on Linux.
176 # ifdef IP_RECVDSTADDR
177 # define IP_PKTINFO IP_RECVDSTADDR
181 #define socket_wrapper_init_mutex(m) \
182 _socket_wrapper_init_mutex(m, #m)
184 /* Add new global locks here please */
185 # define SWRAP_REINIT_ALL do { \
188 ret = socket_wrapper_init_mutex(&sockets_mutex); \
189 if (ret != 0) exit(-1); \
190 ret = socket_wrapper_init_mutex(&socket_reset_mutex); \
191 if (ret != 0) exit(-1); \
192 ret = socket_wrapper_init_mutex(&first_free_mutex); \
193 if (ret != 0) exit(-1); \
194 for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \
195 ret = socket_wrapper_init_mutex(&sockets[__i].meta.mutex); \
196 if (ret != 0) exit(-1); \
198 ret = socket_wrapper_init_mutex(&autobind_start_mutex); \
199 if (ret != 0) exit(-1); \
200 ret = socket_wrapper_init_mutex(&pcap_dump_mutex); \
201 if (ret != 0) exit(-1); \
202 ret = socket_wrapper_init_mutex(&mtu_update_mutex); \
203 if (ret != 0) exit(-1); \
206 # define SWRAP_LOCK_ALL do { \
208 swrap_mutex_lock(&sockets_mutex); \
209 swrap_mutex_lock(&socket_reset_mutex); \
210 swrap_mutex_lock(&first_free_mutex); \
211 for (__i = 0; (sockets != NULL) && __i < socket_info_max; __i++) { \
212 swrap_mutex_lock(&sockets[__i].meta.mutex); \
214 swrap_mutex_lock(&autobind_start_mutex); \
215 swrap_mutex_lock(&pcap_dump_mutex); \
216 swrap_mutex_lock(&mtu_update_mutex); \
219 # define SWRAP_UNLOCK_ALL do { \
221 swrap_mutex_unlock(&mtu_update_mutex); \
222 swrap_mutex_unlock(&pcap_dump_mutex); \
223 swrap_mutex_unlock(&autobind_start_mutex); \
224 for (__s = 0; (sockets != NULL) && __s < socket_info_max; __s++) { \
225 size_t __i = (socket_info_max - 1) - __s; \
226 swrap_mutex_unlock(&sockets[__i].meta.mutex); \
228 swrap_mutex_unlock(&first_free_mutex); \
229 swrap_mutex_unlock(&socket_reset_mutex); \
230 swrap_mutex_unlock(&sockets_mutex); \
233 #define SOCKET_INFO_CONTAINER(si) \
234 (struct socket_info_container *)(si)
236 #define SWRAP_LOCK_SI(si) do { \
237 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
238 swrap_mutex_lock(&sic->meta.mutex); \
241 #define SWRAP_UNLOCK_SI(si) do { \
242 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
243 swrap_mutex_unlock(&sic->meta.mutex); \
246 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
247 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
249 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
252 /* we need to use a very terse format here as IRIX 6.4 silently
253 truncates names to 16 chars, so if we use a longer name then we
254 can't tell which port a packet came from with recvfrom()
256 with this format we have 8 chars left for the directory name
258 #define SOCKET_FORMAT "%c%02X%04X"
259 #define SOCKET_TYPE_CHAR_TCP 'T'
260 #define SOCKET_TYPE_CHAR_UDP 'U'
261 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
262 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
265 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
266 * format PCAP capture files (as the caller will simply continue from here).
268 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
269 #define SOCKET_WRAPPER_MTU_MIN 512
270 #define SOCKET_WRAPPER_MTU_MAX 32768
272 #define SOCKET_MAX_SOCKETS 1024
275 * Maximum number of socket_info structures that can
276 * be used. Can be overriden by the environment variable
277 * SOCKET_WRAPPER_MAX_SOCKETS.
279 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
281 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
283 /* This limit is to avoid broadcast sendto() needing to stat too many
284 * files. It may be raised (with a performance cost) to up to 254
285 * without changing the format above */
286 #define MAX_WRAPPED_INTERFACES 64
288 struct swrap_address {
289 socklen_t sa_socklen;
292 struct sockaddr_in in;
294 struct sockaddr_in6 in6;
296 struct sockaddr_un un;
297 struct sockaddr_storage ss;
301 static int first_free;
306 * Remember to update swrap_unix_scm_right_magic
323 /* The unix path so we can unlink it on close() */
324 struct sockaddr_un un_addr;
326 struct swrap_address bindname;
327 struct swrap_address myname;
328 struct swrap_address peername;
331 unsigned long pck_snd;
332 unsigned long pck_rcv;
336 struct socket_info_meta
338 unsigned int refcount;
340 pthread_mutex_t mutex;
343 struct socket_info_container
345 struct socket_info info;
346 struct socket_info_meta meta;
349 static struct socket_info_container *sockets;
351 static size_t socket_info_max = 0;
354 * Allocate the socket array always on the limit value. We want it to be
355 * at least bigger than the default so if we reach the limit we can
356 * still deal with duplicate fds pointing to the same socket_info.
358 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
360 /* Hash table to map fds to corresponding socket_info index */
361 static int *socket_fds_idx;
363 /* Mutex for syncronizing port selection during swrap_auto_bind() */
364 static pthread_mutex_t autobind_start_mutex = PTHREAD_MUTEX_INITIALIZER;
366 /* Mutex to guard the initialization of array of socket_info structures */
367 static pthread_mutex_t sockets_mutex = PTHREAD_MUTEX_INITIALIZER;
369 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
370 static pthread_mutex_t socket_reset_mutex = PTHREAD_MUTEX_INITIALIZER;
372 /* Mutex to synchronize access to first free index in socket_info array */
373 static pthread_mutex_t first_free_mutex = PTHREAD_MUTEX_INITIALIZER;
375 /* Mutex to synchronize access to packet capture dump file */
376 static pthread_mutex_t pcap_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
378 /* Mutex for synchronizing mtu value fetch*/
379 static pthread_mutex_t mtu_update_mutex = PTHREAD_MUTEX_INITIALIZER;
381 /* Function prototypes */
383 bool socket_wrapper_enabled(void);
385 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
386 /* xlC and other oldschool compilers support (only) this */
387 #pragma init (swrap_constructor)
389 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
390 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
391 #pragma fini (swrap_destructor)
393 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
395 #ifndef HAVE_GETPROGNAME
396 static const char *getprogname(void)
398 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
399 return program_invocation_short_name;
400 #elif defined(HAVE_GETEXECNAME)
401 return getexecname();
404 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
406 #endif /* HAVE_GETPROGNAME */
408 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
409 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
411 static void swrap_log(enum swrap_dbglvl_e dbglvl,
413 const char *format, ...)
418 unsigned int lvl = 0;
419 const char *prefix = "SWRAP";
420 const char *progname = getprogname();
422 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
431 va_start(va, format);
432 vsnprintf(buffer, sizeof(buffer), format, va);
436 case SWRAP_LOG_ERROR:
437 prefix = "SWRAP_ERROR";
440 prefix = "SWRAP_WARN";
442 case SWRAP_LOG_DEBUG:
443 prefix = "SWRAP_DEBUG";
445 case SWRAP_LOG_TRACE:
446 prefix = "SWRAP_TRACE";
450 if (progname == NULL) {
451 progname = "<unknown>";
455 "%s[%s (%u)] - %s: %s\n",
458 (unsigned int)getpid(),
463 /*********************************************************
464 * SWRAP LOADING LIBC FUNCTIONS
465 *********************************************************/
470 typedef int (*__libc_accept4)(int sockfd,
471 struct sockaddr *addr,
475 typedef int (*__libc_accept)(int sockfd,
476 struct sockaddr *addr,
479 typedef int (*__libc_bind)(int sockfd,
480 const struct sockaddr *addr,
482 typedef int (*__libc_close)(int fd);
483 typedef int (*__libc_connect)(int sockfd,
484 const struct sockaddr *addr,
486 typedef int (*__libc_dup)(int fd);
487 typedef int (*__libc_dup2)(int oldfd, int newfd);
488 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
489 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
491 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
494 typedef int (*__libc_eventfd)(int count, int flags);
496 typedef int (*__libc_getpeername)(int sockfd,
497 struct sockaddr *addr,
499 typedef int (*__libc_getsockname)(int sockfd,
500 struct sockaddr *addr,
502 typedef int (*__libc_getsockopt)(int sockfd,
507 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
508 typedef int (*__libc_listen)(int sockfd, int backlog);
509 typedef int (*__libc_open)(const char *pathname, int flags, ...);
511 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
512 #endif /* HAVE_OPEN64 */
513 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
514 typedef int (*__libc_pipe)(int pipefd[2]);
515 typedef int (*__libc_read)(int fd, void *buf, size_t count);
516 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
517 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
518 typedef int (*__libc_recvfrom)(int sockfd,
522 struct sockaddr *src_addr,
524 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
525 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
526 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
527 typedef int (*__libc_sendto)(int sockfd,
531 const struct sockaddr *dst_addr,
533 typedef int (*__libc_setsockopt)(int sockfd,
539 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
541 typedef int (*__libc_socket)(int domain, int type, int protocol);
542 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
543 #ifdef HAVE_TIMERFD_CREATE
544 typedef int (*__libc_timerfd_create)(int clockid, int flags);
546 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
547 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
549 #define SWRAP_SYMBOL_ENTRY(i) \
555 struct swrap_libc_symbols {
557 SWRAP_SYMBOL_ENTRY(accept4);
559 SWRAP_SYMBOL_ENTRY(accept);
561 SWRAP_SYMBOL_ENTRY(bind);
562 SWRAP_SYMBOL_ENTRY(close);
563 SWRAP_SYMBOL_ENTRY(connect);
564 SWRAP_SYMBOL_ENTRY(dup);
565 SWRAP_SYMBOL_ENTRY(dup2);
566 SWRAP_SYMBOL_ENTRY(fcntl);
567 SWRAP_SYMBOL_ENTRY(fopen);
569 SWRAP_SYMBOL_ENTRY(fopen64);
572 SWRAP_SYMBOL_ENTRY(eventfd);
574 SWRAP_SYMBOL_ENTRY(getpeername);
575 SWRAP_SYMBOL_ENTRY(getsockname);
576 SWRAP_SYMBOL_ENTRY(getsockopt);
577 SWRAP_SYMBOL_ENTRY(ioctl);
578 SWRAP_SYMBOL_ENTRY(listen);
579 SWRAP_SYMBOL_ENTRY(open);
581 SWRAP_SYMBOL_ENTRY(open64);
583 SWRAP_SYMBOL_ENTRY(openat);
584 SWRAP_SYMBOL_ENTRY(pipe);
585 SWRAP_SYMBOL_ENTRY(read);
586 SWRAP_SYMBOL_ENTRY(readv);
587 SWRAP_SYMBOL_ENTRY(recv);
588 SWRAP_SYMBOL_ENTRY(recvfrom);
589 SWRAP_SYMBOL_ENTRY(recvmsg);
590 SWRAP_SYMBOL_ENTRY(send);
591 SWRAP_SYMBOL_ENTRY(sendmsg);
592 SWRAP_SYMBOL_ENTRY(sendto);
593 SWRAP_SYMBOL_ENTRY(setsockopt);
595 SWRAP_SYMBOL_ENTRY(signalfd);
597 SWRAP_SYMBOL_ENTRY(socket);
598 SWRAP_SYMBOL_ENTRY(socketpair);
599 #ifdef HAVE_TIMERFD_CREATE
600 SWRAP_SYMBOL_ENTRY(timerfd_create);
602 SWRAP_SYMBOL_ENTRY(write);
603 SWRAP_SYMBOL_ENTRY(writev);
610 struct swrap_libc_symbols symbols;
614 static struct swrap swrap;
617 static char *socket_wrapper_dir(void);
619 #define LIBC_NAME "libc.so"
626 static const char *swrap_str_lib(enum swrap_lib lib)
631 case SWRAP_LIBSOCKET:
635 /* Compiler would warn us about unhandled enum value if we get here */
639 static void *swrap_load_lib_handle(enum swrap_lib lib)
641 int flags = RTLD_LAZY;
646 const char *env_preload = getenv("LD_PRELOAD");
647 const char *env_deepbind = getenv("SOCKET_WRAPPER_DISABLE_DEEPBIND");
648 bool enable_deepbind = true;
650 /* Don't do a deepbind if we run with libasan */
651 if (env_preload != NULL && strlen(env_preload) < 1024) {
652 const char *p = strstr(env_preload, "libasan.so");
654 enable_deepbind = false;
658 if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
659 enable_deepbind = false;
662 if (enable_deepbind) {
663 flags |= RTLD_DEEPBIND;
668 case SWRAP_LIBSOCKET:
669 #ifdef HAVE_LIBSOCKET
670 handle = swrap.libc.socket_handle;
671 if (handle == NULL) {
672 for (i = 10; i >= 0; i--) {
673 char soname[256] = {0};
675 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
676 handle = dlopen(soname, flags);
677 if (handle != NULL) {
682 swrap.libc.socket_handle = handle;
687 handle = swrap.libc.handle;
689 if (handle == NULL) {
690 handle = dlopen(LIBC_SO, flags);
692 swrap.libc.handle = handle;
695 if (handle == NULL) {
696 for (i = 10; i >= 0; i--) {
697 char soname[256] = {0};
699 snprintf(soname, sizeof(soname), "libc.so.%d", i);
700 handle = dlopen(soname, flags);
701 if (handle != NULL) {
706 swrap.libc.handle = handle;
711 if (handle == NULL) {
713 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
715 SWRAP_LOG(SWRAP_LOG_ERROR,
716 "Failed to dlopen library: %s",
725 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
730 handle = swrap_load_lib_handle(lib);
732 func = dlsym(handle, fn_name);
734 SWRAP_LOG(SWRAP_LOG_ERROR,
735 "Failed to find %s: %s",
741 SWRAP_LOG(SWRAP_LOG_TRACE,
749 #define swrap_mutex_lock(m) _swrap_mutex_lock(m, #m, __func__, __LINE__)
750 static void _swrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
754 ret = pthread_mutex_lock(mutex);
756 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
757 getpid(), getppid(), caller, line, name, strerror(ret));
761 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
762 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
766 ret = pthread_mutex_unlock(mutex);
768 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
769 getpid(), getppid(), caller, line, name, strerror(ret));
774 * These macros have a thread race condition on purpose!
776 * This is an optimization to avoid locking each time we check if the symbol is
779 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
780 swrap.libc.symbols._libc_##sym_name.obj = \
781 _swrap_bind_symbol(lib, #sym_name); \
784 #define swrap_bind_symbol_libc(sym_name) \
785 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
787 #define swrap_bind_symbol_libsocket(sym_name) \
788 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
790 static void swrap_bind_symbol_all(void);
792 /****************************************************************************
794 ****************************************************************************
796 * Functions especially from libc need to be loaded individually, you can't
797 * load all at once or gdb will segfault at startup. The same applies to
798 * valgrind and has probably something todo with with the linker. So we need
799 * load each function at the point it is called the first time.
801 ****************************************************************************/
804 static int libc_accept4(int sockfd,
805 struct sockaddr *addr,
809 swrap_bind_symbol_all();
811 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
814 #else /* HAVE_ACCEPT4 */
816 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
818 swrap_bind_symbol_all();
820 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
822 #endif /* HAVE_ACCEPT4 */
824 static int libc_bind(int sockfd,
825 const struct sockaddr *addr,
828 swrap_bind_symbol_all();
830 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
833 static int libc_close(int fd)
835 swrap_bind_symbol_all();
837 return swrap.libc.symbols._libc_close.f(fd);
840 static int libc_connect(int sockfd,
841 const struct sockaddr *addr,
844 swrap_bind_symbol_all();
846 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
849 static int libc_dup(int fd)
851 swrap_bind_symbol_all();
853 return swrap.libc.symbols._libc_dup.f(fd);
856 static int libc_dup2(int oldfd, int newfd)
858 swrap_bind_symbol_all();
860 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
864 static int libc_eventfd(int count, int flags)
866 swrap_bind_symbol_all();
868 return swrap.libc.symbols._libc_eventfd.f(count, flags);
872 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
873 static int libc_vfcntl(int fd, int cmd, va_list ap)
878 swrap_bind_symbol_all();
880 arg = va_arg(ap, void *);
882 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
887 static int libc_getpeername(int sockfd,
888 struct sockaddr *addr,
891 swrap_bind_symbol_all();
893 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
896 static int libc_getsockname(int sockfd,
897 struct sockaddr *addr,
900 swrap_bind_symbol_all();
902 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
905 static int libc_getsockopt(int sockfd,
911 swrap_bind_symbol_all();
913 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
920 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
921 static int libc_vioctl(int d, unsigned long int request, va_list ap)
926 swrap_bind_symbol_all();
928 arg = va_arg(ap, void *);
930 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
935 static int libc_listen(int sockfd, int backlog)
937 swrap_bind_symbol_all();
939 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
942 static FILE *libc_fopen(const char *name, const char *mode)
944 swrap_bind_symbol_all();
946 return swrap.libc.symbols._libc_fopen.f(name, mode);
950 static FILE *libc_fopen64(const char *name, const char *mode)
952 swrap_bind_symbol_all();
954 return swrap.libc.symbols._libc_fopen64.f(name, mode);
956 #endif /* HAVE_FOPEN64 */
958 static int libc_vopen(const char *pathname, int flags, va_list ap)
963 swrap_bind_symbol_all();
965 if (flags & O_CREAT) {
966 mode = va_arg(ap, int);
968 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
973 static int libc_open(const char *pathname, int flags, ...)
979 fd = libc_vopen(pathname, flags, ap);
986 static int libc_vopen64(const char *pathname, int flags, va_list ap)
991 swrap_bind_symbol_all();
993 if (flags & O_CREAT) {
994 mode = va_arg(ap, int);
996 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1000 #endif /* HAVE_OPEN64 */
1002 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1007 swrap_bind_symbol_all();
1009 if (flags & O_CREAT) {
1010 mode = va_arg(ap, int);
1012 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1021 static int libc_openat(int dirfd, const char *path, int flags, ...)
1026 va_start(ap, flags);
1027 fd = libc_vopenat(dirfd, path, flags, ap);
1034 static int libc_pipe(int pipefd[2])
1036 swrap_bind_symbol_all();
1038 return swrap.libc.symbols._libc_pipe.f(pipefd);
1041 static int libc_read(int fd, void *buf, size_t count)
1043 swrap_bind_symbol_all();
1045 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1048 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1050 swrap_bind_symbol_all();
1052 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1055 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1057 swrap_bind_symbol_all();
1059 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1062 static int libc_recvfrom(int sockfd,
1066 struct sockaddr *src_addr,
1069 swrap_bind_symbol_all();
1071 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1079 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1081 swrap_bind_symbol_all();
1083 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1086 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1088 swrap_bind_symbol_all();
1090 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1093 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1095 swrap_bind_symbol_all();
1097 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1100 static int libc_sendto(int sockfd,
1104 const struct sockaddr *dst_addr,
1107 swrap_bind_symbol_all();
1109 return swrap.libc.symbols._libc_sendto.f(sockfd,
1117 static int libc_setsockopt(int sockfd,
1123 swrap_bind_symbol_all();
1125 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1132 #ifdef HAVE_SIGNALFD
1133 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1135 swrap_bind_symbol_all();
1137 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1141 static int libc_socket(int domain, int type, int protocol)
1143 swrap_bind_symbol_all();
1145 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1148 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1150 swrap_bind_symbol_all();
1152 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1155 #ifdef HAVE_TIMERFD_CREATE
1156 static int libc_timerfd_create(int clockid, int flags)
1158 swrap_bind_symbol_all();
1160 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1164 static ssize_t libc_write(int fd, const void *buf, size_t count)
1166 swrap_bind_symbol_all();
1168 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1171 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1173 swrap_bind_symbol_all();
1175 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1178 /* DO NOT call this function during library initialization! */
1179 static void __swrap_bind_symbol_all_once(void)
1182 swrap_bind_symbol_libsocket(accept4);
1184 swrap_bind_symbol_libsocket(accept);
1186 swrap_bind_symbol_libsocket(bind);
1187 swrap_bind_symbol_libc(close);
1188 swrap_bind_symbol_libsocket(connect);
1189 swrap_bind_symbol_libc(dup);
1190 swrap_bind_symbol_libc(dup2);
1191 swrap_bind_symbol_libc(fcntl);
1192 swrap_bind_symbol_libc(fopen);
1194 swrap_bind_symbol_libc(fopen64);
1197 swrap_bind_symbol_libc(eventfd);
1199 swrap_bind_symbol_libsocket(getpeername);
1200 swrap_bind_symbol_libsocket(getsockname);
1201 swrap_bind_symbol_libsocket(getsockopt);
1202 swrap_bind_symbol_libc(ioctl);
1203 swrap_bind_symbol_libsocket(listen);
1204 swrap_bind_symbol_libc(open);
1206 swrap_bind_symbol_libc(open64);
1208 swrap_bind_symbol_libc(openat);
1209 swrap_bind_symbol_libsocket(pipe);
1210 swrap_bind_symbol_libc(read);
1211 swrap_bind_symbol_libsocket(readv);
1212 swrap_bind_symbol_libsocket(recv);
1213 swrap_bind_symbol_libsocket(recvfrom);
1214 swrap_bind_symbol_libsocket(recvmsg);
1215 swrap_bind_symbol_libsocket(send);
1216 swrap_bind_symbol_libsocket(sendmsg);
1217 swrap_bind_symbol_libsocket(sendto);
1218 swrap_bind_symbol_libsocket(setsockopt);
1219 #ifdef HAVE_SIGNALFD
1220 swrap_bind_symbol_libsocket(signalfd);
1222 swrap_bind_symbol_libsocket(socket);
1223 swrap_bind_symbol_libsocket(socketpair);
1224 #ifdef HAVE_TIMERFD_CREATE
1225 swrap_bind_symbol_libc(timerfd_create);
1227 swrap_bind_symbol_libc(write);
1228 swrap_bind_symbol_libsocket(writev);
1231 static void swrap_bind_symbol_all(void)
1233 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1235 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1238 /*********************************************************
1239 * SWRAP HELPER FUNCTIONS
1240 *********************************************************/
1243 * We return 127.0.0.0 (default) or 10.53.57.0.
1245 * This can be controlled by:
1246 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1248 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1250 static in_addr_t swrap_ipv4_net(void)
1252 static int initialized;
1253 static in_addr_t hv;
1254 const char *net_str = NULL;
1263 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1264 if (net_str == NULL) {
1265 net_str = "127.0.0.0";
1268 ret = inet_pton(AF_INET, net_str, &nv);
1270 SWRAP_LOG(SWRAP_LOG_ERROR,
1271 "INVALID IPv4 Network [%s]",
1276 hv = ntohl(nv.s_addr);
1286 SWRAP_LOG(SWRAP_LOG_ERROR,
1287 "INVALID IPv4 Network [%s][0x%x] should be "
1288 "127.0.0.0 or 10.53.57.0",
1289 net_str, (unsigned)hv);
1297 * This returns 127.255.255.255 or 10.255.255.255
1299 static in_addr_t swrap_ipv4_bcast(void)
1303 hv = swrap_ipv4_net();
1304 hv |= IN_CLASSA_HOST;
1310 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1312 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1316 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1317 SWRAP_LOG(SWRAP_LOG_ERROR,
1318 "swrap_ipv4_iface(%u) invalid!",
1324 hv = swrap_ipv4_net();
1334 static const struct in6_addr *swrap_ipv6(void)
1336 static struct in6_addr v;
1337 static int initialized;
1345 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1354 static void set_port(int family, int prt, struct swrap_address *addr)
1358 addr->sa.in.sin_port = htons(prt);
1362 addr->sa.in6.sin6_port = htons(prt);
1368 static size_t socket_length(int family)
1372 return sizeof(struct sockaddr_in);
1375 return sizeof(struct sockaddr_in6);
1381 static struct socket_info *swrap_get_socket_info(int si_index)
1383 return (struct socket_info *)(&(sockets[si_index].info));
1386 static int swrap_get_refcount(struct socket_info *si)
1388 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1389 return sic->meta.refcount;
1392 static void swrap_inc_refcount(struct socket_info *si)
1394 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1396 sic->meta.refcount += 1;
1399 static void swrap_dec_refcount(struct socket_info *si)
1401 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1403 sic->meta.refcount -= 1;
1406 static int swrap_get_next_free(struct socket_info *si)
1408 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1410 return sic->meta.next_free;
1413 static void swrap_set_next_free(struct socket_info *si, int next_free)
1415 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1417 sic->meta.next_free = next_free;
1420 static int swrap_un_path(struct sockaddr_un *un,
1421 const char *swrap_dir,
1428 ret = snprintf(un->sun_path,
1429 sizeof(un->sun_path),
1435 if ((size_t)ret >= sizeof(un->sun_path)) {
1436 return ENAMETOOLONG;
1442 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1443 const char *swrap_dir)
1447 ret = snprintf(un->sun_path,
1448 sizeof(un->sun_path),
1452 if ((size_t)ret >= sizeof(un->sun_path)) {
1453 return ENAMETOOLONG;
1459 static bool swrap_dir_usable(const char *swrap_dir)
1461 struct sockaddr_un un;
1464 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1469 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1477 static char *socket_wrapper_dir(void)
1479 char *swrap_dir = NULL;
1480 char *s = getenv("SOCKET_WRAPPER_DIR");
1484 if (s == NULL || s[0] == '\0') {
1485 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1489 swrap_dir = realpath(s, NULL);
1490 if (swrap_dir == NULL) {
1491 SWRAP_LOG(SWRAP_LOG_ERROR,
1492 "Unable to resolve socket_wrapper dir path: %s - %s",
1498 ok = swrap_dir_usable(swrap_dir);
1505 ok = swrap_dir_usable(s);
1507 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1511 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1513 SWRAP_LOG(SWRAP_LOG_ERROR,
1514 "realpath(SOCKET_WRAPPER_DIR) too long and "
1515 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1520 swrap_dir = strdup(s);
1521 if (swrap_dir == NULL) {
1522 SWRAP_LOG(SWRAP_LOG_ERROR,
1523 "Unable to duplicate socket_wrapper dir path");
1527 SWRAP_LOG(SWRAP_LOG_WARN,
1528 "realpath(SOCKET_WRAPPER_DIR) too long, "
1529 "using original SOCKET_WRAPPER_DIR\n");
1532 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1536 static unsigned int socket_wrapper_mtu(void)
1538 static unsigned int max_mtu = 0;
1543 swrap_mutex_lock(&mtu_update_mutex);
1549 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1551 s = getenv("SOCKET_WRAPPER_MTU");
1556 tmp = strtol(s, &endp, 10);
1561 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1567 swrap_mutex_unlock(&mtu_update_mutex);
1571 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1573 pthread_mutexattr_t ma;
1574 bool need_destroy = false;
1577 #define __CHECK(cmd) do { \
1580 SWRAP_LOG(SWRAP_LOG_ERROR, \
1581 "%s: %s - failed %d", \
1587 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1588 __CHECK(pthread_mutexattr_init(&ma));
1589 need_destroy = true;
1590 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1591 __CHECK(pthread_mutex_init(m, &ma));
1594 pthread_mutexattr_destroy(&ma);
1599 static size_t socket_wrapper_max_sockets(void)
1605 if (socket_info_max != 0) {
1606 return socket_info_max;
1609 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1611 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1612 if (s == NULL || s[0] == '\0') {
1616 tmp = strtoul(s, &endp, 10);
1621 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1622 SWRAP_LOG(SWRAP_LOG_ERROR,
1623 "Invalid number of sockets specified, "
1624 "using default (%zu)",
1628 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1629 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1630 SWRAP_LOG(SWRAP_LOG_ERROR,
1631 "Invalid number of sockets specified, "
1632 "using maximum (%zu).",
1636 socket_info_max = tmp;
1639 return socket_info_max;
1642 static void socket_wrapper_init_fds_idx(void)
1647 if (socket_fds_idx != NULL) {
1651 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1653 SWRAP_LOG(SWRAP_LOG_ERROR,
1654 "Failed to allocate socket fds index array: %s",
1659 for (i = 0; i < socket_fds_max; i++) {
1663 socket_fds_idx = tmp;
1666 static void socket_wrapper_init_sockets(void)
1672 swrap_bind_symbol_all();
1674 swrap_mutex_lock(&sockets_mutex);
1676 if (sockets != NULL) {
1677 swrap_mutex_unlock(&sockets_mutex);
1681 SWRAP_LOG(SWRAP_LOG_DEBUG,
1682 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1683 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1686 * Intialize the static cache early before
1687 * any thread is able to start.
1689 (void)swrap_ipv4_net();
1691 socket_wrapper_init_fds_idx();
1693 /* Needs to be called inside the sockets_mutex lock here. */
1694 max_sockets = socket_wrapper_max_sockets();
1696 sockets = (struct socket_info_container *)calloc(max_sockets,
1697 sizeof(struct socket_info_container));
1699 if (sockets == NULL) {
1700 SWRAP_LOG(SWRAP_LOG_ERROR,
1701 "Failed to allocate sockets array: %s",
1703 swrap_mutex_unlock(&sockets_mutex);
1707 swrap_mutex_lock(&first_free_mutex);
1711 for (i = 0; i < max_sockets; i++) {
1712 swrap_set_next_free(&sockets[i].info, i+1);
1713 sockets[i].meta.mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1716 for (i = 0; i < max_sockets; i++) {
1717 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1719 SWRAP_LOG(SWRAP_LOG_ERROR,
1720 "Failed to initialize pthread mutex i=%zu", i);
1725 /* mark the end of the free list */
1726 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1729 swrap_mutex_unlock(&first_free_mutex);
1730 swrap_mutex_unlock(&sockets_mutex);
1736 bool socket_wrapper_enabled(void)
1738 char *s = socket_wrapper_dir();
1746 socket_wrapper_init_sockets();
1751 static unsigned int socket_wrapper_default_iface(void)
1753 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1756 if (sscanf(s, "%u", &iface) == 1) {
1757 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1763 return 1;/* 127.0.0.1 */
1766 static void set_socket_info_index(int fd, int idx)
1768 SWRAP_LOG(SWRAP_LOG_TRACE,
1771 socket_fds_idx[fd] = idx;
1772 /* This builtin issues a full memory barrier. */
1773 __sync_synchronize();
1776 static void reset_socket_info_index(int fd)
1778 SWRAP_LOG(SWRAP_LOG_TRACE,
1781 set_socket_info_index(fd, -1);
1784 static int find_socket_info_index(int fd)
1790 if (socket_fds_idx == NULL) {
1794 if ((size_t)fd >= socket_fds_max) {
1796 * Do not add a log here as some applications do stupid things
1799 * for (fd = 0; fd <= getdtablesize(); fd++) {
1803 * This would produce millions of lines of debug messages.
1806 SWRAP_LOG(SWRAP_LOG_ERROR,
1807 "Looking for a socket info for the fd %d is over the "
1808 "max socket index limit of %zu.",
1815 /* This builtin issues a full memory barrier. */
1816 __sync_synchronize();
1817 return socket_fds_idx[fd];
1820 static int swrap_add_socket_info(const struct socket_info *si_input)
1822 struct socket_info *si = NULL;
1825 if (si_input == NULL) {
1830 swrap_mutex_lock(&first_free_mutex);
1831 if (first_free == -1) {
1836 si_index = first_free;
1837 si = swrap_get_socket_info(si_index);
1841 first_free = swrap_get_next_free(si);
1843 swrap_inc_refcount(si);
1845 SWRAP_UNLOCK_SI(si);
1848 swrap_mutex_unlock(&first_free_mutex);
1853 static int swrap_create_socket(struct socket_info *si, int fd)
1857 if ((size_t)fd >= socket_fds_max) {
1858 SWRAP_LOG(SWRAP_LOG_ERROR,
1859 "The max socket index limit of %zu has been reached, "
1867 idx = swrap_add_socket_info(si);
1872 set_socket_info_index(fd, idx);
1877 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1884 p = strrchr(un->sun_path, '/');
1885 if (p) p++; else p = un->sun_path;
1887 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1888 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1894 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1895 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1902 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1908 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1912 case SOCKET_TYPE_CHAR_TCP:
1913 case SOCKET_TYPE_CHAR_UDP: {
1914 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1916 if ((*len) < sizeof(*in2)) {
1917 SWRAP_LOG(SWRAP_LOG_ERROR,
1918 "V4: *len(%zu) < sizeof(*in2)=%zu",
1919 (size_t)*len, sizeof(*in2));
1924 memset(in2, 0, sizeof(*in2));
1925 in2->sin_family = AF_INET;
1926 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1927 in2->sin_port = htons(prt);
1929 *len = sizeof(*in2);
1933 case SOCKET_TYPE_CHAR_TCP_V6:
1934 case SOCKET_TYPE_CHAR_UDP_V6: {
1935 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1937 if ((*len) < sizeof(*in2)) {
1938 SWRAP_LOG(SWRAP_LOG_ERROR,
1939 "V6: *len(%zu) < sizeof(*in2)=%zu",
1940 (size_t)*len, sizeof(*in2));
1941 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1946 memset(in2, 0, sizeof(*in2));
1947 in2->sin6_family = AF_INET6;
1948 in2->sin6_addr = *swrap_ipv6();
1949 in2->sin6_addr.s6_addr[15] = iface;
1950 in2->sin6_port = htons(prt);
1952 *len = sizeof(*in2);
1957 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1966 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1973 char *swrap_dir = NULL;
1975 if (bcast) *bcast = 0;
1977 switch (inaddr->sa_family) {
1979 const struct sockaddr_in *in =
1980 (const struct sockaddr_in *)(const void *)inaddr;
1981 unsigned int addr = ntohl(in->sin_addr.s_addr);
1985 const unsigned int sw_net_addr = swrap_ipv4_net();
1986 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1990 u_type = SOCKET_TYPE_CHAR_TCP;
1993 u_type = SOCKET_TYPE_CHAR_UDP;
1994 a_type = SOCKET_TYPE_CHAR_UDP;
1995 b_type = SOCKET_TYPE_CHAR_UDP;
1998 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
1999 errno = ESOCKTNOSUPPORT;
2003 prt = ntohs(in->sin_port);
2004 if (a_type && addr == 0xFFFFFFFF) {
2005 /* 255.255.255.255 only udp */
2008 iface = socket_wrapper_default_iface();
2009 } else if (b_type && addr == sw_bcast_addr) {
2018 iface = socket_wrapper_default_iface();
2019 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2020 /* 127.0.0.X or 10.53.57.X */
2023 iface = (addr & 0x000000FF);
2025 errno = ENETUNREACH;
2028 if (bcast) *bcast = is_bcast;
2033 const struct sockaddr_in6 *in =
2034 (const struct sockaddr_in6 *)(const void *)inaddr;
2035 struct in6_addr cmp1, cmp2;
2039 type = SOCKET_TYPE_CHAR_TCP_V6;
2042 type = SOCKET_TYPE_CHAR_UDP_V6;
2045 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2046 errno = ESOCKTNOSUPPORT;
2050 /* XXX no multicast/broadcast */
2052 prt = ntohs(in->sin6_port);
2054 cmp1 = *swrap_ipv6();
2055 cmp2 = in->sin6_addr;
2056 cmp2.s6_addr[15] = 0;
2057 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2058 iface = in->sin6_addr.s6_addr[15];
2060 errno = ENETUNREACH;
2068 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2069 errno = ENETUNREACH;
2074 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2079 swrap_dir = socket_wrapper_dir();
2080 if (swrap_dir == NULL) {
2086 swrap_un_path_EINVAL(un, swrap_dir);
2087 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2088 SAFE_FREE(swrap_dir);
2089 /* the caller need to do more processing */
2093 swrap_un_path(un, swrap_dir, type, iface, prt);
2094 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2096 SAFE_FREE(swrap_dir);
2101 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2109 char *swrap_dir = NULL;
2111 if (bcast) *bcast = 0;
2113 switch (si->family) {
2115 const struct sockaddr_in *in =
2116 (const struct sockaddr_in *)(const void *)inaddr;
2117 unsigned int addr = ntohl(in->sin_addr.s_addr);
2122 const unsigned int sw_net_addr = swrap_ipv4_net();
2123 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2125 prt = ntohs(in->sin_port);
2129 u_type = SOCKET_TYPE_CHAR_TCP;
2130 d_type = SOCKET_TYPE_CHAR_TCP;
2133 u_type = SOCKET_TYPE_CHAR_UDP;
2134 d_type = SOCKET_TYPE_CHAR_UDP;
2135 a_type = SOCKET_TYPE_CHAR_UDP;
2136 b_type = SOCKET_TYPE_CHAR_UDP;
2139 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2140 errno = ESOCKTNOSUPPORT;
2148 iface = socket_wrapper_default_iface();
2149 } else if (a_type && addr == 0xFFFFFFFF) {
2150 /* 255.255.255.255 only udp */
2153 iface = socket_wrapper_default_iface();
2154 } else if (b_type && addr == sw_bcast_addr) {
2155 /* 127.255.255.255 only udp */
2158 iface = socket_wrapper_default_iface();
2159 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2163 iface = (addr & 0x000000FF);
2165 errno = EADDRNOTAVAIL;
2169 /* Store the bind address for connect() */
2170 if (si->bindname.sa_socklen == 0) {
2171 struct sockaddr_in bind_in;
2172 socklen_t blen = sizeof(struct sockaddr_in);
2174 ZERO_STRUCT(bind_in);
2175 bind_in.sin_family = in->sin_family;
2176 bind_in.sin_port = in->sin_port;
2177 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2178 si->bindname.sa_socklen = blen;
2179 memcpy(&si->bindname.sa.in, &bind_in, blen);
2186 const struct sockaddr_in6 *in =
2187 (const struct sockaddr_in6 *)(const void *)inaddr;
2188 struct in6_addr cmp1, cmp2;
2192 type = SOCKET_TYPE_CHAR_TCP_V6;
2195 type = SOCKET_TYPE_CHAR_UDP_V6;
2198 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2199 errno = ESOCKTNOSUPPORT;
2203 /* XXX no multicast/broadcast */
2205 prt = ntohs(in->sin6_port);
2207 cmp1 = *swrap_ipv6();
2208 cmp2 = in->sin6_addr;
2209 cmp2.s6_addr[15] = 0;
2210 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2211 iface = socket_wrapper_default_iface();
2212 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2213 iface = in->sin6_addr.s6_addr[15];
2215 errno = EADDRNOTAVAIL;
2219 /* Store the bind address for connect() */
2220 if (si->bindname.sa_socklen == 0) {
2221 struct sockaddr_in6 bind_in;
2222 socklen_t blen = sizeof(struct sockaddr_in6);
2224 ZERO_STRUCT(bind_in);
2225 bind_in.sin6_family = in->sin6_family;
2226 bind_in.sin6_port = in->sin6_port;
2228 bind_in.sin6_addr = *swrap_ipv6();
2229 bind_in.sin6_addr.s6_addr[15] = iface;
2231 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2232 si->bindname.sa_socklen = blen;
2239 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2240 errno = EADDRNOTAVAIL;
2245 if (bcast) *bcast = is_bcast;
2247 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2252 swrap_dir = socket_wrapper_dir();
2253 if (swrap_dir == NULL) {
2259 /* handle auto-allocation of ephemeral ports */
2260 for (prt = 5001; prt < 10000; prt++) {
2261 swrap_un_path(un, swrap_dir, type, iface, prt);
2262 if (stat(un->sun_path, &st) == 0) continue;
2264 set_port(si->family, prt, &si->myname);
2265 set_port(si->family, prt, &si->bindname);
2272 SAFE_FREE(swrap_dir);
2277 swrap_un_path(un, swrap_dir, type, iface, prt);
2278 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2280 SAFE_FREE(swrap_dir);
2285 static struct socket_info *find_socket_info(int fd)
2287 int idx = find_socket_info_index(fd);
2293 return swrap_get_socket_info(idx);
2297 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2299 struct socket_info_fd *f;
2300 const struct socket_info *last_s = NULL;
2302 /* first catch invalid input */
2303 switch (sa->sa_family) {
2305 if (len < sizeof(struct sockaddr_in)) {
2311 if (len < sizeof(struct sockaddr_in6)) {
2321 for (f = socket_fds; f; f = f->next) {
2322 struct socket_info *s = swrap_get_socket_info(f->si_index);
2329 if (s->myname == NULL) {
2332 if (s->myname->sa_family != sa->sa_family) {
2335 switch (s->myname->sa_family) {
2337 struct sockaddr_in *sin1, *sin2;
2339 sin1 = (struct sockaddr_in *)s->myname;
2340 sin2 = (struct sockaddr_in *)sa;
2342 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2345 if (sin1->sin_port != sin2->sin_port) {
2348 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2358 struct sockaddr_in6 *sin1, *sin2;
2360 sin1 = (struct sockaddr_in6 *)s->myname;
2361 sin2 = (struct sockaddr_in6 *)sa;
2363 if (sin1->sin6_port != sin2->sin6_port) {
2366 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2388 static void swrap_remove_stale(int fd)
2390 struct socket_info *si;
2393 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2395 swrap_mutex_lock(&socket_reset_mutex);
2397 si_index = find_socket_info_index(fd);
2398 if (si_index == -1) {
2399 swrap_mutex_unlock(&socket_reset_mutex);
2403 reset_socket_info_index(fd);
2405 si = swrap_get_socket_info(si_index);
2407 swrap_mutex_lock(&first_free_mutex);
2410 swrap_dec_refcount(si);
2412 if (swrap_get_refcount(si) > 0) {
2416 if (si->un_addr.sun_path[0] != '\0') {
2417 unlink(si->un_addr.sun_path);
2420 swrap_set_next_free(si, first_free);
2421 first_free = si_index;
2424 SWRAP_UNLOCK_SI(si);
2425 swrap_mutex_unlock(&first_free_mutex);
2426 swrap_mutex_unlock(&socket_reset_mutex);
2429 static int sockaddr_convert_to_un(struct socket_info *si,
2430 const struct sockaddr *in_addr,
2432 struct sockaddr_un *out_addr,
2436 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2438 (void) in_len; /* unused */
2440 if (out_addr == NULL) {
2444 out->sa_family = AF_UNIX;
2445 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2446 out->sa_len = sizeof(*out_addr);
2449 switch (in_addr->sa_family) {
2451 const struct sockaddr_in *sin;
2452 if (si->family != AF_INET) {
2455 if (in_len < sizeof(struct sockaddr_in)) {
2458 sin = (const struct sockaddr_in *)(const void *)in_addr;
2459 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2464 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2465 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2479 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2480 errno = ESOCKTNOSUPPORT;
2484 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2486 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2492 errno = EAFNOSUPPORT;
2493 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2497 static int sockaddr_convert_from_un(const struct socket_info *si,
2498 const struct sockaddr_un *in_addr,
2499 socklen_t un_addrlen,
2501 struct sockaddr *out_addr,
2502 socklen_t *out_addrlen)
2506 if (out_addr == NULL || out_addrlen == NULL)
2509 if (un_addrlen == 0) {
2524 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2525 errno = ESOCKTNOSUPPORT;
2528 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2529 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2530 out_addr->sa_len = *out_addrlen;
2537 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2538 errno = EAFNOSUPPORT;
2542 enum swrap_packet_type {
2544 SWRAP_CONNECT_UNREACH,
2552 SWRAP_SENDTO_UNREACH,
2563 struct swrap_file_hdr {
2565 uint16_t version_major;
2566 uint16_t version_minor;
2569 uint32_t frame_max_len;
2570 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2573 #define SWRAP_FILE_HDR_SIZE 24
2575 struct swrap_packet_frame {
2577 uint32_t micro_seconds;
2578 uint32_t recorded_length;
2579 uint32_t full_length;
2581 #define SWRAP_PACKET_FRAME_SIZE 16
2583 union swrap_packet_ip {
2587 uint16_t packet_length;
2588 uint16_t identification;
2593 uint16_t hdr_checksum;
2597 #define SWRAP_PACKET_IP_V4_SIZE 20
2600 uint8_t flow_label_high;
2601 uint16_t flow_label_low;
2602 uint16_t payload_length;
2603 uint8_t next_header;
2605 uint8_t src_addr[16];
2606 uint8_t dest_addr[16];
2608 #define SWRAP_PACKET_IP_V6_SIZE 40
2610 #define SWRAP_PACKET_IP_SIZE 40
2612 union swrap_packet_payload {
2614 uint16_t source_port;
2624 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2626 uint16_t source_port;
2631 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2638 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2645 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2647 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2649 #define SWRAP_PACKET_MIN_ALLOC \
2650 (SWRAP_PACKET_FRAME_SIZE + \
2651 SWRAP_PACKET_IP_SIZE + \
2652 SWRAP_PACKET_PAYLOAD_SIZE)
2654 static const char *swrap_pcap_init_file(void)
2656 static int initialized = 0;
2657 static const char *s = NULL;
2658 static const struct swrap_file_hdr h;
2659 static const struct swrap_packet_frame f;
2660 static const union swrap_packet_ip i;
2661 static const union swrap_packet_payload p;
2663 if (initialized == 1) {
2669 * TODO: don't use the structs use plain buffer offsets
2670 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2672 * for now make sure we disable PCAP support
2673 * if the struct has alignment!
2675 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2678 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2681 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2684 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2687 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2690 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2693 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2696 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2699 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2702 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2706 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2710 if (strncmp(s, "./", 2) == 0) {
2713 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2717 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2718 const struct sockaddr *src,
2719 const struct sockaddr *dest,
2721 const uint8_t *payload,
2723 unsigned long tcp_seqno,
2724 unsigned long tcp_ack,
2725 unsigned char tcp_ctl,
2727 size_t *_packet_len)
2729 uint8_t *base = NULL;
2730 uint8_t *buf = NULL;
2733 struct swrap_packet_frame *frame;
2737 union swrap_packet_ip *ip;
2739 union swrap_packet_payload *pay;
2742 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2743 size_t wire_hdr_len = 0;
2744 size_t wire_len = 0;
2745 size_t ip_hdr_len = 0;
2746 size_t icmp_hdr_len = 0;
2747 size_t icmp_truncate_len = 0;
2748 uint8_t protocol = 0, icmp_protocol = 0;
2749 const struct sockaddr_in *src_in = NULL;
2750 const struct sockaddr_in *dest_in = NULL;
2752 const struct sockaddr_in6 *src_in6 = NULL;
2753 const struct sockaddr_in6 *dest_in6 = NULL;
2758 switch (src->sa_family) {
2760 src_in = (const struct sockaddr_in *)(const void *)src;
2761 dest_in = (const struct sockaddr_in *)(const void *)dest;
2762 src_port = src_in->sin_port;
2763 dest_port = dest_in->sin_port;
2764 ip_hdr_len = sizeof(i.ip->v4);
2768 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2769 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2770 src_port = src_in6->sin6_port;
2771 dest_port = dest_in6->sin6_port;
2772 ip_hdr_len = sizeof(i.ip->v6);
2779 switch (socket_type) {
2781 protocol = 0x06; /* TCP */
2782 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2783 wire_len = wire_hdr_len + payload_len;
2787 protocol = 0x11; /* UDP */
2788 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2789 wire_len = wire_hdr_len + payload_len;
2797 icmp_protocol = protocol;
2798 switch (src->sa_family) {
2800 protocol = 0x01; /* ICMPv4 */
2801 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2805 protocol = 0x3A; /* ICMPv6 */
2806 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2810 if (wire_len > 64 ) {
2811 icmp_truncate_len = wire_len - 64;
2813 wire_len += icmp_hdr_len;
2816 packet_len = nonwire_len + wire_len;
2817 alloc_len = packet_len;
2818 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2819 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2822 base = (uint8_t *)calloc(1, alloc_len);
2830 f.frame->seconds = tval->tv_sec;
2831 f.frame->micro_seconds = tval->tv_usec;
2832 f.frame->recorded_length = wire_len - icmp_truncate_len;
2833 f.frame->full_length = wire_len - icmp_truncate_len;
2835 buf += SWRAP_PACKET_FRAME_SIZE;
2838 switch (src->sa_family) {
2840 if (src_in == NULL || dest_in == NULL) {
2845 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2846 i.ip->v4.tos = 0x00;
2847 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2848 i.ip->v4.identification = htons(0xFFFF);
2849 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2850 i.ip->v4.fragment = htons(0x0000);
2851 i.ip->v4.ttl = 0xFF;
2852 i.ip->v4.protocol = protocol;
2853 i.ip->v4.hdr_checksum = htons(0x0000);
2854 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2855 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2856 buf += SWRAP_PACKET_IP_V4_SIZE;
2860 if (src_in6 == NULL || dest_in6 == NULL) {
2865 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2866 i.ip->v6.flow_label_high = 0x00;
2867 i.ip->v6.flow_label_low = 0x0000;
2868 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2869 i.ip->v6.next_header = protocol;
2870 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2871 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2872 buf += SWRAP_PACKET_IP_V6_SIZE;
2878 pay = (union swrap_packet_payload *)(void *)buf;
2879 switch (src->sa_family) {
2881 pay->icmp4.type = 0x03; /* destination unreachable */
2882 pay->icmp4.code = 0x01; /* host unreachable */
2883 pay->icmp4.checksum = htons(0x0000);
2884 pay->icmp4.unused = htonl(0x00000000);
2886 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2888 /* set the ip header in the ICMP payload */
2890 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2891 i.ip->v4.tos = 0x00;
2892 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2893 i.ip->v4.identification = htons(0xFFFF);
2894 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2895 i.ip->v4.fragment = htons(0x0000);
2896 i.ip->v4.ttl = 0xFF;
2897 i.ip->v4.protocol = icmp_protocol;
2898 i.ip->v4.hdr_checksum = htons(0x0000);
2899 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2900 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2902 buf += SWRAP_PACKET_IP_V4_SIZE;
2904 src_port = dest_in->sin_port;
2905 dest_port = src_in->sin_port;
2909 pay->icmp6.type = 0x01; /* destination unreachable */
2910 pay->icmp6.code = 0x03; /* address unreachable */
2911 pay->icmp6.checksum = htons(0x0000);
2912 pay->icmp6.unused = htonl(0x00000000);
2913 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2915 /* set the ip header in the ICMP payload */
2917 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2918 i.ip->v6.flow_label_high = 0x00;
2919 i.ip->v6.flow_label_low = 0x0000;
2920 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2921 i.ip->v6.next_header = protocol;
2922 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2923 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2925 buf += SWRAP_PACKET_IP_V6_SIZE;
2927 src_port = dest_in6->sin6_port;
2928 dest_port = src_in6->sin6_port;
2934 pay = (union swrap_packet_payload *)(void *)buf;
2936 switch (socket_type) {
2938 pay->tcp.source_port = src_port;
2939 pay->tcp.dest_port = dest_port;
2940 pay->tcp.seq_num = htonl(tcp_seqno);
2941 pay->tcp.ack_num = htonl(tcp_ack);
2942 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2943 pay->tcp.control = tcp_ctl;
2944 pay->tcp.window = htons(0x7FFF);
2945 pay->tcp.checksum = htons(0x0000);
2946 pay->tcp.urg = htons(0x0000);
2947 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2952 pay->udp.source_port = src_port;
2953 pay->udp.dest_port = dest_port;
2954 pay->udp.length = htons(8 + payload_len);
2955 pay->udp.checksum = htons(0x0000);
2956 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2961 if (payload && payload_len > 0) {
2962 memcpy(buf, payload, payload_len);
2965 *_packet_len = packet_len - icmp_truncate_len;
2969 static int swrap_pcap_get_fd(const char *fname)
2977 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2979 struct swrap_file_hdr file_hdr;
2980 file_hdr.magic = 0xA1B2C3D4;
2981 file_hdr.version_major = 0x0002;
2982 file_hdr.version_minor = 0x0004;
2983 file_hdr.timezone = 0x00000000;
2984 file_hdr.sigfigs = 0x00000000;
2985 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2986 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2988 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2995 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3000 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3001 const struct sockaddr *addr,
3002 enum swrap_packet_type type,
3003 const void *buf, size_t len,
3006 const struct sockaddr *src_addr;
3007 const struct sockaddr *dest_addr;
3008 unsigned long tcp_seqno = 0;
3009 unsigned long tcp_ack = 0;
3010 unsigned char tcp_ctl = 0;
3011 int unreachable = 0;
3015 switch (si->family) {
3027 case SWRAP_CONNECT_SEND:
3028 if (si->type != SOCK_STREAM) {
3032 src_addr = &si->myname.sa.s;
3035 tcp_seqno = si->io.pck_snd;
3036 tcp_ack = si->io.pck_rcv;
3037 tcp_ctl = 0x02; /* SYN */
3039 si->io.pck_snd += 1;
3043 case SWRAP_CONNECT_RECV:
3044 if (si->type != SOCK_STREAM) {
3048 dest_addr = &si->myname.sa.s;
3051 tcp_seqno = si->io.pck_rcv;
3052 tcp_ack = si->io.pck_snd;
3053 tcp_ctl = 0x12; /** SYN,ACK */
3055 si->io.pck_rcv += 1;
3059 case SWRAP_CONNECT_UNREACH:
3060 if (si->type != SOCK_STREAM) {
3064 dest_addr = &si->myname.sa.s;
3067 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3068 tcp_seqno = si->io.pck_snd - 1;
3069 tcp_ack = si->io.pck_rcv;
3070 tcp_ctl = 0x02; /* SYN */
3075 case SWRAP_CONNECT_ACK:
3076 if (si->type != SOCK_STREAM) {
3080 src_addr = &si->myname.sa.s;
3083 tcp_seqno = si->io.pck_snd;
3084 tcp_ack = si->io.pck_rcv;
3085 tcp_ctl = 0x10; /* ACK */
3089 case SWRAP_ACCEPT_SEND:
3090 if (si->type != SOCK_STREAM) {
3094 dest_addr = &si->myname.sa.s;
3097 tcp_seqno = si->io.pck_rcv;
3098 tcp_ack = si->io.pck_snd;
3099 tcp_ctl = 0x02; /* SYN */
3101 si->io.pck_rcv += 1;
3105 case SWRAP_ACCEPT_RECV:
3106 if (si->type != SOCK_STREAM) {
3110 src_addr = &si->myname.sa.s;
3113 tcp_seqno = si->io.pck_snd;
3114 tcp_ack = si->io.pck_rcv;
3115 tcp_ctl = 0x12; /* SYN,ACK */
3117 si->io.pck_snd += 1;
3121 case SWRAP_ACCEPT_ACK:
3122 if (si->type != SOCK_STREAM) {
3126 dest_addr = &si->myname.sa.s;
3129 tcp_seqno = si->io.pck_rcv;
3130 tcp_ack = si->io.pck_snd;
3131 tcp_ctl = 0x10; /* ACK */
3136 src_addr = &si->myname.sa.s;
3137 dest_addr = &si->peername.sa.s;
3139 tcp_seqno = si->io.pck_snd;
3140 tcp_ack = si->io.pck_rcv;
3141 tcp_ctl = 0x18; /* PSH,ACK */
3143 si->io.pck_snd += len;
3147 case SWRAP_SEND_RST:
3148 dest_addr = &si->myname.sa.s;
3149 src_addr = &si->peername.sa.s;
3151 if (si->type == SOCK_DGRAM) {
3152 return swrap_pcap_marshall_packet(si,
3154 SWRAP_SENDTO_UNREACH,
3160 tcp_seqno = si->io.pck_rcv;
3161 tcp_ack = si->io.pck_snd;
3162 tcp_ctl = 0x14; /** RST,ACK */
3166 case SWRAP_PENDING_RST:
3167 dest_addr = &si->myname.sa.s;
3168 src_addr = &si->peername.sa.s;
3170 if (si->type == SOCK_DGRAM) {
3174 tcp_seqno = si->io.pck_rcv;
3175 tcp_ack = si->io.pck_snd;
3176 tcp_ctl = 0x14; /* RST,ACK */
3181 dest_addr = &si->myname.sa.s;
3182 src_addr = &si->peername.sa.s;
3184 tcp_seqno = si->io.pck_rcv;
3185 tcp_ack = si->io.pck_snd;
3186 tcp_ctl = 0x18; /* PSH,ACK */
3188 si->io.pck_rcv += len;
3192 case SWRAP_RECV_RST:
3193 dest_addr = &si->myname.sa.s;
3194 src_addr = &si->peername.sa.s;
3196 if (si->type == SOCK_DGRAM) {
3200 tcp_seqno = si->io.pck_rcv;
3201 tcp_ack = si->io.pck_snd;
3202 tcp_ctl = 0x14; /* RST,ACK */
3207 src_addr = &si->myname.sa.s;
3210 si->io.pck_snd += len;
3214 case SWRAP_SENDTO_UNREACH:
3215 dest_addr = &si->myname.sa.s;
3222 case SWRAP_RECVFROM:
3223 dest_addr = &si->myname.sa.s;
3226 si->io.pck_rcv += len;
3230 case SWRAP_CLOSE_SEND:
3231 if (si->type != SOCK_STREAM) {
3235 src_addr = &si->myname.sa.s;
3236 dest_addr = &si->peername.sa.s;
3238 tcp_seqno = si->io.pck_snd;
3239 tcp_ack = si->io.pck_rcv;
3240 tcp_ctl = 0x11; /* FIN, ACK */
3242 si->io.pck_snd += 1;
3246 case SWRAP_CLOSE_RECV:
3247 if (si->type != SOCK_STREAM) {
3251 dest_addr = &si->myname.sa.s;
3252 src_addr = &si->peername.sa.s;
3254 tcp_seqno = si->io.pck_rcv;
3255 tcp_ack = si->io.pck_snd;
3256 tcp_ctl = 0x11; /* FIN,ACK */
3258 si->io.pck_rcv += 1;
3262 case SWRAP_CLOSE_ACK:
3263 if (si->type != SOCK_STREAM) {
3267 src_addr = &si->myname.sa.s;
3268 dest_addr = &si->peername.sa.s;
3270 tcp_seqno = si->io.pck_snd;
3271 tcp_ack = si->io.pck_rcv;
3272 tcp_ctl = 0x10; /* ACK */
3279 swrapGetTimeOfDay(&tv);
3281 return swrap_pcap_packet_init(&tv,
3285 (const uint8_t *)buf,
3294 static void swrap_pcap_dump_packet(struct socket_info *si,
3295 const struct sockaddr *addr,
3296 enum swrap_packet_type type,
3297 const void *buf, size_t len)
3299 const char *file_name;
3301 size_t packet_len = 0;
3304 swrap_mutex_lock(&pcap_dump_mutex);
3306 file_name = swrap_pcap_init_file();
3311 packet = swrap_pcap_marshall_packet(si,
3317 if (packet == NULL) {
3321 fd = swrap_pcap_get_fd(file_name);
3323 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3332 swrap_mutex_unlock(&pcap_dump_mutex);
3335 /****************************************************************************
3337 ***************************************************************************/
3339 #ifdef HAVE_SIGNALFD
3340 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3344 rc = libc_signalfd(fd, mask, flags);
3346 swrap_remove_stale(fd);
3352 int signalfd(int fd, const sigset_t *mask, int flags)
3354 return swrap_signalfd(fd, mask, flags);
3358 /****************************************************************************
3360 ***************************************************************************/
3362 static int swrap_socket(int family, int type, int protocol)
3364 struct socket_info *si = NULL;
3365 struct socket_info _si = { 0 };
3368 int real_type = type;
3371 * Remove possible addition flags passed to socket() so
3372 * do not fail checking the type.
3373 * See https://lwn.net/Articles/281965/
3376 real_type &= ~SOCK_CLOEXEC;
3378 #ifdef SOCK_NONBLOCK
3379 real_type &= ~SOCK_NONBLOCK;
3382 if (!socket_wrapper_enabled()) {
3383 return libc_socket(family, type, protocol);
3394 #endif /* AF_NETLINK */
3397 #endif /* AF_PACKET */
3399 fd = libc_socket(family, type, protocol);
3401 /* Check if we have a stale fd and remove it */
3402 swrap_remove_stale(fd);
3403 SWRAP_LOG(SWRAP_LOG_TRACE,
3404 "Unix socket fd=%d",
3409 errno = EAFNOSUPPORT;
3413 switch (real_type) {
3419 errno = EPROTONOSUPPORT;
3427 if (real_type == SOCK_STREAM) {
3432 if (real_type == SOCK_DGRAM) {
3437 errno = EPROTONOSUPPORT;
3442 * We must call libc_socket with type, from the caller, not the version
3443 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3445 fd = libc_socket(AF_UNIX, type, 0);
3451 /* Check if we have a stale fd and remove it */
3452 swrap_remove_stale(fd);
3455 si->family = family;
3457 /* however, the rest of the socket_wrapper code expects just
3458 * the type, not the flags */
3459 si->type = real_type;
3460 si->protocol = protocol;
3463 * Setup myname so getsockname() can succeed to find out the socket
3466 switch(si->family) {
3468 struct sockaddr_in sin = {
3469 .sin_family = AF_INET,
3472 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3473 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3478 struct sockaddr_in6 sin6 = {
3479 .sin6_family = AF_INET6,
3482 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3483 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3492 ret = swrap_create_socket(si, fd);
3494 int saved_errno = errno;
3496 errno = saved_errno;
3500 SWRAP_LOG(SWRAP_LOG_TRACE,
3501 "Created %s socket for protocol %s, fd=%d",
3502 family == AF_INET ? "IPv4" : "IPv6",
3503 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3509 int socket(int family, int type, int protocol)
3511 return swrap_socket(family, type, protocol);
3514 /****************************************************************************
3516 ***************************************************************************/
3518 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3522 rc = libc_socketpair(family, type, protocol, sv);
3524 swrap_remove_stale(sv[0]);
3525 swrap_remove_stale(sv[1]);
3531 int socketpair(int family, int type, int protocol, int sv[2])
3533 return swrap_socketpair(family, type, protocol, sv);
3536 /****************************************************************************
3538 ***************************************************************************/
3540 #ifdef HAVE_TIMERFD_CREATE
3541 static int swrap_timerfd_create(int clockid, int flags)
3545 fd = libc_timerfd_create(clockid, flags);
3547 swrap_remove_stale(fd);
3553 int timerfd_create(int clockid, int flags)
3555 return swrap_timerfd_create(clockid, flags);
3559 /****************************************************************************
3561 ***************************************************************************/
3563 static int swrap_pipe(int pipefd[2])
3567 rc = libc_pipe(pipefd);
3569 swrap_remove_stale(pipefd[0]);
3570 swrap_remove_stale(pipefd[1]);
3576 int pipe(int pipefd[2])
3578 return swrap_pipe(pipefd);
3581 /****************************************************************************
3583 ***************************************************************************/
3585 static int swrap_accept(int s,
3586 struct sockaddr *addr,
3590 struct socket_info *parent_si, *child_si;
3591 struct socket_info new_si = { 0 };
3594 struct swrap_address un_addr = {
3595 .sa_socklen = sizeof(struct sockaddr_un),
3597 struct swrap_address un_my_addr = {
3598 .sa_socklen = sizeof(struct sockaddr_un),
3600 struct swrap_address in_addr = {
3601 .sa_socklen = sizeof(struct sockaddr_storage),
3603 struct swrap_address in_my_addr = {
3604 .sa_socklen = sizeof(struct sockaddr_storage),
3608 parent_si = find_socket_info(s);
3611 return libc_accept4(s, addr, addrlen, flags);
3614 return libc_accept(s, addr, addrlen);
3620 * prevent parent_si from being altered / closed
3623 SWRAP_LOCK_SI(parent_si);
3626 * assume out sockaddr have the same size as the in parent
3629 in_addr.sa_socklen = socket_length(parent_si->family);
3630 if (in_addr.sa_socklen <= 0) {
3631 SWRAP_UNLOCK_SI(parent_si);
3636 SWRAP_UNLOCK_SI(parent_si);
3639 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3642 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3645 int saved_errno = errno;
3646 if (saved_errno == ENOTSOCK) {
3647 /* Remove stale fds */
3648 swrap_remove_stale(s);
3650 errno = saved_errno;
3656 /* Check if we have a stale fd and remove it */
3657 swrap_remove_stale(fd);
3659 if (un_addr.sa.un.sun_path[0] == '\0') {
3661 * FreeBSD seems to have a problem where
3662 * accept4() on the unix socket doesn't
3663 * ECONNABORTED for already disconnected connections.
3665 * Let's try libc_getpeername() to get the peer address
3666 * as a fallback, but it'll likely return ENOTCONN,
3667 * which we have to map to ECONNABORTED.
3669 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3670 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3672 int saved_errno = errno;
3674 if (saved_errno == ENOTCONN) {
3676 * If the connection is already disconnected
3677 * we should return ECONNABORTED.
3679 saved_errno = ECONNABORTED;
3681 errno = saved_errno;
3686 ret = libc_getsockname(fd,
3688 &un_my_addr.sa_socklen);
3690 int saved_errno = errno;
3692 if (saved_errno == ENOTCONN) {
3694 * If the connection is already disconnected
3695 * we should return ECONNABORTED.
3697 saved_errno = ECONNABORTED;
3699 errno = saved_errno;
3703 SWRAP_LOCK_SI(parent_si);
3705 ret = sockaddr_convert_from_un(parent_si,
3710 &in_addr.sa_socklen);
3712 int saved_errno = errno;
3713 SWRAP_UNLOCK_SI(parent_si);
3715 errno = saved_errno;
3721 child_si->family = parent_si->family;
3722 child_si->type = parent_si->type;
3723 child_si->protocol = parent_si->protocol;
3724 child_si->bound = 1;
3725 child_si->is_server = 1;
3726 child_si->connected = 1;
3728 SWRAP_UNLOCK_SI(parent_si);
3730 child_si->peername = (struct swrap_address) {
3731 .sa_socklen = in_addr.sa_socklen,
3733 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3735 if (addr != NULL && addrlen != NULL) {
3736 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3738 memcpy(addr, &in_addr.sa.ss, copy_len);
3740 *addrlen = in_addr.sa_socklen;
3743 ret = sockaddr_convert_from_un(child_si,
3745 un_my_addr.sa_socklen,
3748 &in_my_addr.sa_socklen);
3750 int saved_errno = errno;
3752 errno = saved_errno;
3756 SWRAP_LOG(SWRAP_LOG_TRACE,
3757 "accept() path=%s, fd=%d",
3758 un_my_addr.sa.un.sun_path, s);
3760 child_si->myname = (struct swrap_address) {
3761 .sa_socklen = in_my_addr.sa_socklen,
3763 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3765 idx = swrap_create_socket(&new_si, fd);
3767 int saved_errno = errno;
3769 errno = saved_errno;
3774 struct socket_info *si = swrap_get_socket_info(idx);
3777 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3778 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3779 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3780 SWRAP_UNLOCK_SI(si);
3787 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3789 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3793 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3794 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3796 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3799 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3802 static int autobind_start_init;
3803 static int autobind_start;
3805 /* using sendto() or connect() on an unbound socket would give the
3806 recipient no way to reply, as unlike UDP and TCP, a unix domain
3807 socket can't auto-assign ephemeral port numbers, so we need to
3809 Note: this might change the family from ipv6 to ipv4
3811 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3813 struct swrap_address un_addr = {
3814 .sa_socklen = sizeof(struct sockaddr_un),
3821 char *swrap_dir = NULL;
3823 swrap_mutex_lock(&autobind_start_mutex);
3825 if (autobind_start_init != 1) {
3826 autobind_start_init = 1;
3827 autobind_start = getpid();
3828 autobind_start %= 50000;
3829 autobind_start += 10000;
3832 un_addr.sa.un.sun_family = AF_UNIX;
3836 struct sockaddr_in in;
3840 type = SOCKET_TYPE_CHAR_TCP;
3843 type = SOCKET_TYPE_CHAR_UDP;
3846 errno = ESOCKTNOSUPPORT;
3851 memset(&in, 0, sizeof(in));
3852 in.sin_family = AF_INET;
3853 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3854 socket_wrapper_default_iface()));
3856 si->myname = (struct swrap_address) {
3857 .sa_socklen = sizeof(in),
3859 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3864 struct sockaddr_in6 in6;
3866 if (si->family != family) {
3867 errno = ENETUNREACH;
3874 type = SOCKET_TYPE_CHAR_TCP_V6;
3877 type = SOCKET_TYPE_CHAR_UDP_V6;
3880 errno = ESOCKTNOSUPPORT;
3885 memset(&in6, 0, sizeof(in6));
3886 in6.sin6_family = AF_INET6;
3887 in6.sin6_addr = *swrap_ipv6();
3888 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3890 si->myname = (struct swrap_address) {
3891 .sa_socklen = sizeof(in6),
3893 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3898 errno = ESOCKTNOSUPPORT;
3903 if (autobind_start > 60000) {
3904 autobind_start = 10000;
3907 swrap_dir = socket_wrapper_dir();
3908 if (swrap_dir == NULL) {
3914 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3915 port = autobind_start + i;
3916 swrap_un_path(&un_addr.sa.un,
3919 socket_wrapper_default_iface(),
3921 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3923 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3928 si->un_addr = un_addr.sa.un;
3931 autobind_start = port + 1;
3934 if (i == SOCKET_MAX_SOCKETS) {
3935 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3936 "interface "SOCKET_FORMAT,
3939 socket_wrapper_default_iface(),
3946 si->family = family;
3947 set_port(si->family, port, &si->myname);
3952 SAFE_FREE(swrap_dir);
3953 swrap_mutex_unlock(&autobind_start_mutex);
3957 /****************************************************************************
3959 ***************************************************************************/
3961 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3965 struct swrap_address un_addr = {
3966 .sa_socklen = sizeof(struct sockaddr_un),
3968 struct socket_info *si = find_socket_info(s);
3972 return libc_connect(s, serv_addr, addrlen);
3977 if (si->bound == 0) {
3978 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3984 if (si->family != serv_addr->sa_family) {
3985 SWRAP_LOG(SWRAP_LOG_ERROR,
3986 "called for fd=%d (family=%d) called with invalid family=%d",
3987 s, si->family, serv_addr->sa_family);
3993 ret = sockaddr_convert_to_un(si, serv_addr,
3994 addrlen, &un_addr.sa.un, 0, &bcast);
4000 errno = ENETUNREACH;
4005 if (si->type == SOCK_DGRAM) {
4006 si->defer_connect = 1;
4009 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4011 ret = libc_connect(s,
4013 un_addr.sa_socklen);
4016 SWRAP_LOG(SWRAP_LOG_TRACE,
4017 "connect() path=%s, fd=%d",
4018 un_addr.sa.un.sun_path, s);
4021 /* to give better errors */
4022 if (ret == -1 && errno == ENOENT) {
4023 errno = EHOSTUNREACH;
4027 si->peername = (struct swrap_address) {
4028 .sa_socklen = addrlen,
4031 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4035 * When we connect() on a socket than we have to bind the
4036 * outgoing connection on the interface we use for the
4037 * transport. We already bound it on the right interface
4038 * but here we have to update the name so getsockname()
4039 * returns correct information.
4041 if (si->bindname.sa_socklen > 0) {
4042 si->myname = (struct swrap_address) {
4043 .sa_socklen = si->bindname.sa_socklen,
4046 memcpy(&si->myname.sa.ss,
4047 &si->bindname.sa.ss,
4048 si->bindname.sa_socklen);
4050 /* Cleanup bindname */
4051 si->bindname = (struct swrap_address) {
4056 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4057 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4059 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4063 SWRAP_UNLOCK_SI(si);
4067 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4069 return swrap_connect(s, serv_addr, addrlen);
4072 /****************************************************************************
4074 ***************************************************************************/
4076 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4079 struct swrap_address un_addr = {
4080 .sa_socklen = sizeof(struct sockaddr_un),
4082 struct socket_info *si = find_socket_info(s);
4089 return libc_bind(s, myaddr, addrlen);
4094 switch (si->family) {
4096 const struct sockaddr_in *sin;
4097 if (addrlen < sizeof(struct sockaddr_in)) {
4098 bind_error = EINVAL;
4102 sin = (const struct sockaddr_in *)(const void *)myaddr;
4104 if (sin->sin_family != AF_INET) {
4105 bind_error = EAFNOSUPPORT;
4108 /* special case for AF_UNSPEC */
4109 if (sin->sin_family == AF_UNSPEC &&
4110 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4119 const struct sockaddr_in6 *sin6;
4120 if (addrlen < sizeof(struct sockaddr_in6)) {
4121 bind_error = EINVAL;
4125 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4127 if (sin6->sin6_family != AF_INET6) {
4128 bind_error = EAFNOSUPPORT;
4135 bind_error = EINVAL;
4139 if (bind_error != 0) {
4146 in_use = check_addr_port_in_use(myaddr, addrlen);
4154 si->myname.sa_socklen = addrlen;
4155 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4157 ret = sockaddr_convert_to_un(si,
4167 unlink(un_addr.sa.un.sun_path);
4169 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4171 SWRAP_LOG(SWRAP_LOG_TRACE,
4172 "bind() path=%s, fd=%d",
4173 un_addr.sa.un.sun_path, s);
4180 SWRAP_UNLOCK_SI(si);
4185 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4187 return swrap_bind(s, myaddr, addrlen);
4190 /****************************************************************************
4192 ***************************************************************************/
4194 #ifdef HAVE_BINDRESVPORT
4195 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4197 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4199 struct swrap_address myaddr = {
4200 .sa_socklen = sizeof(struct sockaddr_storage),
4203 static uint16_t port;
4208 #define SWRAP_STARTPORT 600
4209 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4210 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4213 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4217 salen = myaddr.sa_socklen;
4220 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4226 memset(&myaddr.sa.ss, 0, salen);
4231 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4234 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4236 salen = sizeof(struct sockaddr_in);
4237 sinp->sin_port = htons(port);
4241 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4243 salen = sizeof(struct sockaddr_in6);
4244 sin6p->sin6_port = htons(port);
4248 errno = EAFNOSUPPORT;
4253 if (port > SWRAP_ENDPORT) {
4254 port = SWRAP_STARTPORT;
4257 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4258 if (rc == 0 || errno != EADDRINUSE) {
4266 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4268 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4272 /****************************************************************************
4274 ***************************************************************************/
4276 static int swrap_listen(int s, int backlog)
4279 struct socket_info *si = find_socket_info(s);
4282 return libc_listen(s, backlog);
4287 if (si->bound == 0) {
4288 ret = swrap_auto_bind(s, si, si->family);
4295 ret = libc_listen(s, backlog);
4301 SWRAP_UNLOCK_SI(si);
4306 int listen(int s, int backlog)
4308 return swrap_listen(s, backlog);
4311 /****************************************************************************
4313 ***************************************************************************/
4315 static FILE *swrap_fopen(const char *name, const char *mode)
4319 fp = libc_fopen(name, mode);
4321 int fd = fileno(fp);
4323 swrap_remove_stale(fd);
4329 FILE *fopen(const char *name, const char *mode)
4331 return swrap_fopen(name, mode);
4334 /****************************************************************************
4336 ***************************************************************************/
4339 static FILE *swrap_fopen64(const char *name, const char *mode)
4343 fp = libc_fopen64(name, mode);
4345 int fd = fileno(fp);
4347 swrap_remove_stale(fd);
4353 FILE *fopen64(const char *name, const char *mode)
4355 return swrap_fopen64(name, mode);
4357 #endif /* HAVE_FOPEN64 */
4359 /****************************************************************************
4361 ***************************************************************************/
4363 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4367 ret = libc_vopen(pathname, flags, ap);
4370 * There are methods for closing descriptors (libc-internal code
4371 * paths, direct syscalls) which close descriptors in ways that
4372 * we can't intercept, so try to recover when we notice that
4375 swrap_remove_stale(ret);
4380 int open(const char *pathname, int flags, ...)
4385 va_start(ap, flags);
4386 fd = swrap_vopen(pathname, flags, ap);
4392 /****************************************************************************
4394 ***************************************************************************/
4397 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4401 ret = libc_vopen64(pathname, flags, ap);
4404 * There are methods for closing descriptors (libc-internal code
4405 * paths, direct syscalls) which close descriptors in ways that
4406 * we can't intercept, so try to recover when we notice that
4409 swrap_remove_stale(ret);
4414 int open64(const char *pathname, int flags, ...)
4419 va_start(ap, flags);
4420 fd = swrap_vopen64(pathname, flags, ap);
4425 #endif /* HAVE_OPEN64 */
4427 /****************************************************************************
4429 ***************************************************************************/
4431 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4435 ret = libc_vopenat(dirfd, path, flags, ap);
4438 * There are methods for closing descriptors (libc-internal code
4439 * paths, direct syscalls) which close descriptors in ways that
4440 * we can't intercept, so try to recover when we notice that
4443 swrap_remove_stale(ret);
4449 int openat(int dirfd, const char *path, int flags, ...)
4454 va_start(ap, flags);
4455 fd = swrap_vopenat(dirfd, path, flags, ap);
4461 /****************************************************************************
4463 ***************************************************************************/
4465 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4467 struct socket_info *si = find_socket_info(s);
4472 return libc_getpeername(s, name, addrlen);
4477 if (si->peername.sa_socklen == 0)
4483 len = MIN(*addrlen, si->peername.sa_socklen);
4489 memcpy(name, &si->peername.sa.ss, len);
4490 *addrlen = si->peername.sa_socklen;
4494 SWRAP_UNLOCK_SI(si);
4499 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4500 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4502 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4505 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4508 /****************************************************************************
4510 ***************************************************************************/
4512 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4514 struct socket_info *si = find_socket_info(s);
4519 return libc_getsockname(s, name, addrlen);
4524 len = MIN(*addrlen, si->myname.sa_socklen);
4530 memcpy(name, &si->myname.sa.ss, len);
4531 *addrlen = si->myname.sa_socklen;
4535 SWRAP_UNLOCK_SI(si);
4540 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4541 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4543 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4546 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4549 /****************************************************************************
4551 ***************************************************************************/
4554 # ifdef SO_PROTOTYPE /* The Solaris name */
4555 # define SO_PROTOCOL SO_PROTOTYPE
4556 # endif /* SO_PROTOTYPE */
4557 #endif /* SO_PROTOCOL */
4559 static int swrap_getsockopt(int s, int level, int optname,
4560 void *optval, socklen_t *optlen)
4562 struct socket_info *si = find_socket_info(s);
4566 return libc_getsockopt(s,
4575 if (level == SOL_SOCKET) {
4579 if (optval == NULL || optlen == NULL ||
4580 *optlen < (socklen_t)sizeof(int)) {
4586 *optlen = sizeof(int);
4587 *(int *)optval = si->family;
4590 #endif /* SO_DOMAIN */
4594 if (optval == NULL || optlen == NULL ||
4595 *optlen < (socklen_t)sizeof(int)) {
4601 *optlen = sizeof(int);
4602 *(int *)optval = si->protocol;
4605 #endif /* SO_PROTOCOL */
4607 if (optval == NULL || optlen == NULL ||
4608 *optlen < (socklen_t)sizeof(int)) {
4614 *optlen = sizeof(int);
4615 *(int *)optval = si->type;
4619 ret = libc_getsockopt(s,
4626 } else if (level == IPPROTO_TCP) {
4631 * This enables sending packets directly out over TCP.
4632 * As a unix socket is doing that any way, report it as
4635 if (optval == NULL || optlen == NULL ||
4636 *optlen < (socklen_t)sizeof(int)) {
4642 *optlen = sizeof(int);
4643 *(int *)optval = si->tcp_nodelay;
4647 #endif /* TCP_NODELAY */
4650 struct tcp_info info;
4651 socklen_t ilen = sizeof(info);
4653 #ifdef HAVE_NETINET_TCP_FSM_H
4654 /* This is FreeBSD */
4655 # define __TCP_LISTEN TCPS_LISTEN
4656 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4657 # define __TCP_CLOSE TCPS_CLOSED
4660 # define __TCP_LISTEN TCP_LISTEN
4661 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4662 # define __TCP_CLOSE TCP_CLOSE
4666 if (si->listening) {
4667 info.tcpi_state = __TCP_LISTEN;
4668 } else if (si->connected) {
4670 * For now we just fake a few values
4671 * supported both by FreeBSD and Linux
4673 info.tcpi_state = __TCP_ESTABLISHED;
4674 info.tcpi_rto = 200000; /* 200 msec */
4675 info.tcpi_rtt = 5000; /* 5 msec */
4676 info.tcpi_rttvar = 5000; /* 5 msec */
4678 info.tcpi_state = __TCP_CLOSE;
4679 info.tcpi_rto = 1000000; /* 1 sec */
4681 info.tcpi_rttvar = 250000; /* 250 msec */
4684 if (optval == NULL || optlen == NULL ||
4685 *optlen < (socklen_t)ilen) {
4692 memcpy(optval, &info, ilen);
4697 #endif /* TCP_INFO */
4703 errno = ENOPROTOOPT;
4707 SWRAP_UNLOCK_SI(si);
4711 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4712 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4714 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4717 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4720 /****************************************************************************
4722 ***************************************************************************/
4724 static int swrap_setsockopt(int s, int level, int optname,
4725 const void *optval, socklen_t optlen)
4727 struct socket_info *si = find_socket_info(s);
4731 return libc_setsockopt(s,
4738 if (level == SOL_SOCKET) {
4739 return libc_setsockopt(s,
4748 if (level == IPPROTO_TCP) {
4755 * This enables sending packets directly out over TCP.
4756 * A unix socket is doing that any way.
4758 if (optval == NULL || optlen == 0 ||
4759 optlen < (socklen_t)sizeof(int)) {
4765 i = *discard_const_p(int, optval);
4766 if (i != 0 && i != 1) {
4771 si->tcp_nodelay = i;
4776 #endif /* TCP_NODELAY */
4782 switch (si->family) {
4784 if (level == IPPROTO_IP) {
4786 if (optname == IP_PKTINFO) {
4787 si->pktinfo = AF_INET;
4789 #endif /* IP_PKTINFO */
4795 if (level == IPPROTO_IPV6) {
4796 #ifdef IPV6_RECVPKTINFO
4797 if (optname == IPV6_RECVPKTINFO) {
4798 si->pktinfo = AF_INET6;
4800 #endif /* IPV6_PKTINFO */
4806 errno = ENOPROTOOPT;
4812 SWRAP_UNLOCK_SI(si);
4816 int setsockopt(int s, int level, int optname,
4817 const void *optval, socklen_t optlen)
4819 return swrap_setsockopt(s, level, optname, optval, optlen);
4822 /****************************************************************************
4824 ***************************************************************************/
4826 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4828 struct socket_info *si = find_socket_info(s);
4830 int *value_ptr = NULL;
4834 return libc_vioctl(s, r, va);
4841 rc = libc_vioctl(s, r, va);
4846 value_ptr = ((int *)va_arg(ap, int *));
4849 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4850 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4851 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4852 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4857 /* this is FreeBSD */
4858 FALL_THROUGH; /* to TIOCOUTQ */
4859 #endif /* FIONWRITE */
4860 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4862 * This may return more bytes then the application
4863 * sent into the socket, for tcp it should
4864 * return the number of unacked bytes.
4866 * On AF_UNIX, all bytes are immediately acked!
4869 value_ptr = ((int *)va_arg(ap, int *));
4877 SWRAP_UNLOCK_SI(si);
4881 #ifdef HAVE_IOCTL_INT
4882 int ioctl(int s, int r, ...)
4884 int ioctl(int s, unsigned long int r, ...)
4892 rc = swrap_vioctl(s, (unsigned long int) r, va);
4903 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4906 # ifdef _ALIGN /* BSD */
4907 #define CMSG_ALIGN _ALIGN
4909 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4910 # endif /* _ALIGN */
4911 #endif /* CMSG_ALIGN */
4914 * @brief Add a cmsghdr to a msghdr.
4916 * This is an function to add any type of cmsghdr. It will operate on the
4917 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4918 * the buffer position after the added cmsg element. Hence, this function is
4919 * intended to be used with an intermediate msghdr and not on the original
4920 * one handed in by the client.
4922 * @param[in] msg The msghdr to which to add the cmsg.
4924 * @param[in] level The cmsg level to set.
4926 * @param[in] type The cmsg type to set.
4928 * @param[in] data The cmsg data to set.
4930 * @param[in] len the length of the data to set.
4932 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4938 size_t cmlen = CMSG_LEN(len);
4939 size_t cmspace = CMSG_SPACE(len);
4940 uint8_t cmbuf[cmspace];
4941 void *cast_ptr = (void *)cmbuf;
4942 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4945 memset(cmbuf, 0, cmspace);
4947 if (msg->msg_controllen < cmlen) {
4948 cmlen = msg->msg_controllen;
4949 msg->msg_flags |= MSG_CTRUNC;
4952 if (msg->msg_controllen < cmspace) {
4953 cmspace = msg->msg_controllen;
4957 * We copy the full input data into an intermediate cmsghdr first
4958 * in order to more easily cope with truncation.
4960 cm->cmsg_len = cmlen;
4961 cm->cmsg_level = level;
4962 cm->cmsg_type = type;
4963 memcpy(CMSG_DATA(cm), data, len);
4966 * We now copy the possibly truncated buffer.
4967 * We copy cmlen bytes, but consume cmspace bytes,
4968 * leaving the possible padding uninitialiazed.
4970 p = (uint8_t *)msg->msg_control;
4971 memcpy(p, cm, cmlen);
4973 msg->msg_control = p;
4974 msg->msg_controllen -= cmspace;
4979 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4982 /* Add packet info */
4983 switch (si->pktinfo) {
4984 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4986 struct sockaddr_in *sin;
4987 #if defined(HAVE_STRUCT_IN_PKTINFO)
4988 struct in_pktinfo pkt;
4989 #elif defined(IP_RECVDSTADDR)
4993 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4994 sin = &si->bindname.sa.in;
4996 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4999 sin = &si->myname.sa.in;
5004 #if defined(HAVE_STRUCT_IN_PKTINFO)
5005 pkt.ipi_ifindex = socket_wrapper_default_iface();
5006 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5007 #elif defined(IP_RECVDSTADDR)
5008 pkt = sin->sin_addr;
5011 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5016 #endif /* IP_PKTINFO */
5017 #if defined(HAVE_IPV6)
5019 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5020 struct sockaddr_in6 *sin6;
5021 struct in6_pktinfo pkt6;
5023 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5024 sin6 = &si->bindname.sa.in6;
5026 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5029 sin6 = &si->myname.sa.in6;
5034 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5035 pkt6.ipi6_addr = sin6->sin6_addr;
5037 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5038 &pkt6, sizeof(pkt6));
5039 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5043 #endif /* IPV6_PKTINFO */
5051 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5052 struct msghdr *omsg)
5056 if (si->pktinfo > 0) {
5057 rc = swrap_msghdr_add_pktinfo(si, omsg);
5063 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5065 size_t *cm_data_space);
5066 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5068 size_t *cm_data_space);
5069 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5071 size_t *cm_data_space);
5073 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5075 size_t *cm_data_space)
5077 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5078 struct cmsghdr *cmsg;
5082 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5086 for (cmsg = CMSG_FIRSTHDR(msg);
5088 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5089 switch (cmsg->cmsg_level) {
5091 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5096 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5101 rc = swrap_sendmsg_copy_cmsg(cmsg,
5107 int saved_errno = errno;
5108 SAFE_FREE(*cm_data);
5110 errno = saved_errno;
5118 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5120 size_t *cm_data_space)
5125 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5127 p = realloc((*cm_data), cmspace);
5133 p = (*cm_data) + (*cm_data_space);
5134 *cm_data_space = cmspace;
5136 memcpy(p, cmsg, cmsg->cmsg_len);
5141 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5143 size_t *cm_data_space);
5146 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5148 size_t *cm_data_space)
5152 switch(cmsg->cmsg_type) {
5155 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5162 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5174 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5176 size_t *cm_data_space)
5178 (void)cmsg; /* unused */
5179 (void)cm_data; /* unused */
5180 (void)cm_data_space; /* unused */
5183 * Passing a IP pktinfo to a unix socket might be rejected by the
5184 * Kernel, at least on FreeBSD. So skip this cmsg.
5189 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5191 size_t *cm_data_space)
5195 switch (cmsg->cmsg_type) {
5197 SWRAP_LOG(SWRAP_LOG_TRACE,
5198 "Ignoring SCM_RIGHTS on inet socket!");
5201 #ifdef SCM_CREDENTIALS
5202 case SCM_CREDENTIALS:
5203 SWRAP_LOG(SWRAP_LOG_TRACE,
5204 "Ignoring SCM_CREDENTIALS on inet socket!");
5207 #endif /* SCM_CREDENTIALS */
5209 rc = swrap_sendmsg_copy_cmsg(cmsg,
5218 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5221 * We only allow up to 6 fds at a time
5222 * as that's more than enough for Samba
5223 * and it means we can keep the logic simple
5224 * and work with fixed size arrays.
5226 * We also keep sizeof(struct swrap_unix_scm_rights)
5227 * under PIPE_BUF (4096) in order to allow a non-blocking
5228 * write into the pipe.
5231 #define PIPE_BUF 4096
5233 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5234 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5235 struct swrap_unix_scm_rights_payload {
5237 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5238 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5240 struct swrap_unix_scm_rights {
5242 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5243 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5245 uint32_t payload_size;
5246 struct swrap_unix_scm_rights_payload payload;
5249 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5251 int saved_errno = errno;
5254 for (i = 0; i < num; i++) {
5255 struct socket_info *si = array[i];
5261 swrap_dec_refcount(si);
5262 if (si->fd_passed > 0) {
5265 SWRAP_UNLOCK_SI(si);
5269 errno = saved_errno;
5272 static void swrap_undo_si_idx_array(size_t num, int *array)
5274 int saved_errno = errno;
5277 swrap_mutex_lock(&first_free_mutex);
5279 for (i = 0; i < num; i++) {
5280 struct socket_info *si = NULL;
5282 if (array[i] == -1) {
5286 si = swrap_get_socket_info(array[i]);
5292 swrap_dec_refcount(si);
5293 SWRAP_UNLOCK_SI(si);
5295 swrap_set_next_free(si, first_free);
5296 first_free = array[i];
5300 swrap_mutex_unlock(&first_free_mutex);
5301 errno = saved_errno;
5304 static void swrap_close_fd_array(size_t num, const int *array)
5306 int saved_errno = errno;
5309 for (i = 0; i < num; i++) {
5310 if (array[i] == -1) {
5313 libc_close(array[i]);
5316 errno = saved_errno;
5324 union __swrap_cmsghdr {
5326 struct cmsghdr *cmsg;
5329 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5331 size_t *cm_data_space,
5332 int *scm_rights_pipe_fd)
5334 struct swrap_unix_scm_rights info;
5335 struct swrap_unix_scm_rights_payload *payload = NULL;
5336 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5337 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5338 size_t info_idx = 0;
5341 union __swrap_fds __fds_in = { .p = NULL, };
5342 const int *fds_in = NULL;
5344 size_t size_fds_out;
5345 union __swrap_fds __fds_out = { .p = NULL, };
5346 int *fds_out = NULL;
5349 size_t new_cm_data_space;
5350 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5351 struct cmsghdr *new_cmsg = NULL;
5354 int pipefd[2] = { -1, -1 };
5359 * We pass this a buffer to the kernel make sure any padding
5363 info.magic = swrap_unix_scm_right_magic;
5364 memcpy(info.package_name,
5365 SOCKET_WRAPPER_PACKAGE,
5366 sizeof(info.package_name));
5367 memcpy(info.package_version,
5368 SOCKET_WRAPPER_VERSION,
5369 sizeof(info.package_version));
5370 info.full_size = sizeof(info);
5371 info.payload_size = sizeof(info.payload);
5372 payload = &info.payload;
5374 if (*scm_rights_pipe_fd != -1) {
5375 SWRAP_LOG(SWRAP_LOG_ERROR,
5376 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5381 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5382 SWRAP_LOG(SWRAP_LOG_ERROR,
5383 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5384 (size_t)cmsg->cmsg_len,
5389 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5390 if ((size_fds_in % sizeof(int)) != 0) {
5391 SWRAP_LOG(SWRAP_LOG_ERROR,
5392 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5393 (size_t)cmsg->cmsg_len,
5399 num_fds_in = size_fds_in / sizeof(int);
5400 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5401 SWRAP_LOG(SWRAP_LOG_ERROR,
5402 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5404 "SWRAP_MAX_PASSED_FDS(%zu)",
5405 (size_t)cmsg->cmsg_len,
5408 SWRAP_MAX_PASSED_FDS);
5412 if (num_fds_in == 0) {
5413 SWRAP_LOG(SWRAP_LOG_ERROR,
5414 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5416 (size_t)cmsg->cmsg_len,
5422 __fds_in.p = CMSG_DATA(cmsg);
5423 fds_in = __fds_in.fds;
5424 num_fds_out = num_fds_in + 1;
5426 SWRAP_LOG(SWRAP_LOG_TRACE,
5427 "num_fds_in=%zu num_fds_out=%zu",
5428 num_fds_in, num_fds_out);
5430 size_fds_out = sizeof(int) * num_fds_out;
5431 cmsg_len = CMSG_LEN(size_fds_out);
5432 cmsg_space = CMSG_SPACE(size_fds_out);
5434 new_cm_data_space = *cm_data_space + cmsg_space;
5436 p = realloc((*cm_data), new_cm_data_space);
5441 p = (*cm_data) + (*cm_data_space);
5442 memset(p, 0, cmsg_space);
5444 new_cmsg = __new_cmsg.cmsg;
5446 __fds_out.p = CMSG_DATA(new_cmsg);
5447 fds_out = __fds_out.fds;
5448 memcpy(fds_out, fds_in, size_fds_out);
5449 new_cmsg->cmsg_len = cmsg->cmsg_len;
5451 for (i = 0; i < num_fds_in; i++) {
5454 payload->idxs[i] = -1;
5455 payload->num_idxs++;
5457 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5458 if (si_idx_array[i] == -1) {
5462 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5463 if (si_array[i] == NULL) {
5464 SWRAP_LOG(SWRAP_LOG_ERROR,
5465 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5466 i, fds_in[i], i, si_idx_array[i]);
5471 for (j = 0; j < i; j++) {
5472 if (si_array[j] == si_array[i]) {
5473 payload->idxs[i] = payload->idxs[j];
5477 if (payload->idxs[i] == -1) {
5478 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5479 SWRAP_LOG(SWRAP_LOG_ERROR,
5480 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5481 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5482 i, fds_in[i], i, si_idx_array[i],
5484 SWRAP_MAX_PASSED_SOCKET_INFO);
5488 payload->idxs[i] = info_idx;
5494 for (i = 0; i < num_fds_in; i++) {
5495 struct socket_info *si = si_array[i];
5498 SWRAP_LOG(SWRAP_LOG_TRACE,
5499 "fds_in[%zu]=%d not an inet socket",
5504 SWRAP_LOG(SWRAP_LOG_TRACE,
5505 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5506 "passing as info.idxs[%zu]=%d!",
5509 i, payload->idxs[i]);
5513 payload->infos[payload->idxs[i]] = *si;
5514 payload->infos[payload->idxs[i]].fd_passed = 0;
5515 SWRAP_UNLOCK_SI(si);
5520 int saved_errno = errno;
5521 SWRAP_LOG(SWRAP_LOG_ERROR,
5522 "pipe() failed - %d %s",
5524 strerror(saved_errno));
5525 swrap_dec_fd_passed_array(num_fds_in, si_array);
5526 errno = saved_errno;
5530 sret = write(pipefd[1], &info, sizeof(info));
5531 if (sret != sizeof(info)) {
5532 int saved_errno = errno;
5534 saved_errno = EINVAL;
5536 SWRAP_LOG(SWRAP_LOG_ERROR,
5537 "write() failed - sret=%zd - %d %s",
5539 strerror(saved_errno));
5540 swrap_dec_fd_passed_array(num_fds_in, si_array);
5541 libc_close(pipefd[1]);
5542 libc_close(pipefd[0]);
5543 errno = saved_errno;
5546 libc_close(pipefd[1]);
5549 * Add the pipe read end to the end of the passed fd array
5551 fds_out[num_fds_in] = pipefd[0];
5552 new_cmsg->cmsg_len = cmsg_len;
5554 /* we're done ... */
5555 *scm_rights_pipe_fd = pipefd[0];
5556 *cm_data_space = new_cm_data_space;
5561 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5563 size_t *cm_data_space,
5564 int *scm_rights_pipe_fd)
5568 switch (cmsg->cmsg_type) {
5570 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5573 scm_rights_pipe_fd);
5576 rc = swrap_sendmsg_copy_cmsg(cmsg,
5585 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5587 size_t *cm_data_space)
5589 int scm_rights_pipe_fd = -1;
5590 struct swrap_unix_scm_rights info;
5591 struct swrap_unix_scm_rights_payload *payload = NULL;
5592 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5595 union __swrap_fds __fds_in = { .p = NULL, };
5596 const int *fds_in = NULL;
5598 size_t size_fds_out;
5599 union __swrap_fds __fds_out = { .p = NULL, };
5600 int *fds_out = NULL;
5603 size_t new_cm_data_space;
5604 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5605 struct cmsghdr *new_cmsg = NULL;
5611 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5612 SWRAP_LOG(SWRAP_LOG_ERROR,
5613 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5614 (size_t)cmsg->cmsg_len,
5619 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5620 if ((size_fds_in % sizeof(int)) != 0) {
5621 SWRAP_LOG(SWRAP_LOG_ERROR,
5622 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5623 (size_t)cmsg->cmsg_len,
5629 num_fds_in = size_fds_in / sizeof(int);
5630 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5631 SWRAP_LOG(SWRAP_LOG_ERROR,
5632 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5633 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5634 (size_t)cmsg->cmsg_len,
5637 SWRAP_MAX_PASSED_FDS+1);
5641 if (num_fds_in <= 1) {
5642 SWRAP_LOG(SWRAP_LOG_ERROR,
5643 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5645 (size_t)cmsg->cmsg_len,
5651 __fds_in.p = CMSG_DATA(cmsg);
5652 fds_in = __fds_in.fds;
5653 num_fds_out = num_fds_in - 1;
5655 SWRAP_LOG(SWRAP_LOG_TRACE,
5656 "num_fds_in=%zu num_fds_out=%zu",
5657 num_fds_in, num_fds_out);
5659 for (i = 0; i < num_fds_in; i++) {
5660 /* Check if we have a stale fd and remove it */
5661 swrap_remove_stale(fds_in[i]);
5664 scm_rights_pipe_fd = fds_in[num_fds_out];
5665 size_fds_out = sizeof(int) * num_fds_out;
5666 cmsg_len = CMSG_LEN(size_fds_out);
5667 cmsg_space = CMSG_SPACE(size_fds_out);
5669 new_cm_data_space = *cm_data_space + cmsg_space;
5671 p = realloc((*cm_data), new_cm_data_space);
5673 swrap_close_fd_array(num_fds_in, fds_in);
5677 p = (*cm_data) + (*cm_data_space);
5678 memset(p, 0, cmsg_space);
5680 new_cmsg = __new_cmsg.cmsg;
5682 __fds_out.p = CMSG_DATA(new_cmsg);
5683 fds_out = __fds_out.fds;
5684 memcpy(fds_out, fds_in, size_fds_out);
5685 new_cmsg->cmsg_len = cmsg_len;
5687 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5688 if (sret != sizeof(info)) {
5689 int saved_errno = errno;
5691 saved_errno = EINVAL;
5693 SWRAP_LOG(SWRAP_LOG_ERROR,
5694 "read() failed - sret=%zd - %d %s",
5696 strerror(saved_errno));
5697 swrap_close_fd_array(num_fds_in, fds_in);
5698 errno = saved_errno;
5701 libc_close(scm_rights_pipe_fd);
5702 payload = &info.payload;
5704 if (info.magic != swrap_unix_scm_right_magic) {
5705 SWRAP_LOG(SWRAP_LOG_ERROR,
5706 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5707 (unsigned long long)info.magic,
5708 (unsigned long long)swrap_unix_scm_right_magic);
5709 swrap_close_fd_array(num_fds_out, fds_out);
5714 cmp = memcmp(info.package_name,
5715 SOCKET_WRAPPER_PACKAGE,
5716 sizeof(info.package_name));
5718 SWRAP_LOG(SWRAP_LOG_ERROR,
5719 "info.package_name='%.*s' != '%s'",
5720 (int)sizeof(info.package_name),
5722 SOCKET_WRAPPER_PACKAGE);
5723 swrap_close_fd_array(num_fds_out, fds_out);
5728 cmp = memcmp(info.package_version,
5729 SOCKET_WRAPPER_VERSION,
5730 sizeof(info.package_version));
5732 SWRAP_LOG(SWRAP_LOG_ERROR,
5733 "info.package_version='%.*s' != '%s'",
5734 (int)sizeof(info.package_version),
5735 info.package_version,
5736 SOCKET_WRAPPER_VERSION);
5737 swrap_close_fd_array(num_fds_out, fds_out);
5742 if (info.full_size != sizeof(info)) {
5743 SWRAP_LOG(SWRAP_LOG_ERROR,
5744 "info.full_size=%zu != sizeof(info)=%zu",
5745 (size_t)info.full_size,
5747 swrap_close_fd_array(num_fds_out, fds_out);
5752 if (info.payload_size != sizeof(info.payload)) {
5753 SWRAP_LOG(SWRAP_LOG_ERROR,
5754 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5755 (size_t)info.payload_size,
5756 sizeof(info.payload));
5757 swrap_close_fd_array(num_fds_out, fds_out);
5762 if (payload->num_idxs != num_fds_out) {
5763 SWRAP_LOG(SWRAP_LOG_ERROR,
5764 "info.num_idxs=%u != num_fds_out=%zu",
5765 payload->num_idxs, num_fds_out);
5766 swrap_close_fd_array(num_fds_out, fds_out);
5771 for (i = 0; i < num_fds_out; i++) {
5774 si_idx_array[i] = -1;
5776 if (payload->idxs[i] == -1) {
5777 SWRAP_LOG(SWRAP_LOG_TRACE,
5778 "fds_out[%zu]=%d not an inet socket",
5783 if (payload->idxs[i] < 0) {
5784 SWRAP_LOG(SWRAP_LOG_ERROR,
5785 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5786 i, fds_out[i], i, payload->idxs[i]);
5787 swrap_close_fd_array(num_fds_out, fds_out);
5792 if (payload->idxs[i] >= payload->num_idxs) {
5793 SWRAP_LOG(SWRAP_LOG_ERROR,
5794 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5795 i, fds_out[i], i, payload->idxs[i],
5797 swrap_close_fd_array(num_fds_out, fds_out);
5802 if ((size_t)fds_out[i] >= socket_fds_max) {
5803 SWRAP_LOG(SWRAP_LOG_ERROR,
5804 "The max socket index limit of %zu has been reached, "
5808 swrap_close_fd_array(num_fds_out, fds_out);
5813 SWRAP_LOG(SWRAP_LOG_TRACE,
5815 "received as info.idxs[%zu]=%d!",
5817 i, payload->idxs[i]);
5819 for (j = 0; j < i; j++) {
5820 if (payload->idxs[j] == -1) {
5823 if (payload->idxs[j] == payload->idxs[i]) {
5824 si_idx_array[i] = si_idx_array[j];
5827 if (si_idx_array[i] == -1) {
5828 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5830 si_idx_array[i] = swrap_add_socket_info(si);
5831 if (si_idx_array[i] == -1) {
5832 int saved_errno = errno;
5833 SWRAP_LOG(SWRAP_LOG_ERROR,
5834 "The max socket index limit of %zu has been reached, "
5838 swrap_undo_si_idx_array(i, si_idx_array);
5839 swrap_close_fd_array(num_fds_out, fds_out);
5840 errno = saved_errno;
5843 SWRAP_LOG(SWRAP_LOG_TRACE,
5844 "Imported %s socket for protocol %s, fd=%d",
5845 si->family == AF_INET ? "IPv4" : "IPv6",
5846 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5851 for (i = 0; i < num_fds_out; i++) {
5852 if (si_idx_array[i] == -1) {
5855 set_socket_info_index(fds_out[i], si_idx_array[i]);
5858 /* we're done ... */
5859 *cm_data_space = new_cm_data_space;
5864 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5866 size_t *cm_data_space)
5870 switch (cmsg->cmsg_type) {
5872 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5877 rc = swrap_sendmsg_copy_cmsg(cmsg,
5886 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5888 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5889 struct msghdr *msg_tmp,
5890 int *scm_rights_pipe_fd)
5892 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5893 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5894 struct cmsghdr *cmsg = NULL;
5895 uint8_t *cm_data = NULL;
5896 size_t cm_data_space = 0;
5900 *scm_rights_pipe_fd = -1;
5903 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5907 for (cmsg = CMSG_FIRSTHDR(msg_in);
5909 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5910 switch (cmsg->cmsg_level) {
5912 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5915 scm_rights_pipe_fd);
5919 rc = swrap_sendmsg_copy_cmsg(cmsg,
5925 int saved_errno = errno;
5927 errno = saved_errno;
5932 msg_tmp->msg_controllen = cm_data_space;
5933 msg_tmp->msg_control = cm_data;
5936 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5937 *msg_tmp = *_msg_in;
5939 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5942 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5944 int scm_rights_pipe_fd)
5946 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5947 int saved_errno = errno;
5948 SAFE_FREE(msg_tmp->msg_control);
5949 if (scm_rights_pipe_fd != -1) {
5950 libc_close(scm_rights_pipe_fd);
5952 errno = saved_errno;
5953 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5957 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5958 struct msghdr *msg_tmp)
5964 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5965 struct msghdr *msg_out,
5968 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5969 struct cmsghdr *cmsg = NULL;
5970 uint8_t *cm_data = NULL;
5971 size_t cm_data_space = 0;
5975 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
5979 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
5981 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
5982 switch (cmsg->cmsg_level) {
5984 rc = swrap_recvmsg_unix_sol_socket(cmsg,
5990 rc = swrap_sendmsg_copy_cmsg(cmsg,
5996 int saved_errno = errno;
5998 errno = saved_errno;
6004 * msg_tmp->msg_control is still the buffer of the caller.
6006 memcpy(msg_tmp->msg_control, cm_data, cm_data_space);
6007 msg_tmp->msg_controllen = cm_data_space;
6010 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6011 *msg_out = *msg_tmp;
6015 static ssize_t swrap_sendmsg_before(int fd,
6016 struct socket_info *si,
6018 struct iovec *tmp_iov,
6019 struct sockaddr_un *tmp_un,
6020 const struct sockaddr_un **to_un,
6021 const struct sockaddr **to,
6043 if (!si->connected) {
6048 if (msg->msg_iovlen == 0) {
6052 mtu = socket_wrapper_mtu();
6053 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6055 nlen = len + msg->msg_iov[i].iov_len;
6065 msg->msg_iovlen = i;
6066 if (msg->msg_iovlen == 0) {
6067 *tmp_iov = msg->msg_iov[0];
6068 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6070 msg->msg_iov = tmp_iov;
6071 msg->msg_iovlen = 1;
6076 if (si->connected) {
6077 if (msg->msg_name != NULL) {
6079 * We are dealing with unix sockets and if we
6080 * are connected, we should only talk to the
6081 * connected unix path. Using the fd to send
6082 * to another server would be hard to achieve.
6084 msg->msg_name = NULL;
6085 msg->msg_namelen = 0;
6088 const struct sockaddr *msg_name;
6089 msg_name = (const struct sockaddr *)msg->msg_name;
6091 if (msg_name == NULL) {
6097 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6109 msg->msg_name = tmp_un;
6110 msg->msg_namelen = sizeof(*tmp_un);
6113 if (si->bound == 0) {
6114 ret = swrap_auto_bind(fd, si, si->family);
6116 SWRAP_UNLOCK_SI(si);
6117 if (errno == ENOTSOCK) {
6118 swrap_remove_stale(fd);
6121 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6127 if (!si->defer_connect) {
6131 ret = sockaddr_convert_to_un(si,
6133 si->peername.sa_socklen,
6141 ret = libc_connect(fd,
6142 (struct sockaddr *)(void *)tmp_un,
6145 /* to give better errors */
6146 if (ret == -1 && errno == ENOENT) {
6147 errno = EHOSTUNREACH;
6154 si->defer_connect = 0;
6157 errno = EHOSTUNREACH;
6163 SWRAP_UNLOCK_SI(si);
6168 static void swrap_sendmsg_after(int fd,
6169 struct socket_info *si,
6171 const struct sockaddr *to,
6174 int saved_errno = errno;
6181 /* to give better errors */
6183 if (saved_errno == ENOENT) {
6184 saved_errno = EHOSTUNREACH;
6185 } else if (saved_errno == ENOTSOCK) {
6186 /* If the fd is not a socket, remove it */
6187 swrap_remove_stale(fd);
6191 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6192 avail += msg->msg_iov[i].iov_len;
6196 remain = MIN(80, avail);
6201 /* we capture it as one single packet */
6202 buf = (uint8_t *)malloc(remain);
6204 /* we just not capture the packet */
6205 errno = saved_errno;
6209 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6210 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6212 msg->msg_iov[i].iov_base,
6215 remain -= this_time;
6224 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6225 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6227 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6232 if (si->connected) {
6233 to = &si->peername.sa.s;
6236 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6237 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6239 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6244 SWRAP_UNLOCK_SI(si);
6247 errno = saved_errno;
6250 static int swrap_recvmsg_before(int fd,
6251 struct socket_info *si,
6253 struct iovec *tmp_iov)
6260 (void)fd; /* unused */
6265 if (!si->connected) {
6270 if (msg->msg_iovlen == 0) {
6274 mtu = socket_wrapper_mtu();
6275 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6277 nlen = len + msg->msg_iov[i].iov_len;
6282 msg->msg_iovlen = i;
6283 if (msg->msg_iovlen == 0) {
6284 *tmp_iov = msg->msg_iov[0];
6285 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6287 msg->msg_iov = tmp_iov;
6288 msg->msg_iovlen = 1;
6293 if (msg->msg_name == NULL) {
6298 if (msg->msg_iovlen == 0) {
6302 if (si->bound == 0) {
6303 ret = swrap_auto_bind(fd, si, si->family);
6305 SWRAP_UNLOCK_SI(si);
6307 * When attempting to read or write to a
6308 * descriptor, if an underlying autobind fails
6309 * because it's not a socket, stop intercepting
6310 * uses of that descriptor.
6312 if (errno == ENOTSOCK) {
6313 swrap_remove_stale(fd);
6316 SWRAP_LOG(SWRAP_LOG_ERROR,
6317 "swrap_recvmsg_before failed");
6324 errno = EHOSTUNREACH;
6330 SWRAP_UNLOCK_SI(si);
6335 static int swrap_recvmsg_after(int fd,
6336 struct socket_info *si,
6338 const struct sockaddr_un *un_addr,
6339 socklen_t un_addrlen,
6342 int saved_errno = errno;
6344 uint8_t *buf = NULL;
6350 /* to give better errors */
6352 if (saved_errno == ENOENT) {
6353 saved_errno = EHOSTUNREACH;
6354 } else if (saved_errno == ENOTSOCK) {
6355 /* If the fd is not a socket, remove it */
6356 swrap_remove_stale(fd);
6360 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6361 avail += msg->msg_iov[i].iov_len;
6366 /* Convert the socket address before we leave */
6367 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6368 rc = sockaddr_convert_from_un(si,
6385 remain = MIN(80, avail);
6390 /* we capture it as one single packet */
6391 buf = (uint8_t *)malloc(remain);
6393 /* we just not capture the packet */
6394 SWRAP_UNLOCK_SI(si);
6395 errno = saved_errno;
6399 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6400 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6402 msg->msg_iov[i].iov_base,
6405 remain -= this_time;
6410 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6411 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6412 } else if (ret == 0) { /* END OF FILE */
6413 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6414 } else if (ret > 0) {
6415 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6424 if (un_addr != NULL) {
6425 swrap_pcap_dump_packet(si,
6431 swrap_pcap_dump_packet(si,
6444 errno = saved_errno;
6446 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6448 msg->msg_controllen > 0 &&
6449 msg->msg_control != NULL) {
6450 rc = swrap_msghdr_add_socket_info(si, msg);
6452 SWRAP_UNLOCK_SI(si);
6458 SWRAP_UNLOCK_SI(si);
6462 /****************************************************************************
6464 ***************************************************************************/
6466 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6467 struct sockaddr *from, socklen_t *fromlen)
6469 struct swrap_address from_addr = {
6470 .sa_socklen = sizeof(struct sockaddr_un),
6473 struct socket_info *si = find_socket_info(s);
6474 struct swrap_address saddr = {
6475 .sa_socklen = sizeof(struct sockaddr_storage),
6482 return libc_recvfrom(s,
6494 if (from != NULL && fromlen != NULL) {
6495 msg.msg_name = from; /* optional address */
6496 msg.msg_namelen = *fromlen; /* size of address */
6498 msg.msg_name = &saddr.sa.s; /* optional address */
6499 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6501 msg.msg_iov = &tmp; /* scatter/gather array */
6502 msg.msg_iovlen = 1; /* # elements in msg_iov */
6503 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6504 msg.msg_control = NULL; /* ancillary data, see below */
6505 msg.msg_controllen = 0; /* ancillary data buffer len */
6506 msg.msg_flags = 0; /* flags on received message */
6509 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6514 buf = msg.msg_iov[0].iov_base;
6515 len = msg.msg_iov[0].iov_len;
6517 ret = libc_recvfrom(s,
6522 &from_addr.sa_socklen);
6527 tret = swrap_recvmsg_after(s,
6531 from_addr.sa_socklen,
6537 if (from != NULL && fromlen != NULL) {
6538 *fromlen = msg.msg_namelen;
6544 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6545 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6546 struct sockaddr *from, Psocklen_t fromlen)
6548 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6549 struct sockaddr *from, socklen_t *fromlen)
6552 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6555 /****************************************************************************
6557 ***************************************************************************/
6559 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6560 const struct sockaddr *to, socklen_t tolen)
6564 struct swrap_address un_addr = {
6565 .sa_socklen = sizeof(struct sockaddr_un),
6567 const struct sockaddr_un *to_un = NULL;
6570 struct socket_info *si = find_socket_info(s);
6574 return libc_sendto(s, buf, len, flags, to, tolen);
6577 tmp.iov_base = discard_const_p(char, buf);
6581 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6582 msg.msg_namelen = tolen; /* size of address */
6583 msg.msg_iov = &tmp; /* scatter/gather array */
6584 msg.msg_iovlen = 1; /* # elements in msg_iov */
6585 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6586 msg.msg_control = NULL; /* ancillary data, see below */
6587 msg.msg_controllen = 0; /* ancillary data buffer len */
6588 msg.msg_flags = 0; /* flags on received message */
6591 rc = swrap_sendmsg_before(s,
6603 buf = msg.msg_iov[0].iov_base;
6604 len = msg.msg_iov[0].iov_len;
6609 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6611 char *swrap_dir = NULL;
6613 type = SOCKET_TYPE_CHAR_UDP;
6615 swrap_dir = socket_wrapper_dir();
6616 if (swrap_dir == NULL) {
6620 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6621 swrap_un_path(&un_addr.sa.un,
6626 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6628 /* ignore the any errors in broadcast sends */
6634 un_addr.sa_socklen);
6637 SAFE_FREE(swrap_dir);
6641 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6643 SWRAP_UNLOCK_SI(si);
6650 * If it is a dgram socket and we are connected, don't include the
6653 if (si->type == SOCK_DGRAM && si->connected) {
6654 ret = libc_sendto(s,
6661 ret = libc_sendto(s,
6665 (struct sockaddr *)msg.msg_name,
6669 SWRAP_UNLOCK_SI(si);
6671 swrap_sendmsg_after(s, si, &msg, to, ret);
6676 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6677 const struct sockaddr *to, socklen_t tolen)
6679 return swrap_sendto(s, buf, len, flags, to, tolen);
6682 /****************************************************************************
6684 ***************************************************************************/
6686 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6688 struct socket_info *si;
6690 struct swrap_address saddr = {
6691 .sa_socklen = sizeof(struct sockaddr_storage),
6697 si = find_socket_info(s);
6699 return libc_recv(s, buf, len, flags);
6706 msg.msg_name = &saddr.sa.s; /* optional address */
6707 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6708 msg.msg_iov = &tmp; /* scatter/gather array */
6709 msg.msg_iovlen = 1; /* # elements in msg_iov */
6710 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6711 msg.msg_control = NULL; /* ancillary data, see below */
6712 msg.msg_controllen = 0; /* ancillary data buffer len */
6713 msg.msg_flags = 0; /* flags on received message */
6716 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6721 buf = msg.msg_iov[0].iov_base;
6722 len = msg.msg_iov[0].iov_len;
6724 ret = libc_recv(s, buf, len, flags);
6726 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6734 ssize_t recv(int s, void *buf, size_t len, int flags)
6736 return swrap_recv(s, buf, len, flags);
6739 /****************************************************************************
6741 ***************************************************************************/
6743 static ssize_t swrap_read(int s, void *buf, size_t len)
6745 struct socket_info *si;
6748 struct swrap_address saddr = {
6749 .sa_socklen = sizeof(struct sockaddr_storage),
6754 si = find_socket_info(s);
6756 return libc_read(s, buf, len);
6763 msg.msg_name = &saddr.sa.ss; /* optional address */
6764 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6765 msg.msg_iov = &tmp; /* scatter/gather array */
6766 msg.msg_iovlen = 1; /* # elements in msg_iov */
6767 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6768 msg.msg_control = NULL; /* ancillary data, see below */
6769 msg.msg_controllen = 0; /* ancillary data buffer len */
6770 msg.msg_flags = 0; /* flags on received message */
6773 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6775 if (tret == -ENOTSOCK) {
6776 return libc_read(s, buf, len);
6781 buf = msg.msg_iov[0].iov_base;
6782 len = msg.msg_iov[0].iov_len;
6784 ret = libc_read(s, buf, len);
6786 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6794 ssize_t read(int s, void *buf, size_t len)
6796 return swrap_read(s, buf, len);
6799 /****************************************************************************
6801 ***************************************************************************/
6803 static ssize_t swrap_write(int s, const void *buf, size_t len)
6807 struct sockaddr_un un_addr;
6810 struct socket_info *si;
6812 si = find_socket_info(s);
6814 return libc_write(s, buf, len);
6817 tmp.iov_base = discard_const_p(char, buf);
6821 msg.msg_name = NULL; /* optional address */
6822 msg.msg_namelen = 0; /* size of address */
6823 msg.msg_iov = &tmp; /* scatter/gather array */
6824 msg.msg_iovlen = 1; /* # elements in msg_iov */
6825 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6826 msg.msg_control = NULL; /* ancillary data, see below */
6827 msg.msg_controllen = 0; /* ancillary data buffer len */
6828 msg.msg_flags = 0; /* flags on received message */
6831 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6836 buf = msg.msg_iov[0].iov_base;
6837 len = msg.msg_iov[0].iov_len;
6839 ret = libc_write(s, buf, len);
6841 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6846 ssize_t write(int s, const void *buf, size_t len)
6848 return swrap_write(s, buf, len);
6851 /****************************************************************************
6853 ***************************************************************************/
6855 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6859 struct sockaddr_un un_addr;
6862 struct socket_info *si = find_socket_info(s);
6865 return libc_send(s, buf, len, flags);
6868 tmp.iov_base = discard_const_p(char, buf);
6872 msg.msg_name = NULL; /* optional address */
6873 msg.msg_namelen = 0; /* size of address */
6874 msg.msg_iov = &tmp; /* scatter/gather array */
6875 msg.msg_iovlen = 1; /* # elements in msg_iov */
6876 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6877 msg.msg_control = NULL; /* ancillary data, see below */
6878 msg.msg_controllen = 0; /* ancillary data buffer len */
6879 msg.msg_flags = 0; /* flags on received message */
6882 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6887 buf = msg.msg_iov[0].iov_base;
6888 len = msg.msg_iov[0].iov_len;
6890 ret = libc_send(s, buf, len, flags);
6892 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6897 ssize_t send(int s, const void *buf, size_t len, int flags)
6899 return swrap_send(s, buf, len, flags);
6902 /****************************************************************************
6904 ***************************************************************************/
6906 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6908 struct swrap_address from_addr = {
6909 .sa_socklen = sizeof(struct sockaddr_un),
6911 struct swrap_address convert_addr = {
6912 .sa_socklen = sizeof(struct sockaddr_storage),
6914 struct socket_info *si;
6917 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6918 size_t msg_ctrllen_filled;
6919 size_t msg_ctrllen_left;
6925 si = find_socket_info(s);
6927 rc = swrap_recvmsg_before_unix(omsg, &msg);
6931 ret = libc_recvmsg(s, &msg, flags);
6932 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6935 tmp.iov_base = NULL;
6939 msg.msg_name = &from_addr.sa; /* optional address */
6940 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6941 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6942 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6943 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6944 msg_ctrllen_filled = 0;
6945 msg_ctrllen_left = omsg->msg_controllen;
6947 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6948 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6949 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6952 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6957 ret = libc_recvmsg(s, &msg, flags);
6959 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6960 msg_ctrllen_filled += msg.msg_controllen;
6961 msg_ctrllen_left -= msg.msg_controllen;
6963 if (omsg->msg_control != NULL) {
6966 p = omsg->msg_control;
6967 p += msg_ctrllen_filled;
6969 msg.msg_control = p;
6970 msg.msg_controllen = msg_ctrllen_left;
6972 msg.msg_control = NULL;
6973 msg.msg_controllen = 0;
6978 * We convert the unix address to a IP address so we need a buffer
6979 * which can store the address in case of SOCK_DGRAM, see below.
6981 msg.msg_name = &convert_addr.sa;
6982 msg.msg_namelen = convert_addr.sa_socklen;
6984 rc = swrap_recvmsg_after(s,
6988 from_addr.sa_socklen,
6994 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6995 if (omsg->msg_control != NULL) {
6996 /* msg.msg_controllen = space left */
6997 msg_ctrllen_left = msg.msg_controllen;
6998 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7001 /* Update the original message length */
7002 omsg->msg_controllen = msg_ctrllen_filled;
7003 omsg->msg_flags = msg.msg_flags;
7005 omsg->msg_iovlen = msg.msg_iovlen;
7012 * The msg_name field points to a caller-allocated buffer that is
7013 * used to return the source address if the socket is unconnected. The
7014 * caller should set msg_namelen to the size of this buffer before this
7015 * call; upon return from a successful call, msg_name will contain the
7016 * length of the returned address. If the application does not need
7017 * to know the source address, msg_name can be specified as NULL.
7019 if (si->type == SOCK_STREAM) {
7020 omsg->msg_namelen = 0;
7021 } else if (omsg->msg_name != NULL &&
7022 omsg->msg_namelen != 0 &&
7023 omsg->msg_namelen >= msg.msg_namelen) {
7024 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7025 omsg->msg_namelen = msg.msg_namelen;
7028 SWRAP_UNLOCK_SI(si);
7033 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7035 return swrap_recvmsg(sockfd, msg, flags);
7038 /****************************************************************************
7040 ***************************************************************************/
7042 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7046 struct sockaddr_un un_addr;
7047 const struct sockaddr_un *to_un = NULL;
7048 const struct sockaddr *to = NULL;
7051 struct socket_info *si = find_socket_info(s);
7055 int scm_rights_pipe_fd = -1;
7057 rc = swrap_sendmsg_before_unix(omsg, &msg,
7058 &scm_rights_pipe_fd);
7062 ret = libc_sendmsg(s, &msg, flags);
7063 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7066 ZERO_STRUCT(un_addr);
7068 tmp.iov_base = NULL;
7075 if (si->connected == 0) {
7076 msg.msg_name = omsg->msg_name; /* optional address */
7077 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7079 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7080 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7082 SWRAP_UNLOCK_SI(si);
7084 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7085 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7086 uint8_t *cmbuf = NULL;
7089 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7095 msg.msg_controllen = 0;
7096 msg.msg_control = NULL;
7098 msg.msg_control = cmbuf;
7099 msg.msg_controllen = cmlen;
7102 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7104 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7106 int saved_errno = errno;
7107 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7108 SAFE_FREE(msg.msg_control);
7110 errno = saved_errno;
7117 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7124 char *swrap_dir = NULL;
7126 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7127 avail += msg.msg_iov[i].iov_len;
7133 /* we capture it as one single packet */
7134 buf = (uint8_t *)malloc(remain);
7136 int saved_errno = errno;
7137 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7138 SAFE_FREE(msg.msg_control);
7140 errno = saved_errno;
7144 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7145 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7147 msg.msg_iov[i].iov_base,
7150 remain -= this_time;
7153 type = SOCKET_TYPE_CHAR_UDP;
7155 swrap_dir = socket_wrapper_dir();
7156 if (swrap_dir == NULL) {
7157 int saved_errno = errno;
7158 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7159 SAFE_FREE(msg.msg_control);
7162 errno = saved_errno;
7166 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7167 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7168 if (stat(un_addr.sun_path, &st) != 0) continue;
7170 msg.msg_name = &un_addr; /* optional address */
7171 msg.msg_namelen = sizeof(un_addr); /* size of address */
7173 /* ignore the any errors in broadcast sends */
7174 libc_sendmsg(s, &msg, flags);
7177 SAFE_FREE(swrap_dir);
7181 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7184 SWRAP_UNLOCK_SI(si);
7189 ret = libc_sendmsg(s, &msg, flags);
7191 swrap_sendmsg_after(s, si, &msg, to, ret);
7193 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7195 int saved_errno = errno;
7196 SAFE_FREE(msg.msg_control);
7197 errno = saved_errno;
7204 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7206 return swrap_sendmsg(s, omsg, flags);
7209 /****************************************************************************
7211 ***************************************************************************/
7213 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7215 struct socket_info *si;
7218 struct swrap_address saddr = {
7219 .sa_socklen = sizeof(struct sockaddr_storage)
7224 si = find_socket_info(s);
7226 return libc_readv(s, vector, count);
7229 tmp.iov_base = NULL;
7233 msg.msg_name = &saddr.sa.s; /* optional address */
7234 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7235 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7236 msg.msg_iovlen = count; /* # elements in msg_iov */
7237 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7238 msg.msg_control = NULL; /* ancillary data, see below */
7239 msg.msg_controllen = 0; /* ancillary data buffer len */
7240 msg.msg_flags = 0; /* flags on received message */
7243 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7245 if (rc == -ENOTSOCK) {
7246 return libc_readv(s, vector, count);
7251 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7253 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7261 ssize_t readv(int s, const struct iovec *vector, int count)
7263 return swrap_readv(s, vector, count);
7266 /****************************************************************************
7268 ***************************************************************************/
7270 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7274 struct sockaddr_un un_addr;
7277 struct socket_info *si = find_socket_info(s);
7280 return libc_writev(s, vector, count);
7283 tmp.iov_base = NULL;
7287 msg.msg_name = NULL; /* optional address */
7288 msg.msg_namelen = 0; /* size of address */
7289 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7290 msg.msg_iovlen = count; /* # elements in msg_iov */
7291 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7292 msg.msg_control = NULL; /* ancillary data, see below */
7293 msg.msg_controllen = 0; /* ancillary data buffer len */
7294 msg.msg_flags = 0; /* flags on received message */
7297 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7299 if (rc == -ENOTSOCK) {
7300 return libc_readv(s, vector, count);
7305 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7307 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7312 ssize_t writev(int s, const struct iovec *vector, int count)
7314 return swrap_writev(s, vector, count);
7317 /****************************
7319 ***************************/
7321 static int swrap_close(int fd)
7323 struct socket_info *si = NULL;
7327 swrap_mutex_lock(&socket_reset_mutex);
7329 si_index = find_socket_info_index(fd);
7330 if (si_index == -1) {
7331 swrap_mutex_unlock(&socket_reset_mutex);
7332 return libc_close(fd);
7335 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7336 reset_socket_info_index(fd);
7338 si = swrap_get_socket_info(si_index);
7340 swrap_mutex_lock(&first_free_mutex);
7343 ret = libc_close(fd);
7345 swrap_dec_refcount(si);
7347 if (swrap_get_refcount(si) > 0) {
7348 /* there are still references left */
7352 if (si->fd_passed) {
7356 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7357 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7360 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7361 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7362 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7365 if (si->un_addr.sun_path[0] != '\0') {
7366 unlink(si->un_addr.sun_path);
7370 swrap_set_next_free(si, first_free);
7371 first_free = si_index;
7374 SWRAP_UNLOCK_SI(si);
7375 swrap_mutex_unlock(&first_free_mutex);
7376 swrap_mutex_unlock(&socket_reset_mutex);
7383 return swrap_close(fd);
7386 /****************************
7388 ***************************/
7390 static int swrap_dup(int fd)
7392 struct socket_info *si;
7395 idx = find_socket_info_index(fd);
7397 return libc_dup(fd);
7400 si = swrap_get_socket_info(idx);
7402 dup_fd = libc_dup(fd);
7404 int saved_errno = errno;
7405 errno = saved_errno;
7409 if ((size_t)dup_fd >= socket_fds_max) {
7410 SWRAP_LOG(SWRAP_LOG_ERROR,
7411 "The max socket index limit of %zu has been reached, "
7422 swrap_inc_refcount(si);
7424 SWRAP_UNLOCK_SI(si);
7426 /* Make sure we don't have an entry for the fd */
7427 swrap_remove_stale(dup_fd);
7429 set_socket_info_index(dup_fd, idx);
7436 return swrap_dup(fd);
7439 /****************************
7441 ***************************/
7443 static int swrap_dup2(int fd, int newfd)
7445 struct socket_info *si;
7448 idx = find_socket_info_index(fd);
7450 return libc_dup2(fd, newfd);
7453 si = swrap_get_socket_info(idx);
7457 * According to the manpage:
7459 * "If oldfd is a valid file descriptor, and newfd has the same
7460 * value as oldfd, then dup2() does nothing, and returns newfd."
7465 if ((size_t)newfd >= socket_fds_max) {
7466 SWRAP_LOG(SWRAP_LOG_ERROR,
7467 "The max socket index limit of %zu has been reached, "
7475 if (find_socket_info(newfd)) {
7476 /* dup2() does an implicit close of newfd, which we
7477 * need to emulate */
7481 dup_fd = libc_dup2(fd, newfd);
7483 int saved_errno = errno;
7484 errno = saved_errno;
7490 swrap_inc_refcount(si);
7492 SWRAP_UNLOCK_SI(si);
7494 /* Make sure we don't have an entry for the fd */
7495 swrap_remove_stale(dup_fd);
7497 set_socket_info_index(dup_fd, idx);
7502 int dup2(int fd, int newfd)
7504 return swrap_dup2(fd, newfd);
7507 /****************************
7509 ***************************/
7511 static int swrap_vfcntl(int fd, int cmd, va_list va)
7513 struct socket_info *si;
7514 int rc, dup_fd, idx;
7516 idx = find_socket_info_index(fd);
7518 return libc_vfcntl(fd, cmd, va);
7521 si = swrap_get_socket_info(idx);
7525 dup_fd = libc_vfcntl(fd, cmd, va);
7527 int saved_errno = errno;
7528 errno = saved_errno;
7532 /* Make sure we don't have an entry for the fd */
7533 swrap_remove_stale(dup_fd);
7535 if ((size_t)dup_fd >= socket_fds_max) {
7536 SWRAP_LOG(SWRAP_LOG_ERROR,
7537 "The max socket index limit of %zu has been reached, "
7548 swrap_inc_refcount(si);
7550 SWRAP_UNLOCK_SI(si);
7553 set_socket_info_index(dup_fd, idx);
7558 rc = libc_vfcntl(fd, cmd, va);
7565 int fcntl(int fd, int cmd, ...)
7572 rc = swrap_vfcntl(fd, cmd, va);
7579 /****************************
7581 ***************************/
7584 static int swrap_eventfd(int count, int flags)
7588 fd = libc_eventfd(count, flags);
7590 swrap_remove_stale(fd);
7596 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7597 int eventfd(unsigned int count, int flags)
7599 int eventfd(int count, int flags)
7602 return swrap_eventfd(count, flags);
7607 int pledge(const char *promises, const char *paths[])
7609 (void)promises; /* unused */
7610 (void)paths; /* unused */
7614 #endif /* HAVE_PLEDGE */
7616 static void swrap_thread_prepare(void)
7619 * This function should only be called here!!
7621 * We bind all symobls to avoid deadlocks of the fork is
7622 * interrupted by a signal handler using a symbol of this
7625 swrap_bind_symbol_all();
7630 static void swrap_thread_parent(void)
7635 static void swrap_thread_child(void)
7640 /****************************
7642 ***************************/
7643 void swrap_constructor(void)
7645 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7646 SWRAP_LOG(SWRAP_LOG_ERROR,
7648 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7649 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7650 "sizeof(struct socket_info)=%zu",
7652 sizeof(struct swrap_unix_scm_rights),
7653 sizeof(struct swrap_unix_scm_rights_payload),
7654 sizeof(struct socket_info));
7661 * If we hold a lock and the application forks, then the child
7662 * is not able to unlock the mutex and we are in a deadlock.
7663 * This should prevent such deadlocks.
7665 pthread_atfork(&swrap_thread_prepare,
7666 &swrap_thread_parent,
7667 &swrap_thread_child);
7670 /****************************
7672 ***************************/
7675 * This function is called when the library is unloaded and makes sure that
7676 * sockets get closed and the unix file for the socket are unlinked.
7678 void swrap_destructor(void)
7682 if (socket_fds_idx != NULL) {
7683 for (i = 0; i < socket_fds_max; ++i) {
7684 if (socket_fds_idx[i] != -1) {
7688 SAFE_FREE(socket_fds_idx);
7693 if (swrap.libc.handle != NULL) {
7694 dlclose(swrap.libc.handle);
7696 if (swrap.libc.socket_handle) {
7697 dlclose(swrap.libc.socket_handle);
7701 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7703 * On FreeBSD 12 (and maybe other platforms)
7704 * system libraries like libresolv prefix there
7705 * syscalls with '_' in order to always use
7706 * the symbols from libc.
7708 * In the interaction with resolv_wrapper,
7709 * we need to inject socket wrapper into libresolv,
7710 * which means we need to private all socket
7711 * related syscalls also with the '_' prefix.
7713 * This is tested in Samba's 'make test',
7714 * there we noticed that providing '_read'
7715 * and '_open' would cause errors, which
7716 * means we skip '_read', '_write' and
7717 * all non socket related calls without
7718 * further analyzing the problem.
7720 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7721 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7724 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7726 SWRAP_SYMBOL_ALIAS(accept, _accept);
7727 SWRAP_SYMBOL_ALIAS(bind, _bind);
7728 SWRAP_SYMBOL_ALIAS(close, _close);
7729 SWRAP_SYMBOL_ALIAS(connect, _connect);
7730 SWRAP_SYMBOL_ALIAS(dup, _dup);
7731 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7732 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7733 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7734 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7735 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7736 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7737 SWRAP_SYMBOL_ALIAS(listen, _listen);
7738 SWRAP_SYMBOL_ALIAS(readv, _readv);
7739 SWRAP_SYMBOL_ALIAS(recv, _recv);
7740 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7741 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7742 SWRAP_SYMBOL_ALIAS(send, _send);
7743 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7744 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7745 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7746 SWRAP_SYMBOL_ALIAS(socket, _socket);
7747 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7748 SWRAP_SYMBOL_ALIAS(writev, _writev);
7750 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */