2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
45 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
100 #define DESTRUCTOR_ATTRIBUTE
103 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
106 # define SWRAP_THREAD
110 #define MIN(a,b) ((a)<(b)?(a):(b))
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
118 #define ZERO_STRUCTP(x) do { \
120 memset((char *)(x), 0, sizeof(*(x))); \
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
150 #define SWRAP_DLIST_ADD(list,item) do { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
167 (list)->prev = NULL; \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct 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;
247 struct sockaddr *bindname;
248 socklen_t bindname_len;
250 struct sockaddr *myname;
251 socklen_t myname_len;
253 struct sockaddr *peername;
254 socklen_t peername_len;
257 unsigned long pck_snd;
258 unsigned long pck_rcv;
261 struct socket_info *prev, *next;
265 * File descriptors are shared between threads so we should share socket
268 struct socket_info *sockets;
270 /* Function prototypes */
272 bool socket_wrapper_enabled(void);
273 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
276 # define SWRAP_LOG(...)
279 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
280 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
282 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
287 unsigned int lvl = 0;
289 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
294 va_start(va, format);
295 vsnprintf(buffer, sizeof(buffer), format, va);
300 case SWRAP_LOG_ERROR:
302 "SWRAP_ERROR(%d): %s\n",
303 (int)getpid(), buffer);
307 "SWRAP_WARN(%d): %s\n",
308 (int)getpid(), buffer);
310 case SWRAP_LOG_DEBUG:
312 "SWRAP_DEBUG(%d): %s\n",
313 (int)getpid(), buffer);
315 case SWRAP_LOG_TRACE:
317 "SWRAP_TRACE(%d): %s\n",
318 (int)getpid(), buffer);
325 /*********************************************************
326 * SWRAP LOADING LIBC FUNCTIONS
327 *********************************************************/
331 struct swrap_libc_fns {
332 int (*libc_accept)(int sockfd,
333 struct sockaddr *addr,
335 int (*libc_bind)(int sockfd,
336 const struct sockaddr *addr,
338 int (*libc_close)(int fd);
339 int (*libc_connect)(int sockfd,
340 const struct sockaddr *addr,
342 int (*libc_dup)(int fd);
343 int (*libc_dup2)(int oldfd, int newfd);
345 int (*libc_eventfd)(int count, int flags);
347 int (*libc_getpeername)(int sockfd,
348 struct sockaddr *addr,
350 int (*libc_getsockname)(int sockfd,
351 struct sockaddr *addr,
353 int (*libc_getsockopt)(int sockfd,
358 int (*libc_ioctl)(int d, unsigned long int request, ...);
359 int (*libc_listen)(int sockfd, int backlog);
360 int (*libc_open)(const char *pathname, int flags, mode_t mode);
361 int (*libc_pipe)(int pipefd[2]);
362 int (*libc_read)(int fd, void *buf, size_t count);
363 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
364 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
365 int (*libc_recvfrom)(int sockfd,
369 struct sockaddr *src_addr,
371 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
372 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
373 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
374 int (*libc_sendto)(int sockfd,
378 const struct sockaddr *dst_addr,
380 int (*libc_setsockopt)(int sockfd,
386 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
388 int (*libc_socket)(int domain, int type, int protocol);
389 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
390 #ifdef HAVE_TIMERFD_CREATE
391 int (*libc_timerfd_create)(int clockid, int flags);
393 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
398 void *libsocket_handle;
405 struct swrap_libc_fns fns;
408 static struct swrap swrap;
411 static const char *socket_wrapper_dir(void);
413 #define LIBC_NAME "libc.so"
422 static const char *swrap_str_lib(enum swrap_lib lib)
429 case SWRAP_LIBSOCKET:
433 /* Compiler would warn us about unhandled enum value if we get here */
438 static void *swrap_load_lib_handle(enum swrap_lib lib)
440 int flags = RTLD_LAZY;
445 flags |= RTLD_DEEPBIND;
451 case SWRAP_LIBSOCKET:
452 #ifdef HAVE_LIBSOCKET
453 handle = swrap.libsocket_handle;
454 if (handle == NULL) {
455 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
456 char soname[256] = {0};
458 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
459 handle = dlopen(soname, flags);
462 swrap.libsocket_handle = handle;
468 handle = swrap.libc_handle;
470 if (handle == NULL) {
471 handle = dlopen(LIBC_SO, flags);
473 swrap.libc_handle = handle;
476 if (handle == NULL) {
477 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
478 char soname[256] = {0};
480 snprintf(soname, sizeof(soname), "libc.so.%d", i);
481 handle = dlopen(soname, flags);
484 swrap.libc_handle = handle;
489 if (handle == NULL) {
491 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
493 SWRAP_LOG(SWRAP_LOG_ERROR,
494 "Failed to dlopen library: %s\n",
503 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
508 handle = swrap_load_lib_handle(lib);
510 func = dlsym(handle, fn_name);
512 SWRAP_LOG(SWRAP_LOG_ERROR,
513 "Failed to find %s: %s\n",
518 SWRAP_LOG(SWRAP_LOG_TRACE,
520 fn_name, swrap_str_lib(lib));
524 #define swrap_load_lib_function(lib, fn_name) \
525 if (swrap.fns.libc_##fn_name == NULL) { \
526 *(void **) (&swrap.fns.libc_##fn_name) = \
527 _swrap_load_lib_function(lib, #fn_name); \
534 * Functions especially from libc need to be loaded individually, you can't load
535 * all at once or gdb will segfault at startup. The same applies to valgrind and
536 * has probably something todo with with the linker.
537 * So we need load each function at the point it is called the first time.
539 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
541 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
543 return swrap.fns.libc_accept(sockfd, addr, addrlen);
546 static int libc_bind(int sockfd,
547 const struct sockaddr *addr,
550 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
552 return swrap.fns.libc_bind(sockfd, addr, addrlen);
555 static int libc_close(int fd)
557 swrap_load_lib_function(SWRAP_LIBC, close);
559 return swrap.fns.libc_close(fd);
562 static int libc_connect(int sockfd,
563 const struct sockaddr *addr,
566 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
568 return swrap.fns.libc_connect(sockfd, addr, addrlen);
571 static int libc_dup(int fd)
573 swrap_load_lib_function(SWRAP_LIBC, dup);
575 return swrap.fns.libc_dup(fd);
578 static int libc_dup2(int oldfd, int newfd)
580 swrap_load_lib_function(SWRAP_LIBC, dup2);
582 return swrap.fns.libc_dup2(oldfd, newfd);
586 static int libc_eventfd(int count, int flags)
588 swrap_load_lib_function(SWRAP_LIBC, eventfd);
590 return swrap.fns.libc_eventfd(count, flags);
594 static int libc_getpeername(int sockfd,
595 struct sockaddr *addr,
598 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
600 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
603 static int libc_getsockname(int sockfd,
604 struct sockaddr *addr,
607 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
609 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
612 static int libc_getsockopt(int sockfd,
618 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
620 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
623 static int libc_vioctl(int d, unsigned long int request, va_list ap)
629 swrap_load_lib_function(SWRAP_LIBC, ioctl);
631 for (i = 0; i < 4; i++) {
632 args[i] = va_arg(ap, long int);
635 rc = swrap.fns.libc_ioctl(d,
645 static int libc_listen(int sockfd, int backlog)
647 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
649 return swrap.fns.libc_listen(sockfd, backlog);
652 static int libc_vopen(const char *pathname, int flags, va_list ap)
657 swrap_load_lib_function(SWRAP_LIBC, open);
659 mode = va_arg(ap, long int);
661 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
666 static int libc_open(const char *pathname, int flags, ...)
672 fd = libc_vopen(pathname, flags, ap);
678 static int libc_pipe(int pipefd[2])
680 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
682 return swrap.fns.libc_pipe(pipefd);
685 static int libc_read(int fd, void *buf, size_t count)
687 swrap_load_lib_function(SWRAP_LIBC, read);
689 return swrap.fns.libc_read(fd, buf, count);
692 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
694 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
696 return swrap.fns.libc_readv(fd, iov, iovcnt);
699 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
701 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
703 return swrap.fns.libc_recv(sockfd, buf, len, flags);
706 static int libc_recvfrom(int sockfd,
710 struct sockaddr *src_addr,
713 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
715 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
718 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
720 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
722 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
725 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
727 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
729 return swrap.fns.libc_send(sockfd, buf, len, flags);
732 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
734 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
736 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
739 static int libc_sendto(int sockfd,
743 const struct sockaddr *dst_addr,
746 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
748 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
751 static int libc_setsockopt(int sockfd,
757 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
759 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
763 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
765 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
767 return swrap.fns.libc_signalfd(fd, mask, flags);
771 static int libc_socket(int domain, int type, int protocol)
773 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
775 return swrap.fns.libc_socket(domain, type, protocol);
778 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
780 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
782 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
785 #ifdef HAVE_TIMERFD_CREATE
786 static int libc_timerfd_create(int clockid, int flags)
788 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
790 return swrap.fns.libc_timerfd_create(clockid, flags);
794 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
796 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
798 return swrap.fns.libc_writev(fd, iov, iovcnt);
801 /*********************************************************
802 * SWRAP HELPER FUNCTIONS
803 *********************************************************/
809 static const struct in6_addr *swrap_ipv6(void)
811 static struct in6_addr v;
812 static int initialized;
820 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
829 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
831 struct sockaddr *ret = (struct sockaddr *)malloc(len);
832 memcpy(ret, data, len);
836 static void set_port(int family, int prt, struct sockaddr *addr)
840 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
844 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
850 static size_t socket_length(int family)
854 return sizeof(struct sockaddr_in);
857 return sizeof(struct sockaddr_in6);
863 static const char *socket_wrapper_dir(void)
865 const char *s = getenv("SOCKET_WRAPPER_DIR");
869 /* TODO use realpath(3) here, when we add support for threads */
870 if (strncmp(s, "./", 2) == 0) {
874 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
878 bool socket_wrapper_enabled(void)
880 const char *s = socket_wrapper_dir();
882 return s != NULL ? true : false;
885 static unsigned int socket_wrapper_default_iface(void)
887 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
890 if (sscanf(s, "%u", &iface) == 1) {
891 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
897 return 1;/* 127.0.0.1 */
900 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
907 p = strrchr(un->sun_path, '/');
908 if (p) p++; else p = un->sun_path;
910 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
915 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
918 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
929 case SOCKET_TYPE_CHAR_TCP:
930 case SOCKET_TYPE_CHAR_UDP: {
931 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
933 if ((*len) < sizeof(*in2)) {
938 memset(in2, 0, sizeof(*in2));
939 in2->sin_family = AF_INET;
940 in2->sin_addr.s_addr = htonl((127<<24) | iface);
941 in2->sin_port = htons(prt);
947 case SOCKET_TYPE_CHAR_TCP_V6:
948 case SOCKET_TYPE_CHAR_UDP_V6: {
949 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
951 if ((*len) < sizeof(*in2)) {
956 memset(in2, 0, sizeof(*in2));
957 in2->sin6_family = AF_INET6;
958 in2->sin6_addr = *swrap_ipv6();
959 in2->sin6_addr.s6_addr[15] = iface;
960 in2->sin6_port = htons(prt);
974 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
982 if (bcast) *bcast = 0;
984 switch (inaddr->sa_family) {
986 const struct sockaddr_in *in =
987 (const struct sockaddr_in *)(const void *)inaddr;
988 unsigned int addr = ntohl(in->sin_addr.s_addr);
995 u_type = SOCKET_TYPE_CHAR_TCP;
998 u_type = SOCKET_TYPE_CHAR_UDP;
999 a_type = SOCKET_TYPE_CHAR_UDP;
1000 b_type = SOCKET_TYPE_CHAR_UDP;
1003 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1004 errno = ESOCKTNOSUPPORT;
1008 prt = ntohs(in->sin_port);
1009 if (a_type && addr == 0xFFFFFFFF) {
1010 /* 255.255.255.255 only udp */
1013 iface = socket_wrapper_default_iface();
1014 } else if (b_type && addr == 0x7FFFFFFF) {
1015 /* 127.255.255.255 only udp */
1018 iface = socket_wrapper_default_iface();
1019 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1023 iface = (addr & 0x000000FF);
1025 errno = ENETUNREACH;
1028 if (bcast) *bcast = is_bcast;
1033 const struct sockaddr_in6 *in =
1034 (const struct sockaddr_in6 *)(const void *)inaddr;
1035 struct in6_addr cmp1, cmp2;
1039 type = SOCKET_TYPE_CHAR_TCP_V6;
1042 type = SOCKET_TYPE_CHAR_UDP_V6;
1045 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1046 errno = ESOCKTNOSUPPORT;
1050 /* XXX no multicast/broadcast */
1052 prt = ntohs(in->sin6_port);
1054 cmp1 = *swrap_ipv6();
1055 cmp2 = in->sin6_addr;
1056 cmp2.s6_addr[15] = 0;
1057 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1058 iface = in->sin6_addr.s6_addr[15];
1060 errno = ENETUNREACH;
1068 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1069 errno = ENETUNREACH;
1074 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1080 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1081 socket_wrapper_dir());
1082 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1083 /* the caller need to do more processing */
1087 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1088 socket_wrapper_dir(), type, iface, prt);
1089 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1094 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1103 if (bcast) *bcast = 0;
1105 switch (si->family) {
1107 const struct sockaddr_in *in =
1108 (const struct sockaddr_in *)(const void *)inaddr;
1109 unsigned int addr = ntohl(in->sin_addr.s_addr);
1115 prt = ntohs(in->sin_port);
1119 u_type = SOCKET_TYPE_CHAR_TCP;
1120 d_type = SOCKET_TYPE_CHAR_TCP;
1123 u_type = SOCKET_TYPE_CHAR_UDP;
1124 d_type = SOCKET_TYPE_CHAR_UDP;
1125 a_type = SOCKET_TYPE_CHAR_UDP;
1126 b_type = SOCKET_TYPE_CHAR_UDP;
1129 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1130 errno = ESOCKTNOSUPPORT;
1138 iface = socket_wrapper_default_iface();
1139 } else if (a_type && addr == 0xFFFFFFFF) {
1140 /* 255.255.255.255 only udp */
1143 iface = socket_wrapper_default_iface();
1144 } else if (b_type && addr == 0x7FFFFFFF) {
1145 /* 127.255.255.255 only udp */
1148 iface = socket_wrapper_default_iface();
1149 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1153 iface = (addr & 0x000000FF);
1155 errno = EADDRNOTAVAIL;
1159 /* Store the bind address for connect() */
1160 if (si->bindname == NULL) {
1161 struct sockaddr_in bind_in;
1162 socklen_t blen = sizeof(struct sockaddr_in);
1164 ZERO_STRUCT(bind_in);
1165 bind_in.sin_family = in->sin_family;
1166 bind_in.sin_port = in->sin_port;
1167 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1169 si->bindname = sockaddr_dup(&bind_in, blen);
1170 si->bindname_len = blen;
1177 const struct sockaddr_in6 *in =
1178 (const struct sockaddr_in6 *)(const void *)inaddr;
1179 struct in6_addr cmp1, cmp2;
1183 type = SOCKET_TYPE_CHAR_TCP_V6;
1186 type = SOCKET_TYPE_CHAR_UDP_V6;
1189 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1190 errno = ESOCKTNOSUPPORT;
1194 /* XXX no multicast/broadcast */
1196 prt = ntohs(in->sin6_port);
1198 cmp1 = *swrap_ipv6();
1199 cmp2 = in->sin6_addr;
1200 cmp2.s6_addr[15] = 0;
1201 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1202 iface = socket_wrapper_default_iface();
1203 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1204 iface = in->sin6_addr.s6_addr[15];
1206 errno = EADDRNOTAVAIL;
1210 /* Store the bind address for connect() */
1211 if (si->bindname == NULL) {
1212 struct sockaddr_in6 bind_in;
1213 socklen_t blen = sizeof(struct sockaddr_in6);
1215 ZERO_STRUCT(bind_in);
1216 bind_in.sin6_family = in->sin6_family;
1217 bind_in.sin6_port = in->sin6_port;
1219 bind_in.sin6_addr = *swrap_ipv6();
1220 bind_in.sin6_addr.s6_addr[15] = iface;
1222 si->bindname = sockaddr_dup(&bind_in, blen);
1223 si->bindname_len = blen;
1230 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1231 errno = EADDRNOTAVAIL;
1236 if (bcast) *bcast = is_bcast;
1238 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1244 /* handle auto-allocation of ephemeral ports */
1245 for (prt = 5001; prt < 10000; prt++) {
1246 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1247 socket_wrapper_dir(), type, iface, prt);
1248 if (stat(un->sun_path, &st) == 0) continue;
1250 set_port(si->family, prt, si->myname);
1251 set_port(si->family, prt, si->bindname);
1261 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1262 socket_wrapper_dir(), type, iface, prt);
1263 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1267 static struct socket_info *find_socket_info(int fd)
1269 struct socket_info *i;
1271 for (i = sockets; i; i = i->next) {
1272 struct socket_info_fd *f;
1273 for (f = i->fds; f; f = f->next) {
1284 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1286 struct socket_info *s;
1288 /* first catch invalid input */
1289 switch (sa->sa_family) {
1291 if (len < sizeof(struct sockaddr_in)) {
1297 if (len < sizeof(struct sockaddr_in6)) {
1307 for (s = sockets; s != NULL; s = s->next) {
1308 if (s->myname == NULL) {
1311 if (s->myname->sa_family != sa->sa_family) {
1314 switch (s->myname->sa_family) {
1316 struct sockaddr_in *sin1, *sin2;
1318 sin1 = (struct sockaddr_in *)s->myname;
1319 sin2 = (struct sockaddr_in *)sa;
1321 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1324 if (sin1->sin_port != sin2->sin_port) {
1327 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1337 struct sockaddr_in6 *sin1, *sin2;
1339 sin1 = (struct sockaddr_in6 *)s->myname;
1340 sin2 = (struct sockaddr_in6 *)sa;
1342 if (sin1->sin6_port != sin2->sin6_port) {
1345 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1367 static void swrap_remove_stale(int fd)
1369 struct socket_info *si = find_socket_info(fd);
1370 struct socket_info_fd *fi;
1373 for (fi = si->fds; fi; fi = fi->next) {
1375 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1376 SWRAP_DLIST_REMOVE(si->fds, fi);
1382 if (si->fds == NULL) {
1383 SWRAP_DLIST_REMOVE(sockets, si);
1388 static int sockaddr_convert_to_un(struct socket_info *si,
1389 const struct sockaddr *in_addr,
1391 struct sockaddr_un *out_addr,
1395 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1397 (void) in_len; /* unused */
1399 if (out_addr == NULL) {
1403 out->sa_family = AF_UNIX;
1404 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1405 out->sa_len = sizeof(*out_addr);
1408 switch (in_addr->sa_family) {
1410 const struct sockaddr_in *sin;
1411 if (si->family != AF_INET) {
1414 if (in_len < sizeof(struct sockaddr_in)) {
1417 sin = (const struct sockaddr_in *)in_addr;
1418 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1423 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1424 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1438 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1439 errno = ESOCKTNOSUPPORT;
1443 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1445 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1451 errno = EAFNOSUPPORT;
1452 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1456 static int sockaddr_convert_from_un(const struct socket_info *si,
1457 const struct sockaddr_un *in_addr,
1458 socklen_t un_addrlen,
1460 struct sockaddr *out_addr,
1461 socklen_t *out_addrlen)
1465 if (out_addr == NULL || out_addrlen == NULL)
1468 if (un_addrlen == 0) {
1483 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1484 errno = ESOCKTNOSUPPORT;
1487 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1488 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1489 out_addr->sa_len = *out_addrlen;
1496 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1497 errno = EAFNOSUPPORT;
1501 enum swrap_packet_type {
1503 SWRAP_CONNECT_UNREACH,
1511 SWRAP_SENDTO_UNREACH,
1522 struct swrap_file_hdr {
1524 uint16_t version_major;
1525 uint16_t version_minor;
1528 uint32_t frame_max_len;
1529 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1532 #define SWRAP_FILE_HDR_SIZE 24
1534 struct swrap_packet_frame {
1536 uint32_t micro_seconds;
1537 uint32_t recorded_length;
1538 uint32_t full_length;
1540 #define SWRAP_PACKET_FRAME_SIZE 16
1542 union swrap_packet_ip {
1546 uint16_t packet_length;
1547 uint16_t identification;
1552 uint16_t hdr_checksum;
1556 #define SWRAP_PACKET_IP_V4_SIZE 20
1559 uint8_t flow_label_high;
1560 uint16_t flow_label_low;
1561 uint16_t payload_length;
1562 uint8_t next_header;
1564 uint8_t src_addr[16];
1565 uint8_t dest_addr[16];
1567 #define SWRAP_PACKET_IP_V6_SIZE 40
1569 #define SWRAP_PACKET_IP_SIZE 40
1571 union swrap_packet_payload {
1573 uint16_t source_port;
1583 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1585 uint16_t source_port;
1590 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1597 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1604 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1606 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1608 #define SWRAP_PACKET_MIN_ALLOC \
1609 (SWRAP_PACKET_FRAME_SIZE + \
1610 SWRAP_PACKET_IP_SIZE + \
1611 SWRAP_PACKET_PAYLOAD_SIZE)
1613 static const char *swrap_pcap_init_file(void)
1615 static int initialized = 0;
1616 static const char *s = NULL;
1617 static const struct swrap_file_hdr h;
1618 static const struct swrap_packet_frame f;
1619 static const union swrap_packet_ip i;
1620 static const union swrap_packet_payload p;
1622 if (initialized == 1) {
1628 * TODO: don't use the structs use plain buffer offsets
1629 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1631 * for now make sure we disable PCAP support
1632 * if the struct has alignment!
1634 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1637 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1640 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1643 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1646 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1649 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1652 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1655 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1658 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1661 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1665 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1669 if (strncmp(s, "./", 2) == 0) {
1675 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1676 const struct sockaddr *src,
1677 const struct sockaddr *dest,
1679 const uint8_t *payload,
1681 unsigned long tcp_seqno,
1682 unsigned long tcp_ack,
1683 unsigned char tcp_ctl,
1685 size_t *_packet_len)
1689 struct swrap_packet_frame *frame;
1690 union swrap_packet_ip *ip;
1691 union swrap_packet_payload *pay;
1694 size_t nonwire_len = sizeof(*frame);
1695 size_t wire_hdr_len = 0;
1696 size_t wire_len = 0;
1697 size_t ip_hdr_len = 0;
1698 size_t icmp_hdr_len = 0;
1699 size_t icmp_truncate_len = 0;
1700 uint8_t protocol = 0, icmp_protocol = 0;
1701 const struct sockaddr_in *src_in = NULL;
1702 const struct sockaddr_in *dest_in = NULL;
1704 const struct sockaddr_in6 *src_in6 = NULL;
1705 const struct sockaddr_in6 *dest_in6 = NULL;
1710 switch (src->sa_family) {
1712 src_in = (const struct sockaddr_in *)src;
1713 dest_in = (const struct sockaddr_in *)dest;
1714 src_port = src_in->sin_port;
1715 dest_port = dest_in->sin_port;
1716 ip_hdr_len = sizeof(ip->v4);
1720 src_in6 = (const struct sockaddr_in6 *)src;
1721 dest_in6 = (const struct sockaddr_in6 *)dest;
1722 src_port = src_in6->sin6_port;
1723 dest_port = dest_in6->sin6_port;
1724 ip_hdr_len = sizeof(ip->v6);
1731 switch (socket_type) {
1733 protocol = 0x06; /* TCP */
1734 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1735 wire_len = wire_hdr_len + payload_len;
1739 protocol = 0x11; /* UDP */
1740 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1741 wire_len = wire_hdr_len + payload_len;
1749 icmp_protocol = protocol;
1750 switch (src->sa_family) {
1752 protocol = 0x01; /* ICMPv4 */
1753 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1757 protocol = 0x3A; /* ICMPv6 */
1758 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1762 if (wire_len > 64 ) {
1763 icmp_truncate_len = wire_len - 64;
1765 wire_hdr_len += icmp_hdr_len;
1766 wire_len += icmp_hdr_len;
1769 packet_len = nonwire_len + wire_len;
1770 alloc_len = packet_len;
1771 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1772 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1775 base = (uint8_t *)malloc(alloc_len);
1779 memset(base, 0x0, alloc_len);
1783 frame = (struct swrap_packet_frame *)buf;
1784 frame->seconds = tval->tv_sec;
1785 frame->micro_seconds = tval->tv_usec;
1786 frame->recorded_length = wire_len - icmp_truncate_len;
1787 frame->full_length = wire_len - icmp_truncate_len;
1788 buf += SWRAP_PACKET_FRAME_SIZE;
1790 ip = (union swrap_packet_ip *)buf;
1791 switch (src->sa_family) {
1793 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1795 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1796 ip->v4.identification = htons(0xFFFF);
1797 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1798 ip->v4.fragment = htons(0x0000);
1800 ip->v4.protocol = protocol;
1801 ip->v4.hdr_checksum = htons(0x0000);
1802 ip->v4.src_addr = src_in->sin_addr.s_addr;
1803 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1804 buf += SWRAP_PACKET_IP_V4_SIZE;
1808 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1809 ip->v6.flow_label_high = 0x00;
1810 ip->v6.flow_label_low = 0x0000;
1811 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1812 ip->v6.next_header = protocol;
1813 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1814 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1815 buf += SWRAP_PACKET_IP_V6_SIZE;
1821 pay = (union swrap_packet_payload *)buf;
1822 switch (src->sa_family) {
1824 pay->icmp4.type = 0x03; /* destination unreachable */
1825 pay->icmp4.code = 0x01; /* host unreachable */
1826 pay->icmp4.checksum = htons(0x0000);
1827 pay->icmp4.unused = htonl(0x00000000);
1828 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1830 /* set the ip header in the ICMP payload */
1831 ip = (union swrap_packet_ip *)buf;
1832 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1834 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1835 ip->v4.identification = htons(0xFFFF);
1836 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1837 ip->v4.fragment = htons(0x0000);
1839 ip->v4.protocol = icmp_protocol;
1840 ip->v4.hdr_checksum = htons(0x0000);
1841 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1842 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1843 buf += SWRAP_PACKET_IP_V4_SIZE;
1845 src_port = dest_in->sin_port;
1846 dest_port = src_in->sin_port;
1850 pay->icmp6.type = 0x01; /* destination unreachable */
1851 pay->icmp6.code = 0x03; /* address unreachable */
1852 pay->icmp6.checksum = htons(0x0000);
1853 pay->icmp6.unused = htonl(0x00000000);
1854 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1856 /* set the ip header in the ICMP payload */
1857 ip = (union swrap_packet_ip *)buf;
1858 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1859 ip->v6.flow_label_high = 0x00;
1860 ip->v6.flow_label_low = 0x0000;
1861 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1862 ip->v6.next_header = protocol;
1863 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1864 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1865 buf += SWRAP_PACKET_IP_V6_SIZE;
1867 src_port = dest_in6->sin6_port;
1868 dest_port = src_in6->sin6_port;
1874 pay = (union swrap_packet_payload *)buf;
1876 switch (socket_type) {
1878 pay->tcp.source_port = src_port;
1879 pay->tcp.dest_port = dest_port;
1880 pay->tcp.seq_num = htonl(tcp_seqno);
1881 pay->tcp.ack_num = htonl(tcp_ack);
1882 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1883 pay->tcp.control = tcp_ctl;
1884 pay->tcp.window = htons(0x7FFF);
1885 pay->tcp.checksum = htons(0x0000);
1886 pay->tcp.urg = htons(0x0000);
1887 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1892 pay->udp.source_port = src_port;
1893 pay->udp.dest_port = dest_port;
1894 pay->udp.length = htons(8 + payload_len);
1895 pay->udp.checksum = htons(0x0000);
1896 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1901 if (payload && payload_len > 0) {
1902 memcpy(buf, payload, payload_len);
1905 *_packet_len = packet_len - icmp_truncate_len;
1909 static int swrap_get_pcap_fd(const char *fname)
1913 if (fd != -1) return fd;
1915 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1917 struct swrap_file_hdr file_hdr;
1918 file_hdr.magic = 0xA1B2C3D4;
1919 file_hdr.version_major = 0x0002;
1920 file_hdr.version_minor = 0x0004;
1921 file_hdr.timezone = 0x00000000;
1922 file_hdr.sigfigs = 0x00000000;
1923 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1924 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1926 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1933 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1938 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1939 const struct sockaddr *addr,
1940 enum swrap_packet_type type,
1941 const void *buf, size_t len,
1944 const struct sockaddr *src_addr;
1945 const struct sockaddr *dest_addr;
1946 unsigned long tcp_seqno = 0;
1947 unsigned long tcp_ack = 0;
1948 unsigned char tcp_ctl = 0;
1949 int unreachable = 0;
1953 switch (si->family) {
1965 case SWRAP_CONNECT_SEND:
1966 if (si->type != SOCK_STREAM) return NULL;
1968 src_addr = si->myname;
1971 tcp_seqno = si->io.pck_snd;
1972 tcp_ack = si->io.pck_rcv;
1973 tcp_ctl = 0x02; /* SYN */
1975 si->io.pck_snd += 1;
1979 case SWRAP_CONNECT_RECV:
1980 if (si->type != SOCK_STREAM) return NULL;
1982 dest_addr = si->myname;
1985 tcp_seqno = si->io.pck_rcv;
1986 tcp_ack = si->io.pck_snd;
1987 tcp_ctl = 0x12; /** SYN,ACK */
1989 si->io.pck_rcv += 1;
1993 case SWRAP_CONNECT_UNREACH:
1994 if (si->type != SOCK_STREAM) return NULL;
1996 dest_addr = si->myname;
1999 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2000 tcp_seqno = si->io.pck_snd - 1;
2001 tcp_ack = si->io.pck_rcv;
2002 tcp_ctl = 0x02; /* SYN */
2007 case SWRAP_CONNECT_ACK:
2008 if (si->type != SOCK_STREAM) return NULL;
2010 src_addr = si->myname;
2013 tcp_seqno = si->io.pck_snd;
2014 tcp_ack = si->io.pck_rcv;
2015 tcp_ctl = 0x10; /* ACK */
2019 case SWRAP_ACCEPT_SEND:
2020 if (si->type != SOCK_STREAM) return NULL;
2022 dest_addr = si->myname;
2025 tcp_seqno = si->io.pck_rcv;
2026 tcp_ack = si->io.pck_snd;
2027 tcp_ctl = 0x02; /* SYN */
2029 si->io.pck_rcv += 1;
2033 case SWRAP_ACCEPT_RECV:
2034 if (si->type != SOCK_STREAM) return NULL;
2036 src_addr = si->myname;
2039 tcp_seqno = si->io.pck_snd;
2040 tcp_ack = si->io.pck_rcv;
2041 tcp_ctl = 0x12; /* SYN,ACK */
2043 si->io.pck_snd += 1;
2047 case SWRAP_ACCEPT_ACK:
2048 if (si->type != SOCK_STREAM) return NULL;
2050 dest_addr = si->myname;
2053 tcp_seqno = si->io.pck_rcv;
2054 tcp_ack = si->io.pck_snd;
2055 tcp_ctl = 0x10; /* ACK */
2060 src_addr = si->myname;
2061 dest_addr = si->peername;
2063 tcp_seqno = si->io.pck_snd;
2064 tcp_ack = si->io.pck_rcv;
2065 tcp_ctl = 0x18; /* PSH,ACK */
2067 si->io.pck_snd += len;
2071 case SWRAP_SEND_RST:
2072 dest_addr = si->myname;
2073 src_addr = si->peername;
2075 if (si->type == SOCK_DGRAM) {
2076 return swrap_marshall_packet(si, si->peername,
2077 SWRAP_SENDTO_UNREACH,
2078 buf, len, packet_len);
2081 tcp_seqno = si->io.pck_rcv;
2082 tcp_ack = si->io.pck_snd;
2083 tcp_ctl = 0x14; /** RST,ACK */
2087 case SWRAP_PENDING_RST:
2088 dest_addr = si->myname;
2089 src_addr = si->peername;
2091 if (si->type == SOCK_DGRAM) {
2095 tcp_seqno = si->io.pck_rcv;
2096 tcp_ack = si->io.pck_snd;
2097 tcp_ctl = 0x14; /* RST,ACK */
2102 dest_addr = si->myname;
2103 src_addr = si->peername;
2105 tcp_seqno = si->io.pck_rcv;
2106 tcp_ack = si->io.pck_snd;
2107 tcp_ctl = 0x18; /* PSH,ACK */
2109 si->io.pck_rcv += len;
2113 case SWRAP_RECV_RST:
2114 dest_addr = si->myname;
2115 src_addr = si->peername;
2117 if (si->type == SOCK_DGRAM) {
2121 tcp_seqno = si->io.pck_rcv;
2122 tcp_ack = si->io.pck_snd;
2123 tcp_ctl = 0x14; /* RST,ACK */
2128 src_addr = si->myname;
2131 si->io.pck_snd += len;
2135 case SWRAP_SENDTO_UNREACH:
2136 dest_addr = si->myname;
2143 case SWRAP_RECVFROM:
2144 dest_addr = si->myname;
2147 si->io.pck_rcv += len;
2151 case SWRAP_CLOSE_SEND:
2152 if (si->type != SOCK_STREAM) return NULL;
2154 src_addr = si->myname;
2155 dest_addr = si->peername;
2157 tcp_seqno = si->io.pck_snd;
2158 tcp_ack = si->io.pck_rcv;
2159 tcp_ctl = 0x11; /* FIN, ACK */
2161 si->io.pck_snd += 1;
2165 case SWRAP_CLOSE_RECV:
2166 if (si->type != SOCK_STREAM) return NULL;
2168 dest_addr = si->myname;
2169 src_addr = si->peername;
2171 tcp_seqno = si->io.pck_rcv;
2172 tcp_ack = si->io.pck_snd;
2173 tcp_ctl = 0x11; /* FIN,ACK */
2175 si->io.pck_rcv += 1;
2179 case SWRAP_CLOSE_ACK:
2180 if (si->type != SOCK_STREAM) return NULL;
2182 src_addr = si->myname;
2183 dest_addr = si->peername;
2185 tcp_seqno = si->io.pck_snd;
2186 tcp_ack = si->io.pck_rcv;
2187 tcp_ctl = 0x10; /* ACK */
2194 swrapGetTimeOfDay(&tv);
2196 return swrap_pcap_packet_init(&tv,
2200 (const uint8_t *)buf,
2209 static void swrap_dump_packet(struct socket_info *si,
2210 const struct sockaddr *addr,
2211 enum swrap_packet_type type,
2212 const void *buf, size_t len)
2214 const char *file_name;
2216 size_t packet_len = 0;
2219 file_name = swrap_pcap_init_file();
2224 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2229 fd = swrap_get_pcap_fd(file_name);
2231 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2240 /****************************************************************************
2242 ***************************************************************************/
2244 #ifdef HAVE_SIGNALFD
2245 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2249 rc = libc_signalfd(fd, mask, flags);
2251 swrap_remove_stale(fd);
2257 int signalfd(int fd, const sigset_t *mask, int flags)
2259 return swrap_signalfd(fd, mask, flags);
2263 /****************************************************************************
2265 ***************************************************************************/
2267 static int swrap_socket(int family, int type, int protocol)
2269 struct socket_info *si;
2270 struct socket_info_fd *fi;
2272 int real_type = type;
2275 * Remove possible addition flags passed to socket() so
2276 * do not fail checking the type.
2277 * See https://lwn.net/Articles/281965/
2280 real_type &= ~SOCK_CLOEXEC;
2282 #ifdef SOCK_NONBLOCK
2283 real_type &= ~SOCK_NONBLOCK;
2286 if (!socket_wrapper_enabled()) {
2287 return libc_socket(family, type, protocol);
2297 return libc_socket(family, type, protocol);
2299 errno = EAFNOSUPPORT;
2303 switch (real_type) {
2309 errno = EPROTONOSUPPORT;
2317 if (real_type == SOCK_STREAM) {
2322 if (real_type == SOCK_DGRAM) {
2327 errno = EPROTONOSUPPORT;
2332 * We must call libc_socket with type, from the caller, not the version
2333 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2335 fd = libc_socket(AF_UNIX, type, 0);
2341 /* Check if we have a stale fd and remove it */
2342 si = find_socket_info(fd);
2344 swrap_remove_stale(fd);
2347 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2348 memset(si, 0, sizeof(struct socket_info));
2354 si->family = family;
2356 /* however, the rest of the socket_wrapper code expects just
2357 * the type, not the flags */
2358 si->type = real_type;
2359 si->protocol = protocol;
2362 * Setup myname so getsockname() can succeed to find out the socket
2365 switch(si->family) {
2367 struct sockaddr_in sin = {
2368 .sin_family = AF_INET,
2371 si->myname_len = sizeof(struct sockaddr_in);
2372 si->myname = sockaddr_dup(&sin, si->myname_len);
2376 struct sockaddr_in6 sin6 = {
2377 .sin6_family = AF_INET6,
2380 si->myname_len = sizeof(struct sockaddr_in6);
2381 si->myname = sockaddr_dup(&sin6, si->myname_len);
2390 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2392 if (si->myname != NULL) {
2402 SWRAP_DLIST_ADD(si->fds, fi);
2403 SWRAP_DLIST_ADD(sockets, si);
2408 int socket(int family, int type, int protocol)
2410 return swrap_socket(family, type, protocol);
2413 /****************************************************************************
2415 ***************************************************************************/
2417 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2421 rc = libc_socketpair(family, type, protocol, sv);
2423 swrap_remove_stale(sv[0]);
2424 swrap_remove_stale(sv[1]);
2430 int socketpair(int family, int type, int protocol, int sv[2])
2432 return swrap_socketpair(family, type, protocol, sv);
2435 /****************************************************************************
2437 ***************************************************************************/
2439 #ifdef HAVE_TIMERFD_CREATE
2440 static int swrap_timerfd_create(int clockid, int flags)
2444 fd = libc_timerfd_create(clockid, flags);
2446 swrap_remove_stale(fd);
2452 int timerfd_create(int clockid, int flags)
2454 return swrap_timerfd_create(clockid, flags);
2458 /****************************************************************************
2460 ***************************************************************************/
2462 static int swrap_pipe(int pipefd[2])
2466 rc = libc_pipe(pipefd);
2468 swrap_remove_stale(pipefd[0]);
2469 swrap_remove_stale(pipefd[1]);
2475 int pipe(int pipefd[2])
2477 return swrap_pipe(pipefd);
2480 /****************************************************************************
2482 ***************************************************************************/
2484 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2486 struct socket_info *parent_si, *child_si;
2487 struct socket_info_fd *child_fi;
2489 struct swrap_address un_addr = {
2490 .sa_socklen = sizeof(struct sockaddr_un),
2492 struct swrap_address un_my_addr = {
2493 .sa_socklen = sizeof(struct sockaddr_un),
2495 struct sockaddr *my_addr;
2496 socklen_t my_addrlen, len;
2499 parent_si = find_socket_info(s);
2501 return libc_accept(s, addr, addrlen);
2505 * assume out sockaddr have the same size as the in parent
2508 my_addrlen = socket_length(parent_si->family);
2509 if (my_addrlen <= 0) {
2514 my_addr = (struct sockaddr *)malloc(my_addrlen);
2515 if (my_addr == NULL) {
2519 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2521 if (errno == ENOTSOCK) {
2522 /* Remove stale fds */
2523 swrap_remove_stale(s);
2532 ret = sockaddr_convert_from_un(parent_si,
2544 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2545 memset(child_si, 0, sizeof(struct socket_info));
2547 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2548 if (child_fi == NULL) {
2558 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2560 child_si->family = parent_si->family;
2561 child_si->type = parent_si->type;
2562 child_si->protocol = parent_si->protocol;
2563 child_si->bound = 1;
2564 child_si->is_server = 1;
2565 child_si->connected = 1;
2567 child_si->peername_len = len;
2568 child_si->peername = sockaddr_dup(my_addr, len);
2570 if (addr != NULL && addrlen != NULL) {
2571 size_t copy_len = MIN(*addrlen, len);
2573 memcpy(addr, my_addr, copy_len);
2578 ret = libc_getsockname(fd,
2580 &un_my_addr.sa_socklen);
2590 ret = sockaddr_convert_from_un(child_si,
2592 un_my_addr.sa_socklen,
2604 SWRAP_LOG(SWRAP_LOG_TRACE,
2605 "accept() path=%s, fd=%d",
2606 un_my_addr.sa.un.sun_path, s);
2608 child_si->myname_len = len;
2609 child_si->myname = sockaddr_dup(my_addr, len);
2612 SWRAP_DLIST_ADD(sockets, child_si);
2615 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2616 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2617 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2623 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2624 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2626 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2629 return swrap_accept(s, addr, (socklen_t *)addrlen);
2632 static int autobind_start_init;
2633 static int autobind_start;
2635 /* using sendto() or connect() on an unbound socket would give the
2636 recipient no way to reply, as unlike UDP and TCP, a unix domain
2637 socket can't auto-assign ephemeral port numbers, so we need to
2639 Note: this might change the family from ipv6 to ipv4
2641 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2643 struct swrap_address un_addr = {
2644 .sa_socklen = sizeof(struct sockaddr_un),
2652 if (autobind_start_init != 1) {
2653 autobind_start_init = 1;
2654 autobind_start = getpid();
2655 autobind_start %= 50000;
2656 autobind_start += 10000;
2659 un_addr.sa.un.sun_family = AF_UNIX;
2663 struct sockaddr_in in;
2667 type = SOCKET_TYPE_CHAR_TCP;
2670 type = SOCKET_TYPE_CHAR_UDP;
2673 errno = ESOCKTNOSUPPORT;
2677 memset(&in, 0, sizeof(in));
2678 in.sin_family = AF_INET;
2679 in.sin_addr.s_addr = htonl(127<<24 |
2680 socket_wrapper_default_iface());
2683 si->myname_len = sizeof(in);
2684 si->myname = sockaddr_dup(&in, si->myname_len);
2689 struct sockaddr_in6 in6;
2691 if (si->family != family) {
2692 errno = ENETUNREACH;
2698 type = SOCKET_TYPE_CHAR_TCP_V6;
2701 type = SOCKET_TYPE_CHAR_UDP_V6;
2704 errno = ESOCKTNOSUPPORT;
2708 memset(&in6, 0, sizeof(in6));
2709 in6.sin6_family = AF_INET6;
2710 in6.sin6_addr = *swrap_ipv6();
2711 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2713 si->myname_len = sizeof(in6);
2714 si->myname = sockaddr_dup(&in6, si->myname_len);
2719 errno = ESOCKTNOSUPPORT;
2723 if (autobind_start > 60000) {
2724 autobind_start = 10000;
2727 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2728 port = autobind_start + i;
2729 snprintf(un_addr.sa.un.sun_path, un_addr.sa_socklen,
2730 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2731 type, socket_wrapper_default_iface(), port);
2732 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2734 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2735 if (ret == -1) return ret;
2737 si->tmp_path = strdup(un_addr.sa.un.sun_path);
2739 autobind_start = port + 1;
2742 if (i == SOCKET_MAX_SOCKETS) {
2743 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2744 "interface "SOCKET_FORMAT,
2747 socket_wrapper_default_iface(),
2753 si->family = family;
2754 set_port(si->family, port, si->myname);
2759 /****************************************************************************
2761 ***************************************************************************/
2763 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2767 struct swrap_address un_addr = {
2768 .sa_socklen = sizeof(struct sockaddr_un),
2770 struct socket_info *si = find_socket_info(s);
2774 return libc_connect(s, serv_addr, addrlen);
2777 if (si->bound == 0) {
2778 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2779 if (ret == -1) return -1;
2782 if (si->family != serv_addr->sa_family) {
2787 ret = sockaddr_convert_to_un(si, serv_addr,
2788 addrlen, &un_addr.sa.un, 0, &bcast);
2789 if (ret == -1) return -1;
2792 errno = ENETUNREACH;
2796 if (si->type == SOCK_DGRAM) {
2797 si->defer_connect = 1;
2800 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2802 ret = libc_connect(s,
2804 un_addr.sa_socklen);
2807 SWRAP_LOG(SWRAP_LOG_TRACE,
2808 "connect() path=%s, fd=%d",
2809 un_addr.un.sun_path, s);
2812 /* to give better errors */
2813 if (ret == -1 && errno == ENOENT) {
2814 errno = EHOSTUNREACH;
2818 si->peername_len = addrlen;
2819 si->peername = sockaddr_dup(serv_addr, addrlen);
2823 * When we connect() on a socket than we have to bind the
2824 * outgoing connection on the interface we use for the
2825 * transport. We already bound it on the right interface
2826 * but here we have to update the name so getsockname()
2827 * returns correct information.
2829 if (si->bindname != NULL) {
2832 si->myname = si->bindname;
2833 si->myname_len = si->bindname_len;
2835 si->bindname = NULL;
2836 si->bindname_len = 0;
2839 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2840 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2842 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2848 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2850 return swrap_connect(s, serv_addr, addrlen);
2853 /****************************************************************************
2855 ***************************************************************************/
2857 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2860 struct swrap_address un_addr = {
2861 .sa_socklen = sizeof(struct sockaddr_un),
2863 struct socket_info *si = find_socket_info(s);
2870 return libc_bind(s, myaddr, addrlen);
2873 switch (si->family) {
2875 const struct sockaddr_in *sin;
2876 if (addrlen < sizeof(struct sockaddr_in)) {
2877 bind_error = EINVAL;
2881 sin = (const struct sockaddr_in *)myaddr;
2883 if (sin->sin_family != AF_INET) {
2884 bind_error = EAFNOSUPPORT;
2887 /* special case for AF_UNSPEC */
2888 if (sin->sin_family == AF_UNSPEC &&
2889 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2898 const struct sockaddr_in6 *sin6;
2899 if (addrlen < sizeof(struct sockaddr_in6)) {
2900 bind_error = EINVAL;
2904 sin6 = (const struct sockaddr_in6 *)myaddr;
2906 if (sin6->sin6_family != AF_INET6) {
2907 bind_error = EAFNOSUPPORT;
2914 bind_error = EINVAL;
2918 if (bind_error != 0) {
2924 in_use = check_addr_port_in_use(myaddr, addrlen);
2932 si->myname_len = addrlen;
2933 si->myname = sockaddr_dup(myaddr, addrlen);
2935 ret = sockaddr_convert_to_un(si,
2941 if (ret == -1) return -1;
2943 unlink(un_addr.sa.un.sun_path);
2945 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
2947 SWRAP_LOG(SWRAP_LOG_TRACE,
2948 "bind() path=%s, fd=%d",
2949 un_addr.sa_un.sun_path, s);
2958 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2960 return swrap_bind(s, myaddr, addrlen);
2963 /****************************************************************************
2965 ***************************************************************************/
2967 #ifdef HAVE_BINDRESVPORT
2968 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2970 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2972 struct swrap_address myaddr = {
2973 .sa_socklen = sizeof(struct sockaddr_storage),
2976 static uint16_t port;
2981 #define SWRAP_STARTPORT 600
2982 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2983 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2986 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2990 salen = myaddr.sa_socklen;
2993 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
2999 memset(&myaddr.sa.ss, 0, salen);
3004 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3007 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3009 salen = sizeof(struct sockaddr_in);
3010 sinp->sin_port = htons(port);
3014 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
3016 salen = sizeof(struct sockaddr_in6);
3017 sin6p->sin6_port = htons(port);
3021 errno = EAFNOSUPPORT;
3026 if (port > SWRAP_ENDPORT) {
3027 port = SWRAP_STARTPORT;
3030 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3031 if (rc == 0 || errno != EADDRINUSE) {
3039 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3041 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3045 /****************************************************************************
3047 ***************************************************************************/
3049 static int swrap_listen(int s, int backlog)
3052 struct socket_info *si = find_socket_info(s);
3055 return libc_listen(s, backlog);
3058 ret = libc_listen(s, backlog);
3063 int listen(int s, int backlog)
3065 return swrap_listen(s, backlog);
3068 /****************************************************************************
3070 ***************************************************************************/
3072 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3076 ret = libc_vopen(pathname, flags, ap);
3079 * There are methods for closing descriptors (libc-internal code
3080 * paths, direct syscalls) which close descriptors in ways that
3081 * we can't intercept, so try to recover when we notice that
3084 swrap_remove_stale(ret);
3089 int open(const char *pathname, int flags, ...)
3094 va_start(ap, flags);
3095 fd = swrap_vopen(pathname, flags, ap);
3101 /****************************************************************************
3103 ***************************************************************************/
3105 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3107 struct socket_info *si = find_socket_info(s);
3111 return libc_getpeername(s, name, addrlen);
3120 len = MIN(*addrlen, si->peername_len);
3125 memcpy(name, si->peername, len);
3126 *addrlen = si->peername_len;
3131 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3132 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3134 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3137 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3140 /****************************************************************************
3142 ***************************************************************************/
3144 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3146 struct socket_info *si = find_socket_info(s);
3150 return libc_getsockname(s, name, addrlen);
3153 len = MIN(*addrlen, si->myname_len);
3158 memcpy(name, si->myname, len);
3159 *addrlen = si->myname_len;
3164 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3165 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3167 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3170 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3173 /****************************************************************************
3175 ***************************************************************************/
3178 # ifdef SO_PROTOTYPE /* The Solaris name */
3179 # define SO_PROTOCOL SO_PROTOTYPE
3180 # endif /* SO_PROTOTYPE */
3181 #endif /* SO_PROTOCOL */
3183 static int swrap_getsockopt(int s, int level, int optname,
3184 void *optval, socklen_t *optlen)
3186 struct socket_info *si = find_socket_info(s);
3189 return libc_getsockopt(s,
3196 if (level == SOL_SOCKET) {
3200 if (optval == NULL || optlen == NULL ||
3201 *optlen < (socklen_t)sizeof(int)) {
3206 *optlen = sizeof(int);
3207 *(int *)optval = si->family;
3209 #endif /* SO_DOMAIN */
3213 if (optval == NULL || optlen == NULL ||
3214 *optlen < (socklen_t)sizeof(int)) {
3219 *optlen = sizeof(int);
3220 *(int *)optval = si->protocol;
3222 #endif /* SO_PROTOCOL */
3224 if (optval == NULL || optlen == NULL ||
3225 *optlen < (socklen_t)sizeof(int)) {
3230 *optlen = sizeof(int);
3231 *(int *)optval = si->type;
3234 return libc_getsockopt(s,
3242 errno = ENOPROTOOPT;
3246 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3247 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3249 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3252 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3255 /****************************************************************************
3257 ***************************************************************************/
3259 static int swrap_setsockopt(int s, int level, int optname,
3260 const void *optval, socklen_t optlen)
3262 struct socket_info *si = find_socket_info(s);
3265 return libc_setsockopt(s,
3272 if (level == SOL_SOCKET) {
3273 return libc_setsockopt(s,
3280 switch (si->family) {
3282 if (level == IPPROTO_IP) {
3284 if (optname == IP_PKTINFO) {
3285 si->pktinfo = AF_INET;
3287 #endif /* IP_PKTINFO */
3292 if (level == IPPROTO_IPV6) {
3293 #ifdef IPV6_RECVPKTINFO
3294 if (optname == IPV6_RECVPKTINFO) {
3295 si->pktinfo = AF_INET6;
3297 #endif /* IPV6_PKTINFO */
3302 errno = ENOPROTOOPT;
3307 int setsockopt(int s, int level, int optname,
3308 const void *optval, socklen_t optlen)
3310 return swrap_setsockopt(s, level, optname, optval, optlen);
3313 /****************************************************************************
3315 ***************************************************************************/
3317 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3319 struct socket_info *si = find_socket_info(s);
3325 return libc_vioctl(s, r, va);
3330 rc = libc_vioctl(s, r, va);
3334 value = *((int *)va_arg(ap, int *));
3336 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3337 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3338 } else if (value == 0) { /* END OF FILE */
3339 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3349 #ifdef HAVE_IOCTL_INT
3350 int ioctl(int s, int r, ...)
3352 int ioctl(int s, unsigned long int r, ...)
3360 rc = swrap_vioctl(s, (unsigned long int) r, va);
3371 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3374 # ifdef _ALIGN /* BSD */
3375 #define CMSG_ALIGN _ALIGN
3377 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3378 # endif /* _ALIGN */
3379 #endif /* CMSG_ALIGN */
3382 * @brief Add a cmsghdr to a msghdr.
3384 * This is an function to add any type of cmsghdr. It will operate on the
3385 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3386 * the buffer position after the added cmsg element. Hence, this function is
3387 * intended to be used with an intermediate msghdr and not on the original
3388 * one handed in by the client.
3390 * @param[in] msg The msghdr to which to add the cmsg.
3392 * @param[in] level The cmsg level to set.
3394 * @param[in] type The cmsg type to set.
3396 * @param[in] data The cmsg data to set.
3398 * @param[in] len the length of the data to set.
3400 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3406 size_t cmlen = CMSG_LEN(len);
3407 size_t cmspace = CMSG_SPACE(len);
3408 uint8_t cmbuf[cmspace];
3409 void *cast_ptr = (void *)cmbuf;
3410 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3413 memset(cmbuf, 0, cmspace);
3415 if (msg->msg_controllen < cmlen) {
3416 cmlen = msg->msg_controllen;
3417 msg->msg_flags |= MSG_CTRUNC;
3420 if (msg->msg_controllen < cmspace) {
3421 cmspace = msg->msg_controllen;
3425 * We copy the full input data into an intermediate cmsghdr first
3426 * in order to more easily cope with truncation.
3428 cm->cmsg_len = cmlen;
3429 cm->cmsg_level = level;
3430 cm->cmsg_type = type;
3431 memcpy(CMSG_DATA(cm), data, len);
3434 * We now copy the possibly truncated buffer.
3435 * We copy cmlen bytes, but consume cmspace bytes,
3436 * leaving the possible padding uninitialiazed.
3438 p = (uint8_t *)msg->msg_control;
3439 memcpy(p, cm, cmlen);
3441 msg->msg_control = p;
3442 msg->msg_controllen -= cmspace;
3447 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3450 /* Add packet info */
3451 switch (si->pktinfo) {
3452 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3454 struct sockaddr_in *sin;
3455 #if defined(HAVE_STRUCT_IN_PKTINFO)
3456 struct in_pktinfo pkt;
3457 #elif defined(IP_RECVDSTADDR)
3461 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3462 sin = (struct sockaddr_in*)si->bindname;
3464 if (si->myname_len != sizeof(struct sockaddr_in)) {
3467 sin = (struct sockaddr_in*)si->myname;
3472 #if defined(HAVE_STRUCT_IN_PKTINFO)
3473 pkt.ipi_ifindex = socket_wrapper_default_iface();
3474 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3475 #elif defined(IP_RECVDSTADDR)
3476 pkt = sin->sin_addr;
3479 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3484 #endif /* IP_PKTINFO */
3485 #if defined(HAVE_IPV6)
3487 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3488 struct sockaddr_in6 *sin6;
3489 struct in6_pktinfo pkt6;
3491 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3492 sin6 = (struct sockaddr_in6*)si->bindname;
3494 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3497 sin6 = (struct sockaddr_in6*)si->myname;
3502 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3503 pkt6.ipi6_addr = sin6->sin6_addr;
3505 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3506 &pkt6, sizeof(pkt6));
3507 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3511 #endif /* IPV6_PKTINFO */
3519 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3520 struct msghdr *omsg)
3524 if (si->pktinfo > 0) {
3525 rc = swrap_msghdr_add_pktinfo(si, omsg);
3531 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3533 size_t *cm_data_space);
3534 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3536 size_t *cm_data_space);
3538 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3540 size_t *cm_data_space) {
3541 struct cmsghdr *cmsg;
3545 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3549 for (cmsg = CMSG_FIRSTHDR(msg);
3551 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3552 switch (cmsg->cmsg_level) {
3554 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3559 rc = swrap_sendmsg_copy_cmsg(cmsg,
3569 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3571 size_t *cm_data_space)
3578 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3580 p = realloc((*cm_data), cmspace);
3586 p = (*cm_data) + (*cm_data_space);
3587 *cm_data_space = cmspace;
3589 memcpy(p, cmsg, cmsg->cmsg_len);
3594 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3596 size_t *cm_data_space);
3599 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3601 size_t *cm_data_space)
3605 switch(cmsg->cmsg_type) {
3608 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3615 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3627 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3629 size_t *cm_data_space)
3631 (void)cmsg; /* unused */
3632 (void)cm_data; /* unused */
3633 (void)cm_data_space; /* unused */
3636 * Passing a IP pktinfo to a unix socket might be rejected by the
3637 * Kernel, at least on FreeBSD. So skip this cmsg.
3641 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3643 static ssize_t swrap_sendmsg_before(int fd,
3644 struct socket_info *si,
3646 struct iovec *tmp_iov,
3647 struct sockaddr_un *tmp_un,
3648 const struct sockaddr_un **to_un,
3649 const struct sockaddr **to,
3667 if (!si->connected) {
3672 if (msg->msg_iovlen == 0) {
3676 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3678 nlen = len + msg->msg_iov[i].iov_len;
3679 if (nlen > SOCKET_MAX_PACKET) {
3683 msg->msg_iovlen = i;
3684 if (msg->msg_iovlen == 0) {
3685 *tmp_iov = msg->msg_iov[0];
3686 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3687 msg->msg_iov = tmp_iov;
3688 msg->msg_iovlen = 1;
3693 if (si->connected) {
3694 if (msg->msg_name) {
3699 const struct sockaddr *msg_name;
3700 msg_name = (const struct sockaddr *)msg->msg_name;
3702 if (msg_name == NULL) {
3708 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3710 if (ret == -1) return -1;
3718 msg->msg_name = tmp_un;
3719 msg->msg_namelen = sizeof(*tmp_un);
3722 if (si->bound == 0) {
3723 ret = swrap_auto_bind(fd, si, si->family);
3725 if (errno == ENOTSOCK) {
3726 swrap_remove_stale(fd);
3729 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3735 if (!si->defer_connect) {
3739 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3741 if (ret == -1) return -1;
3743 ret = libc_connect(fd,
3744 (struct sockaddr *)(void *)tmp_un,
3747 /* to give better errors */
3748 if (ret == -1 && errno == ENOENT) {
3749 errno = EHOSTUNREACH;
3756 si->defer_connect = 0;
3759 errno = EHOSTUNREACH;
3763 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3764 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3765 uint8_t *cmbuf = NULL;
3768 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3775 msg->msg_controllen = 0;
3776 msg->msg_control = NULL;
3777 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3778 memcpy(msg->msg_control, cmbuf, cmlen);
3779 msg->msg_controllen = cmlen;
3788 static void swrap_sendmsg_after(int fd,
3789 struct socket_info *si,
3791 const struct sockaddr *to,
3794 int saved_errno = errno;
3801 /* to give better errors */
3803 if (saved_errno == ENOENT) {
3804 saved_errno = EHOSTUNREACH;
3805 } else if (saved_errno == ENOTSOCK) {
3806 /* If the fd is not a socket, remove it */
3807 swrap_remove_stale(fd);
3811 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3812 avail += msg->msg_iov[i].iov_len;
3816 remain = MIN(80, avail);
3821 /* we capture it as one single packet */
3822 buf = (uint8_t *)malloc(remain);
3824 /* we just not capture the packet */
3825 errno = saved_errno;
3829 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3830 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3832 msg->msg_iov[i].iov_base,
3835 remain -= this_time;
3842 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3843 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3845 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3850 if (si->connected) {
3854 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3855 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3857 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3863 errno = saved_errno;
3866 static int swrap_recvmsg_before(int fd,
3867 struct socket_info *si,
3869 struct iovec *tmp_iov)
3874 (void)fd; /* unused */
3878 if (!si->connected) {
3883 if (msg->msg_iovlen == 0) {
3887 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3889 nlen = len + msg->msg_iov[i].iov_len;
3890 if (nlen > SOCKET_MAX_PACKET) {
3894 msg->msg_iovlen = i;
3895 if (msg->msg_iovlen == 0) {
3896 *tmp_iov = msg->msg_iov[0];
3897 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3898 msg->msg_iov = tmp_iov;
3899 msg->msg_iovlen = 1;
3904 if (msg->msg_name == NULL) {
3909 if (msg->msg_iovlen == 0) {
3913 if (si->bound == 0) {
3914 ret = swrap_auto_bind(fd, si, si->family);
3917 * When attempting to read or write to a
3918 * descriptor, if an underlying autobind fails
3919 * because it's not a socket, stop intercepting
3920 * uses of that descriptor.
3922 if (errno == ENOTSOCK) {
3923 swrap_remove_stale(fd);
3926 SWRAP_LOG(SWRAP_LOG_ERROR,
3927 "swrap_recvmsg_before failed");
3934 errno = EHOSTUNREACH;
3941 static int swrap_recvmsg_after(int fd,
3942 struct socket_info *si,
3944 const struct sockaddr_un *un_addr,
3945 socklen_t un_addrlen,
3948 int saved_errno = errno;
3950 uint8_t *buf = NULL;
3956 /* to give better errors */
3958 if (saved_errno == ENOENT) {
3959 saved_errno = EHOSTUNREACH;
3960 } else if (saved_errno == ENOTSOCK) {
3961 /* If the fd is not a socket, remove it */
3962 swrap_remove_stale(fd);
3966 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3967 avail += msg->msg_iov[i].iov_len;
3976 remain = MIN(80, avail);
3981 /* we capture it as one single packet */
3982 buf = (uint8_t *)malloc(remain);
3984 /* we just not capture the packet */
3985 errno = saved_errno;
3989 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3990 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3992 msg->msg_iov[i].iov_base,
3995 remain -= this_time;
4000 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4001 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4002 } else if (ret == 0) { /* END OF FILE */
4003 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4004 } else if (ret > 0) {
4005 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4014 if (un_addr != NULL) {
4015 rc = sockaddr_convert_from_un(si,
4025 swrap_dump_packet(si,
4031 swrap_dump_packet(si,
4044 errno = saved_errno;
4046 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4048 msg->msg_controllen > 0 &&
4049 msg->msg_control != NULL) {
4050 rc = swrap_msghdr_add_socket_info(si, msg);
4060 /****************************************************************************
4062 ***************************************************************************/
4064 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4065 struct sockaddr *from, socklen_t *fromlen)
4067 struct swrap_address from_addr = {
4068 .sa_socklen = sizeof(struct sockaddr_un),
4071 struct socket_info *si = find_socket_info(s);
4072 struct swrap_address saddr = {
4073 .sa_socklen = sizeof(struct sockaddr_storage),
4080 return libc_recvfrom(s,
4092 if (from != NULL && fromlen != NULL) {
4093 msg.msg_name = from; /* optional address */
4094 msg.msg_namelen = *fromlen; /* size of address */
4096 msg.msg_name = &saddr.sa.s; /* optional address */
4097 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4099 msg.msg_iov = &tmp; /* scatter/gather array */
4100 msg.msg_iovlen = 1; /* # elements in msg_iov */
4101 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4102 msg.msg_control = NULL; /* ancillary data, see below */
4103 msg.msg_controllen = 0; /* ancillary data buffer len */
4104 msg.msg_flags = 0; /* flags on received message */
4107 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4112 buf = msg.msg_iov[0].iov_base;
4113 len = msg.msg_iov[0].iov_len;
4115 ret = libc_recvfrom(s,
4120 &from_addr.sa_socklen);
4125 tret = swrap_recvmsg_after(s,
4129 from_addr.sa_socklen,
4135 if (from != NULL && fromlen != NULL) {
4136 *fromlen = msg.msg_namelen;
4142 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4143 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4144 struct sockaddr *from, Psocklen_t fromlen)
4146 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4147 struct sockaddr *from, socklen_t *fromlen)
4150 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4153 /****************************************************************************
4155 ***************************************************************************/
4157 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4158 const struct sockaddr *to, socklen_t tolen)
4162 struct swrap_address un_addr = {
4163 .sa_socklen = sizeof(struct sockaddr_un),
4165 const struct sockaddr_un *to_un = NULL;
4168 struct socket_info *si = find_socket_info(s);
4172 return libc_sendto(s, buf, len, flags, to, tolen);
4175 tmp.iov_base = discard_const_p(char, buf);
4179 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4180 msg.msg_namelen = tolen; /* size of address */
4181 msg.msg_iov = &tmp; /* scatter/gather array */
4182 msg.msg_iovlen = 1; /* # elements in msg_iov */
4183 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4184 msg.msg_control = NULL; /* ancillary data, see below */
4185 msg.msg_controllen = 0; /* ancillary data buffer len */
4186 msg.msg_flags = 0; /* flags on received message */
4189 rc = swrap_sendmsg_before(s,
4201 buf = msg.msg_iov[0].iov_base;
4202 len = msg.msg_iov[0].iov_len;
4207 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4210 type = SOCKET_TYPE_CHAR_UDP;
4212 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4213 snprintf(un_addr.sa.un.sun_path,
4214 sizeof(un_addr.sa.un.sun_path),
4216 socket_wrapper_dir(), type, iface, prt);
4217 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4219 /* ignore the any errors in broadcast sends */
4225 un_addr.sa_socklen);
4228 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4233 ret = libc_sendto(s,
4237 (struct sockaddr *)msg.msg_name,
4240 swrap_sendmsg_after(s, si, &msg, to, ret);
4245 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4246 const struct sockaddr *to, socklen_t tolen)
4248 return swrap_sendto(s, buf, len, flags, to, tolen);
4251 /****************************************************************************
4253 ***************************************************************************/
4255 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4257 struct socket_info *si;
4259 struct swrap_address saddr = {
4260 .sa_socklen = sizeof(struct sockaddr_storage),
4266 si = find_socket_info(s);
4268 return libc_recv(s, buf, len, flags);
4275 msg.msg_name = &saddr.sa.s; /* optional address */
4276 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4277 msg.msg_iov = &tmp; /* scatter/gather array */
4278 msg.msg_iovlen = 1; /* # elements in msg_iov */
4279 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4280 msg.msg_control = NULL; /* ancillary data, see below */
4281 msg.msg_controllen = 0; /* ancillary data buffer len */
4282 msg.msg_flags = 0; /* flags on received message */
4285 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4290 buf = msg.msg_iov[0].iov_base;
4291 len = msg.msg_iov[0].iov_len;
4293 ret = libc_recv(s, buf, len, flags);
4295 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4303 ssize_t recv(int s, void *buf, size_t len, int flags)
4305 return swrap_recv(s, buf, len, flags);
4308 /****************************************************************************
4310 ***************************************************************************/
4312 static ssize_t swrap_read(int s, void *buf, size_t len)
4314 struct socket_info *si;
4317 struct swrap_address saddr = {
4318 .sa_socklen = sizeof(struct sockaddr_storage),
4323 si = find_socket_info(s);
4325 return libc_read(s, buf, len);
4332 msg.msg_name = &saddr.sa.ss; /* optional address */
4333 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4334 msg.msg_iov = &tmp; /* scatter/gather array */
4335 msg.msg_iovlen = 1; /* # elements in msg_iov */
4336 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4337 msg.msg_control = NULL; /* ancillary data, see below */
4338 msg.msg_controllen = 0; /* ancillary data buffer len */
4339 msg.msg_flags = 0; /* flags on received message */
4342 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4344 if (tret == -ENOTSOCK) {
4345 return libc_read(s, buf, len);
4350 buf = msg.msg_iov[0].iov_base;
4351 len = msg.msg_iov[0].iov_len;
4353 ret = libc_read(s, buf, len);
4355 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4363 ssize_t read(int s, void *buf, size_t len)
4365 return swrap_read(s, buf, len);
4368 /****************************************************************************
4370 ***************************************************************************/
4372 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4376 struct sockaddr_un un_addr;
4379 struct socket_info *si = find_socket_info(s);
4382 return libc_send(s, buf, len, flags);
4385 tmp.iov_base = discard_const_p(char, buf);
4389 msg.msg_name = NULL; /* optional address */
4390 msg.msg_namelen = 0; /* size of address */
4391 msg.msg_iov = &tmp; /* scatter/gather array */
4392 msg.msg_iovlen = 1; /* # elements in msg_iov */
4393 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4394 msg.msg_control = NULL; /* ancillary data, see below */
4395 msg.msg_controllen = 0; /* ancillary data buffer len */
4396 msg.msg_flags = 0; /* flags on received message */
4399 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4404 buf = msg.msg_iov[0].iov_base;
4405 len = msg.msg_iov[0].iov_len;
4407 ret = libc_send(s, buf, len, flags);
4409 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4414 ssize_t send(int s, const void *buf, size_t len, int flags)
4416 return swrap_send(s, buf, len, flags);
4419 /****************************************************************************
4421 ***************************************************************************/
4423 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4425 struct swrap_address from_addr = {
4426 .sa_socklen = sizeof(struct sockaddr_un),
4428 struct socket_info *si;
4431 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4432 size_t msg_ctrllen_filled;
4433 size_t msg_ctrllen_left;
4439 si = find_socket_info(s);
4441 return libc_recvmsg(s, omsg, flags);
4444 tmp.iov_base = NULL;
4448 msg.msg_name = &from_addr.sa; /* optional address */
4449 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4450 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4451 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4452 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4453 msg_ctrllen_filled = 0;
4454 msg_ctrllen_left = omsg->msg_controllen;
4456 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4457 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4458 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4461 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4466 ret = libc_recvmsg(s, &msg, flags);
4468 msg.msg_name = omsg->msg_name;
4469 msg.msg_namelen = omsg->msg_namelen;
4471 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4472 msg_ctrllen_filled += msg.msg_controllen;
4473 msg_ctrllen_left -= msg.msg_controllen;
4475 if (omsg->msg_control != NULL) {
4478 p = omsg->msg_control;
4479 p += msg_ctrllen_filled;
4481 msg.msg_control = p;
4482 msg.msg_controllen = msg_ctrllen_left;
4484 msg.msg_control = NULL;
4485 msg.msg_controllen = 0;
4489 rc = swrap_recvmsg_after(s,
4493 from_addr.sa_socklen,
4499 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4500 if (omsg->msg_control != NULL) {
4501 /* msg.msg_controllen = space left */
4502 msg_ctrllen_left = msg.msg_controllen;
4503 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4506 /* Update the original message length */
4507 omsg->msg_controllen = msg_ctrllen_filled;
4508 omsg->msg_flags = msg.msg_flags;
4510 omsg->msg_iovlen = msg.msg_iovlen;
4515 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4517 return swrap_recvmsg(sockfd, msg, flags);
4520 /****************************************************************************
4522 ***************************************************************************/
4524 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4528 struct sockaddr_un un_addr;
4529 const struct sockaddr_un *to_un = NULL;
4530 const struct sockaddr *to = NULL;
4533 struct socket_info *si = find_socket_info(s);
4537 return libc_sendmsg(s, omsg, flags);
4540 ZERO_STRUCT(un_addr);
4542 tmp.iov_base = NULL;
4546 msg.msg_name = omsg->msg_name; /* optional address */
4547 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4548 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4549 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4550 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4551 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4552 /* omsg is a const so use a local buffer for modifications */
4553 uint8_t cmbuf[omsg->msg_controllen];
4555 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4557 msg.msg_control = cmbuf; /* ancillary data, see below */
4558 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4560 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4563 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4571 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4579 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4580 avail += msg.msg_iov[i].iov_len;
4586 /* we capture it as one single packet */
4587 buf = (uint8_t *)malloc(remain);
4592 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4593 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4595 msg.msg_iov[i].iov_base,
4598 remain -= this_time;
4601 type = SOCKET_TYPE_CHAR_UDP;
4603 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4604 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4605 socket_wrapper_dir(), type, iface, prt);
4606 if (stat(un_addr.sun_path, &st) != 0) continue;
4608 msg.msg_name = &un_addr; /* optional address */
4609 msg.msg_namelen = sizeof(un_addr); /* size of address */
4611 /* ignore the any errors in broadcast sends */
4612 libc_sendmsg(s, &msg, flags);
4615 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4621 ret = libc_sendmsg(s, &msg, flags);
4623 swrap_sendmsg_after(s, si, &msg, to, ret);
4628 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4630 return swrap_sendmsg(s, omsg, flags);
4633 /****************************************************************************
4635 ***************************************************************************/
4637 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4639 struct socket_info *si;
4642 struct swrap_address saddr = {
4643 .sa_socklen = sizeof(struct sockaddr_storage)
4648 si = find_socket_info(s);
4650 return libc_readv(s, vector, count);
4653 tmp.iov_base = NULL;
4657 msg.msg_name = &saddr.sa.s; /* optional address */
4658 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4659 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4660 msg.msg_iovlen = count; /* # elements in msg_iov */
4661 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4662 msg.msg_control = NULL; /* ancillary data, see below */
4663 msg.msg_controllen = 0; /* ancillary data buffer len */
4664 msg.msg_flags = 0; /* flags on received message */
4667 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4669 if (rc == -ENOTSOCK) {
4670 return libc_readv(s, vector, count);
4675 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4677 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4685 ssize_t readv(int s, const struct iovec *vector, int count)
4687 return swrap_readv(s, vector, count);
4690 /****************************************************************************
4692 ***************************************************************************/
4694 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4698 struct sockaddr_un un_addr;
4701 struct socket_info *si = find_socket_info(s);
4704 return libc_writev(s, vector, count);
4707 tmp.iov_base = NULL;
4711 msg.msg_name = NULL; /* optional address */
4712 msg.msg_namelen = 0; /* size of address */
4713 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4714 msg.msg_iovlen = count; /* # elements in msg_iov */
4715 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4716 msg.msg_control = NULL; /* ancillary data, see below */
4717 msg.msg_controllen = 0; /* ancillary data buffer len */
4718 msg.msg_flags = 0; /* flags on received message */
4721 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4723 if (rc == -ENOTSOCK) {
4724 return libc_readv(s, vector, count);
4729 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4731 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4736 ssize_t writev(int s, const struct iovec *vector, int count)
4738 return swrap_writev(s, vector, count);
4741 /****************************
4743 ***************************/
4745 static int swrap_close(int fd)
4747 struct socket_info *si = find_socket_info(fd);
4748 struct socket_info_fd *fi;
4752 return libc_close(fd);
4755 for (fi = si->fds; fi; fi = fi->next) {
4757 SWRAP_DLIST_REMOVE(si->fds, fi);
4764 /* there are still references left */
4765 return libc_close(fd);
4768 SWRAP_DLIST_REMOVE(sockets, si);
4770 if (si->myname && si->peername) {
4771 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4774 ret = libc_close(fd);
4776 if (si->myname && si->peername) {
4777 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4778 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4781 if (si->bindname != NULL) {
4785 if (si->myname) free(si->myname);
4786 if (si->peername) free(si->peername);
4788 unlink(si->tmp_path);
4798 return swrap_close(fd);
4801 /****************************
4803 ***************************/
4805 static int swrap_dup(int fd)
4807 struct socket_info *si;
4808 struct socket_info_fd *fi;
4810 si = find_socket_info(fd);
4813 return libc_dup(fd);
4816 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4822 fi->fd = libc_dup(fd);
4824 int saved_errno = errno;
4826 errno = saved_errno;
4830 /* Make sure we don't have an entry for the fd */
4831 swrap_remove_stale(fi->fd);
4833 SWRAP_DLIST_ADD(si->fds, fi);
4839 return swrap_dup(fd);
4842 /****************************
4844 ***************************/
4846 static int swrap_dup2(int fd, int newfd)
4848 struct socket_info *si;
4849 struct socket_info_fd *fi;
4851 si = find_socket_info(fd);
4854 return libc_dup2(fd, newfd);
4857 if (find_socket_info(newfd)) {
4858 /* dup2() does an implicit close of newfd, which we
4859 * need to emulate */
4863 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4869 fi->fd = libc_dup2(fd, newfd);
4871 int saved_errno = errno;
4873 errno = saved_errno;
4877 /* Make sure we don't have an entry for the fd */
4878 swrap_remove_stale(fi->fd);
4880 SWRAP_DLIST_ADD(si->fds, fi);
4884 int dup2(int fd, int newfd)
4886 return swrap_dup2(fd, newfd);
4889 /****************************
4891 ***************************/
4894 static int swrap_eventfd(int count, int flags)
4898 fd = libc_eventfd(count, flags);
4900 swrap_remove_stale(fd);
4906 int eventfd(int count, int flags)
4908 return swrap_eventfd(count, flags);
4912 /****************************
4914 ***************************/
4917 * This function is called when the library is unloaded and makes sure that
4918 * sockets get closed and the unix file for the socket are unlinked.
4920 void swrap_destructor(void)
4922 struct socket_info *s = sockets;
4925 struct socket_info_fd *f = s->fds;