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>
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
100 #define DESTRUCTOR_ATTRIBUTE
103 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
104 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
106 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
109 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
110 # define SWRAP_THREAD __thread
112 # define SWRAP_THREAD
116 #define MIN(a,b) ((a)<(b)?(a):(b))
120 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
124 #define ZERO_STRUCTP(x) do { \
126 memset((char *)(x), 0, sizeof(*(x))); \
130 #ifndef discard_const
131 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
134 #ifndef discard_const_p
135 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
139 # ifndef IPV6_RECVPKTINFO
140 # define IPV6_RECVPKTINFO IPV6_PKTINFO
141 # endif /* IPV6_RECVPKTINFO */
142 #endif /* IPV6_PKTINFO */
145 * On BSD IP_PKTINFO has a different name because during
146 * the time when they implemented it, there was no RFC.
147 * The name for IPv6 is the same as on Linux.
150 # ifdef IP_RECVDSTADDR
151 # define IP_PKTINFO IP_RECVDSTADDR
156 #define SWRAP_DLIST_ADD(list,item) do { \
158 (item)->prev = NULL; \
159 (item)->next = NULL; \
162 (item)->prev = NULL; \
163 (item)->next = (list); \
164 (list)->prev = (item); \
169 #define SWRAP_DLIST_REMOVE(list,item) do { \
170 if ((list) == (item)) { \
171 (list) = (item)->next; \
173 (list)->prev = NULL; \
176 if ((item)->prev) { \
177 (item)->prev->next = (item)->next; \
179 if ((item)->next) { \
180 (item)->next->prev = (item)->prev; \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
187 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
188 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
190 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
193 /* we need to use a very terse format here as IRIX 6.4 silently
194 truncates names to 16 chars, so if we use a longer name then we
195 can't tell which port a packet came from with recvfrom()
197 with this format we have 8 chars left for the directory name
199 #define SOCKET_FORMAT "%c%02X%04X"
200 #define SOCKET_TYPE_CHAR_TCP 'T'
201 #define SOCKET_TYPE_CHAR_UDP 'U'
202 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
203 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
206 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
207 * format PCAP capture files (as the caller will simply continue from here).
209 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
210 #define SOCKET_WRAPPER_MTU_MIN 512
211 #define SOCKET_WRAPPER_MTU_MAX 32768
213 #define SOCKET_MAX_SOCKETS 1024
215 /* This limit is to avoid broadcast sendto() needing to stat too many
216 * files. It may be raised (with a performance cost) to up to 254
217 * without changing the format above */
218 #define MAX_WRAPPED_INTERFACES 40
220 struct swrap_address
{
221 socklen_t sa_socklen
;
224 struct sockaddr_in in
;
226 struct sockaddr_in6 in6
;
228 struct sockaddr_un un
;
229 struct sockaddr_storage ss
;
233 struct socket_info_fd
{
234 struct socket_info_fd
*prev
, *next
;
240 struct socket_info_fd
*fds
;
253 /* The unix path so we can unlink it on close() */
254 struct sockaddr_un un_addr
;
256 struct swrap_address bindname
;
257 struct swrap_address myname
;
258 struct swrap_address peername
;
261 unsigned long pck_snd
;
262 unsigned long pck_rcv
;
265 struct socket_info
*prev
, *next
;
269 * File descriptors are shared between threads so we should share socket
272 struct socket_info
*sockets
;
274 /* Function prototypes */
276 bool socket_wrapper_enabled(void);
277 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
280 # define SWRAP_LOG(...)
283 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *func
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
284 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
286 static void swrap_log(enum swrap_dbglvl_e dbglvl
,
288 const char *format
, ...)
293 unsigned int lvl
= 0;
295 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
300 va_start(va
, format
);
301 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
306 case SWRAP_LOG_ERROR
:
308 "SWRAP_ERROR(%d) - %s: %s\n",
309 (int)getpid(), func
, buffer
);
313 "SWRAP_WARN(%d) - %s: %s\n",
314 (int)getpid(), func
, buffer
);
316 case SWRAP_LOG_DEBUG
:
318 "SWRAP_DEBUG(%d) - %s: %s\n",
319 (int)getpid(), func
, buffer
);
321 case SWRAP_LOG_TRACE
:
323 "SWRAP_TRACE(%d) - %s: %s\n",
324 (int)getpid(), func
, buffer
);
331 /*********************************************************
332 * SWRAP LOADING LIBC FUNCTIONS
333 *********************************************************/
337 struct swrap_libc_fns
{
339 int (*libc_accept4
)(int sockfd
,
340 struct sockaddr
*addr
,
344 int (*libc_accept
)(int sockfd
,
345 struct sockaddr
*addr
,
348 int (*libc_bind
)(int sockfd
,
349 const struct sockaddr
*addr
,
351 int (*libc_close
)(int fd
);
352 int (*libc_connect
)(int sockfd
,
353 const struct sockaddr
*addr
,
355 int (*libc_dup
)(int fd
);
356 int (*libc_dup2
)(int oldfd
, int newfd
);
357 int (*libc_fcntl
)(int fd
, int cmd
, ...);
358 FILE *(*libc_fopen
)(const char *name
, const char *mode
);
360 int (*libc_eventfd
)(int count
, int flags
);
362 int (*libc_getpeername
)(int sockfd
,
363 struct sockaddr
*addr
,
365 int (*libc_getsockname
)(int sockfd
,
366 struct sockaddr
*addr
,
368 int (*libc_getsockopt
)(int sockfd
,
373 int (*libc_ioctl
)(int d
, unsigned long int request
, ...);
374 int (*libc_listen
)(int sockfd
, int backlog
);
375 int (*libc_open
)(const char *pathname
, int flags
, mode_t mode
);
376 int (*libc_pipe
)(int pipefd
[2]);
377 int (*libc_read
)(int fd
, void *buf
, size_t count
);
378 ssize_t (*libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
379 int (*libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
380 int (*libc_recvfrom
)(int sockfd
,
384 struct sockaddr
*src_addr
,
386 int (*libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
387 int (*libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
388 int (*libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
389 int (*libc_sendto
)(int sockfd
,
393 const struct sockaddr
*dst_addr
,
395 int (*libc_setsockopt
)(int sockfd
,
401 int (*libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
403 int (*libc_socket
)(int domain
, int type
, int protocol
);
404 int (*libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
405 #ifdef HAVE_TIMERFD_CREATE
406 int (*libc_timerfd_create
)(int clockid
, int flags
);
408 ssize_t (*libc_write
)(int fd
, const void *buf
, size_t count
);
409 ssize_t (*libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
414 void *libsocket_handle
;
421 struct swrap_libc_fns fns
;
424 static struct swrap swrap
;
427 static const char *socket_wrapper_dir(void);
429 #define LIBC_NAME "libc.so"
438 static const char *swrap_str_lib(enum swrap_lib lib
)
445 case SWRAP_LIBSOCKET
:
449 /* Compiler would warn us about unhandled enum value if we get here */
454 static void *swrap_load_lib_handle(enum swrap_lib lib
)
456 int flags
= RTLD_LAZY
;
461 flags
|= RTLD_DEEPBIND
;
467 case SWRAP_LIBSOCKET
:
468 #ifdef HAVE_LIBSOCKET
469 handle
= swrap
.libsocket_handle
;
470 if (handle
== NULL
) {
471 for (i
= 10; i
>= 0; i
--) {
472 char soname
[256] = {0};
474 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
475 handle
= dlopen(soname
, flags
);
476 if (handle
!= NULL
) {
481 swrap
.libsocket_handle
= handle
;
487 handle
= swrap
.libc_handle
;
489 if (handle
== NULL
) {
490 handle
= dlopen(LIBC_SO
, flags
);
492 swrap
.libc_handle
= handle
;
495 if (handle
== NULL
) {
496 for (i
= 10; i
>= 0; i
--) {
497 char soname
[256] = {0};
499 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
500 handle
= dlopen(soname
, flags
);
501 if (handle
!= NULL
) {
506 swrap
.libc_handle
= handle
;
511 if (handle
== NULL
) {
513 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
515 SWRAP_LOG(SWRAP_LOG_ERROR
,
516 "Failed to dlopen library: %s\n",
525 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
530 handle
= swrap_load_lib_handle(lib
);
532 func
= dlsym(handle
, fn_name
);
534 SWRAP_LOG(SWRAP_LOG_ERROR
,
535 "Failed to find %s: %s\n",
540 SWRAP_LOG(SWRAP_LOG_TRACE
,
542 fn_name
, swrap_str_lib(lib
));
546 #define swrap_load_lib_function(lib, fn_name) \
547 if (swrap.fns.libc_##fn_name == NULL) { \
548 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
549 *(void **) (&swrap.fns.libc_##fn_name) = \
557 * Functions especially from libc need to be loaded individually, you can't load
558 * all at once or gdb will segfault at startup. The same applies to valgrind and
559 * has probably something todo with with the linker.
560 * So we need load each function at the point it is called the first time.
563 static int libc_accept4(int sockfd
,
564 struct sockaddr
*addr
,
568 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept4
);
570 return swrap
.fns
.libc_accept4(sockfd
, addr
, addrlen
, flags
);
573 #else /* HAVE_ACCEPT4 */
575 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
577 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
579 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
581 #endif /* HAVE_ACCEPT4 */
583 static int libc_bind(int sockfd
,
584 const struct sockaddr
*addr
,
587 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
589 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
592 static int libc_close(int fd
)
594 swrap_load_lib_function(SWRAP_LIBC
, close
);
596 return swrap
.fns
.libc_close(fd
);
599 static int libc_connect(int sockfd
,
600 const struct sockaddr
*addr
,
603 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
605 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
608 static int libc_dup(int fd
)
610 swrap_load_lib_function(SWRAP_LIBC
, dup
);
612 return swrap
.fns
.libc_dup(fd
);
615 static int libc_dup2(int oldfd
, int newfd
)
617 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
619 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
623 static int libc_eventfd(int count
, int flags
)
625 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
627 return swrap
.fns
.libc_eventfd(count
, flags
);
631 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
632 static int libc_vfcntl(int fd
, int cmd
, va_list ap
)
638 swrap_load_lib_function(SWRAP_LIBC
, fcntl
);
640 for (i
= 0; i
< 4; i
++) {
641 args
[i
] = va_arg(ap
, long int);
644 rc
= swrap
.fns
.libc_fcntl(fd
,
654 static int libc_getpeername(int sockfd
,
655 struct sockaddr
*addr
,
658 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
660 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
663 static int libc_getsockname(int sockfd
,
664 struct sockaddr
*addr
,
667 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
669 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
672 static int libc_getsockopt(int sockfd
,
678 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
680 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
683 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
684 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
690 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
692 for (i
= 0; i
< 4; i
++) {
693 args
[i
] = va_arg(ap
, long int);
696 rc
= swrap
.fns
.libc_ioctl(d
,
706 static int libc_listen(int sockfd
, int backlog
)
708 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
710 return swrap
.fns
.libc_listen(sockfd
, backlog
);
713 static FILE *libc_fopen(const char *name
, const char *mode
)
715 swrap_load_lib_function(SWRAP_LIBC
, fopen
);
717 return swrap
.fns
.libc_fopen(name
, mode
);
720 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
725 swrap_load_lib_function(SWRAP_LIBC
, open
);
727 mode
= va_arg(ap
, long int);
729 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
734 static int libc_open(const char *pathname
, int flags
, ...)
740 fd
= libc_vopen(pathname
, flags
, ap
);
746 static int libc_pipe(int pipefd
[2])
748 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
750 return swrap
.fns
.libc_pipe(pipefd
);
753 static int libc_read(int fd
, void *buf
, size_t count
)
755 swrap_load_lib_function(SWRAP_LIBC
, read
);
757 return swrap
.fns
.libc_read(fd
, buf
, count
);
760 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
762 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
764 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
767 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
769 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
771 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
774 static int libc_recvfrom(int sockfd
,
778 struct sockaddr
*src_addr
,
781 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
783 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
786 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
788 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
790 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
793 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
795 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
797 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
800 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
802 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
804 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
807 static int libc_sendto(int sockfd
,
811 const struct sockaddr
*dst_addr
,
814 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
816 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
819 static int libc_setsockopt(int sockfd
,
825 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
827 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
831 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
833 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
835 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
839 static int libc_socket(int domain
, int type
, int protocol
)
841 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
843 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
846 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
848 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
850 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
853 #ifdef HAVE_TIMERFD_CREATE
854 static int libc_timerfd_create(int clockid
, int flags
)
856 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
858 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
862 static ssize_t
libc_write(int fd
, const void *buf
, size_t count
)
864 swrap_load_lib_function(SWRAP_LIBC
, write
);
866 return swrap
.fns
.libc_write(fd
, buf
, count
);
869 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
871 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
873 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
876 /*********************************************************
877 * SWRAP HELPER FUNCTIONS
878 *********************************************************/
884 static const struct in6_addr
*swrap_ipv6(void)
886 static struct in6_addr v
;
887 static int initialized
;
895 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
904 static void set_port(int family
, int prt
, struct swrap_address
*addr
)
908 addr
->sa
.in
.sin_port
= htons(prt
);
912 addr
->sa
.in6
.sin6_port
= htons(prt
);
918 static size_t socket_length(int family
)
922 return sizeof(struct sockaddr_in
);
925 return sizeof(struct sockaddr_in6
);
931 static const char *socket_wrapper_dir(void)
933 const char *s
= getenv("SOCKET_WRAPPER_DIR");
937 /* TODO use realpath(3) here, when we add support for threads */
938 if (strncmp(s
, "./", 2) == 0) {
942 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
946 static unsigned int socket_wrapper_mtu(void)
948 static unsigned int max_mtu
= 0;
957 max_mtu
= SOCKET_WRAPPER_MTU_DEFAULT
;
959 s
= getenv("SOCKET_WRAPPER_MTU");
964 tmp
= strtol(s
, &endp
, 10);
969 if (tmp
< SOCKET_WRAPPER_MTU_MIN
|| tmp
> SOCKET_WRAPPER_MTU_MAX
) {
978 bool socket_wrapper_enabled(void)
980 const char *s
= socket_wrapper_dir();
982 return s
!= NULL
? true : false;
985 static unsigned int socket_wrapper_default_iface(void)
987 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
990 if (sscanf(s
, "%u", &iface
) == 1) {
991 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
997 return 1;/* 127.0.0.1 */
1000 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
1007 p
= strrchr(un
->sun_path
, '/');
1008 if (p
) p
++; else p
= un
->sun_path
;
1010 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
1015 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
1018 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1029 case SOCKET_TYPE_CHAR_TCP
:
1030 case SOCKET_TYPE_CHAR_UDP
: {
1031 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
1033 if ((*len
) < sizeof(*in2
)) {
1038 memset(in2
, 0, sizeof(*in2
));
1039 in2
->sin_family
= AF_INET
;
1040 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
1041 in2
->sin_port
= htons(prt
);
1043 *len
= sizeof(*in2
);
1047 case SOCKET_TYPE_CHAR_TCP_V6
:
1048 case SOCKET_TYPE_CHAR_UDP_V6
: {
1049 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
1051 if ((*len
) < sizeof(*in2
)) {
1056 memset(in2
, 0, sizeof(*in2
));
1057 in2
->sin6_family
= AF_INET6
;
1058 in2
->sin6_addr
= *swrap_ipv6();
1059 in2
->sin6_addr
.s6_addr
[15] = iface
;
1060 in2
->sin6_port
= htons(prt
);
1062 *len
= sizeof(*in2
);
1074 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1082 if (bcast
) *bcast
= 0;
1084 switch (inaddr
->sa_family
) {
1086 const struct sockaddr_in
*in
=
1087 (const struct sockaddr_in
*)(const void *)inaddr
;
1088 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1095 u_type
= SOCKET_TYPE_CHAR_TCP
;
1098 u_type
= SOCKET_TYPE_CHAR_UDP
;
1099 a_type
= SOCKET_TYPE_CHAR_UDP
;
1100 b_type
= SOCKET_TYPE_CHAR_UDP
;
1103 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1104 errno
= ESOCKTNOSUPPORT
;
1108 prt
= ntohs(in
->sin_port
);
1109 if (a_type
&& addr
== 0xFFFFFFFF) {
1110 /* 255.255.255.255 only udp */
1113 iface
= socket_wrapper_default_iface();
1114 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1115 /* 127.255.255.255 only udp */
1118 iface
= socket_wrapper_default_iface();
1119 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1123 iface
= (addr
& 0x000000FF);
1125 errno
= ENETUNREACH
;
1128 if (bcast
) *bcast
= is_bcast
;
1133 const struct sockaddr_in6
*in
=
1134 (const struct sockaddr_in6
*)(const void *)inaddr
;
1135 struct in6_addr cmp1
, cmp2
;
1139 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1142 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1145 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1146 errno
= ESOCKTNOSUPPORT
;
1150 /* XXX no multicast/broadcast */
1152 prt
= ntohs(in
->sin6_port
);
1154 cmp1
= *swrap_ipv6();
1155 cmp2
= in
->sin6_addr
;
1156 cmp2
.s6_addr
[15] = 0;
1157 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1158 iface
= in
->sin6_addr
.s6_addr
[15];
1160 errno
= ENETUNREACH
;
1168 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1169 errno
= ENETUNREACH
;
1174 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1180 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1181 socket_wrapper_dir());
1182 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1183 /* the caller need to do more processing */
1187 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1188 socket_wrapper_dir(), type
, iface
, prt
);
1189 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1194 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1203 if (bcast
) *bcast
= 0;
1205 switch (si
->family
) {
1207 const struct sockaddr_in
*in
=
1208 (const struct sockaddr_in
*)(const void *)inaddr
;
1209 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1215 prt
= ntohs(in
->sin_port
);
1219 u_type
= SOCKET_TYPE_CHAR_TCP
;
1220 d_type
= SOCKET_TYPE_CHAR_TCP
;
1223 u_type
= SOCKET_TYPE_CHAR_UDP
;
1224 d_type
= SOCKET_TYPE_CHAR_UDP
;
1225 a_type
= SOCKET_TYPE_CHAR_UDP
;
1226 b_type
= SOCKET_TYPE_CHAR_UDP
;
1229 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1230 errno
= ESOCKTNOSUPPORT
;
1238 iface
= socket_wrapper_default_iface();
1239 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1240 /* 255.255.255.255 only udp */
1243 iface
= socket_wrapper_default_iface();
1244 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1245 /* 127.255.255.255 only udp */
1248 iface
= socket_wrapper_default_iface();
1249 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1253 iface
= (addr
& 0x000000FF);
1255 errno
= EADDRNOTAVAIL
;
1259 /* Store the bind address for connect() */
1260 if (si
->bindname
.sa_socklen
== 0) {
1261 struct sockaddr_in bind_in
;
1262 socklen_t blen
= sizeof(struct sockaddr_in
);
1264 ZERO_STRUCT(bind_in
);
1265 bind_in
.sin_family
= in
->sin_family
;
1266 bind_in
.sin_port
= in
->sin_port
;
1267 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1269 si
->bindname
.sa_socklen
= blen
;
1270 memcpy(&si
->bindname
.sa
.in
, &bind_in
, blen
);
1277 const struct sockaddr_in6
*in
=
1278 (const struct sockaddr_in6
*)(const void *)inaddr
;
1279 struct in6_addr cmp1
, cmp2
;
1283 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1286 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1289 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1290 errno
= ESOCKTNOSUPPORT
;
1294 /* XXX no multicast/broadcast */
1296 prt
= ntohs(in
->sin6_port
);
1298 cmp1
= *swrap_ipv6();
1299 cmp2
= in
->sin6_addr
;
1300 cmp2
.s6_addr
[15] = 0;
1301 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1302 iface
= socket_wrapper_default_iface();
1303 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1304 iface
= in
->sin6_addr
.s6_addr
[15];
1306 errno
= EADDRNOTAVAIL
;
1310 /* Store the bind address for connect() */
1311 if (si
->bindname
.sa_socklen
== 0) {
1312 struct sockaddr_in6 bind_in
;
1313 socklen_t blen
= sizeof(struct sockaddr_in6
);
1315 ZERO_STRUCT(bind_in
);
1316 bind_in
.sin6_family
= in
->sin6_family
;
1317 bind_in
.sin6_port
= in
->sin6_port
;
1319 bind_in
.sin6_addr
= *swrap_ipv6();
1320 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1322 memcpy(&si
->bindname
.sa
.in6
, &bind_in
, blen
);
1323 si
->bindname
.sa_socklen
= blen
;
1330 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1331 errno
= EADDRNOTAVAIL
;
1336 if (bcast
) *bcast
= is_bcast
;
1338 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1344 /* handle auto-allocation of ephemeral ports */
1345 for (prt
= 5001; prt
< 10000; prt
++) {
1346 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1347 socket_wrapper_dir(), type
, iface
, prt
);
1348 if (stat(un
->sun_path
, &st
) == 0) continue;
1350 set_port(si
->family
, prt
, &si
->myname
);
1351 set_port(si
->family
, prt
, &si
->bindname
);
1361 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1362 socket_wrapper_dir(), type
, iface
, prt
);
1363 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1367 static struct socket_info
*find_socket_info(int fd
)
1369 struct socket_info
*i
;
1371 for (i
= sockets
; i
; i
= i
->next
) {
1372 struct socket_info_fd
*f
;
1373 for (f
= i
->fds
; f
; f
= f
->next
) {
1384 static bool check_addr_port_in_use(const struct sockaddr
*sa
, socklen_t len
)
1386 struct socket_info
*s
;
1388 /* first catch invalid input */
1389 switch (sa
->sa_family
) {
1391 if (len
< sizeof(struct sockaddr_in
)) {
1397 if (len
< sizeof(struct sockaddr_in6
)) {
1407 for (s
= sockets
; s
!= NULL
; s
= s
->next
) {
1408 if (s
->myname
== NULL
) {
1411 if (s
->myname
->sa_family
!= sa
->sa_family
) {
1414 switch (s
->myname
->sa_family
) {
1416 struct sockaddr_in
*sin1
, *sin2
;
1418 sin1
= (struct sockaddr_in
*)s
->myname
;
1419 sin2
= (struct sockaddr_in
*)sa
;
1421 if (sin1
->sin_addr
.s_addr
== htonl(INADDR_ANY
)) {
1424 if (sin1
->sin_port
!= sin2
->sin_port
) {
1427 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
1437 struct sockaddr_in6
*sin1
, *sin2
;
1439 sin1
= (struct sockaddr_in6
*)s
->myname
;
1440 sin2
= (struct sockaddr_in6
*)sa
;
1442 if (sin1
->sin6_port
!= sin2
->sin6_port
) {
1445 if (!IN6_ARE_ADDR_EQUAL(&sin1
->sin6_addr
,
1467 static void swrap_remove_stale(int fd
)
1469 struct socket_info
*si
= find_socket_info(fd
);
1470 struct socket_info_fd
*fi
;
1473 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1475 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1476 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1482 if (si
->fds
== NULL
) {
1483 SWRAP_DLIST_REMOVE(sockets
, si
);
1484 if (si
->un_addr
.sun_path
[0] != '\0') {
1485 unlink(si
->un_addr
.sun_path
);
1492 static int sockaddr_convert_to_un(struct socket_info
*si
,
1493 const struct sockaddr
*in_addr
,
1495 struct sockaddr_un
*out_addr
,
1499 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1501 (void) in_len
; /* unused */
1503 if (out_addr
== NULL
) {
1507 out
->sa_family
= AF_UNIX
;
1508 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1509 out
->sa_len
= sizeof(*out_addr
);
1512 switch (in_addr
->sa_family
) {
1514 const struct sockaddr_in
*sin
;
1515 if (si
->family
!= AF_INET
) {
1518 if (in_len
< sizeof(struct sockaddr_in
)) {
1521 sin
= (const struct sockaddr_in
*)(const void *)in_addr
;
1522 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
1527 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1528 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1542 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1543 errno
= ESOCKTNOSUPPORT
;
1547 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1549 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1555 errno
= EAFNOSUPPORT
;
1556 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1560 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1561 const struct sockaddr_un
*in_addr
,
1562 socklen_t un_addrlen
,
1564 struct sockaddr
*out_addr
,
1565 socklen_t
*out_addrlen
)
1569 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1572 if (un_addrlen
== 0) {
1587 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1588 errno
= ESOCKTNOSUPPORT
;
1591 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1592 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1593 out_addr
->sa_len
= *out_addrlen
;
1600 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1601 errno
= EAFNOSUPPORT
;
1605 enum swrap_packet_type
{
1607 SWRAP_CONNECT_UNREACH
,
1615 SWRAP_SENDTO_UNREACH
,
1626 struct swrap_file_hdr
{
1628 uint16_t version_major
;
1629 uint16_t version_minor
;
1632 uint32_t frame_max_len
;
1633 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1636 #define SWRAP_FILE_HDR_SIZE 24
1638 struct swrap_packet_frame
{
1640 uint32_t micro_seconds
;
1641 uint32_t recorded_length
;
1642 uint32_t full_length
;
1644 #define SWRAP_PACKET_FRAME_SIZE 16
1646 union swrap_packet_ip
{
1650 uint16_t packet_length
;
1651 uint16_t identification
;
1656 uint16_t hdr_checksum
;
1660 #define SWRAP_PACKET_IP_V4_SIZE 20
1663 uint8_t flow_label_high
;
1664 uint16_t flow_label_low
;
1665 uint16_t payload_length
;
1666 uint8_t next_header
;
1668 uint8_t src_addr
[16];
1669 uint8_t dest_addr
[16];
1671 #define SWRAP_PACKET_IP_V6_SIZE 40
1673 #define SWRAP_PACKET_IP_SIZE 40
1675 union swrap_packet_payload
{
1677 uint16_t source_port
;
1687 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1689 uint16_t source_port
;
1694 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1701 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1708 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1710 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1712 #define SWRAP_PACKET_MIN_ALLOC \
1713 (SWRAP_PACKET_FRAME_SIZE + \
1714 SWRAP_PACKET_IP_SIZE + \
1715 SWRAP_PACKET_PAYLOAD_SIZE)
1717 static const char *swrap_pcap_init_file(void)
1719 static int initialized
= 0;
1720 static const char *s
= NULL
;
1721 static const struct swrap_file_hdr h
;
1722 static const struct swrap_packet_frame f
;
1723 static const union swrap_packet_ip i
;
1724 static const union swrap_packet_payload p
;
1726 if (initialized
== 1) {
1732 * TODO: don't use the structs use plain buffer offsets
1733 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1735 * for now make sure we disable PCAP support
1736 * if the struct has alignment!
1738 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1741 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1744 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1747 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1750 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1753 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1756 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1759 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1762 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1765 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1769 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1773 if (strncmp(s
, "./", 2) == 0) {
1779 static uint8_t *swrap_pcap_packet_init(struct timeval
*tval
,
1780 const struct sockaddr
*src
,
1781 const struct sockaddr
*dest
,
1783 const uint8_t *payload
,
1785 unsigned long tcp_seqno
,
1786 unsigned long tcp_ack
,
1787 unsigned char tcp_ctl
,
1789 size_t *_packet_len
)
1793 struct swrap_packet_frame
*frame
;
1794 union swrap_packet_ip
*ip
;
1795 union swrap_packet_payload
*pay
;
1798 size_t nonwire_len
= sizeof(*frame
);
1799 size_t wire_hdr_len
= 0;
1800 size_t wire_len
= 0;
1801 size_t ip_hdr_len
= 0;
1802 size_t icmp_hdr_len
= 0;
1803 size_t icmp_truncate_len
= 0;
1804 uint8_t protocol
= 0, icmp_protocol
= 0;
1805 const struct sockaddr_in
*src_in
= NULL
;
1806 const struct sockaddr_in
*dest_in
= NULL
;
1808 const struct sockaddr_in6
*src_in6
= NULL
;
1809 const struct sockaddr_in6
*dest_in6
= NULL
;
1814 switch (src
->sa_family
) {
1816 src_in
= (const struct sockaddr_in
*)(const void *)src
;
1817 dest_in
= (const struct sockaddr_in
*)(const void *)dest
;
1818 src_port
= src_in
->sin_port
;
1819 dest_port
= dest_in
->sin_port
;
1820 ip_hdr_len
= sizeof(ip
->v4
);
1824 src_in6
= (const struct sockaddr_in6
*)(const void *)src
;
1825 dest_in6
= (const struct sockaddr_in6
*)(const void *)dest
;
1826 src_port
= src_in6
->sin6_port
;
1827 dest_port
= dest_in6
->sin6_port
;
1828 ip_hdr_len
= sizeof(ip
->v6
);
1835 switch (socket_type
) {
1837 protocol
= 0x06; /* TCP */
1838 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1839 wire_len
= wire_hdr_len
+ payload_len
;
1843 protocol
= 0x11; /* UDP */
1844 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1845 wire_len
= wire_hdr_len
+ payload_len
;
1853 icmp_protocol
= protocol
;
1854 switch (src
->sa_family
) {
1856 protocol
= 0x01; /* ICMPv4 */
1857 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1861 protocol
= 0x3A; /* ICMPv6 */
1862 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1866 if (wire_len
> 64 ) {
1867 icmp_truncate_len
= wire_len
- 64;
1869 wire_hdr_len
+= icmp_hdr_len
;
1870 wire_len
+= icmp_hdr_len
;
1873 packet_len
= nonwire_len
+ wire_len
;
1874 alloc_len
= packet_len
;
1875 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1876 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1879 base
= (uint8_t *)calloc(1, alloc_len
);
1886 frame
= (struct swrap_packet_frame
*)(void *)buf
;
1887 frame
->seconds
= tval
->tv_sec
;
1888 frame
->micro_seconds
= tval
->tv_usec
;
1889 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1890 frame
->full_length
= wire_len
- icmp_truncate_len
;
1891 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1893 ip
= (union swrap_packet_ip
*)(void *)buf
;
1894 switch (src
->sa_family
) {
1896 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1898 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1899 ip
->v4
.identification
= htons(0xFFFF);
1900 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1901 ip
->v4
.fragment
= htons(0x0000);
1903 ip
->v4
.protocol
= protocol
;
1904 ip
->v4
.hdr_checksum
= htons(0x0000);
1905 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1906 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1907 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1911 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1912 ip
->v6
.flow_label_high
= 0x00;
1913 ip
->v6
.flow_label_low
= 0x0000;
1914 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1915 ip
->v6
.next_header
= protocol
;
1916 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1917 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1918 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1924 pay
= (union swrap_packet_payload
*)(void *)buf
;
1925 switch (src
->sa_family
) {
1927 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1928 pay
->icmp4
.code
= 0x01; /* host unreachable */
1929 pay
->icmp4
.checksum
= htons(0x0000);
1930 pay
->icmp4
.unused
= htonl(0x00000000);
1931 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1933 /* set the ip header in the ICMP payload */
1934 ip
= (union swrap_packet_ip
*)(void *)buf
;
1935 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1937 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1938 ip
->v4
.identification
= htons(0xFFFF);
1939 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1940 ip
->v4
.fragment
= htons(0x0000);
1942 ip
->v4
.protocol
= icmp_protocol
;
1943 ip
->v4
.hdr_checksum
= htons(0x0000);
1944 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1945 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1946 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1948 src_port
= dest_in
->sin_port
;
1949 dest_port
= src_in
->sin_port
;
1953 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1954 pay
->icmp6
.code
= 0x03; /* address unreachable */
1955 pay
->icmp6
.checksum
= htons(0x0000);
1956 pay
->icmp6
.unused
= htonl(0x00000000);
1957 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1959 /* set the ip header in the ICMP payload */
1960 ip
= (union swrap_packet_ip
*)(void *)buf
;
1961 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1962 ip
->v6
.flow_label_high
= 0x00;
1963 ip
->v6
.flow_label_low
= 0x0000;
1964 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1965 ip
->v6
.next_header
= protocol
;
1966 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1967 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1968 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1970 src_port
= dest_in6
->sin6_port
;
1971 dest_port
= src_in6
->sin6_port
;
1977 pay
= (union swrap_packet_payload
*)(void *)buf
;
1979 switch (socket_type
) {
1981 pay
->tcp
.source_port
= src_port
;
1982 pay
->tcp
.dest_port
= dest_port
;
1983 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1984 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1985 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1986 pay
->tcp
.control
= tcp_ctl
;
1987 pay
->tcp
.window
= htons(0x7FFF);
1988 pay
->tcp
.checksum
= htons(0x0000);
1989 pay
->tcp
.urg
= htons(0x0000);
1990 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1995 pay
->udp
.source_port
= src_port
;
1996 pay
->udp
.dest_port
= dest_port
;
1997 pay
->udp
.length
= htons(8 + payload_len
);
1998 pay
->udp
.checksum
= htons(0x0000);
1999 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
2004 if (payload
&& payload_len
> 0) {
2005 memcpy(buf
, payload
, payload_len
);
2008 *_packet_len
= packet_len
- icmp_truncate_len
;
2012 static int swrap_pcap_get_fd(const char *fname
)
2016 if (fd
!= -1) return fd
;
2018 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
2020 struct swrap_file_hdr file_hdr
;
2021 file_hdr
.magic
= 0xA1B2C3D4;
2022 file_hdr
.version_major
= 0x0002;
2023 file_hdr
.version_minor
= 0x0004;
2024 file_hdr
.timezone
= 0x00000000;
2025 file_hdr
.sigfigs
= 0x00000000;
2026 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
2027 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
2029 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
2036 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
2041 static uint8_t *swrap_pcap_marshall_packet(struct socket_info
*si
,
2042 const struct sockaddr
*addr
,
2043 enum swrap_packet_type type
,
2044 const void *buf
, size_t len
,
2047 const struct sockaddr
*src_addr
;
2048 const struct sockaddr
*dest_addr
;
2049 unsigned long tcp_seqno
= 0;
2050 unsigned long tcp_ack
= 0;
2051 unsigned char tcp_ctl
= 0;
2052 int unreachable
= 0;
2056 switch (si
->family
) {
2068 case SWRAP_CONNECT_SEND
:
2069 if (si
->type
!= SOCK_STREAM
) return NULL
;
2071 src_addr
= &si
->myname
.sa
.s
;
2074 tcp_seqno
= si
->io
.pck_snd
;
2075 tcp_ack
= si
->io
.pck_rcv
;
2076 tcp_ctl
= 0x02; /* SYN */
2078 si
->io
.pck_snd
+= 1;
2082 case SWRAP_CONNECT_RECV
:
2083 if (si
->type
!= SOCK_STREAM
) return NULL
;
2085 dest_addr
= &si
->myname
.sa
.s
;
2088 tcp_seqno
= si
->io
.pck_rcv
;
2089 tcp_ack
= si
->io
.pck_snd
;
2090 tcp_ctl
= 0x12; /** SYN,ACK */
2092 si
->io
.pck_rcv
+= 1;
2096 case SWRAP_CONNECT_UNREACH
:
2097 if (si
->type
!= SOCK_STREAM
) return NULL
;
2099 dest_addr
= &si
->myname
.sa
.s
;
2102 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2103 tcp_seqno
= si
->io
.pck_snd
- 1;
2104 tcp_ack
= si
->io
.pck_rcv
;
2105 tcp_ctl
= 0x02; /* SYN */
2110 case SWRAP_CONNECT_ACK
:
2111 if (si
->type
!= SOCK_STREAM
) return NULL
;
2113 src_addr
= &si
->myname
.sa
.s
;
2116 tcp_seqno
= si
->io
.pck_snd
;
2117 tcp_ack
= si
->io
.pck_rcv
;
2118 tcp_ctl
= 0x10; /* ACK */
2122 case SWRAP_ACCEPT_SEND
:
2123 if (si
->type
!= SOCK_STREAM
) return NULL
;
2125 dest_addr
= &si
->myname
.sa
.s
;
2128 tcp_seqno
= si
->io
.pck_rcv
;
2129 tcp_ack
= si
->io
.pck_snd
;
2130 tcp_ctl
= 0x02; /* SYN */
2132 si
->io
.pck_rcv
+= 1;
2136 case SWRAP_ACCEPT_RECV
:
2137 if (si
->type
!= SOCK_STREAM
) return NULL
;
2139 src_addr
= &si
->myname
.sa
.s
;
2142 tcp_seqno
= si
->io
.pck_snd
;
2143 tcp_ack
= si
->io
.pck_rcv
;
2144 tcp_ctl
= 0x12; /* SYN,ACK */
2146 si
->io
.pck_snd
+= 1;
2150 case SWRAP_ACCEPT_ACK
:
2151 if (si
->type
!= SOCK_STREAM
) return NULL
;
2153 dest_addr
= &si
->myname
.sa
.s
;
2156 tcp_seqno
= si
->io
.pck_rcv
;
2157 tcp_ack
= si
->io
.pck_snd
;
2158 tcp_ctl
= 0x10; /* ACK */
2163 src_addr
= &si
->myname
.sa
.s
;
2164 dest_addr
= &si
->peername
.sa
.s
;
2166 tcp_seqno
= si
->io
.pck_snd
;
2167 tcp_ack
= si
->io
.pck_rcv
;
2168 tcp_ctl
= 0x18; /* PSH,ACK */
2170 si
->io
.pck_snd
+= len
;
2174 case SWRAP_SEND_RST
:
2175 dest_addr
= &si
->myname
.sa
.s
;
2176 src_addr
= &si
->peername
.sa
.s
;
2178 if (si
->type
== SOCK_DGRAM
) {
2179 return swrap_pcap_marshall_packet(si
,
2181 SWRAP_SENDTO_UNREACH
,
2187 tcp_seqno
= si
->io
.pck_rcv
;
2188 tcp_ack
= si
->io
.pck_snd
;
2189 tcp_ctl
= 0x14; /** RST,ACK */
2193 case SWRAP_PENDING_RST
:
2194 dest_addr
= &si
->myname
.sa
.s
;
2195 src_addr
= &si
->peername
.sa
.s
;
2197 if (si
->type
== SOCK_DGRAM
) {
2201 tcp_seqno
= si
->io
.pck_rcv
;
2202 tcp_ack
= si
->io
.pck_snd
;
2203 tcp_ctl
= 0x14; /* RST,ACK */
2208 dest_addr
= &si
->myname
.sa
.s
;
2209 src_addr
= &si
->peername
.sa
.s
;
2211 tcp_seqno
= si
->io
.pck_rcv
;
2212 tcp_ack
= si
->io
.pck_snd
;
2213 tcp_ctl
= 0x18; /* PSH,ACK */
2215 si
->io
.pck_rcv
+= len
;
2219 case SWRAP_RECV_RST
:
2220 dest_addr
= &si
->myname
.sa
.s
;
2221 src_addr
= &si
->peername
.sa
.s
;
2223 if (si
->type
== SOCK_DGRAM
) {
2227 tcp_seqno
= si
->io
.pck_rcv
;
2228 tcp_ack
= si
->io
.pck_snd
;
2229 tcp_ctl
= 0x14; /* RST,ACK */
2234 src_addr
= &si
->myname
.sa
.s
;
2237 si
->io
.pck_snd
+= len
;
2241 case SWRAP_SENDTO_UNREACH
:
2242 dest_addr
= &si
->myname
.sa
.s
;
2249 case SWRAP_RECVFROM
:
2250 dest_addr
= &si
->myname
.sa
.s
;
2253 si
->io
.pck_rcv
+= len
;
2257 case SWRAP_CLOSE_SEND
:
2258 if (si
->type
!= SOCK_STREAM
) return NULL
;
2260 src_addr
= &si
->myname
.sa
.s
;
2261 dest_addr
= &si
->peername
.sa
.s
;
2263 tcp_seqno
= si
->io
.pck_snd
;
2264 tcp_ack
= si
->io
.pck_rcv
;
2265 tcp_ctl
= 0x11; /* FIN, ACK */
2267 si
->io
.pck_snd
+= 1;
2271 case SWRAP_CLOSE_RECV
:
2272 if (si
->type
!= SOCK_STREAM
) return NULL
;
2274 dest_addr
= &si
->myname
.sa
.s
;
2275 src_addr
= &si
->peername
.sa
.s
;
2277 tcp_seqno
= si
->io
.pck_rcv
;
2278 tcp_ack
= si
->io
.pck_snd
;
2279 tcp_ctl
= 0x11; /* FIN,ACK */
2281 si
->io
.pck_rcv
+= 1;
2285 case SWRAP_CLOSE_ACK
:
2286 if (si
->type
!= SOCK_STREAM
) return NULL
;
2288 src_addr
= &si
->myname
.sa
.s
;
2289 dest_addr
= &si
->peername
.sa
.s
;
2291 tcp_seqno
= si
->io
.pck_snd
;
2292 tcp_ack
= si
->io
.pck_rcv
;
2293 tcp_ctl
= 0x10; /* ACK */
2300 swrapGetTimeOfDay(&tv
);
2302 return swrap_pcap_packet_init(&tv
,
2306 (const uint8_t *)buf
,
2315 static void swrap_pcap_dump_packet(struct socket_info
*si
,
2316 const struct sockaddr
*addr
,
2317 enum swrap_packet_type type
,
2318 const void *buf
, size_t len
)
2320 const char *file_name
;
2322 size_t packet_len
= 0;
2325 file_name
= swrap_pcap_init_file();
2330 packet
= swrap_pcap_marshall_packet(si
,
2336 if (packet
== NULL
) {
2340 fd
= swrap_pcap_get_fd(file_name
);
2342 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2351 /****************************************************************************
2353 ***************************************************************************/
2355 #ifdef HAVE_SIGNALFD
2356 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2360 rc
= libc_signalfd(fd
, mask
, flags
);
2362 swrap_remove_stale(fd
);
2368 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2370 return swrap_signalfd(fd
, mask
, flags
);
2374 /****************************************************************************
2376 ***************************************************************************/
2378 static int swrap_socket(int family
, int type
, int protocol
)
2380 struct socket_info
*si
;
2381 struct socket_info_fd
*fi
;
2383 int real_type
= type
;
2386 * Remove possible addition flags passed to socket() so
2387 * do not fail checking the type.
2388 * See https://lwn.net/Articles/281965/
2391 real_type
&= ~SOCK_CLOEXEC
;
2393 #ifdef SOCK_NONBLOCK
2394 real_type
&= ~SOCK_NONBLOCK
;
2397 if (!socket_wrapper_enabled()) {
2398 return libc_socket(family
, type
, protocol
);
2409 #endif /* AF_NETLINK */
2412 #endif /* AF_PACKET */
2414 return libc_socket(family
, type
, protocol
);
2416 errno
= EAFNOSUPPORT
;
2420 switch (real_type
) {
2426 errno
= EPROTONOSUPPORT
;
2434 if (real_type
== SOCK_STREAM
) {
2439 if (real_type
== SOCK_DGRAM
) {
2444 errno
= EPROTONOSUPPORT
;
2449 * We must call libc_socket with type, from the caller, not the version
2450 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2452 fd
= libc_socket(AF_UNIX
, type
, 0);
2458 /* Check if we have a stale fd and remove it */
2459 si
= find_socket_info(fd
);
2461 swrap_remove_stale(fd
);
2464 si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
2470 si
->family
= family
;
2472 /* however, the rest of the socket_wrapper code expects just
2473 * the type, not the flags */
2474 si
->type
= real_type
;
2475 si
->protocol
= protocol
;
2478 * Setup myname so getsockname() can succeed to find out the socket
2481 switch(si
->family
) {
2483 struct sockaddr_in sin
= {
2484 .sin_family
= AF_INET
,
2487 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in
);
2488 memcpy(&si
->myname
.sa
.in
, &sin
, si
->myname
.sa_socklen
);
2492 struct sockaddr_in6 sin6
= {
2493 .sin6_family
= AF_INET6
,
2496 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in6
);
2497 memcpy(&si
->myname
.sa
.in6
, &sin6
, si
->myname
.sa_socklen
);
2506 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2515 SWRAP_DLIST_ADD(si
->fds
, fi
);
2516 SWRAP_DLIST_ADD(sockets
, si
);
2518 SWRAP_LOG(SWRAP_LOG_TRACE
,
2519 "Created %s socket for protocol %s",
2520 si
->family
== AF_INET
? "IPv4" : "IPv6",
2521 si
->type
== SOCK_DGRAM
? "UDP" : "TCP");
2526 int socket(int family
, int type
, int protocol
)
2528 return swrap_socket(family
, type
, protocol
);
2531 /****************************************************************************
2533 ***************************************************************************/
2535 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2539 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2541 swrap_remove_stale(sv
[0]);
2542 swrap_remove_stale(sv
[1]);
2548 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2550 return swrap_socketpair(family
, type
, protocol
, sv
);
2553 /****************************************************************************
2555 ***************************************************************************/
2557 #ifdef HAVE_TIMERFD_CREATE
2558 static int swrap_timerfd_create(int clockid
, int flags
)
2562 fd
= libc_timerfd_create(clockid
, flags
);
2564 swrap_remove_stale(fd
);
2570 int timerfd_create(int clockid
, int flags
)
2572 return swrap_timerfd_create(clockid
, flags
);
2576 /****************************************************************************
2578 ***************************************************************************/
2580 static int swrap_pipe(int pipefd
[2])
2584 rc
= libc_pipe(pipefd
);
2586 swrap_remove_stale(pipefd
[0]);
2587 swrap_remove_stale(pipefd
[1]);
2593 int pipe(int pipefd
[2])
2595 return swrap_pipe(pipefd
);
2598 /****************************************************************************
2600 ***************************************************************************/
2602 static int swrap_accept(int s
,
2603 struct sockaddr
*addr
,
2607 struct socket_info
*parent_si
, *child_si
;
2608 struct socket_info_fd
*child_fi
;
2610 struct swrap_address un_addr
= {
2611 .sa_socklen
= sizeof(struct sockaddr_un
),
2613 struct swrap_address un_my_addr
= {
2614 .sa_socklen
= sizeof(struct sockaddr_un
),
2616 struct swrap_address in_addr
= {
2617 .sa_socklen
= sizeof(struct sockaddr_storage
),
2619 struct swrap_address in_my_addr
= {
2620 .sa_socklen
= sizeof(struct sockaddr_storage
),
2624 parent_si
= find_socket_info(s
);
2627 return libc_accept4(s
, addr
, addrlen
, flags
);
2629 return libc_accept(s
, addr
, addrlen
);
2634 * assume out sockaddr have the same size as the in parent
2637 in_addr
.sa_socklen
= socket_length(parent_si
->family
);
2638 if (in_addr
.sa_socklen
<= 0) {
2644 ret
= libc_accept4(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
, flags
);
2646 ret
= libc_accept(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
);
2649 if (errno
== ENOTSOCK
) {
2650 /* Remove stale fds */
2651 swrap_remove_stale(s
);
2658 ret
= sockaddr_convert_from_un(parent_si
,
2663 &in_addr
.sa_socklen
);
2669 child_si
= (struct socket_info
*)calloc(1, sizeof(struct socket_info
));
2670 if (child_si
== NULL
) {
2676 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2677 if (child_fi
== NULL
) {
2686 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2688 child_si
->family
= parent_si
->family
;
2689 child_si
->type
= parent_si
->type
;
2690 child_si
->protocol
= parent_si
->protocol
;
2691 child_si
->bound
= 1;
2692 child_si
->is_server
= 1;
2693 child_si
->connected
= 1;
2695 child_si
->peername
= (struct swrap_address
) {
2696 .sa_socklen
= in_addr
.sa_socklen
,
2698 memcpy(&child_si
->peername
.sa
.ss
, &in_addr
.sa
.ss
, in_addr
.sa_socklen
);
2700 if (addr
!= NULL
&& addrlen
!= NULL
) {
2701 size_t copy_len
= MIN(*addrlen
, in_addr
.sa_socklen
);
2703 memcpy(addr
, &in_addr
.sa
.ss
, copy_len
);
2705 *addrlen
= in_addr
.sa_socklen
;
2708 ret
= libc_getsockname(fd
,
2710 &un_my_addr
.sa_socklen
);
2718 ret
= sockaddr_convert_from_un(child_si
,
2720 un_my_addr
.sa_socklen
,
2723 &in_my_addr
.sa_socklen
);
2731 SWRAP_LOG(SWRAP_LOG_TRACE
,
2732 "accept() path=%s, fd=%d",
2733 un_my_addr
.sa
.un
.sun_path
, s
);
2735 child_si
->myname
= (struct swrap_address
) {
2736 .sa_socklen
= in_my_addr
.sa_socklen
,
2738 memcpy(&child_si
->myname
.sa
.ss
, &in_my_addr
.sa
.ss
, in_my_addr
.sa_socklen
);
2740 SWRAP_DLIST_ADD(sockets
, child_si
);
2743 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2744 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2745 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2752 int accept4(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
, int flags
)
2754 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
, flags
);
2758 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2759 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2761 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2764 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
, 0);
2767 static int autobind_start_init
;
2768 static int autobind_start
;
2770 /* using sendto() or connect() on an unbound socket would give the
2771 recipient no way to reply, as unlike UDP and TCP, a unix domain
2772 socket can't auto-assign ephemeral port numbers, so we need to
2774 Note: this might change the family from ipv6 to ipv4
2776 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2778 struct swrap_address un_addr
= {
2779 .sa_socklen
= sizeof(struct sockaddr_un
),
2787 if (autobind_start_init
!= 1) {
2788 autobind_start_init
= 1;
2789 autobind_start
= getpid();
2790 autobind_start
%= 50000;
2791 autobind_start
+= 10000;
2794 un_addr
.sa
.un
.sun_family
= AF_UNIX
;
2798 struct sockaddr_in in
;
2802 type
= SOCKET_TYPE_CHAR_TCP
;
2805 type
= SOCKET_TYPE_CHAR_UDP
;
2808 errno
= ESOCKTNOSUPPORT
;
2812 memset(&in
, 0, sizeof(in
));
2813 in
.sin_family
= AF_INET
;
2814 in
.sin_addr
.s_addr
= htonl(127<<24 |
2815 socket_wrapper_default_iface());
2817 si
->myname
= (struct swrap_address
) {
2818 .sa_socklen
= sizeof(in
),
2820 memcpy(&si
->myname
.sa
.in
, &in
, si
->myname
.sa_socklen
);
2825 struct sockaddr_in6 in6
;
2827 if (si
->family
!= family
) {
2828 errno
= ENETUNREACH
;
2834 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2837 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2840 errno
= ESOCKTNOSUPPORT
;
2844 memset(&in6
, 0, sizeof(in6
));
2845 in6
.sin6_family
= AF_INET6
;
2846 in6
.sin6_addr
= *swrap_ipv6();
2847 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2849 si
->myname
= (struct swrap_address
) {
2850 .sa_socklen
= sizeof(in6
),
2852 memcpy(&si
->myname
.sa
.in6
, &in6
, si
->myname
.sa_socklen
);
2857 errno
= ESOCKTNOSUPPORT
;
2861 if (autobind_start
> 60000) {
2862 autobind_start
= 10000;
2865 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2866 port
= autobind_start
+ i
;
2867 snprintf(un_addr
.sa
.un
.sun_path
, sizeof(un_addr
.sa
.un
.sun_path
),
2868 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2869 type
, socket_wrapper_default_iface(), port
);
2870 if (stat(un_addr
.sa
.un
.sun_path
, &st
) == 0) continue;
2872 ret
= libc_bind(fd
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
2873 if (ret
== -1) return ret
;
2875 si
->un_addr
= un_addr
.sa
.un
;
2878 autobind_start
= port
+ 1;
2881 if (i
== SOCKET_MAX_SOCKETS
) {
2882 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2883 "interface "SOCKET_FORMAT
,
2886 socket_wrapper_default_iface(),
2892 si
->family
= family
;
2893 set_port(si
->family
, port
, &si
->myname
);
2898 /****************************************************************************
2900 ***************************************************************************/
2902 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2906 struct swrap_address un_addr
= {
2907 .sa_socklen
= sizeof(struct sockaddr_un
),
2909 struct socket_info
*si
= find_socket_info(s
);
2913 return libc_connect(s
, serv_addr
, addrlen
);
2916 if (si
->bound
== 0) {
2917 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2918 if (ret
== -1) return -1;
2921 if (si
->family
!= serv_addr
->sa_family
) {
2926 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2927 addrlen
, &un_addr
.sa
.un
, 0, &bcast
);
2928 if (ret
== -1) return -1;
2931 errno
= ENETUNREACH
;
2935 if (si
->type
== SOCK_DGRAM
) {
2936 si
->defer_connect
= 1;
2939 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2941 ret
= libc_connect(s
,
2943 un_addr
.sa_socklen
);
2946 SWRAP_LOG(SWRAP_LOG_TRACE
,
2947 "connect() path=%s, fd=%d",
2948 un_addr
.sa
.un
.sun_path
, s
);
2951 /* to give better errors */
2952 if (ret
== -1 && errno
== ENOENT
) {
2953 errno
= EHOSTUNREACH
;
2957 si
->peername
= (struct swrap_address
) {
2958 .sa_socklen
= addrlen
,
2961 memcpy(&si
->peername
.sa
.ss
, serv_addr
, addrlen
);
2965 * When we connect() on a socket than we have to bind the
2966 * outgoing connection on the interface we use for the
2967 * transport. We already bound it on the right interface
2968 * but here we have to update the name so getsockname()
2969 * returns correct information.
2971 if (si
->bindname
.sa_socklen
> 0) {
2972 si
->myname
= (struct swrap_address
) {
2973 .sa_socklen
= si
->bindname
.sa_socklen
,
2976 memcpy(&si
->myname
.sa
.ss
,
2977 &si
->bindname
.sa
.ss
,
2978 si
->bindname
.sa_socklen
);
2980 /* Cleanup bindname */
2981 si
->bindname
= (struct swrap_address
) {
2986 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2987 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2989 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2995 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2997 return swrap_connect(s
, serv_addr
, addrlen
);
3000 /****************************************************************************
3002 ***************************************************************************/
3004 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
3007 struct swrap_address un_addr
= {
3008 .sa_socklen
= sizeof(struct sockaddr_un
),
3010 struct socket_info
*si
= find_socket_info(s
);
3017 return libc_bind(s
, myaddr
, addrlen
);
3020 switch (si
->family
) {
3022 const struct sockaddr_in
*sin
;
3023 if (addrlen
< sizeof(struct sockaddr_in
)) {
3024 bind_error
= EINVAL
;
3028 sin
= (const struct sockaddr_in
*)(const void *)myaddr
;
3030 if (sin
->sin_family
!= AF_INET
) {
3031 bind_error
= EAFNOSUPPORT
;
3034 /* special case for AF_UNSPEC */
3035 if (sin
->sin_family
== AF_UNSPEC
&&
3036 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
3045 const struct sockaddr_in6
*sin6
;
3046 if (addrlen
< sizeof(struct sockaddr_in6
)) {
3047 bind_error
= EINVAL
;
3051 sin6
= (const struct sockaddr_in6
*)(const void *)myaddr
;
3053 if (sin6
->sin6_family
!= AF_INET6
) {
3054 bind_error
= EAFNOSUPPORT
;
3061 bind_error
= EINVAL
;
3065 if (bind_error
!= 0) {
3071 in_use
= check_addr_port_in_use(myaddr
, addrlen
);
3078 si
->myname
.sa_socklen
= addrlen
;
3079 memcpy(&si
->myname
.sa
.ss
, myaddr
, addrlen
);
3081 ret
= sockaddr_convert_to_un(si
,
3087 if (ret
== -1) return -1;
3089 unlink(un_addr
.sa
.un
.sun_path
);
3091 ret
= libc_bind(s
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
3093 SWRAP_LOG(SWRAP_LOG_TRACE
,
3094 "bind() path=%s, fd=%d",
3095 un_addr
.sa
.un
.sun_path
, s
);
3104 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
3106 return swrap_bind(s
, myaddr
, addrlen
);
3109 /****************************************************************************
3111 ***************************************************************************/
3113 #ifdef HAVE_BINDRESVPORT
3114 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
3116 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
3118 struct swrap_address myaddr
= {
3119 .sa_socklen
= sizeof(struct sockaddr_storage
),
3122 static uint16_t port
;
3127 #define SWRAP_STARTPORT 600
3128 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3129 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3132 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
3136 salen
= myaddr
.sa_socklen
;
3139 rc
= swrap_getsockname(sd
, &myaddr
.sa
.s
, &salen
);
3145 memset(&myaddr
.sa
.ss
, 0, salen
);
3150 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
3153 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)(void *)sa
;
3155 salen
= sizeof(struct sockaddr_in
);
3156 sinp
->sin_port
= htons(port
);
3160 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)(void *)sa
;
3162 salen
= sizeof(struct sockaddr_in6
);
3163 sin6p
->sin6_port
= htons(port
);
3167 errno
= EAFNOSUPPORT
;
3172 if (port
> SWRAP_ENDPORT
) {
3173 port
= SWRAP_STARTPORT
;
3176 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
3177 if (rc
== 0 || errno
!= EADDRINUSE
) {
3185 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
3187 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
3191 /****************************************************************************
3193 ***************************************************************************/
3195 static int swrap_listen(int s
, int backlog
)
3198 struct socket_info
*si
= find_socket_info(s
);
3201 return libc_listen(s
, backlog
);
3204 if (si
->bound
== 0) {
3205 ret
= swrap_auto_bind(s
, si
, si
->family
);
3212 ret
= libc_listen(s
, backlog
);
3217 int listen(int s
, int backlog
)
3219 return swrap_listen(s
, backlog
);
3222 /****************************************************************************
3224 ***************************************************************************/
3226 static FILE *swrap_fopen(const char *name
, const char *mode
)
3230 fp
= libc_fopen(name
, mode
);
3232 int fd
= fileno(fp
);
3234 swrap_remove_stale(fd
);
3240 FILE *fopen(const char *name
, const char *mode
)
3242 return swrap_fopen(name
, mode
);
3245 /****************************************************************************
3247 ***************************************************************************/
3249 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
3253 ret
= libc_vopen(pathname
, flags
, ap
);
3256 * There are methods for closing descriptors (libc-internal code
3257 * paths, direct syscalls) which close descriptors in ways that
3258 * we can't intercept, so try to recover when we notice that
3261 swrap_remove_stale(ret
);
3266 int open(const char *pathname
, int flags
, ...)
3271 va_start(ap
, flags
);
3272 fd
= swrap_vopen(pathname
, flags
, ap
);
3278 /****************************************************************************
3280 ***************************************************************************/
3282 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3284 struct socket_info
*si
= find_socket_info(s
);
3288 return libc_getpeername(s
, name
, addrlen
);
3291 if (si
->peername
.sa_socklen
== 0)
3297 len
= MIN(*addrlen
, si
->peername
.sa_socklen
);
3302 memcpy(name
, &si
->peername
.sa
.ss
, len
);
3303 *addrlen
= si
->peername
.sa_socklen
;
3308 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3309 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3311 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3314 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
3317 /****************************************************************************
3319 ***************************************************************************/
3321 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3323 struct socket_info
*si
= find_socket_info(s
);
3327 return libc_getsockname(s
, name
, addrlen
);
3330 len
= MIN(*addrlen
, si
->myname
.sa_socklen
);
3335 memcpy(name
, &si
->myname
.sa
.ss
, len
);
3336 *addrlen
= si
->myname
.sa_socklen
;
3341 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3342 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3344 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3347 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
3350 /****************************************************************************
3352 ***************************************************************************/
3355 # ifdef SO_PROTOTYPE /* The Solaris name */
3356 # define SO_PROTOCOL SO_PROTOTYPE
3357 # endif /* SO_PROTOTYPE */
3358 #endif /* SO_PROTOCOL */
3360 static int swrap_getsockopt(int s
, int level
, int optname
,
3361 void *optval
, socklen_t
*optlen
)
3363 struct socket_info
*si
= find_socket_info(s
);
3366 return libc_getsockopt(s
,
3373 if (level
== SOL_SOCKET
) {
3377 if (optval
== NULL
|| optlen
== NULL
||
3378 *optlen
< (socklen_t
)sizeof(int)) {
3383 *optlen
= sizeof(int);
3384 *(int *)optval
= si
->family
;
3386 #endif /* SO_DOMAIN */
3390 if (optval
== NULL
|| optlen
== NULL
||
3391 *optlen
< (socklen_t
)sizeof(int)) {
3396 *optlen
= sizeof(int);
3397 *(int *)optval
= si
->protocol
;
3399 #endif /* SO_PROTOCOL */
3401 if (optval
== NULL
|| optlen
== NULL
||
3402 *optlen
< (socklen_t
)sizeof(int)) {
3407 *optlen
= sizeof(int);
3408 *(int *)optval
= si
->type
;
3411 return libc_getsockopt(s
,
3417 } else if (level
== IPPROTO_TCP
) {
3422 * This enables sending packets directly out over TCP.
3423 * As a unix socket is doing that any way, report it as
3426 if (optval
== NULL
|| optlen
== NULL
||
3427 *optlen
< (socklen_t
)sizeof(int)) {
3432 *optlen
= sizeof(int);
3433 *(int *)optval
= si
->tcp_nodelay
;
3436 #endif /* TCP_NODELAY */
3442 errno
= ENOPROTOOPT
;
3446 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3447 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
3449 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
3452 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
3455 /****************************************************************************
3457 ***************************************************************************/
3459 static int swrap_setsockopt(int s
, int level
, int optname
,
3460 const void *optval
, socklen_t optlen
)
3462 struct socket_info
*si
= find_socket_info(s
);
3465 return libc_setsockopt(s
,
3472 if (level
== SOL_SOCKET
) {
3473 return libc_setsockopt(s
,
3478 } else if (level
== IPPROTO_TCP
) {
3485 * This enables sending packets directly out over TCP.
3486 * A unix socket is doing that any way.
3488 if (optval
== NULL
|| optlen
== 0 ||
3489 optlen
< (socklen_t
)sizeof(int)) {
3494 i
= *discard_const_p(int, optval
);
3495 if (i
!= 0 && i
!= 1) {
3499 si
->tcp_nodelay
= i
;
3503 #endif /* TCP_NODELAY */
3509 switch (si
->family
) {
3511 if (level
== IPPROTO_IP
) {
3513 if (optname
== IP_PKTINFO
) {
3514 si
->pktinfo
= AF_INET
;
3516 #endif /* IP_PKTINFO */
3521 if (level
== IPPROTO_IPV6
) {
3522 #ifdef IPV6_RECVPKTINFO
3523 if (optname
== IPV6_RECVPKTINFO
) {
3524 si
->pktinfo
= AF_INET6
;
3526 #endif /* IPV6_PKTINFO */
3531 errno
= ENOPROTOOPT
;
3536 int setsockopt(int s
, int level
, int optname
,
3537 const void *optval
, socklen_t optlen
)
3539 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
3542 /****************************************************************************
3544 ***************************************************************************/
3546 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
3548 struct socket_info
*si
= find_socket_info(s
);
3554 return libc_vioctl(s
, r
, va
);
3559 rc
= libc_vioctl(s
, r
, va
);
3563 value
= *((int *)va_arg(ap
, int *));
3565 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
3566 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3567 } else if (value
== 0) { /* END OF FILE */
3568 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3578 #ifdef HAVE_IOCTL_INT
3579 int ioctl(int s
, int r
, ...)
3581 int ioctl(int s
, unsigned long int r
, ...)
3589 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
3600 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3603 # ifdef _ALIGN /* BSD */
3604 #define CMSG_ALIGN _ALIGN
3606 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3607 # endif /* _ALIGN */
3608 #endif /* CMSG_ALIGN */
3611 * @brief Add a cmsghdr to a msghdr.
3613 * This is an function to add any type of cmsghdr. It will operate on the
3614 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3615 * the buffer position after the added cmsg element. Hence, this function is
3616 * intended to be used with an intermediate msghdr and not on the original
3617 * one handed in by the client.
3619 * @param[in] msg The msghdr to which to add the cmsg.
3621 * @param[in] level The cmsg level to set.
3623 * @param[in] type The cmsg type to set.
3625 * @param[in] data The cmsg data to set.
3627 * @param[in] len the length of the data to set.
3629 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3635 size_t cmlen
= CMSG_LEN(len
);
3636 size_t cmspace
= CMSG_SPACE(len
);
3637 uint8_t cmbuf
[cmspace
];
3638 void *cast_ptr
= (void *)cmbuf
;
3639 struct cmsghdr
*cm
= (struct cmsghdr
*)cast_ptr
;
3642 memset(cmbuf
, 0, cmspace
);
3644 if (msg
->msg_controllen
< cmlen
) {
3645 cmlen
= msg
->msg_controllen
;
3646 msg
->msg_flags
|= MSG_CTRUNC
;
3649 if (msg
->msg_controllen
< cmspace
) {
3650 cmspace
= msg
->msg_controllen
;
3654 * We copy the full input data into an intermediate cmsghdr first
3655 * in order to more easily cope with truncation.
3657 cm
->cmsg_len
= cmlen
;
3658 cm
->cmsg_level
= level
;
3659 cm
->cmsg_type
= type
;
3660 memcpy(CMSG_DATA(cm
), data
, len
);
3663 * We now copy the possibly truncated buffer.
3664 * We copy cmlen bytes, but consume cmspace bytes,
3665 * leaving the possible padding uninitialiazed.
3667 p
= (uint8_t *)msg
->msg_control
;
3668 memcpy(p
, cm
, cmlen
);
3670 msg
->msg_control
= p
;
3671 msg
->msg_controllen
-= cmspace
;
3676 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3679 /* Add packet info */
3680 switch (si
->pktinfo
) {
3681 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3683 struct sockaddr_in
*sin
;
3684 #if defined(HAVE_STRUCT_IN_PKTINFO)
3685 struct in_pktinfo pkt
;
3686 #elif defined(IP_RECVDSTADDR)
3690 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in
)) {
3691 sin
= &si
->bindname
.sa
.in
;
3693 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in
)) {
3696 sin
= &si
->myname
.sa
.in
;
3701 #if defined(HAVE_STRUCT_IN_PKTINFO)
3702 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3703 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3704 #elif defined(IP_RECVDSTADDR)
3705 pkt
= sin
->sin_addr
;
3708 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3713 #endif /* IP_PKTINFO */
3714 #if defined(HAVE_IPV6)
3716 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3717 struct sockaddr_in6
*sin6
;
3718 struct in6_pktinfo pkt6
;
3720 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in6
)) {
3721 sin6
= &si
->bindname
.sa
.in6
;
3723 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in6
)) {
3726 sin6
= &si
->myname
.sa
.in6
;
3731 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3732 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3734 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3735 &pkt6
, sizeof(pkt6
));
3736 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3740 #endif /* IPV6_PKTINFO */
3748 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3749 struct msghdr
*omsg
)
3753 if (si
->pktinfo
> 0) {
3754 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3760 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3762 size_t *cm_data_space
);
3763 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3765 size_t *cm_data_space
);
3767 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
3769 size_t *cm_data_space
) {
3770 struct cmsghdr
*cmsg
;
3774 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
3778 for (cmsg
= CMSG_FIRSTHDR(msg
);
3780 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
3781 switch (cmsg
->cmsg_level
) {
3783 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
3788 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
3798 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3800 size_t *cm_data_space
)
3805 cmspace
= *cm_data_space
+ CMSG_ALIGN(cmsg
->cmsg_len
);
3807 p
= realloc((*cm_data
), cmspace
);
3813 p
= (*cm_data
) + (*cm_data_space
);
3814 *cm_data_space
= cmspace
;
3816 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
3821 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3823 size_t *cm_data_space
);
3826 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3828 size_t *cm_data_space
)
3832 switch(cmsg
->cmsg_type
) {
3835 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3842 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3854 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3856 size_t *cm_data_space
)
3858 (void)cmsg
; /* unused */
3859 (void)cm_data
; /* unused */
3860 (void)cm_data_space
; /* unused */
3863 * Passing a IP pktinfo to a unix socket might be rejected by the
3864 * Kernel, at least on FreeBSD. So skip this cmsg.
3868 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3870 static ssize_t
swrap_sendmsg_before(int fd
,
3871 struct socket_info
*si
,
3873 struct iovec
*tmp_iov
,
3874 struct sockaddr_un
*tmp_un
,
3875 const struct sockaddr_un
**to_un
,
3876 const struct sockaddr
**to
,
3896 if (!si
->connected
) {
3901 if (msg
->msg_iovlen
== 0) {
3905 mtu
= socket_wrapper_mtu();
3906 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3908 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3913 msg
->msg_iovlen
= i
;
3914 if (msg
->msg_iovlen
== 0) {
3915 *tmp_iov
= msg
->msg_iov
[0];
3916 tmp_iov
->iov_len
= MIN((size_t)tmp_iov
->iov_len
,
3918 msg
->msg_iov
= tmp_iov
;
3919 msg
->msg_iovlen
= 1;
3924 if (si
->connected
) {
3925 if (msg
->msg_name
!= NULL
) {
3927 * We are dealing with unix sockets and if we
3928 * are connected, we should only talk to the
3929 * connected unix path. Using the fd to send
3930 * to another server would be hard to achieve.
3932 msg
->msg_name
= NULL
;
3933 msg
->msg_namelen
= 0;
3936 const struct sockaddr
*msg_name
;
3937 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3939 if (msg_name
== NULL
) {
3945 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3947 if (ret
== -1) return -1;
3955 msg
->msg_name
= tmp_un
;
3956 msg
->msg_namelen
= sizeof(*tmp_un
);
3959 if (si
->bound
== 0) {
3960 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3962 if (errno
== ENOTSOCK
) {
3963 swrap_remove_stale(fd
);
3966 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3972 if (!si
->defer_connect
) {
3976 ret
= sockaddr_convert_to_un(si
,
3978 si
->peername
.sa_socklen
,
3982 if (ret
== -1) return -1;
3984 ret
= libc_connect(fd
,
3985 (struct sockaddr
*)(void *)tmp_un
,
3988 /* to give better errors */
3989 if (ret
== -1 && errno
== ENOENT
) {
3990 errno
= EHOSTUNREACH
;
3997 si
->defer_connect
= 0;
4000 errno
= EHOSTUNREACH
;
4004 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4005 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
4006 uint8_t *cmbuf
= NULL
;
4009 ret
= swrap_sendmsg_filter_cmsghdr(msg
, &cmbuf
, &cmlen
);
4016 msg
->msg_controllen
= 0;
4017 msg
->msg_control
= NULL
;
4018 } else if (cmlen
< msg
->msg_controllen
&& cmbuf
!= NULL
) {
4019 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
4020 msg
->msg_controllen
= cmlen
;
4029 static void swrap_sendmsg_after(int fd
,
4030 struct socket_info
*si
,
4032 const struct sockaddr
*to
,
4035 int saved_errno
= errno
;
4042 /* to give better errors */
4044 if (saved_errno
== ENOENT
) {
4045 saved_errno
= EHOSTUNREACH
;
4046 } else if (saved_errno
== ENOTSOCK
) {
4047 /* If the fd is not a socket, remove it */
4048 swrap_remove_stale(fd
);
4052 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4053 avail
+= msg
->msg_iov
[i
].iov_len
;
4057 remain
= MIN(80, avail
);
4062 /* we capture it as one single packet */
4063 buf
= (uint8_t *)malloc(remain
);
4065 /* we just not capture the packet */
4066 errno
= saved_errno
;
4070 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4071 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
4073 msg
->msg_iov
[i
].iov_base
,
4076 remain
-= this_time
;
4083 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
4084 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
4086 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
4091 if (si
->connected
) {
4092 to
= &si
->peername
.sa
.s
;
4095 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4096 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
4098 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4104 errno
= saved_errno
;
4107 static int swrap_recvmsg_before(int fd
,
4108 struct socket_info
*si
,
4110 struct iovec
*tmp_iov
)
4115 (void)fd
; /* unused */
4120 if (!si
->connected
) {
4125 if (msg
->msg_iovlen
== 0) {
4129 mtu
= socket_wrapper_mtu();
4130 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4132 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
4137 msg
->msg_iovlen
= i
;
4138 if (msg
->msg_iovlen
== 0) {
4139 *tmp_iov
= msg
->msg_iov
[0];
4140 tmp_iov
->iov_len
= MIN((size_t)tmp_iov
->iov_len
,
4142 msg
->msg_iov
= tmp_iov
;
4143 msg
->msg_iovlen
= 1;
4148 if (msg
->msg_name
== NULL
) {
4153 if (msg
->msg_iovlen
== 0) {
4157 if (si
->bound
== 0) {
4158 ret
= swrap_auto_bind(fd
, si
, si
->family
);
4161 * When attempting to read or write to a
4162 * descriptor, if an underlying autobind fails
4163 * because it's not a socket, stop intercepting
4164 * uses of that descriptor.
4166 if (errno
== ENOTSOCK
) {
4167 swrap_remove_stale(fd
);
4170 SWRAP_LOG(SWRAP_LOG_ERROR
,
4171 "swrap_recvmsg_before failed");
4178 errno
= EHOSTUNREACH
;
4185 static int swrap_recvmsg_after(int fd
,
4186 struct socket_info
*si
,
4188 const struct sockaddr_un
*un_addr
,
4189 socklen_t un_addrlen
,
4192 int saved_errno
= errno
;
4194 uint8_t *buf
= NULL
;
4200 /* to give better errors */
4202 if (saved_errno
== ENOENT
) {
4203 saved_errno
= EHOSTUNREACH
;
4204 } else if (saved_errno
== ENOTSOCK
) {
4205 /* If the fd is not a socket, remove it */
4206 swrap_remove_stale(fd
);
4210 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4211 avail
+= msg
->msg_iov
[i
].iov_len
;
4214 /* Convert the socket address before we leave */
4215 if (si
->type
== SOCK_DGRAM
&& un_addr
!= NULL
) {
4216 rc
= sockaddr_convert_from_un(si
,
4233 remain
= MIN(80, avail
);
4238 /* we capture it as one single packet */
4239 buf
= (uint8_t *)malloc(remain
);
4241 /* we just not capture the packet */
4242 errno
= saved_errno
;
4246 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4247 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
4249 msg
->msg_iov
[i
].iov_base
,
4252 remain
-= this_time
;
4257 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
4258 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4259 } else if (ret
== 0) { /* END OF FILE */
4260 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4261 } else if (ret
> 0) {
4262 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
4271 if (un_addr
!= NULL
) {
4272 swrap_pcap_dump_packet(si
,
4278 swrap_pcap_dump_packet(si
,
4291 errno
= saved_errno
;
4293 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4295 msg
->msg_controllen
> 0 &&
4296 msg
->msg_control
!= NULL
) {
4297 rc
= swrap_msghdr_add_socket_info(si
, msg
);
4307 /****************************************************************************
4309 ***************************************************************************/
4311 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
4312 struct sockaddr
*from
, socklen_t
*fromlen
)
4314 struct swrap_address from_addr
= {
4315 .sa_socklen
= sizeof(struct sockaddr_un
),
4318 struct socket_info
*si
= find_socket_info(s
);
4319 struct swrap_address saddr
= {
4320 .sa_socklen
= sizeof(struct sockaddr_storage
),
4327 return libc_recvfrom(s
,
4339 if (from
!= NULL
&& fromlen
!= NULL
) {
4340 msg
.msg_name
= from
; /* optional address */
4341 msg
.msg_namelen
= *fromlen
; /* size of address */
4343 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4344 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4346 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4347 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4348 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4349 msg
.msg_control
= NULL
; /* ancillary data, see below */
4350 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4351 msg
.msg_flags
= 0; /* flags on received message */
4354 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4359 buf
= msg
.msg_iov
[0].iov_base
;
4360 len
= msg
.msg_iov
[0].iov_len
;
4362 ret
= libc_recvfrom(s
,
4367 &from_addr
.sa_socklen
);
4372 tret
= swrap_recvmsg_after(s
,
4376 from_addr
.sa_socklen
,
4382 if (from
!= NULL
&& fromlen
!= NULL
) {
4383 *fromlen
= msg
.msg_namelen
;
4389 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4390 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4391 struct sockaddr
*from
, Psocklen_t fromlen
)
4393 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4394 struct sockaddr
*from
, socklen_t
*fromlen
)
4397 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
4400 /****************************************************************************
4402 ***************************************************************************/
4404 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
4405 const struct sockaddr
*to
, socklen_t tolen
)
4409 struct swrap_address un_addr
= {
4410 .sa_socklen
= sizeof(struct sockaddr_un
),
4412 const struct sockaddr_un
*to_un
= NULL
;
4415 struct socket_info
*si
= find_socket_info(s
);
4419 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
4422 tmp
.iov_base
= discard_const_p(char, buf
);
4426 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
4427 msg
.msg_namelen
= tolen
; /* size of address */
4428 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4429 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4430 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4431 msg
.msg_control
= NULL
; /* ancillary data, see below */
4432 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4433 msg
.msg_flags
= 0; /* flags on received message */
4436 rc
= swrap_sendmsg_before(s
,
4448 buf
= msg
.msg_iov
[0].iov_base
;
4449 len
= msg
.msg_iov
[0].iov_len
;
4454 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
4457 type
= SOCKET_TYPE_CHAR_UDP
;
4459 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4460 snprintf(un_addr
.sa
.un
.sun_path
,
4461 sizeof(un_addr
.sa
.un
.sun_path
),
4463 socket_wrapper_dir(), type
, iface
, prt
);
4464 if (stat(un_addr
.sa
.un
.sun_path
, &st
) != 0) continue;
4466 /* ignore the any errors in broadcast sends */
4472 un_addr
.sa_socklen
);
4475 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4481 * If it is a dgram socket and we are connected, don't include the
4484 if (si
->type
== SOCK_DGRAM
&& si
->connected
) {
4485 ret
= libc_sendto(s
,
4492 ret
= libc_sendto(s
,
4496 (struct sockaddr
*)msg
.msg_name
,
4500 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4505 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
4506 const struct sockaddr
*to
, socklen_t tolen
)
4508 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
4511 /****************************************************************************
4513 ***************************************************************************/
4515 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
4517 struct socket_info
*si
;
4519 struct swrap_address saddr
= {
4520 .sa_socklen
= sizeof(struct sockaddr_storage
),
4526 si
= find_socket_info(s
);
4528 return libc_recv(s
, buf
, len
, flags
);
4535 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4536 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4537 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4538 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4539 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4540 msg
.msg_control
= NULL
; /* ancillary data, see below */
4541 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4542 msg
.msg_flags
= 0; /* flags on received message */
4545 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4550 buf
= msg
.msg_iov
[0].iov_base
;
4551 len
= msg
.msg_iov
[0].iov_len
;
4553 ret
= libc_recv(s
, buf
, len
, flags
);
4555 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4563 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
4565 return swrap_recv(s
, buf
, len
, flags
);
4568 /****************************************************************************
4570 ***************************************************************************/
4572 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
4574 struct socket_info
*si
;
4577 struct swrap_address saddr
= {
4578 .sa_socklen
= sizeof(struct sockaddr_storage
),
4583 si
= find_socket_info(s
);
4585 return libc_read(s
, buf
, len
);
4592 msg
.msg_name
= &saddr
.sa
.ss
; /* optional address */
4593 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4594 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4595 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4596 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4597 msg
.msg_control
= NULL
; /* ancillary data, see below */
4598 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4599 msg
.msg_flags
= 0; /* flags on received message */
4602 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4604 if (tret
== -ENOTSOCK
) {
4605 return libc_read(s
, buf
, len
);
4610 buf
= msg
.msg_iov
[0].iov_base
;
4611 len
= msg
.msg_iov
[0].iov_len
;
4613 ret
= libc_read(s
, buf
, len
);
4615 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4623 ssize_t
read(int s
, void *buf
, size_t len
)
4625 return swrap_read(s
, buf
, len
);
4628 /****************************************************************************
4630 ***************************************************************************/
4632 static ssize_t
swrap_write(int s
, const void *buf
, size_t len
)
4636 struct sockaddr_un un_addr
;
4639 struct socket_info
*si
;
4641 si
= find_socket_info(s
);
4643 return libc_write(s
, buf
, len
);
4646 tmp
.iov_base
= discard_const_p(char, buf
);
4650 msg
.msg_name
= NULL
; /* optional address */
4651 msg
.msg_namelen
= 0; /* size of address */
4652 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4653 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4654 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4655 msg
.msg_control
= NULL
; /* ancillary data, see below */
4656 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4657 msg
.msg_flags
= 0; /* flags on received message */
4660 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4665 buf
= msg
.msg_iov
[0].iov_base
;
4666 len
= msg
.msg_iov
[0].iov_len
;
4668 ret
= libc_write(s
, buf
, len
);
4670 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4675 ssize_t
write(int s
, const void *buf
, size_t len
)
4677 return swrap_write(s
, buf
, len
);
4680 /****************************************************************************
4682 ***************************************************************************/
4684 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
4688 struct sockaddr_un un_addr
;
4691 struct socket_info
*si
= find_socket_info(s
);
4694 return libc_send(s
, buf
, len
, flags
);
4697 tmp
.iov_base
= discard_const_p(char, buf
);
4701 msg
.msg_name
= NULL
; /* optional address */
4702 msg
.msg_namelen
= 0; /* size of address */
4703 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4704 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4705 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4706 msg
.msg_control
= NULL
; /* ancillary data, see below */
4707 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4708 msg
.msg_flags
= 0; /* flags on received message */
4711 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4716 buf
= msg
.msg_iov
[0].iov_base
;
4717 len
= msg
.msg_iov
[0].iov_len
;
4719 ret
= libc_send(s
, buf
, len
, flags
);
4721 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4726 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
4728 return swrap_send(s
, buf
, len
, flags
);
4731 /****************************************************************************
4733 ***************************************************************************/
4735 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
4737 struct swrap_address from_addr
= {
4738 .sa_socklen
= sizeof(struct sockaddr_un
),
4740 struct swrap_address convert_addr
= {
4741 .sa_socklen
= sizeof(struct sockaddr_storage
),
4743 struct socket_info
*si
;
4746 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4747 size_t msg_ctrllen_filled
;
4748 size_t msg_ctrllen_left
;
4754 si
= find_socket_info(s
);
4756 return libc_recvmsg(s
, omsg
, flags
);
4759 tmp
.iov_base
= NULL
;
4763 msg
.msg_name
= &from_addr
.sa
; /* optional address */
4764 msg
.msg_namelen
= from_addr
.sa_socklen
; /* size of address */
4765 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4766 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4767 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4768 msg_ctrllen_filled
= 0;
4769 msg_ctrllen_left
= omsg
->msg_controllen
;
4771 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
4772 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4773 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4776 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4781 ret
= libc_recvmsg(s
, &msg
, flags
);
4783 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4784 msg_ctrllen_filled
+= msg
.msg_controllen
;
4785 msg_ctrllen_left
-= msg
.msg_controllen
;
4787 if (omsg
->msg_control
!= NULL
) {
4790 p
= omsg
->msg_control
;
4791 p
+= msg_ctrllen_filled
;
4793 msg
.msg_control
= p
;
4794 msg
.msg_controllen
= msg_ctrllen_left
;
4796 msg
.msg_control
= NULL
;
4797 msg
.msg_controllen
= 0;
4802 * We convert the unix address to a IP address so we need a buffer
4803 * which can store the address in case of SOCK_DGRAM, see below.
4805 msg
.msg_name
= &convert_addr
.sa
;
4806 msg
.msg_namelen
= convert_addr
.sa_socklen
;
4808 rc
= swrap_recvmsg_after(s
,
4812 from_addr
.sa_socklen
,
4818 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4819 if (omsg
->msg_control
!= NULL
) {
4820 /* msg.msg_controllen = space left */
4821 msg_ctrllen_left
= msg
.msg_controllen
;
4822 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
4825 /* Update the original message length */
4826 omsg
->msg_controllen
= msg_ctrllen_filled
;
4827 omsg
->msg_flags
= msg
.msg_flags
;
4829 omsg
->msg_iovlen
= msg
.msg_iovlen
;
4834 * The msg_name field points to a caller-allocated buffer that is
4835 * used to return the source address if the socket is unconnected. The
4836 * caller should set msg_namelen to the size of this buffer before this
4837 * call; upon return from a successful call, msg_name will contain the
4838 * length of the returned address. If the application does not need
4839 * to know the source address, msg_name can be specified as NULL.
4841 if (si
->type
== SOCK_STREAM
) {
4842 omsg
->msg_namelen
= 0;
4843 } else if (omsg
->msg_name
!= NULL
&&
4844 omsg
->msg_namelen
!= 0 &&
4845 omsg
->msg_namelen
>= msg
.msg_namelen
) {
4846 memcpy(omsg
->msg_name
, msg
.msg_name
, msg
.msg_namelen
);
4847 omsg
->msg_namelen
= msg
.msg_namelen
;
4853 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
4855 return swrap_recvmsg(sockfd
, msg
, flags
);
4858 /****************************************************************************
4860 ***************************************************************************/
4862 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4866 struct sockaddr_un un_addr
;
4867 const struct sockaddr_un
*to_un
= NULL
;
4868 const struct sockaddr
*to
= NULL
;
4871 struct socket_info
*si
= find_socket_info(s
);
4875 return libc_sendmsg(s
, omsg
, flags
);
4878 ZERO_STRUCT(un_addr
);
4880 tmp
.iov_base
= NULL
;
4885 if (si
->connected
== 0) {
4886 msg
.msg_name
= omsg
->msg_name
; /* optional address */
4887 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
4889 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4890 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4891 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4892 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
4893 /* omsg is a const so use a local buffer for modifications */
4894 uint8_t cmbuf
[omsg
->msg_controllen
];
4896 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
4898 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
4899 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4901 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4904 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4912 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
4920 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4921 avail
+= msg
.msg_iov
[i
].iov_len
;
4927 /* we capture it as one single packet */
4928 buf
= (uint8_t *)malloc(remain
);
4933 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4934 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4936 msg
.msg_iov
[i
].iov_base
,
4939 remain
-= this_time
;
4942 type
= SOCKET_TYPE_CHAR_UDP
;
4944 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4945 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4946 socket_wrapper_dir(), type
, iface
, prt
);
4947 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4949 msg
.msg_name
= &un_addr
; /* optional address */
4950 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4952 /* ignore the any errors in broadcast sends */
4953 libc_sendmsg(s
, &msg
, flags
);
4956 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4962 ret
= libc_sendmsg(s
, &msg
, flags
);
4964 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4969 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4971 return swrap_sendmsg(s
, omsg
, flags
);
4974 /****************************************************************************
4976 ***************************************************************************/
4978 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4980 struct socket_info
*si
;
4983 struct swrap_address saddr
= {
4984 .sa_socklen
= sizeof(struct sockaddr_storage
)
4989 si
= find_socket_info(s
);
4991 return libc_readv(s
, vector
, count
);
4994 tmp
.iov_base
= NULL
;
4998 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4999 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
5000 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
5001 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
5002 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5003 msg
.msg_control
= NULL
; /* ancillary data, see below */
5004 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5005 msg
.msg_flags
= 0; /* flags on received message */
5008 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
5010 if (rc
== -ENOTSOCK
) {
5011 return libc_readv(s
, vector
, count
);
5016 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
5018 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
5026 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
5028 return swrap_readv(s
, vector
, count
);
5031 /****************************************************************************
5033 ***************************************************************************/
5035 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
5039 struct sockaddr_un un_addr
;
5042 struct socket_info
*si
= find_socket_info(s
);
5045 return libc_writev(s
, vector
, count
);
5048 tmp
.iov_base
= NULL
;
5052 msg
.msg_name
= NULL
; /* optional address */
5053 msg
.msg_namelen
= 0; /* size of address */
5054 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
5055 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
5056 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5057 msg
.msg_control
= NULL
; /* ancillary data, see below */
5058 msg
.msg_controllen
= 0; /* ancillary data buffer len */
5059 msg
.msg_flags
= 0; /* flags on received message */
5062 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
5064 if (rc
== -ENOTSOCK
) {
5065 return libc_readv(s
, vector
, count
);
5070 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
5072 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
5077 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
5079 return swrap_writev(s
, vector
, count
);
5082 /****************************
5084 ***************************/
5086 static int swrap_close(int fd
)
5088 struct socket_info
*si
= find_socket_info(fd
);
5089 struct socket_info_fd
*fi
;
5093 return libc_close(fd
);
5096 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
5098 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
5105 /* there are still references left */
5106 return libc_close(fd
);
5109 SWRAP_DLIST_REMOVE(sockets
, si
);
5111 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
5112 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
5115 ret
= libc_close(fd
);
5117 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
5118 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
5119 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
5122 if (si
->un_addr
.sun_path
[0] != '\0') {
5123 unlink(si
->un_addr
.sun_path
);
5132 return swrap_close(fd
);
5135 /****************************
5137 ***************************/
5139 static int swrap_dup(int fd
)
5141 struct socket_info
*si
;
5142 struct socket_info_fd
*fi
;
5144 si
= find_socket_info(fd
);
5147 return libc_dup(fd
);
5150 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
5156 fi
->fd
= libc_dup(fd
);
5158 int saved_errno
= errno
;
5160 errno
= saved_errno
;
5164 /* Make sure we don't have an entry for the fd */
5165 swrap_remove_stale(fi
->fd
);
5167 SWRAP_DLIST_ADD(si
->fds
, fi
);
5173 return swrap_dup(fd
);
5176 /****************************
5178 ***************************/
5180 static int swrap_dup2(int fd
, int newfd
)
5182 struct socket_info
*si
;
5183 struct socket_info_fd
*fi
;
5185 si
= find_socket_info(fd
);
5188 return libc_dup2(fd
, newfd
);
5191 if (find_socket_info(newfd
)) {
5192 /* dup2() does an implicit close of newfd, which we
5193 * need to emulate */
5197 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
5203 fi
->fd
= libc_dup2(fd
, newfd
);
5205 int saved_errno
= errno
;
5207 errno
= saved_errno
;
5211 /* Make sure we don't have an entry for the fd */
5212 swrap_remove_stale(fi
->fd
);
5214 SWRAP_DLIST_ADD(si
->fds
, fi
);
5218 int dup2(int fd
, int newfd
)
5220 return swrap_dup2(fd
, newfd
);
5223 /****************************
5225 ***************************/
5227 static int swrap_vfcntl(int fd
, int cmd
, va_list va
)
5229 struct socket_info_fd
*fi
;
5230 struct socket_info
*si
;
5233 si
= find_socket_info(fd
);
5235 rc
= libc_vfcntl(fd
, cmd
, va
);
5242 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
5248 fi
->fd
= libc_vfcntl(fd
, cmd
, va
);
5250 int saved_errno
= errno
;
5252 errno
= saved_errno
;
5256 /* Make sure we don't have an entry for the fd */
5257 swrap_remove_stale(fi
->fd
);
5259 SWRAP_DLIST_ADD(si
->fds
, fi
);
5264 rc
= libc_vfcntl(fd
, cmd
, va
);
5271 int fcntl(int fd
, int cmd
, ...)
5278 rc
= swrap_vfcntl(fd
, cmd
, va
);
5285 /****************************
5287 ***************************/
5290 static int swrap_eventfd(int count
, int flags
)
5294 fd
= libc_eventfd(count
, flags
);
5296 swrap_remove_stale(fd
);
5302 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5303 int eventfd(unsigned int count
, int flags
)
5305 int eventfd(int count
, int flags
)
5308 return swrap_eventfd(count
, flags
);
5313 int pledge(const char *promises
, const char *paths
[])
5315 (void)promises
; /* unused */
5316 (void)paths
; /* unused */
5320 #endif /* HAVE_PLEDGE */
5322 /****************************
5324 ***************************/
5327 * This function is called when the library is unloaded and makes sure that
5328 * sockets get closed and the unix file for the socket are unlinked.
5330 void swrap_destructor(void)
5332 struct socket_info
*s
= sockets
;
5335 struct socket_info_fd
*f
= s
->fds
;
5342 if (swrap
.libc_handle
!= NULL
) {
5343 dlclose(swrap
.libc_handle
);
5345 if (swrap
.libsocket_handle
) {
5346 dlclose(swrap
.libsocket_handle
);