2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
45 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
87 /* GCC have printf type attribute check. */
88 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
89 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
91 #define PRINTF_ATTRIBUTE(a,b)
92 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
94 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
95 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
97 #define DESTRUCTOR_ATTRIBUTE
100 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
101 # define SWRAP_THREAD __thread
103 # define SWRAP_THREAD
107 #define MIN(a,b) ((a)<(b)?(a):(b))
111 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
114 #ifndef discard_const
115 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
118 #ifndef discard_const_p
119 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
123 # ifndef IPV6_RECVPKTINFO
124 # define IPV6_RECVPKTINFO IPV6_PKTINFO
125 # endif /* IPV6_RECVPKTINFO */
126 #endif /* IPV6_PKTINFO */
128 #define SWRAP_DLIST_ADD(list,item) do { \
130 (item)->prev = NULL; \
131 (item)->next = NULL; \
134 (item)->prev = NULL; \
135 (item)->next = (list); \
136 (list)->prev = (item); \
141 #define SWRAP_DLIST_REMOVE(list,item) do { \
142 if ((list) == (item)) { \
143 (list) = (item)->next; \
145 (list)->prev = NULL; \
148 if ((item)->prev) { \
149 (item)->prev->next = (item)->next; \
151 if ((item)->next) { \
152 (item)->next->prev = (item)->prev; \
155 (item)->prev = NULL; \
156 (item)->next = NULL; \
159 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
160 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
162 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
165 /* we need to use a very terse format here as IRIX 6.4 silently
166 truncates names to 16 chars, so if we use a longer name then we
167 can't tell which port a packet came from with recvfrom()
169 with this format we have 8 chars left for the directory name
171 #define SOCKET_FORMAT "%c%02X%04X"
172 #define SOCKET_TYPE_CHAR_TCP 'T'
173 #define SOCKET_TYPE_CHAR_UDP 'U'
174 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
175 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
178 * Cut down to 1500 byte packets for stream sockets,
179 * which makes it easier to format PCAP capture files
180 * (as the caller will simply continue from here)
182 #define SOCKET_MAX_PACKET 1500
184 #define SOCKET_MAX_SOCKETS 1024
186 /* This limit is to avoid broadcast sendto() needing to stat too many
187 * files. It may be raised (with a performance cost) to up to 254
188 * without changing the format above */
189 #define MAX_WRAPPED_INTERFACES 40
191 struct socket_info_fd {
192 struct socket_info_fd *prev, *next;
198 struct socket_info_fd *fds;
212 struct sockaddr *bindname;
213 socklen_t bindname_len;
215 struct sockaddr *myname;
216 socklen_t myname_len;
218 struct sockaddr *peername;
219 socklen_t peername_len;
222 unsigned long pck_snd;
223 unsigned long pck_rcv;
226 struct socket_info *prev, *next;
230 * File descriptors are shared between threads so we should share socket
233 struct socket_info *sockets;
235 /* Function prototypes */
237 bool socket_wrapper_enabled(void);
238 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
241 # define SWRAP_LOG(...)
244 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
245 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
247 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
252 unsigned int lvl = 0;
254 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
259 va_start(va, format);
260 vsnprintf(buffer, sizeof(buffer), format, va);
265 case SWRAP_LOG_ERROR:
267 "SWRAP_ERROR(%d): %s\n",
268 (int)getpid(), buffer);
272 "SWRAP_WARN(%d): %s\n",
273 (int)getpid(), buffer);
275 case SWRAP_LOG_DEBUG:
277 "SWRAP_DEBUG(%d): %s\n",
278 (int)getpid(), buffer);
280 case SWRAP_LOG_TRACE:
282 "SWRAP_TRACE(%d): %s\n",
283 (int)getpid(), buffer);
290 /*********************************************************
291 * SWRAP LOADING LIBC FUNCTIONS
292 *********************************************************/
296 struct swrap_libc_fns {
297 int (*libc_accept)(int sockfd,
298 struct sockaddr *addr,
300 int (*libc_bind)(int sockfd,
301 const struct sockaddr *addr,
303 int (*libc_close)(int fd);
304 int (*libc_connect)(int sockfd,
305 const struct sockaddr *addr,
307 int (*libc_dup)(int fd);
308 int (*libc_dup2)(int oldfd, int newfd);
310 int (*libc_eventfd)(int count, int flags);
312 int (*libc_getpeername)(int sockfd,
313 struct sockaddr *addr,
315 int (*libc_getsockname)(int sockfd,
316 struct sockaddr *addr,
318 int (*libc_getsockopt)(int sockfd,
323 int (*libc_ioctl)(int d, unsigned long int request, ...);
324 int (*libc_listen)(int sockfd, int backlog);
325 int (*libc_open)(const char *pathname, int flags, mode_t mode);
326 int (*libc_pipe)(int pipefd[2]);
327 int (*libc_read)(int fd, void *buf, size_t count);
328 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
329 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
330 int (*libc_recvfrom)(int sockfd,
334 struct sockaddr *src_addr,
336 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
337 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
338 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
339 int (*libc_sendto)(int sockfd,
343 const struct sockaddr *dst_addr,
345 int (*libc_setsockopt)(int sockfd,
351 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
353 int (*libc_socket)(int domain, int type, int protocol);
354 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
355 #ifdef HAVE_TIMERFD_CREATE
356 int (*libc_timerfd_create)(int clockid, int flags);
358 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
363 void *libsocket_handle;
370 struct swrap_libc_fns fns;
373 static struct swrap swrap;
376 static const char *socket_wrapper_dir(void);
378 #define LIBC_NAME "libc.so"
387 static const char *swrap_str_lib(enum swrap_lib lib)
394 case SWRAP_LIBSOCKET:
398 /* Compiler would warn us about unhandled enum value if we get here */
403 static void *swrap_load_lib_handle(enum swrap_lib lib)
405 int flags = RTLD_LAZY;
410 flags |= RTLD_DEEPBIND;
416 case SWRAP_LIBSOCKET:
417 #ifdef HAVE_LIBSOCKET
418 handle = swrap.libsocket_handle;
419 if (handle == NULL) {
420 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
421 char soname[256] = {0};
423 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
424 handle = dlopen(soname, flags);
427 swrap.libsocket_handle = handle;
433 handle = swrap.libc_handle;
435 if (handle == NULL) {
436 handle = dlopen(LIBC_SO, flags);
439 if (handle == NULL) {
440 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
441 char soname[256] = {0};
443 snprintf(soname, sizeof(soname), "libc.so.%d", i);
444 handle = dlopen(soname, flags);
447 swrap.libc_handle = handle;
452 if (handle == NULL) {
454 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
456 SWRAP_LOG(SWRAP_LOG_ERROR,
457 "Failed to dlopen library: %s\n",
466 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
471 handle = swrap_load_lib_handle(lib);
473 func = dlsym(handle, fn_name);
475 SWRAP_LOG(SWRAP_LOG_ERROR,
476 "Failed to find %s: %s\n",
481 SWRAP_LOG(SWRAP_LOG_TRACE,
483 fn_name, swrap_str_lib(lib));
487 #define swrap_load_lib_function(lib, fn_name) \
488 if (swrap.fns.libc_##fn_name == NULL) { \
489 *(void **) (&swrap.fns.libc_##fn_name) = \
490 _swrap_load_lib_function(lib, #fn_name); \
497 * Functions especially from libc need to be loaded individually, you can't load
498 * all at once or gdb will segfault at startup. The same applies to valgrind and
499 * has probably something todo with with the linker.
500 * So we need load each function at the point it is called the first time.
502 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
504 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
506 return swrap.fns.libc_accept(sockfd, addr, addrlen);
509 static int libc_bind(int sockfd,
510 const struct sockaddr *addr,
513 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
515 return swrap.fns.libc_bind(sockfd, addr, addrlen);
518 static int libc_close(int fd)
520 swrap_load_lib_function(SWRAP_LIBC, close);
522 return swrap.fns.libc_close(fd);
525 static int libc_connect(int sockfd,
526 const struct sockaddr *addr,
529 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
531 return swrap.fns.libc_connect(sockfd, addr, addrlen);
534 static int libc_dup(int fd)
536 swrap_load_lib_function(SWRAP_LIBC, dup);
538 return swrap.fns.libc_dup(fd);
541 static int libc_dup2(int oldfd, int newfd)
543 swrap_load_lib_function(SWRAP_LIBC, dup2);
545 return swrap.fns.libc_dup2(oldfd, newfd);
549 static int libc_eventfd(int count, int flags)
551 swrap_load_lib_function(SWRAP_LIBC, eventfd);
553 return swrap.fns.libc_eventfd(count, flags);
557 static int libc_getpeername(int sockfd,
558 struct sockaddr *addr,
561 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
563 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
566 static int libc_getsockname(int sockfd,
567 struct sockaddr *addr,
570 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
572 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
575 static int libc_getsockopt(int sockfd,
581 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
583 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
586 static int libc_vioctl(int d, unsigned long int request, va_list ap)
592 swrap_load_lib_function(SWRAP_LIBC, ioctl);
594 for (i = 0; i < 4; i++) {
595 args[i] = va_arg(ap, long int);
598 rc = swrap.fns.libc_ioctl(d,
608 static int libc_listen(int sockfd, int backlog)
610 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
612 return swrap.fns.libc_listen(sockfd, backlog);
615 static int libc_vopen(const char *pathname, int flags, va_list ap)
620 swrap_load_lib_function(SWRAP_LIBC, open);
622 mode = va_arg(ap, long int);
624 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
629 static int libc_open(const char *pathname, int flags, ...)
635 fd = libc_vopen(pathname, flags, ap);
641 static int libc_pipe(int pipefd[2])
643 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
645 return swrap.fns.libc_pipe(pipefd);
648 static int libc_read(int fd, void *buf, size_t count)
650 swrap_load_lib_function(SWRAP_LIBC, read);
652 return swrap.fns.libc_read(fd, buf, count);
655 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
657 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
659 return swrap.fns.libc_readv(fd, iov, iovcnt);
662 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
664 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
666 return swrap.fns.libc_recv(sockfd, buf, len, flags);
669 static int libc_recvfrom(int sockfd,
673 struct sockaddr *src_addr,
676 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
678 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
681 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
683 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
685 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
688 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
690 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
692 return swrap.fns.libc_send(sockfd, buf, len, flags);
695 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
697 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
699 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
702 static int libc_sendto(int sockfd,
706 const struct sockaddr *dst_addr,
709 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
711 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
714 static int libc_setsockopt(int sockfd,
720 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
722 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
726 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
728 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
730 return swrap.fns.libc_signalfd(fd, mask, flags);
734 static int libc_socket(int domain, int type, int protocol)
736 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
738 return swrap.fns.libc_socket(domain, type, protocol);
741 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
743 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
745 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
748 #ifdef HAVE_TIMERFD_CREATE
749 static int libc_timerfd_create(int clockid, int flags)
751 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
753 return swrap.fns.libc_timerfd_create(clockid, flags);
757 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
759 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
761 return swrap.fns.libc_writev(fd, iov, iovcnt);
764 /*********************************************************
765 * SWRAP HELPER FUNCTIONS
766 *********************************************************/
772 static const struct in6_addr *swrap_ipv6(void)
774 static struct in6_addr v;
775 static int initialized;
783 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
792 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
794 struct sockaddr *ret = (struct sockaddr *)malloc(len);
795 memcpy(ret, data, len);
799 static void set_port(int family, int prt, struct sockaddr *addr)
803 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
807 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
813 static size_t socket_length(int family)
817 return sizeof(struct sockaddr_in);
820 return sizeof(struct sockaddr_in6);
826 static const char *socket_wrapper_dir(void)
828 const char *s = getenv("SOCKET_WRAPPER_DIR");
832 if (strncmp(s, "./", 2) == 0) {
836 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
840 bool socket_wrapper_enabled(void)
842 const char *s = socket_wrapper_dir();
844 return s != NULL ? true : false;
847 static unsigned int socket_wrapper_default_iface(void)
849 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
852 if (sscanf(s, "%u", &iface) == 1) {
853 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
859 return 1;/* 127.0.0.1 */
862 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
869 p = strrchr(un->sun_path, '/');
870 if (p) p++; else p = un->sun_path;
872 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
877 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
880 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
891 case SOCKET_TYPE_CHAR_TCP:
892 case SOCKET_TYPE_CHAR_UDP: {
893 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
895 if ((*len) < sizeof(*in2)) {
900 memset(in2, 0, sizeof(*in2));
901 in2->sin_family = AF_INET;
902 in2->sin_addr.s_addr = htonl((127<<24) | iface);
903 in2->sin_port = htons(prt);
909 case SOCKET_TYPE_CHAR_TCP_V6:
910 case SOCKET_TYPE_CHAR_UDP_V6: {
911 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
913 if ((*len) < sizeof(*in2)) {
918 memset(in2, 0, sizeof(*in2));
919 in2->sin6_family = AF_INET6;
920 in2->sin6_addr = *swrap_ipv6();
921 in2->sin6_addr.s6_addr[15] = iface;
922 in2->sin6_port = htons(prt);
936 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
944 if (bcast) *bcast = 0;
946 switch (inaddr->sa_family) {
948 const struct sockaddr_in *in =
949 (const struct sockaddr_in *)(const void *)inaddr;
950 unsigned int addr = ntohl(in->sin_addr.s_addr);
957 u_type = SOCKET_TYPE_CHAR_TCP;
960 u_type = SOCKET_TYPE_CHAR_UDP;
961 a_type = SOCKET_TYPE_CHAR_UDP;
962 b_type = SOCKET_TYPE_CHAR_UDP;
965 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
966 errno = ESOCKTNOSUPPORT;
970 prt = ntohs(in->sin_port);
971 if (a_type && addr == 0xFFFFFFFF) {
972 /* 255.255.255.255 only udp */
975 iface = socket_wrapper_default_iface();
976 } else if (b_type && addr == 0x7FFFFFFF) {
977 /* 127.255.255.255 only udp */
980 iface = socket_wrapper_default_iface();
981 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
985 iface = (addr & 0x000000FF);
990 if (bcast) *bcast = is_bcast;
995 const struct sockaddr_in6 *in =
996 (const struct sockaddr_in6 *)(const void *)inaddr;
997 struct in6_addr cmp1, cmp2;
1001 type = SOCKET_TYPE_CHAR_TCP_V6;
1004 type = SOCKET_TYPE_CHAR_UDP_V6;
1007 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1008 errno = ESOCKTNOSUPPORT;
1012 /* XXX no multicast/broadcast */
1014 prt = ntohs(in->sin6_port);
1016 cmp1 = *swrap_ipv6();
1017 cmp2 = in->sin6_addr;
1018 cmp2.s6_addr[15] = 0;
1019 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1020 iface = in->sin6_addr.s6_addr[15];
1022 errno = ENETUNREACH;
1030 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1031 errno = ENETUNREACH;
1036 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1042 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1043 socket_wrapper_dir());
1044 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1045 /* the caller need to do more processing */
1049 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1050 socket_wrapper_dir(), type, iface, prt);
1051 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1056 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1065 if (bcast) *bcast = 0;
1067 switch (si->family) {
1069 const struct sockaddr_in *in =
1070 (const struct sockaddr_in *)(const void *)inaddr;
1071 unsigned int addr = ntohl(in->sin_addr.s_addr);
1077 prt = ntohs(in->sin_port);
1081 u_type = SOCKET_TYPE_CHAR_TCP;
1082 d_type = SOCKET_TYPE_CHAR_TCP;
1085 u_type = SOCKET_TYPE_CHAR_UDP;
1086 d_type = SOCKET_TYPE_CHAR_UDP;
1087 a_type = SOCKET_TYPE_CHAR_UDP;
1088 b_type = SOCKET_TYPE_CHAR_UDP;
1091 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1092 errno = ESOCKTNOSUPPORT;
1100 iface = socket_wrapper_default_iface();
1101 } else if (a_type && addr == 0xFFFFFFFF) {
1102 /* 255.255.255.255 only udp */
1105 iface = socket_wrapper_default_iface();
1106 } else if (b_type && addr == 0x7FFFFFFF) {
1107 /* 127.255.255.255 only udp */
1110 iface = socket_wrapper_default_iface();
1111 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1115 iface = (addr & 0x000000FF);
1117 errno = EADDRNOTAVAIL;
1121 /* Store the bind address for connect() */
1122 if (si->bindname == NULL) {
1123 struct sockaddr_in bind_in;
1124 socklen_t blen = sizeof(struct sockaddr_in);
1126 ZERO_STRUCT(bind_in);
1127 bind_in.sin_family = in->sin_family;
1128 bind_in.sin_port = in->sin_port;
1129 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1131 si->bindname = sockaddr_dup(&bind_in, blen);
1132 si->bindname_len = blen;
1139 const struct sockaddr_in6 *in =
1140 (const struct sockaddr_in6 *)(const void *)inaddr;
1141 struct in6_addr cmp1, cmp2;
1145 type = SOCKET_TYPE_CHAR_TCP_V6;
1148 type = SOCKET_TYPE_CHAR_UDP_V6;
1151 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1152 errno = ESOCKTNOSUPPORT;
1156 /* XXX no multicast/broadcast */
1158 prt = ntohs(in->sin6_port);
1160 cmp1 = *swrap_ipv6();
1161 cmp2 = in->sin6_addr;
1162 cmp2.s6_addr[15] = 0;
1163 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1164 iface = socket_wrapper_default_iface();
1165 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1166 iface = in->sin6_addr.s6_addr[15];
1168 errno = EADDRNOTAVAIL;
1172 /* Store the bind address for connect() */
1173 if (si->bindname == NULL) {
1174 struct sockaddr_in6 bind_in;
1175 socklen_t blen = sizeof(struct sockaddr_in6);
1177 ZERO_STRUCT(bind_in);
1178 bind_in.sin6_family = in->sin6_family;
1179 bind_in.sin6_port = in->sin6_port;
1181 bind_in.sin6_addr = *swrap_ipv6();
1182 bind_in.sin6_addr.s6_addr[15] = iface;
1184 si->bindname = sockaddr_dup(&bind_in, blen);
1185 si->bindname_len = blen;
1192 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1193 errno = EADDRNOTAVAIL;
1198 if (bcast) *bcast = is_bcast;
1200 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1206 /* handle auto-allocation of ephemeral ports */
1207 for (prt = 5001; prt < 10000; prt++) {
1208 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1209 socket_wrapper_dir(), type, iface, prt);
1210 if (stat(un->sun_path, &st) == 0) continue;
1212 set_port(si->family, prt, si->myname);
1213 set_port(si->family, prt, si->bindname);
1223 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1224 socket_wrapper_dir(), type, iface, prt);
1225 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1229 static struct socket_info *find_socket_info(int fd)
1231 struct socket_info *i;
1233 for (i = sockets; i; i = i->next) {
1234 struct socket_info_fd *f;
1235 for (f = i->fds; f; f = f->next) {
1245 static void swrap_remove_stale(int fd)
1247 struct socket_info *si = find_socket_info(fd);
1248 struct socket_info_fd *fi;
1251 for (fi = si->fds; fi; fi = fi->next) {
1253 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1254 SWRAP_DLIST_REMOVE(si->fds, fi);
1260 if (si->fds == NULL) {
1261 SWRAP_DLIST_REMOVE(sockets, si);
1266 static int sockaddr_convert_to_un(struct socket_info *si,
1267 const struct sockaddr *in_addr,
1269 struct sockaddr_un *out_addr,
1273 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1275 (void) in_len; /* unused */
1277 if (out_addr == NULL) {
1281 out->sa_family = AF_UNIX;
1282 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1283 out->sa_len = sizeof(*out_addr);
1286 switch (in_addr->sa_family) {
1296 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1297 errno = ESOCKTNOSUPPORT;
1301 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1303 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1309 errno = EAFNOSUPPORT;
1310 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1314 static int sockaddr_convert_from_un(const struct socket_info *si,
1315 const struct sockaddr_un *in_addr,
1316 socklen_t un_addrlen,
1318 struct sockaddr *out_addr,
1319 socklen_t *out_addrlen)
1323 if (out_addr == NULL || out_addrlen == NULL)
1326 if (un_addrlen == 0) {
1341 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1342 errno = ESOCKTNOSUPPORT;
1345 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1346 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1347 out_addr->sa_len = *out_addrlen;
1354 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1355 errno = EAFNOSUPPORT;
1359 enum swrap_packet_type {
1361 SWRAP_CONNECT_UNREACH,
1369 SWRAP_SENDTO_UNREACH,
1380 struct swrap_file_hdr {
1382 uint16_t version_major;
1383 uint16_t version_minor;
1386 uint32_t frame_max_len;
1387 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1390 #define SWRAP_FILE_HDR_SIZE 24
1392 struct swrap_packet_frame {
1394 uint32_t micro_seconds;
1395 uint32_t recorded_length;
1396 uint32_t full_length;
1398 #define SWRAP_PACKET_FRAME_SIZE 16
1400 union swrap_packet_ip {
1404 uint16_t packet_length;
1405 uint16_t identification;
1410 uint16_t hdr_checksum;
1414 #define SWRAP_PACKET_IP_V4_SIZE 20
1417 uint8_t flow_label_high;
1418 uint16_t flow_label_low;
1419 uint16_t payload_length;
1420 uint8_t next_header;
1422 uint8_t src_addr[16];
1423 uint8_t dest_addr[16];
1425 #define SWRAP_PACKET_IP_V6_SIZE 40
1427 #define SWRAP_PACKET_IP_SIZE 40
1429 union swrap_packet_payload {
1431 uint16_t source_port;
1441 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1443 uint16_t source_port;
1448 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1455 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1462 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1464 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1466 #define SWRAP_PACKET_MIN_ALLOC \
1467 (SWRAP_PACKET_FRAME_SIZE + \
1468 SWRAP_PACKET_IP_SIZE + \
1469 SWRAP_PACKET_PAYLOAD_SIZE)
1471 static const char *socket_wrapper_pcap_file(void)
1473 static int initialized = 0;
1474 static const char *s = NULL;
1475 static const struct swrap_file_hdr h;
1476 static const struct swrap_packet_frame f;
1477 static const union swrap_packet_ip i;
1478 static const union swrap_packet_payload p;
1480 if (initialized == 1) {
1486 * TODO: don't use the structs use plain buffer offsets
1487 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1489 * for now make sure we disable PCAP support
1490 * if the struct has alignment!
1492 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1495 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1498 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1501 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1504 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1507 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1510 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1513 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1516 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1519 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1523 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1527 if (strncmp(s, "./", 2) == 0) {
1533 static uint8_t *swrap_packet_init(struct timeval *tval,
1534 const struct sockaddr *src,
1535 const struct sockaddr *dest,
1537 const uint8_t *payload,
1539 unsigned long tcp_seqno,
1540 unsigned long tcp_ack,
1541 unsigned char tcp_ctl,
1543 size_t *_packet_len)
1547 struct swrap_packet_frame *frame;
1548 union swrap_packet_ip *ip;
1549 union swrap_packet_payload *pay;
1552 size_t nonwire_len = sizeof(*frame);
1553 size_t wire_hdr_len = 0;
1554 size_t wire_len = 0;
1555 size_t ip_hdr_len = 0;
1556 size_t icmp_hdr_len = 0;
1557 size_t icmp_truncate_len = 0;
1558 uint8_t protocol = 0, icmp_protocol = 0;
1559 const struct sockaddr_in *src_in = NULL;
1560 const struct sockaddr_in *dest_in = NULL;
1562 const struct sockaddr_in6 *src_in6 = NULL;
1563 const struct sockaddr_in6 *dest_in6 = NULL;
1568 switch (src->sa_family) {
1570 src_in = (const struct sockaddr_in *)src;
1571 dest_in = (const struct sockaddr_in *)dest;
1572 src_port = src_in->sin_port;
1573 dest_port = dest_in->sin_port;
1574 ip_hdr_len = sizeof(ip->v4);
1578 src_in6 = (const struct sockaddr_in6 *)src;
1579 dest_in6 = (const struct sockaddr_in6 *)dest;
1580 src_port = src_in6->sin6_port;
1581 dest_port = dest_in6->sin6_port;
1582 ip_hdr_len = sizeof(ip->v6);
1589 switch (socket_type) {
1591 protocol = 0x06; /* TCP */
1592 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1593 wire_len = wire_hdr_len + payload_len;
1597 protocol = 0x11; /* UDP */
1598 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1599 wire_len = wire_hdr_len + payload_len;
1607 icmp_protocol = protocol;
1608 switch (src->sa_family) {
1610 protocol = 0x01; /* ICMPv4 */
1611 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1615 protocol = 0x3A; /* ICMPv6 */
1616 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1620 if (wire_len > 64 ) {
1621 icmp_truncate_len = wire_len - 64;
1623 wire_hdr_len += icmp_hdr_len;
1624 wire_len += icmp_hdr_len;
1627 packet_len = nonwire_len + wire_len;
1628 alloc_len = packet_len;
1629 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1630 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1633 base = (uint8_t *)malloc(alloc_len);
1637 memset(base, 0x0, alloc_len);
1641 frame = (struct swrap_packet_frame *)buf;
1642 frame->seconds = tval->tv_sec;
1643 frame->micro_seconds = tval->tv_usec;
1644 frame->recorded_length = wire_len - icmp_truncate_len;
1645 frame->full_length = wire_len - icmp_truncate_len;
1646 buf += SWRAP_PACKET_FRAME_SIZE;
1648 ip = (union swrap_packet_ip *)buf;
1649 switch (src->sa_family) {
1651 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1653 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1654 ip->v4.identification = htons(0xFFFF);
1655 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1656 ip->v4.fragment = htons(0x0000);
1658 ip->v4.protocol = protocol;
1659 ip->v4.hdr_checksum = htons(0x0000);
1660 ip->v4.src_addr = src_in->sin_addr.s_addr;
1661 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1662 buf += SWRAP_PACKET_IP_V4_SIZE;
1666 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1667 ip->v6.flow_label_high = 0x00;
1668 ip->v6.flow_label_low = 0x0000;
1669 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1670 ip->v6.next_header = protocol;
1671 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1672 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1673 buf += SWRAP_PACKET_IP_V6_SIZE;
1679 pay = (union swrap_packet_payload *)buf;
1680 switch (src->sa_family) {
1682 pay->icmp4.type = 0x03; /* destination unreachable */
1683 pay->icmp4.code = 0x01; /* host unreachable */
1684 pay->icmp4.checksum = htons(0x0000);
1685 pay->icmp4.unused = htonl(0x00000000);
1686 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1688 /* set the ip header in the ICMP payload */
1689 ip = (union swrap_packet_ip *)buf;
1690 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1692 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1693 ip->v4.identification = htons(0xFFFF);
1694 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1695 ip->v4.fragment = htons(0x0000);
1697 ip->v4.protocol = icmp_protocol;
1698 ip->v4.hdr_checksum = htons(0x0000);
1699 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1700 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1701 buf += SWRAP_PACKET_IP_V4_SIZE;
1703 src_port = dest_in->sin_port;
1704 dest_port = src_in->sin_port;
1708 pay->icmp6.type = 0x01; /* destination unreachable */
1709 pay->icmp6.code = 0x03; /* address unreachable */
1710 pay->icmp6.checksum = htons(0x0000);
1711 pay->icmp6.unused = htonl(0x00000000);
1712 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1714 /* set the ip header in the ICMP payload */
1715 ip = (union swrap_packet_ip *)buf;
1716 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1717 ip->v6.flow_label_high = 0x00;
1718 ip->v6.flow_label_low = 0x0000;
1719 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1720 ip->v6.next_header = protocol;
1721 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1722 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1723 buf += SWRAP_PACKET_IP_V6_SIZE;
1725 src_port = dest_in6->sin6_port;
1726 dest_port = src_in6->sin6_port;
1732 pay = (union swrap_packet_payload *)buf;
1734 switch (socket_type) {
1736 pay->tcp.source_port = src_port;
1737 pay->tcp.dest_port = dest_port;
1738 pay->tcp.seq_num = htonl(tcp_seqno);
1739 pay->tcp.ack_num = htonl(tcp_ack);
1740 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1741 pay->tcp.control = tcp_ctl;
1742 pay->tcp.window = htons(0x7FFF);
1743 pay->tcp.checksum = htons(0x0000);
1744 pay->tcp.urg = htons(0x0000);
1745 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1750 pay->udp.source_port = src_port;
1751 pay->udp.dest_port = dest_port;
1752 pay->udp.length = htons(8 + payload_len);
1753 pay->udp.checksum = htons(0x0000);
1754 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1759 if (payload && payload_len > 0) {
1760 memcpy(buf, payload, payload_len);
1763 *_packet_len = packet_len - icmp_truncate_len;
1767 static int swrap_get_pcap_fd(const char *fname)
1771 if (fd != -1) return fd;
1773 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1775 struct swrap_file_hdr file_hdr;
1776 file_hdr.magic = 0xA1B2C3D4;
1777 file_hdr.version_major = 0x0002;
1778 file_hdr.version_minor = 0x0004;
1779 file_hdr.timezone = 0x00000000;
1780 file_hdr.sigfigs = 0x00000000;
1781 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1782 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1784 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1791 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1796 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1797 const struct sockaddr *addr,
1798 enum swrap_packet_type type,
1799 const void *buf, size_t len,
1802 const struct sockaddr *src_addr;
1803 const struct sockaddr *dest_addr;
1804 unsigned long tcp_seqno = 0;
1805 unsigned long tcp_ack = 0;
1806 unsigned char tcp_ctl = 0;
1807 int unreachable = 0;
1811 switch (si->family) {
1823 case SWRAP_CONNECT_SEND:
1824 if (si->type != SOCK_STREAM) return NULL;
1826 src_addr = si->myname;
1829 tcp_seqno = si->io.pck_snd;
1830 tcp_ack = si->io.pck_rcv;
1831 tcp_ctl = 0x02; /* SYN */
1833 si->io.pck_snd += 1;
1837 case SWRAP_CONNECT_RECV:
1838 if (si->type != SOCK_STREAM) return NULL;
1840 dest_addr = si->myname;
1843 tcp_seqno = si->io.pck_rcv;
1844 tcp_ack = si->io.pck_snd;
1845 tcp_ctl = 0x12; /** SYN,ACK */
1847 si->io.pck_rcv += 1;
1851 case SWRAP_CONNECT_UNREACH:
1852 if (si->type != SOCK_STREAM) return NULL;
1854 dest_addr = si->myname;
1857 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1858 tcp_seqno = si->io.pck_snd - 1;
1859 tcp_ack = si->io.pck_rcv;
1860 tcp_ctl = 0x02; /* SYN */
1865 case SWRAP_CONNECT_ACK:
1866 if (si->type != SOCK_STREAM) return NULL;
1868 src_addr = si->myname;
1871 tcp_seqno = si->io.pck_snd;
1872 tcp_ack = si->io.pck_rcv;
1873 tcp_ctl = 0x10; /* ACK */
1877 case SWRAP_ACCEPT_SEND:
1878 if (si->type != SOCK_STREAM) return NULL;
1880 dest_addr = si->myname;
1883 tcp_seqno = si->io.pck_rcv;
1884 tcp_ack = si->io.pck_snd;
1885 tcp_ctl = 0x02; /* SYN */
1887 si->io.pck_rcv += 1;
1891 case SWRAP_ACCEPT_RECV:
1892 if (si->type != SOCK_STREAM) return NULL;
1894 src_addr = si->myname;
1897 tcp_seqno = si->io.pck_snd;
1898 tcp_ack = si->io.pck_rcv;
1899 tcp_ctl = 0x12; /* SYN,ACK */
1901 si->io.pck_snd += 1;
1905 case SWRAP_ACCEPT_ACK:
1906 if (si->type != SOCK_STREAM) return NULL;
1908 dest_addr = si->myname;
1911 tcp_seqno = si->io.pck_rcv;
1912 tcp_ack = si->io.pck_snd;
1913 tcp_ctl = 0x10; /* ACK */
1918 src_addr = si->myname;
1919 dest_addr = si->peername;
1921 tcp_seqno = si->io.pck_snd;
1922 tcp_ack = si->io.pck_rcv;
1923 tcp_ctl = 0x18; /* PSH,ACK */
1925 si->io.pck_snd += len;
1929 case SWRAP_SEND_RST:
1930 dest_addr = si->myname;
1931 src_addr = si->peername;
1933 if (si->type == SOCK_DGRAM) {
1934 return swrap_marshall_packet(si, si->peername,
1935 SWRAP_SENDTO_UNREACH,
1936 buf, len, packet_len);
1939 tcp_seqno = si->io.pck_rcv;
1940 tcp_ack = si->io.pck_snd;
1941 tcp_ctl = 0x14; /** RST,ACK */
1945 case SWRAP_PENDING_RST:
1946 dest_addr = si->myname;
1947 src_addr = si->peername;
1949 if (si->type == SOCK_DGRAM) {
1953 tcp_seqno = si->io.pck_rcv;
1954 tcp_ack = si->io.pck_snd;
1955 tcp_ctl = 0x14; /* RST,ACK */
1960 dest_addr = si->myname;
1961 src_addr = si->peername;
1963 tcp_seqno = si->io.pck_rcv;
1964 tcp_ack = si->io.pck_snd;
1965 tcp_ctl = 0x18; /* PSH,ACK */
1967 si->io.pck_rcv += len;
1971 case SWRAP_RECV_RST:
1972 dest_addr = si->myname;
1973 src_addr = si->peername;
1975 if (si->type == SOCK_DGRAM) {
1979 tcp_seqno = si->io.pck_rcv;
1980 tcp_ack = si->io.pck_snd;
1981 tcp_ctl = 0x14; /* RST,ACK */
1986 src_addr = si->myname;
1989 si->io.pck_snd += len;
1993 case SWRAP_SENDTO_UNREACH:
1994 dest_addr = si->myname;
2001 case SWRAP_RECVFROM:
2002 dest_addr = si->myname;
2005 si->io.pck_rcv += len;
2009 case SWRAP_CLOSE_SEND:
2010 if (si->type != SOCK_STREAM) return NULL;
2012 src_addr = si->myname;
2013 dest_addr = si->peername;
2015 tcp_seqno = si->io.pck_snd;
2016 tcp_ack = si->io.pck_rcv;
2017 tcp_ctl = 0x11; /* FIN, ACK */
2019 si->io.pck_snd += 1;
2023 case SWRAP_CLOSE_RECV:
2024 if (si->type != SOCK_STREAM) return NULL;
2026 dest_addr = si->myname;
2027 src_addr = si->peername;
2029 tcp_seqno = si->io.pck_rcv;
2030 tcp_ack = si->io.pck_snd;
2031 tcp_ctl = 0x11; /* FIN,ACK */
2033 si->io.pck_rcv += 1;
2037 case SWRAP_CLOSE_ACK:
2038 if (si->type != SOCK_STREAM) return NULL;
2040 src_addr = si->myname;
2041 dest_addr = si->peername;
2043 tcp_seqno = si->io.pck_snd;
2044 tcp_ack = si->io.pck_rcv;
2045 tcp_ctl = 0x10; /* ACK */
2052 swrapGetTimeOfDay(&tv);
2054 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2055 (const uint8_t *)buf, len,
2056 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2060 static void swrap_dump_packet(struct socket_info *si,
2061 const struct sockaddr *addr,
2062 enum swrap_packet_type type,
2063 const void *buf, size_t len)
2065 const char *file_name;
2067 size_t packet_len = 0;
2070 file_name = socket_wrapper_pcap_file();
2075 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2080 fd = swrap_get_pcap_fd(file_name);
2082 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2091 /****************************************************************************
2093 ***************************************************************************/
2095 #ifdef HAVE_SIGNALFD
2096 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2100 rc = libc_signalfd(fd, mask, flags);
2102 swrap_remove_stale(fd);
2108 int signalfd(int fd, const sigset_t *mask, int flags)
2110 return swrap_signalfd(fd, mask, flags);
2114 /****************************************************************************
2116 ***************************************************************************/
2118 static int swrap_socket(int family, int type, int protocol)
2120 struct socket_info *si;
2121 struct socket_info_fd *fi;
2123 int real_type = type;
2126 * Remove possible addition flags passed to socket() so
2127 * do not fail checking the type.
2128 * See https://lwn.net/Articles/281965/
2131 real_type &= ~SOCK_CLOEXEC;
2133 #ifdef SOCK_NONBLOCK
2134 real_type &= ~SOCK_NONBLOCK;
2137 if (!socket_wrapper_enabled()) {
2138 return libc_socket(family, type, protocol);
2148 return libc_socket(family, type, protocol);
2150 errno = EAFNOSUPPORT;
2154 switch (real_type) {
2160 errno = EPROTONOSUPPORT;
2168 if (real_type == SOCK_STREAM) {
2173 if (real_type == SOCK_DGRAM) {
2178 errno = EPROTONOSUPPORT;
2183 * We must call libc_socket with type, from the caller, not the version
2184 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2186 fd = libc_socket(AF_UNIX, type, 0);
2192 /* Check if we have a stale fd and remove it */
2193 si = find_socket_info(fd);
2195 swrap_remove_stale(fd);
2198 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2199 memset(si, 0, sizeof(struct socket_info));
2205 si->family = family;
2207 /* however, the rest of the socket_wrapper code expects just
2208 * the type, not the flags */
2209 si->type = real_type;
2210 si->protocol = protocol;
2212 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2221 SWRAP_DLIST_ADD(si->fds, fi);
2222 SWRAP_DLIST_ADD(sockets, si);
2227 int socket(int family, int type, int protocol)
2229 return swrap_socket(family, type, protocol);
2232 /****************************************************************************
2234 ***************************************************************************/
2236 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2240 rc = libc_socketpair(family, type, protocol, sv);
2242 swrap_remove_stale(sv[0]);
2243 swrap_remove_stale(sv[1]);
2249 int socketpair(int family, int type, int protocol, int sv[2])
2251 return swrap_socketpair(family, type, protocol, sv);
2254 /****************************************************************************
2256 ***************************************************************************/
2258 #ifdef HAVE_TIMERFD_CREATE
2259 static int swrap_timerfd_create(int clockid, int flags)
2263 fd = libc_timerfd_create(clockid, flags);
2265 swrap_remove_stale(fd);
2271 int timerfd_create(int clockid, int flags)
2273 return swrap_timerfd_create(clockid, flags);
2277 /****************************************************************************
2279 ***************************************************************************/
2281 static int swrap_pipe(int pipefd[2])
2285 rc = libc_pipe(pipefd);
2287 swrap_remove_stale(pipefd[0]);
2288 swrap_remove_stale(pipefd[1]);
2294 int pipe(int pipefd[2])
2296 return swrap_pipe(pipefd);
2299 /****************************************************************************
2301 ***************************************************************************/
2303 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2305 struct socket_info *parent_si, *child_si;
2306 struct socket_info_fd *child_fi;
2308 struct sockaddr_un un_addr;
2309 socklen_t un_addrlen = sizeof(un_addr);
2310 struct sockaddr_un un_my_addr;
2311 socklen_t un_my_addrlen = sizeof(un_my_addr);
2312 struct sockaddr *my_addr;
2313 socklen_t my_addrlen, len;
2316 parent_si = find_socket_info(s);
2318 return libc_accept(s, addr, addrlen);
2322 * assume out sockaddr have the same size as the in parent
2325 my_addrlen = socket_length(parent_si->family);
2326 if (my_addrlen <= 0) {
2331 my_addr = (struct sockaddr *)malloc(my_addrlen);
2332 if (my_addr == NULL) {
2336 memset(&un_addr, 0, sizeof(un_addr));
2337 memset(&un_my_addr, 0, sizeof(un_my_addr));
2339 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2341 if (errno == ENOTSOCK) {
2342 /* Remove stale fds */
2343 swrap_remove_stale(s);
2352 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2353 parent_si->family, my_addr, &len);
2360 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2361 memset(child_si, 0, sizeof(struct socket_info));
2363 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2364 if (child_fi == NULL) {
2374 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2376 child_si->family = parent_si->family;
2377 child_si->type = parent_si->type;
2378 child_si->protocol = parent_si->protocol;
2379 child_si->bound = 1;
2380 child_si->is_server = 1;
2381 child_si->connected = 1;
2383 child_si->peername_len = len;
2384 child_si->peername = sockaddr_dup(my_addr, len);
2386 if (addr != NULL && addrlen != NULL) {
2387 size_t copy_len = MIN(*addrlen, len);
2389 memcpy(addr, my_addr, copy_len);
2394 ret = libc_getsockname(fd,
2395 (struct sockaddr *)(void *)&un_my_addr,
2406 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2407 child_si->family, my_addr, &len);
2416 SWRAP_LOG(SWRAP_LOG_TRACE,
2417 "accept() path=%s, fd=%d",
2418 un_my_addr.sun_path, s);
2420 child_si->myname_len = len;
2421 child_si->myname = sockaddr_dup(my_addr, len);
2424 SWRAP_DLIST_ADD(sockets, child_si);
2427 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2428 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2429 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2435 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2436 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2438 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2441 return swrap_accept(s, addr, (socklen_t *)addrlen);
2444 static int autobind_start_init;
2445 static int autobind_start;
2447 /* using sendto() or connect() on an unbound socket would give the
2448 recipient no way to reply, as unlike UDP and TCP, a unix domain
2449 socket can't auto-assign ephemeral port numbers, so we need to
2451 Note: this might change the family from ipv6 to ipv4
2453 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2455 struct sockaddr_un un_addr;
2462 if (autobind_start_init != 1) {
2463 autobind_start_init = 1;
2464 autobind_start = getpid();
2465 autobind_start %= 50000;
2466 autobind_start += 10000;
2469 un_addr.sun_family = AF_UNIX;
2473 struct sockaddr_in in;
2477 type = SOCKET_TYPE_CHAR_TCP;
2480 type = SOCKET_TYPE_CHAR_UDP;
2483 errno = ESOCKTNOSUPPORT;
2487 memset(&in, 0, sizeof(in));
2488 in.sin_family = AF_INET;
2489 in.sin_addr.s_addr = htonl(127<<24 |
2490 socket_wrapper_default_iface());
2492 si->myname_len = sizeof(in);
2493 si->myname = sockaddr_dup(&in, si->myname_len);
2498 struct sockaddr_in6 in6;
2500 if (si->family != family) {
2501 errno = ENETUNREACH;
2507 type = SOCKET_TYPE_CHAR_TCP_V6;
2510 type = SOCKET_TYPE_CHAR_UDP_V6;
2513 errno = ESOCKTNOSUPPORT;
2517 memset(&in6, 0, sizeof(in6));
2518 in6.sin6_family = AF_INET6;
2519 in6.sin6_addr = *swrap_ipv6();
2520 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2521 si->myname_len = sizeof(in6);
2522 si->myname = sockaddr_dup(&in6, si->myname_len);
2527 errno = ESOCKTNOSUPPORT;
2531 if (autobind_start > 60000) {
2532 autobind_start = 10000;
2535 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2536 port = autobind_start + i;
2537 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2538 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2539 type, socket_wrapper_default_iface(), port);
2540 if (stat(un_addr.sun_path, &st) == 0) continue;
2542 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2544 if (ret == -1) return ret;
2546 si->tmp_path = strdup(un_addr.sun_path);
2548 autobind_start = port + 1;
2551 if (i == SOCKET_MAX_SOCKETS) {
2552 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2553 "interface "SOCKET_FORMAT,
2556 socket_wrapper_default_iface(),
2562 si->family = family;
2563 set_port(si->family, port, si->myname);
2568 /****************************************************************************
2570 ***************************************************************************/
2572 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2576 struct sockaddr_un un_addr;
2577 struct socket_info *si = find_socket_info(s);
2581 return libc_connect(s, serv_addr, addrlen);
2584 if (si->bound == 0) {
2585 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2586 if (ret == -1) return -1;
2589 if (si->family != serv_addr->sa_family) {
2594 ret = sockaddr_convert_to_un(si, serv_addr,
2595 addrlen, &un_addr, 0, &bcast);
2596 if (ret == -1) return -1;
2599 errno = ENETUNREACH;
2603 if (si->type == SOCK_DGRAM) {
2604 si->defer_connect = 1;
2607 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2609 ret = libc_connect(s,
2610 (struct sockaddr *)(void *)&un_addr,
2611 sizeof(struct sockaddr_un));
2614 SWRAP_LOG(SWRAP_LOG_TRACE,
2615 "connect() path=%s, fd=%d",
2616 un_addr.sun_path, s);
2619 /* to give better errors */
2620 if (ret == -1 && errno == ENOENT) {
2621 errno = EHOSTUNREACH;
2625 si->peername_len = addrlen;
2626 si->peername = sockaddr_dup(serv_addr, addrlen);
2630 * When we connect() on a socket than we have to bind the
2631 * outgoing connection on the interface we use for the
2632 * transport. We already bound it on the right interface
2633 * but here we have to update the name so getsockname()
2634 * returns correct information.
2636 if (si->bindname != NULL) {
2639 si->myname = si->bindname;
2640 si->myname_len = si->bindname_len;
2642 si->bindname = NULL;
2643 si->bindname_len = 0;
2646 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2647 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2649 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2655 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2657 return swrap_connect(s, serv_addr, addrlen);
2660 /****************************************************************************
2662 ***************************************************************************/
2664 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2667 struct sockaddr_un un_addr;
2668 struct socket_info *si = find_socket_info(s);
2671 return libc_bind(s, myaddr, addrlen);
2674 si->myname_len = addrlen;
2675 si->myname = sockaddr_dup(myaddr, addrlen);
2677 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2678 if (ret == -1) return -1;
2680 unlink(un_addr.sun_path);
2682 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2683 sizeof(struct sockaddr_un));
2685 SWRAP_LOG(SWRAP_LOG_TRACE,
2686 "bind() path=%s, fd=%d",
2687 un_addr.sun_path, s);
2696 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2698 return swrap_bind(s, myaddr, addrlen);
2701 /****************************************************************************
2703 ***************************************************************************/
2705 static int swrap_listen(int s, int backlog)
2708 struct socket_info *si = find_socket_info(s);
2711 return libc_listen(s, backlog);
2714 ret = libc_listen(s, backlog);
2719 int listen(int s, int backlog)
2721 return swrap_listen(s, backlog);
2724 /****************************************************************************
2726 ***************************************************************************/
2728 static int swrap_vopen(const char *pathname, int flags, va_list ap)
2732 ret = libc_vopen(pathname, flags, ap);
2735 * There are methods for closing descriptors (libc-internal code
2736 * paths, direct syscalls) which close descriptors in ways that
2737 * we can't intercept, so try to recover when we notice that
2740 swrap_remove_stale(ret);
2745 int open(const char *pathname, int flags, ...)
2750 va_start(ap, flags);
2751 fd = swrap_vopen(pathname, flags, ap);
2757 /****************************************************************************
2759 ***************************************************************************/
2761 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2763 struct socket_info *si = find_socket_info(s);
2766 return libc_getpeername(s, name, addrlen);
2775 memcpy(name, si->peername, si->peername_len);
2776 *addrlen = si->peername_len;
2781 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2782 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
2784 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2787 return swrap_getpeername(s, name, (socklen_t *)addrlen);
2790 /****************************************************************************
2792 ***************************************************************************/
2794 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2796 struct socket_info *si = find_socket_info(s);
2799 return libc_getsockname(s, name, addrlen);
2802 memcpy(name, si->myname, si->myname_len);
2803 *addrlen = si->myname_len;
2808 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2809 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
2811 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2814 return swrap_getsockname(s, name, (socklen_t *)addrlen);
2817 /****************************************************************************
2819 ***************************************************************************/
2821 static int swrap_getsockopt(int s, int level, int optname,
2822 void *optval, socklen_t *optlen)
2824 struct socket_info *si = find_socket_info(s);
2827 return libc_getsockopt(s,
2834 if (level == SOL_SOCKET) {
2835 return libc_getsockopt(s,
2842 errno = ENOPROTOOPT;
2846 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2847 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
2849 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
2852 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
2855 /****************************************************************************
2857 ***************************************************************************/
2859 static int swrap_setsockopt(int s, int level, int optname,
2860 const void *optval, socklen_t optlen)
2862 struct socket_info *si = find_socket_info(s);
2865 return libc_setsockopt(s,
2872 if (level == SOL_SOCKET) {
2873 return libc_setsockopt(s,
2880 switch (si->family) {
2882 if (level == IPPROTO_IP) {
2884 if (optname == IP_PKTINFO) {
2885 si->pktinfo = AF_INET;
2887 #endif /* IP_PKTINFO */
2892 if (level == IPPROTO_IPV6) {
2893 #ifdef IPV6_RECVPKTINFO
2894 if (optname == IPV6_RECVPKTINFO) {
2895 si->pktinfo = AF_INET6;
2897 #endif /* IPV6_PKTINFO */
2902 errno = ENOPROTOOPT;
2907 int setsockopt(int s, int level, int optname,
2908 const void *optval, socklen_t optlen)
2910 return swrap_setsockopt(s, level, optname, optval, optlen);
2913 /****************************************************************************
2915 ***************************************************************************/
2917 static int swrap_vioctl(int s, unsigned long int r, va_list va)
2919 struct socket_info *si = find_socket_info(s);
2925 return libc_vioctl(s, r, va);
2930 rc = libc_vioctl(s, r, va);
2934 value = *((int *)va_arg(ap, int *));
2936 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
2937 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2938 } else if (value == 0) { /* END OF FILE */
2939 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2949 #ifdef HAVE_IOCTL_INT
2950 int ioctl(int s, int r, ...)
2952 int ioctl(int s, unsigned long int r, ...)
2960 rc = swrap_vioctl(s, (unsigned long int) r, va);
2971 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2973 * @brief Add a cmsghdr to a msghdr.
2975 * This is an function to add any type of cmsghdr. It will operate on the
2976 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
2977 * the buffer position after the added cmsg element. Hence, this function is
2978 * intended to be used with an intermediate msghdr and not on the original
2979 * one handed in by the client.
2981 * @param[in] msg The msghdr to which to add the cmsg.
2983 * @param[in] level The cmsg level to set.
2985 * @param[in] type The cmsg type to set.
2987 * @param[in] data The cmsg data to set.
2989 * @param[in] len the length of the data to set.
2991 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
2997 size_t cmlen = CMSG_LEN(len);
2998 size_t cmspace = CMSG_SPACE(len);
2999 uint8_t cmbuf[cmspace];
3000 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3003 memset(cmbuf, 0, cmspace);
3005 if (msg->msg_controllen < cmlen) {
3006 cmlen = msg->msg_controllen;
3007 msg->msg_flags |= MSG_CTRUNC;
3010 if (msg->msg_controllen < cmspace) {
3011 cmspace = msg->msg_controllen;
3015 * We copy the full input data into an intermediate cmsghdr first
3016 * in order to more easily cope with truncation.
3018 cm->cmsg_len = cmlen;
3019 cm->cmsg_level = level;
3020 cm->cmsg_type = type;
3021 memcpy(CMSG_DATA(cm), data, len);
3024 * We now copy the possibly truncated buffer.
3025 * We copy cmlen bytes, but consume cmspace bytes,
3026 * leaving the possible padding uninitialiazed.
3028 p = (uint8_t *)msg->msg_control;
3029 memcpy(p, cm, cmlen);
3031 msg->msg_control = p;
3032 msg->msg_controllen -= cmspace;
3037 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3040 /* Add packet info */
3041 switch (si->pktinfo) {
3044 struct sockaddr_in *sin;
3045 struct in_pktinfo pkt;
3047 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3048 sin = (struct sockaddr_in*)si->bindname;
3050 if (si->myname_len != sizeof(struct sockaddr_in)) {
3053 sin = (struct sockaddr_in*)si->myname;
3058 pkt.ipi_ifindex = socket_wrapper_default_iface();
3059 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3061 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3066 #endif /* IP_PKTINFO */
3067 #if defined(HAVE_IPV6)
3069 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3070 struct sockaddr_in6 *sin6;
3071 struct in6_pktinfo pkt6;
3073 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3074 sin6 = (struct sockaddr_in6*)si->bindname;
3076 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3079 sin6 = (struct sockaddr_in6*)si->myname;
3084 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3085 pkt6.ipi6_addr = sin6->sin6_addr;
3087 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3088 &pkt6, sizeof(pkt6));
3089 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3093 #endif /* IPV6_PKTINFO */
3101 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3102 struct msghdr *omsg)
3106 if (si->pktinfo > 0) {
3107 rc = swrap_msghdr_add_pktinfo(si, omsg);
3112 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3114 static ssize_t swrap_sendmsg_before(int fd,
3115 struct socket_info *si,
3117 struct iovec *tmp_iov,
3118 struct sockaddr_un *tmp_un,
3119 const struct sockaddr_un **to_un,
3120 const struct sockaddr **to,
3138 if (!si->connected) {
3143 if (msg->msg_iovlen == 0) {
3147 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3149 nlen = len + msg->msg_iov[i].iov_len;
3150 if (nlen > SOCKET_MAX_PACKET) {
3154 msg->msg_iovlen = i;
3155 if (msg->msg_iovlen == 0) {
3156 *tmp_iov = msg->msg_iov[0];
3157 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3158 msg->msg_iov = tmp_iov;
3159 msg->msg_iovlen = 1;
3164 if (si->connected) {
3165 if (msg->msg_name) {
3170 const struct sockaddr *msg_name;
3171 msg_name = (const struct sockaddr *)msg->msg_name;
3173 if (msg_name == NULL) {
3179 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3181 if (ret == -1) return -1;
3189 msg->msg_name = tmp_un;
3190 msg->msg_namelen = sizeof(*tmp_un);
3193 if (si->bound == 0) {
3194 ret = swrap_auto_bind(fd, si, si->family);
3196 if (errno == ENOTSOCK) {
3197 swrap_remove_stale(fd);
3200 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3206 if (!si->defer_connect) {
3210 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3212 if (ret == -1) return -1;
3214 ret = libc_connect(fd,
3215 (struct sockaddr *)(void *)tmp_un,
3218 /* to give better errors */
3219 if (ret == -1 && errno == ENOENT) {
3220 errno = EHOSTUNREACH;
3227 si->defer_connect = 0;
3230 errno = EHOSTUNREACH;
3237 static void swrap_sendmsg_after(int fd,
3238 struct socket_info *si,
3240 const struct sockaddr *to,
3243 int saved_errno = errno;
3250 /* to give better errors */
3252 if (saved_errno == ENOENT) {
3253 saved_errno = EHOSTUNREACH;
3254 } else if (saved_errno == ENOTSOCK) {
3255 /* If the fd is not a socket, remove it */
3256 swrap_remove_stale(fd);
3260 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3261 avail += msg->msg_iov[i].iov_len;
3265 remain = MIN(80, avail);
3270 /* we capture it as one single packet */
3271 buf = (uint8_t *)malloc(remain);
3273 /* we just not capture the packet */
3274 errno = saved_errno;
3278 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3279 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3281 msg->msg_iov[i].iov_base,
3284 remain -= this_time;
3291 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3292 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3294 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3299 if (si->connected) {
3303 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3304 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3306 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3312 errno = saved_errno;
3315 static int swrap_recvmsg_before(int fd,
3316 struct socket_info *si,
3318 struct iovec *tmp_iov)
3323 (void)fd; /* unused */
3327 if (!si->connected) {
3332 if (msg->msg_iovlen == 0) {
3336 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3338 nlen = len + msg->msg_iov[i].iov_len;
3339 if (nlen > SOCKET_MAX_PACKET) {
3343 msg->msg_iovlen = i;
3344 if (msg->msg_iovlen == 0) {
3345 *tmp_iov = msg->msg_iov[0];
3346 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3347 msg->msg_iov = tmp_iov;
3348 msg->msg_iovlen = 1;
3353 if (msg->msg_name == NULL) {
3358 if (msg->msg_iovlen == 0) {
3362 if (si->bound == 0) {
3363 ret = swrap_auto_bind(fd, si, si->family);
3366 * When attempting to read or write to a
3367 * descriptor, if an underlying autobind fails
3368 * because it's not a socket, stop intercepting
3369 * uses of that descriptor.
3371 if (errno == ENOTSOCK) {
3372 swrap_remove_stale(fd);
3375 SWRAP_LOG(SWRAP_LOG_ERROR,
3376 "swrap_recvmsg_before failed");
3383 errno = EHOSTUNREACH;
3390 static int swrap_recvmsg_after(int fd,
3391 struct socket_info *si,
3393 const struct sockaddr_un *un_addr,
3394 socklen_t un_addrlen,
3397 int saved_errno = errno;
3399 uint8_t *buf = NULL;
3405 /* to give better errors */
3407 if (saved_errno == ENOENT) {
3408 saved_errno = EHOSTUNREACH;
3409 } else if (saved_errno == ENOTSOCK) {
3410 /* If the fd is not a socket, remove it */
3411 swrap_remove_stale(fd);
3415 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3416 avail += msg->msg_iov[i].iov_len;
3425 remain = MIN(80, avail);
3430 /* we capture it as one single packet */
3431 buf = (uint8_t *)malloc(remain);
3433 /* we just not capture the packet */
3434 errno = saved_errno;
3438 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3439 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3441 msg->msg_iov[i].iov_base,
3444 remain -= this_time;
3449 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3450 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3451 } else if (ret == 0) { /* END OF FILE */
3452 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3453 } else if (ret > 0) {
3454 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3463 if (un_addr != NULL) {
3464 rc = sockaddr_convert_from_un(si,
3474 swrap_dump_packet(si,
3480 swrap_dump_packet(si,
3493 errno = saved_errno;
3495 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3497 msg->msg_controllen > 0 &&
3498 msg->msg_control != NULL) {
3499 rc = swrap_msghdr_add_socket_info(si, msg);
3509 /****************************************************************************
3511 ***************************************************************************/
3513 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
3514 struct sockaddr *from, socklen_t *fromlen)
3516 struct sockaddr_un from_addr;
3517 socklen_t from_addrlen = sizeof(from_addr);
3519 struct socket_info *si = find_socket_info(s);
3520 struct sockaddr_storage ss;
3521 socklen_t ss_len = sizeof(ss);
3527 return libc_recvfrom(s,
3539 if (from != NULL && fromlen != NULL) {
3540 msg.msg_name = from; /* optional address */
3541 msg.msg_namelen = *fromlen; /* size of address */
3543 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3544 msg.msg_namelen = ss_len; /* size of address */
3546 msg.msg_iov = &tmp; /* scatter/gather array */
3547 msg.msg_iovlen = 1; /* # elements in msg_iov */
3548 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3549 msg.msg_control = NULL; /* ancillary data, see below */
3550 msg.msg_controllen = 0; /* ancillary data buffer len */
3551 msg.msg_flags = 0; /* flags on received message */
3554 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3559 buf = msg.msg_iov[0].iov_base;
3560 len = msg.msg_iov[0].iov_len;
3562 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3563 memset(&from_addr, 0, sizeof(from_addr));
3564 ret = libc_recvfrom(s,
3568 (struct sockaddr *)(void *)&from_addr,
3574 tret = swrap_recvmsg_after(s,
3584 if (from != NULL && fromlen != NULL) {
3585 *fromlen = msg.msg_namelen;
3591 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3592 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3593 struct sockaddr *from, Psocklen_t fromlen)
3595 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3596 struct sockaddr *from, socklen_t *fromlen)
3599 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
3602 /****************************************************************************
3604 ***************************************************************************/
3606 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
3607 const struct sockaddr *to, socklen_t tolen)
3611 struct sockaddr_un un_addr;
3612 const struct sockaddr_un *to_un = NULL;
3615 struct socket_info *si = find_socket_info(s);
3619 return libc_sendto(s, buf, len, flags, to, tolen);
3622 tmp.iov_base = discard_const_p(char, buf);
3626 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
3627 msg.msg_namelen = tolen; /* size of address */
3628 msg.msg_iov = &tmp; /* scatter/gather array */
3629 msg.msg_iovlen = 1; /* # elements in msg_iov */
3630 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3631 msg.msg_control = NULL; /* ancillary data, see below */
3632 msg.msg_controllen = 0; /* ancillary data buffer len */
3633 msg.msg_flags = 0; /* flags on received message */
3636 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3641 buf = msg.msg_iov[0].iov_base;
3642 len = msg.msg_iov[0].iov_len;
3647 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3650 type = SOCKET_TYPE_CHAR_UDP;
3652 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3653 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3654 socket_wrapper_dir(), type, iface, prt);
3655 if (stat(un_addr.sun_path, &st) != 0) continue;
3657 /* ignore the any errors in broadcast sends */
3662 (struct sockaddr *)(void *)&un_addr,
3666 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3671 ret = libc_sendto(s,
3675 (struct sockaddr *)msg.msg_name,
3678 swrap_sendmsg_after(s, si, &msg, to, ret);
3683 ssize_t sendto(int s, const void *buf, size_t len, int flags,
3684 const struct sockaddr *to, socklen_t tolen)
3686 return swrap_sendto(s, buf, len, flags, to, tolen);
3689 /****************************************************************************
3691 ***************************************************************************/
3693 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
3695 struct socket_info *si;
3697 struct sockaddr_storage ss;
3698 socklen_t ss_len = sizeof(ss);
3703 si = find_socket_info(s);
3705 return libc_recv(s, buf, len, flags);
3712 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3713 msg.msg_namelen = ss_len; /* size of address */
3714 msg.msg_iov = &tmp; /* scatter/gather array */
3715 msg.msg_iovlen = 1; /* # elements in msg_iov */
3716 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3717 msg.msg_control = NULL; /* ancillary data, see below */
3718 msg.msg_controllen = 0; /* ancillary data buffer len */
3719 msg.msg_flags = 0; /* flags on received message */
3722 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3727 buf = msg.msg_iov[0].iov_base;
3728 len = msg.msg_iov[0].iov_len;
3730 ret = libc_recv(s, buf, len, flags);
3732 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
3740 ssize_t recv(int s, void *buf, size_t len, int flags)
3742 return swrap_recv(s, buf, len, flags);
3745 /****************************************************************************
3747 ***************************************************************************/
3749 static ssize_t swrap_read(int s, void *buf, size_t len)
3751 struct socket_info *si;
3754 struct sockaddr_storage ss;
3755 socklen_t ss_len = sizeof(ss);
3759 si = find_socket_info(s);
3761 return libc_read(s, buf, len);
3768 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3769 msg.msg_namelen = ss_len; /* size of address */
3770 msg.msg_iov = &tmp; /* scatter/gather array */
3771 msg.msg_iovlen = 1; /* # elements in msg_iov */
3772 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3773 msg.msg_control = NULL; /* ancillary data, see below */
3774 msg.msg_controllen = 0; /* ancillary data buffer len */
3775 msg.msg_flags = 0; /* flags on received message */
3778 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3780 if (tret == -ENOTSOCK) {
3781 return libc_read(s, buf, len);
3786 buf = msg.msg_iov[0].iov_base;
3787 len = msg.msg_iov[0].iov_len;
3789 ret = libc_read(s, buf, len);
3791 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
3799 ssize_t read(int s, void *buf, size_t len)
3801 return swrap_read(s, buf, len);
3804 /****************************************************************************
3806 ***************************************************************************/
3808 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
3812 struct sockaddr_un un_addr;
3815 struct socket_info *si = find_socket_info(s);
3818 return libc_send(s, buf, len, flags);
3821 tmp.iov_base = discard_const_p(char, buf);
3825 msg.msg_name = NULL; /* optional address */
3826 msg.msg_namelen = 0; /* size of address */
3827 msg.msg_iov = &tmp; /* scatter/gather array */
3828 msg.msg_iovlen = 1; /* # elements in msg_iov */
3829 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3830 msg.msg_control = NULL; /* ancillary data, see below */
3831 msg.msg_controllen = 0; /* ancillary data buffer len */
3832 msg.msg_flags = 0; /* flags on received message */
3835 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
3840 buf = msg.msg_iov[0].iov_base;
3841 len = msg.msg_iov[0].iov_len;
3843 ret = libc_send(s, buf, len, flags);
3845 swrap_sendmsg_after(s, si, &msg, NULL, ret);
3850 ssize_t send(int s, const void *buf, size_t len, int flags)
3852 return swrap_send(s, buf, len, flags);
3855 /****************************************************************************
3857 ***************************************************************************/
3859 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
3861 struct sockaddr_un from_addr;
3862 socklen_t from_addrlen = sizeof(from_addr);
3863 struct socket_info *si;
3870 si = find_socket_info(s);
3872 return libc_recvmsg(s, omsg, flags);
3875 tmp.iov_base = NULL;
3879 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
3880 msg.msg_namelen = from_addrlen; /* size of address */
3881 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3882 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3883 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3884 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3885 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3886 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3889 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
3894 ret = libc_recvmsg(s, &msg, flags);
3896 rc = swrap_recvmsg_after(s, si, omsg, &from_addr, from_addrlen, ret);
3904 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
3906 return swrap_recvmsg(sockfd, msg, flags);
3909 /****************************************************************************
3911 ***************************************************************************/
3913 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
3917 struct sockaddr_un un_addr;
3918 const struct sockaddr_un *to_un = NULL;
3919 const struct sockaddr *to = NULL;
3922 struct socket_info *si = find_socket_info(s);
3926 return libc_sendmsg(s, omsg, flags);
3929 ZERO_STRUCT(un_addr);
3931 tmp.iov_base = NULL;
3935 msg.msg_name = omsg->msg_name; /* optional address */
3936 msg.msg_namelen = omsg->msg_namelen; /* size of address */
3937 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3938 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3939 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3940 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3941 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3942 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3945 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3953 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3961 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
3962 avail += msg.msg_iov[i].iov_len;
3968 /* we capture it as one single packet */
3969 buf = (uint8_t *)malloc(remain);
3974 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
3975 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
3977 msg.msg_iov[i].iov_base,
3980 remain -= this_time;
3983 type = SOCKET_TYPE_CHAR_UDP;
3985 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3986 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3987 socket_wrapper_dir(), type, iface, prt);
3988 if (stat(un_addr.sun_path, &st) != 0) continue;
3990 msg.msg_name = &un_addr; /* optional address */
3991 msg.msg_namelen = sizeof(un_addr); /* size of address */
3993 /* ignore the any errors in broadcast sends */
3994 libc_sendmsg(s, &msg, flags);
3997 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4003 ret = libc_sendmsg(s, &msg, flags);
4005 swrap_sendmsg_after(s, si, &msg, to, ret);
4010 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4012 return swrap_sendmsg(s, omsg, flags);
4015 /****************************************************************************
4017 ***************************************************************************/
4019 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4021 struct socket_info *si;
4024 struct sockaddr_storage ss;
4025 socklen_t ss_len = sizeof(ss);
4029 si = find_socket_info(s);
4031 return libc_readv(s, vector, count);
4034 tmp.iov_base = NULL;
4038 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4039 msg.msg_namelen = ss_len; /* size of address */
4040 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4041 msg.msg_iovlen = count; /* # elements in msg_iov */
4042 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4043 msg.msg_control = NULL; /* ancillary data, see below */
4044 msg.msg_controllen = 0; /* ancillary data buffer len */
4045 msg.msg_flags = 0; /* flags on received message */
4048 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4050 if (rc == -ENOTSOCK) {
4051 return libc_readv(s, vector, count);
4056 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4058 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4066 ssize_t readv(int s, const struct iovec *vector, int count)
4068 return swrap_readv(s, vector, count);
4071 /****************************************************************************
4073 ***************************************************************************/
4075 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4079 struct sockaddr_un un_addr;
4082 struct socket_info *si = find_socket_info(s);
4085 return libc_writev(s, vector, count);
4088 tmp.iov_base = NULL;
4092 msg.msg_name = NULL; /* optional address */
4093 msg.msg_namelen = 0; /* size of address */
4094 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4095 msg.msg_iovlen = count; /* # elements in msg_iov */
4096 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4097 msg.msg_control = NULL; /* ancillary data, see below */
4098 msg.msg_controllen = 0; /* ancillary data buffer len */
4099 msg.msg_flags = 0; /* flags on received message */
4102 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4104 if (rc == -ENOTSOCK) {
4105 return libc_readv(s, vector, count);
4110 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4112 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4117 ssize_t writev(int s, const struct iovec *vector, int count)
4119 return swrap_writev(s, vector, count);
4122 /****************************
4124 ***************************/
4126 static int swrap_close(int fd)
4128 struct socket_info *si = find_socket_info(fd);
4129 struct socket_info_fd *fi;
4133 return libc_close(fd);
4136 for (fi = si->fds; fi; fi = fi->next) {
4138 SWRAP_DLIST_REMOVE(si->fds, fi);
4145 /* there are still references left */
4146 return libc_close(fd);
4149 SWRAP_DLIST_REMOVE(sockets, si);
4151 if (si->myname && si->peername) {
4152 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4155 ret = libc_close(fd);
4157 if (si->myname && si->peername) {
4158 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4159 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4162 if (si->bindname != NULL) {
4166 if (si->myname) free(si->myname);
4167 if (si->peername) free(si->peername);
4169 unlink(si->tmp_path);
4179 return swrap_close(fd);
4182 /****************************
4184 ***************************/
4186 static int swrap_dup(int fd)
4188 struct socket_info *si;
4189 struct socket_info_fd *fi;
4191 si = find_socket_info(fd);
4194 return libc_dup(fd);
4197 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4203 fi->fd = libc_dup(fd);
4205 int saved_errno = errno;
4207 errno = saved_errno;
4211 /* Make sure we don't have an entry for the fd */
4212 swrap_remove_stale(fi->fd);
4214 SWRAP_DLIST_ADD(si->fds, fi);
4220 return swrap_dup(fd);
4223 /****************************
4225 ***************************/
4227 static int swrap_dup2(int fd, int newfd)
4229 struct socket_info *si;
4230 struct socket_info_fd *fi;
4232 si = find_socket_info(fd);
4235 return libc_dup2(fd, newfd);
4238 if (find_socket_info(newfd)) {
4239 /* dup2() does an implicit close of newfd, which we
4240 * need to emulate */
4244 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4250 fi->fd = libc_dup2(fd, newfd);
4252 int saved_errno = errno;
4254 errno = saved_errno;
4258 /* Make sure we don't have an entry for the fd */
4259 swrap_remove_stale(fi->fd);
4261 SWRAP_DLIST_ADD(si->fds, fi);
4265 int dup2(int fd, int newfd)
4267 return swrap_dup2(fd, newfd);
4270 /****************************
4272 ***************************/
4275 static int swrap_eventfd(int count, int flags)
4279 fd = libc_eventfd(count, flags);
4281 swrap_remove_stale(fd);
4287 int eventfd(int count, int flags)
4289 return swrap_eventfd(count, flags);
4293 /****************************
4295 ***************************/
4298 * This function is called when the library is unloaded and makes sure that
4299 * sockets get closed and the unix file for the socket are unlinked.
4301 void swrap_destructor(void)
4303 struct socket_info *s = sockets;
4306 struct socket_info_fd *f = s->fds;