2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <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_ADDRESS_SANITIZER_ATTRIBUTE
104 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
106 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
109 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
110 # define SWRAP_THREAD __thread
112 # define SWRAP_THREAD
116 #define MIN(a,b) ((a)<(b)?(a):(b))
120 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
124 #define ZERO_STRUCTP(x) do { \
126 memset((char *)(x), 0, sizeof(*(x))); \
130 #ifndef discard_const
131 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
134 #ifndef discard_const_p
135 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
139 # ifndef IPV6_RECVPKTINFO
140 # define IPV6_RECVPKTINFO IPV6_PKTINFO
141 # endif /* IPV6_RECVPKTINFO */
142 #endif /* IPV6_PKTINFO */
145 * On BSD IP_PKTINFO has a different name because during
146 * the time when they implemented it, there was no RFC.
147 * The name for IPv6 is the same as on Linux.
150 # ifdef IP_RECVDSTADDR
151 # define IP_PKTINFO IP_RECVDSTADDR
156 #define SWRAP_DLIST_ADD(list,item) do { \
158 (item)->prev = NULL; \
159 (item)->next = NULL; \
162 (item)->prev = NULL; \
163 (item)->next = (list); \
164 (list)->prev = (item); \
169 #define SWRAP_DLIST_REMOVE(list,item) do { \
170 if ((list) == (item)) { \
171 (list) = (item)->next; \
173 (list)->prev = NULL; \
176 if ((item)->prev) { \
177 (item)->prev->next = (item)->next; \
179 if ((item)->next) { \
180 (item)->next->prev = (item)->prev; \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
187 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
188 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
190 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
193 /* we need to use a very terse format here as IRIX 6.4 silently
194 truncates names to 16 chars, so if we use a longer name then we
195 can't tell which port a packet came from with recvfrom()
197 with this format we have 8 chars left for the directory name
199 #define SOCKET_FORMAT "%c%02X%04X"
200 #define SOCKET_TYPE_CHAR_TCP 'T'
201 #define SOCKET_TYPE_CHAR_UDP 'U'
202 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
203 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
206 * Cut down to 1500 byte packets for stream sockets,
207 * which makes it easier to format PCAP capture files
208 * (as the caller will simply continue from here)
210 #define SOCKET_MAX_PACKET 1500
212 #define SOCKET_MAX_SOCKETS 1024
214 /* This limit is to avoid broadcast sendto() needing to stat too many
215 * files. It may be raised (with a performance cost) to up to 254
216 * without changing the format above */
217 #define MAX_WRAPPED_INTERFACES 40
219 struct swrap_address
{
220 socklen_t sa_socklen
;
223 struct sockaddr_in in
;
225 struct sockaddr_in6 in6
;
227 struct sockaddr_un un
;
228 struct sockaddr_storage ss
;
232 struct socket_info_fd
{
233 struct socket_info_fd
*prev
, *next
;
239 struct socket_info_fd
*fds
;
251 /* The unix path so we can unlink it on close() */
252 struct sockaddr_un un_addr
;
254 struct swrap_address bindname
;
255 struct swrap_address myname
;
256 struct swrap_address peername
;
259 unsigned long pck_snd
;
260 unsigned long pck_rcv
;
263 struct socket_info
*prev
, *next
;
267 * File descriptors are shared between threads so we should share socket
270 struct socket_info
*sockets
;
272 /* Function prototypes */
274 bool socket_wrapper_enabled(void);
275 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
278 # define SWRAP_LOG(...)
281 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *func
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
282 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
284 static void swrap_log(enum swrap_dbglvl_e dbglvl
,
286 const char *format
, ...)
291 unsigned int lvl
= 0;
293 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
298 va_start(va
, format
);
299 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
304 case SWRAP_LOG_ERROR
:
306 "SWRAP_ERROR(%d) - %s: %s\n",
307 (int)getpid(), func
, buffer
);
311 "SWRAP_WARN(%d) - %s: %s\n",
312 (int)getpid(), func
, buffer
);
314 case SWRAP_LOG_DEBUG
:
316 "SWRAP_DEBUG(%d) - %s: %s\n",
317 (int)getpid(), func
, buffer
);
319 case SWRAP_LOG_TRACE
:
321 "SWRAP_TRACE(%d) - %s: %s\n",
322 (int)getpid(), func
, buffer
);
329 /*********************************************************
330 * SWRAP LOADING LIBC FUNCTIONS
331 *********************************************************/
335 struct swrap_libc_fns
{
336 int (*libc_accept
)(int sockfd
,
337 struct sockaddr
*addr
,
339 int (*libc_bind
)(int sockfd
,
340 const struct sockaddr
*addr
,
342 int (*libc_close
)(int fd
);
343 int (*libc_connect
)(int sockfd
,
344 const struct sockaddr
*addr
,
346 int (*libc_dup
)(int fd
);
347 int (*libc_dup2
)(int oldfd
, int newfd
);
348 int (*libc_fcntl
)(int fd
, int cmd
, ...);
349 FILE *(*libc_fopen
)(const char *name
, const char *mode
);
351 int (*libc_eventfd
)(int count
, int flags
);
353 int (*libc_getpeername
)(int sockfd
,
354 struct sockaddr
*addr
,
356 int (*libc_getsockname
)(int sockfd
,
357 struct sockaddr
*addr
,
359 int (*libc_getsockopt
)(int sockfd
,
364 int (*libc_ioctl
)(int d
, unsigned long int request
, ...);
365 int (*libc_listen
)(int sockfd
, int backlog
);
366 int (*libc_open
)(const char *pathname
, int flags
, mode_t mode
);
367 int (*libc_pipe
)(int pipefd
[2]);
368 int (*libc_read
)(int fd
, void *buf
, size_t count
);
369 ssize_t (*libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
370 int (*libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
371 int (*libc_recvfrom
)(int sockfd
,
375 struct sockaddr
*src_addr
,
377 int (*libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
378 int (*libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
379 int (*libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
380 int (*libc_sendto
)(int sockfd
,
384 const struct sockaddr
*dst_addr
,
386 int (*libc_setsockopt
)(int sockfd
,
392 int (*libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
394 int (*libc_socket
)(int domain
, int type
, int protocol
);
395 int (*libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
396 #ifdef HAVE_TIMERFD_CREATE
397 int (*libc_timerfd_create
)(int clockid
, int flags
);
399 ssize_t (*libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
404 void *libsocket_handle
;
411 struct swrap_libc_fns fns
;
414 static struct swrap swrap
;
417 static const char *socket_wrapper_dir(void);
419 #define LIBC_NAME "libc.so"
428 static const char *swrap_str_lib(enum swrap_lib lib
)
435 case SWRAP_LIBSOCKET
:
439 /* Compiler would warn us about unhandled enum value if we get here */
444 static void *swrap_load_lib_handle(enum swrap_lib lib
)
446 int flags
= RTLD_LAZY
;
451 flags
|= RTLD_DEEPBIND
;
457 case SWRAP_LIBSOCKET
:
458 #ifdef HAVE_LIBSOCKET
459 handle
= swrap
.libsocket_handle
;
460 if (handle
== NULL
) {
461 for (i
= 10; i
>= 0; i
--) {
462 char soname
[256] = {0};
464 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
465 handle
= dlopen(soname
, flags
);
466 if (handle
!= NULL
) {
471 swrap
.libsocket_handle
= handle
;
477 handle
= swrap
.libc_handle
;
479 if (handle
== NULL
) {
480 handle
= dlopen(LIBC_SO
, flags
);
482 swrap
.libc_handle
= handle
;
485 if (handle
== NULL
) {
486 for (i
= 10; i
>= 0; i
--) {
487 char soname
[256] = {0};
489 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
490 handle
= dlopen(soname
, flags
);
491 if (handle
!= NULL
) {
496 swrap
.libc_handle
= handle
;
501 if (handle
== NULL
) {
503 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
505 SWRAP_LOG(SWRAP_LOG_ERROR
,
506 "Failed to dlopen library: %s\n",
515 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
520 handle
= swrap_load_lib_handle(lib
);
522 func
= dlsym(handle
, fn_name
);
524 SWRAP_LOG(SWRAP_LOG_ERROR
,
525 "Failed to find %s: %s\n",
530 SWRAP_LOG(SWRAP_LOG_TRACE
,
532 fn_name
, swrap_str_lib(lib
));
536 #define swrap_load_lib_function(lib, fn_name) \
537 if (swrap.fns.libc_##fn_name == NULL) { \
538 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
539 *(void **) (&swrap.fns.libc_##fn_name) = \
547 * Functions especially from libc need to be loaded individually, you can't load
548 * all at once or gdb will segfault at startup. The same applies to valgrind and
549 * has probably something todo with with the linker.
550 * So we need load each function at the point it is called the first time.
552 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
554 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
556 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
559 static int libc_bind(int sockfd
,
560 const struct sockaddr
*addr
,
563 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
565 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
568 static int libc_close(int fd
)
570 swrap_load_lib_function(SWRAP_LIBC
, close
);
572 return swrap
.fns
.libc_close(fd
);
575 static int libc_connect(int sockfd
,
576 const struct sockaddr
*addr
,
579 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
581 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
584 static int libc_dup(int fd
)
586 swrap_load_lib_function(SWRAP_LIBC
, dup
);
588 return swrap
.fns
.libc_dup(fd
);
591 static int libc_dup2(int oldfd
, int newfd
)
593 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
595 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
599 static int libc_eventfd(int count
, int flags
)
601 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
603 return swrap
.fns
.libc_eventfd(count
, flags
);
607 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
608 static int libc_vfcntl(int fd
, int cmd
, va_list ap
)
614 swrap_load_lib_function(SWRAP_LIBC
, fcntl
);
616 for (i
= 0; i
< 4; i
++) {
617 args
[i
] = va_arg(ap
, long int);
620 rc
= swrap
.fns
.libc_fcntl(fd
,
630 static int libc_getpeername(int sockfd
,
631 struct sockaddr
*addr
,
634 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
636 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
639 static int libc_getsockname(int sockfd
,
640 struct sockaddr
*addr
,
643 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
645 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
648 static int libc_getsockopt(int sockfd
,
654 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
656 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
659 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
660 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
666 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
668 for (i
= 0; i
< 4; i
++) {
669 args
[i
] = va_arg(ap
, long int);
672 rc
= swrap
.fns
.libc_ioctl(d
,
682 static int libc_listen(int sockfd
, int backlog
)
684 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
686 return swrap
.fns
.libc_listen(sockfd
, backlog
);
689 static FILE *libc_fopen(const char *name
, const char *mode
)
691 swrap_load_lib_function(SWRAP_LIBC
, fopen
);
693 return swrap
.fns
.libc_fopen(name
, mode
);
696 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
701 swrap_load_lib_function(SWRAP_LIBC
, open
);
703 mode
= va_arg(ap
, long int);
705 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
710 static int libc_open(const char *pathname
, int flags
, ...)
716 fd
= libc_vopen(pathname
, flags
, ap
);
722 static int libc_pipe(int pipefd
[2])
724 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
726 return swrap
.fns
.libc_pipe(pipefd
);
729 static int libc_read(int fd
, void *buf
, size_t count
)
731 swrap_load_lib_function(SWRAP_LIBC
, read
);
733 return swrap
.fns
.libc_read(fd
, buf
, count
);
736 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
738 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
740 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
743 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
745 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
747 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
750 static int libc_recvfrom(int sockfd
,
754 struct sockaddr
*src_addr
,
757 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
759 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
762 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
764 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
766 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
769 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
771 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
773 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
776 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
778 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
780 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
783 static int libc_sendto(int sockfd
,
787 const struct sockaddr
*dst_addr
,
790 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
792 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
795 static int libc_setsockopt(int sockfd
,
801 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
803 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
807 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
809 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
811 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
815 static int libc_socket(int domain
, int type
, int protocol
)
817 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
819 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
822 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
824 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
826 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
829 #ifdef HAVE_TIMERFD_CREATE
830 static int libc_timerfd_create(int clockid
, int flags
)
832 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
834 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
838 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
840 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
842 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
845 /*********************************************************
846 * SWRAP HELPER FUNCTIONS
847 *********************************************************/
853 static const struct in6_addr
*swrap_ipv6(void)
855 static struct in6_addr v
;
856 static int initialized
;
864 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
873 static void set_port(int family
, int prt
, struct swrap_address
*addr
)
877 addr
->sa
.in
.sin_port
= htons(prt
);
881 addr
->sa
.in6
.sin6_port
= htons(prt
);
887 static size_t socket_length(int family
)
891 return sizeof(struct sockaddr_in
);
894 return sizeof(struct sockaddr_in6
);
900 static const char *socket_wrapper_dir(void)
902 const char *s
= getenv("SOCKET_WRAPPER_DIR");
906 /* TODO use realpath(3) here, when we add support for threads */
907 if (strncmp(s
, "./", 2) == 0) {
911 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
915 bool socket_wrapper_enabled(void)
917 const char *s
= socket_wrapper_dir();
919 return s
!= NULL
? true : false;
922 static unsigned int socket_wrapper_default_iface(void)
924 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
927 if (sscanf(s
, "%u", &iface
) == 1) {
928 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
934 return 1;/* 127.0.0.1 */
937 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
944 p
= strrchr(un
->sun_path
, '/');
945 if (p
) p
++; else p
= un
->sun_path
;
947 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
952 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
955 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
966 case SOCKET_TYPE_CHAR_TCP
:
967 case SOCKET_TYPE_CHAR_UDP
: {
968 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
970 if ((*len
) < sizeof(*in2
)) {
975 memset(in2
, 0, sizeof(*in2
));
976 in2
->sin_family
= AF_INET
;
977 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
978 in2
->sin_port
= htons(prt
);
984 case SOCKET_TYPE_CHAR_TCP_V6
:
985 case SOCKET_TYPE_CHAR_UDP_V6
: {
986 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
988 if ((*len
) < sizeof(*in2
)) {
993 memset(in2
, 0, sizeof(*in2
));
994 in2
->sin6_family
= AF_INET6
;
995 in2
->sin6_addr
= *swrap_ipv6();
996 in2
->sin6_addr
.s6_addr
[15] = iface
;
997 in2
->sin6_port
= htons(prt
);
1011 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1019 if (bcast
) *bcast
= 0;
1021 switch (inaddr
->sa_family
) {
1023 const struct sockaddr_in
*in
=
1024 (const struct sockaddr_in
*)(const void *)inaddr
;
1025 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1032 u_type
= SOCKET_TYPE_CHAR_TCP
;
1035 u_type
= SOCKET_TYPE_CHAR_UDP
;
1036 a_type
= SOCKET_TYPE_CHAR_UDP
;
1037 b_type
= SOCKET_TYPE_CHAR_UDP
;
1040 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1041 errno
= ESOCKTNOSUPPORT
;
1045 prt
= ntohs(in
->sin_port
);
1046 if (a_type
&& addr
== 0xFFFFFFFF) {
1047 /* 255.255.255.255 only udp */
1050 iface
= socket_wrapper_default_iface();
1051 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1052 /* 127.255.255.255 only udp */
1055 iface
= socket_wrapper_default_iface();
1056 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1060 iface
= (addr
& 0x000000FF);
1062 errno
= ENETUNREACH
;
1065 if (bcast
) *bcast
= is_bcast
;
1070 const struct sockaddr_in6
*in
=
1071 (const struct sockaddr_in6
*)(const void *)inaddr
;
1072 struct in6_addr cmp1
, cmp2
;
1076 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1079 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1082 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1083 errno
= ESOCKTNOSUPPORT
;
1087 /* XXX no multicast/broadcast */
1089 prt
= ntohs(in
->sin6_port
);
1091 cmp1
= *swrap_ipv6();
1092 cmp2
= in
->sin6_addr
;
1093 cmp2
.s6_addr
[15] = 0;
1094 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1095 iface
= in
->sin6_addr
.s6_addr
[15];
1097 errno
= ENETUNREACH
;
1105 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1106 errno
= ENETUNREACH
;
1111 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1117 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1118 socket_wrapper_dir());
1119 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1120 /* the caller need to do more processing */
1124 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1125 socket_wrapper_dir(), type
, iface
, prt
);
1126 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1131 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1140 if (bcast
) *bcast
= 0;
1142 switch (si
->family
) {
1144 const struct sockaddr_in
*in
=
1145 (const struct sockaddr_in
*)(const void *)inaddr
;
1146 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1152 prt
= ntohs(in
->sin_port
);
1156 u_type
= SOCKET_TYPE_CHAR_TCP
;
1157 d_type
= SOCKET_TYPE_CHAR_TCP
;
1160 u_type
= SOCKET_TYPE_CHAR_UDP
;
1161 d_type
= SOCKET_TYPE_CHAR_UDP
;
1162 a_type
= SOCKET_TYPE_CHAR_UDP
;
1163 b_type
= SOCKET_TYPE_CHAR_UDP
;
1166 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1167 errno
= ESOCKTNOSUPPORT
;
1175 iface
= socket_wrapper_default_iface();
1176 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1177 /* 255.255.255.255 only udp */
1180 iface
= socket_wrapper_default_iface();
1181 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1182 /* 127.255.255.255 only udp */
1185 iface
= socket_wrapper_default_iface();
1186 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1190 iface
= (addr
& 0x000000FF);
1192 errno
= EADDRNOTAVAIL
;
1196 /* Store the bind address for connect() */
1197 if (si
->bindname
.sa_socklen
== 0) {
1198 struct sockaddr_in bind_in
;
1199 socklen_t blen
= sizeof(struct sockaddr_in
);
1201 ZERO_STRUCT(bind_in
);
1202 bind_in
.sin_family
= in
->sin_family
;
1203 bind_in
.sin_port
= in
->sin_port
;
1204 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1206 si
->bindname
.sa_socklen
= blen
;
1207 memcpy(&si
->bindname
.sa
.in
, &bind_in
, blen
);
1214 const struct sockaddr_in6
*in
=
1215 (const struct sockaddr_in6
*)(const void *)inaddr
;
1216 struct in6_addr cmp1
, cmp2
;
1220 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1223 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1226 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1227 errno
= ESOCKTNOSUPPORT
;
1231 /* XXX no multicast/broadcast */
1233 prt
= ntohs(in
->sin6_port
);
1235 cmp1
= *swrap_ipv6();
1236 cmp2
= in
->sin6_addr
;
1237 cmp2
.s6_addr
[15] = 0;
1238 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1239 iface
= socket_wrapper_default_iface();
1240 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1241 iface
= in
->sin6_addr
.s6_addr
[15];
1243 errno
= EADDRNOTAVAIL
;
1247 /* Store the bind address for connect() */
1248 if (si
->bindname
.sa_socklen
== 0) {
1249 struct sockaddr_in6 bind_in
;
1250 socklen_t blen
= sizeof(struct sockaddr_in6
);
1252 ZERO_STRUCT(bind_in
);
1253 bind_in
.sin6_family
= in
->sin6_family
;
1254 bind_in
.sin6_port
= in
->sin6_port
;
1256 bind_in
.sin6_addr
= *swrap_ipv6();
1257 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1259 memcpy(&si
->bindname
.sa
.in6
, &bind_in
, blen
);
1260 si
->bindname
.sa_socklen
= blen
;
1267 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1268 errno
= EADDRNOTAVAIL
;
1273 if (bcast
) *bcast
= is_bcast
;
1275 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1281 /* handle auto-allocation of ephemeral ports */
1282 for (prt
= 5001; prt
< 10000; prt
++) {
1283 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1284 socket_wrapper_dir(), type
, iface
, prt
);
1285 if (stat(un
->sun_path
, &st
) == 0) continue;
1287 set_port(si
->family
, prt
, &si
->myname
);
1288 set_port(si
->family
, prt
, &si
->bindname
);
1298 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1299 socket_wrapper_dir(), type
, iface
, prt
);
1300 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1304 static struct socket_info
*find_socket_info(int fd
)
1306 struct socket_info
*i
;
1308 for (i
= sockets
; i
; i
= i
->next
) {
1309 struct socket_info_fd
*f
;
1310 for (f
= i
->fds
; f
; f
= f
->next
) {
1321 static bool check_addr_port_in_use(const struct sockaddr
*sa
, socklen_t len
)
1323 struct socket_info
*s
;
1325 /* first catch invalid input */
1326 switch (sa
->sa_family
) {
1328 if (len
< sizeof(struct sockaddr_in
)) {
1334 if (len
< sizeof(struct sockaddr_in6
)) {
1344 for (s
= sockets
; s
!= NULL
; s
= s
->next
) {
1345 if (s
->myname
== NULL
) {
1348 if (s
->myname
->sa_family
!= sa
->sa_family
) {
1351 switch (s
->myname
->sa_family
) {
1353 struct sockaddr_in
*sin1
, *sin2
;
1355 sin1
= (struct sockaddr_in
*)s
->myname
;
1356 sin2
= (struct sockaddr_in
*)sa
;
1358 if (sin1
->sin_addr
.s_addr
== htonl(INADDR_ANY
)) {
1361 if (sin1
->sin_port
!= sin2
->sin_port
) {
1364 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
1374 struct sockaddr_in6
*sin1
, *sin2
;
1376 sin1
= (struct sockaddr_in6
*)s
->myname
;
1377 sin2
= (struct sockaddr_in6
*)sa
;
1379 if (sin1
->sin6_port
!= sin2
->sin6_port
) {
1382 if (!IN6_ARE_ADDR_EQUAL(&sin1
->sin6_addr
,
1404 static void swrap_remove_stale(int fd
)
1406 struct socket_info
*si
= find_socket_info(fd
);
1407 struct socket_info_fd
*fi
;
1410 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1412 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1413 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1419 if (si
->fds
== NULL
) {
1420 SWRAP_DLIST_REMOVE(sockets
, si
);
1421 if (si
->un_addr
.sun_path
[0] != '\0') {
1422 unlink(si
->un_addr
.sun_path
);
1429 static int sockaddr_convert_to_un(struct socket_info
*si
,
1430 const struct sockaddr
*in_addr
,
1432 struct sockaddr_un
*out_addr
,
1436 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1438 (void) in_len
; /* unused */
1440 if (out_addr
== NULL
) {
1444 out
->sa_family
= AF_UNIX
;
1445 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1446 out
->sa_len
= sizeof(*out_addr
);
1449 switch (in_addr
->sa_family
) {
1451 const struct sockaddr_in
*sin
;
1452 if (si
->family
!= AF_INET
) {
1455 if (in_len
< sizeof(struct sockaddr_in
)) {
1458 sin
= (const struct sockaddr_in
*)(const void *)in_addr
;
1459 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
1464 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1465 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1479 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1480 errno
= ESOCKTNOSUPPORT
;
1484 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1486 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1492 errno
= EAFNOSUPPORT
;
1493 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1497 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1498 const struct sockaddr_un
*in_addr
,
1499 socklen_t un_addrlen
,
1501 struct sockaddr
*out_addr
,
1502 socklen_t
*out_addrlen
)
1506 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1509 if (un_addrlen
== 0) {
1524 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1525 errno
= ESOCKTNOSUPPORT
;
1528 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1529 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1530 out_addr
->sa_len
= *out_addrlen
;
1537 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1538 errno
= EAFNOSUPPORT
;
1542 enum swrap_packet_type
{
1544 SWRAP_CONNECT_UNREACH
,
1552 SWRAP_SENDTO_UNREACH
,
1563 struct swrap_file_hdr
{
1565 uint16_t version_major
;
1566 uint16_t version_minor
;
1569 uint32_t frame_max_len
;
1570 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1573 #define SWRAP_FILE_HDR_SIZE 24
1575 struct swrap_packet_frame
{
1577 uint32_t micro_seconds
;
1578 uint32_t recorded_length
;
1579 uint32_t full_length
;
1581 #define SWRAP_PACKET_FRAME_SIZE 16
1583 union swrap_packet_ip
{
1587 uint16_t packet_length
;
1588 uint16_t identification
;
1593 uint16_t hdr_checksum
;
1597 #define SWRAP_PACKET_IP_V4_SIZE 20
1600 uint8_t flow_label_high
;
1601 uint16_t flow_label_low
;
1602 uint16_t payload_length
;
1603 uint8_t next_header
;
1605 uint8_t src_addr
[16];
1606 uint8_t dest_addr
[16];
1608 #define SWRAP_PACKET_IP_V6_SIZE 40
1610 #define SWRAP_PACKET_IP_SIZE 40
1612 union swrap_packet_payload
{
1614 uint16_t source_port
;
1624 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1626 uint16_t source_port
;
1631 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1638 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1645 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1647 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1649 #define SWRAP_PACKET_MIN_ALLOC \
1650 (SWRAP_PACKET_FRAME_SIZE + \
1651 SWRAP_PACKET_IP_SIZE + \
1652 SWRAP_PACKET_PAYLOAD_SIZE)
1654 static const char *swrap_pcap_init_file(void)
1656 static int initialized
= 0;
1657 static const char *s
= NULL
;
1658 static const struct swrap_file_hdr h
;
1659 static const struct swrap_packet_frame f
;
1660 static const union swrap_packet_ip i
;
1661 static const union swrap_packet_payload p
;
1663 if (initialized
== 1) {
1669 * TODO: don't use the structs use plain buffer offsets
1670 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1672 * for now make sure we disable PCAP support
1673 * if the struct has alignment!
1675 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1678 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1681 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1684 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1687 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1690 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1693 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1696 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1699 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1702 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1706 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1710 if (strncmp(s
, "./", 2) == 0) {
1716 static uint8_t *swrap_pcap_packet_init(struct timeval
*tval
,
1717 const struct sockaddr
*src
,
1718 const struct sockaddr
*dest
,
1720 const uint8_t *payload
,
1722 unsigned long tcp_seqno
,
1723 unsigned long tcp_ack
,
1724 unsigned char tcp_ctl
,
1726 size_t *_packet_len
)
1730 struct swrap_packet_frame
*frame
;
1731 union swrap_packet_ip
*ip
;
1732 union swrap_packet_payload
*pay
;
1735 size_t nonwire_len
= sizeof(*frame
);
1736 size_t wire_hdr_len
= 0;
1737 size_t wire_len
= 0;
1738 size_t ip_hdr_len
= 0;
1739 size_t icmp_hdr_len
= 0;
1740 size_t icmp_truncate_len
= 0;
1741 uint8_t protocol
= 0, icmp_protocol
= 0;
1742 const struct sockaddr_in
*src_in
= NULL
;
1743 const struct sockaddr_in
*dest_in
= NULL
;
1745 const struct sockaddr_in6
*src_in6
= NULL
;
1746 const struct sockaddr_in6
*dest_in6
= NULL
;
1751 switch (src
->sa_family
) {
1753 src_in
= (const struct sockaddr_in
*)(const void *)src
;
1754 dest_in
= (const struct sockaddr_in
*)(const void *)dest
;
1755 src_port
= src_in
->sin_port
;
1756 dest_port
= dest_in
->sin_port
;
1757 ip_hdr_len
= sizeof(ip
->v4
);
1761 src_in6
= (const struct sockaddr_in6
*)(const void *)src
;
1762 dest_in6
= (const struct sockaddr_in6
*)(const void *)dest
;
1763 src_port
= src_in6
->sin6_port
;
1764 dest_port
= dest_in6
->sin6_port
;
1765 ip_hdr_len
= sizeof(ip
->v6
);
1772 switch (socket_type
) {
1774 protocol
= 0x06; /* TCP */
1775 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1776 wire_len
= wire_hdr_len
+ payload_len
;
1780 protocol
= 0x11; /* UDP */
1781 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1782 wire_len
= wire_hdr_len
+ payload_len
;
1790 icmp_protocol
= protocol
;
1791 switch (src
->sa_family
) {
1793 protocol
= 0x01; /* ICMPv4 */
1794 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1798 protocol
= 0x3A; /* ICMPv6 */
1799 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1803 if (wire_len
> 64 ) {
1804 icmp_truncate_len
= wire_len
- 64;
1806 wire_hdr_len
+= icmp_hdr_len
;
1807 wire_len
+= icmp_hdr_len
;
1810 packet_len
= nonwire_len
+ wire_len
;
1811 alloc_len
= packet_len
;
1812 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1813 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1816 base
= (uint8_t *)malloc(alloc_len
);
1820 memset(base
, 0x0, alloc_len
);
1824 frame
= (struct swrap_packet_frame
*)(void *)buf
;
1825 frame
->seconds
= tval
->tv_sec
;
1826 frame
->micro_seconds
= tval
->tv_usec
;
1827 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1828 frame
->full_length
= wire_len
- icmp_truncate_len
;
1829 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1831 ip
= (union swrap_packet_ip
*)(void *)buf
;
1832 switch (src
->sa_family
) {
1834 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1836 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1837 ip
->v4
.identification
= htons(0xFFFF);
1838 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1839 ip
->v4
.fragment
= htons(0x0000);
1841 ip
->v4
.protocol
= protocol
;
1842 ip
->v4
.hdr_checksum
= htons(0x0000);
1843 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1844 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1845 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1849 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1850 ip
->v6
.flow_label_high
= 0x00;
1851 ip
->v6
.flow_label_low
= 0x0000;
1852 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1853 ip
->v6
.next_header
= protocol
;
1854 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1855 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1856 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1862 pay
= (union swrap_packet_payload
*)(void *)buf
;
1863 switch (src
->sa_family
) {
1865 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1866 pay
->icmp4
.code
= 0x01; /* host unreachable */
1867 pay
->icmp4
.checksum
= htons(0x0000);
1868 pay
->icmp4
.unused
= htonl(0x00000000);
1869 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1871 /* set the ip header in the ICMP payload */
1872 ip
= (union swrap_packet_ip
*)(void *)buf
;
1873 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1875 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1876 ip
->v4
.identification
= htons(0xFFFF);
1877 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1878 ip
->v4
.fragment
= htons(0x0000);
1880 ip
->v4
.protocol
= icmp_protocol
;
1881 ip
->v4
.hdr_checksum
= htons(0x0000);
1882 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1883 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1884 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1886 src_port
= dest_in
->sin_port
;
1887 dest_port
= src_in
->sin_port
;
1891 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1892 pay
->icmp6
.code
= 0x03; /* address unreachable */
1893 pay
->icmp6
.checksum
= htons(0x0000);
1894 pay
->icmp6
.unused
= htonl(0x00000000);
1895 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1897 /* set the ip header in the ICMP payload */
1898 ip
= (union swrap_packet_ip
*)(void *)buf
;
1899 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1900 ip
->v6
.flow_label_high
= 0x00;
1901 ip
->v6
.flow_label_low
= 0x0000;
1902 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1903 ip
->v6
.next_header
= protocol
;
1904 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1905 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1906 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1908 src_port
= dest_in6
->sin6_port
;
1909 dest_port
= src_in6
->sin6_port
;
1915 pay
= (union swrap_packet_payload
*)(void *)buf
;
1917 switch (socket_type
) {
1919 pay
->tcp
.source_port
= src_port
;
1920 pay
->tcp
.dest_port
= dest_port
;
1921 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1922 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1923 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1924 pay
->tcp
.control
= tcp_ctl
;
1925 pay
->tcp
.window
= htons(0x7FFF);
1926 pay
->tcp
.checksum
= htons(0x0000);
1927 pay
->tcp
.urg
= htons(0x0000);
1928 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1933 pay
->udp
.source_port
= src_port
;
1934 pay
->udp
.dest_port
= dest_port
;
1935 pay
->udp
.length
= htons(8 + payload_len
);
1936 pay
->udp
.checksum
= htons(0x0000);
1937 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1942 if (payload
&& payload_len
> 0) {
1943 memcpy(buf
, payload
, payload_len
);
1946 *_packet_len
= packet_len
- icmp_truncate_len
;
1950 static int swrap_pcap_get_fd(const char *fname
)
1954 if (fd
!= -1) return fd
;
1956 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1958 struct swrap_file_hdr file_hdr
;
1959 file_hdr
.magic
= 0xA1B2C3D4;
1960 file_hdr
.version_major
= 0x0002;
1961 file_hdr
.version_minor
= 0x0004;
1962 file_hdr
.timezone
= 0x00000000;
1963 file_hdr
.sigfigs
= 0x00000000;
1964 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1965 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1967 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1974 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1979 static uint8_t *swrap_pcap_marshall_packet(struct socket_info
*si
,
1980 const struct sockaddr
*addr
,
1981 enum swrap_packet_type type
,
1982 const void *buf
, size_t len
,
1985 const struct sockaddr
*src_addr
;
1986 const struct sockaddr
*dest_addr
;
1987 unsigned long tcp_seqno
= 0;
1988 unsigned long tcp_ack
= 0;
1989 unsigned char tcp_ctl
= 0;
1990 int unreachable
= 0;
1994 switch (si
->family
) {
2006 case SWRAP_CONNECT_SEND
:
2007 if (si
->type
!= SOCK_STREAM
) return NULL
;
2009 src_addr
= &si
->myname
.sa
.s
;
2012 tcp_seqno
= si
->io
.pck_snd
;
2013 tcp_ack
= si
->io
.pck_rcv
;
2014 tcp_ctl
= 0x02; /* SYN */
2016 si
->io
.pck_snd
+= 1;
2020 case SWRAP_CONNECT_RECV
:
2021 if (si
->type
!= SOCK_STREAM
) return NULL
;
2023 dest_addr
= &si
->myname
.sa
.s
;
2026 tcp_seqno
= si
->io
.pck_rcv
;
2027 tcp_ack
= si
->io
.pck_snd
;
2028 tcp_ctl
= 0x12; /** SYN,ACK */
2030 si
->io
.pck_rcv
+= 1;
2034 case SWRAP_CONNECT_UNREACH
:
2035 if (si
->type
!= SOCK_STREAM
) return NULL
;
2037 dest_addr
= &si
->myname
.sa
.s
;
2040 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2041 tcp_seqno
= si
->io
.pck_snd
- 1;
2042 tcp_ack
= si
->io
.pck_rcv
;
2043 tcp_ctl
= 0x02; /* SYN */
2048 case SWRAP_CONNECT_ACK
:
2049 if (si
->type
!= SOCK_STREAM
) return NULL
;
2051 src_addr
= &si
->myname
.sa
.s
;
2054 tcp_seqno
= si
->io
.pck_snd
;
2055 tcp_ack
= si
->io
.pck_rcv
;
2056 tcp_ctl
= 0x10; /* ACK */
2060 case SWRAP_ACCEPT_SEND
:
2061 if (si
->type
!= SOCK_STREAM
) return NULL
;
2063 dest_addr
= &si
->myname
.sa
.s
;
2066 tcp_seqno
= si
->io
.pck_rcv
;
2067 tcp_ack
= si
->io
.pck_snd
;
2068 tcp_ctl
= 0x02; /* SYN */
2070 si
->io
.pck_rcv
+= 1;
2074 case SWRAP_ACCEPT_RECV
:
2075 if (si
->type
!= SOCK_STREAM
) return NULL
;
2077 src_addr
= &si
->myname
.sa
.s
;
2080 tcp_seqno
= si
->io
.pck_snd
;
2081 tcp_ack
= si
->io
.pck_rcv
;
2082 tcp_ctl
= 0x12; /* SYN,ACK */
2084 si
->io
.pck_snd
+= 1;
2088 case SWRAP_ACCEPT_ACK
:
2089 if (si
->type
!= SOCK_STREAM
) return NULL
;
2091 dest_addr
= &si
->myname
.sa
.s
;
2094 tcp_seqno
= si
->io
.pck_rcv
;
2095 tcp_ack
= si
->io
.pck_snd
;
2096 tcp_ctl
= 0x10; /* ACK */
2101 src_addr
= &si
->myname
.sa
.s
;
2102 dest_addr
= &si
->peername
.sa
.s
;
2104 tcp_seqno
= si
->io
.pck_snd
;
2105 tcp_ack
= si
->io
.pck_rcv
;
2106 tcp_ctl
= 0x18; /* PSH,ACK */
2108 si
->io
.pck_snd
+= len
;
2112 case SWRAP_SEND_RST
:
2113 dest_addr
= &si
->myname
.sa
.s
;
2114 src_addr
= &si
->peername
.sa
.s
;
2116 if (si
->type
== SOCK_DGRAM
) {
2117 return swrap_pcap_marshall_packet(si
,
2119 SWRAP_SENDTO_UNREACH
,
2125 tcp_seqno
= si
->io
.pck_rcv
;
2126 tcp_ack
= si
->io
.pck_snd
;
2127 tcp_ctl
= 0x14; /** RST,ACK */
2131 case SWRAP_PENDING_RST
:
2132 dest_addr
= &si
->myname
.sa
.s
;
2133 src_addr
= &si
->peername
.sa
.s
;
2135 if (si
->type
== SOCK_DGRAM
) {
2139 tcp_seqno
= si
->io
.pck_rcv
;
2140 tcp_ack
= si
->io
.pck_snd
;
2141 tcp_ctl
= 0x14; /* RST,ACK */
2146 dest_addr
= &si
->myname
.sa
.s
;
2147 src_addr
= &si
->peername
.sa
.s
;
2149 tcp_seqno
= si
->io
.pck_rcv
;
2150 tcp_ack
= si
->io
.pck_snd
;
2151 tcp_ctl
= 0x18; /* PSH,ACK */
2153 si
->io
.pck_rcv
+= len
;
2157 case SWRAP_RECV_RST
:
2158 dest_addr
= &si
->myname
.sa
.s
;
2159 src_addr
= &si
->peername
.sa
.s
;
2161 if (si
->type
== SOCK_DGRAM
) {
2165 tcp_seqno
= si
->io
.pck_rcv
;
2166 tcp_ack
= si
->io
.pck_snd
;
2167 tcp_ctl
= 0x14; /* RST,ACK */
2172 src_addr
= &si
->myname
.sa
.s
;
2175 si
->io
.pck_snd
+= len
;
2179 case SWRAP_SENDTO_UNREACH
:
2180 dest_addr
= &si
->myname
.sa
.s
;
2187 case SWRAP_RECVFROM
:
2188 dest_addr
= &si
->myname
.sa
.s
;
2191 si
->io
.pck_rcv
+= len
;
2195 case SWRAP_CLOSE_SEND
:
2196 if (si
->type
!= SOCK_STREAM
) return NULL
;
2198 src_addr
= &si
->myname
.sa
.s
;
2199 dest_addr
= &si
->peername
.sa
.s
;
2201 tcp_seqno
= si
->io
.pck_snd
;
2202 tcp_ack
= si
->io
.pck_rcv
;
2203 tcp_ctl
= 0x11; /* FIN, ACK */
2205 si
->io
.pck_snd
+= 1;
2209 case SWRAP_CLOSE_RECV
:
2210 if (si
->type
!= SOCK_STREAM
) return NULL
;
2212 dest_addr
= &si
->myname
.sa
.s
;
2213 src_addr
= &si
->peername
.sa
.s
;
2215 tcp_seqno
= si
->io
.pck_rcv
;
2216 tcp_ack
= si
->io
.pck_snd
;
2217 tcp_ctl
= 0x11; /* FIN,ACK */
2219 si
->io
.pck_rcv
+= 1;
2223 case SWRAP_CLOSE_ACK
:
2224 if (si
->type
!= SOCK_STREAM
) return NULL
;
2226 src_addr
= &si
->myname
.sa
.s
;
2227 dest_addr
= &si
->peername
.sa
.s
;
2229 tcp_seqno
= si
->io
.pck_snd
;
2230 tcp_ack
= si
->io
.pck_rcv
;
2231 tcp_ctl
= 0x10; /* ACK */
2238 swrapGetTimeOfDay(&tv
);
2240 return swrap_pcap_packet_init(&tv
,
2244 (const uint8_t *)buf
,
2253 static void swrap_pcap_dump_packet(struct socket_info
*si
,
2254 const struct sockaddr
*addr
,
2255 enum swrap_packet_type type
,
2256 const void *buf
, size_t len
)
2258 const char *file_name
;
2260 size_t packet_len
= 0;
2263 file_name
= swrap_pcap_init_file();
2268 packet
= swrap_pcap_marshall_packet(si
,
2274 if (packet
== NULL
) {
2278 fd
= swrap_pcap_get_fd(file_name
);
2280 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2289 /****************************************************************************
2291 ***************************************************************************/
2293 #ifdef HAVE_SIGNALFD
2294 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2298 rc
= libc_signalfd(fd
, mask
, flags
);
2300 swrap_remove_stale(fd
);
2306 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2308 return swrap_signalfd(fd
, mask
, flags
);
2312 /****************************************************************************
2314 ***************************************************************************/
2316 static int swrap_socket(int family
, int type
, int protocol
)
2318 struct socket_info
*si
;
2319 struct socket_info_fd
*fi
;
2321 int real_type
= type
;
2324 * Remove possible addition flags passed to socket() so
2325 * do not fail checking the type.
2326 * See https://lwn.net/Articles/281965/
2329 real_type
&= ~SOCK_CLOEXEC
;
2331 #ifdef SOCK_NONBLOCK
2332 real_type
&= ~SOCK_NONBLOCK
;
2335 if (!socket_wrapper_enabled()) {
2336 return libc_socket(family
, type
, protocol
);
2346 return libc_socket(family
, type
, protocol
);
2348 errno
= EAFNOSUPPORT
;
2352 switch (real_type
) {
2358 errno
= EPROTONOSUPPORT
;
2366 if (real_type
== SOCK_STREAM
) {
2371 if (real_type
== SOCK_DGRAM
) {
2376 errno
= EPROTONOSUPPORT
;
2381 * We must call libc_socket with type, from the caller, not the version
2382 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2384 fd
= libc_socket(AF_UNIX
, type
, 0);
2390 /* Check if we have a stale fd and remove it */
2391 si
= find_socket_info(fd
);
2393 swrap_remove_stale(fd
);
2396 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2397 memset(si
, 0, sizeof(struct socket_info
));
2403 si
->family
= family
;
2405 /* however, the rest of the socket_wrapper code expects just
2406 * the type, not the flags */
2407 si
->type
= real_type
;
2408 si
->protocol
= protocol
;
2411 * Setup myname so getsockname() can succeed to find out the socket
2414 switch(si
->family
) {
2416 struct sockaddr_in sin
= {
2417 .sin_family
= AF_INET
,
2420 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in
);
2421 memcpy(&si
->myname
.sa
.in
, &sin
, si
->myname
.sa_socklen
);
2425 struct sockaddr_in6 sin6
= {
2426 .sin6_family
= AF_INET6
,
2429 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in6
);
2430 memcpy(&si
->myname
.sa
.in6
, &sin6
, si
->myname
.sa_socklen
);
2439 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2448 SWRAP_DLIST_ADD(si
->fds
, fi
);
2449 SWRAP_DLIST_ADD(sockets
, si
);
2451 SWRAP_LOG(SWRAP_LOG_TRACE
,
2452 "Created %s socket for protocol %s",
2453 si
->family
== AF_INET
? "IPv4" : "IPv6",
2454 si
->type
== SOCK_DGRAM
? "UDP" : "TCP");
2459 int socket(int family
, int type
, int protocol
)
2461 return swrap_socket(family
, type
, protocol
);
2464 /****************************************************************************
2466 ***************************************************************************/
2468 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2472 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2474 swrap_remove_stale(sv
[0]);
2475 swrap_remove_stale(sv
[1]);
2481 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2483 return swrap_socketpair(family
, type
, protocol
, sv
);
2486 /****************************************************************************
2488 ***************************************************************************/
2490 #ifdef HAVE_TIMERFD_CREATE
2491 static int swrap_timerfd_create(int clockid
, int flags
)
2495 fd
= libc_timerfd_create(clockid
, flags
);
2497 swrap_remove_stale(fd
);
2503 int timerfd_create(int clockid
, int flags
)
2505 return swrap_timerfd_create(clockid
, flags
);
2509 /****************************************************************************
2511 ***************************************************************************/
2513 static int swrap_pipe(int pipefd
[2])
2517 rc
= libc_pipe(pipefd
);
2519 swrap_remove_stale(pipefd
[0]);
2520 swrap_remove_stale(pipefd
[1]);
2526 int pipe(int pipefd
[2])
2528 return swrap_pipe(pipefd
);
2531 /****************************************************************************
2533 ***************************************************************************/
2535 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2537 struct socket_info
*parent_si
, *child_si
;
2538 struct socket_info_fd
*child_fi
;
2540 struct swrap_address un_addr
= {
2541 .sa_socklen
= sizeof(struct sockaddr_un
),
2543 struct swrap_address un_my_addr
= {
2544 .sa_socklen
= sizeof(struct sockaddr_un
),
2546 struct swrap_address in_addr
= {
2547 .sa_socklen
= sizeof(struct sockaddr_storage
),
2549 struct swrap_address in_my_addr
= {
2550 .sa_socklen
= sizeof(struct sockaddr_storage
),
2554 parent_si
= find_socket_info(s
);
2556 return libc_accept(s
, addr
, addrlen
);
2560 * assume out sockaddr have the same size as the in parent
2563 in_addr
.sa_socklen
= socket_length(parent_si
->family
);
2564 if (in_addr
.sa_socklen
<= 0) {
2569 ret
= libc_accept(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
);
2571 if (errno
== ENOTSOCK
) {
2572 /* Remove stale fds */
2573 swrap_remove_stale(s
);
2580 ret
= sockaddr_convert_from_un(parent_si
,
2585 &in_addr
.sa_socklen
);
2591 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2592 memset(child_si
, 0, sizeof(struct socket_info
));
2594 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2595 if (child_fi
== NULL
) {
2604 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2606 child_si
->family
= parent_si
->family
;
2607 child_si
->type
= parent_si
->type
;
2608 child_si
->protocol
= parent_si
->protocol
;
2609 child_si
->bound
= 1;
2610 child_si
->is_server
= 1;
2611 child_si
->connected
= 1;
2613 child_si
->peername
= (struct swrap_address
) {
2614 .sa_socklen
= in_addr
.sa_socklen
,
2616 memcpy(&child_si
->peername
.sa
.ss
, &in_addr
.sa
.ss
, in_addr
.sa_socklen
);
2618 if (addr
!= NULL
&& addrlen
!= NULL
) {
2619 size_t copy_len
= MIN(*addrlen
, in_addr
.sa_socklen
);
2621 memcpy(addr
, &in_addr
.sa
.ss
, copy_len
);
2623 *addrlen
= in_addr
.sa_socklen
;
2626 ret
= libc_getsockname(fd
,
2628 &un_my_addr
.sa_socklen
);
2636 ret
= sockaddr_convert_from_un(child_si
,
2638 un_my_addr
.sa_socklen
,
2641 &in_my_addr
.sa_socklen
);
2649 SWRAP_LOG(SWRAP_LOG_TRACE
,
2650 "accept() path=%s, fd=%d",
2651 un_my_addr
.sa
.un
.sun_path
, s
);
2653 child_si
->myname
= (struct swrap_address
) {
2654 .sa_socklen
= in_my_addr
.sa_socklen
,
2656 memcpy(&child_si
->myname
.sa
.ss
, &in_my_addr
.sa
.ss
, in_my_addr
.sa_socklen
);
2658 SWRAP_DLIST_ADD(sockets
, child_si
);
2661 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2662 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2663 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2669 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2670 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2672 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2675 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2678 static int autobind_start_init
;
2679 static int autobind_start
;
2681 /* using sendto() or connect() on an unbound socket would give the
2682 recipient no way to reply, as unlike UDP and TCP, a unix domain
2683 socket can't auto-assign ephemeral port numbers, so we need to
2685 Note: this might change the family from ipv6 to ipv4
2687 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2689 struct swrap_address un_addr
= {
2690 .sa_socklen
= sizeof(struct sockaddr_un
),
2698 if (autobind_start_init
!= 1) {
2699 autobind_start_init
= 1;
2700 autobind_start
= getpid();
2701 autobind_start
%= 50000;
2702 autobind_start
+= 10000;
2705 un_addr
.sa
.un
.sun_family
= AF_UNIX
;
2709 struct sockaddr_in in
;
2713 type
= SOCKET_TYPE_CHAR_TCP
;
2716 type
= SOCKET_TYPE_CHAR_UDP
;
2719 errno
= ESOCKTNOSUPPORT
;
2723 memset(&in
, 0, sizeof(in
));
2724 in
.sin_family
= AF_INET
;
2725 in
.sin_addr
.s_addr
= htonl(127<<24 |
2726 socket_wrapper_default_iface());
2728 si
->myname
= (struct swrap_address
) {
2729 .sa_socklen
= sizeof(in
),
2731 memcpy(&si
->myname
.sa
.in
, &in
, si
->myname
.sa_socklen
);
2736 struct sockaddr_in6 in6
;
2738 if (si
->family
!= family
) {
2739 errno
= ENETUNREACH
;
2745 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2748 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2751 errno
= ESOCKTNOSUPPORT
;
2755 memset(&in6
, 0, sizeof(in6
));
2756 in6
.sin6_family
= AF_INET6
;
2757 in6
.sin6_addr
= *swrap_ipv6();
2758 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2760 si
->myname
= (struct swrap_address
) {
2761 .sa_socklen
= sizeof(in6
),
2763 memcpy(&si
->myname
.sa
.in6
, &in6
, si
->myname
.sa_socklen
);
2768 errno
= ESOCKTNOSUPPORT
;
2772 if (autobind_start
> 60000) {
2773 autobind_start
= 10000;
2776 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2777 port
= autobind_start
+ i
;
2778 snprintf(un_addr
.sa
.un
.sun_path
, sizeof(un_addr
.sa
.un
.sun_path
),
2779 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2780 type
, socket_wrapper_default_iface(), port
);
2781 if (stat(un_addr
.sa
.un
.sun_path
, &st
) == 0) continue;
2783 ret
= libc_bind(fd
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
2784 if (ret
== -1) return ret
;
2786 si
->un_addr
= un_addr
.sa
.un
;
2789 autobind_start
= port
+ 1;
2792 if (i
== SOCKET_MAX_SOCKETS
) {
2793 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2794 "interface "SOCKET_FORMAT
,
2797 socket_wrapper_default_iface(),
2803 si
->family
= family
;
2804 set_port(si
->family
, port
, &si
->myname
);
2809 /****************************************************************************
2811 ***************************************************************************/
2813 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2817 struct swrap_address un_addr
= {
2818 .sa_socklen
= sizeof(struct sockaddr_un
),
2820 struct socket_info
*si
= find_socket_info(s
);
2824 return libc_connect(s
, serv_addr
, addrlen
);
2827 if (si
->bound
== 0) {
2828 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2829 if (ret
== -1) return -1;
2832 if (si
->family
!= serv_addr
->sa_family
) {
2837 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2838 addrlen
, &un_addr
.sa
.un
, 0, &bcast
);
2839 if (ret
== -1) return -1;
2842 errno
= ENETUNREACH
;
2846 if (si
->type
== SOCK_DGRAM
) {
2847 si
->defer_connect
= 1;
2850 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2852 ret
= libc_connect(s
,
2854 un_addr
.sa_socklen
);
2857 SWRAP_LOG(SWRAP_LOG_TRACE
,
2858 "connect() path=%s, fd=%d",
2859 un_addr
.sa
.un
.sun_path
, s
);
2862 /* to give better errors */
2863 if (ret
== -1 && errno
== ENOENT
) {
2864 errno
= EHOSTUNREACH
;
2868 si
->peername
= (struct swrap_address
) {
2869 .sa_socklen
= addrlen
,
2872 memcpy(&si
->peername
.sa
.ss
, serv_addr
, addrlen
);
2876 * When we connect() on a socket than we have to bind the
2877 * outgoing connection on the interface we use for the
2878 * transport. We already bound it on the right interface
2879 * but here we have to update the name so getsockname()
2880 * returns correct information.
2882 if (si
->bindname
.sa_socklen
> 0) {
2883 si
->myname
= (struct swrap_address
) {
2884 .sa_socklen
= si
->bindname
.sa_socklen
,
2887 memcpy(&si
->myname
.sa
.ss
,
2888 &si
->bindname
.sa
.ss
,
2889 si
->bindname
.sa_socklen
);
2891 /* Cleanup bindname */
2892 si
->bindname
= (struct swrap_address
) {
2897 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2898 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2900 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2906 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2908 return swrap_connect(s
, serv_addr
, addrlen
);
2911 /****************************************************************************
2913 ***************************************************************************/
2915 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2918 struct swrap_address un_addr
= {
2919 .sa_socklen
= sizeof(struct sockaddr_un
),
2921 struct socket_info
*si
= find_socket_info(s
);
2928 return libc_bind(s
, myaddr
, addrlen
);
2931 switch (si
->family
) {
2933 const struct sockaddr_in
*sin
;
2934 if (addrlen
< sizeof(struct sockaddr_in
)) {
2935 bind_error
= EINVAL
;
2939 sin
= (const struct sockaddr_in
*)(const void *)myaddr
;
2941 if (sin
->sin_family
!= AF_INET
) {
2942 bind_error
= EAFNOSUPPORT
;
2945 /* special case for AF_UNSPEC */
2946 if (sin
->sin_family
== AF_UNSPEC
&&
2947 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
2956 const struct sockaddr_in6
*sin6
;
2957 if (addrlen
< sizeof(struct sockaddr_in6
)) {
2958 bind_error
= EINVAL
;
2962 sin6
= (const struct sockaddr_in6
*)(const void *)myaddr
;
2964 if (sin6
->sin6_family
!= AF_INET6
) {
2965 bind_error
= EAFNOSUPPORT
;
2972 bind_error
= EINVAL
;
2976 if (bind_error
!= 0) {
2982 in_use
= check_addr_port_in_use(myaddr
, addrlen
);
2989 si
->myname
.sa_socklen
= addrlen
;
2990 memcpy(&si
->myname
.sa
.ss
, myaddr
, addrlen
);
2992 ret
= sockaddr_convert_to_un(si
,
2998 if (ret
== -1) return -1;
3000 unlink(un_addr
.sa
.un
.sun_path
);
3002 ret
= libc_bind(s
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
3004 SWRAP_LOG(SWRAP_LOG_TRACE
,
3005 "bind() path=%s, fd=%d",
3006 un_addr
.sa
.un
.sun_path
, s
);
3015 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
3017 return swrap_bind(s
, myaddr
, addrlen
);
3020 /****************************************************************************
3022 ***************************************************************************/
3024 #ifdef HAVE_BINDRESVPORT
3025 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
3027 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
3029 struct swrap_address myaddr
= {
3030 .sa_socklen
= sizeof(struct sockaddr_storage
),
3033 static uint16_t port
;
3038 #define SWRAP_STARTPORT 600
3039 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3040 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3043 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
3047 salen
= myaddr
.sa_socklen
;
3050 rc
= swrap_getsockname(sd
, &myaddr
.sa
.s
, &salen
);
3056 memset(&myaddr
.sa
.ss
, 0, salen
);
3061 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
3064 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)(void *)sa
;
3066 salen
= sizeof(struct sockaddr_in
);
3067 sinp
->sin_port
= htons(port
);
3071 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)(void *)sa
;
3073 salen
= sizeof(struct sockaddr_in6
);
3074 sin6p
->sin6_port
= htons(port
);
3078 errno
= EAFNOSUPPORT
;
3083 if (port
> SWRAP_ENDPORT
) {
3084 port
= SWRAP_STARTPORT
;
3087 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
3088 if (rc
== 0 || errno
!= EADDRINUSE
) {
3096 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
3098 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
3102 /****************************************************************************
3104 ***************************************************************************/
3106 static int swrap_listen(int s
, int backlog
)
3109 struct socket_info
*si
= find_socket_info(s
);
3112 return libc_listen(s
, backlog
);
3115 ret
= libc_listen(s
, backlog
);
3120 int listen(int s
, int backlog
)
3122 return swrap_listen(s
, backlog
);
3125 /****************************************************************************
3127 ***************************************************************************/
3129 static FILE *swrap_fopen(const char *name
, const char *mode
)
3133 fp
= libc_fopen(name
, mode
);
3135 int fd
= fileno(fp
);
3137 swrap_remove_stale(fd
);
3143 FILE *fopen(const char *name
, const char *mode
)
3145 return swrap_fopen(name
, mode
);
3148 /****************************************************************************
3150 ***************************************************************************/
3152 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
3156 ret
= libc_vopen(pathname
, flags
, ap
);
3159 * There are methods for closing descriptors (libc-internal code
3160 * paths, direct syscalls) which close descriptors in ways that
3161 * we can't intercept, so try to recover when we notice that
3164 swrap_remove_stale(ret
);
3169 int open(const char *pathname
, int flags
, ...)
3174 va_start(ap
, flags
);
3175 fd
= swrap_vopen(pathname
, flags
, ap
);
3181 /****************************************************************************
3183 ***************************************************************************/
3185 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3187 struct socket_info
*si
= find_socket_info(s
);
3191 return libc_getpeername(s
, name
, addrlen
);
3194 if (si
->peername
.sa_socklen
== 0)
3200 len
= MIN(*addrlen
, si
->peername
.sa_socklen
);
3205 memcpy(name
, &si
->peername
.sa
.ss
, len
);
3206 *addrlen
= si
->peername
.sa_socklen
;
3211 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3212 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3214 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3217 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
3220 /****************************************************************************
3222 ***************************************************************************/
3224 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3226 struct socket_info
*si
= find_socket_info(s
);
3230 return libc_getsockname(s
, name
, addrlen
);
3233 len
= MIN(*addrlen
, si
->myname
.sa_socklen
);
3238 memcpy(name
, &si
->myname
.sa
.ss
, len
);
3239 *addrlen
= si
->myname
.sa_socklen
;
3244 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3245 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3247 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3250 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
3253 /****************************************************************************
3255 ***************************************************************************/
3258 # ifdef SO_PROTOTYPE /* The Solaris name */
3259 # define SO_PROTOCOL SO_PROTOTYPE
3260 # endif /* SO_PROTOTYPE */
3261 #endif /* SO_PROTOCOL */
3263 static int swrap_getsockopt(int s
, int level
, int optname
,
3264 void *optval
, socklen_t
*optlen
)
3266 struct socket_info
*si
= find_socket_info(s
);
3269 return libc_getsockopt(s
,
3276 if (level
== SOL_SOCKET
) {
3280 if (optval
== NULL
|| optlen
== NULL
||
3281 *optlen
< (socklen_t
)sizeof(int)) {
3286 *optlen
= sizeof(int);
3287 *(int *)optval
= si
->family
;
3289 #endif /* SO_DOMAIN */
3293 if (optval
== NULL
|| optlen
== NULL
||
3294 *optlen
< (socklen_t
)sizeof(int)) {
3299 *optlen
= sizeof(int);
3300 *(int *)optval
= si
->protocol
;
3302 #endif /* SO_PROTOCOL */
3304 if (optval
== NULL
|| optlen
== NULL
||
3305 *optlen
< (socklen_t
)sizeof(int)) {
3310 *optlen
= sizeof(int);
3311 *(int *)optval
= si
->type
;
3314 return libc_getsockopt(s
,
3322 errno
= ENOPROTOOPT
;
3326 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3327 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
3329 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
3332 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
3335 /****************************************************************************
3337 ***************************************************************************/
3339 static int swrap_setsockopt(int s
, int level
, int optname
,
3340 const void *optval
, socklen_t optlen
)
3342 struct socket_info
*si
= find_socket_info(s
);
3345 return libc_setsockopt(s
,
3352 if (level
== SOL_SOCKET
) {
3353 return libc_setsockopt(s
,
3360 switch (si
->family
) {
3362 if (level
== IPPROTO_IP
) {
3364 if (optname
== IP_PKTINFO
) {
3365 si
->pktinfo
= AF_INET
;
3367 #endif /* IP_PKTINFO */
3372 if (level
== IPPROTO_IPV6
) {
3373 #ifdef IPV6_RECVPKTINFO
3374 if (optname
== IPV6_RECVPKTINFO
) {
3375 si
->pktinfo
= AF_INET6
;
3377 #endif /* IPV6_PKTINFO */
3382 errno
= ENOPROTOOPT
;
3387 int setsockopt(int s
, int level
, int optname
,
3388 const void *optval
, socklen_t optlen
)
3390 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
3393 /****************************************************************************
3395 ***************************************************************************/
3397 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
3399 struct socket_info
*si
= find_socket_info(s
);
3405 return libc_vioctl(s
, r
, va
);
3410 rc
= libc_vioctl(s
, r
, va
);
3414 value
= *((int *)va_arg(ap
, int *));
3416 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
3417 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3418 } else if (value
== 0) { /* END OF FILE */
3419 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3429 #ifdef HAVE_IOCTL_INT
3430 int ioctl(int s
, int r
, ...)
3432 int ioctl(int s
, unsigned long int r
, ...)
3440 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
3451 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3454 # ifdef _ALIGN /* BSD */
3455 #define CMSG_ALIGN _ALIGN
3457 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3458 # endif /* _ALIGN */
3459 #endif /* CMSG_ALIGN */
3462 * @brief Add a cmsghdr to a msghdr.
3464 * This is an function to add any type of cmsghdr. It will operate on the
3465 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3466 * the buffer position after the added cmsg element. Hence, this function is
3467 * intended to be used with an intermediate msghdr and not on the original
3468 * one handed in by the client.
3470 * @param[in] msg The msghdr to which to add the cmsg.
3472 * @param[in] level The cmsg level to set.
3474 * @param[in] type The cmsg type to set.
3476 * @param[in] data The cmsg data to set.
3478 * @param[in] len the length of the data to set.
3480 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3486 size_t cmlen
= CMSG_LEN(len
);
3487 size_t cmspace
= CMSG_SPACE(len
);
3488 uint8_t cmbuf
[cmspace
];
3489 void *cast_ptr
= (void *)cmbuf
;
3490 struct cmsghdr
*cm
= (struct cmsghdr
*)cast_ptr
;
3493 memset(cmbuf
, 0, cmspace
);
3495 if (msg
->msg_controllen
< cmlen
) {
3496 cmlen
= msg
->msg_controllen
;
3497 msg
->msg_flags
|= MSG_CTRUNC
;
3500 if (msg
->msg_controllen
< cmspace
) {
3501 cmspace
= msg
->msg_controllen
;
3505 * We copy the full input data into an intermediate cmsghdr first
3506 * in order to more easily cope with truncation.
3508 cm
->cmsg_len
= cmlen
;
3509 cm
->cmsg_level
= level
;
3510 cm
->cmsg_type
= type
;
3511 memcpy(CMSG_DATA(cm
), data
, len
);
3514 * We now copy the possibly truncated buffer.
3515 * We copy cmlen bytes, but consume cmspace bytes,
3516 * leaving the possible padding uninitialiazed.
3518 p
= (uint8_t *)msg
->msg_control
;
3519 memcpy(p
, cm
, cmlen
);
3521 msg
->msg_control
= p
;
3522 msg
->msg_controllen
-= cmspace
;
3527 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3530 /* Add packet info */
3531 switch (si
->pktinfo
) {
3532 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3534 struct sockaddr_in
*sin
;
3535 #if defined(HAVE_STRUCT_IN_PKTINFO)
3536 struct in_pktinfo pkt
;
3537 #elif defined(IP_RECVDSTADDR)
3541 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in
)) {
3542 sin
= &si
->bindname
.sa
.in
;
3544 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in
)) {
3547 sin
= &si
->myname
.sa
.in
;
3552 #if defined(HAVE_STRUCT_IN_PKTINFO)
3553 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3554 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3555 #elif defined(IP_RECVDSTADDR)
3556 pkt
= sin
->sin_addr
;
3559 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3564 #endif /* IP_PKTINFO */
3565 #if defined(HAVE_IPV6)
3567 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3568 struct sockaddr_in6
*sin6
;
3569 struct in6_pktinfo pkt6
;
3571 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in6
)) {
3572 sin6
= &si
->bindname
.sa
.in6
;
3574 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in6
)) {
3577 sin6
= &si
->myname
.sa
.in6
;
3582 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3583 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3585 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3586 &pkt6
, sizeof(pkt6
));
3587 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3591 #endif /* IPV6_PKTINFO */
3599 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3600 struct msghdr
*omsg
)
3604 if (si
->pktinfo
> 0) {
3605 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3611 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3613 size_t *cm_data_space
);
3614 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3616 size_t *cm_data_space
);
3618 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
3620 size_t *cm_data_space
) {
3621 struct cmsghdr
*cmsg
;
3625 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
3629 for (cmsg
= CMSG_FIRSTHDR(msg
);
3631 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
3632 switch (cmsg
->cmsg_level
) {
3634 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
3639 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
3649 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3651 size_t *cm_data_space
)
3658 CMSG_SPACE(cmsg
->cmsg_len
- CMSG_ALIGN(sizeof(struct cmsghdr
)));
3660 p
= realloc((*cm_data
), cmspace
);
3666 p
= (*cm_data
) + (*cm_data_space
);
3667 *cm_data_space
= cmspace
;
3669 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
3674 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3676 size_t *cm_data_space
);
3679 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3681 size_t *cm_data_space
)
3685 switch(cmsg
->cmsg_type
) {
3688 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3695 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3707 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3709 size_t *cm_data_space
)
3711 (void)cmsg
; /* unused */
3712 (void)cm_data
; /* unused */
3713 (void)cm_data_space
; /* unused */
3716 * Passing a IP pktinfo to a unix socket might be rejected by the
3717 * Kernel, at least on FreeBSD. So skip this cmsg.
3721 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3723 static ssize_t
swrap_sendmsg_before(int fd
,
3724 struct socket_info
*si
,
3726 struct iovec
*tmp_iov
,
3727 struct sockaddr_un
*tmp_un
,
3728 const struct sockaddr_un
**to_un
,
3729 const struct sockaddr
**to
,
3747 if (!si
->connected
) {
3752 if (msg
->msg_iovlen
== 0) {
3756 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3758 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3759 if (nlen
> SOCKET_MAX_PACKET
) {
3763 msg
->msg_iovlen
= i
;
3764 if (msg
->msg_iovlen
== 0) {
3765 *tmp_iov
= msg
->msg_iov
[0];
3766 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3767 msg
->msg_iov
= tmp_iov
;
3768 msg
->msg_iovlen
= 1;
3773 if (si
->connected
) {
3774 if (msg
->msg_name
) {
3779 const struct sockaddr
*msg_name
;
3780 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3782 if (msg_name
== NULL
) {
3788 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3790 if (ret
== -1) return -1;
3798 msg
->msg_name
= tmp_un
;
3799 msg
->msg_namelen
= sizeof(*tmp_un
);
3802 if (si
->bound
== 0) {
3803 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3805 if (errno
== ENOTSOCK
) {
3806 swrap_remove_stale(fd
);
3809 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3815 if (!si
->defer_connect
) {
3819 ret
= sockaddr_convert_to_un(si
,
3821 si
->peername
.sa_socklen
,
3825 if (ret
== -1) return -1;
3827 ret
= libc_connect(fd
,
3828 (struct sockaddr
*)(void *)tmp_un
,
3831 /* to give better errors */
3832 if (ret
== -1 && errno
== ENOENT
) {
3833 errno
= EHOSTUNREACH
;
3840 si
->defer_connect
= 0;
3843 errno
= EHOSTUNREACH
;
3847 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3848 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
3849 uint8_t *cmbuf
= NULL
;
3852 ret
= swrap_sendmsg_filter_cmsghdr(msg
, &cmbuf
, &cmlen
);
3859 msg
->msg_controllen
= 0;
3860 msg
->msg_control
= NULL
;
3861 } else if (cmlen
< msg
->msg_controllen
&& cmbuf
!= NULL
) {
3862 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
3863 msg
->msg_controllen
= cmlen
;
3872 static void swrap_sendmsg_after(int fd
,
3873 struct socket_info
*si
,
3875 const struct sockaddr
*to
,
3878 int saved_errno
= errno
;
3885 /* to give better errors */
3887 if (saved_errno
== ENOENT
) {
3888 saved_errno
= EHOSTUNREACH
;
3889 } else if (saved_errno
== ENOTSOCK
) {
3890 /* If the fd is not a socket, remove it */
3891 swrap_remove_stale(fd
);
3895 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3896 avail
+= msg
->msg_iov
[i
].iov_len
;
3900 remain
= MIN(80, avail
);
3905 /* we capture it as one single packet */
3906 buf
= (uint8_t *)malloc(remain
);
3908 /* we just not capture the packet */
3909 errno
= saved_errno
;
3913 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3914 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3916 msg
->msg_iov
[i
].iov_base
,
3919 remain
-= this_time
;
3926 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3927 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3929 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3934 if (si
->connected
) {
3935 to
= &si
->peername
.sa
.s
;
3938 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3939 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3941 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3947 errno
= saved_errno
;
3950 static int swrap_recvmsg_before(int fd
,
3951 struct socket_info
*si
,
3953 struct iovec
*tmp_iov
)
3958 (void)fd
; /* unused */
3962 if (!si
->connected
) {
3967 if (msg
->msg_iovlen
== 0) {
3971 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3973 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3974 if (nlen
> SOCKET_MAX_PACKET
) {
3978 msg
->msg_iovlen
= i
;
3979 if (msg
->msg_iovlen
== 0) {
3980 *tmp_iov
= msg
->msg_iov
[0];
3981 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3982 msg
->msg_iov
= tmp_iov
;
3983 msg
->msg_iovlen
= 1;
3988 if (msg
->msg_name
== NULL
) {
3993 if (msg
->msg_iovlen
== 0) {
3997 if (si
->bound
== 0) {
3998 ret
= swrap_auto_bind(fd
, si
, si
->family
);
4001 * When attempting to read or write to a
4002 * descriptor, if an underlying autobind fails
4003 * because it's not a socket, stop intercepting
4004 * uses of that descriptor.
4006 if (errno
== ENOTSOCK
) {
4007 swrap_remove_stale(fd
);
4010 SWRAP_LOG(SWRAP_LOG_ERROR
,
4011 "swrap_recvmsg_before failed");
4018 errno
= EHOSTUNREACH
;
4025 static int swrap_recvmsg_after(int fd
,
4026 struct socket_info
*si
,
4028 const struct sockaddr_un
*un_addr
,
4029 socklen_t un_addrlen
,
4032 int saved_errno
= errno
;
4034 uint8_t *buf
= NULL
;
4040 /* to give better errors */
4042 if (saved_errno
== ENOENT
) {
4043 saved_errno
= EHOSTUNREACH
;
4044 } else if (saved_errno
== ENOTSOCK
) {
4045 /* If the fd is not a socket, remove it */
4046 swrap_remove_stale(fd
);
4050 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4051 avail
+= msg
->msg_iov
[i
].iov_len
;
4060 remain
= MIN(80, avail
);
4065 /* we capture it as one single packet */
4066 buf
= (uint8_t *)malloc(remain
);
4068 /* we just not capture the packet */
4069 errno
= saved_errno
;
4073 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4074 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
4076 msg
->msg_iov
[i
].iov_base
,
4079 remain
-= this_time
;
4084 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
4085 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4086 } else if (ret
== 0) { /* END OF FILE */
4087 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4088 } else if (ret
> 0) {
4089 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
4098 if (un_addr
!= NULL
) {
4099 rc
= sockaddr_convert_from_un(si
,
4109 swrap_pcap_dump_packet(si
,
4115 swrap_pcap_dump_packet(si
,
4128 errno
= saved_errno
;
4130 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4132 msg
->msg_controllen
> 0 &&
4133 msg
->msg_control
!= NULL
) {
4134 rc
= swrap_msghdr_add_socket_info(si
, msg
);
4144 /****************************************************************************
4146 ***************************************************************************/
4148 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
4149 struct sockaddr
*from
, socklen_t
*fromlen
)
4151 struct swrap_address from_addr
= {
4152 .sa_socklen
= sizeof(struct sockaddr_un
),
4155 struct socket_info
*si
= find_socket_info(s
);
4156 struct swrap_address saddr
= {
4157 .sa_socklen
= sizeof(struct sockaddr_storage
),
4164 return libc_recvfrom(s
,
4176 if (from
!= NULL
&& fromlen
!= NULL
) {
4177 msg
.msg_name
= from
; /* optional address */
4178 msg
.msg_namelen
= *fromlen
; /* size of address */
4180 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4181 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4183 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4184 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4185 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4186 msg
.msg_control
= NULL
; /* ancillary data, see below */
4187 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4188 msg
.msg_flags
= 0; /* flags on received message */
4191 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4196 buf
= msg
.msg_iov
[0].iov_base
;
4197 len
= msg
.msg_iov
[0].iov_len
;
4199 ret
= libc_recvfrom(s
,
4204 &from_addr
.sa_socklen
);
4209 tret
= swrap_recvmsg_after(s
,
4213 from_addr
.sa_socklen
,
4219 if (from
!= NULL
&& fromlen
!= NULL
) {
4220 *fromlen
= msg
.msg_namelen
;
4226 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4227 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4228 struct sockaddr
*from
, Psocklen_t fromlen
)
4230 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4231 struct sockaddr
*from
, socklen_t
*fromlen
)
4234 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
4237 /****************************************************************************
4239 ***************************************************************************/
4241 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
4242 const struct sockaddr
*to
, socklen_t tolen
)
4246 struct swrap_address un_addr
= {
4247 .sa_socklen
= sizeof(struct sockaddr_un
),
4249 const struct sockaddr_un
*to_un
= NULL
;
4252 struct socket_info
*si
= find_socket_info(s
);
4256 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
4259 tmp
.iov_base
= discard_const_p(char, buf
);
4263 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
4264 msg
.msg_namelen
= tolen
; /* size of address */
4265 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4266 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4267 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4268 msg
.msg_control
= NULL
; /* ancillary data, see below */
4269 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4270 msg
.msg_flags
= 0; /* flags on received message */
4273 rc
= swrap_sendmsg_before(s
,
4285 buf
= msg
.msg_iov
[0].iov_base
;
4286 len
= msg
.msg_iov
[0].iov_len
;
4291 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
4294 type
= SOCKET_TYPE_CHAR_UDP
;
4296 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4297 snprintf(un_addr
.sa
.un
.sun_path
,
4298 sizeof(un_addr
.sa
.un
.sun_path
),
4300 socket_wrapper_dir(), type
, iface
, prt
);
4301 if (stat(un_addr
.sa
.un
.sun_path
, &st
) != 0) continue;
4303 /* ignore the any errors in broadcast sends */
4309 un_addr
.sa_socklen
);
4312 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4317 ret
= libc_sendto(s
,
4321 (struct sockaddr
*)msg
.msg_name
,
4324 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4329 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
4330 const struct sockaddr
*to
, socklen_t tolen
)
4332 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
4335 /****************************************************************************
4337 ***************************************************************************/
4339 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
4341 struct socket_info
*si
;
4343 struct swrap_address saddr
= {
4344 .sa_socklen
= sizeof(struct sockaddr_storage
),
4350 si
= find_socket_info(s
);
4352 return libc_recv(s
, buf
, len
, flags
);
4359 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4360 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4361 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4362 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4363 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4364 msg
.msg_control
= NULL
; /* ancillary data, see below */
4365 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4366 msg
.msg_flags
= 0; /* flags on received message */
4369 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4374 buf
= msg
.msg_iov
[0].iov_base
;
4375 len
= msg
.msg_iov
[0].iov_len
;
4377 ret
= libc_recv(s
, buf
, len
, flags
);
4379 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4387 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
4389 return swrap_recv(s
, buf
, len
, flags
);
4392 /****************************************************************************
4394 ***************************************************************************/
4396 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
4398 struct socket_info
*si
;
4401 struct swrap_address saddr
= {
4402 .sa_socklen
= sizeof(struct sockaddr_storage
),
4407 si
= find_socket_info(s
);
4409 return libc_read(s
, buf
, len
);
4416 msg
.msg_name
= &saddr
.sa
.ss
; /* optional address */
4417 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4418 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4419 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4420 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4421 msg
.msg_control
= NULL
; /* ancillary data, see below */
4422 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4423 msg
.msg_flags
= 0; /* flags on received message */
4426 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4428 if (tret
== -ENOTSOCK
) {
4429 return libc_read(s
, buf
, len
);
4434 buf
= msg
.msg_iov
[0].iov_base
;
4435 len
= msg
.msg_iov
[0].iov_len
;
4437 ret
= libc_read(s
, buf
, len
);
4439 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4447 ssize_t
read(int s
, void *buf
, size_t len
)
4449 return swrap_read(s
, buf
, len
);
4452 /****************************************************************************
4454 ***************************************************************************/
4456 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
4460 struct sockaddr_un un_addr
;
4463 struct socket_info
*si
= find_socket_info(s
);
4466 return libc_send(s
, buf
, len
, flags
);
4469 tmp
.iov_base
= discard_const_p(char, buf
);
4473 msg
.msg_name
= NULL
; /* optional address */
4474 msg
.msg_namelen
= 0; /* size of address */
4475 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4476 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4477 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4478 msg
.msg_control
= NULL
; /* ancillary data, see below */
4479 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4480 msg
.msg_flags
= 0; /* flags on received message */
4483 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4488 buf
= msg
.msg_iov
[0].iov_base
;
4489 len
= msg
.msg_iov
[0].iov_len
;
4491 ret
= libc_send(s
, buf
, len
, flags
);
4493 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4498 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
4500 return swrap_send(s
, buf
, len
, flags
);
4503 /****************************************************************************
4505 ***************************************************************************/
4507 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
4509 struct swrap_address from_addr
= {
4510 .sa_socklen
= sizeof(struct sockaddr_un
),
4512 struct socket_info
*si
;
4515 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4516 size_t msg_ctrllen_filled
;
4517 size_t msg_ctrllen_left
;
4523 si
= find_socket_info(s
);
4525 return libc_recvmsg(s
, omsg
, flags
);
4528 tmp
.iov_base
= NULL
;
4532 msg
.msg_name
= &from_addr
.sa
; /* optional address */
4533 msg
.msg_namelen
= from_addr
.sa_socklen
; /* size of address */
4534 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4535 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4536 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4537 msg_ctrllen_filled
= 0;
4538 msg_ctrllen_left
= omsg
->msg_controllen
;
4540 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
4541 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4542 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4545 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4550 ret
= libc_recvmsg(s
, &msg
, flags
);
4552 msg
.msg_name
= omsg
->msg_name
;
4553 msg
.msg_namelen
= omsg
->msg_namelen
;
4555 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4556 msg_ctrllen_filled
+= msg
.msg_controllen
;
4557 msg_ctrllen_left
-= msg
.msg_controllen
;
4559 if (omsg
->msg_control
!= NULL
) {
4562 p
= omsg
->msg_control
;
4563 p
+= msg_ctrllen_filled
;
4565 msg
.msg_control
= p
;
4566 msg
.msg_controllen
= msg_ctrllen_left
;
4568 msg
.msg_control
= NULL
;
4569 msg
.msg_controllen
= 0;
4573 rc
= swrap_recvmsg_after(s
,
4577 from_addr
.sa_socklen
,
4583 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4584 if (omsg
->msg_control
!= NULL
) {
4585 /* msg.msg_controllen = space left */
4586 msg_ctrllen_left
= msg
.msg_controllen
;
4587 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
4590 /* Update the original message length */
4591 omsg
->msg_controllen
= msg_ctrllen_filled
;
4592 omsg
->msg_flags
= msg
.msg_flags
;
4594 omsg
->msg_iovlen
= msg
.msg_iovlen
;
4599 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
4601 return swrap_recvmsg(sockfd
, msg
, flags
);
4604 /****************************************************************************
4606 ***************************************************************************/
4608 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4612 struct sockaddr_un un_addr
;
4613 const struct sockaddr_un
*to_un
= NULL
;
4614 const struct sockaddr
*to
= NULL
;
4617 struct socket_info
*si
= find_socket_info(s
);
4621 return libc_sendmsg(s
, omsg
, flags
);
4624 ZERO_STRUCT(un_addr
);
4626 tmp
.iov_base
= NULL
;
4630 msg
.msg_name
= omsg
->msg_name
; /* optional address */
4631 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
4632 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4633 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4634 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4635 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
4636 /* omsg is a const so use a local buffer for modifications */
4637 uint8_t cmbuf
[omsg
->msg_controllen
];
4639 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
4641 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
4642 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4644 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4647 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4655 unsigned int prt
= ntohs(((const struct sockaddr_in
*)(const void *)to
)->sin_port
);
4663 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4664 avail
+= msg
.msg_iov
[i
].iov_len
;
4670 /* we capture it as one single packet */
4671 buf
= (uint8_t *)malloc(remain
);
4676 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4677 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4679 msg
.msg_iov
[i
].iov_base
,
4682 remain
-= this_time
;
4685 type
= SOCKET_TYPE_CHAR_UDP
;
4687 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4688 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4689 socket_wrapper_dir(), type
, iface
, prt
);
4690 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4692 msg
.msg_name
= &un_addr
; /* optional address */
4693 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4695 /* ignore the any errors in broadcast sends */
4696 libc_sendmsg(s
, &msg
, flags
);
4699 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4705 ret
= libc_sendmsg(s
, &msg
, flags
);
4707 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4712 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4714 return swrap_sendmsg(s
, omsg
, flags
);
4717 /****************************************************************************
4719 ***************************************************************************/
4721 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4723 struct socket_info
*si
;
4726 struct swrap_address saddr
= {
4727 .sa_socklen
= sizeof(struct sockaddr_storage
)
4732 si
= find_socket_info(s
);
4734 return libc_readv(s
, vector
, count
);
4737 tmp
.iov_base
= NULL
;
4741 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4742 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4743 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4744 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4745 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4746 msg
.msg_control
= NULL
; /* ancillary data, see below */
4747 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4748 msg
.msg_flags
= 0; /* flags on received message */
4751 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4753 if (rc
== -ENOTSOCK
) {
4754 return libc_readv(s
, vector
, count
);
4759 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4761 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4769 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4771 return swrap_readv(s
, vector
, count
);
4774 /****************************************************************************
4776 ***************************************************************************/
4778 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4782 struct sockaddr_un un_addr
;
4785 struct socket_info
*si
= find_socket_info(s
);
4788 return libc_writev(s
, vector
, count
);
4791 tmp
.iov_base
= NULL
;
4795 msg
.msg_name
= NULL
; /* optional address */
4796 msg
.msg_namelen
= 0; /* size of address */
4797 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4798 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4799 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4800 msg
.msg_control
= NULL
; /* ancillary data, see below */
4801 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4802 msg
.msg_flags
= 0; /* flags on received message */
4805 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4807 if (rc
== -ENOTSOCK
) {
4808 return libc_readv(s
, vector
, count
);
4813 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4815 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4820 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4822 return swrap_writev(s
, vector
, count
);
4825 /****************************
4827 ***************************/
4829 static int swrap_close(int fd
)
4831 struct socket_info
*si
= find_socket_info(fd
);
4832 struct socket_info_fd
*fi
;
4836 return libc_close(fd
);
4839 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4841 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4848 /* there are still references left */
4849 return libc_close(fd
);
4852 SWRAP_DLIST_REMOVE(sockets
, si
);
4854 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
4855 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4858 ret
= libc_close(fd
);
4860 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
4861 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4862 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4865 if (si
->un_addr
.sun_path
[0] != '\0') {
4866 unlink(si
->un_addr
.sun_path
);
4875 return swrap_close(fd
);
4878 /****************************
4880 ***************************/
4882 static int swrap_dup(int fd
)
4884 struct socket_info
*si
;
4885 struct socket_info_fd
*fi
;
4887 si
= find_socket_info(fd
);
4890 return libc_dup(fd
);
4893 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4899 fi
->fd
= libc_dup(fd
);
4901 int saved_errno
= errno
;
4903 errno
= saved_errno
;
4907 /* Make sure we don't have an entry for the fd */
4908 swrap_remove_stale(fi
->fd
);
4910 SWRAP_DLIST_ADD(si
->fds
, fi
);
4916 return swrap_dup(fd
);
4919 /****************************
4921 ***************************/
4923 static int swrap_dup2(int fd
, int newfd
)
4925 struct socket_info
*si
;
4926 struct socket_info_fd
*fi
;
4928 si
= find_socket_info(fd
);
4931 return libc_dup2(fd
, newfd
);
4934 if (find_socket_info(newfd
)) {
4935 /* dup2() does an implicit close of newfd, which we
4936 * need to emulate */
4940 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4946 fi
->fd
= libc_dup2(fd
, newfd
);
4948 int saved_errno
= errno
;
4950 errno
= saved_errno
;
4954 /* Make sure we don't have an entry for the fd */
4955 swrap_remove_stale(fi
->fd
);
4957 SWRAP_DLIST_ADD(si
->fds
, fi
);
4961 int dup2(int fd
, int newfd
)
4963 return swrap_dup2(fd
, newfd
);
4966 /****************************
4968 ***************************/
4970 static int swrap_vfcntl(int fd
, int cmd
, va_list va
)
4972 struct socket_info_fd
*fi
;
4973 struct socket_info
*si
;
4976 si
= find_socket_info(fd
);
4978 rc
= libc_vfcntl(fd
, cmd
, va
);
4985 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4991 fi
->fd
= libc_vfcntl(fd
, cmd
, va
);
4993 int saved_errno
= errno
;
4995 errno
= saved_errno
;
4999 /* Make sure we don't have an entry for the fd */
5000 swrap_remove_stale(fi
->fd
);
5002 SWRAP_DLIST_ADD(si
->fds
, fi
);
5007 rc
= libc_vfcntl(fd
, cmd
, va
);
5014 int fcntl(int fd
, int cmd
, ...)
5021 rc
= swrap_vfcntl(fd
, cmd
, va
);
5028 /****************************
5030 ***************************/
5033 static int swrap_eventfd(int count
, int flags
)
5037 fd
= libc_eventfd(count
, flags
);
5039 swrap_remove_stale(fd
);
5045 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5046 int eventfd(unsigned int count
, int flags
)
5048 int eventfd(int count
, int flags
)
5051 return swrap_eventfd(count
, flags
);
5055 /****************************
5057 ***************************/
5060 * This function is called when the library is unloaded and makes sure that
5061 * sockets get closed and the unix file for the socket are unlinked.
5063 void swrap_destructor(void)
5065 struct socket_info
*s
= sockets
;
5068 struct socket_info_fd
*f
= s
->fds
;