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
);
438 swrap
.libc_handle
= handle
;
441 if (handle
== NULL
) {
442 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
443 char soname
[256] = {0};
445 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
446 handle
= dlopen(soname
, flags
);
449 swrap
.libc_handle
= handle
;
454 if (handle
== NULL
) {
456 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
458 SWRAP_LOG(SWRAP_LOG_ERROR
,
459 "Failed to dlopen library: %s\n",
468 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
473 handle
= swrap_load_lib_handle(lib
);
475 func
= dlsym(handle
, fn_name
);
477 SWRAP_LOG(SWRAP_LOG_ERROR
,
478 "Failed to find %s: %s\n",
483 SWRAP_LOG(SWRAP_LOG_TRACE
,
485 fn_name
, swrap_str_lib(lib
));
489 #define swrap_load_lib_function(lib, fn_name) \
490 if (swrap.fns.libc_##fn_name == NULL) { \
491 *(void **) (&swrap.fns.libc_##fn_name) = \
492 _swrap_load_lib_function(lib, #fn_name); \
499 * Functions especially from libc need to be loaded individually, you can't load
500 * all at once or gdb will segfault at startup. The same applies to valgrind and
501 * has probably something todo with with the linker.
502 * So we need load each function at the point it is called the first time.
504 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
506 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
508 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
511 static int libc_bind(int sockfd
,
512 const struct sockaddr
*addr
,
515 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
517 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
520 static int libc_close(int fd
)
522 swrap_load_lib_function(SWRAP_LIBC
, close
);
524 return swrap
.fns
.libc_close(fd
);
527 static int libc_connect(int sockfd
,
528 const struct sockaddr
*addr
,
531 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
533 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
536 static int libc_dup(int fd
)
538 swrap_load_lib_function(SWRAP_LIBC
, dup
);
540 return swrap
.fns
.libc_dup(fd
);
543 static int libc_dup2(int oldfd
, int newfd
)
545 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
547 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
551 static int libc_eventfd(int count
, int flags
)
553 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
555 return swrap
.fns
.libc_eventfd(count
, flags
);
559 static int libc_getpeername(int sockfd
,
560 struct sockaddr
*addr
,
563 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
565 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
568 static int libc_getsockname(int sockfd
,
569 struct sockaddr
*addr
,
572 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
574 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
577 static int libc_getsockopt(int sockfd
,
583 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
585 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
588 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
594 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
596 for (i
= 0; i
< 4; i
++) {
597 args
[i
] = va_arg(ap
, long int);
600 rc
= swrap
.fns
.libc_ioctl(d
,
610 static int libc_listen(int sockfd
, int backlog
)
612 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
614 return swrap
.fns
.libc_listen(sockfd
, backlog
);
617 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
622 swrap_load_lib_function(SWRAP_LIBC
, open
);
624 mode
= va_arg(ap
, long int);
626 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
631 static int libc_open(const char *pathname
, int flags
, ...)
637 fd
= libc_vopen(pathname
, flags
, ap
);
643 static int libc_pipe(int pipefd
[2])
645 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
647 return swrap
.fns
.libc_pipe(pipefd
);
650 static int libc_read(int fd
, void *buf
, size_t count
)
652 swrap_load_lib_function(SWRAP_LIBC
, read
);
654 return swrap
.fns
.libc_read(fd
, buf
, count
);
657 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
659 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
661 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
664 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
666 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
668 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
671 static int libc_recvfrom(int sockfd
,
675 struct sockaddr
*src_addr
,
678 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
680 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
683 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
685 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
687 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
690 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
692 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
694 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
697 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
699 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
701 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
704 static int libc_sendto(int sockfd
,
708 const struct sockaddr
*dst_addr
,
711 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
713 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
716 static int libc_setsockopt(int sockfd
,
722 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
724 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
728 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
730 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
732 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
736 static int libc_socket(int domain
, int type
, int protocol
)
738 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
740 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
743 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
745 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
747 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
750 #ifdef HAVE_TIMERFD_CREATE
751 static int libc_timerfd_create(int clockid
, int flags
)
753 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
755 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
759 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
761 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
763 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
766 /*********************************************************
767 * SWRAP HELPER FUNCTIONS
768 *********************************************************/
774 static const struct in6_addr
*swrap_ipv6(void)
776 static struct in6_addr v
;
777 static int initialized
;
785 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
794 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
796 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
797 memcpy(ret
, data
, len
);
801 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
805 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
809 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
815 static size_t socket_length(int family
)
819 return sizeof(struct sockaddr_in
);
822 return sizeof(struct sockaddr_in6
);
828 static const char *socket_wrapper_dir(void)
830 const char *s
= getenv("SOCKET_WRAPPER_DIR");
834 if (strncmp(s
, "./", 2) == 0) {
838 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
842 bool socket_wrapper_enabled(void)
844 const char *s
= socket_wrapper_dir();
846 return s
!= NULL
? true : false;
849 static unsigned int socket_wrapper_default_iface(void)
851 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
854 if (sscanf(s
, "%u", &iface
) == 1) {
855 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
861 return 1;/* 127.0.0.1 */
864 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
871 p
= strrchr(un
->sun_path
, '/');
872 if (p
) p
++; else p
= un
->sun_path
;
874 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
879 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
882 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
893 case SOCKET_TYPE_CHAR_TCP
:
894 case SOCKET_TYPE_CHAR_UDP
: {
895 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
897 if ((*len
) < sizeof(*in2
)) {
902 memset(in2
, 0, sizeof(*in2
));
903 in2
->sin_family
= AF_INET
;
904 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
905 in2
->sin_port
= htons(prt
);
911 case SOCKET_TYPE_CHAR_TCP_V6
:
912 case SOCKET_TYPE_CHAR_UDP_V6
: {
913 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
915 if ((*len
) < sizeof(*in2
)) {
920 memset(in2
, 0, sizeof(*in2
));
921 in2
->sin6_family
= AF_INET6
;
922 in2
->sin6_addr
= *swrap_ipv6();
923 in2
->sin6_addr
.s6_addr
[15] = iface
;
924 in2
->sin6_port
= htons(prt
);
938 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
946 if (bcast
) *bcast
= 0;
948 switch (inaddr
->sa_family
) {
950 const struct sockaddr_in
*in
=
951 (const struct sockaddr_in
*)(const void *)inaddr
;
952 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
959 u_type
= SOCKET_TYPE_CHAR_TCP
;
962 u_type
= SOCKET_TYPE_CHAR_UDP
;
963 a_type
= SOCKET_TYPE_CHAR_UDP
;
964 b_type
= SOCKET_TYPE_CHAR_UDP
;
967 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
968 errno
= ESOCKTNOSUPPORT
;
972 prt
= ntohs(in
->sin_port
);
973 if (a_type
&& addr
== 0xFFFFFFFF) {
974 /* 255.255.255.255 only udp */
977 iface
= socket_wrapper_default_iface();
978 } else if (b_type
&& addr
== 0x7FFFFFFF) {
979 /* 127.255.255.255 only udp */
982 iface
= socket_wrapper_default_iface();
983 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
987 iface
= (addr
& 0x000000FF);
992 if (bcast
) *bcast
= is_bcast
;
997 const struct sockaddr_in6
*in
=
998 (const struct sockaddr_in6
*)(const void *)inaddr
;
999 struct in6_addr cmp1
, cmp2
;
1003 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1006 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1009 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1010 errno
= ESOCKTNOSUPPORT
;
1014 /* XXX no multicast/broadcast */
1016 prt
= ntohs(in
->sin6_port
);
1018 cmp1
= *swrap_ipv6();
1019 cmp2
= in
->sin6_addr
;
1020 cmp2
.s6_addr
[15] = 0;
1021 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1022 iface
= in
->sin6_addr
.s6_addr
[15];
1024 errno
= ENETUNREACH
;
1032 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1033 errno
= ENETUNREACH
;
1038 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1044 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1045 socket_wrapper_dir());
1046 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1047 /* the caller need to do more processing */
1051 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1052 socket_wrapper_dir(), type
, iface
, prt
);
1053 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1058 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1067 if (bcast
) *bcast
= 0;
1069 switch (si
->family
) {
1071 const struct sockaddr_in
*in
=
1072 (const struct sockaddr_in
*)(const void *)inaddr
;
1073 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1079 prt
= ntohs(in
->sin_port
);
1083 u_type
= SOCKET_TYPE_CHAR_TCP
;
1084 d_type
= SOCKET_TYPE_CHAR_TCP
;
1087 u_type
= SOCKET_TYPE_CHAR_UDP
;
1088 d_type
= SOCKET_TYPE_CHAR_UDP
;
1089 a_type
= SOCKET_TYPE_CHAR_UDP
;
1090 b_type
= SOCKET_TYPE_CHAR_UDP
;
1093 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1094 errno
= ESOCKTNOSUPPORT
;
1102 iface
= socket_wrapper_default_iface();
1103 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1104 /* 255.255.255.255 only udp */
1107 iface
= socket_wrapper_default_iface();
1108 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1109 /* 127.255.255.255 only udp */
1112 iface
= socket_wrapper_default_iface();
1113 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1117 iface
= (addr
& 0x000000FF);
1119 errno
= EADDRNOTAVAIL
;
1123 /* Store the bind address for connect() */
1124 if (si
->bindname
== NULL
) {
1125 struct sockaddr_in bind_in
;
1126 socklen_t blen
= sizeof(struct sockaddr_in
);
1128 ZERO_STRUCT(bind_in
);
1129 bind_in
.sin_family
= in
->sin_family
;
1130 bind_in
.sin_port
= in
->sin_port
;
1131 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1133 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1134 si
->bindname_len
= blen
;
1141 const struct sockaddr_in6
*in
=
1142 (const struct sockaddr_in6
*)(const void *)inaddr
;
1143 struct in6_addr cmp1
, cmp2
;
1147 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1150 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1153 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1154 errno
= ESOCKTNOSUPPORT
;
1158 /* XXX no multicast/broadcast */
1160 prt
= ntohs(in
->sin6_port
);
1162 cmp1
= *swrap_ipv6();
1163 cmp2
= in
->sin6_addr
;
1164 cmp2
.s6_addr
[15] = 0;
1165 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1166 iface
= socket_wrapper_default_iface();
1167 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1168 iface
= in
->sin6_addr
.s6_addr
[15];
1170 errno
= EADDRNOTAVAIL
;
1174 /* Store the bind address for connect() */
1175 if (si
->bindname
== NULL
) {
1176 struct sockaddr_in6 bind_in
;
1177 socklen_t blen
= sizeof(struct sockaddr_in6
);
1179 ZERO_STRUCT(bind_in
);
1180 bind_in
.sin6_family
= in
->sin6_family
;
1181 bind_in
.sin6_port
= in
->sin6_port
;
1183 bind_in
.sin6_addr
= *swrap_ipv6();
1184 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1186 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1187 si
->bindname_len
= blen
;
1194 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1195 errno
= EADDRNOTAVAIL
;
1200 if (bcast
) *bcast
= is_bcast
;
1202 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1208 /* handle auto-allocation of ephemeral ports */
1209 for (prt
= 5001; prt
< 10000; prt
++) {
1210 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1211 socket_wrapper_dir(), type
, iface
, prt
);
1212 if (stat(un
->sun_path
, &st
) == 0) continue;
1214 set_port(si
->family
, prt
, si
->myname
);
1215 set_port(si
->family
, prt
, si
->bindname
);
1225 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1226 socket_wrapper_dir(), type
, iface
, prt
);
1227 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1231 static struct socket_info
*find_socket_info(int fd
)
1233 struct socket_info
*i
;
1235 for (i
= sockets
; i
; i
= i
->next
) {
1236 struct socket_info_fd
*f
;
1237 for (f
= i
->fds
; f
; f
= f
->next
) {
1247 static void swrap_remove_stale(int fd
)
1249 struct socket_info
*si
= find_socket_info(fd
);
1250 struct socket_info_fd
*fi
;
1253 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1255 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1256 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1262 if (si
->fds
== NULL
) {
1263 SWRAP_DLIST_REMOVE(sockets
, si
);
1268 static int sockaddr_convert_to_un(struct socket_info
*si
,
1269 const struct sockaddr
*in_addr
,
1271 struct sockaddr_un
*out_addr
,
1275 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1277 (void) in_len
; /* unused */
1279 if (out_addr
== NULL
) {
1283 out
->sa_family
= AF_UNIX
;
1284 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1285 out
->sa_len
= sizeof(*out_addr
);
1288 switch (in_addr
->sa_family
) {
1298 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1299 errno
= ESOCKTNOSUPPORT
;
1303 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1305 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1311 errno
= EAFNOSUPPORT
;
1312 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1316 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1317 const struct sockaddr_un
*in_addr
,
1318 socklen_t un_addrlen
,
1320 struct sockaddr
*out_addr
,
1321 socklen_t
*out_addrlen
)
1325 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1328 if (un_addrlen
== 0) {
1343 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1344 errno
= ESOCKTNOSUPPORT
;
1347 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1348 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1349 out_addr
->sa_len
= *out_addrlen
;
1356 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1357 errno
= EAFNOSUPPORT
;
1361 enum swrap_packet_type
{
1363 SWRAP_CONNECT_UNREACH
,
1371 SWRAP_SENDTO_UNREACH
,
1382 struct swrap_file_hdr
{
1384 uint16_t version_major
;
1385 uint16_t version_minor
;
1388 uint32_t frame_max_len
;
1389 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1392 #define SWRAP_FILE_HDR_SIZE 24
1394 struct swrap_packet_frame
{
1396 uint32_t micro_seconds
;
1397 uint32_t recorded_length
;
1398 uint32_t full_length
;
1400 #define SWRAP_PACKET_FRAME_SIZE 16
1402 union swrap_packet_ip
{
1406 uint16_t packet_length
;
1407 uint16_t identification
;
1412 uint16_t hdr_checksum
;
1416 #define SWRAP_PACKET_IP_V4_SIZE 20
1419 uint8_t flow_label_high
;
1420 uint16_t flow_label_low
;
1421 uint16_t payload_length
;
1422 uint8_t next_header
;
1424 uint8_t src_addr
[16];
1425 uint8_t dest_addr
[16];
1427 #define SWRAP_PACKET_IP_V6_SIZE 40
1429 #define SWRAP_PACKET_IP_SIZE 40
1431 union swrap_packet_payload
{
1433 uint16_t source_port
;
1443 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1445 uint16_t source_port
;
1450 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1457 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1464 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1466 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1468 #define SWRAP_PACKET_MIN_ALLOC \
1469 (SWRAP_PACKET_FRAME_SIZE + \
1470 SWRAP_PACKET_IP_SIZE + \
1471 SWRAP_PACKET_PAYLOAD_SIZE)
1473 static const char *socket_wrapper_pcap_file(void)
1475 static int initialized
= 0;
1476 static const char *s
= NULL
;
1477 static const struct swrap_file_hdr h
;
1478 static const struct swrap_packet_frame f
;
1479 static const union swrap_packet_ip i
;
1480 static const union swrap_packet_payload p
;
1482 if (initialized
== 1) {
1488 * TODO: don't use the structs use plain buffer offsets
1489 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1491 * for now make sure we disable PCAP support
1492 * if the struct has alignment!
1494 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1497 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1500 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1503 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1506 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1509 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1512 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1515 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1518 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1521 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1525 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1529 if (strncmp(s
, "./", 2) == 0) {
1535 static uint8_t *swrap_packet_init(struct timeval
*tval
,
1536 const struct sockaddr
*src
,
1537 const struct sockaddr
*dest
,
1539 const uint8_t *payload
,
1541 unsigned long tcp_seqno
,
1542 unsigned long tcp_ack
,
1543 unsigned char tcp_ctl
,
1545 size_t *_packet_len
)
1549 struct swrap_packet_frame
*frame
;
1550 union swrap_packet_ip
*ip
;
1551 union swrap_packet_payload
*pay
;
1554 size_t nonwire_len
= sizeof(*frame
);
1555 size_t wire_hdr_len
= 0;
1556 size_t wire_len
= 0;
1557 size_t ip_hdr_len
= 0;
1558 size_t icmp_hdr_len
= 0;
1559 size_t icmp_truncate_len
= 0;
1560 uint8_t protocol
= 0, icmp_protocol
= 0;
1561 const struct sockaddr_in
*src_in
= NULL
;
1562 const struct sockaddr_in
*dest_in
= NULL
;
1564 const struct sockaddr_in6
*src_in6
= NULL
;
1565 const struct sockaddr_in6
*dest_in6
= NULL
;
1570 switch (src
->sa_family
) {
1572 src_in
= (const struct sockaddr_in
*)src
;
1573 dest_in
= (const struct sockaddr_in
*)dest
;
1574 src_port
= src_in
->sin_port
;
1575 dest_port
= dest_in
->sin_port
;
1576 ip_hdr_len
= sizeof(ip
->v4
);
1580 src_in6
= (const struct sockaddr_in6
*)src
;
1581 dest_in6
= (const struct sockaddr_in6
*)dest
;
1582 src_port
= src_in6
->sin6_port
;
1583 dest_port
= dest_in6
->sin6_port
;
1584 ip_hdr_len
= sizeof(ip
->v6
);
1591 switch (socket_type
) {
1593 protocol
= 0x06; /* TCP */
1594 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1595 wire_len
= wire_hdr_len
+ payload_len
;
1599 protocol
= 0x11; /* UDP */
1600 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1601 wire_len
= wire_hdr_len
+ payload_len
;
1609 icmp_protocol
= protocol
;
1610 switch (src
->sa_family
) {
1612 protocol
= 0x01; /* ICMPv4 */
1613 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1617 protocol
= 0x3A; /* ICMPv6 */
1618 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1622 if (wire_len
> 64 ) {
1623 icmp_truncate_len
= wire_len
- 64;
1625 wire_hdr_len
+= icmp_hdr_len
;
1626 wire_len
+= icmp_hdr_len
;
1629 packet_len
= nonwire_len
+ wire_len
;
1630 alloc_len
= packet_len
;
1631 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1632 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1635 base
= (uint8_t *)malloc(alloc_len
);
1639 memset(base
, 0x0, alloc_len
);
1643 frame
= (struct swrap_packet_frame
*)buf
;
1644 frame
->seconds
= tval
->tv_sec
;
1645 frame
->micro_seconds
= tval
->tv_usec
;
1646 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1647 frame
->full_length
= wire_len
- icmp_truncate_len
;
1648 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1650 ip
= (union swrap_packet_ip
*)buf
;
1651 switch (src
->sa_family
) {
1653 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1655 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1656 ip
->v4
.identification
= htons(0xFFFF);
1657 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1658 ip
->v4
.fragment
= htons(0x0000);
1660 ip
->v4
.protocol
= protocol
;
1661 ip
->v4
.hdr_checksum
= htons(0x0000);
1662 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1663 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1664 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1668 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1669 ip
->v6
.flow_label_high
= 0x00;
1670 ip
->v6
.flow_label_low
= 0x0000;
1671 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1672 ip
->v6
.next_header
= protocol
;
1673 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1674 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1675 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1681 pay
= (union swrap_packet_payload
*)buf
;
1682 switch (src
->sa_family
) {
1684 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1685 pay
->icmp4
.code
= 0x01; /* host unreachable */
1686 pay
->icmp4
.checksum
= htons(0x0000);
1687 pay
->icmp4
.unused
= htonl(0x00000000);
1688 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1690 /* set the ip header in the ICMP payload */
1691 ip
= (union swrap_packet_ip
*)buf
;
1692 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1694 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1695 ip
->v4
.identification
= htons(0xFFFF);
1696 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1697 ip
->v4
.fragment
= htons(0x0000);
1699 ip
->v4
.protocol
= icmp_protocol
;
1700 ip
->v4
.hdr_checksum
= htons(0x0000);
1701 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1702 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1703 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1705 src_port
= dest_in
->sin_port
;
1706 dest_port
= src_in
->sin_port
;
1710 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1711 pay
->icmp6
.code
= 0x03; /* address unreachable */
1712 pay
->icmp6
.checksum
= htons(0x0000);
1713 pay
->icmp6
.unused
= htonl(0x00000000);
1714 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1716 /* set the ip header in the ICMP payload */
1717 ip
= (union swrap_packet_ip
*)buf
;
1718 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1719 ip
->v6
.flow_label_high
= 0x00;
1720 ip
->v6
.flow_label_low
= 0x0000;
1721 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1722 ip
->v6
.next_header
= protocol
;
1723 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1724 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1725 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1727 src_port
= dest_in6
->sin6_port
;
1728 dest_port
= src_in6
->sin6_port
;
1734 pay
= (union swrap_packet_payload
*)buf
;
1736 switch (socket_type
) {
1738 pay
->tcp
.source_port
= src_port
;
1739 pay
->tcp
.dest_port
= dest_port
;
1740 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1741 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1742 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1743 pay
->tcp
.control
= tcp_ctl
;
1744 pay
->tcp
.window
= htons(0x7FFF);
1745 pay
->tcp
.checksum
= htons(0x0000);
1746 pay
->tcp
.urg
= htons(0x0000);
1747 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1752 pay
->udp
.source_port
= src_port
;
1753 pay
->udp
.dest_port
= dest_port
;
1754 pay
->udp
.length
= htons(8 + payload_len
);
1755 pay
->udp
.checksum
= htons(0x0000);
1756 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1761 if (payload
&& payload_len
> 0) {
1762 memcpy(buf
, payload
, payload_len
);
1765 *_packet_len
= packet_len
- icmp_truncate_len
;
1769 static int swrap_get_pcap_fd(const char *fname
)
1773 if (fd
!= -1) return fd
;
1775 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1777 struct swrap_file_hdr file_hdr
;
1778 file_hdr
.magic
= 0xA1B2C3D4;
1779 file_hdr
.version_major
= 0x0002;
1780 file_hdr
.version_minor
= 0x0004;
1781 file_hdr
.timezone
= 0x00000000;
1782 file_hdr
.sigfigs
= 0x00000000;
1783 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1784 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1786 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1793 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1798 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1799 const struct sockaddr
*addr
,
1800 enum swrap_packet_type type
,
1801 const void *buf
, size_t len
,
1804 const struct sockaddr
*src_addr
;
1805 const struct sockaddr
*dest_addr
;
1806 unsigned long tcp_seqno
= 0;
1807 unsigned long tcp_ack
= 0;
1808 unsigned char tcp_ctl
= 0;
1809 int unreachable
= 0;
1813 switch (si
->family
) {
1825 case SWRAP_CONNECT_SEND
:
1826 if (si
->type
!= SOCK_STREAM
) return NULL
;
1828 src_addr
= si
->myname
;
1831 tcp_seqno
= si
->io
.pck_snd
;
1832 tcp_ack
= si
->io
.pck_rcv
;
1833 tcp_ctl
= 0x02; /* SYN */
1835 si
->io
.pck_snd
+= 1;
1839 case SWRAP_CONNECT_RECV
:
1840 if (si
->type
!= SOCK_STREAM
) return NULL
;
1842 dest_addr
= si
->myname
;
1845 tcp_seqno
= si
->io
.pck_rcv
;
1846 tcp_ack
= si
->io
.pck_snd
;
1847 tcp_ctl
= 0x12; /** SYN,ACK */
1849 si
->io
.pck_rcv
+= 1;
1853 case SWRAP_CONNECT_UNREACH
:
1854 if (si
->type
!= SOCK_STREAM
) return NULL
;
1856 dest_addr
= si
->myname
;
1859 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1860 tcp_seqno
= si
->io
.pck_snd
- 1;
1861 tcp_ack
= si
->io
.pck_rcv
;
1862 tcp_ctl
= 0x02; /* SYN */
1867 case SWRAP_CONNECT_ACK
:
1868 if (si
->type
!= SOCK_STREAM
) return NULL
;
1870 src_addr
= si
->myname
;
1873 tcp_seqno
= si
->io
.pck_snd
;
1874 tcp_ack
= si
->io
.pck_rcv
;
1875 tcp_ctl
= 0x10; /* ACK */
1879 case SWRAP_ACCEPT_SEND
:
1880 if (si
->type
!= SOCK_STREAM
) return NULL
;
1882 dest_addr
= si
->myname
;
1885 tcp_seqno
= si
->io
.pck_rcv
;
1886 tcp_ack
= si
->io
.pck_snd
;
1887 tcp_ctl
= 0x02; /* SYN */
1889 si
->io
.pck_rcv
+= 1;
1893 case SWRAP_ACCEPT_RECV
:
1894 if (si
->type
!= SOCK_STREAM
) return NULL
;
1896 src_addr
= si
->myname
;
1899 tcp_seqno
= si
->io
.pck_snd
;
1900 tcp_ack
= si
->io
.pck_rcv
;
1901 tcp_ctl
= 0x12; /* SYN,ACK */
1903 si
->io
.pck_snd
+= 1;
1907 case SWRAP_ACCEPT_ACK
:
1908 if (si
->type
!= SOCK_STREAM
) return NULL
;
1910 dest_addr
= si
->myname
;
1913 tcp_seqno
= si
->io
.pck_rcv
;
1914 tcp_ack
= si
->io
.pck_snd
;
1915 tcp_ctl
= 0x10; /* ACK */
1920 src_addr
= si
->myname
;
1921 dest_addr
= si
->peername
;
1923 tcp_seqno
= si
->io
.pck_snd
;
1924 tcp_ack
= si
->io
.pck_rcv
;
1925 tcp_ctl
= 0x18; /* PSH,ACK */
1927 si
->io
.pck_snd
+= len
;
1931 case SWRAP_SEND_RST
:
1932 dest_addr
= si
->myname
;
1933 src_addr
= si
->peername
;
1935 if (si
->type
== SOCK_DGRAM
) {
1936 return swrap_marshall_packet(si
, si
->peername
,
1937 SWRAP_SENDTO_UNREACH
,
1938 buf
, len
, packet_len
);
1941 tcp_seqno
= si
->io
.pck_rcv
;
1942 tcp_ack
= si
->io
.pck_snd
;
1943 tcp_ctl
= 0x14; /** RST,ACK */
1947 case SWRAP_PENDING_RST
:
1948 dest_addr
= si
->myname
;
1949 src_addr
= si
->peername
;
1951 if (si
->type
== SOCK_DGRAM
) {
1955 tcp_seqno
= si
->io
.pck_rcv
;
1956 tcp_ack
= si
->io
.pck_snd
;
1957 tcp_ctl
= 0x14; /* RST,ACK */
1962 dest_addr
= si
->myname
;
1963 src_addr
= si
->peername
;
1965 tcp_seqno
= si
->io
.pck_rcv
;
1966 tcp_ack
= si
->io
.pck_snd
;
1967 tcp_ctl
= 0x18; /* PSH,ACK */
1969 si
->io
.pck_rcv
+= len
;
1973 case SWRAP_RECV_RST
:
1974 dest_addr
= si
->myname
;
1975 src_addr
= si
->peername
;
1977 if (si
->type
== SOCK_DGRAM
) {
1981 tcp_seqno
= si
->io
.pck_rcv
;
1982 tcp_ack
= si
->io
.pck_snd
;
1983 tcp_ctl
= 0x14; /* RST,ACK */
1988 src_addr
= si
->myname
;
1991 si
->io
.pck_snd
+= len
;
1995 case SWRAP_SENDTO_UNREACH
:
1996 dest_addr
= si
->myname
;
2003 case SWRAP_RECVFROM
:
2004 dest_addr
= si
->myname
;
2007 si
->io
.pck_rcv
+= len
;
2011 case SWRAP_CLOSE_SEND
:
2012 if (si
->type
!= SOCK_STREAM
) return NULL
;
2014 src_addr
= si
->myname
;
2015 dest_addr
= si
->peername
;
2017 tcp_seqno
= si
->io
.pck_snd
;
2018 tcp_ack
= si
->io
.pck_rcv
;
2019 tcp_ctl
= 0x11; /* FIN, ACK */
2021 si
->io
.pck_snd
+= 1;
2025 case SWRAP_CLOSE_RECV
:
2026 if (si
->type
!= SOCK_STREAM
) return NULL
;
2028 dest_addr
= si
->myname
;
2029 src_addr
= si
->peername
;
2031 tcp_seqno
= si
->io
.pck_rcv
;
2032 tcp_ack
= si
->io
.pck_snd
;
2033 tcp_ctl
= 0x11; /* FIN,ACK */
2035 si
->io
.pck_rcv
+= 1;
2039 case SWRAP_CLOSE_ACK
:
2040 if (si
->type
!= SOCK_STREAM
) return NULL
;
2042 src_addr
= si
->myname
;
2043 dest_addr
= si
->peername
;
2045 tcp_seqno
= si
->io
.pck_snd
;
2046 tcp_ack
= si
->io
.pck_rcv
;
2047 tcp_ctl
= 0x10; /* ACK */
2054 swrapGetTimeOfDay(&tv
);
2056 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
2057 (const uint8_t *)buf
, len
,
2058 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
2062 static void swrap_dump_packet(struct socket_info
*si
,
2063 const struct sockaddr
*addr
,
2064 enum swrap_packet_type type
,
2065 const void *buf
, size_t len
)
2067 const char *file_name
;
2069 size_t packet_len
= 0;
2072 file_name
= socket_wrapper_pcap_file();
2077 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
2082 fd
= swrap_get_pcap_fd(file_name
);
2084 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2093 /****************************************************************************
2095 ***************************************************************************/
2097 #ifdef HAVE_SIGNALFD
2098 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2102 rc
= libc_signalfd(fd
, mask
, flags
);
2104 swrap_remove_stale(fd
);
2110 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2112 return swrap_signalfd(fd
, mask
, flags
);
2116 /****************************************************************************
2118 ***************************************************************************/
2120 static int swrap_socket(int family
, int type
, int protocol
)
2122 struct socket_info
*si
;
2123 struct socket_info_fd
*fi
;
2125 int real_type
= type
;
2128 * Remove possible addition flags passed to socket() so
2129 * do not fail checking the type.
2130 * See https://lwn.net/Articles/281965/
2133 real_type
&= ~SOCK_CLOEXEC
;
2135 #ifdef SOCK_NONBLOCK
2136 real_type
&= ~SOCK_NONBLOCK
;
2139 if (!socket_wrapper_enabled()) {
2140 return libc_socket(family
, type
, protocol
);
2150 return libc_socket(family
, type
, protocol
);
2152 errno
= EAFNOSUPPORT
;
2156 switch (real_type
) {
2162 errno
= EPROTONOSUPPORT
;
2170 if (real_type
== SOCK_STREAM
) {
2175 if (real_type
== SOCK_DGRAM
) {
2180 errno
= EPROTONOSUPPORT
;
2185 * We must call libc_socket with type, from the caller, not the version
2186 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2188 fd
= libc_socket(AF_UNIX
, type
, 0);
2194 /* Check if we have a stale fd and remove it */
2195 si
= find_socket_info(fd
);
2197 swrap_remove_stale(fd
);
2200 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2201 memset(si
, 0, sizeof(struct socket_info
));
2207 si
->family
= family
;
2209 /* however, the rest of the socket_wrapper code expects just
2210 * the type, not the flags */
2211 si
->type
= real_type
;
2212 si
->protocol
= protocol
;
2214 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2223 SWRAP_DLIST_ADD(si
->fds
, fi
);
2224 SWRAP_DLIST_ADD(sockets
, si
);
2229 int socket(int family
, int type
, int protocol
)
2231 return swrap_socket(family
, type
, protocol
);
2234 /****************************************************************************
2236 ***************************************************************************/
2238 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2242 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2244 swrap_remove_stale(sv
[0]);
2245 swrap_remove_stale(sv
[1]);
2251 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2253 return swrap_socketpair(family
, type
, protocol
, sv
);
2256 /****************************************************************************
2258 ***************************************************************************/
2260 #ifdef HAVE_TIMERFD_CREATE
2261 static int swrap_timerfd_create(int clockid
, int flags
)
2265 fd
= libc_timerfd_create(clockid
, flags
);
2267 swrap_remove_stale(fd
);
2273 int timerfd_create(int clockid
, int flags
)
2275 return swrap_timerfd_create(clockid
, flags
);
2279 /****************************************************************************
2281 ***************************************************************************/
2283 static int swrap_pipe(int pipefd
[2])
2287 rc
= libc_pipe(pipefd
);
2289 swrap_remove_stale(pipefd
[0]);
2290 swrap_remove_stale(pipefd
[1]);
2296 int pipe(int pipefd
[2])
2298 return swrap_pipe(pipefd
);
2301 /****************************************************************************
2303 ***************************************************************************/
2305 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2307 struct socket_info
*parent_si
, *child_si
;
2308 struct socket_info_fd
*child_fi
;
2310 struct sockaddr_un un_addr
;
2311 socklen_t un_addrlen
= sizeof(un_addr
);
2312 struct sockaddr_un un_my_addr
;
2313 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
2314 struct sockaddr
*my_addr
;
2315 socklen_t my_addrlen
, len
;
2318 parent_si
= find_socket_info(s
);
2320 return libc_accept(s
, addr
, addrlen
);
2324 * assume out sockaddr have the same size as the in parent
2327 my_addrlen
= socket_length(parent_si
->family
);
2328 if (my_addrlen
<= 0) {
2333 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
2334 if (my_addr
== NULL
) {
2338 memset(&un_addr
, 0, sizeof(un_addr
));
2339 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
2341 ret
= libc_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2343 if (errno
== ENOTSOCK
) {
2344 /* Remove stale fds */
2345 swrap_remove_stale(s
);
2354 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
2355 parent_si
->family
, my_addr
, &len
);
2362 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2363 memset(child_si
, 0, sizeof(struct socket_info
));
2365 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2366 if (child_fi
== NULL
) {
2376 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2378 child_si
->family
= parent_si
->family
;
2379 child_si
->type
= parent_si
->type
;
2380 child_si
->protocol
= parent_si
->protocol
;
2381 child_si
->bound
= 1;
2382 child_si
->is_server
= 1;
2383 child_si
->connected
= 1;
2385 child_si
->peername_len
= len
;
2386 child_si
->peername
= sockaddr_dup(my_addr
, len
);
2388 if (addr
!= NULL
&& addrlen
!= NULL
) {
2389 size_t copy_len
= MIN(*addrlen
, len
);
2391 memcpy(addr
, my_addr
, copy_len
);
2396 ret
= libc_getsockname(fd
,
2397 (struct sockaddr
*)(void *)&un_my_addr
,
2408 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
2409 child_si
->family
, my_addr
, &len
);
2418 SWRAP_LOG(SWRAP_LOG_TRACE
,
2419 "accept() path=%s, fd=%d",
2420 un_my_addr
.sun_path
, s
);
2422 child_si
->myname_len
= len
;
2423 child_si
->myname
= sockaddr_dup(my_addr
, len
);
2426 SWRAP_DLIST_ADD(sockets
, child_si
);
2429 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2430 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2431 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2437 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2438 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2440 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2443 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2446 static int autobind_start_init
;
2447 static int autobind_start
;
2449 /* using sendto() or connect() on an unbound socket would give the
2450 recipient no way to reply, as unlike UDP and TCP, a unix domain
2451 socket can't auto-assign ephemeral port numbers, so we need to
2453 Note: this might change the family from ipv6 to ipv4
2455 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2457 struct sockaddr_un un_addr
;
2464 if (autobind_start_init
!= 1) {
2465 autobind_start_init
= 1;
2466 autobind_start
= getpid();
2467 autobind_start
%= 50000;
2468 autobind_start
+= 10000;
2471 un_addr
.sun_family
= AF_UNIX
;
2475 struct sockaddr_in in
;
2479 type
= SOCKET_TYPE_CHAR_TCP
;
2482 type
= SOCKET_TYPE_CHAR_UDP
;
2485 errno
= ESOCKTNOSUPPORT
;
2489 memset(&in
, 0, sizeof(in
));
2490 in
.sin_family
= AF_INET
;
2491 in
.sin_addr
.s_addr
= htonl(127<<24 |
2492 socket_wrapper_default_iface());
2494 si
->myname_len
= sizeof(in
);
2495 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
2500 struct sockaddr_in6 in6
;
2502 if (si
->family
!= family
) {
2503 errno
= ENETUNREACH
;
2509 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2512 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2515 errno
= ESOCKTNOSUPPORT
;
2519 memset(&in6
, 0, sizeof(in6
));
2520 in6
.sin6_family
= AF_INET6
;
2521 in6
.sin6_addr
= *swrap_ipv6();
2522 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2523 si
->myname_len
= sizeof(in6
);
2524 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
2529 errno
= ESOCKTNOSUPPORT
;
2533 if (autobind_start
> 60000) {
2534 autobind_start
= 10000;
2537 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2538 port
= autobind_start
+ i
;
2539 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
2540 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2541 type
, socket_wrapper_default_iface(), port
);
2542 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
2544 ret
= libc_bind(fd
, (struct sockaddr
*)(void *)&un_addr
,
2546 if (ret
== -1) return ret
;
2548 si
->tmp_path
= strdup(un_addr
.sun_path
);
2550 autobind_start
= port
+ 1;
2553 if (i
== SOCKET_MAX_SOCKETS
) {
2554 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2555 "interface "SOCKET_FORMAT
,
2558 socket_wrapper_default_iface(),
2564 si
->family
= family
;
2565 set_port(si
->family
, port
, si
->myname
);
2570 /****************************************************************************
2572 ***************************************************************************/
2574 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2578 struct sockaddr_un un_addr
;
2579 struct socket_info
*si
= find_socket_info(s
);
2583 return libc_connect(s
, serv_addr
, addrlen
);
2586 if (si
->bound
== 0) {
2587 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2588 if (ret
== -1) return -1;
2591 if (si
->family
!= serv_addr
->sa_family
) {
2596 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2597 addrlen
, &un_addr
, 0, &bcast
);
2598 if (ret
== -1) return -1;
2601 errno
= ENETUNREACH
;
2605 if (si
->type
== SOCK_DGRAM
) {
2606 si
->defer_connect
= 1;
2609 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2611 ret
= libc_connect(s
,
2612 (struct sockaddr
*)(void *)&un_addr
,
2613 sizeof(struct sockaddr_un
));
2616 SWRAP_LOG(SWRAP_LOG_TRACE
,
2617 "connect() path=%s, fd=%d",
2618 un_addr
.sun_path
, s
);
2621 /* to give better errors */
2622 if (ret
== -1 && errno
== ENOENT
) {
2623 errno
= EHOSTUNREACH
;
2627 si
->peername_len
= addrlen
;
2628 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
2632 * When we connect() on a socket than we have to bind the
2633 * outgoing connection on the interface we use for the
2634 * transport. We already bound it on the right interface
2635 * but here we have to update the name so getsockname()
2636 * returns correct information.
2638 if (si
->bindname
!= NULL
) {
2641 si
->myname
= si
->bindname
;
2642 si
->myname_len
= si
->bindname_len
;
2644 si
->bindname
= NULL
;
2645 si
->bindname_len
= 0;
2648 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2649 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2651 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2657 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2659 return swrap_connect(s
, serv_addr
, addrlen
);
2662 /****************************************************************************
2664 ***************************************************************************/
2666 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2669 struct sockaddr_un un_addr
;
2670 struct socket_info
*si
= find_socket_info(s
);
2673 return libc_bind(s
, myaddr
, addrlen
);
2676 si
->myname_len
= addrlen
;
2677 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
2679 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
2680 if (ret
== -1) return -1;
2682 unlink(un_addr
.sun_path
);
2684 ret
= libc_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
2685 sizeof(struct sockaddr_un
));
2687 SWRAP_LOG(SWRAP_LOG_TRACE
,
2688 "bind() path=%s, fd=%d",
2689 un_addr
.sun_path
, s
);
2698 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2700 return swrap_bind(s
, myaddr
, addrlen
);
2703 /****************************************************************************
2705 ***************************************************************************/
2707 static int swrap_listen(int s
, int backlog
)
2710 struct socket_info
*si
= find_socket_info(s
);
2713 return libc_listen(s
, backlog
);
2716 ret
= libc_listen(s
, backlog
);
2721 int listen(int s
, int backlog
)
2723 return swrap_listen(s
, backlog
);
2726 /****************************************************************************
2728 ***************************************************************************/
2730 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
2734 ret
= libc_vopen(pathname
, flags
, ap
);
2737 * There are methods for closing descriptors (libc-internal code
2738 * paths, direct syscalls) which close descriptors in ways that
2739 * we can't intercept, so try to recover when we notice that
2742 swrap_remove_stale(ret
);
2747 int open(const char *pathname
, int flags
, ...)
2752 va_start(ap
, flags
);
2753 fd
= swrap_vopen(pathname
, flags
, ap
);
2759 /****************************************************************************
2761 ***************************************************************************/
2763 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2765 struct socket_info
*si
= find_socket_info(s
);
2769 return libc_getpeername(s
, name
, addrlen
);
2778 len
= MIN(*addrlen
, si
->peername_len
);
2783 memcpy(name
, si
->peername
, len
);
2784 *addrlen
= si
->peername_len
;
2789 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2790 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
2792 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2795 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
2798 /****************************************************************************
2800 ***************************************************************************/
2802 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2804 struct socket_info
*si
= find_socket_info(s
);
2808 return libc_getsockname(s
, name
, addrlen
);
2811 len
= MIN(*addrlen
, si
->myname_len
);
2816 memcpy(name
, si
->myname
, len
);
2817 *addrlen
= si
->myname_len
;
2822 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2823 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
2825 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2828 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
2831 /****************************************************************************
2833 ***************************************************************************/
2835 static int swrap_getsockopt(int s
, int level
, int optname
,
2836 void *optval
, socklen_t
*optlen
)
2838 struct socket_info
*si
= find_socket_info(s
);
2841 return libc_getsockopt(s
,
2848 if (level
== SOL_SOCKET
) {
2849 return libc_getsockopt(s
,
2856 errno
= ENOPROTOOPT
;
2860 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2861 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
2863 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
2866 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
2869 /****************************************************************************
2871 ***************************************************************************/
2873 static int swrap_setsockopt(int s
, int level
, int optname
,
2874 const void *optval
, socklen_t optlen
)
2876 struct socket_info
*si
= find_socket_info(s
);
2879 return libc_setsockopt(s
,
2886 if (level
== SOL_SOCKET
) {
2887 return libc_setsockopt(s
,
2894 switch (si
->family
) {
2896 if (level
== IPPROTO_IP
) {
2898 if (optname
== IP_PKTINFO
) {
2899 si
->pktinfo
= AF_INET
;
2901 #endif /* IP_PKTINFO */
2906 if (level
== IPPROTO_IPV6
) {
2907 #ifdef IPV6_RECVPKTINFO
2908 if (optname
== IPV6_RECVPKTINFO
) {
2909 si
->pktinfo
= AF_INET6
;
2911 #endif /* IPV6_PKTINFO */
2916 errno
= ENOPROTOOPT
;
2921 int setsockopt(int s
, int level
, int optname
,
2922 const void *optval
, socklen_t optlen
)
2924 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
2927 /****************************************************************************
2929 ***************************************************************************/
2931 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
2933 struct socket_info
*si
= find_socket_info(s
);
2939 return libc_vioctl(s
, r
, va
);
2944 rc
= libc_vioctl(s
, r
, va
);
2948 value
= *((int *)va_arg(ap
, int *));
2950 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
2951 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2952 } else if (value
== 0) { /* END OF FILE */
2953 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
2963 #ifdef HAVE_IOCTL_INT
2964 int ioctl(int s
, int r
, ...)
2966 int ioctl(int s
, unsigned long int r
, ...)
2974 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
2985 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2987 * @brief Add a cmsghdr to a msghdr.
2989 * This is an function to add any type of cmsghdr. It will operate on the
2990 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
2991 * the buffer position after the added cmsg element. Hence, this function is
2992 * intended to be used with an intermediate msghdr and not on the original
2993 * one handed in by the client.
2995 * @param[in] msg The msghdr to which to add the cmsg.
2997 * @param[in] level The cmsg level to set.
2999 * @param[in] type The cmsg type to set.
3001 * @param[in] data The cmsg data to set.
3003 * @param[in] len the length of the data to set.
3005 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3011 size_t cmlen
= CMSG_LEN(len
);
3012 size_t cmspace
= CMSG_SPACE(len
);
3013 uint8_t cmbuf
[cmspace
];
3014 struct cmsghdr
*cm
= (struct cmsghdr
*)cmbuf
;
3017 memset(cmbuf
, 0, cmspace
);
3019 if (msg
->msg_controllen
< cmlen
) {
3020 cmlen
= msg
->msg_controllen
;
3021 msg
->msg_flags
|= MSG_CTRUNC
;
3024 if (msg
->msg_controllen
< cmspace
) {
3025 cmspace
= msg
->msg_controllen
;
3029 * We copy the full input data into an intermediate cmsghdr first
3030 * in order to more easily cope with truncation.
3032 cm
->cmsg_len
= cmlen
;
3033 cm
->cmsg_level
= level
;
3034 cm
->cmsg_type
= type
;
3035 memcpy(CMSG_DATA(cm
), data
, len
);
3038 * We now copy the possibly truncated buffer.
3039 * We copy cmlen bytes, but consume cmspace bytes,
3040 * leaving the possible padding uninitialiazed.
3042 p
= (uint8_t *)msg
->msg_control
;
3043 memcpy(p
, cm
, cmlen
);
3045 msg
->msg_control
= p
;
3046 msg
->msg_controllen
-= cmspace
;
3051 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3054 /* Add packet info */
3055 switch (si
->pktinfo
) {
3056 #if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
3058 struct sockaddr_in
*sin
;
3059 struct in_pktinfo pkt
;
3061 if (si
->bindname_len
== sizeof(struct sockaddr_in
)) {
3062 sin
= (struct sockaddr_in
*)si
->bindname
;
3064 if (si
->myname_len
!= sizeof(struct sockaddr_in
)) {
3067 sin
= (struct sockaddr_in
*)si
->myname
;
3072 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3073 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3075 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3080 #endif /* IP_PKTINFO */
3081 #if defined(HAVE_IPV6)
3083 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3084 struct sockaddr_in6
*sin6
;
3085 struct in6_pktinfo pkt6
;
3087 if (si
->bindname_len
== sizeof(struct sockaddr_in6
)) {
3088 sin6
= (struct sockaddr_in6
*)si
->bindname
;
3090 if (si
->myname_len
!= sizeof(struct sockaddr_in6
)) {
3093 sin6
= (struct sockaddr_in6
*)si
->myname
;
3098 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3099 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3101 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3102 &pkt6
, sizeof(pkt6
));
3103 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3107 #endif /* IPV6_PKTINFO */
3115 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3116 struct msghdr
*omsg
)
3120 if (si
->pktinfo
> 0) {
3121 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3126 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3128 static ssize_t
swrap_sendmsg_before(int fd
,
3129 struct socket_info
*si
,
3131 struct iovec
*tmp_iov
,
3132 struct sockaddr_un
*tmp_un
,
3133 const struct sockaddr_un
**to_un
,
3134 const struct sockaddr
**to
,
3152 if (!si
->connected
) {
3157 if (msg
->msg_iovlen
== 0) {
3161 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3163 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3164 if (nlen
> SOCKET_MAX_PACKET
) {
3168 msg
->msg_iovlen
= i
;
3169 if (msg
->msg_iovlen
== 0) {
3170 *tmp_iov
= msg
->msg_iov
[0];
3171 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3172 msg
->msg_iov
= tmp_iov
;
3173 msg
->msg_iovlen
= 1;
3178 if (si
->connected
) {
3179 if (msg
->msg_name
) {
3184 const struct sockaddr
*msg_name
;
3185 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3187 if (msg_name
== NULL
) {
3193 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3195 if (ret
== -1) return -1;
3203 msg
->msg_name
= tmp_un
;
3204 msg
->msg_namelen
= sizeof(*tmp_un
);
3207 if (si
->bound
== 0) {
3208 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3210 if (errno
== ENOTSOCK
) {
3211 swrap_remove_stale(fd
);
3214 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3220 if (!si
->defer_connect
) {
3224 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
3226 if (ret
== -1) return -1;
3228 ret
= libc_connect(fd
,
3229 (struct sockaddr
*)(void *)tmp_un
,
3232 /* to give better errors */
3233 if (ret
== -1 && errno
== ENOENT
) {
3234 errno
= EHOSTUNREACH
;
3241 si
->defer_connect
= 0;
3244 errno
= EHOSTUNREACH
;
3251 static void swrap_sendmsg_after(int fd
,
3252 struct socket_info
*si
,
3254 const struct sockaddr
*to
,
3257 int saved_errno
= errno
;
3264 /* to give better errors */
3266 if (saved_errno
== ENOENT
) {
3267 saved_errno
= EHOSTUNREACH
;
3268 } else if (saved_errno
== ENOTSOCK
) {
3269 /* If the fd is not a socket, remove it */
3270 swrap_remove_stale(fd
);
3274 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3275 avail
+= msg
->msg_iov
[i
].iov_len
;
3279 remain
= MIN(80, avail
);
3284 /* we capture it as one single packet */
3285 buf
= (uint8_t *)malloc(remain
);
3287 /* we just not capture the packet */
3288 errno
= saved_errno
;
3292 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3293 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3295 msg
->msg_iov
[i
].iov_base
,
3298 remain
-= this_time
;
3305 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3306 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3308 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3313 if (si
->connected
) {
3317 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3318 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3320 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3326 errno
= saved_errno
;
3329 static int swrap_recvmsg_before(int fd
,
3330 struct socket_info
*si
,
3332 struct iovec
*tmp_iov
)
3337 (void)fd
; /* unused */
3341 if (!si
->connected
) {
3346 if (msg
->msg_iovlen
== 0) {
3350 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3352 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3353 if (nlen
> SOCKET_MAX_PACKET
) {
3357 msg
->msg_iovlen
= i
;
3358 if (msg
->msg_iovlen
== 0) {
3359 *tmp_iov
= msg
->msg_iov
[0];
3360 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3361 msg
->msg_iov
= tmp_iov
;
3362 msg
->msg_iovlen
= 1;
3367 if (msg
->msg_name
== NULL
) {
3372 if (msg
->msg_iovlen
== 0) {
3376 if (si
->bound
== 0) {
3377 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3380 * When attempting to read or write to a
3381 * descriptor, if an underlying autobind fails
3382 * because it's not a socket, stop intercepting
3383 * uses of that descriptor.
3385 if (errno
== ENOTSOCK
) {
3386 swrap_remove_stale(fd
);
3389 SWRAP_LOG(SWRAP_LOG_ERROR
,
3390 "swrap_recvmsg_before failed");
3397 errno
= EHOSTUNREACH
;
3404 static int swrap_recvmsg_after(int fd
,
3405 struct socket_info
*si
,
3407 const struct sockaddr_un
*un_addr
,
3408 socklen_t un_addrlen
,
3411 int saved_errno
= errno
;
3413 uint8_t *buf
= NULL
;
3419 /* to give better errors */
3421 if (saved_errno
== ENOENT
) {
3422 saved_errno
= EHOSTUNREACH
;
3423 } else if (saved_errno
== ENOTSOCK
) {
3424 /* If the fd is not a socket, remove it */
3425 swrap_remove_stale(fd
);
3429 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3430 avail
+= msg
->msg_iov
[i
].iov_len
;
3439 remain
= MIN(80, avail
);
3444 /* we capture it as one single packet */
3445 buf
= (uint8_t *)malloc(remain
);
3447 /* we just not capture the packet */
3448 errno
= saved_errno
;
3452 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3453 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3455 msg
->msg_iov
[i
].iov_base
,
3458 remain
-= this_time
;
3463 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
3464 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3465 } else if (ret
== 0) { /* END OF FILE */
3466 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3467 } else if (ret
> 0) {
3468 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
3477 if (un_addr
!= NULL
) {
3478 rc
= sockaddr_convert_from_un(si
,
3488 swrap_dump_packet(si
,
3494 swrap_dump_packet(si
,
3507 errno
= saved_errno
;
3509 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3511 msg
->msg_controllen
> 0 &&
3512 msg
->msg_control
!= NULL
) {
3513 rc
= swrap_msghdr_add_socket_info(si
, msg
);
3523 /****************************************************************************
3525 ***************************************************************************/
3527 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
3528 struct sockaddr
*from
, socklen_t
*fromlen
)
3530 struct sockaddr_un from_addr
;
3531 socklen_t from_addrlen
= sizeof(from_addr
);
3533 struct socket_info
*si
= find_socket_info(s
);
3534 struct sockaddr_storage ss
;
3535 socklen_t ss_len
= sizeof(ss
);
3541 return libc_recvfrom(s
,
3553 if (from
!= NULL
&& fromlen
!= NULL
) {
3554 msg
.msg_name
= from
; /* optional address */
3555 msg
.msg_namelen
= *fromlen
; /* size of address */
3557 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3558 msg
.msg_namelen
= ss_len
; /* size of address */
3560 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3561 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3562 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3563 msg
.msg_control
= NULL
; /* ancillary data, see below */
3564 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3565 msg
.msg_flags
= 0; /* flags on received message */
3568 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3573 buf
= msg
.msg_iov
[0].iov_base
;
3574 len
= msg
.msg_iov
[0].iov_len
;
3576 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3577 memset(&from_addr
, 0, sizeof(from_addr
));
3578 ret
= libc_recvfrom(s
,
3582 (struct sockaddr
*)(void *)&from_addr
,
3588 tret
= swrap_recvmsg_after(s
,
3598 if (from
!= NULL
&& fromlen
!= NULL
) {
3599 *fromlen
= msg
.msg_namelen
;
3605 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3606 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
3607 struct sockaddr
*from
, Psocklen_t fromlen
)
3609 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
3610 struct sockaddr
*from
, socklen_t
*fromlen
)
3613 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
3616 /****************************************************************************
3618 ***************************************************************************/
3620 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
3621 const struct sockaddr
*to
, socklen_t tolen
)
3625 struct sockaddr_un un_addr
;
3626 const struct sockaddr_un
*to_un
= NULL
;
3629 struct socket_info
*si
= find_socket_info(s
);
3633 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
3636 tmp
.iov_base
= discard_const_p(char, buf
);
3640 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
3641 msg
.msg_namelen
= tolen
; /* size of address */
3642 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3643 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3644 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3645 msg
.msg_control
= NULL
; /* ancillary data, see below */
3646 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3647 msg
.msg_flags
= 0; /* flags on received message */
3650 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
3655 buf
= msg
.msg_iov
[0].iov_base
;
3656 len
= msg
.msg_iov
[0].iov_len
;
3661 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
3664 type
= SOCKET_TYPE_CHAR_UDP
;
3666 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
3667 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
3668 socket_wrapper_dir(), type
, iface
, prt
);
3669 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
3671 /* ignore the any errors in broadcast sends */
3676 (struct sockaddr
*)(void *)&un_addr
,
3680 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3685 ret
= libc_sendto(s
,
3689 (struct sockaddr
*)msg
.msg_name
,
3692 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
3697 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
3698 const struct sockaddr
*to
, socklen_t tolen
)
3700 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
3703 /****************************************************************************
3705 ***************************************************************************/
3707 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
3709 struct socket_info
*si
;
3711 struct sockaddr_storage ss
;
3712 socklen_t ss_len
= sizeof(ss
);
3717 si
= find_socket_info(s
);
3719 return libc_recv(s
, buf
, len
, flags
);
3726 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3727 msg
.msg_namelen
= ss_len
; /* size of address */
3728 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3729 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3730 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3731 msg
.msg_control
= NULL
; /* ancillary data, see below */
3732 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3733 msg
.msg_flags
= 0; /* flags on received message */
3736 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3741 buf
= msg
.msg_iov
[0].iov_base
;
3742 len
= msg
.msg_iov
[0].iov_len
;
3744 ret
= libc_recv(s
, buf
, len
, flags
);
3746 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
3754 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
3756 return swrap_recv(s
, buf
, len
, flags
);
3759 /****************************************************************************
3761 ***************************************************************************/
3763 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
3765 struct socket_info
*si
;
3768 struct sockaddr_storage ss
;
3769 socklen_t ss_len
= sizeof(ss
);
3773 si
= find_socket_info(s
);
3775 return libc_read(s
, buf
, len
);
3782 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3783 msg
.msg_namelen
= ss_len
; /* size of address */
3784 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3785 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3786 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3787 msg
.msg_control
= NULL
; /* ancillary data, see below */
3788 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3789 msg
.msg_flags
= 0; /* flags on received message */
3792 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3794 if (tret
== -ENOTSOCK
) {
3795 return libc_read(s
, buf
, len
);
3800 buf
= msg
.msg_iov
[0].iov_base
;
3801 len
= msg
.msg_iov
[0].iov_len
;
3803 ret
= libc_read(s
, buf
, len
);
3805 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
3813 ssize_t
read(int s
, void *buf
, size_t len
)
3815 return swrap_read(s
, buf
, len
);
3818 /****************************************************************************
3820 ***************************************************************************/
3822 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
3826 struct sockaddr_un un_addr
;
3829 struct socket_info
*si
= find_socket_info(s
);
3832 return libc_send(s
, buf
, len
, flags
);
3835 tmp
.iov_base
= discard_const_p(char, buf
);
3839 msg
.msg_name
= NULL
; /* optional address */
3840 msg
.msg_namelen
= 0; /* size of address */
3841 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3842 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3843 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3844 msg
.msg_control
= NULL
; /* ancillary data, see below */
3845 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3846 msg
.msg_flags
= 0; /* flags on received message */
3849 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
3854 buf
= msg
.msg_iov
[0].iov_base
;
3855 len
= msg
.msg_iov
[0].iov_len
;
3857 ret
= libc_send(s
, buf
, len
, flags
);
3859 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
3864 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
3866 return swrap_send(s
, buf
, len
, flags
);
3869 /****************************************************************************
3871 ***************************************************************************/
3873 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
3875 struct sockaddr_un from_addr
;
3876 socklen_t from_addrlen
= sizeof(from_addr
);
3877 struct socket_info
*si
;
3880 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3881 size_t msg_ctrllen_filled
;
3882 size_t msg_ctrllen_left
;
3888 si
= find_socket_info(s
);
3890 return libc_recvmsg(s
, omsg
, flags
);
3893 tmp
.iov_base
= NULL
;
3897 msg
.msg_name
= (struct sockaddr
*)&from_addr
; /* optional address */
3898 msg
.msg_namelen
= from_addrlen
; /* size of address */
3899 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
3900 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
3901 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3902 msg_ctrllen_filled
= 0;
3903 msg_ctrllen_left
= omsg
->msg_controllen
;
3905 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
3906 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
3907 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
3910 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3915 ret
= libc_recvmsg(s
, &msg
, flags
);
3917 msg
.msg_name
= omsg
->msg_name
;
3918 msg
.msg_namelen
= omsg
->msg_namelen
;
3920 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3921 msg_ctrllen_filled
+= msg
.msg_controllen
;
3922 msg_ctrllen_left
-= msg
.msg_controllen
;
3924 if (omsg
->msg_control
!= NULL
) {
3927 p
= omsg
->msg_control
;
3928 p
+= msg_ctrllen_filled
;
3930 msg
.msg_control
= p
;
3931 msg
.msg_controllen
= msg_ctrllen_left
;
3933 msg
.msg_control
= NULL
;
3934 msg
.msg_controllen
= 0;
3938 rc
= swrap_recvmsg_after(s
, si
, &msg
, &from_addr
, from_addrlen
, ret
);
3943 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3944 if (omsg
->msg_control
!= NULL
) {
3945 /* msg.msg_controllen = space left */
3946 msg_ctrllen_left
= msg
.msg_controllen
;
3947 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
3950 /* Update the original message length */
3951 omsg
->msg_controllen
= msg_ctrllen_filled
;
3952 omsg
->msg_flags
= msg
.msg_flags
;
3954 omsg
->msg_iovlen
= msg
.msg_iovlen
;
3959 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
3961 return swrap_recvmsg(sockfd
, msg
, flags
);
3964 /****************************************************************************
3966 ***************************************************************************/
3968 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
3972 struct sockaddr_un un_addr
;
3973 const struct sockaddr_un
*to_un
= NULL
;
3974 const struct sockaddr
*to
= NULL
;
3977 struct socket_info
*si
= find_socket_info(s
);
3981 return libc_sendmsg(s
, omsg
, flags
);
3984 ZERO_STRUCT(un_addr
);
3986 tmp
.iov_base
= NULL
;
3990 msg
.msg_name
= omsg
->msg_name
; /* optional address */
3991 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
3992 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
3993 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
3994 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3995 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
3996 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
3997 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4000 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4008 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4016 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4017 avail
+= msg
.msg_iov
[i
].iov_len
;
4023 /* we capture it as one single packet */
4024 buf
= (uint8_t *)malloc(remain
);
4029 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4030 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4032 msg
.msg_iov
[i
].iov_base
,
4035 remain
-= this_time
;
4038 type
= SOCKET_TYPE_CHAR_UDP
;
4040 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4041 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4042 socket_wrapper_dir(), type
, iface
, prt
);
4043 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4045 msg
.msg_name
= &un_addr
; /* optional address */
4046 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4048 /* ignore the any errors in broadcast sends */
4049 libc_sendmsg(s
, &msg
, flags
);
4052 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4058 ret
= libc_sendmsg(s
, &msg
, flags
);
4060 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4065 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4067 return swrap_sendmsg(s
, omsg
, flags
);
4070 /****************************************************************************
4072 ***************************************************************************/
4074 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4076 struct socket_info
*si
;
4079 struct sockaddr_storage ss
;
4080 socklen_t ss_len
= sizeof(ss
);
4084 si
= find_socket_info(s
);
4086 return libc_readv(s
, vector
, count
);
4089 tmp
.iov_base
= NULL
;
4093 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4094 msg
.msg_namelen
= ss_len
; /* size of address */
4095 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4096 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4097 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4098 msg
.msg_control
= NULL
; /* ancillary data, see below */
4099 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4100 msg
.msg_flags
= 0; /* flags on received message */
4103 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4105 if (rc
== -ENOTSOCK
) {
4106 return libc_readv(s
, vector
, count
);
4111 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4113 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4121 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4123 return swrap_readv(s
, vector
, count
);
4126 /****************************************************************************
4128 ***************************************************************************/
4130 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4134 struct sockaddr_un un_addr
;
4137 struct socket_info
*si
= find_socket_info(s
);
4140 return libc_writev(s
, vector
, count
);
4143 tmp
.iov_base
= NULL
;
4147 msg
.msg_name
= NULL
; /* optional address */
4148 msg
.msg_namelen
= 0; /* size of address */
4149 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4150 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4151 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4152 msg
.msg_control
= NULL
; /* ancillary data, see below */
4153 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4154 msg
.msg_flags
= 0; /* flags on received message */
4157 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4159 if (rc
== -ENOTSOCK
) {
4160 return libc_readv(s
, vector
, count
);
4165 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4167 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4172 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4174 return swrap_writev(s
, vector
, count
);
4177 /****************************
4179 ***************************/
4181 static int swrap_close(int fd
)
4183 struct socket_info
*si
= find_socket_info(fd
);
4184 struct socket_info_fd
*fi
;
4188 return libc_close(fd
);
4191 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4193 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4200 /* there are still references left */
4201 return libc_close(fd
);
4204 SWRAP_DLIST_REMOVE(sockets
, si
);
4206 if (si
->myname
&& si
->peername
) {
4207 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4210 ret
= libc_close(fd
);
4212 if (si
->myname
&& si
->peername
) {
4213 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4214 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4217 if (si
->bindname
!= NULL
) {
4221 if (si
->myname
) free(si
->myname
);
4222 if (si
->peername
) free(si
->peername
);
4224 unlink(si
->tmp_path
);
4234 return swrap_close(fd
);
4237 /****************************
4239 ***************************/
4241 static int swrap_dup(int fd
)
4243 struct socket_info
*si
;
4244 struct socket_info_fd
*fi
;
4246 si
= find_socket_info(fd
);
4249 return libc_dup(fd
);
4252 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4258 fi
->fd
= libc_dup(fd
);
4260 int saved_errno
= errno
;
4262 errno
= saved_errno
;
4266 /* Make sure we don't have an entry for the fd */
4267 swrap_remove_stale(fi
->fd
);
4269 SWRAP_DLIST_ADD(si
->fds
, fi
);
4275 return swrap_dup(fd
);
4278 /****************************
4280 ***************************/
4282 static int swrap_dup2(int fd
, int newfd
)
4284 struct socket_info
*si
;
4285 struct socket_info_fd
*fi
;
4287 si
= find_socket_info(fd
);
4290 return libc_dup2(fd
, newfd
);
4293 if (find_socket_info(newfd
)) {
4294 /* dup2() does an implicit close of newfd, which we
4295 * need to emulate */
4299 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4305 fi
->fd
= libc_dup2(fd
, newfd
);
4307 int saved_errno
= errno
;
4309 errno
= saved_errno
;
4313 /* Make sure we don't have an entry for the fd */
4314 swrap_remove_stale(fi
->fd
);
4316 SWRAP_DLIST_ADD(si
->fds
, fi
);
4320 int dup2(int fd
, int newfd
)
4322 return swrap_dup2(fd
, newfd
);
4325 /****************************
4327 ***************************/
4330 static int swrap_eventfd(int count
, int flags
)
4334 fd
= libc_eventfd(count
, flags
);
4336 swrap_remove_stale(fd
);
4342 int eventfd(int count
, int flags
)
4344 return swrap_eventfd(count
, flags
);
4348 /****************************
4350 ***************************/
4353 * This function is called when the library is unloaded and makes sure that
4354 * sockets get closed and the unix file for the socket are unlinked.
4356 void swrap_destructor(void)
4358 struct socket_info
*s
= sockets
;
4361 struct socket_info_fd
*f
= s
->fds
;