2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <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>
87 /* GCC have printf type attribute check. */
88 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
89 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
91 #define PRINTF_ATTRIBUTE(a,b)
92 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
94 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
95 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
97 #define DESTRUCTOR_ATTRIBUTE
100 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
101 # define SWRAP_THREAD __thread
103 # define SWRAP_THREAD
107 #define MIN(a,b) ((a)<(b)?(a):(b))
111 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
114 #ifndef discard_const
115 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
118 #ifndef discard_const_p
119 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
123 # ifndef IPV6_RECVPKTINFO
124 # define IPV6_RECVPKTINFO IPV6_PKTINFO
125 # endif /* IPV6_RECVPKTINFO */
126 #endif /* IPV6_PKTINFO */
129 * On BSD IP_PKTINFO has a different name because during
130 * the time when they implemented it, there was no RFC.
131 * The name for IPv6 is the same as on Linux.
134 # ifdef IP_RECVDSTADDR
135 # define IP_PKTINFO IP_RECVDSTADDR
140 #define SWRAP_DLIST_ADD(list,item) do { \
142 (item)->prev = NULL; \
143 (item)->next = NULL; \
146 (item)->prev = NULL; \
147 (item)->next = (list); \
148 (list)->prev = (item); \
153 #define SWRAP_DLIST_REMOVE(list,item) do { \
154 if ((list) == (item)) { \
155 (list) = (item)->next; \
157 (list)->prev = NULL; \
160 if ((item)->prev) { \
161 (item)->prev->next = (item)->next; \
163 if ((item)->next) { \
164 (item)->next->prev = (item)->prev; \
167 (item)->prev = NULL; \
168 (item)->next = NULL; \
171 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
172 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
174 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
177 /* we need to use a very terse format here as IRIX 6.4 silently
178 truncates names to 16 chars, so if we use a longer name then we
179 can't tell which port a packet came from with recvfrom()
181 with this format we have 8 chars left for the directory name
183 #define SOCKET_FORMAT "%c%02X%04X"
184 #define SOCKET_TYPE_CHAR_TCP 'T'
185 #define SOCKET_TYPE_CHAR_UDP 'U'
186 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
187 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
190 * Cut down to 1500 byte packets for stream sockets,
191 * which makes it easier to format PCAP capture files
192 * (as the caller will simply continue from here)
194 #define SOCKET_MAX_PACKET 1500
196 #define SOCKET_MAX_SOCKETS 1024
198 /* This limit is to avoid broadcast sendto() needing to stat too many
199 * files. It may be raised (with a performance cost) to up to 254
200 * without changing the format above */
201 #define MAX_WRAPPED_INTERFACES 40
203 struct socket_info_fd
{
204 struct socket_info_fd
*prev
, *next
;
210 struct socket_info_fd
*fds
;
224 struct sockaddr
*bindname
;
225 socklen_t bindname_len
;
227 struct sockaddr
*myname
;
228 socklen_t myname_len
;
230 struct sockaddr
*peername
;
231 socklen_t peername_len
;
234 unsigned long pck_snd
;
235 unsigned long pck_rcv
;
238 struct socket_info
*prev
, *next
;
242 * File descriptors are shared between threads so we should share socket
245 struct socket_info
*sockets
;
247 /* Function prototypes */
249 bool socket_wrapper_enabled(void);
250 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
253 # define SWRAP_LOG(...)
256 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...) PRINTF_ATTRIBUTE(2, 3);
257 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
259 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...)
264 unsigned int lvl
= 0;
266 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
271 va_start(va
, format
);
272 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
277 case SWRAP_LOG_ERROR
:
279 "SWRAP_ERROR(%d): %s\n",
280 (int)getpid(), buffer
);
284 "SWRAP_WARN(%d): %s\n",
285 (int)getpid(), buffer
);
287 case SWRAP_LOG_DEBUG
:
289 "SWRAP_DEBUG(%d): %s\n",
290 (int)getpid(), buffer
);
292 case SWRAP_LOG_TRACE
:
294 "SWRAP_TRACE(%d): %s\n",
295 (int)getpid(), buffer
);
302 /*********************************************************
303 * SWRAP LOADING LIBC FUNCTIONS
304 *********************************************************/
308 struct swrap_libc_fns
{
309 int (*libc_accept
)(int sockfd
,
310 struct sockaddr
*addr
,
312 int (*libc_bind
)(int sockfd
,
313 const struct sockaddr
*addr
,
315 int (*libc_close
)(int fd
);
316 int (*libc_connect
)(int sockfd
,
317 const struct sockaddr
*addr
,
319 int (*libc_dup
)(int fd
);
320 int (*libc_dup2
)(int oldfd
, int newfd
);
322 int (*libc_eventfd
)(int count
, int flags
);
324 int (*libc_getpeername
)(int sockfd
,
325 struct sockaddr
*addr
,
327 int (*libc_getsockname
)(int sockfd
,
328 struct sockaddr
*addr
,
330 int (*libc_getsockopt
)(int sockfd
,
335 int (*libc_ioctl
)(int d
, unsigned long int request
, ...);
336 int (*libc_listen
)(int sockfd
, int backlog
);
337 int (*libc_open
)(const char *pathname
, int flags
, mode_t mode
);
338 int (*libc_pipe
)(int pipefd
[2]);
339 int (*libc_read
)(int fd
, void *buf
, size_t count
);
340 ssize_t (*libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
341 int (*libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
342 int (*libc_recvfrom
)(int sockfd
,
346 struct sockaddr
*src_addr
,
348 int (*libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
349 int (*libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
350 int (*libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
351 int (*libc_sendto
)(int sockfd
,
355 const struct sockaddr
*dst_addr
,
357 int (*libc_setsockopt
)(int sockfd
,
363 int (*libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
365 int (*libc_socket
)(int domain
, int type
, int protocol
);
366 int (*libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
367 #ifdef HAVE_TIMERFD_CREATE
368 int (*libc_timerfd_create
)(int clockid
, int flags
);
370 ssize_t (*libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
375 void *libsocket_handle
;
382 struct swrap_libc_fns fns
;
385 static struct swrap swrap
;
388 static const char *socket_wrapper_dir(void);
390 #define LIBC_NAME "libc.so"
399 static const char *swrap_str_lib(enum swrap_lib lib
)
406 case SWRAP_LIBSOCKET
:
410 /* Compiler would warn us about unhandled enum value if we get here */
415 static void *swrap_load_lib_handle(enum swrap_lib lib
)
417 int flags
= RTLD_LAZY
;
422 flags
|= RTLD_DEEPBIND
;
428 case SWRAP_LIBSOCKET
:
429 #ifdef HAVE_LIBSOCKET
430 handle
= swrap
.libsocket_handle
;
431 if (handle
== NULL
) {
432 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
433 char soname
[256] = {0};
435 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
436 handle
= dlopen(soname
, flags
);
439 swrap
.libsocket_handle
= handle
;
445 handle
= swrap
.libc_handle
;
447 if (handle
== NULL
) {
448 handle
= dlopen(LIBC_SO
, flags
);
450 swrap
.libc_handle
= handle
;
453 if (handle
== NULL
) {
454 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
455 char soname
[256] = {0};
457 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
458 handle
= dlopen(soname
, flags
);
461 swrap
.libc_handle
= handle
;
466 if (handle
== NULL
) {
468 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
470 SWRAP_LOG(SWRAP_LOG_ERROR
,
471 "Failed to dlopen library: %s\n",
480 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
485 handle
= swrap_load_lib_handle(lib
);
487 func
= dlsym(handle
, fn_name
);
489 SWRAP_LOG(SWRAP_LOG_ERROR
,
490 "Failed to find %s: %s\n",
495 SWRAP_LOG(SWRAP_LOG_TRACE
,
497 fn_name
, swrap_str_lib(lib
));
501 #define swrap_load_lib_function(lib, fn_name) \
502 if (swrap.fns.libc_##fn_name == NULL) { \
503 *(void **) (&swrap.fns.libc_##fn_name) = \
504 _swrap_load_lib_function(lib, #fn_name); \
511 * Functions especially from libc need to be loaded individually, you can't load
512 * all at once or gdb will segfault at startup. The same applies to valgrind and
513 * has probably something todo with with the linker.
514 * So we need load each function at the point it is called the first time.
516 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
518 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
520 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
523 static int libc_bind(int sockfd
,
524 const struct sockaddr
*addr
,
527 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
529 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
532 static int libc_close(int fd
)
534 swrap_load_lib_function(SWRAP_LIBC
, close
);
536 return swrap
.fns
.libc_close(fd
);
539 static int libc_connect(int sockfd
,
540 const struct sockaddr
*addr
,
543 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
545 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
548 static int libc_dup(int fd
)
550 swrap_load_lib_function(SWRAP_LIBC
, dup
);
552 return swrap
.fns
.libc_dup(fd
);
555 static int libc_dup2(int oldfd
, int newfd
)
557 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
559 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
563 static int libc_eventfd(int count
, int flags
)
565 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
567 return swrap
.fns
.libc_eventfd(count
, flags
);
571 static int libc_getpeername(int sockfd
,
572 struct sockaddr
*addr
,
575 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
577 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
580 static int libc_getsockname(int sockfd
,
581 struct sockaddr
*addr
,
584 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
586 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
589 static int libc_getsockopt(int sockfd
,
595 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
597 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
600 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
606 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
608 for (i
= 0; i
< 4; i
++) {
609 args
[i
] = va_arg(ap
, long int);
612 rc
= swrap
.fns
.libc_ioctl(d
,
622 static int libc_listen(int sockfd
, int backlog
)
624 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
626 return swrap
.fns
.libc_listen(sockfd
, backlog
);
629 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
634 swrap_load_lib_function(SWRAP_LIBC
, open
);
636 mode
= va_arg(ap
, long int);
638 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
643 static int libc_open(const char *pathname
, int flags
, ...)
649 fd
= libc_vopen(pathname
, flags
, ap
);
655 static int libc_pipe(int pipefd
[2])
657 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
659 return swrap
.fns
.libc_pipe(pipefd
);
662 static int libc_read(int fd
, void *buf
, size_t count
)
664 swrap_load_lib_function(SWRAP_LIBC
, read
);
666 return swrap
.fns
.libc_read(fd
, buf
, count
);
669 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
671 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
673 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
676 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
678 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
680 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
683 static int libc_recvfrom(int sockfd
,
687 struct sockaddr
*src_addr
,
690 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
692 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
695 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
697 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
699 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
702 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
704 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
706 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
709 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
711 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
713 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
716 static int libc_sendto(int sockfd
,
720 const struct sockaddr
*dst_addr
,
723 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
725 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
728 static int libc_setsockopt(int sockfd
,
734 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
736 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
740 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
742 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
744 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
748 static int libc_socket(int domain
, int type
, int protocol
)
750 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
752 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
755 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
757 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
759 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
762 #ifdef HAVE_TIMERFD_CREATE
763 static int libc_timerfd_create(int clockid
, int flags
)
765 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
767 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
771 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
773 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
775 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
778 /*********************************************************
779 * SWRAP HELPER FUNCTIONS
780 *********************************************************/
786 static const struct in6_addr
*swrap_ipv6(void)
788 static struct in6_addr v
;
789 static int initialized
;
797 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
806 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
808 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
809 memcpy(ret
, data
, len
);
813 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
817 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
821 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
827 static size_t socket_length(int family
)
831 return sizeof(struct sockaddr_in
);
834 return sizeof(struct sockaddr_in6
);
840 static const char *socket_wrapper_dir(void)
842 const char *s
= getenv("SOCKET_WRAPPER_DIR");
846 if (strncmp(s
, "./", 2) == 0) {
850 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
854 bool socket_wrapper_enabled(void)
856 const char *s
= socket_wrapper_dir();
858 return s
!= NULL
? true : false;
861 static unsigned int socket_wrapper_default_iface(void)
863 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
866 if (sscanf(s
, "%u", &iface
) == 1) {
867 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
873 return 1;/* 127.0.0.1 */
876 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
883 p
= strrchr(un
->sun_path
, '/');
884 if (p
) p
++; else p
= un
->sun_path
;
886 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
891 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
894 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
905 case SOCKET_TYPE_CHAR_TCP
:
906 case SOCKET_TYPE_CHAR_UDP
: {
907 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
909 if ((*len
) < sizeof(*in2
)) {
914 memset(in2
, 0, sizeof(*in2
));
915 in2
->sin_family
= AF_INET
;
916 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
917 in2
->sin_port
= htons(prt
);
923 case SOCKET_TYPE_CHAR_TCP_V6
:
924 case SOCKET_TYPE_CHAR_UDP_V6
: {
925 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
927 if ((*len
) < sizeof(*in2
)) {
932 memset(in2
, 0, sizeof(*in2
));
933 in2
->sin6_family
= AF_INET6
;
934 in2
->sin6_addr
= *swrap_ipv6();
935 in2
->sin6_addr
.s6_addr
[15] = iface
;
936 in2
->sin6_port
= htons(prt
);
950 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
958 if (bcast
) *bcast
= 0;
960 switch (inaddr
->sa_family
) {
962 const struct sockaddr_in
*in
=
963 (const struct sockaddr_in
*)(const void *)inaddr
;
964 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
971 u_type
= SOCKET_TYPE_CHAR_TCP
;
974 u_type
= SOCKET_TYPE_CHAR_UDP
;
975 a_type
= SOCKET_TYPE_CHAR_UDP
;
976 b_type
= SOCKET_TYPE_CHAR_UDP
;
979 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
980 errno
= ESOCKTNOSUPPORT
;
984 prt
= ntohs(in
->sin_port
);
985 if (a_type
&& addr
== 0xFFFFFFFF) {
986 /* 255.255.255.255 only udp */
989 iface
= socket_wrapper_default_iface();
990 } else if (b_type
&& addr
== 0x7FFFFFFF) {
991 /* 127.255.255.255 only udp */
994 iface
= socket_wrapper_default_iface();
995 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
999 iface
= (addr
& 0x000000FF);
1001 errno
= ENETUNREACH
;
1004 if (bcast
) *bcast
= is_bcast
;
1009 const struct sockaddr_in6
*in
=
1010 (const struct sockaddr_in6
*)(const void *)inaddr
;
1011 struct in6_addr cmp1
, cmp2
;
1015 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1018 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1021 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1022 errno
= ESOCKTNOSUPPORT
;
1026 /* XXX no multicast/broadcast */
1028 prt
= ntohs(in
->sin6_port
);
1030 cmp1
= *swrap_ipv6();
1031 cmp2
= in
->sin6_addr
;
1032 cmp2
.s6_addr
[15] = 0;
1033 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1034 iface
= in
->sin6_addr
.s6_addr
[15];
1036 errno
= ENETUNREACH
;
1044 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1045 errno
= ENETUNREACH
;
1050 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1056 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1057 socket_wrapper_dir());
1058 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1059 /* the caller need to do more processing */
1063 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1064 socket_wrapper_dir(), type
, iface
, prt
);
1065 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1070 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1079 if (bcast
) *bcast
= 0;
1081 switch (si
->family
) {
1083 const struct sockaddr_in
*in
=
1084 (const struct sockaddr_in
*)(const void *)inaddr
;
1085 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1091 prt
= ntohs(in
->sin_port
);
1095 u_type
= SOCKET_TYPE_CHAR_TCP
;
1096 d_type
= SOCKET_TYPE_CHAR_TCP
;
1099 u_type
= SOCKET_TYPE_CHAR_UDP
;
1100 d_type
= SOCKET_TYPE_CHAR_UDP
;
1101 a_type
= SOCKET_TYPE_CHAR_UDP
;
1102 b_type
= SOCKET_TYPE_CHAR_UDP
;
1105 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1106 errno
= ESOCKTNOSUPPORT
;
1114 iface
= socket_wrapper_default_iface();
1115 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1116 /* 255.255.255.255 only udp */
1119 iface
= socket_wrapper_default_iface();
1120 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1121 /* 127.255.255.255 only udp */
1124 iface
= socket_wrapper_default_iface();
1125 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1129 iface
= (addr
& 0x000000FF);
1131 errno
= EADDRNOTAVAIL
;
1135 /* Store the bind address for connect() */
1136 if (si
->bindname
== NULL
) {
1137 struct sockaddr_in bind_in
;
1138 socklen_t blen
= sizeof(struct sockaddr_in
);
1140 ZERO_STRUCT(bind_in
);
1141 bind_in
.sin_family
= in
->sin_family
;
1142 bind_in
.sin_port
= in
->sin_port
;
1143 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1145 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1146 si
->bindname_len
= blen
;
1153 const struct sockaddr_in6
*in
=
1154 (const struct sockaddr_in6
*)(const void *)inaddr
;
1155 struct in6_addr cmp1
, cmp2
;
1159 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1162 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1165 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1166 errno
= ESOCKTNOSUPPORT
;
1170 /* XXX no multicast/broadcast */
1172 prt
= ntohs(in
->sin6_port
);
1174 cmp1
= *swrap_ipv6();
1175 cmp2
= in
->sin6_addr
;
1176 cmp2
.s6_addr
[15] = 0;
1177 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1178 iface
= socket_wrapper_default_iface();
1179 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1180 iface
= in
->sin6_addr
.s6_addr
[15];
1182 errno
= EADDRNOTAVAIL
;
1186 /* Store the bind address for connect() */
1187 if (si
->bindname
== NULL
) {
1188 struct sockaddr_in6 bind_in
;
1189 socklen_t blen
= sizeof(struct sockaddr_in6
);
1191 ZERO_STRUCT(bind_in
);
1192 bind_in
.sin6_family
= in
->sin6_family
;
1193 bind_in
.sin6_port
= in
->sin6_port
;
1195 bind_in
.sin6_addr
= *swrap_ipv6();
1196 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1198 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1199 si
->bindname_len
= blen
;
1206 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1207 errno
= EADDRNOTAVAIL
;
1212 if (bcast
) *bcast
= is_bcast
;
1214 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1220 /* handle auto-allocation of ephemeral ports */
1221 for (prt
= 5001; prt
< 10000; prt
++) {
1222 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1223 socket_wrapper_dir(), type
, iface
, prt
);
1224 if (stat(un
->sun_path
, &st
) == 0) continue;
1226 set_port(si
->family
, prt
, si
->myname
);
1227 set_port(si
->family
, prt
, si
->bindname
);
1237 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1238 socket_wrapper_dir(), type
, iface
, prt
);
1239 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1243 static struct socket_info
*find_socket_info(int fd
)
1245 struct socket_info
*i
;
1247 for (i
= sockets
; i
; i
= i
->next
) {
1248 struct socket_info_fd
*f
;
1249 for (f
= i
->fds
; f
; f
= f
->next
) {
1259 static void swrap_remove_stale(int fd
)
1261 struct socket_info
*si
= find_socket_info(fd
);
1262 struct socket_info_fd
*fi
;
1265 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1267 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1268 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1274 if (si
->fds
== NULL
) {
1275 SWRAP_DLIST_REMOVE(sockets
, si
);
1280 static int sockaddr_convert_to_un(struct socket_info
*si
,
1281 const struct sockaddr
*in_addr
,
1283 struct sockaddr_un
*out_addr
,
1287 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1289 (void) in_len
; /* unused */
1291 if (out_addr
== NULL
) {
1295 out
->sa_family
= AF_UNIX
;
1296 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1297 out
->sa_len
= sizeof(*out_addr
);
1300 switch (in_addr
->sa_family
) {
1310 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1311 errno
= ESOCKTNOSUPPORT
;
1315 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1317 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1323 errno
= EAFNOSUPPORT
;
1324 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1328 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1329 const struct sockaddr_un
*in_addr
,
1330 socklen_t un_addrlen
,
1332 struct sockaddr
*out_addr
,
1333 socklen_t
*out_addrlen
)
1337 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1340 if (un_addrlen
== 0) {
1355 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1356 errno
= ESOCKTNOSUPPORT
;
1359 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1360 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1361 out_addr
->sa_len
= *out_addrlen
;
1368 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1369 errno
= EAFNOSUPPORT
;
1373 enum swrap_packet_type
{
1375 SWRAP_CONNECT_UNREACH
,
1383 SWRAP_SENDTO_UNREACH
,
1394 struct swrap_file_hdr
{
1396 uint16_t version_major
;
1397 uint16_t version_minor
;
1400 uint32_t frame_max_len
;
1401 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1404 #define SWRAP_FILE_HDR_SIZE 24
1406 struct swrap_packet_frame
{
1408 uint32_t micro_seconds
;
1409 uint32_t recorded_length
;
1410 uint32_t full_length
;
1412 #define SWRAP_PACKET_FRAME_SIZE 16
1414 union swrap_packet_ip
{
1418 uint16_t packet_length
;
1419 uint16_t identification
;
1424 uint16_t hdr_checksum
;
1428 #define SWRAP_PACKET_IP_V4_SIZE 20
1431 uint8_t flow_label_high
;
1432 uint16_t flow_label_low
;
1433 uint16_t payload_length
;
1434 uint8_t next_header
;
1436 uint8_t src_addr
[16];
1437 uint8_t dest_addr
[16];
1439 #define SWRAP_PACKET_IP_V6_SIZE 40
1441 #define SWRAP_PACKET_IP_SIZE 40
1443 union swrap_packet_payload
{
1445 uint16_t source_port
;
1455 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1457 uint16_t source_port
;
1462 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1469 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1476 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1478 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1480 #define SWRAP_PACKET_MIN_ALLOC \
1481 (SWRAP_PACKET_FRAME_SIZE + \
1482 SWRAP_PACKET_IP_SIZE + \
1483 SWRAP_PACKET_PAYLOAD_SIZE)
1485 static const char *socket_wrapper_pcap_file(void)
1487 static int initialized
= 0;
1488 static const char *s
= NULL
;
1489 static const struct swrap_file_hdr h
;
1490 static const struct swrap_packet_frame f
;
1491 static const union swrap_packet_ip i
;
1492 static const union swrap_packet_payload p
;
1494 if (initialized
== 1) {
1500 * TODO: don't use the structs use plain buffer offsets
1501 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1503 * for now make sure we disable PCAP support
1504 * if the struct has alignment!
1506 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1509 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1512 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1515 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1518 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1521 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1524 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1527 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1530 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1533 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1537 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1541 if (strncmp(s
, "./", 2) == 0) {
1547 static uint8_t *swrap_packet_init(struct timeval
*tval
,
1548 const struct sockaddr
*src
,
1549 const struct sockaddr
*dest
,
1551 const uint8_t *payload
,
1553 unsigned long tcp_seqno
,
1554 unsigned long tcp_ack
,
1555 unsigned char tcp_ctl
,
1557 size_t *_packet_len
)
1561 struct swrap_packet_frame
*frame
;
1562 union swrap_packet_ip
*ip
;
1563 union swrap_packet_payload
*pay
;
1566 size_t nonwire_len
= sizeof(*frame
);
1567 size_t wire_hdr_len
= 0;
1568 size_t wire_len
= 0;
1569 size_t ip_hdr_len
= 0;
1570 size_t icmp_hdr_len
= 0;
1571 size_t icmp_truncate_len
= 0;
1572 uint8_t protocol
= 0, icmp_protocol
= 0;
1573 const struct sockaddr_in
*src_in
= NULL
;
1574 const struct sockaddr_in
*dest_in
= NULL
;
1576 const struct sockaddr_in6
*src_in6
= NULL
;
1577 const struct sockaddr_in6
*dest_in6
= NULL
;
1582 switch (src
->sa_family
) {
1584 src_in
= (const struct sockaddr_in
*)src
;
1585 dest_in
= (const struct sockaddr_in
*)dest
;
1586 src_port
= src_in
->sin_port
;
1587 dest_port
= dest_in
->sin_port
;
1588 ip_hdr_len
= sizeof(ip
->v4
);
1592 src_in6
= (const struct sockaddr_in6
*)src
;
1593 dest_in6
= (const struct sockaddr_in6
*)dest
;
1594 src_port
= src_in6
->sin6_port
;
1595 dest_port
= dest_in6
->sin6_port
;
1596 ip_hdr_len
= sizeof(ip
->v6
);
1603 switch (socket_type
) {
1605 protocol
= 0x06; /* TCP */
1606 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1607 wire_len
= wire_hdr_len
+ payload_len
;
1611 protocol
= 0x11; /* UDP */
1612 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1613 wire_len
= wire_hdr_len
+ payload_len
;
1621 icmp_protocol
= protocol
;
1622 switch (src
->sa_family
) {
1624 protocol
= 0x01; /* ICMPv4 */
1625 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1629 protocol
= 0x3A; /* ICMPv6 */
1630 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1634 if (wire_len
> 64 ) {
1635 icmp_truncate_len
= wire_len
- 64;
1637 wire_hdr_len
+= icmp_hdr_len
;
1638 wire_len
+= icmp_hdr_len
;
1641 packet_len
= nonwire_len
+ wire_len
;
1642 alloc_len
= packet_len
;
1643 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1644 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1647 base
= (uint8_t *)malloc(alloc_len
);
1651 memset(base
, 0x0, alloc_len
);
1655 frame
= (struct swrap_packet_frame
*)buf
;
1656 frame
->seconds
= tval
->tv_sec
;
1657 frame
->micro_seconds
= tval
->tv_usec
;
1658 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1659 frame
->full_length
= wire_len
- icmp_truncate_len
;
1660 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1662 ip
= (union swrap_packet_ip
*)buf
;
1663 switch (src
->sa_family
) {
1665 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1667 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1668 ip
->v4
.identification
= htons(0xFFFF);
1669 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1670 ip
->v4
.fragment
= htons(0x0000);
1672 ip
->v4
.protocol
= protocol
;
1673 ip
->v4
.hdr_checksum
= htons(0x0000);
1674 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1675 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1676 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1680 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1681 ip
->v6
.flow_label_high
= 0x00;
1682 ip
->v6
.flow_label_low
= 0x0000;
1683 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1684 ip
->v6
.next_header
= protocol
;
1685 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1686 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1687 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1693 pay
= (union swrap_packet_payload
*)buf
;
1694 switch (src
->sa_family
) {
1696 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1697 pay
->icmp4
.code
= 0x01; /* host unreachable */
1698 pay
->icmp4
.checksum
= htons(0x0000);
1699 pay
->icmp4
.unused
= htonl(0x00000000);
1700 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1702 /* set the ip header in the ICMP payload */
1703 ip
= (union swrap_packet_ip
*)buf
;
1704 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1706 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1707 ip
->v4
.identification
= htons(0xFFFF);
1708 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1709 ip
->v4
.fragment
= htons(0x0000);
1711 ip
->v4
.protocol
= icmp_protocol
;
1712 ip
->v4
.hdr_checksum
= htons(0x0000);
1713 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1714 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1715 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1717 src_port
= dest_in
->sin_port
;
1718 dest_port
= src_in
->sin_port
;
1722 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1723 pay
->icmp6
.code
= 0x03; /* address unreachable */
1724 pay
->icmp6
.checksum
= htons(0x0000);
1725 pay
->icmp6
.unused
= htonl(0x00000000);
1726 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1728 /* set the ip header in the ICMP payload */
1729 ip
= (union swrap_packet_ip
*)buf
;
1730 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1731 ip
->v6
.flow_label_high
= 0x00;
1732 ip
->v6
.flow_label_low
= 0x0000;
1733 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1734 ip
->v6
.next_header
= protocol
;
1735 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1736 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1737 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1739 src_port
= dest_in6
->sin6_port
;
1740 dest_port
= src_in6
->sin6_port
;
1746 pay
= (union swrap_packet_payload
*)buf
;
1748 switch (socket_type
) {
1750 pay
->tcp
.source_port
= src_port
;
1751 pay
->tcp
.dest_port
= dest_port
;
1752 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1753 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1754 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1755 pay
->tcp
.control
= tcp_ctl
;
1756 pay
->tcp
.window
= htons(0x7FFF);
1757 pay
->tcp
.checksum
= htons(0x0000);
1758 pay
->tcp
.urg
= htons(0x0000);
1759 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1764 pay
->udp
.source_port
= src_port
;
1765 pay
->udp
.dest_port
= dest_port
;
1766 pay
->udp
.length
= htons(8 + payload_len
);
1767 pay
->udp
.checksum
= htons(0x0000);
1768 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1773 if (payload
&& payload_len
> 0) {
1774 memcpy(buf
, payload
, payload_len
);
1777 *_packet_len
= packet_len
- icmp_truncate_len
;
1781 static int swrap_get_pcap_fd(const char *fname
)
1785 if (fd
!= -1) return fd
;
1787 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1789 struct swrap_file_hdr file_hdr
;
1790 file_hdr
.magic
= 0xA1B2C3D4;
1791 file_hdr
.version_major
= 0x0002;
1792 file_hdr
.version_minor
= 0x0004;
1793 file_hdr
.timezone
= 0x00000000;
1794 file_hdr
.sigfigs
= 0x00000000;
1795 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1796 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1798 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1805 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1810 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1811 const struct sockaddr
*addr
,
1812 enum swrap_packet_type type
,
1813 const void *buf
, size_t len
,
1816 const struct sockaddr
*src_addr
;
1817 const struct sockaddr
*dest_addr
;
1818 unsigned long tcp_seqno
= 0;
1819 unsigned long tcp_ack
= 0;
1820 unsigned char tcp_ctl
= 0;
1821 int unreachable
= 0;
1825 switch (si
->family
) {
1837 case SWRAP_CONNECT_SEND
:
1838 if (si
->type
!= SOCK_STREAM
) return NULL
;
1840 src_addr
= si
->myname
;
1843 tcp_seqno
= si
->io
.pck_snd
;
1844 tcp_ack
= si
->io
.pck_rcv
;
1845 tcp_ctl
= 0x02; /* SYN */
1847 si
->io
.pck_snd
+= 1;
1851 case SWRAP_CONNECT_RECV
:
1852 if (si
->type
!= SOCK_STREAM
) return NULL
;
1854 dest_addr
= si
->myname
;
1857 tcp_seqno
= si
->io
.pck_rcv
;
1858 tcp_ack
= si
->io
.pck_snd
;
1859 tcp_ctl
= 0x12; /** SYN,ACK */
1861 si
->io
.pck_rcv
+= 1;
1865 case SWRAP_CONNECT_UNREACH
:
1866 if (si
->type
!= SOCK_STREAM
) return NULL
;
1868 dest_addr
= si
->myname
;
1871 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1872 tcp_seqno
= si
->io
.pck_snd
- 1;
1873 tcp_ack
= si
->io
.pck_rcv
;
1874 tcp_ctl
= 0x02; /* SYN */
1879 case SWRAP_CONNECT_ACK
:
1880 if (si
->type
!= SOCK_STREAM
) return NULL
;
1882 src_addr
= si
->myname
;
1885 tcp_seqno
= si
->io
.pck_snd
;
1886 tcp_ack
= si
->io
.pck_rcv
;
1887 tcp_ctl
= 0x10; /* ACK */
1891 case SWRAP_ACCEPT_SEND
:
1892 if (si
->type
!= SOCK_STREAM
) return NULL
;
1894 dest_addr
= si
->myname
;
1897 tcp_seqno
= si
->io
.pck_rcv
;
1898 tcp_ack
= si
->io
.pck_snd
;
1899 tcp_ctl
= 0x02; /* SYN */
1901 si
->io
.pck_rcv
+= 1;
1905 case SWRAP_ACCEPT_RECV
:
1906 if (si
->type
!= SOCK_STREAM
) return NULL
;
1908 src_addr
= si
->myname
;
1911 tcp_seqno
= si
->io
.pck_snd
;
1912 tcp_ack
= si
->io
.pck_rcv
;
1913 tcp_ctl
= 0x12; /* SYN,ACK */
1915 si
->io
.pck_snd
+= 1;
1919 case SWRAP_ACCEPT_ACK
:
1920 if (si
->type
!= SOCK_STREAM
) return NULL
;
1922 dest_addr
= si
->myname
;
1925 tcp_seqno
= si
->io
.pck_rcv
;
1926 tcp_ack
= si
->io
.pck_snd
;
1927 tcp_ctl
= 0x10; /* ACK */
1932 src_addr
= si
->myname
;
1933 dest_addr
= si
->peername
;
1935 tcp_seqno
= si
->io
.pck_snd
;
1936 tcp_ack
= si
->io
.pck_rcv
;
1937 tcp_ctl
= 0x18; /* PSH,ACK */
1939 si
->io
.pck_snd
+= len
;
1943 case SWRAP_SEND_RST
:
1944 dest_addr
= si
->myname
;
1945 src_addr
= si
->peername
;
1947 if (si
->type
== SOCK_DGRAM
) {
1948 return swrap_marshall_packet(si
, si
->peername
,
1949 SWRAP_SENDTO_UNREACH
,
1950 buf
, len
, packet_len
);
1953 tcp_seqno
= si
->io
.pck_rcv
;
1954 tcp_ack
= si
->io
.pck_snd
;
1955 tcp_ctl
= 0x14; /** RST,ACK */
1959 case SWRAP_PENDING_RST
:
1960 dest_addr
= si
->myname
;
1961 src_addr
= si
->peername
;
1963 if (si
->type
== SOCK_DGRAM
) {
1967 tcp_seqno
= si
->io
.pck_rcv
;
1968 tcp_ack
= si
->io
.pck_snd
;
1969 tcp_ctl
= 0x14; /* RST,ACK */
1974 dest_addr
= si
->myname
;
1975 src_addr
= si
->peername
;
1977 tcp_seqno
= si
->io
.pck_rcv
;
1978 tcp_ack
= si
->io
.pck_snd
;
1979 tcp_ctl
= 0x18; /* PSH,ACK */
1981 si
->io
.pck_rcv
+= len
;
1985 case SWRAP_RECV_RST
:
1986 dest_addr
= si
->myname
;
1987 src_addr
= si
->peername
;
1989 if (si
->type
== SOCK_DGRAM
) {
1993 tcp_seqno
= si
->io
.pck_rcv
;
1994 tcp_ack
= si
->io
.pck_snd
;
1995 tcp_ctl
= 0x14; /* RST,ACK */
2000 src_addr
= si
->myname
;
2003 si
->io
.pck_snd
+= len
;
2007 case SWRAP_SENDTO_UNREACH
:
2008 dest_addr
= si
->myname
;
2015 case SWRAP_RECVFROM
:
2016 dest_addr
= si
->myname
;
2019 si
->io
.pck_rcv
+= len
;
2023 case SWRAP_CLOSE_SEND
:
2024 if (si
->type
!= SOCK_STREAM
) return NULL
;
2026 src_addr
= si
->myname
;
2027 dest_addr
= si
->peername
;
2029 tcp_seqno
= si
->io
.pck_snd
;
2030 tcp_ack
= si
->io
.pck_rcv
;
2031 tcp_ctl
= 0x11; /* FIN, ACK */
2033 si
->io
.pck_snd
+= 1;
2037 case SWRAP_CLOSE_RECV
:
2038 if (si
->type
!= SOCK_STREAM
) return NULL
;
2040 dest_addr
= si
->myname
;
2041 src_addr
= si
->peername
;
2043 tcp_seqno
= si
->io
.pck_rcv
;
2044 tcp_ack
= si
->io
.pck_snd
;
2045 tcp_ctl
= 0x11; /* FIN,ACK */
2047 si
->io
.pck_rcv
+= 1;
2051 case SWRAP_CLOSE_ACK
:
2052 if (si
->type
!= SOCK_STREAM
) return NULL
;
2054 src_addr
= si
->myname
;
2055 dest_addr
= si
->peername
;
2057 tcp_seqno
= si
->io
.pck_snd
;
2058 tcp_ack
= si
->io
.pck_rcv
;
2059 tcp_ctl
= 0x10; /* ACK */
2066 swrapGetTimeOfDay(&tv
);
2068 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
2069 (const uint8_t *)buf
, len
,
2070 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
2074 static void swrap_dump_packet(struct socket_info
*si
,
2075 const struct sockaddr
*addr
,
2076 enum swrap_packet_type type
,
2077 const void *buf
, size_t len
)
2079 const char *file_name
;
2081 size_t packet_len
= 0;
2084 file_name
= socket_wrapper_pcap_file();
2089 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
2094 fd
= swrap_get_pcap_fd(file_name
);
2096 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2105 /****************************************************************************
2107 ***************************************************************************/
2109 #ifdef HAVE_SIGNALFD
2110 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2114 rc
= libc_signalfd(fd
, mask
, flags
);
2116 swrap_remove_stale(fd
);
2122 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2124 return swrap_signalfd(fd
, mask
, flags
);
2128 /****************************************************************************
2130 ***************************************************************************/
2132 static int swrap_socket(int family
, int type
, int protocol
)
2134 struct socket_info
*si
;
2135 struct socket_info_fd
*fi
;
2137 int real_type
= type
;
2140 * Remove possible addition flags passed to socket() so
2141 * do not fail checking the type.
2142 * See https://lwn.net/Articles/281965/
2145 real_type
&= ~SOCK_CLOEXEC
;
2147 #ifdef SOCK_NONBLOCK
2148 real_type
&= ~SOCK_NONBLOCK
;
2151 if (!socket_wrapper_enabled()) {
2152 return libc_socket(family
, type
, protocol
);
2162 return libc_socket(family
, type
, protocol
);
2164 errno
= EAFNOSUPPORT
;
2168 switch (real_type
) {
2174 errno
= EPROTONOSUPPORT
;
2182 if (real_type
== SOCK_STREAM
) {
2187 if (real_type
== SOCK_DGRAM
) {
2192 errno
= EPROTONOSUPPORT
;
2197 * We must call libc_socket with type, from the caller, not the version
2198 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2200 fd
= libc_socket(AF_UNIX
, type
, 0);
2206 /* Check if we have a stale fd and remove it */
2207 si
= find_socket_info(fd
);
2209 swrap_remove_stale(fd
);
2212 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2213 memset(si
, 0, sizeof(struct socket_info
));
2219 si
->family
= family
;
2221 /* however, the rest of the socket_wrapper code expects just
2222 * the type, not the flags */
2223 si
->type
= real_type
;
2224 si
->protocol
= protocol
;
2226 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2235 SWRAP_DLIST_ADD(si
->fds
, fi
);
2236 SWRAP_DLIST_ADD(sockets
, si
);
2241 int socket(int family
, int type
, int protocol
)
2243 return swrap_socket(family
, type
, protocol
);
2246 /****************************************************************************
2248 ***************************************************************************/
2250 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2254 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2256 swrap_remove_stale(sv
[0]);
2257 swrap_remove_stale(sv
[1]);
2263 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2265 return swrap_socketpair(family
, type
, protocol
, sv
);
2268 /****************************************************************************
2270 ***************************************************************************/
2272 #ifdef HAVE_TIMERFD_CREATE
2273 static int swrap_timerfd_create(int clockid
, int flags
)
2277 fd
= libc_timerfd_create(clockid
, flags
);
2279 swrap_remove_stale(fd
);
2285 int timerfd_create(int clockid
, int flags
)
2287 return swrap_timerfd_create(clockid
, flags
);
2291 /****************************************************************************
2293 ***************************************************************************/
2295 static int swrap_pipe(int pipefd
[2])
2299 rc
= libc_pipe(pipefd
);
2301 swrap_remove_stale(pipefd
[0]);
2302 swrap_remove_stale(pipefd
[1]);
2308 int pipe(int pipefd
[2])
2310 return swrap_pipe(pipefd
);
2313 /****************************************************************************
2315 ***************************************************************************/
2317 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2319 struct socket_info
*parent_si
, *child_si
;
2320 struct socket_info_fd
*child_fi
;
2322 struct sockaddr_un un_addr
;
2323 socklen_t un_addrlen
= sizeof(un_addr
);
2324 struct sockaddr_un un_my_addr
;
2325 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
2326 struct sockaddr
*my_addr
;
2327 socklen_t my_addrlen
, len
;
2330 parent_si
= find_socket_info(s
);
2332 return libc_accept(s
, addr
, addrlen
);
2336 * assume out sockaddr have the same size as the in parent
2339 my_addrlen
= socket_length(parent_si
->family
);
2340 if (my_addrlen
<= 0) {
2345 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
2346 if (my_addr
== NULL
) {
2350 memset(&un_addr
, 0, sizeof(un_addr
));
2351 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
2353 ret
= libc_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2355 if (errno
== ENOTSOCK
) {
2356 /* Remove stale fds */
2357 swrap_remove_stale(s
);
2366 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
2367 parent_si
->family
, my_addr
, &len
);
2374 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2375 memset(child_si
, 0, sizeof(struct socket_info
));
2377 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2378 if (child_fi
== NULL
) {
2388 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2390 child_si
->family
= parent_si
->family
;
2391 child_si
->type
= parent_si
->type
;
2392 child_si
->protocol
= parent_si
->protocol
;
2393 child_si
->bound
= 1;
2394 child_si
->is_server
= 1;
2395 child_si
->connected
= 1;
2397 child_si
->peername_len
= len
;
2398 child_si
->peername
= sockaddr_dup(my_addr
, len
);
2400 if (addr
!= NULL
&& addrlen
!= NULL
) {
2401 size_t copy_len
= MIN(*addrlen
, len
);
2403 memcpy(addr
, my_addr
, copy_len
);
2408 ret
= libc_getsockname(fd
,
2409 (struct sockaddr
*)(void *)&un_my_addr
,
2420 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
2421 child_si
->family
, my_addr
, &len
);
2430 SWRAP_LOG(SWRAP_LOG_TRACE
,
2431 "accept() path=%s, fd=%d",
2432 un_my_addr
.sun_path
, s
);
2434 child_si
->myname_len
= len
;
2435 child_si
->myname
= sockaddr_dup(my_addr
, len
);
2438 SWRAP_DLIST_ADD(sockets
, child_si
);
2441 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2442 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2443 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2449 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2450 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2452 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2455 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2458 static int autobind_start_init
;
2459 static int autobind_start
;
2461 /* using sendto() or connect() on an unbound socket would give the
2462 recipient no way to reply, as unlike UDP and TCP, a unix domain
2463 socket can't auto-assign ephemeral port numbers, so we need to
2465 Note: this might change the family from ipv6 to ipv4
2467 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2469 struct sockaddr_un un_addr
;
2476 if (autobind_start_init
!= 1) {
2477 autobind_start_init
= 1;
2478 autobind_start
= getpid();
2479 autobind_start
%= 50000;
2480 autobind_start
+= 10000;
2483 un_addr
.sun_family
= AF_UNIX
;
2487 struct sockaddr_in in
;
2491 type
= SOCKET_TYPE_CHAR_TCP
;
2494 type
= SOCKET_TYPE_CHAR_UDP
;
2497 errno
= ESOCKTNOSUPPORT
;
2501 memset(&in
, 0, sizeof(in
));
2502 in
.sin_family
= AF_INET
;
2503 in
.sin_addr
.s_addr
= htonl(127<<24 |
2504 socket_wrapper_default_iface());
2506 si
->myname_len
= sizeof(in
);
2507 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
2512 struct sockaddr_in6 in6
;
2514 if (si
->family
!= family
) {
2515 errno
= ENETUNREACH
;
2521 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2524 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2527 errno
= ESOCKTNOSUPPORT
;
2531 memset(&in6
, 0, sizeof(in6
));
2532 in6
.sin6_family
= AF_INET6
;
2533 in6
.sin6_addr
= *swrap_ipv6();
2534 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2535 si
->myname_len
= sizeof(in6
);
2536 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
2541 errno
= ESOCKTNOSUPPORT
;
2545 if (autobind_start
> 60000) {
2546 autobind_start
= 10000;
2549 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2550 port
= autobind_start
+ i
;
2551 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
2552 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2553 type
, socket_wrapper_default_iface(), port
);
2554 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
2556 ret
= libc_bind(fd
, (struct sockaddr
*)(void *)&un_addr
,
2558 if (ret
== -1) return ret
;
2560 si
->tmp_path
= strdup(un_addr
.sun_path
);
2562 autobind_start
= port
+ 1;
2565 if (i
== SOCKET_MAX_SOCKETS
) {
2566 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2567 "interface "SOCKET_FORMAT
,
2570 socket_wrapper_default_iface(),
2576 si
->family
= family
;
2577 set_port(si
->family
, port
, si
->myname
);
2582 /****************************************************************************
2584 ***************************************************************************/
2586 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2590 struct sockaddr_un un_addr
;
2591 struct socket_info
*si
= find_socket_info(s
);
2595 return libc_connect(s
, serv_addr
, addrlen
);
2598 if (si
->bound
== 0) {
2599 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2600 if (ret
== -1) return -1;
2603 if (si
->family
!= serv_addr
->sa_family
) {
2608 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2609 addrlen
, &un_addr
, 0, &bcast
);
2610 if (ret
== -1) return -1;
2613 errno
= ENETUNREACH
;
2617 if (si
->type
== SOCK_DGRAM
) {
2618 si
->defer_connect
= 1;
2621 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2623 ret
= libc_connect(s
,
2624 (struct sockaddr
*)(void *)&un_addr
,
2625 sizeof(struct sockaddr_un
));
2628 SWRAP_LOG(SWRAP_LOG_TRACE
,
2629 "connect() path=%s, fd=%d",
2630 un_addr
.sun_path
, s
);
2633 /* to give better errors */
2634 if (ret
== -1 && errno
== ENOENT
) {
2635 errno
= EHOSTUNREACH
;
2639 si
->peername_len
= addrlen
;
2640 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
2644 * When we connect() on a socket than we have to bind the
2645 * outgoing connection on the interface we use for the
2646 * transport. We already bound it on the right interface
2647 * but here we have to update the name so getsockname()
2648 * returns correct information.
2650 if (si
->bindname
!= NULL
) {
2653 si
->myname
= si
->bindname
;
2654 si
->myname_len
= si
->bindname_len
;
2656 si
->bindname
= NULL
;
2657 si
->bindname_len
= 0;
2660 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2661 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2663 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2669 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2671 return swrap_connect(s
, serv_addr
, addrlen
);
2674 /****************************************************************************
2676 ***************************************************************************/
2678 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2681 struct sockaddr_un un_addr
;
2682 struct socket_info
*si
= find_socket_info(s
);
2685 return libc_bind(s
, myaddr
, addrlen
);
2688 si
->myname_len
= addrlen
;
2689 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
2691 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
2692 if (ret
== -1) return -1;
2694 unlink(un_addr
.sun_path
);
2696 ret
= libc_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
2697 sizeof(struct sockaddr_un
));
2699 SWRAP_LOG(SWRAP_LOG_TRACE
,
2700 "bind() path=%s, fd=%d",
2701 un_addr
.sun_path
, s
);
2710 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2712 return swrap_bind(s
, myaddr
, addrlen
);
2715 /****************************************************************************
2717 ***************************************************************************/
2719 static int swrap_listen(int s
, int backlog
)
2722 struct socket_info
*si
= find_socket_info(s
);
2725 return libc_listen(s
, backlog
);
2728 ret
= libc_listen(s
, backlog
);
2733 int listen(int s
, int backlog
)
2735 return swrap_listen(s
, backlog
);
2738 /****************************************************************************
2740 ***************************************************************************/
2742 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
2746 ret
= libc_vopen(pathname
, flags
, ap
);
2749 * There are methods for closing descriptors (libc-internal code
2750 * paths, direct syscalls) which close descriptors in ways that
2751 * we can't intercept, so try to recover when we notice that
2754 swrap_remove_stale(ret
);
2759 int open(const char *pathname
, int flags
, ...)
2764 va_start(ap
, flags
);
2765 fd
= swrap_vopen(pathname
, flags
, ap
);
2771 /****************************************************************************
2773 ***************************************************************************/
2775 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2777 struct socket_info
*si
= find_socket_info(s
);
2781 return libc_getpeername(s
, name
, addrlen
);
2790 len
= MIN(*addrlen
, si
->peername_len
);
2795 memcpy(name
, si
->peername
, len
);
2796 *addrlen
= si
->peername_len
;
2801 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2802 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
2804 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2807 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
2810 /****************************************************************************
2812 ***************************************************************************/
2814 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2816 struct socket_info
*si
= find_socket_info(s
);
2820 return libc_getsockname(s
, name
, addrlen
);
2823 len
= MIN(*addrlen
, si
->myname_len
);
2828 memcpy(name
, si
->myname
, len
);
2829 *addrlen
= si
->myname_len
;
2834 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2835 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
2837 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2840 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
2843 /****************************************************************************
2845 ***************************************************************************/
2847 static int swrap_getsockopt(int s
, int level
, int optname
,
2848 void *optval
, socklen_t
*optlen
)
2850 struct socket_info
*si
= find_socket_info(s
);
2853 return libc_getsockopt(s
,
2860 if (level
== SOL_SOCKET
) {
2861 return libc_getsockopt(s
,
2868 errno
= ENOPROTOOPT
;
2872 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2873 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
2875 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
2878 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
2881 /****************************************************************************
2883 ***************************************************************************/
2885 static int swrap_setsockopt(int s
, int level
, int optname
,
2886 const void *optval
, socklen_t optlen
)
2888 struct socket_info
*si
= find_socket_info(s
);
2891 return libc_setsockopt(s
,
2898 if (level
== SOL_SOCKET
) {
2899 return libc_setsockopt(s
,
2906 switch (si
->family
) {
2908 if (level
== IPPROTO_IP
) {
2910 if (optname
== IP_PKTINFO
) {
2911 si
->pktinfo
= AF_INET
;
2913 #endif /* IP_PKTINFO */
2918 if (level
== IPPROTO_IPV6
) {
2919 #ifdef IPV6_RECVPKTINFO
2920 if (optname
== IPV6_RECVPKTINFO
) {
2921 si
->pktinfo
= AF_INET6
;
2923 #endif /* IPV6_PKTINFO */
2928 errno
= ENOPROTOOPT
;
2933 int setsockopt(int s
, int level
, int optname
,
2934 const void *optval
, socklen_t optlen
)
2936 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
2939 /****************************************************************************
2941 ***************************************************************************/
2943 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
2945 struct socket_info
*si
= find_socket_info(s
);
2951 return libc_vioctl(s
, r
, va
);
2956 rc
= libc_vioctl(s
, r
, va
);
2960 value
= *((int *)va_arg(ap
, int *));
2962 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2963 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2964 } else if (value
== 0) { /* END OF FILE */
2965 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2975 #ifdef HAVE_IOCTL_INT
2976 int ioctl(int s
, int r
, ...)
2978 int ioctl(int s
, unsigned long int r
, ...)
2986 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
2997 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3000 # ifdef _ALIGN /* BSD */
3001 #define CMSG_ALIGN _ALIGN
3003 #error NO_CMSG_ALIGN
3004 # endif /* _ALIGN */
3005 #endif /* CMSG_ALIGN */
3008 * @brief Add a cmsghdr to a msghdr.
3010 * This is an function to add any type of cmsghdr. It will operate on the
3011 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3012 * the buffer position after the added cmsg element. Hence, this function is
3013 * intended to be used with an intermediate msghdr and not on the original
3014 * one handed in by the client.
3016 * @param[in] msg The msghdr to which to add the cmsg.
3018 * @param[in] level The cmsg level to set.
3020 * @param[in] type The cmsg type to set.
3022 * @param[in] data The cmsg data to set.
3024 * @param[in] len the length of the data to set.
3026 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3032 size_t cmlen
= CMSG_LEN(len
);
3033 size_t cmspace
= CMSG_SPACE(len
);
3034 uint8_t cmbuf
[cmspace
];
3035 struct cmsghdr
*cm
= (struct cmsghdr
*)cmbuf
;
3038 memset(cmbuf
, 0, cmspace
);
3040 if (msg
->msg_controllen
< cmlen
) {
3041 cmlen
= msg
->msg_controllen
;
3042 msg
->msg_flags
|= MSG_CTRUNC
;
3045 if (msg
->msg_controllen
< cmspace
) {
3046 cmspace
= msg
->msg_controllen
;
3050 * We copy the full input data into an intermediate cmsghdr first
3051 * in order to more easily cope with truncation.
3053 cm
->cmsg_len
= cmlen
;
3054 cm
->cmsg_level
= level
;
3055 cm
->cmsg_type
= type
;
3056 memcpy(CMSG_DATA(cm
), data
, len
);
3059 * We now copy the possibly truncated buffer.
3060 * We copy cmlen bytes, but consume cmspace bytes,
3061 * leaving the possible padding uninitialiazed.
3063 p
= (uint8_t *)msg
->msg_control
;
3064 memcpy(p
, cm
, cmlen
);
3066 msg
->msg_control
= p
;
3067 msg
->msg_controllen
-= cmspace
;
3072 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3075 /* Add packet info */
3076 switch (si
->pktinfo
) {
3077 #if defined(IP_PKTINFO)
3078 /* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
3080 struct sockaddr_in
*sin
;
3081 #if defined(HAVE_STRUCT_IN_PKTINFO)
3082 struct in_pktinfo pkt
;
3083 #elif defined(IP_RECVDSTADDR)
3087 if (si
->bindname_len
== sizeof(struct sockaddr_in
)) {
3088 sin
= (struct sockaddr_in
*)si
->bindname
;
3090 if (si
->myname_len
!= sizeof(struct sockaddr_in
)) {
3093 sin
= (struct sockaddr_in
*)si
->myname
;
3098 #if defined(HAVE_STRUCT_IN_PKTINFO)
3099 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3100 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3101 #elif defined(IP_RECVDSTADDR)
3102 pkt
= sin
->sin_addr
;
3105 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3110 #endif /* IP_PKTINFO */
3111 #if defined(HAVE_IPV6)
3113 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3114 struct sockaddr_in6
*sin6
;
3115 struct in6_pktinfo pkt6
;
3117 if (si
->bindname_len
== sizeof(struct sockaddr_in6
)) {
3118 sin6
= (struct sockaddr_in6
*)si
->bindname
;
3120 if (si
->myname_len
!= sizeof(struct sockaddr_in6
)) {
3123 sin6
= (struct sockaddr_in6
*)si
->myname
;
3128 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3129 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3131 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3132 &pkt6
, sizeof(pkt6
));
3133 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3137 #endif /* IPV6_PKTINFO */
3145 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3146 struct msghdr
*omsg
)
3150 if (si
->pktinfo
> 0) {
3151 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3157 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3159 size_t *cm_data_space
);
3160 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3162 size_t *cm_data_space
);
3164 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
3166 size_t *cm_data_space
) {
3167 struct cmsghdr
*cmsg
;
3171 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
3175 for (cmsg
= CMSG_FIRSTHDR(msg
);
3177 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
3178 switch (cmsg
->cmsg_level
) {
3180 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
3185 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
3195 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3197 size_t *cm_data_space
)
3204 CMSG_SPACE(cmsg
->cmsg_len
- CMSG_ALIGN(sizeof(struct cmsghdr
)));
3206 p
= realloc(cm_data
, cmspace
);
3212 p
= cm_data
+ (*cm_data_space
);
3213 *cm_data_space
= cmspace
;
3215 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
3220 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3222 size_t *cm_data_space
);
3225 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3227 size_t *cm_data_space
)
3231 switch(cmsg
->cmsg_type
) {
3234 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3241 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3253 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3255 size_t *cm_data_space
)
3257 (void)cmsg
; /* unused */
3258 (void)cm_data
; /* unused */
3259 (void)cm_data_space
; /* unused */
3262 * Passing a IP pktinfo to a unix socket might be rejected by the
3263 * Kernel, at least on FreeBSD. So skip this cmsg.
3267 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3269 static ssize_t
swrap_sendmsg_before(int fd
,
3270 struct socket_info
*si
,
3272 struct iovec
*tmp_iov
,
3273 struct sockaddr_un
*tmp_un
,
3274 const struct sockaddr_un
**to_un
,
3275 const struct sockaddr
**to
,
3293 if (!si
->connected
) {
3298 if (msg
->msg_iovlen
== 0) {
3302 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3304 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3305 if (nlen
> SOCKET_MAX_PACKET
) {
3309 msg
->msg_iovlen
= i
;
3310 if (msg
->msg_iovlen
== 0) {
3311 *tmp_iov
= msg
->msg_iov
[0];
3312 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3313 msg
->msg_iov
= tmp_iov
;
3314 msg
->msg_iovlen
= 1;
3319 if (si
->connected
) {
3320 if (msg
->msg_name
) {
3325 const struct sockaddr
*msg_name
;
3326 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3328 if (msg_name
== NULL
) {
3334 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3336 if (ret
== -1) return -1;
3344 msg
->msg_name
= tmp_un
;
3345 msg
->msg_namelen
= sizeof(*tmp_un
);
3348 if (si
->bound
== 0) {
3349 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3351 if (errno
== ENOTSOCK
) {
3352 swrap_remove_stale(fd
);
3355 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3361 if (!si
->defer_connect
) {
3365 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
3367 if (ret
== -1) return -1;
3369 ret
= libc_connect(fd
,
3370 (struct sockaddr
*)(void *)tmp_un
,
3373 /* to give better errors */
3374 if (ret
== -1 && errno
== ENOENT
) {
3375 errno
= EHOSTUNREACH
;
3382 si
->defer_connect
= 0;
3385 errno
= EHOSTUNREACH
;
3389 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3390 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
3391 uint8_t *cmbuf
= NULL
;
3394 ret
= swrap_sendmsg_filter_cmsghdr(msg
, cmbuf
, &cmlen
);
3401 msg
->msg_controllen
= 0;
3402 msg
->msg_control
= NULL
;
3403 } else if (cmlen
< msg
->msg_controllen
) {
3404 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
3405 msg
->msg_controllen
= cmlen
;
3414 static void swrap_sendmsg_after(int fd
,
3415 struct socket_info
*si
,
3417 const struct sockaddr
*to
,
3420 int saved_errno
= errno
;
3427 /* to give better errors */
3429 if (saved_errno
== ENOENT
) {
3430 saved_errno
= EHOSTUNREACH
;
3431 } else if (saved_errno
== ENOTSOCK
) {
3432 /* If the fd is not a socket, remove it */
3433 swrap_remove_stale(fd
);
3437 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3438 avail
+= msg
->msg_iov
[i
].iov_len
;
3442 remain
= MIN(80, avail
);
3447 /* we capture it as one single packet */
3448 buf
= (uint8_t *)malloc(remain
);
3450 /* we just not capture the packet */
3451 errno
= saved_errno
;
3455 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3456 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3458 msg
->msg_iov
[i
].iov_base
,
3461 remain
-= this_time
;
3468 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3469 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3471 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3476 if (si
->connected
) {
3480 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3481 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3483 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3489 errno
= saved_errno
;
3492 static int swrap_recvmsg_before(int fd
,
3493 struct socket_info
*si
,
3495 struct iovec
*tmp_iov
)
3500 (void)fd
; /* unused */
3504 if (!si
->connected
) {
3509 if (msg
->msg_iovlen
== 0) {
3513 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3515 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3516 if (nlen
> SOCKET_MAX_PACKET
) {
3520 msg
->msg_iovlen
= i
;
3521 if (msg
->msg_iovlen
== 0) {
3522 *tmp_iov
= msg
->msg_iov
[0];
3523 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3524 msg
->msg_iov
= tmp_iov
;
3525 msg
->msg_iovlen
= 1;
3530 if (msg
->msg_name
== NULL
) {
3535 if (msg
->msg_iovlen
== 0) {
3539 if (si
->bound
== 0) {
3540 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3543 * When attempting to read or write to a
3544 * descriptor, if an underlying autobind fails
3545 * because it's not a socket, stop intercepting
3546 * uses of that descriptor.
3548 if (errno
== ENOTSOCK
) {
3549 swrap_remove_stale(fd
);
3552 SWRAP_LOG(SWRAP_LOG_ERROR
,
3553 "swrap_recvmsg_before failed");
3560 errno
= EHOSTUNREACH
;
3567 static int swrap_recvmsg_after(int fd
,
3568 struct socket_info
*si
,
3570 const struct sockaddr_un
*un_addr
,
3571 socklen_t un_addrlen
,
3574 int saved_errno
= errno
;
3576 uint8_t *buf
= NULL
;
3582 /* to give better errors */
3584 if (saved_errno
== ENOENT
) {
3585 saved_errno
= EHOSTUNREACH
;
3586 } else if (saved_errno
== ENOTSOCK
) {
3587 /* If the fd is not a socket, remove it */
3588 swrap_remove_stale(fd
);
3592 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3593 avail
+= msg
->msg_iov
[i
].iov_len
;
3602 remain
= MIN(80, avail
);
3607 /* we capture it as one single packet */
3608 buf
= (uint8_t *)malloc(remain
);
3610 /* we just not capture the packet */
3611 errno
= saved_errno
;
3615 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3616 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3618 msg
->msg_iov
[i
].iov_base
,
3621 remain
-= this_time
;
3626 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
3627 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3628 } else if (ret
== 0) { /* END OF FILE */
3629 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3630 } else if (ret
> 0) {
3631 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
3640 if (un_addr
!= NULL
) {
3641 rc
= sockaddr_convert_from_un(si
,
3651 swrap_dump_packet(si
,
3657 swrap_dump_packet(si
,
3670 errno
= saved_errno
;
3672 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3674 msg
->msg_controllen
> 0 &&
3675 msg
->msg_control
!= NULL
) {
3676 rc
= swrap_msghdr_add_socket_info(si
, msg
);
3686 /****************************************************************************
3688 ***************************************************************************/
3690 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
3691 struct sockaddr
*from
, socklen_t
*fromlen
)
3693 struct sockaddr_un from_addr
;
3694 socklen_t from_addrlen
= sizeof(from_addr
);
3696 struct socket_info
*si
= find_socket_info(s
);
3697 struct sockaddr_storage ss
;
3698 socklen_t ss_len
= sizeof(ss
);
3704 return libc_recvfrom(s
,
3716 if (from
!= NULL
&& fromlen
!= NULL
) {
3717 msg
.msg_name
= from
; /* optional address */
3718 msg
.msg_namelen
= *fromlen
; /* size of address */
3720 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3721 msg
.msg_namelen
= ss_len
; /* size of address */
3723 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3724 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3725 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3726 msg
.msg_control
= NULL
; /* ancillary data, see below */
3727 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3728 msg
.msg_flags
= 0; /* flags on received message */
3731 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3736 buf
= msg
.msg_iov
[0].iov_base
;
3737 len
= msg
.msg_iov
[0].iov_len
;
3739 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3740 memset(&from_addr
, 0, sizeof(from_addr
));
3741 ret
= libc_recvfrom(s
,
3745 (struct sockaddr
*)(void *)&from_addr
,
3751 tret
= swrap_recvmsg_after(s
,
3761 if (from
!= NULL
&& fromlen
!= NULL
) {
3762 *fromlen
= msg
.msg_namelen
;
3768 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3769 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
3770 struct sockaddr
*from
, Psocklen_t fromlen
)
3772 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
3773 struct sockaddr
*from
, socklen_t
*fromlen
)
3776 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
3779 /****************************************************************************
3781 ***************************************************************************/
3783 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
3784 const struct sockaddr
*to
, socklen_t tolen
)
3788 struct sockaddr_un un_addr
;
3789 const struct sockaddr_un
*to_un
= NULL
;
3792 struct socket_info
*si
= find_socket_info(s
);
3796 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
3799 tmp
.iov_base
= discard_const_p(char, buf
);
3803 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
3804 msg
.msg_namelen
= tolen
; /* size of address */
3805 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3806 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3807 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3808 msg
.msg_control
= NULL
; /* ancillary data, see below */
3809 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3810 msg
.msg_flags
= 0; /* flags on received message */
3813 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
3818 buf
= msg
.msg_iov
[0].iov_base
;
3819 len
= msg
.msg_iov
[0].iov_len
;
3824 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
3827 type
= SOCKET_TYPE_CHAR_UDP
;
3829 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
3830 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
3831 socket_wrapper_dir(), type
, iface
, prt
);
3832 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
3834 /* ignore the any errors in broadcast sends */
3839 (struct sockaddr
*)(void *)&un_addr
,
3843 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3848 ret
= libc_sendto(s
,
3852 (struct sockaddr
*)msg
.msg_name
,
3855 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
3860 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
3861 const struct sockaddr
*to
, socklen_t tolen
)
3863 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
3866 /****************************************************************************
3868 ***************************************************************************/
3870 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
3872 struct socket_info
*si
;
3874 struct sockaddr_storage ss
;
3875 socklen_t ss_len
= sizeof(ss
);
3880 si
= find_socket_info(s
);
3882 return libc_recv(s
, buf
, len
, flags
);
3889 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3890 msg
.msg_namelen
= ss_len
; /* size of address */
3891 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3892 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3893 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3894 msg
.msg_control
= NULL
; /* ancillary data, see below */
3895 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3896 msg
.msg_flags
= 0; /* flags on received message */
3899 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3904 buf
= msg
.msg_iov
[0].iov_base
;
3905 len
= msg
.msg_iov
[0].iov_len
;
3907 ret
= libc_recv(s
, buf
, len
, flags
);
3909 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
3917 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
3919 return swrap_recv(s
, buf
, len
, flags
);
3922 /****************************************************************************
3924 ***************************************************************************/
3926 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
3928 struct socket_info
*si
;
3931 struct sockaddr_storage ss
;
3932 socklen_t ss_len
= sizeof(ss
);
3936 si
= find_socket_info(s
);
3938 return libc_read(s
, buf
, len
);
3945 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3946 msg
.msg_namelen
= ss_len
; /* size of address */
3947 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3948 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3949 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3950 msg
.msg_control
= NULL
; /* ancillary data, see below */
3951 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3952 msg
.msg_flags
= 0; /* flags on received message */
3955 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3957 if (tret
== -ENOTSOCK
) {
3958 return libc_read(s
, buf
, len
);
3963 buf
= msg
.msg_iov
[0].iov_base
;
3964 len
= msg
.msg_iov
[0].iov_len
;
3966 ret
= libc_read(s
, buf
, len
);
3968 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
3976 ssize_t
read(int s
, void *buf
, size_t len
)
3978 return swrap_read(s
, buf
, len
);
3981 /****************************************************************************
3983 ***************************************************************************/
3985 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
3989 struct sockaddr_un un_addr
;
3992 struct socket_info
*si
= find_socket_info(s
);
3995 return libc_send(s
, buf
, len
, flags
);
3998 tmp
.iov_base
= discard_const_p(char, buf
);
4002 msg
.msg_name
= NULL
; /* optional address */
4003 msg
.msg_namelen
= 0; /* size of address */
4004 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4005 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4006 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4007 msg
.msg_control
= NULL
; /* ancillary data, see below */
4008 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4009 msg
.msg_flags
= 0; /* flags on received message */
4012 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4017 buf
= msg
.msg_iov
[0].iov_base
;
4018 len
= msg
.msg_iov
[0].iov_len
;
4020 ret
= libc_send(s
, buf
, len
, flags
);
4022 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4027 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
4029 return swrap_send(s
, buf
, len
, flags
);
4032 /****************************************************************************
4034 ***************************************************************************/
4036 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
4038 struct sockaddr_un from_addr
;
4039 socklen_t from_addrlen
= sizeof(from_addr
);
4040 struct socket_info
*si
;
4043 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4044 size_t msg_ctrllen_filled
;
4045 size_t msg_ctrllen_left
;
4051 si
= find_socket_info(s
);
4053 return libc_recvmsg(s
, omsg
, flags
);
4056 tmp
.iov_base
= NULL
;
4060 msg
.msg_name
= (struct sockaddr
*)&from_addr
; /* optional address */
4061 msg
.msg_namelen
= from_addrlen
; /* size of address */
4062 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4063 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4064 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4065 msg_ctrllen_filled
= 0;
4066 msg_ctrllen_left
= omsg
->msg_controllen
;
4068 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
4069 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4070 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4073 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4078 ret
= libc_recvmsg(s
, &msg
, flags
);
4080 msg
.msg_name
= omsg
->msg_name
;
4081 msg
.msg_namelen
= omsg
->msg_namelen
;
4083 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4084 msg_ctrllen_filled
+= msg
.msg_controllen
;
4085 msg_ctrllen_left
-= msg
.msg_controllen
;
4087 if (omsg
->msg_control
!= NULL
) {
4090 p
= omsg
->msg_control
;
4091 p
+= msg_ctrllen_filled
;
4093 msg
.msg_control
= p
;
4094 msg
.msg_controllen
= msg_ctrllen_left
;
4096 msg
.msg_control
= NULL
;
4097 msg
.msg_controllen
= 0;
4101 rc
= swrap_recvmsg_after(s
, si
, &msg
, &from_addr
, from_addrlen
, ret
);
4106 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4107 if (omsg
->msg_control
!= NULL
) {
4108 /* msg.msg_controllen = space left */
4109 msg_ctrllen_left
= msg
.msg_controllen
;
4110 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
4113 /* Update the original message length */
4114 omsg
->msg_controllen
= msg_ctrllen_filled
;
4115 omsg
->msg_flags
= msg
.msg_flags
;
4117 omsg
->msg_iovlen
= msg
.msg_iovlen
;
4122 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
4124 return swrap_recvmsg(sockfd
, msg
, flags
);
4127 /****************************************************************************
4129 ***************************************************************************/
4131 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4135 struct sockaddr_un un_addr
;
4136 const struct sockaddr_un
*to_un
= NULL
;
4137 const struct sockaddr
*to
= NULL
;
4140 struct socket_info
*si
= find_socket_info(s
);
4144 return libc_sendmsg(s
, omsg
, flags
);
4147 ZERO_STRUCT(un_addr
);
4149 tmp
.iov_base
= NULL
;
4153 msg
.msg_name
= omsg
->msg_name
; /* optional address */
4154 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
4155 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4156 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4157 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4158 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
4159 /* omsg is a const so use a local buffer for modifications */
4160 uint8_t cmbuf
[omsg
->msg_controllen
];
4162 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
4164 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
4165 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4167 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4170 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4178 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4186 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4187 avail
+= msg
.msg_iov
[i
].iov_len
;
4193 /* we capture it as one single packet */
4194 buf
= (uint8_t *)malloc(remain
);
4199 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4200 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4202 msg
.msg_iov
[i
].iov_base
,
4205 remain
-= this_time
;
4208 type
= SOCKET_TYPE_CHAR_UDP
;
4210 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4211 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4212 socket_wrapper_dir(), type
, iface
, prt
);
4213 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4215 msg
.msg_name
= &un_addr
; /* optional address */
4216 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4218 /* ignore the any errors in broadcast sends */
4219 libc_sendmsg(s
, &msg
, flags
);
4222 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4228 ret
= libc_sendmsg(s
, &msg
, flags
);
4230 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4235 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4237 return swrap_sendmsg(s
, omsg
, flags
);
4240 /****************************************************************************
4242 ***************************************************************************/
4244 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4246 struct socket_info
*si
;
4249 struct sockaddr_storage ss
;
4250 socklen_t ss_len
= sizeof(ss
);
4254 si
= find_socket_info(s
);
4256 return libc_readv(s
, vector
, count
);
4259 tmp
.iov_base
= NULL
;
4263 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4264 msg
.msg_namelen
= ss_len
; /* size of address */
4265 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4266 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4267 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4268 msg
.msg_control
= NULL
; /* ancillary data, see below */
4269 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4270 msg
.msg_flags
= 0; /* flags on received message */
4273 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4275 if (rc
== -ENOTSOCK
) {
4276 return libc_readv(s
, vector
, count
);
4281 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4283 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4291 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4293 return swrap_readv(s
, vector
, count
);
4296 /****************************************************************************
4298 ***************************************************************************/
4300 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4304 struct sockaddr_un un_addr
;
4307 struct socket_info
*si
= find_socket_info(s
);
4310 return libc_writev(s
, vector
, count
);
4313 tmp
.iov_base
= NULL
;
4317 msg
.msg_name
= NULL
; /* optional address */
4318 msg
.msg_namelen
= 0; /* size of address */
4319 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4320 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4321 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4322 msg
.msg_control
= NULL
; /* ancillary data, see below */
4323 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4324 msg
.msg_flags
= 0; /* flags on received message */
4327 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4329 if (rc
== -ENOTSOCK
) {
4330 return libc_readv(s
, vector
, count
);
4335 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4337 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4342 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4344 return swrap_writev(s
, vector
, count
);
4347 /****************************
4349 ***************************/
4351 static int swrap_close(int fd
)
4353 struct socket_info
*si
= find_socket_info(fd
);
4354 struct socket_info_fd
*fi
;
4358 return libc_close(fd
);
4361 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4363 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4370 /* there are still references left */
4371 return libc_close(fd
);
4374 SWRAP_DLIST_REMOVE(sockets
, si
);
4376 if (si
->myname
&& si
->peername
) {
4377 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4380 ret
= libc_close(fd
);
4382 if (si
->myname
&& si
->peername
) {
4383 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4384 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4387 if (si
->bindname
!= NULL
) {
4391 if (si
->myname
) free(si
->myname
);
4392 if (si
->peername
) free(si
->peername
);
4394 unlink(si
->tmp_path
);
4404 return swrap_close(fd
);
4407 /****************************
4409 ***************************/
4411 static int swrap_dup(int fd
)
4413 struct socket_info
*si
;
4414 struct socket_info_fd
*fi
;
4416 si
= find_socket_info(fd
);
4419 return libc_dup(fd
);
4422 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4428 fi
->fd
= libc_dup(fd
);
4430 int saved_errno
= errno
;
4432 errno
= saved_errno
;
4436 /* Make sure we don't have an entry for the fd */
4437 swrap_remove_stale(fi
->fd
);
4439 SWRAP_DLIST_ADD(si
->fds
, fi
);
4445 return swrap_dup(fd
);
4448 /****************************
4450 ***************************/
4452 static int swrap_dup2(int fd
, int newfd
)
4454 struct socket_info
*si
;
4455 struct socket_info_fd
*fi
;
4457 si
= find_socket_info(fd
);
4460 return libc_dup2(fd
, newfd
);
4463 if (find_socket_info(newfd
)) {
4464 /* dup2() does an implicit close of newfd, which we
4465 * need to emulate */
4469 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4475 fi
->fd
= libc_dup2(fd
, newfd
);
4477 int saved_errno
= errno
;
4479 errno
= saved_errno
;
4483 /* Make sure we don't have an entry for the fd */
4484 swrap_remove_stale(fi
->fd
);
4486 SWRAP_DLIST_ADD(si
->fds
, fi
);
4490 int dup2(int fd
, int newfd
)
4492 return swrap_dup2(fd
, newfd
);
4495 /****************************
4497 ***************************/
4500 static int swrap_eventfd(int count
, int flags
)
4504 fd
= libc_eventfd(count
, flags
);
4506 swrap_remove_stale(fd
);
4512 int eventfd(int count
, int flags
)
4514 return swrap_eventfd(count
, flags
);
4518 /****************************
4520 ***************************/
4523 * This function is called when the library is unloaded and makes sure that
4524 * sockets get closed and the unix file for the socket are unlinked.
4526 void swrap_destructor(void)
4528 struct socket_info
*s
= sockets
;
4531 struct socket_info_fd
*f
= s
->fds
;