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_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
106 # define SWRAP_THREAD
110 #define MIN(a,b) ((a)<(b)?(a):(b))
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
118 #define ZERO_STRUCTP(x) do { \
120 memset((char *)(x), 0, sizeof(*(x))); \
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
150 #define SWRAP_DLIST_ADD(list,item) do { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
167 (list)->prev = NULL; \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct swrap_address
{
214 socklen_t sa_socklen
;
217 struct sockaddr_in in
;
219 struct sockaddr_in6 in6
;
221 struct sockaddr_un un
;
222 struct sockaddr_storage ss
;
226 struct socket_info_fd
{
227 struct socket_info_fd
*prev
, *next
;
233 struct socket_info_fd
*fds
;
245 /* The unix path so we can unlink it on close() */
246 struct sockaddr_un un_addr
;
248 struct swrap_address bindname
;
249 struct swrap_address myname
;
250 struct swrap_address peername
;
253 unsigned long pck_snd
;
254 unsigned long pck_rcv
;
257 struct socket_info
*prev
, *next
;
261 * File descriptors are shared between threads so we should share socket
264 struct socket_info
*sockets
;
266 /* Function prototypes */
268 bool socket_wrapper_enabled(void);
269 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
272 # define SWRAP_LOG(...)
275 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...) PRINTF_ATTRIBUTE(2, 3);
276 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
278 static void swrap_log(enum swrap_dbglvl_e dbglvl
, const char *format
, ...)
283 unsigned int lvl
= 0;
285 d
= getenv("SOCKET_WRAPPER_DEBUGLEVEL");
290 va_start(va
, format
);
291 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
296 case SWRAP_LOG_ERROR
:
298 "SWRAP_ERROR(%d): %s\n",
299 (int)getpid(), buffer
);
303 "SWRAP_WARN(%d): %s\n",
304 (int)getpid(), buffer
);
306 case SWRAP_LOG_DEBUG
:
308 "SWRAP_DEBUG(%d): %s\n",
309 (int)getpid(), buffer
);
311 case SWRAP_LOG_TRACE
:
313 "SWRAP_TRACE(%d): %s\n",
314 (int)getpid(), buffer
);
321 /*********************************************************
322 * SWRAP LOADING LIBC FUNCTIONS
323 *********************************************************/
327 struct swrap_libc_fns
{
328 int (*libc_accept
)(int sockfd
,
329 struct sockaddr
*addr
,
331 int (*libc_bind
)(int sockfd
,
332 const struct sockaddr
*addr
,
334 int (*libc_close
)(int fd
);
335 int (*libc_connect
)(int sockfd
,
336 const struct sockaddr
*addr
,
338 int (*libc_dup
)(int fd
);
339 int (*libc_dup2
)(int oldfd
, int newfd
);
340 FILE *(*libc_fopen
)(const char *name
, const char *mode
);
342 int (*libc_eventfd
)(int count
, int flags
);
344 int (*libc_getpeername
)(int sockfd
,
345 struct sockaddr
*addr
,
347 int (*libc_getsockname
)(int sockfd
,
348 struct sockaddr
*addr
,
350 int (*libc_getsockopt
)(int sockfd
,
355 int (*libc_ioctl
)(int d
, unsigned long int request
, ...);
356 int (*libc_listen
)(int sockfd
, int backlog
);
357 int (*libc_open
)(const char *pathname
, int flags
, mode_t mode
);
358 int (*libc_pipe
)(int pipefd
[2]);
359 int (*libc_read
)(int fd
, void *buf
, size_t count
);
360 ssize_t (*libc_readv
)(int fd
, const struct iovec
*iov
, int iovcnt
);
361 int (*libc_recv
)(int sockfd
, void *buf
, size_t len
, int flags
);
362 int (*libc_recvfrom
)(int sockfd
,
366 struct sockaddr
*src_addr
,
368 int (*libc_recvmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
369 int (*libc_send
)(int sockfd
, const void *buf
, size_t len
, int flags
);
370 int (*libc_sendmsg
)(int sockfd
, const struct msghdr
*msg
, int flags
);
371 int (*libc_sendto
)(int sockfd
,
375 const struct sockaddr
*dst_addr
,
377 int (*libc_setsockopt
)(int sockfd
,
383 int (*libc_signalfd
)(int fd
, const sigset_t
*mask
, int flags
);
385 int (*libc_socket
)(int domain
, int type
, int protocol
);
386 int (*libc_socketpair
)(int domain
, int type
, int protocol
, int sv
[2]);
387 #ifdef HAVE_TIMERFD_CREATE
388 int (*libc_timerfd_create
)(int clockid
, int flags
);
390 ssize_t (*libc_writev
)(int fd
, const struct iovec
*iov
, int iovcnt
);
395 void *libsocket_handle
;
402 struct swrap_libc_fns fns
;
405 static struct swrap swrap
;
408 static const char *socket_wrapper_dir(void);
410 #define LIBC_NAME "libc.so"
419 static const char *swrap_str_lib(enum swrap_lib lib
)
426 case SWRAP_LIBSOCKET
:
430 /* Compiler would warn us about unhandled enum value if we get here */
435 static void *swrap_load_lib_handle(enum swrap_lib lib
)
437 int flags
= RTLD_LAZY
;
442 flags
|= RTLD_DEEPBIND
;
448 case SWRAP_LIBSOCKET
:
449 #ifdef HAVE_LIBSOCKET
450 handle
= swrap
.libsocket_handle
;
451 if (handle
== NULL
) {
452 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
453 char soname
[256] = {0};
455 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
456 handle
= dlopen(soname
, flags
);
459 swrap
.libsocket_handle
= handle
;
465 handle
= swrap
.libc_handle
;
467 if (handle
== NULL
) {
468 handle
= dlopen(LIBC_SO
, flags
);
470 swrap
.libc_handle
= handle
;
473 if (handle
== NULL
) {
474 for (handle
= NULL
, i
= 10; handle
== NULL
&& i
>= 0; i
--) {
475 char soname
[256] = {0};
477 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
478 handle
= dlopen(soname
, flags
);
481 swrap
.libc_handle
= handle
;
486 if (handle
== NULL
) {
488 handle
= swrap
.libc_handle
= swrap
.libsocket_handle
= RTLD_NEXT
;
490 SWRAP_LOG(SWRAP_LOG_ERROR
,
491 "Failed to dlopen library: %s\n",
500 static void *_swrap_load_lib_function(enum swrap_lib lib
, const char *fn_name
)
505 handle
= swrap_load_lib_handle(lib
);
507 func
= dlsym(handle
, fn_name
);
509 SWRAP_LOG(SWRAP_LOG_ERROR
,
510 "Failed to find %s: %s\n",
515 SWRAP_LOG(SWRAP_LOG_TRACE
,
517 fn_name
, swrap_str_lib(lib
));
521 #define swrap_load_lib_function(lib, fn_name) \
522 if (swrap.fns.libc_##fn_name == NULL) { \
523 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
524 *(void **) (&swrap.fns.libc_##fn_name) = \
532 * Functions especially from libc need to be loaded individually, you can't load
533 * all at once or gdb will segfault at startup. The same applies to valgrind and
534 * has probably something todo with with the linker.
535 * So we need load each function at the point it is called the first time.
537 static int libc_accept(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
539 swrap_load_lib_function(SWRAP_LIBSOCKET
, accept
);
541 return swrap
.fns
.libc_accept(sockfd
, addr
, addrlen
);
544 static int libc_bind(int sockfd
,
545 const struct sockaddr
*addr
,
548 swrap_load_lib_function(SWRAP_LIBSOCKET
, bind
);
550 return swrap
.fns
.libc_bind(sockfd
, addr
, addrlen
);
553 static int libc_close(int fd
)
555 swrap_load_lib_function(SWRAP_LIBC
, close
);
557 return swrap
.fns
.libc_close(fd
);
560 static int libc_connect(int sockfd
,
561 const struct sockaddr
*addr
,
564 swrap_load_lib_function(SWRAP_LIBSOCKET
, connect
);
566 return swrap
.fns
.libc_connect(sockfd
, addr
, addrlen
);
569 static int libc_dup(int fd
)
571 swrap_load_lib_function(SWRAP_LIBC
, dup
);
573 return swrap
.fns
.libc_dup(fd
);
576 static int libc_dup2(int oldfd
, int newfd
)
578 swrap_load_lib_function(SWRAP_LIBC
, dup2
);
580 return swrap
.fns
.libc_dup2(oldfd
, newfd
);
584 static int libc_eventfd(int count
, int flags
)
586 swrap_load_lib_function(SWRAP_LIBC
, eventfd
);
588 return swrap
.fns
.libc_eventfd(count
, flags
);
592 static int libc_getpeername(int sockfd
,
593 struct sockaddr
*addr
,
596 swrap_load_lib_function(SWRAP_LIBSOCKET
, getpeername
);
598 return swrap
.fns
.libc_getpeername(sockfd
, addr
, addrlen
);
601 static int libc_getsockname(int sockfd
,
602 struct sockaddr
*addr
,
605 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockname
);
607 return swrap
.fns
.libc_getsockname(sockfd
, addr
, addrlen
);
610 static int libc_getsockopt(int sockfd
,
616 swrap_load_lib_function(SWRAP_LIBSOCKET
, getsockopt
);
618 return swrap
.fns
.libc_getsockopt(sockfd
, level
, optname
, optval
, optlen
);
621 static int libc_vioctl(int d
, unsigned long int request
, va_list ap
)
627 swrap_load_lib_function(SWRAP_LIBC
, ioctl
);
629 for (i
= 0; i
< 4; i
++) {
630 args
[i
] = va_arg(ap
, long int);
633 rc
= swrap
.fns
.libc_ioctl(d
,
643 static int libc_listen(int sockfd
, int backlog
)
645 swrap_load_lib_function(SWRAP_LIBSOCKET
, listen
);
647 return swrap
.fns
.libc_listen(sockfd
, backlog
);
650 static FILE *libc_fopen(const char *name
, const char *mode
)
652 swrap_load_lib_function(SWRAP_LIBC
, fopen
);
654 return swrap
.fns
.libc_fopen(name
, mode
);
657 static int libc_vopen(const char *pathname
, int flags
, va_list ap
)
662 swrap_load_lib_function(SWRAP_LIBC
, open
);
664 mode
= va_arg(ap
, long int);
666 fd
= swrap
.fns
.libc_open(pathname
, flags
, (mode_t
)mode
);
671 static int libc_open(const char *pathname
, int flags
, ...)
677 fd
= libc_vopen(pathname
, flags
, ap
);
683 static int libc_pipe(int pipefd
[2])
685 swrap_load_lib_function(SWRAP_LIBSOCKET
, pipe
);
687 return swrap
.fns
.libc_pipe(pipefd
);
690 static int libc_read(int fd
, void *buf
, size_t count
)
692 swrap_load_lib_function(SWRAP_LIBC
, read
);
694 return swrap
.fns
.libc_read(fd
, buf
, count
);
697 static ssize_t
libc_readv(int fd
, const struct iovec
*iov
, int iovcnt
)
699 swrap_load_lib_function(SWRAP_LIBSOCKET
, readv
);
701 return swrap
.fns
.libc_readv(fd
, iov
, iovcnt
);
704 static int libc_recv(int sockfd
, void *buf
, size_t len
, int flags
)
706 swrap_load_lib_function(SWRAP_LIBSOCKET
, recv
);
708 return swrap
.fns
.libc_recv(sockfd
, buf
, len
, flags
);
711 static int libc_recvfrom(int sockfd
,
715 struct sockaddr
*src_addr
,
718 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvfrom
);
720 return swrap
.fns
.libc_recvfrom(sockfd
, buf
, len
, flags
, src_addr
, addrlen
);
723 static int libc_recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
725 swrap_load_lib_function(SWRAP_LIBSOCKET
, recvmsg
);
727 return swrap
.fns
.libc_recvmsg(sockfd
, msg
, flags
);
730 static int libc_send(int sockfd
, const void *buf
, size_t len
, int flags
)
732 swrap_load_lib_function(SWRAP_LIBSOCKET
, send
);
734 return swrap
.fns
.libc_send(sockfd
, buf
, len
, flags
);
737 static int libc_sendmsg(int sockfd
, const struct msghdr
*msg
, int flags
)
739 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendmsg
);
741 return swrap
.fns
.libc_sendmsg(sockfd
, msg
, flags
);
744 static int libc_sendto(int sockfd
,
748 const struct sockaddr
*dst_addr
,
751 swrap_load_lib_function(SWRAP_LIBSOCKET
, sendto
);
753 return swrap
.fns
.libc_sendto(sockfd
, buf
, len
, flags
, dst_addr
, addrlen
);
756 static int libc_setsockopt(int sockfd
,
762 swrap_load_lib_function(SWRAP_LIBSOCKET
, setsockopt
);
764 return swrap
.fns
.libc_setsockopt(sockfd
, level
, optname
, optval
, optlen
);
768 static int libc_signalfd(int fd
, const sigset_t
*mask
, int flags
)
770 swrap_load_lib_function(SWRAP_LIBSOCKET
, signalfd
);
772 return swrap
.fns
.libc_signalfd(fd
, mask
, flags
);
776 static int libc_socket(int domain
, int type
, int protocol
)
778 swrap_load_lib_function(SWRAP_LIBSOCKET
, socket
);
780 return swrap
.fns
.libc_socket(domain
, type
, protocol
);
783 static int libc_socketpair(int domain
, int type
, int protocol
, int sv
[2])
785 swrap_load_lib_function(SWRAP_LIBSOCKET
, socketpair
);
787 return swrap
.fns
.libc_socketpair(domain
, type
, protocol
, sv
);
790 #ifdef HAVE_TIMERFD_CREATE
791 static int libc_timerfd_create(int clockid
, int flags
)
793 swrap_load_lib_function(SWRAP_LIBC
, timerfd_create
);
795 return swrap
.fns
.libc_timerfd_create(clockid
, flags
);
799 static ssize_t
libc_writev(int fd
, const struct iovec
*iov
, int iovcnt
)
801 swrap_load_lib_function(SWRAP_LIBSOCKET
, writev
);
803 return swrap
.fns
.libc_writev(fd
, iov
, iovcnt
);
806 /*********************************************************
807 * SWRAP HELPER FUNCTIONS
808 *********************************************************/
814 static const struct in6_addr
*swrap_ipv6(void)
816 static struct in6_addr v
;
817 static int initialized
;
825 ret
= inet_pton(AF_INET6
, "FD00::5357:5F00", &v
);
834 static void set_port(int family
, int prt
, struct swrap_address
*addr
)
838 addr
->sa
.in
.sin_port
= htons(prt
);
842 addr
->sa
.in6
.sin6_port
= htons(prt
);
848 static size_t socket_length(int family
)
852 return sizeof(struct sockaddr_in
);
855 return sizeof(struct sockaddr_in6
);
861 static const char *socket_wrapper_dir(void)
863 const char *s
= getenv("SOCKET_WRAPPER_DIR");
867 /* TODO use realpath(3) here, when we add support for threads */
868 if (strncmp(s
, "./", 2) == 0) {
872 SWRAP_LOG(SWRAP_LOG_TRACE
, "socket_wrapper_dir: %s", s
);
876 bool socket_wrapper_enabled(void)
878 const char *s
= socket_wrapper_dir();
880 return s
!= NULL
? true : false;
883 static unsigned int socket_wrapper_default_iface(void)
885 const char *s
= getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
888 if (sscanf(s
, "%u", &iface
) == 1) {
889 if (iface
>= 1 && iface
<= MAX_WRAPPED_INTERFACES
) {
895 return 1;/* 127.0.0.1 */
898 static int convert_un_in(const struct sockaddr_un
*un
, struct sockaddr
*in
, socklen_t
*len
)
905 p
= strrchr(un
->sun_path
, '/');
906 if (p
) p
++; else p
= un
->sun_path
;
908 if (sscanf(p
, SOCKET_FORMAT
, &type
, &iface
, &prt
) != 3) {
913 SWRAP_LOG(SWRAP_LOG_TRACE
, "type %c iface %u port %u",
916 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
927 case SOCKET_TYPE_CHAR_TCP
:
928 case SOCKET_TYPE_CHAR_UDP
: {
929 struct sockaddr_in
*in2
= (struct sockaddr_in
*)(void *)in
;
931 if ((*len
) < sizeof(*in2
)) {
936 memset(in2
, 0, sizeof(*in2
));
937 in2
->sin_family
= AF_INET
;
938 in2
->sin_addr
.s_addr
= htonl((127<<24) | iface
);
939 in2
->sin_port
= htons(prt
);
945 case SOCKET_TYPE_CHAR_TCP_V6
:
946 case SOCKET_TYPE_CHAR_UDP_V6
: {
947 struct sockaddr_in6
*in2
= (struct sockaddr_in6
*)(void *)in
;
949 if ((*len
) < sizeof(*in2
)) {
954 memset(in2
, 0, sizeof(*in2
));
955 in2
->sin6_family
= AF_INET6
;
956 in2
->sin6_addr
= *swrap_ipv6();
957 in2
->sin6_addr
.s6_addr
[15] = iface
;
958 in2
->sin6_port
= htons(prt
);
972 static int convert_in_un_remote(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
980 if (bcast
) *bcast
= 0;
982 switch (inaddr
->sa_family
) {
984 const struct sockaddr_in
*in
=
985 (const struct sockaddr_in
*)(const void *)inaddr
;
986 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
993 u_type
= SOCKET_TYPE_CHAR_TCP
;
996 u_type
= SOCKET_TYPE_CHAR_UDP
;
997 a_type
= SOCKET_TYPE_CHAR_UDP
;
998 b_type
= SOCKET_TYPE_CHAR_UDP
;
1001 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1002 errno
= ESOCKTNOSUPPORT
;
1006 prt
= ntohs(in
->sin_port
);
1007 if (a_type
&& addr
== 0xFFFFFFFF) {
1008 /* 255.255.255.255 only udp */
1011 iface
= socket_wrapper_default_iface();
1012 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1013 /* 127.255.255.255 only udp */
1016 iface
= socket_wrapper_default_iface();
1017 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1021 iface
= (addr
& 0x000000FF);
1023 errno
= ENETUNREACH
;
1026 if (bcast
) *bcast
= is_bcast
;
1031 const struct sockaddr_in6
*in
=
1032 (const struct sockaddr_in6
*)(const void *)inaddr
;
1033 struct in6_addr cmp1
, cmp2
;
1037 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1040 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1043 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1044 errno
= ESOCKTNOSUPPORT
;
1048 /* XXX no multicast/broadcast */
1050 prt
= ntohs(in
->sin6_port
);
1052 cmp1
= *swrap_ipv6();
1053 cmp2
= in
->sin6_addr
;
1054 cmp2
.s6_addr
[15] = 0;
1055 if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1056 iface
= in
->sin6_addr
.s6_addr
[15];
1058 errno
= ENETUNREACH
;
1066 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family!\n");
1067 errno
= ENETUNREACH
;
1072 SWRAP_LOG(SWRAP_LOG_WARN
, "Port not set\n");
1078 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/EINVAL",
1079 socket_wrapper_dir());
1080 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1081 /* the caller need to do more processing */
1085 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1086 socket_wrapper_dir(), type
, iface
, prt
);
1087 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1092 static int convert_in_un_alloc(struct socket_info
*si
, const struct sockaddr
*inaddr
, struct sockaddr_un
*un
,
1101 if (bcast
) *bcast
= 0;
1103 switch (si
->family
) {
1105 const struct sockaddr_in
*in
=
1106 (const struct sockaddr_in
*)(const void *)inaddr
;
1107 unsigned int addr
= ntohl(in
->sin_addr
.s_addr
);
1113 prt
= ntohs(in
->sin_port
);
1117 u_type
= SOCKET_TYPE_CHAR_TCP
;
1118 d_type
= SOCKET_TYPE_CHAR_TCP
;
1121 u_type
= SOCKET_TYPE_CHAR_UDP
;
1122 d_type
= SOCKET_TYPE_CHAR_UDP
;
1123 a_type
= SOCKET_TYPE_CHAR_UDP
;
1124 b_type
= SOCKET_TYPE_CHAR_UDP
;
1127 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1128 errno
= ESOCKTNOSUPPORT
;
1136 iface
= socket_wrapper_default_iface();
1137 } else if (a_type
&& addr
== 0xFFFFFFFF) {
1138 /* 255.255.255.255 only udp */
1141 iface
= socket_wrapper_default_iface();
1142 } else if (b_type
&& addr
== 0x7FFFFFFF) {
1143 /* 127.255.255.255 only udp */
1146 iface
= socket_wrapper_default_iface();
1147 } else if ((addr
& 0xFFFFFF00) == 0x7F000000) {
1151 iface
= (addr
& 0x000000FF);
1153 errno
= EADDRNOTAVAIL
;
1157 /* Store the bind address for connect() */
1158 if (si
->bindname
.sa_socklen
== 0) {
1159 struct sockaddr_in bind_in
;
1160 socklen_t blen
= sizeof(struct sockaddr_in
);
1162 ZERO_STRUCT(bind_in
);
1163 bind_in
.sin_family
= in
->sin_family
;
1164 bind_in
.sin_port
= in
->sin_port
;
1165 bind_in
.sin_addr
.s_addr
= htonl(0x7F000000 | iface
);
1167 si
->bindname
.sa_socklen
= blen
;
1168 memcpy(&si
->bindname
.sa
.in
, &bind_in
, blen
);
1175 const struct sockaddr_in6
*in
=
1176 (const struct sockaddr_in6
*)(const void *)inaddr
;
1177 struct in6_addr cmp1
, cmp2
;
1181 type
= SOCKET_TYPE_CHAR_TCP_V6
;
1184 type
= SOCKET_TYPE_CHAR_UDP_V6
;
1187 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1188 errno
= ESOCKTNOSUPPORT
;
1192 /* XXX no multicast/broadcast */
1194 prt
= ntohs(in
->sin6_port
);
1196 cmp1
= *swrap_ipv6();
1197 cmp2
= in
->sin6_addr
;
1198 cmp2
.s6_addr
[15] = 0;
1199 if (IN6_IS_ADDR_UNSPECIFIED(&in
->sin6_addr
)) {
1200 iface
= socket_wrapper_default_iface();
1201 } else if (IN6_ARE_ADDR_EQUAL(&cmp1
, &cmp2
)) {
1202 iface
= in
->sin6_addr
.s6_addr
[15];
1204 errno
= EADDRNOTAVAIL
;
1208 /* Store the bind address for connect() */
1209 if (si
->bindname
.sa_socklen
== 0) {
1210 struct sockaddr_in6 bind_in
;
1211 socklen_t blen
= sizeof(struct sockaddr_in6
);
1213 ZERO_STRUCT(bind_in
);
1214 bind_in
.sin6_family
= in
->sin6_family
;
1215 bind_in
.sin6_port
= in
->sin6_port
;
1217 bind_in
.sin6_addr
= *swrap_ipv6();
1218 bind_in
.sin6_addr
.s6_addr
[15] = iface
;
1220 memcpy(&si
->bindname
.sa
.in6
, &bind_in
, blen
);
1221 si
->bindname
.sa_socklen
= blen
;
1228 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1229 errno
= EADDRNOTAVAIL
;
1234 if (bcast
) *bcast
= is_bcast
;
1236 if (iface
== 0 || iface
> MAX_WRAPPED_INTERFACES
) {
1242 /* handle auto-allocation of ephemeral ports */
1243 for (prt
= 5001; prt
< 10000; prt
++) {
1244 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1245 socket_wrapper_dir(), type
, iface
, prt
);
1246 if (stat(un
->sun_path
, &st
) == 0) continue;
1248 set_port(si
->family
, prt
, &si
->myname
);
1249 set_port(si
->family
, prt
, &si
->bindname
);
1259 snprintf(un
->sun_path
, sizeof(un
->sun_path
), "%s/"SOCKET_FORMAT
,
1260 socket_wrapper_dir(), type
, iface
, prt
);
1261 SWRAP_LOG(SWRAP_LOG_DEBUG
, "un path [%s]", un
->sun_path
);
1265 static struct socket_info
*find_socket_info(int fd
)
1267 struct socket_info
*i
;
1269 for (i
= sockets
; i
; i
= i
->next
) {
1270 struct socket_info_fd
*f
;
1271 for (f
= i
->fds
; f
; f
= f
->next
) {
1282 static bool check_addr_port_in_use(const struct sockaddr
*sa
, socklen_t len
)
1284 struct socket_info
*s
;
1286 /* first catch invalid input */
1287 switch (sa
->sa_family
) {
1289 if (len
< sizeof(struct sockaddr_in
)) {
1295 if (len
< sizeof(struct sockaddr_in6
)) {
1305 for (s
= sockets
; s
!= NULL
; s
= s
->next
) {
1306 if (s
->myname
== NULL
) {
1309 if (s
->myname
->sa_family
!= sa
->sa_family
) {
1312 switch (s
->myname
->sa_family
) {
1314 struct sockaddr_in
*sin1
, *sin2
;
1316 sin1
= (struct sockaddr_in
*)s
->myname
;
1317 sin2
= (struct sockaddr_in
*)sa
;
1319 if (sin1
->sin_addr
.s_addr
== htonl(INADDR_ANY
)) {
1322 if (sin1
->sin_port
!= sin2
->sin_port
) {
1325 if (sin1
->sin_addr
.s_addr
!= sin2
->sin_addr
.s_addr
) {
1335 struct sockaddr_in6
*sin1
, *sin2
;
1337 sin1
= (struct sockaddr_in6
*)s
->myname
;
1338 sin2
= (struct sockaddr_in6
*)sa
;
1340 if (sin1
->sin6_port
!= sin2
->sin6_port
) {
1343 if (!IN6_ARE_ADDR_EQUAL(&sin1
->sin6_addr
,
1365 static void swrap_remove_stale(int fd
)
1367 struct socket_info
*si
= find_socket_info(fd
);
1368 struct socket_info_fd
*fi
;
1371 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
1373 SWRAP_LOG(SWRAP_LOG_TRACE
, "remove stale wrapper for %d", fd
);
1374 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
1380 if (si
->fds
== NULL
) {
1381 SWRAP_DLIST_REMOVE(sockets
, si
);
1386 static int sockaddr_convert_to_un(struct socket_info
*si
,
1387 const struct sockaddr
*in_addr
,
1389 struct sockaddr_un
*out_addr
,
1393 struct sockaddr
*out
= (struct sockaddr
*)(void *)out_addr
;
1395 (void) in_len
; /* unused */
1397 if (out_addr
== NULL
) {
1401 out
->sa_family
= AF_UNIX
;
1402 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1403 out
->sa_len
= sizeof(*out_addr
);
1406 switch (in_addr
->sa_family
) {
1408 const struct sockaddr_in
*sin
;
1409 if (si
->family
!= AF_INET
) {
1412 if (in_len
< sizeof(struct sockaddr_in
)) {
1415 sin
= (const struct sockaddr_in
*)in_addr
;
1416 if(sin
->sin_addr
.s_addr
!= htonl(INADDR_ANY
)) {
1421 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1422 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1436 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1437 errno
= ESOCKTNOSUPPORT
;
1441 return convert_in_un_alloc(si
, in_addr
, out_addr
, bcast
);
1443 return convert_in_un_remote(si
, in_addr
, out_addr
, bcast
);
1449 errno
= EAFNOSUPPORT
;
1450 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1454 static int sockaddr_convert_from_un(const struct socket_info
*si
,
1455 const struct sockaddr_un
*in_addr
,
1456 socklen_t un_addrlen
,
1458 struct sockaddr
*out_addr
,
1459 socklen_t
*out_addrlen
)
1463 if (out_addr
== NULL
|| out_addrlen
== NULL
)
1466 if (un_addrlen
== 0) {
1481 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown socket type!\n");
1482 errno
= ESOCKTNOSUPPORT
;
1485 ret
= convert_un_in(in_addr
, out_addr
, out_addrlen
);
1486 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1487 out_addr
->sa_len
= *out_addrlen
;
1494 SWRAP_LOG(SWRAP_LOG_ERROR
, "Unknown address family\n");
1495 errno
= EAFNOSUPPORT
;
1499 enum swrap_packet_type
{
1501 SWRAP_CONNECT_UNREACH
,
1509 SWRAP_SENDTO_UNREACH
,
1520 struct swrap_file_hdr
{
1522 uint16_t version_major
;
1523 uint16_t version_minor
;
1526 uint32_t frame_max_len
;
1527 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1530 #define SWRAP_FILE_HDR_SIZE 24
1532 struct swrap_packet_frame
{
1534 uint32_t micro_seconds
;
1535 uint32_t recorded_length
;
1536 uint32_t full_length
;
1538 #define SWRAP_PACKET_FRAME_SIZE 16
1540 union swrap_packet_ip
{
1544 uint16_t packet_length
;
1545 uint16_t identification
;
1550 uint16_t hdr_checksum
;
1554 #define SWRAP_PACKET_IP_V4_SIZE 20
1557 uint8_t flow_label_high
;
1558 uint16_t flow_label_low
;
1559 uint16_t payload_length
;
1560 uint8_t next_header
;
1562 uint8_t src_addr
[16];
1563 uint8_t dest_addr
[16];
1565 #define SWRAP_PACKET_IP_V6_SIZE 40
1567 #define SWRAP_PACKET_IP_SIZE 40
1569 union swrap_packet_payload
{
1571 uint16_t source_port
;
1581 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1583 uint16_t source_port
;
1588 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1595 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1602 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1604 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1606 #define SWRAP_PACKET_MIN_ALLOC \
1607 (SWRAP_PACKET_FRAME_SIZE + \
1608 SWRAP_PACKET_IP_SIZE + \
1609 SWRAP_PACKET_PAYLOAD_SIZE)
1611 static const char *swrap_pcap_init_file(void)
1613 static int initialized
= 0;
1614 static const char *s
= NULL
;
1615 static const struct swrap_file_hdr h
;
1616 static const struct swrap_packet_frame f
;
1617 static const union swrap_packet_ip i
;
1618 static const union swrap_packet_payload p
;
1620 if (initialized
== 1) {
1626 * TODO: don't use the structs use plain buffer offsets
1627 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1629 * for now make sure we disable PCAP support
1630 * if the struct has alignment!
1632 if (sizeof(h
) != SWRAP_FILE_HDR_SIZE
) {
1635 if (sizeof(f
) != SWRAP_PACKET_FRAME_SIZE
) {
1638 if (sizeof(i
) != SWRAP_PACKET_IP_SIZE
) {
1641 if (sizeof(i
.v4
) != SWRAP_PACKET_IP_V4_SIZE
) {
1644 if (sizeof(i
.v6
) != SWRAP_PACKET_IP_V6_SIZE
) {
1647 if (sizeof(p
) != SWRAP_PACKET_PAYLOAD_SIZE
) {
1650 if (sizeof(p
.tcp
) != SWRAP_PACKET_PAYLOAD_TCP_SIZE
) {
1653 if (sizeof(p
.udp
) != SWRAP_PACKET_PAYLOAD_UDP_SIZE
) {
1656 if (sizeof(p
.icmp4
) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
) {
1659 if (sizeof(p
.icmp6
) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
) {
1663 s
= getenv("SOCKET_WRAPPER_PCAP_FILE");
1667 if (strncmp(s
, "./", 2) == 0) {
1673 static uint8_t *swrap_pcap_packet_init(struct timeval
*tval
,
1674 const struct sockaddr
*src
,
1675 const struct sockaddr
*dest
,
1677 const uint8_t *payload
,
1679 unsigned long tcp_seqno
,
1680 unsigned long tcp_ack
,
1681 unsigned char tcp_ctl
,
1683 size_t *_packet_len
)
1687 struct swrap_packet_frame
*frame
;
1688 union swrap_packet_ip
*ip
;
1689 union swrap_packet_payload
*pay
;
1692 size_t nonwire_len
= sizeof(*frame
);
1693 size_t wire_hdr_len
= 0;
1694 size_t wire_len
= 0;
1695 size_t ip_hdr_len
= 0;
1696 size_t icmp_hdr_len
= 0;
1697 size_t icmp_truncate_len
= 0;
1698 uint8_t protocol
= 0, icmp_protocol
= 0;
1699 const struct sockaddr_in
*src_in
= NULL
;
1700 const struct sockaddr_in
*dest_in
= NULL
;
1702 const struct sockaddr_in6
*src_in6
= NULL
;
1703 const struct sockaddr_in6
*dest_in6
= NULL
;
1708 switch (src
->sa_family
) {
1710 src_in
= (const struct sockaddr_in
*)src
;
1711 dest_in
= (const struct sockaddr_in
*)dest
;
1712 src_port
= src_in
->sin_port
;
1713 dest_port
= dest_in
->sin_port
;
1714 ip_hdr_len
= sizeof(ip
->v4
);
1718 src_in6
= (const struct sockaddr_in6
*)src
;
1719 dest_in6
= (const struct sockaddr_in6
*)dest
;
1720 src_port
= src_in6
->sin6_port
;
1721 dest_port
= dest_in6
->sin6_port
;
1722 ip_hdr_len
= sizeof(ip
->v6
);
1729 switch (socket_type
) {
1731 protocol
= 0x06; /* TCP */
1732 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->tcp
);
1733 wire_len
= wire_hdr_len
+ payload_len
;
1737 protocol
= 0x11; /* UDP */
1738 wire_hdr_len
= ip_hdr_len
+ sizeof(pay
->udp
);
1739 wire_len
= wire_hdr_len
+ payload_len
;
1747 icmp_protocol
= protocol
;
1748 switch (src
->sa_family
) {
1750 protocol
= 0x01; /* ICMPv4 */
1751 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp4
);
1755 protocol
= 0x3A; /* ICMPv6 */
1756 icmp_hdr_len
= ip_hdr_len
+ sizeof(pay
->icmp6
);
1760 if (wire_len
> 64 ) {
1761 icmp_truncate_len
= wire_len
- 64;
1763 wire_hdr_len
+= icmp_hdr_len
;
1764 wire_len
+= icmp_hdr_len
;
1767 packet_len
= nonwire_len
+ wire_len
;
1768 alloc_len
= packet_len
;
1769 if (alloc_len
< SWRAP_PACKET_MIN_ALLOC
) {
1770 alloc_len
= SWRAP_PACKET_MIN_ALLOC
;
1773 base
= (uint8_t *)malloc(alloc_len
);
1777 memset(base
, 0x0, alloc_len
);
1781 frame
= (struct swrap_packet_frame
*)buf
;
1782 frame
->seconds
= tval
->tv_sec
;
1783 frame
->micro_seconds
= tval
->tv_usec
;
1784 frame
->recorded_length
= wire_len
- icmp_truncate_len
;
1785 frame
->full_length
= wire_len
- icmp_truncate_len
;
1786 buf
+= SWRAP_PACKET_FRAME_SIZE
;
1788 ip
= (union swrap_packet_ip
*)buf
;
1789 switch (src
->sa_family
) {
1791 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1793 ip
->v4
.packet_length
= htons(wire_len
- icmp_truncate_len
);
1794 ip
->v4
.identification
= htons(0xFFFF);
1795 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1796 ip
->v4
.fragment
= htons(0x0000);
1798 ip
->v4
.protocol
= protocol
;
1799 ip
->v4
.hdr_checksum
= htons(0x0000);
1800 ip
->v4
.src_addr
= src_in
->sin_addr
.s_addr
;
1801 ip
->v4
.dest_addr
= dest_in
->sin_addr
.s_addr
;
1802 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1806 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1807 ip
->v6
.flow_label_high
= 0x00;
1808 ip
->v6
.flow_label_low
= 0x0000;
1809 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1810 ip
->v6
.next_header
= protocol
;
1811 memcpy(ip
->v6
.src_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1812 memcpy(ip
->v6
.dest_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1813 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1819 pay
= (union swrap_packet_payload
*)buf
;
1820 switch (src
->sa_family
) {
1822 pay
->icmp4
.type
= 0x03; /* destination unreachable */
1823 pay
->icmp4
.code
= 0x01; /* host unreachable */
1824 pay
->icmp4
.checksum
= htons(0x0000);
1825 pay
->icmp4
.unused
= htonl(0x00000000);
1826 buf
+= SWRAP_PACKET_PAYLOAD_ICMP4_SIZE
;
1828 /* set the ip header in the ICMP payload */
1829 ip
= (union swrap_packet_ip
*)buf
;
1830 ip
->v4
.ver_hdrlen
= 0x45; /* version 4 and 5 * 32 bit words */
1832 ip
->v4
.packet_length
= htons(wire_len
- icmp_hdr_len
);
1833 ip
->v4
.identification
= htons(0xFFFF);
1834 ip
->v4
.flags
= 0x40; /* BIT 1 set - means don't fragment */
1835 ip
->v4
.fragment
= htons(0x0000);
1837 ip
->v4
.protocol
= icmp_protocol
;
1838 ip
->v4
.hdr_checksum
= htons(0x0000);
1839 ip
->v4
.src_addr
= dest_in
->sin_addr
.s_addr
;
1840 ip
->v4
.dest_addr
= src_in
->sin_addr
.s_addr
;
1841 buf
+= SWRAP_PACKET_IP_V4_SIZE
;
1843 src_port
= dest_in
->sin_port
;
1844 dest_port
= src_in
->sin_port
;
1848 pay
->icmp6
.type
= 0x01; /* destination unreachable */
1849 pay
->icmp6
.code
= 0x03; /* address unreachable */
1850 pay
->icmp6
.checksum
= htons(0x0000);
1851 pay
->icmp6
.unused
= htonl(0x00000000);
1852 buf
+= SWRAP_PACKET_PAYLOAD_ICMP6_SIZE
;
1854 /* set the ip header in the ICMP payload */
1855 ip
= (union swrap_packet_ip
*)buf
;
1856 ip
->v6
.ver_prio
= 0x60; /* version 4 and 5 * 32 bit words */
1857 ip
->v6
.flow_label_high
= 0x00;
1858 ip
->v6
.flow_label_low
= 0x0000;
1859 ip
->v6
.payload_length
= htons(wire_len
- icmp_truncate_len
); /* TODO */
1860 ip
->v6
.next_header
= protocol
;
1861 memcpy(ip
->v6
.src_addr
, dest_in6
->sin6_addr
.s6_addr
, 16);
1862 memcpy(ip
->v6
.dest_addr
, src_in6
->sin6_addr
.s6_addr
, 16);
1863 buf
+= SWRAP_PACKET_IP_V6_SIZE
;
1865 src_port
= dest_in6
->sin6_port
;
1866 dest_port
= src_in6
->sin6_port
;
1872 pay
= (union swrap_packet_payload
*)buf
;
1874 switch (socket_type
) {
1876 pay
->tcp
.source_port
= src_port
;
1877 pay
->tcp
.dest_port
= dest_port
;
1878 pay
->tcp
.seq_num
= htonl(tcp_seqno
);
1879 pay
->tcp
.ack_num
= htonl(tcp_ack
);
1880 pay
->tcp
.hdr_length
= 0x50; /* 5 * 32 bit words */
1881 pay
->tcp
.control
= tcp_ctl
;
1882 pay
->tcp
.window
= htons(0x7FFF);
1883 pay
->tcp
.checksum
= htons(0x0000);
1884 pay
->tcp
.urg
= htons(0x0000);
1885 buf
+= SWRAP_PACKET_PAYLOAD_TCP_SIZE
;
1890 pay
->udp
.source_port
= src_port
;
1891 pay
->udp
.dest_port
= dest_port
;
1892 pay
->udp
.length
= htons(8 + payload_len
);
1893 pay
->udp
.checksum
= htons(0x0000);
1894 buf
+= SWRAP_PACKET_PAYLOAD_UDP_SIZE
;
1899 if (payload
&& payload_len
> 0) {
1900 memcpy(buf
, payload
, payload_len
);
1903 *_packet_len
= packet_len
- icmp_truncate_len
;
1907 static int swrap_pcap_get_fd(const char *fname
)
1911 if (fd
!= -1) return fd
;
1913 fd
= libc_open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_APPEND
, 0644);
1915 struct swrap_file_hdr file_hdr
;
1916 file_hdr
.magic
= 0xA1B2C3D4;
1917 file_hdr
.version_major
= 0x0002;
1918 file_hdr
.version_minor
= 0x0004;
1919 file_hdr
.timezone
= 0x00000000;
1920 file_hdr
.sigfigs
= 0x00000000;
1921 file_hdr
.frame_max_len
= SWRAP_FRAME_LENGTH_MAX
;
1922 file_hdr
.link_type
= 0x0065; /* 101 RAW IP */
1924 if (write(fd
, &file_hdr
, sizeof(file_hdr
)) != sizeof(file_hdr
)) {
1931 fd
= libc_open(fname
, O_WRONLY
|O_APPEND
, 0644);
1936 static uint8_t *swrap_pcap_marshall_packet(struct socket_info
*si
,
1937 const struct sockaddr
*addr
,
1938 enum swrap_packet_type type
,
1939 const void *buf
, size_t len
,
1942 const struct sockaddr
*src_addr
;
1943 const struct sockaddr
*dest_addr
;
1944 unsigned long tcp_seqno
= 0;
1945 unsigned long tcp_ack
= 0;
1946 unsigned char tcp_ctl
= 0;
1947 int unreachable
= 0;
1951 switch (si
->family
) {
1963 case SWRAP_CONNECT_SEND
:
1964 if (si
->type
!= SOCK_STREAM
) return NULL
;
1966 src_addr
= &si
->myname
.sa
.s
;
1969 tcp_seqno
= si
->io
.pck_snd
;
1970 tcp_ack
= si
->io
.pck_rcv
;
1971 tcp_ctl
= 0x02; /* SYN */
1973 si
->io
.pck_snd
+= 1;
1977 case SWRAP_CONNECT_RECV
:
1978 if (si
->type
!= SOCK_STREAM
) return NULL
;
1980 dest_addr
= &si
->myname
.sa
.s
;
1983 tcp_seqno
= si
->io
.pck_rcv
;
1984 tcp_ack
= si
->io
.pck_snd
;
1985 tcp_ctl
= 0x12; /** SYN,ACK */
1987 si
->io
.pck_rcv
+= 1;
1991 case SWRAP_CONNECT_UNREACH
:
1992 if (si
->type
!= SOCK_STREAM
) return NULL
;
1994 dest_addr
= &si
->myname
.sa
.s
;
1997 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1998 tcp_seqno
= si
->io
.pck_snd
- 1;
1999 tcp_ack
= si
->io
.pck_rcv
;
2000 tcp_ctl
= 0x02; /* SYN */
2005 case SWRAP_CONNECT_ACK
:
2006 if (si
->type
!= SOCK_STREAM
) return NULL
;
2008 src_addr
= &si
->myname
.sa
.s
;
2011 tcp_seqno
= si
->io
.pck_snd
;
2012 tcp_ack
= si
->io
.pck_rcv
;
2013 tcp_ctl
= 0x10; /* ACK */
2017 case SWRAP_ACCEPT_SEND
:
2018 if (si
->type
!= SOCK_STREAM
) return NULL
;
2020 dest_addr
= &si
->myname
.sa
.s
;
2023 tcp_seqno
= si
->io
.pck_rcv
;
2024 tcp_ack
= si
->io
.pck_snd
;
2025 tcp_ctl
= 0x02; /* SYN */
2027 si
->io
.pck_rcv
+= 1;
2031 case SWRAP_ACCEPT_RECV
:
2032 if (si
->type
!= SOCK_STREAM
) return NULL
;
2034 src_addr
= &si
->myname
.sa
.s
;
2037 tcp_seqno
= si
->io
.pck_snd
;
2038 tcp_ack
= si
->io
.pck_rcv
;
2039 tcp_ctl
= 0x12; /* SYN,ACK */
2041 si
->io
.pck_snd
+= 1;
2045 case SWRAP_ACCEPT_ACK
:
2046 if (si
->type
!= SOCK_STREAM
) return NULL
;
2048 dest_addr
= &si
->myname
.sa
.s
;
2051 tcp_seqno
= si
->io
.pck_rcv
;
2052 tcp_ack
= si
->io
.pck_snd
;
2053 tcp_ctl
= 0x10; /* ACK */
2058 src_addr
= &si
->myname
.sa
.s
;
2059 dest_addr
= &si
->peername
.sa
.s
;
2061 tcp_seqno
= si
->io
.pck_snd
;
2062 tcp_ack
= si
->io
.pck_rcv
;
2063 tcp_ctl
= 0x18; /* PSH,ACK */
2065 si
->io
.pck_snd
+= len
;
2069 case SWRAP_SEND_RST
:
2070 dest_addr
= &si
->myname
.sa
.s
;
2071 src_addr
= &si
->peername
.sa
.s
;
2073 if (si
->type
== SOCK_DGRAM
) {
2074 return swrap_pcap_marshall_packet(si
,
2076 SWRAP_SENDTO_UNREACH
,
2082 tcp_seqno
= si
->io
.pck_rcv
;
2083 tcp_ack
= si
->io
.pck_snd
;
2084 tcp_ctl
= 0x14; /** RST,ACK */
2088 case SWRAP_PENDING_RST
:
2089 dest_addr
= &si
->myname
.sa
.s
;
2090 src_addr
= &si
->peername
.sa
.s
;
2092 if (si
->type
== SOCK_DGRAM
) {
2096 tcp_seqno
= si
->io
.pck_rcv
;
2097 tcp_ack
= si
->io
.pck_snd
;
2098 tcp_ctl
= 0x14; /* RST,ACK */
2103 dest_addr
= &si
->myname
.sa
.s
;
2104 src_addr
= &si
->peername
.sa
.s
;
2106 tcp_seqno
= si
->io
.pck_rcv
;
2107 tcp_ack
= si
->io
.pck_snd
;
2108 tcp_ctl
= 0x18; /* PSH,ACK */
2110 si
->io
.pck_rcv
+= len
;
2114 case SWRAP_RECV_RST
:
2115 dest_addr
= &si
->myname
.sa
.s
;
2116 src_addr
= &si
->peername
.sa
.s
;
2118 if (si
->type
== SOCK_DGRAM
) {
2122 tcp_seqno
= si
->io
.pck_rcv
;
2123 tcp_ack
= si
->io
.pck_snd
;
2124 tcp_ctl
= 0x14; /* RST,ACK */
2129 src_addr
= &si
->myname
.sa
.s
;
2132 si
->io
.pck_snd
+= len
;
2136 case SWRAP_SENDTO_UNREACH
:
2137 dest_addr
= &si
->myname
.sa
.s
;
2144 case SWRAP_RECVFROM
:
2145 dest_addr
= &si
->myname
.sa
.s
;
2148 si
->io
.pck_rcv
+= len
;
2152 case SWRAP_CLOSE_SEND
:
2153 if (si
->type
!= SOCK_STREAM
) return NULL
;
2155 src_addr
= &si
->myname
.sa
.s
;
2156 dest_addr
= &si
->peername
.sa
.s
;
2158 tcp_seqno
= si
->io
.pck_snd
;
2159 tcp_ack
= si
->io
.pck_rcv
;
2160 tcp_ctl
= 0x11; /* FIN, ACK */
2162 si
->io
.pck_snd
+= 1;
2166 case SWRAP_CLOSE_RECV
:
2167 if (si
->type
!= SOCK_STREAM
) return NULL
;
2169 dest_addr
= &si
->myname
.sa
.s
;
2170 src_addr
= &si
->peername
.sa
.s
;
2172 tcp_seqno
= si
->io
.pck_rcv
;
2173 tcp_ack
= si
->io
.pck_snd
;
2174 tcp_ctl
= 0x11; /* FIN,ACK */
2176 si
->io
.pck_rcv
+= 1;
2180 case SWRAP_CLOSE_ACK
:
2181 if (si
->type
!= SOCK_STREAM
) return NULL
;
2183 src_addr
= &si
->myname
.sa
.s
;
2184 dest_addr
= &si
->peername
.sa
.s
;
2186 tcp_seqno
= si
->io
.pck_snd
;
2187 tcp_ack
= si
->io
.pck_rcv
;
2188 tcp_ctl
= 0x10; /* ACK */
2195 swrapGetTimeOfDay(&tv
);
2197 return swrap_pcap_packet_init(&tv
,
2201 (const uint8_t *)buf
,
2210 static void swrap_pcap_dump_packet(struct socket_info
*si
,
2211 const struct sockaddr
*addr
,
2212 enum swrap_packet_type type
,
2213 const void *buf
, size_t len
)
2215 const char *file_name
;
2217 size_t packet_len
= 0;
2220 file_name
= swrap_pcap_init_file();
2225 packet
= swrap_pcap_marshall_packet(si
,
2231 if (packet
== NULL
) {
2235 fd
= swrap_pcap_get_fd(file_name
);
2237 if (write(fd
, packet
, packet_len
) != (ssize_t
)packet_len
) {
2246 /****************************************************************************
2248 ***************************************************************************/
2250 #ifdef HAVE_SIGNALFD
2251 static int swrap_signalfd(int fd
, const sigset_t
*mask
, int flags
)
2255 rc
= libc_signalfd(fd
, mask
, flags
);
2257 swrap_remove_stale(fd
);
2263 int signalfd(int fd
, const sigset_t
*mask
, int flags
)
2265 return swrap_signalfd(fd
, mask
, flags
);
2269 /****************************************************************************
2271 ***************************************************************************/
2273 static int swrap_socket(int family
, int type
, int protocol
)
2275 struct socket_info
*si
;
2276 struct socket_info_fd
*fi
;
2278 int real_type
= type
;
2281 * Remove possible addition flags passed to socket() so
2282 * do not fail checking the type.
2283 * See https://lwn.net/Articles/281965/
2286 real_type
&= ~SOCK_CLOEXEC
;
2288 #ifdef SOCK_NONBLOCK
2289 real_type
&= ~SOCK_NONBLOCK
;
2292 if (!socket_wrapper_enabled()) {
2293 return libc_socket(family
, type
, protocol
);
2303 return libc_socket(family
, type
, protocol
);
2305 errno
= EAFNOSUPPORT
;
2309 switch (real_type
) {
2315 errno
= EPROTONOSUPPORT
;
2323 if (real_type
== SOCK_STREAM
) {
2328 if (real_type
== SOCK_DGRAM
) {
2333 errno
= EPROTONOSUPPORT
;
2338 * We must call libc_socket with type, from the caller, not the version
2339 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2341 fd
= libc_socket(AF_UNIX
, type
, 0);
2347 /* Check if we have a stale fd and remove it */
2348 si
= find_socket_info(fd
);
2350 swrap_remove_stale(fd
);
2353 si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2354 memset(si
, 0, sizeof(struct socket_info
));
2360 si
->family
= family
;
2362 /* however, the rest of the socket_wrapper code expects just
2363 * the type, not the flags */
2364 si
->type
= real_type
;
2365 si
->protocol
= protocol
;
2368 * Setup myname so getsockname() can succeed to find out the socket
2371 switch(si
->family
) {
2373 struct sockaddr_in sin
= {
2374 .sin_family
= AF_INET
,
2377 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in
);
2378 memcpy(&si
->myname
.sa
.in
, &sin
, si
->myname
.sa_socklen
);
2382 struct sockaddr_in6 sin6
= {
2383 .sin6_family
= AF_INET6
,
2386 si
->myname
.sa_socklen
= sizeof(struct sockaddr_in6
);
2387 memcpy(&si
->myname
.sa
.in6
, &sin6
, si
->myname
.sa_socklen
);
2396 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2405 SWRAP_DLIST_ADD(si
->fds
, fi
);
2406 SWRAP_DLIST_ADD(sockets
, si
);
2411 int socket(int family
, int type
, int protocol
)
2413 return swrap_socket(family
, type
, protocol
);
2416 /****************************************************************************
2418 ***************************************************************************/
2420 static int swrap_socketpair(int family
, int type
, int protocol
, int sv
[2])
2424 rc
= libc_socketpair(family
, type
, protocol
, sv
);
2426 swrap_remove_stale(sv
[0]);
2427 swrap_remove_stale(sv
[1]);
2433 int socketpair(int family
, int type
, int protocol
, int sv
[2])
2435 return swrap_socketpair(family
, type
, protocol
, sv
);
2438 /****************************************************************************
2440 ***************************************************************************/
2442 #ifdef HAVE_TIMERFD_CREATE
2443 static int swrap_timerfd_create(int clockid
, int flags
)
2447 fd
= libc_timerfd_create(clockid
, flags
);
2449 swrap_remove_stale(fd
);
2455 int timerfd_create(int clockid
, int flags
)
2457 return swrap_timerfd_create(clockid
, flags
);
2461 /****************************************************************************
2463 ***************************************************************************/
2465 static int swrap_pipe(int pipefd
[2])
2469 rc
= libc_pipe(pipefd
);
2471 swrap_remove_stale(pipefd
[0]);
2472 swrap_remove_stale(pipefd
[1]);
2478 int pipe(int pipefd
[2])
2480 return swrap_pipe(pipefd
);
2483 /****************************************************************************
2485 ***************************************************************************/
2487 static int swrap_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2489 struct socket_info
*parent_si
, *child_si
;
2490 struct socket_info_fd
*child_fi
;
2492 struct swrap_address un_addr
= {
2493 .sa_socklen
= sizeof(struct sockaddr_un
),
2495 struct swrap_address un_my_addr
= {
2496 .sa_socklen
= sizeof(struct sockaddr_un
),
2498 struct swrap_address in_addr
= {
2499 .sa_socklen
= sizeof(struct sockaddr_storage
),
2501 struct swrap_address in_my_addr
= {
2502 .sa_socklen
= sizeof(struct sockaddr_storage
),
2506 parent_si
= find_socket_info(s
);
2508 return libc_accept(s
, addr
, addrlen
);
2512 * assume out sockaddr have the same size as the in parent
2515 in_addr
.sa_socklen
= socket_length(parent_si
->family
);
2516 if (in_addr
.sa_socklen
<= 0) {
2521 ret
= libc_accept(s
, &un_addr
.sa
.s
, &un_addr
.sa_socklen
);
2523 if (errno
== ENOTSOCK
) {
2524 /* Remove stale fds */
2525 swrap_remove_stale(s
);
2532 ret
= sockaddr_convert_from_un(parent_si
,
2537 &in_addr
.sa_socklen
);
2543 child_si
= (struct socket_info
*)malloc(sizeof(struct socket_info
));
2544 memset(child_si
, 0, sizeof(struct socket_info
));
2546 child_fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
2547 if (child_fi
== NULL
) {
2556 SWRAP_DLIST_ADD(child_si
->fds
, child_fi
);
2558 child_si
->family
= parent_si
->family
;
2559 child_si
->type
= parent_si
->type
;
2560 child_si
->protocol
= parent_si
->protocol
;
2561 child_si
->bound
= 1;
2562 child_si
->is_server
= 1;
2563 child_si
->connected
= 1;
2565 child_si
->peername
= (struct swrap_address
) {
2566 .sa_socklen
= in_addr
.sa_socklen
,
2568 memcpy(&child_si
->peername
.sa
.ss
, &in_addr
.sa
.ss
, in_addr
.sa_socklen
);
2570 if (addr
!= NULL
&& addrlen
!= NULL
) {
2571 size_t copy_len
= MIN(*addrlen
, in_addr
.sa_socklen
);
2573 memcpy(addr
, &in_addr
.sa
.ss
, copy_len
);
2575 *addrlen
= in_addr
.sa_socklen
;
2578 ret
= libc_getsockname(fd
,
2580 &un_my_addr
.sa_socklen
);
2588 ret
= sockaddr_convert_from_un(child_si
,
2590 un_my_addr
.sa_socklen
,
2593 &in_my_addr
.sa_socklen
);
2601 SWRAP_LOG(SWRAP_LOG_TRACE
,
2602 "accept() path=%s, fd=%d",
2603 un_my_addr
.sa
.un
.sun_path
, s
);
2605 child_si
->myname
= (struct swrap_address
) {
2606 .sa_socklen
= in_my_addr
.sa_socklen
,
2608 memcpy(&child_si
->myname
.sa
.ss
, &in_my_addr
.sa
.ss
, in_my_addr
.sa_socklen
);
2610 SWRAP_DLIST_ADD(sockets
, child_si
);
2613 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_SEND
, NULL
, 0);
2614 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_RECV
, NULL
, 0);
2615 swrap_pcap_dump_packet(child_si
, addr
, SWRAP_ACCEPT_ACK
, NULL
, 0);
2621 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2622 int accept(int s
, struct sockaddr
*addr
, Psocklen_t addrlen
)
2624 int accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
2627 return swrap_accept(s
, addr
, (socklen_t
*)addrlen
);
2630 static int autobind_start_init
;
2631 static int autobind_start
;
2633 /* using sendto() or connect() on an unbound socket would give the
2634 recipient no way to reply, as unlike UDP and TCP, a unix domain
2635 socket can't auto-assign ephemeral port numbers, so we need to
2637 Note: this might change the family from ipv6 to ipv4
2639 static int swrap_auto_bind(int fd
, struct socket_info
*si
, int family
)
2641 struct swrap_address un_addr
= {
2642 .sa_socklen
= sizeof(struct sockaddr_un
),
2650 if (autobind_start_init
!= 1) {
2651 autobind_start_init
= 1;
2652 autobind_start
= getpid();
2653 autobind_start
%= 50000;
2654 autobind_start
+= 10000;
2657 un_addr
.sa
.un
.sun_family
= AF_UNIX
;
2661 struct sockaddr_in in
;
2665 type
= SOCKET_TYPE_CHAR_TCP
;
2668 type
= SOCKET_TYPE_CHAR_UDP
;
2671 errno
= ESOCKTNOSUPPORT
;
2675 memset(&in
, 0, sizeof(in
));
2676 in
.sin_family
= AF_INET
;
2677 in
.sin_addr
.s_addr
= htonl(127<<24 |
2678 socket_wrapper_default_iface());
2680 si
->myname
= (struct swrap_address
) {
2681 .sa_socklen
= sizeof(in
),
2683 memcpy(&si
->myname
.sa
.in
, &in
, si
->myname
.sa_socklen
);
2688 struct sockaddr_in6 in6
;
2690 if (si
->family
!= family
) {
2691 errno
= ENETUNREACH
;
2697 type
= SOCKET_TYPE_CHAR_TCP_V6
;
2700 type
= SOCKET_TYPE_CHAR_UDP_V6
;
2703 errno
= ESOCKTNOSUPPORT
;
2707 memset(&in6
, 0, sizeof(in6
));
2708 in6
.sin6_family
= AF_INET6
;
2709 in6
.sin6_addr
= *swrap_ipv6();
2710 in6
.sin6_addr
.s6_addr
[15] = socket_wrapper_default_iface();
2712 si
->myname
= (struct swrap_address
) {
2713 .sa_socklen
= sizeof(in6
),
2715 memcpy(&si
->myname
.sa
.in6
, &in6
, si
->myname
.sa_socklen
);
2720 errno
= ESOCKTNOSUPPORT
;
2724 if (autobind_start
> 60000) {
2725 autobind_start
= 10000;
2728 for (i
= 0; i
< SOCKET_MAX_SOCKETS
; i
++) {
2729 port
= autobind_start
+ i
;
2730 snprintf(un_addr
.sa
.un
.sun_path
, un_addr
.sa_socklen
,
2731 "%s/"SOCKET_FORMAT
, socket_wrapper_dir(),
2732 type
, socket_wrapper_default_iface(), port
);
2733 if (stat(un_addr
.sa
.un
.sun_path
, &st
) == 0) continue;
2735 ret
= libc_bind(fd
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
2736 if (ret
== -1) return ret
;
2738 si
->un_addr
= un_addr
.sa
.un
;
2741 autobind_start
= port
+ 1;
2744 if (i
== SOCKET_MAX_SOCKETS
) {
2745 SWRAP_LOG(SWRAP_LOG_ERROR
, "Too many open unix sockets (%u) for "
2746 "interface "SOCKET_FORMAT
,
2749 socket_wrapper_default_iface(),
2755 si
->family
= family
;
2756 set_port(si
->family
, port
, &si
->myname
);
2761 /****************************************************************************
2763 ***************************************************************************/
2765 static int swrap_connect(int s
, const struct sockaddr
*serv_addr
,
2769 struct swrap_address un_addr
= {
2770 .sa_socklen
= sizeof(struct sockaddr_un
),
2772 struct socket_info
*si
= find_socket_info(s
);
2776 return libc_connect(s
, serv_addr
, addrlen
);
2779 if (si
->bound
== 0) {
2780 ret
= swrap_auto_bind(s
, si
, serv_addr
->sa_family
);
2781 if (ret
== -1) return -1;
2784 if (si
->family
!= serv_addr
->sa_family
) {
2789 ret
= sockaddr_convert_to_un(si
, serv_addr
,
2790 addrlen
, &un_addr
.sa
.un
, 0, &bcast
);
2791 if (ret
== -1) return -1;
2794 errno
= ENETUNREACH
;
2798 if (si
->type
== SOCK_DGRAM
) {
2799 si
->defer_connect
= 1;
2802 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_SEND
, NULL
, 0);
2804 ret
= libc_connect(s
,
2806 un_addr
.sa_socklen
);
2809 SWRAP_LOG(SWRAP_LOG_TRACE
,
2810 "connect() path=%s, fd=%d",
2811 un_addr
.sa
.un
.sun_path
, s
);
2814 /* to give better errors */
2815 if (ret
== -1 && errno
== ENOENT
) {
2816 errno
= EHOSTUNREACH
;
2820 si
->peername
= (struct swrap_address
) {
2821 .sa_socklen
= addrlen
,
2824 memcpy(&si
->peername
.sa
.ss
, serv_addr
, addrlen
);
2828 * When we connect() on a socket than we have to bind the
2829 * outgoing connection on the interface we use for the
2830 * transport. We already bound it on the right interface
2831 * but here we have to update the name so getsockname()
2832 * returns correct information.
2834 if (si
->bindname
.sa_socklen
> 0) {
2835 si
->myname
= (struct swrap_address
) {
2836 .sa_socklen
= si
->bindname
.sa_socklen
,
2839 memcpy(&si
->myname
.sa
.ss
,
2840 &si
->bindname
.sa
.ss
,
2841 si
->bindname
.sa_socklen
);
2843 /* Cleanup bindname */
2844 si
->bindname
= (struct swrap_address
) {
2849 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_RECV
, NULL
, 0);
2850 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_ACK
, NULL
, 0);
2852 swrap_pcap_dump_packet(si
, serv_addr
, SWRAP_CONNECT_UNREACH
, NULL
, 0);
2858 int connect(int s
, const struct sockaddr
*serv_addr
, socklen_t addrlen
)
2860 return swrap_connect(s
, serv_addr
, addrlen
);
2863 /****************************************************************************
2865 ***************************************************************************/
2867 static int swrap_bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2870 struct swrap_address un_addr
= {
2871 .sa_socklen
= sizeof(struct sockaddr_un
),
2873 struct socket_info
*si
= find_socket_info(s
);
2880 return libc_bind(s
, myaddr
, addrlen
);
2883 switch (si
->family
) {
2885 const struct sockaddr_in
*sin
;
2886 if (addrlen
< sizeof(struct sockaddr_in
)) {
2887 bind_error
= EINVAL
;
2891 sin
= (const struct sockaddr_in
*)myaddr
;
2893 if (sin
->sin_family
!= AF_INET
) {
2894 bind_error
= EAFNOSUPPORT
;
2897 /* special case for AF_UNSPEC */
2898 if (sin
->sin_family
== AF_UNSPEC
&&
2899 (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
)))
2908 const struct sockaddr_in6
*sin6
;
2909 if (addrlen
< sizeof(struct sockaddr_in6
)) {
2910 bind_error
= EINVAL
;
2914 sin6
= (const struct sockaddr_in6
*)myaddr
;
2916 if (sin6
->sin6_family
!= AF_INET6
) {
2917 bind_error
= EAFNOSUPPORT
;
2924 bind_error
= EINVAL
;
2928 if (bind_error
!= 0) {
2934 in_use
= check_addr_port_in_use(myaddr
, addrlen
);
2941 si
->myname
.sa_socklen
= addrlen
;
2942 memcpy(&si
->myname
.sa
.ss
, myaddr
, addrlen
);
2944 ret
= sockaddr_convert_to_un(si
,
2950 if (ret
== -1) return -1;
2952 unlink(un_addr
.sa
.un
.sun_path
);
2954 ret
= libc_bind(s
, &un_addr
.sa
.s
, un_addr
.sa_socklen
);
2956 SWRAP_LOG(SWRAP_LOG_TRACE
,
2957 "bind() path=%s, fd=%d",
2958 un_addr
.sa
.un
.sun_path
, s
);
2967 int bind(int s
, const struct sockaddr
*myaddr
, socklen_t addrlen
)
2969 return swrap_bind(s
, myaddr
, addrlen
);
2972 /****************************************************************************
2974 ***************************************************************************/
2976 #ifdef HAVE_BINDRESVPORT
2977 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
);
2979 static int swrap_bindresvport_sa(int sd
, struct sockaddr
*sa
)
2981 struct swrap_address myaddr
= {
2982 .sa_socklen
= sizeof(struct sockaddr_storage
),
2985 static uint16_t port
;
2990 #define SWRAP_STARTPORT 600
2991 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2992 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2995 port
= (getpid() % SWRAP_NPORTS
) + SWRAP_STARTPORT
;
2999 salen
= myaddr
.sa_socklen
;
3002 rc
= swrap_getsockname(sd
, &myaddr
.sa
.s
, &salen
);
3008 memset(&myaddr
.sa
.ss
, 0, salen
);
3013 for (i
= 0; i
< SWRAP_NPORTS
; i
++, port
++) {
3016 struct sockaddr_in
*sinp
= (struct sockaddr_in
*)(void *)sa
;
3018 salen
= sizeof(struct sockaddr_in
);
3019 sinp
->sin_port
= htons(port
);
3023 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*)sa
;
3025 salen
= sizeof(struct sockaddr_in6
);
3026 sin6p
->sin6_port
= htons(port
);
3030 errno
= EAFNOSUPPORT
;
3035 if (port
> SWRAP_ENDPORT
) {
3036 port
= SWRAP_STARTPORT
;
3039 rc
= swrap_bind(sd
, (struct sockaddr
*)sa
, salen
);
3040 if (rc
== 0 || errno
!= EADDRINUSE
) {
3048 int bindresvport(int sockfd
, struct sockaddr_in
*sinp
)
3050 return swrap_bindresvport_sa(sockfd
, (struct sockaddr
*)sinp
);
3054 /****************************************************************************
3056 ***************************************************************************/
3058 static int swrap_listen(int s
, int backlog
)
3061 struct socket_info
*si
= find_socket_info(s
);
3064 return libc_listen(s
, backlog
);
3067 ret
= libc_listen(s
, backlog
);
3072 int listen(int s
, int backlog
)
3074 return swrap_listen(s
, backlog
);
3077 /****************************************************************************
3079 ***************************************************************************/
3081 static FILE *swrap_fopen(const char *name
, const char *mode
)
3085 fp
= libc_fopen(name
, mode
);
3087 int fd
= fileno(fp
);
3089 swrap_remove_stale(fd
);
3095 FILE *fopen(const char *name
, const char *mode
)
3097 return swrap_fopen(name
, mode
);
3100 /****************************************************************************
3102 ***************************************************************************/
3104 static int swrap_vopen(const char *pathname
, int flags
, va_list ap
)
3108 ret
= libc_vopen(pathname
, flags
, ap
);
3111 * There are methods for closing descriptors (libc-internal code
3112 * paths, direct syscalls) which close descriptors in ways that
3113 * we can't intercept, so try to recover when we notice that
3116 swrap_remove_stale(ret
);
3121 int open(const char *pathname
, int flags
, ...)
3126 va_start(ap
, flags
);
3127 fd
= swrap_vopen(pathname
, flags
, ap
);
3133 /****************************************************************************
3135 ***************************************************************************/
3137 static int swrap_getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3139 struct socket_info
*si
= find_socket_info(s
);
3143 return libc_getpeername(s
, name
, addrlen
);
3146 if (si
->peername
.sa_socklen
== 0)
3152 len
= MIN(*addrlen
, si
->peername
.sa_socklen
);
3157 memcpy(name
, &si
->peername
.sa
.ss
, len
);
3158 *addrlen
= si
->peername
.sa_socklen
;
3163 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3164 int getpeername(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3166 int getpeername(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3169 return swrap_getpeername(s
, name
, (socklen_t
*)addrlen
);
3172 /****************************************************************************
3174 ***************************************************************************/
3176 static int swrap_getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3178 struct socket_info
*si
= find_socket_info(s
);
3182 return libc_getsockname(s
, name
, addrlen
);
3185 len
= MIN(*addrlen
, si
->myname
.sa_socklen
);
3190 memcpy(name
, &si
->myname
.sa
.ss
, len
);
3191 *addrlen
= si
->myname
.sa_socklen
;
3196 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3197 int getsockname(int s
, struct sockaddr
*name
, Psocklen_t addrlen
)
3199 int getsockname(int s
, struct sockaddr
*name
, socklen_t
*addrlen
)
3202 return swrap_getsockname(s
, name
, (socklen_t
*)addrlen
);
3205 /****************************************************************************
3207 ***************************************************************************/
3210 # ifdef SO_PROTOTYPE /* The Solaris name */
3211 # define SO_PROTOCOL SO_PROTOTYPE
3212 # endif /* SO_PROTOTYPE */
3213 #endif /* SO_PROTOCOL */
3215 static int swrap_getsockopt(int s
, int level
, int optname
,
3216 void *optval
, socklen_t
*optlen
)
3218 struct socket_info
*si
= find_socket_info(s
);
3221 return libc_getsockopt(s
,
3228 if (level
== SOL_SOCKET
) {
3232 if (optval
== NULL
|| optlen
== NULL
||
3233 *optlen
< (socklen_t
)sizeof(int)) {
3238 *optlen
= sizeof(int);
3239 *(int *)optval
= si
->family
;
3241 #endif /* SO_DOMAIN */
3245 if (optval
== NULL
|| optlen
== NULL
||
3246 *optlen
< (socklen_t
)sizeof(int)) {
3251 *optlen
= sizeof(int);
3252 *(int *)optval
= si
->protocol
;
3254 #endif /* SO_PROTOCOL */
3256 if (optval
== NULL
|| optlen
== NULL
||
3257 *optlen
< (socklen_t
)sizeof(int)) {
3262 *optlen
= sizeof(int);
3263 *(int *)optval
= si
->type
;
3266 return libc_getsockopt(s
,
3274 errno
= ENOPROTOOPT
;
3278 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3279 int getsockopt(int s
, int level
, int optname
, void *optval
, Psocklen_t optlen
)
3281 int getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
3284 return swrap_getsockopt(s
, level
, optname
, optval
, (socklen_t
*)optlen
);
3287 /****************************************************************************
3289 ***************************************************************************/
3291 static int swrap_setsockopt(int s
, int level
, int optname
,
3292 const void *optval
, socklen_t optlen
)
3294 struct socket_info
*si
= find_socket_info(s
);
3297 return libc_setsockopt(s
,
3304 if (level
== SOL_SOCKET
) {
3305 return libc_setsockopt(s
,
3312 switch (si
->family
) {
3314 if (level
== IPPROTO_IP
) {
3316 if (optname
== IP_PKTINFO
) {
3317 si
->pktinfo
= AF_INET
;
3319 #endif /* IP_PKTINFO */
3324 if (level
== IPPROTO_IPV6
) {
3325 #ifdef IPV6_RECVPKTINFO
3326 if (optname
== IPV6_RECVPKTINFO
) {
3327 si
->pktinfo
= AF_INET6
;
3329 #endif /* IPV6_PKTINFO */
3334 errno
= ENOPROTOOPT
;
3339 int setsockopt(int s
, int level
, int optname
,
3340 const void *optval
, socklen_t optlen
)
3342 return swrap_setsockopt(s
, level
, optname
, optval
, optlen
);
3345 /****************************************************************************
3347 ***************************************************************************/
3349 static int swrap_vioctl(int s
, unsigned long int r
, va_list va
)
3351 struct socket_info
*si
= find_socket_info(s
);
3357 return libc_vioctl(s
, r
, va
);
3362 rc
= libc_vioctl(s
, r
, va
);
3366 value
= *((int *)va_arg(ap
, int *));
3368 if (rc
== -1 && errno
!= EAGAIN
&& errno
!= ENOBUFS
) {
3369 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3370 } else if (value
== 0) { /* END OF FILE */
3371 swrap_pcap_dump_packet(si
, NULL
, SWRAP_PENDING_RST
, NULL
, 0);
3381 #ifdef HAVE_IOCTL_INT
3382 int ioctl(int s
, int r
, ...)
3384 int ioctl(int s
, unsigned long int r
, ...)
3392 rc
= swrap_vioctl(s
, (unsigned long int) r
, va
);
3403 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3406 # ifdef _ALIGN /* BSD */
3407 #define CMSG_ALIGN _ALIGN
3409 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3410 # endif /* _ALIGN */
3411 #endif /* CMSG_ALIGN */
3414 * @brief Add a cmsghdr to a msghdr.
3416 * This is an function to add any type of cmsghdr. It will operate on the
3417 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3418 * the buffer position after the added cmsg element. Hence, this function is
3419 * intended to be used with an intermediate msghdr and not on the original
3420 * one handed in by the client.
3422 * @param[in] msg The msghdr to which to add the cmsg.
3424 * @param[in] level The cmsg level to set.
3426 * @param[in] type The cmsg type to set.
3428 * @param[in] data The cmsg data to set.
3430 * @param[in] len the length of the data to set.
3432 static void swrap_msghdr_add_cmsghdr(struct msghdr
*msg
,
3438 size_t cmlen
= CMSG_LEN(len
);
3439 size_t cmspace
= CMSG_SPACE(len
);
3440 uint8_t cmbuf
[cmspace
];
3441 void *cast_ptr
= (void *)cmbuf
;
3442 struct cmsghdr
*cm
= (struct cmsghdr
*)cast_ptr
;
3445 memset(cmbuf
, 0, cmspace
);
3447 if (msg
->msg_controllen
< cmlen
) {
3448 cmlen
= msg
->msg_controllen
;
3449 msg
->msg_flags
|= MSG_CTRUNC
;
3452 if (msg
->msg_controllen
< cmspace
) {
3453 cmspace
= msg
->msg_controllen
;
3457 * We copy the full input data into an intermediate cmsghdr first
3458 * in order to more easily cope with truncation.
3460 cm
->cmsg_len
= cmlen
;
3461 cm
->cmsg_level
= level
;
3462 cm
->cmsg_type
= type
;
3463 memcpy(CMSG_DATA(cm
), data
, len
);
3466 * We now copy the possibly truncated buffer.
3467 * We copy cmlen bytes, but consume cmspace bytes,
3468 * leaving the possible padding uninitialiazed.
3470 p
= (uint8_t *)msg
->msg_control
;
3471 memcpy(p
, cm
, cmlen
);
3473 msg
->msg_control
= p
;
3474 msg
->msg_controllen
-= cmspace
;
3479 static int swrap_msghdr_add_pktinfo(struct socket_info
*si
,
3482 /* Add packet info */
3483 switch (si
->pktinfo
) {
3484 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3486 struct sockaddr_in
*sin
;
3487 #if defined(HAVE_STRUCT_IN_PKTINFO)
3488 struct in_pktinfo pkt
;
3489 #elif defined(IP_RECVDSTADDR)
3493 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in
)) {
3494 sin
= &si
->bindname
.sa
.in
;
3496 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in
)) {
3499 sin
= &si
->myname
.sa
.in
;
3504 #if defined(HAVE_STRUCT_IN_PKTINFO)
3505 pkt
.ipi_ifindex
= socket_wrapper_default_iface();
3506 pkt
.ipi_addr
.s_addr
= sin
->sin_addr
.s_addr
;
3507 #elif defined(IP_RECVDSTADDR)
3508 pkt
= sin
->sin_addr
;
3511 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IP
, IP_PKTINFO
,
3516 #endif /* IP_PKTINFO */
3517 #if defined(HAVE_IPV6)
3519 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3520 struct sockaddr_in6
*sin6
;
3521 struct in6_pktinfo pkt6
;
3523 if (si
->bindname
.sa_socklen
== sizeof(struct sockaddr_in6
)) {
3524 sin6
= &si
->bindname
.sa
.in6
;
3526 if (si
->myname
.sa_socklen
!= sizeof(struct sockaddr_in6
)) {
3529 sin6
= &si
->myname
.sa
.in6
;
3534 pkt6
.ipi6_ifindex
= socket_wrapper_default_iface();
3535 pkt6
.ipi6_addr
= sin6
->sin6_addr
;
3537 swrap_msghdr_add_cmsghdr(msg
, IPPROTO_IPV6
, IPV6_PKTINFO
,
3538 &pkt6
, sizeof(pkt6
));
3539 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3543 #endif /* IPV6_PKTINFO */
3551 static int swrap_msghdr_add_socket_info(struct socket_info
*si
,
3552 struct msghdr
*omsg
)
3556 if (si
->pktinfo
> 0) {
3557 rc
= swrap_msghdr_add_pktinfo(si
, omsg
);
3563 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3565 size_t *cm_data_space
);
3566 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3568 size_t *cm_data_space
);
3570 static int swrap_sendmsg_filter_cmsghdr(struct msghdr
*msg
,
3572 size_t *cm_data_space
) {
3573 struct cmsghdr
*cmsg
;
3577 if (msg
->msg_controllen
== 0 || msg
->msg_control
== NULL
) {
3581 for (cmsg
= CMSG_FIRSTHDR(msg
);
3583 cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
3584 switch (cmsg
->cmsg_level
) {
3586 rc
= swrap_sendmsg_filter_cmsg_socket(cmsg
,
3591 rc
= swrap_sendmsg_copy_cmsg(cmsg
,
3601 static int swrap_sendmsg_copy_cmsg(struct cmsghdr
*cmsg
,
3603 size_t *cm_data_space
)
3610 CMSG_SPACE(cmsg
->cmsg_len
- CMSG_ALIGN(sizeof(struct cmsghdr
)));
3612 p
= realloc((*cm_data
), cmspace
);
3618 p
= (*cm_data
) + (*cm_data_space
);
3619 *cm_data_space
= cmspace
;
3621 memcpy(p
, cmsg
, cmsg
->cmsg_len
);
3626 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3628 size_t *cm_data_space
);
3631 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr
*cmsg
,
3633 size_t *cm_data_space
)
3637 switch(cmsg
->cmsg_type
) {
3640 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3647 rc
= swrap_sendmsg_filter_cmsg_pktinfo(cmsg
,
3659 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr
*cmsg
,
3661 size_t *cm_data_space
)
3663 (void)cmsg
; /* unused */
3664 (void)cm_data
; /* unused */
3665 (void)cm_data_space
; /* unused */
3668 * Passing a IP pktinfo to a unix socket might be rejected by the
3669 * Kernel, at least on FreeBSD. So skip this cmsg.
3673 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3675 static ssize_t
swrap_sendmsg_before(int fd
,
3676 struct socket_info
*si
,
3678 struct iovec
*tmp_iov
,
3679 struct sockaddr_un
*tmp_un
,
3680 const struct sockaddr_un
**to_un
,
3681 const struct sockaddr
**to
,
3699 if (!si
->connected
) {
3704 if (msg
->msg_iovlen
== 0) {
3708 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3710 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3711 if (nlen
> SOCKET_MAX_PACKET
) {
3715 msg
->msg_iovlen
= i
;
3716 if (msg
->msg_iovlen
== 0) {
3717 *tmp_iov
= msg
->msg_iov
[0];
3718 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3719 msg
->msg_iov
= tmp_iov
;
3720 msg
->msg_iovlen
= 1;
3725 if (si
->connected
) {
3726 if (msg
->msg_name
) {
3731 const struct sockaddr
*msg_name
;
3732 msg_name
= (const struct sockaddr
*)msg
->msg_name
;
3734 if (msg_name
== NULL
) {
3740 ret
= sockaddr_convert_to_un(si
, msg_name
, msg
->msg_namelen
,
3742 if (ret
== -1) return -1;
3750 msg
->msg_name
= tmp_un
;
3751 msg
->msg_namelen
= sizeof(*tmp_un
);
3754 if (si
->bound
== 0) {
3755 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3757 if (errno
== ENOTSOCK
) {
3758 swrap_remove_stale(fd
);
3761 SWRAP_LOG(SWRAP_LOG_ERROR
, "swrap_sendmsg_before failed");
3767 if (!si
->defer_connect
) {
3771 ret
= sockaddr_convert_to_un(si
,
3773 si
->peername
.sa_socklen
,
3777 if (ret
== -1) return -1;
3779 ret
= libc_connect(fd
,
3780 (struct sockaddr
*)(void *)tmp_un
,
3783 /* to give better errors */
3784 if (ret
== -1 && errno
== ENOENT
) {
3785 errno
= EHOSTUNREACH
;
3792 si
->defer_connect
= 0;
3795 errno
= EHOSTUNREACH
;
3799 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3800 if (msg
->msg_controllen
> 0 && msg
->msg_control
!= NULL
) {
3801 uint8_t *cmbuf
= NULL
;
3804 ret
= swrap_sendmsg_filter_cmsghdr(msg
, &cmbuf
, &cmlen
);
3811 msg
->msg_controllen
= 0;
3812 msg
->msg_control
= NULL
;
3813 } else if (cmlen
< msg
->msg_controllen
&& cmbuf
!= NULL
) {
3814 memcpy(msg
->msg_control
, cmbuf
, cmlen
);
3815 msg
->msg_controllen
= cmlen
;
3824 static void swrap_sendmsg_after(int fd
,
3825 struct socket_info
*si
,
3827 const struct sockaddr
*to
,
3830 int saved_errno
= errno
;
3837 /* to give better errors */
3839 if (saved_errno
== ENOENT
) {
3840 saved_errno
= EHOSTUNREACH
;
3841 } else if (saved_errno
== ENOTSOCK
) {
3842 /* If the fd is not a socket, remove it */
3843 swrap_remove_stale(fd
);
3847 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3848 avail
+= msg
->msg_iov
[i
].iov_len
;
3852 remain
= MIN(80, avail
);
3857 /* we capture it as one single packet */
3858 buf
= (uint8_t *)malloc(remain
);
3860 /* we just not capture the packet */
3861 errno
= saved_errno
;
3865 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3866 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
3868 msg
->msg_iov
[i
].iov_base
,
3871 remain
-= this_time
;
3878 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3879 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND_RST
, NULL
, 0);
3881 swrap_pcap_dump_packet(si
, NULL
, SWRAP_SEND
, buf
, len
);
3886 if (si
->connected
) {
3887 to
= &si
->peername
.sa
.s
;
3890 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3891 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO_UNREACH
, buf
, len
);
3893 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
3899 errno
= saved_errno
;
3902 static int swrap_recvmsg_before(int fd
,
3903 struct socket_info
*si
,
3905 struct iovec
*tmp_iov
)
3910 (void)fd
; /* unused */
3914 if (!si
->connected
) {
3919 if (msg
->msg_iovlen
== 0) {
3923 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
3925 nlen
= len
+ msg
->msg_iov
[i
].iov_len
;
3926 if (nlen
> SOCKET_MAX_PACKET
) {
3930 msg
->msg_iovlen
= i
;
3931 if (msg
->msg_iovlen
== 0) {
3932 *tmp_iov
= msg
->msg_iov
[0];
3933 tmp_iov
->iov_len
= MIN(tmp_iov
->iov_len
, SOCKET_MAX_PACKET
);
3934 msg
->msg_iov
= tmp_iov
;
3935 msg
->msg_iovlen
= 1;
3940 if (msg
->msg_name
== NULL
) {
3945 if (msg
->msg_iovlen
== 0) {
3949 if (si
->bound
== 0) {
3950 ret
= swrap_auto_bind(fd
, si
, si
->family
);
3953 * When attempting to read or write to a
3954 * descriptor, if an underlying autobind fails
3955 * because it's not a socket, stop intercepting
3956 * uses of that descriptor.
3958 if (errno
== ENOTSOCK
) {
3959 swrap_remove_stale(fd
);
3962 SWRAP_LOG(SWRAP_LOG_ERROR
,
3963 "swrap_recvmsg_before failed");
3970 errno
= EHOSTUNREACH
;
3977 static int swrap_recvmsg_after(int fd
,
3978 struct socket_info
*si
,
3980 const struct sockaddr_un
*un_addr
,
3981 socklen_t un_addrlen
,
3984 int saved_errno
= errno
;
3986 uint8_t *buf
= NULL
;
3992 /* to give better errors */
3994 if (saved_errno
== ENOENT
) {
3995 saved_errno
= EHOSTUNREACH
;
3996 } else if (saved_errno
== ENOTSOCK
) {
3997 /* If the fd is not a socket, remove it */
3998 swrap_remove_stale(fd
);
4002 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4003 avail
+= msg
->msg_iov
[i
].iov_len
;
4012 remain
= MIN(80, avail
);
4017 /* we capture it as one single packet */
4018 buf
= (uint8_t *)malloc(remain
);
4020 /* we just not capture the packet */
4021 errno
= saved_errno
;
4025 for (i
= 0; i
< (size_t)msg
->msg_iovlen
; i
++) {
4026 size_t this_time
= MIN(remain
, (size_t)msg
->msg_iov
[i
].iov_len
);
4028 msg
->msg_iov
[i
].iov_base
,
4031 remain
-= this_time
;
4036 if (ret
== -1 && saved_errno
!= EAGAIN
&& saved_errno
!= ENOBUFS
) {
4037 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4038 } else if (ret
== 0) { /* END OF FILE */
4039 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV_RST
, NULL
, 0);
4040 } else if (ret
> 0) {
4041 swrap_pcap_dump_packet(si
, NULL
, SWRAP_RECV
, buf
, ret
);
4050 if (un_addr
!= NULL
) {
4051 rc
= sockaddr_convert_from_un(si
,
4061 swrap_pcap_dump_packet(si
,
4067 swrap_pcap_dump_packet(si
,
4080 errno
= saved_errno
;
4082 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4084 msg
->msg_controllen
> 0 &&
4085 msg
->msg_control
!= NULL
) {
4086 rc
= swrap_msghdr_add_socket_info(si
, msg
);
4096 /****************************************************************************
4098 ***************************************************************************/
4100 static ssize_t
swrap_recvfrom(int s
, void *buf
, size_t len
, int flags
,
4101 struct sockaddr
*from
, socklen_t
*fromlen
)
4103 struct swrap_address from_addr
= {
4104 .sa_socklen
= sizeof(struct sockaddr_un
),
4107 struct socket_info
*si
= find_socket_info(s
);
4108 struct swrap_address saddr
= {
4109 .sa_socklen
= sizeof(struct sockaddr_storage
),
4116 return libc_recvfrom(s
,
4128 if (from
!= NULL
&& fromlen
!= NULL
) {
4129 msg
.msg_name
= from
; /* optional address */
4130 msg
.msg_namelen
= *fromlen
; /* size of address */
4132 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4133 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4135 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4136 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4137 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4138 msg
.msg_control
= NULL
; /* ancillary data, see below */
4139 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4140 msg
.msg_flags
= 0; /* flags on received message */
4143 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4148 buf
= msg
.msg_iov
[0].iov_base
;
4149 len
= msg
.msg_iov
[0].iov_len
;
4151 ret
= libc_recvfrom(s
,
4156 &from_addr
.sa_socklen
);
4161 tret
= swrap_recvmsg_after(s
,
4165 from_addr
.sa_socklen
,
4171 if (from
!= NULL
&& fromlen
!= NULL
) {
4172 *fromlen
= msg
.msg_namelen
;
4178 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4179 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4180 struct sockaddr
*from
, Psocklen_t fromlen
)
4182 ssize_t
recvfrom(int s
, void *buf
, size_t len
, int flags
,
4183 struct sockaddr
*from
, socklen_t
*fromlen
)
4186 return swrap_recvfrom(s
, buf
, len
, flags
, from
, (socklen_t
*)fromlen
);
4189 /****************************************************************************
4191 ***************************************************************************/
4193 static ssize_t
swrap_sendto(int s
, const void *buf
, size_t len
, int flags
,
4194 const struct sockaddr
*to
, socklen_t tolen
)
4198 struct swrap_address un_addr
= {
4199 .sa_socklen
= sizeof(struct sockaddr_un
),
4201 const struct sockaddr_un
*to_un
= NULL
;
4204 struct socket_info
*si
= find_socket_info(s
);
4208 return libc_sendto(s
, buf
, len
, flags
, to
, tolen
);
4211 tmp
.iov_base
= discard_const_p(char, buf
);
4215 msg
.msg_name
= discard_const_p(struct sockaddr
, to
); /* optional address */
4216 msg
.msg_namelen
= tolen
; /* size of address */
4217 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4218 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4219 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4220 msg
.msg_control
= NULL
; /* ancillary data, see below */
4221 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4222 msg
.msg_flags
= 0; /* flags on received message */
4225 rc
= swrap_sendmsg_before(s
,
4237 buf
= msg
.msg_iov
[0].iov_base
;
4238 len
= msg
.msg_iov
[0].iov_len
;
4243 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4246 type
= SOCKET_TYPE_CHAR_UDP
;
4248 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4249 snprintf(un_addr
.sa
.un
.sun_path
,
4250 sizeof(un_addr
.sa
.un
.sun_path
),
4252 socket_wrapper_dir(), type
, iface
, prt
);
4253 if (stat(un_addr
.sa
.un
.sun_path
, &st
) != 0) continue;
4255 /* ignore the any errors in broadcast sends */
4261 un_addr
.sa_socklen
);
4264 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4269 ret
= libc_sendto(s
,
4273 (struct sockaddr
*)msg
.msg_name
,
4276 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4281 ssize_t
sendto(int s
, const void *buf
, size_t len
, int flags
,
4282 const struct sockaddr
*to
, socklen_t tolen
)
4284 return swrap_sendto(s
, buf
, len
, flags
, to
, tolen
);
4287 /****************************************************************************
4289 ***************************************************************************/
4291 static ssize_t
swrap_recv(int s
, void *buf
, size_t len
, int flags
)
4293 struct socket_info
*si
;
4295 struct swrap_address saddr
= {
4296 .sa_socklen
= sizeof(struct sockaddr_storage
),
4302 si
= find_socket_info(s
);
4304 return libc_recv(s
, buf
, len
, flags
);
4311 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4312 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4313 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4314 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4315 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4316 msg
.msg_control
= NULL
; /* ancillary data, see below */
4317 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4318 msg
.msg_flags
= 0; /* flags on received message */
4321 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4326 buf
= msg
.msg_iov
[0].iov_base
;
4327 len
= msg
.msg_iov
[0].iov_len
;
4329 ret
= libc_recv(s
, buf
, len
, flags
);
4331 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4339 ssize_t
recv(int s
, void *buf
, size_t len
, int flags
)
4341 return swrap_recv(s
, buf
, len
, flags
);
4344 /****************************************************************************
4346 ***************************************************************************/
4348 static ssize_t
swrap_read(int s
, void *buf
, size_t len
)
4350 struct socket_info
*si
;
4353 struct swrap_address saddr
= {
4354 .sa_socklen
= sizeof(struct sockaddr_storage
),
4359 si
= find_socket_info(s
);
4361 return libc_read(s
, buf
, len
);
4368 msg
.msg_name
= &saddr
.sa
.ss
; /* optional address */
4369 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4370 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4371 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4372 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4373 msg
.msg_control
= NULL
; /* ancillary data, see below */
4374 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4375 msg
.msg_flags
= 0; /* flags on received message */
4378 tret
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4380 if (tret
== -ENOTSOCK
) {
4381 return libc_read(s
, buf
, len
);
4386 buf
= msg
.msg_iov
[0].iov_base
;
4387 len
= msg
.msg_iov
[0].iov_len
;
4389 ret
= libc_read(s
, buf
, len
);
4391 tret
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4399 ssize_t
read(int s
, void *buf
, size_t len
)
4401 return swrap_read(s
, buf
, len
);
4404 /****************************************************************************
4406 ***************************************************************************/
4408 static ssize_t
swrap_send(int s
, const void *buf
, size_t len
, int flags
)
4412 struct sockaddr_un un_addr
;
4415 struct socket_info
*si
= find_socket_info(s
);
4418 return libc_send(s
, buf
, len
, flags
);
4421 tmp
.iov_base
= discard_const_p(char, buf
);
4425 msg
.msg_name
= NULL
; /* optional address */
4426 msg
.msg_namelen
= 0; /* size of address */
4427 msg
.msg_iov
= &tmp
; /* scatter/gather array */
4428 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
4429 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4430 msg
.msg_control
= NULL
; /* ancillary data, see below */
4431 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4432 msg
.msg_flags
= 0; /* flags on received message */
4435 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4440 buf
= msg
.msg_iov
[0].iov_base
;
4441 len
= msg
.msg_iov
[0].iov_len
;
4443 ret
= libc_send(s
, buf
, len
, flags
);
4445 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4450 ssize_t
send(int s
, const void *buf
, size_t len
, int flags
)
4452 return swrap_send(s
, buf
, len
, flags
);
4455 /****************************************************************************
4457 ***************************************************************************/
4459 static ssize_t
swrap_recvmsg(int s
, struct msghdr
*omsg
, int flags
)
4461 struct swrap_address from_addr
= {
4462 .sa_socklen
= sizeof(struct sockaddr_un
),
4464 struct socket_info
*si
;
4467 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4468 size_t msg_ctrllen_filled
;
4469 size_t msg_ctrllen_left
;
4475 si
= find_socket_info(s
);
4477 return libc_recvmsg(s
, omsg
, flags
);
4480 tmp
.iov_base
= NULL
;
4484 msg
.msg_name
= &from_addr
.sa
; /* optional address */
4485 msg
.msg_namelen
= from_addr
.sa_socklen
; /* size of address */
4486 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4487 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4488 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4489 msg_ctrllen_filled
= 0;
4490 msg_ctrllen_left
= omsg
->msg_controllen
;
4492 msg
.msg_control
= omsg
->msg_control
; /* ancillary data, see below */
4493 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4494 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4497 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4502 ret
= libc_recvmsg(s
, &msg
, flags
);
4504 msg
.msg_name
= omsg
->msg_name
;
4505 msg
.msg_namelen
= omsg
->msg_namelen
;
4507 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4508 msg_ctrllen_filled
+= msg
.msg_controllen
;
4509 msg_ctrllen_left
-= msg
.msg_controllen
;
4511 if (omsg
->msg_control
!= NULL
) {
4514 p
= omsg
->msg_control
;
4515 p
+= msg_ctrllen_filled
;
4517 msg
.msg_control
= p
;
4518 msg
.msg_controllen
= msg_ctrllen_left
;
4520 msg
.msg_control
= NULL
;
4521 msg
.msg_controllen
= 0;
4525 rc
= swrap_recvmsg_after(s
,
4529 from_addr
.sa_socklen
,
4535 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4536 if (omsg
->msg_control
!= NULL
) {
4537 /* msg.msg_controllen = space left */
4538 msg_ctrllen_left
= msg
.msg_controllen
;
4539 msg_ctrllen_filled
= omsg
->msg_controllen
- msg_ctrllen_left
;
4542 /* Update the original message length */
4543 omsg
->msg_controllen
= msg_ctrllen_filled
;
4544 omsg
->msg_flags
= msg
.msg_flags
;
4546 omsg
->msg_iovlen
= msg
.msg_iovlen
;
4551 ssize_t
recvmsg(int sockfd
, struct msghdr
*msg
, int flags
)
4553 return swrap_recvmsg(sockfd
, msg
, flags
);
4556 /****************************************************************************
4558 ***************************************************************************/
4560 static ssize_t
swrap_sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4564 struct sockaddr_un un_addr
;
4565 const struct sockaddr_un
*to_un
= NULL
;
4566 const struct sockaddr
*to
= NULL
;
4569 struct socket_info
*si
= find_socket_info(s
);
4573 return libc_sendmsg(s
, omsg
, flags
);
4576 ZERO_STRUCT(un_addr
);
4578 tmp
.iov_base
= NULL
;
4582 msg
.msg_name
= omsg
->msg_name
; /* optional address */
4583 msg
.msg_namelen
= omsg
->msg_namelen
; /* size of address */
4584 msg
.msg_iov
= omsg
->msg_iov
; /* scatter/gather array */
4585 msg
.msg_iovlen
= omsg
->msg_iovlen
; /* # elements in msg_iov */
4586 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4587 if (msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
) {
4588 /* omsg is a const so use a local buffer for modifications */
4589 uint8_t cmbuf
[omsg
->msg_controllen
];
4591 memcpy(cmbuf
, omsg
->msg_control
, omsg
->msg_controllen
);
4593 msg
.msg_control
= cmbuf
; /* ancillary data, see below */
4594 msg
.msg_controllen
= omsg
->msg_controllen
; /* ancillary data buffer len */
4596 msg
.msg_flags
= omsg
->msg_flags
; /* flags on received message */
4599 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, &to_un
, &to
, &bcast
);
4607 unsigned int prt
= ntohs(((const struct sockaddr_in
*)to
)->sin_port
);
4615 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4616 avail
+= msg
.msg_iov
[i
].iov_len
;
4622 /* we capture it as one single packet */
4623 buf
= (uint8_t *)malloc(remain
);
4628 for (i
= 0; i
< (size_t)msg
.msg_iovlen
; i
++) {
4629 size_t this_time
= MIN(remain
, (size_t)msg
.msg_iov
[i
].iov_len
);
4631 msg
.msg_iov
[i
].iov_base
,
4634 remain
-= this_time
;
4637 type
= SOCKET_TYPE_CHAR_UDP
;
4639 for(iface
=0; iface
<= MAX_WRAPPED_INTERFACES
; iface
++) {
4640 snprintf(un_addr
.sun_path
, sizeof(un_addr
.sun_path
), "%s/"SOCKET_FORMAT
,
4641 socket_wrapper_dir(), type
, iface
, prt
);
4642 if (stat(un_addr
.sun_path
, &st
) != 0) continue;
4644 msg
.msg_name
= &un_addr
; /* optional address */
4645 msg
.msg_namelen
= sizeof(un_addr
); /* size of address */
4647 /* ignore the any errors in broadcast sends */
4648 libc_sendmsg(s
, &msg
, flags
);
4651 swrap_pcap_dump_packet(si
, to
, SWRAP_SENDTO
, buf
, len
);
4657 ret
= libc_sendmsg(s
, &msg
, flags
);
4659 swrap_sendmsg_after(s
, si
, &msg
, to
, ret
);
4664 ssize_t
sendmsg(int s
, const struct msghdr
*omsg
, int flags
)
4666 return swrap_sendmsg(s
, omsg
, flags
);
4669 /****************************************************************************
4671 ***************************************************************************/
4673 static ssize_t
swrap_readv(int s
, const struct iovec
*vector
, int count
)
4675 struct socket_info
*si
;
4678 struct swrap_address saddr
= {
4679 .sa_socklen
= sizeof(struct sockaddr_storage
)
4684 si
= find_socket_info(s
);
4686 return libc_readv(s
, vector
, count
);
4689 tmp
.iov_base
= NULL
;
4693 msg
.msg_name
= &saddr
.sa
.s
; /* optional address */
4694 msg
.msg_namelen
= saddr
.sa_socklen
; /* size of address */
4695 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4696 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4697 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4698 msg
.msg_control
= NULL
; /* ancillary data, see below */
4699 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4700 msg
.msg_flags
= 0; /* flags on received message */
4703 rc
= swrap_recvmsg_before(s
, si
, &msg
, &tmp
);
4705 if (rc
== -ENOTSOCK
) {
4706 return libc_readv(s
, vector
, count
);
4711 ret
= libc_readv(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4713 rc
= swrap_recvmsg_after(s
, si
, &msg
, NULL
, 0, ret
);
4721 ssize_t
readv(int s
, const struct iovec
*vector
, int count
)
4723 return swrap_readv(s
, vector
, count
);
4726 /****************************************************************************
4728 ***************************************************************************/
4730 static ssize_t
swrap_writev(int s
, const struct iovec
*vector
, int count
)
4734 struct sockaddr_un un_addr
;
4737 struct socket_info
*si
= find_socket_info(s
);
4740 return libc_writev(s
, vector
, count
);
4743 tmp
.iov_base
= NULL
;
4747 msg
.msg_name
= NULL
; /* optional address */
4748 msg
.msg_namelen
= 0; /* size of address */
4749 msg
.msg_iov
= discard_const_p(struct iovec
, vector
); /* scatter/gather array */
4750 msg
.msg_iovlen
= count
; /* # elements in msg_iov */
4751 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4752 msg
.msg_control
= NULL
; /* ancillary data, see below */
4753 msg
.msg_controllen
= 0; /* ancillary data buffer len */
4754 msg
.msg_flags
= 0; /* flags on received message */
4757 rc
= swrap_sendmsg_before(s
, si
, &msg
, &tmp
, &un_addr
, NULL
, NULL
, NULL
);
4759 if (rc
== -ENOTSOCK
) {
4760 return libc_readv(s
, vector
, count
);
4765 ret
= libc_writev(s
, msg
.msg_iov
, msg
.msg_iovlen
);
4767 swrap_sendmsg_after(s
, si
, &msg
, NULL
, ret
);
4772 ssize_t
writev(int s
, const struct iovec
*vector
, int count
)
4774 return swrap_writev(s
, vector
, count
);
4777 /****************************
4779 ***************************/
4781 static int swrap_close(int fd
)
4783 struct socket_info
*si
= find_socket_info(fd
);
4784 struct socket_info_fd
*fi
;
4788 return libc_close(fd
);
4791 for (fi
= si
->fds
; fi
; fi
= fi
->next
) {
4793 SWRAP_DLIST_REMOVE(si
->fds
, fi
);
4800 /* there are still references left */
4801 return libc_close(fd
);
4804 SWRAP_DLIST_REMOVE(sockets
, si
);
4806 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
4807 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_SEND
, NULL
, 0);
4810 ret
= libc_close(fd
);
4812 if (si
->myname
.sa_socklen
> 0 && si
->peername
.sa_socklen
> 0) {
4813 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_RECV
, NULL
, 0);
4814 swrap_pcap_dump_packet(si
, NULL
, SWRAP_CLOSE_ACK
, NULL
, 0);
4817 if (si
->un_addr
.sun_path
[0] != '\0') {
4818 unlink(si
->un_addr
.sun_path
);
4827 return swrap_close(fd
);
4830 /****************************
4832 ***************************/
4834 static int swrap_dup(int fd
)
4836 struct socket_info
*si
;
4837 struct socket_info_fd
*fi
;
4839 si
= find_socket_info(fd
);
4842 return libc_dup(fd
);
4845 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4851 fi
->fd
= libc_dup(fd
);
4853 int saved_errno
= errno
;
4855 errno
= saved_errno
;
4859 /* Make sure we don't have an entry for the fd */
4860 swrap_remove_stale(fi
->fd
);
4862 SWRAP_DLIST_ADD(si
->fds
, fi
);
4868 return swrap_dup(fd
);
4871 /****************************
4873 ***************************/
4875 static int swrap_dup2(int fd
, int newfd
)
4877 struct socket_info
*si
;
4878 struct socket_info_fd
*fi
;
4880 si
= find_socket_info(fd
);
4883 return libc_dup2(fd
, newfd
);
4886 if (find_socket_info(newfd
)) {
4887 /* dup2() does an implicit close of newfd, which we
4888 * need to emulate */
4892 fi
= (struct socket_info_fd
*)calloc(1, sizeof(struct socket_info_fd
));
4898 fi
->fd
= libc_dup2(fd
, newfd
);
4900 int saved_errno
= errno
;
4902 errno
= saved_errno
;
4906 /* Make sure we don't have an entry for the fd */
4907 swrap_remove_stale(fi
->fd
);
4909 SWRAP_DLIST_ADD(si
->fds
, fi
);
4913 int dup2(int fd
, int newfd
)
4915 return swrap_dup2(fd
, newfd
);
4918 /****************************
4920 ***************************/
4923 static int swrap_eventfd(int count
, int flags
)
4927 fd
= libc_eventfd(count
, flags
);
4929 swrap_remove_stale(fd
);
4935 int eventfd(int count
, int flags
)
4937 return swrap_eventfd(count
, flags
);
4941 /****************************
4943 ***************************/
4946 * This function is called when the library is unloaded and makes sure that
4947 * sockets get closed and the unix file for the socket are unlinked.
4949 void swrap_destructor(void)
4951 struct socket_info
*s
= sockets
;
4954 struct socket_info_fd
*f
= s
->fds
;