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 */
128 #define SWRAP_DLIST_ADD(list,item) do { \
130 (item)->prev = NULL; \
131 (item)->next = NULL; \
134 (item)->prev = NULL; \
135 (item)->next = (list); \
136 (list)->prev = (item); \
141 #define SWRAP_DLIST_REMOVE(list,item) do { \
142 if ((list) == (item)) { \
143 (list) = (item)->next; \
145 (list)->prev = NULL; \
148 if ((item)->prev) { \
149 (item)->prev->next = (item)->next; \
151 if ((item)->next) { \
152 (item)->next->prev = (item)->prev; \
155 (item)->prev = NULL; \
156 (item)->next = NULL; \
159 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
160 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
162 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
165 /* we need to use a very terse format here as IRIX 6.4 silently
166 truncates names to 16 chars, so if we use a longer name then we
167 can't tell which port a packet came from with recvfrom()
169 with this format we have 8 chars left for the directory name
171 #define SOCKET_FORMAT "%c%02X%04X"
172 #define SOCKET_TYPE_CHAR_TCP 'T'
173 #define SOCKET_TYPE_CHAR_UDP 'U'
174 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
175 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
178 * Cut down to 1500 byte packets for stream sockets,
179 * which makes it easier to format PCAP capture files
180 * (as the caller will simply continue from here)
182 #define SOCKET_MAX_PACKET 1500
184 #define SOCKET_MAX_SOCKETS 1024
186 /* This limit is to avoid broadcast sendto() needing to stat too many
187 * files. It may be raised (with a performance cost) to up to 254
188 * without changing the format above */
189 #define MAX_WRAPPED_INTERFACES 40
191 struct socket_info_fd
{
192 struct socket_info_fd
*prev
, *next
;
198 struct socket_info_fd
*fds
;
212 struct sockaddr
*bindname
;
213 socklen_t bindname_len
;
215 struct sockaddr
*myname
;
216 socklen_t myname_len
;
218 struct sockaddr
*peername
;
219 socklen_t peername_len
;
222 unsigned long pck_snd
;
223 unsigned long pck_rcv
;
226 struct socket_info
*prev
, *next
;
230 * File descriptors are shared between threads so we should share socket
233 struct socket_info
*sockets
;
235 /* Function prototypes */
237 bool socket_wrapper_enabled(void);
238 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
241 # define SWRAP_LOG(...)
244 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...) PRINTF_ATTRIBUTE(2, 3);
245 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
247 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...)
252 unsigned int lvl
= 0;
254 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
259 va_start(va
, format
);
260 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
265 case SWRAP_LOG_ERROR
:
267 "SWRAP_ERROR(%d): %s\n",
268 (int)getpid(), buffer
);
272 "SWRAP_WARN(%d): %s\n",
273 (int)getpid(), buffer
);
275 case SWRAP_LOG_DEBUG
:
277 "SWRAP_DEBUG(%d): %s\n",
278 (int)getpid(), buffer
);
280 case SWRAP_LOG_TRACE
:
282 "SWRAP_TRACE(%d): %s\n",
283 (int)getpid(), buffer
);
290 /*********************************************************
291 * SWRAP LOADING LIBC FUNCTIONS
292 *********************************************************/
296 struct swrap_libc_fns
{
297 int (*libc_accept
)(int sockfd
,
298 struct sockaddr
*addr
,
300 int (*libc_bind
)(int sockfd
,
301 const struct sockaddr
*addr
,
303 int (*libc_close
)(int fd
);
304 int (*libc_connect
)(int sockfd
,
305 const struct sockaddr
*addr
,
307 int (*libc_dup
)(int fd
);
308 int (*libc_dup2
)(int oldfd
, int newfd
);
310 int (*libc_eventfd
)(int count
, int flags
);
312 int (*libc_getpeername
)(int sockfd
,
313 struct sockaddr
*addr
,
315 int (*libc_getsockname
)(int sockfd
,
316 struct sockaddr
*addr
,
318 int (*libc_getsockopt
)(int sockfd
,
323 int (*libc_ioctl
)(int d
, unsigned long int request
, ...);
324 int (*libc_listen
)(int sockfd
, int backlog
);
325 int (*libc_open
)(const char *pathname
, int flags
, mode_t mode
);
326 int (*libc_pipe
)(int pipefd
[2]);
327 int (*libc_read
)(int fd
, void *buf
, size_t count
);
328 ssize_t (*libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
329 int (*libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
330 int (*libc_recvfrom
)(int sockfd
,
334 struct sockaddr
*src_addr
,
336 int (*libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
337 int (*libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
338 int (*libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
339 int (*libc_sendto
)(int sockfd
,
343 const struct sockaddr
*dst_addr
,
345 int (*libc_setsockopt
)(int sockfd
,
351 int (*libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
353 int (*libc_socket
)(int domain
, int type
, int protocol
);
354 int (*libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
355 #ifdef HAVE_TIMERFD_CREATE
356 int (*libc_timerfd_create
)(int clockid
, int flags
);
358 ssize_t (*libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
363 void *libsocket_handle
;
370 struct swrap_libc_fns fns
;
373 static struct swrap swrap
;
376 static const char *socket_wrapper_dir(void);
378 #define LIBC_NAME "libc.so"
387 static const char *swrap_str_lib(enum swrap_lib lib
)
394 case SWRAP_LIBSOCKET
:
398 /* Compiler would warn us about unhandled enum value if we get here */
403 static void *swrap_load_lib_handle(enum swrap_lib lib
)
405 int flags
= RTLD_LAZY
;
410 flags
|= RTLD_DEEPBIND
;
416 case SWRAP_LIBSOCKET
:
417 #ifdef HAVE_LIBSOCKET
418 handle
= swrap
.libsocket_handle
;
419 if (handle
== NULL
) {
420 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
421 char soname
[256] = {0};
423 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
424 handle
= dlopen(soname
, flags
);
427 swrap
.libsocket_handle
= handle
;
433 handle
= swrap
.libc_handle
;
435 if (handle
== NULL
) {
436 handle
= dlopen(LIBC_SO
, flags
);
439 if (handle
== NULL
) {
440 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
441 char soname
[256] = {0};
443 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
444 handle
= dlopen(soname
, flags
);
447 swrap
.libc_handle
= handle
;
452 if (handle
== NULL
) {
454 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
456 SWRAP_LOG(SWRAP_LOG_ERROR
,
457 "Failed to dlopen library: %s\n",
466 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
471 handle
= swrap_load_lib_handle(lib
);
473 func
= dlsym(handle
, fn_name
);
475 SWRAP_LOG(SWRAP_LOG_ERROR
,
476 "Failed to find %s: %s\n",
481 SWRAP_LOG(SWRAP_LOG_TRACE
,
483 fn_name
, swrap_str_lib(lib
));
487 #define swrap_load_lib_function(lib, fn_name) \
488 if (swrap.fns.libc_##fn_name == NULL) { \
489 *(void **) (&swrap.fns.libc_##fn_name) = \
490 _swrap_load_lib_function(lib, #fn_name); \
497 * Functions especially from libc need to be loaded individually, you can't load
498 * all at once or gdb will segfault at startup. The same applies to valgrind and
499 * has probably something todo with with the linker.
500 * So we need load each function at the point it is called the first time.
502 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
504 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
506 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
509 static int libc_bind(int sockfd
,
510 const struct sockaddr
*addr
,
513 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
515 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
518 static int libc_close(int fd
)
520 swrap_load_lib_function(SWRAP_LIBC
, close
);
522 return swrap
.fns
.libc_close(fd
);
525 static int libc_connect(int sockfd
,
526 const struct sockaddr
*addr
,
529 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
531 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
534 static int libc_dup(int fd
)
536 swrap_load_lib_function(SWRAP_LIBC
, dup
);
538 return swrap
.fns
.libc_dup(fd
);
541 static int libc_dup2(int oldfd
, int newfd
)
543 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
545 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
549 static int libc_eventfd(int count
, int flags
)
551 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
553 return swrap
.fns
.libc_eventfd(count
, flags
);
557 static int libc_getpeername(int sockfd
,
558 struct sockaddr
*addr
,
561 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
563 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
566 static int libc_getsockname(int sockfd
,
567 struct sockaddr
*addr
,
570 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
572 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
575 static int libc_getsockopt(int sockfd
,
581 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
583 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
586 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
592 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
594 for (i
= 0; i
< 4; i
++) {
595 args
[i
] = va_arg(ap
, long int);
598 rc
= swrap
.fns
.libc_ioctl(d
,
608 static int libc_listen(int sockfd
, int backlog
)
610 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
612 return swrap
.fns
.libc_listen(sockfd
, backlog
);
615 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
620 swrap_load_lib_function(SWRAP_LIBC
, open
);
622 mode
= va_arg(ap
, long int);
624 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
629 static int libc_open(const char *pathname
, int flags
, ...)
635 fd
= libc_vopen(pathname
, flags
, ap
);
641 static int libc_pipe(int pipefd
[2])
643 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
645 return swrap
.fns
.libc_pipe(pipefd
);
648 static int libc_read(int fd
, void *buf
, size_t count
)
650 swrap_load_lib_function(SWRAP_LIBC
, read
);
652 return swrap
.fns
.libc_read(fd
, buf
, count
);
655 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
657 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
659 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
662 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
664 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
666 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
669 static int libc_recvfrom(int sockfd
,
673 struct sockaddr
*src_addr
,
676 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
678 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
681 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
683 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
685 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
688 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
690 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
692 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
695 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
697 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
699 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
702 static int libc_sendto(int sockfd
,
706 const struct sockaddr
*dst_addr
,
709 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
711 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
714 static int libc_setsockopt(int sockfd
,
720 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
722 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
726 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
728 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
730 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
734 static int libc_socket(int domain
, int type
, int protocol
)
736 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
738 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
741 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
743 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
745 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
748 #ifdef HAVE_TIMERFD_CREATE
749 static int libc_timerfd_create(int clockid
, int flags
)
751 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
753 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
757 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
759 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
761 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
764 /*********************************************************
765 * SWRAP HELPER FUNCTIONS
766 *********************************************************/
772 static const struct in6_addr
*swrap_ipv6(void)
774 static struct in6_addr v
;
775 static int initialized
;
783 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
792 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
794 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
795 memcpy(ret
, data
, len
);
799 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
803 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
807 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
813 static size_t socket_length(int family
)
817 return sizeof(struct sockaddr_in
);
820 return sizeof(struct sockaddr_in6
);
826 static const char *socket_wrapper_dir(void)
828 const char *s
= getenv("SOCKET_WRAPPER_DIR");
832 if (strncmp(s
, "./", 2) == 0) {
836 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
840 bool socket_wrapper_enabled(void)
842 const char *s
= socket_wrapper_dir();
844 return s
!= NULL
? true : false;
847 static unsigned int socket_wrapper_default_iface(void)
849 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
852 if (sscanf(s
, "%u", &iface
) == 1) {
853 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
859 return 1;/* 127.0.0.1 */
862 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
869 p
= strrchr(un
->sun_path
, '/');
870 if (p
) p
++; else p
= un
->sun_path
;
872 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
877 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
880 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
891 case SOCKET_TYPE_CHAR_TCP
:
892 case SOCKET_TYPE_CHAR_UDP
: {
893 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
895 if ((*len
) < sizeof(*in2
)) {
900 memset(in2
, 0, sizeof(*in2
));
901 in2
->sin_family
= AF_INET
;
902 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
903 in2
->sin_port
= htons(prt
);
909 case SOCKET_TYPE_CHAR_TCP_V6
:
910 case SOCKET_TYPE_CHAR_UDP_V6
: {
911 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
913 if ((*len
) < sizeof(*in2
)) {
918 memset(in2
, 0, sizeof(*in2
));
919 in2
->sin6_family
= AF_INET6
;
920 in2
->sin6_addr
= *swrap_ipv6();
921 in2
->sin6_addr
.s6_addr
[15] = iface
;
922 in2
->sin6_port
= htons(prt
);
936 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
944 if (bcast
) *bcast
= 0;
946 switch (inaddr
->sa_family
) {
948 const struct sockaddr_in
*in
=
949 (const struct sockaddr_in
*)(const void *)inaddr
;
950 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
957 u_type
= SOCKET_TYPE_CHAR_TCP
;
960 u_type
= SOCKET_TYPE_CHAR_UDP
;
961 a_type
= SOCKET_TYPE_CHAR_UDP
;
962 b_type
= SOCKET_TYPE_CHAR_UDP
;
965 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
966 errno
= ESOCKTNOSUPPORT
;
970 prt
= ntohs(in
->sin_port
);
971 if (a_type
&& addr
== 0xFFFFFFFF) {
972 /* 255.255.255.255 only udp */
975 iface
= socket_wrapper_default_iface();
976 } else if (b_type
&& addr
== 0x7FFFFFFF) {
977 /* 127.255.255.255 only udp */
980 iface
= socket_wrapper_default_iface();
981 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
985 iface
= (addr
& 0x000000FF);
990 if (bcast
) *bcast
= is_bcast
;
995 const struct sockaddr_in6
*in
=
996 (const struct sockaddr_in6
*)(const void *)inaddr
;
997 struct in6_addr cmp1
, cmp2
;
1001 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1004 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1007 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1008 errno
= ESOCKTNOSUPPORT
;
1012 /* XXX no multicast/broadcast */
1014 prt
= ntohs(in
->sin6_port
);
1016 cmp1
= *swrap_ipv6();
1017 cmp2
= in
->sin6_addr
;
1018 cmp2
.s6_addr
[15] = 0;
1019 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1020 iface
= in
->sin6_addr
.s6_addr
[15];
1022 errno
= ENETUNREACH
;
1030 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1031 errno
= ENETUNREACH
;
1036 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1042 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1043 socket_wrapper_dir());
1044 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1045 /* the caller need to do more processing */
1049 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1050 socket_wrapper_dir(), type
, iface
, prt
);
1051 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1056 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1065 if (bcast
) *bcast
= 0;
1067 switch (si
->family
) {
1069 const struct sockaddr_in
*in
=
1070 (const struct sockaddr_in
*)(const void *)inaddr
;
1071 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1077 prt
= ntohs(in
->sin_port
);
1081 u_type
= SOCKET_TYPE_CHAR_TCP
;
1082 d_type
= SOCKET_TYPE_CHAR_TCP
;
1085 u_type
= SOCKET_TYPE_CHAR_UDP
;
1086 d_type
= SOCKET_TYPE_CHAR_UDP
;
1087 a_type
= SOCKET_TYPE_CHAR_UDP
;
1088 b_type
= SOCKET_TYPE_CHAR_UDP
;
1091 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1092 errno
= ESOCKTNOSUPPORT
;
1100 iface
= socket_wrapper_default_iface();
1101 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1102 /* 255.255.255.255 only udp */
1105 iface
= socket_wrapper_default_iface();
1106 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1107 /* 127.255.255.255 only udp */
1110 iface
= socket_wrapper_default_iface();
1111 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1115 iface
= (addr
& 0x000000FF);
1117 errno
= EADDRNOTAVAIL
;
1121 /* Store the bind address for connect() */
1122 if (si
->bindname
== NULL
) {
1123 struct sockaddr_in bind_in
;
1124 socklen_t blen
= sizeof(struct sockaddr_in
);
1126 ZERO_STRUCT(bind_in
);
1127 bind_in
.sin_family
= in
->sin_family
;
1128 bind_in
.sin_port
= in
->sin_port
;
1129 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1131 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1132 si
->bindname_len
= blen
;
1139 const struct sockaddr_in6
*in
=
1140 (const struct sockaddr_in6
*)(const void *)inaddr
;
1141 struct in6_addr cmp1
, cmp2
;
1145 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1148 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1151 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1152 errno
= ESOCKTNOSUPPORT
;
1156 /* XXX no multicast/broadcast */
1158 prt
= ntohs(in
->sin6_port
);
1160 cmp1
= *swrap_ipv6();
1161 cmp2
= in
->sin6_addr
;
1162 cmp2
.s6_addr
[15] = 0;
1163 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1164 iface
= socket_wrapper_default_iface();
1165 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1166 iface
= in
->sin6_addr
.s6_addr
[15];
1168 errno
= EADDRNOTAVAIL
;
1172 /* Store the bind address for connect() */
1173 if (si
->bindname
== NULL
) {
1174 struct sockaddr_in6 bind_in
;
1175 socklen_t blen
= sizeof(struct sockaddr_in6
);
1177 ZERO_STRUCT(bind_in
);
1178 bind_in
.sin6_family
= in
->sin6_family
;
1179 bind_in
.sin6_port
= in
->sin6_port
;
1181 bind_in
.sin6_addr
= *swrap_ipv6();
1182 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1184 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1185 si
->bindname_len
= blen
;
1192 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1193 errno
= EADDRNOTAVAIL
;
1198 if (bcast
) *bcast
= is_bcast
;
1200 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1206 /* handle auto-allocation of ephemeral ports */
1207 for (prt
= 5001; prt
< 10000; prt
++) {
1208 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1209 socket_wrapper_dir(), type
, iface
, prt
);
1210 if (stat(un
->sun_path
, &st
) == 0) continue;
1212 set_port(si
->family
, prt
, si
->myname
);
1213 set_port(si
->family
, prt
, si
->bindname
);
1223 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1224 socket_wrapper_dir(), type
, iface
, prt
);
1225 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1229 static struct socket_info
*find_socket_info(int fd
)
1231 struct socket_info
*i
;
1233 for (i
= sockets
; i
; i
= i
->next
) {
1234 struct socket_info_fd
*f
;
1235 for (f
= i
->fds
; f
; f
= f
->next
) {
1245 static void swrap_remove_stale(int fd
)
1247 struct socket_info
*si
= find_socket_info(fd
);
1248 struct socket_info_fd
*fi
;
1251 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1253 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1254 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1260 if (si
->fds
== NULL
) {
1261 SWRAP_DLIST_REMOVE(sockets
, si
);
1266 static int sockaddr_convert_to_un(struct socket_info
*si
,
1267 const struct sockaddr
*in_addr
,
1269 struct sockaddr_un
*out_addr
,
1273 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1275 (void) in_len
; /* unused */
1277 if (out_addr
== NULL
) {
1281 out
->sa_family
= AF_UNIX
;
1282 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1283 out
->sa_len
= sizeof(*out_addr
);
1286 switch (in_addr
->sa_family
) {
1296 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1297 errno
= ESOCKTNOSUPPORT
;
1301 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1303 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1309 errno
= EAFNOSUPPORT
;
1310 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1314 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1315 const struct sockaddr_un
*in_addr
,
1316 socklen_t un_addrlen
,
1318 struct sockaddr
*out_addr
,
1319 socklen_t
*out_addrlen
)
1323 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1326 if (un_addrlen
== 0) {
1341 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1342 errno
= ESOCKTNOSUPPORT
;
1345 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1346 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1347 out_addr
->sa_len
= *out_addrlen
;
1354 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1355 errno
= EAFNOSUPPORT
;
1359 enum swrap_packet_type
{
1361 SWRAP_CONNECT_UNREACH
,
1369 SWRAP_SENDTO_UNREACH
,
1380 struct swrap_file_hdr
{
1382 uint16_t version_major
;
1383 uint16_t version_minor
;
1386 uint32_t frame_max_len
;
1387 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1390 #define SWRAP_FILE_HDR_SIZE 24
1392 struct swrap_packet_frame
{
1394 uint32_t micro_seconds
;
1395 uint32_t recorded_length
;
1396 uint32_t full_length
;
1398 #define SWRAP_PACKET_FRAME_SIZE 16
1400 union swrap_packet_ip
{
1404 uint16_t packet_length
;
1405 uint16_t identification
;
1410 uint16_t hdr_checksum
;
1414 #define SWRAP_PACKET_IP_V4_SIZE 20
1417 uint8_t flow_label_high
;
1418 uint16_t flow_label_low
;
1419 uint16_t payload_length
;
1420 uint8_t next_header
;
1422 uint8_t src_addr
[16];
1423 uint8_t dest_addr
[16];
1425 #define SWRAP_PACKET_IP_V6_SIZE 40
1427 #define SWRAP_PACKET_IP_SIZE 40
1429 union swrap_packet_payload
{
1431 uint16_t source_port
;
1441 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1443 uint16_t source_port
;
1448 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1455 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1462 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1464 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1466 #define SWRAP_PACKET_MIN_ALLOC \
1467 (SWRAP_PACKET_FRAME_SIZE + \
1468 SWRAP_PACKET_IP_SIZE + \
1469 SWRAP_PACKET_PAYLOAD_SIZE)
1471 static const char *socket_wrapper_pcap_file(void)
1473 static int initialized
= 0;
1474 static const char *s
= NULL
;
1475 static const struct swrap_file_hdr h
;
1476 static const struct swrap_packet_frame f
;
1477 static const union swrap_packet_ip i
;
1478 static const union swrap_packet_payload p
;
1480 if (initialized
== 1) {
1486 * TODO: don't use the structs use plain buffer offsets
1487 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1489 * for now make sure we disable PCAP support
1490 * if the struct has alignment!
1492 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1495 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1498 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1501 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1504 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1507 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1510 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1513 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1516 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1519 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1523 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1527 if (strncmp(s
, "./", 2) == 0) {
1533 static uint8_t *swrap_packet_init(struct timeval
*tval
,
1534 const struct sockaddr
*src
,
1535 const struct sockaddr
*dest
,
1537 const uint8_t *payload
,
1539 unsigned long tcp_seqno
,
1540 unsigned long tcp_ack
,
1541 unsigned char tcp_ctl
,
1543 size_t *_packet_len
)
1547 struct swrap_packet_frame
*frame
;
1548 union swrap_packet_ip
*ip
;
1549 union swrap_packet_payload
*pay
;
1552 size_t nonwire_len
= sizeof(*frame
);
1553 size_t wire_hdr_len
= 0;
1554 size_t wire_len
= 0;
1555 size_t ip_hdr_len
= 0;
1556 size_t icmp_hdr_len
= 0;
1557 size_t icmp_truncate_len
= 0;
1558 uint8_t protocol
= 0, icmp_protocol
= 0;
1559 const struct sockaddr_in
*src_in
= NULL
;
1560 const struct sockaddr_in
*dest_in
= NULL
;
1562 const struct sockaddr_in6
*src_in6
= NULL
;
1563 const struct sockaddr_in6
*dest_in6
= NULL
;
1568 switch (src
->sa_family
) {
1570 src_in
= (const struct sockaddr_in
*)src
;
1571 dest_in
= (const struct sockaddr_in
*)dest
;
1572 src_port
= src_in
->sin_port
;
1573 dest_port
= dest_in
->sin_port
;
1574 ip_hdr_len
= sizeof(ip
->v4
);
1578 src_in6
= (const struct sockaddr_in6
*)src
;
1579 dest_in6
= (const struct sockaddr_in6
*)dest
;
1580 src_port
= src_in6
->sin6_port
;
1581 dest_port
= dest_in6
->sin6_port
;
1582 ip_hdr_len
= sizeof(ip
->v6
);
1589 switch (socket_type
) {
1591 protocol
= 0x06; /* TCP */
1592 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1593 wire_len
= wire_hdr_len
+ payload_len
;
1597 protocol
= 0x11; /* UDP */
1598 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1599 wire_len
= wire_hdr_len
+ payload_len
;
1607 icmp_protocol
= protocol
;
1608 switch (src
->sa_family
) {
1610 protocol
= 0x01; /* ICMPv4 */
1611 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1615 protocol
= 0x3A; /* ICMPv6 */
1616 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1620 if (wire_len
> 64 ) {
1621 icmp_truncate_len
= wire_len
- 64;
1623 wire_hdr_len
+= icmp_hdr_len
;
1624 wire_len
+= icmp_hdr_len
;
1627 packet_len
= nonwire_len
+ wire_len
;
1628 alloc_len
= packet_len
;
1629 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1630 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1633 base
= (uint8_t *)malloc(alloc_len
);
1637 memset(base
, 0x0, alloc_len
);
1641 frame
= (struct swrap_packet_frame
*)buf
;
1642 frame
->seconds
= tval
->tv_sec
;
1643 frame
->micro_seconds
= tval
->tv_usec
;
1644 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1645 frame
->full_length
= wire_len
- icmp_truncate_len
;
1646 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1648 ip
= (union swrap_packet_ip
*)buf
;
1649 switch (src
->sa_family
) {
1651 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1653 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1654 ip
->v4
.identification
= htons(0xFFFF);
1655 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1656 ip
->v4
.fragment
= htons(0x0000);
1658 ip
->v4
.protocol
= protocol
;
1659 ip
->v4
.hdr_checksum
= htons(0x0000);
1660 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1661 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1662 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1666 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1667 ip
->v6
.flow_label_high
= 0x00;
1668 ip
->v6
.flow_label_low
= 0x0000;
1669 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1670 ip
->v6
.next_header
= protocol
;
1671 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1672 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1673 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1679 pay
= (union swrap_packet_payload
*)buf
;
1680 switch (src
->sa_family
) {
1682 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1683 pay
->icmp4
.code
= 0x01; /* host unreachable */
1684 pay
->icmp4
.checksum
= htons(0x0000);
1685 pay
->icmp4
.unused
= htonl(0x00000000);
1686 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1688 /* set the ip header in the ICMP payload */
1689 ip
= (union swrap_packet_ip
*)buf
;
1690 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1692 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1693 ip
->v4
.identification
= htons(0xFFFF);
1694 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1695 ip
->v4
.fragment
= htons(0x0000);
1697 ip
->v4
.protocol
= icmp_protocol
;
1698 ip
->v4
.hdr_checksum
= htons(0x0000);
1699 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1700 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1701 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1703 src_port
= dest_in
->sin_port
;
1704 dest_port
= src_in
->sin_port
;
1708 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1709 pay
->icmp6
.code
= 0x03; /* address unreachable */
1710 pay
->icmp6
.checksum
= htons(0x0000);
1711 pay
->icmp6
.unused
= htonl(0x00000000);
1712 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1714 /* set the ip header in the ICMP payload */
1715 ip
= (union swrap_packet_ip
*)buf
;
1716 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1717 ip
->v6
.flow_label_high
= 0x00;
1718 ip
->v6
.flow_label_low
= 0x0000;
1719 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1720 ip
->v6
.next_header
= protocol
;
1721 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1722 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1723 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1725 src_port
= dest_in6
->sin6_port
;
1726 dest_port
= src_in6
->sin6_port
;
1732 pay
= (union swrap_packet_payload
*)buf
;
1734 switch (socket_type
) {
1736 pay
->tcp
.source_port
= src_port
;
1737 pay
->tcp
.dest_port
= dest_port
;
1738 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1739 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1740 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1741 pay
->tcp
.control
= tcp_ctl
;
1742 pay
->tcp
.window
= htons(0x7FFF);
1743 pay
->tcp
.checksum
= htons(0x0000);
1744 pay
->tcp
.urg
= htons(0x0000);
1745 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1750 pay
->udp
.source_port
= src_port
;
1751 pay
->udp
.dest_port
= dest_port
;
1752 pay
->udp
.length
= htons(8 + payload_len
);
1753 pay
->udp
.checksum
= htons(0x0000);
1754 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1759 if (payload
&& payload_len
> 0) {
1760 memcpy(buf
, payload
, payload_len
);
1763 *_packet_len
= packet_len
- icmp_truncate_len
;
1767 static int swrap_get_pcap_fd(const char *fname
)
1771 if (fd
!= -1) return fd
;
1773 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1775 struct swrap_file_hdr file_hdr
;
1776 file_hdr
.magic
= 0xA1B2C3D4;
1777 file_hdr
.version_major
= 0x0002;
1778 file_hdr
.version_minor
= 0x0004;
1779 file_hdr
.timezone
= 0x00000000;
1780 file_hdr
.sigfigs
= 0x00000000;
1781 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1782 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1784 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1791 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1796 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1797 const struct sockaddr
*addr
,
1798 enum swrap_packet_type type
,
1799 const void *buf
, size_t len
,
1802 const struct sockaddr
*src_addr
;
1803 const struct sockaddr
*dest_addr
;
1804 unsigned long tcp_seqno
= 0;
1805 unsigned long tcp_ack
= 0;
1806 unsigned char tcp_ctl
= 0;
1807 int unreachable
= 0;
1811 switch (si
->family
) {
1823 case SWRAP_CONNECT_SEND
:
1824 if (si
->type
!= SOCK_STREAM
) return NULL
;
1826 src_addr
= si
->myname
;
1829 tcp_seqno
= si
->io
.pck_snd
;
1830 tcp_ack
= si
->io
.pck_rcv
;
1831 tcp_ctl
= 0x02; /* SYN */
1833 si
->io
.pck_snd
+= 1;
1837 case SWRAP_CONNECT_RECV
:
1838 if (si
->type
!= SOCK_STREAM
) return NULL
;
1840 dest_addr
= si
->myname
;
1843 tcp_seqno
= si
->io
.pck_rcv
;
1844 tcp_ack
= si
->io
.pck_snd
;
1845 tcp_ctl
= 0x12; /** SYN,ACK */
1847 si
->io
.pck_rcv
+= 1;
1851 case SWRAP_CONNECT_UNREACH
:
1852 if (si
->type
!= SOCK_STREAM
) return NULL
;
1854 dest_addr
= si
->myname
;
1857 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1858 tcp_seqno
= si
->io
.pck_snd
- 1;
1859 tcp_ack
= si
->io
.pck_rcv
;
1860 tcp_ctl
= 0x02; /* SYN */
1865 case SWRAP_CONNECT_ACK
:
1866 if (si
->type
!= SOCK_STREAM
) return NULL
;
1868 src_addr
= si
->myname
;
1871 tcp_seqno
= si
->io
.pck_snd
;
1872 tcp_ack
= si
->io
.pck_rcv
;
1873 tcp_ctl
= 0x10; /* ACK */
1877 case SWRAP_ACCEPT_SEND
:
1878 if (si
->type
!= SOCK_STREAM
) return NULL
;
1880 dest_addr
= si
->myname
;
1883 tcp_seqno
= si
->io
.pck_rcv
;
1884 tcp_ack
= si
->io
.pck_snd
;
1885 tcp_ctl
= 0x02; /* SYN */
1887 si
->io
.pck_rcv
+= 1;
1891 case SWRAP_ACCEPT_RECV
:
1892 if (si
->type
!= SOCK_STREAM
) return NULL
;
1894 src_addr
= si
->myname
;
1897 tcp_seqno
= si
->io
.pck_snd
;
1898 tcp_ack
= si
->io
.pck_rcv
;
1899 tcp_ctl
= 0x12; /* SYN,ACK */
1901 si
->io
.pck_snd
+= 1;
1905 case SWRAP_ACCEPT_ACK
:
1906 if (si
->type
!= SOCK_STREAM
) return NULL
;
1908 dest_addr
= si
->myname
;
1911 tcp_seqno
= si
->io
.pck_rcv
;
1912 tcp_ack
= si
->io
.pck_snd
;
1913 tcp_ctl
= 0x10; /* ACK */
1918 src_addr
= si
->myname
;
1919 dest_addr
= si
->peername
;
1921 tcp_seqno
= si
->io
.pck_snd
;
1922 tcp_ack
= si
->io
.pck_rcv
;
1923 tcp_ctl
= 0x18; /* PSH,ACK */
1925 si
->io
.pck_snd
+= len
;
1929 case SWRAP_SEND_RST
:
1930 dest_addr
= si
->myname
;
1931 src_addr
= si
->peername
;
1933 if (si
->type
== SOCK_DGRAM
) {
1934 return swrap_marshall_packet(si
, si
->peername
,
1935 SWRAP_SENDTO_UNREACH
,
1936 buf
, len
, packet_len
);
1939 tcp_seqno
= si
->io
.pck_rcv
;
1940 tcp_ack
= si
->io
.pck_snd
;
1941 tcp_ctl
= 0x14; /** RST,ACK */
1945 case SWRAP_PENDING_RST
:
1946 dest_addr
= si
->myname
;
1947 src_addr
= si
->peername
;
1949 if (si
->type
== SOCK_DGRAM
) {
1953 tcp_seqno
= si
->io
.pck_rcv
;
1954 tcp_ack
= si
->io
.pck_snd
;
1955 tcp_ctl
= 0x14; /* RST,ACK */
1960 dest_addr
= si
->myname
;
1961 src_addr
= si
->peername
;
1963 tcp_seqno
= si
->io
.pck_rcv
;
1964 tcp_ack
= si
->io
.pck_snd
;
1965 tcp_ctl
= 0x18; /* PSH,ACK */
1967 si
->io
.pck_rcv
+= len
;
1971 case SWRAP_RECV_RST
:
1972 dest_addr
= si
->myname
;
1973 src_addr
= si
->peername
;
1975 if (si
->type
== SOCK_DGRAM
) {
1979 tcp_seqno
= si
->io
.pck_rcv
;
1980 tcp_ack
= si
->io
.pck_snd
;
1981 tcp_ctl
= 0x14; /* RST,ACK */
1986 src_addr
= si
->myname
;
1989 si
->io
.pck_snd
+= len
;
1993 case SWRAP_SENDTO_UNREACH
:
1994 dest_addr
= si
->myname
;
2001 case SWRAP_RECVFROM
:
2002 dest_addr
= si
->myname
;
2005 si
->io
.pck_rcv
+= len
;
2009 case SWRAP_CLOSE_SEND
:
2010 if (si
->type
!= SOCK_STREAM
) return NULL
;
2012 src_addr
= si
->myname
;
2013 dest_addr
= si
->peername
;
2015 tcp_seqno
= si
->io
.pck_snd
;
2016 tcp_ack
= si
->io
.pck_rcv
;
2017 tcp_ctl
= 0x11; /* FIN, ACK */
2019 si
->io
.pck_snd
+= 1;
2023 case SWRAP_CLOSE_RECV
:
2024 if (si
->type
!= SOCK_STREAM
) return NULL
;
2026 dest_addr
= si
->myname
;
2027 src_addr
= si
->peername
;
2029 tcp_seqno
= si
->io
.pck_rcv
;
2030 tcp_ack
= si
->io
.pck_snd
;
2031 tcp_ctl
= 0x11; /* FIN,ACK */
2033 si
->io
.pck_rcv
+= 1;
2037 case SWRAP_CLOSE_ACK
:
2038 if (si
->type
!= SOCK_STREAM
) return NULL
;
2040 src_addr
= si
->myname
;
2041 dest_addr
= si
->peername
;
2043 tcp_seqno
= si
->io
.pck_snd
;
2044 tcp_ack
= si
->io
.pck_rcv
;
2045 tcp_ctl
= 0x10; /* ACK */
2052 swrapGetTimeOfDay(&tv
);
2054 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
2055 (const uint8_t *)buf
, len
,
2056 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
2060 static void swrap_dump_packet(struct socket_info
*si
,
2061 const struct sockaddr
*addr
,
2062 enum swrap_packet_type type
,
2063 const void *buf
, size_t len
)
2065 const char *file_name
;
2067 size_t packet_len
= 0;
2070 file_name
= socket_wrapper_pcap_file();
2075 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
2080 fd
= swrap_get_pcap_fd(file_name
);
2082 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2091 /****************************************************************************
2093 ***************************************************************************/
2095 #ifdef HAVE_SIGNALFD
2096 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2100 rc
= libc_signalfd(fd
, mask
, flags
);
2102 swrap_remove_stale(fd
);
2108 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2110 return swrap_signalfd(fd
, mask
, flags
);
2114 /****************************************************************************
2116 ***************************************************************************/
2118 static int swrap_socket(int family
, int type
, int protocol
)
2120 struct socket_info
*si
;
2121 struct socket_info_fd
*fi
;
2123 int real_type
= type
;
2126 * Remove possible addition flags passed to socket() so
2127 * do not fail checking the type.
2128 * See https://lwn.net/Articles/281965/
2131 real_type
&= ~SOCK_CLOEXEC
;
2133 #ifdef SOCK_NONBLOCK
2134 real_type
&= ~SOCK_NONBLOCK
;
2137 if (!socket_wrapper_enabled()) {
2138 return libc_socket(family
, type
, protocol
);
2148 return libc_socket(family
, type
, protocol
);
2150 errno
= EAFNOSUPPORT
;
2154 switch (real_type
) {
2160 errno
= EPROTONOSUPPORT
;
2168 if (real_type
== SOCK_STREAM
) {
2173 if (real_type
== SOCK_DGRAM
) {
2178 errno
= EPROTONOSUPPORT
;
2183 * We must call libc_socket with type, from the caller, not the version
2184 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2186 fd
= libc_socket(AF_UNIX
, type
, 0);
2192 /* Check if we have a stale fd and remove it */
2193 si
= find_socket_info(fd
);
2195 swrap_remove_stale(fd
);
2198 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2199 memset(si
, 0, sizeof(struct socket_info
));
2205 si
->family
= family
;
2207 /* however, the rest of the socket_wrapper code expects just
2208 * the type, not the flags */
2209 si
->type
= real_type
;
2210 si
->protocol
= protocol
;
2212 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2221 SWRAP_DLIST_ADD(si
->fds
, fi
);
2222 SWRAP_DLIST_ADD(sockets
, si
);
2227 int socket(int family
, int type
, int protocol
)
2229 return swrap_socket(family
, type
, protocol
);
2232 /****************************************************************************
2234 ***************************************************************************/
2236 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2240 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2242 swrap_remove_stale(sv
[0]);
2243 swrap_remove_stale(sv
[1]);
2249 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2251 return swrap_socketpair(family
, type
, protocol
, sv
);
2254 /****************************************************************************
2256 ***************************************************************************/
2258 #ifdef HAVE_TIMERFD_CREATE
2259 static int swrap_timerfd_create(int clockid
, int flags
)
2263 fd
= libc_timerfd_create(clockid
, flags
);
2265 swrap_remove_stale(fd
);
2271 int timerfd_create(int clockid
, int flags
)
2273 return swrap_timerfd_create(clockid
, flags
);
2277 /****************************************************************************
2279 ***************************************************************************/
2281 static int swrap_pipe(int pipefd
[2])
2285 rc
= libc_pipe(pipefd
);
2287 swrap_remove_stale(pipefd
[0]);
2288 swrap_remove_stale(pipefd
[1]);
2294 int pipe(int pipefd
[2])
2296 return swrap_pipe(pipefd
);
2299 /****************************************************************************
2301 ***************************************************************************/
2303 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2305 struct socket_info
*parent_si
, *child_si
;
2306 struct socket_info_fd
*child_fi
;
2308 struct sockaddr_un un_addr
;
2309 socklen_t un_addrlen
= sizeof(un_addr
);
2310 struct sockaddr_un un_my_addr
;
2311 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
2312 struct sockaddr
*my_addr
;
2313 socklen_t my_addrlen
, len
;
2316 parent_si
= find_socket_info(s
);
2318 return libc_accept(s
, addr
, addrlen
);
2322 * assume out sockaddr have the same size as the in parent
2325 my_addrlen
= socket_length(parent_si
->family
);
2326 if (my_addrlen
<= 0) {
2331 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
2332 if (my_addr
== NULL
) {
2336 memset(&un_addr
, 0, sizeof(un_addr
));
2337 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
2339 ret
= libc_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2341 if (errno
== ENOTSOCK
) {
2342 /* Remove stale fds */
2343 swrap_remove_stale(s
);
2352 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
2353 parent_si
->family
, my_addr
, &len
);
2360 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2361 memset(child_si
, 0, sizeof(struct socket_info
));
2363 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2364 if (child_fi
== NULL
) {
2374 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2376 child_si
->family
= parent_si
->family
;
2377 child_si
->type
= parent_si
->type
;
2378 child_si
->protocol
= parent_si
->protocol
;
2379 child_si
->bound
= 1;
2380 child_si
->is_server
= 1;
2381 child_si
->connected
= 1;
2383 child_si
->peername_len
= len
;
2384 child_si
->peername
= sockaddr_dup(my_addr
, len
);
2386 if (addr
!= NULL
&& addrlen
!= NULL
) {
2387 size_t copy_len
= MIN(*addrlen
, len
);
2389 memcpy(addr
, my_addr
, copy_len
);
2394 ret
= libc_getsockname(fd
,
2395 (struct sockaddr
*)(void *)&un_my_addr
,
2406 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
2407 child_si
->family
, my_addr
, &len
);
2416 SWRAP_LOG(SWRAP_LOG_TRACE
,
2417 "accept() path=%s, fd=%d",
2418 un_my_addr
.sun_path
, s
);
2420 child_si
->myname_len
= len
;
2421 child_si
->myname
= sockaddr_dup(my_addr
, len
);
2424 SWRAP_DLIST_ADD(sockets
, child_si
);
2427 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2428 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2429 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2435 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2436 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2438 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2441 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2444 static int autobind_start_init
;
2445 static int autobind_start
;
2447 /* using sendto() or connect() on an unbound socket would give the
2448 recipient no way to reply, as unlike UDP and TCP, a unix domain
2449 socket can't auto-assign ephemeral port numbers, so we need to
2451 Note: this might change the family from ipv6 to ipv4
2453 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2455 struct sockaddr_un un_addr
;
2462 if (autobind_start_init
!= 1) {
2463 autobind_start_init
= 1;
2464 autobind_start
= getpid();
2465 autobind_start
%= 50000;
2466 autobind_start
+= 10000;
2469 un_addr
.sun_family
= AF_UNIX
;
2473 struct sockaddr_in in
;
2477 type
= SOCKET_TYPE_CHAR_TCP
;
2480 type
= SOCKET_TYPE_CHAR_UDP
;
2483 errno
= ESOCKTNOSUPPORT
;
2487 memset(&in
, 0, sizeof(in
));
2488 in
.sin_family
= AF_INET
;
2489 in
.sin_addr
.s_addr
= htonl(127<<24 |
2490 socket_wrapper_default_iface());
2492 si
->myname_len
= sizeof(in
);
2493 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
2498 struct sockaddr_in6 in6
;
2500 if (si
->family
!= family
) {
2501 errno
= ENETUNREACH
;
2507 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2510 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2513 errno
= ESOCKTNOSUPPORT
;
2517 memset(&in6
, 0, sizeof(in6
));
2518 in6
.sin6_family
= AF_INET6
;
2519 in6
.sin6_addr
= *swrap_ipv6();
2520 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2521 si
->myname_len
= sizeof(in6
);
2522 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
2527 errno
= ESOCKTNOSUPPORT
;
2531 if (autobind_start
> 60000) {
2532 autobind_start
= 10000;
2535 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2536 port
= autobind_start
+ i
;
2537 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
2538 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2539 type
, socket_wrapper_default_iface(), port
);
2540 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
2542 ret
= libc_bind(fd
, (struct sockaddr
*)(void *)&un_addr
,
2544 if (ret
== -1) return ret
;
2546 si
->tmp_path
= strdup(un_addr
.sun_path
);
2548 autobind_start
= port
+ 1;
2551 if (i
== SOCKET_MAX_SOCKETS
) {
2552 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2553 "interface "SOCKET_FORMAT
,
2556 socket_wrapper_default_iface(),
2562 si
->family
= family
;
2563 set_port(si
->family
, port
, si
->myname
);
2568 /****************************************************************************
2570 ***************************************************************************/
2572 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2576 struct sockaddr_un un_addr
;
2577 struct socket_info
*si
= find_socket_info(s
);
2581 return libc_connect(s
, serv_addr
, addrlen
);
2584 if (si
->bound
== 0) {
2585 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2586 if (ret
== -1) return -1;
2589 if (si
->family
!= serv_addr
->sa_family
) {
2594 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2595 addrlen
, &un_addr
, 0, &bcast
);
2596 if (ret
== -1) return -1;
2599 errno
= ENETUNREACH
;
2603 if (si
->type
== SOCK_DGRAM
) {
2604 si
->defer_connect
= 1;
2607 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2609 ret
= libc_connect(s
,
2610 (struct sockaddr
*)(void *)&un_addr
,
2611 sizeof(struct sockaddr_un
));
2614 SWRAP_LOG(SWRAP_LOG_TRACE
,
2615 "connect() path=%s, fd=%d",
2616 un_addr
.sun_path
, s
);
2619 /* to give better errors */
2620 if (ret
== -1 && errno
== ENOENT
) {
2621 errno
= EHOSTUNREACH
;
2625 si
->peername_len
= addrlen
;
2626 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
2630 * When we connect() on a socket than we have to bind the
2631 * outgoing connection on the interface we use for the
2632 * transport. We already bound it on the right interface
2633 * but here we have to update the name so getsockname()
2634 * returns correct information.
2636 if (si
->bindname
!= NULL
) {
2639 si
->myname
= si
->bindname
;
2640 si
->myname_len
= si
->bindname_len
;
2642 si
->bindname
= NULL
;
2643 si
->bindname_len
= 0;
2646 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2647 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2649 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2655 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2657 return swrap_connect(s
, serv_addr
, addrlen
);
2660 /****************************************************************************
2662 ***************************************************************************/
2664 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2667 struct sockaddr_un un_addr
;
2668 struct socket_info
*si
= find_socket_info(s
);
2671 return libc_bind(s
, myaddr
, addrlen
);
2674 si
->myname_len
= addrlen
;
2675 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
2677 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
2678 if (ret
== -1) return -1;
2680 unlink(un_addr
.sun_path
);
2682 ret
= libc_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
2683 sizeof(struct sockaddr_un
));
2685 SWRAP_LOG(SWRAP_LOG_TRACE
,
2686 "bind() path=%s, fd=%d",
2687 un_addr
.sun_path
, s
);
2696 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2698 return swrap_bind(s
, myaddr
, addrlen
);
2701 /****************************************************************************
2703 ***************************************************************************/
2705 static int swrap_listen(int s
, int backlog
)
2708 struct socket_info
*si
= find_socket_info(s
);
2711 return libc_listen(s
, backlog
);
2714 ret
= libc_listen(s
, backlog
);
2719 int listen(int s
, int backlog
)
2721 return swrap_listen(s
, backlog
);
2724 /****************************************************************************
2726 ***************************************************************************/
2728 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
2732 ret
= libc_vopen(pathname
, flags
, ap
);
2735 * There are methods for closing descriptors (libc-internal code
2736 * paths, direct syscalls) which close descriptors in ways that
2737 * we can't intercept, so try to recover when we notice that
2740 swrap_remove_stale(ret
);
2745 int open(const char *pathname
, int flags
, ...)
2750 va_start(ap
, flags
);
2751 fd
= swrap_vopen(pathname
, flags
, ap
);
2757 /****************************************************************************
2759 ***************************************************************************/
2761 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2763 struct socket_info
*si
= find_socket_info(s
);
2766 return libc_getpeername(s
, name
, addrlen
);
2775 memcpy(name
, si
->peername
, si
->peername_len
);
2776 *addrlen
= si
->peername_len
;
2781 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2782 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
2784 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2787 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
2790 /****************************************************************************
2792 ***************************************************************************/
2794 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2796 struct socket_info
*si
= find_socket_info(s
);
2799 return libc_getsockname(s
, name
, addrlen
);
2802 memcpy(name
, si
->myname
, si
->myname_len
);
2803 *addrlen
= si
->myname_len
;
2808 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2809 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
2811 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2814 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
2817 /****************************************************************************
2819 ***************************************************************************/
2821 static int swrap_getsockopt(int s
, int level
, int optname
,
2822 void *optval
, socklen_t
*optlen
)
2824 struct socket_info
*si
= find_socket_info(s
);
2827 return libc_getsockopt(s
,
2834 if (level
== SOL_SOCKET
) {
2835 return libc_getsockopt(s
,
2842 errno
= ENOPROTOOPT
;
2846 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2847 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
2849 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
2852 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
2855 /****************************************************************************
2857 ***************************************************************************/
2859 static int swrap_setsockopt(int s
, int level
, int optname
,
2860 const void *optval
, socklen_t optlen
)
2862 struct socket_info
*si
= find_socket_info(s
);
2865 return libc_setsockopt(s
,
2872 if (level
== SOL_SOCKET
) {
2873 return libc_setsockopt(s
,
2880 switch (si
->family
) {
2882 if (level
== IPPROTO_IP
) {
2884 if (optname
== IP_PKTINFO
) {
2885 si
->pktinfo
= AF_INET
;
2887 #endif /* IP_PKTINFO */
2892 if (level
== IPPROTO_IPV6
) {
2893 #ifdef IPV6_RECVPKTINFO
2894 if (optname
== IPV6_RECVPKTINFO
) {
2895 si
->pktinfo
= AF_INET6
;
2897 #endif /* IPV6_PKTINFO */
2902 errno
= ENOPROTOOPT
;
2907 int setsockopt(int s
, int level
, int optname
,
2908 const void *optval
, socklen_t optlen
)
2910 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
2913 /****************************************************************************
2915 ***************************************************************************/
2917 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
2919 struct socket_info
*si
= find_socket_info(s
);
2925 return libc_vioctl(s
, r
, va
);
2930 rc
= libc_vioctl(s
, r
, va
);
2934 value
= *((int *)va_arg(ap
, int *));
2936 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2937 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2938 } else if (value
== 0) { /* END OF FILE */
2939 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2949 #ifdef HAVE_IOCTL_INT
2950 int ioctl(int s
, int r
, ...)
2952 int ioctl(int s
, unsigned long int r
, ...)
2960 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
2971 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2973 * @brief Add a cmsghdr to a msghdr.
2975 * This is an function to add any type of cmsghdr. It will operate on the
2976 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
2977 * the buffer position after the added cmsg element. Hence, this function is
2978 * intended to be used with an intermediate msghdr and not on the original
2979 * one handed in by the client.
2981 * @param[in] msg The msghdr to which to add the cmsg.
2983 * @param[in] level The cmsg level to set.
2985 * @param[in] type The cmsg type to set.
2987 * @param[in] data The cmsg data to set.
2989 * @param[in] len the length of the data to set.
2991 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
2997 size_t cmlen
= CMSG_LEN(len
);
2998 size_t cmspace
= CMSG_SPACE(len
);
2999 uint8_t cmbuf
[cmspace
];
3000 struct cmsghdr
*cm
= (struct cmsghdr
*)cmbuf
;
3003 memset(cmbuf
, 0, cmspace
);
3005 if (msg
->msg_controllen
< cmlen
) {
3006 cmlen
= msg
->msg_controllen
;
3007 msg
->msg_flags
|= MSG_CTRUNC
;
3010 if (msg
->msg_controllen
< cmspace
) {
3011 cmspace
= msg
->msg_controllen
;
3015 * We copy the full input data into an intermediate cmsghdr first
3016 * in order to more easily cope with truncation.
3018 cm
->cmsg_len
= cmlen
;
3019 cm
->cmsg_level
= level
;
3020 cm
->cmsg_type
= type
;
3021 memcpy(CMSG_DATA(cm
), data
, len
);
3024 * We now copy the possibly truncated buffer.
3025 * We copy cmlen bytes, but consume cmspace bytes,
3026 * leaving the possible padding uninitialiazed.
3028 p
= (uint8_t *)msg
->msg_control
;
3029 memcpy(p
, cm
, cmlen
);
3031 msg
->msg_control
= p
;
3032 msg
->msg_controllen
-= cmspace
;
3037 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3040 /* Add packet info */
3041 switch (si
->pktinfo
) {
3044 struct sockaddr_in
*sin
;
3045 struct in_pktinfo pkt
;
3047 if (si
->bindname_len
== sizeof(struct sockaddr_in
)) {
3048 sin
= (struct sockaddr_in
*)si
->bindname
;
3050 if (si
->myname_len
!= sizeof(struct sockaddr_in
)) {
3053 sin
= (struct sockaddr_in
*)si
->myname
;
3058 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3059 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3061 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3066 #endif /* IP_PKTINFO */
3067 #if defined(HAVE_IPV6)
3069 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3070 struct sockaddr_in6
*sin6
;
3071 struct in6_pktinfo pkt6
;
3073 if (si
->bindname_len
== sizeof(struct sockaddr_in6
)) {
3074 sin6
= (struct sockaddr_in6
*)si
->bindname
;
3076 if (si
->myname_len
!= sizeof(struct sockaddr_in6
)) {
3079 sin6
= (struct sockaddr_in6
*)si
->myname
;
3084 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3085 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3087 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3088 &pkt6
, sizeof(pkt6
));
3089 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3093 #endif /* IPV6_PKTINFO */
3101 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3103 static ssize_t
swrap_sendmsg_before(int fd
,
3104 struct socket_info
*si
,
3106 struct iovec
*tmp_iov
,
3107 struct sockaddr_un
*tmp_un
,
3108 const struct sockaddr_un
**to_un
,
3109 const struct sockaddr
**to
,
3127 if (!si
->connected
) {
3132 if (msg
->msg_iovlen
== 0) {
3136 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3138 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3139 if (nlen
> SOCKET_MAX_PACKET
) {
3143 msg
->msg_iovlen
= i
;
3144 if (msg
->msg_iovlen
== 0) {
3145 *tmp_iov
= msg
->msg_iov
[0];
3146 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3147 msg
->msg_iov
= tmp_iov
;
3148 msg
->msg_iovlen
= 1;
3153 if (si
->connected
) {
3154 if (msg
->msg_name
) {
3159 const struct sockaddr
*msg_name
;
3160 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3162 if (msg_name
== NULL
) {
3168 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3170 if (ret
== -1) return -1;
3178 msg
->msg_name
= tmp_un
;
3179 msg
->msg_namelen
= sizeof(*tmp_un
);
3182 if (si
->bound
== 0) {
3183 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3185 if (errno
== ENOTSOCK
) {
3186 swrap_remove_stale(fd
);
3189 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3195 if (!si
->defer_connect
) {
3199 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
3201 if (ret
== -1) return -1;
3203 ret
= libc_connect(fd
,
3204 (struct sockaddr
*)(void *)tmp_un
,
3207 /* to give better errors */
3208 if (ret
== -1 && errno
== ENOENT
) {
3209 errno
= EHOSTUNREACH
;
3216 si
->defer_connect
= 0;
3219 errno
= EHOSTUNREACH
;
3226 static void swrap_sendmsg_after(int fd
,
3227 struct socket_info
*si
,
3229 const struct sockaddr
*to
,
3232 int saved_errno
= errno
;
3239 /* to give better errors */
3241 if (saved_errno
== ENOENT
) {
3242 saved_errno
= EHOSTUNREACH
;
3243 } else if (saved_errno
== ENOTSOCK
) {
3244 /* If the fd is not a socket, remove it */
3245 swrap_remove_stale(fd
);
3249 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3250 avail
+= msg
->msg_iov
[i
].iov_len
;
3254 remain
= MIN(80, avail
);
3259 /* we capture it as one single packet */
3260 buf
= (uint8_t *)malloc(remain
);
3262 /* we just not capture the packet */
3263 errno
= saved_errno
;
3267 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3268 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3270 msg
->msg_iov
[i
].iov_base
,
3273 remain
-= this_time
;
3280 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3281 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3283 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3288 if (si
->connected
) {
3292 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3293 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3295 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3301 errno
= saved_errno
;
3304 static int swrap_recvmsg_before(int fd
,
3305 struct socket_info
*si
,
3307 struct iovec
*tmp_iov
)
3312 (void)fd
; /* unused */
3316 if (!si
->connected
) {
3321 if (msg
->msg_iovlen
== 0) {
3325 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3327 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3328 if (nlen
> SOCKET_MAX_PACKET
) {
3332 msg
->msg_iovlen
= i
;
3333 if (msg
->msg_iovlen
== 0) {
3334 *tmp_iov
= msg
->msg_iov
[0];
3335 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3336 msg
->msg_iov
= tmp_iov
;
3337 msg
->msg_iovlen
= 1;
3342 if (msg
->msg_name
== NULL
) {
3347 if (msg
->msg_iovlen
== 0) {
3351 if (si
->bound
== 0) {
3352 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3355 * When attempting to read or write to a
3356 * descriptor, if an underlying autobind fails
3357 * because it's not a socket, stop intercepting
3358 * uses of that descriptor.
3360 if (errno
== ENOTSOCK
) {
3361 swrap_remove_stale(fd
);
3364 SWRAP_LOG(SWRAP_LOG_ERROR
,
3365 "swrap_recvmsg_before failed");
3372 errno
= EHOSTUNREACH
;
3379 static int swrap_recvmsg_after(int fd
,
3380 struct socket_info
*si
,
3382 const struct sockaddr_un
*un_addr
,
3383 socklen_t un_addrlen
,
3386 int saved_errno
= errno
;
3388 uint8_t *buf
= NULL
;
3393 /* to give better errors */
3395 if (saved_errno
== ENOENT
) {
3396 saved_errno
= EHOSTUNREACH
;
3397 } else if (saved_errno
== ENOTSOCK
) {
3398 /* If the fd is not a socket, remove it */
3399 swrap_remove_stale(fd
);
3403 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3404 avail
+= msg
->msg_iov
[i
].iov_len
;
3408 errno
= saved_errno
;
3413 remain
= MIN(80, avail
);
3418 /* we capture it as one single packet */
3419 buf
= (uint8_t *)malloc(remain
);
3421 /* we just not capture the packet */
3422 errno
= saved_errno
;
3426 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3427 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3429 msg
->msg_iov
[i
].iov_base
,
3432 remain
-= this_time
;
3437 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
3438 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3439 } else if (ret
== 0) { /* END OF FILE */
3440 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3441 } else if (ret
> 0) {
3442 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
3451 if (un_addr
!= NULL
) {
3454 rc
= sockaddr_convert_from_un(si
,
3464 swrap_dump_packet(si
,
3470 swrap_dump_packet(si
,
3482 errno
= saved_errno
;
3486 /****************************************************************************
3488 ***************************************************************************/
3490 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
3491 struct sockaddr
*from
, socklen_t
*fromlen
)
3493 struct sockaddr_un from_addr
;
3494 socklen_t from_addrlen
= sizeof(from_addr
);
3496 struct socket_info
*si
= find_socket_info(s
);
3497 struct sockaddr_storage ss
;
3498 socklen_t ss_len
= sizeof(ss
);
3504 return libc_recvfrom(s
,
3516 if (from
!= NULL
&& fromlen
!= NULL
) {
3517 msg
.msg_name
= from
; /* optional address */
3518 msg
.msg_namelen
= *fromlen
; /* size of address */
3520 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3521 msg
.msg_namelen
= ss_len
; /* size of address */
3523 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3524 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3525 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3526 msg
.msg_control
= NULL
; /* ancillary data, see below */
3527 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3528 msg
.msg_flags
= 0; /* flags on received message */
3531 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3536 buf
= msg
.msg_iov
[0].iov_base
;
3537 len
= msg
.msg_iov
[0].iov_len
;
3539 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3540 memset(&from_addr
, 0, sizeof(from_addr
));
3541 ret
= libc_recvfrom(s
,
3545 (struct sockaddr
*)(void *)&from_addr
,
3551 tret
= swrap_recvmsg_after(s
,
3561 if (from
!= NULL
&& fromlen
!= NULL
) {
3562 *fromlen
= msg
.msg_namelen
;
3568 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3569 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
3570 struct sockaddr
*from
, Psocklen_t fromlen
)
3572 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
3573 struct sockaddr
*from
, socklen_t
*fromlen
)
3576 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
3579 /****************************************************************************
3581 ***************************************************************************/
3583 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
3584 const struct sockaddr
*to
, socklen_t tolen
)
3588 struct sockaddr_un un_addr
;
3589 const struct sockaddr_un
*to_un
= NULL
;
3592 struct socket_info
*si
= find_socket_info(s
);
3596 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
3599 tmp
.iov_base
= discard_const_p(char, buf
);
3603 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
3604 msg
.msg_namelen
= tolen
; /* size of address */
3605 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3606 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3607 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3608 msg
.msg_control
= NULL
; /* ancillary data, see below */
3609 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3610 msg
.msg_flags
= 0; /* flags on received message */
3613 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
3618 buf
= msg
.msg_iov
[0].iov_base
;
3619 len
= msg
.msg_iov
[0].iov_len
;
3624 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
3627 type
= SOCKET_TYPE_CHAR_UDP
;
3629 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
3630 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
3631 socket_wrapper_dir(), type
, iface
, prt
);
3632 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
3634 /* ignore the any errors in broadcast sends */
3639 (struct sockaddr
*)(void *)&un_addr
,
3643 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3648 ret
= libc_sendto(s
,
3652 (struct sockaddr
*)msg
.msg_name
,
3655 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
3660 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
3661 const struct sockaddr
*to
, socklen_t tolen
)
3663 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
3666 /****************************************************************************
3668 ***************************************************************************/
3670 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
3672 struct socket_info
*si
;
3674 struct sockaddr_storage ss
;
3675 socklen_t ss_len
= sizeof(ss
);
3680 si
= find_socket_info(s
);
3682 return libc_recv(s
, buf
, len
, flags
);
3689 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3690 msg
.msg_namelen
= ss_len
; /* size of address */
3691 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3692 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3693 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3694 msg
.msg_control
= NULL
; /* ancillary data, see below */
3695 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3696 msg
.msg_flags
= 0; /* flags on received message */
3699 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3704 buf
= msg
.msg_iov
[0].iov_base
;
3705 len
= msg
.msg_iov
[0].iov_len
;
3707 ret
= libc_recv(s
, buf
, len
, flags
);
3709 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
3717 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
3719 return swrap_recv(s
, buf
, len
, flags
);
3722 /****************************************************************************
3724 ***************************************************************************/
3726 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
3728 struct socket_info
*si
;
3731 struct sockaddr_storage ss
;
3732 socklen_t ss_len
= sizeof(ss
);
3736 si
= find_socket_info(s
);
3738 return libc_read(s
, buf
, len
);
3745 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3746 msg
.msg_namelen
= ss_len
; /* size of address */
3747 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3748 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3749 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3750 msg
.msg_control
= NULL
; /* ancillary data, see below */
3751 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3752 msg
.msg_flags
= 0; /* flags on received message */
3755 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3757 if (tret
== -ENOTSOCK
) {
3758 return libc_read(s
, buf
, len
);
3763 buf
= msg
.msg_iov
[0].iov_base
;
3764 len
= msg
.msg_iov
[0].iov_len
;
3766 ret
= libc_read(s
, buf
, len
);
3768 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
3776 ssize_t
read(int s
, void *buf
, size_t len
)
3778 return swrap_read(s
, buf
, len
);
3781 /****************************************************************************
3783 ***************************************************************************/
3785 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
3789 struct sockaddr_un un_addr
;
3792 struct socket_info
*si
= find_socket_info(s
);
3795 return libc_send(s
, buf
, len
, flags
);
3798 tmp
.iov_base
= discard_const_p(char, buf
);
3802 msg
.msg_name
= NULL
; /* optional address */
3803 msg
.msg_namelen
= 0; /* size of address */
3804 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3805 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3806 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3807 msg
.msg_control
= NULL
; /* ancillary data, see below */
3808 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3809 msg
.msg_flags
= 0; /* flags on received message */
3812 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
3817 buf
= msg
.msg_iov
[0].iov_base
;
3818 len
= msg
.msg_iov
[0].iov_len
;
3820 ret
= libc_send(s
, buf
, len
, flags
);
3822 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
3827 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
3829 return swrap_send(s
, buf
, len
, flags
);
3832 /****************************************************************************
3834 ***************************************************************************/
3836 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
3838 struct sockaddr_un from_addr
;
3839 socklen_t from_addrlen
= sizeof(from_addr
);
3840 struct socket_info
*si
;
3847 si
= find_socket_info(s
);
3849 return libc_recvmsg(s
, omsg
, flags
);
3852 tmp
.iov_base
= NULL
;
3856 msg
.msg_name
= (struct sockaddr
*)&from_addr
; /* optional address */
3857 msg
.msg_namelen
= from_addrlen
; /* size of address */
3858 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
3859 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
3860 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3861 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
3862 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
3863 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
3866 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3871 ret
= libc_recvmsg(s
, &msg
, flags
);
3873 rc
= swrap_recvmsg_after(s
, si
, omsg
, &from_addr
, from_addrlen
, ret
);
3881 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
3883 return swrap_recvmsg(sockfd
, msg
, flags
);
3886 /****************************************************************************
3888 ***************************************************************************/
3890 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
3894 struct sockaddr_un un_addr
;
3895 const struct sockaddr_un
*to_un
= NULL
;
3896 const struct sockaddr
*to
= NULL
;
3899 struct socket_info
*si
= find_socket_info(s
);
3903 return libc_sendmsg(s
, omsg
, flags
);
3906 ZERO_STRUCT(un_addr
);
3908 tmp
.iov_base
= NULL
;
3912 msg
.msg_name
= omsg
->msg_name
; /* optional address */
3913 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
3914 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
3915 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
3916 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3917 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
3918 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
3919 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
3922 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
3930 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
3938 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
3939 avail
+= msg
.msg_iov
[i
].iov_len
;
3945 /* we capture it as one single packet */
3946 buf
= (uint8_t *)malloc(remain
);
3951 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
3952 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
3954 msg
.msg_iov
[i
].iov_base
,
3957 remain
-= this_time
;
3960 type
= SOCKET_TYPE_CHAR_UDP
;
3962 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
3963 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
3964 socket_wrapper_dir(), type
, iface
, prt
);
3965 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
3967 msg
.msg_name
= &un_addr
; /* optional address */
3968 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
3970 /* ignore the any errors in broadcast sends */
3971 libc_sendmsg(s
, &msg
, flags
);
3974 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3980 ret
= libc_sendmsg(s
, &msg
, flags
);
3982 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
3987 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
3989 return swrap_sendmsg(s
, omsg
, flags
);
3992 /****************************************************************************
3994 ***************************************************************************/
3996 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
3998 struct socket_info
*si
;
4001 struct sockaddr_storage ss
;
4002 socklen_t ss_len
= sizeof(ss
);
4006 si
= find_socket_info(s
);
4008 return libc_readv(s
, vector
, count
);
4011 tmp
.iov_base
= NULL
;
4015 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4016 msg
.msg_namelen
= ss_len
; /* size of address */
4017 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4018 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4019 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4020 msg
.msg_control
= NULL
; /* ancillary data, see below */
4021 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4022 msg
.msg_flags
= 0; /* flags on received message */
4025 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4027 if (rc
== -ENOTSOCK
) {
4028 return libc_readv(s
, vector
, count
);
4033 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4035 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4043 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4045 return swrap_readv(s
, vector
, count
);
4048 /****************************************************************************
4050 ***************************************************************************/
4052 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4056 struct sockaddr_un un_addr
;
4059 struct socket_info
*si
= find_socket_info(s
);
4062 return libc_writev(s
, vector
, count
);
4065 tmp
.iov_base
= NULL
;
4069 msg
.msg_name
= NULL
; /* optional address */
4070 msg
.msg_namelen
= 0; /* size of address */
4071 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4072 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4073 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4074 msg
.msg_control
= NULL
; /* ancillary data, see below */
4075 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4076 msg
.msg_flags
= 0; /* flags on received message */
4079 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4081 if (rc
== -ENOTSOCK
) {
4082 return libc_readv(s
, vector
, count
);
4087 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4089 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4094 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4096 return swrap_writev(s
, vector
, count
);
4099 /****************************
4101 ***************************/
4103 static int swrap_close(int fd
)
4105 struct socket_info
*si
= find_socket_info(fd
);
4106 struct socket_info_fd
*fi
;
4110 return libc_close(fd
);
4113 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4115 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4122 /* there are still references left */
4123 return libc_close(fd
);
4126 SWRAP_DLIST_REMOVE(sockets
, si
);
4128 if (si
->myname
&& si
->peername
) {
4129 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4132 ret
= libc_close(fd
);
4134 if (si
->myname
&& si
->peername
) {
4135 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4136 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4139 if (si
->bindname
!= NULL
) {
4143 if (si
->myname
) free(si
->myname
);
4144 if (si
->peername
) free(si
->peername
);
4146 unlink(si
->tmp_path
);
4156 return swrap_close(fd
);
4159 /****************************
4161 ***************************/
4163 static int swrap_dup(int fd
)
4165 struct socket_info
*si
;
4166 struct socket_info_fd
*fi
;
4168 si
= find_socket_info(fd
);
4171 return libc_dup(fd
);
4174 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4180 fi
->fd
= libc_dup(fd
);
4182 int saved_errno
= errno
;
4184 errno
= saved_errno
;
4188 /* Make sure we don't have an entry for the fd */
4189 swrap_remove_stale(fi
->fd
);
4191 SWRAP_DLIST_ADD(si
->fds
, fi
);
4197 return swrap_dup(fd
);
4200 /****************************
4202 ***************************/
4204 static int swrap_dup2(int fd
, int newfd
)
4206 struct socket_info
*si
;
4207 struct socket_info_fd
*fi
;
4209 si
= find_socket_info(fd
);
4212 return libc_dup2(fd
, newfd
);
4215 if (find_socket_info(newfd
)) {
4216 /* dup2() does an implicit close of newfd, which we
4217 * need to emulate */
4221 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4227 fi
->fd
= libc_dup2(fd
, newfd
);
4229 int saved_errno
= errno
;
4231 errno
= saved_errno
;
4235 /* Make sure we don't have an entry for the fd */
4236 swrap_remove_stale(fi
->fd
);
4238 SWRAP_DLIST_ADD(si
->fds
, fi
);
4242 int dup2(int fd
, int newfd
)
4244 return swrap_dup2(fd
, newfd
);
4247 /****************************
4249 ***************************/
4252 static int swrap_eventfd(int count
, int flags
)
4256 fd
= libc_eventfd(count
, flags
);
4258 swrap_remove_stale(fd
);
4264 int eventfd(int count
, int flags
)
4266 return swrap_eventfd(count
, flags
);
4270 /****************************
4272 ***************************/
4275 * This function is called when the library is unloaded and makes sure that
4276 * sockets get closed and the unix file for the socket are unlinked.
4278 void swrap_destructor(void)
4280 struct socket_info
*s
= sockets
;
4283 struct socket_info_fd
*f
= s
->fds
;