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 *socket_wrapper_pcap_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_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_packet_init(&tv, src_addr, dest_addr, si->type,
2197 (const uint8_t *)buf, len,
2198 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2202 static void swrap_dump_packet(struct socket_info *si,
2203 const struct sockaddr *addr,
2204 enum swrap_packet_type type,
2205 const void *buf, size_t len)
2207 const char *file_name;
2209 size_t packet_len = 0;
2212 file_name = socket_wrapper_pcap_file();
2217 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2222 fd = swrap_get_pcap_fd(file_name);
2224 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2233 /****************************************************************************
2235 ***************************************************************************/
2237 #ifdef HAVE_SIGNALFD
2238 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2242 rc = libc_signalfd(fd, mask, flags);
2244 swrap_remove_stale(fd);
2250 int signalfd(int fd, const sigset_t *mask, int flags)
2252 return swrap_signalfd(fd, mask, flags);
2256 /****************************************************************************
2258 ***************************************************************************/
2260 static int swrap_socket(int family, int type, int protocol)
2262 struct socket_info *si;
2263 struct socket_info_fd *fi;
2265 int real_type = type;
2268 * Remove possible addition flags passed to socket() so
2269 * do not fail checking the type.
2270 * See https://lwn.net/Articles/281965/
2273 real_type &= ~SOCK_CLOEXEC;
2275 #ifdef SOCK_NONBLOCK
2276 real_type &= ~SOCK_NONBLOCK;
2279 if (!socket_wrapper_enabled()) {
2280 return libc_socket(family, type, protocol);
2290 return libc_socket(family, type, protocol);
2292 errno = EAFNOSUPPORT;
2296 switch (real_type) {
2302 errno = EPROTONOSUPPORT;
2310 if (real_type == SOCK_STREAM) {
2315 if (real_type == SOCK_DGRAM) {
2320 errno = EPROTONOSUPPORT;
2325 * We must call libc_socket with type, from the caller, not the version
2326 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2328 fd = libc_socket(AF_UNIX, type, 0);
2334 /* Check if we have a stale fd and remove it */
2335 si = find_socket_info(fd);
2337 swrap_remove_stale(fd);
2340 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2341 memset(si, 0, sizeof(struct socket_info));
2347 si->family = family;
2349 /* however, the rest of the socket_wrapper code expects just
2350 * the type, not the flags */
2351 si->type = real_type;
2352 si->protocol = protocol;
2355 * Setup myname so getsockname() can succeed to find out the socket
2358 switch(si->family) {
2360 struct sockaddr_in sin = {
2361 .sin_family = AF_INET,
2364 si->myname_len = sizeof(struct sockaddr_in);
2365 si->myname = sockaddr_dup(&sin, si->myname_len);
2369 struct sockaddr_in6 sin6 = {
2370 .sin6_family = AF_INET6,
2373 si->myname_len = sizeof(struct sockaddr_in6);
2374 si->myname = sockaddr_dup(&sin6, si->myname_len);
2383 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2385 if (si->myname != NULL) {
2395 SWRAP_DLIST_ADD(si->fds, fi);
2396 SWRAP_DLIST_ADD(sockets, si);
2401 int socket(int family, int type, int protocol)
2403 return swrap_socket(family, type, protocol);
2406 /****************************************************************************
2408 ***************************************************************************/
2410 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2414 rc = libc_socketpair(family, type, protocol, sv);
2416 swrap_remove_stale(sv[0]);
2417 swrap_remove_stale(sv[1]);
2423 int socketpair(int family, int type, int protocol, int sv[2])
2425 return swrap_socketpair(family, type, protocol, sv);
2428 /****************************************************************************
2430 ***************************************************************************/
2432 #ifdef HAVE_TIMERFD_CREATE
2433 static int swrap_timerfd_create(int clockid, int flags)
2437 fd = libc_timerfd_create(clockid, flags);
2439 swrap_remove_stale(fd);
2445 int timerfd_create(int clockid, int flags)
2447 return swrap_timerfd_create(clockid, flags);
2451 /****************************************************************************
2453 ***************************************************************************/
2455 static int swrap_pipe(int pipefd[2])
2459 rc = libc_pipe(pipefd);
2461 swrap_remove_stale(pipefd[0]);
2462 swrap_remove_stale(pipefd[1]);
2468 int pipe(int pipefd[2])
2470 return swrap_pipe(pipefd);
2473 /****************************************************************************
2475 ***************************************************************************/
2477 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2479 struct socket_info *parent_si, *child_si;
2480 struct socket_info_fd *child_fi;
2482 struct swrap_address un_addr = {
2483 .sa_socklen = sizeof(struct sockaddr_un),
2485 struct swrap_address un_my_addr = {
2486 .sa_socklen = sizeof(struct sockaddr_un),
2488 struct sockaddr *my_addr;
2489 socklen_t my_addrlen, len;
2492 parent_si = find_socket_info(s);
2494 return libc_accept(s, addr, addrlen);
2498 * assume out sockaddr have the same size as the in parent
2501 my_addrlen = socket_length(parent_si->family);
2502 if (my_addrlen <= 0) {
2507 my_addr = (struct sockaddr *)malloc(my_addrlen);
2508 if (my_addr == NULL) {
2512 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2514 if (errno == ENOTSOCK) {
2515 /* Remove stale fds */
2516 swrap_remove_stale(s);
2525 ret = sockaddr_convert_from_un(parent_si,
2537 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2538 memset(child_si, 0, sizeof(struct socket_info));
2540 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2541 if (child_fi == NULL) {
2551 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2553 child_si->family = parent_si->family;
2554 child_si->type = parent_si->type;
2555 child_si->protocol = parent_si->protocol;
2556 child_si->bound = 1;
2557 child_si->is_server = 1;
2558 child_si->connected = 1;
2560 child_si->peername_len = len;
2561 child_si->peername = sockaddr_dup(my_addr, len);
2563 if (addr != NULL && addrlen != NULL) {
2564 size_t copy_len = MIN(*addrlen, len);
2566 memcpy(addr, my_addr, copy_len);
2571 ret = libc_getsockname(fd,
2573 &un_my_addr.sa_socklen);
2583 ret = sockaddr_convert_from_un(child_si,
2585 un_my_addr.sa_socklen,
2597 SWRAP_LOG(SWRAP_LOG_TRACE,
2598 "accept() path=%s, fd=%d",
2599 un_my_addr.sa.un.sun_path, s);
2601 child_si->myname_len = len;
2602 child_si->myname = sockaddr_dup(my_addr, len);
2605 SWRAP_DLIST_ADD(sockets, child_si);
2608 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2609 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2610 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2616 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2617 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2619 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2622 return swrap_accept(s, addr, (socklen_t *)addrlen);
2625 static int autobind_start_init;
2626 static int autobind_start;
2628 /* using sendto() or connect() on an unbound socket would give the
2629 recipient no way to reply, as unlike UDP and TCP, a unix domain
2630 socket can't auto-assign ephemeral port numbers, so we need to
2632 Note: this might change the family from ipv6 to ipv4
2634 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2636 struct swrap_address un_addr = {
2637 .sa_socklen = sizeof(struct sockaddr_un),
2645 if (autobind_start_init != 1) {
2646 autobind_start_init = 1;
2647 autobind_start = getpid();
2648 autobind_start %= 50000;
2649 autobind_start += 10000;
2652 un_addr.sa.un.sun_family = AF_UNIX;
2656 struct sockaddr_in in;
2660 type = SOCKET_TYPE_CHAR_TCP;
2663 type = SOCKET_TYPE_CHAR_UDP;
2666 errno = ESOCKTNOSUPPORT;
2670 memset(&in, 0, sizeof(in));
2671 in.sin_family = AF_INET;
2672 in.sin_addr.s_addr = htonl(127<<24 |
2673 socket_wrapper_default_iface());
2676 si->myname_len = sizeof(in);
2677 si->myname = sockaddr_dup(&in, si->myname_len);
2682 struct sockaddr_in6 in6;
2684 if (si->family != family) {
2685 errno = ENETUNREACH;
2691 type = SOCKET_TYPE_CHAR_TCP_V6;
2694 type = SOCKET_TYPE_CHAR_UDP_V6;
2697 errno = ESOCKTNOSUPPORT;
2701 memset(&in6, 0, sizeof(in6));
2702 in6.sin6_family = AF_INET6;
2703 in6.sin6_addr = *swrap_ipv6();
2704 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2706 si->myname_len = sizeof(in6);
2707 si->myname = sockaddr_dup(&in6, si->myname_len);
2712 errno = ESOCKTNOSUPPORT;
2716 if (autobind_start > 60000) {
2717 autobind_start = 10000;
2720 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2721 port = autobind_start + i;
2722 snprintf(un_addr.sa.un.sun_path, un_addr.sa_socklen,
2723 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2724 type, socket_wrapper_default_iface(), port);
2725 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2727 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2728 if (ret == -1) return ret;
2730 si->tmp_path = strdup(un_addr.sa.un.sun_path);
2732 autobind_start = port + 1;
2735 if (i == SOCKET_MAX_SOCKETS) {
2736 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2737 "interface "SOCKET_FORMAT,
2740 socket_wrapper_default_iface(),
2746 si->family = family;
2747 set_port(si->family, port, si->myname);
2752 /****************************************************************************
2754 ***************************************************************************/
2756 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2760 struct swrap_address un_addr = {
2761 .sa_socklen = sizeof(struct sockaddr_un),
2763 struct socket_info *si = find_socket_info(s);
2767 return libc_connect(s, serv_addr, addrlen);
2770 if (si->bound == 0) {
2771 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2772 if (ret == -1) return -1;
2775 if (si->family != serv_addr->sa_family) {
2780 ret = sockaddr_convert_to_un(si, serv_addr,
2781 addrlen, &un_addr.sa.un, 0, &bcast);
2782 if (ret == -1) return -1;
2785 errno = ENETUNREACH;
2789 if (si->type == SOCK_DGRAM) {
2790 si->defer_connect = 1;
2793 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2795 ret = libc_connect(s,
2797 un_addr.sa_socklen);
2800 SWRAP_LOG(SWRAP_LOG_TRACE,
2801 "connect() path=%s, fd=%d",
2802 un_addr.un.sun_path, s);
2805 /* to give better errors */
2806 if (ret == -1 && errno == ENOENT) {
2807 errno = EHOSTUNREACH;
2811 si->peername_len = addrlen;
2812 si->peername = sockaddr_dup(serv_addr, addrlen);
2816 * When we connect() on a socket than we have to bind the
2817 * outgoing connection on the interface we use for the
2818 * transport. We already bound it on the right interface
2819 * but here we have to update the name so getsockname()
2820 * returns correct information.
2822 if (si->bindname != NULL) {
2825 si->myname = si->bindname;
2826 si->myname_len = si->bindname_len;
2828 si->bindname = NULL;
2829 si->bindname_len = 0;
2832 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2833 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2835 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2841 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2843 return swrap_connect(s, serv_addr, addrlen);
2846 /****************************************************************************
2848 ***************************************************************************/
2850 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2853 struct swrap_address un_addr = {
2854 .sa_socklen = sizeof(struct sockaddr_un),
2856 struct socket_info *si = find_socket_info(s);
2863 return libc_bind(s, myaddr, addrlen);
2866 switch (si->family) {
2868 const struct sockaddr_in *sin;
2869 if (addrlen < sizeof(struct sockaddr_in)) {
2870 bind_error = EINVAL;
2874 sin = (const struct sockaddr_in *)myaddr;
2876 if (sin->sin_family != AF_INET) {
2877 bind_error = EAFNOSUPPORT;
2880 /* special case for AF_UNSPEC */
2881 if (sin->sin_family == AF_UNSPEC &&
2882 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2891 const struct sockaddr_in6 *sin6;
2892 if (addrlen < sizeof(struct sockaddr_in6)) {
2893 bind_error = EINVAL;
2897 sin6 = (const struct sockaddr_in6 *)myaddr;
2899 if (sin6->sin6_family != AF_INET6) {
2900 bind_error = EAFNOSUPPORT;
2907 bind_error = EINVAL;
2911 if (bind_error != 0) {
2917 in_use = check_addr_port_in_use(myaddr, addrlen);
2925 si->myname_len = addrlen;
2926 si->myname = sockaddr_dup(myaddr, addrlen);
2928 ret = sockaddr_convert_to_un(si,
2934 if (ret == -1) return -1;
2936 unlink(un_addr.sa.un.sun_path);
2938 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
2940 SWRAP_LOG(SWRAP_LOG_TRACE,
2941 "bind() path=%s, fd=%d",
2942 un_addr.sa_un.sun_path, s);
2951 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2953 return swrap_bind(s, myaddr, addrlen);
2956 /****************************************************************************
2958 ***************************************************************************/
2960 #ifdef HAVE_BINDRESVPORT
2961 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2963 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2965 struct swrap_address myaddr = {
2966 .sa_socklen = sizeof(struct sockaddr_storage),
2969 static uint16_t port;
2974 #define SWRAP_STARTPORT 600
2975 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2976 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2979 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2983 salen = myaddr.sa_socklen;
2986 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
2992 memset(&myaddr.sa.ss, 0, salen);
2997 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3000 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3002 salen = sizeof(struct sockaddr_in);
3003 sinp->sin_port = htons(port);
3007 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
3009 salen = sizeof(struct sockaddr_in6);
3010 sin6p->sin6_port = htons(port);
3014 errno = EAFNOSUPPORT;
3019 if (port > SWRAP_ENDPORT) {
3020 port = SWRAP_STARTPORT;
3023 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3024 if (rc == 0 || errno != EADDRINUSE) {
3032 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3034 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3038 /****************************************************************************
3040 ***************************************************************************/
3042 static int swrap_listen(int s, int backlog)
3045 struct socket_info *si = find_socket_info(s);
3048 return libc_listen(s, backlog);
3051 ret = libc_listen(s, backlog);
3056 int listen(int s, int backlog)
3058 return swrap_listen(s, backlog);
3061 /****************************************************************************
3063 ***************************************************************************/
3065 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3069 ret = libc_vopen(pathname, flags, ap);
3072 * There are methods for closing descriptors (libc-internal code
3073 * paths, direct syscalls) which close descriptors in ways that
3074 * we can't intercept, so try to recover when we notice that
3077 swrap_remove_stale(ret);
3082 int open(const char *pathname, int flags, ...)
3087 va_start(ap, flags);
3088 fd = swrap_vopen(pathname, flags, ap);
3094 /****************************************************************************
3096 ***************************************************************************/
3098 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3100 struct socket_info *si = find_socket_info(s);
3104 return libc_getpeername(s, name, addrlen);
3113 len = MIN(*addrlen, si->peername_len);
3118 memcpy(name, si->peername, len);
3119 *addrlen = si->peername_len;
3124 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3125 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3127 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3130 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3133 /****************************************************************************
3135 ***************************************************************************/
3137 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3139 struct socket_info *si = find_socket_info(s);
3143 return libc_getsockname(s, name, addrlen);
3146 len = MIN(*addrlen, si->myname_len);
3151 memcpy(name, si->myname, len);
3152 *addrlen = si->myname_len;
3157 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3158 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3160 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3163 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3166 /****************************************************************************
3168 ***************************************************************************/
3171 # ifdef SO_PROTOTYPE /* The Solaris name */
3172 # define SO_PROTOCOL SO_PROTOTYPE
3173 # endif /* SO_PROTOTYPE */
3174 #endif /* SO_PROTOCOL */
3176 static int swrap_getsockopt(int s, int level, int optname,
3177 void *optval, socklen_t *optlen)
3179 struct socket_info *si = find_socket_info(s);
3182 return libc_getsockopt(s,
3189 if (level == SOL_SOCKET) {
3193 if (optval == NULL || optlen == NULL ||
3194 *optlen < (socklen_t)sizeof(int)) {
3199 *optlen = sizeof(int);
3200 *(int *)optval = si->family;
3202 #endif /* SO_DOMAIN */
3206 if (optval == NULL || optlen == NULL ||
3207 *optlen < (socklen_t)sizeof(int)) {
3212 *optlen = sizeof(int);
3213 *(int *)optval = si->protocol;
3215 #endif /* SO_PROTOCOL */
3217 if (optval == NULL || optlen == NULL ||
3218 *optlen < (socklen_t)sizeof(int)) {
3223 *optlen = sizeof(int);
3224 *(int *)optval = si->type;
3227 return libc_getsockopt(s,
3235 errno = ENOPROTOOPT;
3239 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3240 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3242 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3245 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3248 /****************************************************************************
3250 ***************************************************************************/
3252 static int swrap_setsockopt(int s, int level, int optname,
3253 const void *optval, socklen_t optlen)
3255 struct socket_info *si = find_socket_info(s);
3258 return libc_setsockopt(s,
3265 if (level == SOL_SOCKET) {
3266 return libc_setsockopt(s,
3273 switch (si->family) {
3275 if (level == IPPROTO_IP) {
3277 if (optname == IP_PKTINFO) {
3278 si->pktinfo = AF_INET;
3280 #endif /* IP_PKTINFO */
3285 if (level == IPPROTO_IPV6) {
3286 #ifdef IPV6_RECVPKTINFO
3287 if (optname == IPV6_RECVPKTINFO) {
3288 si->pktinfo = AF_INET6;
3290 #endif /* IPV6_PKTINFO */
3295 errno = ENOPROTOOPT;
3300 int setsockopt(int s, int level, int optname,
3301 const void *optval, socklen_t optlen)
3303 return swrap_setsockopt(s, level, optname, optval, optlen);
3306 /****************************************************************************
3308 ***************************************************************************/
3310 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3312 struct socket_info *si = find_socket_info(s);
3318 return libc_vioctl(s, r, va);
3323 rc = libc_vioctl(s, r, va);
3327 value = *((int *)va_arg(ap, int *));
3329 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3330 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3331 } else if (value == 0) { /* END OF FILE */
3332 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3342 #ifdef HAVE_IOCTL_INT
3343 int ioctl(int s, int r, ...)
3345 int ioctl(int s, unsigned long int r, ...)
3353 rc = swrap_vioctl(s, (unsigned long int) r, va);
3364 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3367 # ifdef _ALIGN /* BSD */
3368 #define CMSG_ALIGN _ALIGN
3370 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3371 # endif /* _ALIGN */
3372 #endif /* CMSG_ALIGN */
3375 * @brief Add a cmsghdr to a msghdr.
3377 * This is an function to add any type of cmsghdr. It will operate on the
3378 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3379 * the buffer position after the added cmsg element. Hence, this function is
3380 * intended to be used with an intermediate msghdr and not on the original
3381 * one handed in by the client.
3383 * @param[in] msg The msghdr to which to add the cmsg.
3385 * @param[in] level The cmsg level to set.
3387 * @param[in] type The cmsg type to set.
3389 * @param[in] data The cmsg data to set.
3391 * @param[in] len the length of the data to set.
3393 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3399 size_t cmlen = CMSG_LEN(len);
3400 size_t cmspace = CMSG_SPACE(len);
3401 uint8_t cmbuf[cmspace];
3402 void *cast_ptr = (void *)cmbuf;
3403 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3406 memset(cmbuf, 0, cmspace);
3408 if (msg->msg_controllen < cmlen) {
3409 cmlen = msg->msg_controllen;
3410 msg->msg_flags |= MSG_CTRUNC;
3413 if (msg->msg_controllen < cmspace) {
3414 cmspace = msg->msg_controllen;
3418 * We copy the full input data into an intermediate cmsghdr first
3419 * in order to more easily cope with truncation.
3421 cm->cmsg_len = cmlen;
3422 cm->cmsg_level = level;
3423 cm->cmsg_type = type;
3424 memcpy(CMSG_DATA(cm), data, len);
3427 * We now copy the possibly truncated buffer.
3428 * We copy cmlen bytes, but consume cmspace bytes,
3429 * leaving the possible padding uninitialiazed.
3431 p = (uint8_t *)msg->msg_control;
3432 memcpy(p, cm, cmlen);
3434 msg->msg_control = p;
3435 msg->msg_controllen -= cmspace;
3440 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3443 /* Add packet info */
3444 switch (si->pktinfo) {
3445 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3447 struct sockaddr_in *sin;
3448 #if defined(HAVE_STRUCT_IN_PKTINFO)
3449 struct in_pktinfo pkt;
3450 #elif defined(IP_RECVDSTADDR)
3454 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3455 sin = (struct sockaddr_in*)si->bindname;
3457 if (si->myname_len != sizeof(struct sockaddr_in)) {
3460 sin = (struct sockaddr_in*)si->myname;
3465 #if defined(HAVE_STRUCT_IN_PKTINFO)
3466 pkt.ipi_ifindex = socket_wrapper_default_iface();
3467 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3468 #elif defined(IP_RECVDSTADDR)
3469 pkt = sin->sin_addr;
3472 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3477 #endif /* IP_PKTINFO */
3478 #if defined(HAVE_IPV6)
3480 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3481 struct sockaddr_in6 *sin6;
3482 struct in6_pktinfo pkt6;
3484 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3485 sin6 = (struct sockaddr_in6*)si->bindname;
3487 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3490 sin6 = (struct sockaddr_in6*)si->myname;
3495 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3496 pkt6.ipi6_addr = sin6->sin6_addr;
3498 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3499 &pkt6, sizeof(pkt6));
3500 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3504 #endif /* IPV6_PKTINFO */
3512 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3513 struct msghdr *omsg)
3517 if (si->pktinfo > 0) {
3518 rc = swrap_msghdr_add_pktinfo(si, omsg);
3524 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3526 size_t *cm_data_space);
3527 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3529 size_t *cm_data_space);
3531 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3533 size_t *cm_data_space) {
3534 struct cmsghdr *cmsg;
3538 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3542 for (cmsg = CMSG_FIRSTHDR(msg);
3544 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3545 switch (cmsg->cmsg_level) {
3547 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3552 rc = swrap_sendmsg_copy_cmsg(cmsg,
3562 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3564 size_t *cm_data_space)
3571 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3573 p = realloc((*cm_data), cmspace);
3579 p = (*cm_data) + (*cm_data_space);
3580 *cm_data_space = cmspace;
3582 memcpy(p, cmsg, cmsg->cmsg_len);
3587 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3589 size_t *cm_data_space);
3592 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3594 size_t *cm_data_space)
3598 switch(cmsg->cmsg_type) {
3601 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3608 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3620 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3622 size_t *cm_data_space)
3624 (void)cmsg; /* unused */
3625 (void)cm_data; /* unused */
3626 (void)cm_data_space; /* unused */
3629 * Passing a IP pktinfo to a unix socket might be rejected by the
3630 * Kernel, at least on FreeBSD. So skip this cmsg.
3634 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3636 static ssize_t swrap_sendmsg_before(int fd,
3637 struct socket_info *si,
3639 struct iovec *tmp_iov,
3640 struct sockaddr_un *tmp_un,
3641 const struct sockaddr_un **to_un,
3642 const struct sockaddr **to,
3660 if (!si->connected) {
3665 if (msg->msg_iovlen == 0) {
3669 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3671 nlen = len + msg->msg_iov[i].iov_len;
3672 if (nlen > SOCKET_MAX_PACKET) {
3676 msg->msg_iovlen = i;
3677 if (msg->msg_iovlen == 0) {
3678 *tmp_iov = msg->msg_iov[0];
3679 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3680 msg->msg_iov = tmp_iov;
3681 msg->msg_iovlen = 1;
3686 if (si->connected) {
3687 if (msg->msg_name) {
3692 const struct sockaddr *msg_name;
3693 msg_name = (const struct sockaddr *)msg->msg_name;
3695 if (msg_name == NULL) {
3701 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3703 if (ret == -1) return -1;
3711 msg->msg_name = tmp_un;
3712 msg->msg_namelen = sizeof(*tmp_un);
3715 if (si->bound == 0) {
3716 ret = swrap_auto_bind(fd, si, si->family);
3718 if (errno == ENOTSOCK) {
3719 swrap_remove_stale(fd);
3722 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3728 if (!si->defer_connect) {
3732 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3734 if (ret == -1) return -1;
3736 ret = libc_connect(fd,
3737 (struct sockaddr *)(void *)tmp_un,
3740 /* to give better errors */
3741 if (ret == -1 && errno == ENOENT) {
3742 errno = EHOSTUNREACH;
3749 si->defer_connect = 0;
3752 errno = EHOSTUNREACH;
3756 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3757 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3758 uint8_t *cmbuf = NULL;
3761 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3768 msg->msg_controllen = 0;
3769 msg->msg_control = NULL;
3770 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3771 memcpy(msg->msg_control, cmbuf, cmlen);
3772 msg->msg_controllen = cmlen;
3781 static void swrap_sendmsg_after(int fd,
3782 struct socket_info *si,
3784 const struct sockaddr *to,
3787 int saved_errno = errno;
3794 /* to give better errors */
3796 if (saved_errno == ENOENT) {
3797 saved_errno = EHOSTUNREACH;
3798 } else if (saved_errno == ENOTSOCK) {
3799 /* If the fd is not a socket, remove it */
3800 swrap_remove_stale(fd);
3804 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3805 avail += msg->msg_iov[i].iov_len;
3809 remain = MIN(80, avail);
3814 /* we capture it as one single packet */
3815 buf = (uint8_t *)malloc(remain);
3817 /* we just not capture the packet */
3818 errno = saved_errno;
3822 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3823 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3825 msg->msg_iov[i].iov_base,
3828 remain -= this_time;
3835 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3836 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3838 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3843 if (si->connected) {
3847 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3848 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3850 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3856 errno = saved_errno;
3859 static int swrap_recvmsg_before(int fd,
3860 struct socket_info *si,
3862 struct iovec *tmp_iov)
3867 (void)fd; /* unused */
3871 if (!si->connected) {
3876 if (msg->msg_iovlen == 0) {
3880 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3882 nlen = len + msg->msg_iov[i].iov_len;
3883 if (nlen > SOCKET_MAX_PACKET) {
3887 msg->msg_iovlen = i;
3888 if (msg->msg_iovlen == 0) {
3889 *tmp_iov = msg->msg_iov[0];
3890 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3891 msg->msg_iov = tmp_iov;
3892 msg->msg_iovlen = 1;
3897 if (msg->msg_name == NULL) {
3902 if (msg->msg_iovlen == 0) {
3906 if (si->bound == 0) {
3907 ret = swrap_auto_bind(fd, si, si->family);
3910 * When attempting to read or write to a
3911 * descriptor, if an underlying autobind fails
3912 * because it's not a socket, stop intercepting
3913 * uses of that descriptor.
3915 if (errno == ENOTSOCK) {
3916 swrap_remove_stale(fd);
3919 SWRAP_LOG(SWRAP_LOG_ERROR,
3920 "swrap_recvmsg_before failed");
3927 errno = EHOSTUNREACH;
3934 static int swrap_recvmsg_after(int fd,
3935 struct socket_info *si,
3937 const struct sockaddr_un *un_addr,
3938 socklen_t un_addrlen,
3941 int saved_errno = errno;
3943 uint8_t *buf = NULL;
3949 /* to give better errors */
3951 if (saved_errno == ENOENT) {
3952 saved_errno = EHOSTUNREACH;
3953 } else if (saved_errno == ENOTSOCK) {
3954 /* If the fd is not a socket, remove it */
3955 swrap_remove_stale(fd);
3959 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3960 avail += msg->msg_iov[i].iov_len;
3969 remain = MIN(80, avail);
3974 /* we capture it as one single packet */
3975 buf = (uint8_t *)malloc(remain);
3977 /* we just not capture the packet */
3978 errno = saved_errno;
3982 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3983 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3985 msg->msg_iov[i].iov_base,
3988 remain -= this_time;
3993 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3994 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3995 } else if (ret == 0) { /* END OF FILE */
3996 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3997 } else if (ret > 0) {
3998 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4007 if (un_addr != NULL) {
4008 rc = sockaddr_convert_from_un(si,
4018 swrap_dump_packet(si,
4024 swrap_dump_packet(si,
4037 errno = saved_errno;
4039 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4041 msg->msg_controllen > 0 &&
4042 msg->msg_control != NULL) {
4043 rc = swrap_msghdr_add_socket_info(si, msg);
4053 /****************************************************************************
4055 ***************************************************************************/
4057 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4058 struct sockaddr *from, socklen_t *fromlen)
4060 struct swrap_address from_addr = {
4061 .sa_socklen = sizeof(struct sockaddr_un),
4064 struct socket_info *si = find_socket_info(s);
4065 struct swrap_address saddr = {
4066 .sa_socklen = sizeof(struct sockaddr_storage),
4073 return libc_recvfrom(s,
4085 if (from != NULL && fromlen != NULL) {
4086 msg.msg_name = from; /* optional address */
4087 msg.msg_namelen = *fromlen; /* size of address */
4089 msg.msg_name = &saddr.sa.s; /* optional address */
4090 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4092 msg.msg_iov = &tmp; /* scatter/gather array */
4093 msg.msg_iovlen = 1; /* # elements in msg_iov */
4094 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4095 msg.msg_control = NULL; /* ancillary data, see below */
4096 msg.msg_controllen = 0; /* ancillary data buffer len */
4097 msg.msg_flags = 0; /* flags on received message */
4100 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4105 buf = msg.msg_iov[0].iov_base;
4106 len = msg.msg_iov[0].iov_len;
4108 ret = libc_recvfrom(s,
4113 &from_addr.sa_socklen);
4118 tret = swrap_recvmsg_after(s,
4122 from_addr.sa_socklen,
4128 if (from != NULL && fromlen != NULL) {
4129 *fromlen = msg.msg_namelen;
4135 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4136 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4137 struct sockaddr *from, Psocklen_t fromlen)
4139 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4140 struct sockaddr *from, socklen_t *fromlen)
4143 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4146 /****************************************************************************
4148 ***************************************************************************/
4150 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4151 const struct sockaddr *to, socklen_t tolen)
4155 struct swrap_address un_addr = {
4156 .sa_socklen = sizeof(struct sockaddr_un),
4158 const struct sockaddr_un *to_un = NULL;
4161 struct socket_info *si = find_socket_info(s);
4165 return libc_sendto(s, buf, len, flags, to, tolen);
4168 tmp.iov_base = discard_const_p(char, buf);
4172 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4173 msg.msg_namelen = tolen; /* size of address */
4174 msg.msg_iov = &tmp; /* scatter/gather array */
4175 msg.msg_iovlen = 1; /* # elements in msg_iov */
4176 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4177 msg.msg_control = NULL; /* ancillary data, see below */
4178 msg.msg_controllen = 0; /* ancillary data buffer len */
4179 msg.msg_flags = 0; /* flags on received message */
4182 rc = swrap_sendmsg_before(s,
4194 buf = msg.msg_iov[0].iov_base;
4195 len = msg.msg_iov[0].iov_len;
4200 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4203 type = SOCKET_TYPE_CHAR_UDP;
4205 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4206 snprintf(un_addr.sa.un.sun_path,
4207 sizeof(un_addr.sa.un.sun_path),
4209 socket_wrapper_dir(), type, iface, prt);
4210 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4212 /* ignore the any errors in broadcast sends */
4218 un_addr.sa_socklen);
4221 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4226 ret = libc_sendto(s,
4230 (struct sockaddr *)msg.msg_name,
4233 swrap_sendmsg_after(s, si, &msg, to, ret);
4238 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4239 const struct sockaddr *to, socklen_t tolen)
4241 return swrap_sendto(s, buf, len, flags, to, tolen);
4244 /****************************************************************************
4246 ***************************************************************************/
4248 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4250 struct socket_info *si;
4252 struct swrap_address saddr = {
4253 .sa_socklen = sizeof(struct sockaddr_storage),
4259 si = find_socket_info(s);
4261 return libc_recv(s, buf, len, flags);
4268 msg.msg_name = &saddr.sa.s; /* optional address */
4269 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4270 msg.msg_iov = &tmp; /* scatter/gather array */
4271 msg.msg_iovlen = 1; /* # elements in msg_iov */
4272 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4273 msg.msg_control = NULL; /* ancillary data, see below */
4274 msg.msg_controllen = 0; /* ancillary data buffer len */
4275 msg.msg_flags = 0; /* flags on received message */
4278 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4283 buf = msg.msg_iov[0].iov_base;
4284 len = msg.msg_iov[0].iov_len;
4286 ret = libc_recv(s, buf, len, flags);
4288 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4296 ssize_t recv(int s, void *buf, size_t len, int flags)
4298 return swrap_recv(s, buf, len, flags);
4301 /****************************************************************************
4303 ***************************************************************************/
4305 static ssize_t swrap_read(int s, void *buf, size_t len)
4307 struct socket_info *si;
4310 struct swrap_address saddr = {
4311 .sa_socklen = sizeof(struct sockaddr_storage),
4316 si = find_socket_info(s);
4318 return libc_read(s, buf, len);
4325 msg.msg_name = &saddr.sa.ss; /* optional address */
4326 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4327 msg.msg_iov = &tmp; /* scatter/gather array */
4328 msg.msg_iovlen = 1; /* # elements in msg_iov */
4329 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4330 msg.msg_control = NULL; /* ancillary data, see below */
4331 msg.msg_controllen = 0; /* ancillary data buffer len */
4332 msg.msg_flags = 0; /* flags on received message */
4335 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4337 if (tret == -ENOTSOCK) {
4338 return libc_read(s, buf, len);
4343 buf = msg.msg_iov[0].iov_base;
4344 len = msg.msg_iov[0].iov_len;
4346 ret = libc_read(s, buf, len);
4348 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4356 ssize_t read(int s, void *buf, size_t len)
4358 return swrap_read(s, buf, len);
4361 /****************************************************************************
4363 ***************************************************************************/
4365 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4369 struct sockaddr_un un_addr;
4372 struct socket_info *si = find_socket_info(s);
4375 return libc_send(s, buf, len, flags);
4378 tmp.iov_base = discard_const_p(char, buf);
4382 msg.msg_name = NULL; /* optional address */
4383 msg.msg_namelen = 0; /* size of address */
4384 msg.msg_iov = &tmp; /* scatter/gather array */
4385 msg.msg_iovlen = 1; /* # elements in msg_iov */
4386 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4387 msg.msg_control = NULL; /* ancillary data, see below */
4388 msg.msg_controllen = 0; /* ancillary data buffer len */
4389 msg.msg_flags = 0; /* flags on received message */
4392 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4397 buf = msg.msg_iov[0].iov_base;
4398 len = msg.msg_iov[0].iov_len;
4400 ret = libc_send(s, buf, len, flags);
4402 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4407 ssize_t send(int s, const void *buf, size_t len, int flags)
4409 return swrap_send(s, buf, len, flags);
4412 /****************************************************************************
4414 ***************************************************************************/
4416 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4418 struct swrap_address from_addr = {
4419 .sa_socklen = sizeof(struct sockaddr_un),
4421 struct socket_info *si;
4424 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4425 size_t msg_ctrllen_filled;
4426 size_t msg_ctrllen_left;
4432 si = find_socket_info(s);
4434 return libc_recvmsg(s, omsg, flags);
4437 tmp.iov_base = NULL;
4441 msg.msg_name = &from_addr.sa; /* optional address */
4442 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4443 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4444 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4445 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4446 msg_ctrllen_filled = 0;
4447 msg_ctrllen_left = omsg->msg_controllen;
4449 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4450 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4451 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4454 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4459 ret = libc_recvmsg(s, &msg, flags);
4461 msg.msg_name = omsg->msg_name;
4462 msg.msg_namelen = omsg->msg_namelen;
4464 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4465 msg_ctrllen_filled += msg.msg_controllen;
4466 msg_ctrllen_left -= msg.msg_controllen;
4468 if (omsg->msg_control != NULL) {
4471 p = omsg->msg_control;
4472 p += msg_ctrllen_filled;
4474 msg.msg_control = p;
4475 msg.msg_controllen = msg_ctrllen_left;
4477 msg.msg_control = NULL;
4478 msg.msg_controllen = 0;
4482 rc = swrap_recvmsg_after(s,
4486 from_addr.sa_socklen,
4492 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4493 if (omsg->msg_control != NULL) {
4494 /* msg.msg_controllen = space left */
4495 msg_ctrllen_left = msg.msg_controllen;
4496 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4499 /* Update the original message length */
4500 omsg->msg_controllen = msg_ctrllen_filled;
4501 omsg->msg_flags = msg.msg_flags;
4503 omsg->msg_iovlen = msg.msg_iovlen;
4508 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4510 return swrap_recvmsg(sockfd, msg, flags);
4513 /****************************************************************************
4515 ***************************************************************************/
4517 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4521 struct sockaddr_un un_addr;
4522 const struct sockaddr_un *to_un = NULL;
4523 const struct sockaddr *to = NULL;
4526 struct socket_info *si = find_socket_info(s);
4530 return libc_sendmsg(s, omsg, flags);
4533 ZERO_STRUCT(un_addr);
4535 tmp.iov_base = NULL;
4539 msg.msg_name = omsg->msg_name; /* optional address */
4540 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4541 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4542 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4543 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4544 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4545 /* omsg is a const so use a local buffer for modifications */
4546 uint8_t cmbuf[omsg->msg_controllen];
4548 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4550 msg.msg_control = cmbuf; /* ancillary data, see below */
4551 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4553 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4556 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4564 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4572 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4573 avail += msg.msg_iov[i].iov_len;
4579 /* we capture it as one single packet */
4580 buf = (uint8_t *)malloc(remain);
4585 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4586 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4588 msg.msg_iov[i].iov_base,
4591 remain -= this_time;
4594 type = SOCKET_TYPE_CHAR_UDP;
4596 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4597 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4598 socket_wrapper_dir(), type, iface, prt);
4599 if (stat(un_addr.sun_path, &st) != 0) continue;
4601 msg.msg_name = &un_addr; /* optional address */
4602 msg.msg_namelen = sizeof(un_addr); /* size of address */
4604 /* ignore the any errors in broadcast sends */
4605 libc_sendmsg(s, &msg, flags);
4608 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4614 ret = libc_sendmsg(s, &msg, flags);
4616 swrap_sendmsg_after(s, si, &msg, to, ret);
4621 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4623 return swrap_sendmsg(s, omsg, flags);
4626 /****************************************************************************
4628 ***************************************************************************/
4630 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4632 struct socket_info *si;
4635 struct swrap_address saddr = {
4636 .sa_socklen = sizeof(struct sockaddr_storage)
4641 si = find_socket_info(s);
4643 return libc_readv(s, vector, count);
4646 tmp.iov_base = NULL;
4650 msg.msg_name = &saddr.sa.s; /* optional address */
4651 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4652 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4653 msg.msg_iovlen = count; /* # elements in msg_iov */
4654 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4655 msg.msg_control = NULL; /* ancillary data, see below */
4656 msg.msg_controllen = 0; /* ancillary data buffer len */
4657 msg.msg_flags = 0; /* flags on received message */
4660 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4662 if (rc == -ENOTSOCK) {
4663 return libc_readv(s, vector, count);
4668 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4670 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4678 ssize_t readv(int s, const struct iovec *vector, int count)
4680 return swrap_readv(s, vector, count);
4683 /****************************************************************************
4685 ***************************************************************************/
4687 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4691 struct sockaddr_un un_addr;
4694 struct socket_info *si = find_socket_info(s);
4697 return libc_writev(s, vector, count);
4700 tmp.iov_base = NULL;
4704 msg.msg_name = NULL; /* optional address */
4705 msg.msg_namelen = 0; /* size of address */
4706 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4707 msg.msg_iovlen = count; /* # elements in msg_iov */
4708 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4709 msg.msg_control = NULL; /* ancillary data, see below */
4710 msg.msg_controllen = 0; /* ancillary data buffer len */
4711 msg.msg_flags = 0; /* flags on received message */
4714 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4716 if (rc == -ENOTSOCK) {
4717 return libc_readv(s, vector, count);
4722 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4724 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4729 ssize_t writev(int s, const struct iovec *vector, int count)
4731 return swrap_writev(s, vector, count);
4734 /****************************
4736 ***************************/
4738 static int swrap_close(int fd)
4740 struct socket_info *si = find_socket_info(fd);
4741 struct socket_info_fd *fi;
4745 return libc_close(fd);
4748 for (fi = si->fds; fi; fi = fi->next) {
4750 SWRAP_DLIST_REMOVE(si->fds, fi);
4757 /* there are still references left */
4758 return libc_close(fd);
4761 SWRAP_DLIST_REMOVE(sockets, si);
4763 if (si->myname && si->peername) {
4764 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4767 ret = libc_close(fd);
4769 if (si->myname && si->peername) {
4770 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4771 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4774 if (si->bindname != NULL) {
4778 if (si->myname) free(si->myname);
4779 if (si->peername) free(si->peername);
4781 unlink(si->tmp_path);
4791 return swrap_close(fd);
4794 /****************************
4796 ***************************/
4798 static int swrap_dup(int fd)
4800 struct socket_info *si;
4801 struct socket_info_fd *fi;
4803 si = find_socket_info(fd);
4806 return libc_dup(fd);
4809 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4815 fi->fd = libc_dup(fd);
4817 int saved_errno = errno;
4819 errno = saved_errno;
4823 /* Make sure we don't have an entry for the fd */
4824 swrap_remove_stale(fi->fd);
4826 SWRAP_DLIST_ADD(si->fds, fi);
4832 return swrap_dup(fd);
4835 /****************************
4837 ***************************/
4839 static int swrap_dup2(int fd, int newfd)
4841 struct socket_info *si;
4842 struct socket_info_fd *fi;
4844 si = find_socket_info(fd);
4847 return libc_dup2(fd, newfd);
4850 if (find_socket_info(newfd)) {
4851 /* dup2() does an implicit close of newfd, which we
4852 * need to emulate */
4856 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4862 fi->fd = libc_dup2(fd, newfd);
4864 int saved_errno = errno;
4866 errno = saved_errno;
4870 /* Make sure we don't have an entry for the fd */
4871 swrap_remove_stale(fi->fd);
4873 SWRAP_DLIST_ADD(si->fds, fi);
4877 int dup2(int fd, int newfd)
4879 return swrap_dup2(fd, newfd);
4882 /****************************
4884 ***************************/
4887 static int swrap_eventfd(int count, int flags)
4891 fd = libc_eventfd(count, flags);
4893 swrap_remove_stale(fd);
4899 int eventfd(int count, int flags)
4901 return swrap_eventfd(count, flags);
4905 /****************************
4907 ***************************/
4910 * This function is called when the library is unloaded and makes sure that
4911 * sockets get closed and the unix file for the socket are unlinked.
4913 void swrap_destructor(void)
4915 struct socket_info *s = sockets;
4918 struct socket_info_fd *f = s->fds;