2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
45 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
91 /* GCC have printf type attribute check. */
92 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
93 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
95 #define PRINTF_ATTRIBUTE(a,b)
96 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
98 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
99 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
101 #define CONSTRUCTOR_ATTRIBUTE
102 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
104 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
105 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
107 #define DESTRUCTOR_ATTRIBUTE
111 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
112 # define FALL_THROUGH __attribute__ ((fallthrough))
113 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
114 # define FALL_THROUGH
115 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
116 #endif /* FALL_THROUGH */
118 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
119 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
121 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
124 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
125 # define SWRAP_THREAD __thread
127 # define SWRAP_THREAD
131 #define MIN(a,b) ((a)<(b)?(a):(b))
135 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
139 #define ZERO_STRUCTP(x) do { \
141 memset((char *)(x), 0, sizeof(*(x))); \
145 #ifndef discard_const
146 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
149 #ifndef discard_const_p
150 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
153 #define UNUSED(x) (void)(x)
156 # ifndef IPV6_RECVPKTINFO
157 # define IPV6_RECVPKTINFO IPV6_PKTINFO
158 # endif /* IPV6_RECVPKTINFO */
159 #endif /* IPV6_PKTINFO */
162 * On BSD IP_PKTINFO has a different name because during
163 * the time when they implemented it, there was no RFC.
164 * The name for IPv6 is the same as on Linux.
167 # ifdef IP_RECVDSTADDR
168 # define IP_PKTINFO IP_RECVDSTADDR
172 /* Macros for accessing mutexes */
173 # define SWRAP_LOCK(m) do { \
174 pthread_mutex_lock(&(m ## _mutex)); \
177 # define SWRAP_UNLOCK(m) do { \
178 pthread_mutex_unlock(&(m ## _mutex)); \
181 /* Add new global locks here please */
182 # define SWRAP_LOCK_ALL \
183 SWRAP_LOCK(libc_symbol_binding); \
185 # define SWRAP_UNLOCK_ALL \
186 SWRAP_UNLOCK(libc_symbol_binding); \
189 #define SWRAP_DLIST_ADD(list,item) do { \
191 (item)->prev = NULL; \
192 (item)->next = NULL; \
195 (item)->prev = NULL; \
196 (item)->next = (list); \
197 (list)->prev = (item); \
202 #define SWRAP_DLIST_REMOVE(list,item) do { \
203 if ((list) == (item)) { \
204 (list) = (item)->next; \
206 (list)->prev = NULL; \
209 if ((item)->prev) { \
210 (item)->prev->next = (item)->next; \
212 if ((item)->next) { \
213 (item)->next->prev = (item)->prev; \
216 (item)->prev = NULL; \
217 (item)->next = NULL; \
220 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
222 if ((list) == NULL || (el) == NULL) { \
223 SWRAP_DLIST_ADD(list, item); \
225 (item)->prev = (el); \
226 (item)->next = (el)->next; \
227 (el)->next = (item); \
228 if ((item)->next != NULL) { \
229 (item)->next->prev = (item); \
234 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
235 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
237 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
240 /* we need to use a very terse format here as IRIX 6.4 silently
241 truncates names to 16 chars, so if we use a longer name then we
242 can't tell which port a packet came from with recvfrom()
244 with this format we have 8 chars left for the directory name
246 #define SOCKET_FORMAT "%c%02X%04X"
247 #define SOCKET_TYPE_CHAR_TCP 'T'
248 #define SOCKET_TYPE_CHAR_UDP 'U'
249 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
250 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
253 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
254 * format PCAP capture files (as the caller will simply continue from here).
256 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
257 #define SOCKET_WRAPPER_MTU_MIN 512
258 #define SOCKET_WRAPPER_MTU_MAX 32768
260 #define SOCKET_MAX_SOCKETS 1024
264 * Maximum number of socket_info structures that can
265 * be used. Can be overriden by the environment variable
266 * SOCKET_WRAPPER_MAX_SOCKETS.
268 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
270 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 256000
272 /* This limit is to avoid broadcast sendto() needing to stat too many
273 * files. It may be raised (with a performance cost) to up to 254
274 * without changing the format above */
275 #define MAX_WRAPPED_INTERFACES 64
277 struct swrap_address
{
278 socklen_t sa_socklen
;
281 struct sockaddr_in in
;
283 struct sockaddr_in6 in6
;
285 struct sockaddr_un un
;
286 struct sockaddr_storage ss
;
290 struct socket_info_fd
{
291 struct socket_info_fd
*prev
, *next
;
295 * Points to corresponding index in array of
296 * socket_info structures
305 unsigned int refcount
;
320 /* The unix path so we can unlink it on close() */
321 struct sockaddr_un un_addr
;
323 struct swrap_address bindname
;
324 struct swrap_address myname
;
325 struct swrap_address peername
;
328 unsigned long pck_snd
;
329 unsigned long pck_rcv
;
333 static struct socket_info
*sockets
;
334 static size_t max_sockets
= 0;
337 * While socket file descriptors are passed among different processes, the
338 * numerical value gets changed. So its better to store it locally to each
339 * process rather than including it within socket_info which will be shared.
341 static struct socket_info_fd
*socket_fds
;
343 /* The mutex for accessing the global libc.symbols */
344 static pthread_mutex_t libc_symbol_binding_mutex
= PTHREAD_MUTEX_INITIALIZER
;
346 /* Function prototypes */
348 bool socket_wrapper_enabled(void);
350 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE
;
351 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
353 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *func
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
354 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
356 static void swrap_log(enum swrap_dbglvl_e dbglvl
,
358 const char *format
, ...)
363 unsigned int lvl
= 0;
364 const char *prefix
= "SWRAP";
366 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
375 va_start(va
, format
);
376 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
380 case SWRAP_LOG_ERROR
:
381 prefix
= "SWRAP_ERROR";
384 prefix
= "SWRAP_WARN";
386 case SWRAP_LOG_DEBUG
:
387 prefix
= "SWRAP_DEBUG";
389 case SWRAP_LOG_TRACE
:
390 prefix
= "SWRAP_TRACE";
396 prefix
, (int)getpid(), func
, buffer
);
399 /*********************************************************
400 * SWRAP LOADING LIBC FUNCTIONS
401 *********************************************************/
406 typedef int (*__libc_accept4
)(int sockfd
,
407 struct sockaddr
*addr
,
411 typedef int (*__libc_accept
)(int sockfd
,
412 struct sockaddr
*addr
,
415 typedef int (*__libc_bind
)(int sockfd
,
416 const struct sockaddr
*addr
,
418 typedef int (*__libc_close
)(int fd
);
419 typedef int (*__libc_connect
)(int sockfd
,
420 const struct sockaddr
*addr
,
422 typedef int (*__libc_dup
)(int fd
);
423 typedef int (*__libc_dup2
)(int oldfd
, int newfd
);
424 typedef int (*__libc_fcntl
)(int fd
, int cmd
, ...);
425 typedef FILE *(*__libc_fopen
)(const char *name
, const char *mode
);
427 typedef FILE *(*__libc_fopen64
)(const char *name
, const char *mode
);
430 typedef int (*__libc_eventfd
)(int count
, int flags
);
432 typedef int (*__libc_getpeername
)(int sockfd
,
433 struct sockaddr
*addr
,
435 typedef int (*__libc_getsockname
)(int sockfd
,
436 struct sockaddr
*addr
,
438 typedef int (*__libc_getsockopt
)(int sockfd
,
443 typedef int (*__libc_ioctl
)(int d
, unsigned long int request
, ...);
444 typedef int (*__libc_listen
)(int sockfd
, int backlog
);
445 typedef int (*__libc_open
)(const char *pathname
, int flags
, ...);
447 typedef int (*__libc_open64
)(const char *pathname
, int flags
, ...);
448 #endif /* HAVE_OPEN64 */
449 typedef int (*__libc_openat
)(int dirfd
, const char *path
, int flags
, ...);
450 typedef int (*__libc_pipe
)(int pipefd
[2]);
451 typedef int (*__libc_read
)(int fd
, void *buf
, size_t count
);
452 typedef ssize_t (*__libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
453 typedef int (*__libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
454 typedef int (*__libc_recvfrom
)(int sockfd
,
458 struct sockaddr
*src_addr
,
460 typedef int (*__libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
461 typedef int (*__libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
462 typedef int (*__libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
463 typedef int (*__libc_sendto
)(int sockfd
,
467 const struct sockaddr
*dst_addr
,
469 typedef int (*__libc_setsockopt
)(int sockfd
,
475 typedef int (*__libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
477 typedef int (*__libc_socket
)(int domain
, int type
, int protocol
);
478 typedef int (*__libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
479 #ifdef HAVE_TIMERFD_CREATE
480 typedef int (*__libc_timerfd_create
)(int clockid
, int flags
);
482 typedef ssize_t (*__libc_write
)(int fd
, const void *buf
, size_t count
);
483 typedef ssize_t (*__libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
485 #define SWRAP_SYMBOL_ENTRY(i) \
491 struct swrap_libc_symbols
{
493 SWRAP_SYMBOL_ENTRY(accept4
);
495 SWRAP_SYMBOL_ENTRY(accept
);
497 SWRAP_SYMBOL_ENTRY(bind
);
498 SWRAP_SYMBOL_ENTRY(close
);
499 SWRAP_SYMBOL_ENTRY(connect
);
500 SWRAP_SYMBOL_ENTRY(dup
);
501 SWRAP_SYMBOL_ENTRY(dup2
);
502 SWRAP_SYMBOL_ENTRY(fcntl
);
503 SWRAP_SYMBOL_ENTRY(fopen
);
505 SWRAP_SYMBOL_ENTRY(fopen64
);
508 SWRAP_SYMBOL_ENTRY(eventfd
);
510 SWRAP_SYMBOL_ENTRY(getpeername
);
511 SWRAP_SYMBOL_ENTRY(getsockname
);
512 SWRAP_SYMBOL_ENTRY(getsockopt
);
513 SWRAP_SYMBOL_ENTRY(ioctl
);
514 SWRAP_SYMBOL_ENTRY(listen
);
515 SWRAP_SYMBOL_ENTRY(open
);
517 SWRAP_SYMBOL_ENTRY(open64
);
519 SWRAP_SYMBOL_ENTRY(openat
);
520 SWRAP_SYMBOL_ENTRY(pipe
);
521 SWRAP_SYMBOL_ENTRY(read
);
522 SWRAP_SYMBOL_ENTRY(readv
);
523 SWRAP_SYMBOL_ENTRY(recv
);
524 SWRAP_SYMBOL_ENTRY(recvfrom
);
525 SWRAP_SYMBOL_ENTRY(recvmsg
);
526 SWRAP_SYMBOL_ENTRY(send
);
527 SWRAP_SYMBOL_ENTRY(sendmsg
);
528 SWRAP_SYMBOL_ENTRY(sendto
);
529 SWRAP_SYMBOL_ENTRY(setsockopt
);
531 SWRAP_SYMBOL_ENTRY(signalfd
);
533 SWRAP_SYMBOL_ENTRY(socket
);
534 SWRAP_SYMBOL_ENTRY(socketpair
);
535 #ifdef HAVE_TIMERFD_CREATE
536 SWRAP_SYMBOL_ENTRY(timerfd_create
);
538 SWRAP_SYMBOL_ENTRY(write
);
539 SWRAP_SYMBOL_ENTRY(writev
);
546 struct swrap_libc_symbols symbols
;
550 static struct swrap swrap
;
553 static const char *socket_wrapper_dir(void);
555 #define LIBC_NAME "libc.so"
563 static const char *swrap_str_lib(enum swrap_lib lib
)
570 case SWRAP_LIBSOCKET
:
574 /* Compiler would warn us about unhandled enum value if we get here */
578 static void *swrap_load_lib_handle(enum swrap_lib lib
)
580 int flags
= RTLD_LAZY
;
585 flags
|= RTLD_DEEPBIND
;
591 case SWRAP_LIBSOCKET
:
592 #ifdef HAVE_LIBSOCKET
593 handle
= swrap
.libc
.socket_handle
;
594 if (handle
== NULL
) {
595 for (i
= 10; i
>= 0; i
--) {
596 char soname
[256] = {0};
598 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
599 handle
= dlopen(soname
, flags
);
600 if (handle
!= NULL
) {
605 swrap
.libc
.socket_handle
= handle
;
611 handle
= swrap
.libc
.handle
;
613 if (handle
== NULL
) {
614 handle
= dlopen(LIBC_SO
, flags
);
616 swrap
.libc
.handle
= handle
;
619 if (handle
== NULL
) {
620 for (i
= 10; i
>= 0; i
--) {
621 char soname
[256] = {0};
623 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
624 handle
= dlopen(soname
, flags
);
625 if (handle
!= NULL
) {
630 swrap
.libc
.handle
= handle
;
635 if (handle
== NULL
) {
637 handle
= swrap
.libc
.handle
= swrap
.libc
.socket_handle
= RTLD_NEXT
;
639 SWRAP_LOG(SWRAP_LOG_ERROR
,
640 "Failed to dlopen library: %s\n",
649 static void *_swrap_bind_symbol(enum swrap_lib lib
, const char *fn_name
)
654 handle
= swrap_load_lib_handle(lib
);
656 func
= dlsym(handle
, fn_name
);
658 SWRAP_LOG(SWRAP_LOG_ERROR
,
659 "Failed to find %s: %s\n",
665 SWRAP_LOG(SWRAP_LOG_TRACE
,
673 #define swrap_bind_symbol_libc(sym_name) \
674 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
675 SWRAP_LOCK(libc_symbol_binding); \
676 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
677 swrap.libc.symbols._libc_##sym_name.obj = \
678 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
680 SWRAP_UNLOCK(libc_symbol_binding); \
683 #define swrap_bind_symbol_libsocket(sym_name) \
684 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
685 SWRAP_LOCK(libc_symbol_binding); \
686 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
687 swrap.libc.symbols._libc_##sym_name.obj = \
688 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
690 SWRAP_UNLOCK(libc_symbol_binding); \
693 #define swrap_bind_symbol_libnsl(sym_name) \
694 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
695 SWRAP_LOCK(libc_symbol_binding); \
696 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
697 swrap.libc.symbols._libc_##sym_name.obj = \
698 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
700 SWRAP_UNLOCK(libc_symbol_binding); \
703 /****************************************************************************
705 ****************************************************************************
707 * Functions especially from libc need to be loaded individually, you can't
708 * load all at once or gdb will segfault at startup. The same applies to
709 * valgrind and has probably something todo with with the linker. So we need
710 * load each function at the point it is called the first time.
712 ****************************************************************************/
715 static int libc_accept4(int sockfd
,
716 struct sockaddr
*addr
,
720 swrap_bind_symbol_libsocket(accept4
);
722 return swrap
.libc
.symbols
._libc_accept4
.f(sockfd
, addr
, addrlen
, flags
);
725 #else /* HAVE_ACCEPT4 */
727 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
729 swrap_bind_symbol_libsocket(accept
);
731 return swrap
.libc
.symbols
._libc_accept
.f(sockfd
, addr
, addrlen
);
733 #endif /* HAVE_ACCEPT4 */
735 static int libc_bind(int sockfd
,
736 const struct sockaddr
*addr
,
739 swrap_bind_symbol_libsocket(bind
);
741 return swrap
.libc
.symbols
._libc_bind
.f(sockfd
, addr
, addrlen
);
744 static int libc_close(int fd
)
746 swrap_bind_symbol_libc(close
);
748 return swrap
.libc
.symbols
._libc_close
.f(fd
);
751 static int libc_connect(int sockfd
,
752 const struct sockaddr
*addr
,
755 swrap_bind_symbol_libsocket(connect
);
757 return swrap
.libc
.symbols
._libc_connect
.f(sockfd
, addr
, addrlen
);
760 static int libc_dup(int fd
)
762 swrap_bind_symbol_libc(dup
);
764 return swrap
.libc
.symbols
._libc_dup
.f(fd
);
767 static int libc_dup2(int oldfd
, int newfd
)
769 swrap_bind_symbol_libc(dup2
);
771 return swrap
.libc
.symbols
._libc_dup2
.f(oldfd
, newfd
);
775 static int libc_eventfd(int count
, int flags
)
777 swrap_bind_symbol_libc(eventfd
);
779 return swrap
.libc
.symbols
._libc_eventfd
.f(count
, flags
);
783 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
784 static int libc_vfcntl(int fd
, int cmd
, va_list ap
)
789 swrap_bind_symbol_libc(fcntl
);
791 arg
= va_arg(ap
, void *);
793 rc
= swrap
.libc
.symbols
._libc_fcntl
.f(fd
, cmd
, arg
);
798 static int libc_getpeername(int sockfd
,
799 struct sockaddr
*addr
,
802 swrap_bind_symbol_libsocket(getpeername
);
804 return swrap
.libc
.symbols
._libc_getpeername
.f(sockfd
, addr
, addrlen
);
807 static int libc_getsockname(int sockfd
,
808 struct sockaddr
*addr
,
811 swrap_bind_symbol_libsocket(getsockname
);
813 return swrap
.libc
.symbols
._libc_getsockname
.f(sockfd
, addr
, addrlen
);
816 static int libc_getsockopt(int sockfd
,
822 swrap_bind_symbol_libsocket(getsockopt
);
824 return swrap
.libc
.symbols
._libc_getsockopt
.f(sockfd
,
831 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
832 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
837 swrap_bind_symbol_libc(ioctl
);
839 arg
= va_arg(ap
, void *);
841 rc
= swrap
.libc
.symbols
._libc_ioctl
.f(d
, request
, arg
);
846 static int libc_listen(int sockfd
, int backlog
)
848 swrap_bind_symbol_libsocket(listen
);
850 return swrap
.libc
.symbols
._libc_listen
.f(sockfd
, backlog
);
853 static FILE *libc_fopen(const char *name
, const char *mode
)
855 swrap_bind_symbol_libc(fopen
);
857 return swrap
.libc
.symbols
._libc_fopen
.f(name
, mode
);
861 static FILE *libc_fopen64(const char *name
, const char *mode
)
863 swrap_bind_symbol_libc(fopen64
);
865 return swrap
.libc
.symbols
._libc_fopen64
.f(name
, mode
);
867 #endif /* HAVE_FOPEN64 */
869 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
874 swrap_bind_symbol_libc(open
);
876 if (flags
& O_CREAT
) {
877 mode
= va_arg(ap
, int);
879 fd
= swrap
.libc
.symbols
._libc_open
.f(pathname
, flags
, (mode_t
)mode
);
884 static int libc_open(const char *pathname
, int flags
, ...)
890 fd
= libc_vopen(pathname
, flags
, ap
);
897 static int libc_vopen64(const char *pathname
, int flags
, va_list ap
)
902 swrap_bind_symbol_libc(open64
);
904 if (flags
& O_CREAT
) {
905 mode
= va_arg(ap
, int);
907 fd
= swrap
.libc
.symbols
._libc_open64
.f(pathname
, flags
, (mode_t
)mode
);
911 #endif /* HAVE_OPEN64 */
913 static int libc_vopenat(int dirfd
, const char *path
, int flags
, va_list ap
)
918 swrap_bind_symbol_libc(openat
);
920 if (flags
& O_CREAT
) {
921 mode
= va_arg(ap
, int);
923 fd
= swrap
.libc
.symbols
._libc_openat
.f(dirfd
,
932 static int libc_openat(int dirfd
, const char *path
, int flags
, ...)
938 fd
= libc_vopenat(dirfd
, path
, flags
, ap
);
945 static int libc_pipe(int pipefd
[2])
947 swrap_bind_symbol_libsocket(pipe
);
949 return swrap
.libc
.symbols
._libc_pipe
.f(pipefd
);
952 static int libc_read(int fd
, void *buf
, size_t count
)
954 swrap_bind_symbol_libc(read
);
956 return swrap
.libc
.symbols
._libc_read
.f(fd
, buf
, count
);
959 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
961 swrap_bind_symbol_libsocket(readv
);
963 return swrap
.libc
.symbols
._libc_readv
.f(fd
, iov
, iovcnt
);
966 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
968 swrap_bind_symbol_libsocket(recv
);
970 return swrap
.libc
.symbols
._libc_recv
.f(sockfd
, buf
, len
, flags
);
973 static int libc_recvfrom(int sockfd
,
977 struct sockaddr
*src_addr
,
980 swrap_bind_symbol_libsocket(recvfrom
);
982 return swrap
.libc
.symbols
._libc_recvfrom
.f(sockfd
,
990 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
992 swrap_bind_symbol_libsocket(recvmsg
);
994 return swrap
.libc
.symbols
._libc_recvmsg
.f(sockfd
, msg
, flags
);
997 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
999 swrap_bind_symbol_libsocket(send
);
1001 return swrap
.libc
.symbols
._libc_send
.f(sockfd
, buf
, len
, flags
);
1004 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
1006 swrap_bind_symbol_libsocket(sendmsg
);
1008 return swrap
.libc
.symbols
._libc_sendmsg
.f(sockfd
, msg
, flags
);
1011 static int libc_sendto(int sockfd
,
1015 const struct sockaddr
*dst_addr
,
1018 swrap_bind_symbol_libsocket(sendto
);
1020 return swrap
.libc
.symbols
._libc_sendto
.f(sockfd
,
1028 static int libc_setsockopt(int sockfd
,
1034 swrap_bind_symbol_libsocket(setsockopt
);
1036 return swrap
.libc
.symbols
._libc_setsockopt
.f(sockfd
,
1043 #ifdef HAVE_SIGNALFD
1044 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
1046 swrap_bind_symbol_libsocket(signalfd
);
1048 return swrap
.libc
.symbols
._libc_signalfd
.f(fd
, mask
, flags
);
1052 static int libc_socket(int domain
, int type
, int protocol
)
1054 swrap_bind_symbol_libsocket(socket
);
1056 return swrap
.libc
.symbols
._libc_socket
.f(domain
, type
, protocol
);
1059 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
1061 swrap_bind_symbol_libsocket(socketpair
);
1063 return swrap
.libc
.symbols
._libc_socketpair
.f(domain
, type
, protocol
, sv
);
1066 #ifdef HAVE_TIMERFD_CREATE
1067 static int libc_timerfd_create(int clockid
, int flags
)
1069 swrap_bind_symbol_libc(timerfd_create
);
1071 return swrap
.libc
.symbols
._libc_timerfd_create
.f(clockid
, flags
);
1075 static ssize_t
libc_write(int fd
, const void *buf
, size_t count
)
1077 swrap_bind_symbol_libc(write
);
1079 return swrap
.libc
.symbols
._libc_write
.f(fd
, buf
, count
);
1082 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
1084 swrap_bind_symbol_libsocket(writev
);
1086 return swrap
.libc
.symbols
._libc_writev
.f(fd
, iov
, iovcnt
);
1089 /* DO NOT call this function during library initialization! */
1090 static void swrap_bind_symbol_all(void)
1093 swrap_bind_symbol_libsocket(accept4
);
1095 swrap_bind_symbol_libsocket(accept
);
1097 swrap_bind_symbol_libsocket(bind
);
1098 swrap_bind_symbol_libc(close
);
1099 swrap_bind_symbol_libsocket(connect
);
1100 swrap_bind_symbol_libc(dup
);
1101 swrap_bind_symbol_libc(dup2
);
1102 swrap_bind_symbol_libc(fcntl
);
1103 swrap_bind_symbol_libc(fopen
);
1105 swrap_bind_symbol_libc(fopen64
);
1108 swrap_bind_symbol_libc(eventfd
);
1110 swrap_bind_symbol_libsocket(getpeername
);
1111 swrap_bind_symbol_libsocket(getsockname
);
1112 swrap_bind_symbol_libsocket(getsockopt
);
1113 swrap_bind_symbol_libc(ioctl
);
1114 swrap_bind_symbol_libsocket(listen
);
1115 swrap_bind_symbol_libc(open
);
1117 swrap_bind_symbol_libc(open64
);
1119 swrap_bind_symbol_libc(openat
);
1120 swrap_bind_symbol_libsocket(pipe
);
1121 swrap_bind_symbol_libc(read
);
1122 swrap_bind_symbol_libsocket(readv
);
1123 swrap_bind_symbol_libsocket(recv
);
1124 swrap_bind_symbol_libsocket(recvfrom
);
1125 swrap_bind_symbol_libsocket(recvmsg
);
1126 swrap_bind_symbol_libsocket(send
);
1127 swrap_bind_symbol_libsocket(sendmsg
);
1128 swrap_bind_symbol_libsocket(sendto
);
1129 swrap_bind_symbol_libsocket(setsockopt
);
1130 #ifdef HAVE_SIGNALFD
1131 swrap_bind_symbol_libsocket(signalfd
);
1133 swrap_bind_symbol_libsocket(socket
);
1134 swrap_bind_symbol_libsocket(socketpair
);
1135 #ifdef HAVE_TIMERFD_CREATE
1136 swrap_bind_symbol_libc(timerfd_create
);
1138 swrap_bind_symbol_libc(write
);
1139 swrap_bind_symbol_libsocket(writev
);
1142 /*********************************************************
1143 * SWRAP HELPER FUNCTIONS
1144 *********************************************************/
1150 static const struct in6_addr
*swrap_ipv6(void)
1152 static struct in6_addr v
;
1153 static int initialized
;
1161 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
1170 static void set_port(int family
, int prt
, struct swrap_address
*addr
)
1174 addr
->sa
.in
.sin_port
= htons(prt
);
1178 addr
->sa
.in6
.sin6_port
= htons(prt
);
1184 static size_t socket_length(int family
)
1188 return sizeof(struct sockaddr_in
);
1191 return sizeof(struct sockaddr_in6
);
1197 static const char *socket_wrapper_dir(void)
1199 const char *s
= getenv("SOCKET_WRAPPER_DIR");
1203 /* TODO use realpath(3) here, when we add support for threads */
1204 if (strncmp(s
, "./", 2) == 0) {
1208 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
1212 static unsigned int socket_wrapper_mtu(void)
1214 static unsigned int max_mtu
= 0;
1223 max_mtu
= SOCKET_WRAPPER_MTU_DEFAULT
;
1225 s
= getenv("SOCKET_WRAPPER_MTU");
1230 tmp
= strtol(s
, &endp
, 10);
1235 if (tmp
< SOCKET_WRAPPER_MTU_MIN
|| tmp
> SOCKET_WRAPPER_MTU_MAX
) {
1244 static size_t socket_wrapper_max_sockets(void)
1250 if (max_sockets
!= 0) {
1254 max_sockets
= SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT
;
1256 s
= getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1257 if (s
== NULL
|| s
[0] == '\0') {
1261 tmp
= strtoul(s
, &endp
, 10);
1265 if (tmp
== 0 || tmp
> SOCKET_WRAPPER_MAX_SOCKETS_LIMIT
) {
1266 SWRAP_LOG(SWRAP_LOG_ERROR
,
1267 "Invalid number of sockets specified, using default.");
1277 static void socket_wrapper_init_sockets(void)
1281 if (sockets
!= NULL
) {
1285 max_sockets
= socket_wrapper_max_sockets();
1287 sockets
= (struct socket_info
*)calloc(max_sockets
,
1288 sizeof(struct socket_info
));
1290 if (sockets
== NULL
) {
1291 SWRAP_LOG(SWRAP_LOG_ERROR
,
1292 "Failed to allocate sockets array.\n");
1298 for (i
= 0; i
< max_sockets
; i
++) {
1299 sockets
[i
].next_free
= i
+1;
1302 sockets
[max_sockets
-1].next_free
= -1;
1305 bool socket_wrapper_enabled(void)
1307 const char *s
= socket_wrapper_dir();
1313 socket_wrapper_init_sockets();
1318 static unsigned int socket_wrapper_default_iface(void)
1320 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1323 if (sscanf(s
, "%u", &iface
) == 1) {
1324 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
1330 return 1;/* 127.0.0.1 */
1334 * Return the first free entry (if any) and make
1335 * it re-usable again (by nulling it out)
1337 static int socket_wrapper_first_free_index(void)
1341 if (first_free
== -1) {
1345 next_free
= sockets
[first_free
].next_free
;
1346 ZERO_STRUCT(sockets
[first_free
]);
1347 sockets
[first_free
].next_free
= next_free
;
1352 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
1359 p
= strrchr(un
->sun_path
, '/');
1360 if (p
) p
++; else p
= un
->sun_path
;
1362 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
1367 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
1370 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1381 case SOCKET_TYPE_CHAR_TCP
:
1382 case SOCKET_TYPE_CHAR_UDP
: {
1383 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
1385 if ((*len
) < sizeof(*in2
)) {
1390 memset(in2
, 0, sizeof(*in2
));
1391 in2
->sin_family
= AF_INET
;
1392 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
1393 in2
->sin_port
= htons(prt
);
1395 *len
= sizeof(*in2
);
1399 case SOCKET_TYPE_CHAR_TCP_V6
:
1400 case SOCKET_TYPE_CHAR_UDP_V6
: {
1401 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
1403 if ((*len
) < sizeof(*in2
)) {
1408 memset(in2
, 0, sizeof(*in2
));
1409 in2
->sin6_family
= AF_INET6
;
1410 in2
->sin6_addr
= *swrap_ipv6();
1411 in2
->sin6_addr
.s6_addr
[15] = iface
;
1412 in2
->sin6_port
= htons(prt
);
1414 *len
= sizeof(*in2
);
1426 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1434 if (bcast
) *bcast
= 0;
1436 switch (inaddr
->sa_family
) {
1438 const struct sockaddr_in
*in
=
1439 (const struct sockaddr_in
*)(const void *)inaddr
;
1440 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1447 u_type
= SOCKET_TYPE_CHAR_TCP
;
1450 u_type
= SOCKET_TYPE_CHAR_UDP
;
1451 a_type
= SOCKET_TYPE_CHAR_UDP
;
1452 b_type
= SOCKET_TYPE_CHAR_UDP
;
1455 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1456 errno
= ESOCKTNOSUPPORT
;
1460 prt
= ntohs(in
->sin_port
);
1461 if (a_type
&& addr
== 0xFFFFFFFF) {
1462 /* 255.255.255.255 only udp */
1465 iface
= socket_wrapper_default_iface();
1466 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1467 /* 127.255.255.255 only udp */
1470 iface
= socket_wrapper_default_iface();
1471 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1475 iface
= (addr
& 0x000000FF);
1477 errno
= ENETUNREACH
;
1480 if (bcast
) *bcast
= is_bcast
;
1485 const struct sockaddr_in6
*in
=
1486 (const struct sockaddr_in6
*)(const void *)inaddr
;
1487 struct in6_addr cmp1
, cmp2
;
1491 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1494 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1497 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1498 errno
= ESOCKTNOSUPPORT
;
1502 /* XXX no multicast/broadcast */
1504 prt
= ntohs(in
->sin6_port
);
1506 cmp1
= *swrap_ipv6();
1507 cmp2
= in
->sin6_addr
;
1508 cmp2
.s6_addr
[15] = 0;
1509 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1510 iface
= in
->sin6_addr
.s6_addr
[15];
1512 errno
= ENETUNREACH
;
1520 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1521 errno
= ENETUNREACH
;
1526 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1532 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1533 socket_wrapper_dir());
1534 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1535 /* the caller need to do more processing */
1539 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1540 socket_wrapper_dir(), type
, iface
, prt
);
1541 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1546 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1555 if (bcast
) *bcast
= 0;
1557 switch (si
->family
) {
1559 const struct sockaddr_in
*in
=
1560 (const struct sockaddr_in
*)(const void *)inaddr
;
1561 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1567 prt
= ntohs(in
->sin_port
);
1571 u_type
= SOCKET_TYPE_CHAR_TCP
;
1572 d_type
= SOCKET_TYPE_CHAR_TCP
;
1575 u_type
= SOCKET_TYPE_CHAR_UDP
;
1576 d_type
= SOCKET_TYPE_CHAR_UDP
;
1577 a_type
= SOCKET_TYPE_CHAR_UDP
;
1578 b_type
= SOCKET_TYPE_CHAR_UDP
;
1581 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1582 errno
= ESOCKTNOSUPPORT
;
1590 iface
= socket_wrapper_default_iface();
1591 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1592 /* 255.255.255.255 only udp */
1595 iface
= socket_wrapper_default_iface();
1596 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1597 /* 127.255.255.255 only udp */
1600 iface
= socket_wrapper_default_iface();
1601 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1605 iface
= (addr
& 0x000000FF);
1607 errno
= EADDRNOTAVAIL
;
1611 /* Store the bind address for connect() */
1612 if (si
->bindname
.sa_socklen
== 0) {
1613 struct sockaddr_in bind_in
;
1614 socklen_t blen
= sizeof(struct sockaddr_in
);
1616 ZERO_STRUCT(bind_in
);
1617 bind_in
.sin_family
= in
->sin_family
;
1618 bind_in
.sin_port
= in
->sin_port
;
1619 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1621 si
->bindname
.sa_socklen
= blen
;
1622 memcpy(&si
->bindname
.sa
.in
, &bind_in
, blen
);
1629 const struct sockaddr_in6
*in
=
1630 (const struct sockaddr_in6
*)(const void *)inaddr
;
1631 struct in6_addr cmp1
, cmp2
;
1635 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1638 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1641 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1642 errno
= ESOCKTNOSUPPORT
;
1646 /* XXX no multicast/broadcast */
1648 prt
= ntohs(in
->sin6_port
);
1650 cmp1
= *swrap_ipv6();
1651 cmp2
= in
->sin6_addr
;
1652 cmp2
.s6_addr
[15] = 0;
1653 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1654 iface
= socket_wrapper_default_iface();
1655 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1656 iface
= in
->sin6_addr
.s6_addr
[15];
1658 errno
= EADDRNOTAVAIL
;
1662 /* Store the bind address for connect() */
1663 if (si
->bindname
.sa_socklen
== 0) {
1664 struct sockaddr_in6 bind_in
;
1665 socklen_t blen
= sizeof(struct sockaddr_in6
);
1667 ZERO_STRUCT(bind_in
);
1668 bind_in
.sin6_family
= in
->sin6_family
;
1669 bind_in
.sin6_port
= in
->sin6_port
;
1671 bind_in
.sin6_addr
= *swrap_ipv6();
1672 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1674 memcpy(&si
->bindname
.sa
.in6
, &bind_in
, blen
);
1675 si
->bindname
.sa_socklen
= blen
;
1682 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1683 errno
= EADDRNOTAVAIL
;
1688 if (bcast
) *bcast
= is_bcast
;
1690 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1696 /* handle auto-allocation of ephemeral ports */
1697 for (prt
= 5001; prt
< 10000; prt
++) {
1698 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1699 socket_wrapper_dir(), type
, iface
, prt
);
1700 if (stat(un
->sun_path
, &st
) == 0) continue;
1702 set_port(si
->family
, prt
, &si
->myname
);
1703 set_port(si
->family
, prt
, &si
->bindname
);
1713 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1714 socket_wrapper_dir(), type
, iface
, prt
);
1715 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1719 static struct socket_info_fd
*find_socket_info_fd(int fd
)
1721 struct socket_info_fd
*f
;
1723 for (f
= socket_fds
; f
; f
= f
->next
) {
1732 static int find_socket_info_index(int fd
)
1734 struct socket_info_fd
*fi
= find_socket_info_fd(fd
);
1740 return fi
->si_index
;
1743 static struct socket_info
*find_socket_info(int fd
)
1745 int idx
= find_socket_info_index(fd
);
1751 return &sockets
[idx
];
1755 static bool check_addr_port_in_use(const struct sockaddr
*sa
, socklen_t len
)
1757 struct socket_info_fd
*f
;
1758 const struct socket_info
*last_s
= NULL
;
1760 /* first catch invalid input */
1761 switch (sa
->sa_family
) {
1763 if (len
< sizeof(struct sockaddr_in
)) {
1769 if (len
< sizeof(struct sockaddr_in6
)) {
1779 for (f
= socket_fds
; f
; f
= f
->next
) {
1780 struct socket_info
*s
= &sockets
[f
->si_index
];
1787 if (s
->myname
== NULL
) {
1790 if (s
->myname
->sa_family
!= sa
->sa_family
) {
1793 switch (s
->myname
->sa_family
) {
1795 struct sockaddr_in
*sin1
, *sin2
;
1797 sin1
= (struct sockaddr_in
*)s
->myname
;
1798 sin2
= (struct sockaddr_in
*)sa
;
1800 if (sin1
->sin_addr
.s_addr
== htonl(INADDR_ANY
)) {
1803 if (sin1
->sin_port
!= sin2
->sin_port
) {
1806 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
1816 struct sockaddr_in6
*sin1
, *sin2
;
1818 sin1
= (struct sockaddr_in6
*)s
->myname
;
1819 sin2
= (struct sockaddr_in6
*)sa
;
1821 if (sin1
->sin6_port
!= sin2
->sin6_port
) {
1824 if (!IN6_ARE_ADDR_EQUAL(&sin1
->sin6_addr
,
1846 static void swrap_remove_stale(int fd
)
1848 struct socket_info_fd
*fi
= find_socket_info_fd(fd
);
1849 struct socket_info
*si
;
1856 si_index
= fi
->si_index
;
1858 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1859 SWRAP_DLIST_REMOVE(socket_fds
, fi
);
1862 si
= &sockets
[si_index
];
1865 if (si
->refcount
> 0) {
1869 if (si
->un_addr
.sun_path
[0] != '\0') {
1870 unlink(si
->un_addr
.sun_path
);
1873 si
->next_free
= first_free
;
1874 first_free
= si_index
;
1877 static int sockaddr_convert_to_un(struct socket_info
*si
,
1878 const struct sockaddr
*in_addr
,
1880 struct sockaddr_un
*out_addr
,
1884 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1886 (void) in_len
; /* unused */
1888 if (out_addr
== NULL
) {
1892 out
->sa_family
= AF_UNIX
;
1893 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1894 out
->sa_len
= sizeof(*out_addr
);
1897 switch (in_addr
->sa_family
) {
1899 const struct sockaddr_in
*sin
;
1900 if (si
->family
!= AF_INET
) {
1903 if (in_len
< sizeof(struct sockaddr_in
)) {
1906 sin
= (const struct sockaddr_in
*)(const void *)in_addr
;
1907 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
1912 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1913 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1927 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1928 errno
= ESOCKTNOSUPPORT
;
1932 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1934 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1940 errno
= EAFNOSUPPORT
;
1941 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1945 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1946 const struct sockaddr_un
*in_addr
,
1947 socklen_t un_addrlen
,
1949 struct sockaddr
*out_addr
,
1950 socklen_t
*out_addrlen
)
1954 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1957 if (un_addrlen
== 0) {
1972 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1973 errno
= ESOCKTNOSUPPORT
;
1976 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1977 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1978 out_addr
->sa_len
= *out_addrlen
;
1985 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1986 errno
= EAFNOSUPPORT
;
1990 enum swrap_packet_type
{
1992 SWRAP_CONNECT_UNREACH
,
2000 SWRAP_SENDTO_UNREACH
,
2011 struct swrap_file_hdr
{
2013 uint16_t version_major
;
2014 uint16_t version_minor
;
2017 uint32_t frame_max_len
;
2018 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2021 #define SWRAP_FILE_HDR_SIZE 24
2023 struct swrap_packet_frame
{
2025 uint32_t micro_seconds
;
2026 uint32_t recorded_length
;
2027 uint32_t full_length
;
2029 #define SWRAP_PACKET_FRAME_SIZE 16
2031 union swrap_packet_ip
{
2035 uint16_t packet_length
;
2036 uint16_t identification
;
2041 uint16_t hdr_checksum
;
2045 #define SWRAP_PACKET_IP_V4_SIZE 20
2048 uint8_t flow_label_high
;
2049 uint16_t flow_label_low
;
2050 uint16_t payload_length
;
2051 uint8_t next_header
;
2053 uint8_t src_addr
[16];
2054 uint8_t dest_addr
[16];
2056 #define SWRAP_PACKET_IP_V6_SIZE 40
2058 #define SWRAP_PACKET_IP_SIZE 40
2060 union swrap_packet_payload
{
2062 uint16_t source_port
;
2072 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2074 uint16_t source_port
;
2079 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2086 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2093 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2095 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2097 #define SWRAP_PACKET_MIN_ALLOC \
2098 (SWRAP_PACKET_FRAME_SIZE + \
2099 SWRAP_PACKET_IP_SIZE + \
2100 SWRAP_PACKET_PAYLOAD_SIZE)
2102 static const char *swrap_pcap_init_file(void)
2104 static int initialized
= 0;
2105 static const char *s
= NULL
;
2106 static const struct swrap_file_hdr h
;
2107 static const struct swrap_packet_frame f
;
2108 static const union swrap_packet_ip i
;
2109 static const union swrap_packet_payload p
;
2111 if (initialized
== 1) {
2117 * TODO: don't use the structs use plain buffer offsets
2118 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2120 * for now make sure we disable PCAP support
2121 * if the struct has alignment!
2123 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
2126 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
2129 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
2132 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
2135 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
2138 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
2141 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
2144 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
2147 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
2150 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
2154 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
2158 if (strncmp(s
, "./", 2) == 0) {
2164 static uint8_t *swrap_pcap_packet_init(struct timeval
*tval
,
2165 const struct sockaddr
*src
,
2166 const struct sockaddr
*dest
,
2168 const uint8_t *payload
,
2170 unsigned long tcp_seqno
,
2171 unsigned long tcp_ack
,
2172 unsigned char tcp_ctl
,
2174 size_t *_packet_len
)
2178 struct swrap_packet_frame
*frame
;
2179 union swrap_packet_ip
*ip
;
2180 union swrap_packet_payload
*pay
;
2183 size_t nonwire_len
= sizeof(*frame
);
2184 size_t wire_hdr_len
= 0;
2185 size_t wire_len
= 0;
2186 size_t ip_hdr_len
= 0;
2187 size_t icmp_hdr_len
= 0;
2188 size_t icmp_truncate_len
= 0;
2189 uint8_t protocol
= 0, icmp_protocol
= 0;
2190 const struct sockaddr_in
*src_in
= NULL
;
2191 const struct sockaddr_in
*dest_in
= NULL
;
2193 const struct sockaddr_in6
*src_in6
= NULL
;
2194 const struct sockaddr_in6
*dest_in6
= NULL
;
2199 switch (src
->sa_family
) {
2201 src_in
= (const struct sockaddr_in
*)(const void *)src
;
2202 dest_in
= (const struct sockaddr_in
*)(const void *)dest
;
2203 src_port
= src_in
->sin_port
;
2204 dest_port
= dest_in
->sin_port
;
2205 ip_hdr_len
= sizeof(ip
->v4
);
2209 src_in6
= (const struct sockaddr_in6
*)(const void *)src
;
2210 dest_in6
= (const struct sockaddr_in6
*)(const void *)dest
;
2211 src_port
= src_in6
->sin6_port
;
2212 dest_port
= dest_in6
->sin6_port
;
2213 ip_hdr_len
= sizeof(ip
->v6
);
2220 switch (socket_type
) {
2222 protocol
= 0x06; /* TCP */
2223 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
2224 wire_len
= wire_hdr_len
+ payload_len
;
2228 protocol
= 0x11; /* UDP */
2229 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
2230 wire_len
= wire_hdr_len
+ payload_len
;
2238 icmp_protocol
= protocol
;
2239 switch (src
->sa_family
) {
2241 protocol
= 0x01; /* ICMPv4 */
2242 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
2246 protocol
= 0x3A; /* ICMPv6 */
2247 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
2251 if (wire_len
> 64 ) {
2252 icmp_truncate_len
= wire_len
- 64;
2254 wire_hdr_len
+= icmp_hdr_len
;
2255 wire_len
+= icmp_hdr_len
;
2258 packet_len
= nonwire_len
+ wire_len
;
2259 alloc_len
= packet_len
;
2260 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
2261 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
2264 base
= (uint8_t *)calloc(1, alloc_len
);
2271 frame
= (struct swrap_packet_frame
*)(void *)buf
;
2272 frame
->seconds
= tval
->tv_sec
;
2273 frame
->micro_seconds
= tval
->tv_usec
;
2274 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
2275 frame
->full_length
= wire_len
- icmp_truncate_len
;
2276 buf
+= SWRAP_PACKET_FRAME_SIZE
;
2278 ip
= (union swrap_packet_ip
*)(void *)buf
;
2279 switch (src
->sa_family
) {
2281 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
2283 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
2284 ip
->v4
.identification
= htons(0xFFFF);
2285 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
2286 ip
->v4
.fragment
= htons(0x0000);
2288 ip
->v4
.protocol
= protocol
;
2289 ip
->v4
.hdr_checksum
= htons(0x0000);
2290 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
2291 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
2292 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
2296 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
2297 ip
->v6
.flow_label_high
= 0x00;
2298 ip
->v6
.flow_label_low
= 0x0000;
2299 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
2300 ip
->v6
.next_header
= protocol
;
2301 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
2302 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
2303 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
2309 pay
= (union swrap_packet_payload
*)(void *)buf
;
2310 switch (src
->sa_family
) {
2312 pay
->icmp4
.type
= 0x03; /* destination unreachable */
2313 pay
->icmp4
.code
= 0x01; /* host unreachable */
2314 pay
->icmp4
.checksum
= htons(0x0000);
2315 pay
->icmp4
.unused
= htonl(0x00000000);
2316 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
2318 /* set the ip header in the ICMP payload */
2319 ip
= (union swrap_packet_ip
*)(void *)buf
;
2320 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
2322 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
2323 ip
->v4
.identification
= htons(0xFFFF);
2324 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
2325 ip
->v4
.fragment
= htons(0x0000);
2327 ip
->v4
.protocol
= icmp_protocol
;
2328 ip
->v4
.hdr_checksum
= htons(0x0000);
2329 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
2330 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
2331 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
2333 src_port
= dest_in
->sin_port
;
2334 dest_port
= src_in
->sin_port
;
2338 pay
->icmp6
.type
= 0x01; /* destination unreachable */
2339 pay
->icmp6
.code
= 0x03; /* address unreachable */
2340 pay
->icmp6
.checksum
= htons(0x0000);
2341 pay
->icmp6
.unused
= htonl(0x00000000);
2342 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
2344 /* set the ip header in the ICMP payload */
2345 ip
= (union swrap_packet_ip
*)(void *)buf
;
2346 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
2347 ip
->v6
.flow_label_high
= 0x00;
2348 ip
->v6
.flow_label_low
= 0x0000;
2349 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
2350 ip
->v6
.next_header
= protocol
;
2351 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
2352 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
2353 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
2355 src_port
= dest_in6
->sin6_port
;
2356 dest_port
= src_in6
->sin6_port
;
2362 pay
= (union swrap_packet_payload
*)(void *)buf
;
2364 switch (socket_type
) {
2366 pay
->tcp
.source_port
= src_port
;
2367 pay
->tcp
.dest_port
= dest_port
;
2368 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
2369 pay
->tcp
.ack_num
= htonl(tcp_ack
);
2370 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
2371 pay
->tcp
.control
= tcp_ctl
;
2372 pay
->tcp
.window
= htons(0x7FFF);
2373 pay
->tcp
.checksum
= htons(0x0000);
2374 pay
->tcp
.urg
= htons(0x0000);
2375 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
2380 pay
->udp
.source_port
= src_port
;
2381 pay
->udp
.dest_port
= dest_port
;
2382 pay
->udp
.length
= htons(8 + payload_len
);
2383 pay
->udp
.checksum
= htons(0x0000);
2384 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
2389 if (payload
&& payload_len
> 0) {
2390 memcpy(buf
, payload
, payload_len
);
2393 *_packet_len
= packet_len
- icmp_truncate_len
;
2397 static int swrap_pcap_get_fd(const char *fname
)
2405 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
2407 struct swrap_file_hdr file_hdr
;
2408 file_hdr
.magic
= 0xA1B2C3D4;
2409 file_hdr
.version_major
= 0x0002;
2410 file_hdr
.version_minor
= 0x0004;
2411 file_hdr
.timezone
= 0x00000000;
2412 file_hdr
.sigfigs
= 0x00000000;
2413 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
2414 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
2416 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
2423 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
2428 static uint8_t *swrap_pcap_marshall_packet(struct socket_info
*si
,
2429 const struct sockaddr
*addr
,
2430 enum swrap_packet_type type
,
2431 const void *buf
, size_t len
,
2434 const struct sockaddr
*src_addr
;
2435 const struct sockaddr
*dest_addr
;
2436 unsigned long tcp_seqno
= 0;
2437 unsigned long tcp_ack
= 0;
2438 unsigned char tcp_ctl
= 0;
2439 int unreachable
= 0;
2443 switch (si
->family
) {
2455 case SWRAP_CONNECT_SEND
:
2456 if (si
->type
!= SOCK_STREAM
) {
2460 src_addr
= &si
->myname
.sa
.s
;
2463 tcp_seqno
= si
->io
.pck_snd
;
2464 tcp_ack
= si
->io
.pck_rcv
;
2465 tcp_ctl
= 0x02; /* SYN */
2467 si
->io
.pck_snd
+= 1;
2471 case SWRAP_CONNECT_RECV
:
2472 if (si
->type
!= SOCK_STREAM
) {
2476 dest_addr
= &si
->myname
.sa
.s
;
2479 tcp_seqno
= si
->io
.pck_rcv
;
2480 tcp_ack
= si
->io
.pck_snd
;
2481 tcp_ctl
= 0x12; /** SYN,ACK */
2483 si
->io
.pck_rcv
+= 1;
2487 case SWRAP_CONNECT_UNREACH
:
2488 if (si
->type
!= SOCK_STREAM
) {
2492 dest_addr
= &si
->myname
.sa
.s
;
2495 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2496 tcp_seqno
= si
->io
.pck_snd
- 1;
2497 tcp_ack
= si
->io
.pck_rcv
;
2498 tcp_ctl
= 0x02; /* SYN */
2503 case SWRAP_CONNECT_ACK
:
2504 if (si
->type
!= SOCK_STREAM
) {
2508 src_addr
= &si
->myname
.sa
.s
;
2511 tcp_seqno
= si
->io
.pck_snd
;
2512 tcp_ack
= si
->io
.pck_rcv
;
2513 tcp_ctl
= 0x10; /* ACK */
2517 case SWRAP_ACCEPT_SEND
:
2518 if (si
->type
!= SOCK_STREAM
) {
2522 dest_addr
= &si
->myname
.sa
.s
;
2525 tcp_seqno
= si
->io
.pck_rcv
;
2526 tcp_ack
= si
->io
.pck_snd
;
2527 tcp_ctl
= 0x02; /* SYN */
2529 si
->io
.pck_rcv
+= 1;
2533 case SWRAP_ACCEPT_RECV
:
2534 if (si
->type
!= SOCK_STREAM
) {
2538 src_addr
= &si
->myname
.sa
.s
;
2541 tcp_seqno
= si
->io
.pck_snd
;
2542 tcp_ack
= si
->io
.pck_rcv
;
2543 tcp_ctl
= 0x12; /* SYN,ACK */
2545 si
->io
.pck_snd
+= 1;
2549 case SWRAP_ACCEPT_ACK
:
2550 if (si
->type
!= SOCK_STREAM
) {
2554 dest_addr
= &si
->myname
.sa
.s
;
2557 tcp_seqno
= si
->io
.pck_rcv
;
2558 tcp_ack
= si
->io
.pck_snd
;
2559 tcp_ctl
= 0x10; /* ACK */
2564 src_addr
= &si
->myname
.sa
.s
;
2565 dest_addr
= &si
->peername
.sa
.s
;
2567 tcp_seqno
= si
->io
.pck_snd
;
2568 tcp_ack
= si
->io
.pck_rcv
;
2569 tcp_ctl
= 0x18; /* PSH,ACK */
2571 si
->io
.pck_snd
+= len
;
2575 case SWRAP_SEND_RST
:
2576 dest_addr
= &si
->myname
.sa
.s
;
2577 src_addr
= &si
->peername
.sa
.s
;
2579 if (si
->type
== SOCK_DGRAM
) {
2580 return swrap_pcap_marshall_packet(si
,
2582 SWRAP_SENDTO_UNREACH
,
2588 tcp_seqno
= si
->io
.pck_rcv
;
2589 tcp_ack
= si
->io
.pck_snd
;
2590 tcp_ctl
= 0x14; /** RST,ACK */
2594 case SWRAP_PENDING_RST
:
2595 dest_addr
= &si
->myname
.sa
.s
;
2596 src_addr
= &si
->peername
.sa
.s
;
2598 if (si
->type
== SOCK_DGRAM
) {
2602 tcp_seqno
= si
->io
.pck_rcv
;
2603 tcp_ack
= si
->io
.pck_snd
;
2604 tcp_ctl
= 0x14; /* RST,ACK */
2609 dest_addr
= &si
->myname
.sa
.s
;
2610 src_addr
= &si
->peername
.sa
.s
;
2612 tcp_seqno
= si
->io
.pck_rcv
;
2613 tcp_ack
= si
->io
.pck_snd
;
2614 tcp_ctl
= 0x18; /* PSH,ACK */
2616 si
->io
.pck_rcv
+= len
;
2620 case SWRAP_RECV_RST
:
2621 dest_addr
= &si
->myname
.sa
.s
;
2622 src_addr
= &si
->peername
.sa
.s
;
2624 if (si
->type
== SOCK_DGRAM
) {
2628 tcp_seqno
= si
->io
.pck_rcv
;
2629 tcp_ack
= si
->io
.pck_snd
;
2630 tcp_ctl
= 0x14; /* RST,ACK */
2635 src_addr
= &si
->myname
.sa
.s
;
2638 si
->io
.pck_snd
+= len
;
2642 case SWRAP_SENDTO_UNREACH
:
2643 dest_addr
= &si
->myname
.sa
.s
;
2650 case SWRAP_RECVFROM
:
2651 dest_addr
= &si
->myname
.sa
.s
;
2654 si
->io
.pck_rcv
+= len
;
2658 case SWRAP_CLOSE_SEND
:
2659 if (si
->type
!= SOCK_STREAM
) {
2663 src_addr
= &si
->myname
.sa
.s
;
2664 dest_addr
= &si
->peername
.sa
.s
;
2666 tcp_seqno
= si
->io
.pck_snd
;
2667 tcp_ack
= si
->io
.pck_rcv
;
2668 tcp_ctl
= 0x11; /* FIN, ACK */
2670 si
->io
.pck_snd
+= 1;
2674 case SWRAP_CLOSE_RECV
:
2675 if (si
->type
!= SOCK_STREAM
) {
2679 dest_addr
= &si
->myname
.sa
.s
;
2680 src_addr
= &si
->peername
.sa
.s
;
2682 tcp_seqno
= si
->io
.pck_rcv
;
2683 tcp_ack
= si
->io
.pck_snd
;
2684 tcp_ctl
= 0x11; /* FIN,ACK */
2686 si
->io
.pck_rcv
+= 1;
2690 case SWRAP_CLOSE_ACK
:
2691 if (si
->type
!= SOCK_STREAM
) {
2695 src_addr
= &si
->myname
.sa
.s
;
2696 dest_addr
= &si
->peername
.sa
.s
;
2698 tcp_seqno
= si
->io
.pck_snd
;
2699 tcp_ack
= si
->io
.pck_rcv
;
2700 tcp_ctl
= 0x10; /* ACK */
2707 swrapGetTimeOfDay(&tv
);
2709 return swrap_pcap_packet_init(&tv
,
2713 (const uint8_t *)buf
,
2722 static void swrap_pcap_dump_packet(struct socket_info
*si
,
2723 const struct sockaddr
*addr
,
2724 enum swrap_packet_type type
,
2725 const void *buf
, size_t len
)
2727 const char *file_name
;
2729 size_t packet_len
= 0;
2732 file_name
= swrap_pcap_init_file();
2737 packet
= swrap_pcap_marshall_packet(si
,
2743 if (packet
== NULL
) {
2747 fd
= swrap_pcap_get_fd(file_name
);
2749 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2758 /****************************************************************************
2760 ***************************************************************************/
2762 #ifdef HAVE_SIGNALFD
2763 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2767 rc
= libc_signalfd(fd
, mask
, flags
);
2769 swrap_remove_stale(fd
);
2775 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2777 return swrap_signalfd(fd
, mask
, flags
);
2781 /****************************************************************************
2783 ***************************************************************************/
2785 static int swrap_socket(int family
, int type
, int protocol
)
2787 struct socket_info
*si
;
2788 struct socket_info_fd
*fi
;
2791 int real_type
= type
;
2794 * Remove possible addition flags passed to socket() so
2795 * do not fail checking the type.
2796 * See https://lwn.net/Articles/281965/
2799 real_type
&= ~SOCK_CLOEXEC
;
2801 #ifdef SOCK_NONBLOCK
2802 real_type
&= ~SOCK_NONBLOCK
;
2805 if (!socket_wrapper_enabled()) {
2806 return libc_socket(family
, type
, protocol
);
2817 #endif /* AF_NETLINK */
2820 #endif /* AF_PACKET */
2822 return libc_socket(family
, type
, protocol
);
2824 errno
= EAFNOSUPPORT
;
2828 switch (real_type
) {
2834 errno
= EPROTONOSUPPORT
;
2842 if (real_type
== SOCK_STREAM
) {
2847 if (real_type
== SOCK_DGRAM
) {
2852 errno
= EPROTONOSUPPORT
;
2857 * We must call libc_socket with type, from the caller, not the version
2858 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2860 fd
= libc_socket(AF_UNIX
, type
, 0);
2866 /* Check if we have a stale fd and remove it */
2867 swrap_remove_stale(fd
);
2869 idx
= socket_wrapper_first_free_index();
2877 si
->family
= family
;
2879 /* however, the rest of the socket_wrapper code expects just
2880 * the type, not the flags */
2881 si
->type
= real_type
;
2882 si
->protocol
= protocol
;
2885 * Setup myname so getsockname() can succeed to find out the socket
2888 switch(si
->family
) {
2890 struct sockaddr_in sin
= {
2891 .sin_family
= AF_INET
,
2894 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in
);
2895 memcpy(&si
->myname
.sa
.in
, &sin
, si
->myname
.sa_socklen
);
2899 struct sockaddr_in6 sin6
= {
2900 .sin6_family
= AF_INET6
,
2903 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in6
);
2904 memcpy(&si
->myname
.sa
.in6
, &sin6
, si
->myname
.sa_socklen
);
2912 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2919 first_free
= si
->next_free
;
2925 SWRAP_DLIST_ADD(socket_fds
, fi
);
2927 SWRAP_LOG(SWRAP_LOG_TRACE
,
2928 "Created %s socket for protocol %s",
2929 si
->family
== AF_INET
? "IPv4" : "IPv6",
2930 si
->type
== SOCK_DGRAM
? "UDP" : "TCP");
2935 int socket(int family
, int type
, int protocol
)
2937 return swrap_socket(family
, type
, protocol
);
2940 /****************************************************************************
2942 ***************************************************************************/
2944 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2948 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2950 swrap_remove_stale(sv
[0]);
2951 swrap_remove_stale(sv
[1]);
2957 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2959 return swrap_socketpair(family
, type
, protocol
, sv
);
2962 /****************************************************************************
2964 ***************************************************************************/
2966 #ifdef HAVE_TIMERFD_CREATE
2967 static int swrap_timerfd_create(int clockid
, int flags
)
2971 fd
= libc_timerfd_create(clockid
, flags
);
2973 swrap_remove_stale(fd
);
2979 int timerfd_create(int clockid
, int flags
)
2981 return swrap_timerfd_create(clockid
, flags
);
2985 /****************************************************************************
2987 ***************************************************************************/
2989 static int swrap_pipe(int pipefd
[2])
2993 rc
= libc_pipe(pipefd
);
2995 swrap_remove_stale(pipefd
[0]);
2996 swrap_remove_stale(pipefd
[1]);
3002 int pipe(int pipefd
[2])
3004 return swrap_pipe(pipefd
);
3007 /****************************************************************************
3009 ***************************************************************************/
3011 static int swrap_accept(int s
,
3012 struct sockaddr
*addr
,
3016 struct socket_info
*parent_si
, *child_si
;
3017 struct socket_info_fd
*child_fi
;
3020 struct swrap_address un_addr
= {
3021 .sa_socklen
= sizeof(struct sockaddr_un
),
3023 struct swrap_address un_my_addr
= {
3024 .sa_socklen
= sizeof(struct sockaddr_un
),
3026 struct swrap_address in_addr
= {
3027 .sa_socklen
= sizeof(struct sockaddr_storage
),
3029 struct swrap_address in_my_addr
= {
3030 .sa_socklen
= sizeof(struct sockaddr_storage
),
3034 parent_si
= find_socket_info(s
);
3037 return libc_accept4(s
, addr
, addrlen
, flags
);
3040 return libc_accept(s
, addr
, addrlen
);
3045 * assume out sockaddr have the same size as the in parent
3048 in_addr
.sa_socklen
= socket_length(parent_si
->family
);
3049 if (in_addr
.sa_socklen
<= 0) {
3055 ret
= libc_accept4(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
, flags
);
3058 ret
= libc_accept(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
);
3061 if (errno
== ENOTSOCK
) {
3062 /* Remove stale fds */
3063 swrap_remove_stale(s
);
3070 ret
= sockaddr_convert_from_un(parent_si
,
3075 &in_addr
.sa_socklen
);
3081 idx
= socket_wrapper_first_free_index();
3087 child_si
= &sockets
[idx
];
3089 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
3090 if (child_fi
== NULL
) {
3098 child_si
->family
= parent_si
->family
;
3099 child_si
->type
= parent_si
->type
;
3100 child_si
->protocol
= parent_si
->protocol
;
3101 child_si
->bound
= 1;
3102 child_si
->is_server
= 1;
3103 child_si
->connected
= 1;
3105 child_si
->peername
= (struct swrap_address
) {
3106 .sa_socklen
= in_addr
.sa_socklen
,
3108 memcpy(&child_si
->peername
.sa
.ss
, &in_addr
.sa
.ss
, in_addr
.sa_socklen
);
3110 if (addr
!= NULL
&& addrlen
!= NULL
) {
3111 size_t copy_len
= MIN(*addrlen
, in_addr
.sa_socklen
);
3113 memcpy(addr
, &in_addr
.sa
.ss
, copy_len
);
3115 *addrlen
= in_addr
.sa_socklen
;
3118 ret
= libc_getsockname(fd
,
3120 &un_my_addr
.sa_socklen
);
3127 ret
= sockaddr_convert_from_un(child_si
,
3129 un_my_addr
.sa_socklen
,
3132 &in_my_addr
.sa_socklen
);
3139 SWRAP_LOG(SWRAP_LOG_TRACE
,
3140 "accept() path=%s, fd=%d",
3141 un_my_addr
.sa
.un
.sun_path
, s
);
3143 child_si
->myname
= (struct swrap_address
) {
3144 .sa_socklen
= in_my_addr
.sa_socklen
,
3146 memcpy(&child_si
->myname
.sa
.ss
, &in_my_addr
.sa
.ss
, in_my_addr
.sa_socklen
);
3148 child_si
->refcount
= 1;
3149 first_free
= child_si
->next_free
;
3150 child_si
->next_free
= 0;
3152 child_fi
->si_index
= idx
;
3154 SWRAP_DLIST_ADD(socket_fds
, child_fi
);
3157 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
3158 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
3159 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
3166 int accept4(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
, int flags
)
3168 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
, flags
);
3172 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3173 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
3175 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
3178 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
, 0);
3181 static int autobind_start_init
;
3182 static int autobind_start
;
3184 /* using sendto() or connect() on an unbound socket would give the
3185 recipient no way to reply, as unlike UDP and TCP, a unix domain
3186 socket can't auto-assign ephemeral port numbers, so we need to
3188 Note: this might change the family from ipv6 to ipv4
3190 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
3192 struct swrap_address un_addr
= {
3193 .sa_socklen
= sizeof(struct sockaddr_un
),
3201 if (autobind_start_init
!= 1) {
3202 autobind_start_init
= 1;
3203 autobind_start
= getpid();
3204 autobind_start
%= 50000;
3205 autobind_start
+= 10000;
3208 un_addr
.sa
.un
.sun_family
= AF_UNIX
;
3212 struct sockaddr_in in
;
3216 type
= SOCKET_TYPE_CHAR_TCP
;
3219 type
= SOCKET_TYPE_CHAR_UDP
;
3222 errno
= ESOCKTNOSUPPORT
;
3227 memset(&in
, 0, sizeof(in
));
3228 in
.sin_family
= AF_INET
;
3229 in
.sin_addr
.s_addr
= htonl(127<<24 |
3230 socket_wrapper_default_iface());
3232 si
->myname
= (struct swrap_address
) {
3233 .sa_socklen
= sizeof(in
),
3235 memcpy(&si
->myname
.sa
.in
, &in
, si
->myname
.sa_socklen
);
3240 struct sockaddr_in6 in6
;
3242 if (si
->family
!= family
) {
3243 errno
= ENETUNREACH
;
3250 type
= SOCKET_TYPE_CHAR_TCP_V6
;
3253 type
= SOCKET_TYPE_CHAR_UDP_V6
;
3256 errno
= ESOCKTNOSUPPORT
;
3261 memset(&in6
, 0, sizeof(in6
));
3262 in6
.sin6_family
= AF_INET6
;
3263 in6
.sin6_addr
= *swrap_ipv6();
3264 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
3266 si
->myname
= (struct swrap_address
) {
3267 .sa_socklen
= sizeof(in6
),
3269 memcpy(&si
->myname
.sa
.in6
, &in6
, si
->myname
.sa_socklen
);
3274 errno
= ESOCKTNOSUPPORT
;
3279 if (autobind_start
> 60000) {
3280 autobind_start
= 10000;
3283 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
3284 port
= autobind_start
+ i
;
3285 snprintf(un_addr
.sa
.un
.sun_path
, sizeof(un_addr
.sa
.un
.sun_path
),
3286 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
3287 type
, socket_wrapper_default_iface(), port
);
3288 if (stat(un_addr
.sa
.un
.sun_path
, &st
) == 0) continue;
3290 ret
= libc_bind(fd
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
3295 si
->un_addr
= un_addr
.sa
.un
;
3298 autobind_start
= port
+ 1;
3301 if (i
== SOCKET_MAX_SOCKETS
) {
3302 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
3303 "interface "SOCKET_FORMAT
,
3306 socket_wrapper_default_iface(),
3313 si
->family
= family
;
3314 set_port(si
->family
, port
, &si
->myname
);
3322 /****************************************************************************
3324 ***************************************************************************/
3326 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
3330 struct swrap_address un_addr
= {
3331 .sa_socklen
= sizeof(struct sockaddr_un
),
3333 struct socket_info
*si
= find_socket_info(s
);
3337 return libc_connect(s
, serv_addr
, addrlen
);
3340 if (si
->bound
== 0) {
3341 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
3347 if (si
->family
!= serv_addr
->sa_family
) {
3353 ret
= sockaddr_convert_to_un(si
, serv_addr
,
3354 addrlen
, &un_addr
.sa
.un
, 0, &bcast
);
3360 errno
= ENETUNREACH
;
3365 if (si
->type
== SOCK_DGRAM
) {
3366 si
->defer_connect
= 1;
3369 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
3371 ret
= libc_connect(s
,
3373 un_addr
.sa_socklen
);
3376 SWRAP_LOG(SWRAP_LOG_TRACE
,
3377 "connect() path=%s, fd=%d",
3378 un_addr
.sa
.un
.sun_path
, s
);
3381 /* to give better errors */
3382 if (ret
== -1 && errno
== ENOENT
) {
3383 errno
= EHOSTUNREACH
;
3387 si
->peername
= (struct swrap_address
) {
3388 .sa_socklen
= addrlen
,
3391 memcpy(&si
->peername
.sa
.ss
, serv_addr
, addrlen
);
3395 * When we connect() on a socket than we have to bind the
3396 * outgoing connection on the interface we use for the
3397 * transport. We already bound it on the right interface
3398 * but here we have to update the name so getsockname()
3399 * returns correct information.
3401 if (si
->bindname
.sa_socklen
> 0) {
3402 si
->myname
= (struct swrap_address
) {
3403 .sa_socklen
= si
->bindname
.sa_socklen
,
3406 memcpy(&si
->myname
.sa
.ss
,
3407 &si
->bindname
.sa
.ss
,
3408 si
->bindname
.sa_socklen
);
3410 /* Cleanup bindname */
3411 si
->bindname
= (struct swrap_address
) {
3416 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
3417 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
3419 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
3426 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
3428 return swrap_connect(s
, serv_addr
, addrlen
);
3431 /****************************************************************************
3433 ***************************************************************************/
3435 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
3438 struct swrap_address un_addr
= {
3439 .sa_socklen
= sizeof(struct sockaddr_un
),
3441 struct socket_info
*si
= find_socket_info(s
);
3448 return libc_bind(s
, myaddr
, addrlen
);
3451 switch (si
->family
) {
3453 const struct sockaddr_in
*sin
;
3454 if (addrlen
< sizeof(struct sockaddr_in
)) {
3455 bind_error
= EINVAL
;
3459 sin
= (const struct sockaddr_in
*)(const void *)myaddr
;
3461 if (sin
->sin_family
!= AF_INET
) {
3462 bind_error
= EAFNOSUPPORT
;
3465 /* special case for AF_UNSPEC */
3466 if (sin
->sin_family
== AF_UNSPEC
&&
3467 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
3476 const struct sockaddr_in6
*sin6
;
3477 if (addrlen
< sizeof(struct sockaddr_in6
)) {
3478 bind_error
= EINVAL
;
3482 sin6
= (const struct sockaddr_in6
*)(const void *)myaddr
;
3484 if (sin6
->sin6_family
!= AF_INET6
) {
3485 bind_error
= EAFNOSUPPORT
;
3492 bind_error
= EINVAL
;
3496 if (bind_error
!= 0) {
3502 in_use
= check_addr_port_in_use(myaddr
, addrlen
);
3509 si
->myname
.sa_socklen
= addrlen
;
3510 memcpy(&si
->myname
.sa
.ss
, myaddr
, addrlen
);
3512 ret
= sockaddr_convert_to_un(si
,
3522 unlink(un_addr
.sa
.un
.sun_path
);
3524 ret
= libc_bind(s
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
3526 SWRAP_LOG(SWRAP_LOG_TRACE
,
3527 "bind() path=%s, fd=%d",
3528 un_addr
.sa
.un
.sun_path
, s
);
3537 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
3539 return swrap_bind(s
, myaddr
, addrlen
);
3542 /****************************************************************************
3544 ***************************************************************************/
3546 #ifdef HAVE_BINDRESVPORT
3547 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
3549 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
3551 struct swrap_address myaddr
= {
3552 .sa_socklen
= sizeof(struct sockaddr_storage
),
3555 static uint16_t port
;
3560 #define SWRAP_STARTPORT 600
3561 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3562 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3565 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
3569 salen
= myaddr
.sa_socklen
;
3572 rc
= swrap_getsockname(sd
, &myaddr
.sa
.s
, &salen
);
3578 memset(&myaddr
.sa
.ss
, 0, salen
);
3583 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
3586 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)(void *)sa
;
3588 salen
= sizeof(struct sockaddr_in
);
3589 sinp
->sin_port
= htons(port
);
3593 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)(void *)sa
;
3595 salen
= sizeof(struct sockaddr_in6
);
3596 sin6p
->sin6_port
= htons(port
);
3600 errno
= EAFNOSUPPORT
;
3605 if (port
> SWRAP_ENDPORT
) {
3606 port
= SWRAP_STARTPORT
;
3609 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
3610 if (rc
== 0 || errno
!= EADDRINUSE
) {
3618 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
3620 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
3624 /****************************************************************************
3626 ***************************************************************************/
3628 static int swrap_listen(int s
, int backlog
)
3631 struct socket_info
*si
= find_socket_info(s
);
3634 return libc_listen(s
, backlog
);
3637 if (si
->bound
== 0) {
3638 ret
= swrap_auto_bind(s
, si
, si
->family
);
3645 ret
= libc_listen(s
, backlog
);
3650 int listen(int s
, int backlog
)
3652 return swrap_listen(s
, backlog
);
3655 /****************************************************************************
3657 ***************************************************************************/
3659 static FILE *swrap_fopen(const char *name
, const char *mode
)
3663 fp
= libc_fopen(name
, mode
);
3665 int fd
= fileno(fp
);
3667 swrap_remove_stale(fd
);
3673 FILE *fopen(const char *name
, const char *mode
)
3675 return swrap_fopen(name
, mode
);
3678 /****************************************************************************
3680 ***************************************************************************/
3683 static FILE *swrap_fopen64(const char *name
, const char *mode
)
3687 fp
= libc_fopen64(name
, mode
);
3689 int fd
= fileno(fp
);
3691 swrap_remove_stale(fd
);
3697 FILE *fopen64(const char *name
, const char *mode
)
3699 return swrap_fopen64(name
, mode
);
3701 #endif /* HAVE_FOPEN64 */
3703 /****************************************************************************
3705 ***************************************************************************/
3707 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
3711 ret
= libc_vopen(pathname
, flags
, ap
);
3714 * There are methods for closing descriptors (libc-internal code
3715 * paths, direct syscalls) which close descriptors in ways that
3716 * we can't intercept, so try to recover when we notice that
3719 swrap_remove_stale(ret
);
3724 int open(const char *pathname
, int flags
, ...)
3729 va_start(ap
, flags
);
3730 fd
= swrap_vopen(pathname
, flags
, ap
);
3736 /****************************************************************************
3738 ***************************************************************************/
3741 static int swrap_vopen64(const char *pathname
, int flags
, va_list ap
)
3745 ret
= libc_vopen64(pathname
, flags
, ap
);
3748 * There are methods for closing descriptors (libc-internal code
3749 * paths, direct syscalls) which close descriptors in ways that
3750 * we can't intercept, so try to recover when we notice that
3753 swrap_remove_stale(ret
);
3758 int open64(const char *pathname
, int flags
, ...)
3763 va_start(ap
, flags
);
3764 fd
= swrap_vopen64(pathname
, flags
, ap
);
3769 #endif /* HAVE_OPEN64 */
3771 /****************************************************************************
3773 ***************************************************************************/
3775 static int swrap_vopenat(int dirfd
, const char *path
, int flags
, va_list ap
)
3779 ret
= libc_vopenat(dirfd
, path
, flags
, ap
);
3782 * There are methods for closing descriptors (libc-internal code
3783 * paths, direct syscalls) which close descriptors in ways that
3784 * we can't intercept, so try to recover when we notice that
3787 swrap_remove_stale(ret
);
3793 int openat(int dirfd
, const char *path
, int flags
, ...)
3798 va_start(ap
, flags
);
3799 fd
= swrap_vopenat(dirfd
, path
, flags
, ap
);
3805 /****************************************************************************
3807 ***************************************************************************/
3809 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3811 struct socket_info
*si
= find_socket_info(s
);
3815 return libc_getpeername(s
, name
, addrlen
);
3818 if (si
->peername
.sa_socklen
== 0)
3824 len
= MIN(*addrlen
, si
->peername
.sa_socklen
);
3829 memcpy(name
, &si
->peername
.sa
.ss
, len
);
3830 *addrlen
= si
->peername
.sa_socklen
;
3835 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3836 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3838 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3841 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
3844 /****************************************************************************
3846 ***************************************************************************/
3848 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3850 struct socket_info
*si
= find_socket_info(s
);
3854 return libc_getsockname(s
, name
, addrlen
);
3857 len
= MIN(*addrlen
, si
->myname
.sa_socklen
);
3862 memcpy(name
, &si
->myname
.sa
.ss
, len
);
3863 *addrlen
= si
->myname
.sa_socklen
;
3868 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3869 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3871 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3874 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
3877 /****************************************************************************
3879 ***************************************************************************/
3882 # ifdef SO_PROTOTYPE /* The Solaris name */
3883 # define SO_PROTOCOL SO_PROTOTYPE
3884 # endif /* SO_PROTOTYPE */
3885 #endif /* SO_PROTOCOL */
3887 static int swrap_getsockopt(int s
, int level
, int optname
,
3888 void *optval
, socklen_t
*optlen
)
3890 struct socket_info
*si
= find_socket_info(s
);
3894 return libc_getsockopt(s
,
3901 if (level
== SOL_SOCKET
) {
3905 if (optval
== NULL
|| optlen
== NULL
||
3906 *optlen
< (socklen_t
)sizeof(int)) {
3912 *optlen
= sizeof(int);
3913 *(int *)optval
= si
->family
;
3916 #endif /* SO_DOMAIN */
3920 if (optval
== NULL
|| optlen
== NULL
||
3921 *optlen
< (socklen_t
)sizeof(int)) {
3927 *optlen
= sizeof(int);
3928 *(int *)optval
= si
->protocol
;
3931 #endif /* SO_PROTOCOL */
3933 if (optval
== NULL
|| optlen
== NULL
||
3934 *optlen
< (socklen_t
)sizeof(int)) {
3940 *optlen
= sizeof(int);
3941 *(int *)optval
= si
->type
;
3945 ret
= libc_getsockopt(s
,
3952 } else if (level
== IPPROTO_TCP
) {
3957 * This enables sending packets directly out over TCP.
3958 * As a unix socket is doing that any way, report it as
3961 if (optval
== NULL
|| optlen
== NULL
||
3962 *optlen
< (socklen_t
)sizeof(int)) {
3968 *optlen
= sizeof(int);
3969 *(int *)optval
= si
->tcp_nodelay
;
3973 #endif /* TCP_NODELAY */
3979 errno
= ENOPROTOOPT
;
3986 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3987 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
3989 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
3992 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
3995 /****************************************************************************
3997 ***************************************************************************/
3999 static int swrap_setsockopt(int s
, int level
, int optname
,
4000 const void *optval
, socklen_t optlen
)
4002 struct socket_info
*si
= find_socket_info(s
);
4006 return libc_setsockopt(s
,
4013 if (level
== SOL_SOCKET
) {
4014 return libc_setsockopt(s
,
4019 } else if (level
== IPPROTO_TCP
) {
4026 * This enables sending packets directly out over TCP.
4027 * A unix socket is doing that any way.
4029 if (optval
== NULL
|| optlen
== 0 ||
4030 optlen
< (socklen_t
)sizeof(int)) {
4036 i
= *discard_const_p(int, optval
);
4037 if (i
!= 0 && i
!= 1) {
4042 si
->tcp_nodelay
= i
;
4047 #endif /* TCP_NODELAY */
4053 switch (si
->family
) {
4055 if (level
== IPPROTO_IP
) {
4057 if (optname
== IP_PKTINFO
) {
4058 si
->pktinfo
= AF_INET
;
4060 #endif /* IP_PKTINFO */
4066 if (level
== IPPROTO_IPV6
) {
4067 #ifdef IPV6_RECVPKTINFO
4068 if (optname
== IPV6_RECVPKTINFO
) {
4069 si
->pktinfo
= AF_INET6
;
4071 #endif /* IPV6_PKTINFO */
4077 errno
= ENOPROTOOPT
;
4086 int setsockopt(int s
, int level
, int optname
,
4087 const void *optval
, socklen_t optlen
)
4089 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
4092 /****************************************************************************
4094 ***************************************************************************/
4096 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
4098 struct socket_info
*si
= find_socket_info(s
);
4104 return libc_vioctl(s
, r
, va
);
4109 rc
= libc_vioctl(s
, r
, va
);
4113 value
= *((int *)va_arg(ap
, int *));
4115 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
4116 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
4117 } else if (value
== 0) { /* END OF FILE */
4118 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
4128 #ifdef HAVE_IOCTL_INT
4129 int ioctl(int s
, int r
, ...)
4131 int ioctl(int s
, unsigned long int r
, ...)
4139 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
4150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4153 # ifdef _ALIGN /* BSD */
4154 #define CMSG_ALIGN _ALIGN
4156 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4157 # endif /* _ALIGN */
4158 #endif /* CMSG_ALIGN */
4161 * @brief Add a cmsghdr to a msghdr.
4163 * This is an function to add any type of cmsghdr. It will operate on the
4164 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4165 * the buffer position after the added cmsg element. Hence, this function is
4166 * intended to be used with an intermediate msghdr and not on the original
4167 * one handed in by the client.
4169 * @param[in] msg The msghdr to which to add the cmsg.
4171 * @param[in] level The cmsg level to set.
4173 * @param[in] type The cmsg type to set.
4175 * @param[in] data The cmsg data to set.
4177 * @param[in] len the length of the data to set.
4179 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
4185 size_t cmlen
= CMSG_LEN(len
);
4186 size_t cmspace
= CMSG_SPACE(len
);
4187 uint8_t cmbuf
[cmspace
];
4188 void *cast_ptr
= (void *)cmbuf
;
4189 struct cmsghdr
*cm
= (struct cmsghdr
*)cast_ptr
;
4192 memset(cmbuf
, 0, cmspace
);
4194 if (msg
->msg_controllen
< cmlen
) {
4195 cmlen
= msg
->msg_controllen
;
4196 msg
->msg_flags
|= MSG_CTRUNC
;
4199 if (msg
->msg_controllen
< cmspace
) {
4200 cmspace
= msg
->msg_controllen
;
4204 * We copy the full input data into an intermediate cmsghdr first
4205 * in order to more easily cope with truncation.
4207 cm
->cmsg_len
= cmlen
;
4208 cm
->cmsg_level
= level
;
4209 cm
->cmsg_type
= type
;
4210 memcpy(CMSG_DATA(cm
), data
, len
);
4213 * We now copy the possibly truncated buffer.
4214 * We copy cmlen bytes, but consume cmspace bytes,
4215 * leaving the possible padding uninitialiazed.
4217 p
= (uint8_t *)msg
->msg_control
;
4218 memcpy(p
, cm
, cmlen
);
4220 msg
->msg_control
= p
;
4221 msg
->msg_controllen
-= cmspace
;
4226 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
4229 /* Add packet info */
4230 switch (si
->pktinfo
) {
4231 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4233 struct sockaddr_in
*sin
;
4234 #if defined(HAVE_STRUCT_IN_PKTINFO)
4235 struct in_pktinfo pkt
;
4236 #elif defined(IP_RECVDSTADDR)
4240 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in
)) {
4241 sin
= &si
->bindname
.sa
.in
;
4243 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in
)) {
4246 sin
= &si
->myname
.sa
.in
;
4251 #if defined(HAVE_STRUCT_IN_PKTINFO)
4252 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
4253 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
4254 #elif defined(IP_RECVDSTADDR)
4255 pkt
= sin
->sin_addr
;
4258 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
4263 #endif /* IP_PKTINFO */
4264 #if defined(HAVE_IPV6)
4266 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4267 struct sockaddr_in6
*sin6
;
4268 struct in6_pktinfo pkt6
;
4270 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in6
)) {
4271 sin6
= &si
->bindname
.sa
.in6
;
4273 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in6
)) {
4276 sin6
= &si
->myname
.sa
.in6
;
4281 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
4282 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
4284 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
4285 &pkt6
, sizeof(pkt6
));
4286 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4290 #endif /* IPV6_PKTINFO */
4298 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
4299 struct msghdr
*omsg
)
4303 if (si
->pktinfo
> 0) {
4304 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
4310 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
4312 size_t *cm_data_space
);
4313 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
4315 size_t *cm_data_space
);
4317 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
4319 size_t *cm_data_space
) {
4320 struct cmsghdr
*cmsg
;
4324 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
4328 for (cmsg
= CMSG_FIRSTHDR(msg
);
4330 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
4331 switch (cmsg
->cmsg_level
) {
4333 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
4338 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
4348 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
4350 size_t *cm_data_space
)
4355 cmspace
= *cm_data_space
+ CMSG_ALIGN(cmsg
->cmsg_len
);
4357 p
= realloc((*cm_data
), cmspace
);
4363 p
= (*cm_data
) + (*cm_data_space
);
4364 *cm_data_space
= cmspace
;
4366 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
4371 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
4373 size_t *cm_data_space
);
4376 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
4378 size_t *cm_data_space
)
4382 switch(cmsg
->cmsg_type
) {
4385 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
4392 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
4404 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
4406 size_t *cm_data_space
)
4408 (void)cmsg
; /* unused */
4409 (void)cm_data
; /* unused */
4410 (void)cm_data_space
; /* unused */
4413 * Passing a IP pktinfo to a unix socket might be rejected by the
4414 * Kernel, at least on FreeBSD. So skip this cmsg.
4418 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4420 static ssize_t
swrap_sendmsg_before(int fd
,
4421 struct socket_info
*si
,
4423 struct iovec
*tmp_iov
,
4424 struct sockaddr_un
*tmp_un
,
4425 const struct sockaddr_un
**to_un
,
4426 const struct sockaddr
**to
,
4446 if (!si
->connected
) {
4451 if (msg
->msg_iovlen
== 0) {
4455 mtu
= socket_wrapper_mtu();
4456 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4458 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
4463 msg
->msg_iovlen
= i
;
4464 if (msg
->msg_iovlen
== 0) {
4465 *tmp_iov
= msg
->msg_iov
[0];
4466 tmp_iov
->iov_len
= MIN((size_t)tmp_iov
->iov_len
,
4468 msg
->msg_iov
= tmp_iov
;
4469 msg
->msg_iovlen
= 1;
4474 if (si
->connected
) {
4475 if (msg
->msg_name
!= NULL
) {
4477 * We are dealing with unix sockets and if we
4478 * are connected, we should only talk to the
4479 * connected unix path. Using the fd to send
4480 * to another server would be hard to achieve.
4482 msg
->msg_name
= NULL
;
4483 msg
->msg_namelen
= 0;
4486 const struct sockaddr
*msg_name
;
4487 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
4489 if (msg_name
== NULL
) {
4495 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
4507 msg
->msg_name
= tmp_un
;
4508 msg
->msg_namelen
= sizeof(*tmp_un
);
4511 if (si
->bound
== 0) {
4512 ret
= swrap_auto_bind(fd
, si
, si
->family
);
4514 if (errno
== ENOTSOCK
) {
4515 swrap_remove_stale(fd
);
4518 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
4524 if (!si
->defer_connect
) {
4528 ret
= sockaddr_convert_to_un(si
,
4530 si
->peername
.sa_socklen
,
4538 ret
= libc_connect(fd
,
4539 (struct sockaddr
*)(void *)tmp_un
,
4542 /* to give better errors */
4543 if (ret
== -1 && errno
== ENOENT
) {
4544 errno
= EHOSTUNREACH
;
4551 si
->defer_connect
= 0;
4554 errno
= EHOSTUNREACH
;
4558 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4559 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
4560 uint8_t *cmbuf
= NULL
;
4563 ret
= swrap_sendmsg_filter_cmsghdr(msg
, &cmbuf
, &cmlen
);
4570 msg
->msg_controllen
= 0;
4571 msg
->msg_control
= NULL
;
4572 } else if (cmlen
< msg
->msg_controllen
&& cmbuf
!= NULL
) {
4573 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
4574 msg
->msg_controllen
= cmlen
;
4583 static void swrap_sendmsg_after(int fd
,
4584 struct socket_info
*si
,
4586 const struct sockaddr
*to
,
4589 int saved_errno
= errno
;
4596 /* to give better errors */
4598 if (saved_errno
== ENOENT
) {
4599 saved_errno
= EHOSTUNREACH
;
4600 } else if (saved_errno
== ENOTSOCK
) {
4601 /* If the fd is not a socket, remove it */
4602 swrap_remove_stale(fd
);
4606 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4607 avail
+= msg
->msg_iov
[i
].iov_len
;
4611 remain
= MIN(80, avail
);
4616 /* we capture it as one single packet */
4617 buf
= (uint8_t *)malloc(remain
);
4619 /* we just not capture the packet */
4620 errno
= saved_errno
;
4624 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4625 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
4627 msg
->msg_iov
[i
].iov_base
,
4630 remain
-= this_time
;
4637 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
4638 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
4640 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
4645 if (si
->connected
) {
4646 to
= &si
->peername
.sa
.s
;
4649 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4650 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
4652 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4658 errno
= saved_errno
;
4661 static int swrap_recvmsg_before(int fd
,
4662 struct socket_info
*si
,
4664 struct iovec
*tmp_iov
)
4669 (void)fd
; /* unused */
4674 if (!si
->connected
) {
4679 if (msg
->msg_iovlen
== 0) {
4683 mtu
= socket_wrapper_mtu();
4684 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4686 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
4691 msg
->msg_iovlen
= i
;
4692 if (msg
->msg_iovlen
== 0) {
4693 *tmp_iov
= msg
->msg_iov
[0];
4694 tmp_iov
->iov_len
= MIN((size_t)tmp_iov
->iov_len
,
4696 msg
->msg_iov
= tmp_iov
;
4697 msg
->msg_iovlen
= 1;
4702 if (msg
->msg_name
== NULL
) {
4707 if (msg
->msg_iovlen
== 0) {
4711 if (si
->bound
== 0) {
4712 ret
= swrap_auto_bind(fd
, si
, si
->family
);
4715 * When attempting to read or write to a
4716 * descriptor, if an underlying autobind fails
4717 * because it's not a socket, stop intercepting
4718 * uses of that descriptor.
4720 if (errno
== ENOTSOCK
) {
4721 swrap_remove_stale(fd
);
4724 SWRAP_LOG(SWRAP_LOG_ERROR
,
4725 "swrap_recvmsg_before failed");
4732 errno
= EHOSTUNREACH
;
4739 static int swrap_recvmsg_after(int fd
,
4740 struct socket_info
*si
,
4742 const struct sockaddr_un
*un_addr
,
4743 socklen_t un_addrlen
,
4746 int saved_errno
= errno
;
4748 uint8_t *buf
= NULL
;
4754 /* to give better errors */
4756 if (saved_errno
== ENOENT
) {
4757 saved_errno
= EHOSTUNREACH
;
4758 } else if (saved_errno
== ENOTSOCK
) {
4759 /* If the fd is not a socket, remove it */
4760 swrap_remove_stale(fd
);
4764 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4765 avail
+= msg
->msg_iov
[i
].iov_len
;
4768 /* Convert the socket address before we leave */
4769 if (si
->type
== SOCK_DGRAM
&& un_addr
!= NULL
) {
4770 rc
= sockaddr_convert_from_un(si
,
4787 remain
= MIN(80, avail
);
4792 /* we capture it as one single packet */
4793 buf
= (uint8_t *)malloc(remain
);
4795 /* we just not capture the packet */
4796 errno
= saved_errno
;
4800 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4801 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
4803 msg
->msg_iov
[i
].iov_base
,
4806 remain
-= this_time
;
4811 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
4812 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4813 } else if (ret
== 0) { /* END OF FILE */
4814 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4815 } else if (ret
> 0) {
4816 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
4825 if (un_addr
!= NULL
) {
4826 swrap_pcap_dump_packet(si
,
4832 swrap_pcap_dump_packet(si
,
4845 errno
= saved_errno
;
4847 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4849 msg
->msg_controllen
> 0 &&
4850 msg
->msg_control
!= NULL
) {
4851 rc
= swrap_msghdr_add_socket_info(si
, msg
);
4861 /****************************************************************************
4863 ***************************************************************************/
4865 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
4866 struct sockaddr
*from
, socklen_t
*fromlen
)
4868 struct swrap_address from_addr
= {
4869 .sa_socklen
= sizeof(struct sockaddr_un
),
4872 struct socket_info
*si
= find_socket_info(s
);
4873 struct swrap_address saddr
= {
4874 .sa_socklen
= sizeof(struct sockaddr_storage
),
4881 return libc_recvfrom(s
,
4893 if (from
!= NULL
&& fromlen
!= NULL
) {
4894 msg
.msg_name
= from
; /* optional address */
4895 msg
.msg_namelen
= *fromlen
; /* size of address */
4897 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4898 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4900 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4901 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4902 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4903 msg
.msg_control
= NULL
; /* ancillary data, see below */
4904 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4905 msg
.msg_flags
= 0; /* flags on received message */
4908 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4913 buf
= msg
.msg_iov
[0].iov_base
;
4914 len
= msg
.msg_iov
[0].iov_len
;
4916 ret
= libc_recvfrom(s
,
4921 &from_addr
.sa_socklen
);
4926 tret
= swrap_recvmsg_after(s
,
4930 from_addr
.sa_socklen
,
4936 if (from
!= NULL
&& fromlen
!= NULL
) {
4937 *fromlen
= msg
.msg_namelen
;
4943 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4944 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4945 struct sockaddr
*from
, Psocklen_t fromlen
)
4947 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4948 struct sockaddr
*from
, socklen_t
*fromlen
)
4951 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
4954 /****************************************************************************
4956 ***************************************************************************/
4958 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
4959 const struct sockaddr
*to
, socklen_t tolen
)
4963 struct swrap_address un_addr
= {
4964 .sa_socklen
= sizeof(struct sockaddr_un
),
4966 const struct sockaddr_un
*to_un
= NULL
;
4969 struct socket_info
*si
= find_socket_info(s
);
4973 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
4976 tmp
.iov_base
= discard_const_p(char, buf
);
4980 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
4981 msg
.msg_namelen
= tolen
; /* size of address */
4982 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4983 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4984 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4985 msg
.msg_control
= NULL
; /* ancillary data, see below */
4986 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4987 msg
.msg_flags
= 0; /* flags on received message */
4990 rc
= swrap_sendmsg_before(s
,
5002 buf
= msg
.msg_iov
[0].iov_base
;
5003 len
= msg
.msg_iov
[0].iov_len
;
5008 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
5011 type
= SOCKET_TYPE_CHAR_UDP
;
5013 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
5014 snprintf(un_addr
.sa
.un
.sun_path
,
5015 sizeof(un_addr
.sa
.un
.sun_path
),
5017 socket_wrapper_dir(), type
, iface
, prt
);
5018 if (stat(un_addr
.sa
.un
.sun_path
, &st
) != 0) continue;
5020 /* ignore the any errors in broadcast sends */
5026 un_addr
.sa_socklen
);
5029 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
5035 * If it is a dgram socket and we are connected, don't include the
5038 if (si
->type
== SOCK_DGRAM
&& si
->connected
) {
5039 ret
= libc_sendto(s
,
5046 ret
= libc_sendto(s
,
5050 (struct sockaddr
*)msg
.msg_name
,
5054 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
5059 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
5060 const struct sockaddr
*to
, socklen_t tolen
)
5062 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
5065 /****************************************************************************
5067 ***************************************************************************/
5069 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
5071 struct socket_info
*si
;
5073 struct swrap_address saddr
= {
5074 .sa_socklen
= sizeof(struct sockaddr_storage
),
5080 si
= find_socket_info(s
);
5082 return libc_recv(s
, buf
, len
, flags
);
5089 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
5090 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
5091 msg
.msg_iov
= &tmp
; /* scatter/gather array */
5092 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
5093 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5094 msg
.msg_control
= NULL
; /* ancillary data, see below */
5095 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5096 msg
.msg_flags
= 0; /* flags on received message */
5099 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
5104 buf
= msg
.msg_iov
[0].iov_base
;
5105 len
= msg
.msg_iov
[0].iov_len
;
5107 ret
= libc_recv(s
, buf
, len
, flags
);
5109 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
5117 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
5119 return swrap_recv(s
, buf
, len
, flags
);
5122 /****************************************************************************
5124 ***************************************************************************/
5126 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
5128 struct socket_info
*si
;
5131 struct swrap_address saddr
= {
5132 .sa_socklen
= sizeof(struct sockaddr_storage
),
5137 si
= find_socket_info(s
);
5139 return libc_read(s
, buf
, len
);
5146 msg
.msg_name
= &saddr
.sa
.ss
; /* optional address */
5147 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
5148 msg
.msg_iov
= &tmp
; /* scatter/gather array */
5149 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
5150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5151 msg
.msg_control
= NULL
; /* ancillary data, see below */
5152 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5153 msg
.msg_flags
= 0; /* flags on received message */
5156 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
5158 if (tret
== -ENOTSOCK
) {
5159 return libc_read(s
, buf
, len
);
5164 buf
= msg
.msg_iov
[0].iov_base
;
5165 len
= msg
.msg_iov
[0].iov_len
;
5167 ret
= libc_read(s
, buf
, len
);
5169 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
5177 ssize_t
read(int s
, void *buf
, size_t len
)
5179 return swrap_read(s
, buf
, len
);
5182 /****************************************************************************
5184 ***************************************************************************/
5186 static ssize_t
swrap_write(int s
, const void *buf
, size_t len
)
5190 struct sockaddr_un un_addr
;
5193 struct socket_info
*si
;
5195 si
= find_socket_info(s
);
5197 return libc_write(s
, buf
, len
);
5200 tmp
.iov_base
= discard_const_p(char, buf
);
5204 msg
.msg_name
= NULL
; /* optional address */
5205 msg
.msg_namelen
= 0; /* size of address */
5206 msg
.msg_iov
= &tmp
; /* scatter/gather array */
5207 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
5208 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5209 msg
.msg_control
= NULL
; /* ancillary data, see below */
5210 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5211 msg
.msg_flags
= 0; /* flags on received message */
5214 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
5219 buf
= msg
.msg_iov
[0].iov_base
;
5220 len
= msg
.msg_iov
[0].iov_len
;
5222 ret
= libc_write(s
, buf
, len
);
5224 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
5229 ssize_t
write(int s
, const void *buf
, size_t len
)
5231 return swrap_write(s
, buf
, len
);
5234 /****************************************************************************
5236 ***************************************************************************/
5238 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
5242 struct sockaddr_un un_addr
;
5245 struct socket_info
*si
= find_socket_info(s
);
5248 return libc_send(s
, buf
, len
, flags
);
5251 tmp
.iov_base
= discard_const_p(char, buf
);
5255 msg
.msg_name
= NULL
; /* optional address */
5256 msg
.msg_namelen
= 0; /* size of address */
5257 msg
.msg_iov
= &tmp
; /* scatter/gather array */
5258 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
5259 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5260 msg
.msg_control
= NULL
; /* ancillary data, see below */
5261 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5262 msg
.msg_flags
= 0; /* flags on received message */
5265 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
5270 buf
= msg
.msg_iov
[0].iov_base
;
5271 len
= msg
.msg_iov
[0].iov_len
;
5273 ret
= libc_send(s
, buf
, len
, flags
);
5275 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
5280 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
5282 return swrap_send(s
, buf
, len
, flags
);
5285 /****************************************************************************
5287 ***************************************************************************/
5289 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
5291 struct swrap_address from_addr
= {
5292 .sa_socklen
= sizeof(struct sockaddr_un
),
5294 struct swrap_address convert_addr
= {
5295 .sa_socklen
= sizeof(struct sockaddr_storage
),
5297 struct socket_info
*si
;
5300 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5301 size_t msg_ctrllen_filled
;
5302 size_t msg_ctrllen_left
;
5308 si
= find_socket_info(s
);
5310 return libc_recvmsg(s
, omsg
, flags
);
5313 tmp
.iov_base
= NULL
;
5317 msg
.msg_name
= &from_addr
.sa
; /* optional address */
5318 msg
.msg_namelen
= from_addr
.sa_socklen
; /* size of address */
5319 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
5320 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
5321 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5322 msg_ctrllen_filled
= 0;
5323 msg_ctrllen_left
= omsg
->msg_controllen
;
5325 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
5326 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
5327 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
5330 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
5335 ret
= libc_recvmsg(s
, &msg
, flags
);
5337 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5338 msg_ctrllen_filled
+= msg
.msg_controllen
;
5339 msg_ctrllen_left
-= msg
.msg_controllen
;
5341 if (omsg
->msg_control
!= NULL
) {
5344 p
= omsg
->msg_control
;
5345 p
+= msg_ctrllen_filled
;
5347 msg
.msg_control
= p
;
5348 msg
.msg_controllen
= msg_ctrllen_left
;
5350 msg
.msg_control
= NULL
;
5351 msg
.msg_controllen
= 0;
5356 * We convert the unix address to a IP address so we need a buffer
5357 * which can store the address in case of SOCK_DGRAM, see below.
5359 msg
.msg_name
= &convert_addr
.sa
;
5360 msg
.msg_namelen
= convert_addr
.sa_socklen
;
5362 rc
= swrap_recvmsg_after(s
,
5366 from_addr
.sa_socklen
,
5372 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5373 if (omsg
->msg_control
!= NULL
) {
5374 /* msg.msg_controllen = space left */
5375 msg_ctrllen_left
= msg
.msg_controllen
;
5376 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
5379 /* Update the original message length */
5380 omsg
->msg_controllen
= msg_ctrllen_filled
;
5381 omsg
->msg_flags
= msg
.msg_flags
;
5383 omsg
->msg_iovlen
= msg
.msg_iovlen
;
5388 * The msg_name field points to a caller-allocated buffer that is
5389 * used to return the source address if the socket is unconnected. The
5390 * caller should set msg_namelen to the size of this buffer before this
5391 * call; upon return from a successful call, msg_name will contain the
5392 * length of the returned address. If the application does not need
5393 * to know the source address, msg_name can be specified as NULL.
5395 if (si
->type
== SOCK_STREAM
) {
5396 omsg
->msg_namelen
= 0;
5397 } else if (omsg
->msg_name
!= NULL
&&
5398 omsg
->msg_namelen
!= 0 &&
5399 omsg
->msg_namelen
>= msg
.msg_namelen
) {
5400 memcpy(omsg
->msg_name
, msg
.msg_name
, msg
.msg_namelen
);
5401 omsg
->msg_namelen
= msg
.msg_namelen
;
5407 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
5409 return swrap_recvmsg(sockfd
, msg
, flags
);
5412 /****************************************************************************
5414 ***************************************************************************/
5416 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
5420 struct sockaddr_un un_addr
;
5421 const struct sockaddr_un
*to_un
= NULL
;
5422 const struct sockaddr
*to
= NULL
;
5425 struct socket_info
*si
= find_socket_info(s
);
5429 return libc_sendmsg(s
, omsg
, flags
);
5432 ZERO_STRUCT(un_addr
);
5434 tmp
.iov_base
= NULL
;
5439 if (si
->connected
== 0) {
5440 msg
.msg_name
= omsg
->msg_name
; /* optional address */
5441 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
5443 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
5444 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
5445 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5446 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
5447 /* omsg is a const so use a local buffer for modifications */
5448 uint8_t cmbuf
[omsg
->msg_controllen
];
5450 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
5452 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
5453 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
5455 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
5458 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
5466 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
5474 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
5475 avail
+= msg
.msg_iov
[i
].iov_len
;
5481 /* we capture it as one single packet */
5482 buf
= (uint8_t *)malloc(remain
);
5487 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
5488 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
5490 msg
.msg_iov
[i
].iov_base
,
5493 remain
-= this_time
;
5496 type
= SOCKET_TYPE_CHAR_UDP
;
5498 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
5499 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
5500 socket_wrapper_dir(), type
, iface
, prt
);
5501 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
5503 msg
.msg_name
= &un_addr
; /* optional address */
5504 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
5506 /* ignore the any errors in broadcast sends */
5507 libc_sendmsg(s
, &msg
, flags
);
5510 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
5516 ret
= libc_sendmsg(s
, &msg
, flags
);
5518 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
5523 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
5525 return swrap_sendmsg(s
, omsg
, flags
);
5528 /****************************************************************************
5530 ***************************************************************************/
5532 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
5534 struct socket_info
*si
;
5537 struct swrap_address saddr
= {
5538 .sa_socklen
= sizeof(struct sockaddr_storage
)
5543 si
= find_socket_info(s
);
5545 return libc_readv(s
, vector
, count
);
5548 tmp
.iov_base
= NULL
;
5552 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
5553 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
5554 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
5555 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
5556 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5557 msg
.msg_control
= NULL
; /* ancillary data, see below */
5558 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5559 msg
.msg_flags
= 0; /* flags on received message */
5562 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
5564 if (rc
== -ENOTSOCK
) {
5565 return libc_readv(s
, vector
, count
);
5570 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
5572 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
5580 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
5582 return swrap_readv(s
, vector
, count
);
5585 /****************************************************************************
5587 ***************************************************************************/
5589 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
5593 struct sockaddr_un un_addr
;
5596 struct socket_info
*si
= find_socket_info(s
);
5599 return libc_writev(s
, vector
, count
);
5602 tmp
.iov_base
= NULL
;
5606 msg
.msg_name
= NULL
; /* optional address */
5607 msg
.msg_namelen
= 0; /* size of address */
5608 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
5609 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
5610 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5611 msg
.msg_control
= NULL
; /* ancillary data, see below */
5612 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5613 msg
.msg_flags
= 0; /* flags on received message */
5616 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
5618 if (rc
== -ENOTSOCK
) {
5619 return libc_readv(s
, vector
, count
);
5624 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
5626 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
5631 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
5633 return swrap_writev(s
, vector
, count
);
5636 /****************************
5638 ***************************/
5640 static int swrap_close(int fd
)
5642 struct socket_info_fd
*fi
= find_socket_info_fd(fd
);
5643 struct socket_info
*si
= NULL
;
5648 return libc_close(fd
);
5651 si_index
= fi
->si_index
;
5653 SWRAP_DLIST_REMOVE(socket_fds
, fi
);
5656 ret
= libc_close(fd
);
5658 si
= &sockets
[si_index
];
5661 if (si
->refcount
> 0) {
5662 /* there are still references left */
5666 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
5667 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
5670 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
5671 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
5672 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
5675 if (si
->un_addr
.sun_path
[0] != '\0') {
5676 unlink(si
->un_addr
.sun_path
);
5679 si
->next_free
= first_free
;
5680 first_free
= si_index
;
5687 return swrap_close(fd
);
5690 /****************************
5692 ***************************/
5694 static int swrap_dup(int fd
)
5696 struct socket_info
*si
;
5697 struct socket_info_fd
*src_fi
, *fi
;
5699 src_fi
= find_socket_info_fd(fd
);
5700 if (src_fi
== NULL
) {
5701 return libc_dup(fd
);
5704 si
= &sockets
[src_fi
->si_index
];
5706 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
5712 fi
->fd
= libc_dup(fd
);
5714 int saved_errno
= errno
;
5716 errno
= saved_errno
;
5721 fi
->si_index
= src_fi
->si_index
;
5723 /* Make sure we don't have an entry for the fd */
5724 swrap_remove_stale(fi
->fd
);
5726 SWRAP_DLIST_ADD_AFTER(socket_fds
, fi
, src_fi
);
5732 return swrap_dup(fd
);
5735 /****************************
5737 ***************************/
5739 static int swrap_dup2(int fd
, int newfd
)
5741 struct socket_info
*si
;
5742 struct socket_info_fd
*src_fi
, *fi
;
5744 src_fi
= find_socket_info_fd(fd
);
5745 if (src_fi
== NULL
) {
5746 return libc_dup2(fd
, newfd
);
5749 si
= &sockets
[src_fi
->si_index
];
5753 * According to the manpage:
5755 * "If oldfd is a valid file descriptor, and newfd has the same
5756 * value as oldfd, then dup2() does nothing, and returns newfd."
5761 if (find_socket_info(newfd
)) {
5762 /* dup2() does an implicit close of newfd, which we
5763 * need to emulate */
5767 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
5773 fi
->fd
= libc_dup2(fd
, newfd
);
5775 int saved_errno
= errno
;
5777 errno
= saved_errno
;
5782 fi
->si_index
= src_fi
->si_index
;
5784 /* Make sure we don't have an entry for the fd */
5785 swrap_remove_stale(fi
->fd
);
5787 SWRAP_DLIST_ADD_AFTER(socket_fds
, fi
, src_fi
);
5791 int dup2(int fd
, int newfd
)
5793 return swrap_dup2(fd
, newfd
);
5796 /****************************
5798 ***************************/
5800 static int swrap_vfcntl(int fd
, int cmd
, va_list va
)
5802 struct socket_info_fd
*src_fi
, *fi
;
5803 struct socket_info
*si
;
5806 src_fi
= find_socket_info_fd(fd
);
5807 if (src_fi
== NULL
) {
5808 return libc_vfcntl(fd
, cmd
, va
);
5811 si
= &sockets
[src_fi
->si_index
];
5815 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
5821 fi
->fd
= libc_vfcntl(fd
, cmd
, va
);
5823 int saved_errno
= errno
;
5825 errno
= saved_errno
;
5830 fi
->si_index
= src_fi
->si_index
;
5832 /* Make sure we don't have an entry for the fd */
5833 swrap_remove_stale(fi
->fd
);
5835 SWRAP_DLIST_ADD_AFTER(socket_fds
, fi
, src_fi
);
5840 rc
= libc_vfcntl(fd
, cmd
, va
);
5847 int fcntl(int fd
, int cmd
, ...)
5854 rc
= swrap_vfcntl(fd
, cmd
, va
);
5861 /****************************
5863 ***************************/
5866 static int swrap_eventfd(int count
, int flags
)
5870 fd
= libc_eventfd(count
, flags
);
5872 swrap_remove_stale(fd
);
5878 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5879 int eventfd(unsigned int count
, int flags
)
5881 int eventfd(int count
, int flags
)
5884 return swrap_eventfd(count
, flags
);
5889 int pledge(const char *promises
, const char *paths
[])
5891 (void)promises
; /* unused */
5892 (void)paths
; /* unused */
5896 #endif /* HAVE_PLEDGE */
5898 static void swrap_thread_prepare(void)
5901 * This function should only be called here!!
5903 * We bind all symobls to avoid deadlocks of the fork is
5904 * interrupted by a signal handler using a symbol of this
5907 swrap_bind_symbol_all();
5912 static void swrap_thread_parent(void)
5917 static void swrap_thread_child(void)
5922 /****************************
5924 ***************************/
5925 void swrap_constructor(void)
5928 * If we hold a lock and the application forks, then the child
5929 * is not able to unlock the mutex and we are in a deadlock.
5930 * This should prevent such deadlocks.
5932 pthread_atfork(&swrap_thread_prepare
,
5933 &swrap_thread_parent
,
5934 &swrap_thread_child
);
5937 /****************************
5939 ***************************/
5942 * This function is called when the library is unloaded and makes sure that
5943 * sockets get closed and the unix file for the socket are unlinked.
5945 void swrap_destructor(void)
5947 struct socket_info_fd
*s
= socket_fds
;
5956 if (swrap
.libc
.handle
!= NULL
) {
5957 dlclose(swrap
.libc
.handle
);
5959 if (swrap
.libc
.socket_handle
) {
5960 dlclose(swrap
.libc
.socket_handle
);