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) {
1544 * Do not add a log here as some applications do stupid things
1547 * for (fd = 0; fd <= getdtablesize(); fd++) {
1551 * This would produce millions of lines of debug messages.
1554 SWRAP_LOG(SWRAP_LOG_ERROR,
1555 "Looking for a socket info for the fd %d is over the "
1556 "max socket index limit of %zu.",
1563 /* This builtin issues a full memory barrier. */
1564 __sync_synchronize();
1565 return socket_fds_idx[fd];
1568 static int swrap_add_socket_info(struct socket_info *si_input)
1570 struct socket_info *si = NULL;
1573 if (si_input == NULL) {
1578 swrap_mutex_lock(&first_free_mutex);
1579 if (first_free == -1) {
1584 si_index = first_free;
1585 si = swrap_get_socket_info(si_index);
1589 first_free = swrap_get_next_free(si);
1591 swrap_inc_refcount(si);
1593 SWRAP_UNLOCK_SI(si);
1596 swrap_mutex_unlock(&first_free_mutex);
1601 static int swrap_create_socket(struct socket_info *si, int fd)
1605 if ((size_t)fd >= socket_fds_max) {
1606 SWRAP_LOG(SWRAP_LOG_ERROR,
1607 "The max socket index limit of %zu has been reached, "
1614 idx = swrap_add_socket_info(si);
1619 set_socket_info_index(fd, idx);
1624 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1631 p = strrchr(un->sun_path, '/');
1632 if (p) p++; else p = un->sun_path;
1634 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1639 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1642 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1653 case SOCKET_TYPE_CHAR_TCP:
1654 case SOCKET_TYPE_CHAR_UDP: {
1655 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1657 if ((*len) < sizeof(*in2)) {
1662 memset(in2, 0, sizeof(*in2));
1663 in2->sin_family = AF_INET;
1664 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1665 in2->sin_port = htons(prt);
1667 *len = sizeof(*in2);
1671 case SOCKET_TYPE_CHAR_TCP_V6:
1672 case SOCKET_TYPE_CHAR_UDP_V6: {
1673 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1675 if ((*len) < sizeof(*in2)) {
1680 memset(in2, 0, sizeof(*in2));
1681 in2->sin6_family = AF_INET6;
1682 in2->sin6_addr = *swrap_ipv6();
1683 in2->sin6_addr.s6_addr[15] = iface;
1684 in2->sin6_port = htons(prt);
1686 *len = sizeof(*in2);
1698 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1706 if (bcast) *bcast = 0;
1708 switch (inaddr->sa_family) {
1710 const struct sockaddr_in *in =
1711 (const struct sockaddr_in *)(const void *)inaddr;
1712 unsigned int addr = ntohl(in->sin_addr.s_addr);
1719 u_type = SOCKET_TYPE_CHAR_TCP;
1722 u_type = SOCKET_TYPE_CHAR_UDP;
1723 a_type = SOCKET_TYPE_CHAR_UDP;
1724 b_type = SOCKET_TYPE_CHAR_UDP;
1727 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1728 errno = ESOCKTNOSUPPORT;
1732 prt = ntohs(in->sin_port);
1733 if (a_type && addr == 0xFFFFFFFF) {
1734 /* 255.255.255.255 only udp */
1737 iface = socket_wrapper_default_iface();
1738 } else if (b_type && addr == 0x7FFFFFFF) {
1739 /* 127.255.255.255 only udp */
1742 iface = socket_wrapper_default_iface();
1743 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1747 iface = (addr & 0x000000FF);
1749 errno = ENETUNREACH;
1752 if (bcast) *bcast = is_bcast;
1757 const struct sockaddr_in6 *in =
1758 (const struct sockaddr_in6 *)(const void *)inaddr;
1759 struct in6_addr cmp1, cmp2;
1763 type = SOCKET_TYPE_CHAR_TCP_V6;
1766 type = SOCKET_TYPE_CHAR_UDP_V6;
1769 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1770 errno = ESOCKTNOSUPPORT;
1774 /* XXX no multicast/broadcast */
1776 prt = ntohs(in->sin6_port);
1778 cmp1 = *swrap_ipv6();
1779 cmp2 = in->sin6_addr;
1780 cmp2.s6_addr[15] = 0;
1781 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1782 iface = in->sin6_addr.s6_addr[15];
1784 errno = ENETUNREACH;
1792 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1793 errno = ENETUNREACH;
1798 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1804 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1805 socket_wrapper_dir());
1806 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1807 /* the caller need to do more processing */
1811 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1812 socket_wrapper_dir(), type, iface, prt);
1813 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1818 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1827 if (bcast) *bcast = 0;
1829 switch (si->family) {
1831 const struct sockaddr_in *in =
1832 (const struct sockaddr_in *)(const void *)inaddr;
1833 unsigned int addr = ntohl(in->sin_addr.s_addr);
1839 prt = ntohs(in->sin_port);
1843 u_type = SOCKET_TYPE_CHAR_TCP;
1844 d_type = SOCKET_TYPE_CHAR_TCP;
1847 u_type = SOCKET_TYPE_CHAR_UDP;
1848 d_type = SOCKET_TYPE_CHAR_UDP;
1849 a_type = SOCKET_TYPE_CHAR_UDP;
1850 b_type = SOCKET_TYPE_CHAR_UDP;
1853 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1854 errno = ESOCKTNOSUPPORT;
1862 iface = socket_wrapper_default_iface();
1863 } else if (a_type && addr == 0xFFFFFFFF) {
1864 /* 255.255.255.255 only udp */
1867 iface = socket_wrapper_default_iface();
1868 } else if (b_type && addr == 0x7FFFFFFF) {
1869 /* 127.255.255.255 only udp */
1872 iface = socket_wrapper_default_iface();
1873 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1877 iface = (addr & 0x000000FF);
1879 errno = EADDRNOTAVAIL;
1883 /* Store the bind address for connect() */
1884 if (si->bindname.sa_socklen == 0) {
1885 struct sockaddr_in bind_in;
1886 socklen_t blen = sizeof(struct sockaddr_in);
1888 ZERO_STRUCT(bind_in);
1889 bind_in.sin_family = in->sin_family;
1890 bind_in.sin_port = in->sin_port;
1891 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1893 si->bindname.sa_socklen = blen;
1894 memcpy(&si->bindname.sa.in, &bind_in, blen);
1901 const struct sockaddr_in6 *in =
1902 (const struct sockaddr_in6 *)(const void *)inaddr;
1903 struct in6_addr cmp1, cmp2;
1907 type = SOCKET_TYPE_CHAR_TCP_V6;
1910 type = SOCKET_TYPE_CHAR_UDP_V6;
1913 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1914 errno = ESOCKTNOSUPPORT;
1918 /* XXX no multicast/broadcast */
1920 prt = ntohs(in->sin6_port);
1922 cmp1 = *swrap_ipv6();
1923 cmp2 = in->sin6_addr;
1924 cmp2.s6_addr[15] = 0;
1925 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1926 iface = socket_wrapper_default_iface();
1927 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1928 iface = in->sin6_addr.s6_addr[15];
1930 errno = EADDRNOTAVAIL;
1934 /* Store the bind address for connect() */
1935 if (si->bindname.sa_socklen == 0) {
1936 struct sockaddr_in6 bind_in;
1937 socklen_t blen = sizeof(struct sockaddr_in6);
1939 ZERO_STRUCT(bind_in);
1940 bind_in.sin6_family = in->sin6_family;
1941 bind_in.sin6_port = in->sin6_port;
1943 bind_in.sin6_addr = *swrap_ipv6();
1944 bind_in.sin6_addr.s6_addr[15] = iface;
1946 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1947 si->bindname.sa_socklen = blen;
1954 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1955 errno = EADDRNOTAVAIL;
1960 if (bcast) *bcast = is_bcast;
1962 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1968 /* handle auto-allocation of ephemeral ports */
1969 for (prt = 5001; prt < 10000; prt++) {
1970 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1971 socket_wrapper_dir(), type, iface, prt);
1972 if (stat(un->sun_path, &st) == 0) continue;
1974 set_port(si->family, prt, &si->myname);
1975 set_port(si->family, prt, &si->bindname);
1985 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1986 socket_wrapper_dir(), type, iface, prt);
1987 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1991 static struct socket_info *find_socket_info(int fd)
1993 int idx = find_socket_info_index(fd);
1999 return swrap_get_socket_info(idx);
2003 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
2005 struct socket_info_fd *f;
2006 const struct socket_info *last_s = NULL;
2008 /* first catch invalid input */
2009 switch (sa->sa_family) {
2011 if (len < sizeof(struct sockaddr_in)) {
2017 if (len < sizeof(struct sockaddr_in6)) {
2027 for (f = socket_fds; f; f = f->next) {
2028 struct socket_info *s = swrap_get_socket_info(f->si_index);
2035 if (s->myname == NULL) {
2038 if (s->myname->sa_family != sa->sa_family) {
2041 switch (s->myname->sa_family) {
2043 struct sockaddr_in *sin1, *sin2;
2045 sin1 = (struct sockaddr_in *)s->myname;
2046 sin2 = (struct sockaddr_in *)sa;
2048 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
2051 if (sin1->sin_port != sin2->sin_port) {
2054 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2064 struct sockaddr_in6 *sin1, *sin2;
2066 sin1 = (struct sockaddr_in6 *)s->myname;
2067 sin2 = (struct sockaddr_in6 *)sa;
2069 if (sin1->sin6_port != sin2->sin6_port) {
2072 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2094 static void swrap_remove_stale(int fd)
2096 struct socket_info *si;
2099 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2101 swrap_mutex_lock(&socket_reset_mutex);
2103 si_index = find_socket_info_index(fd);
2104 if (si_index == -1) {
2105 swrap_mutex_unlock(&socket_reset_mutex);
2109 reset_socket_info_index(fd);
2111 si = swrap_get_socket_info(si_index);
2113 swrap_mutex_lock(&first_free_mutex);
2116 swrap_dec_refcount(si);
2118 if (swrap_get_refcount(si) > 0) {
2122 if (si->un_addr.sun_path[0] != '\0') {
2123 unlink(si->un_addr.sun_path);
2126 swrap_set_next_free(si, first_free);
2127 first_free = si_index;
2130 SWRAP_UNLOCK_SI(si);
2131 swrap_mutex_unlock(&first_free_mutex);
2132 swrap_mutex_unlock(&socket_reset_mutex);
2135 static int sockaddr_convert_to_un(struct socket_info *si,
2136 const struct sockaddr *in_addr,
2138 struct sockaddr_un *out_addr,
2142 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2144 (void) in_len; /* unused */
2146 if (out_addr == NULL) {
2150 out->sa_family = AF_UNIX;
2151 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2152 out->sa_len = sizeof(*out_addr);
2155 switch (in_addr->sa_family) {
2157 const struct sockaddr_in *sin;
2158 if (si->family != AF_INET) {
2161 if (in_len < sizeof(struct sockaddr_in)) {
2164 sin = (const struct sockaddr_in *)(const void *)in_addr;
2165 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2170 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2171 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2185 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2186 errno = ESOCKTNOSUPPORT;
2190 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2192 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2198 errno = EAFNOSUPPORT;
2199 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2203 static int sockaddr_convert_from_un(const struct socket_info *si,
2204 const struct sockaddr_un *in_addr,
2205 socklen_t un_addrlen,
2207 struct sockaddr *out_addr,
2208 socklen_t *out_addrlen)
2212 if (out_addr == NULL || out_addrlen == NULL)
2215 if (un_addrlen == 0) {
2230 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2231 errno = ESOCKTNOSUPPORT;
2234 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2235 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2236 out_addr->sa_len = *out_addrlen;
2243 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2244 errno = EAFNOSUPPORT;
2248 enum swrap_packet_type {
2250 SWRAP_CONNECT_UNREACH,
2258 SWRAP_SENDTO_UNREACH,
2269 struct swrap_file_hdr {
2271 uint16_t version_major;
2272 uint16_t version_minor;
2275 uint32_t frame_max_len;
2276 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2279 #define SWRAP_FILE_HDR_SIZE 24
2281 struct swrap_packet_frame {
2283 uint32_t micro_seconds;
2284 uint32_t recorded_length;
2285 uint32_t full_length;
2287 #define SWRAP_PACKET_FRAME_SIZE 16
2289 union swrap_packet_ip {
2293 uint16_t packet_length;
2294 uint16_t identification;
2299 uint16_t hdr_checksum;
2303 #define SWRAP_PACKET_IP_V4_SIZE 20
2306 uint8_t flow_label_high;
2307 uint16_t flow_label_low;
2308 uint16_t payload_length;
2309 uint8_t next_header;
2311 uint8_t src_addr[16];
2312 uint8_t dest_addr[16];
2314 #define SWRAP_PACKET_IP_V6_SIZE 40
2316 #define SWRAP_PACKET_IP_SIZE 40
2318 union swrap_packet_payload {
2320 uint16_t source_port;
2330 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2332 uint16_t source_port;
2337 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2344 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2351 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2353 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2355 #define SWRAP_PACKET_MIN_ALLOC \
2356 (SWRAP_PACKET_FRAME_SIZE + \
2357 SWRAP_PACKET_IP_SIZE + \
2358 SWRAP_PACKET_PAYLOAD_SIZE)
2360 static const char *swrap_pcap_init_file(void)
2362 static int initialized = 0;
2363 static const char *s = NULL;
2364 static const struct swrap_file_hdr h;
2365 static const struct swrap_packet_frame f;
2366 static const union swrap_packet_ip i;
2367 static const union swrap_packet_payload p;
2369 if (initialized == 1) {
2375 * TODO: don't use the structs use plain buffer offsets
2376 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2378 * for now make sure we disable PCAP support
2379 * if the struct has alignment!
2381 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2384 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2387 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2390 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2393 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2396 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2399 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2402 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2405 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2408 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2412 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2416 if (strncmp(s, "./", 2) == 0) {
2422 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2423 const struct sockaddr *src,
2424 const struct sockaddr *dest,
2426 const uint8_t *payload,
2428 unsigned long tcp_seqno,
2429 unsigned long tcp_ack,
2430 unsigned char tcp_ctl,
2432 size_t *_packet_len)
2436 struct swrap_packet_frame *frame;
2437 union swrap_packet_ip *ip;
2438 union swrap_packet_payload *pay;
2441 size_t nonwire_len = sizeof(*frame);
2442 size_t wire_hdr_len = 0;
2443 size_t wire_len = 0;
2444 size_t ip_hdr_len = 0;
2445 size_t icmp_hdr_len = 0;
2446 size_t icmp_truncate_len = 0;
2447 uint8_t protocol = 0, icmp_protocol = 0;
2448 const struct sockaddr_in *src_in = NULL;
2449 const struct sockaddr_in *dest_in = NULL;
2451 const struct sockaddr_in6 *src_in6 = NULL;
2452 const struct sockaddr_in6 *dest_in6 = NULL;
2457 switch (src->sa_family) {
2459 src_in = (const struct sockaddr_in *)(const void *)src;
2460 dest_in = (const struct sockaddr_in *)(const void *)dest;
2461 src_port = src_in->sin_port;
2462 dest_port = dest_in->sin_port;
2463 ip_hdr_len = sizeof(ip->v4);
2467 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2468 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2469 src_port = src_in6->sin6_port;
2470 dest_port = dest_in6->sin6_port;
2471 ip_hdr_len = sizeof(ip->v6);
2478 switch (socket_type) {
2480 protocol = 0x06; /* TCP */
2481 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2482 wire_len = wire_hdr_len + payload_len;
2486 protocol = 0x11; /* UDP */
2487 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2488 wire_len = wire_hdr_len + payload_len;
2496 icmp_protocol = protocol;
2497 switch (src->sa_family) {
2499 protocol = 0x01; /* ICMPv4 */
2500 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2504 protocol = 0x3A; /* ICMPv6 */
2505 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2509 if (wire_len > 64 ) {
2510 icmp_truncate_len = wire_len - 64;
2512 wire_hdr_len += icmp_hdr_len;
2513 wire_len += icmp_hdr_len;
2516 packet_len = nonwire_len + wire_len;
2517 alloc_len = packet_len;
2518 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2519 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2522 base = (uint8_t *)calloc(1, alloc_len);
2529 frame = (struct swrap_packet_frame *)(void *)buf;
2530 frame->seconds = tval->tv_sec;
2531 frame->micro_seconds = tval->tv_usec;
2532 frame->recorded_length = wire_len - icmp_truncate_len;
2533 frame->full_length = wire_len - icmp_truncate_len;
2534 buf += SWRAP_PACKET_FRAME_SIZE;
2536 ip = (union swrap_packet_ip *)(void *)buf;
2537 switch (src->sa_family) {
2539 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2541 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2542 ip->v4.identification = htons(0xFFFF);
2543 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2544 ip->v4.fragment = htons(0x0000);
2546 ip->v4.protocol = protocol;
2547 ip->v4.hdr_checksum = htons(0x0000);
2548 ip->v4.src_addr = src_in->sin_addr.s_addr;
2549 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2550 buf += SWRAP_PACKET_IP_V4_SIZE;
2554 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2555 ip->v6.flow_label_high = 0x00;
2556 ip->v6.flow_label_low = 0x0000;
2557 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2558 ip->v6.next_header = protocol;
2559 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2560 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2561 buf += SWRAP_PACKET_IP_V6_SIZE;
2567 pay = (union swrap_packet_payload *)(void *)buf;
2568 switch (src->sa_family) {
2570 pay->icmp4.type = 0x03; /* destination unreachable */
2571 pay->icmp4.code = 0x01; /* host unreachable */
2572 pay->icmp4.checksum = htons(0x0000);
2573 pay->icmp4.unused = htonl(0x00000000);
2574 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2576 /* set the ip header in the ICMP payload */
2577 ip = (union swrap_packet_ip *)(void *)buf;
2578 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2580 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2581 ip->v4.identification = htons(0xFFFF);
2582 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2583 ip->v4.fragment = htons(0x0000);
2585 ip->v4.protocol = icmp_protocol;
2586 ip->v4.hdr_checksum = htons(0x0000);
2587 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2588 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2589 buf += SWRAP_PACKET_IP_V4_SIZE;
2591 src_port = dest_in->sin_port;
2592 dest_port = src_in->sin_port;
2596 pay->icmp6.type = 0x01; /* destination unreachable */
2597 pay->icmp6.code = 0x03; /* address unreachable */
2598 pay->icmp6.checksum = htons(0x0000);
2599 pay->icmp6.unused = htonl(0x00000000);
2600 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2602 /* set the ip header in the ICMP payload */
2603 ip = (union swrap_packet_ip *)(void *)buf;
2604 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2605 ip->v6.flow_label_high = 0x00;
2606 ip->v6.flow_label_low = 0x0000;
2607 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2608 ip->v6.next_header = protocol;
2609 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2610 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2611 buf += SWRAP_PACKET_IP_V6_SIZE;
2613 src_port = dest_in6->sin6_port;
2614 dest_port = src_in6->sin6_port;
2620 pay = (union swrap_packet_payload *)(void *)buf;
2622 switch (socket_type) {
2624 pay->tcp.source_port = src_port;
2625 pay->tcp.dest_port = dest_port;
2626 pay->tcp.seq_num = htonl(tcp_seqno);
2627 pay->tcp.ack_num = htonl(tcp_ack);
2628 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2629 pay->tcp.control = tcp_ctl;
2630 pay->tcp.window = htons(0x7FFF);
2631 pay->tcp.checksum = htons(0x0000);
2632 pay->tcp.urg = htons(0x0000);
2633 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2638 pay->udp.source_port = src_port;
2639 pay->udp.dest_port = dest_port;
2640 pay->udp.length = htons(8 + payload_len);
2641 pay->udp.checksum = htons(0x0000);
2642 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2647 if (payload && payload_len > 0) {
2648 memcpy(buf, payload, payload_len);
2651 *_packet_len = packet_len - icmp_truncate_len;
2655 static int swrap_pcap_get_fd(const char *fname)
2663 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2665 struct swrap_file_hdr file_hdr;
2666 file_hdr.magic = 0xA1B2C3D4;
2667 file_hdr.version_major = 0x0002;
2668 file_hdr.version_minor = 0x0004;
2669 file_hdr.timezone = 0x00000000;
2670 file_hdr.sigfigs = 0x00000000;
2671 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2672 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2674 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2681 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2686 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2687 const struct sockaddr *addr,
2688 enum swrap_packet_type type,
2689 const void *buf, size_t len,
2692 const struct sockaddr *src_addr;
2693 const struct sockaddr *dest_addr;
2694 unsigned long tcp_seqno = 0;
2695 unsigned long tcp_ack = 0;
2696 unsigned char tcp_ctl = 0;
2697 int unreachable = 0;
2701 switch (si->family) {
2713 case SWRAP_CONNECT_SEND:
2714 if (si->type != SOCK_STREAM) {
2718 src_addr = &si->myname.sa.s;
2721 tcp_seqno = si->io.pck_snd;
2722 tcp_ack = si->io.pck_rcv;
2723 tcp_ctl = 0x02; /* SYN */
2725 si->io.pck_snd += 1;
2729 case SWRAP_CONNECT_RECV:
2730 if (si->type != SOCK_STREAM) {
2734 dest_addr = &si->myname.sa.s;
2737 tcp_seqno = si->io.pck_rcv;
2738 tcp_ack = si->io.pck_snd;
2739 tcp_ctl = 0x12; /** SYN,ACK */
2741 si->io.pck_rcv += 1;
2745 case SWRAP_CONNECT_UNREACH:
2746 if (si->type != SOCK_STREAM) {
2750 dest_addr = &si->myname.sa.s;
2753 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2754 tcp_seqno = si->io.pck_snd - 1;
2755 tcp_ack = si->io.pck_rcv;
2756 tcp_ctl = 0x02; /* SYN */
2761 case SWRAP_CONNECT_ACK:
2762 if (si->type != SOCK_STREAM) {
2766 src_addr = &si->myname.sa.s;
2769 tcp_seqno = si->io.pck_snd;
2770 tcp_ack = si->io.pck_rcv;
2771 tcp_ctl = 0x10; /* ACK */
2775 case SWRAP_ACCEPT_SEND:
2776 if (si->type != SOCK_STREAM) {
2780 dest_addr = &si->myname.sa.s;
2783 tcp_seqno = si->io.pck_rcv;
2784 tcp_ack = si->io.pck_snd;
2785 tcp_ctl = 0x02; /* SYN */
2787 si->io.pck_rcv += 1;
2791 case SWRAP_ACCEPT_RECV:
2792 if (si->type != SOCK_STREAM) {
2796 src_addr = &si->myname.sa.s;
2799 tcp_seqno = si->io.pck_snd;
2800 tcp_ack = si->io.pck_rcv;
2801 tcp_ctl = 0x12; /* SYN,ACK */
2803 si->io.pck_snd += 1;
2807 case SWRAP_ACCEPT_ACK:
2808 if (si->type != SOCK_STREAM) {
2812 dest_addr = &si->myname.sa.s;
2815 tcp_seqno = si->io.pck_rcv;
2816 tcp_ack = si->io.pck_snd;
2817 tcp_ctl = 0x10; /* ACK */
2822 src_addr = &si->myname.sa.s;
2823 dest_addr = &si->peername.sa.s;
2825 tcp_seqno = si->io.pck_snd;
2826 tcp_ack = si->io.pck_rcv;
2827 tcp_ctl = 0x18; /* PSH,ACK */
2829 si->io.pck_snd += len;
2833 case SWRAP_SEND_RST:
2834 dest_addr = &si->myname.sa.s;
2835 src_addr = &si->peername.sa.s;
2837 if (si->type == SOCK_DGRAM) {
2838 return swrap_pcap_marshall_packet(si,
2840 SWRAP_SENDTO_UNREACH,
2846 tcp_seqno = si->io.pck_rcv;
2847 tcp_ack = si->io.pck_snd;
2848 tcp_ctl = 0x14; /** RST,ACK */
2852 case SWRAP_PENDING_RST:
2853 dest_addr = &si->myname.sa.s;
2854 src_addr = &si->peername.sa.s;
2856 if (si->type == SOCK_DGRAM) {
2860 tcp_seqno = si->io.pck_rcv;
2861 tcp_ack = si->io.pck_snd;
2862 tcp_ctl = 0x14; /* RST,ACK */
2867 dest_addr = &si->myname.sa.s;
2868 src_addr = &si->peername.sa.s;
2870 tcp_seqno = si->io.pck_rcv;
2871 tcp_ack = si->io.pck_snd;
2872 tcp_ctl = 0x18; /* PSH,ACK */
2874 si->io.pck_rcv += len;
2878 case SWRAP_RECV_RST:
2879 dest_addr = &si->myname.sa.s;
2880 src_addr = &si->peername.sa.s;
2882 if (si->type == SOCK_DGRAM) {
2886 tcp_seqno = si->io.pck_rcv;
2887 tcp_ack = si->io.pck_snd;
2888 tcp_ctl = 0x14; /* RST,ACK */
2893 src_addr = &si->myname.sa.s;
2896 si->io.pck_snd += len;
2900 case SWRAP_SENDTO_UNREACH:
2901 dest_addr = &si->myname.sa.s;
2908 case SWRAP_RECVFROM:
2909 dest_addr = &si->myname.sa.s;
2912 si->io.pck_rcv += len;
2916 case SWRAP_CLOSE_SEND:
2917 if (si->type != SOCK_STREAM) {
2921 src_addr = &si->myname.sa.s;
2922 dest_addr = &si->peername.sa.s;
2924 tcp_seqno = si->io.pck_snd;
2925 tcp_ack = si->io.pck_rcv;
2926 tcp_ctl = 0x11; /* FIN, ACK */
2928 si->io.pck_snd += 1;
2932 case SWRAP_CLOSE_RECV:
2933 if (si->type != SOCK_STREAM) {
2937 dest_addr = &si->myname.sa.s;
2938 src_addr = &si->peername.sa.s;
2940 tcp_seqno = si->io.pck_rcv;
2941 tcp_ack = si->io.pck_snd;
2942 tcp_ctl = 0x11; /* FIN,ACK */
2944 si->io.pck_rcv += 1;
2948 case SWRAP_CLOSE_ACK:
2949 if (si->type != SOCK_STREAM) {
2953 src_addr = &si->myname.sa.s;
2954 dest_addr = &si->peername.sa.s;
2956 tcp_seqno = si->io.pck_snd;
2957 tcp_ack = si->io.pck_rcv;
2958 tcp_ctl = 0x10; /* ACK */
2965 swrapGetTimeOfDay(&tv);
2967 return swrap_pcap_packet_init(&tv,
2971 (const uint8_t *)buf,
2980 static void swrap_pcap_dump_packet(struct socket_info *si,
2981 const struct sockaddr *addr,
2982 enum swrap_packet_type type,
2983 const void *buf, size_t len)
2985 const char *file_name;
2987 size_t packet_len = 0;
2990 swrap_mutex_lock(&pcap_dump_mutex);
2992 file_name = swrap_pcap_init_file();
2997 packet = swrap_pcap_marshall_packet(si,
3003 if (packet == NULL) {
3007 fd = swrap_pcap_get_fd(file_name);
3009 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
3018 swrap_mutex_unlock(&pcap_dump_mutex);
3021 /****************************************************************************
3023 ***************************************************************************/
3025 #ifdef HAVE_SIGNALFD
3026 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
3030 rc = libc_signalfd(fd, mask, flags);
3032 swrap_remove_stale(fd);
3038 int signalfd(int fd, const sigset_t *mask, int flags)
3040 return swrap_signalfd(fd, mask, flags);
3044 /****************************************************************************
3046 ***************************************************************************/
3048 static int swrap_socket(int family, int type, int protocol)
3050 struct socket_info *si = NULL;
3051 struct socket_info _si = { 0 };
3054 int real_type = type;
3057 * Remove possible addition flags passed to socket() so
3058 * do not fail checking the type.
3059 * See https://lwn.net/Articles/281965/
3062 real_type &= ~SOCK_CLOEXEC;
3064 #ifdef SOCK_NONBLOCK
3065 real_type &= ~SOCK_NONBLOCK;
3068 if (!socket_wrapper_enabled()) {
3069 return libc_socket(family, type, protocol);
3080 #endif /* AF_NETLINK */
3083 #endif /* AF_PACKET */
3085 return libc_socket(family, type, protocol);
3087 errno = EAFNOSUPPORT;
3091 switch (real_type) {
3097 errno = EPROTONOSUPPORT;
3105 if (real_type == SOCK_STREAM) {
3110 if (real_type == SOCK_DGRAM) {
3115 errno = EPROTONOSUPPORT;
3120 * We must call libc_socket with type, from the caller, not the version
3121 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3123 fd = libc_socket(AF_UNIX, type, 0);
3129 /* Check if we have a stale fd and remove it */
3130 swrap_remove_stale(fd);
3133 si->family = family;
3135 /* however, the rest of the socket_wrapper code expects just
3136 * the type, not the flags */
3137 si->type = real_type;
3138 si->protocol = protocol;
3141 * Setup myname so getsockname() can succeed to find out the socket
3144 switch(si->family) {
3146 struct sockaddr_in sin = {
3147 .sin_family = AF_INET,
3150 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3151 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3156 struct sockaddr_in6 sin6 = {
3157 .sin6_family = AF_INET6,
3160 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3161 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3170 ret = swrap_create_socket(si, fd);
3175 SWRAP_LOG(SWRAP_LOG_TRACE,
3176 "Created %s socket for protocol %s, fd=%d",
3177 family == AF_INET ? "IPv4" : "IPv6",
3178 real_type == SOCK_DGRAM ? "UDP" : "TCP",
3184 int socket(int family, int type, int protocol)
3186 return swrap_socket(family, type, protocol);
3189 /****************************************************************************
3191 ***************************************************************************/
3193 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3197 rc = libc_socketpair(family, type, protocol, sv);
3199 swrap_remove_stale(sv[0]);
3200 swrap_remove_stale(sv[1]);
3206 int socketpair(int family, int type, int protocol, int sv[2])
3208 return swrap_socketpair(family, type, protocol, sv);
3211 /****************************************************************************
3213 ***************************************************************************/
3215 #ifdef HAVE_TIMERFD_CREATE
3216 static int swrap_timerfd_create(int clockid, int flags)
3220 fd = libc_timerfd_create(clockid, flags);
3222 swrap_remove_stale(fd);
3228 int timerfd_create(int clockid, int flags)
3230 return swrap_timerfd_create(clockid, flags);
3234 /****************************************************************************
3236 ***************************************************************************/
3238 static int swrap_pipe(int pipefd[2])
3242 rc = libc_pipe(pipefd);
3244 swrap_remove_stale(pipefd[0]);
3245 swrap_remove_stale(pipefd[1]);
3251 int pipe(int pipefd[2])
3253 return swrap_pipe(pipefd);
3256 /****************************************************************************
3258 ***************************************************************************/
3260 static int swrap_accept(int s,
3261 struct sockaddr *addr,
3265 struct socket_info *parent_si, *child_si;
3266 struct socket_info new_si = { 0 };
3269 struct swrap_address un_addr = {
3270 .sa_socklen = sizeof(struct sockaddr_un),
3272 struct swrap_address un_my_addr = {
3273 .sa_socklen = sizeof(struct sockaddr_un),
3275 struct swrap_address in_addr = {
3276 .sa_socklen = sizeof(struct sockaddr_storage),
3278 struct swrap_address in_my_addr = {
3279 .sa_socklen = sizeof(struct sockaddr_storage),
3283 parent_si = find_socket_info(s);
3286 return libc_accept4(s, addr, addrlen, flags);
3289 return libc_accept(s, addr, addrlen);
3295 * prevent parent_si from being altered / closed
3298 SWRAP_LOCK_SI(parent_si);
3301 * assume out sockaddr have the same size as the in parent
3304 in_addr.sa_socklen = socket_length(parent_si->family);
3305 if (in_addr.sa_socklen <= 0) {
3306 SWRAP_UNLOCK_SI(parent_si);
3311 SWRAP_UNLOCK_SI(parent_si);
3314 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3317 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3320 if (errno == ENOTSOCK) {
3321 /* Remove stale fds */
3322 swrap_remove_stale(s);
3329 SWRAP_LOCK_SI(parent_si);
3331 ret = sockaddr_convert_from_un(parent_si,
3336 &in_addr.sa_socklen);
3338 SWRAP_UNLOCK_SI(parent_si);
3345 child_si->family = parent_si->family;
3346 child_si->type = parent_si->type;
3347 child_si->protocol = parent_si->protocol;
3348 child_si->bound = 1;
3349 child_si->is_server = 1;
3350 child_si->connected = 1;
3352 SWRAP_UNLOCK_SI(parent_si);
3354 child_si->peername = (struct swrap_address) {
3355 .sa_socklen = in_addr.sa_socklen,
3357 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3359 if (addr != NULL && addrlen != NULL) {
3360 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3362 memcpy(addr, &in_addr.sa.ss, copy_len);
3364 *addrlen = in_addr.sa_socklen;
3367 ret = libc_getsockname(fd,
3369 &un_my_addr.sa_socklen);
3375 ret = sockaddr_convert_from_un(child_si,
3377 un_my_addr.sa_socklen,
3380 &in_my_addr.sa_socklen);
3386 SWRAP_LOG(SWRAP_LOG_TRACE,
3387 "accept() path=%s, fd=%d",
3388 un_my_addr.sa.un.sun_path, s);
3390 child_si->myname = (struct swrap_address) {
3391 .sa_socklen = in_my_addr.sa_socklen,
3393 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3395 idx = swrap_create_socket(&new_si, fd);
3402 struct socket_info *si = swrap_get_socket_info(idx);
3405 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3406 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3407 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3408 SWRAP_UNLOCK_SI(si);
3415 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3417 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3421 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3422 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3424 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3427 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3430 static int autobind_start_init;
3431 static int autobind_start;
3433 /* using sendto() or connect() on an unbound socket would give the
3434 recipient no way to reply, as unlike UDP and TCP, a unix domain
3435 socket can't auto-assign ephemeral port numbers, so we need to
3437 Note: this might change the family from ipv6 to ipv4
3439 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3441 struct swrap_address un_addr = {
3442 .sa_socklen = sizeof(struct sockaddr_un),
3450 swrap_mutex_lock(&autobind_start_mutex);
3452 if (autobind_start_init != 1) {
3453 autobind_start_init = 1;
3454 autobind_start = getpid();
3455 autobind_start %= 50000;
3456 autobind_start += 10000;
3459 un_addr.sa.un.sun_family = AF_UNIX;
3463 struct sockaddr_in in;
3467 type = SOCKET_TYPE_CHAR_TCP;
3470 type = SOCKET_TYPE_CHAR_UDP;
3473 errno = ESOCKTNOSUPPORT;
3478 memset(&in, 0, sizeof(in));
3479 in.sin_family = AF_INET;
3480 in.sin_addr.s_addr = htonl(127<<24 |
3481 socket_wrapper_default_iface());
3483 si->myname = (struct swrap_address) {
3484 .sa_socklen = sizeof(in),
3486 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3491 struct sockaddr_in6 in6;
3493 if (si->family != family) {
3494 errno = ENETUNREACH;
3501 type = SOCKET_TYPE_CHAR_TCP_V6;
3504 type = SOCKET_TYPE_CHAR_UDP_V6;
3507 errno = ESOCKTNOSUPPORT;
3512 memset(&in6, 0, sizeof(in6));
3513 in6.sin6_family = AF_INET6;
3514 in6.sin6_addr = *swrap_ipv6();
3515 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3517 si->myname = (struct swrap_address) {
3518 .sa_socklen = sizeof(in6),
3520 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3525 errno = ESOCKTNOSUPPORT;
3530 if (autobind_start > 60000) {
3531 autobind_start = 10000;
3534 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3535 port = autobind_start + i;
3536 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3537 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3538 type, socket_wrapper_default_iface(), port);
3539 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3541 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3546 si->un_addr = un_addr.sa.un;
3549 autobind_start = port + 1;
3552 if (i == SOCKET_MAX_SOCKETS) {
3553 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3554 "interface "SOCKET_FORMAT,
3557 socket_wrapper_default_iface(),
3564 si->family = family;
3565 set_port(si->family, port, &si->myname);
3570 swrap_mutex_unlock(&autobind_start_mutex);
3574 /****************************************************************************
3576 ***************************************************************************/
3578 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3582 struct swrap_address un_addr = {
3583 .sa_socklen = sizeof(struct sockaddr_un),
3585 struct socket_info *si = find_socket_info(s);
3589 return libc_connect(s, serv_addr, addrlen);
3594 if (si->bound == 0) {
3595 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3601 if (si->family != serv_addr->sa_family) {
3607 ret = sockaddr_convert_to_un(si, serv_addr,
3608 addrlen, &un_addr.sa.un, 0, &bcast);
3614 errno = ENETUNREACH;
3619 if (si->type == SOCK_DGRAM) {
3620 si->defer_connect = 1;
3623 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3625 ret = libc_connect(s,
3627 un_addr.sa_socklen);
3630 SWRAP_LOG(SWRAP_LOG_TRACE,
3631 "connect() path=%s, fd=%d",
3632 un_addr.sa.un.sun_path, s);
3635 /* to give better errors */
3636 if (ret == -1 && errno == ENOENT) {
3637 errno = EHOSTUNREACH;
3641 si->peername = (struct swrap_address) {
3642 .sa_socklen = addrlen,
3645 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3649 * When we connect() on a socket than we have to bind the
3650 * outgoing connection on the interface we use for the
3651 * transport. We already bound it on the right interface
3652 * but here we have to update the name so getsockname()
3653 * returns correct information.
3655 if (si->bindname.sa_socklen > 0) {
3656 si->myname = (struct swrap_address) {
3657 .sa_socklen = si->bindname.sa_socklen,
3660 memcpy(&si->myname.sa.ss,
3661 &si->bindname.sa.ss,
3662 si->bindname.sa_socklen);
3664 /* Cleanup bindname */
3665 si->bindname = (struct swrap_address) {
3670 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3671 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3673 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3677 SWRAP_UNLOCK_SI(si);
3681 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3683 return swrap_connect(s, serv_addr, addrlen);
3686 /****************************************************************************
3688 ***************************************************************************/
3690 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3693 struct swrap_address un_addr = {
3694 .sa_socklen = sizeof(struct sockaddr_un),
3696 struct socket_info *si = find_socket_info(s);
3703 return libc_bind(s, myaddr, addrlen);
3708 switch (si->family) {
3710 const struct sockaddr_in *sin;
3711 if (addrlen < sizeof(struct sockaddr_in)) {
3712 bind_error = EINVAL;
3716 sin = (const struct sockaddr_in *)(const void *)myaddr;
3718 if (sin->sin_family != AF_INET) {
3719 bind_error = EAFNOSUPPORT;
3722 /* special case for AF_UNSPEC */
3723 if (sin->sin_family == AF_UNSPEC &&
3724 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3733 const struct sockaddr_in6 *sin6;
3734 if (addrlen < sizeof(struct sockaddr_in6)) {
3735 bind_error = EINVAL;
3739 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3741 if (sin6->sin6_family != AF_INET6) {
3742 bind_error = EAFNOSUPPORT;
3749 bind_error = EINVAL;
3753 if (bind_error != 0) {
3760 in_use = check_addr_port_in_use(myaddr, addrlen);
3768 si->myname.sa_socklen = addrlen;
3769 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3771 ret = sockaddr_convert_to_un(si,
3781 unlink(un_addr.sa.un.sun_path);
3783 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3785 SWRAP_LOG(SWRAP_LOG_TRACE,
3786 "bind() path=%s, fd=%d",
3787 un_addr.sa.un.sun_path, s);
3794 SWRAP_UNLOCK_SI(si);
3799 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3801 return swrap_bind(s, myaddr, addrlen);
3804 /****************************************************************************
3806 ***************************************************************************/
3808 #ifdef HAVE_BINDRESVPORT
3809 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3811 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3813 struct swrap_address myaddr = {
3814 .sa_socklen = sizeof(struct sockaddr_storage),
3817 static uint16_t port;
3822 #define SWRAP_STARTPORT 600
3823 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3824 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3827 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3831 salen = myaddr.sa_socklen;
3834 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3840 memset(&myaddr.sa.ss, 0, salen);
3845 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3848 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3850 salen = sizeof(struct sockaddr_in);
3851 sinp->sin_port = htons(port);
3855 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3857 salen = sizeof(struct sockaddr_in6);
3858 sin6p->sin6_port = htons(port);
3862 errno = EAFNOSUPPORT;
3867 if (port > SWRAP_ENDPORT) {
3868 port = SWRAP_STARTPORT;
3871 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3872 if (rc == 0 || errno != EADDRINUSE) {
3880 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3882 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3886 /****************************************************************************
3888 ***************************************************************************/
3890 static int swrap_listen(int s, int backlog)
3893 struct socket_info *si = find_socket_info(s);
3896 return libc_listen(s, backlog);
3901 if (si->bound == 0) {
3902 ret = swrap_auto_bind(s, si, si->family);
3909 ret = libc_listen(s, backlog);
3912 SWRAP_UNLOCK_SI(si);
3917 int listen(int s, int backlog)
3919 return swrap_listen(s, backlog);
3922 /****************************************************************************
3924 ***************************************************************************/
3926 static FILE *swrap_fopen(const char *name, const char *mode)
3930 fp = libc_fopen(name, mode);
3932 int fd = fileno(fp);
3934 swrap_remove_stale(fd);
3940 FILE *fopen(const char *name, const char *mode)
3942 return swrap_fopen(name, mode);
3945 /****************************************************************************
3947 ***************************************************************************/
3950 static FILE *swrap_fopen64(const char *name, const char *mode)
3954 fp = libc_fopen64(name, mode);
3956 int fd = fileno(fp);
3958 swrap_remove_stale(fd);
3964 FILE *fopen64(const char *name, const char *mode)
3966 return swrap_fopen64(name, mode);
3968 #endif /* HAVE_FOPEN64 */
3970 /****************************************************************************
3972 ***************************************************************************/
3974 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3978 ret = libc_vopen(pathname, flags, ap);
3981 * There are methods for closing descriptors (libc-internal code
3982 * paths, direct syscalls) which close descriptors in ways that
3983 * we can't intercept, so try to recover when we notice that
3986 swrap_remove_stale(ret);
3991 int open(const char *pathname, int flags, ...)
3996 va_start(ap, flags);
3997 fd = swrap_vopen(pathname, flags, ap);
4003 /****************************************************************************
4005 ***************************************************************************/
4008 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
4012 ret = libc_vopen64(pathname, flags, ap);
4015 * There are methods for closing descriptors (libc-internal code
4016 * paths, direct syscalls) which close descriptors in ways that
4017 * we can't intercept, so try to recover when we notice that
4020 swrap_remove_stale(ret);
4025 int open64(const char *pathname, int flags, ...)
4030 va_start(ap, flags);
4031 fd = swrap_vopen64(pathname, flags, ap);
4036 #endif /* HAVE_OPEN64 */
4038 /****************************************************************************
4040 ***************************************************************************/
4042 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
4046 ret = libc_vopenat(dirfd, path, flags, ap);
4049 * There are methods for closing descriptors (libc-internal code
4050 * paths, direct syscalls) which close descriptors in ways that
4051 * we can't intercept, so try to recover when we notice that
4054 swrap_remove_stale(ret);
4060 int openat(int dirfd, const char *path, int flags, ...)
4065 va_start(ap, flags);
4066 fd = swrap_vopenat(dirfd, path, flags, ap);
4072 /****************************************************************************
4074 ***************************************************************************/
4076 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4078 struct socket_info *si = find_socket_info(s);
4083 return libc_getpeername(s, name, addrlen);
4088 if (si->peername.sa_socklen == 0)
4094 len = MIN(*addrlen, si->peername.sa_socklen);
4100 memcpy(name, &si->peername.sa.ss, len);
4101 *addrlen = si->peername.sa_socklen;
4105 SWRAP_UNLOCK_SI(si);
4110 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4111 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4113 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4116 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4119 /****************************************************************************
4121 ***************************************************************************/
4123 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4125 struct socket_info *si = find_socket_info(s);
4130 return libc_getsockname(s, name, addrlen);
4135 len = MIN(*addrlen, si->myname.sa_socklen);
4141 memcpy(name, &si->myname.sa.ss, len);
4142 *addrlen = si->myname.sa_socklen;
4146 SWRAP_UNLOCK_SI(si);
4151 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4152 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4154 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4157 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4160 /****************************************************************************
4162 ***************************************************************************/
4165 # ifdef SO_PROTOTYPE /* The Solaris name */
4166 # define SO_PROTOCOL SO_PROTOTYPE
4167 # endif /* SO_PROTOTYPE */
4168 #endif /* SO_PROTOCOL */
4170 static int swrap_getsockopt(int s, int level, int optname,
4171 void *optval, socklen_t *optlen)
4173 struct socket_info *si = find_socket_info(s);
4177 return libc_getsockopt(s,
4186 if (level == SOL_SOCKET) {
4190 if (optval == NULL || optlen == NULL ||
4191 *optlen < (socklen_t)sizeof(int)) {
4197 *optlen = sizeof(int);
4198 *(int *)optval = si->family;
4201 #endif /* SO_DOMAIN */
4205 if (optval == NULL || optlen == NULL ||
4206 *optlen < (socklen_t)sizeof(int)) {
4212 *optlen = sizeof(int);
4213 *(int *)optval = si->protocol;
4216 #endif /* SO_PROTOCOL */
4218 if (optval == NULL || optlen == NULL ||
4219 *optlen < (socklen_t)sizeof(int)) {
4225 *optlen = sizeof(int);
4226 *(int *)optval = si->type;
4230 ret = libc_getsockopt(s,
4237 } else if (level == IPPROTO_TCP) {
4242 * This enables sending packets directly out over TCP.
4243 * As a unix socket is doing that any way, report it as
4246 if (optval == NULL || optlen == NULL ||
4247 *optlen < (socklen_t)sizeof(int)) {
4253 *optlen = sizeof(int);
4254 *(int *)optval = si->tcp_nodelay;
4258 #endif /* TCP_NODELAY */
4264 errno = ENOPROTOOPT;
4268 SWRAP_UNLOCK_SI(si);
4272 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4273 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4275 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4278 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4281 /****************************************************************************
4283 ***************************************************************************/
4285 static int swrap_setsockopt(int s, int level, int optname,
4286 const void *optval, socklen_t optlen)
4288 struct socket_info *si = find_socket_info(s);
4292 return libc_setsockopt(s,
4299 if (level == SOL_SOCKET) {
4300 return libc_setsockopt(s,
4309 if (level == IPPROTO_TCP) {
4316 * This enables sending packets directly out over TCP.
4317 * A unix socket is doing that any way.
4319 if (optval == NULL || optlen == 0 ||
4320 optlen < (socklen_t)sizeof(int)) {
4326 i = *discard_const_p(int, optval);
4327 if (i != 0 && i != 1) {
4332 si->tcp_nodelay = i;
4337 #endif /* TCP_NODELAY */
4343 switch (si->family) {
4345 if (level == IPPROTO_IP) {
4347 if (optname == IP_PKTINFO) {
4348 si->pktinfo = AF_INET;
4350 #endif /* IP_PKTINFO */
4356 if (level == IPPROTO_IPV6) {
4357 #ifdef IPV6_RECVPKTINFO
4358 if (optname == IPV6_RECVPKTINFO) {
4359 si->pktinfo = AF_INET6;
4361 #endif /* IPV6_PKTINFO */
4367 errno = ENOPROTOOPT;
4373 SWRAP_UNLOCK_SI(si);
4377 int setsockopt(int s, int level, int optname,
4378 const void *optval, socklen_t optlen)
4380 return swrap_setsockopt(s, level, optname, optval, optlen);
4383 /****************************************************************************
4385 ***************************************************************************/
4387 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4389 struct socket_info *si = find_socket_info(s);
4395 return libc_vioctl(s, r, va);
4402 rc = libc_vioctl(s, r, va);
4406 value = *((int *)va_arg(ap, int *));
4408 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4409 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4410 } else if (value == 0) { /* END OF FILE */
4411 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4418 SWRAP_UNLOCK_SI(si);
4422 #ifdef HAVE_IOCTL_INT
4423 int ioctl(int s, int r, ...)
4425 int ioctl(int s, unsigned long int r, ...)
4433 rc = swrap_vioctl(s, (unsigned long int) r, va);
4444 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4447 # ifdef _ALIGN /* BSD */
4448 #define CMSG_ALIGN _ALIGN
4450 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4451 # endif /* _ALIGN */
4452 #endif /* CMSG_ALIGN */
4455 * @brief Add a cmsghdr to a msghdr.
4457 * This is an function to add any type of cmsghdr. It will operate on the
4458 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4459 * the buffer position after the added cmsg element. Hence, this function is
4460 * intended to be used with an intermediate msghdr and not on the original
4461 * one handed in by the client.
4463 * @param[in] msg The msghdr to which to add the cmsg.
4465 * @param[in] level The cmsg level to set.
4467 * @param[in] type The cmsg type to set.
4469 * @param[in] data The cmsg data to set.
4471 * @param[in] len the length of the data to set.
4473 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4479 size_t cmlen = CMSG_LEN(len);
4480 size_t cmspace = CMSG_SPACE(len);
4481 uint8_t cmbuf[cmspace];
4482 void *cast_ptr = (void *)cmbuf;
4483 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4486 memset(cmbuf, 0, cmspace);
4488 if (msg->msg_controllen < cmlen) {
4489 cmlen = msg->msg_controllen;
4490 msg->msg_flags |= MSG_CTRUNC;
4493 if (msg->msg_controllen < cmspace) {
4494 cmspace = msg->msg_controllen;
4498 * We copy the full input data into an intermediate cmsghdr first
4499 * in order to more easily cope with truncation.
4501 cm->cmsg_len = cmlen;
4502 cm->cmsg_level = level;
4503 cm->cmsg_type = type;
4504 memcpy(CMSG_DATA(cm), data, len);
4507 * We now copy the possibly truncated buffer.
4508 * We copy cmlen bytes, but consume cmspace bytes,
4509 * leaving the possible padding uninitialiazed.
4511 p = (uint8_t *)msg->msg_control;
4512 memcpy(p, cm, cmlen);
4514 msg->msg_control = p;
4515 msg->msg_controllen -= cmspace;
4520 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4523 /* Add packet info */
4524 switch (si->pktinfo) {
4525 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4527 struct sockaddr_in *sin;
4528 #if defined(HAVE_STRUCT_IN_PKTINFO)
4529 struct in_pktinfo pkt;
4530 #elif defined(IP_RECVDSTADDR)
4534 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4535 sin = &si->bindname.sa.in;
4537 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4540 sin = &si->myname.sa.in;
4545 #if defined(HAVE_STRUCT_IN_PKTINFO)
4546 pkt.ipi_ifindex = socket_wrapper_default_iface();
4547 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4548 #elif defined(IP_RECVDSTADDR)
4549 pkt = sin->sin_addr;
4552 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4557 #endif /* IP_PKTINFO */
4558 #if defined(HAVE_IPV6)
4560 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4561 struct sockaddr_in6 *sin6;
4562 struct in6_pktinfo pkt6;
4564 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4565 sin6 = &si->bindname.sa.in6;
4567 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4570 sin6 = &si->myname.sa.in6;
4575 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4576 pkt6.ipi6_addr = sin6->sin6_addr;
4578 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4579 &pkt6, sizeof(pkt6));
4580 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4584 #endif /* IPV6_PKTINFO */
4592 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4593 struct msghdr *omsg)
4597 if (si->pktinfo > 0) {
4598 rc = swrap_msghdr_add_pktinfo(si, omsg);
4604 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4606 size_t *cm_data_space);
4607 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4609 size_t *cm_data_space);
4611 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4613 size_t *cm_data_space) {
4614 struct cmsghdr *cmsg;
4618 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4622 for (cmsg = CMSG_FIRSTHDR(msg);
4624 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4625 switch (cmsg->cmsg_level) {
4627 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4632 rc = swrap_sendmsg_copy_cmsg(cmsg,
4642 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4644 size_t *cm_data_space)
4649 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4651 p = realloc((*cm_data), cmspace);
4657 p = (*cm_data) + (*cm_data_space);
4658 *cm_data_space = cmspace;
4660 memcpy(p, cmsg, cmsg->cmsg_len);
4665 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4667 size_t *cm_data_space);
4670 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4672 size_t *cm_data_space)
4676 switch(cmsg->cmsg_type) {
4679 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4686 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4698 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4700 size_t *cm_data_space)
4702 (void)cmsg; /* unused */
4703 (void)cm_data; /* unused */
4704 (void)cm_data_space; /* unused */
4707 * Passing a IP pktinfo to a unix socket might be rejected by the
4708 * Kernel, at least on FreeBSD. So skip this cmsg.
4712 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4714 static ssize_t swrap_sendmsg_before(int fd,
4715 struct socket_info *si,
4717 struct iovec *tmp_iov,
4718 struct sockaddr_un *tmp_un,
4719 const struct sockaddr_un **to_un,
4720 const struct sockaddr **to,
4742 if (!si->connected) {
4747 if (msg->msg_iovlen == 0) {
4751 mtu = socket_wrapper_mtu();
4752 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4754 nlen = len + msg->msg_iov[i].iov_len;
4759 msg->msg_iovlen = i;
4760 if (msg->msg_iovlen == 0) {
4761 *tmp_iov = msg->msg_iov[0];
4762 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4764 msg->msg_iov = tmp_iov;
4765 msg->msg_iovlen = 1;
4770 if (si->connected) {
4771 if (msg->msg_name != NULL) {
4773 * We are dealing with unix sockets and if we
4774 * are connected, we should only talk to the
4775 * connected unix path. Using the fd to send
4776 * to another server would be hard to achieve.
4778 msg->msg_name = NULL;
4779 msg->msg_namelen = 0;
4782 const struct sockaddr *msg_name;
4783 msg_name = (const struct sockaddr *)msg->msg_name;
4785 if (msg_name == NULL) {
4791 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4803 msg->msg_name = tmp_un;
4804 msg->msg_namelen = sizeof(*tmp_un);
4807 if (si->bound == 0) {
4808 ret = swrap_auto_bind(fd, si, si->family);
4810 SWRAP_UNLOCK_SI(si);
4811 if (errno == ENOTSOCK) {
4812 swrap_remove_stale(fd);
4815 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4821 if (!si->defer_connect) {
4825 ret = sockaddr_convert_to_un(si,
4827 si->peername.sa_socklen,
4835 ret = libc_connect(fd,
4836 (struct sockaddr *)(void *)tmp_un,
4839 /* to give better errors */
4840 if (ret == -1 && errno == ENOENT) {
4841 errno = EHOSTUNREACH;
4848 si->defer_connect = 0;
4851 errno = EHOSTUNREACH;
4855 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4856 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4857 uint8_t *cmbuf = NULL;
4860 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4867 msg->msg_controllen = 0;
4868 msg->msg_control = NULL;
4869 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4870 memcpy(msg->msg_control, cmbuf, cmlen);
4871 msg->msg_controllen = cmlen;
4879 SWRAP_UNLOCK_SI(si);
4884 static void swrap_sendmsg_after(int fd,
4885 struct socket_info *si,
4887 const struct sockaddr *to,
4890 int saved_errno = errno;
4897 /* to give better errors */
4899 if (saved_errno == ENOENT) {
4900 saved_errno = EHOSTUNREACH;
4901 } else if (saved_errno == ENOTSOCK) {
4902 /* If the fd is not a socket, remove it */
4903 swrap_remove_stale(fd);
4907 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4908 avail += msg->msg_iov[i].iov_len;
4912 remain = MIN(80, avail);
4917 /* we capture it as one single packet */
4918 buf = (uint8_t *)malloc(remain);
4920 /* we just not capture the packet */
4921 errno = saved_errno;
4925 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4926 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4928 msg->msg_iov[i].iov_base,
4931 remain -= this_time;
4940 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4941 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4943 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4948 if (si->connected) {
4949 to = &si->peername.sa.s;
4952 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4953 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4955 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4960 SWRAP_UNLOCK_SI(si);
4963 errno = saved_errno;
4966 static int swrap_recvmsg_before(int fd,
4967 struct socket_info *si,
4969 struct iovec *tmp_iov)
4976 (void)fd; /* unused */
4981 if (!si->connected) {
4986 if (msg->msg_iovlen == 0) {
4990 mtu = socket_wrapper_mtu();
4991 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4993 nlen = len + msg->msg_iov[i].iov_len;
4998 msg->msg_iovlen = i;
4999 if (msg->msg_iovlen == 0) {
5000 *tmp_iov = msg->msg_iov[0];
5001 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
5003 msg->msg_iov = tmp_iov;
5004 msg->msg_iovlen = 1;
5009 if (msg->msg_name == NULL) {
5014 if (msg->msg_iovlen == 0) {
5018 if (si->bound == 0) {
5019 ret = swrap_auto_bind(fd, si, si->family);
5021 SWRAP_UNLOCK_SI(si);
5023 * When attempting to read or write to a
5024 * descriptor, if an underlying autobind fails
5025 * because it's not a socket, stop intercepting
5026 * uses of that descriptor.
5028 if (errno == ENOTSOCK) {
5029 swrap_remove_stale(fd);
5032 SWRAP_LOG(SWRAP_LOG_ERROR,
5033 "swrap_recvmsg_before failed");
5040 errno = EHOSTUNREACH;
5046 SWRAP_UNLOCK_SI(si);
5051 static int swrap_recvmsg_after(int fd,
5052 struct socket_info *si,
5054 const struct sockaddr_un *un_addr,
5055 socklen_t un_addrlen,
5058 int saved_errno = errno;
5060 uint8_t *buf = NULL;
5066 /* to give better errors */
5068 if (saved_errno == ENOENT) {
5069 saved_errno = EHOSTUNREACH;
5070 } else if (saved_errno == ENOTSOCK) {
5071 /* If the fd is not a socket, remove it */
5072 swrap_remove_stale(fd);
5076 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5077 avail += msg->msg_iov[i].iov_len;
5082 /* Convert the socket address before we leave */
5083 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5084 rc = sockaddr_convert_from_un(si,
5101 remain = MIN(80, avail);
5106 /* we capture it as one single packet */
5107 buf = (uint8_t *)malloc(remain);
5109 /* we just not capture the packet */
5110 SWRAP_UNLOCK_SI(si);
5111 errno = saved_errno;
5115 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5116 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5118 msg->msg_iov[i].iov_base,
5121 remain -= this_time;
5126 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5127 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5128 } else if (ret == 0) { /* END OF FILE */
5129 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5130 } else if (ret > 0) {
5131 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5140 if (un_addr != NULL) {
5141 swrap_pcap_dump_packet(si,
5147 swrap_pcap_dump_packet(si,
5160 errno = saved_errno;
5162 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5164 msg->msg_controllen > 0 &&
5165 msg->msg_control != NULL) {
5166 rc = swrap_msghdr_add_socket_info(si, msg);
5168 SWRAP_UNLOCK_SI(si);
5174 SWRAP_UNLOCK_SI(si);
5178 /****************************************************************************
5180 ***************************************************************************/
5182 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5183 struct sockaddr *from, socklen_t *fromlen)
5185 struct swrap_address from_addr = {
5186 .sa_socklen = sizeof(struct sockaddr_un),
5189 struct socket_info *si = find_socket_info(s);
5190 struct swrap_address saddr = {
5191 .sa_socklen = sizeof(struct sockaddr_storage),
5198 return libc_recvfrom(s,
5210 if (from != NULL && fromlen != NULL) {
5211 msg.msg_name = from; /* optional address */
5212 msg.msg_namelen = *fromlen; /* size of address */
5214 msg.msg_name = &saddr.sa.s; /* optional address */
5215 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5217 msg.msg_iov = &tmp; /* scatter/gather array */
5218 msg.msg_iovlen = 1; /* # elements in msg_iov */
5219 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5220 msg.msg_control = NULL; /* ancillary data, see below */
5221 msg.msg_controllen = 0; /* ancillary data buffer len */
5222 msg.msg_flags = 0; /* flags on received message */
5225 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5230 buf = msg.msg_iov[0].iov_base;
5231 len = msg.msg_iov[0].iov_len;
5233 ret = libc_recvfrom(s,
5238 &from_addr.sa_socklen);
5243 tret = swrap_recvmsg_after(s,
5247 from_addr.sa_socklen,
5253 if (from != NULL && fromlen != NULL) {
5254 *fromlen = msg.msg_namelen;
5260 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5261 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5262 struct sockaddr *from, Psocklen_t fromlen)
5264 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5265 struct sockaddr *from, socklen_t *fromlen)
5268 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5271 /****************************************************************************
5273 ***************************************************************************/
5275 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5276 const struct sockaddr *to, socklen_t tolen)
5280 struct swrap_address un_addr = {
5281 .sa_socklen = sizeof(struct sockaddr_un),
5283 const struct sockaddr_un *to_un = NULL;
5286 struct socket_info *si = find_socket_info(s);
5290 return libc_sendto(s, buf, len, flags, to, tolen);
5293 tmp.iov_base = discard_const_p(char, buf);
5297 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5298 msg.msg_namelen = tolen; /* size of address */
5299 msg.msg_iov = &tmp; /* scatter/gather array */
5300 msg.msg_iovlen = 1; /* # elements in msg_iov */
5301 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5302 msg.msg_control = NULL; /* ancillary data, see below */
5303 msg.msg_controllen = 0; /* ancillary data buffer len */
5304 msg.msg_flags = 0; /* flags on received message */
5307 rc = swrap_sendmsg_before(s,
5319 buf = msg.msg_iov[0].iov_base;
5320 len = msg.msg_iov[0].iov_len;
5325 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5328 type = SOCKET_TYPE_CHAR_UDP;
5330 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5331 snprintf(un_addr.sa.un.sun_path,
5332 sizeof(un_addr.sa.un.sun_path),
5334 socket_wrapper_dir(), type, iface, prt);
5335 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5337 /* ignore the any errors in broadcast sends */
5343 un_addr.sa_socklen);
5348 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5350 SWRAP_UNLOCK_SI(si);
5357 * If it is a dgram socket and we are connected, don't include the
5360 if (si->type == SOCK_DGRAM && si->connected) {
5361 ret = libc_sendto(s,
5368 ret = libc_sendto(s,
5372 (struct sockaddr *)msg.msg_name,
5376 SWRAP_UNLOCK_SI(si);
5378 swrap_sendmsg_after(s, si, &msg, to, ret);
5383 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5384 const struct sockaddr *to, socklen_t tolen)
5386 return swrap_sendto(s, buf, len, flags, to, tolen);
5389 /****************************************************************************
5391 ***************************************************************************/
5393 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5395 struct socket_info *si;
5397 struct swrap_address saddr = {
5398 .sa_socklen = sizeof(struct sockaddr_storage),
5404 si = find_socket_info(s);
5406 return libc_recv(s, buf, len, flags);
5413 msg.msg_name = &saddr.sa.s; /* optional address */
5414 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5415 msg.msg_iov = &tmp; /* scatter/gather array */
5416 msg.msg_iovlen = 1; /* # elements in msg_iov */
5417 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5418 msg.msg_control = NULL; /* ancillary data, see below */
5419 msg.msg_controllen = 0; /* ancillary data buffer len */
5420 msg.msg_flags = 0; /* flags on received message */
5423 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5428 buf = msg.msg_iov[0].iov_base;
5429 len = msg.msg_iov[0].iov_len;
5431 ret = libc_recv(s, buf, len, flags);
5433 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5441 ssize_t recv(int s, void *buf, size_t len, int flags)
5443 return swrap_recv(s, buf, len, flags);
5446 /****************************************************************************
5448 ***************************************************************************/
5450 static ssize_t swrap_read(int s, void *buf, size_t len)
5452 struct socket_info *si;
5455 struct swrap_address saddr = {
5456 .sa_socklen = sizeof(struct sockaddr_storage),
5461 si = find_socket_info(s);
5463 return libc_read(s, buf, len);
5470 msg.msg_name = &saddr.sa.ss; /* optional address */
5471 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5472 msg.msg_iov = &tmp; /* scatter/gather array */
5473 msg.msg_iovlen = 1; /* # elements in msg_iov */
5474 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5475 msg.msg_control = NULL; /* ancillary data, see below */
5476 msg.msg_controllen = 0; /* ancillary data buffer len */
5477 msg.msg_flags = 0; /* flags on received message */
5480 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5482 if (tret == -ENOTSOCK) {
5483 return libc_read(s, buf, len);
5488 buf = msg.msg_iov[0].iov_base;
5489 len = msg.msg_iov[0].iov_len;
5491 ret = libc_read(s, buf, len);
5493 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5501 ssize_t read(int s, void *buf, size_t len)
5503 return swrap_read(s, buf, len);
5506 /****************************************************************************
5508 ***************************************************************************/
5510 static ssize_t swrap_write(int s, const void *buf, size_t len)
5514 struct sockaddr_un un_addr;
5517 struct socket_info *si;
5519 si = find_socket_info(s);
5521 return libc_write(s, buf, len);
5524 tmp.iov_base = discard_const_p(char, buf);
5528 msg.msg_name = NULL; /* optional address */
5529 msg.msg_namelen = 0; /* size of address */
5530 msg.msg_iov = &tmp; /* scatter/gather array */
5531 msg.msg_iovlen = 1; /* # elements in msg_iov */
5532 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5533 msg.msg_control = NULL; /* ancillary data, see below */
5534 msg.msg_controllen = 0; /* ancillary data buffer len */
5535 msg.msg_flags = 0; /* flags on received message */
5538 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5543 buf = msg.msg_iov[0].iov_base;
5544 len = msg.msg_iov[0].iov_len;
5546 ret = libc_write(s, buf, len);
5548 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5553 ssize_t write(int s, const void *buf, size_t len)
5555 return swrap_write(s, buf, len);
5558 /****************************************************************************
5560 ***************************************************************************/
5562 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5566 struct sockaddr_un un_addr;
5569 struct socket_info *si = find_socket_info(s);
5572 return libc_send(s, buf, len, flags);
5575 tmp.iov_base = discard_const_p(char, buf);
5579 msg.msg_name = NULL; /* optional address */
5580 msg.msg_namelen = 0; /* size of address */
5581 msg.msg_iov = &tmp; /* scatter/gather array */
5582 msg.msg_iovlen = 1; /* # elements in msg_iov */
5583 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5584 msg.msg_control = NULL; /* ancillary data, see below */
5585 msg.msg_controllen = 0; /* ancillary data buffer len */
5586 msg.msg_flags = 0; /* flags on received message */
5589 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5594 buf = msg.msg_iov[0].iov_base;
5595 len = msg.msg_iov[0].iov_len;
5597 ret = libc_send(s, buf, len, flags);
5599 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5604 ssize_t send(int s, const void *buf, size_t len, int flags)
5606 return swrap_send(s, buf, len, flags);
5609 /****************************************************************************
5611 ***************************************************************************/
5613 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5615 struct swrap_address from_addr = {
5616 .sa_socklen = sizeof(struct sockaddr_un),
5618 struct swrap_address convert_addr = {
5619 .sa_socklen = sizeof(struct sockaddr_storage),
5621 struct socket_info *si;
5624 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5625 size_t msg_ctrllen_filled;
5626 size_t msg_ctrllen_left;
5632 si = find_socket_info(s);
5634 return libc_recvmsg(s, omsg, flags);
5637 tmp.iov_base = NULL;
5641 msg.msg_name = &from_addr.sa; /* optional address */
5642 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5643 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5644 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5645 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5646 msg_ctrllen_filled = 0;
5647 msg_ctrllen_left = omsg->msg_controllen;
5649 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5650 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5651 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5654 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5659 ret = libc_recvmsg(s, &msg, flags);
5661 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5662 msg_ctrllen_filled += msg.msg_controllen;
5663 msg_ctrllen_left -= msg.msg_controllen;
5665 if (omsg->msg_control != NULL) {
5668 p = omsg->msg_control;
5669 p += msg_ctrllen_filled;
5671 msg.msg_control = p;
5672 msg.msg_controllen = msg_ctrllen_left;
5674 msg.msg_control = NULL;
5675 msg.msg_controllen = 0;
5680 * We convert the unix address to a IP address so we need a buffer
5681 * which can store the address in case of SOCK_DGRAM, see below.
5683 msg.msg_name = &convert_addr.sa;
5684 msg.msg_namelen = convert_addr.sa_socklen;
5686 rc = swrap_recvmsg_after(s,
5690 from_addr.sa_socklen,
5696 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5697 if (omsg->msg_control != NULL) {
5698 /* msg.msg_controllen = space left */
5699 msg_ctrllen_left = msg.msg_controllen;
5700 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5703 /* Update the original message length */
5704 omsg->msg_controllen = msg_ctrllen_filled;
5705 omsg->msg_flags = msg.msg_flags;
5707 omsg->msg_iovlen = msg.msg_iovlen;
5714 * The msg_name field points to a caller-allocated buffer that is
5715 * used to return the source address if the socket is unconnected. The
5716 * caller should set msg_namelen to the size of this buffer before this
5717 * call; upon return from a successful call, msg_name will contain the
5718 * length of the returned address. If the application does not need
5719 * to know the source address, msg_name can be specified as NULL.
5721 if (si->type == SOCK_STREAM) {
5722 omsg->msg_namelen = 0;
5723 } else if (omsg->msg_name != NULL &&
5724 omsg->msg_namelen != 0 &&
5725 omsg->msg_namelen >= msg.msg_namelen) {
5726 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5727 omsg->msg_namelen = msg.msg_namelen;
5730 SWRAP_UNLOCK_SI(si);
5735 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5737 return swrap_recvmsg(sockfd, msg, flags);
5740 /****************************************************************************
5742 ***************************************************************************/
5744 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5748 struct sockaddr_un un_addr;
5749 const struct sockaddr_un *to_un = NULL;
5750 const struct sockaddr *to = NULL;
5753 struct socket_info *si = find_socket_info(s);
5757 return libc_sendmsg(s, omsg, flags);
5760 ZERO_STRUCT(un_addr);
5762 tmp.iov_base = NULL;
5769 if (si->connected == 0) {
5770 msg.msg_name = omsg->msg_name; /* optional address */
5771 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5773 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5774 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5776 SWRAP_UNLOCK_SI(si);
5778 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5779 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5780 /* omsg is a const so use a local buffer for modifications */
5781 uint8_t cmbuf[omsg->msg_controllen];
5783 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5785 msg.msg_control = cmbuf; /* ancillary data, see below */
5786 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5788 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5791 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5799 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5807 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5808 avail += msg.msg_iov[i].iov_len;
5814 /* we capture it as one single packet */
5815 buf = (uint8_t *)malloc(remain);
5820 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5821 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5823 msg.msg_iov[i].iov_base,
5826 remain -= this_time;
5829 type = SOCKET_TYPE_CHAR_UDP;
5831 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5832 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5833 socket_wrapper_dir(), type, iface, prt);
5834 if (stat(un_addr.sun_path, &st) != 0) continue;
5836 msg.msg_name = &un_addr; /* optional address */
5837 msg.msg_namelen = sizeof(un_addr); /* size of address */
5839 /* ignore the any errors in broadcast sends */
5840 libc_sendmsg(s, &msg, flags);
5845 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5848 SWRAP_UNLOCK_SI(si);
5853 ret = libc_sendmsg(s, &msg, flags);
5855 swrap_sendmsg_after(s, si, &msg, to, ret);
5860 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5862 return swrap_sendmsg(s, omsg, flags);
5865 /****************************************************************************
5867 ***************************************************************************/
5869 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5871 struct socket_info *si;
5874 struct swrap_address saddr = {
5875 .sa_socklen = sizeof(struct sockaddr_storage)
5880 si = find_socket_info(s);
5882 return libc_readv(s, vector, count);
5885 tmp.iov_base = NULL;
5889 msg.msg_name = &saddr.sa.s; /* optional address */
5890 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5891 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5892 msg.msg_iovlen = count; /* # elements in msg_iov */
5893 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5894 msg.msg_control = NULL; /* ancillary data, see below */
5895 msg.msg_controllen = 0; /* ancillary data buffer len */
5896 msg.msg_flags = 0; /* flags on received message */
5899 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5901 if (rc == -ENOTSOCK) {
5902 return libc_readv(s, vector, count);
5907 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5909 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5917 ssize_t readv(int s, const struct iovec *vector, int count)
5919 return swrap_readv(s, vector, count);
5922 /****************************************************************************
5924 ***************************************************************************/
5926 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5930 struct sockaddr_un un_addr;
5933 struct socket_info *si = find_socket_info(s);
5936 return libc_writev(s, vector, count);
5939 tmp.iov_base = NULL;
5943 msg.msg_name = NULL; /* optional address */
5944 msg.msg_namelen = 0; /* size of address */
5945 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5946 msg.msg_iovlen = count; /* # elements in msg_iov */
5947 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5948 msg.msg_control = NULL; /* ancillary data, see below */
5949 msg.msg_controllen = 0; /* ancillary data buffer len */
5950 msg.msg_flags = 0; /* flags on received message */
5953 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5955 if (rc == -ENOTSOCK) {
5956 return libc_readv(s, vector, count);
5961 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5963 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5968 ssize_t writev(int s, const struct iovec *vector, int count)
5970 return swrap_writev(s, vector, count);
5973 /****************************
5975 ***************************/
5977 static int swrap_close(int fd)
5979 struct socket_info *si = NULL;
5983 swrap_mutex_lock(&socket_reset_mutex);
5985 si_index = find_socket_info_index(fd);
5986 if (si_index == -1) {
5987 swrap_mutex_unlock(&socket_reset_mutex);
5988 return libc_close(fd);
5991 reset_socket_info_index(fd);
5993 si = swrap_get_socket_info(si_index);
5995 swrap_mutex_lock(&first_free_mutex);
5998 ret = libc_close(fd);
6000 swrap_dec_refcount(si);
6002 if (swrap_get_refcount(si) > 0) {
6003 /* there are still references left */
6007 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6008 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
6011 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
6012 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
6013 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
6016 if (si->un_addr.sun_path[0] != '\0') {
6017 unlink(si->un_addr.sun_path);
6020 swrap_set_next_free(si, first_free);
6021 first_free = si_index;
6024 SWRAP_UNLOCK_SI(si);
6025 swrap_mutex_unlock(&first_free_mutex);
6026 swrap_mutex_unlock(&socket_reset_mutex);
6033 return swrap_close(fd);
6036 /****************************
6038 ***************************/
6040 static int swrap_dup(int fd)
6042 struct socket_info *si;
6045 idx = find_socket_info_index(fd);
6047 return libc_dup(fd);
6050 si = swrap_get_socket_info(idx);
6052 dup_fd = libc_dup(fd);
6054 int saved_errno = errno;
6055 errno = saved_errno;
6061 swrap_inc_refcount(si);
6063 SWRAP_UNLOCK_SI(si);
6065 /* Make sure we don't have an entry for the fd */
6066 swrap_remove_stale(dup_fd);
6068 set_socket_info_index(dup_fd, idx);
6075 return swrap_dup(fd);
6078 /****************************
6080 ***************************/
6082 static int swrap_dup2(int fd, int newfd)
6084 struct socket_info *si;
6087 idx = find_socket_info_index(fd);
6089 return libc_dup2(fd, newfd);
6092 si = swrap_get_socket_info(idx);
6096 * According to the manpage:
6098 * "If oldfd is a valid file descriptor, and newfd has the same
6099 * value as oldfd, then dup2() does nothing, and returns newfd."
6104 if (find_socket_info(newfd)) {
6105 /* dup2() does an implicit close of newfd, which we
6106 * need to emulate */
6110 dup_fd = libc_dup2(fd, newfd);
6112 int saved_errno = errno;
6113 errno = saved_errno;
6119 swrap_inc_refcount(si);
6121 SWRAP_UNLOCK_SI(si);
6123 /* Make sure we don't have an entry for the fd */
6124 swrap_remove_stale(dup_fd);
6126 set_socket_info_index(dup_fd, idx);
6131 int dup2(int fd, int newfd)
6133 return swrap_dup2(fd, newfd);
6136 /****************************
6138 ***************************/
6140 static int swrap_vfcntl(int fd, int cmd, va_list va)
6142 struct socket_info *si;
6143 int rc, dup_fd, idx;
6145 idx = find_socket_info_index(fd);
6147 return libc_vfcntl(fd, cmd, va);
6150 si = swrap_get_socket_info(idx);
6154 dup_fd = libc_vfcntl(fd, cmd, va);
6156 int saved_errno = errno;
6157 errno = saved_errno;
6163 swrap_inc_refcount(si);
6165 SWRAP_UNLOCK_SI(si);
6167 /* Make sure we don't have an entry for the fd */
6168 swrap_remove_stale(dup_fd);
6170 set_socket_info_index(dup_fd, idx);
6175 rc = libc_vfcntl(fd, cmd, va);
6182 int fcntl(int fd, int cmd, ...)
6189 rc = swrap_vfcntl(fd, cmd, va);
6196 /****************************
6198 ***************************/
6201 static int swrap_eventfd(int count, int flags)
6205 fd = libc_eventfd(count, flags);
6207 swrap_remove_stale(fd);
6213 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6214 int eventfd(unsigned int count, int flags)
6216 int eventfd(int count, int flags)
6219 return swrap_eventfd(count, flags);
6224 int pledge(const char *promises, const char *paths[])
6226 (void)promises; /* unused */
6227 (void)paths; /* unused */
6231 #endif /* HAVE_PLEDGE */
6233 static void swrap_thread_prepare(void)
6236 * This function should only be called here!!
6238 * We bind all symobls to avoid deadlocks of the fork is
6239 * interrupted by a signal handler using a symbol of this
6242 swrap_bind_symbol_all();
6247 static void swrap_thread_parent(void)
6252 static void swrap_thread_child(void)
6257 /****************************
6259 ***************************/
6260 void swrap_constructor(void)
6265 * If we hold a lock and the application forks, then the child
6266 * is not able to unlock the mutex and we are in a deadlock.
6267 * This should prevent such deadlocks.
6269 pthread_atfork(&swrap_thread_prepare,
6270 &swrap_thread_parent,
6271 &swrap_thread_child);
6273 ret = socket_wrapper_init_mutex(&sockets_mutex);
6275 SWRAP_LOG(SWRAP_LOG_ERROR,
6276 "Failed to initialize pthread mutex");
6280 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6282 SWRAP_LOG(SWRAP_LOG_ERROR,
6283 "Failed to initialize pthread mutex");
6287 ret = socket_wrapper_init_mutex(&first_free_mutex);
6289 SWRAP_LOG(SWRAP_LOG_ERROR,
6290 "Failed to initialize pthread mutex");
6295 /****************************
6297 ***************************/
6300 * This function is called when the library is unloaded and makes sure that
6301 * sockets get closed and the unix file for the socket are unlinked.
6303 void swrap_destructor(void)
6307 if (socket_fds_idx != NULL) {
6308 for (i = 0; i < socket_fds_max; ++i) {
6309 if (socket_fds_idx[i] != -1) {
6313 SAFE_FREE(socket_fds_idx);
6318 if (swrap.libc.handle != NULL) {
6319 dlclose(swrap.libc.handle);
6321 if (swrap.libc.socket_handle) {
6322 dlclose(swrap.libc.socket_handle);