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));
762 #define swrap_mutex_unlock(m) _swrap_mutex_unlock(m, #m, __func__, __LINE__)
763 static void _swrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
767 ret = pthread_mutex_unlock(mutex);
769 SWRAP_LOG(SWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
770 getpid(), getppid(), caller, line, name, strerror(ret));
776 * These macros have a thread race condition on purpose!
778 * This is an optimization to avoid locking each time we check if the symbol is
781 #define _swrap_bind_symbol_generic(lib, sym_name) do { \
782 swrap.libc.symbols._libc_##sym_name.obj = \
783 _swrap_bind_symbol(lib, #sym_name); \
786 #define swrap_bind_symbol_libc(sym_name) \
787 _swrap_bind_symbol_generic(SWRAP_LIBC, sym_name)
789 #define swrap_bind_symbol_libsocket(sym_name) \
790 _swrap_bind_symbol_generic(SWRAP_LIBSOCKET, sym_name)
792 static void swrap_bind_symbol_all(void);
794 /****************************************************************************
796 ****************************************************************************
798 * Functions especially from libc need to be loaded individually, you can't
799 * load all at once or gdb will segfault at startup. The same applies to
800 * valgrind and has probably something todo with with the linker. So we need
801 * load each function at the point it is called the first time.
803 ****************************************************************************/
806 static int libc_accept4(int sockfd,
807 struct sockaddr *addr,
811 swrap_bind_symbol_all();
813 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
816 #else /* HAVE_ACCEPT4 */
818 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
820 swrap_bind_symbol_all();
822 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
824 #endif /* HAVE_ACCEPT4 */
826 static int libc_bind(int sockfd,
827 const struct sockaddr *addr,
830 swrap_bind_symbol_all();
832 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
835 static int libc_close(int fd)
837 swrap_bind_symbol_all();
839 return swrap.libc.symbols._libc_close.f(fd);
842 static int libc_connect(int sockfd,
843 const struct sockaddr *addr,
846 swrap_bind_symbol_all();
848 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
851 static int libc_dup(int fd)
853 swrap_bind_symbol_all();
855 return swrap.libc.symbols._libc_dup.f(fd);
858 static int libc_dup2(int oldfd, int newfd)
860 swrap_bind_symbol_all();
862 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
866 static int libc_eventfd(int count, int flags)
868 swrap_bind_symbol_all();
870 return swrap.libc.symbols._libc_eventfd.f(count, flags);
874 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
875 static int libc_vfcntl(int fd, int cmd, va_list ap)
880 swrap_bind_symbol_all();
882 arg = va_arg(ap, void *);
884 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
889 static int libc_getpeername(int sockfd,
890 struct sockaddr *addr,
893 swrap_bind_symbol_all();
895 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
898 static int libc_getsockname(int sockfd,
899 struct sockaddr *addr,
902 swrap_bind_symbol_all();
904 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
907 static int libc_getsockopt(int sockfd,
913 swrap_bind_symbol_all();
915 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
922 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
923 static int libc_vioctl(int d, unsigned long int request, va_list ap)
928 swrap_bind_symbol_all();
930 arg = va_arg(ap, void *);
932 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
937 static int libc_listen(int sockfd, int backlog)
939 swrap_bind_symbol_all();
941 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
944 static FILE *libc_fopen(const char *name, const char *mode)
946 swrap_bind_symbol_all();
948 return swrap.libc.symbols._libc_fopen.f(name, mode);
952 static FILE *libc_fopen64(const char *name, const char *mode)
954 swrap_bind_symbol_all();
956 return swrap.libc.symbols._libc_fopen64.f(name, mode);
958 #endif /* HAVE_FOPEN64 */
960 static int libc_vopen(const char *pathname, int flags, va_list ap)
965 swrap_bind_symbol_all();
967 if (flags & O_CREAT) {
968 mode = va_arg(ap, int);
970 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
975 static int libc_open(const char *pathname, int flags, ...)
981 fd = libc_vopen(pathname, flags, ap);
988 static int libc_vopen64(const char *pathname, int flags, va_list ap)
993 swrap_bind_symbol_all();
995 if (flags & O_CREAT) {
996 mode = va_arg(ap, int);
998 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
1002 #endif /* HAVE_OPEN64 */
1004 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
1009 swrap_bind_symbol_all();
1011 if (flags & O_CREAT) {
1012 mode = va_arg(ap, int);
1014 fd = swrap.libc.symbols._libc_openat.f(dirfd,
1023 static int libc_openat(int dirfd, const char *path, int flags, ...)
1028 va_start(ap, flags);
1029 fd = libc_vopenat(dirfd, path, flags, ap);
1036 static int libc_pipe(int pipefd[2])
1038 swrap_bind_symbol_all();
1040 return swrap.libc.symbols._libc_pipe.f(pipefd);
1043 static int libc_read(int fd, void *buf, size_t count)
1045 swrap_bind_symbol_all();
1047 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1050 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1052 swrap_bind_symbol_all();
1054 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1057 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1059 swrap_bind_symbol_all();
1061 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1064 static int libc_recvfrom(int sockfd,
1068 struct sockaddr *src_addr,
1071 swrap_bind_symbol_all();
1073 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1081 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1083 swrap_bind_symbol_all();
1085 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1088 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1090 swrap_bind_symbol_all();
1092 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1095 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1097 swrap_bind_symbol_all();
1099 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1102 static int libc_sendto(int sockfd,
1106 const struct sockaddr *dst_addr,
1109 swrap_bind_symbol_all();
1111 return swrap.libc.symbols._libc_sendto.f(sockfd,
1119 static int libc_setsockopt(int sockfd,
1125 swrap_bind_symbol_all();
1127 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1134 #ifdef HAVE_SIGNALFD
1135 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1137 swrap_bind_symbol_all();
1139 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1143 static int libc_socket(int domain, int type, int protocol)
1145 swrap_bind_symbol_all();
1147 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1150 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1152 swrap_bind_symbol_all();
1154 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1157 #ifdef HAVE_TIMERFD_CREATE
1158 static int libc_timerfd_create(int clockid, int flags)
1160 swrap_bind_symbol_all();
1162 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1166 static ssize_t libc_write(int fd, const void *buf, size_t count)
1168 swrap_bind_symbol_all();
1170 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1173 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1175 swrap_bind_symbol_all();
1177 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1180 /* DO NOT call this function during library initialization! */
1181 static void __swrap_bind_symbol_all_once(void)
1184 swrap_bind_symbol_libsocket(accept4);
1186 swrap_bind_symbol_libsocket(accept);
1188 swrap_bind_symbol_libsocket(bind);
1189 swrap_bind_symbol_libc(close);
1190 swrap_bind_symbol_libsocket(connect);
1191 swrap_bind_symbol_libc(dup);
1192 swrap_bind_symbol_libc(dup2);
1193 swrap_bind_symbol_libc(fcntl);
1194 swrap_bind_symbol_libc(fopen);
1196 swrap_bind_symbol_libc(fopen64);
1199 swrap_bind_symbol_libc(eventfd);
1201 swrap_bind_symbol_libsocket(getpeername);
1202 swrap_bind_symbol_libsocket(getsockname);
1203 swrap_bind_symbol_libsocket(getsockopt);
1204 swrap_bind_symbol_libc(ioctl);
1205 swrap_bind_symbol_libsocket(listen);
1206 swrap_bind_symbol_libc(open);
1208 swrap_bind_symbol_libc(open64);
1210 swrap_bind_symbol_libc(openat);
1211 swrap_bind_symbol_libsocket(pipe);
1212 swrap_bind_symbol_libc(read);
1213 swrap_bind_symbol_libsocket(readv);
1214 swrap_bind_symbol_libsocket(recv);
1215 swrap_bind_symbol_libsocket(recvfrom);
1216 swrap_bind_symbol_libsocket(recvmsg);
1217 swrap_bind_symbol_libsocket(send);
1218 swrap_bind_symbol_libsocket(sendmsg);
1219 swrap_bind_symbol_libsocket(sendto);
1220 swrap_bind_symbol_libsocket(setsockopt);
1221 #ifdef HAVE_SIGNALFD
1222 swrap_bind_symbol_libsocket(signalfd);
1224 swrap_bind_symbol_libsocket(socket);
1225 swrap_bind_symbol_libsocket(socketpair);
1226 #ifdef HAVE_TIMERFD_CREATE
1227 swrap_bind_symbol_libc(timerfd_create);
1229 swrap_bind_symbol_libc(write);
1230 swrap_bind_symbol_libsocket(writev);
1233 static void swrap_bind_symbol_all(void)
1235 static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1237 pthread_once(&all_symbol_binding_once, __swrap_bind_symbol_all_once);
1240 /*********************************************************
1241 * SWRAP HELPER FUNCTIONS
1242 *********************************************************/
1245 * We return 127.0.0.0 (default) or 10.53.57.0.
1247 * This can be controlled by:
1248 * SOCKET_WRAPPER_IPV4_NETWORK=127.0.0.0 (default)
1250 * SOCKET_WRAPPER_IPV4_NETWORK=10.53.57.0
1252 static in_addr_t swrap_ipv4_net(void)
1254 static int initialized;
1255 static in_addr_t hv;
1256 const char *net_str = NULL;
1265 net_str = getenv("SOCKET_WRAPPER_IPV4_NETWORK");
1266 if (net_str == NULL) {
1267 net_str = "127.0.0.0";
1270 ret = inet_pton(AF_INET, net_str, &nv);
1272 SWRAP_LOG(SWRAP_LOG_ERROR,
1273 "INVALID IPv4 Network [%s]",
1278 hv = ntohl(nv.s_addr);
1288 SWRAP_LOG(SWRAP_LOG_ERROR,
1289 "INVALID IPv4 Network [%s][0x%x] should be "
1290 "127.0.0.0 or 10.53.57.0",
1291 net_str, (unsigned)hv);
1299 * This returns 127.255.255.255 or 10.255.255.255
1301 static in_addr_t swrap_ipv4_bcast(void)
1305 hv = swrap_ipv4_net();
1306 hv |= IN_CLASSA_HOST;
1312 * This returns 127.0.0.${iface} or 10.53.57.${iface}
1314 static in_addr_t swrap_ipv4_iface(unsigned int iface)
1318 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1319 SWRAP_LOG(SWRAP_LOG_ERROR,
1320 "swrap_ipv4_iface(%u) invalid!",
1326 hv = swrap_ipv4_net();
1336 static const struct in6_addr *swrap_ipv6(void)
1338 static struct in6_addr v;
1339 static int initialized;
1347 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1356 static void set_port(int family, int prt, struct swrap_address *addr)
1360 addr->sa.in.sin_port = htons(prt);
1364 addr->sa.in6.sin6_port = htons(prt);
1370 static size_t socket_length(int family)
1374 return sizeof(struct sockaddr_in);
1377 return sizeof(struct sockaddr_in6);
1383 static struct socket_info *swrap_get_socket_info(int si_index)
1385 return (struct socket_info *)(&(sockets[si_index].info));
1388 static int swrap_get_refcount(struct socket_info *si)
1390 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1391 return sic->meta.refcount;
1394 static void swrap_inc_refcount(struct socket_info *si)
1396 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1398 sic->meta.refcount += 1;
1401 static void swrap_dec_refcount(struct socket_info *si)
1403 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1405 sic->meta.refcount -= 1;
1408 static int swrap_get_next_free(struct socket_info *si)
1410 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1412 return sic->meta.next_free;
1415 static void swrap_set_next_free(struct socket_info *si, int next_free)
1417 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1419 sic->meta.next_free = next_free;
1422 static int swrap_un_path(struct sockaddr_un *un,
1423 const char *swrap_dir,
1430 ret = snprintf(un->sun_path,
1431 sizeof(un->sun_path),
1437 if ((size_t)ret >= sizeof(un->sun_path)) {
1438 return ENAMETOOLONG;
1444 static int swrap_un_path_EINVAL(struct sockaddr_un *un,
1445 const char *swrap_dir)
1449 ret = snprintf(un->sun_path,
1450 sizeof(un->sun_path),
1454 if ((size_t)ret >= sizeof(un->sun_path)) {
1455 return ENAMETOOLONG;
1461 static bool swrap_dir_usable(const char *swrap_dir)
1463 struct sockaddr_un un;
1466 ret = swrap_un_path(&un, swrap_dir, SOCKET_TYPE_CHAR_TCP, 0, 0);
1471 ret = swrap_un_path_EINVAL(&un, swrap_dir);
1479 static char *socket_wrapper_dir(void)
1481 char *swrap_dir = NULL;
1482 char *s = getenv("SOCKET_WRAPPER_DIR");
1486 if (s == NULL || s[0] == '\0') {
1487 SWRAP_LOG(SWRAP_LOG_WARN, "SOCKET_WRAPPER_DIR not set");
1491 swrap_dir = realpath(s, NULL);
1492 if (swrap_dir == NULL) {
1493 SWRAP_LOG(SWRAP_LOG_ERROR,
1494 "Unable to resolve socket_wrapper dir path: %s - %s",
1500 ok = swrap_dir_usable(swrap_dir);
1507 ok = swrap_dir_usable(s);
1509 SWRAP_LOG(SWRAP_LOG_ERROR, "SOCKET_WRAPPER_DIR is too long");
1513 t = getenv("SOCKET_WRAPPER_DIR_ALLOW_ORIG");
1515 SWRAP_LOG(SWRAP_LOG_ERROR,
1516 "realpath(SOCKET_WRAPPER_DIR) too long and "
1517 "SOCKET_WRAPPER_DIR_ALLOW_ORIG not set");
1522 swrap_dir = strdup(s);
1523 if (swrap_dir == NULL) {
1524 SWRAP_LOG(SWRAP_LOG_ERROR,
1525 "Unable to duplicate socket_wrapper dir path");
1529 SWRAP_LOG(SWRAP_LOG_WARN,
1530 "realpath(SOCKET_WRAPPER_DIR) too long, "
1531 "using original SOCKET_WRAPPER_DIR\n");
1534 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", swrap_dir);
1538 static unsigned int socket_wrapper_mtu(void)
1540 static unsigned int max_mtu = 0;
1545 swrap_mutex_lock(&mtu_update_mutex);
1551 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1553 s = getenv("SOCKET_WRAPPER_MTU");
1558 tmp = strtol(s, &endp, 10);
1563 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1569 swrap_mutex_unlock(&mtu_update_mutex);
1573 static int _socket_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1575 pthread_mutexattr_t ma;
1576 bool need_destroy = false;
1579 #define __CHECK(cmd) do { \
1582 SWRAP_LOG(SWRAP_LOG_ERROR, \
1583 "%s: %s - failed %d", \
1589 *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1590 __CHECK(pthread_mutexattr_init(&ma));
1591 need_destroy = true;
1592 __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1593 __CHECK(pthread_mutex_init(m, &ma));
1596 pthread_mutexattr_destroy(&ma);
1601 static size_t socket_wrapper_max_sockets(void)
1607 if (socket_info_max != 0) {
1608 return socket_info_max;
1611 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1613 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1614 if (s == NULL || s[0] == '\0') {
1618 tmp = strtoul(s, &endp, 10);
1623 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1624 SWRAP_LOG(SWRAP_LOG_ERROR,
1625 "Invalid number of sockets specified, "
1626 "using default (%zu)",
1630 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1631 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1632 SWRAP_LOG(SWRAP_LOG_ERROR,
1633 "Invalid number of sockets specified, "
1634 "using maximum (%zu).",
1638 socket_info_max = tmp;
1641 return socket_info_max;
1644 static void socket_wrapper_init_fds_idx(void)
1649 if (socket_fds_idx != NULL) {
1653 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1655 SWRAP_LOG(SWRAP_LOG_ERROR,
1656 "Failed to allocate socket fds index array: %s",
1661 for (i = 0; i < socket_fds_max; i++) {
1665 socket_fds_idx = tmp;
1668 static void socket_wrapper_init_sockets(void)
1674 swrap_bind_symbol_all();
1676 swrap_mutex_lock(&sockets_mutex);
1678 if (sockets != NULL) {
1679 swrap_mutex_unlock(&sockets_mutex);
1683 SWRAP_LOG(SWRAP_LOG_DEBUG,
1684 "SOCKET_WRAPPER_PACKAGE[%s] SOCKET_WRAPPER_VERSION[%s]",
1685 SOCKET_WRAPPER_PACKAGE, SOCKET_WRAPPER_VERSION);
1688 * Intialize the static cache early before
1689 * any thread is able to start.
1691 (void)swrap_ipv4_net();
1693 socket_wrapper_init_fds_idx();
1695 /* Needs to be called inside the sockets_mutex lock here. */
1696 max_sockets = socket_wrapper_max_sockets();
1698 sockets = (struct socket_info_container *)calloc(max_sockets,
1699 sizeof(struct socket_info_container));
1701 if (sockets == NULL) {
1702 SWRAP_LOG(SWRAP_LOG_ERROR,
1703 "Failed to allocate sockets array: %s",
1705 swrap_mutex_unlock(&sockets_mutex);
1709 swrap_mutex_lock(&first_free_mutex);
1713 for (i = 0; i < max_sockets; i++) {
1714 swrap_set_next_free(&sockets[i].info, i+1);
1715 sockets[i].meta.mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1718 for (i = 0; i < max_sockets; i++) {
1719 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1721 SWRAP_LOG(SWRAP_LOG_ERROR,
1722 "Failed to initialize pthread mutex i=%zu", i);
1727 /* mark the end of the free list */
1728 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1731 swrap_mutex_unlock(&first_free_mutex);
1732 swrap_mutex_unlock(&sockets_mutex);
1738 bool socket_wrapper_enabled(void)
1740 char *s = socket_wrapper_dir();
1748 socket_wrapper_init_sockets();
1753 static unsigned int socket_wrapper_default_iface(void)
1755 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1758 if (sscanf(s, "%u", &iface) == 1) {
1759 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1765 return 1;/* 127.0.0.1 */
1768 static void set_socket_info_index(int fd, int idx)
1770 SWRAP_LOG(SWRAP_LOG_TRACE,
1773 socket_fds_idx[fd] = idx;
1774 /* This builtin issues a full memory barrier. */
1775 __sync_synchronize();
1778 static void reset_socket_info_index(int fd)
1780 SWRAP_LOG(SWRAP_LOG_TRACE,
1783 set_socket_info_index(fd, -1);
1786 static int find_socket_info_index(int fd)
1792 if (socket_fds_idx == NULL) {
1796 if ((size_t)fd >= socket_fds_max) {
1798 * Do not add a log here as some applications do stupid things
1801 * for (fd = 0; fd <= getdtablesize(); fd++) {
1805 * This would produce millions of lines of debug messages.
1808 SWRAP_LOG(SWRAP_LOG_ERROR,
1809 "Looking for a socket info for the fd %d is over the "
1810 "max socket index limit of %zu.",
1817 /* This builtin issues a full memory barrier. */
1818 __sync_synchronize();
1819 return socket_fds_idx[fd];
1822 static int swrap_add_socket_info(const struct socket_info *si_input)
1824 struct socket_info *si = NULL;
1827 if (si_input == NULL) {
1832 swrap_mutex_lock(&first_free_mutex);
1833 if (first_free == -1) {
1838 si_index = first_free;
1839 si = swrap_get_socket_info(si_index);
1843 first_free = swrap_get_next_free(si);
1845 swrap_inc_refcount(si);
1847 SWRAP_UNLOCK_SI(si);
1850 swrap_mutex_unlock(&first_free_mutex);
1855 static int swrap_create_socket(struct socket_info *si, int fd)
1859 if ((size_t)fd >= socket_fds_max) {
1860 SWRAP_LOG(SWRAP_LOG_ERROR,
1861 "The max socket index limit of %zu has been reached, "
1869 idx = swrap_add_socket_info(si);
1874 set_socket_info_index(fd, idx);
1879 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1886 p = strrchr(un->sun_path, '/');
1887 if (p) p++; else p = un->sun_path;
1889 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1890 SWRAP_LOG(SWRAP_LOG_ERROR, "sun_path[%s] p[%s]",
1896 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1897 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1904 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1910 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1914 case SOCKET_TYPE_CHAR_TCP:
1915 case SOCKET_TYPE_CHAR_UDP: {
1916 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1918 if ((*len) < sizeof(*in2)) {
1919 SWRAP_LOG(SWRAP_LOG_ERROR,
1920 "V4: *len(%zu) < sizeof(*in2)=%zu",
1921 (size_t)*len, sizeof(*in2));
1926 memset(in2, 0, sizeof(*in2));
1927 in2->sin_family = AF_INET;
1928 in2->sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
1929 in2->sin_port = htons(prt);
1931 *len = sizeof(*in2);
1935 case SOCKET_TYPE_CHAR_TCP_V6:
1936 case SOCKET_TYPE_CHAR_UDP_V6: {
1937 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1939 if ((*len) < sizeof(*in2)) {
1940 SWRAP_LOG(SWRAP_LOG_ERROR,
1941 "V6: *len(%zu) < sizeof(*in2)=%zu",
1942 (size_t)*len, sizeof(*in2));
1943 SWRAP_LOG(SWRAP_LOG_ERROR, "LINE:%d", __LINE__);
1948 memset(in2, 0, sizeof(*in2));
1949 in2->sin6_family = AF_INET6;
1950 in2->sin6_addr = *swrap_ipv6();
1951 in2->sin6_addr.s6_addr[15] = iface;
1952 in2->sin6_port = htons(prt);
1954 *len = sizeof(*in2);
1959 SWRAP_LOG(SWRAP_LOG_ERROR, "type %c iface %u port %u",
1968 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1975 char *swrap_dir = NULL;
1977 if (bcast) *bcast = 0;
1979 switch (inaddr->sa_family) {
1981 const struct sockaddr_in *in =
1982 (const struct sockaddr_in *)(const void *)inaddr;
1983 unsigned int addr = ntohl(in->sin_addr.s_addr);
1987 const unsigned int sw_net_addr = swrap_ipv4_net();
1988 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
1992 u_type = SOCKET_TYPE_CHAR_TCP;
1995 u_type = SOCKET_TYPE_CHAR_UDP;
1996 a_type = SOCKET_TYPE_CHAR_UDP;
1997 b_type = SOCKET_TYPE_CHAR_UDP;
2000 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2001 errno = ESOCKTNOSUPPORT;
2005 prt = ntohs(in->sin_port);
2006 if (a_type && addr == 0xFFFFFFFF) {
2007 /* 255.255.255.255 only udp */
2010 iface = socket_wrapper_default_iface();
2011 } else if (b_type && addr == sw_bcast_addr) {
2020 iface = socket_wrapper_default_iface();
2021 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2022 /* 127.0.0.X or 10.53.57.X */
2025 iface = (addr & 0x000000FF);
2027 errno = ENETUNREACH;
2030 if (bcast) *bcast = is_bcast;
2035 const struct sockaddr_in6 *in =
2036 (const struct sockaddr_in6 *)(const void *)inaddr;
2037 struct in6_addr cmp1, cmp2;
2041 type = SOCKET_TYPE_CHAR_TCP_V6;
2044 type = SOCKET_TYPE_CHAR_UDP_V6;
2047 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2048 errno = ESOCKTNOSUPPORT;
2052 /* XXX no multicast/broadcast */
2054 prt = ntohs(in->sin6_port);
2056 cmp1 = *swrap_ipv6();
2057 cmp2 = in->sin6_addr;
2058 cmp2.s6_addr[15] = 0;
2059 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2060 iface = in->sin6_addr.s6_addr[15];
2062 errno = ENETUNREACH;
2070 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!");
2071 errno = ENETUNREACH;
2076 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set");
2081 swrap_dir = socket_wrapper_dir();
2082 if (swrap_dir == NULL) {
2088 swrap_un_path_EINVAL(un, swrap_dir);
2089 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2090 SAFE_FREE(swrap_dir);
2091 /* the caller need to do more processing */
2095 swrap_un_path(un, swrap_dir, type, iface, prt);
2096 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2098 SAFE_FREE(swrap_dir);
2103 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
2111 char *swrap_dir = NULL;
2113 if (bcast) *bcast = 0;
2115 switch (si->family) {
2117 const struct sockaddr_in *in =
2118 (const struct sockaddr_in *)(const void *)inaddr;
2119 unsigned int addr = ntohl(in->sin_addr.s_addr);
2124 const unsigned int sw_net_addr = swrap_ipv4_net();
2125 const unsigned int sw_bcast_addr = swrap_ipv4_bcast();
2127 prt = ntohs(in->sin_port);
2131 u_type = SOCKET_TYPE_CHAR_TCP;
2132 d_type = SOCKET_TYPE_CHAR_TCP;
2135 u_type = SOCKET_TYPE_CHAR_UDP;
2136 d_type = SOCKET_TYPE_CHAR_UDP;
2137 a_type = SOCKET_TYPE_CHAR_UDP;
2138 b_type = SOCKET_TYPE_CHAR_UDP;
2141 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2142 errno = ESOCKTNOSUPPORT;
2150 iface = socket_wrapper_default_iface();
2151 } else if (a_type && addr == 0xFFFFFFFF) {
2152 /* 255.255.255.255 only udp */
2155 iface = socket_wrapper_default_iface();
2156 } else if (b_type && addr == sw_bcast_addr) {
2157 /* 127.255.255.255 only udp */
2160 iface = socket_wrapper_default_iface();
2161 } else if ((addr & 0xFFFFFF00) == sw_net_addr) {
2165 iface = (addr & 0x000000FF);
2167 errno = EADDRNOTAVAIL;
2171 /* Store the bind address for connect() */
2172 if (si->bindname.sa_socklen == 0) {
2173 struct sockaddr_in bind_in;
2174 socklen_t blen = sizeof(struct sockaddr_in);
2176 ZERO_STRUCT(bind_in);
2177 bind_in.sin_family = in->sin_family;
2178 bind_in.sin_port = in->sin_port;
2179 bind_in.sin_addr.s_addr = htonl(swrap_ipv4_iface(iface));
2180 si->bindname.sa_socklen = blen;
2181 memcpy(&si->bindname.sa.in, &bind_in, blen);
2188 const struct sockaddr_in6 *in =
2189 (const struct sockaddr_in6 *)(const void *)inaddr;
2190 struct in6_addr cmp1, cmp2;
2194 type = SOCKET_TYPE_CHAR_TCP_V6;
2197 type = SOCKET_TYPE_CHAR_UDP_V6;
2200 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2201 errno = ESOCKTNOSUPPORT;
2205 /* XXX no multicast/broadcast */
2207 prt = ntohs(in->sin6_port);
2209 cmp1 = *swrap_ipv6();
2210 cmp2 = in->sin6_addr;
2211 cmp2.s6_addr[15] = 0;
2212 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
2213 iface = socket_wrapper_default_iface();
2214 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
2215 iface = in->sin6_addr.s6_addr[15];
2217 errno = EADDRNOTAVAIL;
2221 /* Store the bind address for connect() */
2222 if (si->bindname.sa_socklen == 0) {
2223 struct sockaddr_in6 bind_in;
2224 socklen_t blen = sizeof(struct sockaddr_in6);
2226 ZERO_STRUCT(bind_in);
2227 bind_in.sin6_family = in->sin6_family;
2228 bind_in.sin6_port = in->sin6_port;
2230 bind_in.sin6_addr = *swrap_ipv6();
2231 bind_in.sin6_addr.s6_addr[15] = iface;
2233 memcpy(&si->bindname.sa.in6, &bind_in, blen);
2234 si->bindname.sa_socklen = blen;
2241 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2242 errno = EADDRNOTAVAIL;
2247 if (bcast) *bcast = is_bcast;
2249 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
2254 swrap_dir = socket_wrapper_dir();
2255 if (swrap_dir == NULL) {
2261 /* handle auto-allocation of ephemeral ports */
2262 for (prt = 5001; prt < 10000; prt++) {
2263 swrap_un_path(un, swrap_dir, type, iface, prt);
2264 if (stat(un->sun_path, &st) == 0) continue;
2266 set_port(si->family, prt, &si->myname);
2267 set_port(si->family, prt, &si->bindname);
2274 SAFE_FREE(swrap_dir);
2279 swrap_un_path(un, swrap_dir, type, iface, prt);
2280 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
2282 SAFE_FREE(swrap_dir);
2287 static struct socket_info *find_socket_info(int fd)
2289 int idx = find_socket_info_index(fd);
2295 return swrap_get_socket_info(idx);
2299 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2301 struct socket_info_fd *f;
2302 const struct socket_info *last_s = NULL;
2304 /* first catch invalid input */
2305 switch (sa->sa_family) {
2307 if (len < sizeof(struct sockaddr_in)) {
2313 if (len < sizeof(struct sockaddr_in6)) {
2323 for (f = socket_fds; f; f = f->next) {
2324 struct socket_info *s = swrap_get_socket_info(f->si_index);
2331 if (s->myname == NULL) {
2334 if (s->myname->sa_family != sa->sa_family) {
2337 switch (s->myname->sa_family) {
2339 struct sockaddr_in *sin1, *sin2;
2341 sin1 = (struct sockaddr_in *)s->myname;
2342 sin2 = (struct sockaddr_in *)sa;
2344 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2347 if (sin1->sin_port != sin2->sin_port) {
2350 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2360 struct sockaddr_in6 *sin1, *sin2;
2362 sin1 = (struct sockaddr_in6 *)s->myname;
2363 sin2 = (struct sockaddr_in6 *)sa;
2365 if (sin1->sin6_port != sin2->sin6_port) {
2368 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2390 static void swrap_remove_stale(int fd)
2392 struct socket_info *si;
2395 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2397 swrap_mutex_lock(&socket_reset_mutex);
2399 si_index = find_socket_info_index(fd);
2400 if (si_index == -1) {
2401 swrap_mutex_unlock(&socket_reset_mutex);
2405 reset_socket_info_index(fd);
2407 si = swrap_get_socket_info(si_index);
2409 swrap_mutex_lock(&first_free_mutex);
2412 swrap_dec_refcount(si);
2414 if (swrap_get_refcount(si) > 0) {
2418 if (si->un_addr.sun_path[0] != '\0') {
2419 unlink(si->un_addr.sun_path);
2422 swrap_set_next_free(si, first_free);
2423 first_free = si_index;
2426 SWRAP_UNLOCK_SI(si);
2427 swrap_mutex_unlock(&first_free_mutex);
2428 swrap_mutex_unlock(&socket_reset_mutex);
2431 static int sockaddr_convert_to_un(struct socket_info *si,
2432 const struct sockaddr *in_addr,
2434 struct sockaddr_un *out_addr,
2438 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2440 (void) in_len; /* unused */
2442 if (out_addr == NULL) {
2446 out->sa_family = AF_UNIX;
2447 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2448 out->sa_len = sizeof(*out_addr);
2451 switch (in_addr->sa_family) {
2453 const struct sockaddr_in *sin;
2454 if (si->family != AF_INET) {
2457 if (in_len < sizeof(struct sockaddr_in)) {
2460 sin = (const struct sockaddr_in *)(const void *)in_addr;
2461 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2466 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2467 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2481 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2482 errno = ESOCKTNOSUPPORT;
2486 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2488 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2494 errno = EAFNOSUPPORT;
2495 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2499 static int sockaddr_convert_from_un(const struct socket_info *si,
2500 const struct sockaddr_un *in_addr,
2501 socklen_t un_addrlen,
2503 struct sockaddr *out_addr,
2504 socklen_t *out_addrlen)
2508 if (out_addr == NULL || out_addrlen == NULL)
2511 if (un_addrlen == 0) {
2526 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!");
2527 errno = ESOCKTNOSUPPORT;
2530 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2531 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2532 out_addr->sa_len = *out_addrlen;
2539 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family");
2540 errno = EAFNOSUPPORT;
2544 enum swrap_packet_type {
2546 SWRAP_CONNECT_UNREACH,
2554 SWRAP_SENDTO_UNREACH,
2565 struct swrap_file_hdr {
2567 uint16_t version_major;
2568 uint16_t version_minor;
2571 uint32_t frame_max_len;
2572 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2575 #define SWRAP_FILE_HDR_SIZE 24
2577 struct swrap_packet_frame {
2579 uint32_t micro_seconds;
2580 uint32_t recorded_length;
2581 uint32_t full_length;
2583 #define SWRAP_PACKET_FRAME_SIZE 16
2585 union swrap_packet_ip {
2589 uint16_t packet_length;
2590 uint16_t identification;
2595 uint16_t hdr_checksum;
2599 #define SWRAP_PACKET_IP_V4_SIZE 20
2602 uint8_t flow_label_high;
2603 uint16_t flow_label_low;
2604 uint16_t payload_length;
2605 uint8_t next_header;
2607 uint8_t src_addr[16];
2608 uint8_t dest_addr[16];
2610 #define SWRAP_PACKET_IP_V6_SIZE 40
2612 #define SWRAP_PACKET_IP_SIZE 40
2614 union swrap_packet_payload {
2616 uint16_t source_port;
2626 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2628 uint16_t source_port;
2633 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2640 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2647 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2649 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2651 #define SWRAP_PACKET_MIN_ALLOC \
2652 (SWRAP_PACKET_FRAME_SIZE + \
2653 SWRAP_PACKET_IP_SIZE + \
2654 SWRAP_PACKET_PAYLOAD_SIZE)
2656 static const char *swrap_pcap_init_file(void)
2658 static int initialized = 0;
2659 static const char *s = NULL;
2660 static const struct swrap_file_hdr h;
2661 static const struct swrap_packet_frame f;
2662 static const union swrap_packet_ip i;
2663 static const union swrap_packet_payload p;
2665 if (initialized == 1) {
2671 * TODO: don't use the structs use plain buffer offsets
2672 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2674 * for now make sure we disable PCAP support
2675 * if the struct has alignment!
2677 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2680 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2683 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2686 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2689 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2692 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2695 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2698 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2701 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2704 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2708 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2712 if (strncmp(s, "./", 2) == 0) {
2715 SWRAP_LOG(SWRAP_LOG_TRACE, "SOCKET_WRAPPER_PCAP_FILE: %s", s);
2719 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2720 const struct sockaddr *src,
2721 const struct sockaddr *dest,
2723 const uint8_t *payload,
2725 unsigned long tcp_seqno,
2726 unsigned long tcp_ack,
2727 unsigned char tcp_ctl,
2729 size_t *_packet_len)
2731 uint8_t *base = NULL;
2732 uint8_t *buf = NULL;
2735 struct swrap_packet_frame *frame;
2739 union swrap_packet_ip *ip;
2741 union swrap_packet_payload *pay;
2744 size_t nonwire_len = sizeof(struct swrap_packet_frame);
2745 size_t wire_hdr_len = 0;
2746 size_t wire_len = 0;
2747 size_t ip_hdr_len = 0;
2748 size_t icmp_hdr_len = 0;
2749 size_t icmp_truncate_len = 0;
2750 uint8_t protocol = 0, icmp_protocol = 0;
2751 const struct sockaddr_in *src_in = NULL;
2752 const struct sockaddr_in *dest_in = NULL;
2754 const struct sockaddr_in6 *src_in6 = NULL;
2755 const struct sockaddr_in6 *dest_in6 = NULL;
2760 switch (src->sa_family) {
2762 src_in = (const struct sockaddr_in *)(const void *)src;
2763 dest_in = (const struct sockaddr_in *)(const void *)dest;
2764 src_port = src_in->sin_port;
2765 dest_port = dest_in->sin_port;
2766 ip_hdr_len = sizeof(i.ip->v4);
2770 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2771 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2772 src_port = src_in6->sin6_port;
2773 dest_port = dest_in6->sin6_port;
2774 ip_hdr_len = sizeof(i.ip->v6);
2781 switch (socket_type) {
2783 protocol = 0x06; /* TCP */
2784 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2785 wire_len = wire_hdr_len + payload_len;
2789 protocol = 0x11; /* UDP */
2790 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2791 wire_len = wire_hdr_len + payload_len;
2799 icmp_protocol = protocol;
2800 switch (src->sa_family) {
2802 protocol = 0x01; /* ICMPv4 */
2803 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2807 protocol = 0x3A; /* ICMPv6 */
2808 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2812 if (wire_len > 64 ) {
2813 icmp_truncate_len = wire_len - 64;
2815 wire_len += icmp_hdr_len;
2818 packet_len = nonwire_len + wire_len;
2819 alloc_len = packet_len;
2820 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2821 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2824 base = (uint8_t *)calloc(1, alloc_len);
2832 f.frame->seconds = tval->tv_sec;
2833 f.frame->micro_seconds = tval->tv_usec;
2834 f.frame->recorded_length = wire_len - icmp_truncate_len;
2835 f.frame->full_length = wire_len - icmp_truncate_len;
2837 buf += SWRAP_PACKET_FRAME_SIZE;
2840 switch (src->sa_family) {
2842 if (src_in == NULL || dest_in == NULL) {
2847 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2848 i.ip->v4.tos = 0x00;
2849 i.ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2850 i.ip->v4.identification = htons(0xFFFF);
2851 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2852 i.ip->v4.fragment = htons(0x0000);
2853 i.ip->v4.ttl = 0xFF;
2854 i.ip->v4.protocol = protocol;
2855 i.ip->v4.hdr_checksum = htons(0x0000);
2856 i.ip->v4.src_addr = src_in->sin_addr.s_addr;
2857 i.ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2858 buf += SWRAP_PACKET_IP_V4_SIZE;
2862 if (src_in6 == NULL || dest_in6 == NULL) {
2867 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2868 i.ip->v6.flow_label_high = 0x00;
2869 i.ip->v6.flow_label_low = 0x0000;
2870 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2871 i.ip->v6.next_header = protocol;
2872 memcpy(i.ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2873 memcpy(i.ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2874 buf += SWRAP_PACKET_IP_V6_SIZE;
2880 pay = (union swrap_packet_payload *)(void *)buf;
2881 switch (src->sa_family) {
2883 pay->icmp4.type = 0x03; /* destination unreachable */
2884 pay->icmp4.code = 0x01; /* host unreachable */
2885 pay->icmp4.checksum = htons(0x0000);
2886 pay->icmp4.unused = htonl(0x00000000);
2888 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2890 /* set the ip header in the ICMP payload */
2892 i.ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2893 i.ip->v4.tos = 0x00;
2894 i.ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2895 i.ip->v4.identification = htons(0xFFFF);
2896 i.ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2897 i.ip->v4.fragment = htons(0x0000);
2898 i.ip->v4.ttl = 0xFF;
2899 i.ip->v4.protocol = icmp_protocol;
2900 i.ip->v4.hdr_checksum = htons(0x0000);
2901 i.ip->v4.src_addr = dest_in->sin_addr.s_addr;
2902 i.ip->v4.dest_addr = src_in->sin_addr.s_addr;
2904 buf += SWRAP_PACKET_IP_V4_SIZE;
2906 src_port = dest_in->sin_port;
2907 dest_port = src_in->sin_port;
2911 pay->icmp6.type = 0x01; /* destination unreachable */
2912 pay->icmp6.code = 0x03; /* address unreachable */
2913 pay->icmp6.checksum = htons(0x0000);
2914 pay->icmp6.unused = htonl(0x00000000);
2915 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2917 /* set the ip header in the ICMP payload */
2919 i.ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2920 i.ip->v6.flow_label_high = 0x00;
2921 i.ip->v6.flow_label_low = 0x0000;
2922 i.ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2923 i.ip->v6.next_header = protocol;
2924 memcpy(i.ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2925 memcpy(i.ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2927 buf += SWRAP_PACKET_IP_V6_SIZE;
2929 src_port = dest_in6->sin6_port;
2930 dest_port = src_in6->sin6_port;
2936 pay = (union swrap_packet_payload *)(void *)buf;
2938 switch (socket_type) {
2940 pay->tcp.source_port = src_port;
2941 pay->tcp.dest_port = dest_port;
2942 pay->tcp.seq_num = htonl(tcp_seqno);
2943 pay->tcp.ack_num = htonl(tcp_ack);
2944 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2945 pay->tcp.control = tcp_ctl;
2946 pay->tcp.window = htons(0x7FFF);
2947 pay->tcp.checksum = htons(0x0000);
2948 pay->tcp.urg = htons(0x0000);
2949 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2954 pay->udp.source_port = src_port;
2955 pay->udp.dest_port = dest_port;
2956 pay->udp.length = htons(8 + payload_len);
2957 pay->udp.checksum = htons(0x0000);
2958 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2963 if (payload && payload_len > 0) {
2964 memcpy(buf, payload, payload_len);
2967 *_packet_len = packet_len - icmp_truncate_len;
2971 static int swrap_pcap_get_fd(const char *fname)
2979 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2981 struct swrap_file_hdr file_hdr;
2982 file_hdr.magic = 0xA1B2C3D4;
2983 file_hdr.version_major = 0x0002;
2984 file_hdr.version_minor = 0x0004;
2985 file_hdr.timezone = 0x00000000;
2986 file_hdr.sigfigs = 0x00000000;
2987 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2988 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2990 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2997 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
3002 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
3003 const struct sockaddr *addr,
3004 enum swrap_packet_type type,
3005 const void *buf, size_t len,
3008 const struct sockaddr *src_addr;
3009 const struct sockaddr *dest_addr;
3010 unsigned long tcp_seqno = 0;
3011 unsigned long tcp_ack = 0;
3012 unsigned char tcp_ctl = 0;
3013 int unreachable = 0;
3017 switch (si->family) {
3029 case SWRAP_CONNECT_SEND:
3030 if (si->type != SOCK_STREAM) {
3034 src_addr = &si->myname.sa.s;
3037 tcp_seqno = si->io.pck_snd;
3038 tcp_ack = si->io.pck_rcv;
3039 tcp_ctl = 0x02; /* SYN */
3041 si->io.pck_snd += 1;
3045 case SWRAP_CONNECT_RECV:
3046 if (si->type != SOCK_STREAM) {
3050 dest_addr = &si->myname.sa.s;
3053 tcp_seqno = si->io.pck_rcv;
3054 tcp_ack = si->io.pck_snd;
3055 tcp_ctl = 0x12; /** SYN,ACK */
3057 si->io.pck_rcv += 1;
3061 case SWRAP_CONNECT_UNREACH:
3062 if (si->type != SOCK_STREAM) {
3066 dest_addr = &si->myname.sa.s;
3069 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
3070 tcp_seqno = si->io.pck_snd - 1;
3071 tcp_ack = si->io.pck_rcv;
3072 tcp_ctl = 0x02; /* SYN */
3077 case SWRAP_CONNECT_ACK:
3078 if (si->type != SOCK_STREAM) {
3082 src_addr = &si->myname.sa.s;
3085 tcp_seqno = si->io.pck_snd;
3086 tcp_ack = si->io.pck_rcv;
3087 tcp_ctl = 0x10; /* ACK */
3091 case SWRAP_ACCEPT_SEND:
3092 if (si->type != SOCK_STREAM) {
3096 dest_addr = &si->myname.sa.s;
3099 tcp_seqno = si->io.pck_rcv;
3100 tcp_ack = si->io.pck_snd;
3101 tcp_ctl = 0x02; /* SYN */
3103 si->io.pck_rcv += 1;
3107 case SWRAP_ACCEPT_RECV:
3108 if (si->type != SOCK_STREAM) {
3112 src_addr = &si->myname.sa.s;
3115 tcp_seqno = si->io.pck_snd;
3116 tcp_ack = si->io.pck_rcv;
3117 tcp_ctl = 0x12; /* SYN,ACK */
3119 si->io.pck_snd += 1;
3123 case SWRAP_ACCEPT_ACK:
3124 if (si->type != SOCK_STREAM) {
3128 dest_addr = &si->myname.sa.s;
3131 tcp_seqno = si->io.pck_rcv;
3132 tcp_ack = si->io.pck_snd;
3133 tcp_ctl = 0x10; /* ACK */
3138 src_addr = &si->myname.sa.s;
3139 dest_addr = &si->peername.sa.s;
3141 tcp_seqno = si->io.pck_snd;
3142 tcp_ack = si->io.pck_rcv;
3143 tcp_ctl = 0x18; /* PSH,ACK */
3145 si->io.pck_snd += len;
3149 case SWRAP_SEND_RST:
3150 dest_addr = &si->myname.sa.s;
3151 src_addr = &si->peername.sa.s;
3153 if (si->type == SOCK_DGRAM) {
3154 return swrap_pcap_marshall_packet(si,
3156 SWRAP_SENDTO_UNREACH,
3162 tcp_seqno = si->io.pck_rcv;
3163 tcp_ack = si->io.pck_snd;
3164 tcp_ctl = 0x14; /** RST,ACK */
3168 case SWRAP_PENDING_RST:
3169 dest_addr = &si->myname.sa.s;
3170 src_addr = &si->peername.sa.s;
3172 if (si->type == SOCK_DGRAM) {
3176 tcp_seqno = si->io.pck_rcv;
3177 tcp_ack = si->io.pck_snd;
3178 tcp_ctl = 0x14; /* RST,ACK */
3183 dest_addr = &si->myname.sa.s;
3184 src_addr = &si->peername.sa.s;
3186 tcp_seqno = si->io.pck_rcv;
3187 tcp_ack = si->io.pck_snd;
3188 tcp_ctl = 0x18; /* PSH,ACK */
3190 si->io.pck_rcv += len;
3194 case SWRAP_RECV_RST:
3195 dest_addr = &si->myname.sa.s;
3196 src_addr = &si->peername.sa.s;
3198 if (si->type == SOCK_DGRAM) {
3202 tcp_seqno = si->io.pck_rcv;
3203 tcp_ack = si->io.pck_snd;
3204 tcp_ctl = 0x14; /* RST,ACK */
3209 src_addr = &si->myname.sa.s;
3212 si->io.pck_snd += len;
3216 case SWRAP_SENDTO_UNREACH:
3217 dest_addr = &si->myname.sa.s;
3224 case SWRAP_RECVFROM:
3225 dest_addr = &si->myname.sa.s;
3228 si->io.pck_rcv += len;
3232 case SWRAP_CLOSE_SEND:
3233 if (si->type != SOCK_STREAM) {
3237 src_addr = &si->myname.sa.s;
3238 dest_addr = &si->peername.sa.s;
3240 tcp_seqno = si->io.pck_snd;
3241 tcp_ack = si->io.pck_rcv;
3242 tcp_ctl = 0x11; /* FIN, ACK */
3244 si->io.pck_snd += 1;
3248 case SWRAP_CLOSE_RECV:
3249 if (si->type != SOCK_STREAM) {
3253 dest_addr = &si->myname.sa.s;
3254 src_addr = &si->peername.sa.s;
3256 tcp_seqno = si->io.pck_rcv;
3257 tcp_ack = si->io.pck_snd;
3258 tcp_ctl = 0x11; /* FIN,ACK */
3260 si->io.pck_rcv += 1;
3264 case SWRAP_CLOSE_ACK:
3265 if (si->type != SOCK_STREAM) {
3269 src_addr = &si->myname.sa.s;
3270 dest_addr = &si->peername.sa.s;
3272 tcp_seqno = si->io.pck_snd;
3273 tcp_ack = si->io.pck_rcv;
3274 tcp_ctl = 0x10; /* ACK */
3281 swrapGetTimeOfDay(&tv);
3283 return swrap_pcap_packet_init(&tv,
3287 (const uint8_t *)buf,
3296 static void swrap_pcap_dump_packet(struct socket_info *si,
3297 const struct sockaddr *addr,
3298 enum swrap_packet_type type,
3299 const void *buf, size_t len)
3301 const char *file_name;
3303 size_t packet_len = 0;
3306 swrap_mutex_lock(&pcap_dump_mutex);
3308 file_name = swrap_pcap_init_file();
3313 packet = swrap_pcap_marshall_packet(si,
3319 if (packet == NULL) {
3323 fd = swrap_pcap_get_fd(file_name);
3325 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3334 swrap_mutex_unlock(&pcap_dump_mutex);
3337 /****************************************************************************
3339 ***************************************************************************/
3341 #ifdef HAVE_SIGNALFD
3342 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3346 rc = libc_signalfd(fd, mask, flags);
3348 swrap_remove_stale(fd);
3354 int signalfd(int fd, const sigset_t *mask, int flags)
3356 return swrap_signalfd(fd, mask, flags);
3360 /****************************************************************************
3362 ***************************************************************************/
3364 static int swrap_socket(int family, int type, int protocol)
3366 struct socket_info *si = NULL;
3367 struct socket_info _si = { 0 };
3370 int real_type = type;
3373 * Remove possible addition flags passed to socket() so
3374 * do not fail checking the type.
3375 * See https://lwn.net/Articles/281965/
3378 real_type &= ~SOCK_CLOEXEC;
3380 #ifdef SOCK_NONBLOCK
3381 real_type &= ~SOCK_NONBLOCK;
3384 if (!socket_wrapper_enabled()) {
3385 return libc_socket(family, type, protocol);
3396 #endif /* AF_NETLINK */
3399 #endif /* AF_PACKET */
3401 fd = libc_socket(family, type, protocol);
3403 /* Check if we have a stale fd and remove it */
3404 swrap_remove_stale(fd);
3405 SWRAP_LOG(SWRAP_LOG_TRACE,
3406 "Unix socket fd=%d",
3411 errno = EAFNOSUPPORT;
3415 switch (real_type) {
3421 errno = EPROTONOSUPPORT;
3429 if (real_type == SOCK_STREAM) {
3434 if (real_type == SOCK_DGRAM) {
3439 errno = EPROTONOSUPPORT;
3444 * We must call libc_socket with type, from the caller, not the version
3445 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3447 fd = libc_socket(AF_UNIX, type, 0);
3453 /* Check if we have a stale fd and remove it */
3454 swrap_remove_stale(fd);
3457 si->family = family;
3459 /* however, the rest of the socket_wrapper code expects just
3460 * the type, not the flags */
3461 si->type = real_type;
3462 si->protocol = protocol;
3465 * Setup myname so getsockname() can succeed to find out the socket
3468 switch(si->family) {
3470 struct sockaddr_in sin = {
3471 .sin_family = AF_INET,
3474 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3475 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3480 struct sockaddr_in6 sin6 = {
3481 .sin6_family = AF_INET6,
3484 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3485 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3494 ret = swrap_create_socket(si, fd);
3496 int saved_errno = errno;
3498 errno = saved_errno;
3502 SWRAP_LOG(SWRAP_LOG_TRACE,
3503 "Created %s socket for protocol %s, fd=%d",
3504 family == AF_INET ? "IPv4" : "IPv6",
3505 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3511 int socket(int family, int type, int protocol)
3513 return swrap_socket(family, type, protocol);
3516 /****************************************************************************
3518 ***************************************************************************/
3520 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3524 rc = libc_socketpair(family, type, protocol, sv);
3526 swrap_remove_stale(sv[0]);
3527 swrap_remove_stale(sv[1]);
3533 int socketpair(int family, int type, int protocol, int sv[2])
3535 return swrap_socketpair(family, type, protocol, sv);
3538 /****************************************************************************
3540 ***************************************************************************/
3542 #ifdef HAVE_TIMERFD_CREATE
3543 static int swrap_timerfd_create(int clockid, int flags)
3547 fd = libc_timerfd_create(clockid, flags);
3549 swrap_remove_stale(fd);
3555 int timerfd_create(int clockid, int flags)
3557 return swrap_timerfd_create(clockid, flags);
3561 /****************************************************************************
3563 ***************************************************************************/
3565 static int swrap_pipe(int pipefd[2])
3569 rc = libc_pipe(pipefd);
3571 swrap_remove_stale(pipefd[0]);
3572 swrap_remove_stale(pipefd[1]);
3578 int pipe(int pipefd[2])
3580 return swrap_pipe(pipefd);
3583 /****************************************************************************
3585 ***************************************************************************/
3587 static int swrap_accept(int s,
3588 struct sockaddr *addr,
3592 struct socket_info *parent_si, *child_si;
3593 struct socket_info new_si = { 0 };
3596 struct swrap_address un_addr = {
3597 .sa_socklen = sizeof(struct sockaddr_un),
3599 struct swrap_address un_my_addr = {
3600 .sa_socklen = sizeof(struct sockaddr_un),
3602 struct swrap_address in_addr = {
3603 .sa_socklen = sizeof(struct sockaddr_storage),
3605 struct swrap_address in_my_addr = {
3606 .sa_socklen = sizeof(struct sockaddr_storage),
3610 parent_si = find_socket_info(s);
3613 return libc_accept4(s, addr, addrlen, flags);
3616 return libc_accept(s, addr, addrlen);
3622 * prevent parent_si from being altered / closed
3625 SWRAP_LOCK_SI(parent_si);
3628 * assume out sockaddr have the same size as the in parent
3631 in_addr.sa_socklen = socket_length(parent_si->family);
3632 if (in_addr.sa_socklen <= 0) {
3633 SWRAP_UNLOCK_SI(parent_si);
3638 SWRAP_UNLOCK_SI(parent_si);
3641 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3644 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3647 int saved_errno = errno;
3648 if (saved_errno == ENOTSOCK) {
3649 /* Remove stale fds */
3650 swrap_remove_stale(s);
3652 errno = saved_errno;
3658 /* Check if we have a stale fd and remove it */
3659 swrap_remove_stale(fd);
3661 if (un_addr.sa.un.sun_path[0] == '\0') {
3663 * FreeBSD seems to have a problem where
3664 * accept4() on the unix socket doesn't
3665 * ECONNABORTED for already disconnected connections.
3667 * Let's try libc_getpeername() to get the peer address
3668 * as a fallback, but it'll likely return ENOTCONN,
3669 * which we have to map to ECONNABORTED.
3671 un_addr.sa_socklen = sizeof(struct sockaddr_un),
3672 ret = libc_getpeername(fd, &un_addr.sa.s, &un_addr.sa_socklen);
3674 int saved_errno = errno;
3676 if (saved_errno == ENOTCONN) {
3678 * If the connection is already disconnected
3679 * we should return ECONNABORTED.
3681 saved_errno = ECONNABORTED;
3683 errno = saved_errno;
3688 ret = libc_getsockname(fd,
3690 &un_my_addr.sa_socklen);
3692 int saved_errno = errno;
3694 if (saved_errno == ENOTCONN) {
3696 * If the connection is already disconnected
3697 * we should return ECONNABORTED.
3699 saved_errno = ECONNABORTED;
3701 errno = saved_errno;
3705 SWRAP_LOCK_SI(parent_si);
3707 ret = sockaddr_convert_from_un(parent_si,
3712 &in_addr.sa_socklen);
3714 int saved_errno = errno;
3715 SWRAP_UNLOCK_SI(parent_si);
3717 errno = saved_errno;
3723 child_si->family = parent_si->family;
3724 child_si->type = parent_si->type;
3725 child_si->protocol = parent_si->protocol;
3726 child_si->bound = 1;
3727 child_si->is_server = 1;
3728 child_si->connected = 1;
3730 SWRAP_UNLOCK_SI(parent_si);
3732 child_si->peername = (struct swrap_address) {
3733 .sa_socklen = in_addr.sa_socklen,
3735 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3737 if (addr != NULL && addrlen != NULL) {
3738 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3740 memcpy(addr, &in_addr.sa.ss, copy_len);
3742 *addrlen = in_addr.sa_socklen;
3745 ret = sockaddr_convert_from_un(child_si,
3747 un_my_addr.sa_socklen,
3750 &in_my_addr.sa_socklen);
3752 int saved_errno = errno;
3754 errno = saved_errno;
3758 SWRAP_LOG(SWRAP_LOG_TRACE,
3759 "accept() path=%s, fd=%d",
3760 un_my_addr.sa.un.sun_path, s);
3762 child_si->myname = (struct swrap_address) {
3763 .sa_socklen = in_my_addr.sa_socklen,
3765 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3767 idx = swrap_create_socket(&new_si, fd);
3769 int saved_errno = errno;
3771 errno = saved_errno;
3776 struct socket_info *si = swrap_get_socket_info(idx);
3779 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3780 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3781 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3782 SWRAP_UNLOCK_SI(si);
3789 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3791 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3795 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3796 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3798 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3801 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3804 static int autobind_start_init;
3805 static int autobind_start;
3807 /* using sendto() or connect() on an unbound socket would give the
3808 recipient no way to reply, as unlike UDP and TCP, a unix domain
3809 socket can't auto-assign ephemeral port numbers, so we need to
3811 Note: this might change the family from ipv6 to ipv4
3813 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3815 struct swrap_address un_addr = {
3816 .sa_socklen = sizeof(struct sockaddr_un),
3823 char *swrap_dir = NULL;
3825 swrap_mutex_lock(&autobind_start_mutex);
3827 if (autobind_start_init != 1) {
3828 autobind_start_init = 1;
3829 autobind_start = getpid();
3830 autobind_start %= 50000;
3831 autobind_start += 10000;
3834 un_addr.sa.un.sun_family = AF_UNIX;
3838 struct sockaddr_in in;
3842 type = SOCKET_TYPE_CHAR_TCP;
3845 type = SOCKET_TYPE_CHAR_UDP;
3848 errno = ESOCKTNOSUPPORT;
3853 memset(&in, 0, sizeof(in));
3854 in.sin_family = AF_INET;
3855 in.sin_addr.s_addr = htonl(swrap_ipv4_iface(
3856 socket_wrapper_default_iface()));
3858 si->myname = (struct swrap_address) {
3859 .sa_socklen = sizeof(in),
3861 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3866 struct sockaddr_in6 in6;
3868 if (si->family != family) {
3869 errno = ENETUNREACH;
3876 type = SOCKET_TYPE_CHAR_TCP_V6;
3879 type = SOCKET_TYPE_CHAR_UDP_V6;
3882 errno = ESOCKTNOSUPPORT;
3887 memset(&in6, 0, sizeof(in6));
3888 in6.sin6_family = AF_INET6;
3889 in6.sin6_addr = *swrap_ipv6();
3890 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3892 si->myname = (struct swrap_address) {
3893 .sa_socklen = sizeof(in6),
3895 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3900 errno = ESOCKTNOSUPPORT;
3905 if (autobind_start > 60000) {
3906 autobind_start = 10000;
3909 swrap_dir = socket_wrapper_dir();
3910 if (swrap_dir == NULL) {
3916 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3917 port = autobind_start + i;
3918 swrap_un_path(&un_addr.sa.un,
3921 socket_wrapper_default_iface(),
3923 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3925 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3930 si->un_addr = un_addr.sa.un;
3933 autobind_start = port + 1;
3936 if (i == SOCKET_MAX_SOCKETS) {
3937 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3938 "interface "SOCKET_FORMAT,
3941 socket_wrapper_default_iface(),
3948 si->family = family;
3949 set_port(si->family, port, &si->myname);
3954 SAFE_FREE(swrap_dir);
3955 swrap_mutex_unlock(&autobind_start_mutex);
3959 /****************************************************************************
3961 ***************************************************************************/
3963 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3967 struct swrap_address un_addr = {
3968 .sa_socklen = sizeof(struct sockaddr_un),
3970 struct socket_info *si = find_socket_info(s);
3974 return libc_connect(s, serv_addr, addrlen);
3979 if (si->bound == 0) {
3980 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3986 if (si->family != serv_addr->sa_family) {
3987 SWRAP_LOG(SWRAP_LOG_ERROR,
3988 "called for fd=%d (family=%d) called with invalid family=%d",
3989 s, si->family, serv_addr->sa_family);
3995 ret = sockaddr_convert_to_un(si, serv_addr,
3996 addrlen, &un_addr.sa.un, 0, &bcast);
4002 errno = ENETUNREACH;
4007 if (si->type == SOCK_DGRAM) {
4008 si->defer_connect = 1;
4011 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
4013 ret = libc_connect(s,
4015 un_addr.sa_socklen);
4018 SWRAP_LOG(SWRAP_LOG_TRACE,
4019 "connect() path=%s, fd=%d",
4020 un_addr.sa.un.sun_path, s);
4023 /* to give better errors */
4024 if (ret == -1 && errno == ENOENT) {
4025 errno = EHOSTUNREACH;
4029 si->peername = (struct swrap_address) {
4030 .sa_socklen = addrlen,
4033 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
4037 * When we connect() on a socket than we have to bind the
4038 * outgoing connection on the interface we use for the
4039 * transport. We already bound it on the right interface
4040 * but here we have to update the name so getsockname()
4041 * returns correct information.
4043 if (si->bindname.sa_socklen > 0) {
4044 si->myname = (struct swrap_address) {
4045 .sa_socklen = si->bindname.sa_socklen,
4048 memcpy(&si->myname.sa.ss,
4049 &si->bindname.sa.ss,
4050 si->bindname.sa_socklen);
4052 /* Cleanup bindname */
4053 si->bindname = (struct swrap_address) {
4058 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
4059 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
4061 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
4065 SWRAP_UNLOCK_SI(si);
4069 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
4071 return swrap_connect(s, serv_addr, addrlen);
4074 /****************************************************************************
4076 ***************************************************************************/
4078 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4081 struct swrap_address un_addr = {
4082 .sa_socklen = sizeof(struct sockaddr_un),
4084 struct socket_info *si = find_socket_info(s);
4091 return libc_bind(s, myaddr, addrlen);
4096 switch (si->family) {
4098 const struct sockaddr_in *sin;
4099 if (addrlen < sizeof(struct sockaddr_in)) {
4100 bind_error = EINVAL;
4104 sin = (const struct sockaddr_in *)(const void *)myaddr;
4106 if (sin->sin_family != AF_INET) {
4107 bind_error = EAFNOSUPPORT;
4110 /* special case for AF_UNSPEC */
4111 if (sin->sin_family == AF_UNSPEC &&
4112 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
4121 const struct sockaddr_in6 *sin6;
4122 if (addrlen < sizeof(struct sockaddr_in6)) {
4123 bind_error = EINVAL;
4127 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
4129 if (sin6->sin6_family != AF_INET6) {
4130 bind_error = EAFNOSUPPORT;
4137 bind_error = EINVAL;
4141 if (bind_error != 0) {
4148 in_use = check_addr_port_in_use(myaddr, addrlen);
4156 si->myname.sa_socklen = addrlen;
4157 memcpy(&si->myname.sa.ss, myaddr, addrlen);
4159 ret = sockaddr_convert_to_un(si,
4169 unlink(un_addr.sa.un.sun_path);
4171 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
4173 SWRAP_LOG(SWRAP_LOG_TRACE,
4174 "bind() path=%s, fd=%d",
4175 un_addr.sa.un.sun_path, s);
4182 SWRAP_UNLOCK_SI(si);
4187 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
4189 return swrap_bind(s, myaddr, addrlen);
4192 /****************************************************************************
4194 ***************************************************************************/
4196 #ifdef HAVE_BINDRESVPORT
4197 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
4199 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
4201 struct swrap_address myaddr = {
4202 .sa_socklen = sizeof(struct sockaddr_storage),
4205 static uint16_t port;
4210 #define SWRAP_STARTPORT 600
4211 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
4212 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
4215 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
4219 salen = myaddr.sa_socklen;
4222 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
4228 memset(&myaddr.sa.ss, 0, salen);
4233 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
4236 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
4238 salen = sizeof(struct sockaddr_in);
4239 sinp->sin_port = htons(port);
4243 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
4245 salen = sizeof(struct sockaddr_in6);
4246 sin6p->sin6_port = htons(port);
4250 errno = EAFNOSUPPORT;
4255 if (port > SWRAP_ENDPORT) {
4256 port = SWRAP_STARTPORT;
4259 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
4260 if (rc == 0 || errno != EADDRINUSE) {
4268 int bindresvport(int sockfd, struct sockaddr_in *sinp)
4270 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
4274 /****************************************************************************
4276 ***************************************************************************/
4278 static int swrap_listen(int s, int backlog)
4281 struct socket_info *si = find_socket_info(s);
4284 return libc_listen(s, backlog);
4289 if (si->bound == 0) {
4290 ret = swrap_auto_bind(s, si, si->family);
4297 ret = libc_listen(s, backlog);
4303 SWRAP_UNLOCK_SI(si);
4308 int listen(int s, int backlog)
4310 return swrap_listen(s, backlog);
4313 /****************************************************************************
4315 ***************************************************************************/
4317 static FILE *swrap_fopen(const char *name, const char *mode)
4321 fp = libc_fopen(name, mode);
4323 int fd = fileno(fp);
4325 swrap_remove_stale(fd);
4331 FILE *fopen(const char *name, const char *mode)
4333 return swrap_fopen(name, mode);
4336 /****************************************************************************
4338 ***************************************************************************/
4341 static FILE *swrap_fopen64(const char *name, const char *mode)
4345 fp = libc_fopen64(name, mode);
4347 int fd = fileno(fp);
4349 swrap_remove_stale(fd);
4355 FILE *fopen64(const char *name, const char *mode)
4357 return swrap_fopen64(name, mode);
4359 #endif /* HAVE_FOPEN64 */
4361 /****************************************************************************
4363 ***************************************************************************/
4365 static int swrap_vopen(const char *pathname, int flags, va_list ap)
4369 ret = libc_vopen(pathname, flags, ap);
4372 * There are methods for closing descriptors (libc-internal code
4373 * paths, direct syscalls) which close descriptors in ways that
4374 * we can't intercept, so try to recover when we notice that
4377 swrap_remove_stale(ret);
4382 int open(const char *pathname, int flags, ...)
4387 va_start(ap, flags);
4388 fd = swrap_vopen(pathname, flags, ap);
4394 /****************************************************************************
4396 ***************************************************************************/
4399 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4403 ret = libc_vopen64(pathname, flags, ap);
4406 * There are methods for closing descriptors (libc-internal code
4407 * paths, direct syscalls) which close descriptors in ways that
4408 * we can't intercept, so try to recover when we notice that
4411 swrap_remove_stale(ret);
4416 int open64(const char *pathname, int flags, ...)
4421 va_start(ap, flags);
4422 fd = swrap_vopen64(pathname, flags, ap);
4427 #endif /* HAVE_OPEN64 */
4429 /****************************************************************************
4431 ***************************************************************************/
4433 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4437 ret = libc_vopenat(dirfd, path, flags, ap);
4440 * There are methods for closing descriptors (libc-internal code
4441 * paths, direct syscalls) which close descriptors in ways that
4442 * we can't intercept, so try to recover when we notice that
4445 swrap_remove_stale(ret);
4451 int openat(int dirfd, const char *path, int flags, ...)
4456 va_start(ap, flags);
4457 fd = swrap_vopenat(dirfd, path, flags, ap);
4463 /****************************************************************************
4465 ***************************************************************************/
4467 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4469 struct socket_info *si = find_socket_info(s);
4474 return libc_getpeername(s, name, addrlen);
4479 if (si->peername.sa_socklen == 0)
4485 len = MIN(*addrlen, si->peername.sa_socklen);
4491 memcpy(name, &si->peername.sa.ss, len);
4492 *addrlen = si->peername.sa_socklen;
4496 SWRAP_UNLOCK_SI(si);
4501 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4502 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4504 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4507 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4510 /****************************************************************************
4512 ***************************************************************************/
4514 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4516 struct socket_info *si = find_socket_info(s);
4521 return libc_getsockname(s, name, addrlen);
4526 len = MIN(*addrlen, si->myname.sa_socklen);
4532 memcpy(name, &si->myname.sa.ss, len);
4533 *addrlen = si->myname.sa_socklen;
4537 SWRAP_UNLOCK_SI(si);
4542 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4543 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4545 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4548 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4551 /****************************************************************************
4553 ***************************************************************************/
4556 # ifdef SO_PROTOTYPE /* The Solaris name */
4557 # define SO_PROTOCOL SO_PROTOTYPE
4558 # endif /* SO_PROTOTYPE */
4559 #endif /* SO_PROTOCOL */
4561 static int swrap_getsockopt(int s, int level, int optname,
4562 void *optval, socklen_t *optlen)
4564 struct socket_info *si = find_socket_info(s);
4568 return libc_getsockopt(s,
4577 if (level == SOL_SOCKET) {
4581 if (optval == NULL || optlen == NULL ||
4582 *optlen < (socklen_t)sizeof(int)) {
4588 *optlen = sizeof(int);
4589 *(int *)optval = si->family;
4592 #endif /* SO_DOMAIN */
4596 if (optval == NULL || optlen == NULL ||
4597 *optlen < (socklen_t)sizeof(int)) {
4603 *optlen = sizeof(int);
4604 *(int *)optval = si->protocol;
4607 #endif /* SO_PROTOCOL */
4609 if (optval == NULL || optlen == NULL ||
4610 *optlen < (socklen_t)sizeof(int)) {
4616 *optlen = sizeof(int);
4617 *(int *)optval = si->type;
4621 ret = libc_getsockopt(s,
4628 } else if (level == IPPROTO_TCP) {
4633 * This enables sending packets directly out over TCP.
4634 * As a unix socket is doing that any way, report it as
4637 if (optval == NULL || optlen == NULL ||
4638 *optlen < (socklen_t)sizeof(int)) {
4644 *optlen = sizeof(int);
4645 *(int *)optval = si->tcp_nodelay;
4649 #endif /* TCP_NODELAY */
4652 struct tcp_info info;
4653 socklen_t ilen = sizeof(info);
4655 #ifdef HAVE_NETINET_TCP_FSM_H
4656 /* This is FreeBSD */
4657 # define __TCP_LISTEN TCPS_LISTEN
4658 # define __TCP_ESTABLISHED TCPS_ESTABLISHED
4659 # define __TCP_CLOSE TCPS_CLOSED
4662 # define __TCP_LISTEN TCP_LISTEN
4663 # define __TCP_ESTABLISHED TCP_ESTABLISHED
4664 # define __TCP_CLOSE TCP_CLOSE
4668 if (si->listening) {
4669 info.tcpi_state = __TCP_LISTEN;
4670 } else if (si->connected) {
4672 * For now we just fake a few values
4673 * supported both by FreeBSD and Linux
4675 info.tcpi_state = __TCP_ESTABLISHED;
4676 info.tcpi_rto = 200000; /* 200 msec */
4677 info.tcpi_rtt = 5000; /* 5 msec */
4678 info.tcpi_rttvar = 5000; /* 5 msec */
4680 info.tcpi_state = __TCP_CLOSE;
4681 info.tcpi_rto = 1000000; /* 1 sec */
4683 info.tcpi_rttvar = 250000; /* 250 msec */
4686 if (optval == NULL || optlen == NULL ||
4687 *optlen < (socklen_t)ilen) {
4694 memcpy(optval, &info, ilen);
4699 #endif /* TCP_INFO */
4705 errno = ENOPROTOOPT;
4709 SWRAP_UNLOCK_SI(si);
4713 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4714 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4716 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4719 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4722 /****************************************************************************
4724 ***************************************************************************/
4726 static int swrap_setsockopt(int s, int level, int optname,
4727 const void *optval, socklen_t optlen)
4729 struct socket_info *si = find_socket_info(s);
4733 return libc_setsockopt(s,
4740 if (level == SOL_SOCKET) {
4741 return libc_setsockopt(s,
4750 if (level == IPPROTO_TCP) {
4757 * This enables sending packets directly out over TCP.
4758 * A unix socket is doing that any way.
4760 if (optval == NULL || optlen == 0 ||
4761 optlen < (socklen_t)sizeof(int)) {
4767 i = *discard_const_p(int, optval);
4768 if (i != 0 && i != 1) {
4773 si->tcp_nodelay = i;
4778 #endif /* TCP_NODELAY */
4784 switch (si->family) {
4786 if (level == IPPROTO_IP) {
4788 if (optname == IP_PKTINFO) {
4789 si->pktinfo = AF_INET;
4791 #endif /* IP_PKTINFO */
4797 if (level == IPPROTO_IPV6) {
4798 #ifdef IPV6_RECVPKTINFO
4799 if (optname == IPV6_RECVPKTINFO) {
4800 si->pktinfo = AF_INET6;
4802 #endif /* IPV6_PKTINFO */
4808 errno = ENOPROTOOPT;
4814 SWRAP_UNLOCK_SI(si);
4818 int setsockopt(int s, int level, int optname,
4819 const void *optval, socklen_t optlen)
4821 return swrap_setsockopt(s, level, optname, optval, optlen);
4824 /****************************************************************************
4826 ***************************************************************************/
4828 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4830 struct socket_info *si = find_socket_info(s);
4832 int *value_ptr = NULL;
4836 return libc_vioctl(s, r, va);
4843 rc = libc_vioctl(s, r, va);
4848 value_ptr = ((int *)va_arg(ap, int *));
4851 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4852 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4853 } else if (value_ptr != NULL && *value_ptr == 0) { /* END OF FILE */
4854 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4859 /* this is FreeBSD */
4860 FALL_THROUGH; /* to TIOCOUTQ */
4861 #endif /* FIONWRITE */
4862 case TIOCOUTQ: /* same as SIOCOUTQ on Linux */
4864 * This may return more bytes then the application
4865 * sent into the socket, for tcp it should
4866 * return the number of unacked bytes.
4868 * On AF_UNIX, all bytes are immediately acked!
4871 value_ptr = ((int *)va_arg(ap, int *));
4879 SWRAP_UNLOCK_SI(si);
4883 #ifdef HAVE_IOCTL_INT
4884 int ioctl(int s, int r, ...)
4886 int ioctl(int s, unsigned long int r, ...)
4894 rc = swrap_vioctl(s, (unsigned long int) r, va);
4905 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4908 # ifdef _ALIGN /* BSD */
4909 #define CMSG_ALIGN _ALIGN
4911 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4912 # endif /* _ALIGN */
4913 #endif /* CMSG_ALIGN */
4916 * @brief Add a cmsghdr to a msghdr.
4918 * This is an function to add any type of cmsghdr. It will operate on the
4919 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4920 * the buffer position after the added cmsg element. Hence, this function is
4921 * intended to be used with an intermediate msghdr and not on the original
4922 * one handed in by the client.
4924 * @param[in] msg The msghdr to which to add the cmsg.
4926 * @param[in] level The cmsg level to set.
4928 * @param[in] type The cmsg type to set.
4930 * @param[in] data The cmsg data to set.
4932 * @param[in] len the length of the data to set.
4934 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4940 size_t cmlen = CMSG_LEN(len);
4941 size_t cmspace = CMSG_SPACE(len);
4942 uint8_t cmbuf[cmspace];
4943 void *cast_ptr = (void *)cmbuf;
4944 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4947 memset(cmbuf, 0, cmspace);
4949 if (msg->msg_controllen < cmlen) {
4950 cmlen = msg->msg_controllen;
4951 msg->msg_flags |= MSG_CTRUNC;
4954 if (msg->msg_controllen < cmspace) {
4955 cmspace = msg->msg_controllen;
4959 * We copy the full input data into an intermediate cmsghdr first
4960 * in order to more easily cope with truncation.
4962 cm->cmsg_len = cmlen;
4963 cm->cmsg_level = level;
4964 cm->cmsg_type = type;
4965 memcpy(CMSG_DATA(cm), data, len);
4968 * We now copy the possibly truncated buffer.
4969 * We copy cmlen bytes, but consume cmspace bytes,
4970 * leaving the possible padding uninitialiazed.
4972 p = (uint8_t *)msg->msg_control;
4973 memcpy(p, cm, cmlen);
4975 msg->msg_control = p;
4976 msg->msg_controllen -= cmspace;
4981 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4984 /* Add packet info */
4985 switch (si->pktinfo) {
4986 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4988 struct sockaddr_in *sin;
4989 #if defined(HAVE_STRUCT_IN_PKTINFO)
4990 struct in_pktinfo pkt;
4991 #elif defined(IP_RECVDSTADDR)
4995 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4996 sin = &si->bindname.sa.in;
4998 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
5001 sin = &si->myname.sa.in;
5006 #if defined(HAVE_STRUCT_IN_PKTINFO)
5007 pkt.ipi_ifindex = socket_wrapper_default_iface();
5008 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
5009 #elif defined(IP_RECVDSTADDR)
5010 pkt = sin->sin_addr;
5013 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
5018 #endif /* IP_PKTINFO */
5019 #if defined(HAVE_IPV6)
5021 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
5022 struct sockaddr_in6 *sin6;
5023 struct in6_pktinfo pkt6;
5025 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
5026 sin6 = &si->bindname.sa.in6;
5028 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
5031 sin6 = &si->myname.sa.in6;
5036 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
5037 pkt6.ipi6_addr = sin6->sin6_addr;
5039 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
5040 &pkt6, sizeof(pkt6));
5041 #endif /* HAVE_STRUCT_IN6_PKTINFO */
5045 #endif /* IPV6_PKTINFO */
5053 static int swrap_msghdr_add_socket_info(struct socket_info *si,
5054 struct msghdr *omsg)
5058 if (si->pktinfo > 0) {
5059 rc = swrap_msghdr_add_pktinfo(si, omsg);
5065 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5067 size_t *cm_data_space);
5068 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5070 size_t *cm_data_space);
5071 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5073 size_t *cm_data_space);
5075 static int swrap_sendmsg_filter_cmsghdr(const struct msghdr *_msg,
5077 size_t *cm_data_space)
5079 struct msghdr *msg = discard_const_p(struct msghdr, _msg);
5080 struct cmsghdr *cmsg;
5084 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
5088 for (cmsg = CMSG_FIRSTHDR(msg);
5090 cmsg = CMSG_NXTHDR(msg, cmsg)) {
5091 switch (cmsg->cmsg_level) {
5093 rc = swrap_sendmsg_filter_cmsg_ipproto_ip(cmsg,
5098 rc = swrap_sendmsg_filter_cmsg_sol_socket(cmsg,
5103 rc = swrap_sendmsg_copy_cmsg(cmsg,
5109 int saved_errno = errno;
5110 SAFE_FREE(*cm_data);
5112 errno = saved_errno;
5120 static int swrap_sendmsg_copy_cmsg(const struct cmsghdr *cmsg,
5122 size_t *cm_data_space)
5127 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
5129 p = realloc((*cm_data), cmspace);
5135 p = (*cm_data) + (*cm_data_space);
5136 *cm_data_space = cmspace;
5138 memcpy(p, cmsg, cmsg->cmsg_len);
5143 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5145 size_t *cm_data_space);
5148 static int swrap_sendmsg_filter_cmsg_ipproto_ip(const struct cmsghdr *cmsg,
5150 size_t *cm_data_space)
5154 switch(cmsg->cmsg_type) {
5157 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5164 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
5176 static int swrap_sendmsg_filter_cmsg_pktinfo(const struct cmsghdr *cmsg,
5178 size_t *cm_data_space)
5180 (void)cmsg; /* unused */
5181 (void)cm_data; /* unused */
5182 (void)cm_data_space; /* unused */
5185 * Passing a IP pktinfo to a unix socket might be rejected by the
5186 * Kernel, at least on FreeBSD. So skip this cmsg.
5191 static int swrap_sendmsg_filter_cmsg_sol_socket(const struct cmsghdr *cmsg,
5193 size_t *cm_data_space)
5197 switch (cmsg->cmsg_type) {
5199 SWRAP_LOG(SWRAP_LOG_TRACE,
5200 "Ignoring SCM_RIGHTS on inet socket!");
5203 #ifdef SCM_CREDENTIALS
5204 case SCM_CREDENTIALS:
5205 SWRAP_LOG(SWRAP_LOG_TRACE,
5206 "Ignoring SCM_CREDENTIALS on inet socket!");
5209 #endif /* SCM_CREDENTIALS */
5211 rc = swrap_sendmsg_copy_cmsg(cmsg,
5220 static const uint64_t swrap_unix_scm_right_magic = 0x8e0e13f27c42fc36;
5223 * We only allow up to 6 fds at a time
5224 * as that's more than enough for Samba
5225 * and it means we can keep the logic simple
5226 * and work with fixed size arrays.
5228 * We also keep sizeof(struct swrap_unix_scm_rights)
5229 * under PIPE_BUF (4096) in order to allow a non-blocking
5230 * write into the pipe.
5233 #define PIPE_BUF 4096
5235 #define SWRAP_MAX_PASSED_FDS ((size_t)6)
5236 #define SWRAP_MAX_PASSED_SOCKET_INFO SWRAP_MAX_PASSED_FDS
5237 struct swrap_unix_scm_rights_payload {
5239 int8_t idxs[SWRAP_MAX_PASSED_FDS];
5240 struct socket_info infos[SWRAP_MAX_PASSED_SOCKET_INFO];
5242 struct swrap_unix_scm_rights {
5244 char package_name[sizeof(SOCKET_WRAPPER_PACKAGE)];
5245 char package_version[sizeof(SOCKET_WRAPPER_VERSION)];
5247 uint32_t payload_size;
5248 struct swrap_unix_scm_rights_payload payload;
5251 static void swrap_dec_fd_passed_array(size_t num, struct socket_info **array)
5253 int saved_errno = errno;
5256 for (i = 0; i < num; i++) {
5257 struct socket_info *si = array[i];
5263 swrap_dec_refcount(si);
5264 if (si->fd_passed > 0) {
5267 SWRAP_UNLOCK_SI(si);
5271 errno = saved_errno;
5274 static void swrap_undo_si_idx_array(size_t num, int *array)
5276 int saved_errno = errno;
5279 swrap_mutex_lock(&first_free_mutex);
5281 for (i = 0; i < num; i++) {
5282 struct socket_info *si = NULL;
5284 if (array[i] == -1) {
5288 si = swrap_get_socket_info(array[i]);
5294 swrap_dec_refcount(si);
5295 SWRAP_UNLOCK_SI(si);
5297 swrap_set_next_free(si, first_free);
5298 first_free = array[i];
5302 swrap_mutex_unlock(&first_free_mutex);
5303 errno = saved_errno;
5306 static void swrap_close_fd_array(size_t num, const int *array)
5308 int saved_errno = errno;
5311 for (i = 0; i < num; i++) {
5312 if (array[i] == -1) {
5315 libc_close(array[i]);
5318 errno = saved_errno;
5326 union __swrap_cmsghdr {
5328 struct cmsghdr *cmsg;
5331 static int swrap_sendmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5333 size_t *cm_data_space,
5334 int *scm_rights_pipe_fd)
5336 struct swrap_unix_scm_rights info;
5337 struct swrap_unix_scm_rights_payload *payload = NULL;
5338 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5339 struct socket_info *si_array[SWRAP_MAX_PASSED_FDS] = { NULL, };
5340 size_t info_idx = 0;
5343 union __swrap_fds __fds_in = { .p = NULL, };
5344 const int *fds_in = NULL;
5346 size_t size_fds_out;
5347 union __swrap_fds __fds_out = { .p = NULL, };
5348 int *fds_out = NULL;
5351 size_t new_cm_data_space;
5352 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5353 struct cmsghdr *new_cmsg = NULL;
5356 int pipefd[2] = { -1, -1 };
5361 * We pass this a buffer to the kernel make sure any padding
5365 info.magic = swrap_unix_scm_right_magic;
5366 memcpy(info.package_name,
5367 SOCKET_WRAPPER_PACKAGE,
5368 sizeof(info.package_name));
5369 memcpy(info.package_version,
5370 SOCKET_WRAPPER_VERSION,
5371 sizeof(info.package_version));
5372 info.full_size = sizeof(info);
5373 info.payload_size = sizeof(info.payload);
5374 payload = &info.payload;
5376 if (*scm_rights_pipe_fd != -1) {
5377 SWRAP_LOG(SWRAP_LOG_ERROR,
5378 "Two SCM_RIGHTS headers are not supported by socket_wrapper");
5383 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5384 SWRAP_LOG(SWRAP_LOG_ERROR,
5385 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5386 (size_t)cmsg->cmsg_len,
5391 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5392 if ((size_fds_in % sizeof(int)) != 0) {
5393 SWRAP_LOG(SWRAP_LOG_ERROR,
5394 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5395 (size_t)cmsg->cmsg_len,
5401 num_fds_in = size_fds_in / sizeof(int);
5402 if (num_fds_in > SWRAP_MAX_PASSED_FDS) {
5403 SWRAP_LOG(SWRAP_LOG_ERROR,
5404 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5406 "SWRAP_MAX_PASSED_FDS(%zu)",
5407 (size_t)cmsg->cmsg_len,
5410 SWRAP_MAX_PASSED_FDS);
5414 if (num_fds_in == 0) {
5415 SWRAP_LOG(SWRAP_LOG_ERROR,
5416 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5418 (size_t)cmsg->cmsg_len,
5424 __fds_in.p = CMSG_DATA(cmsg);
5425 fds_in = __fds_in.fds;
5426 num_fds_out = num_fds_in + 1;
5428 SWRAP_LOG(SWRAP_LOG_TRACE,
5429 "num_fds_in=%zu num_fds_out=%zu",
5430 num_fds_in, num_fds_out);
5432 size_fds_out = sizeof(int) * num_fds_out;
5433 cmsg_len = CMSG_LEN(size_fds_out);
5434 cmsg_space = CMSG_SPACE(size_fds_out);
5436 new_cm_data_space = *cm_data_space + cmsg_space;
5438 p = realloc((*cm_data), new_cm_data_space);
5443 p = (*cm_data) + (*cm_data_space);
5444 memset(p, 0, cmsg_space);
5446 new_cmsg = __new_cmsg.cmsg;
5448 __fds_out.p = CMSG_DATA(new_cmsg);
5449 fds_out = __fds_out.fds;
5450 memcpy(fds_out, fds_in, size_fds_out);
5451 new_cmsg->cmsg_len = cmsg->cmsg_len;
5453 for (i = 0; i < num_fds_in; i++) {
5456 payload->idxs[i] = -1;
5457 payload->num_idxs++;
5459 si_idx_array[i] = find_socket_info_index(fds_in[i]);
5460 if (si_idx_array[i] == -1) {
5464 si_array[i] = swrap_get_socket_info(si_idx_array[i]);
5465 if (si_array[i] == NULL) {
5466 SWRAP_LOG(SWRAP_LOG_ERROR,
5467 "fds_in[%zu]=%d si_idx_array[%zu]=%d missing!",
5468 i, fds_in[i], i, si_idx_array[i]);
5473 for (j = 0; j < i; j++) {
5474 if (si_array[j] == si_array[i]) {
5475 payload->idxs[i] = payload->idxs[j];
5479 if (payload->idxs[i] == -1) {
5480 if (info_idx >= SWRAP_MAX_PASSED_SOCKET_INFO) {
5481 SWRAP_LOG(SWRAP_LOG_ERROR,
5482 "fds_in[%zu]=%d,si_idx_array[%zu]=%d: "
5483 "info_idx=%zu >= SWRAP_MAX_PASSED_FDS(%zu)!",
5484 i, fds_in[i], i, si_idx_array[i],
5486 SWRAP_MAX_PASSED_SOCKET_INFO);
5490 payload->idxs[i] = info_idx;
5496 for (i = 0; i < num_fds_in; i++) {
5497 struct socket_info *si = si_array[i];
5500 SWRAP_LOG(SWRAP_LOG_TRACE,
5501 "fds_in[%zu]=%d not an inet socket",
5506 SWRAP_LOG(SWRAP_LOG_TRACE,
5507 "fds_in[%zu]=%d si_idx_array[%zu]=%d "
5508 "passing as info.idxs[%zu]=%d!",
5511 i, payload->idxs[i]);
5515 payload->infos[payload->idxs[i]] = *si;
5516 payload->infos[payload->idxs[i]].fd_passed = 0;
5517 SWRAP_UNLOCK_SI(si);
5522 int saved_errno = errno;
5523 SWRAP_LOG(SWRAP_LOG_ERROR,
5524 "pipe() failed - %d %s",
5526 strerror(saved_errno));
5527 swrap_dec_fd_passed_array(num_fds_in, si_array);
5528 errno = saved_errno;
5532 sret = write(pipefd[1], &info, sizeof(info));
5533 if (sret != sizeof(info)) {
5534 int saved_errno = errno;
5536 saved_errno = EINVAL;
5538 SWRAP_LOG(SWRAP_LOG_ERROR,
5539 "write() failed - sret=%zd - %d %s",
5541 strerror(saved_errno));
5542 swrap_dec_fd_passed_array(num_fds_in, si_array);
5543 libc_close(pipefd[1]);
5544 libc_close(pipefd[0]);
5545 errno = saved_errno;
5548 libc_close(pipefd[1]);
5551 * Add the pipe read end to the end of the passed fd array
5553 fds_out[num_fds_in] = pipefd[0];
5554 new_cmsg->cmsg_len = cmsg_len;
5556 /* we're done ... */
5557 *scm_rights_pipe_fd = pipefd[0];
5558 *cm_data_space = new_cm_data_space;
5563 static int swrap_sendmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5565 size_t *cm_data_space,
5566 int *scm_rights_pipe_fd)
5570 switch (cmsg->cmsg_type) {
5572 rc = swrap_sendmsg_unix_scm_rights(cmsg,
5575 scm_rights_pipe_fd);
5578 rc = swrap_sendmsg_copy_cmsg(cmsg,
5587 static int swrap_recvmsg_unix_scm_rights(const struct cmsghdr *cmsg,
5589 size_t *cm_data_space)
5591 int scm_rights_pipe_fd = -1;
5592 struct swrap_unix_scm_rights info;
5593 struct swrap_unix_scm_rights_payload *payload = NULL;
5594 int si_idx_array[SWRAP_MAX_PASSED_FDS];
5597 union __swrap_fds __fds_in = { .p = NULL, };
5598 const int *fds_in = NULL;
5600 size_t size_fds_out;
5601 union __swrap_fds __fds_out = { .p = NULL, };
5602 int *fds_out = NULL;
5605 size_t new_cm_data_space;
5606 union __swrap_cmsghdr __new_cmsg = { .p = NULL, };
5607 struct cmsghdr *new_cmsg = NULL;
5613 if (cmsg->cmsg_len < CMSG_LEN(0)) {
5614 SWRAP_LOG(SWRAP_LOG_ERROR,
5615 "cmsg->cmsg_len=%zu < CMSG_LEN(0)=%zu",
5616 (size_t)cmsg->cmsg_len,
5621 size_fds_in = cmsg->cmsg_len - CMSG_LEN(0);
5622 if ((size_fds_in % sizeof(int)) != 0) {
5623 SWRAP_LOG(SWRAP_LOG_ERROR,
5624 "cmsg->cmsg_len=%zu => (size_fds_in=%zu %% sizeof(int)=%zu) != 0",
5625 (size_t)cmsg->cmsg_len,
5631 num_fds_in = size_fds_in / sizeof(int);
5632 if (num_fds_in > (SWRAP_MAX_PASSED_FDS + 1)) {
5633 SWRAP_LOG(SWRAP_LOG_ERROR,
5634 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5635 "num_fds_in=%zu > SWRAP_MAX_PASSED_FDS+1(%zu)",
5636 (size_t)cmsg->cmsg_len,
5639 SWRAP_MAX_PASSED_FDS+1);
5643 if (num_fds_in <= 1) {
5644 SWRAP_LOG(SWRAP_LOG_ERROR,
5645 "cmsg->cmsg_len=%zu,size_fds_in=%zu => "
5647 (size_t)cmsg->cmsg_len,
5653 __fds_in.p = CMSG_DATA(cmsg);
5654 fds_in = __fds_in.fds;
5655 num_fds_out = num_fds_in - 1;
5657 SWRAP_LOG(SWRAP_LOG_TRACE,
5658 "num_fds_in=%zu num_fds_out=%zu",
5659 num_fds_in, num_fds_out);
5661 for (i = 0; i < num_fds_in; i++) {
5662 /* Check if we have a stale fd and remove it */
5663 swrap_remove_stale(fds_in[i]);
5666 scm_rights_pipe_fd = fds_in[num_fds_out];
5667 size_fds_out = sizeof(int) * num_fds_out;
5668 cmsg_len = CMSG_LEN(size_fds_out);
5669 cmsg_space = CMSG_SPACE(size_fds_out);
5671 new_cm_data_space = *cm_data_space + cmsg_space;
5673 p = realloc((*cm_data), new_cm_data_space);
5675 swrap_close_fd_array(num_fds_in, fds_in);
5679 p = (*cm_data) + (*cm_data_space);
5680 memset(p, 0, cmsg_space);
5682 new_cmsg = __new_cmsg.cmsg;
5684 __fds_out.p = CMSG_DATA(new_cmsg);
5685 fds_out = __fds_out.fds;
5686 memcpy(fds_out, fds_in, size_fds_out);
5687 new_cmsg->cmsg_len = cmsg_len;
5689 sret = read(scm_rights_pipe_fd, &info, sizeof(info));
5690 if (sret != sizeof(info)) {
5691 int saved_errno = errno;
5693 saved_errno = EINVAL;
5695 SWRAP_LOG(SWRAP_LOG_ERROR,
5696 "read() failed - sret=%zd - %d %s",
5698 strerror(saved_errno));
5699 swrap_close_fd_array(num_fds_in, fds_in);
5700 errno = saved_errno;
5703 libc_close(scm_rights_pipe_fd);
5704 payload = &info.payload;
5706 if (info.magic != swrap_unix_scm_right_magic) {
5707 SWRAP_LOG(SWRAP_LOG_ERROR,
5708 "info.magic=0x%llx != swrap_unix_scm_right_magic=0x%llx",
5709 (unsigned long long)info.magic,
5710 (unsigned long long)swrap_unix_scm_right_magic);
5711 swrap_close_fd_array(num_fds_out, fds_out);
5716 cmp = memcmp(info.package_name,
5717 SOCKET_WRAPPER_PACKAGE,
5718 sizeof(info.package_name));
5720 SWRAP_LOG(SWRAP_LOG_ERROR,
5721 "info.package_name='%.*s' != '%s'",
5722 (int)sizeof(info.package_name),
5724 SOCKET_WRAPPER_PACKAGE);
5725 swrap_close_fd_array(num_fds_out, fds_out);
5730 cmp = memcmp(info.package_version,
5731 SOCKET_WRAPPER_VERSION,
5732 sizeof(info.package_version));
5734 SWRAP_LOG(SWRAP_LOG_ERROR,
5735 "info.package_version='%.*s' != '%s'",
5736 (int)sizeof(info.package_version),
5737 info.package_version,
5738 SOCKET_WRAPPER_VERSION);
5739 swrap_close_fd_array(num_fds_out, fds_out);
5744 if (info.full_size != sizeof(info)) {
5745 SWRAP_LOG(SWRAP_LOG_ERROR,
5746 "info.full_size=%zu != sizeof(info)=%zu",
5747 (size_t)info.full_size,
5749 swrap_close_fd_array(num_fds_out, fds_out);
5754 if (info.payload_size != sizeof(info.payload)) {
5755 SWRAP_LOG(SWRAP_LOG_ERROR,
5756 "info.payload_size=%zu != sizeof(info.payload)=%zu",
5757 (size_t)info.payload_size,
5758 sizeof(info.payload));
5759 swrap_close_fd_array(num_fds_out, fds_out);
5764 if (payload->num_idxs != num_fds_out) {
5765 SWRAP_LOG(SWRAP_LOG_ERROR,
5766 "info.num_idxs=%u != num_fds_out=%zu",
5767 payload->num_idxs, num_fds_out);
5768 swrap_close_fd_array(num_fds_out, fds_out);
5773 for (i = 0; i < num_fds_out; i++) {
5776 si_idx_array[i] = -1;
5778 if (payload->idxs[i] == -1) {
5779 SWRAP_LOG(SWRAP_LOG_TRACE,
5780 "fds_out[%zu]=%d not an inet socket",
5785 if (payload->idxs[i] < 0) {
5786 SWRAP_LOG(SWRAP_LOG_ERROR,
5787 "fds_out[%zu]=%d info.idxs[%zu]=%d < 0!",
5788 i, fds_out[i], i, payload->idxs[i]);
5789 swrap_close_fd_array(num_fds_out, fds_out);
5794 if (payload->idxs[i] >= payload->num_idxs) {
5795 SWRAP_LOG(SWRAP_LOG_ERROR,
5796 "fds_out[%zu]=%d info.idxs[%zu]=%d >= %u!",
5797 i, fds_out[i], i, payload->idxs[i],
5799 swrap_close_fd_array(num_fds_out, fds_out);
5804 if ((size_t)fds_out[i] >= socket_fds_max) {
5805 SWRAP_LOG(SWRAP_LOG_ERROR,
5806 "The max socket index limit of %zu has been reached, "
5810 swrap_close_fd_array(num_fds_out, fds_out);
5815 SWRAP_LOG(SWRAP_LOG_TRACE,
5817 "received as info.idxs[%zu]=%d!",
5819 i, payload->idxs[i]);
5821 for (j = 0; j < i; j++) {
5822 if (payload->idxs[j] == -1) {
5825 if (payload->idxs[j] == payload->idxs[i]) {
5826 si_idx_array[i] = si_idx_array[j];
5829 if (si_idx_array[i] == -1) {
5830 const struct socket_info *si = &payload->infos[payload->idxs[i]];
5832 si_idx_array[i] = swrap_add_socket_info(si);
5833 if (si_idx_array[i] == -1) {
5834 int saved_errno = errno;
5835 SWRAP_LOG(SWRAP_LOG_ERROR,
5836 "The max socket index limit of %zu has been reached, "
5840 swrap_undo_si_idx_array(i, si_idx_array);
5841 swrap_close_fd_array(num_fds_out, fds_out);
5842 errno = saved_errno;
5845 SWRAP_LOG(SWRAP_LOG_TRACE,
5846 "Imported %s socket for protocol %s, fd=%d",
5847 si->family == AF_INET ? "IPv4" : "IPv6",
5848 si->type == SOCK_DGRAM ? "UDP" : "TCP",
5853 for (i = 0; i < num_fds_out; i++) {
5854 if (si_idx_array[i] == -1) {
5857 set_socket_info_index(fds_out[i], si_idx_array[i]);
5860 /* we're done ... */
5861 *cm_data_space = new_cm_data_space;
5866 static int swrap_recvmsg_unix_sol_socket(const struct cmsghdr *cmsg,
5868 size_t *cm_data_space)
5872 switch (cmsg->cmsg_type) {
5874 rc = swrap_recvmsg_unix_scm_rights(cmsg,
5879 rc = swrap_sendmsg_copy_cmsg(cmsg,
5888 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5890 static int swrap_sendmsg_before_unix(const struct msghdr *_msg_in,
5891 struct msghdr *msg_tmp,
5892 int *scm_rights_pipe_fd)
5894 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5895 struct msghdr *msg_in = discard_const_p(struct msghdr, _msg_in);
5896 struct cmsghdr *cmsg = NULL;
5897 uint8_t *cm_data = NULL;
5898 size_t cm_data_space = 0;
5902 *scm_rights_pipe_fd = -1;
5905 if (msg_in->msg_controllen == 0 || msg_in->msg_control == NULL) {
5909 for (cmsg = CMSG_FIRSTHDR(msg_in);
5911 cmsg = CMSG_NXTHDR(msg_in, cmsg)) {
5912 switch (cmsg->cmsg_level) {
5914 rc = swrap_sendmsg_unix_sol_socket(cmsg,
5917 scm_rights_pipe_fd);
5921 rc = swrap_sendmsg_copy_cmsg(cmsg,
5927 int saved_errno = errno;
5929 errno = saved_errno;
5934 msg_tmp->msg_controllen = cm_data_space;
5935 msg_tmp->msg_control = cm_data;
5938 #else /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5939 *msg_tmp = *_msg_in;
5941 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5944 static ssize_t swrap_sendmsg_after_unix(struct msghdr *msg_tmp,
5946 int scm_rights_pipe_fd)
5948 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5949 int saved_errno = errno;
5950 SAFE_FREE(msg_tmp->msg_control);
5951 if (scm_rights_pipe_fd != -1) {
5952 libc_close(scm_rights_pipe_fd);
5954 errno = saved_errno;
5955 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
5959 static int swrap_recvmsg_before_unix(struct msghdr *msg_in,
5960 struct msghdr *msg_tmp)
5966 static ssize_t swrap_recvmsg_after_unix(struct msghdr *msg_tmp,
5967 struct msghdr *msg_out,
5970 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5971 struct cmsghdr *cmsg = NULL;
5972 uint8_t *cm_data = NULL;
5973 size_t cm_data_space = 0;
5977 if (msg_tmp->msg_controllen == 0 || msg_tmp->msg_control == NULL) {
5981 for (cmsg = CMSG_FIRSTHDR(msg_tmp);
5983 cmsg = CMSG_NXTHDR(msg_tmp, cmsg)) {
5984 switch (cmsg->cmsg_level) {
5986 rc = swrap_recvmsg_unix_sol_socket(cmsg,
5992 rc = swrap_sendmsg_copy_cmsg(cmsg,
5998 int saved_errno = errno;
6000 errno = saved_errno;
6006 * msg_tmp->msg_control is still the buffer of the caller.
6008 memcpy(msg_tmp->msg_control, cm_data, cm_data_space);
6009 msg_tmp->msg_controllen = cm_data_space;
6012 #endif /* ! HAVE_STRUCT_MSGHDR_MSG_CONTROL */
6013 *msg_out = *msg_tmp;
6017 static ssize_t swrap_sendmsg_before(int fd,
6018 struct socket_info *si,
6020 struct iovec *tmp_iov,
6021 struct sockaddr_un *tmp_un,
6022 const struct sockaddr_un **to_un,
6023 const struct sockaddr **to,
6045 if (!si->connected) {
6050 if (msg->msg_iovlen == 0) {
6054 mtu = socket_wrapper_mtu();
6055 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6057 nlen = len + msg->msg_iov[i].iov_len;
6067 msg->msg_iovlen = i;
6068 if (msg->msg_iovlen == 0) {
6069 *tmp_iov = msg->msg_iov[0];
6070 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6072 msg->msg_iov = tmp_iov;
6073 msg->msg_iovlen = 1;
6078 if (si->connected) {
6079 if (msg->msg_name != NULL) {
6081 * We are dealing with unix sockets and if we
6082 * are connected, we should only talk to the
6083 * connected unix path. Using the fd to send
6084 * to another server would be hard to achieve.
6086 msg->msg_name = NULL;
6087 msg->msg_namelen = 0;
6090 const struct sockaddr *msg_name;
6091 msg_name = (const struct sockaddr *)msg->msg_name;
6093 if (msg_name == NULL) {
6099 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
6111 msg->msg_name = tmp_un;
6112 msg->msg_namelen = sizeof(*tmp_un);
6115 if (si->bound == 0) {
6116 ret = swrap_auto_bind(fd, si, si->family);
6118 SWRAP_UNLOCK_SI(si);
6119 if (errno == ENOTSOCK) {
6120 swrap_remove_stale(fd);
6123 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
6129 if (!si->defer_connect) {
6133 ret = sockaddr_convert_to_un(si,
6135 si->peername.sa_socklen,
6143 ret = libc_connect(fd,
6144 (struct sockaddr *)(void *)tmp_un,
6147 /* to give better errors */
6148 if (ret == -1 && errno == ENOENT) {
6149 errno = EHOSTUNREACH;
6156 si->defer_connect = 0;
6159 errno = EHOSTUNREACH;
6165 SWRAP_UNLOCK_SI(si);
6170 static void swrap_sendmsg_after(int fd,
6171 struct socket_info *si,
6173 const struct sockaddr *to,
6176 int saved_errno = errno;
6183 /* to give better errors */
6185 if (saved_errno == ENOENT) {
6186 saved_errno = EHOSTUNREACH;
6187 } else if (saved_errno == ENOTSOCK) {
6188 /* If the fd is not a socket, remove it */
6189 swrap_remove_stale(fd);
6193 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6194 avail += msg->msg_iov[i].iov_len;
6198 remain = MIN(80, avail);
6203 /* we capture it as one single packet */
6204 buf = (uint8_t *)malloc(remain);
6206 /* we just not capture the packet */
6207 errno = saved_errno;
6211 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6212 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6214 msg->msg_iov[i].iov_base,
6217 remain -= this_time;
6226 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6227 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
6229 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
6234 if (si->connected) {
6235 to = &si->peername.sa.s;
6238 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6239 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
6241 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6246 SWRAP_UNLOCK_SI(si);
6249 errno = saved_errno;
6252 static int swrap_recvmsg_before(int fd,
6253 struct socket_info *si,
6255 struct iovec *tmp_iov)
6262 (void)fd; /* unused */
6267 if (!si->connected) {
6272 if (msg->msg_iovlen == 0) {
6276 mtu = socket_wrapper_mtu();
6277 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6279 nlen = len + msg->msg_iov[i].iov_len;
6284 msg->msg_iovlen = i;
6285 if (msg->msg_iovlen == 0) {
6286 *tmp_iov = msg->msg_iov[0];
6287 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
6289 msg->msg_iov = tmp_iov;
6290 msg->msg_iovlen = 1;
6295 if (msg->msg_name == NULL) {
6300 if (msg->msg_iovlen == 0) {
6304 if (si->bound == 0) {
6305 ret = swrap_auto_bind(fd, si, si->family);
6307 SWRAP_UNLOCK_SI(si);
6309 * When attempting to read or write to a
6310 * descriptor, if an underlying autobind fails
6311 * because it's not a socket, stop intercepting
6312 * uses of that descriptor.
6314 if (errno == ENOTSOCK) {
6315 swrap_remove_stale(fd);
6318 SWRAP_LOG(SWRAP_LOG_ERROR,
6319 "swrap_recvmsg_before failed");
6326 errno = EHOSTUNREACH;
6332 SWRAP_UNLOCK_SI(si);
6337 static int swrap_recvmsg_after(int fd,
6338 struct socket_info *si,
6340 const struct sockaddr_un *un_addr,
6341 socklen_t un_addrlen,
6344 int saved_errno = errno;
6346 uint8_t *buf = NULL;
6352 /* to give better errors */
6354 if (saved_errno == ENOENT) {
6355 saved_errno = EHOSTUNREACH;
6356 } else if (saved_errno == ENOTSOCK) {
6357 /* If the fd is not a socket, remove it */
6358 swrap_remove_stale(fd);
6362 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6363 avail += msg->msg_iov[i].iov_len;
6368 /* Convert the socket address before we leave */
6369 if (si->type == SOCK_DGRAM && un_addr != NULL) {
6370 rc = sockaddr_convert_from_un(si,
6387 remain = MIN(80, avail);
6392 /* we capture it as one single packet */
6393 buf = (uint8_t *)malloc(remain);
6395 /* we just not capture the packet */
6396 SWRAP_UNLOCK_SI(si);
6397 errno = saved_errno;
6401 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
6402 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
6404 msg->msg_iov[i].iov_base,
6407 remain -= this_time;
6412 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
6413 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6414 } else if (ret == 0) { /* END OF FILE */
6415 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
6416 } else if (ret > 0) {
6417 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
6426 if (un_addr != NULL) {
6427 swrap_pcap_dump_packet(si,
6433 swrap_pcap_dump_packet(si,
6446 errno = saved_errno;
6448 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6450 msg->msg_controllen > 0 &&
6451 msg->msg_control != NULL) {
6452 rc = swrap_msghdr_add_socket_info(si, msg);
6454 SWRAP_UNLOCK_SI(si);
6460 SWRAP_UNLOCK_SI(si);
6464 /****************************************************************************
6466 ***************************************************************************/
6468 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
6469 struct sockaddr *from, socklen_t *fromlen)
6471 struct swrap_address from_addr = {
6472 .sa_socklen = sizeof(struct sockaddr_un),
6475 struct socket_info *si = find_socket_info(s);
6476 struct swrap_address saddr = {
6477 .sa_socklen = sizeof(struct sockaddr_storage),
6484 return libc_recvfrom(s,
6496 if (from != NULL && fromlen != NULL) {
6497 msg.msg_name = from; /* optional address */
6498 msg.msg_namelen = *fromlen; /* size of address */
6500 msg.msg_name = &saddr.sa.s; /* optional address */
6501 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6503 msg.msg_iov = &tmp; /* scatter/gather array */
6504 msg.msg_iovlen = 1; /* # elements in msg_iov */
6505 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6506 msg.msg_control = NULL; /* ancillary data, see below */
6507 msg.msg_controllen = 0; /* ancillary data buffer len */
6508 msg.msg_flags = 0; /* flags on received message */
6511 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6516 buf = msg.msg_iov[0].iov_base;
6517 len = msg.msg_iov[0].iov_len;
6519 ret = libc_recvfrom(s,
6524 &from_addr.sa_socklen);
6529 tret = swrap_recvmsg_after(s,
6533 from_addr.sa_socklen,
6539 if (from != NULL && fromlen != NULL) {
6540 *fromlen = msg.msg_namelen;
6546 #ifdef HAVE_ACCEPT_PSOCKLEN_T
6547 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6548 struct sockaddr *from, Psocklen_t fromlen)
6550 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
6551 struct sockaddr *from, socklen_t *fromlen)
6554 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
6557 /****************************************************************************
6559 ***************************************************************************/
6561 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
6562 const struct sockaddr *to, socklen_t tolen)
6566 struct swrap_address un_addr = {
6567 .sa_socklen = sizeof(struct sockaddr_un),
6569 const struct sockaddr_un *to_un = NULL;
6572 struct socket_info *si = find_socket_info(s);
6576 return libc_sendto(s, buf, len, flags, to, tolen);
6579 tmp.iov_base = discard_const_p(char, buf);
6583 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
6584 msg.msg_namelen = tolen; /* size of address */
6585 msg.msg_iov = &tmp; /* scatter/gather array */
6586 msg.msg_iovlen = 1; /* # elements in msg_iov */
6587 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6588 msg.msg_control = NULL; /* ancillary data, see below */
6589 msg.msg_controllen = 0; /* ancillary data buffer len */
6590 msg.msg_flags = 0; /* flags on received message */
6593 rc = swrap_sendmsg_before(s,
6605 buf = msg.msg_iov[0].iov_base;
6606 len = msg.msg_iov[0].iov_len;
6611 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
6613 char *swrap_dir = NULL;
6615 type = SOCKET_TYPE_CHAR_UDP;
6617 swrap_dir = socket_wrapper_dir();
6618 if (swrap_dir == NULL) {
6622 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
6623 swrap_un_path(&un_addr.sa.un,
6628 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
6630 /* ignore the any errors in broadcast sends */
6636 un_addr.sa_socklen);
6639 SAFE_FREE(swrap_dir);
6643 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
6645 SWRAP_UNLOCK_SI(si);
6652 * If it is a dgram socket and we are connected, don't include the
6655 if (si->type == SOCK_DGRAM && si->connected) {
6656 ret = libc_sendto(s,
6663 ret = libc_sendto(s,
6667 (struct sockaddr *)msg.msg_name,
6671 SWRAP_UNLOCK_SI(si);
6673 swrap_sendmsg_after(s, si, &msg, to, ret);
6678 ssize_t sendto(int s, const void *buf, size_t len, int flags,
6679 const struct sockaddr *to, socklen_t tolen)
6681 return swrap_sendto(s, buf, len, flags, to, tolen);
6684 /****************************************************************************
6686 ***************************************************************************/
6688 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
6690 struct socket_info *si;
6692 struct swrap_address saddr = {
6693 .sa_socklen = sizeof(struct sockaddr_storage),
6699 si = find_socket_info(s);
6701 return libc_recv(s, buf, len, flags);
6708 msg.msg_name = &saddr.sa.s; /* optional address */
6709 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6710 msg.msg_iov = &tmp; /* scatter/gather array */
6711 msg.msg_iovlen = 1; /* # elements in msg_iov */
6712 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6713 msg.msg_control = NULL; /* ancillary data, see below */
6714 msg.msg_controllen = 0; /* ancillary data buffer len */
6715 msg.msg_flags = 0; /* flags on received message */
6718 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6723 buf = msg.msg_iov[0].iov_base;
6724 len = msg.msg_iov[0].iov_len;
6726 ret = libc_recv(s, buf, len, flags);
6728 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6736 ssize_t recv(int s, void *buf, size_t len, int flags)
6738 return swrap_recv(s, buf, len, flags);
6741 /****************************************************************************
6743 ***************************************************************************/
6745 static ssize_t swrap_read(int s, void *buf, size_t len)
6747 struct socket_info *si;
6750 struct swrap_address saddr = {
6751 .sa_socklen = sizeof(struct sockaddr_storage),
6756 si = find_socket_info(s);
6758 return libc_read(s, buf, len);
6765 msg.msg_name = &saddr.sa.ss; /* optional address */
6766 msg.msg_namelen = saddr.sa_socklen; /* size of address */
6767 msg.msg_iov = &tmp; /* scatter/gather array */
6768 msg.msg_iovlen = 1; /* # elements in msg_iov */
6769 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6770 msg.msg_control = NULL; /* ancillary data, see below */
6771 msg.msg_controllen = 0; /* ancillary data buffer len */
6772 msg.msg_flags = 0; /* flags on received message */
6775 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
6777 if (tret == -ENOTSOCK) {
6778 return libc_read(s, buf, len);
6783 buf = msg.msg_iov[0].iov_base;
6784 len = msg.msg_iov[0].iov_len;
6786 ret = libc_read(s, buf, len);
6788 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
6796 ssize_t read(int s, void *buf, size_t len)
6798 return swrap_read(s, buf, len);
6801 /****************************************************************************
6803 ***************************************************************************/
6805 static ssize_t swrap_write(int s, const void *buf, size_t len)
6809 struct sockaddr_un un_addr;
6812 struct socket_info *si;
6814 si = find_socket_info(s);
6816 return libc_write(s, buf, len);
6819 tmp.iov_base = discard_const_p(char, buf);
6823 msg.msg_name = NULL; /* optional address */
6824 msg.msg_namelen = 0; /* size of address */
6825 msg.msg_iov = &tmp; /* scatter/gather array */
6826 msg.msg_iovlen = 1; /* # elements in msg_iov */
6827 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6828 msg.msg_control = NULL; /* ancillary data, see below */
6829 msg.msg_controllen = 0; /* ancillary data buffer len */
6830 msg.msg_flags = 0; /* flags on received message */
6833 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6838 buf = msg.msg_iov[0].iov_base;
6839 len = msg.msg_iov[0].iov_len;
6841 ret = libc_write(s, buf, len);
6843 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6848 ssize_t write(int s, const void *buf, size_t len)
6850 return swrap_write(s, buf, len);
6853 /****************************************************************************
6855 ***************************************************************************/
6857 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
6861 struct sockaddr_un un_addr;
6864 struct socket_info *si = find_socket_info(s);
6867 return libc_send(s, buf, len, flags);
6870 tmp.iov_base = discard_const_p(char, buf);
6874 msg.msg_name = NULL; /* optional address */
6875 msg.msg_namelen = 0; /* size of address */
6876 msg.msg_iov = &tmp; /* scatter/gather array */
6877 msg.msg_iovlen = 1; /* # elements in msg_iov */
6878 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6879 msg.msg_control = NULL; /* ancillary data, see below */
6880 msg.msg_controllen = 0; /* ancillary data buffer len */
6881 msg.msg_flags = 0; /* flags on received message */
6884 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
6889 buf = msg.msg_iov[0].iov_base;
6890 len = msg.msg_iov[0].iov_len;
6892 ret = libc_send(s, buf, len, flags);
6894 swrap_sendmsg_after(s, si, &msg, NULL, ret);
6899 ssize_t send(int s, const void *buf, size_t len, int flags)
6901 return swrap_send(s, buf, len, flags);
6904 /****************************************************************************
6906 ***************************************************************************/
6908 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
6910 struct swrap_address from_addr = {
6911 .sa_socklen = sizeof(struct sockaddr_un),
6913 struct swrap_address convert_addr = {
6914 .sa_socklen = sizeof(struct sockaddr_storage),
6916 struct socket_info *si;
6919 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6920 size_t msg_ctrllen_filled;
6921 size_t msg_ctrllen_left;
6927 si = find_socket_info(s);
6929 rc = swrap_recvmsg_before_unix(omsg, &msg);
6933 ret = libc_recvmsg(s, &msg, flags);
6934 return swrap_recvmsg_after_unix(&msg, omsg, ret);
6937 tmp.iov_base = NULL;
6941 msg.msg_name = &from_addr.sa; /* optional address */
6942 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
6943 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
6944 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
6945 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6946 msg_ctrllen_filled = 0;
6947 msg_ctrllen_left = omsg->msg_controllen;
6949 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
6950 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
6951 msg.msg_flags = omsg->msg_flags; /* flags on received message */
6954 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
6959 ret = libc_recvmsg(s, &msg, flags);
6961 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6962 msg_ctrllen_filled += msg.msg_controllen;
6963 msg_ctrllen_left -= msg.msg_controllen;
6965 if (omsg->msg_control != NULL) {
6968 p = omsg->msg_control;
6969 p += msg_ctrllen_filled;
6971 msg.msg_control = p;
6972 msg.msg_controllen = msg_ctrllen_left;
6974 msg.msg_control = NULL;
6975 msg.msg_controllen = 0;
6980 * We convert the unix address to a IP address so we need a buffer
6981 * which can store the address in case of SOCK_DGRAM, see below.
6983 msg.msg_name = &convert_addr.sa;
6984 msg.msg_namelen = convert_addr.sa_socklen;
6986 rc = swrap_recvmsg_after(s,
6990 from_addr.sa_socklen,
6996 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
6997 if (omsg->msg_control != NULL) {
6998 /* msg.msg_controllen = space left */
6999 msg_ctrllen_left = msg.msg_controllen;
7000 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
7003 /* Update the original message length */
7004 omsg->msg_controllen = msg_ctrllen_filled;
7005 omsg->msg_flags = msg.msg_flags;
7007 omsg->msg_iovlen = msg.msg_iovlen;
7014 * The msg_name field points to a caller-allocated buffer that is
7015 * used to return the source address if the socket is unconnected. The
7016 * caller should set msg_namelen to the size of this buffer before this
7017 * call; upon return from a successful call, msg_name will contain the
7018 * length of the returned address. If the application does not need
7019 * to know the source address, msg_name can be specified as NULL.
7021 if (si->type == SOCK_STREAM) {
7022 omsg->msg_namelen = 0;
7023 } else if (omsg->msg_name != NULL &&
7024 omsg->msg_namelen != 0 &&
7025 omsg->msg_namelen >= msg.msg_namelen) {
7026 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
7027 omsg->msg_namelen = msg.msg_namelen;
7030 SWRAP_UNLOCK_SI(si);
7035 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
7037 return swrap_recvmsg(sockfd, msg, flags);
7040 /****************************************************************************
7042 ***************************************************************************/
7044 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
7048 struct sockaddr_un un_addr;
7049 const struct sockaddr_un *to_un = NULL;
7050 const struct sockaddr *to = NULL;
7053 struct socket_info *si = find_socket_info(s);
7057 int scm_rights_pipe_fd = -1;
7059 rc = swrap_sendmsg_before_unix(omsg, &msg,
7060 &scm_rights_pipe_fd);
7064 ret = libc_sendmsg(s, &msg, flags);
7065 return swrap_sendmsg_after_unix(&msg, ret, scm_rights_pipe_fd);
7068 ZERO_STRUCT(un_addr);
7070 tmp.iov_base = NULL;
7077 if (si->connected == 0) {
7078 msg.msg_name = omsg->msg_name; /* optional address */
7079 msg.msg_namelen = omsg->msg_namelen; /* size of address */
7081 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
7082 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
7084 SWRAP_UNLOCK_SI(si);
7086 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7087 if (omsg != NULL && omsg->msg_controllen > 0 && omsg->msg_control != NULL) {
7088 uint8_t *cmbuf = NULL;
7091 rc = swrap_sendmsg_filter_cmsghdr(omsg, &cmbuf, &cmlen);
7097 msg.msg_controllen = 0;
7098 msg.msg_control = NULL;
7100 msg.msg_control = cmbuf;
7101 msg.msg_controllen = cmlen;
7104 msg.msg_flags = omsg->msg_flags; /* flags on received message */
7106 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
7108 int saved_errno = errno;
7109 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7110 SAFE_FREE(msg.msg_control);
7112 errno = saved_errno;
7119 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
7126 char *swrap_dir = NULL;
7128 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7129 avail += msg.msg_iov[i].iov_len;
7135 /* we capture it as one single packet */
7136 buf = (uint8_t *)malloc(remain);
7138 int saved_errno = errno;
7139 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7140 SAFE_FREE(msg.msg_control);
7142 errno = saved_errno;
7146 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
7147 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
7149 msg.msg_iov[i].iov_base,
7152 remain -= this_time;
7155 type = SOCKET_TYPE_CHAR_UDP;
7157 swrap_dir = socket_wrapper_dir();
7158 if (swrap_dir == NULL) {
7159 int saved_errno = errno;
7160 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7161 SAFE_FREE(msg.msg_control);
7164 errno = saved_errno;
7168 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
7169 swrap_un_path(&un_addr, swrap_dir, type, iface, prt);
7170 if (stat(un_addr.sun_path, &st) != 0) continue;
7172 msg.msg_name = &un_addr; /* optional address */
7173 msg.msg_namelen = sizeof(un_addr); /* size of address */
7175 /* ignore the any errors in broadcast sends */
7176 libc_sendmsg(s, &msg, flags);
7179 SAFE_FREE(swrap_dir);
7183 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
7186 SWRAP_UNLOCK_SI(si);
7191 ret = libc_sendmsg(s, &msg, flags);
7193 swrap_sendmsg_after(s, si, &msg, to, ret);
7195 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7197 int saved_errno = errno;
7198 SAFE_FREE(msg.msg_control);
7199 errno = saved_errno;
7206 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
7208 return swrap_sendmsg(s, omsg, flags);
7211 /****************************************************************************
7213 ***************************************************************************/
7215 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
7217 struct socket_info *si;
7220 struct swrap_address saddr = {
7221 .sa_socklen = sizeof(struct sockaddr_storage)
7226 si = find_socket_info(s);
7228 return libc_readv(s, vector, count);
7231 tmp.iov_base = NULL;
7235 msg.msg_name = &saddr.sa.s; /* optional address */
7236 msg.msg_namelen = saddr.sa_socklen; /* size of address */
7237 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7238 msg.msg_iovlen = count; /* # elements in msg_iov */
7239 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7240 msg.msg_control = NULL; /* ancillary data, see below */
7241 msg.msg_controllen = 0; /* ancillary data buffer len */
7242 msg.msg_flags = 0; /* flags on received message */
7245 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
7247 if (rc == -ENOTSOCK) {
7248 return libc_readv(s, vector, count);
7253 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
7255 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
7263 ssize_t readv(int s, const struct iovec *vector, int count)
7265 return swrap_readv(s, vector, count);
7268 /****************************************************************************
7270 ***************************************************************************/
7272 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
7276 struct sockaddr_un un_addr;
7279 struct socket_info *si = find_socket_info(s);
7282 return libc_writev(s, vector, count);
7285 tmp.iov_base = NULL;
7289 msg.msg_name = NULL; /* optional address */
7290 msg.msg_namelen = 0; /* size of address */
7291 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
7292 msg.msg_iovlen = count; /* # elements in msg_iov */
7293 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
7294 msg.msg_control = NULL; /* ancillary data, see below */
7295 msg.msg_controllen = 0; /* ancillary data buffer len */
7296 msg.msg_flags = 0; /* flags on received message */
7299 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
7301 if (rc == -ENOTSOCK) {
7302 return libc_readv(s, vector, count);
7307 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
7309 swrap_sendmsg_after(s, si, &msg, NULL, ret);
7314 ssize_t writev(int s, const struct iovec *vector, int count)
7316 return swrap_writev(s, vector, count);
7319 /****************************
7321 ***************************/
7323 static int swrap_close(int fd)
7325 struct socket_info *si = NULL;
7329 swrap_mutex_lock(&socket_reset_mutex);
7331 si_index = find_socket_info_index(fd);
7332 if (si_index == -1) {
7333 swrap_mutex_unlock(&socket_reset_mutex);
7334 return libc_close(fd);
7337 SWRAP_LOG(SWRAP_LOG_TRACE, "Close wrapper for fd=%d", fd);
7338 reset_socket_info_index(fd);
7340 si = swrap_get_socket_info(si_index);
7342 swrap_mutex_lock(&first_free_mutex);
7345 ret = libc_close(fd);
7347 swrap_dec_refcount(si);
7349 if (swrap_get_refcount(si) > 0) {
7350 /* there are still references left */
7354 if (si->fd_passed) {
7358 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7359 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
7362 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
7363 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
7364 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
7367 if (si->un_addr.sun_path[0] != '\0') {
7368 unlink(si->un_addr.sun_path);
7372 swrap_set_next_free(si, first_free);
7373 first_free = si_index;
7376 SWRAP_UNLOCK_SI(si);
7377 swrap_mutex_unlock(&first_free_mutex);
7378 swrap_mutex_unlock(&socket_reset_mutex);
7385 return swrap_close(fd);
7388 /****************************
7390 ***************************/
7392 static int swrap_dup(int fd)
7394 struct socket_info *si;
7397 idx = find_socket_info_index(fd);
7399 return libc_dup(fd);
7402 si = swrap_get_socket_info(idx);
7404 dup_fd = libc_dup(fd);
7406 int saved_errno = errno;
7407 errno = saved_errno;
7411 if ((size_t)dup_fd >= socket_fds_max) {
7412 SWRAP_LOG(SWRAP_LOG_ERROR,
7413 "The max socket index limit of %zu has been reached, "
7424 swrap_inc_refcount(si);
7426 SWRAP_UNLOCK_SI(si);
7428 /* Make sure we don't have an entry for the fd */
7429 swrap_remove_stale(dup_fd);
7431 set_socket_info_index(dup_fd, idx);
7438 return swrap_dup(fd);
7441 /****************************
7443 ***************************/
7445 static int swrap_dup2(int fd, int newfd)
7447 struct socket_info *si;
7450 idx = find_socket_info_index(fd);
7452 return libc_dup2(fd, newfd);
7455 si = swrap_get_socket_info(idx);
7459 * According to the manpage:
7461 * "If oldfd is a valid file descriptor, and newfd has the same
7462 * value as oldfd, then dup2() does nothing, and returns newfd."
7467 if ((size_t)newfd >= socket_fds_max) {
7468 SWRAP_LOG(SWRAP_LOG_ERROR,
7469 "The max socket index limit of %zu has been reached, "
7477 if (find_socket_info(newfd)) {
7478 /* dup2() does an implicit close of newfd, which we
7479 * need to emulate */
7483 dup_fd = libc_dup2(fd, newfd);
7485 int saved_errno = errno;
7486 errno = saved_errno;
7492 swrap_inc_refcount(si);
7494 SWRAP_UNLOCK_SI(si);
7496 /* Make sure we don't have an entry for the fd */
7497 swrap_remove_stale(dup_fd);
7499 set_socket_info_index(dup_fd, idx);
7504 int dup2(int fd, int newfd)
7506 return swrap_dup2(fd, newfd);
7509 /****************************
7511 ***************************/
7513 static int swrap_vfcntl(int fd, int cmd, va_list va)
7515 struct socket_info *si;
7516 int rc, dup_fd, idx;
7518 idx = find_socket_info_index(fd);
7520 return libc_vfcntl(fd, cmd, va);
7523 si = swrap_get_socket_info(idx);
7527 dup_fd = libc_vfcntl(fd, cmd, va);
7529 int saved_errno = errno;
7530 errno = saved_errno;
7534 /* Make sure we don't have an entry for the fd */
7535 swrap_remove_stale(dup_fd);
7537 if ((size_t)dup_fd >= socket_fds_max) {
7538 SWRAP_LOG(SWRAP_LOG_ERROR,
7539 "The max socket index limit of %zu has been reached, "
7550 swrap_inc_refcount(si);
7552 SWRAP_UNLOCK_SI(si);
7555 set_socket_info_index(dup_fd, idx);
7560 rc = libc_vfcntl(fd, cmd, va);
7567 int fcntl(int fd, int cmd, ...)
7574 rc = swrap_vfcntl(fd, cmd, va);
7581 /****************************
7583 ***************************/
7586 static int swrap_eventfd(int count, int flags)
7590 fd = libc_eventfd(count, flags);
7592 swrap_remove_stale(fd);
7598 #ifdef HAVE_EVENTFD_UNSIGNED_INT
7599 int eventfd(unsigned int count, int flags)
7601 int eventfd(int count, int flags)
7604 return swrap_eventfd(count, flags);
7609 int pledge(const char *promises, const char *paths[])
7611 (void)promises; /* unused */
7612 (void)paths; /* unused */
7616 #endif /* HAVE_PLEDGE */
7618 static void swrap_thread_prepare(void)
7621 * This function should only be called here!!
7623 * We bind all symobls to avoid deadlocks of the fork is
7624 * interrupted by a signal handler using a symbol of this
7627 swrap_bind_symbol_all();
7632 static void swrap_thread_parent(void)
7637 static void swrap_thread_child(void)
7642 /****************************
7644 ***************************/
7645 void swrap_constructor(void)
7647 if (PIPE_BUF < sizeof(struct swrap_unix_scm_rights)) {
7648 SWRAP_LOG(SWRAP_LOG_ERROR,
7650 "sizeof(struct swrap_unix_scm_rights)=%zu\n"
7651 "sizeof(struct swrap_unix_scm_rights_payload)=%zu "
7652 "sizeof(struct socket_info)=%zu",
7654 sizeof(struct swrap_unix_scm_rights),
7655 sizeof(struct swrap_unix_scm_rights_payload),
7656 sizeof(struct socket_info));
7663 * If we hold a lock and the application forks, then the child
7664 * is not able to unlock the mutex and we are in a deadlock.
7665 * This should prevent such deadlocks.
7667 pthread_atfork(&swrap_thread_prepare,
7668 &swrap_thread_parent,
7669 &swrap_thread_child);
7672 /****************************
7674 ***************************/
7677 * This function is called when the library is unloaded and makes sure that
7678 * sockets get closed and the unix file for the socket are unlinked.
7680 void swrap_destructor(void)
7684 if (socket_fds_idx != NULL) {
7685 for (i = 0; i < socket_fds_max; ++i) {
7686 if (socket_fds_idx[i] != -1) {
7690 SAFE_FREE(socket_fds_idx);
7695 if (swrap.libc.handle != NULL) {
7696 dlclose(swrap.libc.handle);
7698 if (swrap.libc.socket_handle) {
7699 dlclose(swrap.libc.socket_handle);
7703 #if defined(HAVE__SOCKET) && defined(HAVE__CLOSE)
7705 * On FreeBSD 12 (and maybe other platforms)
7706 * system libraries like libresolv prefix there
7707 * syscalls with '_' in order to always use
7708 * the symbols from libc.
7710 * In the interaction with resolv_wrapper,
7711 * we need to inject socket wrapper into libresolv,
7712 * which means we need to private all socket
7713 * related syscalls also with the '_' prefix.
7715 * This is tested in Samba's 'make test',
7716 * there we noticed that providing '_read'
7717 * and '_open' would cause errors, which
7718 * means we skip '_read', '_write' and
7719 * all non socket related calls without
7720 * further analyzing the problem.
7722 #define SWRAP_SYMBOL_ALIAS(__sym, __aliassym) \
7723 extern typeof(__sym) __aliassym __attribute__ ((alias(#__sym)))
7726 SWRAP_SYMBOL_ALIAS(accept4, _accept4);
7728 SWRAP_SYMBOL_ALIAS(accept, _accept);
7729 SWRAP_SYMBOL_ALIAS(bind, _bind);
7730 SWRAP_SYMBOL_ALIAS(close, _close);
7731 SWRAP_SYMBOL_ALIAS(connect, _connect);
7732 SWRAP_SYMBOL_ALIAS(dup, _dup);
7733 SWRAP_SYMBOL_ALIAS(dup2, _dup2);
7734 SWRAP_SYMBOL_ALIAS(fcntl, _fcntl);
7735 SWRAP_SYMBOL_ALIAS(getpeername, _getpeername);
7736 SWRAP_SYMBOL_ALIAS(getsockname, _getsockname);
7737 SWRAP_SYMBOL_ALIAS(getsockopt, _getsockopt);
7738 SWRAP_SYMBOL_ALIAS(ioctl, _ioctl);
7739 SWRAP_SYMBOL_ALIAS(listen, _listen);
7740 SWRAP_SYMBOL_ALIAS(readv, _readv);
7741 SWRAP_SYMBOL_ALIAS(recv, _recv);
7742 SWRAP_SYMBOL_ALIAS(recvfrom, _recvfrom);
7743 SWRAP_SYMBOL_ALIAS(recvmsg, _recvmsg);
7744 SWRAP_SYMBOL_ALIAS(send, _send);
7745 SWRAP_SYMBOL_ALIAS(sendmsg, _sendmsg);
7746 SWRAP_SYMBOL_ALIAS(sendto, _sendto);
7747 SWRAP_SYMBOL_ALIAS(setsockopt, _setsockopt);
7748 SWRAP_SYMBOL_ALIAS(socket, _socket);
7749 SWRAP_SYMBOL_ALIAS(socketpair, _socketpair);
7750 SWRAP_SYMBOL_ALIAS(writev, _writev);
7752 #endif /* SOCKET_WRAPPER_EXPORT_UNDERSCORE_SYMBOLS */