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 #include <arpa/inet.h>
78 #ifdef HAVE_GNU_LIB_NAMES_H
79 #include <gnu/lib-names.h>
93 /* GCC have printf type attribute check. */
94 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
95 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
97 #define PRINTF_ATTRIBUTE(a,b)
98 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
100 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
101 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
103 #define CONSTRUCTOR_ATTRIBUTE
104 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
106 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
107 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
109 #define DESTRUCTOR_ATTRIBUTE
113 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
114 # define FALL_THROUGH __attribute__ ((fallthrough))
115 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
116 # define FALL_THROUGH ((void)0)
117 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
118 #endif /* FALL_THROUGH */
120 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
121 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
123 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
126 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
127 # define SWRAP_THREAD __thread
129 # define SWRAP_THREAD
133 #define MIN(a,b) ((a)<(b)?(a):(b))
137 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
141 #define ZERO_STRUCTP(x) do { \
143 memset((char *)(x), 0, sizeof(*(x))); \
148 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
151 #ifndef discard_const
152 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
155 #ifndef discard_const_p
156 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
159 #define UNUSED(x) (void)(x)
162 # ifndef IPV6_RECVPKTINFO
163 # define IPV6_RECVPKTINFO IPV6_PKTINFO
164 # endif /* IPV6_RECVPKTINFO */
165 #endif /* IPV6_PKTINFO */
168 * On BSD IP_PKTINFO has a different name because during
169 * the time when they implemented it, there was no RFC.
170 * The name for IPv6 is the same as on Linux.
173 # ifdef IP_RECVDSTADDR
174 # define IP_PKTINFO IP_RECVDSTADDR
178 /* Add new global locks here please */
179 # define SWRAP_LOCK_ALL \
180 swrap_mutex_lock(&libc_symbol_binding_mutex); \
182 # define SWRAP_UNLOCK_ALL \
183 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
185 #define SOCKET_INFO_CONTAINER(si) \
186 (struct socket_info_container *)(si)
188 #define SWRAP_LOCK_SI(si) do { \
189 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
190 swrap_mutex_lock(&sic->meta.mutex); \
193 #define SWRAP_UNLOCK_SI(si) do { \
194 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si); \
195 swrap_mutex_unlock(&sic->meta.mutex); \
198 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
199 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
201 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
204 /* we need to use a very terse format here as IRIX 6.4 silently
205 truncates names to 16 chars, so if we use a longer name then we
206 can't tell which port a packet came from with recvfrom()
208 with this format we have 8 chars left for the directory name
210 #define SOCKET_FORMAT "%c%02X%04X"
211 #define SOCKET_TYPE_CHAR_TCP 'T'
212 #define SOCKET_TYPE_CHAR_UDP 'U'
213 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
214 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
217 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
218 * format PCAP capture files (as the caller will simply continue from here).
220 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
221 #define SOCKET_WRAPPER_MTU_MIN 512
222 #define SOCKET_WRAPPER_MTU_MAX 32768
224 #define SOCKET_MAX_SOCKETS 1024
227 * Maximum number of socket_info structures that can
228 * be used. Can be overriden by the environment variable
229 * SOCKET_WRAPPER_MAX_SOCKETS.
231 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
233 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 262140
235 /* This limit is to avoid broadcast sendto() needing to stat too many
236 * files. It may be raised (with a performance cost) to up to 254
237 * without changing the format above */
238 #define MAX_WRAPPED_INTERFACES 64
240 struct swrap_address {
241 socklen_t sa_socklen;
244 struct sockaddr_in in;
246 struct sockaddr_in6 in6;
248 struct sockaddr_un un;
249 struct sockaddr_storage ss;
268 /* The unix path so we can unlink it on close() */
269 struct sockaddr_un un_addr;
271 struct swrap_address bindname;
272 struct swrap_address myname;
273 struct swrap_address peername;
276 unsigned long pck_snd;
277 unsigned long pck_rcv;
281 struct socket_info_meta
283 unsigned int refcount;
285 pthread_mutex_t mutex;
288 struct socket_info_container
290 struct socket_info info;
291 struct socket_info_meta meta;
294 static struct socket_info_container *sockets;
296 static size_t socket_info_max = 0;
299 * Allocate the socket array always on the limit value. We want it to be
300 * at least bigger than the default so if we reach the limit we can
301 * still deal with duplicate fds pointing to the same socket_info.
303 static size_t socket_fds_max = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
305 /* Hash table to map fds to corresponding socket_info index */
306 static int *socket_fds_idx;
308 /* Mutex to synchronize access to global libc.symbols */
309 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
311 /* Mutex for syncronizing port selection during swrap_auto_bind() */
312 static pthread_mutex_t autobind_start_mutex;
314 /* Mutex to guard the initialization of array of socket_info structures */
315 static pthread_mutex_t sockets_mutex;
317 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
318 static pthread_mutex_t socket_reset_mutex;
320 /* Mutex to synchronize access to first free index in socket_info array */
321 static pthread_mutex_t first_free_mutex;
323 /* Mutex to synchronize access to packet capture dump file */
324 static pthread_mutex_t pcap_dump_mutex;
326 /* Mutex for synchronizing mtu value fetch*/
327 static pthread_mutex_t mtu_update_mutex;
329 /* Function prototypes */
331 bool socket_wrapper_enabled(void);
333 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
334 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
336 #ifndef HAVE_GETPROGNAME
337 static const char *getprogname(void)
339 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
340 return program_invocation_short_name;
341 #elif defined(HAVE_GETEXECNAME)
342 return getexecname();
345 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
347 #endif /* HAVE_GETPROGNAME */
349 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
350 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
352 static void swrap_log(enum swrap_dbglvl_e dbglvl,
354 const char *format, ...)
359 unsigned int lvl = 0;
360 const char *prefix = "SWRAP";
361 const char *progname = getprogname();
363 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
372 va_start(va, format);
373 vsnprintf(buffer, sizeof(buffer), format, va);
377 case SWRAP_LOG_ERROR:
378 prefix = "SWRAP_ERROR";
381 prefix = "SWRAP_WARN";
383 case SWRAP_LOG_DEBUG:
384 prefix = "SWRAP_DEBUG";
386 case SWRAP_LOG_TRACE:
387 prefix = "SWRAP_TRACE";
391 if (progname == NULL) {
392 progname = "<unknown>";
396 "%s[%s (%u)] - %s: %s\n",
399 (unsigned int)getpid(),
404 /*********************************************************
405 * SWRAP LOADING LIBC FUNCTIONS
406 *********************************************************/
411 typedef int (*__libc_accept4)(int sockfd,
412 struct sockaddr *addr,
416 typedef int (*__libc_accept)(int sockfd,
417 struct sockaddr *addr,
420 typedef int (*__libc_bind)(int sockfd,
421 const struct sockaddr *addr,
423 typedef int (*__libc_close)(int fd);
424 typedef int (*__libc_connect)(int sockfd,
425 const struct sockaddr *addr,
427 typedef int (*__libc_dup)(int fd);
428 typedef int (*__libc_dup2)(int oldfd, int newfd);
429 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
430 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
432 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
435 typedef int (*__libc_eventfd)(int count, int flags);
437 typedef int (*__libc_getpeername)(int sockfd,
438 struct sockaddr *addr,
440 typedef int (*__libc_getsockname)(int sockfd,
441 struct sockaddr *addr,
443 typedef int (*__libc_getsockopt)(int sockfd,
448 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
449 typedef int (*__libc_listen)(int sockfd, int backlog);
450 typedef int (*__libc_open)(const char *pathname, int flags, ...);
452 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
453 #endif /* HAVE_OPEN64 */
454 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
455 typedef int (*__libc_pipe)(int pipefd[2]);
456 typedef int (*__libc_read)(int fd, void *buf, size_t count);
457 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
458 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
459 typedef int (*__libc_recvfrom)(int sockfd,
463 struct sockaddr *src_addr,
465 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
466 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
467 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
468 typedef int (*__libc_sendto)(int sockfd,
472 const struct sockaddr *dst_addr,
474 typedef int (*__libc_setsockopt)(int sockfd,
480 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
482 typedef int (*__libc_socket)(int domain, int type, int protocol);
483 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
484 #ifdef HAVE_TIMERFD_CREATE
485 typedef int (*__libc_timerfd_create)(int clockid, int flags);
487 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
488 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
490 #define SWRAP_SYMBOL_ENTRY(i) \
496 struct swrap_libc_symbols {
498 SWRAP_SYMBOL_ENTRY(accept4);
500 SWRAP_SYMBOL_ENTRY(accept);
502 SWRAP_SYMBOL_ENTRY(bind);
503 SWRAP_SYMBOL_ENTRY(close);
504 SWRAP_SYMBOL_ENTRY(connect);
505 SWRAP_SYMBOL_ENTRY(dup);
506 SWRAP_SYMBOL_ENTRY(dup2);
507 SWRAP_SYMBOL_ENTRY(fcntl);
508 SWRAP_SYMBOL_ENTRY(fopen);
510 SWRAP_SYMBOL_ENTRY(fopen64);
513 SWRAP_SYMBOL_ENTRY(eventfd);
515 SWRAP_SYMBOL_ENTRY(getpeername);
516 SWRAP_SYMBOL_ENTRY(getsockname);
517 SWRAP_SYMBOL_ENTRY(getsockopt);
518 SWRAP_SYMBOL_ENTRY(ioctl);
519 SWRAP_SYMBOL_ENTRY(listen);
520 SWRAP_SYMBOL_ENTRY(open);
522 SWRAP_SYMBOL_ENTRY(open64);
524 SWRAP_SYMBOL_ENTRY(openat);
525 SWRAP_SYMBOL_ENTRY(pipe);
526 SWRAP_SYMBOL_ENTRY(read);
527 SWRAP_SYMBOL_ENTRY(readv);
528 SWRAP_SYMBOL_ENTRY(recv);
529 SWRAP_SYMBOL_ENTRY(recvfrom);
530 SWRAP_SYMBOL_ENTRY(recvmsg);
531 SWRAP_SYMBOL_ENTRY(send);
532 SWRAP_SYMBOL_ENTRY(sendmsg);
533 SWRAP_SYMBOL_ENTRY(sendto);
534 SWRAP_SYMBOL_ENTRY(setsockopt);
536 SWRAP_SYMBOL_ENTRY(signalfd);
538 SWRAP_SYMBOL_ENTRY(socket);
539 SWRAP_SYMBOL_ENTRY(socketpair);
540 #ifdef HAVE_TIMERFD_CREATE
541 SWRAP_SYMBOL_ENTRY(timerfd_create);
543 SWRAP_SYMBOL_ENTRY(write);
544 SWRAP_SYMBOL_ENTRY(writev);
551 struct swrap_libc_symbols symbols;
555 static struct swrap swrap;
558 static const char *socket_wrapper_dir(void);
560 #define LIBC_NAME "libc.so"
568 static const char *swrap_str_lib(enum swrap_lib lib)
575 case SWRAP_LIBSOCKET:
579 /* Compiler would warn us about unhandled enum value if we get here */
583 static void *swrap_load_lib_handle(enum swrap_lib lib)
585 int flags = RTLD_LAZY;
590 const char *env = getenv("LD_PRELOAD");
592 /* Don't do a deepbind if we run with libasan */
593 if (env != NULL && strlen(env) < 1024) {
594 const char *p = strstr(env, "libasan.so");
596 flags |= RTLD_DEEPBIND;
604 case SWRAP_LIBSOCKET:
605 #ifdef HAVE_LIBSOCKET
606 handle = swrap.libc.socket_handle;
607 if (handle == NULL) {
608 for (i = 10; i >= 0; i--) {
609 char soname[256] = {0};
611 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
612 handle = dlopen(soname, flags);
613 if (handle != NULL) {
618 swrap.libc.socket_handle = handle;
624 handle = swrap.libc.handle;
626 if (handle == NULL) {
627 handle = dlopen(LIBC_SO, flags);
629 swrap.libc.handle = handle;
632 if (handle == NULL) {
633 for (i = 10; i >= 0; i--) {
634 char soname[256] = {0};
636 snprintf(soname, sizeof(soname), "libc.so.%d", i);
637 handle = dlopen(soname, flags);
638 if (handle != NULL) {
643 swrap.libc.handle = handle;
648 if (handle == NULL) {
650 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
652 SWRAP_LOG(SWRAP_LOG_ERROR,
653 "Failed to dlopen library: %s\n",
662 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
667 handle = swrap_load_lib_handle(lib);
669 func = dlsym(handle, fn_name);
671 SWRAP_LOG(SWRAP_LOG_ERROR,
672 "Failed to find %s: %s\n",
678 SWRAP_LOG(SWRAP_LOG_TRACE,
686 static void swrap_mutex_lock(pthread_mutex_t *mutex)
690 ret = pthread_mutex_lock(mutex);
692 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
697 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
701 ret = pthread_mutex_unlock(mutex);
703 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
709 * These macros have a thread race condition on purpose!
711 * This is an optimization to avoid locking each time we check if the symbol is
714 #define swrap_bind_symbol_libc(sym_name) \
715 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
716 swrap_mutex_lock(&libc_symbol_binding_mutex); \
717 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
718 swrap.libc.symbols._libc_##sym_name.obj = \
719 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
721 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
724 #define swrap_bind_symbol_libsocket(sym_name) \
725 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
726 swrap_mutex_lock(&libc_symbol_binding_mutex); \
727 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
728 swrap.libc.symbols._libc_##sym_name.obj = \
729 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
731 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
734 #define swrap_bind_symbol_libnsl(sym_name) \
735 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
736 swrap_mutex_lock(&libc_symbol_binding_mutex); \
737 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
738 swrap.libc.symbols._libc_##sym_name.obj = \
739 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
741 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
744 /****************************************************************************
746 ****************************************************************************
748 * Functions especially from libc need to be loaded individually, you can't
749 * load all at once or gdb will segfault at startup. The same applies to
750 * valgrind and has probably something todo with with the linker. So we need
751 * load each function at the point it is called the first time.
753 ****************************************************************************/
756 static int libc_accept4(int sockfd,
757 struct sockaddr *addr,
761 swrap_bind_symbol_libsocket(accept4);
763 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
766 #else /* HAVE_ACCEPT4 */
768 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
770 swrap_bind_symbol_libsocket(accept);
772 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
774 #endif /* HAVE_ACCEPT4 */
776 static int libc_bind(int sockfd,
777 const struct sockaddr *addr,
780 swrap_bind_symbol_libsocket(bind);
782 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
785 static int libc_close(int fd)
787 swrap_bind_symbol_libc(close);
789 return swrap.libc.symbols._libc_close.f(fd);
792 static int libc_connect(int sockfd,
793 const struct sockaddr *addr,
796 swrap_bind_symbol_libsocket(connect);
798 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
801 static int libc_dup(int fd)
803 swrap_bind_symbol_libc(dup);
805 return swrap.libc.symbols._libc_dup.f(fd);
808 static int libc_dup2(int oldfd, int newfd)
810 swrap_bind_symbol_libc(dup2);
812 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
816 static int libc_eventfd(int count, int flags)
818 swrap_bind_symbol_libc(eventfd);
820 return swrap.libc.symbols._libc_eventfd.f(count, flags);
824 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
825 static int libc_vfcntl(int fd, int cmd, va_list ap)
830 swrap_bind_symbol_libc(fcntl);
832 arg = va_arg(ap, void *);
834 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
839 static int libc_getpeername(int sockfd,
840 struct sockaddr *addr,
843 swrap_bind_symbol_libsocket(getpeername);
845 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
848 static int libc_getsockname(int sockfd,
849 struct sockaddr *addr,
852 swrap_bind_symbol_libsocket(getsockname);
854 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
857 static int libc_getsockopt(int sockfd,
863 swrap_bind_symbol_libsocket(getsockopt);
865 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
872 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
873 static int libc_vioctl(int d, unsigned long int request, va_list ap)
878 swrap_bind_symbol_libc(ioctl);
880 arg = va_arg(ap, void *);
882 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
887 static int libc_listen(int sockfd, int backlog)
889 swrap_bind_symbol_libsocket(listen);
891 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
894 static FILE *libc_fopen(const char *name, const char *mode)
896 swrap_bind_symbol_libc(fopen);
898 return swrap.libc.symbols._libc_fopen.f(name, mode);
902 static FILE *libc_fopen64(const char *name, const char *mode)
904 swrap_bind_symbol_libc(fopen64);
906 return swrap.libc.symbols._libc_fopen64.f(name, mode);
908 #endif /* HAVE_FOPEN64 */
910 static int libc_vopen(const char *pathname, int flags, va_list ap)
915 swrap_bind_symbol_libc(open);
917 if (flags & O_CREAT) {
918 mode = va_arg(ap, int);
920 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
925 static int libc_open(const char *pathname, int flags, ...)
931 fd = libc_vopen(pathname, flags, ap);
938 static int libc_vopen64(const char *pathname, int flags, va_list ap)
943 swrap_bind_symbol_libc(open64);
945 if (flags & O_CREAT) {
946 mode = va_arg(ap, int);
948 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
952 #endif /* HAVE_OPEN64 */
954 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
959 swrap_bind_symbol_libc(openat);
961 if (flags & O_CREAT) {
962 mode = va_arg(ap, int);
964 fd = swrap.libc.symbols._libc_openat.f(dirfd,
973 static int libc_openat(int dirfd, const char *path, int flags, ...)
979 fd = libc_vopenat(dirfd, path, flags, ap);
986 static int libc_pipe(int pipefd[2])
988 swrap_bind_symbol_libsocket(pipe);
990 return swrap.libc.symbols._libc_pipe.f(pipefd);
993 static int libc_read(int fd, void *buf, size_t count)
995 swrap_bind_symbol_libc(read);
997 return swrap.libc.symbols._libc_read.f(fd, buf, count);
1000 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
1002 swrap_bind_symbol_libsocket(readv);
1004 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
1007 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
1009 swrap_bind_symbol_libsocket(recv);
1011 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
1014 static int libc_recvfrom(int sockfd,
1018 struct sockaddr *src_addr,
1021 swrap_bind_symbol_libsocket(recvfrom);
1023 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
1031 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
1033 swrap_bind_symbol_libsocket(recvmsg);
1035 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1038 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1040 swrap_bind_symbol_libsocket(send);
1042 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1045 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1047 swrap_bind_symbol_libsocket(sendmsg);
1049 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1052 static int libc_sendto(int sockfd,
1056 const struct sockaddr *dst_addr,
1059 swrap_bind_symbol_libsocket(sendto);
1061 return swrap.libc.symbols._libc_sendto.f(sockfd,
1069 static int libc_setsockopt(int sockfd,
1075 swrap_bind_symbol_libsocket(setsockopt);
1077 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1084 #ifdef HAVE_SIGNALFD
1085 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1087 swrap_bind_symbol_libsocket(signalfd);
1089 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1093 static int libc_socket(int domain, int type, int protocol)
1095 swrap_bind_symbol_libsocket(socket);
1097 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1100 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1102 swrap_bind_symbol_libsocket(socketpair);
1104 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1107 #ifdef HAVE_TIMERFD_CREATE
1108 static int libc_timerfd_create(int clockid, int flags)
1110 swrap_bind_symbol_libc(timerfd_create);
1112 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1116 static ssize_t libc_write(int fd, const void *buf, size_t count)
1118 swrap_bind_symbol_libc(write);
1120 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1123 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1125 swrap_bind_symbol_libsocket(writev);
1127 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1130 /* DO NOT call this function during library initialization! */
1131 static void swrap_bind_symbol_all(void)
1134 swrap_bind_symbol_libsocket(accept4);
1136 swrap_bind_symbol_libsocket(accept);
1138 swrap_bind_symbol_libsocket(bind);
1139 swrap_bind_symbol_libc(close);
1140 swrap_bind_symbol_libsocket(connect);
1141 swrap_bind_symbol_libc(dup);
1142 swrap_bind_symbol_libc(dup2);
1143 swrap_bind_symbol_libc(fcntl);
1144 swrap_bind_symbol_libc(fopen);
1146 swrap_bind_symbol_libc(fopen64);
1149 swrap_bind_symbol_libc(eventfd);
1151 swrap_bind_symbol_libsocket(getpeername);
1152 swrap_bind_symbol_libsocket(getsockname);
1153 swrap_bind_symbol_libsocket(getsockopt);
1154 swrap_bind_symbol_libc(ioctl);
1155 swrap_bind_symbol_libsocket(listen);
1156 swrap_bind_symbol_libc(open);
1158 swrap_bind_symbol_libc(open64);
1160 swrap_bind_symbol_libc(openat);
1161 swrap_bind_symbol_libsocket(pipe);
1162 swrap_bind_symbol_libc(read);
1163 swrap_bind_symbol_libsocket(readv);
1164 swrap_bind_symbol_libsocket(recv);
1165 swrap_bind_symbol_libsocket(recvfrom);
1166 swrap_bind_symbol_libsocket(recvmsg);
1167 swrap_bind_symbol_libsocket(send);
1168 swrap_bind_symbol_libsocket(sendmsg);
1169 swrap_bind_symbol_libsocket(sendto);
1170 swrap_bind_symbol_libsocket(setsockopt);
1171 #ifdef HAVE_SIGNALFD
1172 swrap_bind_symbol_libsocket(signalfd);
1174 swrap_bind_symbol_libsocket(socket);
1175 swrap_bind_symbol_libsocket(socketpair);
1176 #ifdef HAVE_TIMERFD_CREATE
1177 swrap_bind_symbol_libc(timerfd_create);
1179 swrap_bind_symbol_libc(write);
1180 swrap_bind_symbol_libsocket(writev);
1183 /*********************************************************
1184 * SWRAP HELPER FUNCTIONS
1185 *********************************************************/
1191 static const struct in6_addr *swrap_ipv6(void)
1193 static struct in6_addr v;
1194 static int initialized;
1202 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1211 static void set_port(int family, int prt, struct swrap_address *addr)
1215 addr->sa.in.sin_port = htons(prt);
1219 addr->sa.in6.sin6_port = htons(prt);
1225 static size_t socket_length(int family)
1229 return sizeof(struct sockaddr_in);
1232 return sizeof(struct sockaddr_in6);
1238 static struct socket_info *swrap_get_socket_info(int si_index)
1240 return (struct socket_info *)(&(sockets[si_index].info));
1243 static int swrap_get_refcount(struct socket_info *si)
1245 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1246 return sic->meta.refcount;
1249 static void swrap_inc_refcount(struct socket_info *si)
1251 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1253 sic->meta.refcount += 1;
1256 static void swrap_dec_refcount(struct socket_info *si)
1258 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1260 sic->meta.refcount -= 1;
1263 static int swrap_get_next_free(struct socket_info *si)
1265 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1267 return sic->meta.next_free;
1270 static void swrap_set_next_free(struct socket_info *si, int next_free)
1272 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1274 sic->meta.next_free = next_free;
1277 static const char *socket_wrapper_dir(void)
1279 const char *s = getenv("SOCKET_WRAPPER_DIR");
1283 /* TODO use realpath(3) here, when we add support for threads */
1284 if (strncmp(s, "./", 2) == 0) {
1288 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1292 static unsigned int socket_wrapper_mtu(void)
1294 static unsigned int max_mtu = 0;
1299 swrap_mutex_lock(&mtu_update_mutex);
1305 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1307 s = getenv("SOCKET_WRAPPER_MTU");
1312 tmp = strtol(s, &endp, 10);
1317 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1323 swrap_mutex_unlock(&mtu_update_mutex);
1327 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1329 pthread_mutexattr_t ma;
1332 ret = pthread_mutexattr_init(&ma);
1337 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1342 ret = pthread_mutex_init(m, &ma);
1345 pthread_mutexattr_destroy(&ma);
1350 static size_t socket_wrapper_max_sockets(void)
1356 if (socket_info_max != 0) {
1357 return socket_info_max;
1360 socket_info_max = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1362 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1363 if (s == NULL || s[0] == '\0') {
1367 tmp = strtoul(s, &endp, 10);
1372 tmp = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1373 SWRAP_LOG(SWRAP_LOG_ERROR,
1374 "Invalid number of sockets specified, "
1375 "using default (%zu)",
1379 if (tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1380 tmp = SOCKET_WRAPPER_MAX_SOCKETS_LIMIT;
1381 SWRAP_LOG(SWRAP_LOG_ERROR,
1382 "Invalid number of sockets specified, "
1383 "using maximum (%zu).",
1387 socket_info_max = tmp;
1390 return socket_info_max;
1393 static void socket_wrapper_init_fds_idx(void)
1398 if (socket_fds_idx != NULL) {
1402 tmp = (int *)calloc(socket_fds_max, sizeof(int));
1404 SWRAP_LOG(SWRAP_LOG_ERROR,
1405 "Failed to allocate socket fds index array: %s",
1410 for (i = 0; i < socket_fds_max; i++) {
1414 socket_fds_idx = tmp;
1417 static void socket_wrapper_init_sockets(void)
1423 swrap_mutex_lock(&sockets_mutex);
1425 if (sockets != NULL) {
1426 swrap_mutex_unlock(&sockets_mutex);
1430 socket_wrapper_init_fds_idx();
1432 /* Needs to be called inside the sockets_mutex lock here. */
1433 max_sockets = socket_wrapper_max_sockets();
1435 sockets = (struct socket_info_container *)calloc(max_sockets,
1436 sizeof(struct socket_info_container));
1438 if (sockets == NULL) {
1439 SWRAP_LOG(SWRAP_LOG_ERROR,
1440 "Failed to allocate sockets array: %s",
1442 swrap_mutex_unlock(&sockets_mutex);
1446 swrap_mutex_lock(&first_free_mutex);
1450 for (i = 0; i < max_sockets; i++) {
1451 swrap_set_next_free(&sockets[i].info, i+1);
1452 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1454 SWRAP_LOG(SWRAP_LOG_ERROR,
1455 "Failed to initialize pthread mutex");
1460 /* mark the end of the free list */
1461 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1463 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1465 SWRAP_LOG(SWRAP_LOG_ERROR,
1466 "Failed to initialize pthread mutex");
1470 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1472 SWRAP_LOG(SWRAP_LOG_ERROR,
1473 "Failed to initialize pthread mutex");
1477 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1479 SWRAP_LOG(SWRAP_LOG_ERROR,
1480 "Failed to initialize pthread mutex");
1485 swrap_mutex_unlock(&first_free_mutex);
1486 swrap_mutex_unlock(&sockets_mutex);
1492 bool socket_wrapper_enabled(void)
1494 const char *s = socket_wrapper_dir();
1500 socket_wrapper_init_sockets();
1505 static unsigned int socket_wrapper_default_iface(void)
1507 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1510 if (sscanf(s, "%u", &iface) == 1) {
1511 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1517 return 1;/* 127.0.0.1 */
1520 static void set_socket_info_index(int fd, int idx)
1522 socket_fds_idx[fd] = idx;
1523 /* This builtin issues a full memory barrier. */
1524 __sync_synchronize();
1527 static void reset_socket_info_index(int fd)
1529 set_socket_info_index(fd, -1);
1532 static int find_socket_info_index(int fd)
1538 if (socket_fds_idx == NULL) {
1542 if ((size_t)fd >= socket_fds_max) {
1543 SWRAP_LOG(SWRAP_LOG_ERROR,
1544 "The max socket index limit of %zu has been reached, "
1551 /* This builtin issues a full memory barrier. */
1552 __sync_synchronize();
1553 return socket_fds_idx[fd];
1556 static int swrap_add_socket_info(struct socket_info *si_input)
1558 struct socket_info *si = NULL;
1561 if (si_input == NULL) {
1566 swrap_mutex_lock(&first_free_mutex);
1567 if (first_free == -1) {
1572 si_index = first_free;
1573 si = swrap_get_socket_info(si_index);
1577 first_free = swrap_get_next_free(si);
1579 swrap_inc_refcount(si);
1581 SWRAP_UNLOCK_SI(si);
1584 swrap_mutex_unlock(&first_free_mutex);
1589 static int swrap_create_socket(struct socket_info *si, int fd)
1593 if ((size_t)fd >= socket_fds_max) {
1594 SWRAP_LOG(SWRAP_LOG_ERROR,
1595 "The max socket index limit of %zu has been reached, "
1602 idx = swrap_add_socket_info(si);
1607 set_socket_info_index(fd, idx);
1612 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1619 p = strrchr(un->sun_path, '/');
1620 if (p) p++; else p = un->sun_path;
1622 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1627 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1630 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1641 case SOCKET_TYPE_CHAR_TCP:
1642 case SOCKET_TYPE_CHAR_UDP: {
1643 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1645 if ((*len) < sizeof(*in2)) {
1650 memset(in2, 0, sizeof(*in2));
1651 in2->sin_family = AF_INET;
1652 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1653 in2->sin_port = htons(prt);
1655 *len = sizeof(*in2);
1659 case SOCKET_TYPE_CHAR_TCP_V6:
1660 case SOCKET_TYPE_CHAR_UDP_V6: {
1661 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1663 if ((*len) < sizeof(*in2)) {
1668 memset(in2, 0, sizeof(*in2));
1669 in2->sin6_family = AF_INET6;
1670 in2->sin6_addr = *swrap_ipv6();
1671 in2->sin6_addr.s6_addr[15] = iface;
1672 in2->sin6_port = htons(prt);
1674 *len = sizeof(*in2);
1686 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1694 if (bcast) *bcast = 0;
1696 switch (inaddr->sa_family) {
1698 const struct sockaddr_in *in =
1699 (const struct sockaddr_in *)(const void *)inaddr;
1700 unsigned int addr = ntohl(in->sin_addr.s_addr);
1707 u_type = SOCKET_TYPE_CHAR_TCP;
1710 u_type = SOCKET_TYPE_CHAR_UDP;
1711 a_type = SOCKET_TYPE_CHAR_UDP;
1712 b_type = SOCKET_TYPE_CHAR_UDP;
1715 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1716 errno = ESOCKTNOSUPPORT;
1720 prt = ntohs(in->sin_port);
1721 if (a_type && addr == 0xFFFFFFFF) {
1722 /* 255.255.255.255 only udp */
1725 iface = socket_wrapper_default_iface();
1726 } else if (b_type && addr == 0x7FFFFFFF) {
1727 /* 127.255.255.255 only udp */
1730 iface = socket_wrapper_default_iface();
1731 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1735 iface = (addr & 0x000000FF);
1737 errno = ENETUNREACH;
1740 if (bcast) *bcast = is_bcast;
1745 const struct sockaddr_in6 *in =
1746 (const struct sockaddr_in6 *)(const void *)inaddr;
1747 struct in6_addr cmp1, cmp2;
1751 type = SOCKET_TYPE_CHAR_TCP_V6;
1754 type = SOCKET_TYPE_CHAR_UDP_V6;
1757 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1758 errno = ESOCKTNOSUPPORT;
1762 /* XXX no multicast/broadcast */
1764 prt = ntohs(in->sin6_port);
1766 cmp1 = *swrap_ipv6();
1767 cmp2 = in->sin6_addr;
1768 cmp2.s6_addr[15] = 0;
1769 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1770 iface = in->sin6_addr.s6_addr[15];
1772 errno = ENETUNREACH;
1780 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1781 errno = ENETUNREACH;
1786 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1792 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1793 socket_wrapper_dir());
1794 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1795 /* the caller need to do more processing */
1799 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1800 socket_wrapper_dir(), type, iface, prt);
1801 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1806 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1815 if (bcast) *bcast = 0;
1817 switch (si->family) {
1819 const struct sockaddr_in *in =
1820 (const struct sockaddr_in *)(const void *)inaddr;
1821 unsigned int addr = ntohl(in->sin_addr.s_addr);
1827 prt = ntohs(in->sin_port);
1831 u_type = SOCKET_TYPE_CHAR_TCP;
1832 d_type = SOCKET_TYPE_CHAR_TCP;
1835 u_type = SOCKET_TYPE_CHAR_UDP;
1836 d_type = SOCKET_TYPE_CHAR_UDP;
1837 a_type = SOCKET_TYPE_CHAR_UDP;
1838 b_type = SOCKET_TYPE_CHAR_UDP;
1841 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1842 errno = ESOCKTNOSUPPORT;
1850 iface = socket_wrapper_default_iface();
1851 } else if (a_type && addr == 0xFFFFFFFF) {
1852 /* 255.255.255.255 only udp */
1855 iface = socket_wrapper_default_iface();
1856 } else if (b_type && addr == 0x7FFFFFFF) {
1857 /* 127.255.255.255 only udp */
1860 iface = socket_wrapper_default_iface();
1861 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1865 iface = (addr & 0x000000FF);
1867 errno = EADDRNOTAVAIL;
1871 /* Store the bind address for connect() */
1872 if (si->bindname.sa_socklen == 0) {
1873 struct sockaddr_in bind_in;
1874 socklen_t blen = sizeof(struct sockaddr_in);
1876 ZERO_STRUCT(bind_in);
1877 bind_in.sin_family = in->sin_family;
1878 bind_in.sin_port = in->sin_port;
1879 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1881 si->bindname.sa_socklen = blen;
1882 memcpy(&si->bindname.sa.in, &bind_in, blen);
1889 const struct sockaddr_in6 *in =
1890 (const struct sockaddr_in6 *)(const void *)inaddr;
1891 struct in6_addr cmp1, cmp2;
1895 type = SOCKET_TYPE_CHAR_TCP_V6;
1898 type = SOCKET_TYPE_CHAR_UDP_V6;
1901 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1902 errno = ESOCKTNOSUPPORT;
1906 /* XXX no multicast/broadcast */
1908 prt = ntohs(in->sin6_port);
1910 cmp1 = *swrap_ipv6();
1911 cmp2 = in->sin6_addr;
1912 cmp2.s6_addr[15] = 0;
1913 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1914 iface = socket_wrapper_default_iface();
1915 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1916 iface = in->sin6_addr.s6_addr[15];
1918 errno = EADDRNOTAVAIL;
1922 /* Store the bind address for connect() */
1923 if (si->bindname.sa_socklen == 0) {
1924 struct sockaddr_in6 bind_in;
1925 socklen_t blen = sizeof(struct sockaddr_in6);
1927 ZERO_STRUCT(bind_in);
1928 bind_in.sin6_family = in->sin6_family;
1929 bind_in.sin6_port = in->sin6_port;
1931 bind_in.sin6_addr = *swrap_ipv6();
1932 bind_in.sin6_addr.s6_addr[15] = iface;
1934 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1935 si->bindname.sa_socklen = blen;
1942 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1943 errno = EADDRNOTAVAIL;
1948 if (bcast) *bcast = is_bcast;
1950 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1956 /* handle auto-allocation of ephemeral ports */
1957 for (prt = 5001; prt < 10000; prt++) {
1958 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1959 socket_wrapper_dir(), type, iface, prt);
1960 if (stat(un->sun_path, &st) == 0) continue;
1962 set_port(si->family, prt, &si->myname);
1963 set_port(si->family, prt, &si->bindname);
1973 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1974 socket_wrapper_dir(), type, iface, prt);
1975 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1979 static struct socket_info *find_socket_info(int fd)
1981 int idx = find_socket_info_index(fd);
1987 return swrap_get_socket_info(idx);
1991 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1993 struct socket_info_fd *f;
1994 const struct socket_info *last_s = NULL;
1996 /* first catch invalid input */
1997 switch (sa->sa_family) {
1999 if (len < sizeof(struct sockaddr_in)) {
2005 if (len < sizeof(struct sockaddr_in6)) {
2015 for (f = socket_fds; f; f = f->next) {
2016 struct socket_info *s = swrap_get_socket_info(f->si_index);
2023 if (s->myname == NULL) {
2026 if (s->myname->sa_family != sa->sa_family) {
2029 switch (s->myname->sa_family) {
2031 struct sockaddr_in *sin1, *sin2;
2033 sin1 = (struct sockaddr_in *)s->myname;
2034 sin2 = (struct sockaddr_in *)sa;
2036 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2039 if (sin1->sin_port != sin2->sin_port) {
2042 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2052 struct sockaddr_in6 *sin1, *sin2;
2054 sin1 = (struct sockaddr_in6 *)s->myname;
2055 sin2 = (struct sockaddr_in6 *)sa;
2057 if (sin1->sin6_port != sin2->sin6_port) {
2060 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2082 static void swrap_remove_stale(int fd)
2084 struct socket_info *si;
2087 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2089 swrap_mutex_lock(&socket_reset_mutex);
2091 si_index = find_socket_info_index(fd);
2092 if (si_index == -1) {
2093 swrap_mutex_unlock(&socket_reset_mutex);
2097 reset_socket_info_index(fd);
2099 si = swrap_get_socket_info(si_index);
2101 swrap_mutex_lock(&first_free_mutex);
2104 swrap_dec_refcount(si);
2106 if (swrap_get_refcount(si) > 0) {
2110 if (si->un_addr.sun_path[0] != '\0') {
2111 unlink(si->un_addr.sun_path);
2114 swrap_set_next_free(si, first_free);
2115 first_free = si_index;
2118 SWRAP_UNLOCK_SI(si);
2119 swrap_mutex_unlock(&first_free_mutex);
2120 swrap_mutex_unlock(&socket_reset_mutex);
2123 static int sockaddr_convert_to_un(struct socket_info *si,
2124 const struct sockaddr *in_addr,
2126 struct sockaddr_un *out_addr,
2130 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2132 (void) in_len; /* unused */
2134 if (out_addr == NULL) {
2138 out->sa_family = AF_UNIX;
2139 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2140 out->sa_len = sizeof(*out_addr);
2143 switch (in_addr->sa_family) {
2145 const struct sockaddr_in *sin;
2146 if (si->family != AF_INET) {
2149 if (in_len < sizeof(struct sockaddr_in)) {
2152 sin = (const struct sockaddr_in *)(const void *)in_addr;
2153 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2158 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2159 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2173 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2174 errno = ESOCKTNOSUPPORT;
2178 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2180 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2186 errno = EAFNOSUPPORT;
2187 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2191 static int sockaddr_convert_from_un(const struct socket_info *si,
2192 const struct sockaddr_un *in_addr,
2193 socklen_t un_addrlen,
2195 struct sockaddr *out_addr,
2196 socklen_t *out_addrlen)
2200 if (out_addr == NULL || out_addrlen == NULL)
2203 if (un_addrlen == 0) {
2218 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2219 errno = ESOCKTNOSUPPORT;
2222 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2223 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2224 out_addr->sa_len = *out_addrlen;
2231 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2232 errno = EAFNOSUPPORT;
2236 enum swrap_packet_type {
2238 SWRAP_CONNECT_UNREACH,
2246 SWRAP_SENDTO_UNREACH,
2257 struct swrap_file_hdr {
2259 uint16_t version_major;
2260 uint16_t version_minor;
2263 uint32_t frame_max_len;
2264 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2267 #define SWRAP_FILE_HDR_SIZE 24
2269 struct swrap_packet_frame {
2271 uint32_t micro_seconds;
2272 uint32_t recorded_length;
2273 uint32_t full_length;
2275 #define SWRAP_PACKET_FRAME_SIZE 16
2277 union swrap_packet_ip {
2281 uint16_t packet_length;
2282 uint16_t identification;
2287 uint16_t hdr_checksum;
2291 #define SWRAP_PACKET_IP_V4_SIZE 20
2294 uint8_t flow_label_high;
2295 uint16_t flow_label_low;
2296 uint16_t payload_length;
2297 uint8_t next_header;
2299 uint8_t src_addr[16];
2300 uint8_t dest_addr[16];
2302 #define SWRAP_PACKET_IP_V6_SIZE 40
2304 #define SWRAP_PACKET_IP_SIZE 40
2306 union swrap_packet_payload {
2308 uint16_t source_port;
2318 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2320 uint16_t source_port;
2325 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2332 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2339 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2341 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2343 #define SWRAP_PACKET_MIN_ALLOC \
2344 (SWRAP_PACKET_FRAME_SIZE + \
2345 SWRAP_PACKET_IP_SIZE + \
2346 SWRAP_PACKET_PAYLOAD_SIZE)
2348 static const char *swrap_pcap_init_file(void)
2350 static int initialized = 0;
2351 static const char *s = NULL;
2352 static const struct swrap_file_hdr h;
2353 static const struct swrap_packet_frame f;
2354 static const union swrap_packet_ip i;
2355 static const union swrap_packet_payload p;
2357 if (initialized == 1) {
2363 * TODO: don't use the structs use plain buffer offsets
2364 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2366 * for now make sure we disable PCAP support
2367 * if the struct has alignment!
2369 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2372 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2375 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2378 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2381 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2384 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2387 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2390 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2393 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2396 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2400 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2404 if (strncmp(s, "./", 2) == 0) {
2410 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2411 const struct sockaddr *src,
2412 const struct sockaddr *dest,
2414 const uint8_t *payload,
2416 unsigned long tcp_seqno,
2417 unsigned long tcp_ack,
2418 unsigned char tcp_ctl,
2420 size_t *_packet_len)
2424 struct swrap_packet_frame *frame;
2425 union swrap_packet_ip *ip;
2426 union swrap_packet_payload *pay;
2429 size_t nonwire_len = sizeof(*frame);
2430 size_t wire_hdr_len = 0;
2431 size_t wire_len = 0;
2432 size_t ip_hdr_len = 0;
2433 size_t icmp_hdr_len = 0;
2434 size_t icmp_truncate_len = 0;
2435 uint8_t protocol = 0, icmp_protocol = 0;
2436 const struct sockaddr_in *src_in = NULL;
2437 const struct sockaddr_in *dest_in = NULL;
2439 const struct sockaddr_in6 *src_in6 = NULL;
2440 const struct sockaddr_in6 *dest_in6 = NULL;
2445 switch (src->sa_family) {
2447 src_in = (const struct sockaddr_in *)(const void *)src;
2448 dest_in = (const struct sockaddr_in *)(const void *)dest;
2449 src_port = src_in->sin_port;
2450 dest_port = dest_in->sin_port;
2451 ip_hdr_len = sizeof(ip->v4);
2455 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2456 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2457 src_port = src_in6->sin6_port;
2458 dest_port = dest_in6->sin6_port;
2459 ip_hdr_len = sizeof(ip->v6);
2466 switch (socket_type) {
2468 protocol = 0x06; /* TCP */
2469 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2470 wire_len = wire_hdr_len + payload_len;
2474 protocol = 0x11; /* UDP */
2475 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2476 wire_len = wire_hdr_len + payload_len;
2484 icmp_protocol = protocol;
2485 switch (src->sa_family) {
2487 protocol = 0x01; /* ICMPv4 */
2488 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2492 protocol = 0x3A; /* ICMPv6 */
2493 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2497 if (wire_len > 64 ) {
2498 icmp_truncate_len = wire_len - 64;
2500 wire_hdr_len += icmp_hdr_len;
2501 wire_len += icmp_hdr_len;
2504 packet_len = nonwire_len + wire_len;
2505 alloc_len = packet_len;
2506 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2507 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2510 base = (uint8_t *)calloc(1, alloc_len);
2517 frame = (struct swrap_packet_frame *)(void *)buf;
2518 frame->seconds = tval->tv_sec;
2519 frame->micro_seconds = tval->tv_usec;
2520 frame->recorded_length = wire_len - icmp_truncate_len;
2521 frame->full_length = wire_len - icmp_truncate_len;
2522 buf += SWRAP_PACKET_FRAME_SIZE;
2524 ip = (union swrap_packet_ip *)(void *)buf;
2525 switch (src->sa_family) {
2527 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2529 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2530 ip->v4.identification = htons(0xFFFF);
2531 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2532 ip->v4.fragment = htons(0x0000);
2534 ip->v4.protocol = protocol;
2535 ip->v4.hdr_checksum = htons(0x0000);
2536 ip->v4.src_addr = src_in->sin_addr.s_addr;
2537 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2538 buf += SWRAP_PACKET_IP_V4_SIZE;
2542 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2543 ip->v6.flow_label_high = 0x00;
2544 ip->v6.flow_label_low = 0x0000;
2545 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2546 ip->v6.next_header = protocol;
2547 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2548 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2549 buf += SWRAP_PACKET_IP_V6_SIZE;
2555 pay = (union swrap_packet_payload *)(void *)buf;
2556 switch (src->sa_family) {
2558 pay->icmp4.type = 0x03; /* destination unreachable */
2559 pay->icmp4.code = 0x01; /* host unreachable */
2560 pay->icmp4.checksum = htons(0x0000);
2561 pay->icmp4.unused = htonl(0x00000000);
2562 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2564 /* set the ip header in the ICMP payload */
2565 ip = (union swrap_packet_ip *)(void *)buf;
2566 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2568 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2569 ip->v4.identification = htons(0xFFFF);
2570 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2571 ip->v4.fragment = htons(0x0000);
2573 ip->v4.protocol = icmp_protocol;
2574 ip->v4.hdr_checksum = htons(0x0000);
2575 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2576 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2577 buf += SWRAP_PACKET_IP_V4_SIZE;
2579 src_port = dest_in->sin_port;
2580 dest_port = src_in->sin_port;
2584 pay->icmp6.type = 0x01; /* destination unreachable */
2585 pay->icmp6.code = 0x03; /* address unreachable */
2586 pay->icmp6.checksum = htons(0x0000);
2587 pay->icmp6.unused = htonl(0x00000000);
2588 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2590 /* set the ip header in the ICMP payload */
2591 ip = (union swrap_packet_ip *)(void *)buf;
2592 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2593 ip->v6.flow_label_high = 0x00;
2594 ip->v6.flow_label_low = 0x0000;
2595 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2596 ip->v6.next_header = protocol;
2597 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2598 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2599 buf += SWRAP_PACKET_IP_V6_SIZE;
2601 src_port = dest_in6->sin6_port;
2602 dest_port = src_in6->sin6_port;
2608 pay = (union swrap_packet_payload *)(void *)buf;
2610 switch (socket_type) {
2612 pay->tcp.source_port = src_port;
2613 pay->tcp.dest_port = dest_port;
2614 pay->tcp.seq_num = htonl(tcp_seqno);
2615 pay->tcp.ack_num = htonl(tcp_ack);
2616 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2617 pay->tcp.control = tcp_ctl;
2618 pay->tcp.window = htons(0x7FFF);
2619 pay->tcp.checksum = htons(0x0000);
2620 pay->tcp.urg = htons(0x0000);
2621 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2626 pay->udp.source_port = src_port;
2627 pay->udp.dest_port = dest_port;
2628 pay->udp.length = htons(8 + payload_len);
2629 pay->udp.checksum = htons(0x0000);
2630 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2635 if (payload && payload_len > 0) {
2636 memcpy(buf, payload, payload_len);
2639 *_packet_len = packet_len - icmp_truncate_len;
2643 static int swrap_pcap_get_fd(const char *fname)
2651 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2653 struct swrap_file_hdr file_hdr;
2654 file_hdr.magic = 0xA1B2C3D4;
2655 file_hdr.version_major = 0x0002;
2656 file_hdr.version_minor = 0x0004;
2657 file_hdr.timezone = 0x00000000;
2658 file_hdr.sigfigs = 0x00000000;
2659 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2660 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2662 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2669 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2674 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2675 const struct sockaddr *addr,
2676 enum swrap_packet_type type,
2677 const void *buf, size_t len,
2680 const struct sockaddr *src_addr;
2681 const struct sockaddr *dest_addr;
2682 unsigned long tcp_seqno = 0;
2683 unsigned long tcp_ack = 0;
2684 unsigned char tcp_ctl = 0;
2685 int unreachable = 0;
2689 switch (si->family) {
2701 case SWRAP_CONNECT_SEND:
2702 if (si->type != SOCK_STREAM) {
2706 src_addr = &si->myname.sa.s;
2709 tcp_seqno = si->io.pck_snd;
2710 tcp_ack = si->io.pck_rcv;
2711 tcp_ctl = 0x02; /* SYN */
2713 si->io.pck_snd += 1;
2717 case SWRAP_CONNECT_RECV:
2718 if (si->type != SOCK_STREAM) {
2722 dest_addr = &si->myname.sa.s;
2725 tcp_seqno = si->io.pck_rcv;
2726 tcp_ack = si->io.pck_snd;
2727 tcp_ctl = 0x12; /** SYN,ACK */
2729 si->io.pck_rcv += 1;
2733 case SWRAP_CONNECT_UNREACH:
2734 if (si->type != SOCK_STREAM) {
2738 dest_addr = &si->myname.sa.s;
2741 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2742 tcp_seqno = si->io.pck_snd - 1;
2743 tcp_ack = si->io.pck_rcv;
2744 tcp_ctl = 0x02; /* SYN */
2749 case SWRAP_CONNECT_ACK:
2750 if (si->type != SOCK_STREAM) {
2754 src_addr = &si->myname.sa.s;
2757 tcp_seqno = si->io.pck_snd;
2758 tcp_ack = si->io.pck_rcv;
2759 tcp_ctl = 0x10; /* ACK */
2763 case SWRAP_ACCEPT_SEND:
2764 if (si->type != SOCK_STREAM) {
2768 dest_addr = &si->myname.sa.s;
2771 tcp_seqno = si->io.pck_rcv;
2772 tcp_ack = si->io.pck_snd;
2773 tcp_ctl = 0x02; /* SYN */
2775 si->io.pck_rcv += 1;
2779 case SWRAP_ACCEPT_RECV:
2780 if (si->type != SOCK_STREAM) {
2784 src_addr = &si->myname.sa.s;
2787 tcp_seqno = si->io.pck_snd;
2788 tcp_ack = si->io.pck_rcv;
2789 tcp_ctl = 0x12; /* SYN,ACK */
2791 si->io.pck_snd += 1;
2795 case SWRAP_ACCEPT_ACK:
2796 if (si->type != SOCK_STREAM) {
2800 dest_addr = &si->myname.sa.s;
2803 tcp_seqno = si->io.pck_rcv;
2804 tcp_ack = si->io.pck_snd;
2805 tcp_ctl = 0x10; /* ACK */
2810 src_addr = &si->myname.sa.s;
2811 dest_addr = &si->peername.sa.s;
2813 tcp_seqno = si->io.pck_snd;
2814 tcp_ack = si->io.pck_rcv;
2815 tcp_ctl = 0x18; /* PSH,ACK */
2817 si->io.pck_snd += len;
2821 case SWRAP_SEND_RST:
2822 dest_addr = &si->myname.sa.s;
2823 src_addr = &si->peername.sa.s;
2825 if (si->type == SOCK_DGRAM) {
2826 return swrap_pcap_marshall_packet(si,
2828 SWRAP_SENDTO_UNREACH,
2834 tcp_seqno = si->io.pck_rcv;
2835 tcp_ack = si->io.pck_snd;
2836 tcp_ctl = 0x14; /** RST,ACK */
2840 case SWRAP_PENDING_RST:
2841 dest_addr = &si->myname.sa.s;
2842 src_addr = &si->peername.sa.s;
2844 if (si->type == SOCK_DGRAM) {
2848 tcp_seqno = si->io.pck_rcv;
2849 tcp_ack = si->io.pck_snd;
2850 tcp_ctl = 0x14; /* RST,ACK */
2855 dest_addr = &si->myname.sa.s;
2856 src_addr = &si->peername.sa.s;
2858 tcp_seqno = si->io.pck_rcv;
2859 tcp_ack = si->io.pck_snd;
2860 tcp_ctl = 0x18; /* PSH,ACK */
2862 si->io.pck_rcv += len;
2866 case SWRAP_RECV_RST:
2867 dest_addr = &si->myname.sa.s;
2868 src_addr = &si->peername.sa.s;
2870 if (si->type == SOCK_DGRAM) {
2874 tcp_seqno = si->io.pck_rcv;
2875 tcp_ack = si->io.pck_snd;
2876 tcp_ctl = 0x14; /* RST,ACK */
2881 src_addr = &si->myname.sa.s;
2884 si->io.pck_snd += len;
2888 case SWRAP_SENDTO_UNREACH:
2889 dest_addr = &si->myname.sa.s;
2896 case SWRAP_RECVFROM:
2897 dest_addr = &si->myname.sa.s;
2900 si->io.pck_rcv += len;
2904 case SWRAP_CLOSE_SEND:
2905 if (si->type != SOCK_STREAM) {
2909 src_addr = &si->myname.sa.s;
2910 dest_addr = &si->peername.sa.s;
2912 tcp_seqno = si->io.pck_snd;
2913 tcp_ack = si->io.pck_rcv;
2914 tcp_ctl = 0x11; /* FIN, ACK */
2916 si->io.pck_snd += 1;
2920 case SWRAP_CLOSE_RECV:
2921 if (si->type != SOCK_STREAM) {
2925 dest_addr = &si->myname.sa.s;
2926 src_addr = &si->peername.sa.s;
2928 tcp_seqno = si->io.pck_rcv;
2929 tcp_ack = si->io.pck_snd;
2930 tcp_ctl = 0x11; /* FIN,ACK */
2932 si->io.pck_rcv += 1;
2936 case SWRAP_CLOSE_ACK:
2937 if (si->type != SOCK_STREAM) {
2941 src_addr = &si->myname.sa.s;
2942 dest_addr = &si->peername.sa.s;
2944 tcp_seqno = si->io.pck_snd;
2945 tcp_ack = si->io.pck_rcv;
2946 tcp_ctl = 0x10; /* ACK */
2953 swrapGetTimeOfDay(&tv);
2955 return swrap_pcap_packet_init(&tv,
2959 (const uint8_t *)buf,
2968 static void swrap_pcap_dump_packet(struct socket_info *si,
2969 const struct sockaddr *addr,
2970 enum swrap_packet_type type,
2971 const void *buf, size_t len)
2973 const char *file_name;
2975 size_t packet_len = 0;
2978 swrap_mutex_lock(&pcap_dump_mutex);
2980 file_name = swrap_pcap_init_file();
2985 packet = swrap_pcap_marshall_packet(si,
2991 if (packet == NULL) {
2995 fd = swrap_pcap_get_fd(file_name);
2997 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3006 swrap_mutex_unlock(&pcap_dump_mutex);
3009 /****************************************************************************
3011 ***************************************************************************/
3013 #ifdef HAVE_SIGNALFD
3014 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3018 rc = libc_signalfd(fd, mask, flags);
3020 swrap_remove_stale(fd);
3026 int signalfd(int fd, const sigset_t *mask, int flags)
3028 return swrap_signalfd(fd, mask, flags);
3032 /****************************************************************************
3034 ***************************************************************************/
3036 static int swrap_socket(int family, int type, int protocol)
3038 struct socket_info *si = NULL;
3039 struct socket_info _si = { 0 };
3042 int real_type = type;
3045 * Remove possible addition flags passed to socket() so
3046 * do not fail checking the type.
3047 * See https://lwn.net/Articles/281965/
3050 real_type &= ~SOCK_CLOEXEC;
3052 #ifdef SOCK_NONBLOCK
3053 real_type &= ~SOCK_NONBLOCK;
3056 if (!socket_wrapper_enabled()) {
3057 return libc_socket(family, type, protocol);
3068 #endif /* AF_NETLINK */
3071 #endif /* AF_PACKET */
3073 return libc_socket(family, type, protocol);
3075 errno = EAFNOSUPPORT;
3079 switch (real_type) {
3085 errno = EPROTONOSUPPORT;
3093 if (real_type == SOCK_STREAM) {
3098 if (real_type == SOCK_DGRAM) {
3103 errno = EPROTONOSUPPORT;
3108 * We must call libc_socket with type, from the caller, not the version
3109 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3111 fd = libc_socket(AF_UNIX, type, 0);
3117 /* Check if we have a stale fd and remove it */
3118 swrap_remove_stale(fd);
3121 si->family = family;
3123 /* however, the rest of the socket_wrapper code expects just
3124 * the type, not the flags */
3125 si->type = real_type;
3126 si->protocol = protocol;
3129 * Setup myname so getsockname() can succeed to find out the socket
3132 switch(si->family) {
3134 struct sockaddr_in sin = {
3135 .sin_family = AF_INET,
3138 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3139 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3144 struct sockaddr_in6 sin6 = {
3145 .sin6_family = AF_INET6,
3148 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3149 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3158 ret = swrap_create_socket(si, fd);
3163 SWRAP_LOG(SWRAP_LOG_TRACE,
3164 "Created %s socket for protocol %s, fd=%d",
3165 family == AF_INET ? "IPv4" : "IPv6",
3166 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3172 int socket(int family, int type, int protocol)
3174 return swrap_socket(family, type, protocol);
3177 /****************************************************************************
3179 ***************************************************************************/
3181 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3185 rc = libc_socketpair(family, type, protocol, sv);
3187 swrap_remove_stale(sv[0]);
3188 swrap_remove_stale(sv[1]);
3194 int socketpair(int family, int type, int protocol, int sv[2])
3196 return swrap_socketpair(family, type, protocol, sv);
3199 /****************************************************************************
3201 ***************************************************************************/
3203 #ifdef HAVE_TIMERFD_CREATE
3204 static int swrap_timerfd_create(int clockid, int flags)
3208 fd = libc_timerfd_create(clockid, flags);
3210 swrap_remove_stale(fd);
3216 int timerfd_create(int clockid, int flags)
3218 return swrap_timerfd_create(clockid, flags);
3222 /****************************************************************************
3224 ***************************************************************************/
3226 static int swrap_pipe(int pipefd[2])
3230 rc = libc_pipe(pipefd);
3232 swrap_remove_stale(pipefd[0]);
3233 swrap_remove_stale(pipefd[1]);
3239 int pipe(int pipefd[2])
3241 return swrap_pipe(pipefd);
3244 /****************************************************************************
3246 ***************************************************************************/
3248 static int swrap_accept(int s,
3249 struct sockaddr *addr,
3253 struct socket_info *parent_si, *child_si;
3254 struct socket_info new_si = { 0 };
3257 struct swrap_address un_addr = {
3258 .sa_socklen = sizeof(struct sockaddr_un),
3260 struct swrap_address un_my_addr = {
3261 .sa_socklen = sizeof(struct sockaddr_un),
3263 struct swrap_address in_addr = {
3264 .sa_socklen = sizeof(struct sockaddr_storage),
3266 struct swrap_address in_my_addr = {
3267 .sa_socklen = sizeof(struct sockaddr_storage),
3271 parent_si = find_socket_info(s);
3274 return libc_accept4(s, addr, addrlen, flags);
3277 return libc_accept(s, addr, addrlen);
3283 * prevent parent_si from being altered / closed
3286 SWRAP_LOCK_SI(parent_si);
3289 * assume out sockaddr have the same size as the in parent
3292 in_addr.sa_socklen = socket_length(parent_si->family);
3293 if (in_addr.sa_socklen <= 0) {
3294 SWRAP_UNLOCK_SI(parent_si);
3299 SWRAP_UNLOCK_SI(parent_si);
3302 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3305 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3308 if (errno == ENOTSOCK) {
3309 /* Remove stale fds */
3310 swrap_remove_stale(s);
3317 SWRAP_LOCK_SI(parent_si);
3319 ret = sockaddr_convert_from_un(parent_si,
3324 &in_addr.sa_socklen);
3326 SWRAP_UNLOCK_SI(parent_si);
3333 child_si->family = parent_si->family;
3334 child_si->type = parent_si->type;
3335 child_si->protocol = parent_si->protocol;
3336 child_si->bound = 1;
3337 child_si->is_server = 1;
3338 child_si->connected = 1;
3340 SWRAP_UNLOCK_SI(parent_si);
3342 child_si->peername = (struct swrap_address) {
3343 .sa_socklen = in_addr.sa_socklen,
3345 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3347 if (addr != NULL && addrlen != NULL) {
3348 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3350 memcpy(addr, &in_addr.sa.ss, copy_len);
3352 *addrlen = in_addr.sa_socklen;
3355 ret = libc_getsockname(fd,
3357 &un_my_addr.sa_socklen);
3363 ret = sockaddr_convert_from_un(child_si,
3365 un_my_addr.sa_socklen,
3368 &in_my_addr.sa_socklen);
3374 SWRAP_LOG(SWRAP_LOG_TRACE,
3375 "accept() path=%s, fd=%d",
3376 un_my_addr.sa.un.sun_path, s);
3378 child_si->myname = (struct swrap_address) {
3379 .sa_socklen = in_my_addr.sa_socklen,
3381 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3383 idx = swrap_create_socket(&new_si, fd);
3390 struct socket_info *si = swrap_get_socket_info(idx);
3393 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3394 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3395 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3396 SWRAP_UNLOCK_SI(si);
3403 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3405 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3409 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3410 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3412 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3415 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3418 static int autobind_start_init;
3419 static int autobind_start;
3421 /* using sendto() or connect() on an unbound socket would give the
3422 recipient no way to reply, as unlike UDP and TCP, a unix domain
3423 socket can't auto-assign ephemeral port numbers, so we need to
3425 Note: this might change the family from ipv6 to ipv4
3427 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3429 struct swrap_address un_addr = {
3430 .sa_socklen = sizeof(struct sockaddr_un),
3438 swrap_mutex_lock(&autobind_start_mutex);
3440 if (autobind_start_init != 1) {
3441 autobind_start_init = 1;
3442 autobind_start = getpid();
3443 autobind_start %= 50000;
3444 autobind_start += 10000;
3447 un_addr.sa.un.sun_family = AF_UNIX;
3451 struct sockaddr_in in;
3455 type = SOCKET_TYPE_CHAR_TCP;
3458 type = SOCKET_TYPE_CHAR_UDP;
3461 errno = ESOCKTNOSUPPORT;
3466 memset(&in, 0, sizeof(in));
3467 in.sin_family = AF_INET;
3468 in.sin_addr.s_addr = htonl(127<<24 |
3469 socket_wrapper_default_iface());
3471 si->myname = (struct swrap_address) {
3472 .sa_socklen = sizeof(in),
3474 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3479 struct sockaddr_in6 in6;
3481 if (si->family != family) {
3482 errno = ENETUNREACH;
3489 type = SOCKET_TYPE_CHAR_TCP_V6;
3492 type = SOCKET_TYPE_CHAR_UDP_V6;
3495 errno = ESOCKTNOSUPPORT;
3500 memset(&in6, 0, sizeof(in6));
3501 in6.sin6_family = AF_INET6;
3502 in6.sin6_addr = *swrap_ipv6();
3503 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3505 si->myname = (struct swrap_address) {
3506 .sa_socklen = sizeof(in6),
3508 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3513 errno = ESOCKTNOSUPPORT;
3518 if (autobind_start > 60000) {
3519 autobind_start = 10000;
3522 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3523 port = autobind_start + i;
3524 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3525 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3526 type, socket_wrapper_default_iface(), port);
3527 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3529 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3534 si->un_addr = un_addr.sa.un;
3537 autobind_start = port + 1;
3540 if (i == SOCKET_MAX_SOCKETS) {
3541 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3542 "interface "SOCKET_FORMAT,
3545 socket_wrapper_default_iface(),
3552 si->family = family;
3553 set_port(si->family, port, &si->myname);
3558 swrap_mutex_unlock(&autobind_start_mutex);
3562 /****************************************************************************
3564 ***************************************************************************/
3566 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3570 struct swrap_address un_addr = {
3571 .sa_socklen = sizeof(struct sockaddr_un),
3573 struct socket_info *si = find_socket_info(s);
3577 return libc_connect(s, serv_addr, addrlen);
3582 if (si->bound == 0) {
3583 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3589 if (si->family != serv_addr->sa_family) {
3595 ret = sockaddr_convert_to_un(si, serv_addr,
3596 addrlen, &un_addr.sa.un, 0, &bcast);
3602 errno = ENETUNREACH;
3607 if (si->type == SOCK_DGRAM) {
3608 si->defer_connect = 1;
3611 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3613 ret = libc_connect(s,
3615 un_addr.sa_socklen);
3618 SWRAP_LOG(SWRAP_LOG_TRACE,
3619 "connect() path=%s, fd=%d",
3620 un_addr.sa.un.sun_path, s);
3623 /* to give better errors */
3624 if (ret == -1 && errno == ENOENT) {
3625 errno = EHOSTUNREACH;
3629 si->peername = (struct swrap_address) {
3630 .sa_socklen = addrlen,
3633 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3637 * When we connect() on a socket than we have to bind the
3638 * outgoing connection on the interface we use for the
3639 * transport. We already bound it on the right interface
3640 * but here we have to update the name so getsockname()
3641 * returns correct information.
3643 if (si->bindname.sa_socklen > 0) {
3644 si->myname = (struct swrap_address) {
3645 .sa_socklen = si->bindname.sa_socklen,
3648 memcpy(&si->myname.sa.ss,
3649 &si->bindname.sa.ss,
3650 si->bindname.sa_socklen);
3652 /* Cleanup bindname */
3653 si->bindname = (struct swrap_address) {
3658 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3659 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3661 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3665 SWRAP_UNLOCK_SI(si);
3669 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3671 return swrap_connect(s, serv_addr, addrlen);
3674 /****************************************************************************
3676 ***************************************************************************/
3678 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3681 struct swrap_address un_addr = {
3682 .sa_socklen = sizeof(struct sockaddr_un),
3684 struct socket_info *si = find_socket_info(s);
3691 return libc_bind(s, myaddr, addrlen);
3696 switch (si->family) {
3698 const struct sockaddr_in *sin;
3699 if (addrlen < sizeof(struct sockaddr_in)) {
3700 bind_error = EINVAL;
3704 sin = (const struct sockaddr_in *)(const void *)myaddr;
3706 if (sin->sin_family != AF_INET) {
3707 bind_error = EAFNOSUPPORT;
3710 /* special case for AF_UNSPEC */
3711 if (sin->sin_family == AF_UNSPEC &&
3712 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3721 const struct sockaddr_in6 *sin6;
3722 if (addrlen < sizeof(struct sockaddr_in6)) {
3723 bind_error = EINVAL;
3727 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3729 if (sin6->sin6_family != AF_INET6) {
3730 bind_error = EAFNOSUPPORT;
3737 bind_error = EINVAL;
3741 if (bind_error != 0) {
3748 in_use = check_addr_port_in_use(myaddr, addrlen);
3756 si->myname.sa_socklen = addrlen;
3757 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3759 ret = sockaddr_convert_to_un(si,
3769 unlink(un_addr.sa.un.sun_path);
3771 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3773 SWRAP_LOG(SWRAP_LOG_TRACE,
3774 "bind() path=%s, fd=%d",
3775 un_addr.sa.un.sun_path, s);
3782 SWRAP_UNLOCK_SI(si);
3787 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3789 return swrap_bind(s, myaddr, addrlen);
3792 /****************************************************************************
3794 ***************************************************************************/
3796 #ifdef HAVE_BINDRESVPORT
3797 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3799 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3801 struct swrap_address myaddr = {
3802 .sa_socklen = sizeof(struct sockaddr_storage),
3805 static uint16_t port;
3810 #define SWRAP_STARTPORT 600
3811 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3812 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3815 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3819 salen = myaddr.sa_socklen;
3822 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3828 memset(&myaddr.sa.ss, 0, salen);
3833 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3836 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3838 salen = sizeof(struct sockaddr_in);
3839 sinp->sin_port = htons(port);
3843 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3845 salen = sizeof(struct sockaddr_in6);
3846 sin6p->sin6_port = htons(port);
3850 errno = EAFNOSUPPORT;
3855 if (port > SWRAP_ENDPORT) {
3856 port = SWRAP_STARTPORT;
3859 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3860 if (rc == 0 || errno != EADDRINUSE) {
3868 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3870 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3874 /****************************************************************************
3876 ***************************************************************************/
3878 static int swrap_listen(int s, int backlog)
3881 struct socket_info *si = find_socket_info(s);
3884 return libc_listen(s, backlog);
3889 if (si->bound == 0) {
3890 ret = swrap_auto_bind(s, si, si->family);
3897 ret = libc_listen(s, backlog);
3900 SWRAP_UNLOCK_SI(si);
3905 int listen(int s, int backlog)
3907 return swrap_listen(s, backlog);
3910 /****************************************************************************
3912 ***************************************************************************/
3914 static FILE *swrap_fopen(const char *name, const char *mode)
3918 fp = libc_fopen(name, mode);
3920 int fd = fileno(fp);
3922 swrap_remove_stale(fd);
3928 FILE *fopen(const char *name, const char *mode)
3930 return swrap_fopen(name, mode);
3933 /****************************************************************************
3935 ***************************************************************************/
3938 static FILE *swrap_fopen64(const char *name, const char *mode)
3942 fp = libc_fopen64(name, mode);
3944 int fd = fileno(fp);
3946 swrap_remove_stale(fd);
3952 FILE *fopen64(const char *name, const char *mode)
3954 return swrap_fopen64(name, mode);
3956 #endif /* HAVE_FOPEN64 */
3958 /****************************************************************************
3960 ***************************************************************************/
3962 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3966 ret = libc_vopen(pathname, flags, ap);
3969 * There are methods for closing descriptors (libc-internal code
3970 * paths, direct syscalls) which close descriptors in ways that
3971 * we can't intercept, so try to recover when we notice that
3974 swrap_remove_stale(ret);
3979 int open(const char *pathname, int flags, ...)
3984 va_start(ap, flags);
3985 fd = swrap_vopen(pathname, flags, ap);
3991 /****************************************************************************
3993 ***************************************************************************/
3996 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4000 ret = libc_vopen64(pathname, flags, ap);
4003 * There are methods for closing descriptors (libc-internal code
4004 * paths, direct syscalls) which close descriptors in ways that
4005 * we can't intercept, so try to recover when we notice that
4008 swrap_remove_stale(ret);
4013 int open64(const char *pathname, int flags, ...)
4018 va_start(ap, flags);
4019 fd = swrap_vopen64(pathname, flags, ap);
4024 #endif /* HAVE_OPEN64 */
4026 /****************************************************************************
4028 ***************************************************************************/
4030 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4034 ret = libc_vopenat(dirfd, path, flags, ap);
4037 * There are methods for closing descriptors (libc-internal code
4038 * paths, direct syscalls) which close descriptors in ways that
4039 * we can't intercept, so try to recover when we notice that
4042 swrap_remove_stale(ret);
4048 int openat(int dirfd, const char *path, int flags, ...)
4053 va_start(ap, flags);
4054 fd = swrap_vopenat(dirfd, path, flags, ap);
4060 /****************************************************************************
4062 ***************************************************************************/
4064 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4066 struct socket_info *si = find_socket_info(s);
4071 return libc_getpeername(s, name, addrlen);
4076 if (si->peername.sa_socklen == 0)
4082 len = MIN(*addrlen, si->peername.sa_socklen);
4088 memcpy(name, &si->peername.sa.ss, len);
4089 *addrlen = si->peername.sa_socklen;
4093 SWRAP_UNLOCK_SI(si);
4098 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4099 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4101 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4104 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4107 /****************************************************************************
4109 ***************************************************************************/
4111 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4113 struct socket_info *si = find_socket_info(s);
4118 return libc_getsockname(s, name, addrlen);
4123 len = MIN(*addrlen, si->myname.sa_socklen);
4129 memcpy(name, &si->myname.sa.ss, len);
4130 *addrlen = si->myname.sa_socklen;
4134 SWRAP_UNLOCK_SI(si);
4139 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4140 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4142 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4145 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4148 /****************************************************************************
4150 ***************************************************************************/
4153 # ifdef SO_PROTOTYPE /* The Solaris name */
4154 # define SO_PROTOCOL SO_PROTOTYPE
4155 # endif /* SO_PROTOTYPE */
4156 #endif /* SO_PROTOCOL */
4158 static int swrap_getsockopt(int s, int level, int optname,
4159 void *optval, socklen_t *optlen)
4161 struct socket_info *si = find_socket_info(s);
4165 return libc_getsockopt(s,
4174 if (level == SOL_SOCKET) {
4178 if (optval == NULL || optlen == NULL ||
4179 *optlen < (socklen_t)sizeof(int)) {
4185 *optlen = sizeof(int);
4186 *(int *)optval = si->family;
4189 #endif /* SO_DOMAIN */
4193 if (optval == NULL || optlen == NULL ||
4194 *optlen < (socklen_t)sizeof(int)) {
4200 *optlen = sizeof(int);
4201 *(int *)optval = si->protocol;
4204 #endif /* SO_PROTOCOL */
4206 if (optval == NULL || optlen == NULL ||
4207 *optlen < (socklen_t)sizeof(int)) {
4213 *optlen = sizeof(int);
4214 *(int *)optval = si->type;
4218 ret = libc_getsockopt(s,
4225 } else if (level == IPPROTO_TCP) {
4230 * This enables sending packets directly out over TCP.
4231 * As a unix socket is doing that any way, report it as
4234 if (optval == NULL || optlen == NULL ||
4235 *optlen < (socklen_t)sizeof(int)) {
4241 *optlen = sizeof(int);
4242 *(int *)optval = si->tcp_nodelay;
4246 #endif /* TCP_NODELAY */
4252 errno = ENOPROTOOPT;
4256 SWRAP_UNLOCK_SI(si);
4260 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4261 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4263 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4266 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4269 /****************************************************************************
4271 ***************************************************************************/
4273 static int swrap_setsockopt(int s, int level, int optname,
4274 const void *optval, socklen_t optlen)
4276 struct socket_info *si = find_socket_info(s);
4280 return libc_setsockopt(s,
4287 if (level == SOL_SOCKET) {
4288 return libc_setsockopt(s,
4297 if (level == IPPROTO_TCP) {
4304 * This enables sending packets directly out over TCP.
4305 * A unix socket is doing that any way.
4307 if (optval == NULL || optlen == 0 ||
4308 optlen < (socklen_t)sizeof(int)) {
4314 i = *discard_const_p(int, optval);
4315 if (i != 0 && i != 1) {
4320 si->tcp_nodelay = i;
4325 #endif /* TCP_NODELAY */
4331 switch (si->family) {
4333 if (level == IPPROTO_IP) {
4335 if (optname == IP_PKTINFO) {
4336 si->pktinfo = AF_INET;
4338 #endif /* IP_PKTINFO */
4344 if (level == IPPROTO_IPV6) {
4345 #ifdef IPV6_RECVPKTINFO
4346 if (optname == IPV6_RECVPKTINFO) {
4347 si->pktinfo = AF_INET6;
4349 #endif /* IPV6_PKTINFO */
4355 errno = ENOPROTOOPT;
4361 SWRAP_UNLOCK_SI(si);
4365 int setsockopt(int s, int level, int optname,
4366 const void *optval, socklen_t optlen)
4368 return swrap_setsockopt(s, level, optname, optval, optlen);
4371 /****************************************************************************
4373 ***************************************************************************/
4375 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4377 struct socket_info *si = find_socket_info(s);
4383 return libc_vioctl(s, r, va);
4390 rc = libc_vioctl(s, r, va);
4394 value = *((int *)va_arg(ap, int *));
4396 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4397 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4398 } else if (value == 0) { /* END OF FILE */
4399 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4406 SWRAP_UNLOCK_SI(si);
4410 #ifdef HAVE_IOCTL_INT
4411 int ioctl(int s, int r, ...)
4413 int ioctl(int s, unsigned long int r, ...)
4421 rc = swrap_vioctl(s, (unsigned long int) r, va);
4432 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4435 # ifdef _ALIGN /* BSD */
4436 #define CMSG_ALIGN _ALIGN
4438 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4439 # endif /* _ALIGN */
4440 #endif /* CMSG_ALIGN */
4443 * @brief Add a cmsghdr to a msghdr.
4445 * This is an function to add any type of cmsghdr. It will operate on the
4446 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4447 * the buffer position after the added cmsg element. Hence, this function is
4448 * intended to be used with an intermediate msghdr and not on the original
4449 * one handed in by the client.
4451 * @param[in] msg The msghdr to which to add the cmsg.
4453 * @param[in] level The cmsg level to set.
4455 * @param[in] type The cmsg type to set.
4457 * @param[in] data The cmsg data to set.
4459 * @param[in] len the length of the data to set.
4461 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4467 size_t cmlen = CMSG_LEN(len);
4468 size_t cmspace = CMSG_SPACE(len);
4469 uint8_t cmbuf[cmspace];
4470 void *cast_ptr = (void *)cmbuf;
4471 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4474 memset(cmbuf, 0, cmspace);
4476 if (msg->msg_controllen < cmlen) {
4477 cmlen = msg->msg_controllen;
4478 msg->msg_flags |= MSG_CTRUNC;
4481 if (msg->msg_controllen < cmspace) {
4482 cmspace = msg->msg_controllen;
4486 * We copy the full input data into an intermediate cmsghdr first
4487 * in order to more easily cope with truncation.
4489 cm->cmsg_len = cmlen;
4490 cm->cmsg_level = level;
4491 cm->cmsg_type = type;
4492 memcpy(CMSG_DATA(cm), data, len);
4495 * We now copy the possibly truncated buffer.
4496 * We copy cmlen bytes, but consume cmspace bytes,
4497 * leaving the possible padding uninitialiazed.
4499 p = (uint8_t *)msg->msg_control;
4500 memcpy(p, cm, cmlen);
4502 msg->msg_control = p;
4503 msg->msg_controllen -= cmspace;
4508 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4511 /* Add packet info */
4512 switch (si->pktinfo) {
4513 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4515 struct sockaddr_in *sin;
4516 #if defined(HAVE_STRUCT_IN_PKTINFO)
4517 struct in_pktinfo pkt;
4518 #elif defined(IP_RECVDSTADDR)
4522 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4523 sin = &si->bindname.sa.in;
4525 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4528 sin = &si->myname.sa.in;
4533 #if defined(HAVE_STRUCT_IN_PKTINFO)
4534 pkt.ipi_ifindex = socket_wrapper_default_iface();
4535 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4536 #elif defined(IP_RECVDSTADDR)
4537 pkt = sin->sin_addr;
4540 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4545 #endif /* IP_PKTINFO */
4546 #if defined(HAVE_IPV6)
4548 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4549 struct sockaddr_in6 *sin6;
4550 struct in6_pktinfo pkt6;
4552 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4553 sin6 = &si->bindname.sa.in6;
4555 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4558 sin6 = &si->myname.sa.in6;
4563 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4564 pkt6.ipi6_addr = sin6->sin6_addr;
4566 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4567 &pkt6, sizeof(pkt6));
4568 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4572 #endif /* IPV6_PKTINFO */
4580 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4581 struct msghdr *omsg)
4585 if (si->pktinfo > 0) {
4586 rc = swrap_msghdr_add_pktinfo(si, omsg);
4592 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4594 size_t *cm_data_space);
4595 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4597 size_t *cm_data_space);
4599 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4601 size_t *cm_data_space) {
4602 struct cmsghdr *cmsg;
4606 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4610 for (cmsg = CMSG_FIRSTHDR(msg);
4612 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4613 switch (cmsg->cmsg_level) {
4615 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4620 rc = swrap_sendmsg_copy_cmsg(cmsg,
4630 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4632 size_t *cm_data_space)
4637 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4639 p = realloc((*cm_data), cmspace);
4645 p = (*cm_data) + (*cm_data_space);
4646 *cm_data_space = cmspace;
4648 memcpy(p, cmsg, cmsg->cmsg_len);
4653 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4655 size_t *cm_data_space);
4658 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4660 size_t *cm_data_space)
4664 switch(cmsg->cmsg_type) {
4667 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4674 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4686 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4688 size_t *cm_data_space)
4690 (void)cmsg; /* unused */
4691 (void)cm_data; /* unused */
4692 (void)cm_data_space; /* unused */
4695 * Passing a IP pktinfo to a unix socket might be rejected by the
4696 * Kernel, at least on FreeBSD. So skip this cmsg.
4700 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4702 static ssize_t swrap_sendmsg_before(int fd,
4703 struct socket_info *si,
4705 struct iovec *tmp_iov,
4706 struct sockaddr_un *tmp_un,
4707 const struct sockaddr_un **to_un,
4708 const struct sockaddr **to,
4730 if (!si->connected) {
4735 if (msg->msg_iovlen == 0) {
4739 mtu = socket_wrapper_mtu();
4740 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4742 nlen = len + msg->msg_iov[i].iov_len;
4747 msg->msg_iovlen = i;
4748 if (msg->msg_iovlen == 0) {
4749 *tmp_iov = msg->msg_iov[0];
4750 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4752 msg->msg_iov = tmp_iov;
4753 msg->msg_iovlen = 1;
4758 if (si->connected) {
4759 if (msg->msg_name != NULL) {
4761 * We are dealing with unix sockets and if we
4762 * are connected, we should only talk to the
4763 * connected unix path. Using the fd to send
4764 * to another server would be hard to achieve.
4766 msg->msg_name = NULL;
4767 msg->msg_namelen = 0;
4770 const struct sockaddr *msg_name;
4771 msg_name = (const struct sockaddr *)msg->msg_name;
4773 if (msg_name == NULL) {
4779 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4791 msg->msg_name = tmp_un;
4792 msg->msg_namelen = sizeof(*tmp_un);
4795 if (si->bound == 0) {
4796 ret = swrap_auto_bind(fd, si, si->family);
4798 SWRAP_UNLOCK_SI(si);
4799 if (errno == ENOTSOCK) {
4800 swrap_remove_stale(fd);
4803 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4809 if (!si->defer_connect) {
4813 ret = sockaddr_convert_to_un(si,
4815 si->peername.sa_socklen,
4823 ret = libc_connect(fd,
4824 (struct sockaddr *)(void *)tmp_un,
4827 /* to give better errors */
4828 if (ret == -1 && errno == ENOENT) {
4829 errno = EHOSTUNREACH;
4836 si->defer_connect = 0;
4839 errno = EHOSTUNREACH;
4843 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4844 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4845 uint8_t *cmbuf = NULL;
4848 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4855 msg->msg_controllen = 0;
4856 msg->msg_control = NULL;
4857 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4858 memcpy(msg->msg_control, cmbuf, cmlen);
4859 msg->msg_controllen = cmlen;
4867 SWRAP_UNLOCK_SI(si);
4872 static void swrap_sendmsg_after(int fd,
4873 struct socket_info *si,
4875 const struct sockaddr *to,
4878 int saved_errno = errno;
4885 /* to give better errors */
4887 if (saved_errno == ENOENT) {
4888 saved_errno = EHOSTUNREACH;
4889 } else if (saved_errno == ENOTSOCK) {
4890 /* If the fd is not a socket, remove it */
4891 swrap_remove_stale(fd);
4895 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4896 avail += msg->msg_iov[i].iov_len;
4900 remain = MIN(80, avail);
4905 /* we capture it as one single packet */
4906 buf = (uint8_t *)malloc(remain);
4908 /* we just not capture the packet */
4909 errno = saved_errno;
4913 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4914 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4916 msg->msg_iov[i].iov_base,
4919 remain -= this_time;
4928 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4929 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4931 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4936 if (si->connected) {
4937 to = &si->peername.sa.s;
4940 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4941 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4943 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4948 SWRAP_UNLOCK_SI(si);
4951 errno = saved_errno;
4954 static int swrap_recvmsg_before(int fd,
4955 struct socket_info *si,
4957 struct iovec *tmp_iov)
4964 (void)fd; /* unused */
4969 if (!si->connected) {
4974 if (msg->msg_iovlen == 0) {
4978 mtu = socket_wrapper_mtu();
4979 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4981 nlen = len + msg->msg_iov[i].iov_len;
4986 msg->msg_iovlen = i;
4987 if (msg->msg_iovlen == 0) {
4988 *tmp_iov = msg->msg_iov[0];
4989 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4991 msg->msg_iov = tmp_iov;
4992 msg->msg_iovlen = 1;
4997 if (msg->msg_name == NULL) {
5002 if (msg->msg_iovlen == 0) {
5006 if (si->bound == 0) {
5007 ret = swrap_auto_bind(fd, si, si->family);
5009 SWRAP_UNLOCK_SI(si);
5011 * When attempting to read or write to a
5012 * descriptor, if an underlying autobind fails
5013 * because it's not a socket, stop intercepting
5014 * uses of that descriptor.
5016 if (errno == ENOTSOCK) {
5017 swrap_remove_stale(fd);
5020 SWRAP_LOG(SWRAP_LOG_ERROR,
5021 "swrap_recvmsg_before failed");
5028 errno = EHOSTUNREACH;
5034 SWRAP_UNLOCK_SI(si);
5039 static int swrap_recvmsg_after(int fd,
5040 struct socket_info *si,
5042 const struct sockaddr_un *un_addr,
5043 socklen_t un_addrlen,
5046 int saved_errno = errno;
5048 uint8_t *buf = NULL;
5054 /* to give better errors */
5056 if (saved_errno == ENOENT) {
5057 saved_errno = EHOSTUNREACH;
5058 } else if (saved_errno == ENOTSOCK) {
5059 /* If the fd is not a socket, remove it */
5060 swrap_remove_stale(fd);
5064 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5065 avail += msg->msg_iov[i].iov_len;
5070 /* Convert the socket address before we leave */
5071 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5072 rc = sockaddr_convert_from_un(si,
5089 remain = MIN(80, avail);
5094 /* we capture it as one single packet */
5095 buf = (uint8_t *)malloc(remain);
5097 /* we just not capture the packet */
5098 SWRAP_UNLOCK_SI(si);
5099 errno = saved_errno;
5103 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5104 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5106 msg->msg_iov[i].iov_base,
5109 remain -= this_time;
5114 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5115 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5116 } else if (ret == 0) { /* END OF FILE */
5117 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5118 } else if (ret > 0) {
5119 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5128 if (un_addr != NULL) {
5129 swrap_pcap_dump_packet(si,
5135 swrap_pcap_dump_packet(si,
5148 errno = saved_errno;
5150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5152 msg->msg_controllen > 0 &&
5153 msg->msg_control != NULL) {
5154 rc = swrap_msghdr_add_socket_info(si, msg);
5156 SWRAP_UNLOCK_SI(si);
5162 SWRAP_UNLOCK_SI(si);
5166 /****************************************************************************
5168 ***************************************************************************/
5170 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5171 struct sockaddr *from, socklen_t *fromlen)
5173 struct swrap_address from_addr = {
5174 .sa_socklen = sizeof(struct sockaddr_un),
5177 struct socket_info *si = find_socket_info(s);
5178 struct swrap_address saddr = {
5179 .sa_socklen = sizeof(struct sockaddr_storage),
5186 return libc_recvfrom(s,
5198 if (from != NULL && fromlen != NULL) {
5199 msg.msg_name = from; /* optional address */
5200 msg.msg_namelen = *fromlen; /* size of address */
5202 msg.msg_name = &saddr.sa.s; /* optional address */
5203 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5205 msg.msg_iov = &tmp; /* scatter/gather array */
5206 msg.msg_iovlen = 1; /* # elements in msg_iov */
5207 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5208 msg.msg_control = NULL; /* ancillary data, see below */
5209 msg.msg_controllen = 0; /* ancillary data buffer len */
5210 msg.msg_flags = 0; /* flags on received message */
5213 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5218 buf = msg.msg_iov[0].iov_base;
5219 len = msg.msg_iov[0].iov_len;
5221 ret = libc_recvfrom(s,
5226 &from_addr.sa_socklen);
5231 tret = swrap_recvmsg_after(s,
5235 from_addr.sa_socklen,
5241 if (from != NULL && fromlen != NULL) {
5242 *fromlen = msg.msg_namelen;
5248 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5249 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5250 struct sockaddr *from, Psocklen_t fromlen)
5252 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5253 struct sockaddr *from, socklen_t *fromlen)
5256 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5259 /****************************************************************************
5261 ***************************************************************************/
5263 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5264 const struct sockaddr *to, socklen_t tolen)
5268 struct swrap_address un_addr = {
5269 .sa_socklen = sizeof(struct sockaddr_un),
5271 const struct sockaddr_un *to_un = NULL;
5274 struct socket_info *si = find_socket_info(s);
5278 return libc_sendto(s, buf, len, flags, to, tolen);
5281 tmp.iov_base = discard_const_p(char, buf);
5285 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5286 msg.msg_namelen = tolen; /* size of address */
5287 msg.msg_iov = &tmp; /* scatter/gather array */
5288 msg.msg_iovlen = 1; /* # elements in msg_iov */
5289 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5290 msg.msg_control = NULL; /* ancillary data, see below */
5291 msg.msg_controllen = 0; /* ancillary data buffer len */
5292 msg.msg_flags = 0; /* flags on received message */
5295 rc = swrap_sendmsg_before(s,
5307 buf = msg.msg_iov[0].iov_base;
5308 len = msg.msg_iov[0].iov_len;
5313 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5316 type = SOCKET_TYPE_CHAR_UDP;
5318 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5319 snprintf(un_addr.sa.un.sun_path,
5320 sizeof(un_addr.sa.un.sun_path),
5322 socket_wrapper_dir(), type, iface, prt);
5323 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5325 /* ignore the any errors in broadcast sends */
5331 un_addr.sa_socklen);
5336 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5338 SWRAP_UNLOCK_SI(si);
5345 * If it is a dgram socket and we are connected, don't include the
5348 if (si->type == SOCK_DGRAM && si->connected) {
5349 ret = libc_sendto(s,
5356 ret = libc_sendto(s,
5360 (struct sockaddr *)msg.msg_name,
5364 SWRAP_UNLOCK_SI(si);
5366 swrap_sendmsg_after(s, si, &msg, to, ret);
5371 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5372 const struct sockaddr *to, socklen_t tolen)
5374 return swrap_sendto(s, buf, len, flags, to, tolen);
5377 /****************************************************************************
5379 ***************************************************************************/
5381 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5383 struct socket_info *si;
5385 struct swrap_address saddr = {
5386 .sa_socklen = sizeof(struct sockaddr_storage),
5392 si = find_socket_info(s);
5394 return libc_recv(s, buf, len, flags);
5401 msg.msg_name = &saddr.sa.s; /* optional address */
5402 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5403 msg.msg_iov = &tmp; /* scatter/gather array */
5404 msg.msg_iovlen = 1; /* # elements in msg_iov */
5405 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5406 msg.msg_control = NULL; /* ancillary data, see below */
5407 msg.msg_controllen = 0; /* ancillary data buffer len */
5408 msg.msg_flags = 0; /* flags on received message */
5411 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5416 buf = msg.msg_iov[0].iov_base;
5417 len = msg.msg_iov[0].iov_len;
5419 ret = libc_recv(s, buf, len, flags);
5421 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5429 ssize_t recv(int s, void *buf, size_t len, int flags)
5431 return swrap_recv(s, buf, len, flags);
5434 /****************************************************************************
5436 ***************************************************************************/
5438 static ssize_t swrap_read(int s, void *buf, size_t len)
5440 struct socket_info *si;
5443 struct swrap_address saddr = {
5444 .sa_socklen = sizeof(struct sockaddr_storage),
5449 si = find_socket_info(s);
5451 return libc_read(s, buf, len);
5458 msg.msg_name = &saddr.sa.ss; /* optional address */
5459 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5460 msg.msg_iov = &tmp; /* scatter/gather array */
5461 msg.msg_iovlen = 1; /* # elements in msg_iov */
5462 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5463 msg.msg_control = NULL; /* ancillary data, see below */
5464 msg.msg_controllen = 0; /* ancillary data buffer len */
5465 msg.msg_flags = 0; /* flags on received message */
5468 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5470 if (tret == -ENOTSOCK) {
5471 return libc_read(s, buf, len);
5476 buf = msg.msg_iov[0].iov_base;
5477 len = msg.msg_iov[0].iov_len;
5479 ret = libc_read(s, buf, len);
5481 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5489 ssize_t read(int s, void *buf, size_t len)
5491 return swrap_read(s, buf, len);
5494 /****************************************************************************
5496 ***************************************************************************/
5498 static ssize_t swrap_write(int s, const void *buf, size_t len)
5502 struct sockaddr_un un_addr;
5505 struct socket_info *si;
5507 si = find_socket_info(s);
5509 return libc_write(s, buf, len);
5512 tmp.iov_base = discard_const_p(char, buf);
5516 msg.msg_name = NULL; /* optional address */
5517 msg.msg_namelen = 0; /* size of address */
5518 msg.msg_iov = &tmp; /* scatter/gather array */
5519 msg.msg_iovlen = 1; /* # elements in msg_iov */
5520 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5521 msg.msg_control = NULL; /* ancillary data, see below */
5522 msg.msg_controllen = 0; /* ancillary data buffer len */
5523 msg.msg_flags = 0; /* flags on received message */
5526 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5531 buf = msg.msg_iov[0].iov_base;
5532 len = msg.msg_iov[0].iov_len;
5534 ret = libc_write(s, buf, len);
5536 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5541 ssize_t write(int s, const void *buf, size_t len)
5543 return swrap_write(s, buf, len);
5546 /****************************************************************************
5548 ***************************************************************************/
5550 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5554 struct sockaddr_un un_addr;
5557 struct socket_info *si = find_socket_info(s);
5560 return libc_send(s, buf, len, flags);
5563 tmp.iov_base = discard_const_p(char, buf);
5567 msg.msg_name = NULL; /* optional address */
5568 msg.msg_namelen = 0; /* size of address */
5569 msg.msg_iov = &tmp; /* scatter/gather array */
5570 msg.msg_iovlen = 1; /* # elements in msg_iov */
5571 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5572 msg.msg_control = NULL; /* ancillary data, see below */
5573 msg.msg_controllen = 0; /* ancillary data buffer len */
5574 msg.msg_flags = 0; /* flags on received message */
5577 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5582 buf = msg.msg_iov[0].iov_base;
5583 len = msg.msg_iov[0].iov_len;
5585 ret = libc_send(s, buf, len, flags);
5587 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5592 ssize_t send(int s, const void *buf, size_t len, int flags)
5594 return swrap_send(s, buf, len, flags);
5597 /****************************************************************************
5599 ***************************************************************************/
5601 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5603 struct swrap_address from_addr = {
5604 .sa_socklen = sizeof(struct sockaddr_un),
5606 struct swrap_address convert_addr = {
5607 .sa_socklen = sizeof(struct sockaddr_storage),
5609 struct socket_info *si;
5612 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5613 size_t msg_ctrllen_filled;
5614 size_t msg_ctrllen_left;
5620 si = find_socket_info(s);
5622 return libc_recvmsg(s, omsg, flags);
5625 tmp.iov_base = NULL;
5629 msg.msg_name = &from_addr.sa; /* optional address */
5630 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5631 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5632 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5633 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5634 msg_ctrllen_filled = 0;
5635 msg_ctrllen_left = omsg->msg_controllen;
5637 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5638 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5639 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5642 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5647 ret = libc_recvmsg(s, &msg, flags);
5649 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5650 msg_ctrllen_filled += msg.msg_controllen;
5651 msg_ctrllen_left -= msg.msg_controllen;
5653 if (omsg->msg_control != NULL) {
5656 p = omsg->msg_control;
5657 p += msg_ctrllen_filled;
5659 msg.msg_control = p;
5660 msg.msg_controllen = msg_ctrllen_left;
5662 msg.msg_control = NULL;
5663 msg.msg_controllen = 0;
5668 * We convert the unix address to a IP address so we need a buffer
5669 * which can store the address in case of SOCK_DGRAM, see below.
5671 msg.msg_name = &convert_addr.sa;
5672 msg.msg_namelen = convert_addr.sa_socklen;
5674 rc = swrap_recvmsg_after(s,
5678 from_addr.sa_socklen,
5684 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5685 if (omsg->msg_control != NULL) {
5686 /* msg.msg_controllen = space left */
5687 msg_ctrllen_left = msg.msg_controllen;
5688 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5691 /* Update the original message length */
5692 omsg->msg_controllen = msg_ctrllen_filled;
5693 omsg->msg_flags = msg.msg_flags;
5695 omsg->msg_iovlen = msg.msg_iovlen;
5702 * The msg_name field points to a caller-allocated buffer that is
5703 * used to return the source address if the socket is unconnected. The
5704 * caller should set msg_namelen to the size of this buffer before this
5705 * call; upon return from a successful call, msg_name will contain the
5706 * length of the returned address. If the application does not need
5707 * to know the source address, msg_name can be specified as NULL.
5709 if (si->type == SOCK_STREAM) {
5710 omsg->msg_namelen = 0;
5711 } else if (omsg->msg_name != NULL &&
5712 omsg->msg_namelen != 0 &&
5713 omsg->msg_namelen >= msg.msg_namelen) {
5714 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5715 omsg->msg_namelen = msg.msg_namelen;
5718 SWRAP_UNLOCK_SI(si);
5723 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5725 return swrap_recvmsg(sockfd, msg, flags);
5728 /****************************************************************************
5730 ***************************************************************************/
5732 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5736 struct sockaddr_un un_addr;
5737 const struct sockaddr_un *to_un = NULL;
5738 const struct sockaddr *to = NULL;
5741 struct socket_info *si = find_socket_info(s);
5745 return libc_sendmsg(s, omsg, flags);
5748 ZERO_STRUCT(un_addr);
5750 tmp.iov_base = NULL;
5757 if (si->connected == 0) {
5758 msg.msg_name = omsg->msg_name; /* optional address */
5759 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5761 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5762 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5764 SWRAP_UNLOCK_SI(si);
5766 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5767 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5768 /* omsg is a const so use a local buffer for modifications */
5769 uint8_t cmbuf[omsg->msg_controllen];
5771 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5773 msg.msg_control = cmbuf; /* ancillary data, see below */
5774 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5776 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5779 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5787 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5795 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5796 avail += msg.msg_iov[i].iov_len;
5802 /* we capture it as one single packet */
5803 buf = (uint8_t *)malloc(remain);
5808 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5809 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5811 msg.msg_iov[i].iov_base,
5814 remain -= this_time;
5817 type = SOCKET_TYPE_CHAR_UDP;
5819 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5820 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5821 socket_wrapper_dir(), type, iface, prt);
5822 if (stat(un_addr.sun_path, &st) != 0) continue;
5824 msg.msg_name = &un_addr; /* optional address */
5825 msg.msg_namelen = sizeof(un_addr); /* size of address */
5827 /* ignore the any errors in broadcast sends */
5828 libc_sendmsg(s, &msg, flags);
5833 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5836 SWRAP_UNLOCK_SI(si);
5841 ret = libc_sendmsg(s, &msg, flags);
5843 swrap_sendmsg_after(s, si, &msg, to, ret);
5848 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5850 return swrap_sendmsg(s, omsg, flags);
5853 /****************************************************************************
5855 ***************************************************************************/
5857 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5859 struct socket_info *si;
5862 struct swrap_address saddr = {
5863 .sa_socklen = sizeof(struct sockaddr_storage)
5868 si = find_socket_info(s);
5870 return libc_readv(s, vector, count);
5873 tmp.iov_base = NULL;
5877 msg.msg_name = &saddr.sa.s; /* optional address */
5878 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5879 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5880 msg.msg_iovlen = count; /* # elements in msg_iov */
5881 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5882 msg.msg_control = NULL; /* ancillary data, see below */
5883 msg.msg_controllen = 0; /* ancillary data buffer len */
5884 msg.msg_flags = 0; /* flags on received message */
5887 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5889 if (rc == -ENOTSOCK) {
5890 return libc_readv(s, vector, count);
5895 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5897 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5905 ssize_t readv(int s, const struct iovec *vector, int count)
5907 return swrap_readv(s, vector, count);
5910 /****************************************************************************
5912 ***************************************************************************/
5914 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5918 struct sockaddr_un un_addr;
5921 struct socket_info *si = find_socket_info(s);
5924 return libc_writev(s, vector, count);
5927 tmp.iov_base = NULL;
5931 msg.msg_name = NULL; /* optional address */
5932 msg.msg_namelen = 0; /* size of address */
5933 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5934 msg.msg_iovlen = count; /* # elements in msg_iov */
5935 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5936 msg.msg_control = NULL; /* ancillary data, see below */
5937 msg.msg_controllen = 0; /* ancillary data buffer len */
5938 msg.msg_flags = 0; /* flags on received message */
5941 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5943 if (rc == -ENOTSOCK) {
5944 return libc_readv(s, vector, count);
5949 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5951 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5956 ssize_t writev(int s, const struct iovec *vector, int count)
5958 return swrap_writev(s, vector, count);
5961 /****************************
5963 ***************************/
5965 static int swrap_close(int fd)
5967 struct socket_info *si = NULL;
5971 swrap_mutex_lock(&socket_reset_mutex);
5973 si_index = find_socket_info_index(fd);
5974 if (si_index == -1) {
5975 swrap_mutex_unlock(&socket_reset_mutex);
5976 return libc_close(fd);
5979 reset_socket_info_index(fd);
5981 si = swrap_get_socket_info(si_index);
5983 swrap_mutex_lock(&first_free_mutex);
5986 ret = libc_close(fd);
5988 swrap_dec_refcount(si);
5990 if (swrap_get_refcount(si) > 0) {
5991 /* there are still references left */
5995 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5996 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5999 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6000 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6001 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6004 if (si->un_addr.sun_path[0] != '\0') {
6005 unlink(si->un_addr.sun_path);
6008 swrap_set_next_free(si, first_free);
6009 first_free = si_index;
6012 SWRAP_UNLOCK_SI(si);
6013 swrap_mutex_unlock(&first_free_mutex);
6014 swrap_mutex_unlock(&socket_reset_mutex);
6021 return swrap_close(fd);
6024 /****************************
6026 ***************************/
6028 static int swrap_dup(int fd)
6030 struct socket_info *si;
6033 idx = find_socket_info_index(fd);
6035 return libc_dup(fd);
6038 si = swrap_get_socket_info(idx);
6040 dup_fd = libc_dup(fd);
6042 int saved_errno = errno;
6043 errno = saved_errno;
6049 swrap_inc_refcount(si);
6051 SWRAP_UNLOCK_SI(si);
6053 /* Make sure we don't have an entry for the fd */
6054 swrap_remove_stale(dup_fd);
6056 set_socket_info_index(dup_fd, idx);
6063 return swrap_dup(fd);
6066 /****************************
6068 ***************************/
6070 static int swrap_dup2(int fd, int newfd)
6072 struct socket_info *si;
6075 idx = find_socket_info_index(fd);
6077 return libc_dup2(fd, newfd);
6080 si = swrap_get_socket_info(idx);
6084 * According to the manpage:
6086 * "If oldfd is a valid file descriptor, and newfd has the same
6087 * value as oldfd, then dup2() does nothing, and returns newfd."
6092 if (find_socket_info(newfd)) {
6093 /* dup2() does an implicit close of newfd, which we
6094 * need to emulate */
6098 dup_fd = libc_dup2(fd, newfd);
6100 int saved_errno = errno;
6101 errno = saved_errno;
6107 swrap_inc_refcount(si);
6109 SWRAP_UNLOCK_SI(si);
6111 /* Make sure we don't have an entry for the fd */
6112 swrap_remove_stale(dup_fd);
6114 set_socket_info_index(dup_fd, idx);
6119 int dup2(int fd, int newfd)
6121 return swrap_dup2(fd, newfd);
6124 /****************************
6126 ***************************/
6128 static int swrap_vfcntl(int fd, int cmd, va_list va)
6130 struct socket_info *si;
6131 int rc, dup_fd, idx;
6133 idx = find_socket_info_index(fd);
6135 return libc_vfcntl(fd, cmd, va);
6138 si = swrap_get_socket_info(idx);
6142 dup_fd = libc_vfcntl(fd, cmd, va);
6144 int saved_errno = errno;
6145 errno = saved_errno;
6151 swrap_inc_refcount(si);
6153 SWRAP_UNLOCK_SI(si);
6155 /* Make sure we don't have an entry for the fd */
6156 swrap_remove_stale(dup_fd);
6158 set_socket_info_index(dup_fd, idx);
6163 rc = libc_vfcntl(fd, cmd, va);
6170 int fcntl(int fd, int cmd, ...)
6177 rc = swrap_vfcntl(fd, cmd, va);
6184 /****************************
6186 ***************************/
6189 static int swrap_eventfd(int count, int flags)
6193 fd = libc_eventfd(count, flags);
6195 swrap_remove_stale(fd);
6201 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6202 int eventfd(unsigned int count, int flags)
6204 int eventfd(int count, int flags)
6207 return swrap_eventfd(count, flags);
6212 int pledge(const char *promises, const char *paths[])
6214 (void)promises; /* unused */
6215 (void)paths; /* unused */
6219 #endif /* HAVE_PLEDGE */
6221 static void swrap_thread_prepare(void)
6224 * This function should only be called here!!
6226 * We bind all symobls to avoid deadlocks of the fork is
6227 * interrupted by a signal handler using a symbol of this
6230 swrap_bind_symbol_all();
6235 static void swrap_thread_parent(void)
6240 static void swrap_thread_child(void)
6245 /****************************
6247 ***************************/
6248 void swrap_constructor(void)
6253 * If we hold a lock and the application forks, then the child
6254 * is not able to unlock the mutex and we are in a deadlock.
6255 * This should prevent such deadlocks.
6257 pthread_atfork(&swrap_thread_prepare,
6258 &swrap_thread_parent,
6259 &swrap_thread_child);
6261 ret = socket_wrapper_init_mutex(&sockets_mutex);
6263 SWRAP_LOG(SWRAP_LOG_ERROR,
6264 "Failed to initialize pthread mutex");
6268 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6270 SWRAP_LOG(SWRAP_LOG_ERROR,
6271 "Failed to initialize pthread mutex");
6275 ret = socket_wrapper_init_mutex(&first_free_mutex);
6277 SWRAP_LOG(SWRAP_LOG_ERROR,
6278 "Failed to initialize pthread mutex");
6283 /****************************
6285 ***************************/
6288 * This function is called when the library is unloaded and makes sure that
6289 * sockets get closed and the unix file for the socket are unlinked.
6291 void swrap_destructor(void)
6295 if (socket_fds_idx != NULL) {
6296 for (i = 0; i < socket_fds_max; ++i) {
6297 if (socket_fds_idx[i] != -1) {
6301 SAFE_FREE(socket_fds_idx);
6306 if (swrap.libc.handle != NULL) {
6307 dlclose(swrap.libc.handle);
6309 if (swrap.libc.socket_handle) {
6310 dlclose(swrap.libc.socket_handle);