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>
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
100 #define DESTRUCTOR_ATTRIBUTE
103 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
106 # define SWRAP_THREAD
110 #define MIN(a,b) ((a)<(b)?(a):(b))
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
118 #define ZERO_STRUCTP(x) do { \
120 memset((char *)(x), 0, sizeof(*(x))); \
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
150 #define SWRAP_DLIST_ADD(list,item) do { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
167 (list)->prev = NULL; \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct socket_info_fd
{
214 struct socket_info_fd
*prev
, *next
;
220 struct socket_info_fd
*fds
;
234 struct sockaddr
*bindname
;
235 socklen_t bindname_len
;
237 struct sockaddr
*myname
;
238 socklen_t myname_len
;
240 struct sockaddr
*peername
;
241 socklen_t peername_len
;
244 unsigned long pck_snd
;
245 unsigned long pck_rcv
;
248 struct socket_info
*prev
, *next
;
252 * File descriptors are shared between threads so we should share socket
255 struct socket_info
*sockets
;
257 /* Function prototypes */
259 bool socket_wrapper_enabled(void);
260 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
263 # define SWRAP_LOG(...)
266 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...) PRINTF_ATTRIBUTE(2, 3);
267 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
269 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...)
274 unsigned int lvl
= 0;
276 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
281 va_start(va
, format
);
282 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
287 case SWRAP_LOG_ERROR
:
289 "SWRAP_ERROR(%d): %s\n",
290 (int)getpid(), buffer
);
294 "SWRAP_WARN(%d): %s\n",
295 (int)getpid(), buffer
);
297 case SWRAP_LOG_DEBUG
:
299 "SWRAP_DEBUG(%d): %s\n",
300 (int)getpid(), buffer
);
302 case SWRAP_LOG_TRACE
:
304 "SWRAP_TRACE(%d): %s\n",
305 (int)getpid(), buffer
);
312 /*********************************************************
313 * SWRAP LOADING LIBC FUNCTIONS
314 *********************************************************/
318 struct swrap_libc_fns
{
319 int (*libc_accept
)(int sockfd
,
320 struct sockaddr
*addr
,
322 int (*libc_bind
)(int sockfd
,
323 const struct sockaddr
*addr
,
325 int (*libc_close
)(int fd
);
326 int (*libc_connect
)(int sockfd
,
327 const struct sockaddr
*addr
,
329 int (*libc_dup
)(int fd
);
330 int (*libc_dup2
)(int oldfd
, int newfd
);
332 int (*libc_eventfd
)(int count
, int flags
);
334 int (*libc_getpeername
)(int sockfd
,
335 struct sockaddr
*addr
,
337 int (*libc_getsockname
)(int sockfd
,
338 struct sockaddr
*addr
,
340 int (*libc_getsockopt
)(int sockfd
,
345 int (*libc_ioctl
)(int d
, unsigned long int request
, ...);
346 int (*libc_listen
)(int sockfd
, int backlog
);
347 int (*libc_open
)(const char *pathname
, int flags
, mode_t mode
);
348 int (*libc_pipe
)(int pipefd
[2]);
349 int (*libc_read
)(int fd
, void *buf
, size_t count
);
350 ssize_t (*libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
351 int (*libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
352 int (*libc_recvfrom
)(int sockfd
,
356 struct sockaddr
*src_addr
,
358 int (*libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
359 int (*libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
360 int (*libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
361 int (*libc_sendto
)(int sockfd
,
365 const struct sockaddr
*dst_addr
,
367 int (*libc_setsockopt
)(int sockfd
,
373 int (*libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
375 int (*libc_socket
)(int domain
, int type
, int protocol
);
376 int (*libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
377 #ifdef HAVE_TIMERFD_CREATE
378 int (*libc_timerfd_create
)(int clockid
, int flags
);
380 ssize_t (*libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
385 void *libsocket_handle
;
392 struct swrap_libc_fns fns
;
395 static struct swrap swrap
;
398 static const char *socket_wrapper_dir(void);
400 #define LIBC_NAME "libc.so"
409 static const char *swrap_str_lib(enum swrap_lib lib
)
416 case SWRAP_LIBSOCKET
:
420 /* Compiler would warn us about unhandled enum value if we get here */
425 static void *swrap_load_lib_handle(enum swrap_lib lib
)
427 int flags
= RTLD_LAZY
;
432 flags
|= RTLD_DEEPBIND
;
438 case SWRAP_LIBSOCKET
:
439 #ifdef HAVE_LIBSOCKET
440 handle
= swrap
.libsocket_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
), "libsocket.so.%d", i
);
446 handle
= dlopen(soname
, flags
);
449 swrap
.libsocket_handle
= handle
;
455 handle
= swrap
.libc_handle
;
457 if (handle
== NULL
) {
458 handle
= dlopen(LIBC_SO
, flags
);
460 swrap
.libc_handle
= handle
;
463 if (handle
== NULL
) {
464 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
465 char soname
[256] = {0};
467 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
468 handle
= dlopen(soname
, flags
);
471 swrap
.libc_handle
= handle
;
476 if (handle
== NULL
) {
478 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
480 SWRAP_LOG(SWRAP_LOG_ERROR
,
481 "Failed to dlopen library: %s\n",
490 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
495 handle
= swrap_load_lib_handle(lib
);
497 func
= dlsym(handle
, fn_name
);
499 SWRAP_LOG(SWRAP_LOG_ERROR
,
500 "Failed to find %s: %s\n",
505 SWRAP_LOG(SWRAP_LOG_TRACE
,
507 fn_name
, swrap_str_lib(lib
));
511 #define swrap_load_lib_function(lib, fn_name) \
512 if (swrap.fns.libc_##fn_name == NULL) { \
513 *(void **) (&swrap.fns.libc_##fn_name) = \
514 _swrap_load_lib_function(lib, #fn_name); \
521 * Functions especially from libc need to be loaded individually, you can't load
522 * all at once or gdb will segfault at startup. The same applies to valgrind and
523 * has probably something todo with with the linker.
524 * So we need load each function at the point it is called the first time.
526 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
528 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
530 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
533 static int libc_bind(int sockfd
,
534 const struct sockaddr
*addr
,
537 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
539 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
542 static int libc_close(int fd
)
544 swrap_load_lib_function(SWRAP_LIBC
, close
);
546 return swrap
.fns
.libc_close(fd
);
549 static int libc_connect(int sockfd
,
550 const struct sockaddr
*addr
,
553 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
555 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
558 static int libc_dup(int fd
)
560 swrap_load_lib_function(SWRAP_LIBC
, dup
);
562 return swrap
.fns
.libc_dup(fd
);
565 static int libc_dup2(int oldfd
, int newfd
)
567 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
569 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
573 static int libc_eventfd(int count
, int flags
)
575 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
577 return swrap
.fns
.libc_eventfd(count
, flags
);
581 static int libc_getpeername(int sockfd
,
582 struct sockaddr
*addr
,
585 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
587 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
590 static int libc_getsockname(int sockfd
,
591 struct sockaddr
*addr
,
594 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
596 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
599 static int libc_getsockopt(int sockfd
,
605 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
607 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
610 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
616 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
618 for (i
= 0; i
< 4; i
++) {
619 args
[i
] = va_arg(ap
, long int);
622 rc
= swrap
.fns
.libc_ioctl(d
,
632 static int libc_listen(int sockfd
, int backlog
)
634 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
636 return swrap
.fns
.libc_listen(sockfd
, backlog
);
639 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
644 swrap_load_lib_function(SWRAP_LIBC
, open
);
646 mode
= va_arg(ap
, long int);
648 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
653 static int libc_open(const char *pathname
, int flags
, ...)
659 fd
= libc_vopen(pathname
, flags
, ap
);
665 static int libc_pipe(int pipefd
[2])
667 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
669 return swrap
.fns
.libc_pipe(pipefd
);
672 static int libc_read(int fd
, void *buf
, size_t count
)
674 swrap_load_lib_function(SWRAP_LIBC
, read
);
676 return swrap
.fns
.libc_read(fd
, buf
, count
);
679 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
681 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
683 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
686 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
688 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
690 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
693 static int libc_recvfrom(int sockfd
,
697 struct sockaddr
*src_addr
,
700 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
702 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
705 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
707 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
709 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
712 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
714 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
716 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
719 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
721 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
723 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
726 static int libc_sendto(int sockfd
,
730 const struct sockaddr
*dst_addr
,
733 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
735 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
738 static int libc_setsockopt(int sockfd
,
744 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
746 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
750 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
752 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
754 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
758 static int libc_socket(int domain
, int type
, int protocol
)
760 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
762 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
765 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
767 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
769 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
772 #ifdef HAVE_TIMERFD_CREATE
773 static int libc_timerfd_create(int clockid
, int flags
)
775 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
777 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
781 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
783 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
785 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
788 /*********************************************************
789 * SWRAP HELPER FUNCTIONS
790 *********************************************************/
796 static const struct in6_addr
*swrap_ipv6(void)
798 static struct in6_addr v
;
799 static int initialized
;
807 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
816 static struct sockaddr
*sockaddr_dup(const void *data
, socklen_t len
)
818 struct sockaddr
*ret
= (struct sockaddr
*)malloc(len
);
819 memcpy(ret
, data
, len
);
823 static void set_port(int family
, int prt
, struct sockaddr
*addr
)
827 ((struct sockaddr_in
*)addr
)->sin_port
= htons(prt
);
831 ((struct sockaddr_in6
*)addr
)->sin6_port
= htons(prt
);
837 static size_t socket_length(int family
)
841 return sizeof(struct sockaddr_in
);
844 return sizeof(struct sockaddr_in6
);
850 static const char *socket_wrapper_dir(void)
852 const char *s
= getenv("SOCKET_WRAPPER_DIR");
856 /* TODO use realpath(3) here, when we add support for threads */
857 if (strncmp(s
, "./", 2) == 0) {
861 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
865 bool socket_wrapper_enabled(void)
867 const char *s
= socket_wrapper_dir();
869 return s
!= NULL
? true : false;
872 static unsigned int socket_wrapper_default_iface(void)
874 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
877 if (sscanf(s
, "%u", &iface
) == 1) {
878 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
884 return 1;/* 127.0.0.1 */
887 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
894 p
= strrchr(un
->sun_path
, '/');
895 if (p
) p
++; else p
= un
->sun_path
;
897 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
902 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
905 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
916 case SOCKET_TYPE_CHAR_TCP
:
917 case SOCKET_TYPE_CHAR_UDP
: {
918 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
920 if ((*len
) < sizeof(*in2
)) {
925 memset(in2
, 0, sizeof(*in2
));
926 in2
->sin_family
= AF_INET
;
927 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
928 in2
->sin_port
= htons(prt
);
934 case SOCKET_TYPE_CHAR_TCP_V6
:
935 case SOCKET_TYPE_CHAR_UDP_V6
: {
936 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
938 if ((*len
) < sizeof(*in2
)) {
943 memset(in2
, 0, sizeof(*in2
));
944 in2
->sin6_family
= AF_INET6
;
945 in2
->sin6_addr
= *swrap_ipv6();
946 in2
->sin6_addr
.s6_addr
[15] = iface
;
947 in2
->sin6_port
= htons(prt
);
961 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
969 if (bcast
) *bcast
= 0;
971 switch (inaddr
->sa_family
) {
973 const struct sockaddr_in
*in
=
974 (const struct sockaddr_in
*)(const void *)inaddr
;
975 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
982 u_type
= SOCKET_TYPE_CHAR_TCP
;
985 u_type
= SOCKET_TYPE_CHAR_UDP
;
986 a_type
= SOCKET_TYPE_CHAR_UDP
;
987 b_type
= SOCKET_TYPE_CHAR_UDP
;
990 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
991 errno
= ESOCKTNOSUPPORT
;
995 prt
= ntohs(in
->sin_port
);
996 if (a_type
&& addr
== 0xFFFFFFFF) {
997 /* 255.255.255.255 only udp */
1000 iface
= socket_wrapper_default_iface();
1001 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1002 /* 127.255.255.255 only udp */
1005 iface
= socket_wrapper_default_iface();
1006 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1010 iface
= (addr
& 0x000000FF);
1012 errno
= ENETUNREACH
;
1015 if (bcast
) *bcast
= is_bcast
;
1020 const struct sockaddr_in6
*in
=
1021 (const struct sockaddr_in6
*)(const void *)inaddr
;
1022 struct in6_addr cmp1
, cmp2
;
1026 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1029 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1032 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1033 errno
= ESOCKTNOSUPPORT
;
1037 /* XXX no multicast/broadcast */
1039 prt
= ntohs(in
->sin6_port
);
1041 cmp1
= *swrap_ipv6();
1042 cmp2
= in
->sin6_addr
;
1043 cmp2
.s6_addr
[15] = 0;
1044 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1045 iface
= in
->sin6_addr
.s6_addr
[15];
1047 errno
= ENETUNREACH
;
1055 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1056 errno
= ENETUNREACH
;
1061 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1067 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1068 socket_wrapper_dir());
1069 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1070 /* the caller need to do more processing */
1074 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1075 socket_wrapper_dir(), type
, iface
, prt
);
1076 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1081 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1090 if (bcast
) *bcast
= 0;
1092 switch (si
->family
) {
1094 const struct sockaddr_in
*in
=
1095 (const struct sockaddr_in
*)(const void *)inaddr
;
1096 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1102 prt
= ntohs(in
->sin_port
);
1106 u_type
= SOCKET_TYPE_CHAR_TCP
;
1107 d_type
= SOCKET_TYPE_CHAR_TCP
;
1110 u_type
= SOCKET_TYPE_CHAR_UDP
;
1111 d_type
= SOCKET_TYPE_CHAR_UDP
;
1112 a_type
= SOCKET_TYPE_CHAR_UDP
;
1113 b_type
= SOCKET_TYPE_CHAR_UDP
;
1116 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1117 errno
= ESOCKTNOSUPPORT
;
1125 iface
= socket_wrapper_default_iface();
1126 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1127 /* 255.255.255.255 only udp */
1130 iface
= socket_wrapper_default_iface();
1131 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1132 /* 127.255.255.255 only udp */
1135 iface
= socket_wrapper_default_iface();
1136 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1140 iface
= (addr
& 0x000000FF);
1142 errno
= EADDRNOTAVAIL
;
1146 /* Store the bind address for connect() */
1147 if (si
->bindname
== NULL
) {
1148 struct sockaddr_in bind_in
;
1149 socklen_t blen
= sizeof(struct sockaddr_in
);
1151 ZERO_STRUCT(bind_in
);
1152 bind_in
.sin_family
= in
->sin_family
;
1153 bind_in
.sin_port
= in
->sin_port
;
1154 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1156 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1157 si
->bindname_len
= blen
;
1164 const struct sockaddr_in6
*in
=
1165 (const struct sockaddr_in6
*)(const void *)inaddr
;
1166 struct in6_addr cmp1
, cmp2
;
1170 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1173 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1176 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1177 errno
= ESOCKTNOSUPPORT
;
1181 /* XXX no multicast/broadcast */
1183 prt
= ntohs(in
->sin6_port
);
1185 cmp1
= *swrap_ipv6();
1186 cmp2
= in
->sin6_addr
;
1187 cmp2
.s6_addr
[15] = 0;
1188 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1189 iface
= socket_wrapper_default_iface();
1190 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1191 iface
= in
->sin6_addr
.s6_addr
[15];
1193 errno
= EADDRNOTAVAIL
;
1197 /* Store the bind address for connect() */
1198 if (si
->bindname
== NULL
) {
1199 struct sockaddr_in6 bind_in
;
1200 socklen_t blen
= sizeof(struct sockaddr_in6
);
1202 ZERO_STRUCT(bind_in
);
1203 bind_in
.sin6_family
= in
->sin6_family
;
1204 bind_in
.sin6_port
= in
->sin6_port
;
1206 bind_in
.sin6_addr
= *swrap_ipv6();
1207 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1209 si
->bindname
= sockaddr_dup(&bind_in
, blen
);
1210 si
->bindname_len
= blen
;
1217 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1218 errno
= EADDRNOTAVAIL
;
1223 if (bcast
) *bcast
= is_bcast
;
1225 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1231 /* handle auto-allocation of ephemeral ports */
1232 for (prt
= 5001; prt
< 10000; prt
++) {
1233 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1234 socket_wrapper_dir(), type
, iface
, prt
);
1235 if (stat(un
->sun_path
, &st
) == 0) continue;
1237 set_port(si
->family
, prt
, si
->myname
);
1238 set_port(si
->family
, prt
, si
->bindname
);
1248 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1249 socket_wrapper_dir(), type
, iface
, prt
);
1250 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1254 static struct socket_info
*find_socket_info(int fd
)
1256 struct socket_info
*i
;
1258 for (i
= sockets
; i
; i
= i
->next
) {
1259 struct socket_info_fd
*f
;
1260 for (f
= i
->fds
; f
; f
= f
->next
) {
1270 static bool check_addr_port_in_use(const struct sockaddr
*sa
, socklen_t len
)
1272 struct socket_info
*s
;
1274 /* first catch invalid input */
1275 switch (sa
->sa_family
) {
1277 if (len
< sizeof(struct sockaddr_in
)) {
1283 if (len
< sizeof(struct sockaddr_in6
)) {
1293 for (s
= sockets
; s
!= NULL
; s
= s
->next
) {
1294 if (s
->myname
== NULL
) {
1297 if (s
->myname
->sa_family
!= sa
->sa_family
) {
1300 switch (s
->myname
->sa_family
) {
1302 struct sockaddr_in
*sin1
, *sin2
;
1304 sin1
= (struct sockaddr_in
*)s
->myname
;
1305 sin2
= (struct sockaddr_in
*)sa
;
1307 if (sin1
->sin_addr
.s_addr
== htonl(INADDR_ANY
)) {
1310 if (sin1
->sin_port
!= sin2
->sin_port
) {
1313 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
1323 struct sockaddr_in6
*sin1
, *sin2
;
1325 sin1
= (struct sockaddr_in6
*)s
->myname
;
1326 sin2
= (struct sockaddr_in6
*)sa
;
1328 if (sin1
->sin6_port
!= sin2
->sin6_port
) {
1331 if (!IN6_ARE_ADDR_EQUAL(&sin1
->sin6_addr
,
1353 static void swrap_remove_stale(int fd
)
1355 struct socket_info
*si
= find_socket_info(fd
);
1356 struct socket_info_fd
*fi
;
1359 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1361 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1362 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1368 if (si
->fds
== NULL
) {
1369 SWRAP_DLIST_REMOVE(sockets
, si
);
1374 static int sockaddr_convert_to_un(struct socket_info
*si
,
1375 const struct sockaddr
*in_addr
,
1377 struct sockaddr_un
*out_addr
,
1381 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1383 (void) in_len
; /* unused */
1385 if (out_addr
== NULL
) {
1389 out
->sa_family
= AF_UNIX
;
1390 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1391 out
->sa_len
= sizeof(*out_addr
);
1394 switch (in_addr
->sa_family
) {
1396 struct sockaddr_in
*sin
;
1397 if (si
->family
!= AF_INET
) {
1400 if (in_len
< sizeof(struct sockaddr_in
)) {
1403 sin
= (struct sockaddr_in
*)in_addr
;
1404 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
1409 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1410 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1424 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1425 errno
= ESOCKTNOSUPPORT
;
1429 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1431 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1437 errno
= EAFNOSUPPORT
;
1438 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1442 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1443 const struct sockaddr_un
*in_addr
,
1444 socklen_t un_addrlen
,
1446 struct sockaddr
*out_addr
,
1447 socklen_t
*out_addrlen
)
1451 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1454 if (un_addrlen
== 0) {
1469 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1470 errno
= ESOCKTNOSUPPORT
;
1473 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1474 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1475 out_addr
->sa_len
= *out_addrlen
;
1482 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1483 errno
= EAFNOSUPPORT
;
1487 enum swrap_packet_type
{
1489 SWRAP_CONNECT_UNREACH
,
1497 SWRAP_SENDTO_UNREACH
,
1508 struct swrap_file_hdr
{
1510 uint16_t version_major
;
1511 uint16_t version_minor
;
1514 uint32_t frame_max_len
;
1515 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1518 #define SWRAP_FILE_HDR_SIZE 24
1520 struct swrap_packet_frame
{
1522 uint32_t micro_seconds
;
1523 uint32_t recorded_length
;
1524 uint32_t full_length
;
1526 #define SWRAP_PACKET_FRAME_SIZE 16
1528 union swrap_packet_ip
{
1532 uint16_t packet_length
;
1533 uint16_t identification
;
1538 uint16_t hdr_checksum
;
1542 #define SWRAP_PACKET_IP_V4_SIZE 20
1545 uint8_t flow_label_high
;
1546 uint16_t flow_label_low
;
1547 uint16_t payload_length
;
1548 uint8_t next_header
;
1550 uint8_t src_addr
[16];
1551 uint8_t dest_addr
[16];
1553 #define SWRAP_PACKET_IP_V6_SIZE 40
1555 #define SWRAP_PACKET_IP_SIZE 40
1557 union swrap_packet_payload
{
1559 uint16_t source_port
;
1569 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1571 uint16_t source_port
;
1576 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1583 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1590 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1592 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1594 #define SWRAP_PACKET_MIN_ALLOC \
1595 (SWRAP_PACKET_FRAME_SIZE + \
1596 SWRAP_PACKET_IP_SIZE + \
1597 SWRAP_PACKET_PAYLOAD_SIZE)
1599 static const char *socket_wrapper_pcap_file(void)
1601 static int initialized
= 0;
1602 static const char *s
= NULL
;
1603 static const struct swrap_file_hdr h
;
1604 static const struct swrap_packet_frame f
;
1605 static const union swrap_packet_ip i
;
1606 static const union swrap_packet_payload p
;
1608 if (initialized
== 1) {
1614 * TODO: don't use the structs use plain buffer offsets
1615 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1617 * for now make sure we disable PCAP support
1618 * if the struct has alignment!
1620 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1623 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1626 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1629 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1632 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1635 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1638 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1641 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1644 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1647 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1651 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1655 if (strncmp(s
, "./", 2) == 0) {
1661 static uint8_t *swrap_packet_init(struct timeval
*tval
,
1662 const struct sockaddr
*src
,
1663 const struct sockaddr
*dest
,
1665 const uint8_t *payload
,
1667 unsigned long tcp_seqno
,
1668 unsigned long tcp_ack
,
1669 unsigned char tcp_ctl
,
1671 size_t *_packet_len
)
1675 struct swrap_packet_frame
*frame
;
1676 union swrap_packet_ip
*ip
;
1677 union swrap_packet_payload
*pay
;
1680 size_t nonwire_len
= sizeof(*frame
);
1681 size_t wire_hdr_len
= 0;
1682 size_t wire_len
= 0;
1683 size_t ip_hdr_len
= 0;
1684 size_t icmp_hdr_len
= 0;
1685 size_t icmp_truncate_len
= 0;
1686 uint8_t protocol
= 0, icmp_protocol
= 0;
1687 const struct sockaddr_in
*src_in
= NULL
;
1688 const struct sockaddr_in
*dest_in
= NULL
;
1690 const struct sockaddr_in6
*src_in6
= NULL
;
1691 const struct sockaddr_in6
*dest_in6
= NULL
;
1696 switch (src
->sa_family
) {
1698 src_in
= (const struct sockaddr_in
*)src
;
1699 dest_in
= (const struct sockaddr_in
*)dest
;
1700 src_port
= src_in
->sin_port
;
1701 dest_port
= dest_in
->sin_port
;
1702 ip_hdr_len
= sizeof(ip
->v4
);
1706 src_in6
= (const struct sockaddr_in6
*)src
;
1707 dest_in6
= (const struct sockaddr_in6
*)dest
;
1708 src_port
= src_in6
->sin6_port
;
1709 dest_port
= dest_in6
->sin6_port
;
1710 ip_hdr_len
= sizeof(ip
->v6
);
1717 switch (socket_type
) {
1719 protocol
= 0x06; /* TCP */
1720 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1721 wire_len
= wire_hdr_len
+ payload_len
;
1725 protocol
= 0x11; /* UDP */
1726 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1727 wire_len
= wire_hdr_len
+ payload_len
;
1735 icmp_protocol
= protocol
;
1736 switch (src
->sa_family
) {
1738 protocol
= 0x01; /* ICMPv4 */
1739 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1743 protocol
= 0x3A; /* ICMPv6 */
1744 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1748 if (wire_len
> 64 ) {
1749 icmp_truncate_len
= wire_len
- 64;
1751 wire_hdr_len
+= icmp_hdr_len
;
1752 wire_len
+= icmp_hdr_len
;
1755 packet_len
= nonwire_len
+ wire_len
;
1756 alloc_len
= packet_len
;
1757 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1758 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1761 base
= (uint8_t *)malloc(alloc_len
);
1765 memset(base
, 0x0, alloc_len
);
1769 frame
= (struct swrap_packet_frame
*)buf
;
1770 frame
->seconds
= tval
->tv_sec
;
1771 frame
->micro_seconds
= tval
->tv_usec
;
1772 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1773 frame
->full_length
= wire_len
- icmp_truncate_len
;
1774 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1776 ip
= (union swrap_packet_ip
*)buf
;
1777 switch (src
->sa_family
) {
1779 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1781 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1782 ip
->v4
.identification
= htons(0xFFFF);
1783 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1784 ip
->v4
.fragment
= htons(0x0000);
1786 ip
->v4
.protocol
= protocol
;
1787 ip
->v4
.hdr_checksum
= htons(0x0000);
1788 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1789 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1790 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1794 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1795 ip
->v6
.flow_label_high
= 0x00;
1796 ip
->v6
.flow_label_low
= 0x0000;
1797 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1798 ip
->v6
.next_header
= protocol
;
1799 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1800 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1801 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1807 pay
= (union swrap_packet_payload
*)buf
;
1808 switch (src
->sa_family
) {
1810 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1811 pay
->icmp4
.code
= 0x01; /* host unreachable */
1812 pay
->icmp4
.checksum
= htons(0x0000);
1813 pay
->icmp4
.unused
= htonl(0x00000000);
1814 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1816 /* set the ip header in the ICMP payload */
1817 ip
= (union swrap_packet_ip
*)buf
;
1818 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1820 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1821 ip
->v4
.identification
= htons(0xFFFF);
1822 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1823 ip
->v4
.fragment
= htons(0x0000);
1825 ip
->v4
.protocol
= icmp_protocol
;
1826 ip
->v4
.hdr_checksum
= htons(0x0000);
1827 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1828 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1829 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1831 src_port
= dest_in
->sin_port
;
1832 dest_port
= src_in
->sin_port
;
1836 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1837 pay
->icmp6
.code
= 0x03; /* address unreachable */
1838 pay
->icmp6
.checksum
= htons(0x0000);
1839 pay
->icmp6
.unused
= htonl(0x00000000);
1840 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1842 /* set the ip header in the ICMP payload */
1843 ip
= (union swrap_packet_ip
*)buf
;
1844 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1845 ip
->v6
.flow_label_high
= 0x00;
1846 ip
->v6
.flow_label_low
= 0x0000;
1847 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1848 ip
->v6
.next_header
= protocol
;
1849 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1850 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1851 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1853 src_port
= dest_in6
->sin6_port
;
1854 dest_port
= src_in6
->sin6_port
;
1860 pay
= (union swrap_packet_payload
*)buf
;
1862 switch (socket_type
) {
1864 pay
->tcp
.source_port
= src_port
;
1865 pay
->tcp
.dest_port
= dest_port
;
1866 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1867 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1868 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1869 pay
->tcp
.control
= tcp_ctl
;
1870 pay
->tcp
.window
= htons(0x7FFF);
1871 pay
->tcp
.checksum
= htons(0x0000);
1872 pay
->tcp
.urg
= htons(0x0000);
1873 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1878 pay
->udp
.source_port
= src_port
;
1879 pay
->udp
.dest_port
= dest_port
;
1880 pay
->udp
.length
= htons(8 + payload_len
);
1881 pay
->udp
.checksum
= htons(0x0000);
1882 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1887 if (payload
&& payload_len
> 0) {
1888 memcpy(buf
, payload
, payload_len
);
1891 *_packet_len
= packet_len
- icmp_truncate_len
;
1895 static int swrap_get_pcap_fd(const char *fname
)
1899 if (fd
!= -1) return fd
;
1901 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1903 struct swrap_file_hdr file_hdr
;
1904 file_hdr
.magic
= 0xA1B2C3D4;
1905 file_hdr
.version_major
= 0x0002;
1906 file_hdr
.version_minor
= 0x0004;
1907 file_hdr
.timezone
= 0x00000000;
1908 file_hdr
.sigfigs
= 0x00000000;
1909 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1910 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1912 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1919 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1924 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1925 const struct sockaddr
*addr
,
1926 enum swrap_packet_type type
,
1927 const void *buf
, size_t len
,
1930 const struct sockaddr
*src_addr
;
1931 const struct sockaddr
*dest_addr
;
1932 unsigned long tcp_seqno
= 0;
1933 unsigned long tcp_ack
= 0;
1934 unsigned char tcp_ctl
= 0;
1935 int unreachable
= 0;
1939 switch (si
->family
) {
1951 case SWRAP_CONNECT_SEND
:
1952 if (si
->type
!= SOCK_STREAM
) return NULL
;
1954 src_addr
= si
->myname
;
1957 tcp_seqno
= si
->io
.pck_snd
;
1958 tcp_ack
= si
->io
.pck_rcv
;
1959 tcp_ctl
= 0x02; /* SYN */
1961 si
->io
.pck_snd
+= 1;
1965 case SWRAP_CONNECT_RECV
:
1966 if (si
->type
!= SOCK_STREAM
) return NULL
;
1968 dest_addr
= si
->myname
;
1971 tcp_seqno
= si
->io
.pck_rcv
;
1972 tcp_ack
= si
->io
.pck_snd
;
1973 tcp_ctl
= 0x12; /** SYN,ACK */
1975 si
->io
.pck_rcv
+= 1;
1979 case SWRAP_CONNECT_UNREACH
:
1980 if (si
->type
!= SOCK_STREAM
) return NULL
;
1982 dest_addr
= si
->myname
;
1985 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1986 tcp_seqno
= si
->io
.pck_snd
- 1;
1987 tcp_ack
= si
->io
.pck_rcv
;
1988 tcp_ctl
= 0x02; /* SYN */
1993 case SWRAP_CONNECT_ACK
:
1994 if (si
->type
!= SOCK_STREAM
) return NULL
;
1996 src_addr
= si
->myname
;
1999 tcp_seqno
= si
->io
.pck_snd
;
2000 tcp_ack
= si
->io
.pck_rcv
;
2001 tcp_ctl
= 0x10; /* ACK */
2005 case SWRAP_ACCEPT_SEND
:
2006 if (si
->type
!= SOCK_STREAM
) return NULL
;
2008 dest_addr
= si
->myname
;
2011 tcp_seqno
= si
->io
.pck_rcv
;
2012 tcp_ack
= si
->io
.pck_snd
;
2013 tcp_ctl
= 0x02; /* SYN */
2015 si
->io
.pck_rcv
+= 1;
2019 case SWRAP_ACCEPT_RECV
:
2020 if (si
->type
!= SOCK_STREAM
) return NULL
;
2022 src_addr
= si
->myname
;
2025 tcp_seqno
= si
->io
.pck_snd
;
2026 tcp_ack
= si
->io
.pck_rcv
;
2027 tcp_ctl
= 0x12; /* SYN,ACK */
2029 si
->io
.pck_snd
+= 1;
2033 case SWRAP_ACCEPT_ACK
:
2034 if (si
->type
!= SOCK_STREAM
) return NULL
;
2036 dest_addr
= si
->myname
;
2039 tcp_seqno
= si
->io
.pck_rcv
;
2040 tcp_ack
= si
->io
.pck_snd
;
2041 tcp_ctl
= 0x10; /* ACK */
2046 src_addr
= si
->myname
;
2047 dest_addr
= si
->peername
;
2049 tcp_seqno
= si
->io
.pck_snd
;
2050 tcp_ack
= si
->io
.pck_rcv
;
2051 tcp_ctl
= 0x18; /* PSH,ACK */
2053 si
->io
.pck_snd
+= len
;
2057 case SWRAP_SEND_RST
:
2058 dest_addr
= si
->myname
;
2059 src_addr
= si
->peername
;
2061 if (si
->type
== SOCK_DGRAM
) {
2062 return swrap_marshall_packet(si
, si
->peername
,
2063 SWRAP_SENDTO_UNREACH
,
2064 buf
, len
, packet_len
);
2067 tcp_seqno
= si
->io
.pck_rcv
;
2068 tcp_ack
= si
->io
.pck_snd
;
2069 tcp_ctl
= 0x14; /** RST,ACK */
2073 case SWRAP_PENDING_RST
:
2074 dest_addr
= si
->myname
;
2075 src_addr
= si
->peername
;
2077 if (si
->type
== SOCK_DGRAM
) {
2081 tcp_seqno
= si
->io
.pck_rcv
;
2082 tcp_ack
= si
->io
.pck_snd
;
2083 tcp_ctl
= 0x14; /* RST,ACK */
2088 dest_addr
= si
->myname
;
2089 src_addr
= si
->peername
;
2091 tcp_seqno
= si
->io
.pck_rcv
;
2092 tcp_ack
= si
->io
.pck_snd
;
2093 tcp_ctl
= 0x18; /* PSH,ACK */
2095 si
->io
.pck_rcv
+= len
;
2099 case SWRAP_RECV_RST
:
2100 dest_addr
= si
->myname
;
2101 src_addr
= si
->peername
;
2103 if (si
->type
== SOCK_DGRAM
) {
2107 tcp_seqno
= si
->io
.pck_rcv
;
2108 tcp_ack
= si
->io
.pck_snd
;
2109 tcp_ctl
= 0x14; /* RST,ACK */
2114 src_addr
= si
->myname
;
2117 si
->io
.pck_snd
+= len
;
2121 case SWRAP_SENDTO_UNREACH
:
2122 dest_addr
= si
->myname
;
2129 case SWRAP_RECVFROM
:
2130 dest_addr
= si
->myname
;
2133 si
->io
.pck_rcv
+= len
;
2137 case SWRAP_CLOSE_SEND
:
2138 if (si
->type
!= SOCK_STREAM
) return NULL
;
2140 src_addr
= si
->myname
;
2141 dest_addr
= si
->peername
;
2143 tcp_seqno
= si
->io
.pck_snd
;
2144 tcp_ack
= si
->io
.pck_rcv
;
2145 tcp_ctl
= 0x11; /* FIN, ACK */
2147 si
->io
.pck_snd
+= 1;
2151 case SWRAP_CLOSE_RECV
:
2152 if (si
->type
!= SOCK_STREAM
) return NULL
;
2154 dest_addr
= si
->myname
;
2155 src_addr
= si
->peername
;
2157 tcp_seqno
= si
->io
.pck_rcv
;
2158 tcp_ack
= si
->io
.pck_snd
;
2159 tcp_ctl
= 0x11; /* FIN,ACK */
2161 si
->io
.pck_rcv
+= 1;
2165 case SWRAP_CLOSE_ACK
:
2166 if (si
->type
!= SOCK_STREAM
) return NULL
;
2168 src_addr
= si
->myname
;
2169 dest_addr
= si
->peername
;
2171 tcp_seqno
= si
->io
.pck_snd
;
2172 tcp_ack
= si
->io
.pck_rcv
;
2173 tcp_ctl
= 0x10; /* ACK */
2180 swrapGetTimeOfDay(&tv
);
2182 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
2183 (const uint8_t *)buf
, len
,
2184 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
2188 static void swrap_dump_packet(struct socket_info
*si
,
2189 const struct sockaddr
*addr
,
2190 enum swrap_packet_type type
,
2191 const void *buf
, size_t len
)
2193 const char *file_name
;
2195 size_t packet_len
= 0;
2198 file_name
= socket_wrapper_pcap_file();
2203 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
2208 fd
= swrap_get_pcap_fd(file_name
);
2210 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2219 /****************************************************************************
2221 ***************************************************************************/
2223 #ifdef HAVE_SIGNALFD
2224 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2228 rc
= libc_signalfd(fd
, mask
, flags
);
2230 swrap_remove_stale(fd
);
2236 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2238 return swrap_signalfd(fd
, mask
, flags
);
2242 /****************************************************************************
2244 ***************************************************************************/
2246 static int swrap_socket(int family
, int type
, int protocol
)
2248 struct socket_info
*si
;
2249 struct socket_info_fd
*fi
;
2251 int real_type
= type
;
2254 * Remove possible addition flags passed to socket() so
2255 * do not fail checking the type.
2256 * See https://lwn.net/Articles/281965/
2259 real_type
&= ~SOCK_CLOEXEC
;
2261 #ifdef SOCK_NONBLOCK
2262 real_type
&= ~SOCK_NONBLOCK
;
2265 if (!socket_wrapper_enabled()) {
2266 return libc_socket(family
, type
, protocol
);
2276 return libc_socket(family
, type
, protocol
);
2278 errno
= EAFNOSUPPORT
;
2282 switch (real_type
) {
2288 errno
= EPROTONOSUPPORT
;
2296 if (real_type
== SOCK_STREAM
) {
2301 if (real_type
== SOCK_DGRAM
) {
2306 errno
= EPROTONOSUPPORT
;
2311 * We must call libc_socket with type, from the caller, not the version
2312 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2314 fd
= libc_socket(AF_UNIX
, type
, 0);
2320 /* Check if we have a stale fd and remove it */
2321 si
= find_socket_info(fd
);
2323 swrap_remove_stale(fd
);
2326 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2327 memset(si
, 0, sizeof(struct socket_info
));
2333 si
->family
= family
;
2335 /* however, the rest of the socket_wrapper code expects just
2336 * the type, not the flags */
2337 si
->type
= real_type
;
2338 si
->protocol
= protocol
;
2341 * Setup myname so getsockname() can succeed to find out the socket
2344 switch(si
->family
) {
2346 struct sockaddr_in sin
= {
2347 .sin_family
= AF_INET
,
2350 si
->myname_len
= sizeof(struct sockaddr_in
);
2351 si
->myname
= sockaddr_dup(&sin
, si
->myname_len
);
2355 struct sockaddr_in6 sin6
= {
2356 .sin6_family
= AF_INET6
,
2359 si
->myname_len
= sizeof(struct sockaddr_in6
);
2360 si
->myname
= sockaddr_dup(&sin6
, si
->myname_len
);
2369 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2371 if (si
->myname
!= NULL
) {
2381 SWRAP_DLIST_ADD(si
->fds
, fi
);
2382 SWRAP_DLIST_ADD(sockets
, si
);
2387 int socket(int family
, int type
, int protocol
)
2389 return swrap_socket(family
, type
, protocol
);
2392 /****************************************************************************
2394 ***************************************************************************/
2396 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2400 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2402 swrap_remove_stale(sv
[0]);
2403 swrap_remove_stale(sv
[1]);
2409 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2411 return swrap_socketpair(family
, type
, protocol
, sv
);
2414 /****************************************************************************
2416 ***************************************************************************/
2418 #ifdef HAVE_TIMERFD_CREATE
2419 static int swrap_timerfd_create(int clockid
, int flags
)
2423 fd
= libc_timerfd_create(clockid
, flags
);
2425 swrap_remove_stale(fd
);
2431 int timerfd_create(int clockid
, int flags
)
2433 return swrap_timerfd_create(clockid
, flags
);
2437 /****************************************************************************
2439 ***************************************************************************/
2441 static int swrap_pipe(int pipefd
[2])
2445 rc
= libc_pipe(pipefd
);
2447 swrap_remove_stale(pipefd
[0]);
2448 swrap_remove_stale(pipefd
[1]);
2454 int pipe(int pipefd
[2])
2456 return swrap_pipe(pipefd
);
2459 /****************************************************************************
2461 ***************************************************************************/
2463 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2465 struct socket_info
*parent_si
, *child_si
;
2466 struct socket_info_fd
*child_fi
;
2468 struct sockaddr_un un_addr
;
2469 socklen_t un_addrlen
= sizeof(un_addr
);
2470 struct sockaddr_un un_my_addr
;
2471 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
2472 struct sockaddr
*my_addr
;
2473 socklen_t my_addrlen
, len
;
2476 parent_si
= find_socket_info(s
);
2478 return libc_accept(s
, addr
, addrlen
);
2482 * assume out sockaddr have the same size as the in parent
2485 my_addrlen
= socket_length(parent_si
->family
);
2486 if (my_addrlen
<= 0) {
2491 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
2492 if (my_addr
== NULL
) {
2496 memset(&un_addr
, 0, sizeof(un_addr
));
2497 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
2499 ret
= libc_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2501 if (errno
== ENOTSOCK
) {
2502 /* Remove stale fds */
2503 swrap_remove_stale(s
);
2512 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
2513 parent_si
->family
, my_addr
, &len
);
2520 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2521 memset(child_si
, 0, sizeof(struct socket_info
));
2523 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2524 if (child_fi
== NULL
) {
2534 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2536 child_si
->family
= parent_si
->family
;
2537 child_si
->type
= parent_si
->type
;
2538 child_si
->protocol
= parent_si
->protocol
;
2539 child_si
->bound
= 1;
2540 child_si
->is_server
= 1;
2541 child_si
->connected
= 1;
2543 child_si
->peername_len
= len
;
2544 child_si
->peername
= sockaddr_dup(my_addr
, len
);
2546 if (addr
!= NULL
&& addrlen
!= NULL
) {
2547 size_t copy_len
= MIN(*addrlen
, len
);
2549 memcpy(addr
, my_addr
, copy_len
);
2554 ret
= libc_getsockname(fd
,
2555 (struct sockaddr
*)(void *)&un_my_addr
,
2566 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
2567 child_si
->family
, my_addr
, &len
);
2576 SWRAP_LOG(SWRAP_LOG_TRACE
,
2577 "accept() path=%s, fd=%d",
2578 un_my_addr
.sun_path
, s
);
2580 child_si
->myname_len
= len
;
2581 child_si
->myname
= sockaddr_dup(my_addr
, len
);
2584 SWRAP_DLIST_ADD(sockets
, child_si
);
2587 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2588 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2589 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2595 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2596 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2598 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2601 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2604 static int autobind_start_init
;
2605 static int autobind_start
;
2607 /* using sendto() or connect() on an unbound socket would give the
2608 recipient no way to reply, as unlike UDP and TCP, a unix domain
2609 socket can't auto-assign ephemeral port numbers, so we need to
2611 Note: this might change the family from ipv6 to ipv4
2613 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2615 struct sockaddr_un un_addr
;
2622 if (autobind_start_init
!= 1) {
2623 autobind_start_init
= 1;
2624 autobind_start
= getpid();
2625 autobind_start
%= 50000;
2626 autobind_start
+= 10000;
2629 un_addr
.sun_family
= AF_UNIX
;
2633 struct sockaddr_in in
;
2637 type
= SOCKET_TYPE_CHAR_TCP
;
2640 type
= SOCKET_TYPE_CHAR_UDP
;
2643 errno
= ESOCKTNOSUPPORT
;
2647 memset(&in
, 0, sizeof(in
));
2648 in
.sin_family
= AF_INET
;
2649 in
.sin_addr
.s_addr
= htonl(127<<24 |
2650 socket_wrapper_default_iface());
2653 si
->myname_len
= sizeof(in
);
2654 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
2659 struct sockaddr_in6 in6
;
2661 if (si
->family
!= family
) {
2662 errno
= ENETUNREACH
;
2668 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2671 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2674 errno
= ESOCKTNOSUPPORT
;
2678 memset(&in6
, 0, sizeof(in6
));
2679 in6
.sin6_family
= AF_INET6
;
2680 in6
.sin6_addr
= *swrap_ipv6();
2681 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2683 si
->myname_len
= sizeof(in6
);
2684 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
2689 errno
= ESOCKTNOSUPPORT
;
2693 if (autobind_start
> 60000) {
2694 autobind_start
= 10000;
2697 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2698 port
= autobind_start
+ i
;
2699 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
2700 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2701 type
, socket_wrapper_default_iface(), port
);
2702 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
2704 ret
= libc_bind(fd
, (struct sockaddr
*)(void *)&un_addr
,
2706 if (ret
== -1) return ret
;
2708 si
->tmp_path
= strdup(un_addr
.sun_path
);
2710 autobind_start
= port
+ 1;
2713 if (i
== SOCKET_MAX_SOCKETS
) {
2714 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2715 "interface "SOCKET_FORMAT
,
2718 socket_wrapper_default_iface(),
2724 si
->family
= family
;
2725 set_port(si
->family
, port
, si
->myname
);
2730 /****************************************************************************
2732 ***************************************************************************/
2734 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2738 struct sockaddr_un un_addr
;
2739 struct socket_info
*si
= find_socket_info(s
);
2743 return libc_connect(s
, serv_addr
, addrlen
);
2746 if (si
->bound
== 0) {
2747 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2748 if (ret
== -1) return -1;
2751 if (si
->family
!= serv_addr
->sa_family
) {
2756 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2757 addrlen
, &un_addr
, 0, &bcast
);
2758 if (ret
== -1) return -1;
2761 errno
= ENETUNREACH
;
2765 if (si
->type
== SOCK_DGRAM
) {
2766 si
->defer_connect
= 1;
2769 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2771 ret
= libc_connect(s
,
2772 (struct sockaddr
*)(void *)&un_addr
,
2773 sizeof(struct sockaddr_un
));
2776 SWRAP_LOG(SWRAP_LOG_TRACE
,
2777 "connect() path=%s, fd=%d",
2778 un_addr
.sun_path
, s
);
2781 /* to give better errors */
2782 if (ret
== -1 && errno
== ENOENT
) {
2783 errno
= EHOSTUNREACH
;
2787 si
->peername_len
= addrlen
;
2788 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
2792 * When we connect() on a socket than we have to bind the
2793 * outgoing connection on the interface we use for the
2794 * transport. We already bound it on the right interface
2795 * but here we have to update the name so getsockname()
2796 * returns correct information.
2798 if (si
->bindname
!= NULL
) {
2801 si
->myname
= si
->bindname
;
2802 si
->myname_len
= si
->bindname_len
;
2804 si
->bindname
= NULL
;
2805 si
->bindname_len
= 0;
2808 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2809 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2811 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2817 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2819 return swrap_connect(s
, serv_addr
, addrlen
);
2822 /****************************************************************************
2824 ***************************************************************************/
2826 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2829 struct sockaddr_un un_addr
;
2830 struct socket_info
*si
= find_socket_info(s
);
2834 return libc_bind(s
, myaddr
, addrlen
);
2837 switch (si
->family
) {
2839 const struct sockaddr_in
*sin
;
2840 if (addrlen
< sizeof(struct sockaddr_in
)) {
2841 bind_error
= EINVAL
;
2845 sin
= (struct sockaddr_in
*)myaddr
;
2847 if (sin
->sin_family
!= AF_INET
) {
2848 bind_error
= EAFNOSUPPORT
;
2851 /* special case for AF_UNSPEC */
2852 if (sin
->sin_family
== AF_UNSPEC
&&
2853 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
2862 const struct sockaddr_in6
*sin6
;
2863 if (addrlen
< sizeof(struct sockaddr_in6
)) {
2864 bind_error
= EINVAL
;
2868 sin6
= (struct sockaddr_in6
*)myaddr
;
2870 if (sin6
->sin6_family
!= AF_INET6
) {
2871 bind_error
= EAFNOSUPPORT
;
2878 bind_error
= EINVAL
;
2882 if (bind_error
!= 0) {
2888 si
->myname_len
= addrlen
;
2889 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
2891 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
2892 if (ret
== -1) return -1;
2894 unlink(un_addr
.sun_path
);
2896 ret
= libc_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
2897 sizeof(struct sockaddr_un
));
2899 SWRAP_LOG(SWRAP_LOG_TRACE
,
2900 "bind() path=%s, fd=%d",
2901 un_addr
.sun_path
, s
);
2910 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2912 return swrap_bind(s
, myaddr
, addrlen
);
2915 /****************************************************************************
2917 ***************************************************************************/
2919 #ifdef HAVE_BINDRESVPORT
2920 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
2922 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
2924 struct sockaddr_storage myaddr
;
2926 static uint16_t port
;
2931 #define SWRAP_STARTPORT 600
2932 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2933 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2936 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
2940 salen
= sizeof(struct sockaddr
);
2941 sa
= (struct sockaddr
*)&myaddr
;
2943 rc
= swrap_getsockname(sd
, (struct sockaddr
*)&myaddr
, &salen
);
2949 memset(&myaddr
, 0, salen
);
2954 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
2957 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)sa
;
2959 salen
= sizeof(struct sockaddr_in
);
2960 sinp
->sin_port
= htons(port
);
2964 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)sa
;
2966 salen
= sizeof(struct sockaddr_in6
);
2967 sin6p
->sin6_port
= htons(port
);
2971 errno
= EAFNOSUPPORT
;
2976 if (port
> SWRAP_ENDPORT
) {
2977 port
= SWRAP_STARTPORT
;
2980 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
2981 if (rc
== 0 || errno
!= EADDRINUSE
) {
2989 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
2991 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
2995 /****************************************************************************
2997 ***************************************************************************/
2999 static int swrap_listen(int s
, int backlog
)
3002 struct socket_info
*si
= find_socket_info(s
);
3005 return libc_listen(s
, backlog
);
3008 ret
= libc_listen(s
, backlog
);
3013 int listen(int s
, int backlog
)
3015 return swrap_listen(s
, backlog
);
3018 /****************************************************************************
3020 ***************************************************************************/
3022 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
3026 ret
= libc_vopen(pathname
, flags
, ap
);
3029 * There are methods for closing descriptors (libc-internal code
3030 * paths, direct syscalls) which close descriptors in ways that
3031 * we can't intercept, so try to recover when we notice that
3034 swrap_remove_stale(ret
);
3039 int open(const char *pathname
, int flags
, ...)
3044 va_start(ap
, flags
);
3045 fd
= swrap_vopen(pathname
, flags
, ap
);
3051 /****************************************************************************
3053 ***************************************************************************/
3055 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3057 struct socket_info
*si
= find_socket_info(s
);
3061 return libc_getpeername(s
, name
, addrlen
);
3070 len
= MIN(*addrlen
, si
->peername_len
);
3075 memcpy(name
, si
->peername
, len
);
3076 *addrlen
= si
->peername_len
;
3081 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3082 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3084 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3087 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
3090 /****************************************************************************
3092 ***************************************************************************/
3094 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3096 struct socket_info
*si
= find_socket_info(s
);
3100 return libc_getsockname(s
, name
, addrlen
);
3103 len
= MIN(*addrlen
, si
->myname_len
);
3108 memcpy(name
, si
->myname
, len
);
3109 *addrlen
= si
->myname_len
;
3114 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3115 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3117 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3120 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
3123 /****************************************************************************
3125 ***************************************************************************/
3128 # ifdef SO_PROTOTYPE /* The Solaris name */
3129 # define SO_PROTOCOL SO_PROTOTYPE
3130 # endif /* SO_PROTOTYPE */
3131 #endif /* SO_PROTOCOL */
3133 static int swrap_getsockopt(int s
, int level
, int optname
,
3134 void *optval
, socklen_t
*optlen
)
3136 struct socket_info
*si
= find_socket_info(s
);
3139 return libc_getsockopt(s
,
3146 if (level
== SOL_SOCKET
) {
3150 if (optval
== NULL
|| optlen
== NULL
||
3151 *optlen
< (socklen_t
)sizeof(int)) {
3156 *optlen
= sizeof(int);
3157 *(int *)optval
= si
->family
;
3159 #endif /* SO_DOMAIN */
3161 if (optval
== NULL
|| optlen
== NULL
||
3162 *optlen
< (socklen_t
)sizeof(int)) {
3167 *optlen
= sizeof(int);
3168 *(int *)optval
= si
->protocol
;
3171 if (optval
== NULL
|| optlen
== NULL
||
3172 *optlen
< (socklen_t
)sizeof(int)) {
3177 *optlen
= sizeof(int);
3178 *(int *)optval
= si
->type
;
3181 return libc_getsockopt(s
,
3189 errno
= ENOPROTOOPT
;
3193 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3194 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
3196 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
3199 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
3202 /****************************************************************************
3204 ***************************************************************************/
3206 static int swrap_setsockopt(int s
, int level
, int optname
,
3207 const void *optval
, socklen_t optlen
)
3209 struct socket_info
*si
= find_socket_info(s
);
3212 return libc_setsockopt(s
,
3219 if (level
== SOL_SOCKET
) {
3220 return libc_setsockopt(s
,
3227 switch (si
->family
) {
3229 if (level
== IPPROTO_IP
) {
3231 if (optname
== IP_PKTINFO
) {
3232 si
->pktinfo
= AF_INET
;
3234 #endif /* IP_PKTINFO */
3239 if (level
== IPPROTO_IPV6
) {
3240 #ifdef IPV6_RECVPKTINFO
3241 if (optname
== IPV6_RECVPKTINFO
) {
3242 si
->pktinfo
= AF_INET6
;
3244 #endif /* IPV6_PKTINFO */
3249 errno
= ENOPROTOOPT
;
3254 int setsockopt(int s
, int level
, int optname
,
3255 const void *optval
, socklen_t optlen
)
3257 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
3260 /****************************************************************************
3262 ***************************************************************************/
3264 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
3266 struct socket_info
*si
= find_socket_info(s
);
3272 return libc_vioctl(s
, r
, va
);
3277 rc
= libc_vioctl(s
, r
, va
);
3281 value
= *((int *)va_arg(ap
, int *));
3283 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
3284 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3285 } else if (value
== 0) { /* END OF FILE */
3286 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3296 #ifdef HAVE_IOCTL_INT
3297 int ioctl(int s
, int r
, ...)
3299 int ioctl(int s
, unsigned long int r
, ...)
3307 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
3318 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3321 # ifdef _ALIGN /* BSD */
3322 #define CMSG_ALIGN _ALIGN
3324 #error NO_CMSG_ALIGN
3325 # endif /* _ALIGN */
3326 #endif /* CMSG_ALIGN */
3329 * @brief Add a cmsghdr to a msghdr.
3331 * This is an function to add any type of cmsghdr. It will operate on the
3332 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3333 * the buffer position after the added cmsg element. Hence, this function is
3334 * intended to be used with an intermediate msghdr and not on the original
3335 * one handed in by the client.
3337 * @param[in] msg The msghdr to which to add the cmsg.
3339 * @param[in] level The cmsg level to set.
3341 * @param[in] type The cmsg type to set.
3343 * @param[in] data The cmsg data to set.
3345 * @param[in] len the length of the data to set.
3347 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3353 size_t cmlen
= CMSG_LEN(len
);
3354 size_t cmspace
= CMSG_SPACE(len
);
3355 uint8_t cmbuf
[cmspace
];
3356 struct cmsghdr
*cm
= (struct cmsghdr
*)cmbuf
;
3359 memset(cmbuf
, 0, cmspace
);
3361 if (msg
->msg_controllen
< cmlen
) {
3362 cmlen
= msg
->msg_controllen
;
3363 msg
->msg_flags
|= MSG_CTRUNC
;
3366 if (msg
->msg_controllen
< cmspace
) {
3367 cmspace
= msg
->msg_controllen
;
3371 * We copy the full input data into an intermediate cmsghdr first
3372 * in order to more easily cope with truncation.
3374 cm
->cmsg_len
= cmlen
;
3375 cm
->cmsg_level
= level
;
3376 cm
->cmsg_type
= type
;
3377 memcpy(CMSG_DATA(cm
), data
, len
);
3380 * We now copy the possibly truncated buffer.
3381 * We copy cmlen bytes, but consume cmspace bytes,
3382 * leaving the possible padding uninitialiazed.
3384 p
= (uint8_t *)msg
->msg_control
;
3385 memcpy(p
, cm
, cmlen
);
3387 msg
->msg_control
= p
;
3388 msg
->msg_controllen
-= cmspace
;
3393 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3396 /* Add packet info */
3397 switch (si
->pktinfo
) {
3398 #if defined(IP_PKTINFO)
3399 /* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
3401 struct sockaddr_in
*sin
;
3402 #if defined(HAVE_STRUCT_IN_PKTINFO)
3403 struct in_pktinfo pkt
;
3404 #elif defined(IP_RECVDSTADDR)
3408 if (si
->bindname_len
== sizeof(struct sockaddr_in
)) {
3409 sin
= (struct sockaddr_in
*)si
->bindname
;
3411 if (si
->myname_len
!= sizeof(struct sockaddr_in
)) {
3414 sin
= (struct sockaddr_in
*)si
->myname
;
3419 #if defined(HAVE_STRUCT_IN_PKTINFO)
3420 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3421 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3422 #elif defined(IP_RECVDSTADDR)
3423 pkt
= sin
->sin_addr
;
3426 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3431 #endif /* IP_PKTINFO */
3432 #if defined(HAVE_IPV6)
3434 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3435 struct sockaddr_in6
*sin6
;
3436 struct in6_pktinfo pkt6
;
3438 if (si
->bindname_len
== sizeof(struct sockaddr_in6
)) {
3439 sin6
= (struct sockaddr_in6
*)si
->bindname
;
3441 if (si
->myname_len
!= sizeof(struct sockaddr_in6
)) {
3444 sin6
= (struct sockaddr_in6
*)si
->myname
;
3449 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3450 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3452 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3453 &pkt6
, sizeof(pkt6
));
3454 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3458 #endif /* IPV6_PKTINFO */
3466 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3467 struct msghdr
*omsg
)
3471 if (si
->pktinfo
> 0) {
3472 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3478 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3480 size_t *cm_data_space
);
3481 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3483 size_t *cm_data_space
);
3485 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
3487 size_t *cm_data_space
) {
3488 struct cmsghdr
*cmsg
;
3492 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
3496 for (cmsg
= CMSG_FIRSTHDR(msg
);
3498 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
3499 switch (cmsg
->cmsg_level
) {
3501 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
3506 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
3516 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3518 size_t *cm_data_space
)
3525 CMSG_SPACE(cmsg
->cmsg_len
- CMSG_ALIGN(sizeof(struct cmsghdr
)));
3527 p
= realloc((*cm_data
), cmspace
);
3533 p
= (*cm_data
) + (*cm_data_space
);
3534 *cm_data_space
= cmspace
;
3536 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
3541 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3543 size_t *cm_data_space
);
3546 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3548 size_t *cm_data_space
)
3552 switch(cmsg
->cmsg_type
) {
3555 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3562 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3574 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3576 size_t *cm_data_space
)
3578 (void)cmsg
; /* unused */
3579 (void)cm_data
; /* unused */
3580 (void)cm_data_space
; /* unused */
3583 * Passing a IP pktinfo to a unix socket might be rejected by the
3584 * Kernel, at least on FreeBSD. So skip this cmsg.
3588 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3590 static ssize_t
swrap_sendmsg_before(int fd
,
3591 struct socket_info
*si
,
3593 struct iovec
*tmp_iov
,
3594 struct sockaddr_un
*tmp_un
,
3595 const struct sockaddr_un
**to_un
,
3596 const struct sockaddr
**to
,
3614 if (!si
->connected
) {
3619 if (msg
->msg_iovlen
== 0) {
3623 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3625 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3626 if (nlen
> SOCKET_MAX_PACKET
) {
3630 msg
->msg_iovlen
= i
;
3631 if (msg
->msg_iovlen
== 0) {
3632 *tmp_iov
= msg
->msg_iov
[0];
3633 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3634 msg
->msg_iov
= tmp_iov
;
3635 msg
->msg_iovlen
= 1;
3640 if (si
->connected
) {
3641 if (msg
->msg_name
) {
3646 const struct sockaddr
*msg_name
;
3647 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3649 if (msg_name
== NULL
) {
3655 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3657 if (ret
== -1) return -1;
3665 msg
->msg_name
= tmp_un
;
3666 msg
->msg_namelen
= sizeof(*tmp_un
);
3669 if (si
->bound
== 0) {
3670 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3672 if (errno
== ENOTSOCK
) {
3673 swrap_remove_stale(fd
);
3676 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3682 if (!si
->defer_connect
) {
3686 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
3688 if (ret
== -1) return -1;
3690 ret
= libc_connect(fd
,
3691 (struct sockaddr
*)(void *)tmp_un
,
3694 /* to give better errors */
3695 if (ret
== -1 && errno
== ENOENT
) {
3696 errno
= EHOSTUNREACH
;
3703 si
->defer_connect
= 0;
3706 errno
= EHOSTUNREACH
;
3710 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3711 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
3712 uint8_t *cmbuf
= NULL
;
3715 ret
= swrap_sendmsg_filter_cmsghdr(msg
, &cmbuf
, &cmlen
);
3722 msg
->msg_controllen
= 0;
3723 msg
->msg_control
= NULL
;
3724 } else if (cmlen
< msg
->msg_controllen
&& cmbuf
!= NULL
) {
3725 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
3726 msg
->msg_controllen
= cmlen
;
3735 static void swrap_sendmsg_after(int fd
,
3736 struct socket_info
*si
,
3738 const struct sockaddr
*to
,
3741 int saved_errno
= errno
;
3748 /* to give better errors */
3750 if (saved_errno
== ENOENT
) {
3751 saved_errno
= EHOSTUNREACH
;
3752 } else if (saved_errno
== ENOTSOCK
) {
3753 /* If the fd is not a socket, remove it */
3754 swrap_remove_stale(fd
);
3758 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3759 avail
+= msg
->msg_iov
[i
].iov_len
;
3763 remain
= MIN(80, avail
);
3768 /* we capture it as one single packet */
3769 buf
= (uint8_t *)malloc(remain
);
3771 /* we just not capture the packet */
3772 errno
= saved_errno
;
3776 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3777 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3779 msg
->msg_iov
[i
].iov_base
,
3782 remain
-= this_time
;
3789 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3790 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3792 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3797 if (si
->connected
) {
3801 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3802 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3804 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3810 errno
= saved_errno
;
3813 static int swrap_recvmsg_before(int fd
,
3814 struct socket_info
*si
,
3816 struct iovec
*tmp_iov
)
3821 (void)fd
; /* unused */
3825 if (!si
->connected
) {
3830 if (msg
->msg_iovlen
== 0) {
3834 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3836 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3837 if (nlen
> SOCKET_MAX_PACKET
) {
3841 msg
->msg_iovlen
= i
;
3842 if (msg
->msg_iovlen
== 0) {
3843 *tmp_iov
= msg
->msg_iov
[0];
3844 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3845 msg
->msg_iov
= tmp_iov
;
3846 msg
->msg_iovlen
= 1;
3851 if (msg
->msg_name
== NULL
) {
3856 if (msg
->msg_iovlen
== 0) {
3860 if (si
->bound
== 0) {
3861 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3864 * When attempting to read or write to a
3865 * descriptor, if an underlying autobind fails
3866 * because it's not a socket, stop intercepting
3867 * uses of that descriptor.
3869 if (errno
== ENOTSOCK
) {
3870 swrap_remove_stale(fd
);
3873 SWRAP_LOG(SWRAP_LOG_ERROR
,
3874 "swrap_recvmsg_before failed");
3881 errno
= EHOSTUNREACH
;
3888 static int swrap_recvmsg_after(int fd
,
3889 struct socket_info
*si
,
3891 const struct sockaddr_un
*un_addr
,
3892 socklen_t un_addrlen
,
3895 int saved_errno
= errno
;
3897 uint8_t *buf
= NULL
;
3903 /* to give better errors */
3905 if (saved_errno
== ENOENT
) {
3906 saved_errno
= EHOSTUNREACH
;
3907 } else if (saved_errno
== ENOTSOCK
) {
3908 /* If the fd is not a socket, remove it */
3909 swrap_remove_stale(fd
);
3913 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3914 avail
+= msg
->msg_iov
[i
].iov_len
;
3923 remain
= MIN(80, avail
);
3928 /* we capture it as one single packet */
3929 buf
= (uint8_t *)malloc(remain
);
3931 /* we just not capture the packet */
3932 errno
= saved_errno
;
3936 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3937 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3939 msg
->msg_iov
[i
].iov_base
,
3942 remain
-= this_time
;
3947 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
3948 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3949 } else if (ret
== 0) { /* END OF FILE */
3950 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3951 } else if (ret
> 0) {
3952 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
3961 if (un_addr
!= NULL
) {
3962 rc
= sockaddr_convert_from_un(si
,
3972 swrap_dump_packet(si
,
3978 swrap_dump_packet(si
,
3991 errno
= saved_errno
;
3993 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3995 msg
->msg_controllen
> 0 &&
3996 msg
->msg_control
!= NULL
) {
3997 rc
= swrap_msghdr_add_socket_info(si
, msg
);
4007 /****************************************************************************
4009 ***************************************************************************/
4011 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
4012 struct sockaddr
*from
, socklen_t
*fromlen
)
4014 struct sockaddr_un from_addr
;
4015 socklen_t from_addrlen
= sizeof(from_addr
);
4017 struct socket_info
*si
= find_socket_info(s
);
4018 struct sockaddr_storage ss
;
4019 socklen_t ss_len
= sizeof(ss
);
4025 return libc_recvfrom(s
,
4037 if (from
!= NULL
&& fromlen
!= NULL
) {
4038 msg
.msg_name
= from
; /* optional address */
4039 msg
.msg_namelen
= *fromlen
; /* size of address */
4041 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4042 msg
.msg_namelen
= ss_len
; /* size of address */
4044 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4045 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4046 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4047 msg
.msg_control
= NULL
; /* ancillary data, see below */
4048 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4049 msg
.msg_flags
= 0; /* flags on received message */
4052 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4057 buf
= msg
.msg_iov
[0].iov_base
;
4058 len
= msg
.msg_iov
[0].iov_len
;
4060 /* irix 6.4 forgets to null terminate the sun_path string :-( */
4061 memset(&from_addr
, 0, sizeof(from_addr
));
4062 ret
= libc_recvfrom(s
,
4066 (struct sockaddr
*)(void *)&from_addr
,
4072 tret
= swrap_recvmsg_after(s
,
4082 if (from
!= NULL
&& fromlen
!= NULL
) {
4083 *fromlen
= msg
.msg_namelen
;
4089 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4090 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4091 struct sockaddr
*from
, Psocklen_t fromlen
)
4093 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4094 struct sockaddr
*from
, socklen_t
*fromlen
)
4097 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
4100 /****************************************************************************
4102 ***************************************************************************/
4104 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
4105 const struct sockaddr
*to
, socklen_t tolen
)
4109 struct sockaddr_un un_addr
;
4110 const struct sockaddr_un
*to_un
= NULL
;
4113 struct socket_info
*si
= find_socket_info(s
);
4117 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
4120 tmp
.iov_base
= discard_const_p(char, buf
);
4124 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
4125 msg
.msg_namelen
= tolen
; /* size of address */
4126 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4127 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4128 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4129 msg
.msg_control
= NULL
; /* ancillary data, see below */
4130 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4131 msg
.msg_flags
= 0; /* flags on received message */
4134 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4139 buf
= msg
.msg_iov
[0].iov_base
;
4140 len
= msg
.msg_iov
[0].iov_len
;
4145 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4148 type
= SOCKET_TYPE_CHAR_UDP
;
4150 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4151 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4152 socket_wrapper_dir(), type
, iface
, prt
);
4153 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4155 /* ignore the any errors in broadcast sends */
4160 (struct sockaddr
*)(void *)&un_addr
,
4164 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4169 ret
= libc_sendto(s
,
4173 (struct sockaddr
*)msg
.msg_name
,
4176 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4181 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
4182 const struct sockaddr
*to
, socklen_t tolen
)
4184 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
4187 /****************************************************************************
4189 ***************************************************************************/
4191 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
4193 struct socket_info
*si
;
4195 struct sockaddr_storage ss
;
4196 socklen_t ss_len
= sizeof(ss
);
4201 si
= find_socket_info(s
);
4203 return libc_recv(s
, buf
, len
, flags
);
4210 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4211 msg
.msg_namelen
= ss_len
; /* size of address */
4212 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4213 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4214 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4215 msg
.msg_control
= NULL
; /* ancillary data, see below */
4216 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4217 msg
.msg_flags
= 0; /* flags on received message */
4220 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4225 buf
= msg
.msg_iov
[0].iov_base
;
4226 len
= msg
.msg_iov
[0].iov_len
;
4228 ret
= libc_recv(s
, buf
, len
, flags
);
4230 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4238 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
4240 return swrap_recv(s
, buf
, len
, flags
);
4243 /****************************************************************************
4245 ***************************************************************************/
4247 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
4249 struct socket_info
*si
;
4252 struct sockaddr_storage ss
;
4253 socklen_t ss_len
= sizeof(ss
);
4257 si
= find_socket_info(s
);
4259 return libc_read(s
, buf
, len
);
4266 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4267 msg
.msg_namelen
= ss_len
; /* size of address */
4268 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4269 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4270 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4271 msg
.msg_control
= NULL
; /* ancillary data, see below */
4272 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4273 msg
.msg_flags
= 0; /* flags on received message */
4276 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4278 if (tret
== -ENOTSOCK
) {
4279 return libc_read(s
, buf
, len
);
4284 buf
= msg
.msg_iov
[0].iov_base
;
4285 len
= msg
.msg_iov
[0].iov_len
;
4287 ret
= libc_read(s
, buf
, len
);
4289 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4297 ssize_t
read(int s
, void *buf
, size_t len
)
4299 return swrap_read(s
, buf
, len
);
4302 /****************************************************************************
4304 ***************************************************************************/
4306 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
4310 struct sockaddr_un un_addr
;
4313 struct socket_info
*si
= find_socket_info(s
);
4316 return libc_send(s
, buf
, len
, flags
);
4319 tmp
.iov_base
= discard_const_p(char, buf
);
4323 msg
.msg_name
= NULL
; /* optional address */
4324 msg
.msg_namelen
= 0; /* size of address */
4325 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4326 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4327 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4328 msg
.msg_control
= NULL
; /* ancillary data, see below */
4329 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4330 msg
.msg_flags
= 0; /* flags on received message */
4333 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4338 buf
= msg
.msg_iov
[0].iov_base
;
4339 len
= msg
.msg_iov
[0].iov_len
;
4341 ret
= libc_send(s
, buf
, len
, flags
);
4343 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4348 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
4350 return swrap_send(s
, buf
, len
, flags
);
4353 /****************************************************************************
4355 ***************************************************************************/
4357 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
4359 struct sockaddr_un from_addr
;
4360 socklen_t from_addrlen
= sizeof(from_addr
);
4361 struct socket_info
*si
;
4364 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4365 size_t msg_ctrllen_filled
;
4366 size_t msg_ctrllen_left
;
4372 si
= find_socket_info(s
);
4374 return libc_recvmsg(s
, omsg
, flags
);
4377 tmp
.iov_base
= NULL
;
4381 msg
.msg_name
= (struct sockaddr
*)&from_addr
; /* optional address */
4382 msg
.msg_namelen
= from_addrlen
; /* size of address */
4383 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4384 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4385 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4386 msg_ctrllen_filled
= 0;
4387 msg_ctrllen_left
= omsg
->msg_controllen
;
4389 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
4390 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4391 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4394 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4399 ret
= libc_recvmsg(s
, &msg
, flags
);
4401 msg
.msg_name
= omsg
->msg_name
;
4402 msg
.msg_namelen
= omsg
->msg_namelen
;
4404 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4405 msg_ctrllen_filled
+= msg
.msg_controllen
;
4406 msg_ctrllen_left
-= msg
.msg_controllen
;
4408 if (omsg
->msg_control
!= NULL
) {
4411 p
= omsg
->msg_control
;
4412 p
+= msg_ctrllen_filled
;
4414 msg
.msg_control
= p
;
4415 msg
.msg_controllen
= msg_ctrllen_left
;
4417 msg
.msg_control
= NULL
;
4418 msg
.msg_controllen
= 0;
4422 rc
= swrap_recvmsg_after(s
, si
, &msg
, &from_addr
, from_addrlen
, ret
);
4427 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4428 if (omsg
->msg_control
!= NULL
) {
4429 /* msg.msg_controllen = space left */
4430 msg_ctrllen_left
= msg
.msg_controllen
;
4431 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
4434 /* Update the original message length */
4435 omsg
->msg_controllen
= msg_ctrllen_filled
;
4436 omsg
->msg_flags
= msg
.msg_flags
;
4438 omsg
->msg_iovlen
= msg
.msg_iovlen
;
4443 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
4445 return swrap_recvmsg(sockfd
, msg
, flags
);
4448 /****************************************************************************
4450 ***************************************************************************/
4452 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4456 struct sockaddr_un un_addr
;
4457 const struct sockaddr_un
*to_un
= NULL
;
4458 const struct sockaddr
*to
= NULL
;
4461 struct socket_info
*si
= find_socket_info(s
);
4465 return libc_sendmsg(s
, omsg
, flags
);
4468 ZERO_STRUCT(un_addr
);
4470 tmp
.iov_base
= NULL
;
4474 msg
.msg_name
= omsg
->msg_name
; /* optional address */
4475 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
4476 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4477 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4478 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4479 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
4480 /* omsg is a const so use a local buffer for modifications */
4481 uint8_t cmbuf
[omsg
->msg_controllen
];
4483 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
4485 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
4486 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4488 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4491 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4499 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4507 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4508 avail
+= msg
.msg_iov
[i
].iov_len
;
4514 /* we capture it as one single packet */
4515 buf
= (uint8_t *)malloc(remain
);
4520 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4521 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4523 msg
.msg_iov
[i
].iov_base
,
4526 remain
-= this_time
;
4529 type
= SOCKET_TYPE_CHAR_UDP
;
4531 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4532 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4533 socket_wrapper_dir(), type
, iface
, prt
);
4534 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4536 msg
.msg_name
= &un_addr
; /* optional address */
4537 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4539 /* ignore the any errors in broadcast sends */
4540 libc_sendmsg(s
, &msg
, flags
);
4543 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4549 ret
= libc_sendmsg(s
, &msg
, flags
);
4551 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4556 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4558 return swrap_sendmsg(s
, omsg
, flags
);
4561 /****************************************************************************
4563 ***************************************************************************/
4565 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4567 struct socket_info
*si
;
4570 struct sockaddr_storage ss
;
4571 socklen_t ss_len
= sizeof(ss
);
4575 si
= find_socket_info(s
);
4577 return libc_readv(s
, vector
, count
);
4580 tmp
.iov_base
= NULL
;
4584 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4585 msg
.msg_namelen
= ss_len
; /* size of address */
4586 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4587 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4588 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4589 msg
.msg_control
= NULL
; /* ancillary data, see below */
4590 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4591 msg
.msg_flags
= 0; /* flags on received message */
4594 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4596 if (rc
== -ENOTSOCK
) {
4597 return libc_readv(s
, vector
, count
);
4602 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4604 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4612 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4614 return swrap_readv(s
, vector
, count
);
4617 /****************************************************************************
4619 ***************************************************************************/
4621 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4625 struct sockaddr_un un_addr
;
4628 struct socket_info
*si
= find_socket_info(s
);
4631 return libc_writev(s
, vector
, count
);
4634 tmp
.iov_base
= NULL
;
4638 msg
.msg_name
= NULL
; /* optional address */
4639 msg
.msg_namelen
= 0; /* size of address */
4640 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4641 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4642 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4643 msg
.msg_control
= NULL
; /* ancillary data, see below */
4644 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4645 msg
.msg_flags
= 0; /* flags on received message */
4648 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4650 if (rc
== -ENOTSOCK
) {
4651 return libc_readv(s
, vector
, count
);
4656 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4658 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4663 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4665 return swrap_writev(s
, vector
, count
);
4668 /****************************
4670 ***************************/
4672 static int swrap_close(int fd
)
4674 struct socket_info
*si
= find_socket_info(fd
);
4675 struct socket_info_fd
*fi
;
4679 return libc_close(fd
);
4682 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4684 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4691 /* there are still references left */
4692 return libc_close(fd
);
4695 SWRAP_DLIST_REMOVE(sockets
, si
);
4697 if (si
->myname
&& si
->peername
) {
4698 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4701 ret
= libc_close(fd
);
4703 if (si
->myname
&& si
->peername
) {
4704 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4705 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4708 if (si
->bindname
!= NULL
) {
4712 if (si
->myname
) free(si
->myname
);
4713 if (si
->peername
) free(si
->peername
);
4715 unlink(si
->tmp_path
);
4725 return swrap_close(fd
);
4728 /****************************
4730 ***************************/
4732 static int swrap_dup(int fd
)
4734 struct socket_info
*si
;
4735 struct socket_info_fd
*fi
;
4737 si
= find_socket_info(fd
);
4740 return libc_dup(fd
);
4743 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4749 fi
->fd
= libc_dup(fd
);
4751 int saved_errno
= errno
;
4753 errno
= saved_errno
;
4757 /* Make sure we don't have an entry for the fd */
4758 swrap_remove_stale(fi
->fd
);
4760 SWRAP_DLIST_ADD(si
->fds
, fi
);
4766 return swrap_dup(fd
);
4769 /****************************
4771 ***************************/
4773 static int swrap_dup2(int fd
, int newfd
)
4775 struct socket_info
*si
;
4776 struct socket_info_fd
*fi
;
4778 si
= find_socket_info(fd
);
4781 return libc_dup2(fd
, newfd
);
4784 if (find_socket_info(newfd
)) {
4785 /* dup2() does an implicit close of newfd, which we
4786 * need to emulate */
4790 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4796 fi
->fd
= libc_dup2(fd
, newfd
);
4798 int saved_errno
= errno
;
4800 errno
= saved_errno
;
4804 /* Make sure we don't have an entry for the fd */
4805 swrap_remove_stale(fi
->fd
);
4807 SWRAP_DLIST_ADD(si
->fds
, fi
);
4811 int dup2(int fd
, int newfd
)
4813 return swrap_dup2(fd
, newfd
);
4816 /****************************
4818 ***************************/
4821 static int swrap_eventfd(int count
, int flags
)
4825 fd
= libc_eventfd(count
, flags
);
4827 swrap_remove_stale(fd
);
4833 int eventfd(int count
, int flags
)
4835 return swrap_eventfd(count
, flags
);
4839 /****************************
4841 ***************************/
4844 * This function is called when the library is unloaded and makes sure that
4845 * sockets get closed and the unix file for the socket are unlinked.
4847 void swrap_destructor(void)
4849 struct socket_info
*s
= sockets
;
4852 struct socket_info_fd
*f
= s
->fds
;