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_pcap_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_pcap_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_pcap_marshall_packet(si,
2230 if (packet == NULL) {
2234 fd = swrap_get_pcap_fd(file_name);
2236 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2245 /****************************************************************************
2247 ***************************************************************************/
2249 #ifdef HAVE_SIGNALFD
2250 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2254 rc = libc_signalfd(fd, mask, flags);
2256 swrap_remove_stale(fd);
2262 int signalfd(int fd, const sigset_t *mask, int flags)
2264 return swrap_signalfd(fd, mask, flags);
2268 /****************************************************************************
2270 ***************************************************************************/
2272 static int swrap_socket(int family, int type, int protocol)
2274 struct socket_info *si;
2275 struct socket_info_fd *fi;
2277 int real_type = type;
2280 * Remove possible addition flags passed to socket() so
2281 * do not fail checking the type.
2282 * See https://lwn.net/Articles/281965/
2285 real_type &= ~SOCK_CLOEXEC;
2287 #ifdef SOCK_NONBLOCK
2288 real_type &= ~SOCK_NONBLOCK;
2291 if (!socket_wrapper_enabled()) {
2292 return libc_socket(family, type, protocol);
2302 return libc_socket(family, type, protocol);
2304 errno = EAFNOSUPPORT;
2308 switch (real_type) {
2314 errno = EPROTONOSUPPORT;
2322 if (real_type == SOCK_STREAM) {
2327 if (real_type == SOCK_DGRAM) {
2332 errno = EPROTONOSUPPORT;
2337 * We must call libc_socket with type, from the caller, not the version
2338 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2340 fd = libc_socket(AF_UNIX, type, 0);
2346 /* Check if we have a stale fd and remove it */
2347 si = find_socket_info(fd);
2349 swrap_remove_stale(fd);
2352 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2353 memset(si, 0, sizeof(struct socket_info));
2359 si->family = family;
2361 /* however, the rest of the socket_wrapper code expects just
2362 * the type, not the flags */
2363 si->type = real_type;
2364 si->protocol = protocol;
2367 * Setup myname so getsockname() can succeed to find out the socket
2370 switch(si->family) {
2372 struct sockaddr_in sin = {
2373 .sin_family = AF_INET,
2376 si->myname_len = sizeof(struct sockaddr_in);
2377 si->myname = sockaddr_dup(&sin, si->myname_len);
2381 struct sockaddr_in6 sin6 = {
2382 .sin6_family = AF_INET6,
2385 si->myname_len = sizeof(struct sockaddr_in6);
2386 si->myname = sockaddr_dup(&sin6, si->myname_len);
2395 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2397 if (si->myname != NULL) {
2407 SWRAP_DLIST_ADD(si->fds, fi);
2408 SWRAP_DLIST_ADD(sockets, si);
2413 int socket(int family, int type, int protocol)
2415 return swrap_socket(family, type, protocol);
2418 /****************************************************************************
2420 ***************************************************************************/
2422 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2426 rc = libc_socketpair(family, type, protocol, sv);
2428 swrap_remove_stale(sv[0]);
2429 swrap_remove_stale(sv[1]);
2435 int socketpair(int family, int type, int protocol, int sv[2])
2437 return swrap_socketpair(family, type, protocol, sv);
2440 /****************************************************************************
2442 ***************************************************************************/
2444 #ifdef HAVE_TIMERFD_CREATE
2445 static int swrap_timerfd_create(int clockid, int flags)
2449 fd = libc_timerfd_create(clockid, flags);
2451 swrap_remove_stale(fd);
2457 int timerfd_create(int clockid, int flags)
2459 return swrap_timerfd_create(clockid, flags);
2463 /****************************************************************************
2465 ***************************************************************************/
2467 static int swrap_pipe(int pipefd[2])
2471 rc = libc_pipe(pipefd);
2473 swrap_remove_stale(pipefd[0]);
2474 swrap_remove_stale(pipefd[1]);
2480 int pipe(int pipefd[2])
2482 return swrap_pipe(pipefd);
2485 /****************************************************************************
2487 ***************************************************************************/
2489 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2491 struct socket_info *parent_si, *child_si;
2492 struct socket_info_fd *child_fi;
2494 struct swrap_address un_addr = {
2495 .sa_socklen = sizeof(struct sockaddr_un),
2497 struct swrap_address un_my_addr = {
2498 .sa_socklen = sizeof(struct sockaddr_un),
2500 struct sockaddr *my_addr;
2501 socklen_t my_addrlen, len;
2504 parent_si = find_socket_info(s);
2506 return libc_accept(s, addr, addrlen);
2510 * assume out sockaddr have the same size as the in parent
2513 my_addrlen = socket_length(parent_si->family);
2514 if (my_addrlen <= 0) {
2519 my_addr = (struct sockaddr *)malloc(my_addrlen);
2520 if (my_addr == NULL) {
2524 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2526 if (errno == ENOTSOCK) {
2527 /* Remove stale fds */
2528 swrap_remove_stale(s);
2537 ret = sockaddr_convert_from_un(parent_si,
2549 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2550 memset(child_si, 0, sizeof(struct socket_info));
2552 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2553 if (child_fi == NULL) {
2563 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2565 child_si->family = parent_si->family;
2566 child_si->type = parent_si->type;
2567 child_si->protocol = parent_si->protocol;
2568 child_si->bound = 1;
2569 child_si->is_server = 1;
2570 child_si->connected = 1;
2572 child_si->peername_len = len;
2573 child_si->peername = sockaddr_dup(my_addr, len);
2575 if (addr != NULL && addrlen != NULL) {
2576 size_t copy_len = MIN(*addrlen, len);
2578 memcpy(addr, my_addr, copy_len);
2583 ret = libc_getsockname(fd,
2585 &un_my_addr.sa_socklen);
2595 ret = sockaddr_convert_from_un(child_si,
2597 un_my_addr.sa_socklen,
2609 SWRAP_LOG(SWRAP_LOG_TRACE,
2610 "accept() path=%s, fd=%d",
2611 un_my_addr.sa.un.sun_path, s);
2613 child_si->myname_len = len;
2614 child_si->myname = sockaddr_dup(my_addr, len);
2617 SWRAP_DLIST_ADD(sockets, child_si);
2620 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2621 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2622 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2628 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2629 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2631 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2634 return swrap_accept(s, addr, (socklen_t *)addrlen);
2637 static int autobind_start_init;
2638 static int autobind_start;
2640 /* using sendto() or connect() on an unbound socket would give the
2641 recipient no way to reply, as unlike UDP and TCP, a unix domain
2642 socket can't auto-assign ephemeral port numbers, so we need to
2644 Note: this might change the family from ipv6 to ipv4
2646 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2648 struct swrap_address un_addr = {
2649 .sa_socklen = sizeof(struct sockaddr_un),
2657 if (autobind_start_init != 1) {
2658 autobind_start_init = 1;
2659 autobind_start = getpid();
2660 autobind_start %= 50000;
2661 autobind_start += 10000;
2664 un_addr.sa.un.sun_family = AF_UNIX;
2668 struct sockaddr_in in;
2672 type = SOCKET_TYPE_CHAR_TCP;
2675 type = SOCKET_TYPE_CHAR_UDP;
2678 errno = ESOCKTNOSUPPORT;
2682 memset(&in, 0, sizeof(in));
2683 in.sin_family = AF_INET;
2684 in.sin_addr.s_addr = htonl(127<<24 |
2685 socket_wrapper_default_iface());
2688 si->myname_len = sizeof(in);
2689 si->myname = sockaddr_dup(&in, si->myname_len);
2694 struct sockaddr_in6 in6;
2696 if (si->family != family) {
2697 errno = ENETUNREACH;
2703 type = SOCKET_TYPE_CHAR_TCP_V6;
2706 type = SOCKET_TYPE_CHAR_UDP_V6;
2709 errno = ESOCKTNOSUPPORT;
2713 memset(&in6, 0, sizeof(in6));
2714 in6.sin6_family = AF_INET6;
2715 in6.sin6_addr = *swrap_ipv6();
2716 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2718 si->myname_len = sizeof(in6);
2719 si->myname = sockaddr_dup(&in6, si->myname_len);
2724 errno = ESOCKTNOSUPPORT;
2728 if (autobind_start > 60000) {
2729 autobind_start = 10000;
2732 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2733 port = autobind_start + i;
2734 snprintf(un_addr.sa.un.sun_path, un_addr.sa_socklen,
2735 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2736 type, socket_wrapper_default_iface(), port);
2737 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2739 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2740 if (ret == -1) return ret;
2742 si->tmp_path = strdup(un_addr.sa.un.sun_path);
2744 autobind_start = port + 1;
2747 if (i == SOCKET_MAX_SOCKETS) {
2748 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2749 "interface "SOCKET_FORMAT,
2752 socket_wrapper_default_iface(),
2758 si->family = family;
2759 set_port(si->family, port, si->myname);
2764 /****************************************************************************
2766 ***************************************************************************/
2768 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2772 struct swrap_address un_addr = {
2773 .sa_socklen = sizeof(struct sockaddr_un),
2775 struct socket_info *si = find_socket_info(s);
2779 return libc_connect(s, serv_addr, addrlen);
2782 if (si->bound == 0) {
2783 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2784 if (ret == -1) return -1;
2787 if (si->family != serv_addr->sa_family) {
2792 ret = sockaddr_convert_to_un(si, serv_addr,
2793 addrlen, &un_addr.sa.un, 0, &bcast);
2794 if (ret == -1) return -1;
2797 errno = ENETUNREACH;
2801 if (si->type == SOCK_DGRAM) {
2802 si->defer_connect = 1;
2805 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2807 ret = libc_connect(s,
2809 un_addr.sa_socklen);
2812 SWRAP_LOG(SWRAP_LOG_TRACE,
2813 "connect() path=%s, fd=%d",
2814 un_addr.un.sun_path, s);
2817 /* to give better errors */
2818 if (ret == -1 && errno == ENOENT) {
2819 errno = EHOSTUNREACH;
2823 si->peername_len = addrlen;
2824 si->peername = sockaddr_dup(serv_addr, addrlen);
2828 * When we connect() on a socket than we have to bind the
2829 * outgoing connection on the interface we use for the
2830 * transport. We already bound it on the right interface
2831 * but here we have to update the name so getsockname()
2832 * returns correct information.
2834 if (si->bindname != NULL) {
2837 si->myname = si->bindname;
2838 si->myname_len = si->bindname_len;
2840 si->bindname = NULL;
2841 si->bindname_len = 0;
2844 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2845 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2847 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2853 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2855 return swrap_connect(s, serv_addr, addrlen);
2858 /****************************************************************************
2860 ***************************************************************************/
2862 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2865 struct swrap_address un_addr = {
2866 .sa_socklen = sizeof(struct sockaddr_un),
2868 struct socket_info *si = find_socket_info(s);
2875 return libc_bind(s, myaddr, addrlen);
2878 switch (si->family) {
2880 const struct sockaddr_in *sin;
2881 if (addrlen < sizeof(struct sockaddr_in)) {
2882 bind_error = EINVAL;
2886 sin = (const struct sockaddr_in *)myaddr;
2888 if (sin->sin_family != AF_INET) {
2889 bind_error = EAFNOSUPPORT;
2892 /* special case for AF_UNSPEC */
2893 if (sin->sin_family == AF_UNSPEC &&
2894 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2903 const struct sockaddr_in6 *sin6;
2904 if (addrlen < sizeof(struct sockaddr_in6)) {
2905 bind_error = EINVAL;
2909 sin6 = (const struct sockaddr_in6 *)myaddr;
2911 if (sin6->sin6_family != AF_INET6) {
2912 bind_error = EAFNOSUPPORT;
2919 bind_error = EINVAL;
2923 if (bind_error != 0) {
2929 in_use = check_addr_port_in_use(myaddr, addrlen);
2937 si->myname_len = addrlen;
2938 si->myname = sockaddr_dup(myaddr, addrlen);
2940 ret = sockaddr_convert_to_un(si,
2946 if (ret == -1) return -1;
2948 unlink(un_addr.sa.un.sun_path);
2950 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
2952 SWRAP_LOG(SWRAP_LOG_TRACE,
2953 "bind() path=%s, fd=%d",
2954 un_addr.sa_un.sun_path, s);
2963 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2965 return swrap_bind(s, myaddr, addrlen);
2968 /****************************************************************************
2970 ***************************************************************************/
2972 #ifdef HAVE_BINDRESVPORT
2973 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2975 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2977 struct swrap_address myaddr = {
2978 .sa_socklen = sizeof(struct sockaddr_storage),
2981 static uint16_t port;
2986 #define SWRAP_STARTPORT 600
2987 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2988 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2991 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2995 salen = myaddr.sa_socklen;
2998 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3004 memset(&myaddr.sa.ss, 0, salen);
3009 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3012 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3014 salen = sizeof(struct sockaddr_in);
3015 sinp->sin_port = htons(port);
3019 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
3021 salen = sizeof(struct sockaddr_in6);
3022 sin6p->sin6_port = htons(port);
3026 errno = EAFNOSUPPORT;
3031 if (port > SWRAP_ENDPORT) {
3032 port = SWRAP_STARTPORT;
3035 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3036 if (rc == 0 || errno != EADDRINUSE) {
3044 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3046 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3050 /****************************************************************************
3052 ***************************************************************************/
3054 static int swrap_listen(int s, int backlog)
3057 struct socket_info *si = find_socket_info(s);
3060 return libc_listen(s, backlog);
3063 ret = libc_listen(s, backlog);
3068 int listen(int s, int backlog)
3070 return swrap_listen(s, backlog);
3073 /****************************************************************************
3075 ***************************************************************************/
3077 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3081 ret = libc_vopen(pathname, flags, ap);
3084 * There are methods for closing descriptors (libc-internal code
3085 * paths, direct syscalls) which close descriptors in ways that
3086 * we can't intercept, so try to recover when we notice that
3089 swrap_remove_stale(ret);
3094 int open(const char *pathname, int flags, ...)
3099 va_start(ap, flags);
3100 fd = swrap_vopen(pathname, flags, ap);
3106 /****************************************************************************
3108 ***************************************************************************/
3110 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3112 struct socket_info *si = find_socket_info(s);
3116 return libc_getpeername(s, name, addrlen);
3125 len = MIN(*addrlen, si->peername_len);
3130 memcpy(name, si->peername, len);
3131 *addrlen = si->peername_len;
3136 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3137 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3139 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3142 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3145 /****************************************************************************
3147 ***************************************************************************/
3149 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3151 struct socket_info *si = find_socket_info(s);
3155 return libc_getsockname(s, name, addrlen);
3158 len = MIN(*addrlen, si->myname_len);
3163 memcpy(name, si->myname, len);
3164 *addrlen = si->myname_len;
3169 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3170 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3172 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3175 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3178 /****************************************************************************
3180 ***************************************************************************/
3183 # ifdef SO_PROTOTYPE /* The Solaris name */
3184 # define SO_PROTOCOL SO_PROTOTYPE
3185 # endif /* SO_PROTOTYPE */
3186 #endif /* SO_PROTOCOL */
3188 static int swrap_getsockopt(int s, int level, int optname,
3189 void *optval, socklen_t *optlen)
3191 struct socket_info *si = find_socket_info(s);
3194 return libc_getsockopt(s,
3201 if (level == SOL_SOCKET) {
3205 if (optval == NULL || optlen == NULL ||
3206 *optlen < (socklen_t)sizeof(int)) {
3211 *optlen = sizeof(int);
3212 *(int *)optval = si->family;
3214 #endif /* SO_DOMAIN */
3218 if (optval == NULL || optlen == NULL ||
3219 *optlen < (socklen_t)sizeof(int)) {
3224 *optlen = sizeof(int);
3225 *(int *)optval = si->protocol;
3227 #endif /* SO_PROTOCOL */
3229 if (optval == NULL || optlen == NULL ||
3230 *optlen < (socklen_t)sizeof(int)) {
3235 *optlen = sizeof(int);
3236 *(int *)optval = si->type;
3239 return libc_getsockopt(s,
3247 errno = ENOPROTOOPT;
3251 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3252 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3254 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3257 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3260 /****************************************************************************
3262 ***************************************************************************/
3264 static int swrap_setsockopt(int s, int level, int optname,
3265 const void *optval, socklen_t optlen)
3267 struct socket_info *si = find_socket_info(s);
3270 return libc_setsockopt(s,
3277 if (level == SOL_SOCKET) {
3278 return libc_setsockopt(s,
3285 switch (si->family) {
3287 if (level == IPPROTO_IP) {
3289 if (optname == IP_PKTINFO) {
3290 si->pktinfo = AF_INET;
3292 #endif /* IP_PKTINFO */
3297 if (level == IPPROTO_IPV6) {
3298 #ifdef IPV6_RECVPKTINFO
3299 if (optname == IPV6_RECVPKTINFO) {
3300 si->pktinfo = AF_INET6;
3302 #endif /* IPV6_PKTINFO */
3307 errno = ENOPROTOOPT;
3312 int setsockopt(int s, int level, int optname,
3313 const void *optval, socklen_t optlen)
3315 return swrap_setsockopt(s, level, optname, optval, optlen);
3318 /****************************************************************************
3320 ***************************************************************************/
3322 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3324 struct socket_info *si = find_socket_info(s);
3330 return libc_vioctl(s, r, va);
3335 rc = libc_vioctl(s, r, va);
3339 value = *((int *)va_arg(ap, int *));
3341 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3342 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3343 } else if (value == 0) { /* END OF FILE */
3344 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3354 #ifdef HAVE_IOCTL_INT
3355 int ioctl(int s, int r, ...)
3357 int ioctl(int s, unsigned long int r, ...)
3365 rc = swrap_vioctl(s, (unsigned long int) r, va);
3376 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3379 # ifdef _ALIGN /* BSD */
3380 #define CMSG_ALIGN _ALIGN
3382 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3383 # endif /* _ALIGN */
3384 #endif /* CMSG_ALIGN */
3387 * @brief Add a cmsghdr to a msghdr.
3389 * This is an function to add any type of cmsghdr. It will operate on the
3390 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3391 * the buffer position after the added cmsg element. Hence, this function is
3392 * intended to be used with an intermediate msghdr and not on the original
3393 * one handed in by the client.
3395 * @param[in] msg The msghdr to which to add the cmsg.
3397 * @param[in] level The cmsg level to set.
3399 * @param[in] type The cmsg type to set.
3401 * @param[in] data The cmsg data to set.
3403 * @param[in] len the length of the data to set.
3405 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3411 size_t cmlen = CMSG_LEN(len);
3412 size_t cmspace = CMSG_SPACE(len);
3413 uint8_t cmbuf[cmspace];
3414 void *cast_ptr = (void *)cmbuf;
3415 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3418 memset(cmbuf, 0, cmspace);
3420 if (msg->msg_controllen < cmlen) {
3421 cmlen = msg->msg_controllen;
3422 msg->msg_flags |= MSG_CTRUNC;
3425 if (msg->msg_controllen < cmspace) {
3426 cmspace = msg->msg_controllen;
3430 * We copy the full input data into an intermediate cmsghdr first
3431 * in order to more easily cope with truncation.
3433 cm->cmsg_len = cmlen;
3434 cm->cmsg_level = level;
3435 cm->cmsg_type = type;
3436 memcpy(CMSG_DATA(cm), data, len);
3439 * We now copy the possibly truncated buffer.
3440 * We copy cmlen bytes, but consume cmspace bytes,
3441 * leaving the possible padding uninitialiazed.
3443 p = (uint8_t *)msg->msg_control;
3444 memcpy(p, cm, cmlen);
3446 msg->msg_control = p;
3447 msg->msg_controllen -= cmspace;
3452 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3455 /* Add packet info */
3456 switch (si->pktinfo) {
3457 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3459 struct sockaddr_in *sin;
3460 #if defined(HAVE_STRUCT_IN_PKTINFO)
3461 struct in_pktinfo pkt;
3462 #elif defined(IP_RECVDSTADDR)
3466 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3467 sin = (struct sockaddr_in*)si->bindname;
3469 if (si->myname_len != sizeof(struct sockaddr_in)) {
3472 sin = (struct sockaddr_in*)si->myname;
3477 #if defined(HAVE_STRUCT_IN_PKTINFO)
3478 pkt.ipi_ifindex = socket_wrapper_default_iface();
3479 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3480 #elif defined(IP_RECVDSTADDR)
3481 pkt = sin->sin_addr;
3484 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3489 #endif /* IP_PKTINFO */
3490 #if defined(HAVE_IPV6)
3492 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3493 struct sockaddr_in6 *sin6;
3494 struct in6_pktinfo pkt6;
3496 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3497 sin6 = (struct sockaddr_in6*)si->bindname;
3499 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3502 sin6 = (struct sockaddr_in6*)si->myname;
3507 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3508 pkt6.ipi6_addr = sin6->sin6_addr;
3510 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3511 &pkt6, sizeof(pkt6));
3512 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3516 #endif /* IPV6_PKTINFO */
3524 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3525 struct msghdr *omsg)
3529 if (si->pktinfo > 0) {
3530 rc = swrap_msghdr_add_pktinfo(si, omsg);
3536 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3538 size_t *cm_data_space);
3539 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3541 size_t *cm_data_space);
3543 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3545 size_t *cm_data_space) {
3546 struct cmsghdr *cmsg;
3550 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3554 for (cmsg = CMSG_FIRSTHDR(msg);
3556 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3557 switch (cmsg->cmsg_level) {
3559 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3564 rc = swrap_sendmsg_copy_cmsg(cmsg,
3574 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3576 size_t *cm_data_space)
3583 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3585 p = realloc((*cm_data), cmspace);
3591 p = (*cm_data) + (*cm_data_space);
3592 *cm_data_space = cmspace;
3594 memcpy(p, cmsg, cmsg->cmsg_len);
3599 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3601 size_t *cm_data_space);
3604 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3606 size_t *cm_data_space)
3610 switch(cmsg->cmsg_type) {
3613 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3620 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3632 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3634 size_t *cm_data_space)
3636 (void)cmsg; /* unused */
3637 (void)cm_data; /* unused */
3638 (void)cm_data_space; /* unused */
3641 * Passing a IP pktinfo to a unix socket might be rejected by the
3642 * Kernel, at least on FreeBSD. So skip this cmsg.
3646 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3648 static ssize_t swrap_sendmsg_before(int fd,
3649 struct socket_info *si,
3651 struct iovec *tmp_iov,
3652 struct sockaddr_un *tmp_un,
3653 const struct sockaddr_un **to_un,
3654 const struct sockaddr **to,
3672 if (!si->connected) {
3677 if (msg->msg_iovlen == 0) {
3681 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3683 nlen = len + msg->msg_iov[i].iov_len;
3684 if (nlen > SOCKET_MAX_PACKET) {
3688 msg->msg_iovlen = i;
3689 if (msg->msg_iovlen == 0) {
3690 *tmp_iov = msg->msg_iov[0];
3691 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3692 msg->msg_iov = tmp_iov;
3693 msg->msg_iovlen = 1;
3698 if (si->connected) {
3699 if (msg->msg_name) {
3704 const struct sockaddr *msg_name;
3705 msg_name = (const struct sockaddr *)msg->msg_name;
3707 if (msg_name == NULL) {
3713 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3715 if (ret == -1) return -1;
3723 msg->msg_name = tmp_un;
3724 msg->msg_namelen = sizeof(*tmp_un);
3727 if (si->bound == 0) {
3728 ret = swrap_auto_bind(fd, si, si->family);
3730 if (errno == ENOTSOCK) {
3731 swrap_remove_stale(fd);
3734 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3740 if (!si->defer_connect) {
3744 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3746 if (ret == -1) return -1;
3748 ret = libc_connect(fd,
3749 (struct sockaddr *)(void *)tmp_un,
3752 /* to give better errors */
3753 if (ret == -1 && errno == ENOENT) {
3754 errno = EHOSTUNREACH;
3761 si->defer_connect = 0;
3764 errno = EHOSTUNREACH;
3768 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3769 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3770 uint8_t *cmbuf = NULL;
3773 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3780 msg->msg_controllen = 0;
3781 msg->msg_control = NULL;
3782 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3783 memcpy(msg->msg_control, cmbuf, cmlen);
3784 msg->msg_controllen = cmlen;
3793 static void swrap_sendmsg_after(int fd,
3794 struct socket_info *si,
3796 const struct sockaddr *to,
3799 int saved_errno = errno;
3806 /* to give better errors */
3808 if (saved_errno == ENOENT) {
3809 saved_errno = EHOSTUNREACH;
3810 } else if (saved_errno == ENOTSOCK) {
3811 /* If the fd is not a socket, remove it */
3812 swrap_remove_stale(fd);
3816 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3817 avail += msg->msg_iov[i].iov_len;
3821 remain = MIN(80, avail);
3826 /* we capture it as one single packet */
3827 buf = (uint8_t *)malloc(remain);
3829 /* we just not capture the packet */
3830 errno = saved_errno;
3834 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3835 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3837 msg->msg_iov[i].iov_base,
3840 remain -= this_time;
3847 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3848 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3850 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3855 if (si->connected) {
3859 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3860 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3862 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3868 errno = saved_errno;
3871 static int swrap_recvmsg_before(int fd,
3872 struct socket_info *si,
3874 struct iovec *tmp_iov)
3879 (void)fd; /* unused */
3883 if (!si->connected) {
3888 if (msg->msg_iovlen == 0) {
3892 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3894 nlen = len + msg->msg_iov[i].iov_len;
3895 if (nlen > SOCKET_MAX_PACKET) {
3899 msg->msg_iovlen = i;
3900 if (msg->msg_iovlen == 0) {
3901 *tmp_iov = msg->msg_iov[0];
3902 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3903 msg->msg_iov = tmp_iov;
3904 msg->msg_iovlen = 1;
3909 if (msg->msg_name == NULL) {
3914 if (msg->msg_iovlen == 0) {
3918 if (si->bound == 0) {
3919 ret = swrap_auto_bind(fd, si, si->family);
3922 * When attempting to read or write to a
3923 * descriptor, if an underlying autobind fails
3924 * because it's not a socket, stop intercepting
3925 * uses of that descriptor.
3927 if (errno == ENOTSOCK) {
3928 swrap_remove_stale(fd);
3931 SWRAP_LOG(SWRAP_LOG_ERROR,
3932 "swrap_recvmsg_before failed");
3939 errno = EHOSTUNREACH;
3946 static int swrap_recvmsg_after(int fd,
3947 struct socket_info *si,
3949 const struct sockaddr_un *un_addr,
3950 socklen_t un_addrlen,
3953 int saved_errno = errno;
3955 uint8_t *buf = NULL;
3961 /* to give better errors */
3963 if (saved_errno == ENOENT) {
3964 saved_errno = EHOSTUNREACH;
3965 } else if (saved_errno == ENOTSOCK) {
3966 /* If the fd is not a socket, remove it */
3967 swrap_remove_stale(fd);
3971 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3972 avail += msg->msg_iov[i].iov_len;
3981 remain = MIN(80, avail);
3986 /* we capture it as one single packet */
3987 buf = (uint8_t *)malloc(remain);
3989 /* we just not capture the packet */
3990 errno = saved_errno;
3994 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3995 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3997 msg->msg_iov[i].iov_base,
4000 remain -= this_time;
4005 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4006 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4007 } else if (ret == 0) { /* END OF FILE */
4008 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4009 } else if (ret > 0) {
4010 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4019 if (un_addr != NULL) {
4020 rc = sockaddr_convert_from_un(si,
4030 swrap_dump_packet(si,
4036 swrap_dump_packet(si,
4049 errno = saved_errno;
4051 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4053 msg->msg_controllen > 0 &&
4054 msg->msg_control != NULL) {
4055 rc = swrap_msghdr_add_socket_info(si, msg);
4065 /****************************************************************************
4067 ***************************************************************************/
4069 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4070 struct sockaddr *from, socklen_t *fromlen)
4072 struct swrap_address from_addr = {
4073 .sa_socklen = sizeof(struct sockaddr_un),
4076 struct socket_info *si = find_socket_info(s);
4077 struct swrap_address saddr = {
4078 .sa_socklen = sizeof(struct sockaddr_storage),
4085 return libc_recvfrom(s,
4097 if (from != NULL && fromlen != NULL) {
4098 msg.msg_name = from; /* optional address */
4099 msg.msg_namelen = *fromlen; /* size of address */
4101 msg.msg_name = &saddr.sa.s; /* optional address */
4102 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4104 msg.msg_iov = &tmp; /* scatter/gather array */
4105 msg.msg_iovlen = 1; /* # elements in msg_iov */
4106 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4107 msg.msg_control = NULL; /* ancillary data, see below */
4108 msg.msg_controllen = 0; /* ancillary data buffer len */
4109 msg.msg_flags = 0; /* flags on received message */
4112 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4117 buf = msg.msg_iov[0].iov_base;
4118 len = msg.msg_iov[0].iov_len;
4120 ret = libc_recvfrom(s,
4125 &from_addr.sa_socklen);
4130 tret = swrap_recvmsg_after(s,
4134 from_addr.sa_socklen,
4140 if (from != NULL && fromlen != NULL) {
4141 *fromlen = msg.msg_namelen;
4147 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4148 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4149 struct sockaddr *from, Psocklen_t fromlen)
4151 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4152 struct sockaddr *from, socklen_t *fromlen)
4155 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4158 /****************************************************************************
4160 ***************************************************************************/
4162 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4163 const struct sockaddr *to, socklen_t tolen)
4167 struct swrap_address un_addr = {
4168 .sa_socklen = sizeof(struct sockaddr_un),
4170 const struct sockaddr_un *to_un = NULL;
4173 struct socket_info *si = find_socket_info(s);
4177 return libc_sendto(s, buf, len, flags, to, tolen);
4180 tmp.iov_base = discard_const_p(char, buf);
4184 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4185 msg.msg_namelen = tolen; /* size of address */
4186 msg.msg_iov = &tmp; /* scatter/gather array */
4187 msg.msg_iovlen = 1; /* # elements in msg_iov */
4188 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4189 msg.msg_control = NULL; /* ancillary data, see below */
4190 msg.msg_controllen = 0; /* ancillary data buffer len */
4191 msg.msg_flags = 0; /* flags on received message */
4194 rc = swrap_sendmsg_before(s,
4206 buf = msg.msg_iov[0].iov_base;
4207 len = msg.msg_iov[0].iov_len;
4212 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4215 type = SOCKET_TYPE_CHAR_UDP;
4217 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4218 snprintf(un_addr.sa.un.sun_path,
4219 sizeof(un_addr.sa.un.sun_path),
4221 socket_wrapper_dir(), type, iface, prt);
4222 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4224 /* ignore the any errors in broadcast sends */
4230 un_addr.sa_socklen);
4233 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4238 ret = libc_sendto(s,
4242 (struct sockaddr *)msg.msg_name,
4245 swrap_sendmsg_after(s, si, &msg, to, ret);
4250 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4251 const struct sockaddr *to, socklen_t tolen)
4253 return swrap_sendto(s, buf, len, flags, to, tolen);
4256 /****************************************************************************
4258 ***************************************************************************/
4260 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4262 struct socket_info *si;
4264 struct swrap_address saddr = {
4265 .sa_socklen = sizeof(struct sockaddr_storage),
4271 si = find_socket_info(s);
4273 return libc_recv(s, buf, len, flags);
4280 msg.msg_name = &saddr.sa.s; /* optional address */
4281 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4282 msg.msg_iov = &tmp; /* scatter/gather array */
4283 msg.msg_iovlen = 1; /* # elements in msg_iov */
4284 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4285 msg.msg_control = NULL; /* ancillary data, see below */
4286 msg.msg_controllen = 0; /* ancillary data buffer len */
4287 msg.msg_flags = 0; /* flags on received message */
4290 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4295 buf = msg.msg_iov[0].iov_base;
4296 len = msg.msg_iov[0].iov_len;
4298 ret = libc_recv(s, buf, len, flags);
4300 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4308 ssize_t recv(int s, void *buf, size_t len, int flags)
4310 return swrap_recv(s, buf, len, flags);
4313 /****************************************************************************
4315 ***************************************************************************/
4317 static ssize_t swrap_read(int s, void *buf, size_t len)
4319 struct socket_info *si;
4322 struct swrap_address saddr = {
4323 .sa_socklen = sizeof(struct sockaddr_storage),
4328 si = find_socket_info(s);
4330 return libc_read(s, buf, len);
4337 msg.msg_name = &saddr.sa.ss; /* optional address */
4338 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4339 msg.msg_iov = &tmp; /* scatter/gather array */
4340 msg.msg_iovlen = 1; /* # elements in msg_iov */
4341 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4342 msg.msg_control = NULL; /* ancillary data, see below */
4343 msg.msg_controllen = 0; /* ancillary data buffer len */
4344 msg.msg_flags = 0; /* flags on received message */
4347 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4349 if (tret == -ENOTSOCK) {
4350 return libc_read(s, buf, len);
4355 buf = msg.msg_iov[0].iov_base;
4356 len = msg.msg_iov[0].iov_len;
4358 ret = libc_read(s, buf, len);
4360 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4368 ssize_t read(int s, void *buf, size_t len)
4370 return swrap_read(s, buf, len);
4373 /****************************************************************************
4375 ***************************************************************************/
4377 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4381 struct sockaddr_un un_addr;
4384 struct socket_info *si = find_socket_info(s);
4387 return libc_send(s, buf, len, flags);
4390 tmp.iov_base = discard_const_p(char, buf);
4394 msg.msg_name = NULL; /* optional address */
4395 msg.msg_namelen = 0; /* size of address */
4396 msg.msg_iov = &tmp; /* scatter/gather array */
4397 msg.msg_iovlen = 1; /* # elements in msg_iov */
4398 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4399 msg.msg_control = NULL; /* ancillary data, see below */
4400 msg.msg_controllen = 0; /* ancillary data buffer len */
4401 msg.msg_flags = 0; /* flags on received message */
4404 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4409 buf = msg.msg_iov[0].iov_base;
4410 len = msg.msg_iov[0].iov_len;
4412 ret = libc_send(s, buf, len, flags);
4414 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4419 ssize_t send(int s, const void *buf, size_t len, int flags)
4421 return swrap_send(s, buf, len, flags);
4424 /****************************************************************************
4426 ***************************************************************************/
4428 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4430 struct swrap_address from_addr = {
4431 .sa_socklen = sizeof(struct sockaddr_un),
4433 struct socket_info *si;
4436 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4437 size_t msg_ctrllen_filled;
4438 size_t msg_ctrllen_left;
4444 si = find_socket_info(s);
4446 return libc_recvmsg(s, omsg, flags);
4449 tmp.iov_base = NULL;
4453 msg.msg_name = &from_addr.sa; /* optional address */
4454 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4455 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4456 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4457 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4458 msg_ctrllen_filled = 0;
4459 msg_ctrllen_left = omsg->msg_controllen;
4461 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4462 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4463 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4466 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4471 ret = libc_recvmsg(s, &msg, flags);
4473 msg.msg_name = omsg->msg_name;
4474 msg.msg_namelen = omsg->msg_namelen;
4476 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4477 msg_ctrllen_filled += msg.msg_controllen;
4478 msg_ctrllen_left -= msg.msg_controllen;
4480 if (omsg->msg_control != NULL) {
4483 p = omsg->msg_control;
4484 p += msg_ctrllen_filled;
4486 msg.msg_control = p;
4487 msg.msg_controllen = msg_ctrllen_left;
4489 msg.msg_control = NULL;
4490 msg.msg_controllen = 0;
4494 rc = swrap_recvmsg_after(s,
4498 from_addr.sa_socklen,
4504 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4505 if (omsg->msg_control != NULL) {
4506 /* msg.msg_controllen = space left */
4507 msg_ctrllen_left = msg.msg_controllen;
4508 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4511 /* Update the original message length */
4512 omsg->msg_controllen = msg_ctrllen_filled;
4513 omsg->msg_flags = msg.msg_flags;
4515 omsg->msg_iovlen = msg.msg_iovlen;
4520 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4522 return swrap_recvmsg(sockfd, msg, flags);
4525 /****************************************************************************
4527 ***************************************************************************/
4529 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4533 struct sockaddr_un un_addr;
4534 const struct sockaddr_un *to_un = NULL;
4535 const struct sockaddr *to = NULL;
4538 struct socket_info *si = find_socket_info(s);
4542 return libc_sendmsg(s, omsg, flags);
4545 ZERO_STRUCT(un_addr);
4547 tmp.iov_base = NULL;
4551 msg.msg_name = omsg->msg_name; /* optional address */
4552 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4553 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4554 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4555 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4556 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4557 /* omsg is a const so use a local buffer for modifications */
4558 uint8_t cmbuf[omsg->msg_controllen];
4560 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4562 msg.msg_control = cmbuf; /* ancillary data, see below */
4563 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4565 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4568 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4576 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4584 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4585 avail += msg.msg_iov[i].iov_len;
4591 /* we capture it as one single packet */
4592 buf = (uint8_t *)malloc(remain);
4597 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4598 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4600 msg.msg_iov[i].iov_base,
4603 remain -= this_time;
4606 type = SOCKET_TYPE_CHAR_UDP;
4608 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4609 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4610 socket_wrapper_dir(), type, iface, prt);
4611 if (stat(un_addr.sun_path, &st) != 0) continue;
4613 msg.msg_name = &un_addr; /* optional address */
4614 msg.msg_namelen = sizeof(un_addr); /* size of address */
4616 /* ignore the any errors in broadcast sends */
4617 libc_sendmsg(s, &msg, flags);
4620 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4626 ret = libc_sendmsg(s, &msg, flags);
4628 swrap_sendmsg_after(s, si, &msg, to, ret);
4633 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4635 return swrap_sendmsg(s, omsg, flags);
4638 /****************************************************************************
4640 ***************************************************************************/
4642 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4644 struct socket_info *si;
4647 struct swrap_address saddr = {
4648 .sa_socklen = sizeof(struct sockaddr_storage)
4653 si = find_socket_info(s);
4655 return libc_readv(s, vector, count);
4658 tmp.iov_base = NULL;
4662 msg.msg_name = &saddr.sa.s; /* optional address */
4663 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4664 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4665 msg.msg_iovlen = count; /* # elements in msg_iov */
4666 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4667 msg.msg_control = NULL; /* ancillary data, see below */
4668 msg.msg_controllen = 0; /* ancillary data buffer len */
4669 msg.msg_flags = 0; /* flags on received message */
4672 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4674 if (rc == -ENOTSOCK) {
4675 return libc_readv(s, vector, count);
4680 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4682 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4690 ssize_t readv(int s, const struct iovec *vector, int count)
4692 return swrap_readv(s, vector, count);
4695 /****************************************************************************
4697 ***************************************************************************/
4699 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4703 struct sockaddr_un un_addr;
4706 struct socket_info *si = find_socket_info(s);
4709 return libc_writev(s, vector, count);
4712 tmp.iov_base = NULL;
4716 msg.msg_name = NULL; /* optional address */
4717 msg.msg_namelen = 0; /* size of address */
4718 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4719 msg.msg_iovlen = count; /* # elements in msg_iov */
4720 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4721 msg.msg_control = NULL; /* ancillary data, see below */
4722 msg.msg_controllen = 0; /* ancillary data buffer len */
4723 msg.msg_flags = 0; /* flags on received message */
4726 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4728 if (rc == -ENOTSOCK) {
4729 return libc_readv(s, vector, count);
4734 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4736 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4741 ssize_t writev(int s, const struct iovec *vector, int count)
4743 return swrap_writev(s, vector, count);
4746 /****************************
4748 ***************************/
4750 static int swrap_close(int fd)
4752 struct socket_info *si = find_socket_info(fd);
4753 struct socket_info_fd *fi;
4757 return libc_close(fd);
4760 for (fi = si->fds; fi; fi = fi->next) {
4762 SWRAP_DLIST_REMOVE(si->fds, fi);
4769 /* there are still references left */
4770 return libc_close(fd);
4773 SWRAP_DLIST_REMOVE(sockets, si);
4775 if (si->myname && si->peername) {
4776 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4779 ret = libc_close(fd);
4781 if (si->myname && si->peername) {
4782 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4783 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4786 if (si->bindname != NULL) {
4790 if (si->myname) free(si->myname);
4791 if (si->peername) free(si->peername);
4793 unlink(si->tmp_path);
4803 return swrap_close(fd);
4806 /****************************
4808 ***************************/
4810 static int swrap_dup(int fd)
4812 struct socket_info *si;
4813 struct socket_info_fd *fi;
4815 si = find_socket_info(fd);
4818 return libc_dup(fd);
4821 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4827 fi->fd = libc_dup(fd);
4829 int saved_errno = errno;
4831 errno = saved_errno;
4835 /* Make sure we don't have an entry for the fd */
4836 swrap_remove_stale(fi->fd);
4838 SWRAP_DLIST_ADD(si->fds, fi);
4844 return swrap_dup(fd);
4847 /****************************
4849 ***************************/
4851 static int swrap_dup2(int fd, int newfd)
4853 struct socket_info *si;
4854 struct socket_info_fd *fi;
4856 si = find_socket_info(fd);
4859 return libc_dup2(fd, newfd);
4862 if (find_socket_info(newfd)) {
4863 /* dup2() does an implicit close of newfd, which we
4864 * need to emulate */
4868 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4874 fi->fd = libc_dup2(fd, newfd);
4876 int saved_errno = errno;
4878 errno = saved_errno;
4882 /* Make sure we don't have an entry for the fd */
4883 swrap_remove_stale(fi->fd);
4885 SWRAP_DLIST_ADD(si->fds, fi);
4889 int dup2(int fd, int newfd)
4891 return swrap_dup2(fd, newfd);
4894 /****************************
4896 ***************************/
4899 static int swrap_eventfd(int count, int flags)
4903 fd = libc_eventfd(count, flags);
4905 swrap_remove_stale(fd);
4911 int eventfd(int count, int flags)
4913 return swrap_eventfd(count, flags);
4917 /****************************
4919 ***************************/
4922 * This function is called when the library is unloaded and makes sure that
4923 * sockets get closed and the unix file for the socket are unlinked.
4925 void swrap_destructor(void)
4927 struct socket_info *s = sockets;
4930 struct socket_info_fd *f = s->fds;