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 void swrap_remove_stale(int fd
)
1272 struct socket_info
*si
= find_socket_info(fd
);
1273 struct socket_info_fd
*fi
;
1276 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1278 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1279 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1285 if (si
->fds
== NULL
) {
1286 SWRAP_DLIST_REMOVE(sockets
, si
);
1291 static int sockaddr_convert_to_un(struct socket_info
*si
,
1292 const struct sockaddr
*in_addr
,
1294 struct sockaddr_un
*out_addr
,
1298 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1300 (void) in_len
; /* unused */
1302 if (out_addr
== NULL
) {
1306 out
->sa_family
= AF_UNIX
;
1307 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1308 out
->sa_len
= sizeof(*out_addr
);
1311 switch (in_addr
->sa_family
) {
1313 struct sockaddr_in
*sin
;
1314 if (si
->family
!= AF_INET
) {
1317 if (in_len
< sizeof(struct sockaddr_in
)) {
1320 sin
= (struct sockaddr_in
*)in_addr
;
1321 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
1326 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1327 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1341 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1342 errno
= ESOCKTNOSUPPORT
;
1346 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1348 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1354 errno
= EAFNOSUPPORT
;
1355 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1359 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1360 const struct sockaddr_un
*in_addr
,
1361 socklen_t un_addrlen
,
1363 struct sockaddr
*out_addr
,
1364 socklen_t
*out_addrlen
)
1368 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1371 if (un_addrlen
== 0) {
1386 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1387 errno
= ESOCKTNOSUPPORT
;
1390 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1391 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1392 out_addr
->sa_len
= *out_addrlen
;
1399 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1400 errno
= EAFNOSUPPORT
;
1404 enum swrap_packet_type
{
1406 SWRAP_CONNECT_UNREACH
,
1414 SWRAP_SENDTO_UNREACH
,
1425 struct swrap_file_hdr
{
1427 uint16_t version_major
;
1428 uint16_t version_minor
;
1431 uint32_t frame_max_len
;
1432 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1435 #define SWRAP_FILE_HDR_SIZE 24
1437 struct swrap_packet_frame
{
1439 uint32_t micro_seconds
;
1440 uint32_t recorded_length
;
1441 uint32_t full_length
;
1443 #define SWRAP_PACKET_FRAME_SIZE 16
1445 union swrap_packet_ip
{
1449 uint16_t packet_length
;
1450 uint16_t identification
;
1455 uint16_t hdr_checksum
;
1459 #define SWRAP_PACKET_IP_V4_SIZE 20
1462 uint8_t flow_label_high
;
1463 uint16_t flow_label_low
;
1464 uint16_t payload_length
;
1465 uint8_t next_header
;
1467 uint8_t src_addr
[16];
1468 uint8_t dest_addr
[16];
1470 #define SWRAP_PACKET_IP_V6_SIZE 40
1472 #define SWRAP_PACKET_IP_SIZE 40
1474 union swrap_packet_payload
{
1476 uint16_t source_port
;
1486 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1488 uint16_t source_port
;
1493 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1500 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1507 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1509 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1511 #define SWRAP_PACKET_MIN_ALLOC \
1512 (SWRAP_PACKET_FRAME_SIZE + \
1513 SWRAP_PACKET_IP_SIZE + \
1514 SWRAP_PACKET_PAYLOAD_SIZE)
1516 static const char *socket_wrapper_pcap_file(void)
1518 static int initialized
= 0;
1519 static const char *s
= NULL
;
1520 static const struct swrap_file_hdr h
;
1521 static const struct swrap_packet_frame f
;
1522 static const union swrap_packet_ip i
;
1523 static const union swrap_packet_payload p
;
1525 if (initialized
== 1) {
1531 * TODO: don't use the structs use plain buffer offsets
1532 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1534 * for now make sure we disable PCAP support
1535 * if the struct has alignment!
1537 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1540 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1543 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1546 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1549 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1552 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1555 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1558 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1561 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1564 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1568 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1572 if (strncmp(s
, "./", 2) == 0) {
1578 static uint8_t *swrap_packet_init(struct timeval
*tval
,
1579 const struct sockaddr
*src
,
1580 const struct sockaddr
*dest
,
1582 const uint8_t *payload
,
1584 unsigned long tcp_seqno
,
1585 unsigned long tcp_ack
,
1586 unsigned char tcp_ctl
,
1588 size_t *_packet_len
)
1592 struct swrap_packet_frame
*frame
;
1593 union swrap_packet_ip
*ip
;
1594 union swrap_packet_payload
*pay
;
1597 size_t nonwire_len
= sizeof(*frame
);
1598 size_t wire_hdr_len
= 0;
1599 size_t wire_len
= 0;
1600 size_t ip_hdr_len
= 0;
1601 size_t icmp_hdr_len
= 0;
1602 size_t icmp_truncate_len
= 0;
1603 uint8_t protocol
= 0, icmp_protocol
= 0;
1604 const struct sockaddr_in
*src_in
= NULL
;
1605 const struct sockaddr_in
*dest_in
= NULL
;
1607 const struct sockaddr_in6
*src_in6
= NULL
;
1608 const struct sockaddr_in6
*dest_in6
= NULL
;
1613 switch (src
->sa_family
) {
1615 src_in
= (const struct sockaddr_in
*)src
;
1616 dest_in
= (const struct sockaddr_in
*)dest
;
1617 src_port
= src_in
->sin_port
;
1618 dest_port
= dest_in
->sin_port
;
1619 ip_hdr_len
= sizeof(ip
->v4
);
1623 src_in6
= (const struct sockaddr_in6
*)src
;
1624 dest_in6
= (const struct sockaddr_in6
*)dest
;
1625 src_port
= src_in6
->sin6_port
;
1626 dest_port
= dest_in6
->sin6_port
;
1627 ip_hdr_len
= sizeof(ip
->v6
);
1634 switch (socket_type
) {
1636 protocol
= 0x06; /* TCP */
1637 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1638 wire_len
= wire_hdr_len
+ payload_len
;
1642 protocol
= 0x11; /* UDP */
1643 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1644 wire_len
= wire_hdr_len
+ payload_len
;
1652 icmp_protocol
= protocol
;
1653 switch (src
->sa_family
) {
1655 protocol
= 0x01; /* ICMPv4 */
1656 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1660 protocol
= 0x3A; /* ICMPv6 */
1661 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1665 if (wire_len
> 64 ) {
1666 icmp_truncate_len
= wire_len
- 64;
1668 wire_hdr_len
+= icmp_hdr_len
;
1669 wire_len
+= icmp_hdr_len
;
1672 packet_len
= nonwire_len
+ wire_len
;
1673 alloc_len
= packet_len
;
1674 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1675 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1678 base
= (uint8_t *)malloc(alloc_len
);
1682 memset(base
, 0x0, alloc_len
);
1686 frame
= (struct swrap_packet_frame
*)buf
;
1687 frame
->seconds
= tval
->tv_sec
;
1688 frame
->micro_seconds
= tval
->tv_usec
;
1689 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1690 frame
->full_length
= wire_len
- icmp_truncate_len
;
1691 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1693 ip
= (union swrap_packet_ip
*)buf
;
1694 switch (src
->sa_family
) {
1696 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1698 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1699 ip
->v4
.identification
= htons(0xFFFF);
1700 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1701 ip
->v4
.fragment
= htons(0x0000);
1703 ip
->v4
.protocol
= protocol
;
1704 ip
->v4
.hdr_checksum
= htons(0x0000);
1705 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1706 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1707 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1711 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1712 ip
->v6
.flow_label_high
= 0x00;
1713 ip
->v6
.flow_label_low
= 0x0000;
1714 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1715 ip
->v6
.next_header
= protocol
;
1716 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1717 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1718 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1724 pay
= (union swrap_packet_payload
*)buf
;
1725 switch (src
->sa_family
) {
1727 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1728 pay
->icmp4
.code
= 0x01; /* host unreachable */
1729 pay
->icmp4
.checksum
= htons(0x0000);
1730 pay
->icmp4
.unused
= htonl(0x00000000);
1731 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1733 /* set the ip header in the ICMP payload */
1734 ip
= (union swrap_packet_ip
*)buf
;
1735 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1737 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1738 ip
->v4
.identification
= htons(0xFFFF);
1739 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1740 ip
->v4
.fragment
= htons(0x0000);
1742 ip
->v4
.protocol
= icmp_protocol
;
1743 ip
->v4
.hdr_checksum
= htons(0x0000);
1744 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1745 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1746 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1748 src_port
= dest_in
->sin_port
;
1749 dest_port
= src_in
->sin_port
;
1753 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1754 pay
->icmp6
.code
= 0x03; /* address unreachable */
1755 pay
->icmp6
.checksum
= htons(0x0000);
1756 pay
->icmp6
.unused
= htonl(0x00000000);
1757 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1759 /* set the ip header in the ICMP payload */
1760 ip
= (union swrap_packet_ip
*)buf
;
1761 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1762 ip
->v6
.flow_label_high
= 0x00;
1763 ip
->v6
.flow_label_low
= 0x0000;
1764 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1765 ip
->v6
.next_header
= protocol
;
1766 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1767 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1768 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1770 src_port
= dest_in6
->sin6_port
;
1771 dest_port
= src_in6
->sin6_port
;
1777 pay
= (union swrap_packet_payload
*)buf
;
1779 switch (socket_type
) {
1781 pay
->tcp
.source_port
= src_port
;
1782 pay
->tcp
.dest_port
= dest_port
;
1783 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1784 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1785 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1786 pay
->tcp
.control
= tcp_ctl
;
1787 pay
->tcp
.window
= htons(0x7FFF);
1788 pay
->tcp
.checksum
= htons(0x0000);
1789 pay
->tcp
.urg
= htons(0x0000);
1790 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1795 pay
->udp
.source_port
= src_port
;
1796 pay
->udp
.dest_port
= dest_port
;
1797 pay
->udp
.length
= htons(8 + payload_len
);
1798 pay
->udp
.checksum
= htons(0x0000);
1799 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1804 if (payload
&& payload_len
> 0) {
1805 memcpy(buf
, payload
, payload_len
);
1808 *_packet_len
= packet_len
- icmp_truncate_len
;
1812 static int swrap_get_pcap_fd(const char *fname
)
1816 if (fd
!= -1) return fd
;
1818 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1820 struct swrap_file_hdr file_hdr
;
1821 file_hdr
.magic
= 0xA1B2C3D4;
1822 file_hdr
.version_major
= 0x0002;
1823 file_hdr
.version_minor
= 0x0004;
1824 file_hdr
.timezone
= 0x00000000;
1825 file_hdr
.sigfigs
= 0x00000000;
1826 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1827 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1829 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1836 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1841 static uint8_t *swrap_marshall_packet(struct socket_info
*si
,
1842 const struct sockaddr
*addr
,
1843 enum swrap_packet_type type
,
1844 const void *buf
, size_t len
,
1847 const struct sockaddr
*src_addr
;
1848 const struct sockaddr
*dest_addr
;
1849 unsigned long tcp_seqno
= 0;
1850 unsigned long tcp_ack
= 0;
1851 unsigned char tcp_ctl
= 0;
1852 int unreachable
= 0;
1856 switch (si
->family
) {
1868 case SWRAP_CONNECT_SEND
:
1869 if (si
->type
!= SOCK_STREAM
) return NULL
;
1871 src_addr
= si
->myname
;
1874 tcp_seqno
= si
->io
.pck_snd
;
1875 tcp_ack
= si
->io
.pck_rcv
;
1876 tcp_ctl
= 0x02; /* SYN */
1878 si
->io
.pck_snd
+= 1;
1882 case SWRAP_CONNECT_RECV
:
1883 if (si
->type
!= SOCK_STREAM
) return NULL
;
1885 dest_addr
= si
->myname
;
1888 tcp_seqno
= si
->io
.pck_rcv
;
1889 tcp_ack
= si
->io
.pck_snd
;
1890 tcp_ctl
= 0x12; /** SYN,ACK */
1892 si
->io
.pck_rcv
+= 1;
1896 case SWRAP_CONNECT_UNREACH
:
1897 if (si
->type
!= SOCK_STREAM
) return NULL
;
1899 dest_addr
= si
->myname
;
1902 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1903 tcp_seqno
= si
->io
.pck_snd
- 1;
1904 tcp_ack
= si
->io
.pck_rcv
;
1905 tcp_ctl
= 0x02; /* SYN */
1910 case SWRAP_CONNECT_ACK
:
1911 if (si
->type
!= SOCK_STREAM
) return NULL
;
1913 src_addr
= si
->myname
;
1916 tcp_seqno
= si
->io
.pck_snd
;
1917 tcp_ack
= si
->io
.pck_rcv
;
1918 tcp_ctl
= 0x10; /* ACK */
1922 case SWRAP_ACCEPT_SEND
:
1923 if (si
->type
!= SOCK_STREAM
) return NULL
;
1925 dest_addr
= si
->myname
;
1928 tcp_seqno
= si
->io
.pck_rcv
;
1929 tcp_ack
= si
->io
.pck_snd
;
1930 tcp_ctl
= 0x02; /* SYN */
1932 si
->io
.pck_rcv
+= 1;
1936 case SWRAP_ACCEPT_RECV
:
1937 if (si
->type
!= SOCK_STREAM
) return NULL
;
1939 src_addr
= si
->myname
;
1942 tcp_seqno
= si
->io
.pck_snd
;
1943 tcp_ack
= si
->io
.pck_rcv
;
1944 tcp_ctl
= 0x12; /* SYN,ACK */
1946 si
->io
.pck_snd
+= 1;
1950 case SWRAP_ACCEPT_ACK
:
1951 if (si
->type
!= SOCK_STREAM
) return NULL
;
1953 dest_addr
= si
->myname
;
1956 tcp_seqno
= si
->io
.pck_rcv
;
1957 tcp_ack
= si
->io
.pck_snd
;
1958 tcp_ctl
= 0x10; /* ACK */
1963 src_addr
= si
->myname
;
1964 dest_addr
= si
->peername
;
1966 tcp_seqno
= si
->io
.pck_snd
;
1967 tcp_ack
= si
->io
.pck_rcv
;
1968 tcp_ctl
= 0x18; /* PSH,ACK */
1970 si
->io
.pck_snd
+= len
;
1974 case SWRAP_SEND_RST
:
1975 dest_addr
= si
->myname
;
1976 src_addr
= si
->peername
;
1978 if (si
->type
== SOCK_DGRAM
) {
1979 return swrap_marshall_packet(si
, si
->peername
,
1980 SWRAP_SENDTO_UNREACH
,
1981 buf
, len
, packet_len
);
1984 tcp_seqno
= si
->io
.pck_rcv
;
1985 tcp_ack
= si
->io
.pck_snd
;
1986 tcp_ctl
= 0x14; /** RST,ACK */
1990 case SWRAP_PENDING_RST
:
1991 dest_addr
= si
->myname
;
1992 src_addr
= si
->peername
;
1994 if (si
->type
== SOCK_DGRAM
) {
1998 tcp_seqno
= si
->io
.pck_rcv
;
1999 tcp_ack
= si
->io
.pck_snd
;
2000 tcp_ctl
= 0x14; /* RST,ACK */
2005 dest_addr
= si
->myname
;
2006 src_addr
= si
->peername
;
2008 tcp_seqno
= si
->io
.pck_rcv
;
2009 tcp_ack
= si
->io
.pck_snd
;
2010 tcp_ctl
= 0x18; /* PSH,ACK */
2012 si
->io
.pck_rcv
+= len
;
2016 case SWRAP_RECV_RST
:
2017 dest_addr
= si
->myname
;
2018 src_addr
= si
->peername
;
2020 if (si
->type
== SOCK_DGRAM
) {
2024 tcp_seqno
= si
->io
.pck_rcv
;
2025 tcp_ack
= si
->io
.pck_snd
;
2026 tcp_ctl
= 0x14; /* RST,ACK */
2031 src_addr
= si
->myname
;
2034 si
->io
.pck_snd
+= len
;
2038 case SWRAP_SENDTO_UNREACH
:
2039 dest_addr
= si
->myname
;
2046 case SWRAP_RECVFROM
:
2047 dest_addr
= si
->myname
;
2050 si
->io
.pck_rcv
+= len
;
2054 case SWRAP_CLOSE_SEND
:
2055 if (si
->type
!= SOCK_STREAM
) return NULL
;
2057 src_addr
= si
->myname
;
2058 dest_addr
= si
->peername
;
2060 tcp_seqno
= si
->io
.pck_snd
;
2061 tcp_ack
= si
->io
.pck_rcv
;
2062 tcp_ctl
= 0x11; /* FIN, ACK */
2064 si
->io
.pck_snd
+= 1;
2068 case SWRAP_CLOSE_RECV
:
2069 if (si
->type
!= SOCK_STREAM
) return NULL
;
2071 dest_addr
= si
->myname
;
2072 src_addr
= si
->peername
;
2074 tcp_seqno
= si
->io
.pck_rcv
;
2075 tcp_ack
= si
->io
.pck_snd
;
2076 tcp_ctl
= 0x11; /* FIN,ACK */
2078 si
->io
.pck_rcv
+= 1;
2082 case SWRAP_CLOSE_ACK
:
2083 if (si
->type
!= SOCK_STREAM
) return NULL
;
2085 src_addr
= si
->myname
;
2086 dest_addr
= si
->peername
;
2088 tcp_seqno
= si
->io
.pck_snd
;
2089 tcp_ack
= si
->io
.pck_rcv
;
2090 tcp_ctl
= 0x10; /* ACK */
2097 swrapGetTimeOfDay(&tv
);
2099 return swrap_packet_init(&tv
, src_addr
, dest_addr
, si
->type
,
2100 (const uint8_t *)buf
, len
,
2101 tcp_seqno
, tcp_ack
, tcp_ctl
, unreachable
,
2105 static void swrap_dump_packet(struct socket_info
*si
,
2106 const struct sockaddr
*addr
,
2107 enum swrap_packet_type type
,
2108 const void *buf
, size_t len
)
2110 const char *file_name
;
2112 size_t packet_len
= 0;
2115 file_name
= socket_wrapper_pcap_file();
2120 packet
= swrap_marshall_packet(si
, addr
, type
, buf
, len
, &packet_len
);
2125 fd
= swrap_get_pcap_fd(file_name
);
2127 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2136 /****************************************************************************
2138 ***************************************************************************/
2140 #ifdef HAVE_SIGNALFD
2141 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2145 rc
= libc_signalfd(fd
, mask
, flags
);
2147 swrap_remove_stale(fd
);
2153 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2155 return swrap_signalfd(fd
, mask
, flags
);
2159 /****************************************************************************
2161 ***************************************************************************/
2163 static int swrap_socket(int family
, int type
, int protocol
)
2165 struct socket_info
*si
;
2166 struct socket_info_fd
*fi
;
2168 int real_type
= type
;
2171 * Remove possible addition flags passed to socket() so
2172 * do not fail checking the type.
2173 * See https://lwn.net/Articles/281965/
2176 real_type
&= ~SOCK_CLOEXEC
;
2178 #ifdef SOCK_NONBLOCK
2179 real_type
&= ~SOCK_NONBLOCK
;
2182 if (!socket_wrapper_enabled()) {
2183 return libc_socket(family
, type
, protocol
);
2193 return libc_socket(family
, type
, protocol
);
2195 errno
= EAFNOSUPPORT
;
2199 switch (real_type
) {
2205 errno
= EPROTONOSUPPORT
;
2213 if (real_type
== SOCK_STREAM
) {
2218 if (real_type
== SOCK_DGRAM
) {
2223 errno
= EPROTONOSUPPORT
;
2228 * We must call libc_socket with type, from the caller, not the version
2229 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2231 fd
= libc_socket(AF_UNIX
, type
, 0);
2237 /* Check if we have a stale fd and remove it */
2238 si
= find_socket_info(fd
);
2240 swrap_remove_stale(fd
);
2243 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2244 memset(si
, 0, sizeof(struct socket_info
));
2250 si
->family
= family
;
2252 /* however, the rest of the socket_wrapper code expects just
2253 * the type, not the flags */
2254 si
->type
= real_type
;
2255 si
->protocol
= protocol
;
2258 * Setup myname so getsockname() can succeed to find out the socket
2261 switch(si
->family
) {
2263 struct sockaddr_in sin
= {
2264 .sin_family
= AF_INET
,
2267 si
->myname_len
= sizeof(struct sockaddr_in
);
2268 si
->myname
= sockaddr_dup(&sin
, si
->myname_len
);
2272 struct sockaddr_in6 sin6
= {
2273 .sin6_family
= AF_INET6
,
2276 si
->myname_len
= sizeof(struct sockaddr_in6
);
2277 si
->myname
= sockaddr_dup(&sin6
, si
->myname_len
);
2286 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2288 if (si
->myname
!= NULL
) {
2298 SWRAP_DLIST_ADD(si
->fds
, fi
);
2299 SWRAP_DLIST_ADD(sockets
, si
);
2304 int socket(int family
, int type
, int protocol
)
2306 return swrap_socket(family
, type
, protocol
);
2309 /****************************************************************************
2311 ***************************************************************************/
2313 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2317 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2319 swrap_remove_stale(sv
[0]);
2320 swrap_remove_stale(sv
[1]);
2326 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2328 return swrap_socketpair(family
, type
, protocol
, sv
);
2331 /****************************************************************************
2333 ***************************************************************************/
2335 #ifdef HAVE_TIMERFD_CREATE
2336 static int swrap_timerfd_create(int clockid
, int flags
)
2340 fd
= libc_timerfd_create(clockid
, flags
);
2342 swrap_remove_stale(fd
);
2348 int timerfd_create(int clockid
, int flags
)
2350 return swrap_timerfd_create(clockid
, flags
);
2354 /****************************************************************************
2356 ***************************************************************************/
2358 static int swrap_pipe(int pipefd
[2])
2362 rc
= libc_pipe(pipefd
);
2364 swrap_remove_stale(pipefd
[0]);
2365 swrap_remove_stale(pipefd
[1]);
2371 int pipe(int pipefd
[2])
2373 return swrap_pipe(pipefd
);
2376 /****************************************************************************
2378 ***************************************************************************/
2380 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2382 struct socket_info
*parent_si
, *child_si
;
2383 struct socket_info_fd
*child_fi
;
2385 struct sockaddr_un un_addr
;
2386 socklen_t un_addrlen
= sizeof(un_addr
);
2387 struct sockaddr_un un_my_addr
;
2388 socklen_t un_my_addrlen
= sizeof(un_my_addr
);
2389 struct sockaddr
*my_addr
;
2390 socklen_t my_addrlen
, len
;
2393 parent_si
= find_socket_info(s
);
2395 return libc_accept(s
, addr
, addrlen
);
2399 * assume out sockaddr have the same size as the in parent
2402 my_addrlen
= socket_length(parent_si
->family
);
2403 if (my_addrlen
<= 0) {
2408 my_addr
= (struct sockaddr
*)malloc(my_addrlen
);
2409 if (my_addr
== NULL
) {
2413 memset(&un_addr
, 0, sizeof(un_addr
));
2414 memset(&un_my_addr
, 0, sizeof(un_my_addr
));
2416 ret
= libc_accept(s
, (struct sockaddr
*)(void *)&un_addr
, &un_addrlen
);
2418 if (errno
== ENOTSOCK
) {
2419 /* Remove stale fds */
2420 swrap_remove_stale(s
);
2429 ret
= sockaddr_convert_from_un(parent_si
, &un_addr
, un_addrlen
,
2430 parent_si
->family
, my_addr
, &len
);
2437 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2438 memset(child_si
, 0, sizeof(struct socket_info
));
2440 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2441 if (child_fi
== NULL
) {
2451 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2453 child_si
->family
= parent_si
->family
;
2454 child_si
->type
= parent_si
->type
;
2455 child_si
->protocol
= parent_si
->protocol
;
2456 child_si
->bound
= 1;
2457 child_si
->is_server
= 1;
2458 child_si
->connected
= 1;
2460 child_si
->peername_len
= len
;
2461 child_si
->peername
= sockaddr_dup(my_addr
, len
);
2463 if (addr
!= NULL
&& addrlen
!= NULL
) {
2464 size_t copy_len
= MIN(*addrlen
, len
);
2466 memcpy(addr
, my_addr
, copy_len
);
2471 ret
= libc_getsockname(fd
,
2472 (struct sockaddr
*)(void *)&un_my_addr
,
2483 ret
= sockaddr_convert_from_un(child_si
, &un_my_addr
, un_my_addrlen
,
2484 child_si
->family
, my_addr
, &len
);
2493 SWRAP_LOG(SWRAP_LOG_TRACE
,
2494 "accept() path=%s, fd=%d",
2495 un_my_addr
.sun_path
, s
);
2497 child_si
->myname_len
= len
;
2498 child_si
->myname
= sockaddr_dup(my_addr
, len
);
2501 SWRAP_DLIST_ADD(sockets
, child_si
);
2504 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2505 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2506 swrap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2512 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2513 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2515 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2518 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2521 static int autobind_start_init
;
2522 static int autobind_start
;
2524 /* using sendto() or connect() on an unbound socket would give the
2525 recipient no way to reply, as unlike UDP and TCP, a unix domain
2526 socket can't auto-assign ephemeral port numbers, so we need to
2528 Note: this might change the family from ipv6 to ipv4
2530 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2532 struct sockaddr_un un_addr
;
2539 if (autobind_start_init
!= 1) {
2540 autobind_start_init
= 1;
2541 autobind_start
= getpid();
2542 autobind_start
%= 50000;
2543 autobind_start
+= 10000;
2546 un_addr
.sun_family
= AF_UNIX
;
2550 struct sockaddr_in in
;
2554 type
= SOCKET_TYPE_CHAR_TCP
;
2557 type
= SOCKET_TYPE_CHAR_UDP
;
2560 errno
= ESOCKTNOSUPPORT
;
2564 memset(&in
, 0, sizeof(in
));
2565 in
.sin_family
= AF_INET
;
2566 in
.sin_addr
.s_addr
= htonl(127<<24 |
2567 socket_wrapper_default_iface());
2570 si
->myname_len
= sizeof(in
);
2571 si
->myname
= sockaddr_dup(&in
, si
->myname_len
);
2576 struct sockaddr_in6 in6
;
2578 if (si
->family
!= family
) {
2579 errno
= ENETUNREACH
;
2585 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2588 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2591 errno
= ESOCKTNOSUPPORT
;
2595 memset(&in6
, 0, sizeof(in6
));
2596 in6
.sin6_family
= AF_INET6
;
2597 in6
.sin6_addr
= *swrap_ipv6();
2598 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2600 si
->myname_len
= sizeof(in6
);
2601 si
->myname
= sockaddr_dup(&in6
, si
->myname_len
);
2606 errno
= ESOCKTNOSUPPORT
;
2610 if (autobind_start
> 60000) {
2611 autobind_start
= 10000;
2614 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2615 port
= autobind_start
+ i
;
2616 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
),
2617 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2618 type
, socket_wrapper_default_iface(), port
);
2619 if (stat(un_addr
.sun_path
, &st
) == 0) continue;
2621 ret
= libc_bind(fd
, (struct sockaddr
*)(void *)&un_addr
,
2623 if (ret
== -1) return ret
;
2625 si
->tmp_path
= strdup(un_addr
.sun_path
);
2627 autobind_start
= port
+ 1;
2630 if (i
== SOCKET_MAX_SOCKETS
) {
2631 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2632 "interface "SOCKET_FORMAT
,
2635 socket_wrapper_default_iface(),
2641 si
->family
= family
;
2642 set_port(si
->family
, port
, si
->myname
);
2647 /****************************************************************************
2649 ***************************************************************************/
2651 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2655 struct sockaddr_un un_addr
;
2656 struct socket_info
*si
= find_socket_info(s
);
2660 return libc_connect(s
, serv_addr
, addrlen
);
2663 if (si
->bound
== 0) {
2664 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2665 if (ret
== -1) return -1;
2668 if (si
->family
!= serv_addr
->sa_family
) {
2673 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2674 addrlen
, &un_addr
, 0, &bcast
);
2675 if (ret
== -1) return -1;
2678 errno
= ENETUNREACH
;
2682 if (si
->type
== SOCK_DGRAM
) {
2683 si
->defer_connect
= 1;
2686 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2688 ret
= libc_connect(s
,
2689 (struct sockaddr
*)(void *)&un_addr
,
2690 sizeof(struct sockaddr_un
));
2693 SWRAP_LOG(SWRAP_LOG_TRACE
,
2694 "connect() path=%s, fd=%d",
2695 un_addr
.sun_path
, s
);
2698 /* to give better errors */
2699 if (ret
== -1 && errno
== ENOENT
) {
2700 errno
= EHOSTUNREACH
;
2704 si
->peername_len
= addrlen
;
2705 si
->peername
= sockaddr_dup(serv_addr
, addrlen
);
2709 * When we connect() on a socket than we have to bind the
2710 * outgoing connection on the interface we use for the
2711 * transport. We already bound it on the right interface
2712 * but here we have to update the name so getsockname()
2713 * returns correct information.
2715 if (si
->bindname
!= NULL
) {
2718 si
->myname
= si
->bindname
;
2719 si
->myname_len
= si
->bindname_len
;
2721 si
->bindname
= NULL
;
2722 si
->bindname_len
= 0;
2725 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2726 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2728 swrap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2734 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2736 return swrap_connect(s
, serv_addr
, addrlen
);
2739 /****************************************************************************
2741 ***************************************************************************/
2743 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2746 struct sockaddr_un un_addr
;
2747 struct socket_info
*si
= find_socket_info(s
);
2751 return libc_bind(s
, myaddr
, addrlen
);
2754 switch (si
->family
) {
2756 const struct sockaddr_in
*sin
;
2757 if (addrlen
< sizeof(struct sockaddr_in
)) {
2758 bind_error
= EINVAL
;
2762 sin
= (struct sockaddr_in
*)myaddr
;
2764 if (sin
->sin_family
!= AF_INET
) {
2765 bind_error
= EAFNOSUPPORT
;
2768 /* special case for AF_UNSPEC */
2769 if (sin
->sin_family
== AF_UNSPEC
&&
2770 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
2779 const struct sockaddr_in6
*sin6
;
2780 if (addrlen
< sizeof(struct sockaddr_in6
)) {
2781 bind_error
= EINVAL
;
2785 sin6
= (struct sockaddr_in6
*)myaddr
;
2787 if (sin6
->sin6_family
!= AF_INET6
) {
2788 bind_error
= EAFNOSUPPORT
;
2795 bind_error
= EINVAL
;
2799 if (bind_error
!= 0) {
2805 si
->myname_len
= addrlen
;
2806 si
->myname
= sockaddr_dup(myaddr
, addrlen
);
2808 ret
= sockaddr_convert_to_un(si
, myaddr
, addrlen
, &un_addr
, 1, &si
->bcast
);
2809 if (ret
== -1) return -1;
2811 unlink(un_addr
.sun_path
);
2813 ret
= libc_bind(s
, (struct sockaddr
*)(void *)&un_addr
,
2814 sizeof(struct sockaddr_un
));
2816 SWRAP_LOG(SWRAP_LOG_TRACE
,
2817 "bind() path=%s, fd=%d",
2818 un_addr
.sun_path
, s
);
2827 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2829 return swrap_bind(s
, myaddr
, addrlen
);
2832 /****************************************************************************
2834 ***************************************************************************/
2836 #ifdef HAVE_BINDRESVPORT
2837 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
2839 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
2841 struct sockaddr_storage myaddr
;
2843 static uint16_t port
;
2848 #define SWRAP_STARTPORT 600
2849 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2850 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2853 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
2857 salen
= sizeof(struct sockaddr
);
2858 sa
= (struct sockaddr
*)&myaddr
;
2860 rc
= swrap_getsockname(sd
, (struct sockaddr
*)&myaddr
, &salen
);
2866 memset(&myaddr
, 0, salen
);
2871 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
2874 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)sa
;
2876 salen
= sizeof(struct sockaddr_in
);
2877 sinp
->sin_port
= htons(port
);
2881 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)sa
;
2883 salen
= sizeof(struct sockaddr_in6
);
2884 sin6p
->sin6_port
= htons(port
);
2888 errno
= EAFNOSUPPORT
;
2893 if (port
> SWRAP_ENDPORT
) {
2894 port
= SWRAP_STARTPORT
;
2897 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
2898 if (rc
== 0 || errno
!= EADDRINUSE
) {
2906 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
2908 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
2912 /****************************************************************************
2914 ***************************************************************************/
2916 static int swrap_listen(int s
, int backlog
)
2919 struct socket_info
*si
= find_socket_info(s
);
2922 return libc_listen(s
, backlog
);
2925 ret
= libc_listen(s
, backlog
);
2930 int listen(int s
, int backlog
)
2932 return swrap_listen(s
, backlog
);
2935 /****************************************************************************
2937 ***************************************************************************/
2939 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
2943 ret
= libc_vopen(pathname
, flags
, ap
);
2946 * There are methods for closing descriptors (libc-internal code
2947 * paths, direct syscalls) which close descriptors in ways that
2948 * we can't intercept, so try to recover when we notice that
2951 swrap_remove_stale(ret
);
2956 int open(const char *pathname
, int flags
, ...)
2961 va_start(ap
, flags
);
2962 fd
= swrap_vopen(pathname
, flags
, ap
);
2968 /****************************************************************************
2970 ***************************************************************************/
2972 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
2974 struct socket_info
*si
= find_socket_info(s
);
2978 return libc_getpeername(s
, name
, addrlen
);
2987 len
= MIN(*addrlen
, si
->peername_len
);
2992 memcpy(name
, si
->peername
, len
);
2993 *addrlen
= si
->peername_len
;
2998 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2999 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3001 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3004 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
3007 /****************************************************************************
3009 ***************************************************************************/
3011 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3013 struct socket_info
*si
= find_socket_info(s
);
3017 return libc_getsockname(s
, name
, addrlen
);
3020 len
= MIN(*addrlen
, si
->myname_len
);
3025 memcpy(name
, si
->myname
, len
);
3026 *addrlen
= si
->myname_len
;
3031 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3032 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3034 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3037 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
3040 /****************************************************************************
3042 ***************************************************************************/
3045 # ifdef SO_PROTOTYPE /* The Solaris name */
3046 # define SO_PROTOCOL SO_PROTOTYPE
3047 # endif /* SO_PROTOTYPE */
3048 #endif /* SO_PROTOCOL */
3050 static int swrap_getsockopt(int s
, int level
, int optname
,
3051 void *optval
, socklen_t
*optlen
)
3053 struct socket_info
*si
= find_socket_info(s
);
3056 return libc_getsockopt(s
,
3063 if (level
== SOL_SOCKET
) {
3067 if (optval
== NULL
|| optlen
== NULL
||
3068 *optlen
< (socklen_t
)sizeof(int)) {
3073 *optlen
= sizeof(int);
3074 *(int *)optval
= si
->family
;
3076 #endif /* SO_DOMAIN */
3078 if (optval
== NULL
|| optlen
== NULL
||
3079 *optlen
< (socklen_t
)sizeof(int)) {
3084 *optlen
= sizeof(int);
3085 *(int *)optval
= si
->protocol
;
3088 if (optval
== NULL
|| optlen
== NULL
||
3089 *optlen
< (socklen_t
)sizeof(int)) {
3094 *optlen
= sizeof(int);
3095 *(int *)optval
= si
->type
;
3098 return libc_getsockopt(s
,
3106 errno
= ENOPROTOOPT
;
3110 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3111 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
3113 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
3116 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
3119 /****************************************************************************
3121 ***************************************************************************/
3123 static int swrap_setsockopt(int s
, int level
, int optname
,
3124 const void *optval
, socklen_t optlen
)
3126 struct socket_info
*si
= find_socket_info(s
);
3129 return libc_setsockopt(s
,
3136 if (level
== SOL_SOCKET
) {
3137 return libc_setsockopt(s
,
3144 switch (si
->family
) {
3146 if (level
== IPPROTO_IP
) {
3148 if (optname
== IP_PKTINFO
) {
3149 si
->pktinfo
= AF_INET
;
3151 #endif /* IP_PKTINFO */
3156 if (level
== IPPROTO_IPV6
) {
3157 #ifdef IPV6_RECVPKTINFO
3158 if (optname
== IPV6_RECVPKTINFO
) {
3159 si
->pktinfo
= AF_INET6
;
3161 #endif /* IPV6_PKTINFO */
3166 errno
= ENOPROTOOPT
;
3171 int setsockopt(int s
, int level
, int optname
,
3172 const void *optval
, socklen_t optlen
)
3174 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
3177 /****************************************************************************
3179 ***************************************************************************/
3181 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
3183 struct socket_info
*si
= find_socket_info(s
);
3189 return libc_vioctl(s
, r
, va
);
3194 rc
= libc_vioctl(s
, r
, va
);
3198 value
= *((int *)va_arg(ap
, int *));
3200 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
3201 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3202 } else if (value
== 0) { /* END OF FILE */
3203 swrap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3213 #ifdef HAVE_IOCTL_INT
3214 int ioctl(int s
, int r
, ...)
3216 int ioctl(int s
, unsigned long int r
, ...)
3224 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
3235 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3238 # ifdef _ALIGN /* BSD */
3239 #define CMSG_ALIGN _ALIGN
3241 #error NO_CMSG_ALIGN
3242 # endif /* _ALIGN */
3243 #endif /* CMSG_ALIGN */
3246 * @brief Add a cmsghdr to a msghdr.
3248 * This is an function to add any type of cmsghdr. It will operate on the
3249 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3250 * the buffer position after the added cmsg element. Hence, this function is
3251 * intended to be used with an intermediate msghdr and not on the original
3252 * one handed in by the client.
3254 * @param[in] msg The msghdr to which to add the cmsg.
3256 * @param[in] level The cmsg level to set.
3258 * @param[in] type The cmsg type to set.
3260 * @param[in] data The cmsg data to set.
3262 * @param[in] len the length of the data to set.
3264 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3270 size_t cmlen
= CMSG_LEN(len
);
3271 size_t cmspace
= CMSG_SPACE(len
);
3272 uint8_t cmbuf
[cmspace
];
3273 struct cmsghdr
*cm
= (struct cmsghdr
*)cmbuf
;
3276 memset(cmbuf
, 0, cmspace
);
3278 if (msg
->msg_controllen
< cmlen
) {
3279 cmlen
= msg
->msg_controllen
;
3280 msg
->msg_flags
|= MSG_CTRUNC
;
3283 if (msg
->msg_controllen
< cmspace
) {
3284 cmspace
= msg
->msg_controllen
;
3288 * We copy the full input data into an intermediate cmsghdr first
3289 * in order to more easily cope with truncation.
3291 cm
->cmsg_len
= cmlen
;
3292 cm
->cmsg_level
= level
;
3293 cm
->cmsg_type
= type
;
3294 memcpy(CMSG_DATA(cm
), data
, len
);
3297 * We now copy the possibly truncated buffer.
3298 * We copy cmlen bytes, but consume cmspace bytes,
3299 * leaving the possible padding uninitialiazed.
3301 p
= (uint8_t *)msg
->msg_control
;
3302 memcpy(p
, cm
, cmlen
);
3304 msg
->msg_control
= p
;
3305 msg
->msg_controllen
-= cmspace
;
3310 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3313 /* Add packet info */
3314 switch (si
->pktinfo
) {
3315 #if defined(IP_PKTINFO)
3316 /* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
3318 struct sockaddr_in
*sin
;
3319 #if defined(HAVE_STRUCT_IN_PKTINFO)
3320 struct in_pktinfo pkt
;
3321 #elif defined(IP_RECVDSTADDR)
3325 if (si
->bindname_len
== sizeof(struct sockaddr_in
)) {
3326 sin
= (struct sockaddr_in
*)si
->bindname
;
3328 if (si
->myname_len
!= sizeof(struct sockaddr_in
)) {
3331 sin
= (struct sockaddr_in
*)si
->myname
;
3336 #if defined(HAVE_STRUCT_IN_PKTINFO)
3337 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3338 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3339 #elif defined(IP_RECVDSTADDR)
3340 pkt
= sin
->sin_addr
;
3343 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3348 #endif /* IP_PKTINFO */
3349 #if defined(HAVE_IPV6)
3351 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3352 struct sockaddr_in6
*sin6
;
3353 struct in6_pktinfo pkt6
;
3355 if (si
->bindname_len
== sizeof(struct sockaddr_in6
)) {
3356 sin6
= (struct sockaddr_in6
*)si
->bindname
;
3358 if (si
->myname_len
!= sizeof(struct sockaddr_in6
)) {
3361 sin6
= (struct sockaddr_in6
*)si
->myname
;
3366 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3367 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3369 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3370 &pkt6
, sizeof(pkt6
));
3371 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3375 #endif /* IPV6_PKTINFO */
3383 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3384 struct msghdr
*omsg
)
3388 if (si
->pktinfo
> 0) {
3389 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3395 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3397 size_t *cm_data_space
);
3398 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3400 size_t *cm_data_space
);
3402 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
3404 size_t *cm_data_space
) {
3405 struct cmsghdr
*cmsg
;
3409 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
3413 for (cmsg
= CMSG_FIRSTHDR(msg
);
3415 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
3416 switch (cmsg
->cmsg_level
) {
3418 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
3423 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
3433 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3435 size_t *cm_data_space
)
3442 CMSG_SPACE(cmsg
->cmsg_len
- CMSG_ALIGN(sizeof(struct cmsghdr
)));
3444 p
= realloc((*cm_data
), cmspace
);
3450 p
= (*cm_data
) + (*cm_data_space
);
3451 *cm_data_space
= cmspace
;
3453 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
3458 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3460 size_t *cm_data_space
);
3463 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3465 size_t *cm_data_space
)
3469 switch(cmsg
->cmsg_type
) {
3472 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3479 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3491 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3493 size_t *cm_data_space
)
3495 (void)cmsg
; /* unused */
3496 (void)cm_data
; /* unused */
3497 (void)cm_data_space
; /* unused */
3500 * Passing a IP pktinfo to a unix socket might be rejected by the
3501 * Kernel, at least on FreeBSD. So skip this cmsg.
3505 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3507 static ssize_t
swrap_sendmsg_before(int fd
,
3508 struct socket_info
*si
,
3510 struct iovec
*tmp_iov
,
3511 struct sockaddr_un
*tmp_un
,
3512 const struct sockaddr_un
**to_un
,
3513 const struct sockaddr
**to
,
3531 if (!si
->connected
) {
3536 if (msg
->msg_iovlen
== 0) {
3540 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3542 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3543 if (nlen
> SOCKET_MAX_PACKET
) {
3547 msg
->msg_iovlen
= i
;
3548 if (msg
->msg_iovlen
== 0) {
3549 *tmp_iov
= msg
->msg_iov
[0];
3550 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3551 msg
->msg_iov
= tmp_iov
;
3552 msg
->msg_iovlen
= 1;
3557 if (si
->connected
) {
3558 if (msg
->msg_name
) {
3563 const struct sockaddr
*msg_name
;
3564 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3566 if (msg_name
== NULL
) {
3572 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3574 if (ret
== -1) return -1;
3582 msg
->msg_name
= tmp_un
;
3583 msg
->msg_namelen
= sizeof(*tmp_un
);
3586 if (si
->bound
== 0) {
3587 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3589 if (errno
== ENOTSOCK
) {
3590 swrap_remove_stale(fd
);
3593 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3599 if (!si
->defer_connect
) {
3603 ret
= sockaddr_convert_to_un(si
, si
->peername
, si
->peername_len
,
3605 if (ret
== -1) return -1;
3607 ret
= libc_connect(fd
,
3608 (struct sockaddr
*)(void *)tmp_un
,
3611 /* to give better errors */
3612 if (ret
== -1 && errno
== ENOENT
) {
3613 errno
= EHOSTUNREACH
;
3620 si
->defer_connect
= 0;
3623 errno
= EHOSTUNREACH
;
3627 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3628 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
3629 uint8_t *cmbuf
= NULL
;
3632 ret
= swrap_sendmsg_filter_cmsghdr(msg
, &cmbuf
, &cmlen
);
3639 msg
->msg_controllen
= 0;
3640 msg
->msg_control
= NULL
;
3641 } else if (cmlen
< msg
->msg_controllen
&& cmbuf
!= NULL
) {
3642 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
3643 msg
->msg_controllen
= cmlen
;
3652 static void swrap_sendmsg_after(int fd
,
3653 struct socket_info
*si
,
3655 const struct sockaddr
*to
,
3658 int saved_errno
= errno
;
3665 /* to give better errors */
3667 if (saved_errno
== ENOENT
) {
3668 saved_errno
= EHOSTUNREACH
;
3669 } else if (saved_errno
== ENOTSOCK
) {
3670 /* If the fd is not a socket, remove it */
3671 swrap_remove_stale(fd
);
3675 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3676 avail
+= msg
->msg_iov
[i
].iov_len
;
3680 remain
= MIN(80, avail
);
3685 /* we capture it as one single packet */
3686 buf
= (uint8_t *)malloc(remain
);
3688 /* we just not capture the packet */
3689 errno
= saved_errno
;
3693 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3694 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3696 msg
->msg_iov
[i
].iov_base
,
3699 remain
-= this_time
;
3706 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3707 swrap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3709 swrap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3714 if (si
->connected
) {
3718 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3719 swrap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3721 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3727 errno
= saved_errno
;
3730 static int swrap_recvmsg_before(int fd
,
3731 struct socket_info
*si
,
3733 struct iovec
*tmp_iov
)
3738 (void)fd
; /* unused */
3742 if (!si
->connected
) {
3747 if (msg
->msg_iovlen
== 0) {
3751 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3753 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3754 if (nlen
> SOCKET_MAX_PACKET
) {
3758 msg
->msg_iovlen
= i
;
3759 if (msg
->msg_iovlen
== 0) {
3760 *tmp_iov
= msg
->msg_iov
[0];
3761 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3762 msg
->msg_iov
= tmp_iov
;
3763 msg
->msg_iovlen
= 1;
3768 if (msg
->msg_name
== NULL
) {
3773 if (msg
->msg_iovlen
== 0) {
3777 if (si
->bound
== 0) {
3778 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3781 * When attempting to read or write to a
3782 * descriptor, if an underlying autobind fails
3783 * because it's not a socket, stop intercepting
3784 * uses of that descriptor.
3786 if (errno
== ENOTSOCK
) {
3787 swrap_remove_stale(fd
);
3790 SWRAP_LOG(SWRAP_LOG_ERROR
,
3791 "swrap_recvmsg_before failed");
3798 errno
= EHOSTUNREACH
;
3805 static int swrap_recvmsg_after(int fd
,
3806 struct socket_info
*si
,
3808 const struct sockaddr_un
*un_addr
,
3809 socklen_t un_addrlen
,
3812 int saved_errno
= errno
;
3814 uint8_t *buf
= NULL
;
3820 /* to give better errors */
3822 if (saved_errno
== ENOENT
) {
3823 saved_errno
= EHOSTUNREACH
;
3824 } else if (saved_errno
== ENOTSOCK
) {
3825 /* If the fd is not a socket, remove it */
3826 swrap_remove_stale(fd
);
3830 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3831 avail
+= msg
->msg_iov
[i
].iov_len
;
3840 remain
= MIN(80, avail
);
3845 /* we capture it as one single packet */
3846 buf
= (uint8_t *)malloc(remain
);
3848 /* we just not capture the packet */
3849 errno
= saved_errno
;
3853 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3854 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3856 msg
->msg_iov
[i
].iov_base
,
3859 remain
-= this_time
;
3864 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
3865 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3866 } else if (ret
== 0) { /* END OF FILE */
3867 swrap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
3868 } else if (ret
> 0) {
3869 swrap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
3878 if (un_addr
!= NULL
) {
3879 rc
= sockaddr_convert_from_un(si
,
3889 swrap_dump_packet(si
,
3895 swrap_dump_packet(si
,
3908 errno
= saved_errno
;
3910 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3912 msg
->msg_controllen
> 0 &&
3913 msg
->msg_control
!= NULL
) {
3914 rc
= swrap_msghdr_add_socket_info(si
, msg
);
3924 /****************************************************************************
3926 ***************************************************************************/
3928 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
3929 struct sockaddr
*from
, socklen_t
*fromlen
)
3931 struct sockaddr_un from_addr
;
3932 socklen_t from_addrlen
= sizeof(from_addr
);
3934 struct socket_info
*si
= find_socket_info(s
);
3935 struct sockaddr_storage ss
;
3936 socklen_t ss_len
= sizeof(ss
);
3942 return libc_recvfrom(s
,
3954 if (from
!= NULL
&& fromlen
!= NULL
) {
3955 msg
.msg_name
= from
; /* optional address */
3956 msg
.msg_namelen
= *fromlen
; /* size of address */
3958 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
3959 msg
.msg_namelen
= ss_len
; /* size of address */
3961 msg
.msg_iov
= &tmp
; /* scatter/gather array */
3962 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
3963 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3964 msg
.msg_control
= NULL
; /* ancillary data, see below */
3965 msg
.msg_controllen
= 0; /* ancillary data buffer len */
3966 msg
.msg_flags
= 0; /* flags on received message */
3969 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
3974 buf
= msg
.msg_iov
[0].iov_base
;
3975 len
= msg
.msg_iov
[0].iov_len
;
3977 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3978 memset(&from_addr
, 0, sizeof(from_addr
));
3979 ret
= libc_recvfrom(s
,
3983 (struct sockaddr
*)(void *)&from_addr
,
3989 tret
= swrap_recvmsg_after(s
,
3999 if (from
!= NULL
&& fromlen
!= NULL
) {
4000 *fromlen
= msg
.msg_namelen
;
4006 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4007 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4008 struct sockaddr
*from
, Psocklen_t fromlen
)
4010 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4011 struct sockaddr
*from
, socklen_t
*fromlen
)
4014 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
4017 /****************************************************************************
4019 ***************************************************************************/
4021 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
4022 const struct sockaddr
*to
, socklen_t tolen
)
4026 struct sockaddr_un un_addr
;
4027 const struct sockaddr_un
*to_un
= NULL
;
4030 struct socket_info
*si
= find_socket_info(s
);
4034 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
4037 tmp
.iov_base
= discard_const_p(char, buf
);
4041 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
4042 msg
.msg_namelen
= tolen
; /* size of address */
4043 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4044 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4045 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4046 msg
.msg_control
= NULL
; /* ancillary data, see below */
4047 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4048 msg
.msg_flags
= 0; /* flags on received message */
4051 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4056 buf
= msg
.msg_iov
[0].iov_base
;
4057 len
= msg
.msg_iov
[0].iov_len
;
4062 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4065 type
= SOCKET_TYPE_CHAR_UDP
;
4067 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4068 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4069 socket_wrapper_dir(), type
, iface
, prt
);
4070 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4072 /* ignore the any errors in broadcast sends */
4077 (struct sockaddr
*)(void *)&un_addr
,
4081 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4086 ret
= libc_sendto(s
,
4090 (struct sockaddr
*)msg
.msg_name
,
4093 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4098 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
4099 const struct sockaddr
*to
, socklen_t tolen
)
4101 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
4104 /****************************************************************************
4106 ***************************************************************************/
4108 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
4110 struct socket_info
*si
;
4112 struct sockaddr_storage ss
;
4113 socklen_t ss_len
= sizeof(ss
);
4118 si
= find_socket_info(s
);
4120 return libc_recv(s
, buf
, len
, flags
);
4127 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4128 msg
.msg_namelen
= ss_len
; /* size of address */
4129 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4130 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4131 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4132 msg
.msg_control
= NULL
; /* ancillary data, see below */
4133 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4134 msg
.msg_flags
= 0; /* flags on received message */
4137 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4142 buf
= msg
.msg_iov
[0].iov_base
;
4143 len
= msg
.msg_iov
[0].iov_len
;
4145 ret
= libc_recv(s
, buf
, len
, flags
);
4147 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4155 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
4157 return swrap_recv(s
, buf
, len
, flags
);
4160 /****************************************************************************
4162 ***************************************************************************/
4164 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
4166 struct socket_info
*si
;
4169 struct sockaddr_storage ss
;
4170 socklen_t ss_len
= sizeof(ss
);
4174 si
= find_socket_info(s
);
4176 return libc_read(s
, buf
, len
);
4183 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4184 msg
.msg_namelen
= ss_len
; /* size of address */
4185 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4186 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4187 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4188 msg
.msg_control
= NULL
; /* ancillary data, see below */
4189 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4190 msg
.msg_flags
= 0; /* flags on received message */
4193 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4195 if (tret
== -ENOTSOCK
) {
4196 return libc_read(s
, buf
, len
);
4201 buf
= msg
.msg_iov
[0].iov_base
;
4202 len
= msg
.msg_iov
[0].iov_len
;
4204 ret
= libc_read(s
, buf
, len
);
4206 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4214 ssize_t
read(int s
, void *buf
, size_t len
)
4216 return swrap_read(s
, buf
, len
);
4219 /****************************************************************************
4221 ***************************************************************************/
4223 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
4227 struct sockaddr_un un_addr
;
4230 struct socket_info
*si
= find_socket_info(s
);
4233 return libc_send(s
, buf
, len
, flags
);
4236 tmp
.iov_base
= discard_const_p(char, buf
);
4240 msg
.msg_name
= NULL
; /* optional address */
4241 msg
.msg_namelen
= 0; /* size of address */
4242 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4243 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4244 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4245 msg
.msg_control
= NULL
; /* ancillary data, see below */
4246 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4247 msg
.msg_flags
= 0; /* flags on received message */
4250 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4255 buf
= msg
.msg_iov
[0].iov_base
;
4256 len
= msg
.msg_iov
[0].iov_len
;
4258 ret
= libc_send(s
, buf
, len
, flags
);
4260 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4265 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
4267 return swrap_send(s
, buf
, len
, flags
);
4270 /****************************************************************************
4272 ***************************************************************************/
4274 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
4276 struct sockaddr_un from_addr
;
4277 socklen_t from_addrlen
= sizeof(from_addr
);
4278 struct socket_info
*si
;
4281 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4282 size_t msg_ctrllen_filled
;
4283 size_t msg_ctrllen_left
;
4289 si
= find_socket_info(s
);
4291 return libc_recvmsg(s
, omsg
, flags
);
4294 tmp
.iov_base
= NULL
;
4298 msg
.msg_name
= (struct sockaddr
*)&from_addr
; /* optional address */
4299 msg
.msg_namelen
= from_addrlen
; /* size of address */
4300 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4301 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4302 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4303 msg_ctrllen_filled
= 0;
4304 msg_ctrllen_left
= omsg
->msg_controllen
;
4306 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
4307 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4308 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4311 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4316 ret
= libc_recvmsg(s
, &msg
, flags
);
4318 msg
.msg_name
= omsg
->msg_name
;
4319 msg
.msg_namelen
= omsg
->msg_namelen
;
4321 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4322 msg_ctrllen_filled
+= msg
.msg_controllen
;
4323 msg_ctrllen_left
-= msg
.msg_controllen
;
4325 if (omsg
->msg_control
!= NULL
) {
4328 p
= omsg
->msg_control
;
4329 p
+= msg_ctrllen_filled
;
4331 msg
.msg_control
= p
;
4332 msg
.msg_controllen
= msg_ctrllen_left
;
4334 msg
.msg_control
= NULL
;
4335 msg
.msg_controllen
= 0;
4339 rc
= swrap_recvmsg_after(s
, si
, &msg
, &from_addr
, from_addrlen
, ret
);
4344 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4345 if (omsg
->msg_control
!= NULL
) {
4346 /* msg.msg_controllen = space left */
4347 msg_ctrllen_left
= msg
.msg_controllen
;
4348 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
4351 /* Update the original message length */
4352 omsg
->msg_controllen
= msg_ctrllen_filled
;
4353 omsg
->msg_flags
= msg
.msg_flags
;
4355 omsg
->msg_iovlen
= msg
.msg_iovlen
;
4360 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
4362 return swrap_recvmsg(sockfd
, msg
, flags
);
4365 /****************************************************************************
4367 ***************************************************************************/
4369 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4373 struct sockaddr_un un_addr
;
4374 const struct sockaddr_un
*to_un
= NULL
;
4375 const struct sockaddr
*to
= NULL
;
4378 struct socket_info
*si
= find_socket_info(s
);
4382 return libc_sendmsg(s
, omsg
, flags
);
4385 ZERO_STRUCT(un_addr
);
4387 tmp
.iov_base
= NULL
;
4391 msg
.msg_name
= omsg
->msg_name
; /* optional address */
4392 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
4393 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4394 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4395 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4396 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
4397 /* omsg is a const so use a local buffer for modifications */
4398 uint8_t cmbuf
[omsg
->msg_controllen
];
4400 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
4402 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
4403 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4405 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4408 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4416 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4424 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4425 avail
+= msg
.msg_iov
[i
].iov_len
;
4431 /* we capture it as one single packet */
4432 buf
= (uint8_t *)malloc(remain
);
4437 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4438 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4440 msg
.msg_iov
[i
].iov_base
,
4443 remain
-= this_time
;
4446 type
= SOCKET_TYPE_CHAR_UDP
;
4448 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4449 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4450 socket_wrapper_dir(), type
, iface
, prt
);
4451 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4453 msg
.msg_name
= &un_addr
; /* optional address */
4454 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4456 /* ignore the any errors in broadcast sends */
4457 libc_sendmsg(s
, &msg
, flags
);
4460 swrap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4466 ret
= libc_sendmsg(s
, &msg
, flags
);
4468 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4473 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4475 return swrap_sendmsg(s
, omsg
, flags
);
4478 /****************************************************************************
4480 ***************************************************************************/
4482 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4484 struct socket_info
*si
;
4487 struct sockaddr_storage ss
;
4488 socklen_t ss_len
= sizeof(ss
);
4492 si
= find_socket_info(s
);
4494 return libc_readv(s
, vector
, count
);
4497 tmp
.iov_base
= NULL
;
4501 msg
.msg_name
= (struct sockaddr
*)(void *)&ss
; /* optional address */
4502 msg
.msg_namelen
= ss_len
; /* size of address */
4503 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4504 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4505 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4506 msg
.msg_control
= NULL
; /* ancillary data, see below */
4507 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4508 msg
.msg_flags
= 0; /* flags on received message */
4511 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4513 if (rc
== -ENOTSOCK
) {
4514 return libc_readv(s
, vector
, count
);
4519 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4521 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4529 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4531 return swrap_readv(s
, vector
, count
);
4534 /****************************************************************************
4536 ***************************************************************************/
4538 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4542 struct sockaddr_un un_addr
;
4545 struct socket_info
*si
= find_socket_info(s
);
4548 return libc_writev(s
, vector
, count
);
4551 tmp
.iov_base
= NULL
;
4555 msg
.msg_name
= NULL
; /* optional address */
4556 msg
.msg_namelen
= 0; /* size of address */
4557 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4558 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4559 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4560 msg
.msg_control
= NULL
; /* ancillary data, see below */
4561 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4562 msg
.msg_flags
= 0; /* flags on received message */
4565 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4567 if (rc
== -ENOTSOCK
) {
4568 return libc_readv(s
, vector
, count
);
4573 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4575 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4580 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4582 return swrap_writev(s
, vector
, count
);
4585 /****************************
4587 ***************************/
4589 static int swrap_close(int fd
)
4591 struct socket_info
*si
= find_socket_info(fd
);
4592 struct socket_info_fd
*fi
;
4596 return libc_close(fd
);
4599 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4601 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4608 /* there are still references left */
4609 return libc_close(fd
);
4612 SWRAP_DLIST_REMOVE(sockets
, si
);
4614 if (si
->myname
&& si
->peername
) {
4615 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4618 ret
= libc_close(fd
);
4620 if (si
->myname
&& si
->peername
) {
4621 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4622 swrap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4625 if (si
->bindname
!= NULL
) {
4629 if (si
->myname
) free(si
->myname
);
4630 if (si
->peername
) free(si
->peername
);
4632 unlink(si
->tmp_path
);
4642 return swrap_close(fd
);
4645 /****************************
4647 ***************************/
4649 static int swrap_dup(int fd
)
4651 struct socket_info
*si
;
4652 struct socket_info_fd
*fi
;
4654 si
= find_socket_info(fd
);
4657 return libc_dup(fd
);
4660 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4666 fi
->fd
= libc_dup(fd
);
4668 int saved_errno
= errno
;
4670 errno
= saved_errno
;
4674 /* Make sure we don't have an entry for the fd */
4675 swrap_remove_stale(fi
->fd
);
4677 SWRAP_DLIST_ADD(si
->fds
, fi
);
4683 return swrap_dup(fd
);
4686 /****************************
4688 ***************************/
4690 static int swrap_dup2(int fd
, int newfd
)
4692 struct socket_info
*si
;
4693 struct socket_info_fd
*fi
;
4695 si
= find_socket_info(fd
);
4698 return libc_dup2(fd
, newfd
);
4701 if (find_socket_info(newfd
)) {
4702 /* dup2() does an implicit close of newfd, which we
4703 * need to emulate */
4707 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4713 fi
->fd
= libc_dup2(fd
, newfd
);
4715 int saved_errno
= errno
;
4717 errno
= saved_errno
;
4721 /* Make sure we don't have an entry for the fd */
4722 swrap_remove_stale(fi
->fd
);
4724 SWRAP_DLIST_ADD(si
->fds
, fi
);
4728 int dup2(int fd
, int newfd
)
4730 return swrap_dup2(fd
, newfd
);
4733 /****************************
4735 ***************************/
4738 static int swrap_eventfd(int count
, int flags
)
4742 fd
= libc_eventfd(count
, flags
);
4744 swrap_remove_stale(fd
);
4750 int eventfd(int count
, int flags
)
4752 return swrap_eventfd(count
, flags
);
4756 /****************************
4758 ***************************/
4761 * This function is called when the library is unloaded and makes sure that
4762 * sockets get closed and the unix file for the socket are unlinked.
4764 void swrap_destructor(void)
4766 struct socket_info
*s
= sockets
;
4769 struct socket_info_fd
*f
= s
->fds
;