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 256000
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 max_sockets = 0;
298 /* Hash table to map fds to corresponding socket_info index */
299 static int *socket_fds_idx;
301 /* Mutex to synchronize access to global libc.symbols */
302 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
304 /* Mutex for syncronizing port selection during swrap_auto_bind() */
305 static pthread_mutex_t autobind_start_mutex;
307 /* Mutex to guard the initialization of array of socket_info structures */
308 static pthread_mutex_t sockets_mutex;
310 /* Mutex to guard the socket reset in swrap_close() and swrap_remove_stale() */
311 static pthread_mutex_t socket_reset_mutex;
313 /* Mutex to synchronize access to first free index in socket_info array */
314 static pthread_mutex_t first_free_mutex;
316 /* Mutex to synchronize access to packet capture dump file */
317 static pthread_mutex_t pcap_dump_mutex;
319 /* Mutex for synchronizing mtu value fetch*/
320 static pthread_mutex_t mtu_update_mutex;
322 /* Function prototypes */
324 bool socket_wrapper_enabled(void);
326 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
327 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
329 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
330 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
332 static void swrap_log(enum swrap_dbglvl_e dbglvl,
334 const char *format, ...)
339 unsigned int lvl = 0;
340 const char *prefix = "SWRAP";
342 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
351 va_start(va, format);
352 vsnprintf(buffer, sizeof(buffer), format, va);
356 case SWRAP_LOG_ERROR:
357 prefix = "SWRAP_ERROR";
360 prefix = "SWRAP_WARN";
362 case SWRAP_LOG_DEBUG:
363 prefix = "SWRAP_DEBUG";
365 case SWRAP_LOG_TRACE:
366 prefix = "SWRAP_TRACE";
372 prefix, (int)getpid(), func, buffer);
375 /*********************************************************
376 * SWRAP LOADING LIBC FUNCTIONS
377 *********************************************************/
382 typedef int (*__libc_accept4)(int sockfd,
383 struct sockaddr *addr,
387 typedef int (*__libc_accept)(int sockfd,
388 struct sockaddr *addr,
391 typedef int (*__libc_bind)(int sockfd,
392 const struct sockaddr *addr,
394 typedef int (*__libc_close)(int fd);
395 typedef int (*__libc_connect)(int sockfd,
396 const struct sockaddr *addr,
398 typedef int (*__libc_dup)(int fd);
399 typedef int (*__libc_dup2)(int oldfd, int newfd);
400 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
401 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
403 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
406 typedef int (*__libc_eventfd)(int count, int flags);
408 typedef int (*__libc_getpeername)(int sockfd,
409 struct sockaddr *addr,
411 typedef int (*__libc_getsockname)(int sockfd,
412 struct sockaddr *addr,
414 typedef int (*__libc_getsockopt)(int sockfd,
419 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
420 typedef int (*__libc_listen)(int sockfd, int backlog);
421 typedef int (*__libc_open)(const char *pathname, int flags, ...);
423 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
424 #endif /* HAVE_OPEN64 */
425 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
426 typedef int (*__libc_pipe)(int pipefd[2]);
427 typedef int (*__libc_read)(int fd, void *buf, size_t count);
428 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
429 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
430 typedef int (*__libc_recvfrom)(int sockfd,
434 struct sockaddr *src_addr,
436 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
437 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
438 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
439 typedef int (*__libc_sendto)(int sockfd,
443 const struct sockaddr *dst_addr,
445 typedef int (*__libc_setsockopt)(int sockfd,
451 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
453 typedef int (*__libc_socket)(int domain, int type, int protocol);
454 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
455 #ifdef HAVE_TIMERFD_CREATE
456 typedef int (*__libc_timerfd_create)(int clockid, int flags);
458 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
459 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
461 #define SWRAP_SYMBOL_ENTRY(i) \
467 struct swrap_libc_symbols {
469 SWRAP_SYMBOL_ENTRY(accept4);
471 SWRAP_SYMBOL_ENTRY(accept);
473 SWRAP_SYMBOL_ENTRY(bind);
474 SWRAP_SYMBOL_ENTRY(close);
475 SWRAP_SYMBOL_ENTRY(connect);
476 SWRAP_SYMBOL_ENTRY(dup);
477 SWRAP_SYMBOL_ENTRY(dup2);
478 SWRAP_SYMBOL_ENTRY(fcntl);
479 SWRAP_SYMBOL_ENTRY(fopen);
481 SWRAP_SYMBOL_ENTRY(fopen64);
484 SWRAP_SYMBOL_ENTRY(eventfd);
486 SWRAP_SYMBOL_ENTRY(getpeername);
487 SWRAP_SYMBOL_ENTRY(getsockname);
488 SWRAP_SYMBOL_ENTRY(getsockopt);
489 SWRAP_SYMBOL_ENTRY(ioctl);
490 SWRAP_SYMBOL_ENTRY(listen);
491 SWRAP_SYMBOL_ENTRY(open);
493 SWRAP_SYMBOL_ENTRY(open64);
495 SWRAP_SYMBOL_ENTRY(openat);
496 SWRAP_SYMBOL_ENTRY(pipe);
497 SWRAP_SYMBOL_ENTRY(read);
498 SWRAP_SYMBOL_ENTRY(readv);
499 SWRAP_SYMBOL_ENTRY(recv);
500 SWRAP_SYMBOL_ENTRY(recvfrom);
501 SWRAP_SYMBOL_ENTRY(recvmsg);
502 SWRAP_SYMBOL_ENTRY(send);
503 SWRAP_SYMBOL_ENTRY(sendmsg);
504 SWRAP_SYMBOL_ENTRY(sendto);
505 SWRAP_SYMBOL_ENTRY(setsockopt);
507 SWRAP_SYMBOL_ENTRY(signalfd);
509 SWRAP_SYMBOL_ENTRY(socket);
510 SWRAP_SYMBOL_ENTRY(socketpair);
511 #ifdef HAVE_TIMERFD_CREATE
512 SWRAP_SYMBOL_ENTRY(timerfd_create);
514 SWRAP_SYMBOL_ENTRY(write);
515 SWRAP_SYMBOL_ENTRY(writev);
522 struct swrap_libc_symbols symbols;
526 static struct swrap swrap;
529 static const char *socket_wrapper_dir(void);
531 #define LIBC_NAME "libc.so"
539 static const char *swrap_str_lib(enum swrap_lib lib)
546 case SWRAP_LIBSOCKET:
550 /* Compiler would warn us about unhandled enum value if we get here */
554 static void *swrap_load_lib_handle(enum swrap_lib lib)
556 int flags = RTLD_LAZY;
561 flags |= RTLD_DEEPBIND;
567 case SWRAP_LIBSOCKET:
568 #ifdef HAVE_LIBSOCKET
569 handle = swrap.libc.socket_handle;
570 if (handle == NULL) {
571 for (i = 10; i >= 0; i--) {
572 char soname[256] = {0};
574 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
575 handle = dlopen(soname, flags);
576 if (handle != NULL) {
581 swrap.libc.socket_handle = handle;
587 handle = swrap.libc.handle;
589 if (handle == NULL) {
590 handle = dlopen(LIBC_SO, flags);
592 swrap.libc.handle = handle;
595 if (handle == NULL) {
596 for (i = 10; i >= 0; i--) {
597 char soname[256] = {0};
599 snprintf(soname, sizeof(soname), "libc.so.%d", i);
600 handle = dlopen(soname, flags);
601 if (handle != NULL) {
606 swrap.libc.handle = handle;
611 if (handle == NULL) {
613 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
615 SWRAP_LOG(SWRAP_LOG_ERROR,
616 "Failed to dlopen library: %s\n",
625 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
630 handle = swrap_load_lib_handle(lib);
632 func = dlsym(handle, fn_name);
634 SWRAP_LOG(SWRAP_LOG_ERROR,
635 "Failed to find %s: %s\n",
641 SWRAP_LOG(SWRAP_LOG_TRACE,
649 static void swrap_mutex_lock(pthread_mutex_t *mutex)
653 ret = pthread_mutex_lock(mutex);
655 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't lock pthread mutex - %s",
660 static void swrap_mutex_unlock(pthread_mutex_t *mutex)
664 ret = pthread_mutex_unlock(mutex);
666 SWRAP_LOG(SWRAP_LOG_ERROR, "Couldn't unlock pthread mutex - %s",
672 * These macros have a thread race condition on purpose!
674 * This is an optimization to avoid locking each time we check if the symbol is
677 #define swrap_bind_symbol_libc(sym_name) \
678 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
679 swrap_mutex_lock(&libc_symbol_binding_mutex); \
680 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
681 swrap.libc.symbols._libc_##sym_name.obj = \
682 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
684 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
687 #define swrap_bind_symbol_libsocket(sym_name) \
688 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
689 swrap_mutex_lock(&libc_symbol_binding_mutex); \
690 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
691 swrap.libc.symbols._libc_##sym_name.obj = \
692 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
694 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
697 #define swrap_bind_symbol_libnsl(sym_name) \
698 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
699 swrap_mutex_lock(&libc_symbol_binding_mutex); \
700 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
701 swrap.libc.symbols._libc_##sym_name.obj = \
702 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
704 swrap_mutex_unlock(&libc_symbol_binding_mutex); \
707 /****************************************************************************
709 ****************************************************************************
711 * Functions especially from libc need to be loaded individually, you can't
712 * load all at once or gdb will segfault at startup. The same applies to
713 * valgrind and has probably something todo with with the linker. So we need
714 * load each function at the point it is called the first time.
716 ****************************************************************************/
719 static int libc_accept4(int sockfd,
720 struct sockaddr *addr,
724 swrap_bind_symbol_libsocket(accept4);
726 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
729 #else /* HAVE_ACCEPT4 */
731 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
733 swrap_bind_symbol_libsocket(accept);
735 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
737 #endif /* HAVE_ACCEPT4 */
739 static int libc_bind(int sockfd,
740 const struct sockaddr *addr,
743 swrap_bind_symbol_libsocket(bind);
745 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
748 static int libc_close(int fd)
750 swrap_bind_symbol_libc(close);
752 return swrap.libc.symbols._libc_close.f(fd);
755 static int libc_connect(int sockfd,
756 const struct sockaddr *addr,
759 swrap_bind_symbol_libsocket(connect);
761 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
764 static int libc_dup(int fd)
766 swrap_bind_symbol_libc(dup);
768 return swrap.libc.symbols._libc_dup.f(fd);
771 static int libc_dup2(int oldfd, int newfd)
773 swrap_bind_symbol_libc(dup2);
775 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
779 static int libc_eventfd(int count, int flags)
781 swrap_bind_symbol_libc(eventfd);
783 return swrap.libc.symbols._libc_eventfd.f(count, flags);
787 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
788 static int libc_vfcntl(int fd, int cmd, va_list ap)
793 swrap_bind_symbol_libc(fcntl);
795 arg = va_arg(ap, void *);
797 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
802 static int libc_getpeername(int sockfd,
803 struct sockaddr *addr,
806 swrap_bind_symbol_libsocket(getpeername);
808 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
811 static int libc_getsockname(int sockfd,
812 struct sockaddr *addr,
815 swrap_bind_symbol_libsocket(getsockname);
817 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
820 static int libc_getsockopt(int sockfd,
826 swrap_bind_symbol_libsocket(getsockopt);
828 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
835 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
836 static int libc_vioctl(int d, unsigned long int request, va_list ap)
841 swrap_bind_symbol_libc(ioctl);
843 arg = va_arg(ap, void *);
845 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
850 static int libc_listen(int sockfd, int backlog)
852 swrap_bind_symbol_libsocket(listen);
854 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
857 static FILE *libc_fopen(const char *name, const char *mode)
859 swrap_bind_symbol_libc(fopen);
861 return swrap.libc.symbols._libc_fopen.f(name, mode);
865 static FILE *libc_fopen64(const char *name, const char *mode)
867 swrap_bind_symbol_libc(fopen64);
869 return swrap.libc.symbols._libc_fopen64.f(name, mode);
871 #endif /* HAVE_FOPEN64 */
873 static int libc_vopen(const char *pathname, int flags, va_list ap)
878 swrap_bind_symbol_libc(open);
880 if (flags & O_CREAT) {
881 mode = va_arg(ap, int);
883 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
888 static int libc_open(const char *pathname, int flags, ...)
894 fd = libc_vopen(pathname, flags, ap);
901 static int libc_vopen64(const char *pathname, int flags, va_list ap)
906 swrap_bind_symbol_libc(open64);
908 if (flags & O_CREAT) {
909 mode = va_arg(ap, int);
911 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
915 #endif /* HAVE_OPEN64 */
917 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
922 swrap_bind_symbol_libc(openat);
924 if (flags & O_CREAT) {
925 mode = va_arg(ap, int);
927 fd = swrap.libc.symbols._libc_openat.f(dirfd,
936 static int libc_openat(int dirfd, const char *path, int flags, ...)
942 fd = libc_vopenat(dirfd, path, flags, ap);
949 static int libc_pipe(int pipefd[2])
951 swrap_bind_symbol_libsocket(pipe);
953 return swrap.libc.symbols._libc_pipe.f(pipefd);
956 static int libc_read(int fd, void *buf, size_t count)
958 swrap_bind_symbol_libc(read);
960 return swrap.libc.symbols._libc_read.f(fd, buf, count);
963 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
965 swrap_bind_symbol_libsocket(readv);
967 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
970 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
972 swrap_bind_symbol_libsocket(recv);
974 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
977 static int libc_recvfrom(int sockfd,
981 struct sockaddr *src_addr,
984 swrap_bind_symbol_libsocket(recvfrom);
986 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
994 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
996 swrap_bind_symbol_libsocket(recvmsg);
998 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1001 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1003 swrap_bind_symbol_libsocket(send);
1005 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1008 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1010 swrap_bind_symbol_libsocket(sendmsg);
1012 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1015 static int libc_sendto(int sockfd,
1019 const struct sockaddr *dst_addr,
1022 swrap_bind_symbol_libsocket(sendto);
1024 return swrap.libc.symbols._libc_sendto.f(sockfd,
1032 static int libc_setsockopt(int sockfd,
1038 swrap_bind_symbol_libsocket(setsockopt);
1040 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1047 #ifdef HAVE_SIGNALFD
1048 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1050 swrap_bind_symbol_libsocket(signalfd);
1052 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1056 static int libc_socket(int domain, int type, int protocol)
1058 swrap_bind_symbol_libsocket(socket);
1060 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1063 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1065 swrap_bind_symbol_libsocket(socketpair);
1067 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1070 #ifdef HAVE_TIMERFD_CREATE
1071 static int libc_timerfd_create(int clockid, int flags)
1073 swrap_bind_symbol_libc(timerfd_create);
1075 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1079 static ssize_t libc_write(int fd, const void *buf, size_t count)
1081 swrap_bind_symbol_libc(write);
1083 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1086 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1088 swrap_bind_symbol_libsocket(writev);
1090 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1093 /* DO NOT call this function during library initialization! */
1094 static void swrap_bind_symbol_all(void)
1097 swrap_bind_symbol_libsocket(accept4);
1099 swrap_bind_symbol_libsocket(accept);
1101 swrap_bind_symbol_libsocket(bind);
1102 swrap_bind_symbol_libc(close);
1103 swrap_bind_symbol_libsocket(connect);
1104 swrap_bind_symbol_libc(dup);
1105 swrap_bind_symbol_libc(dup2);
1106 swrap_bind_symbol_libc(fcntl);
1107 swrap_bind_symbol_libc(fopen);
1109 swrap_bind_symbol_libc(fopen64);
1112 swrap_bind_symbol_libc(eventfd);
1114 swrap_bind_symbol_libsocket(getpeername);
1115 swrap_bind_symbol_libsocket(getsockname);
1116 swrap_bind_symbol_libsocket(getsockopt);
1117 swrap_bind_symbol_libc(ioctl);
1118 swrap_bind_symbol_libsocket(listen);
1119 swrap_bind_symbol_libc(open);
1121 swrap_bind_symbol_libc(open64);
1123 swrap_bind_symbol_libc(openat);
1124 swrap_bind_symbol_libsocket(pipe);
1125 swrap_bind_symbol_libc(read);
1126 swrap_bind_symbol_libsocket(readv);
1127 swrap_bind_symbol_libsocket(recv);
1128 swrap_bind_symbol_libsocket(recvfrom);
1129 swrap_bind_symbol_libsocket(recvmsg);
1130 swrap_bind_symbol_libsocket(send);
1131 swrap_bind_symbol_libsocket(sendmsg);
1132 swrap_bind_symbol_libsocket(sendto);
1133 swrap_bind_symbol_libsocket(setsockopt);
1134 #ifdef HAVE_SIGNALFD
1135 swrap_bind_symbol_libsocket(signalfd);
1137 swrap_bind_symbol_libsocket(socket);
1138 swrap_bind_symbol_libsocket(socketpair);
1139 #ifdef HAVE_TIMERFD_CREATE
1140 swrap_bind_symbol_libc(timerfd_create);
1142 swrap_bind_symbol_libc(write);
1143 swrap_bind_symbol_libsocket(writev);
1146 /*********************************************************
1147 * SWRAP HELPER FUNCTIONS
1148 *********************************************************/
1154 static const struct in6_addr *swrap_ipv6(void)
1156 static struct in6_addr v;
1157 static int initialized;
1165 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1174 static void set_port(int family, int prt, struct swrap_address *addr)
1178 addr->sa.in.sin_port = htons(prt);
1182 addr->sa.in6.sin6_port = htons(prt);
1188 static size_t socket_length(int family)
1192 return sizeof(struct sockaddr_in);
1195 return sizeof(struct sockaddr_in6);
1201 static struct socket_info *swrap_get_socket_info(int si_index)
1203 return (struct socket_info *)(&(sockets[si_index].info));
1206 static int swrap_get_refcount(struct socket_info *si)
1208 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1209 return sic->meta.refcount;
1212 static void swrap_inc_refcount(struct socket_info *si)
1214 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1216 sic->meta.refcount += 1;
1219 static void swrap_dec_refcount(struct socket_info *si)
1221 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1223 sic->meta.refcount -= 1;
1226 static int swrap_get_next_free(struct socket_info *si)
1228 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1230 return sic->meta.next_free;
1233 static void swrap_set_next_free(struct socket_info *si, int next_free)
1235 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1237 sic->meta.next_free = next_free;
1240 static const char *socket_wrapper_dir(void)
1242 const char *s = getenv("SOCKET_WRAPPER_DIR");
1246 /* TODO use realpath(3) here, when we add support for threads */
1247 if (strncmp(s, "./", 2) == 0) {
1251 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1255 static unsigned int socket_wrapper_mtu(void)
1257 static unsigned int max_mtu = 0;
1262 swrap_mutex_lock(&mtu_update_mutex);
1268 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1270 s = getenv("SOCKET_WRAPPER_MTU");
1275 tmp = strtol(s, &endp, 10);
1280 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1286 swrap_mutex_unlock(&mtu_update_mutex);
1290 static int socket_wrapper_init_mutex(pthread_mutex_t *m)
1292 pthread_mutexattr_t ma;
1295 ret = pthread_mutexattr_init(&ma);
1300 ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
1305 ret = pthread_mutex_init(m, &ma);
1308 pthread_mutexattr_destroy(&ma);
1313 static size_t socket_wrapper_max_sockets(void)
1319 if (max_sockets != 0) {
1323 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1325 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1326 if (s == NULL || s[0] == '\0') {
1330 tmp = strtoul(s, &endp, 10);
1334 if (tmp == 0 || tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1335 SWRAP_LOG(SWRAP_LOG_ERROR,
1336 "Invalid number of sockets specified, using default.");
1346 static void socket_wrapper_init_fds_idx(void)
1351 if (socket_fds_idx != NULL) {
1355 tmp = (int *)calloc(SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT, sizeof(int));
1357 SWRAP_LOG(SWRAP_LOG_ERROR,
1358 "Failed to allocate socket fds index array: %s",
1363 for (i = 0; i < SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT; i++) {
1367 socket_fds_idx = tmp;
1370 static void socket_wrapper_init_sockets(void)
1375 swrap_mutex_lock(&sockets_mutex);
1377 if (sockets != NULL) {
1378 swrap_mutex_unlock(&sockets_mutex);
1382 socket_wrapper_init_fds_idx();
1384 max_sockets = socket_wrapper_max_sockets();
1386 sockets = (struct socket_info_container *)calloc(max_sockets,
1387 sizeof(struct socket_info_container));
1389 if (sockets == NULL) {
1390 SWRAP_LOG(SWRAP_LOG_ERROR,
1391 "Failed to allocate sockets array: %s",
1393 swrap_mutex_unlock(&sockets_mutex);
1397 swrap_mutex_lock(&first_free_mutex);
1401 for (i = 0; i < max_sockets; i++) {
1402 swrap_set_next_free(&sockets[i].info, i+1);
1403 ret = socket_wrapper_init_mutex(&sockets[i].meta.mutex);
1405 SWRAP_LOG(SWRAP_LOG_ERROR,
1406 "Failed to initialize pthread mutex");
1411 /* mark the end of the free list */
1412 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1414 ret = socket_wrapper_init_mutex(&autobind_start_mutex);
1416 SWRAP_LOG(SWRAP_LOG_ERROR,
1417 "Failed to initialize pthread mutex");
1421 ret = socket_wrapper_init_mutex(&pcap_dump_mutex);
1423 SWRAP_LOG(SWRAP_LOG_ERROR,
1424 "Failed to initialize pthread mutex");
1428 ret = socket_wrapper_init_mutex(&mtu_update_mutex);
1430 SWRAP_LOG(SWRAP_LOG_ERROR,
1431 "Failed to initialize pthread mutex");
1436 swrap_mutex_unlock(&first_free_mutex);
1437 swrap_mutex_unlock(&sockets_mutex);
1443 bool socket_wrapper_enabled(void)
1445 const char *s = socket_wrapper_dir();
1451 socket_wrapper_init_sockets();
1456 static unsigned int socket_wrapper_default_iface(void)
1458 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1461 if (sscanf(s, "%u", &iface) == 1) {
1462 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1468 return 1;/* 127.0.0.1 */
1471 static void set_socket_info_index(int fd, int idx)
1473 socket_fds_idx[fd] = idx;
1474 /* This builtin issues a full memory barrier. */
1475 __sync_synchronize();
1478 static void reset_socket_info_index(int fd)
1480 set_socket_info_index(fd, -1);
1483 static int find_socket_info_index(int fd)
1489 if (socket_fds_idx == NULL) {
1493 if (fd >= SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT) {
1494 SWRAP_LOG(SWRAP_LOG_ERROR,
1495 "The max socket index limit of %u has been reached, "
1497 SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT,
1502 /* This builtin issues a full memory barrier. */
1503 __sync_synchronize();
1504 return socket_fds_idx[fd];
1507 static int swrap_add_socket_info(struct socket_info *si_input)
1509 struct socket_info *si = NULL;
1512 if (si_input == NULL) {
1517 swrap_mutex_lock(&first_free_mutex);
1518 if (first_free == -1) {
1523 si_index = first_free;
1524 si = swrap_get_socket_info(si_index);
1528 first_free = swrap_get_next_free(si);
1530 swrap_inc_refcount(si);
1532 SWRAP_UNLOCK_SI(si);
1535 swrap_mutex_unlock(&first_free_mutex);
1540 static int swrap_create_socket(struct socket_info *si, int fd)
1544 if (fd >= SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT) {
1545 SWRAP_LOG(SWRAP_LOG_ERROR,
1546 "The max socket index limit of %u has been reached, "
1548 SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT,
1553 idx = swrap_add_socket_info(si);
1558 set_socket_info_index(fd, idx);
1563 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1570 p = strrchr(un->sun_path, '/');
1571 if (p) p++; else p = un->sun_path;
1573 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1578 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1581 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1592 case SOCKET_TYPE_CHAR_TCP:
1593 case SOCKET_TYPE_CHAR_UDP: {
1594 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1596 if ((*len) < sizeof(*in2)) {
1601 memset(in2, 0, sizeof(*in2));
1602 in2->sin_family = AF_INET;
1603 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1604 in2->sin_port = htons(prt);
1606 *len = sizeof(*in2);
1610 case SOCKET_TYPE_CHAR_TCP_V6:
1611 case SOCKET_TYPE_CHAR_UDP_V6: {
1612 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1614 if ((*len) < sizeof(*in2)) {
1619 memset(in2, 0, sizeof(*in2));
1620 in2->sin6_family = AF_INET6;
1621 in2->sin6_addr = *swrap_ipv6();
1622 in2->sin6_addr.s6_addr[15] = iface;
1623 in2->sin6_port = htons(prt);
1625 *len = sizeof(*in2);
1637 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1645 if (bcast) *bcast = 0;
1647 switch (inaddr->sa_family) {
1649 const struct sockaddr_in *in =
1650 (const struct sockaddr_in *)(const void *)inaddr;
1651 unsigned int addr = ntohl(in->sin_addr.s_addr);
1658 u_type = SOCKET_TYPE_CHAR_TCP;
1661 u_type = SOCKET_TYPE_CHAR_UDP;
1662 a_type = SOCKET_TYPE_CHAR_UDP;
1663 b_type = SOCKET_TYPE_CHAR_UDP;
1666 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1667 errno = ESOCKTNOSUPPORT;
1671 prt = ntohs(in->sin_port);
1672 if (a_type && addr == 0xFFFFFFFF) {
1673 /* 255.255.255.255 only udp */
1676 iface = socket_wrapper_default_iface();
1677 } else if (b_type && addr == 0x7FFFFFFF) {
1678 /* 127.255.255.255 only udp */
1681 iface = socket_wrapper_default_iface();
1682 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1686 iface = (addr & 0x000000FF);
1688 errno = ENETUNREACH;
1691 if (bcast) *bcast = is_bcast;
1696 const struct sockaddr_in6 *in =
1697 (const struct sockaddr_in6 *)(const void *)inaddr;
1698 struct in6_addr cmp1, cmp2;
1702 type = SOCKET_TYPE_CHAR_TCP_V6;
1705 type = SOCKET_TYPE_CHAR_UDP_V6;
1708 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1709 errno = ESOCKTNOSUPPORT;
1713 /* XXX no multicast/broadcast */
1715 prt = ntohs(in->sin6_port);
1717 cmp1 = *swrap_ipv6();
1718 cmp2 = in->sin6_addr;
1719 cmp2.s6_addr[15] = 0;
1720 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1721 iface = in->sin6_addr.s6_addr[15];
1723 errno = ENETUNREACH;
1731 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1732 errno = ENETUNREACH;
1737 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1743 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1744 socket_wrapper_dir());
1745 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1746 /* the caller need to do more processing */
1750 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1751 socket_wrapper_dir(), type, iface, prt);
1752 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1757 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1766 if (bcast) *bcast = 0;
1768 switch (si->family) {
1770 const struct sockaddr_in *in =
1771 (const struct sockaddr_in *)(const void *)inaddr;
1772 unsigned int addr = ntohl(in->sin_addr.s_addr);
1778 prt = ntohs(in->sin_port);
1782 u_type = SOCKET_TYPE_CHAR_TCP;
1783 d_type = SOCKET_TYPE_CHAR_TCP;
1786 u_type = SOCKET_TYPE_CHAR_UDP;
1787 d_type = SOCKET_TYPE_CHAR_UDP;
1788 a_type = SOCKET_TYPE_CHAR_UDP;
1789 b_type = SOCKET_TYPE_CHAR_UDP;
1792 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1793 errno = ESOCKTNOSUPPORT;
1801 iface = socket_wrapper_default_iface();
1802 } else if (a_type && addr == 0xFFFFFFFF) {
1803 /* 255.255.255.255 only udp */
1806 iface = socket_wrapper_default_iface();
1807 } else if (b_type && addr == 0x7FFFFFFF) {
1808 /* 127.255.255.255 only udp */
1811 iface = socket_wrapper_default_iface();
1812 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1816 iface = (addr & 0x000000FF);
1818 errno = EADDRNOTAVAIL;
1822 /* Store the bind address for connect() */
1823 if (si->bindname.sa_socklen == 0) {
1824 struct sockaddr_in bind_in;
1825 socklen_t blen = sizeof(struct sockaddr_in);
1827 ZERO_STRUCT(bind_in);
1828 bind_in.sin_family = in->sin_family;
1829 bind_in.sin_port = in->sin_port;
1830 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1832 si->bindname.sa_socklen = blen;
1833 memcpy(&si->bindname.sa.in, &bind_in, blen);
1840 const struct sockaddr_in6 *in =
1841 (const struct sockaddr_in6 *)(const void *)inaddr;
1842 struct in6_addr cmp1, cmp2;
1846 type = SOCKET_TYPE_CHAR_TCP_V6;
1849 type = SOCKET_TYPE_CHAR_UDP_V6;
1852 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1853 errno = ESOCKTNOSUPPORT;
1857 /* XXX no multicast/broadcast */
1859 prt = ntohs(in->sin6_port);
1861 cmp1 = *swrap_ipv6();
1862 cmp2 = in->sin6_addr;
1863 cmp2.s6_addr[15] = 0;
1864 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1865 iface = socket_wrapper_default_iface();
1866 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1867 iface = in->sin6_addr.s6_addr[15];
1869 errno = EADDRNOTAVAIL;
1873 /* Store the bind address for connect() */
1874 if (si->bindname.sa_socklen == 0) {
1875 struct sockaddr_in6 bind_in;
1876 socklen_t blen = sizeof(struct sockaddr_in6);
1878 ZERO_STRUCT(bind_in);
1879 bind_in.sin6_family = in->sin6_family;
1880 bind_in.sin6_port = in->sin6_port;
1882 bind_in.sin6_addr = *swrap_ipv6();
1883 bind_in.sin6_addr.s6_addr[15] = iface;
1885 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1886 si->bindname.sa_socklen = blen;
1893 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1894 errno = EADDRNOTAVAIL;
1899 if (bcast) *bcast = is_bcast;
1901 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1907 /* handle auto-allocation of ephemeral ports */
1908 for (prt = 5001; prt < 10000; prt++) {
1909 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1910 socket_wrapper_dir(), type, iface, prt);
1911 if (stat(un->sun_path, &st) == 0) continue;
1913 set_port(si->family, prt, &si->myname);
1914 set_port(si->family, prt, &si->bindname);
1924 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1925 socket_wrapper_dir(), type, iface, prt);
1926 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1930 static struct socket_info *find_socket_info(int fd)
1932 int idx = find_socket_info_index(fd);
1938 return swrap_get_socket_info(idx);
1942 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1944 struct socket_info_fd *f;
1945 const struct socket_info *last_s = NULL;
1947 /* first catch invalid input */
1948 switch (sa->sa_family) {
1950 if (len < sizeof(struct sockaddr_in)) {
1956 if (len < sizeof(struct sockaddr_in6)) {
1966 for (f = socket_fds; f; f = f->next) {
1967 struct socket_info *s = swrap_get_socket_info(f->si_index);
1974 if (s->myname == NULL) {
1977 if (s->myname->sa_family != sa->sa_family) {
1980 switch (s->myname->sa_family) {
1982 struct sockaddr_in *sin1, *sin2;
1984 sin1 = (struct sockaddr_in *)s->myname;
1985 sin2 = (struct sockaddr_in *)sa;
1987 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1990 if (sin1->sin_port != sin2->sin_port) {
1993 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
2003 struct sockaddr_in6 *sin1, *sin2;
2005 sin1 = (struct sockaddr_in6 *)s->myname;
2006 sin2 = (struct sockaddr_in6 *)sa;
2008 if (sin1->sin6_port != sin2->sin6_port) {
2011 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
2033 static void swrap_remove_stale(int fd)
2035 struct socket_info *si;
2038 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
2040 swrap_mutex_lock(&socket_reset_mutex);
2042 si_index = find_socket_info_index(fd);
2043 if (si_index == -1) {
2044 swrap_mutex_unlock(&socket_reset_mutex);
2048 reset_socket_info_index(fd);
2050 swrap_mutex_unlock(&socket_reset_mutex);
2052 si = swrap_get_socket_info(si_index);
2054 swrap_mutex_lock(&first_free_mutex);
2057 swrap_dec_refcount(si);
2059 if (swrap_get_refcount(si) > 0) {
2063 if (si->un_addr.sun_path[0] != '\0') {
2064 unlink(si->un_addr.sun_path);
2067 swrap_set_next_free(si, first_free);
2068 first_free = si_index;
2071 SWRAP_UNLOCK_SI(si);
2072 swrap_mutex_unlock(&first_free_mutex);
2075 static int sockaddr_convert_to_un(struct socket_info *si,
2076 const struct sockaddr *in_addr,
2078 struct sockaddr_un *out_addr,
2082 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
2084 (void) in_len; /* unused */
2086 if (out_addr == NULL) {
2090 out->sa_family = AF_UNIX;
2091 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2092 out->sa_len = sizeof(*out_addr);
2095 switch (in_addr->sa_family) {
2097 const struct sockaddr_in *sin;
2098 if (si->family != AF_INET) {
2101 if (in_len < sizeof(struct sockaddr_in)) {
2104 sin = (const struct sockaddr_in *)(const void *)in_addr;
2105 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2110 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2111 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2125 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2126 errno = ESOCKTNOSUPPORT;
2130 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2132 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2138 errno = EAFNOSUPPORT;
2139 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2143 static int sockaddr_convert_from_un(const struct socket_info *si,
2144 const struct sockaddr_un *in_addr,
2145 socklen_t un_addrlen,
2147 struct sockaddr *out_addr,
2148 socklen_t *out_addrlen)
2152 if (out_addr == NULL || out_addrlen == NULL)
2155 if (un_addrlen == 0) {
2170 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2171 errno = ESOCKTNOSUPPORT;
2174 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2175 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2176 out_addr->sa_len = *out_addrlen;
2183 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2184 errno = EAFNOSUPPORT;
2188 enum swrap_packet_type {
2190 SWRAP_CONNECT_UNREACH,
2198 SWRAP_SENDTO_UNREACH,
2209 struct swrap_file_hdr {
2211 uint16_t version_major;
2212 uint16_t version_minor;
2215 uint32_t frame_max_len;
2216 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2219 #define SWRAP_FILE_HDR_SIZE 24
2221 struct swrap_packet_frame {
2223 uint32_t micro_seconds;
2224 uint32_t recorded_length;
2225 uint32_t full_length;
2227 #define SWRAP_PACKET_FRAME_SIZE 16
2229 union swrap_packet_ip {
2233 uint16_t packet_length;
2234 uint16_t identification;
2239 uint16_t hdr_checksum;
2243 #define SWRAP_PACKET_IP_V4_SIZE 20
2246 uint8_t flow_label_high;
2247 uint16_t flow_label_low;
2248 uint16_t payload_length;
2249 uint8_t next_header;
2251 uint8_t src_addr[16];
2252 uint8_t dest_addr[16];
2254 #define SWRAP_PACKET_IP_V6_SIZE 40
2256 #define SWRAP_PACKET_IP_SIZE 40
2258 union swrap_packet_payload {
2260 uint16_t source_port;
2270 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2272 uint16_t source_port;
2277 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2284 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2291 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2293 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2295 #define SWRAP_PACKET_MIN_ALLOC \
2296 (SWRAP_PACKET_FRAME_SIZE + \
2297 SWRAP_PACKET_IP_SIZE + \
2298 SWRAP_PACKET_PAYLOAD_SIZE)
2300 static const char *swrap_pcap_init_file(void)
2302 static int initialized = 0;
2303 static const char *s = NULL;
2304 static const struct swrap_file_hdr h;
2305 static const struct swrap_packet_frame f;
2306 static const union swrap_packet_ip i;
2307 static const union swrap_packet_payload p;
2309 if (initialized == 1) {
2315 * TODO: don't use the structs use plain buffer offsets
2316 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2318 * for now make sure we disable PCAP support
2319 * if the struct has alignment!
2321 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2324 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2327 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2330 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2333 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2336 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2339 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2342 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2345 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2348 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2352 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2356 if (strncmp(s, "./", 2) == 0) {
2362 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2363 const struct sockaddr *src,
2364 const struct sockaddr *dest,
2366 const uint8_t *payload,
2368 unsigned long tcp_seqno,
2369 unsigned long tcp_ack,
2370 unsigned char tcp_ctl,
2372 size_t *_packet_len)
2376 struct swrap_packet_frame *frame;
2377 union swrap_packet_ip *ip;
2378 union swrap_packet_payload *pay;
2381 size_t nonwire_len = sizeof(*frame);
2382 size_t wire_hdr_len = 0;
2383 size_t wire_len = 0;
2384 size_t ip_hdr_len = 0;
2385 size_t icmp_hdr_len = 0;
2386 size_t icmp_truncate_len = 0;
2387 uint8_t protocol = 0, icmp_protocol = 0;
2388 const struct sockaddr_in *src_in = NULL;
2389 const struct sockaddr_in *dest_in = NULL;
2391 const struct sockaddr_in6 *src_in6 = NULL;
2392 const struct sockaddr_in6 *dest_in6 = NULL;
2397 switch (src->sa_family) {
2399 src_in = (const struct sockaddr_in *)(const void *)src;
2400 dest_in = (const struct sockaddr_in *)(const void *)dest;
2401 src_port = src_in->sin_port;
2402 dest_port = dest_in->sin_port;
2403 ip_hdr_len = sizeof(ip->v4);
2407 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2408 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2409 src_port = src_in6->sin6_port;
2410 dest_port = dest_in6->sin6_port;
2411 ip_hdr_len = sizeof(ip->v6);
2418 switch (socket_type) {
2420 protocol = 0x06; /* TCP */
2421 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2422 wire_len = wire_hdr_len + payload_len;
2426 protocol = 0x11; /* UDP */
2427 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2428 wire_len = wire_hdr_len + payload_len;
2436 icmp_protocol = protocol;
2437 switch (src->sa_family) {
2439 protocol = 0x01; /* ICMPv4 */
2440 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2444 protocol = 0x3A; /* ICMPv6 */
2445 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2449 if (wire_len > 64 ) {
2450 icmp_truncate_len = wire_len - 64;
2452 wire_hdr_len += icmp_hdr_len;
2453 wire_len += icmp_hdr_len;
2456 packet_len = nonwire_len + wire_len;
2457 alloc_len = packet_len;
2458 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2459 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2462 base = (uint8_t *)calloc(1, alloc_len);
2469 frame = (struct swrap_packet_frame *)(void *)buf;
2470 frame->seconds = tval->tv_sec;
2471 frame->micro_seconds = tval->tv_usec;
2472 frame->recorded_length = wire_len - icmp_truncate_len;
2473 frame->full_length = wire_len - icmp_truncate_len;
2474 buf += SWRAP_PACKET_FRAME_SIZE;
2476 ip = (union swrap_packet_ip *)(void *)buf;
2477 switch (src->sa_family) {
2479 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2481 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2482 ip->v4.identification = htons(0xFFFF);
2483 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2484 ip->v4.fragment = htons(0x0000);
2486 ip->v4.protocol = protocol;
2487 ip->v4.hdr_checksum = htons(0x0000);
2488 ip->v4.src_addr = src_in->sin_addr.s_addr;
2489 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2490 buf += SWRAP_PACKET_IP_V4_SIZE;
2494 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2495 ip->v6.flow_label_high = 0x00;
2496 ip->v6.flow_label_low = 0x0000;
2497 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2498 ip->v6.next_header = protocol;
2499 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2500 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2501 buf += SWRAP_PACKET_IP_V6_SIZE;
2507 pay = (union swrap_packet_payload *)(void *)buf;
2508 switch (src->sa_family) {
2510 pay->icmp4.type = 0x03; /* destination unreachable */
2511 pay->icmp4.code = 0x01; /* host unreachable */
2512 pay->icmp4.checksum = htons(0x0000);
2513 pay->icmp4.unused = htonl(0x00000000);
2514 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2516 /* set the ip header in the ICMP payload */
2517 ip = (union swrap_packet_ip *)(void *)buf;
2518 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2520 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2521 ip->v4.identification = htons(0xFFFF);
2522 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2523 ip->v4.fragment = htons(0x0000);
2525 ip->v4.protocol = icmp_protocol;
2526 ip->v4.hdr_checksum = htons(0x0000);
2527 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2528 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2529 buf += SWRAP_PACKET_IP_V4_SIZE;
2531 src_port = dest_in->sin_port;
2532 dest_port = src_in->sin_port;
2536 pay->icmp6.type = 0x01; /* destination unreachable */
2537 pay->icmp6.code = 0x03; /* address unreachable */
2538 pay->icmp6.checksum = htons(0x0000);
2539 pay->icmp6.unused = htonl(0x00000000);
2540 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2542 /* set the ip header in the ICMP payload */
2543 ip = (union swrap_packet_ip *)(void *)buf;
2544 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2545 ip->v6.flow_label_high = 0x00;
2546 ip->v6.flow_label_low = 0x0000;
2547 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2548 ip->v6.next_header = protocol;
2549 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2550 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2551 buf += SWRAP_PACKET_IP_V6_SIZE;
2553 src_port = dest_in6->sin6_port;
2554 dest_port = src_in6->sin6_port;
2560 pay = (union swrap_packet_payload *)(void *)buf;
2562 switch (socket_type) {
2564 pay->tcp.source_port = src_port;
2565 pay->tcp.dest_port = dest_port;
2566 pay->tcp.seq_num = htonl(tcp_seqno);
2567 pay->tcp.ack_num = htonl(tcp_ack);
2568 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2569 pay->tcp.control = tcp_ctl;
2570 pay->tcp.window = htons(0x7FFF);
2571 pay->tcp.checksum = htons(0x0000);
2572 pay->tcp.urg = htons(0x0000);
2573 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2578 pay->udp.source_port = src_port;
2579 pay->udp.dest_port = dest_port;
2580 pay->udp.length = htons(8 + payload_len);
2581 pay->udp.checksum = htons(0x0000);
2582 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2587 if (payload && payload_len > 0) {
2588 memcpy(buf, payload, payload_len);
2591 *_packet_len = packet_len - icmp_truncate_len;
2595 static int swrap_pcap_get_fd(const char *fname)
2603 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2605 struct swrap_file_hdr file_hdr;
2606 file_hdr.magic = 0xA1B2C3D4;
2607 file_hdr.version_major = 0x0002;
2608 file_hdr.version_minor = 0x0004;
2609 file_hdr.timezone = 0x00000000;
2610 file_hdr.sigfigs = 0x00000000;
2611 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2612 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2614 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2621 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2626 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2627 const struct sockaddr *addr,
2628 enum swrap_packet_type type,
2629 const void *buf, size_t len,
2632 const struct sockaddr *src_addr;
2633 const struct sockaddr *dest_addr;
2634 unsigned long tcp_seqno = 0;
2635 unsigned long tcp_ack = 0;
2636 unsigned char tcp_ctl = 0;
2637 int unreachable = 0;
2641 switch (si->family) {
2653 case SWRAP_CONNECT_SEND:
2654 if (si->type != SOCK_STREAM) {
2658 src_addr = &si->myname.sa.s;
2661 tcp_seqno = si->io.pck_snd;
2662 tcp_ack = si->io.pck_rcv;
2663 tcp_ctl = 0x02; /* SYN */
2665 si->io.pck_snd += 1;
2669 case SWRAP_CONNECT_RECV:
2670 if (si->type != SOCK_STREAM) {
2674 dest_addr = &si->myname.sa.s;
2677 tcp_seqno = si->io.pck_rcv;
2678 tcp_ack = si->io.pck_snd;
2679 tcp_ctl = 0x12; /** SYN,ACK */
2681 si->io.pck_rcv += 1;
2685 case SWRAP_CONNECT_UNREACH:
2686 if (si->type != SOCK_STREAM) {
2690 dest_addr = &si->myname.sa.s;
2693 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2694 tcp_seqno = si->io.pck_snd - 1;
2695 tcp_ack = si->io.pck_rcv;
2696 tcp_ctl = 0x02; /* SYN */
2701 case SWRAP_CONNECT_ACK:
2702 if (si->type != SOCK_STREAM) {
2706 src_addr = &si->myname.sa.s;
2709 tcp_seqno = si->io.pck_snd;
2710 tcp_ack = si->io.pck_rcv;
2711 tcp_ctl = 0x10; /* ACK */
2715 case SWRAP_ACCEPT_SEND:
2716 if (si->type != SOCK_STREAM) {
2720 dest_addr = &si->myname.sa.s;
2723 tcp_seqno = si->io.pck_rcv;
2724 tcp_ack = si->io.pck_snd;
2725 tcp_ctl = 0x02; /* SYN */
2727 si->io.pck_rcv += 1;
2731 case SWRAP_ACCEPT_RECV:
2732 if (si->type != SOCK_STREAM) {
2736 src_addr = &si->myname.sa.s;
2739 tcp_seqno = si->io.pck_snd;
2740 tcp_ack = si->io.pck_rcv;
2741 tcp_ctl = 0x12; /* SYN,ACK */
2743 si->io.pck_snd += 1;
2747 case SWRAP_ACCEPT_ACK:
2748 if (si->type != SOCK_STREAM) {
2752 dest_addr = &si->myname.sa.s;
2755 tcp_seqno = si->io.pck_rcv;
2756 tcp_ack = si->io.pck_snd;
2757 tcp_ctl = 0x10; /* ACK */
2762 src_addr = &si->myname.sa.s;
2763 dest_addr = &si->peername.sa.s;
2765 tcp_seqno = si->io.pck_snd;
2766 tcp_ack = si->io.pck_rcv;
2767 tcp_ctl = 0x18; /* PSH,ACK */
2769 si->io.pck_snd += len;
2773 case SWRAP_SEND_RST:
2774 dest_addr = &si->myname.sa.s;
2775 src_addr = &si->peername.sa.s;
2777 if (si->type == SOCK_DGRAM) {
2778 return swrap_pcap_marshall_packet(si,
2780 SWRAP_SENDTO_UNREACH,
2786 tcp_seqno = si->io.pck_rcv;
2787 tcp_ack = si->io.pck_snd;
2788 tcp_ctl = 0x14; /** RST,ACK */
2792 case SWRAP_PENDING_RST:
2793 dest_addr = &si->myname.sa.s;
2794 src_addr = &si->peername.sa.s;
2796 if (si->type == SOCK_DGRAM) {
2800 tcp_seqno = si->io.pck_rcv;
2801 tcp_ack = si->io.pck_snd;
2802 tcp_ctl = 0x14; /* RST,ACK */
2807 dest_addr = &si->myname.sa.s;
2808 src_addr = &si->peername.sa.s;
2810 tcp_seqno = si->io.pck_rcv;
2811 tcp_ack = si->io.pck_snd;
2812 tcp_ctl = 0x18; /* PSH,ACK */
2814 si->io.pck_rcv += len;
2818 case SWRAP_RECV_RST:
2819 dest_addr = &si->myname.sa.s;
2820 src_addr = &si->peername.sa.s;
2822 if (si->type == SOCK_DGRAM) {
2826 tcp_seqno = si->io.pck_rcv;
2827 tcp_ack = si->io.pck_snd;
2828 tcp_ctl = 0x14; /* RST,ACK */
2833 src_addr = &si->myname.sa.s;
2836 si->io.pck_snd += len;
2840 case SWRAP_SENDTO_UNREACH:
2841 dest_addr = &si->myname.sa.s;
2848 case SWRAP_RECVFROM:
2849 dest_addr = &si->myname.sa.s;
2852 si->io.pck_rcv += len;
2856 case SWRAP_CLOSE_SEND:
2857 if (si->type != SOCK_STREAM) {
2861 src_addr = &si->myname.sa.s;
2862 dest_addr = &si->peername.sa.s;
2864 tcp_seqno = si->io.pck_snd;
2865 tcp_ack = si->io.pck_rcv;
2866 tcp_ctl = 0x11; /* FIN, ACK */
2868 si->io.pck_snd += 1;
2872 case SWRAP_CLOSE_RECV:
2873 if (si->type != SOCK_STREAM) {
2877 dest_addr = &si->myname.sa.s;
2878 src_addr = &si->peername.sa.s;
2880 tcp_seqno = si->io.pck_rcv;
2881 tcp_ack = si->io.pck_snd;
2882 tcp_ctl = 0x11; /* FIN,ACK */
2884 si->io.pck_rcv += 1;
2888 case SWRAP_CLOSE_ACK:
2889 if (si->type != SOCK_STREAM) {
2893 src_addr = &si->myname.sa.s;
2894 dest_addr = &si->peername.sa.s;
2896 tcp_seqno = si->io.pck_snd;
2897 tcp_ack = si->io.pck_rcv;
2898 tcp_ctl = 0x10; /* ACK */
2905 swrapGetTimeOfDay(&tv);
2907 return swrap_pcap_packet_init(&tv,
2911 (const uint8_t *)buf,
2920 static void swrap_pcap_dump_packet(struct socket_info *si,
2921 const struct sockaddr *addr,
2922 enum swrap_packet_type type,
2923 const void *buf, size_t len)
2925 const char *file_name;
2927 size_t packet_len = 0;
2930 swrap_mutex_lock(&pcap_dump_mutex);
2932 file_name = swrap_pcap_init_file();
2937 packet = swrap_pcap_marshall_packet(si,
2943 if (packet == NULL) {
2947 fd = swrap_pcap_get_fd(file_name);
2949 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2958 swrap_mutex_unlock(&pcap_dump_mutex);
2961 /****************************************************************************
2963 ***************************************************************************/
2965 #ifdef HAVE_SIGNALFD
2966 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2970 rc = libc_signalfd(fd, mask, flags);
2972 swrap_remove_stale(fd);
2978 int signalfd(int fd, const sigset_t *mask, int flags)
2980 return swrap_signalfd(fd, mask, flags);
2984 /****************************************************************************
2986 ***************************************************************************/
2988 static int swrap_socket(int family, int type, int protocol)
2990 struct socket_info *si = NULL;
2991 struct socket_info _si = { 0 };
2994 int real_type = type;
2997 * Remove possible addition flags passed to socket() so
2998 * do not fail checking the type.
2999 * See https://lwn.net/Articles/281965/
3002 real_type &= ~SOCK_CLOEXEC;
3004 #ifdef SOCK_NONBLOCK
3005 real_type &= ~SOCK_NONBLOCK;
3008 if (!socket_wrapper_enabled()) {
3009 return libc_socket(family, type, protocol);
3020 #endif /* AF_NETLINK */
3023 #endif /* AF_PACKET */
3025 return libc_socket(family, type, protocol);
3027 errno = EAFNOSUPPORT;
3031 switch (real_type) {
3037 errno = EPROTONOSUPPORT;
3045 if (real_type == SOCK_STREAM) {
3050 if (real_type == SOCK_DGRAM) {
3055 errno = EPROTONOSUPPORT;
3060 * We must call libc_socket with type, from the caller, not the version
3061 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
3063 fd = libc_socket(AF_UNIX, type, 0);
3069 /* Check if we have a stale fd and remove it */
3070 swrap_remove_stale(fd);
3073 si->family = family;
3075 /* however, the rest of the socket_wrapper code expects just
3076 * the type, not the flags */
3077 si->type = real_type;
3078 si->protocol = protocol;
3081 * Setup myname so getsockname() can succeed to find out the socket
3084 switch(si->family) {
3086 struct sockaddr_in sin = {
3087 .sin_family = AF_INET,
3090 si->myname.sa_socklen = sizeof(struct sockaddr_in);
3091 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
3095 struct sockaddr_in6 sin6 = {
3096 .sin6_family = AF_INET6,
3099 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
3100 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3108 ret = swrap_create_socket(si, fd);
3113 SWRAP_LOG(SWRAP_LOG_TRACE,
3114 "Created %s socket for protocol %s",
3115 family == AF_INET ? "IPv4" : "IPv6",
3116 real_type == SOCK_DGRAM ? "UDP" : "TCP");
3121 int socket(int family, int type, int protocol)
3123 return swrap_socket(family, type, protocol);
3126 /****************************************************************************
3128 ***************************************************************************/
3130 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3134 rc = libc_socketpair(family, type, protocol, sv);
3136 swrap_remove_stale(sv[0]);
3137 swrap_remove_stale(sv[1]);
3143 int socketpair(int family, int type, int protocol, int sv[2])
3145 return swrap_socketpair(family, type, protocol, sv);
3148 /****************************************************************************
3150 ***************************************************************************/
3152 #ifdef HAVE_TIMERFD_CREATE
3153 static int swrap_timerfd_create(int clockid, int flags)
3157 fd = libc_timerfd_create(clockid, flags);
3159 swrap_remove_stale(fd);
3165 int timerfd_create(int clockid, int flags)
3167 return swrap_timerfd_create(clockid, flags);
3171 /****************************************************************************
3173 ***************************************************************************/
3175 static int swrap_pipe(int pipefd[2])
3179 rc = libc_pipe(pipefd);
3181 swrap_remove_stale(pipefd[0]);
3182 swrap_remove_stale(pipefd[1]);
3188 int pipe(int pipefd[2])
3190 return swrap_pipe(pipefd);
3193 /****************************************************************************
3195 ***************************************************************************/
3197 static int swrap_accept(int s,
3198 struct sockaddr *addr,
3202 struct socket_info *parent_si, *child_si;
3203 struct socket_info new_si = { 0 };
3206 struct swrap_address un_addr = {
3207 .sa_socklen = sizeof(struct sockaddr_un),
3209 struct swrap_address un_my_addr = {
3210 .sa_socklen = sizeof(struct sockaddr_un),
3212 struct swrap_address in_addr = {
3213 .sa_socklen = sizeof(struct sockaddr_storage),
3215 struct swrap_address in_my_addr = {
3216 .sa_socklen = sizeof(struct sockaddr_storage),
3220 parent_si = find_socket_info(s);
3223 return libc_accept4(s, addr, addrlen, flags);
3226 return libc_accept(s, addr, addrlen);
3232 * prevent parent_si from being altered / closed
3235 SWRAP_LOCK_SI(parent_si);
3238 * assume out sockaddr have the same size as the in parent
3241 in_addr.sa_socklen = socket_length(parent_si->family);
3242 if (in_addr.sa_socklen <= 0) {
3243 SWRAP_UNLOCK_SI(parent_si);
3248 SWRAP_UNLOCK_SI(parent_si);
3251 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3254 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3257 if (errno == ENOTSOCK) {
3258 /* Remove stale fds */
3259 swrap_remove_stale(s);
3266 SWRAP_LOCK_SI(parent_si);
3268 ret = sockaddr_convert_from_un(parent_si,
3273 &in_addr.sa_socklen);
3275 SWRAP_UNLOCK_SI(parent_si);
3282 child_si->family = parent_si->family;
3283 child_si->type = parent_si->type;
3284 child_si->protocol = parent_si->protocol;
3285 child_si->bound = 1;
3286 child_si->is_server = 1;
3287 child_si->connected = 1;
3289 SWRAP_UNLOCK_SI(parent_si);
3291 child_si->peername = (struct swrap_address) {
3292 .sa_socklen = in_addr.sa_socklen,
3294 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3296 if (addr != NULL && addrlen != NULL) {
3297 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3299 memcpy(addr, &in_addr.sa.ss, copy_len);
3301 *addrlen = in_addr.sa_socklen;
3304 ret = libc_getsockname(fd,
3306 &un_my_addr.sa_socklen);
3312 ret = sockaddr_convert_from_un(child_si,
3314 un_my_addr.sa_socklen,
3317 &in_my_addr.sa_socklen);
3323 SWRAP_LOG(SWRAP_LOG_TRACE,
3324 "accept() path=%s, fd=%d",
3325 un_my_addr.sa.un.sun_path, s);
3327 child_si->myname = (struct swrap_address) {
3328 .sa_socklen = in_my_addr.sa_socklen,
3330 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3332 idx = swrap_create_socket(&new_si, fd);
3339 struct socket_info *si = swrap_get_socket_info(idx);
3342 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3343 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3344 swrap_pcap_dump_packet(si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3345 SWRAP_UNLOCK_SI(si);
3352 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3354 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3358 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3359 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3361 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3364 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3367 static int autobind_start_init;
3368 static int autobind_start;
3370 /* using sendto() or connect() on an unbound socket would give the
3371 recipient no way to reply, as unlike UDP and TCP, a unix domain
3372 socket can't auto-assign ephemeral port numbers, so we need to
3374 Note: this might change the family from ipv6 to ipv4
3376 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3378 struct swrap_address un_addr = {
3379 .sa_socklen = sizeof(struct sockaddr_un),
3387 swrap_mutex_lock(&autobind_start_mutex);
3389 if (autobind_start_init != 1) {
3390 autobind_start_init = 1;
3391 autobind_start = getpid();
3392 autobind_start %= 50000;
3393 autobind_start += 10000;
3396 un_addr.sa.un.sun_family = AF_UNIX;
3400 struct sockaddr_in in;
3404 type = SOCKET_TYPE_CHAR_TCP;
3407 type = SOCKET_TYPE_CHAR_UDP;
3410 errno = ESOCKTNOSUPPORT;
3415 memset(&in, 0, sizeof(in));
3416 in.sin_family = AF_INET;
3417 in.sin_addr.s_addr = htonl(127<<24 |
3418 socket_wrapper_default_iface());
3420 si->myname = (struct swrap_address) {
3421 .sa_socklen = sizeof(in),
3423 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3428 struct sockaddr_in6 in6;
3430 if (si->family != family) {
3431 errno = ENETUNREACH;
3438 type = SOCKET_TYPE_CHAR_TCP_V6;
3441 type = SOCKET_TYPE_CHAR_UDP_V6;
3444 errno = ESOCKTNOSUPPORT;
3449 memset(&in6, 0, sizeof(in6));
3450 in6.sin6_family = AF_INET6;
3451 in6.sin6_addr = *swrap_ipv6();
3452 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3454 si->myname = (struct swrap_address) {
3455 .sa_socklen = sizeof(in6),
3457 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3462 errno = ESOCKTNOSUPPORT;
3467 if (autobind_start > 60000) {
3468 autobind_start = 10000;
3471 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3472 port = autobind_start + i;
3473 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3474 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3475 type, socket_wrapper_default_iface(), port);
3476 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3478 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3483 si->un_addr = un_addr.sa.un;
3486 autobind_start = port + 1;
3489 if (i == SOCKET_MAX_SOCKETS) {
3490 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3491 "interface "SOCKET_FORMAT,
3494 socket_wrapper_default_iface(),
3501 si->family = family;
3502 set_port(si->family, port, &si->myname);
3507 swrap_mutex_unlock(&autobind_start_mutex);
3511 /****************************************************************************
3513 ***************************************************************************/
3515 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3519 struct swrap_address un_addr = {
3520 .sa_socklen = sizeof(struct sockaddr_un),
3522 struct socket_info *si = find_socket_info(s);
3526 return libc_connect(s, serv_addr, addrlen);
3531 if (si->bound == 0) {
3532 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3538 if (si->family != serv_addr->sa_family) {
3544 ret = sockaddr_convert_to_un(si, serv_addr,
3545 addrlen, &un_addr.sa.un, 0, &bcast);
3551 errno = ENETUNREACH;
3556 if (si->type == SOCK_DGRAM) {
3557 si->defer_connect = 1;
3560 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3562 ret = libc_connect(s,
3564 un_addr.sa_socklen);
3567 SWRAP_LOG(SWRAP_LOG_TRACE,
3568 "connect() path=%s, fd=%d",
3569 un_addr.sa.un.sun_path, s);
3572 /* to give better errors */
3573 if (ret == -1 && errno == ENOENT) {
3574 errno = EHOSTUNREACH;
3578 si->peername = (struct swrap_address) {
3579 .sa_socklen = addrlen,
3582 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3586 * When we connect() on a socket than we have to bind the
3587 * outgoing connection on the interface we use for the
3588 * transport. We already bound it on the right interface
3589 * but here we have to update the name so getsockname()
3590 * returns correct information.
3592 if (si->bindname.sa_socklen > 0) {
3593 si->myname = (struct swrap_address) {
3594 .sa_socklen = si->bindname.sa_socklen,
3597 memcpy(&si->myname.sa.ss,
3598 &si->bindname.sa.ss,
3599 si->bindname.sa_socklen);
3601 /* Cleanup bindname */
3602 si->bindname = (struct swrap_address) {
3607 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3608 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3610 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3614 SWRAP_UNLOCK_SI(si);
3618 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3620 return swrap_connect(s, serv_addr, addrlen);
3623 /****************************************************************************
3625 ***************************************************************************/
3627 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3630 struct swrap_address un_addr = {
3631 .sa_socklen = sizeof(struct sockaddr_un),
3633 struct socket_info *si = find_socket_info(s);
3640 return libc_bind(s, myaddr, addrlen);
3645 switch (si->family) {
3647 const struct sockaddr_in *sin;
3648 if (addrlen < sizeof(struct sockaddr_in)) {
3649 bind_error = EINVAL;
3653 sin = (const struct sockaddr_in *)(const void *)myaddr;
3655 if (sin->sin_family != AF_INET) {
3656 bind_error = EAFNOSUPPORT;
3659 /* special case for AF_UNSPEC */
3660 if (sin->sin_family == AF_UNSPEC &&
3661 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3670 const struct sockaddr_in6 *sin6;
3671 if (addrlen < sizeof(struct sockaddr_in6)) {
3672 bind_error = EINVAL;
3676 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3678 if (sin6->sin6_family != AF_INET6) {
3679 bind_error = EAFNOSUPPORT;
3686 bind_error = EINVAL;
3690 if (bind_error != 0) {
3697 in_use = check_addr_port_in_use(myaddr, addrlen);
3705 si->myname.sa_socklen = addrlen;
3706 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3708 ret = sockaddr_convert_to_un(si,
3718 unlink(un_addr.sa.un.sun_path);
3720 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3722 SWRAP_LOG(SWRAP_LOG_TRACE,
3723 "bind() path=%s, fd=%d",
3724 un_addr.sa.un.sun_path, s);
3731 SWRAP_UNLOCK_SI(si);
3736 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3738 return swrap_bind(s, myaddr, addrlen);
3741 /****************************************************************************
3743 ***************************************************************************/
3745 #ifdef HAVE_BINDRESVPORT
3746 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3748 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3750 struct swrap_address myaddr = {
3751 .sa_socklen = sizeof(struct sockaddr_storage),
3754 static uint16_t port;
3759 #define SWRAP_STARTPORT 600
3760 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3761 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3764 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3768 salen = myaddr.sa_socklen;
3771 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3777 memset(&myaddr.sa.ss, 0, salen);
3782 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3785 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3787 salen = sizeof(struct sockaddr_in);
3788 sinp->sin_port = htons(port);
3792 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3794 salen = sizeof(struct sockaddr_in6);
3795 sin6p->sin6_port = htons(port);
3799 errno = EAFNOSUPPORT;
3804 if (port > SWRAP_ENDPORT) {
3805 port = SWRAP_STARTPORT;
3808 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3809 if (rc == 0 || errno != EADDRINUSE) {
3817 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3819 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3823 /****************************************************************************
3825 ***************************************************************************/
3827 static int swrap_listen(int s, int backlog)
3830 struct socket_info *si = find_socket_info(s);
3833 return libc_listen(s, backlog);
3838 if (si->bound == 0) {
3839 ret = swrap_auto_bind(s, si, si->family);
3846 ret = libc_listen(s, backlog);
3849 SWRAP_UNLOCK_SI(si);
3854 int listen(int s, int backlog)
3856 return swrap_listen(s, backlog);
3859 /****************************************************************************
3861 ***************************************************************************/
3863 static FILE *swrap_fopen(const char *name, const char *mode)
3867 fp = libc_fopen(name, mode);
3869 int fd = fileno(fp);
3871 swrap_remove_stale(fd);
3877 FILE *fopen(const char *name, const char *mode)
3879 return swrap_fopen(name, mode);
3882 /****************************************************************************
3884 ***************************************************************************/
3887 static FILE *swrap_fopen64(const char *name, const char *mode)
3891 fp = libc_fopen64(name, mode);
3893 int fd = fileno(fp);
3895 swrap_remove_stale(fd);
3901 FILE *fopen64(const char *name, const char *mode)
3903 return swrap_fopen64(name, mode);
3905 #endif /* HAVE_FOPEN64 */
3907 /****************************************************************************
3909 ***************************************************************************/
3911 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3915 ret = libc_vopen(pathname, flags, ap);
3918 * There are methods for closing descriptors (libc-internal code
3919 * paths, direct syscalls) which close descriptors in ways that
3920 * we can't intercept, so try to recover when we notice that
3923 swrap_remove_stale(ret);
3928 int open(const char *pathname, int flags, ...)
3933 va_start(ap, flags);
3934 fd = swrap_vopen(pathname, flags, ap);
3940 /****************************************************************************
3942 ***************************************************************************/
3945 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
3949 ret = libc_vopen64(pathname, flags, ap);
3952 * There are methods for closing descriptors (libc-internal code
3953 * paths, direct syscalls) which close descriptors in ways that
3954 * we can't intercept, so try to recover when we notice that
3957 swrap_remove_stale(ret);
3962 int open64(const char *pathname, int flags, ...)
3967 va_start(ap, flags);
3968 fd = swrap_vopen64(pathname, flags, ap);
3973 #endif /* HAVE_OPEN64 */
3975 /****************************************************************************
3977 ***************************************************************************/
3979 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3983 ret = libc_vopenat(dirfd, path, flags, ap);
3986 * There are methods for closing descriptors (libc-internal code
3987 * paths, direct syscalls) which close descriptors in ways that
3988 * we can't intercept, so try to recover when we notice that
3991 swrap_remove_stale(ret);
3997 int openat(int dirfd, const char *path, int flags, ...)
4002 va_start(ap, flags);
4003 fd = swrap_vopenat(dirfd, path, flags, ap);
4009 /****************************************************************************
4011 ***************************************************************************/
4013 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4015 struct socket_info *si = find_socket_info(s);
4020 return libc_getpeername(s, name, addrlen);
4025 if (si->peername.sa_socklen == 0)
4031 len = MIN(*addrlen, si->peername.sa_socklen);
4037 memcpy(name, &si->peername.sa.ss, len);
4038 *addrlen = si->peername.sa_socklen;
4042 SWRAP_UNLOCK_SI(si);
4047 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4048 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
4050 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
4053 return swrap_getpeername(s, name, (socklen_t *)addrlen);
4056 /****************************************************************************
4058 ***************************************************************************/
4060 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4062 struct socket_info *si = find_socket_info(s);
4067 return libc_getsockname(s, name, addrlen);
4072 len = MIN(*addrlen, si->myname.sa_socklen);
4078 memcpy(name, &si->myname.sa.ss, len);
4079 *addrlen = si->myname.sa_socklen;
4083 SWRAP_UNLOCK_SI(si);
4088 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4089 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
4091 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
4094 return swrap_getsockname(s, name, (socklen_t *)addrlen);
4097 /****************************************************************************
4099 ***************************************************************************/
4102 # ifdef SO_PROTOTYPE /* The Solaris name */
4103 # define SO_PROTOCOL SO_PROTOTYPE
4104 # endif /* SO_PROTOTYPE */
4105 #endif /* SO_PROTOCOL */
4107 static int swrap_getsockopt(int s, int level, int optname,
4108 void *optval, socklen_t *optlen)
4110 struct socket_info *si = find_socket_info(s);
4114 return libc_getsockopt(s,
4123 if (level == SOL_SOCKET) {
4127 if (optval == NULL || optlen == NULL ||
4128 *optlen < (socklen_t)sizeof(int)) {
4134 *optlen = sizeof(int);
4135 *(int *)optval = si->family;
4138 #endif /* SO_DOMAIN */
4142 if (optval == NULL || optlen == NULL ||
4143 *optlen < (socklen_t)sizeof(int)) {
4149 *optlen = sizeof(int);
4150 *(int *)optval = si->protocol;
4153 #endif /* SO_PROTOCOL */
4155 if (optval == NULL || optlen == NULL ||
4156 *optlen < (socklen_t)sizeof(int)) {
4162 *optlen = sizeof(int);
4163 *(int *)optval = si->type;
4167 ret = libc_getsockopt(s,
4174 } else if (level == IPPROTO_TCP) {
4179 * This enables sending packets directly out over TCP.
4180 * As a unix socket is doing that any way, report it as
4183 if (optval == NULL || optlen == NULL ||
4184 *optlen < (socklen_t)sizeof(int)) {
4190 *optlen = sizeof(int);
4191 *(int *)optval = si->tcp_nodelay;
4195 #endif /* TCP_NODELAY */
4201 errno = ENOPROTOOPT;
4205 SWRAP_UNLOCK_SI(si);
4209 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4210 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4212 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4215 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4218 /****************************************************************************
4220 ***************************************************************************/
4222 static int swrap_setsockopt(int s, int level, int optname,
4223 const void *optval, socklen_t optlen)
4225 struct socket_info *si = find_socket_info(s);
4229 return libc_setsockopt(s,
4236 if (level == SOL_SOCKET) {
4237 return libc_setsockopt(s,
4246 if (level == IPPROTO_TCP) {
4253 * This enables sending packets directly out over TCP.
4254 * A unix socket is doing that any way.
4256 if (optval == NULL || optlen == 0 ||
4257 optlen < (socklen_t)sizeof(int)) {
4263 i = *discard_const_p(int, optval);
4264 if (i != 0 && i != 1) {
4269 si->tcp_nodelay = i;
4274 #endif /* TCP_NODELAY */
4280 switch (si->family) {
4282 if (level == IPPROTO_IP) {
4284 if (optname == IP_PKTINFO) {
4285 si->pktinfo = AF_INET;
4287 #endif /* IP_PKTINFO */
4293 if (level == IPPROTO_IPV6) {
4294 #ifdef IPV6_RECVPKTINFO
4295 if (optname == IPV6_RECVPKTINFO) {
4296 si->pktinfo = AF_INET6;
4298 #endif /* IPV6_PKTINFO */
4304 errno = ENOPROTOOPT;
4310 SWRAP_UNLOCK_SI(si);
4314 int setsockopt(int s, int level, int optname,
4315 const void *optval, socklen_t optlen)
4317 return swrap_setsockopt(s, level, optname, optval, optlen);
4320 /****************************************************************************
4322 ***************************************************************************/
4324 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4326 struct socket_info *si = find_socket_info(s);
4332 return libc_vioctl(s, r, va);
4339 rc = libc_vioctl(s, r, va);
4343 value = *((int *)va_arg(ap, int *));
4345 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4346 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4347 } else if (value == 0) { /* END OF FILE */
4348 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4355 SWRAP_UNLOCK_SI(si);
4359 #ifdef HAVE_IOCTL_INT
4360 int ioctl(int s, int r, ...)
4362 int ioctl(int s, unsigned long int r, ...)
4370 rc = swrap_vioctl(s, (unsigned long int) r, va);
4381 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4384 # ifdef _ALIGN /* BSD */
4385 #define CMSG_ALIGN _ALIGN
4387 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4388 # endif /* _ALIGN */
4389 #endif /* CMSG_ALIGN */
4392 * @brief Add a cmsghdr to a msghdr.
4394 * This is an function to add any type of cmsghdr. It will operate on the
4395 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4396 * the buffer position after the added cmsg element. Hence, this function is
4397 * intended to be used with an intermediate msghdr and not on the original
4398 * one handed in by the client.
4400 * @param[in] msg The msghdr to which to add the cmsg.
4402 * @param[in] level The cmsg level to set.
4404 * @param[in] type The cmsg type to set.
4406 * @param[in] data The cmsg data to set.
4408 * @param[in] len the length of the data to set.
4410 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4416 size_t cmlen = CMSG_LEN(len);
4417 size_t cmspace = CMSG_SPACE(len);
4418 uint8_t cmbuf[cmspace];
4419 void *cast_ptr = (void *)cmbuf;
4420 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4423 memset(cmbuf, 0, cmspace);
4425 if (msg->msg_controllen < cmlen) {
4426 cmlen = msg->msg_controllen;
4427 msg->msg_flags |= MSG_CTRUNC;
4430 if (msg->msg_controllen < cmspace) {
4431 cmspace = msg->msg_controllen;
4435 * We copy the full input data into an intermediate cmsghdr first
4436 * in order to more easily cope with truncation.
4438 cm->cmsg_len = cmlen;
4439 cm->cmsg_level = level;
4440 cm->cmsg_type = type;
4441 memcpy(CMSG_DATA(cm), data, len);
4444 * We now copy the possibly truncated buffer.
4445 * We copy cmlen bytes, but consume cmspace bytes,
4446 * leaving the possible padding uninitialiazed.
4448 p = (uint8_t *)msg->msg_control;
4449 memcpy(p, cm, cmlen);
4451 msg->msg_control = p;
4452 msg->msg_controllen -= cmspace;
4457 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4460 /* Add packet info */
4461 switch (si->pktinfo) {
4462 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4464 struct sockaddr_in *sin;
4465 #if defined(HAVE_STRUCT_IN_PKTINFO)
4466 struct in_pktinfo pkt;
4467 #elif defined(IP_RECVDSTADDR)
4471 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4472 sin = &si->bindname.sa.in;
4474 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4477 sin = &si->myname.sa.in;
4482 #if defined(HAVE_STRUCT_IN_PKTINFO)
4483 pkt.ipi_ifindex = socket_wrapper_default_iface();
4484 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4485 #elif defined(IP_RECVDSTADDR)
4486 pkt = sin->sin_addr;
4489 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4494 #endif /* IP_PKTINFO */
4495 #if defined(HAVE_IPV6)
4497 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4498 struct sockaddr_in6 *sin6;
4499 struct in6_pktinfo pkt6;
4501 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4502 sin6 = &si->bindname.sa.in6;
4504 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4507 sin6 = &si->myname.sa.in6;
4512 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4513 pkt6.ipi6_addr = sin6->sin6_addr;
4515 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4516 &pkt6, sizeof(pkt6));
4517 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4521 #endif /* IPV6_PKTINFO */
4529 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4530 struct msghdr *omsg)
4534 if (si->pktinfo > 0) {
4535 rc = swrap_msghdr_add_pktinfo(si, omsg);
4541 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4543 size_t *cm_data_space);
4544 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4546 size_t *cm_data_space);
4548 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4550 size_t *cm_data_space) {
4551 struct cmsghdr *cmsg;
4555 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4559 for (cmsg = CMSG_FIRSTHDR(msg);
4561 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4562 switch (cmsg->cmsg_level) {
4564 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4569 rc = swrap_sendmsg_copy_cmsg(cmsg,
4579 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4581 size_t *cm_data_space)
4586 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4588 p = realloc((*cm_data), cmspace);
4594 p = (*cm_data) + (*cm_data_space);
4595 *cm_data_space = cmspace;
4597 memcpy(p, cmsg, cmsg->cmsg_len);
4602 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4604 size_t *cm_data_space);
4607 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4609 size_t *cm_data_space)
4613 switch(cmsg->cmsg_type) {
4616 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4623 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4635 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4637 size_t *cm_data_space)
4639 (void)cmsg; /* unused */
4640 (void)cm_data; /* unused */
4641 (void)cm_data_space; /* unused */
4644 * Passing a IP pktinfo to a unix socket might be rejected by the
4645 * Kernel, at least on FreeBSD. So skip this cmsg.
4649 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4651 static ssize_t swrap_sendmsg_before(int fd,
4652 struct socket_info *si,
4654 struct iovec *tmp_iov,
4655 struct sockaddr_un *tmp_un,
4656 const struct sockaddr_un **to_un,
4657 const struct sockaddr **to,
4679 if (!si->connected) {
4684 if (msg->msg_iovlen == 0) {
4688 mtu = socket_wrapper_mtu();
4689 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4691 nlen = len + msg->msg_iov[i].iov_len;
4696 msg->msg_iovlen = i;
4697 if (msg->msg_iovlen == 0) {
4698 *tmp_iov = msg->msg_iov[0];
4699 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4701 msg->msg_iov = tmp_iov;
4702 msg->msg_iovlen = 1;
4707 if (si->connected) {
4708 if (msg->msg_name != NULL) {
4710 * We are dealing with unix sockets and if we
4711 * are connected, we should only talk to the
4712 * connected unix path. Using the fd to send
4713 * to another server would be hard to achieve.
4715 msg->msg_name = NULL;
4716 msg->msg_namelen = 0;
4719 const struct sockaddr *msg_name;
4720 msg_name = (const struct sockaddr *)msg->msg_name;
4722 if (msg_name == NULL) {
4728 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4740 msg->msg_name = tmp_un;
4741 msg->msg_namelen = sizeof(*tmp_un);
4744 if (si->bound == 0) {
4745 ret = swrap_auto_bind(fd, si, si->family);
4747 SWRAP_UNLOCK_SI(si);
4748 if (errno == ENOTSOCK) {
4749 swrap_remove_stale(fd);
4752 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4758 if (!si->defer_connect) {
4762 ret = sockaddr_convert_to_un(si,
4764 si->peername.sa_socklen,
4772 ret = libc_connect(fd,
4773 (struct sockaddr *)(void *)tmp_un,
4776 /* to give better errors */
4777 if (ret == -1 && errno == ENOENT) {
4778 errno = EHOSTUNREACH;
4785 si->defer_connect = 0;
4788 errno = EHOSTUNREACH;
4792 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4793 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4794 uint8_t *cmbuf = NULL;
4797 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4804 msg->msg_controllen = 0;
4805 msg->msg_control = NULL;
4806 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4807 memcpy(msg->msg_control, cmbuf, cmlen);
4808 msg->msg_controllen = cmlen;
4816 SWRAP_UNLOCK_SI(si);
4821 static void swrap_sendmsg_after(int fd,
4822 struct socket_info *si,
4824 const struct sockaddr *to,
4827 int saved_errno = errno;
4834 /* to give better errors */
4836 if (saved_errno == ENOENT) {
4837 saved_errno = EHOSTUNREACH;
4838 } else if (saved_errno == ENOTSOCK) {
4839 /* If the fd is not a socket, remove it */
4840 swrap_remove_stale(fd);
4844 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4845 avail += msg->msg_iov[i].iov_len;
4849 remain = MIN(80, avail);
4854 /* we capture it as one single packet */
4855 buf = (uint8_t *)malloc(remain);
4857 /* we just not capture the packet */
4858 errno = saved_errno;
4862 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4863 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4865 msg->msg_iov[i].iov_base,
4868 remain -= this_time;
4877 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4878 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4880 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4885 if (si->connected) {
4886 to = &si->peername.sa.s;
4889 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4890 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4892 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4897 SWRAP_UNLOCK_SI(si);
4900 errno = saved_errno;
4903 static int swrap_recvmsg_before(int fd,
4904 struct socket_info *si,
4906 struct iovec *tmp_iov)
4913 (void)fd; /* unused */
4918 if (!si->connected) {
4923 if (msg->msg_iovlen == 0) {
4927 mtu = socket_wrapper_mtu();
4928 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4930 nlen = len + msg->msg_iov[i].iov_len;
4935 msg->msg_iovlen = i;
4936 if (msg->msg_iovlen == 0) {
4937 *tmp_iov = msg->msg_iov[0];
4938 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4940 msg->msg_iov = tmp_iov;
4941 msg->msg_iovlen = 1;
4946 if (msg->msg_name == NULL) {
4951 if (msg->msg_iovlen == 0) {
4955 if (si->bound == 0) {
4956 ret = swrap_auto_bind(fd, si, si->family);
4958 SWRAP_UNLOCK_SI(si);
4960 * When attempting to read or write to a
4961 * descriptor, if an underlying autobind fails
4962 * because it's not a socket, stop intercepting
4963 * uses of that descriptor.
4965 if (errno == ENOTSOCK) {
4966 swrap_remove_stale(fd);
4969 SWRAP_LOG(SWRAP_LOG_ERROR,
4970 "swrap_recvmsg_before failed");
4977 errno = EHOSTUNREACH;
4983 SWRAP_UNLOCK_SI(si);
4988 static int swrap_recvmsg_after(int fd,
4989 struct socket_info *si,
4991 const struct sockaddr_un *un_addr,
4992 socklen_t un_addrlen,
4995 int saved_errno = errno;
4997 uint8_t *buf = NULL;
5003 /* to give better errors */
5005 if (saved_errno == ENOENT) {
5006 saved_errno = EHOSTUNREACH;
5007 } else if (saved_errno == ENOTSOCK) {
5008 /* If the fd is not a socket, remove it */
5009 swrap_remove_stale(fd);
5013 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5014 avail += msg->msg_iov[i].iov_len;
5019 /* Convert the socket address before we leave */
5020 if (si->type == SOCK_DGRAM && un_addr != NULL) {
5021 rc = sockaddr_convert_from_un(si,
5038 remain = MIN(80, avail);
5043 /* we capture it as one single packet */
5044 buf = (uint8_t *)malloc(remain);
5046 /* we just not capture the packet */
5047 SWRAP_UNLOCK_SI(si);
5048 errno = saved_errno;
5052 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
5053 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
5055 msg->msg_iov[i].iov_base,
5058 remain -= this_time;
5063 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
5064 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5065 } else if (ret == 0) { /* END OF FILE */
5066 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
5067 } else if (ret > 0) {
5068 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
5077 if (un_addr != NULL) {
5078 swrap_pcap_dump_packet(si,
5084 swrap_pcap_dump_packet(si,
5097 errno = saved_errno;
5099 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5101 msg->msg_controllen > 0 &&
5102 msg->msg_control != NULL) {
5103 rc = swrap_msghdr_add_socket_info(si, msg);
5105 SWRAP_UNLOCK_SI(si);
5111 SWRAP_UNLOCK_SI(si);
5115 /****************************************************************************
5117 ***************************************************************************/
5119 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
5120 struct sockaddr *from, socklen_t *fromlen)
5122 struct swrap_address from_addr = {
5123 .sa_socklen = sizeof(struct sockaddr_un),
5126 struct socket_info *si = find_socket_info(s);
5127 struct swrap_address saddr = {
5128 .sa_socklen = sizeof(struct sockaddr_storage),
5135 return libc_recvfrom(s,
5147 if (from != NULL && fromlen != NULL) {
5148 msg.msg_name = from; /* optional address */
5149 msg.msg_namelen = *fromlen; /* size of address */
5151 msg.msg_name = &saddr.sa.s; /* optional address */
5152 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5154 msg.msg_iov = &tmp; /* scatter/gather array */
5155 msg.msg_iovlen = 1; /* # elements in msg_iov */
5156 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5157 msg.msg_control = NULL; /* ancillary data, see below */
5158 msg.msg_controllen = 0; /* ancillary data buffer len */
5159 msg.msg_flags = 0; /* flags on received message */
5162 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5167 buf = msg.msg_iov[0].iov_base;
5168 len = msg.msg_iov[0].iov_len;
5170 ret = libc_recvfrom(s,
5175 &from_addr.sa_socklen);
5180 tret = swrap_recvmsg_after(s,
5184 from_addr.sa_socklen,
5190 if (from != NULL && fromlen != NULL) {
5191 *fromlen = msg.msg_namelen;
5197 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5198 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5199 struct sockaddr *from, Psocklen_t fromlen)
5201 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5202 struct sockaddr *from, socklen_t *fromlen)
5205 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5208 /****************************************************************************
5210 ***************************************************************************/
5212 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5213 const struct sockaddr *to, socklen_t tolen)
5217 struct swrap_address un_addr = {
5218 .sa_socklen = sizeof(struct sockaddr_un),
5220 const struct sockaddr_un *to_un = NULL;
5223 struct socket_info *si = find_socket_info(s);
5227 return libc_sendto(s, buf, len, flags, to, tolen);
5230 tmp.iov_base = discard_const_p(char, buf);
5234 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5235 msg.msg_namelen = tolen; /* size of address */
5236 msg.msg_iov = &tmp; /* scatter/gather array */
5237 msg.msg_iovlen = 1; /* # elements in msg_iov */
5238 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5239 msg.msg_control = NULL; /* ancillary data, see below */
5240 msg.msg_controllen = 0; /* ancillary data buffer len */
5241 msg.msg_flags = 0; /* flags on received message */
5244 rc = swrap_sendmsg_before(s,
5256 buf = msg.msg_iov[0].iov_base;
5257 len = msg.msg_iov[0].iov_len;
5262 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5265 type = SOCKET_TYPE_CHAR_UDP;
5267 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5268 snprintf(un_addr.sa.un.sun_path,
5269 sizeof(un_addr.sa.un.sun_path),
5271 socket_wrapper_dir(), type, iface, prt);
5272 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5274 /* ignore the any errors in broadcast sends */
5280 un_addr.sa_socklen);
5285 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5287 SWRAP_UNLOCK_SI(si);
5294 * If it is a dgram socket and we are connected, don't include the
5297 if (si->type == SOCK_DGRAM && si->connected) {
5298 ret = libc_sendto(s,
5305 ret = libc_sendto(s,
5309 (struct sockaddr *)msg.msg_name,
5313 SWRAP_UNLOCK_SI(si);
5315 swrap_sendmsg_after(s, si, &msg, to, ret);
5320 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5321 const struct sockaddr *to, socklen_t tolen)
5323 return swrap_sendto(s, buf, len, flags, to, tolen);
5326 /****************************************************************************
5328 ***************************************************************************/
5330 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5332 struct socket_info *si;
5334 struct swrap_address saddr = {
5335 .sa_socklen = sizeof(struct sockaddr_storage),
5341 si = find_socket_info(s);
5343 return libc_recv(s, buf, len, flags);
5350 msg.msg_name = &saddr.sa.s; /* optional address */
5351 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5352 msg.msg_iov = &tmp; /* scatter/gather array */
5353 msg.msg_iovlen = 1; /* # elements in msg_iov */
5354 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5355 msg.msg_control = NULL; /* ancillary data, see below */
5356 msg.msg_controllen = 0; /* ancillary data buffer len */
5357 msg.msg_flags = 0; /* flags on received message */
5360 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5365 buf = msg.msg_iov[0].iov_base;
5366 len = msg.msg_iov[0].iov_len;
5368 ret = libc_recv(s, buf, len, flags);
5370 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5378 ssize_t recv(int s, void *buf, size_t len, int flags)
5380 return swrap_recv(s, buf, len, flags);
5383 /****************************************************************************
5385 ***************************************************************************/
5387 static ssize_t swrap_read(int s, void *buf, size_t len)
5389 struct socket_info *si;
5392 struct swrap_address saddr = {
5393 .sa_socklen = sizeof(struct sockaddr_storage),
5398 si = find_socket_info(s);
5400 return libc_read(s, buf, len);
5407 msg.msg_name = &saddr.sa.ss; /* optional address */
5408 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5409 msg.msg_iov = &tmp; /* scatter/gather array */
5410 msg.msg_iovlen = 1; /* # elements in msg_iov */
5411 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5412 msg.msg_control = NULL; /* ancillary data, see below */
5413 msg.msg_controllen = 0; /* ancillary data buffer len */
5414 msg.msg_flags = 0; /* flags on received message */
5417 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5419 if (tret == -ENOTSOCK) {
5420 return libc_read(s, buf, len);
5425 buf = msg.msg_iov[0].iov_base;
5426 len = msg.msg_iov[0].iov_len;
5428 ret = libc_read(s, buf, len);
5430 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5438 ssize_t read(int s, void *buf, size_t len)
5440 return swrap_read(s, buf, len);
5443 /****************************************************************************
5445 ***************************************************************************/
5447 static ssize_t swrap_write(int s, const void *buf, size_t len)
5451 struct sockaddr_un un_addr;
5454 struct socket_info *si;
5456 si = find_socket_info(s);
5458 return libc_write(s, buf, len);
5461 tmp.iov_base = discard_const_p(char, buf);
5465 msg.msg_name = NULL; /* optional address */
5466 msg.msg_namelen = 0; /* size of address */
5467 msg.msg_iov = &tmp; /* scatter/gather array */
5468 msg.msg_iovlen = 1; /* # elements in msg_iov */
5469 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5470 msg.msg_control = NULL; /* ancillary data, see below */
5471 msg.msg_controllen = 0; /* ancillary data buffer len */
5472 msg.msg_flags = 0; /* flags on received message */
5475 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5480 buf = msg.msg_iov[0].iov_base;
5481 len = msg.msg_iov[0].iov_len;
5483 ret = libc_write(s, buf, len);
5485 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5490 ssize_t write(int s, const void *buf, size_t len)
5492 return swrap_write(s, buf, len);
5495 /****************************************************************************
5497 ***************************************************************************/
5499 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5503 struct sockaddr_un un_addr;
5506 struct socket_info *si = find_socket_info(s);
5509 return libc_send(s, buf, len, flags);
5512 tmp.iov_base = discard_const_p(char, buf);
5516 msg.msg_name = NULL; /* optional address */
5517 msg.msg_namelen = 0; /* size of address */
5518 msg.msg_iov = &tmp; /* scatter/gather array */
5519 msg.msg_iovlen = 1; /* # elements in msg_iov */
5520 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5521 msg.msg_control = NULL; /* ancillary data, see below */
5522 msg.msg_controllen = 0; /* ancillary data buffer len */
5523 msg.msg_flags = 0; /* flags on received message */
5526 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5531 buf = msg.msg_iov[0].iov_base;
5532 len = msg.msg_iov[0].iov_len;
5534 ret = libc_send(s, buf, len, flags);
5536 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5541 ssize_t send(int s, const void *buf, size_t len, int flags)
5543 return swrap_send(s, buf, len, flags);
5546 /****************************************************************************
5548 ***************************************************************************/
5550 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5552 struct swrap_address from_addr = {
5553 .sa_socklen = sizeof(struct sockaddr_un),
5555 struct swrap_address convert_addr = {
5556 .sa_socklen = sizeof(struct sockaddr_storage),
5558 struct socket_info *si;
5561 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5562 size_t msg_ctrllen_filled;
5563 size_t msg_ctrllen_left;
5569 si = find_socket_info(s);
5571 return libc_recvmsg(s, omsg, flags);
5574 tmp.iov_base = NULL;
5578 msg.msg_name = &from_addr.sa; /* optional address */
5579 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5580 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5581 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5582 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5583 msg_ctrllen_filled = 0;
5584 msg_ctrllen_left = omsg->msg_controllen;
5586 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5587 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5588 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5591 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5596 ret = libc_recvmsg(s, &msg, flags);
5598 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5599 msg_ctrllen_filled += msg.msg_controllen;
5600 msg_ctrllen_left -= msg.msg_controllen;
5602 if (omsg->msg_control != NULL) {
5605 p = omsg->msg_control;
5606 p += msg_ctrllen_filled;
5608 msg.msg_control = p;
5609 msg.msg_controllen = msg_ctrllen_left;
5611 msg.msg_control = NULL;
5612 msg.msg_controllen = 0;
5617 * We convert the unix address to a IP address so we need a buffer
5618 * which can store the address in case of SOCK_DGRAM, see below.
5620 msg.msg_name = &convert_addr.sa;
5621 msg.msg_namelen = convert_addr.sa_socklen;
5623 rc = swrap_recvmsg_after(s,
5627 from_addr.sa_socklen,
5633 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5634 if (omsg->msg_control != NULL) {
5635 /* msg.msg_controllen = space left */
5636 msg_ctrllen_left = msg.msg_controllen;
5637 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5640 /* Update the original message length */
5641 omsg->msg_controllen = msg_ctrllen_filled;
5642 omsg->msg_flags = msg.msg_flags;
5644 omsg->msg_iovlen = msg.msg_iovlen;
5651 * The msg_name field points to a caller-allocated buffer that is
5652 * used to return the source address if the socket is unconnected. The
5653 * caller should set msg_namelen to the size of this buffer before this
5654 * call; upon return from a successful call, msg_name will contain the
5655 * length of the returned address. If the application does not need
5656 * to know the source address, msg_name can be specified as NULL.
5658 if (si->type == SOCK_STREAM) {
5659 omsg->msg_namelen = 0;
5660 } else if (omsg->msg_name != NULL &&
5661 omsg->msg_namelen != 0 &&
5662 omsg->msg_namelen >= msg.msg_namelen) {
5663 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5664 omsg->msg_namelen = msg.msg_namelen;
5667 SWRAP_UNLOCK_SI(si);
5672 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5674 return swrap_recvmsg(sockfd, msg, flags);
5677 /****************************************************************************
5679 ***************************************************************************/
5681 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5685 struct sockaddr_un un_addr;
5686 const struct sockaddr_un *to_un = NULL;
5687 const struct sockaddr *to = NULL;
5690 struct socket_info *si = find_socket_info(s);
5694 return libc_sendmsg(s, omsg, flags);
5697 ZERO_STRUCT(un_addr);
5699 tmp.iov_base = NULL;
5706 if (si->connected == 0) {
5707 msg.msg_name = omsg->msg_name; /* optional address */
5708 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5710 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5711 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5713 SWRAP_UNLOCK_SI(si);
5715 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5716 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5717 /* omsg is a const so use a local buffer for modifications */
5718 uint8_t cmbuf[omsg->msg_controllen];
5720 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5722 msg.msg_control = cmbuf; /* ancillary data, see below */
5723 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5725 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5728 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5736 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5744 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5745 avail += msg.msg_iov[i].iov_len;
5751 /* we capture it as one single packet */
5752 buf = (uint8_t *)malloc(remain);
5757 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5758 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5760 msg.msg_iov[i].iov_base,
5763 remain -= this_time;
5766 type = SOCKET_TYPE_CHAR_UDP;
5768 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5769 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5770 socket_wrapper_dir(), type, iface, prt);
5771 if (stat(un_addr.sun_path, &st) != 0) continue;
5773 msg.msg_name = &un_addr; /* optional address */
5774 msg.msg_namelen = sizeof(un_addr); /* size of address */
5776 /* ignore the any errors in broadcast sends */
5777 libc_sendmsg(s, &msg, flags);
5782 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5785 SWRAP_UNLOCK_SI(si);
5790 ret = libc_sendmsg(s, &msg, flags);
5792 swrap_sendmsg_after(s, si, &msg, to, ret);
5797 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5799 return swrap_sendmsg(s, omsg, flags);
5802 /****************************************************************************
5804 ***************************************************************************/
5806 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5808 struct socket_info *si;
5811 struct swrap_address saddr = {
5812 .sa_socklen = sizeof(struct sockaddr_storage)
5817 si = find_socket_info(s);
5819 return libc_readv(s, vector, count);
5822 tmp.iov_base = NULL;
5826 msg.msg_name = &saddr.sa.s; /* optional address */
5827 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5828 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5829 msg.msg_iovlen = count; /* # elements in msg_iov */
5830 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5831 msg.msg_control = NULL; /* ancillary data, see below */
5832 msg.msg_controllen = 0; /* ancillary data buffer len */
5833 msg.msg_flags = 0; /* flags on received message */
5836 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5838 if (rc == -ENOTSOCK) {
5839 return libc_readv(s, vector, count);
5844 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5846 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5854 ssize_t readv(int s, const struct iovec *vector, int count)
5856 return swrap_readv(s, vector, count);
5859 /****************************************************************************
5861 ***************************************************************************/
5863 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5867 struct sockaddr_un un_addr;
5870 struct socket_info *si = find_socket_info(s);
5873 return libc_writev(s, vector, count);
5876 tmp.iov_base = NULL;
5880 msg.msg_name = NULL; /* optional address */
5881 msg.msg_namelen = 0; /* size of address */
5882 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5883 msg.msg_iovlen = count; /* # elements in msg_iov */
5884 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5885 msg.msg_control = NULL; /* ancillary data, see below */
5886 msg.msg_controllen = 0; /* ancillary data buffer len */
5887 msg.msg_flags = 0; /* flags on received message */
5890 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5892 if (rc == -ENOTSOCK) {
5893 return libc_readv(s, vector, count);
5898 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5900 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5905 ssize_t writev(int s, const struct iovec *vector, int count)
5907 return swrap_writev(s, vector, count);
5910 /****************************
5912 ***************************/
5914 static int swrap_close(int fd)
5916 struct socket_info *si = NULL;
5920 swrap_mutex_lock(&socket_reset_mutex);
5922 si_index = find_socket_info_index(fd);
5923 if (si_index == -1) {
5924 swrap_mutex_unlock(&socket_reset_mutex);
5925 return libc_close(fd);
5928 reset_socket_info_index(fd);
5930 swrap_mutex_unlock(&socket_reset_mutex);
5932 si = swrap_get_socket_info(si_index);
5934 swrap_mutex_lock(&first_free_mutex);
5937 ret = libc_close(fd);
5939 swrap_dec_refcount(si);
5941 if (swrap_get_refcount(si) > 0) {
5942 /* there are still references left */
5946 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5947 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5950 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5951 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5952 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5955 if (si->un_addr.sun_path[0] != '\0') {
5956 unlink(si->un_addr.sun_path);
5959 swrap_set_next_free(si, first_free);
5960 first_free = si_index;
5963 SWRAP_UNLOCK_SI(si);
5964 swrap_mutex_unlock(&first_free_mutex);
5971 return swrap_close(fd);
5974 /****************************
5976 ***************************/
5978 static int swrap_dup(int fd)
5980 struct socket_info *si;
5983 idx = find_socket_info_index(fd);
5985 return libc_dup(fd);
5988 si = swrap_get_socket_info(idx);
5990 dup_fd = libc_dup(fd);
5992 int saved_errno = errno;
5993 errno = saved_errno;
5999 swrap_inc_refcount(si);
6001 SWRAP_UNLOCK_SI(si);
6003 /* Make sure we don't have an entry for the fd */
6004 swrap_remove_stale(dup_fd);
6006 set_socket_info_index(dup_fd, idx);
6013 return swrap_dup(fd);
6016 /****************************
6018 ***************************/
6020 static int swrap_dup2(int fd, int newfd)
6022 struct socket_info *si;
6025 idx = find_socket_info_index(fd);
6027 return libc_dup2(fd, newfd);
6030 si = swrap_get_socket_info(idx);
6034 * According to the manpage:
6036 * "If oldfd is a valid file descriptor, and newfd has the same
6037 * value as oldfd, then dup2() does nothing, and returns newfd."
6042 if (find_socket_info(newfd)) {
6043 /* dup2() does an implicit close of newfd, which we
6044 * need to emulate */
6048 dup_fd = libc_dup2(fd, newfd);
6050 int saved_errno = errno;
6051 errno = saved_errno;
6057 swrap_inc_refcount(si);
6059 SWRAP_UNLOCK_SI(si);
6061 /* Make sure we don't have an entry for the fd */
6062 swrap_remove_stale(dup_fd);
6064 set_socket_info_index(dup_fd, idx);
6069 int dup2(int fd, int newfd)
6071 return swrap_dup2(fd, newfd);
6074 /****************************
6076 ***************************/
6078 static int swrap_vfcntl(int fd, int cmd, va_list va)
6080 struct socket_info *si;
6081 int rc, dup_fd, idx;
6083 idx = find_socket_info_index(fd);
6085 return libc_vfcntl(fd, cmd, va);
6088 si = swrap_get_socket_info(idx);
6092 dup_fd = libc_vfcntl(fd, cmd, va);
6094 int saved_errno = errno;
6095 errno = saved_errno;
6101 swrap_inc_refcount(si);
6103 SWRAP_UNLOCK_SI(si);
6105 /* Make sure we don't have an entry for the fd */
6106 swrap_remove_stale(dup_fd);
6108 set_socket_info_index(dup_fd, idx);
6113 rc = libc_vfcntl(fd, cmd, va);
6120 int fcntl(int fd, int cmd, ...)
6127 rc = swrap_vfcntl(fd, cmd, va);
6134 /****************************
6136 ***************************/
6139 static int swrap_eventfd(int count, int flags)
6143 fd = libc_eventfd(count, flags);
6145 swrap_remove_stale(fd);
6151 #ifdef HAVE_EVENTFD_UNSIGNED_INT
6152 int eventfd(unsigned int count, int flags)
6154 int eventfd(int count, int flags)
6157 return swrap_eventfd(count, flags);
6162 int pledge(const char *promises, const char *paths[])
6164 (void)promises; /* unused */
6165 (void)paths; /* unused */
6169 #endif /* HAVE_PLEDGE */
6171 static void swrap_thread_prepare(void)
6174 * This function should only be called here!!
6176 * We bind all symobls to avoid deadlocks of the fork is
6177 * interrupted by a signal handler using a symbol of this
6180 swrap_bind_symbol_all();
6185 static void swrap_thread_parent(void)
6190 static void swrap_thread_child(void)
6195 /****************************
6197 ***************************/
6198 void swrap_constructor(void)
6203 * If we hold a lock and the application forks, then the child
6204 * is not able to unlock the mutex and we are in a deadlock.
6205 * This should prevent such deadlocks.
6207 pthread_atfork(&swrap_thread_prepare,
6208 &swrap_thread_parent,
6209 &swrap_thread_child);
6211 ret = socket_wrapper_init_mutex(&sockets_mutex);
6213 SWRAP_LOG(SWRAP_LOG_ERROR,
6214 "Failed to initialize pthread mutex");
6218 ret = socket_wrapper_init_mutex(&socket_reset_mutex);
6220 SWRAP_LOG(SWRAP_LOG_ERROR,
6221 "Failed to initialize pthread mutex");
6225 ret = socket_wrapper_init_mutex(&first_free_mutex);
6227 SWRAP_LOG(SWRAP_LOG_ERROR,
6228 "Failed to initialize pthread mutex");
6233 /****************************
6235 ***************************/
6238 * This function is called when the library is unloaded and makes sure that
6239 * sockets get closed and the unix file for the socket are unlinked.
6241 void swrap_destructor(void)
6245 if (socket_fds_idx != NULL) {
6246 for (i = 0; i < SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT; ++i) {
6247 if (socket_fds_idx[i] != -1) {
6251 SAFE_FREE(socket_fds_idx);
6256 if (swrap.libc.handle != NULL) {
6257 dlclose(swrap.libc.handle);
6259 if (swrap.libc.socket_handle) {
6260 dlclose(swrap.libc.socket_handle);