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;
245 /* The unix path so we can unlink it on close() */
246 struct sockaddr_un un_addr;
248 struct swrap_address bindname;
249 struct swrap_address myname;
250 struct swrap_address peername;
253 unsigned long pck_snd;
254 unsigned long pck_rcv;
257 struct socket_info *prev, *next;
261 * File descriptors are shared between threads so we should share socket
264 struct socket_info *sockets;
266 /* Function prototypes */
268 bool socket_wrapper_enabled(void);
269 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
272 # define SWRAP_LOG(...)
275 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
276 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
278 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
283 unsigned int lvl = 0;
285 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
290 va_start(va, format);
291 vsnprintf(buffer, sizeof(buffer), format, va);
296 case SWRAP_LOG_ERROR:
298 "SWRAP_ERROR(%d): %s\n",
299 (int)getpid(), buffer);
303 "SWRAP_WARN(%d): %s\n",
304 (int)getpid(), buffer);
306 case SWRAP_LOG_DEBUG:
308 "SWRAP_DEBUG(%d): %s\n",
309 (int)getpid(), buffer);
311 case SWRAP_LOG_TRACE:
313 "SWRAP_TRACE(%d): %s\n",
314 (int)getpid(), buffer);
321 /*********************************************************
322 * SWRAP LOADING LIBC FUNCTIONS
323 *********************************************************/
327 struct swrap_libc_fns {
328 int (*libc_accept)(int sockfd,
329 struct sockaddr *addr,
331 int (*libc_bind)(int sockfd,
332 const struct sockaddr *addr,
334 int (*libc_close)(int fd);
335 int (*libc_connect)(int sockfd,
336 const struct sockaddr *addr,
338 int (*libc_dup)(int fd);
339 int (*libc_dup2)(int oldfd, int newfd);
341 int (*libc_eventfd)(int count, int flags);
343 int (*libc_getpeername)(int sockfd,
344 struct sockaddr *addr,
346 int (*libc_getsockname)(int sockfd,
347 struct sockaddr *addr,
349 int (*libc_getsockopt)(int sockfd,
354 int (*libc_ioctl)(int d, unsigned long int request, ...);
355 int (*libc_listen)(int sockfd, int backlog);
356 int (*libc_open)(const char *pathname, int flags, mode_t mode);
357 int (*libc_pipe)(int pipefd[2]);
358 int (*libc_read)(int fd, void *buf, size_t count);
359 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
360 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
361 int (*libc_recvfrom)(int sockfd,
365 struct sockaddr *src_addr,
367 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
368 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
369 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
370 int (*libc_sendto)(int sockfd,
374 const struct sockaddr *dst_addr,
376 int (*libc_setsockopt)(int sockfd,
382 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
384 int (*libc_socket)(int domain, int type, int protocol);
385 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
386 #ifdef HAVE_TIMERFD_CREATE
387 int (*libc_timerfd_create)(int clockid, int flags);
389 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
394 void *libsocket_handle;
401 struct swrap_libc_fns fns;
404 static struct swrap swrap;
407 static const char *socket_wrapper_dir(void);
409 #define LIBC_NAME "libc.so"
418 static const char *swrap_str_lib(enum swrap_lib lib)
425 case SWRAP_LIBSOCKET:
429 /* Compiler would warn us about unhandled enum value if we get here */
434 static void *swrap_load_lib_handle(enum swrap_lib lib)
436 int flags = RTLD_LAZY;
441 flags |= RTLD_DEEPBIND;
447 case SWRAP_LIBSOCKET:
448 #ifdef HAVE_LIBSOCKET
449 handle = swrap.libsocket_handle;
450 if (handle == NULL) {
451 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
452 char soname[256] = {0};
454 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
455 handle = dlopen(soname, flags);
458 swrap.libsocket_handle = handle;
464 handle = swrap.libc_handle;
466 if (handle == NULL) {
467 handle = dlopen(LIBC_SO, flags);
469 swrap.libc_handle = handle;
472 if (handle == NULL) {
473 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
474 char soname[256] = {0};
476 snprintf(soname, sizeof(soname), "libc.so.%d", i);
477 handle = dlopen(soname, flags);
480 swrap.libc_handle = handle;
485 if (handle == NULL) {
487 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
489 SWRAP_LOG(SWRAP_LOG_ERROR,
490 "Failed to dlopen library: %s\n",
499 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
504 handle = swrap_load_lib_handle(lib);
506 func = dlsym(handle, fn_name);
508 SWRAP_LOG(SWRAP_LOG_ERROR,
509 "Failed to find %s: %s\n",
514 SWRAP_LOG(SWRAP_LOG_TRACE,
516 fn_name, swrap_str_lib(lib));
520 #define swrap_load_lib_function(lib, fn_name) \
521 if (swrap.fns.libc_##fn_name == NULL) { \
522 *(void **) (&swrap.fns.libc_##fn_name) = \
523 _swrap_load_lib_function(lib, #fn_name); \
530 * Functions especially from libc need to be loaded individually, you can't load
531 * all at once or gdb will segfault at startup. The same applies to valgrind and
532 * has probably something todo with with the linker.
533 * So we need load each function at the point it is called the first time.
535 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
537 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
539 return swrap.fns.libc_accept(sockfd, addr, addrlen);
542 static int libc_bind(int sockfd,
543 const struct sockaddr *addr,
546 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
548 return swrap.fns.libc_bind(sockfd, addr, addrlen);
551 static int libc_close(int fd)
553 swrap_load_lib_function(SWRAP_LIBC, close);
555 return swrap.fns.libc_close(fd);
558 static int libc_connect(int sockfd,
559 const struct sockaddr *addr,
562 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
564 return swrap.fns.libc_connect(sockfd, addr, addrlen);
567 static int libc_dup(int fd)
569 swrap_load_lib_function(SWRAP_LIBC, dup);
571 return swrap.fns.libc_dup(fd);
574 static int libc_dup2(int oldfd, int newfd)
576 swrap_load_lib_function(SWRAP_LIBC, dup2);
578 return swrap.fns.libc_dup2(oldfd, newfd);
582 static int libc_eventfd(int count, int flags)
584 swrap_load_lib_function(SWRAP_LIBC, eventfd);
586 return swrap.fns.libc_eventfd(count, flags);
590 static int libc_getpeername(int sockfd,
591 struct sockaddr *addr,
594 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
596 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
599 static int libc_getsockname(int sockfd,
600 struct sockaddr *addr,
603 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
605 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
608 static int libc_getsockopt(int sockfd,
614 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
616 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
619 static int libc_vioctl(int d, unsigned long int request, va_list ap)
625 swrap_load_lib_function(SWRAP_LIBC, ioctl);
627 for (i = 0; i < 4; i++) {
628 args[i] = va_arg(ap, long int);
631 rc = swrap.fns.libc_ioctl(d,
641 static int libc_listen(int sockfd, int backlog)
643 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
645 return swrap.fns.libc_listen(sockfd, backlog);
648 static int libc_vopen(const char *pathname, int flags, va_list ap)
653 swrap_load_lib_function(SWRAP_LIBC, open);
655 mode = va_arg(ap, long int);
657 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
662 static int libc_open(const char *pathname, int flags, ...)
668 fd = libc_vopen(pathname, flags, ap);
674 static int libc_pipe(int pipefd[2])
676 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
678 return swrap.fns.libc_pipe(pipefd);
681 static int libc_read(int fd, void *buf, size_t count)
683 swrap_load_lib_function(SWRAP_LIBC, read);
685 return swrap.fns.libc_read(fd, buf, count);
688 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
690 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
692 return swrap.fns.libc_readv(fd, iov, iovcnt);
695 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
697 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
699 return swrap.fns.libc_recv(sockfd, buf, len, flags);
702 static int libc_recvfrom(int sockfd,
706 struct sockaddr *src_addr,
709 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
711 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
714 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
716 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
718 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
721 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
723 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
725 return swrap.fns.libc_send(sockfd, buf, len, flags);
728 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
730 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
732 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
735 static int libc_sendto(int sockfd,
739 const struct sockaddr *dst_addr,
742 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
744 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
747 static int libc_setsockopt(int sockfd,
753 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
755 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
759 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
761 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
763 return swrap.fns.libc_signalfd(fd, mask, flags);
767 static int libc_socket(int domain, int type, int protocol)
769 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
771 return swrap.fns.libc_socket(domain, type, protocol);
774 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
776 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
778 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
781 #ifdef HAVE_TIMERFD_CREATE
782 static int libc_timerfd_create(int clockid, int flags)
784 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
786 return swrap.fns.libc_timerfd_create(clockid, flags);
790 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
792 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
794 return swrap.fns.libc_writev(fd, iov, iovcnt);
797 /*********************************************************
798 * SWRAP HELPER FUNCTIONS
799 *********************************************************/
805 static const struct in6_addr *swrap_ipv6(void)
807 static struct in6_addr v;
808 static int initialized;
816 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
825 static void set_port(int family, int prt, struct swrap_address *addr)
829 addr->sa.in.sin_port = htons(prt);
833 addr->sa.in6.sin6_port = htons(prt);
839 static size_t socket_length(int family)
843 return sizeof(struct sockaddr_in);
846 return sizeof(struct sockaddr_in6);
852 static const char *socket_wrapper_dir(void)
854 const char *s = getenv("SOCKET_WRAPPER_DIR");
858 /* TODO use realpath(3) here, when we add support for threads */
859 if (strncmp(s, "./", 2) == 0) {
863 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
867 bool socket_wrapper_enabled(void)
869 const char *s = socket_wrapper_dir();
871 return s != NULL ? true : false;
874 static unsigned int socket_wrapper_default_iface(void)
876 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
879 if (sscanf(s, "%u", &iface) == 1) {
880 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
886 return 1;/* 127.0.0.1 */
889 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
896 p = strrchr(un->sun_path, '/');
897 if (p) p++; else p = un->sun_path;
899 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
904 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
907 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
918 case SOCKET_TYPE_CHAR_TCP:
919 case SOCKET_TYPE_CHAR_UDP: {
920 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
922 if ((*len) < sizeof(*in2)) {
927 memset(in2, 0, sizeof(*in2));
928 in2->sin_family = AF_INET;
929 in2->sin_addr.s_addr = htonl((127<<24) | iface);
930 in2->sin_port = htons(prt);
936 case SOCKET_TYPE_CHAR_TCP_V6:
937 case SOCKET_TYPE_CHAR_UDP_V6: {
938 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
940 if ((*len) < sizeof(*in2)) {
945 memset(in2, 0, sizeof(*in2));
946 in2->sin6_family = AF_INET6;
947 in2->sin6_addr = *swrap_ipv6();
948 in2->sin6_addr.s6_addr[15] = iface;
949 in2->sin6_port = htons(prt);
963 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
971 if (bcast) *bcast = 0;
973 switch (inaddr->sa_family) {
975 const struct sockaddr_in *in =
976 (const struct sockaddr_in *)(const void *)inaddr;
977 unsigned int addr = ntohl(in->sin_addr.s_addr);
984 u_type = SOCKET_TYPE_CHAR_TCP;
987 u_type = SOCKET_TYPE_CHAR_UDP;
988 a_type = SOCKET_TYPE_CHAR_UDP;
989 b_type = SOCKET_TYPE_CHAR_UDP;
992 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
993 errno = ESOCKTNOSUPPORT;
997 prt = ntohs(in->sin_port);
998 if (a_type && addr == 0xFFFFFFFF) {
999 /* 255.255.255.255 only udp */
1002 iface = socket_wrapper_default_iface();
1003 } else if (b_type && addr == 0x7FFFFFFF) {
1004 /* 127.255.255.255 only udp */
1007 iface = socket_wrapper_default_iface();
1008 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1012 iface = (addr & 0x000000FF);
1014 errno = ENETUNREACH;
1017 if (bcast) *bcast = is_bcast;
1022 const struct sockaddr_in6 *in =
1023 (const struct sockaddr_in6 *)(const void *)inaddr;
1024 struct in6_addr cmp1, cmp2;
1028 type = SOCKET_TYPE_CHAR_TCP_V6;
1031 type = SOCKET_TYPE_CHAR_UDP_V6;
1034 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1035 errno = ESOCKTNOSUPPORT;
1039 /* XXX no multicast/broadcast */
1041 prt = ntohs(in->sin6_port);
1043 cmp1 = *swrap_ipv6();
1044 cmp2 = in->sin6_addr;
1045 cmp2.s6_addr[15] = 0;
1046 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1047 iface = in->sin6_addr.s6_addr[15];
1049 errno = ENETUNREACH;
1057 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1058 errno = ENETUNREACH;
1063 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1069 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1070 socket_wrapper_dir());
1071 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1072 /* the caller need to do more processing */
1076 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1077 socket_wrapper_dir(), type, iface, prt);
1078 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1083 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1092 if (bcast) *bcast = 0;
1094 switch (si->family) {
1096 const struct sockaddr_in *in =
1097 (const struct sockaddr_in *)(const void *)inaddr;
1098 unsigned int addr = ntohl(in->sin_addr.s_addr);
1104 prt = ntohs(in->sin_port);
1108 u_type = SOCKET_TYPE_CHAR_TCP;
1109 d_type = SOCKET_TYPE_CHAR_TCP;
1112 u_type = SOCKET_TYPE_CHAR_UDP;
1113 d_type = SOCKET_TYPE_CHAR_UDP;
1114 a_type = SOCKET_TYPE_CHAR_UDP;
1115 b_type = SOCKET_TYPE_CHAR_UDP;
1118 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1119 errno = ESOCKTNOSUPPORT;
1127 iface = socket_wrapper_default_iface();
1128 } else if (a_type && addr == 0xFFFFFFFF) {
1129 /* 255.255.255.255 only udp */
1132 iface = socket_wrapper_default_iface();
1133 } else if (b_type && addr == 0x7FFFFFFF) {
1134 /* 127.255.255.255 only udp */
1137 iface = socket_wrapper_default_iface();
1138 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1142 iface = (addr & 0x000000FF);
1144 errno = EADDRNOTAVAIL;
1148 /* Store the bind address for connect() */
1149 if (si->bindname.sa_socklen == 0) {
1150 struct sockaddr_in bind_in;
1151 socklen_t blen = sizeof(struct sockaddr_in);
1153 ZERO_STRUCT(bind_in);
1154 bind_in.sin_family = in->sin_family;
1155 bind_in.sin_port = in->sin_port;
1156 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1158 si->bindname.sa_socklen = blen;
1159 memcpy(&si->bindname.sa.in, &bind_in, blen);
1166 const struct sockaddr_in6 *in =
1167 (const struct sockaddr_in6 *)(const void *)inaddr;
1168 struct in6_addr cmp1, cmp2;
1172 type = SOCKET_TYPE_CHAR_TCP_V6;
1175 type = SOCKET_TYPE_CHAR_UDP_V6;
1178 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1179 errno = ESOCKTNOSUPPORT;
1183 /* XXX no multicast/broadcast */
1185 prt = ntohs(in->sin6_port);
1187 cmp1 = *swrap_ipv6();
1188 cmp2 = in->sin6_addr;
1189 cmp2.s6_addr[15] = 0;
1190 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1191 iface = socket_wrapper_default_iface();
1192 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1193 iface = in->sin6_addr.s6_addr[15];
1195 errno = EADDRNOTAVAIL;
1199 /* Store the bind address for connect() */
1200 if (si->bindname.sa_socklen == 0) {
1201 struct sockaddr_in6 bind_in;
1202 socklen_t blen = sizeof(struct sockaddr_in6);
1204 ZERO_STRUCT(bind_in);
1205 bind_in.sin6_family = in->sin6_family;
1206 bind_in.sin6_port = in->sin6_port;
1208 bind_in.sin6_addr = *swrap_ipv6();
1209 bind_in.sin6_addr.s6_addr[15] = iface;
1211 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1212 si->bindname.sa_socklen = blen;
1219 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1220 errno = EADDRNOTAVAIL;
1225 if (bcast) *bcast = is_bcast;
1227 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1233 /* handle auto-allocation of ephemeral ports */
1234 for (prt = 5001; prt < 10000; prt++) {
1235 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1236 socket_wrapper_dir(), type, iface, prt);
1237 if (stat(un->sun_path, &st) == 0) continue;
1239 set_port(si->family, prt, &si->myname);
1240 set_port(si->family, prt, &si->bindname);
1250 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1251 socket_wrapper_dir(), type, iface, prt);
1252 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1256 static struct socket_info *find_socket_info(int fd)
1258 struct socket_info *i;
1260 for (i = sockets; i; i = i->next) {
1261 struct socket_info_fd *f;
1262 for (f = i->fds; f; f = f->next) {
1273 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1275 struct socket_info *s;
1277 /* first catch invalid input */
1278 switch (sa->sa_family) {
1280 if (len < sizeof(struct sockaddr_in)) {
1286 if (len < sizeof(struct sockaddr_in6)) {
1296 for (s = sockets; s != NULL; s = s->next) {
1297 if (s->myname == NULL) {
1300 if (s->myname->sa_family != sa->sa_family) {
1303 switch (s->myname->sa_family) {
1305 struct sockaddr_in *sin1, *sin2;
1307 sin1 = (struct sockaddr_in *)s->myname;
1308 sin2 = (struct sockaddr_in *)sa;
1310 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1313 if (sin1->sin_port != sin2->sin_port) {
1316 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1326 struct sockaddr_in6 *sin1, *sin2;
1328 sin1 = (struct sockaddr_in6 *)s->myname;
1329 sin2 = (struct sockaddr_in6 *)sa;
1331 if (sin1->sin6_port != sin2->sin6_port) {
1334 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1356 static void swrap_remove_stale(int fd)
1358 struct socket_info *si = find_socket_info(fd);
1359 struct socket_info_fd *fi;
1362 for (fi = si->fds; fi; fi = fi->next) {
1364 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1365 SWRAP_DLIST_REMOVE(si->fds, fi);
1371 if (si->fds == NULL) {
1372 SWRAP_DLIST_REMOVE(sockets, si);
1377 static int sockaddr_convert_to_un(struct socket_info *si,
1378 const struct sockaddr *in_addr,
1380 struct sockaddr_un *out_addr,
1384 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1386 (void) in_len; /* unused */
1388 if (out_addr == NULL) {
1392 out->sa_family = AF_UNIX;
1393 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1394 out->sa_len = sizeof(*out_addr);
1397 switch (in_addr->sa_family) {
1399 const struct sockaddr_in *sin;
1400 if (si->family != AF_INET) {
1403 if (in_len < sizeof(struct sockaddr_in)) {
1406 sin = (const struct sockaddr_in *)in_addr;
1407 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1412 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1413 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1427 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1428 errno = ESOCKTNOSUPPORT;
1432 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1434 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1440 errno = EAFNOSUPPORT;
1441 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1445 static int sockaddr_convert_from_un(const struct socket_info *si,
1446 const struct sockaddr_un *in_addr,
1447 socklen_t un_addrlen,
1449 struct sockaddr *out_addr,
1450 socklen_t *out_addrlen)
1454 if (out_addr == NULL || out_addrlen == NULL)
1457 if (un_addrlen == 0) {
1472 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1473 errno = ESOCKTNOSUPPORT;
1476 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1477 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1478 out_addr->sa_len = *out_addrlen;
1485 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1486 errno = EAFNOSUPPORT;
1490 enum swrap_packet_type {
1492 SWRAP_CONNECT_UNREACH,
1500 SWRAP_SENDTO_UNREACH,
1511 struct swrap_file_hdr {
1513 uint16_t version_major;
1514 uint16_t version_minor;
1517 uint32_t frame_max_len;
1518 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1521 #define SWRAP_FILE_HDR_SIZE 24
1523 struct swrap_packet_frame {
1525 uint32_t micro_seconds;
1526 uint32_t recorded_length;
1527 uint32_t full_length;
1529 #define SWRAP_PACKET_FRAME_SIZE 16
1531 union swrap_packet_ip {
1535 uint16_t packet_length;
1536 uint16_t identification;
1541 uint16_t hdr_checksum;
1545 #define SWRAP_PACKET_IP_V4_SIZE 20
1548 uint8_t flow_label_high;
1549 uint16_t flow_label_low;
1550 uint16_t payload_length;
1551 uint8_t next_header;
1553 uint8_t src_addr[16];
1554 uint8_t dest_addr[16];
1556 #define SWRAP_PACKET_IP_V6_SIZE 40
1558 #define SWRAP_PACKET_IP_SIZE 40
1560 union swrap_packet_payload {
1562 uint16_t source_port;
1572 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1574 uint16_t source_port;
1579 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1586 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1593 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1595 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1597 #define SWRAP_PACKET_MIN_ALLOC \
1598 (SWRAP_PACKET_FRAME_SIZE + \
1599 SWRAP_PACKET_IP_SIZE + \
1600 SWRAP_PACKET_PAYLOAD_SIZE)
1602 static const char *swrap_pcap_init_file(void)
1604 static int initialized = 0;
1605 static const char *s = NULL;
1606 static const struct swrap_file_hdr h;
1607 static const struct swrap_packet_frame f;
1608 static const union swrap_packet_ip i;
1609 static const union swrap_packet_payload p;
1611 if (initialized == 1) {
1617 * TODO: don't use the structs use plain buffer offsets
1618 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1620 * for now make sure we disable PCAP support
1621 * if the struct has alignment!
1623 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1626 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1629 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1632 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1635 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1638 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1641 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1644 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1647 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1650 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1654 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1658 if (strncmp(s, "./", 2) == 0) {
1664 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1665 const struct sockaddr *src,
1666 const struct sockaddr *dest,
1668 const uint8_t *payload,
1670 unsigned long tcp_seqno,
1671 unsigned long tcp_ack,
1672 unsigned char tcp_ctl,
1674 size_t *_packet_len)
1678 struct swrap_packet_frame *frame;
1679 union swrap_packet_ip *ip;
1680 union swrap_packet_payload *pay;
1683 size_t nonwire_len = sizeof(*frame);
1684 size_t wire_hdr_len = 0;
1685 size_t wire_len = 0;
1686 size_t ip_hdr_len = 0;
1687 size_t icmp_hdr_len = 0;
1688 size_t icmp_truncate_len = 0;
1689 uint8_t protocol = 0, icmp_protocol = 0;
1690 const struct sockaddr_in *src_in = NULL;
1691 const struct sockaddr_in *dest_in = NULL;
1693 const struct sockaddr_in6 *src_in6 = NULL;
1694 const struct sockaddr_in6 *dest_in6 = NULL;
1699 switch (src->sa_family) {
1701 src_in = (const struct sockaddr_in *)src;
1702 dest_in = (const struct sockaddr_in *)dest;
1703 src_port = src_in->sin_port;
1704 dest_port = dest_in->sin_port;
1705 ip_hdr_len = sizeof(ip->v4);
1709 src_in6 = (const struct sockaddr_in6 *)src;
1710 dest_in6 = (const struct sockaddr_in6 *)dest;
1711 src_port = src_in6->sin6_port;
1712 dest_port = dest_in6->sin6_port;
1713 ip_hdr_len = sizeof(ip->v6);
1720 switch (socket_type) {
1722 protocol = 0x06; /* TCP */
1723 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1724 wire_len = wire_hdr_len + payload_len;
1728 protocol = 0x11; /* UDP */
1729 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1730 wire_len = wire_hdr_len + payload_len;
1738 icmp_protocol = protocol;
1739 switch (src->sa_family) {
1741 protocol = 0x01; /* ICMPv4 */
1742 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1746 protocol = 0x3A; /* ICMPv6 */
1747 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1751 if (wire_len > 64 ) {
1752 icmp_truncate_len = wire_len - 64;
1754 wire_hdr_len += icmp_hdr_len;
1755 wire_len += icmp_hdr_len;
1758 packet_len = nonwire_len + wire_len;
1759 alloc_len = packet_len;
1760 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1761 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1764 base = (uint8_t *)malloc(alloc_len);
1768 memset(base, 0x0, alloc_len);
1772 frame = (struct swrap_packet_frame *)buf;
1773 frame->seconds = tval->tv_sec;
1774 frame->micro_seconds = tval->tv_usec;
1775 frame->recorded_length = wire_len - icmp_truncate_len;
1776 frame->full_length = wire_len - icmp_truncate_len;
1777 buf += SWRAP_PACKET_FRAME_SIZE;
1779 ip = (union swrap_packet_ip *)buf;
1780 switch (src->sa_family) {
1782 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1784 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1785 ip->v4.identification = htons(0xFFFF);
1786 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1787 ip->v4.fragment = htons(0x0000);
1789 ip->v4.protocol = protocol;
1790 ip->v4.hdr_checksum = htons(0x0000);
1791 ip->v4.src_addr = src_in->sin_addr.s_addr;
1792 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1793 buf += SWRAP_PACKET_IP_V4_SIZE;
1797 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1798 ip->v6.flow_label_high = 0x00;
1799 ip->v6.flow_label_low = 0x0000;
1800 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1801 ip->v6.next_header = protocol;
1802 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1803 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1804 buf += SWRAP_PACKET_IP_V6_SIZE;
1810 pay = (union swrap_packet_payload *)buf;
1811 switch (src->sa_family) {
1813 pay->icmp4.type = 0x03; /* destination unreachable */
1814 pay->icmp4.code = 0x01; /* host unreachable */
1815 pay->icmp4.checksum = htons(0x0000);
1816 pay->icmp4.unused = htonl(0x00000000);
1817 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1819 /* set the ip header in the ICMP payload */
1820 ip = (union swrap_packet_ip *)buf;
1821 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1823 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1824 ip->v4.identification = htons(0xFFFF);
1825 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1826 ip->v4.fragment = htons(0x0000);
1828 ip->v4.protocol = icmp_protocol;
1829 ip->v4.hdr_checksum = htons(0x0000);
1830 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1831 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1832 buf += SWRAP_PACKET_IP_V4_SIZE;
1834 src_port = dest_in->sin_port;
1835 dest_port = src_in->sin_port;
1839 pay->icmp6.type = 0x01; /* destination unreachable */
1840 pay->icmp6.code = 0x03; /* address unreachable */
1841 pay->icmp6.checksum = htons(0x0000);
1842 pay->icmp6.unused = htonl(0x00000000);
1843 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1845 /* set the ip header in the ICMP payload */
1846 ip = (union swrap_packet_ip *)buf;
1847 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1848 ip->v6.flow_label_high = 0x00;
1849 ip->v6.flow_label_low = 0x0000;
1850 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1851 ip->v6.next_header = protocol;
1852 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1853 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1854 buf += SWRAP_PACKET_IP_V6_SIZE;
1856 src_port = dest_in6->sin6_port;
1857 dest_port = src_in6->sin6_port;
1863 pay = (union swrap_packet_payload *)buf;
1865 switch (socket_type) {
1867 pay->tcp.source_port = src_port;
1868 pay->tcp.dest_port = dest_port;
1869 pay->tcp.seq_num = htonl(tcp_seqno);
1870 pay->tcp.ack_num = htonl(tcp_ack);
1871 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1872 pay->tcp.control = tcp_ctl;
1873 pay->tcp.window = htons(0x7FFF);
1874 pay->tcp.checksum = htons(0x0000);
1875 pay->tcp.urg = htons(0x0000);
1876 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1881 pay->udp.source_port = src_port;
1882 pay->udp.dest_port = dest_port;
1883 pay->udp.length = htons(8 + payload_len);
1884 pay->udp.checksum = htons(0x0000);
1885 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1890 if (payload && payload_len > 0) {
1891 memcpy(buf, payload, payload_len);
1894 *_packet_len = packet_len - icmp_truncate_len;
1898 static int swrap_pcap_get_fd(const char *fname)
1902 if (fd != -1) return fd;
1904 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1906 struct swrap_file_hdr file_hdr;
1907 file_hdr.magic = 0xA1B2C3D4;
1908 file_hdr.version_major = 0x0002;
1909 file_hdr.version_minor = 0x0004;
1910 file_hdr.timezone = 0x00000000;
1911 file_hdr.sigfigs = 0x00000000;
1912 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1913 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1915 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1922 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1927 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
1928 const struct sockaddr *addr,
1929 enum swrap_packet_type type,
1930 const void *buf, size_t len,
1933 const struct sockaddr *src_addr;
1934 const struct sockaddr *dest_addr;
1935 unsigned long tcp_seqno = 0;
1936 unsigned long tcp_ack = 0;
1937 unsigned char tcp_ctl = 0;
1938 int unreachable = 0;
1942 switch (si->family) {
1954 case SWRAP_CONNECT_SEND:
1955 if (si->type != SOCK_STREAM) return NULL;
1957 src_addr = &si->myname.sa.s;
1960 tcp_seqno = si->io.pck_snd;
1961 tcp_ack = si->io.pck_rcv;
1962 tcp_ctl = 0x02; /* SYN */
1964 si->io.pck_snd += 1;
1968 case SWRAP_CONNECT_RECV:
1969 if (si->type != SOCK_STREAM) return NULL;
1971 dest_addr = &si->myname.sa.s;
1974 tcp_seqno = si->io.pck_rcv;
1975 tcp_ack = si->io.pck_snd;
1976 tcp_ctl = 0x12; /** SYN,ACK */
1978 si->io.pck_rcv += 1;
1982 case SWRAP_CONNECT_UNREACH:
1983 if (si->type != SOCK_STREAM) return NULL;
1985 dest_addr = &si->myname.sa.s;
1988 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1989 tcp_seqno = si->io.pck_snd - 1;
1990 tcp_ack = si->io.pck_rcv;
1991 tcp_ctl = 0x02; /* SYN */
1996 case SWRAP_CONNECT_ACK:
1997 if (si->type != SOCK_STREAM) return NULL;
1999 src_addr = &si->myname.sa.s;
2002 tcp_seqno = si->io.pck_snd;
2003 tcp_ack = si->io.pck_rcv;
2004 tcp_ctl = 0x10; /* ACK */
2008 case SWRAP_ACCEPT_SEND:
2009 if (si->type != SOCK_STREAM) return NULL;
2011 dest_addr = &si->myname.sa.s;
2014 tcp_seqno = si->io.pck_rcv;
2015 tcp_ack = si->io.pck_snd;
2016 tcp_ctl = 0x02; /* SYN */
2018 si->io.pck_rcv += 1;
2022 case SWRAP_ACCEPT_RECV:
2023 if (si->type != SOCK_STREAM) return NULL;
2025 src_addr = &si->myname.sa.s;
2028 tcp_seqno = si->io.pck_snd;
2029 tcp_ack = si->io.pck_rcv;
2030 tcp_ctl = 0x12; /* SYN,ACK */
2032 si->io.pck_snd += 1;
2036 case SWRAP_ACCEPT_ACK:
2037 if (si->type != SOCK_STREAM) return NULL;
2039 dest_addr = &si->myname.sa.s;
2042 tcp_seqno = si->io.pck_rcv;
2043 tcp_ack = si->io.pck_snd;
2044 tcp_ctl = 0x10; /* ACK */
2049 src_addr = &si->myname.sa.s;
2050 dest_addr = &si->peername.sa.s;
2052 tcp_seqno = si->io.pck_snd;
2053 tcp_ack = si->io.pck_rcv;
2054 tcp_ctl = 0x18; /* PSH,ACK */
2056 si->io.pck_snd += len;
2060 case SWRAP_SEND_RST:
2061 dest_addr = &si->myname.sa.s;
2062 src_addr = &si->peername.sa.s;
2064 if (si->type == SOCK_DGRAM) {
2065 return swrap_pcap_marshall_packet(si,
2067 SWRAP_SENDTO_UNREACH,
2073 tcp_seqno = si->io.pck_rcv;
2074 tcp_ack = si->io.pck_snd;
2075 tcp_ctl = 0x14; /** RST,ACK */
2079 case SWRAP_PENDING_RST:
2080 dest_addr = &si->myname.sa.s;
2081 src_addr = &si->peername.sa.s;
2083 if (si->type == SOCK_DGRAM) {
2087 tcp_seqno = si->io.pck_rcv;
2088 tcp_ack = si->io.pck_snd;
2089 tcp_ctl = 0x14; /* RST,ACK */
2094 dest_addr = &si->myname.sa.s;
2095 src_addr = &si->peername.sa.s;
2097 tcp_seqno = si->io.pck_rcv;
2098 tcp_ack = si->io.pck_snd;
2099 tcp_ctl = 0x18; /* PSH,ACK */
2101 si->io.pck_rcv += len;
2105 case SWRAP_RECV_RST:
2106 dest_addr = &si->myname.sa.s;
2107 src_addr = &si->peername.sa.s;
2109 if (si->type == SOCK_DGRAM) {
2113 tcp_seqno = si->io.pck_rcv;
2114 tcp_ack = si->io.pck_snd;
2115 tcp_ctl = 0x14; /* RST,ACK */
2120 src_addr = &si->myname.sa.s;
2123 si->io.pck_snd += len;
2127 case SWRAP_SENDTO_UNREACH:
2128 dest_addr = &si->myname.sa.s;
2135 case SWRAP_RECVFROM:
2136 dest_addr = &si->myname.sa.s;
2139 si->io.pck_rcv += len;
2143 case SWRAP_CLOSE_SEND:
2144 if (si->type != SOCK_STREAM) return NULL;
2146 src_addr = &si->myname.sa.s;
2147 dest_addr = &si->peername.sa.s;
2149 tcp_seqno = si->io.pck_snd;
2150 tcp_ack = si->io.pck_rcv;
2151 tcp_ctl = 0x11; /* FIN, ACK */
2153 si->io.pck_snd += 1;
2157 case SWRAP_CLOSE_RECV:
2158 if (si->type != SOCK_STREAM) return NULL;
2160 dest_addr = &si->myname.sa.s;
2161 src_addr = &si->peername.sa.s;
2163 tcp_seqno = si->io.pck_rcv;
2164 tcp_ack = si->io.pck_snd;
2165 tcp_ctl = 0x11; /* FIN,ACK */
2167 si->io.pck_rcv += 1;
2171 case SWRAP_CLOSE_ACK:
2172 if (si->type != SOCK_STREAM) return NULL;
2174 src_addr = &si->myname.sa.s;
2175 dest_addr = &si->peername.sa.s;
2177 tcp_seqno = si->io.pck_snd;
2178 tcp_ack = si->io.pck_rcv;
2179 tcp_ctl = 0x10; /* ACK */
2186 swrapGetTimeOfDay(&tv);
2188 return swrap_pcap_packet_init(&tv,
2192 (const uint8_t *)buf,
2201 static void swrap_pcap_dump_packet(struct socket_info *si,
2202 const struct sockaddr *addr,
2203 enum swrap_packet_type type,
2204 const void *buf, size_t len)
2206 const char *file_name;
2208 size_t packet_len = 0;
2211 file_name = swrap_pcap_init_file();
2216 packet = swrap_pcap_marshall_packet(si,
2222 if (packet == NULL) {
2226 fd = swrap_pcap_get_fd(file_name);
2228 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2237 /****************************************************************************
2239 ***************************************************************************/
2241 #ifdef HAVE_SIGNALFD
2242 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2246 rc = libc_signalfd(fd, mask, flags);
2248 swrap_remove_stale(fd);
2254 int signalfd(int fd, const sigset_t *mask, int flags)
2256 return swrap_signalfd(fd, mask, flags);
2260 /****************************************************************************
2262 ***************************************************************************/
2264 static int swrap_socket(int family, int type, int protocol)
2266 struct socket_info *si;
2267 struct socket_info_fd *fi;
2269 int real_type = type;
2272 * Remove possible addition flags passed to socket() so
2273 * do not fail checking the type.
2274 * See https://lwn.net/Articles/281965/
2277 real_type &= ~SOCK_CLOEXEC;
2279 #ifdef SOCK_NONBLOCK
2280 real_type &= ~SOCK_NONBLOCK;
2283 if (!socket_wrapper_enabled()) {
2284 return libc_socket(family, type, protocol);
2294 return libc_socket(family, type, protocol);
2296 errno = EAFNOSUPPORT;
2300 switch (real_type) {
2306 errno = EPROTONOSUPPORT;
2314 if (real_type == SOCK_STREAM) {
2319 if (real_type == SOCK_DGRAM) {
2324 errno = EPROTONOSUPPORT;
2329 * We must call libc_socket with type, from the caller, not the version
2330 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2332 fd = libc_socket(AF_UNIX, type, 0);
2338 /* Check if we have a stale fd and remove it */
2339 si = find_socket_info(fd);
2341 swrap_remove_stale(fd);
2344 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2345 memset(si, 0, sizeof(struct socket_info));
2351 si->family = family;
2353 /* however, the rest of the socket_wrapper code expects just
2354 * the type, not the flags */
2355 si->type = real_type;
2356 si->protocol = protocol;
2359 * Setup myname so getsockname() can succeed to find out the socket
2362 switch(si->family) {
2364 struct sockaddr_in sin = {
2365 .sin_family = AF_INET,
2368 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2369 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2373 struct sockaddr_in6 sin6 = {
2374 .sin6_family = AF_INET6,
2377 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2378 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2387 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2396 SWRAP_DLIST_ADD(si->fds, fi);
2397 SWRAP_DLIST_ADD(sockets, si);
2402 int socket(int family, int type, int protocol)
2404 return swrap_socket(family, type, protocol);
2407 /****************************************************************************
2409 ***************************************************************************/
2411 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2415 rc = libc_socketpair(family, type, protocol, sv);
2417 swrap_remove_stale(sv[0]);
2418 swrap_remove_stale(sv[1]);
2424 int socketpair(int family, int type, int protocol, int sv[2])
2426 return swrap_socketpair(family, type, protocol, sv);
2429 /****************************************************************************
2431 ***************************************************************************/
2433 #ifdef HAVE_TIMERFD_CREATE
2434 static int swrap_timerfd_create(int clockid, int flags)
2438 fd = libc_timerfd_create(clockid, flags);
2440 swrap_remove_stale(fd);
2446 int timerfd_create(int clockid, int flags)
2448 return swrap_timerfd_create(clockid, flags);
2452 /****************************************************************************
2454 ***************************************************************************/
2456 static int swrap_pipe(int pipefd[2])
2460 rc = libc_pipe(pipefd);
2462 swrap_remove_stale(pipefd[0]);
2463 swrap_remove_stale(pipefd[1]);
2469 int pipe(int pipefd[2])
2471 return swrap_pipe(pipefd);
2474 /****************************************************************************
2476 ***************************************************************************/
2478 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2480 struct socket_info *parent_si, *child_si;
2481 struct socket_info_fd *child_fi;
2483 struct swrap_address un_addr = {
2484 .sa_socklen = sizeof(struct sockaddr_un),
2486 struct swrap_address un_my_addr = {
2487 .sa_socklen = sizeof(struct sockaddr_un),
2489 struct swrap_address in_addr = {
2490 .sa_socklen = sizeof(struct sockaddr_storage),
2492 struct swrap_address in_my_addr = {
2493 .sa_socklen = sizeof(struct sockaddr_storage),
2497 parent_si = find_socket_info(s);
2499 return libc_accept(s, addr, addrlen);
2503 * assume out sockaddr have the same size as the in parent
2506 in_addr.sa_socklen = socket_length(parent_si->family);
2507 if (in_addr.sa_socklen <= 0) {
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);
2523 ret = sockaddr_convert_from_un(parent_si,
2528 &in_addr.sa_socklen);
2534 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2535 memset(child_si, 0, sizeof(struct socket_info));
2537 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2538 if (child_fi == NULL) {
2547 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2549 child_si->family = parent_si->family;
2550 child_si->type = parent_si->type;
2551 child_si->protocol = parent_si->protocol;
2552 child_si->bound = 1;
2553 child_si->is_server = 1;
2554 child_si->connected = 1;
2556 child_si->peername = (struct swrap_address) {
2557 .sa_socklen = in_addr.sa_socklen,
2559 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2561 if (addr != NULL && addrlen != NULL) {
2562 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2564 memcpy(addr, &in_addr.sa.ss, copy_len);
2566 *addrlen = in_addr.sa_socklen;
2569 ret = libc_getsockname(fd,
2571 &un_my_addr.sa_socklen);
2579 ret = sockaddr_convert_from_un(child_si,
2581 un_my_addr.sa_socklen,
2584 &in_my_addr.sa_socklen);
2592 SWRAP_LOG(SWRAP_LOG_TRACE,
2593 "accept() path=%s, fd=%d",
2594 un_my_addr.sa.un.sun_path, s);
2596 child_si->myname = (struct swrap_address) {
2597 .sa_socklen = in_my_addr.sa_socklen,
2599 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2601 SWRAP_DLIST_ADD(sockets, child_si);
2604 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2605 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2606 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2612 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2613 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2615 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2618 return swrap_accept(s, addr, (socklen_t *)addrlen);
2621 static int autobind_start_init;
2622 static int autobind_start;
2624 /* using sendto() or connect() on an unbound socket would give the
2625 recipient no way to reply, as unlike UDP and TCP, a unix domain
2626 socket can't auto-assign ephemeral port numbers, so we need to
2628 Note: this might change the family from ipv6 to ipv4
2630 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2632 struct swrap_address un_addr = {
2633 .sa_socklen = sizeof(struct sockaddr_un),
2641 if (autobind_start_init != 1) {
2642 autobind_start_init = 1;
2643 autobind_start = getpid();
2644 autobind_start %= 50000;
2645 autobind_start += 10000;
2648 un_addr.sa.un.sun_family = AF_UNIX;
2652 struct sockaddr_in in;
2656 type = SOCKET_TYPE_CHAR_TCP;
2659 type = SOCKET_TYPE_CHAR_UDP;
2662 errno = ESOCKTNOSUPPORT;
2666 memset(&in, 0, sizeof(in));
2667 in.sin_family = AF_INET;
2668 in.sin_addr.s_addr = htonl(127<<24 |
2669 socket_wrapper_default_iface());
2671 si->myname = (struct swrap_address) {
2672 .sa_socklen = sizeof(in),
2674 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2679 struct sockaddr_in6 in6;
2681 if (si->family != family) {
2682 errno = ENETUNREACH;
2688 type = SOCKET_TYPE_CHAR_TCP_V6;
2691 type = SOCKET_TYPE_CHAR_UDP_V6;
2694 errno = ESOCKTNOSUPPORT;
2698 memset(&in6, 0, sizeof(in6));
2699 in6.sin6_family = AF_INET6;
2700 in6.sin6_addr = *swrap_ipv6();
2701 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2703 si->myname = (struct swrap_address) {
2704 .sa_socklen = sizeof(in6),
2706 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2711 errno = ESOCKTNOSUPPORT;
2715 if (autobind_start > 60000) {
2716 autobind_start = 10000;
2719 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2720 port = autobind_start + i;
2721 snprintf(un_addr.sa.un.sun_path, un_addr.sa_socklen,
2722 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2723 type, socket_wrapper_default_iface(), port);
2724 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2726 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2727 if (ret == -1) return ret;
2729 si->un_addr = un_addr.sa.un;
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_pcap_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 = (struct swrap_address) {
2812 .sa_socklen = addrlen,
2815 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2819 * When we connect() on a socket than we have to bind the
2820 * outgoing connection on the interface we use for the
2821 * transport. We already bound it on the right interface
2822 * but here we have to update the name so getsockname()
2823 * returns correct information.
2825 if (si->bindname.sa_socklen > 0) {
2826 si->myname = (struct swrap_address) {
2827 .sa_socklen = si->bindname.sa_socklen,
2830 memcpy(&si->myname.sa.ss,
2831 &si->bindname.sa.ss,
2832 si->bindname.sa_socklen);
2834 /* Cleanup bindname */
2835 si->bindname = (struct swrap_address) {
2840 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2841 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2843 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2849 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2851 return swrap_connect(s, serv_addr, addrlen);
2854 /****************************************************************************
2856 ***************************************************************************/
2858 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2861 struct swrap_address un_addr = {
2862 .sa_socklen = sizeof(struct sockaddr_un),
2864 struct socket_info *si = find_socket_info(s);
2871 return libc_bind(s, myaddr, addrlen);
2874 switch (si->family) {
2876 const struct sockaddr_in *sin;
2877 if (addrlen < sizeof(struct sockaddr_in)) {
2878 bind_error = EINVAL;
2882 sin = (const struct sockaddr_in *)myaddr;
2884 if (sin->sin_family != AF_INET) {
2885 bind_error = EAFNOSUPPORT;
2888 /* special case for AF_UNSPEC */
2889 if (sin->sin_family == AF_UNSPEC &&
2890 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2899 const struct sockaddr_in6 *sin6;
2900 if (addrlen < sizeof(struct sockaddr_in6)) {
2901 bind_error = EINVAL;
2905 sin6 = (const struct sockaddr_in6 *)myaddr;
2907 if (sin6->sin6_family != AF_INET6) {
2908 bind_error = EAFNOSUPPORT;
2915 bind_error = EINVAL;
2919 if (bind_error != 0) {
2925 in_use = check_addr_port_in_use(myaddr, addrlen);
2932 si->myname.sa_socklen = addrlen;
2933 memcpy(&si->myname.sa.ss, myaddr, addrlen);
2935 ret = sockaddr_convert_to_un(si,
2941 if (ret == -1) return -1;
2943 unlink(un_addr.sa.un.sun_path);
2945 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
2947 SWRAP_LOG(SWRAP_LOG_TRACE,
2948 "bind() path=%s, fd=%d",
2949 un_addr.sa_un.sun_path, s);
2958 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2960 return swrap_bind(s, myaddr, addrlen);
2963 /****************************************************************************
2965 ***************************************************************************/
2967 #ifdef HAVE_BINDRESVPORT
2968 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2970 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2972 struct swrap_address myaddr = {
2973 .sa_socklen = sizeof(struct sockaddr_storage),
2976 static uint16_t port;
2981 #define SWRAP_STARTPORT 600
2982 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2983 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2986 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2990 salen = myaddr.sa_socklen;
2993 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
2999 memset(&myaddr.sa.ss, 0, salen);
3004 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3007 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3009 salen = sizeof(struct sockaddr_in);
3010 sinp->sin_port = htons(port);
3014 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
3016 salen = sizeof(struct sockaddr_in6);
3017 sin6p->sin6_port = htons(port);
3021 errno = EAFNOSUPPORT;
3026 if (port > SWRAP_ENDPORT) {
3027 port = SWRAP_STARTPORT;
3030 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3031 if (rc == 0 || errno != EADDRINUSE) {
3039 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3041 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3045 /****************************************************************************
3047 ***************************************************************************/
3049 static int swrap_listen(int s, int backlog)
3052 struct socket_info *si = find_socket_info(s);
3055 return libc_listen(s, backlog);
3058 ret = libc_listen(s, backlog);
3063 int listen(int s, int backlog)
3065 return swrap_listen(s, backlog);
3068 /****************************************************************************
3070 ***************************************************************************/
3072 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3076 ret = libc_vopen(pathname, flags, ap);
3079 * There are methods for closing descriptors (libc-internal code
3080 * paths, direct syscalls) which close descriptors in ways that
3081 * we can't intercept, so try to recover when we notice that
3084 swrap_remove_stale(ret);
3089 int open(const char *pathname, int flags, ...)
3094 va_start(ap, flags);
3095 fd = swrap_vopen(pathname, flags, ap);
3101 /****************************************************************************
3103 ***************************************************************************/
3105 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3107 struct socket_info *si = find_socket_info(s);
3111 return libc_getpeername(s, name, addrlen);
3114 if (si->peername.sa_socklen == 0)
3120 len = MIN(*addrlen, si->peername.sa_socklen);
3125 memcpy(name, &si->peername.sa.ss, len);
3126 *addrlen = si->peername.sa_socklen;
3131 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3132 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3134 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3137 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3140 /****************************************************************************
3142 ***************************************************************************/
3144 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3146 struct socket_info *si = find_socket_info(s);
3150 return libc_getsockname(s, name, addrlen);
3153 len = MIN(*addrlen, si->myname.sa_socklen);
3158 memcpy(name, &si->myname.sa.ss, len);
3159 *addrlen = si->myname.sa_socklen;
3164 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3165 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3167 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3170 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3173 /****************************************************************************
3175 ***************************************************************************/
3178 # ifdef SO_PROTOTYPE /* The Solaris name */
3179 # define SO_PROTOCOL SO_PROTOTYPE
3180 # endif /* SO_PROTOTYPE */
3181 #endif /* SO_PROTOCOL */
3183 static int swrap_getsockopt(int s, int level, int optname,
3184 void *optval, socklen_t *optlen)
3186 struct socket_info *si = find_socket_info(s);
3189 return libc_getsockopt(s,
3196 if (level == SOL_SOCKET) {
3200 if (optval == NULL || optlen == NULL ||
3201 *optlen < (socklen_t)sizeof(int)) {
3206 *optlen = sizeof(int);
3207 *(int *)optval = si->family;
3209 #endif /* SO_DOMAIN */
3213 if (optval == NULL || optlen == NULL ||
3214 *optlen < (socklen_t)sizeof(int)) {
3219 *optlen = sizeof(int);
3220 *(int *)optval = si->protocol;
3222 #endif /* SO_PROTOCOL */
3224 if (optval == NULL || optlen == NULL ||
3225 *optlen < (socklen_t)sizeof(int)) {
3230 *optlen = sizeof(int);
3231 *(int *)optval = si->type;
3234 return libc_getsockopt(s,
3242 errno = ENOPROTOOPT;
3246 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3247 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3249 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3252 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3255 /****************************************************************************
3257 ***************************************************************************/
3259 static int swrap_setsockopt(int s, int level, int optname,
3260 const void *optval, socklen_t optlen)
3262 struct socket_info *si = find_socket_info(s);
3265 return libc_setsockopt(s,
3272 if (level == SOL_SOCKET) {
3273 return libc_setsockopt(s,
3280 switch (si->family) {
3282 if (level == IPPROTO_IP) {
3284 if (optname == IP_PKTINFO) {
3285 si->pktinfo = AF_INET;
3287 #endif /* IP_PKTINFO */
3292 if (level == IPPROTO_IPV6) {
3293 #ifdef IPV6_RECVPKTINFO
3294 if (optname == IPV6_RECVPKTINFO) {
3295 si->pktinfo = AF_INET6;
3297 #endif /* IPV6_PKTINFO */
3302 errno = ENOPROTOOPT;
3307 int setsockopt(int s, int level, int optname,
3308 const void *optval, socklen_t optlen)
3310 return swrap_setsockopt(s, level, optname, optval, optlen);
3313 /****************************************************************************
3315 ***************************************************************************/
3317 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3319 struct socket_info *si = find_socket_info(s);
3325 return libc_vioctl(s, r, va);
3330 rc = libc_vioctl(s, r, va);
3334 value = *((int *)va_arg(ap, int *));
3336 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3337 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3338 } else if (value == 0) { /* END OF FILE */
3339 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3349 #ifdef HAVE_IOCTL_INT
3350 int ioctl(int s, int r, ...)
3352 int ioctl(int s, unsigned long int r, ...)
3360 rc = swrap_vioctl(s, (unsigned long int) r, va);
3371 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3374 # ifdef _ALIGN /* BSD */
3375 #define CMSG_ALIGN _ALIGN
3377 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3378 # endif /* _ALIGN */
3379 #endif /* CMSG_ALIGN */
3382 * @brief Add a cmsghdr to a msghdr.
3384 * This is an function to add any type of cmsghdr. It will operate on the
3385 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3386 * the buffer position after the added cmsg element. Hence, this function is
3387 * intended to be used with an intermediate msghdr and not on the original
3388 * one handed in by the client.
3390 * @param[in] msg The msghdr to which to add the cmsg.
3392 * @param[in] level The cmsg level to set.
3394 * @param[in] type The cmsg type to set.
3396 * @param[in] data The cmsg data to set.
3398 * @param[in] len the length of the data to set.
3400 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3406 size_t cmlen = CMSG_LEN(len);
3407 size_t cmspace = CMSG_SPACE(len);
3408 uint8_t cmbuf[cmspace];
3409 void *cast_ptr = (void *)cmbuf;
3410 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3413 memset(cmbuf, 0, cmspace);
3415 if (msg->msg_controllen < cmlen) {
3416 cmlen = msg->msg_controllen;
3417 msg->msg_flags |= MSG_CTRUNC;
3420 if (msg->msg_controllen < cmspace) {
3421 cmspace = msg->msg_controllen;
3425 * We copy the full input data into an intermediate cmsghdr first
3426 * in order to more easily cope with truncation.
3428 cm->cmsg_len = cmlen;
3429 cm->cmsg_level = level;
3430 cm->cmsg_type = type;
3431 memcpy(CMSG_DATA(cm), data, len);
3434 * We now copy the possibly truncated buffer.
3435 * We copy cmlen bytes, but consume cmspace bytes,
3436 * leaving the possible padding uninitialiazed.
3438 p = (uint8_t *)msg->msg_control;
3439 memcpy(p, cm, cmlen);
3441 msg->msg_control = p;
3442 msg->msg_controllen -= cmspace;
3447 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3450 /* Add packet info */
3451 switch (si->pktinfo) {
3452 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3454 struct sockaddr_in *sin;
3455 #if defined(HAVE_STRUCT_IN_PKTINFO)
3456 struct in_pktinfo pkt;
3457 #elif defined(IP_RECVDSTADDR)
3461 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3462 sin = &si->bindname.sa.in;
3464 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3467 sin = &si->myname.sa.in;
3472 #if defined(HAVE_STRUCT_IN_PKTINFO)
3473 pkt.ipi_ifindex = socket_wrapper_default_iface();
3474 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3475 #elif defined(IP_RECVDSTADDR)
3476 pkt = sin->sin_addr;
3479 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3484 #endif /* IP_PKTINFO */
3485 #if defined(HAVE_IPV6)
3487 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3488 struct sockaddr_in6 *sin6;
3489 struct in6_pktinfo pkt6;
3491 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3492 sin6 = &si->bindname.sa.in6;
3494 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3497 sin6 = &si->myname.sa.in6;
3502 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3503 pkt6.ipi6_addr = sin6->sin6_addr;
3505 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3506 &pkt6, sizeof(pkt6));
3507 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3511 #endif /* IPV6_PKTINFO */
3519 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3520 struct msghdr *omsg)
3524 if (si->pktinfo > 0) {
3525 rc = swrap_msghdr_add_pktinfo(si, omsg);
3531 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3533 size_t *cm_data_space);
3534 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3536 size_t *cm_data_space);
3538 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3540 size_t *cm_data_space) {
3541 struct cmsghdr *cmsg;
3545 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3549 for (cmsg = CMSG_FIRSTHDR(msg);
3551 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3552 switch (cmsg->cmsg_level) {
3554 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3559 rc = swrap_sendmsg_copy_cmsg(cmsg,
3569 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3571 size_t *cm_data_space)
3578 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3580 p = realloc((*cm_data), cmspace);
3586 p = (*cm_data) + (*cm_data_space);
3587 *cm_data_space = cmspace;
3589 memcpy(p, cmsg, cmsg->cmsg_len);
3594 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3596 size_t *cm_data_space);
3599 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3601 size_t *cm_data_space)
3605 switch(cmsg->cmsg_type) {
3608 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3615 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3627 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3629 size_t *cm_data_space)
3631 (void)cmsg; /* unused */
3632 (void)cm_data; /* unused */
3633 (void)cm_data_space; /* unused */
3636 * Passing a IP pktinfo to a unix socket might be rejected by the
3637 * Kernel, at least on FreeBSD. So skip this cmsg.
3641 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3643 static ssize_t swrap_sendmsg_before(int fd,
3644 struct socket_info *si,
3646 struct iovec *tmp_iov,
3647 struct sockaddr_un *tmp_un,
3648 const struct sockaddr_un **to_un,
3649 const struct sockaddr **to,
3667 if (!si->connected) {
3672 if (msg->msg_iovlen == 0) {
3676 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3678 nlen = len + msg->msg_iov[i].iov_len;
3679 if (nlen > SOCKET_MAX_PACKET) {
3683 msg->msg_iovlen = i;
3684 if (msg->msg_iovlen == 0) {
3685 *tmp_iov = msg->msg_iov[0];
3686 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3687 msg->msg_iov = tmp_iov;
3688 msg->msg_iovlen = 1;
3693 if (si->connected) {
3694 if (msg->msg_name) {
3699 const struct sockaddr *msg_name;
3700 msg_name = (const struct sockaddr *)msg->msg_name;
3702 if (msg_name == NULL) {
3708 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3710 if (ret == -1) return -1;
3718 msg->msg_name = tmp_un;
3719 msg->msg_namelen = sizeof(*tmp_un);
3722 if (si->bound == 0) {
3723 ret = swrap_auto_bind(fd, si, si->family);
3725 if (errno == ENOTSOCK) {
3726 swrap_remove_stale(fd);
3729 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3735 if (!si->defer_connect) {
3739 ret = sockaddr_convert_to_un(si,
3741 si->peername.sa_socklen,
3745 if (ret == -1) return -1;
3747 ret = libc_connect(fd,
3748 (struct sockaddr *)(void *)tmp_un,
3751 /* to give better errors */
3752 if (ret == -1 && errno == ENOENT) {
3753 errno = EHOSTUNREACH;
3760 si->defer_connect = 0;
3763 errno = EHOSTUNREACH;
3767 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3768 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3769 uint8_t *cmbuf = NULL;
3772 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3779 msg->msg_controllen = 0;
3780 msg->msg_control = NULL;
3781 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3782 memcpy(msg->msg_control, cmbuf, cmlen);
3783 msg->msg_controllen = cmlen;
3792 static void swrap_sendmsg_after(int fd,
3793 struct socket_info *si,
3795 const struct sockaddr *to,
3798 int saved_errno = errno;
3805 /* to give better errors */
3807 if (saved_errno == ENOENT) {
3808 saved_errno = EHOSTUNREACH;
3809 } else if (saved_errno == ENOTSOCK) {
3810 /* If the fd is not a socket, remove it */
3811 swrap_remove_stale(fd);
3815 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3816 avail += msg->msg_iov[i].iov_len;
3820 remain = MIN(80, avail);
3825 /* we capture it as one single packet */
3826 buf = (uint8_t *)malloc(remain);
3828 /* we just not capture the packet */
3829 errno = saved_errno;
3833 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3834 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3836 msg->msg_iov[i].iov_base,
3839 remain -= this_time;
3846 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3847 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3849 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3854 if (si->connected) {
3855 to = &si->peername.sa.s;
3858 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3859 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3861 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3867 errno = saved_errno;
3870 static int swrap_recvmsg_before(int fd,
3871 struct socket_info *si,
3873 struct iovec *tmp_iov)
3878 (void)fd; /* unused */
3882 if (!si->connected) {
3887 if (msg->msg_iovlen == 0) {
3891 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3893 nlen = len + msg->msg_iov[i].iov_len;
3894 if (nlen > SOCKET_MAX_PACKET) {
3898 msg->msg_iovlen = i;
3899 if (msg->msg_iovlen == 0) {
3900 *tmp_iov = msg->msg_iov[0];
3901 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3902 msg->msg_iov = tmp_iov;
3903 msg->msg_iovlen = 1;
3908 if (msg->msg_name == NULL) {
3913 if (msg->msg_iovlen == 0) {
3917 if (si->bound == 0) {
3918 ret = swrap_auto_bind(fd, si, si->family);
3921 * When attempting to read or write to a
3922 * descriptor, if an underlying autobind fails
3923 * because it's not a socket, stop intercepting
3924 * uses of that descriptor.
3926 if (errno == ENOTSOCK) {
3927 swrap_remove_stale(fd);
3930 SWRAP_LOG(SWRAP_LOG_ERROR,
3931 "swrap_recvmsg_before failed");
3938 errno = EHOSTUNREACH;
3945 static int swrap_recvmsg_after(int fd,
3946 struct socket_info *si,
3948 const struct sockaddr_un *un_addr,
3949 socklen_t un_addrlen,
3952 int saved_errno = errno;
3954 uint8_t *buf = NULL;
3960 /* to give better errors */
3962 if (saved_errno == ENOENT) {
3963 saved_errno = EHOSTUNREACH;
3964 } else if (saved_errno == ENOTSOCK) {
3965 /* If the fd is not a socket, remove it */
3966 swrap_remove_stale(fd);
3970 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3971 avail += msg->msg_iov[i].iov_len;
3980 remain = MIN(80, avail);
3985 /* we capture it as one single packet */
3986 buf = (uint8_t *)malloc(remain);
3988 /* we just not capture the packet */
3989 errno = saved_errno;
3993 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3994 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3996 msg->msg_iov[i].iov_base,
3999 remain -= this_time;
4004 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4005 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4006 } else if (ret == 0) { /* END OF FILE */
4007 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4008 } else if (ret > 0) {
4009 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4018 if (un_addr != NULL) {
4019 rc = sockaddr_convert_from_un(si,
4029 swrap_pcap_dump_packet(si,
4035 swrap_pcap_dump_packet(si,
4048 errno = saved_errno;
4050 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4052 msg->msg_controllen > 0 &&
4053 msg->msg_control != NULL) {
4054 rc = swrap_msghdr_add_socket_info(si, msg);
4064 /****************************************************************************
4066 ***************************************************************************/
4068 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4069 struct sockaddr *from, socklen_t *fromlen)
4071 struct swrap_address from_addr = {
4072 .sa_socklen = sizeof(struct sockaddr_un),
4075 struct socket_info *si = find_socket_info(s);
4076 struct swrap_address saddr = {
4077 .sa_socklen = sizeof(struct sockaddr_storage),
4084 return libc_recvfrom(s,
4096 if (from != NULL && fromlen != NULL) {
4097 msg.msg_name = from; /* optional address */
4098 msg.msg_namelen = *fromlen; /* size of address */
4100 msg.msg_name = &saddr.sa.s; /* optional address */
4101 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4103 msg.msg_iov = &tmp; /* scatter/gather array */
4104 msg.msg_iovlen = 1; /* # elements in msg_iov */
4105 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4106 msg.msg_control = NULL; /* ancillary data, see below */
4107 msg.msg_controllen = 0; /* ancillary data buffer len */
4108 msg.msg_flags = 0; /* flags on received message */
4111 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4116 buf = msg.msg_iov[0].iov_base;
4117 len = msg.msg_iov[0].iov_len;
4119 ret = libc_recvfrom(s,
4124 &from_addr.sa_socklen);
4129 tret = swrap_recvmsg_after(s,
4133 from_addr.sa_socklen,
4139 if (from != NULL && fromlen != NULL) {
4140 *fromlen = msg.msg_namelen;
4146 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4147 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4148 struct sockaddr *from, Psocklen_t fromlen)
4150 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4151 struct sockaddr *from, socklen_t *fromlen)
4154 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4157 /****************************************************************************
4159 ***************************************************************************/
4161 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4162 const struct sockaddr *to, socklen_t tolen)
4166 struct swrap_address un_addr = {
4167 .sa_socklen = sizeof(struct sockaddr_un),
4169 const struct sockaddr_un *to_un = NULL;
4172 struct socket_info *si = find_socket_info(s);
4176 return libc_sendto(s, buf, len, flags, to, tolen);
4179 tmp.iov_base = discard_const_p(char, buf);
4183 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4184 msg.msg_namelen = tolen; /* size of address */
4185 msg.msg_iov = &tmp; /* scatter/gather array */
4186 msg.msg_iovlen = 1; /* # elements in msg_iov */
4187 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4188 msg.msg_control = NULL; /* ancillary data, see below */
4189 msg.msg_controllen = 0; /* ancillary data buffer len */
4190 msg.msg_flags = 0; /* flags on received message */
4193 rc = swrap_sendmsg_before(s,
4205 buf = msg.msg_iov[0].iov_base;
4206 len = msg.msg_iov[0].iov_len;
4211 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4214 type = SOCKET_TYPE_CHAR_UDP;
4216 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4217 snprintf(un_addr.sa.un.sun_path,
4218 sizeof(un_addr.sa.un.sun_path),
4220 socket_wrapper_dir(), type, iface, prt);
4221 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4223 /* ignore the any errors in broadcast sends */
4229 un_addr.sa_socklen);
4232 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4237 ret = libc_sendto(s,
4241 (struct sockaddr *)msg.msg_name,
4244 swrap_sendmsg_after(s, si, &msg, to, ret);
4249 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4250 const struct sockaddr *to, socklen_t tolen)
4252 return swrap_sendto(s, buf, len, flags, to, tolen);
4255 /****************************************************************************
4257 ***************************************************************************/
4259 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4261 struct socket_info *si;
4263 struct swrap_address saddr = {
4264 .sa_socklen = sizeof(struct sockaddr_storage),
4270 si = find_socket_info(s);
4272 return libc_recv(s, buf, len, flags);
4279 msg.msg_name = &saddr.sa.s; /* optional address */
4280 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4281 msg.msg_iov = &tmp; /* scatter/gather array */
4282 msg.msg_iovlen = 1; /* # elements in msg_iov */
4283 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4284 msg.msg_control = NULL; /* ancillary data, see below */
4285 msg.msg_controllen = 0; /* ancillary data buffer len */
4286 msg.msg_flags = 0; /* flags on received message */
4289 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4294 buf = msg.msg_iov[0].iov_base;
4295 len = msg.msg_iov[0].iov_len;
4297 ret = libc_recv(s, buf, len, flags);
4299 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4307 ssize_t recv(int s, void *buf, size_t len, int flags)
4309 return swrap_recv(s, buf, len, flags);
4312 /****************************************************************************
4314 ***************************************************************************/
4316 static ssize_t swrap_read(int s, void *buf, size_t len)
4318 struct socket_info *si;
4321 struct swrap_address saddr = {
4322 .sa_socklen = sizeof(struct sockaddr_storage),
4327 si = find_socket_info(s);
4329 return libc_read(s, buf, len);
4336 msg.msg_name = &saddr.sa.ss; /* optional address */
4337 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4338 msg.msg_iov = &tmp; /* scatter/gather array */
4339 msg.msg_iovlen = 1; /* # elements in msg_iov */
4340 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4341 msg.msg_control = NULL; /* ancillary data, see below */
4342 msg.msg_controllen = 0; /* ancillary data buffer len */
4343 msg.msg_flags = 0; /* flags on received message */
4346 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4348 if (tret == -ENOTSOCK) {
4349 return libc_read(s, buf, len);
4354 buf = msg.msg_iov[0].iov_base;
4355 len = msg.msg_iov[0].iov_len;
4357 ret = libc_read(s, buf, len);
4359 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4367 ssize_t read(int s, void *buf, size_t len)
4369 return swrap_read(s, buf, len);
4372 /****************************************************************************
4374 ***************************************************************************/
4376 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4380 struct sockaddr_un un_addr;
4383 struct socket_info *si = find_socket_info(s);
4386 return libc_send(s, buf, len, flags);
4389 tmp.iov_base = discard_const_p(char, buf);
4393 msg.msg_name = NULL; /* optional address */
4394 msg.msg_namelen = 0; /* size of address */
4395 msg.msg_iov = &tmp; /* scatter/gather array */
4396 msg.msg_iovlen = 1; /* # elements in msg_iov */
4397 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4398 msg.msg_control = NULL; /* ancillary data, see below */
4399 msg.msg_controllen = 0; /* ancillary data buffer len */
4400 msg.msg_flags = 0; /* flags on received message */
4403 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4408 buf = msg.msg_iov[0].iov_base;
4409 len = msg.msg_iov[0].iov_len;
4411 ret = libc_send(s, buf, len, flags);
4413 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4418 ssize_t send(int s, const void *buf, size_t len, int flags)
4420 return swrap_send(s, buf, len, flags);
4423 /****************************************************************************
4425 ***************************************************************************/
4427 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4429 struct swrap_address from_addr = {
4430 .sa_socklen = sizeof(struct sockaddr_un),
4432 struct socket_info *si;
4435 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4436 size_t msg_ctrllen_filled;
4437 size_t msg_ctrllen_left;
4443 si = find_socket_info(s);
4445 return libc_recvmsg(s, omsg, flags);
4448 tmp.iov_base = NULL;
4452 msg.msg_name = &from_addr.sa; /* optional address */
4453 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4454 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4455 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4456 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4457 msg_ctrllen_filled = 0;
4458 msg_ctrllen_left = omsg->msg_controllen;
4460 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4461 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4462 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4465 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4470 ret = libc_recvmsg(s, &msg, flags);
4472 msg.msg_name = omsg->msg_name;
4473 msg.msg_namelen = omsg->msg_namelen;
4475 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4476 msg_ctrllen_filled += msg.msg_controllen;
4477 msg_ctrllen_left -= msg.msg_controllen;
4479 if (omsg->msg_control != NULL) {
4482 p = omsg->msg_control;
4483 p += msg_ctrllen_filled;
4485 msg.msg_control = p;
4486 msg.msg_controllen = msg_ctrllen_left;
4488 msg.msg_control = NULL;
4489 msg.msg_controllen = 0;
4493 rc = swrap_recvmsg_after(s,
4497 from_addr.sa_socklen,
4503 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4504 if (omsg->msg_control != NULL) {
4505 /* msg.msg_controllen = space left */
4506 msg_ctrllen_left = msg.msg_controllen;
4507 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4510 /* Update the original message length */
4511 omsg->msg_controllen = msg_ctrllen_filled;
4512 omsg->msg_flags = msg.msg_flags;
4514 omsg->msg_iovlen = msg.msg_iovlen;
4519 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4521 return swrap_recvmsg(sockfd, msg, flags);
4524 /****************************************************************************
4526 ***************************************************************************/
4528 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4532 struct sockaddr_un un_addr;
4533 const struct sockaddr_un *to_un = NULL;
4534 const struct sockaddr *to = NULL;
4537 struct socket_info *si = find_socket_info(s);
4541 return libc_sendmsg(s, omsg, flags);
4544 ZERO_STRUCT(un_addr);
4546 tmp.iov_base = NULL;
4550 msg.msg_name = omsg->msg_name; /* optional address */
4551 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4552 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4553 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4554 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4555 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4556 /* omsg is a const so use a local buffer for modifications */
4557 uint8_t cmbuf[omsg->msg_controllen];
4559 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4561 msg.msg_control = cmbuf; /* ancillary data, see below */
4562 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4564 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4567 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4575 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4583 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4584 avail += msg.msg_iov[i].iov_len;
4590 /* we capture it as one single packet */
4591 buf = (uint8_t *)malloc(remain);
4596 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4597 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4599 msg.msg_iov[i].iov_base,
4602 remain -= this_time;
4605 type = SOCKET_TYPE_CHAR_UDP;
4607 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4608 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4609 socket_wrapper_dir(), type, iface, prt);
4610 if (stat(un_addr.sun_path, &st) != 0) continue;
4612 msg.msg_name = &un_addr; /* optional address */
4613 msg.msg_namelen = sizeof(un_addr); /* size of address */
4615 /* ignore the any errors in broadcast sends */
4616 libc_sendmsg(s, &msg, flags);
4619 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4625 ret = libc_sendmsg(s, &msg, flags);
4627 swrap_sendmsg_after(s, si, &msg, to, ret);
4632 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4634 return swrap_sendmsg(s, omsg, flags);
4637 /****************************************************************************
4639 ***************************************************************************/
4641 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4643 struct socket_info *si;
4646 struct swrap_address saddr = {
4647 .sa_socklen = sizeof(struct sockaddr_storage)
4652 si = find_socket_info(s);
4654 return libc_readv(s, vector, count);
4657 tmp.iov_base = NULL;
4661 msg.msg_name = &saddr.sa.s; /* optional address */
4662 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4663 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4664 msg.msg_iovlen = count; /* # elements in msg_iov */
4665 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4666 msg.msg_control = NULL; /* ancillary data, see below */
4667 msg.msg_controllen = 0; /* ancillary data buffer len */
4668 msg.msg_flags = 0; /* flags on received message */
4671 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4673 if (rc == -ENOTSOCK) {
4674 return libc_readv(s, vector, count);
4679 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4681 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4689 ssize_t readv(int s, const struct iovec *vector, int count)
4691 return swrap_readv(s, vector, count);
4694 /****************************************************************************
4696 ***************************************************************************/
4698 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4702 struct sockaddr_un un_addr;
4705 struct socket_info *si = find_socket_info(s);
4708 return libc_writev(s, vector, count);
4711 tmp.iov_base = NULL;
4715 msg.msg_name = NULL; /* optional address */
4716 msg.msg_namelen = 0; /* size of address */
4717 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4718 msg.msg_iovlen = count; /* # elements in msg_iov */
4719 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4720 msg.msg_control = NULL; /* ancillary data, see below */
4721 msg.msg_controllen = 0; /* ancillary data buffer len */
4722 msg.msg_flags = 0; /* flags on received message */
4725 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4727 if (rc == -ENOTSOCK) {
4728 return libc_readv(s, vector, count);
4733 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4735 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4740 ssize_t writev(int s, const struct iovec *vector, int count)
4742 return swrap_writev(s, vector, count);
4745 /****************************
4747 ***************************/
4749 static int swrap_close(int fd)
4751 struct socket_info *si = find_socket_info(fd);
4752 struct socket_info_fd *fi;
4756 return libc_close(fd);
4759 for (fi = si->fds; fi; fi = fi->next) {
4761 SWRAP_DLIST_REMOVE(si->fds, fi);
4768 /* there are still references left */
4769 return libc_close(fd);
4772 SWRAP_DLIST_REMOVE(sockets, si);
4774 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4775 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4778 ret = libc_close(fd);
4780 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4781 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4782 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4785 if (si->un_addr.sun_path[0] != '\0') {
4786 unlink(si->un_addr.sun_path);
4795 return swrap_close(fd);
4798 /****************************
4800 ***************************/
4802 static int swrap_dup(int fd)
4804 struct socket_info *si;
4805 struct socket_info_fd *fi;
4807 si = find_socket_info(fd);
4810 return libc_dup(fd);
4813 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4819 fi->fd = libc_dup(fd);
4821 int saved_errno = errno;
4823 errno = saved_errno;
4827 /* Make sure we don't have an entry for the fd */
4828 swrap_remove_stale(fi->fd);
4830 SWRAP_DLIST_ADD(si->fds, fi);
4836 return swrap_dup(fd);
4839 /****************************
4841 ***************************/
4843 static int swrap_dup2(int fd, int newfd)
4845 struct socket_info *si;
4846 struct socket_info_fd *fi;
4848 si = find_socket_info(fd);
4851 return libc_dup2(fd, newfd);
4854 if (find_socket_info(newfd)) {
4855 /* dup2() does an implicit close of newfd, which we
4856 * need to emulate */
4860 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4866 fi->fd = libc_dup2(fd, newfd);
4868 int saved_errno = errno;
4870 errno = saved_errno;
4874 /* Make sure we don't have an entry for the fd */
4875 swrap_remove_stale(fi->fd);
4877 SWRAP_DLIST_ADD(si->fds, fi);
4881 int dup2(int fd, int newfd)
4883 return swrap_dup2(fd, newfd);
4886 /****************************
4888 ***************************/
4891 static int swrap_eventfd(int count, int flags)
4895 fd = libc_eventfd(count, flags);
4897 swrap_remove_stale(fd);
4903 int eventfd(int count, int flags)
4905 return swrap_eventfd(count, flags);
4909 /****************************
4911 ***************************/
4914 * This function is called when the library is unloaded and makes sure that
4915 * sockets get closed and the unix file for the socket are unlinked.
4917 void swrap_destructor(void)
4919 struct socket_info *s = sockets;
4922 struct socket_info_fd *f = s->fds;