2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <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 *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
276 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
278 static void swrap_log(enum swrap_dbglvl_e dbglvl,
280 const char *format, ...)
285 unsigned int lvl = 0;
287 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
292 va_start(va, format);
293 vsnprintf(buffer, sizeof(buffer), format, va);
298 case SWRAP_LOG_ERROR:
300 "SWRAP_ERROR(%d) - %s: %s\n",
301 (int)getpid(), func, buffer);
305 "SWRAP_WARN(%d) - %s: %s\n",
306 (int)getpid(), func, buffer);
308 case SWRAP_LOG_DEBUG:
310 "SWRAP_DEBUG(%d) - %s: %s\n",
311 (int)getpid(), func, buffer);
313 case SWRAP_LOG_TRACE:
315 "SWRAP_TRACE(%d) - %s: %s\n",
316 (int)getpid(), func, buffer);
323 /*********************************************************
324 * SWRAP LOADING LIBC FUNCTIONS
325 *********************************************************/
329 struct swrap_libc_fns {
330 int (*libc_accept)(int sockfd,
331 struct sockaddr *addr,
333 int (*libc_bind)(int sockfd,
334 const struct sockaddr *addr,
336 int (*libc_close)(int fd);
337 int (*libc_connect)(int sockfd,
338 const struct sockaddr *addr,
340 int (*libc_dup)(int fd);
341 int (*libc_dup2)(int oldfd, int newfd);
342 int (*libc_fcntl)(int fd, int cmd, ...);
343 FILE *(*libc_fopen)(const char *name, const char *mode);
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_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
527 *(void **) (&swrap.fns.libc_##fn_name) = \
535 * Functions especially from libc need to be loaded individually, you can't load
536 * all at once or gdb will segfault at startup. The same applies to valgrind and
537 * has probably something todo with with the linker.
538 * So we need load each function at the point it is called the first time.
540 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
542 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
544 return swrap.fns.libc_accept(sockfd, addr, addrlen);
547 static int libc_bind(int sockfd,
548 const struct sockaddr *addr,
551 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
553 return swrap.fns.libc_bind(sockfd, addr, addrlen);
556 static int libc_close(int fd)
558 swrap_load_lib_function(SWRAP_LIBC, close);
560 return swrap.fns.libc_close(fd);
563 static int libc_connect(int sockfd,
564 const struct sockaddr *addr,
567 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
569 return swrap.fns.libc_connect(sockfd, addr, addrlen);
572 static int libc_dup(int fd)
574 swrap_load_lib_function(SWRAP_LIBC, dup);
576 return swrap.fns.libc_dup(fd);
579 static int libc_dup2(int oldfd, int newfd)
581 swrap_load_lib_function(SWRAP_LIBC, dup2);
583 return swrap.fns.libc_dup2(oldfd, newfd);
587 static int libc_eventfd(int count, int flags)
589 swrap_load_lib_function(SWRAP_LIBC, eventfd);
591 return swrap.fns.libc_eventfd(count, flags);
595 static int libc_vfcntl(int fd, int cmd, va_list ap)
601 swrap_load_lib_function(SWRAP_LIBC, fcntl);
603 for (i = 0; i < 4; i++) {
604 args[i] = va_arg(ap, long int);
607 rc = swrap.fns.libc_fcntl(fd,
617 static int libc_getpeername(int sockfd,
618 struct sockaddr *addr,
621 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
623 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
626 static int libc_getsockname(int sockfd,
627 struct sockaddr *addr,
630 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
632 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
635 static int libc_getsockopt(int sockfd,
641 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
643 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
646 static int libc_vioctl(int d, unsigned long int request, va_list ap)
652 swrap_load_lib_function(SWRAP_LIBC, ioctl);
654 for (i = 0; i < 4; i++) {
655 args[i] = va_arg(ap, long int);
658 rc = swrap.fns.libc_ioctl(d,
668 static int libc_listen(int sockfd, int backlog)
670 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
672 return swrap.fns.libc_listen(sockfd, backlog);
675 static FILE *libc_fopen(const char *name, const char *mode)
677 swrap_load_lib_function(SWRAP_LIBC, fopen);
679 return swrap.fns.libc_fopen(name, mode);
682 static int libc_vopen(const char *pathname, int flags, va_list ap)
687 swrap_load_lib_function(SWRAP_LIBC, open);
689 mode = va_arg(ap, long int);
691 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
696 static int libc_open(const char *pathname, int flags, ...)
702 fd = libc_vopen(pathname, flags, ap);
708 static int libc_pipe(int pipefd[2])
710 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
712 return swrap.fns.libc_pipe(pipefd);
715 static int libc_read(int fd, void *buf, size_t count)
717 swrap_load_lib_function(SWRAP_LIBC, read);
719 return swrap.fns.libc_read(fd, buf, count);
722 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
724 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
726 return swrap.fns.libc_readv(fd, iov, iovcnt);
729 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
731 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
733 return swrap.fns.libc_recv(sockfd, buf, len, flags);
736 static int libc_recvfrom(int sockfd,
740 struct sockaddr *src_addr,
743 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
745 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
748 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
750 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
752 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
755 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
757 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
759 return swrap.fns.libc_send(sockfd, buf, len, flags);
762 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
764 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
766 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
769 static int libc_sendto(int sockfd,
773 const struct sockaddr *dst_addr,
776 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
778 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
781 static int libc_setsockopt(int sockfd,
787 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
789 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
793 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
795 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
797 return swrap.fns.libc_signalfd(fd, mask, flags);
801 static int libc_socket(int domain, int type, int protocol)
803 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
805 return swrap.fns.libc_socket(domain, type, protocol);
808 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
810 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
812 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
815 #ifdef HAVE_TIMERFD_CREATE
816 static int libc_timerfd_create(int clockid, int flags)
818 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
820 return swrap.fns.libc_timerfd_create(clockid, flags);
824 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
826 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
828 return swrap.fns.libc_writev(fd, iov, iovcnt);
831 /*********************************************************
832 * SWRAP HELPER FUNCTIONS
833 *********************************************************/
839 static const struct in6_addr *swrap_ipv6(void)
841 static struct in6_addr v;
842 static int initialized;
850 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
859 static void set_port(int family, int prt, struct swrap_address *addr)
863 addr->sa.in.sin_port = htons(prt);
867 addr->sa.in6.sin6_port = htons(prt);
873 static size_t socket_length(int family)
877 return sizeof(struct sockaddr_in);
880 return sizeof(struct sockaddr_in6);
886 static const char *socket_wrapper_dir(void)
888 const char *s = getenv("SOCKET_WRAPPER_DIR");
892 /* TODO use realpath(3) here, when we add support for threads */
893 if (strncmp(s, "./", 2) == 0) {
897 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
901 bool socket_wrapper_enabled(void)
903 const char *s = socket_wrapper_dir();
905 return s != NULL ? true : false;
908 static unsigned int socket_wrapper_default_iface(void)
910 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
913 if (sscanf(s, "%u", &iface) == 1) {
914 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
920 return 1;/* 127.0.0.1 */
923 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
930 p = strrchr(un->sun_path, '/');
931 if (p) p++; else p = un->sun_path;
933 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
938 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
941 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
952 case SOCKET_TYPE_CHAR_TCP:
953 case SOCKET_TYPE_CHAR_UDP: {
954 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
956 if ((*len) < sizeof(*in2)) {
961 memset(in2, 0, sizeof(*in2));
962 in2->sin_family = AF_INET;
963 in2->sin_addr.s_addr = htonl((127<<24) | iface);
964 in2->sin_port = htons(prt);
970 case SOCKET_TYPE_CHAR_TCP_V6:
971 case SOCKET_TYPE_CHAR_UDP_V6: {
972 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
974 if ((*len) < sizeof(*in2)) {
979 memset(in2, 0, sizeof(*in2));
980 in2->sin6_family = AF_INET6;
981 in2->sin6_addr = *swrap_ipv6();
982 in2->sin6_addr.s6_addr[15] = iface;
983 in2->sin6_port = htons(prt);
997 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1005 if (bcast) *bcast = 0;
1007 switch (inaddr->sa_family) {
1009 const struct sockaddr_in *in =
1010 (const struct sockaddr_in *)(const void *)inaddr;
1011 unsigned int addr = ntohl(in->sin_addr.s_addr);
1018 u_type = SOCKET_TYPE_CHAR_TCP;
1021 u_type = SOCKET_TYPE_CHAR_UDP;
1022 a_type = SOCKET_TYPE_CHAR_UDP;
1023 b_type = SOCKET_TYPE_CHAR_UDP;
1026 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1027 errno = ESOCKTNOSUPPORT;
1031 prt = ntohs(in->sin_port);
1032 if (a_type && addr == 0xFFFFFFFF) {
1033 /* 255.255.255.255 only udp */
1036 iface = socket_wrapper_default_iface();
1037 } else if (b_type && addr == 0x7FFFFFFF) {
1038 /* 127.255.255.255 only udp */
1041 iface = socket_wrapper_default_iface();
1042 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1046 iface = (addr & 0x000000FF);
1048 errno = ENETUNREACH;
1051 if (bcast) *bcast = is_bcast;
1056 const struct sockaddr_in6 *in =
1057 (const struct sockaddr_in6 *)(const void *)inaddr;
1058 struct in6_addr cmp1, cmp2;
1062 type = SOCKET_TYPE_CHAR_TCP_V6;
1065 type = SOCKET_TYPE_CHAR_UDP_V6;
1068 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1069 errno = ESOCKTNOSUPPORT;
1073 /* XXX no multicast/broadcast */
1075 prt = ntohs(in->sin6_port);
1077 cmp1 = *swrap_ipv6();
1078 cmp2 = in->sin6_addr;
1079 cmp2.s6_addr[15] = 0;
1080 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1081 iface = in->sin6_addr.s6_addr[15];
1083 errno = ENETUNREACH;
1091 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1092 errno = ENETUNREACH;
1097 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1103 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1104 socket_wrapper_dir());
1105 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1106 /* the caller need to do more processing */
1110 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1111 socket_wrapper_dir(), type, iface, prt);
1112 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1117 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1126 if (bcast) *bcast = 0;
1128 switch (si->family) {
1130 const struct sockaddr_in *in =
1131 (const struct sockaddr_in *)(const void *)inaddr;
1132 unsigned int addr = ntohl(in->sin_addr.s_addr);
1138 prt = ntohs(in->sin_port);
1142 u_type = SOCKET_TYPE_CHAR_TCP;
1143 d_type = SOCKET_TYPE_CHAR_TCP;
1146 u_type = SOCKET_TYPE_CHAR_UDP;
1147 d_type = SOCKET_TYPE_CHAR_UDP;
1148 a_type = SOCKET_TYPE_CHAR_UDP;
1149 b_type = SOCKET_TYPE_CHAR_UDP;
1152 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1153 errno = ESOCKTNOSUPPORT;
1161 iface = socket_wrapper_default_iface();
1162 } else if (a_type && addr == 0xFFFFFFFF) {
1163 /* 255.255.255.255 only udp */
1166 iface = socket_wrapper_default_iface();
1167 } else if (b_type && addr == 0x7FFFFFFF) {
1168 /* 127.255.255.255 only udp */
1171 iface = socket_wrapper_default_iface();
1172 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1176 iface = (addr & 0x000000FF);
1178 errno = EADDRNOTAVAIL;
1182 /* Store the bind address for connect() */
1183 if (si->bindname.sa_socklen == 0) {
1184 struct sockaddr_in bind_in;
1185 socklen_t blen = sizeof(struct sockaddr_in);
1187 ZERO_STRUCT(bind_in);
1188 bind_in.sin_family = in->sin_family;
1189 bind_in.sin_port = in->sin_port;
1190 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1192 si->bindname.sa_socklen = blen;
1193 memcpy(&si->bindname.sa.in, &bind_in, blen);
1200 const struct sockaddr_in6 *in =
1201 (const struct sockaddr_in6 *)(const void *)inaddr;
1202 struct in6_addr cmp1, cmp2;
1206 type = SOCKET_TYPE_CHAR_TCP_V6;
1209 type = SOCKET_TYPE_CHAR_UDP_V6;
1212 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1213 errno = ESOCKTNOSUPPORT;
1217 /* XXX no multicast/broadcast */
1219 prt = ntohs(in->sin6_port);
1221 cmp1 = *swrap_ipv6();
1222 cmp2 = in->sin6_addr;
1223 cmp2.s6_addr[15] = 0;
1224 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1225 iface = socket_wrapper_default_iface();
1226 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1227 iface = in->sin6_addr.s6_addr[15];
1229 errno = EADDRNOTAVAIL;
1233 /* Store the bind address for connect() */
1234 if (si->bindname.sa_socklen == 0) {
1235 struct sockaddr_in6 bind_in;
1236 socklen_t blen = sizeof(struct sockaddr_in6);
1238 ZERO_STRUCT(bind_in);
1239 bind_in.sin6_family = in->sin6_family;
1240 bind_in.sin6_port = in->sin6_port;
1242 bind_in.sin6_addr = *swrap_ipv6();
1243 bind_in.sin6_addr.s6_addr[15] = iface;
1245 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1246 si->bindname.sa_socklen = blen;
1253 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1254 errno = EADDRNOTAVAIL;
1259 if (bcast) *bcast = is_bcast;
1261 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1267 /* handle auto-allocation of ephemeral ports */
1268 for (prt = 5001; prt < 10000; prt++) {
1269 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1270 socket_wrapper_dir(), type, iface, prt);
1271 if (stat(un->sun_path, &st) == 0) continue;
1273 set_port(si->family, prt, &si->myname);
1274 set_port(si->family, prt, &si->bindname);
1284 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1285 socket_wrapper_dir(), type, iface, prt);
1286 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1290 static struct socket_info *find_socket_info(int fd)
1292 struct socket_info *i;
1294 for (i = sockets; i; i = i->next) {
1295 struct socket_info_fd *f;
1296 for (f = i->fds; f; f = f->next) {
1307 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1309 struct socket_info *s;
1311 /* first catch invalid input */
1312 switch (sa->sa_family) {
1314 if (len < sizeof(struct sockaddr_in)) {
1320 if (len < sizeof(struct sockaddr_in6)) {
1330 for (s = sockets; s != NULL; s = s->next) {
1331 if (s->myname == NULL) {
1334 if (s->myname->sa_family != sa->sa_family) {
1337 switch (s->myname->sa_family) {
1339 struct sockaddr_in *sin1, *sin2;
1341 sin1 = (struct sockaddr_in *)s->myname;
1342 sin2 = (struct sockaddr_in *)sa;
1344 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1347 if (sin1->sin_port != sin2->sin_port) {
1350 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1360 struct sockaddr_in6 *sin1, *sin2;
1362 sin1 = (struct sockaddr_in6 *)s->myname;
1363 sin2 = (struct sockaddr_in6 *)sa;
1365 if (sin1->sin6_port != sin2->sin6_port) {
1368 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1390 static void swrap_remove_stale(int fd)
1392 struct socket_info *si = find_socket_info(fd);
1393 struct socket_info_fd *fi;
1396 for (fi = si->fds; fi; fi = fi->next) {
1398 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1399 SWRAP_DLIST_REMOVE(si->fds, fi);
1405 if (si->fds == NULL) {
1406 SWRAP_DLIST_REMOVE(sockets, si);
1411 static int sockaddr_convert_to_un(struct socket_info *si,
1412 const struct sockaddr *in_addr,
1414 struct sockaddr_un *out_addr,
1418 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1420 (void) in_len; /* unused */
1422 if (out_addr == NULL) {
1426 out->sa_family = AF_UNIX;
1427 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1428 out->sa_len = sizeof(*out_addr);
1431 switch (in_addr->sa_family) {
1433 const struct sockaddr_in *sin;
1434 if (si->family != AF_INET) {
1437 if (in_len < sizeof(struct sockaddr_in)) {
1440 sin = (const struct sockaddr_in *)(const void *)in_addr;
1441 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1446 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1447 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1461 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1462 errno = ESOCKTNOSUPPORT;
1466 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1468 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1474 errno = EAFNOSUPPORT;
1475 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1479 static int sockaddr_convert_from_un(const struct socket_info *si,
1480 const struct sockaddr_un *in_addr,
1481 socklen_t un_addrlen,
1483 struct sockaddr *out_addr,
1484 socklen_t *out_addrlen)
1488 if (out_addr == NULL || out_addrlen == NULL)
1491 if (un_addrlen == 0) {
1506 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1507 errno = ESOCKTNOSUPPORT;
1510 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1511 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1512 out_addr->sa_len = *out_addrlen;
1519 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1520 errno = EAFNOSUPPORT;
1524 enum swrap_packet_type {
1526 SWRAP_CONNECT_UNREACH,
1534 SWRAP_SENDTO_UNREACH,
1545 struct swrap_file_hdr {
1547 uint16_t version_major;
1548 uint16_t version_minor;
1551 uint32_t frame_max_len;
1552 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1555 #define SWRAP_FILE_HDR_SIZE 24
1557 struct swrap_packet_frame {
1559 uint32_t micro_seconds;
1560 uint32_t recorded_length;
1561 uint32_t full_length;
1563 #define SWRAP_PACKET_FRAME_SIZE 16
1565 union swrap_packet_ip {
1569 uint16_t packet_length;
1570 uint16_t identification;
1575 uint16_t hdr_checksum;
1579 #define SWRAP_PACKET_IP_V4_SIZE 20
1582 uint8_t flow_label_high;
1583 uint16_t flow_label_low;
1584 uint16_t payload_length;
1585 uint8_t next_header;
1587 uint8_t src_addr[16];
1588 uint8_t dest_addr[16];
1590 #define SWRAP_PACKET_IP_V6_SIZE 40
1592 #define SWRAP_PACKET_IP_SIZE 40
1594 union swrap_packet_payload {
1596 uint16_t source_port;
1606 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1608 uint16_t source_port;
1613 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1620 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1627 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1629 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1631 #define SWRAP_PACKET_MIN_ALLOC \
1632 (SWRAP_PACKET_FRAME_SIZE + \
1633 SWRAP_PACKET_IP_SIZE + \
1634 SWRAP_PACKET_PAYLOAD_SIZE)
1636 static const char *swrap_pcap_init_file(void)
1638 static int initialized = 0;
1639 static const char *s = NULL;
1640 static const struct swrap_file_hdr h;
1641 static const struct swrap_packet_frame f;
1642 static const union swrap_packet_ip i;
1643 static const union swrap_packet_payload p;
1645 if (initialized == 1) {
1651 * TODO: don't use the structs use plain buffer offsets
1652 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1654 * for now make sure we disable PCAP support
1655 * if the struct has alignment!
1657 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1660 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1663 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1666 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1669 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1672 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1675 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1678 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1681 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1684 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1688 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1692 if (strncmp(s, "./", 2) == 0) {
1698 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1699 const struct sockaddr *src,
1700 const struct sockaddr *dest,
1702 const uint8_t *payload,
1704 unsigned long tcp_seqno,
1705 unsigned long tcp_ack,
1706 unsigned char tcp_ctl,
1708 size_t *_packet_len)
1712 struct swrap_packet_frame *frame;
1713 union swrap_packet_ip *ip;
1714 union swrap_packet_payload *pay;
1717 size_t nonwire_len = sizeof(*frame);
1718 size_t wire_hdr_len = 0;
1719 size_t wire_len = 0;
1720 size_t ip_hdr_len = 0;
1721 size_t icmp_hdr_len = 0;
1722 size_t icmp_truncate_len = 0;
1723 uint8_t protocol = 0, icmp_protocol = 0;
1724 const struct sockaddr_in *src_in = NULL;
1725 const struct sockaddr_in *dest_in = NULL;
1727 const struct sockaddr_in6 *src_in6 = NULL;
1728 const struct sockaddr_in6 *dest_in6 = NULL;
1733 switch (src->sa_family) {
1735 src_in = (const struct sockaddr_in *)(const void *)src;
1736 dest_in = (const struct sockaddr_in *)(const void *)dest;
1737 src_port = src_in->sin_port;
1738 dest_port = dest_in->sin_port;
1739 ip_hdr_len = sizeof(ip->v4);
1743 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1744 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1745 src_port = src_in6->sin6_port;
1746 dest_port = dest_in6->sin6_port;
1747 ip_hdr_len = sizeof(ip->v6);
1754 switch (socket_type) {
1756 protocol = 0x06; /* TCP */
1757 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1758 wire_len = wire_hdr_len + payload_len;
1762 protocol = 0x11; /* UDP */
1763 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1764 wire_len = wire_hdr_len + payload_len;
1772 icmp_protocol = protocol;
1773 switch (src->sa_family) {
1775 protocol = 0x01; /* ICMPv4 */
1776 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1780 protocol = 0x3A; /* ICMPv6 */
1781 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1785 if (wire_len > 64 ) {
1786 icmp_truncate_len = wire_len - 64;
1788 wire_hdr_len += icmp_hdr_len;
1789 wire_len += icmp_hdr_len;
1792 packet_len = nonwire_len + wire_len;
1793 alloc_len = packet_len;
1794 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1795 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1798 base = (uint8_t *)malloc(alloc_len);
1802 memset(base, 0x0, alloc_len);
1806 frame = (struct swrap_packet_frame *)(void *)buf;
1807 frame->seconds = tval->tv_sec;
1808 frame->micro_seconds = tval->tv_usec;
1809 frame->recorded_length = wire_len - icmp_truncate_len;
1810 frame->full_length = wire_len - icmp_truncate_len;
1811 buf += SWRAP_PACKET_FRAME_SIZE;
1813 ip = (union swrap_packet_ip *)(void *)buf;
1814 switch (src->sa_family) {
1816 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1818 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1819 ip->v4.identification = htons(0xFFFF);
1820 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1821 ip->v4.fragment = htons(0x0000);
1823 ip->v4.protocol = protocol;
1824 ip->v4.hdr_checksum = htons(0x0000);
1825 ip->v4.src_addr = src_in->sin_addr.s_addr;
1826 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1827 buf += SWRAP_PACKET_IP_V4_SIZE;
1831 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1832 ip->v6.flow_label_high = 0x00;
1833 ip->v6.flow_label_low = 0x0000;
1834 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1835 ip->v6.next_header = protocol;
1836 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1837 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1838 buf += SWRAP_PACKET_IP_V6_SIZE;
1844 pay = (union swrap_packet_payload *)(void *)buf;
1845 switch (src->sa_family) {
1847 pay->icmp4.type = 0x03; /* destination unreachable */
1848 pay->icmp4.code = 0x01; /* host unreachable */
1849 pay->icmp4.checksum = htons(0x0000);
1850 pay->icmp4.unused = htonl(0x00000000);
1851 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1853 /* set the ip header in the ICMP payload */
1854 ip = (union swrap_packet_ip *)(void *)buf;
1855 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1857 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1858 ip->v4.identification = htons(0xFFFF);
1859 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1860 ip->v4.fragment = htons(0x0000);
1862 ip->v4.protocol = icmp_protocol;
1863 ip->v4.hdr_checksum = htons(0x0000);
1864 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1865 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1866 buf += SWRAP_PACKET_IP_V4_SIZE;
1868 src_port = dest_in->sin_port;
1869 dest_port = src_in->sin_port;
1873 pay->icmp6.type = 0x01; /* destination unreachable */
1874 pay->icmp6.code = 0x03; /* address unreachable */
1875 pay->icmp6.checksum = htons(0x0000);
1876 pay->icmp6.unused = htonl(0x00000000);
1877 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1879 /* set the ip header in the ICMP payload */
1880 ip = (union swrap_packet_ip *)(void *)buf;
1881 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1882 ip->v6.flow_label_high = 0x00;
1883 ip->v6.flow_label_low = 0x0000;
1884 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1885 ip->v6.next_header = protocol;
1886 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1887 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1888 buf += SWRAP_PACKET_IP_V6_SIZE;
1890 src_port = dest_in6->sin6_port;
1891 dest_port = src_in6->sin6_port;
1897 pay = (union swrap_packet_payload *)(void *)buf;
1899 switch (socket_type) {
1901 pay->tcp.source_port = src_port;
1902 pay->tcp.dest_port = dest_port;
1903 pay->tcp.seq_num = htonl(tcp_seqno);
1904 pay->tcp.ack_num = htonl(tcp_ack);
1905 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1906 pay->tcp.control = tcp_ctl;
1907 pay->tcp.window = htons(0x7FFF);
1908 pay->tcp.checksum = htons(0x0000);
1909 pay->tcp.urg = htons(0x0000);
1910 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1915 pay->udp.source_port = src_port;
1916 pay->udp.dest_port = dest_port;
1917 pay->udp.length = htons(8 + payload_len);
1918 pay->udp.checksum = htons(0x0000);
1919 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1924 if (payload && payload_len > 0) {
1925 memcpy(buf, payload, payload_len);
1928 *_packet_len = packet_len - icmp_truncate_len;
1932 static int swrap_pcap_get_fd(const char *fname)
1936 if (fd != -1) return fd;
1938 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1940 struct swrap_file_hdr file_hdr;
1941 file_hdr.magic = 0xA1B2C3D4;
1942 file_hdr.version_major = 0x0002;
1943 file_hdr.version_minor = 0x0004;
1944 file_hdr.timezone = 0x00000000;
1945 file_hdr.sigfigs = 0x00000000;
1946 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1947 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1949 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1956 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1961 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
1962 const struct sockaddr *addr,
1963 enum swrap_packet_type type,
1964 const void *buf, size_t len,
1967 const struct sockaddr *src_addr;
1968 const struct sockaddr *dest_addr;
1969 unsigned long tcp_seqno = 0;
1970 unsigned long tcp_ack = 0;
1971 unsigned char tcp_ctl = 0;
1972 int unreachable = 0;
1976 switch (si->family) {
1988 case SWRAP_CONNECT_SEND:
1989 if (si->type != SOCK_STREAM) return NULL;
1991 src_addr = &si->myname.sa.s;
1994 tcp_seqno = si->io.pck_snd;
1995 tcp_ack = si->io.pck_rcv;
1996 tcp_ctl = 0x02; /* SYN */
1998 si->io.pck_snd += 1;
2002 case SWRAP_CONNECT_RECV:
2003 if (si->type != SOCK_STREAM) return NULL;
2005 dest_addr = &si->myname.sa.s;
2008 tcp_seqno = si->io.pck_rcv;
2009 tcp_ack = si->io.pck_snd;
2010 tcp_ctl = 0x12; /** SYN,ACK */
2012 si->io.pck_rcv += 1;
2016 case SWRAP_CONNECT_UNREACH:
2017 if (si->type != SOCK_STREAM) return NULL;
2019 dest_addr = &si->myname.sa.s;
2022 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2023 tcp_seqno = si->io.pck_snd - 1;
2024 tcp_ack = si->io.pck_rcv;
2025 tcp_ctl = 0x02; /* SYN */
2030 case SWRAP_CONNECT_ACK:
2031 if (si->type != SOCK_STREAM) return NULL;
2033 src_addr = &si->myname.sa.s;
2036 tcp_seqno = si->io.pck_snd;
2037 tcp_ack = si->io.pck_rcv;
2038 tcp_ctl = 0x10; /* ACK */
2042 case SWRAP_ACCEPT_SEND:
2043 if (si->type != SOCK_STREAM) return NULL;
2045 dest_addr = &si->myname.sa.s;
2048 tcp_seqno = si->io.pck_rcv;
2049 tcp_ack = si->io.pck_snd;
2050 tcp_ctl = 0x02; /* SYN */
2052 si->io.pck_rcv += 1;
2056 case SWRAP_ACCEPT_RECV:
2057 if (si->type != SOCK_STREAM) return NULL;
2059 src_addr = &si->myname.sa.s;
2062 tcp_seqno = si->io.pck_snd;
2063 tcp_ack = si->io.pck_rcv;
2064 tcp_ctl = 0x12; /* SYN,ACK */
2066 si->io.pck_snd += 1;
2070 case SWRAP_ACCEPT_ACK:
2071 if (si->type != SOCK_STREAM) return NULL;
2073 dest_addr = &si->myname.sa.s;
2076 tcp_seqno = si->io.pck_rcv;
2077 tcp_ack = si->io.pck_snd;
2078 tcp_ctl = 0x10; /* ACK */
2083 src_addr = &si->myname.sa.s;
2084 dest_addr = &si->peername.sa.s;
2086 tcp_seqno = si->io.pck_snd;
2087 tcp_ack = si->io.pck_rcv;
2088 tcp_ctl = 0x18; /* PSH,ACK */
2090 si->io.pck_snd += len;
2094 case SWRAP_SEND_RST:
2095 dest_addr = &si->myname.sa.s;
2096 src_addr = &si->peername.sa.s;
2098 if (si->type == SOCK_DGRAM) {
2099 return swrap_pcap_marshall_packet(si,
2101 SWRAP_SENDTO_UNREACH,
2107 tcp_seqno = si->io.pck_rcv;
2108 tcp_ack = si->io.pck_snd;
2109 tcp_ctl = 0x14; /** RST,ACK */
2113 case SWRAP_PENDING_RST:
2114 dest_addr = &si->myname.sa.s;
2115 src_addr = &si->peername.sa.s;
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 dest_addr = &si->myname.sa.s;
2129 src_addr = &si->peername.sa.s;
2131 tcp_seqno = si->io.pck_rcv;
2132 tcp_ack = si->io.pck_snd;
2133 tcp_ctl = 0x18; /* PSH,ACK */
2135 si->io.pck_rcv += len;
2139 case SWRAP_RECV_RST:
2140 dest_addr = &si->myname.sa.s;
2141 src_addr = &si->peername.sa.s;
2143 if (si->type == SOCK_DGRAM) {
2147 tcp_seqno = si->io.pck_rcv;
2148 tcp_ack = si->io.pck_snd;
2149 tcp_ctl = 0x14; /* RST,ACK */
2154 src_addr = &si->myname.sa.s;
2157 si->io.pck_snd += len;
2161 case SWRAP_SENDTO_UNREACH:
2162 dest_addr = &si->myname.sa.s;
2169 case SWRAP_RECVFROM:
2170 dest_addr = &si->myname.sa.s;
2173 si->io.pck_rcv += len;
2177 case SWRAP_CLOSE_SEND:
2178 if (si->type != SOCK_STREAM) return NULL;
2180 src_addr = &si->myname.sa.s;
2181 dest_addr = &si->peername.sa.s;
2183 tcp_seqno = si->io.pck_snd;
2184 tcp_ack = si->io.pck_rcv;
2185 tcp_ctl = 0x11; /* FIN, ACK */
2187 si->io.pck_snd += 1;
2191 case SWRAP_CLOSE_RECV:
2192 if (si->type != SOCK_STREAM) return NULL;
2194 dest_addr = &si->myname.sa.s;
2195 src_addr = &si->peername.sa.s;
2197 tcp_seqno = si->io.pck_rcv;
2198 tcp_ack = si->io.pck_snd;
2199 tcp_ctl = 0x11; /* FIN,ACK */
2201 si->io.pck_rcv += 1;
2205 case SWRAP_CLOSE_ACK:
2206 if (si->type != SOCK_STREAM) return NULL;
2208 src_addr = &si->myname.sa.s;
2209 dest_addr = &si->peername.sa.s;
2211 tcp_seqno = si->io.pck_snd;
2212 tcp_ack = si->io.pck_rcv;
2213 tcp_ctl = 0x10; /* ACK */
2220 swrapGetTimeOfDay(&tv);
2222 return swrap_pcap_packet_init(&tv,
2226 (const uint8_t *)buf,
2235 static void swrap_pcap_dump_packet(struct socket_info *si,
2236 const struct sockaddr *addr,
2237 enum swrap_packet_type type,
2238 const void *buf, size_t len)
2240 const char *file_name;
2242 size_t packet_len = 0;
2245 file_name = swrap_pcap_init_file();
2250 packet = swrap_pcap_marshall_packet(si,
2256 if (packet == NULL) {
2260 fd = swrap_pcap_get_fd(file_name);
2262 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2271 /****************************************************************************
2273 ***************************************************************************/
2275 #ifdef HAVE_SIGNALFD
2276 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2280 rc = libc_signalfd(fd, mask, flags);
2282 swrap_remove_stale(fd);
2288 int signalfd(int fd, const sigset_t *mask, int flags)
2290 return swrap_signalfd(fd, mask, flags);
2294 /****************************************************************************
2296 ***************************************************************************/
2298 static int swrap_socket(int family, int type, int protocol)
2300 struct socket_info *si;
2301 struct socket_info_fd *fi;
2303 int real_type = type;
2306 * Remove possible addition flags passed to socket() so
2307 * do not fail checking the type.
2308 * See https://lwn.net/Articles/281965/
2311 real_type &= ~SOCK_CLOEXEC;
2313 #ifdef SOCK_NONBLOCK
2314 real_type &= ~SOCK_NONBLOCK;
2317 if (!socket_wrapper_enabled()) {
2318 return libc_socket(family, type, protocol);
2328 return libc_socket(family, type, protocol);
2330 errno = EAFNOSUPPORT;
2334 switch (real_type) {
2340 errno = EPROTONOSUPPORT;
2348 if (real_type == SOCK_STREAM) {
2353 if (real_type == SOCK_DGRAM) {
2358 errno = EPROTONOSUPPORT;
2363 * We must call libc_socket with type, from the caller, not the version
2364 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2366 fd = libc_socket(AF_UNIX, type, 0);
2372 /* Check if we have a stale fd and remove it */
2373 si = find_socket_info(fd);
2375 swrap_remove_stale(fd);
2378 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2379 memset(si, 0, sizeof(struct socket_info));
2385 si->family = family;
2387 /* however, the rest of the socket_wrapper code expects just
2388 * the type, not the flags */
2389 si->type = real_type;
2390 si->protocol = protocol;
2393 * Setup myname so getsockname() can succeed to find out the socket
2396 switch(si->family) {
2398 struct sockaddr_in sin = {
2399 .sin_family = AF_INET,
2402 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2403 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2407 struct sockaddr_in6 sin6 = {
2408 .sin6_family = AF_INET6,
2411 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2412 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2421 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2430 SWRAP_DLIST_ADD(si->fds, fi);
2431 SWRAP_DLIST_ADD(sockets, si);
2433 SWRAP_LOG(SWRAP_LOG_TRACE,
2434 "Created %s socket for protocol %s",
2435 si->family == AF_INET ? "IPv4" : "IPv6",
2436 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2441 int socket(int family, int type, int protocol)
2443 return swrap_socket(family, type, protocol);
2446 /****************************************************************************
2448 ***************************************************************************/
2450 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2454 rc = libc_socketpair(family, type, protocol, sv);
2456 swrap_remove_stale(sv[0]);
2457 swrap_remove_stale(sv[1]);
2463 int socketpair(int family, int type, int protocol, int sv[2])
2465 return swrap_socketpair(family, type, protocol, sv);
2468 /****************************************************************************
2470 ***************************************************************************/
2472 #ifdef HAVE_TIMERFD_CREATE
2473 static int swrap_timerfd_create(int clockid, int flags)
2477 fd = libc_timerfd_create(clockid, flags);
2479 swrap_remove_stale(fd);
2485 int timerfd_create(int clockid, int flags)
2487 return swrap_timerfd_create(clockid, flags);
2491 /****************************************************************************
2493 ***************************************************************************/
2495 static int swrap_pipe(int pipefd[2])
2499 rc = libc_pipe(pipefd);
2501 swrap_remove_stale(pipefd[0]);
2502 swrap_remove_stale(pipefd[1]);
2508 int pipe(int pipefd[2])
2510 return swrap_pipe(pipefd);
2513 /****************************************************************************
2515 ***************************************************************************/
2517 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2519 struct socket_info *parent_si, *child_si;
2520 struct socket_info_fd *child_fi;
2522 struct swrap_address un_addr = {
2523 .sa_socklen = sizeof(struct sockaddr_un),
2525 struct swrap_address un_my_addr = {
2526 .sa_socklen = sizeof(struct sockaddr_un),
2528 struct swrap_address in_addr = {
2529 .sa_socklen = sizeof(struct sockaddr_storage),
2531 struct swrap_address in_my_addr = {
2532 .sa_socklen = sizeof(struct sockaddr_storage),
2536 parent_si = find_socket_info(s);
2538 return libc_accept(s, addr, addrlen);
2542 * assume out sockaddr have the same size as the in parent
2545 in_addr.sa_socklen = socket_length(parent_si->family);
2546 if (in_addr.sa_socklen <= 0) {
2551 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2553 if (errno == ENOTSOCK) {
2554 /* Remove stale fds */
2555 swrap_remove_stale(s);
2562 ret = sockaddr_convert_from_un(parent_si,
2567 &in_addr.sa_socklen);
2573 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2574 memset(child_si, 0, sizeof(struct socket_info));
2576 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2577 if (child_fi == NULL) {
2586 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2588 child_si->family = parent_si->family;
2589 child_si->type = parent_si->type;
2590 child_si->protocol = parent_si->protocol;
2591 child_si->bound = 1;
2592 child_si->is_server = 1;
2593 child_si->connected = 1;
2595 child_si->peername = (struct swrap_address) {
2596 .sa_socklen = in_addr.sa_socklen,
2598 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2600 if (addr != NULL && addrlen != NULL) {
2601 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2603 memcpy(addr, &in_addr.sa.ss, copy_len);
2605 *addrlen = in_addr.sa_socklen;
2608 ret = libc_getsockname(fd,
2610 &un_my_addr.sa_socklen);
2618 ret = sockaddr_convert_from_un(child_si,
2620 un_my_addr.sa_socklen,
2623 &in_my_addr.sa_socklen);
2631 SWRAP_LOG(SWRAP_LOG_TRACE,
2632 "accept() path=%s, fd=%d",
2633 un_my_addr.sa.un.sun_path, s);
2635 child_si->myname = (struct swrap_address) {
2636 .sa_socklen = in_my_addr.sa_socklen,
2638 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2640 SWRAP_DLIST_ADD(sockets, child_si);
2643 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2644 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2645 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2651 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2652 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2654 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2657 return swrap_accept(s, addr, (socklen_t *)addrlen);
2660 static int autobind_start_init;
2661 static int autobind_start;
2663 /* using sendto() or connect() on an unbound socket would give the
2664 recipient no way to reply, as unlike UDP and TCP, a unix domain
2665 socket can't auto-assign ephemeral port numbers, so we need to
2667 Note: this might change the family from ipv6 to ipv4
2669 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2671 struct swrap_address un_addr = {
2672 .sa_socklen = sizeof(struct sockaddr_un),
2680 if (autobind_start_init != 1) {
2681 autobind_start_init = 1;
2682 autobind_start = getpid();
2683 autobind_start %= 50000;
2684 autobind_start += 10000;
2687 un_addr.sa.un.sun_family = AF_UNIX;
2691 struct sockaddr_in in;
2695 type = SOCKET_TYPE_CHAR_TCP;
2698 type = SOCKET_TYPE_CHAR_UDP;
2701 errno = ESOCKTNOSUPPORT;
2705 memset(&in, 0, sizeof(in));
2706 in.sin_family = AF_INET;
2707 in.sin_addr.s_addr = htonl(127<<24 |
2708 socket_wrapper_default_iface());
2710 si->myname = (struct swrap_address) {
2711 .sa_socklen = sizeof(in),
2713 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2718 struct sockaddr_in6 in6;
2720 if (si->family != family) {
2721 errno = ENETUNREACH;
2727 type = SOCKET_TYPE_CHAR_TCP_V6;
2730 type = SOCKET_TYPE_CHAR_UDP_V6;
2733 errno = ESOCKTNOSUPPORT;
2737 memset(&in6, 0, sizeof(in6));
2738 in6.sin6_family = AF_INET6;
2739 in6.sin6_addr = *swrap_ipv6();
2740 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2742 si->myname = (struct swrap_address) {
2743 .sa_socklen = sizeof(in6),
2745 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2750 errno = ESOCKTNOSUPPORT;
2754 if (autobind_start > 60000) {
2755 autobind_start = 10000;
2758 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2759 port = autobind_start + i;
2760 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2761 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2762 type, socket_wrapper_default_iface(), port);
2763 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2765 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2766 if (ret == -1) return ret;
2768 si->un_addr = un_addr.sa.un;
2771 autobind_start = port + 1;
2774 if (i == SOCKET_MAX_SOCKETS) {
2775 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2776 "interface "SOCKET_FORMAT,
2779 socket_wrapper_default_iface(),
2785 si->family = family;
2786 set_port(si->family, port, &si->myname);
2791 /****************************************************************************
2793 ***************************************************************************/
2795 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2799 struct swrap_address un_addr = {
2800 .sa_socklen = sizeof(struct sockaddr_un),
2802 struct socket_info *si = find_socket_info(s);
2806 return libc_connect(s, serv_addr, addrlen);
2809 if (si->bound == 0) {
2810 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2811 if (ret == -1) return -1;
2814 if (si->family != serv_addr->sa_family) {
2819 ret = sockaddr_convert_to_un(si, serv_addr,
2820 addrlen, &un_addr.sa.un, 0, &bcast);
2821 if (ret == -1) return -1;
2824 errno = ENETUNREACH;
2828 if (si->type == SOCK_DGRAM) {
2829 si->defer_connect = 1;
2832 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2834 ret = libc_connect(s,
2836 un_addr.sa_socklen);
2839 SWRAP_LOG(SWRAP_LOG_TRACE,
2840 "connect() path=%s, fd=%d",
2841 un_addr.sa.un.sun_path, s);
2844 /* to give better errors */
2845 if (ret == -1 && errno == ENOENT) {
2846 errno = EHOSTUNREACH;
2850 si->peername = (struct swrap_address) {
2851 .sa_socklen = addrlen,
2854 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2858 * When we connect() on a socket than we have to bind the
2859 * outgoing connection on the interface we use for the
2860 * transport. We already bound it on the right interface
2861 * but here we have to update the name so getsockname()
2862 * returns correct information.
2864 if (si->bindname.sa_socklen > 0) {
2865 si->myname = (struct swrap_address) {
2866 .sa_socklen = si->bindname.sa_socklen,
2869 memcpy(&si->myname.sa.ss,
2870 &si->bindname.sa.ss,
2871 si->bindname.sa_socklen);
2873 /* Cleanup bindname */
2874 si->bindname = (struct swrap_address) {
2879 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2880 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2882 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2888 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2890 return swrap_connect(s, serv_addr, addrlen);
2893 /****************************************************************************
2895 ***************************************************************************/
2897 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2900 struct swrap_address un_addr = {
2901 .sa_socklen = sizeof(struct sockaddr_un),
2903 struct socket_info *si = find_socket_info(s);
2910 return libc_bind(s, myaddr, addrlen);
2913 switch (si->family) {
2915 const struct sockaddr_in *sin;
2916 if (addrlen < sizeof(struct sockaddr_in)) {
2917 bind_error = EINVAL;
2921 sin = (const struct sockaddr_in *)(const void *)myaddr;
2923 if (sin->sin_family != AF_INET) {
2924 bind_error = EAFNOSUPPORT;
2927 /* special case for AF_UNSPEC */
2928 if (sin->sin_family == AF_UNSPEC &&
2929 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2938 const struct sockaddr_in6 *sin6;
2939 if (addrlen < sizeof(struct sockaddr_in6)) {
2940 bind_error = EINVAL;
2944 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
2946 if (sin6->sin6_family != AF_INET6) {
2947 bind_error = EAFNOSUPPORT;
2954 bind_error = EINVAL;
2958 if (bind_error != 0) {
2964 in_use = check_addr_port_in_use(myaddr, addrlen);
2971 si->myname.sa_socklen = addrlen;
2972 memcpy(&si->myname.sa.ss, myaddr, addrlen);
2974 ret = sockaddr_convert_to_un(si,
2980 if (ret == -1) return -1;
2982 unlink(un_addr.sa.un.sun_path);
2984 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
2986 SWRAP_LOG(SWRAP_LOG_TRACE,
2987 "bind() path=%s, fd=%d",
2988 un_addr.sa.un.sun_path, s);
2997 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2999 return swrap_bind(s, myaddr, addrlen);
3002 /****************************************************************************
3004 ***************************************************************************/
3006 #ifdef HAVE_BINDRESVPORT
3007 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3009 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3011 struct swrap_address myaddr = {
3012 .sa_socklen = sizeof(struct sockaddr_storage),
3015 static uint16_t port;
3020 #define SWRAP_STARTPORT 600
3021 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3022 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3025 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3029 salen = myaddr.sa_socklen;
3032 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3038 memset(&myaddr.sa.ss, 0, salen);
3043 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3046 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3048 salen = sizeof(struct sockaddr_in);
3049 sinp->sin_port = htons(port);
3053 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3055 salen = sizeof(struct sockaddr_in6);
3056 sin6p->sin6_port = htons(port);
3060 errno = EAFNOSUPPORT;
3065 if (port > SWRAP_ENDPORT) {
3066 port = SWRAP_STARTPORT;
3069 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3070 if (rc == 0 || errno != EADDRINUSE) {
3078 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3080 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3084 /****************************************************************************
3086 ***************************************************************************/
3088 static int swrap_listen(int s, int backlog)
3091 struct socket_info *si = find_socket_info(s);
3094 return libc_listen(s, backlog);
3097 ret = libc_listen(s, backlog);
3102 int listen(int s, int backlog)
3104 return swrap_listen(s, backlog);
3107 /****************************************************************************
3109 ***************************************************************************/
3111 static FILE *swrap_fopen(const char *name, const char *mode)
3115 fp = libc_fopen(name, mode);
3117 int fd = fileno(fp);
3119 swrap_remove_stale(fd);
3125 FILE *fopen(const char *name, const char *mode)
3127 return swrap_fopen(name, mode);
3130 /****************************************************************************
3132 ***************************************************************************/
3134 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3138 ret = libc_vopen(pathname, flags, ap);
3141 * There are methods for closing descriptors (libc-internal code
3142 * paths, direct syscalls) which close descriptors in ways that
3143 * we can't intercept, so try to recover when we notice that
3146 swrap_remove_stale(ret);
3151 int open(const char *pathname, int flags, ...)
3156 va_start(ap, flags);
3157 fd = swrap_vopen(pathname, flags, ap);
3163 /****************************************************************************
3165 ***************************************************************************/
3167 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3169 struct socket_info *si = find_socket_info(s);
3173 return libc_getpeername(s, name, addrlen);
3176 if (si->peername.sa_socklen == 0)
3182 len = MIN(*addrlen, si->peername.sa_socklen);
3187 memcpy(name, &si->peername.sa.ss, len);
3188 *addrlen = si->peername.sa_socklen;
3193 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3194 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3196 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3199 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3202 /****************************************************************************
3204 ***************************************************************************/
3206 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3208 struct socket_info *si = find_socket_info(s);
3212 return libc_getsockname(s, name, addrlen);
3215 len = MIN(*addrlen, si->myname.sa_socklen);
3220 memcpy(name, &si->myname.sa.ss, len);
3221 *addrlen = si->myname.sa_socklen;
3226 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3227 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3229 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3232 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3235 /****************************************************************************
3237 ***************************************************************************/
3240 # ifdef SO_PROTOTYPE /* The Solaris name */
3241 # define SO_PROTOCOL SO_PROTOTYPE
3242 # endif /* SO_PROTOTYPE */
3243 #endif /* SO_PROTOCOL */
3245 static int swrap_getsockopt(int s, int level, int optname,
3246 void *optval, socklen_t *optlen)
3248 struct socket_info *si = find_socket_info(s);
3251 return libc_getsockopt(s,
3258 if (level == SOL_SOCKET) {
3262 if (optval == NULL || optlen == NULL ||
3263 *optlen < (socklen_t)sizeof(int)) {
3268 *optlen = sizeof(int);
3269 *(int *)optval = si->family;
3271 #endif /* SO_DOMAIN */
3275 if (optval == NULL || optlen == NULL ||
3276 *optlen < (socklen_t)sizeof(int)) {
3281 *optlen = sizeof(int);
3282 *(int *)optval = si->protocol;
3284 #endif /* SO_PROTOCOL */
3286 if (optval == NULL || optlen == NULL ||
3287 *optlen < (socklen_t)sizeof(int)) {
3292 *optlen = sizeof(int);
3293 *(int *)optval = si->type;
3296 return libc_getsockopt(s,
3304 errno = ENOPROTOOPT;
3308 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3309 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3311 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3314 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3317 /****************************************************************************
3319 ***************************************************************************/
3321 static int swrap_setsockopt(int s, int level, int optname,
3322 const void *optval, socklen_t optlen)
3324 struct socket_info *si = find_socket_info(s);
3327 return libc_setsockopt(s,
3334 if (level == SOL_SOCKET) {
3335 return libc_setsockopt(s,
3342 switch (si->family) {
3344 if (level == IPPROTO_IP) {
3346 if (optname == IP_PKTINFO) {
3347 si->pktinfo = AF_INET;
3349 #endif /* IP_PKTINFO */
3354 if (level == IPPROTO_IPV6) {
3355 #ifdef IPV6_RECVPKTINFO
3356 if (optname == IPV6_RECVPKTINFO) {
3357 si->pktinfo = AF_INET6;
3359 #endif /* IPV6_PKTINFO */
3364 errno = ENOPROTOOPT;
3369 int setsockopt(int s, int level, int optname,
3370 const void *optval, socklen_t optlen)
3372 return swrap_setsockopt(s, level, optname, optval, optlen);
3375 /****************************************************************************
3377 ***************************************************************************/
3379 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3381 struct socket_info *si = find_socket_info(s);
3387 return libc_vioctl(s, r, va);
3392 rc = libc_vioctl(s, r, va);
3396 value = *((int *)va_arg(ap, int *));
3398 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3399 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3400 } else if (value == 0) { /* END OF FILE */
3401 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3411 #ifdef HAVE_IOCTL_INT
3412 int ioctl(int s, int r, ...)
3414 int ioctl(int s, unsigned long int r, ...)
3422 rc = swrap_vioctl(s, (unsigned long int) r, va);
3433 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3436 # ifdef _ALIGN /* BSD */
3437 #define CMSG_ALIGN _ALIGN
3439 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3440 # endif /* _ALIGN */
3441 #endif /* CMSG_ALIGN */
3444 * @brief Add a cmsghdr to a msghdr.
3446 * This is an function to add any type of cmsghdr. It will operate on the
3447 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3448 * the buffer position after the added cmsg element. Hence, this function is
3449 * intended to be used with an intermediate msghdr and not on the original
3450 * one handed in by the client.
3452 * @param[in] msg The msghdr to which to add the cmsg.
3454 * @param[in] level The cmsg level to set.
3456 * @param[in] type The cmsg type to set.
3458 * @param[in] data The cmsg data to set.
3460 * @param[in] len the length of the data to set.
3462 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3468 size_t cmlen = CMSG_LEN(len);
3469 size_t cmspace = CMSG_SPACE(len);
3470 uint8_t cmbuf[cmspace];
3471 void *cast_ptr = (void *)cmbuf;
3472 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3475 memset(cmbuf, 0, cmspace);
3477 if (msg->msg_controllen < cmlen) {
3478 cmlen = msg->msg_controllen;
3479 msg->msg_flags |= MSG_CTRUNC;
3482 if (msg->msg_controllen < cmspace) {
3483 cmspace = msg->msg_controllen;
3487 * We copy the full input data into an intermediate cmsghdr first
3488 * in order to more easily cope with truncation.
3490 cm->cmsg_len = cmlen;
3491 cm->cmsg_level = level;
3492 cm->cmsg_type = type;
3493 memcpy(CMSG_DATA(cm), data, len);
3496 * We now copy the possibly truncated buffer.
3497 * We copy cmlen bytes, but consume cmspace bytes,
3498 * leaving the possible padding uninitialiazed.
3500 p = (uint8_t *)msg->msg_control;
3501 memcpy(p, cm, cmlen);
3503 msg->msg_control = p;
3504 msg->msg_controllen -= cmspace;
3509 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3512 /* Add packet info */
3513 switch (si->pktinfo) {
3514 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3516 struct sockaddr_in *sin;
3517 #if defined(HAVE_STRUCT_IN_PKTINFO)
3518 struct in_pktinfo pkt;
3519 #elif defined(IP_RECVDSTADDR)
3523 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3524 sin = &si->bindname.sa.in;
3526 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3529 sin = &si->myname.sa.in;
3534 #if defined(HAVE_STRUCT_IN_PKTINFO)
3535 pkt.ipi_ifindex = socket_wrapper_default_iface();
3536 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3537 #elif defined(IP_RECVDSTADDR)
3538 pkt = sin->sin_addr;
3541 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3546 #endif /* IP_PKTINFO */
3547 #if defined(HAVE_IPV6)
3549 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3550 struct sockaddr_in6 *sin6;
3551 struct in6_pktinfo pkt6;
3553 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3554 sin6 = &si->bindname.sa.in6;
3556 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3559 sin6 = &si->myname.sa.in6;
3564 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3565 pkt6.ipi6_addr = sin6->sin6_addr;
3567 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3568 &pkt6, sizeof(pkt6));
3569 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3573 #endif /* IPV6_PKTINFO */
3581 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3582 struct msghdr *omsg)
3586 if (si->pktinfo > 0) {
3587 rc = swrap_msghdr_add_pktinfo(si, omsg);
3593 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3595 size_t *cm_data_space);
3596 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3598 size_t *cm_data_space);
3600 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3602 size_t *cm_data_space) {
3603 struct cmsghdr *cmsg;
3607 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3611 for (cmsg = CMSG_FIRSTHDR(msg);
3613 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3614 switch (cmsg->cmsg_level) {
3616 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3621 rc = swrap_sendmsg_copy_cmsg(cmsg,
3631 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3633 size_t *cm_data_space)
3640 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3642 p = realloc((*cm_data), cmspace);
3648 p = (*cm_data) + (*cm_data_space);
3649 *cm_data_space = cmspace;
3651 memcpy(p, cmsg, cmsg->cmsg_len);
3656 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3658 size_t *cm_data_space);
3661 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3663 size_t *cm_data_space)
3667 switch(cmsg->cmsg_type) {
3670 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3677 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3689 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3691 size_t *cm_data_space)
3693 (void)cmsg; /* unused */
3694 (void)cm_data; /* unused */
3695 (void)cm_data_space; /* unused */
3698 * Passing a IP pktinfo to a unix socket might be rejected by the
3699 * Kernel, at least on FreeBSD. So skip this cmsg.
3703 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3705 static ssize_t swrap_sendmsg_before(int fd,
3706 struct socket_info *si,
3708 struct iovec *tmp_iov,
3709 struct sockaddr_un *tmp_un,
3710 const struct sockaddr_un **to_un,
3711 const struct sockaddr **to,
3729 if (!si->connected) {
3734 if (msg->msg_iovlen == 0) {
3738 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3740 nlen = len + msg->msg_iov[i].iov_len;
3741 if (nlen > SOCKET_MAX_PACKET) {
3745 msg->msg_iovlen = i;
3746 if (msg->msg_iovlen == 0) {
3747 *tmp_iov = msg->msg_iov[0];
3748 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3749 msg->msg_iov = tmp_iov;
3750 msg->msg_iovlen = 1;
3755 if (si->connected) {
3756 if (msg->msg_name) {
3761 const struct sockaddr *msg_name;
3762 msg_name = (const struct sockaddr *)msg->msg_name;
3764 if (msg_name == NULL) {
3770 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3772 if (ret == -1) return -1;
3780 msg->msg_name = tmp_un;
3781 msg->msg_namelen = sizeof(*tmp_un);
3784 if (si->bound == 0) {
3785 ret = swrap_auto_bind(fd, si, si->family);
3787 if (errno == ENOTSOCK) {
3788 swrap_remove_stale(fd);
3791 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3797 if (!si->defer_connect) {
3801 ret = sockaddr_convert_to_un(si,
3803 si->peername.sa_socklen,
3807 if (ret == -1) return -1;
3809 ret = libc_connect(fd,
3810 (struct sockaddr *)(void *)tmp_un,
3813 /* to give better errors */
3814 if (ret == -1 && errno == ENOENT) {
3815 errno = EHOSTUNREACH;
3822 si->defer_connect = 0;
3825 errno = EHOSTUNREACH;
3829 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3830 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3831 uint8_t *cmbuf = NULL;
3834 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3841 msg->msg_controllen = 0;
3842 msg->msg_control = NULL;
3843 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3844 memcpy(msg->msg_control, cmbuf, cmlen);
3845 msg->msg_controllen = cmlen;
3854 static void swrap_sendmsg_after(int fd,
3855 struct socket_info *si,
3857 const struct sockaddr *to,
3860 int saved_errno = errno;
3867 /* to give better errors */
3869 if (saved_errno == ENOENT) {
3870 saved_errno = EHOSTUNREACH;
3871 } else if (saved_errno == ENOTSOCK) {
3872 /* If the fd is not a socket, remove it */
3873 swrap_remove_stale(fd);
3877 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3878 avail += msg->msg_iov[i].iov_len;
3882 remain = MIN(80, avail);
3887 /* we capture it as one single packet */
3888 buf = (uint8_t *)malloc(remain);
3890 /* we just not capture the packet */
3891 errno = saved_errno;
3895 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3896 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3898 msg->msg_iov[i].iov_base,
3901 remain -= this_time;
3908 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3909 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3911 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3916 if (si->connected) {
3917 to = &si->peername.sa.s;
3920 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3921 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3923 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3929 errno = saved_errno;
3932 static int swrap_recvmsg_before(int fd,
3933 struct socket_info *si,
3935 struct iovec *tmp_iov)
3940 (void)fd; /* unused */
3944 if (!si->connected) {
3949 if (msg->msg_iovlen == 0) {
3953 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3955 nlen = len + msg->msg_iov[i].iov_len;
3956 if (nlen > SOCKET_MAX_PACKET) {
3960 msg->msg_iovlen = i;
3961 if (msg->msg_iovlen == 0) {
3962 *tmp_iov = msg->msg_iov[0];
3963 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3964 msg->msg_iov = tmp_iov;
3965 msg->msg_iovlen = 1;
3970 if (msg->msg_name == NULL) {
3975 if (msg->msg_iovlen == 0) {
3979 if (si->bound == 0) {
3980 ret = swrap_auto_bind(fd, si, si->family);
3983 * When attempting to read or write to a
3984 * descriptor, if an underlying autobind fails
3985 * because it's not a socket, stop intercepting
3986 * uses of that descriptor.
3988 if (errno == ENOTSOCK) {
3989 swrap_remove_stale(fd);
3992 SWRAP_LOG(SWRAP_LOG_ERROR,
3993 "swrap_recvmsg_before failed");
4000 errno = EHOSTUNREACH;
4007 static int swrap_recvmsg_after(int fd,
4008 struct socket_info *si,
4010 const struct sockaddr_un *un_addr,
4011 socklen_t un_addrlen,
4014 int saved_errno = errno;
4016 uint8_t *buf = NULL;
4022 /* to give better errors */
4024 if (saved_errno == ENOENT) {
4025 saved_errno = EHOSTUNREACH;
4026 } else if (saved_errno == ENOTSOCK) {
4027 /* If the fd is not a socket, remove it */
4028 swrap_remove_stale(fd);
4032 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4033 avail += msg->msg_iov[i].iov_len;
4042 remain = MIN(80, avail);
4047 /* we capture it as one single packet */
4048 buf = (uint8_t *)malloc(remain);
4050 /* we just not capture the packet */
4051 errno = saved_errno;
4055 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4056 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4058 msg->msg_iov[i].iov_base,
4061 remain -= this_time;
4066 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4067 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4068 } else if (ret == 0) { /* END OF FILE */
4069 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4070 } else if (ret > 0) {
4071 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4080 if (un_addr != NULL) {
4081 rc = sockaddr_convert_from_un(si,
4091 swrap_pcap_dump_packet(si,
4097 swrap_pcap_dump_packet(si,
4110 errno = saved_errno;
4112 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4114 msg->msg_controllen > 0 &&
4115 msg->msg_control != NULL) {
4116 rc = swrap_msghdr_add_socket_info(si, msg);
4126 /****************************************************************************
4128 ***************************************************************************/
4130 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4131 struct sockaddr *from, socklen_t *fromlen)
4133 struct swrap_address from_addr = {
4134 .sa_socklen = sizeof(struct sockaddr_un),
4137 struct socket_info *si = find_socket_info(s);
4138 struct swrap_address saddr = {
4139 .sa_socklen = sizeof(struct sockaddr_storage),
4146 return libc_recvfrom(s,
4158 if (from != NULL && fromlen != NULL) {
4159 msg.msg_name = from; /* optional address */
4160 msg.msg_namelen = *fromlen; /* size of address */
4162 msg.msg_name = &saddr.sa.s; /* optional address */
4163 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4165 msg.msg_iov = &tmp; /* scatter/gather array */
4166 msg.msg_iovlen = 1; /* # elements in msg_iov */
4167 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4168 msg.msg_control = NULL; /* ancillary data, see below */
4169 msg.msg_controllen = 0; /* ancillary data buffer len */
4170 msg.msg_flags = 0; /* flags on received message */
4173 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4178 buf = msg.msg_iov[0].iov_base;
4179 len = msg.msg_iov[0].iov_len;
4181 ret = libc_recvfrom(s,
4186 &from_addr.sa_socklen);
4191 tret = swrap_recvmsg_after(s,
4195 from_addr.sa_socklen,
4201 if (from != NULL && fromlen != NULL) {
4202 *fromlen = msg.msg_namelen;
4208 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4209 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4210 struct sockaddr *from, Psocklen_t fromlen)
4212 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4213 struct sockaddr *from, socklen_t *fromlen)
4216 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4219 /****************************************************************************
4221 ***************************************************************************/
4223 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4224 const struct sockaddr *to, socklen_t tolen)
4228 struct swrap_address un_addr = {
4229 .sa_socklen = sizeof(struct sockaddr_un),
4231 const struct sockaddr_un *to_un = NULL;
4234 struct socket_info *si = find_socket_info(s);
4238 return libc_sendto(s, buf, len, flags, to, tolen);
4241 tmp.iov_base = discard_const_p(char, buf);
4245 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4246 msg.msg_namelen = tolen; /* size of address */
4247 msg.msg_iov = &tmp; /* scatter/gather array */
4248 msg.msg_iovlen = 1; /* # elements in msg_iov */
4249 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4250 msg.msg_control = NULL; /* ancillary data, see below */
4251 msg.msg_controllen = 0; /* ancillary data buffer len */
4252 msg.msg_flags = 0; /* flags on received message */
4255 rc = swrap_sendmsg_before(s,
4267 buf = msg.msg_iov[0].iov_base;
4268 len = msg.msg_iov[0].iov_len;
4273 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4276 type = SOCKET_TYPE_CHAR_UDP;
4278 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4279 snprintf(un_addr.sa.un.sun_path,
4280 sizeof(un_addr.sa.un.sun_path),
4282 socket_wrapper_dir(), type, iface, prt);
4283 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4285 /* ignore the any errors in broadcast sends */
4291 un_addr.sa_socklen);
4294 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4299 ret = libc_sendto(s,
4303 (struct sockaddr *)msg.msg_name,
4306 swrap_sendmsg_after(s, si, &msg, to, ret);
4311 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4312 const struct sockaddr *to, socklen_t tolen)
4314 return swrap_sendto(s, buf, len, flags, to, tolen);
4317 /****************************************************************************
4319 ***************************************************************************/
4321 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4323 struct socket_info *si;
4325 struct swrap_address saddr = {
4326 .sa_socklen = sizeof(struct sockaddr_storage),
4332 si = find_socket_info(s);
4334 return libc_recv(s, buf, len, flags);
4341 msg.msg_name = &saddr.sa.s; /* optional address */
4342 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4343 msg.msg_iov = &tmp; /* scatter/gather array */
4344 msg.msg_iovlen = 1; /* # elements in msg_iov */
4345 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4346 msg.msg_control = NULL; /* ancillary data, see below */
4347 msg.msg_controllen = 0; /* ancillary data buffer len */
4348 msg.msg_flags = 0; /* flags on received message */
4351 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4356 buf = msg.msg_iov[0].iov_base;
4357 len = msg.msg_iov[0].iov_len;
4359 ret = libc_recv(s, buf, len, flags);
4361 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4369 ssize_t recv(int s, void *buf, size_t len, int flags)
4371 return swrap_recv(s, buf, len, flags);
4374 /****************************************************************************
4376 ***************************************************************************/
4378 static ssize_t swrap_read(int s, void *buf, size_t len)
4380 struct socket_info *si;
4383 struct swrap_address saddr = {
4384 .sa_socklen = sizeof(struct sockaddr_storage),
4389 si = find_socket_info(s);
4391 return libc_read(s, buf, len);
4398 msg.msg_name = &saddr.sa.ss; /* optional address */
4399 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4400 msg.msg_iov = &tmp; /* scatter/gather array */
4401 msg.msg_iovlen = 1; /* # elements in msg_iov */
4402 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4403 msg.msg_control = NULL; /* ancillary data, see below */
4404 msg.msg_controllen = 0; /* ancillary data buffer len */
4405 msg.msg_flags = 0; /* flags on received message */
4408 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4410 if (tret == -ENOTSOCK) {
4411 return libc_read(s, buf, len);
4416 buf = msg.msg_iov[0].iov_base;
4417 len = msg.msg_iov[0].iov_len;
4419 ret = libc_read(s, buf, len);
4421 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4429 ssize_t read(int s, void *buf, size_t len)
4431 return swrap_read(s, buf, len);
4434 /****************************************************************************
4436 ***************************************************************************/
4438 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4442 struct sockaddr_un un_addr;
4445 struct socket_info *si = find_socket_info(s);
4448 return libc_send(s, buf, len, flags);
4451 tmp.iov_base = discard_const_p(char, buf);
4455 msg.msg_name = NULL; /* optional address */
4456 msg.msg_namelen = 0; /* size of address */
4457 msg.msg_iov = &tmp; /* scatter/gather array */
4458 msg.msg_iovlen = 1; /* # elements in msg_iov */
4459 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4460 msg.msg_control = NULL; /* ancillary data, see below */
4461 msg.msg_controllen = 0; /* ancillary data buffer len */
4462 msg.msg_flags = 0; /* flags on received message */
4465 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4470 buf = msg.msg_iov[0].iov_base;
4471 len = msg.msg_iov[0].iov_len;
4473 ret = libc_send(s, buf, len, flags);
4475 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4480 ssize_t send(int s, const void *buf, size_t len, int flags)
4482 return swrap_send(s, buf, len, flags);
4485 /****************************************************************************
4487 ***************************************************************************/
4489 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4491 struct swrap_address from_addr = {
4492 .sa_socklen = sizeof(struct sockaddr_un),
4494 struct socket_info *si;
4497 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4498 size_t msg_ctrllen_filled;
4499 size_t msg_ctrllen_left;
4505 si = find_socket_info(s);
4507 return libc_recvmsg(s, omsg, flags);
4510 tmp.iov_base = NULL;
4514 msg.msg_name = &from_addr.sa; /* optional address */
4515 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4516 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4517 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4518 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4519 msg_ctrllen_filled = 0;
4520 msg_ctrllen_left = omsg->msg_controllen;
4522 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4523 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4524 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4527 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4532 ret = libc_recvmsg(s, &msg, flags);
4534 msg.msg_name = omsg->msg_name;
4535 msg.msg_namelen = omsg->msg_namelen;
4537 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4538 msg_ctrllen_filled += msg.msg_controllen;
4539 msg_ctrllen_left -= msg.msg_controllen;
4541 if (omsg->msg_control != NULL) {
4544 p = omsg->msg_control;
4545 p += msg_ctrllen_filled;
4547 msg.msg_control = p;
4548 msg.msg_controllen = msg_ctrllen_left;
4550 msg.msg_control = NULL;
4551 msg.msg_controllen = 0;
4555 rc = swrap_recvmsg_after(s,
4559 from_addr.sa_socklen,
4565 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4566 if (omsg->msg_control != NULL) {
4567 /* msg.msg_controllen = space left */
4568 msg_ctrllen_left = msg.msg_controllen;
4569 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4572 /* Update the original message length */
4573 omsg->msg_controllen = msg_ctrllen_filled;
4574 omsg->msg_flags = msg.msg_flags;
4576 omsg->msg_iovlen = msg.msg_iovlen;
4581 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4583 return swrap_recvmsg(sockfd, msg, flags);
4586 /****************************************************************************
4588 ***************************************************************************/
4590 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4594 struct sockaddr_un un_addr;
4595 const struct sockaddr_un *to_un = NULL;
4596 const struct sockaddr *to = NULL;
4599 struct socket_info *si = find_socket_info(s);
4603 return libc_sendmsg(s, omsg, flags);
4606 ZERO_STRUCT(un_addr);
4608 tmp.iov_base = NULL;
4612 msg.msg_name = omsg->msg_name; /* optional address */
4613 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4614 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4615 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4616 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4617 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4618 /* omsg is a const so use a local buffer for modifications */
4619 uint8_t cmbuf[omsg->msg_controllen];
4621 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4623 msg.msg_control = cmbuf; /* ancillary data, see below */
4624 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4626 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4629 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4637 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4645 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4646 avail += msg.msg_iov[i].iov_len;
4652 /* we capture it as one single packet */
4653 buf = (uint8_t *)malloc(remain);
4658 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4659 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4661 msg.msg_iov[i].iov_base,
4664 remain -= this_time;
4667 type = SOCKET_TYPE_CHAR_UDP;
4669 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4670 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4671 socket_wrapper_dir(), type, iface, prt);
4672 if (stat(un_addr.sun_path, &st) != 0) continue;
4674 msg.msg_name = &un_addr; /* optional address */
4675 msg.msg_namelen = sizeof(un_addr); /* size of address */
4677 /* ignore the any errors in broadcast sends */
4678 libc_sendmsg(s, &msg, flags);
4681 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4687 ret = libc_sendmsg(s, &msg, flags);
4689 swrap_sendmsg_after(s, si, &msg, to, ret);
4694 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4696 return swrap_sendmsg(s, omsg, flags);
4699 /****************************************************************************
4701 ***************************************************************************/
4703 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4705 struct socket_info *si;
4708 struct swrap_address saddr = {
4709 .sa_socklen = sizeof(struct sockaddr_storage)
4714 si = find_socket_info(s);
4716 return libc_readv(s, vector, count);
4719 tmp.iov_base = NULL;
4723 msg.msg_name = &saddr.sa.s; /* optional address */
4724 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4725 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4726 msg.msg_iovlen = count; /* # elements in msg_iov */
4727 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4728 msg.msg_control = NULL; /* ancillary data, see below */
4729 msg.msg_controllen = 0; /* ancillary data buffer len */
4730 msg.msg_flags = 0; /* flags on received message */
4733 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4735 if (rc == -ENOTSOCK) {
4736 return libc_readv(s, vector, count);
4741 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4743 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4751 ssize_t readv(int s, const struct iovec *vector, int count)
4753 return swrap_readv(s, vector, count);
4756 /****************************************************************************
4758 ***************************************************************************/
4760 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4764 struct sockaddr_un un_addr;
4767 struct socket_info *si = find_socket_info(s);
4770 return libc_writev(s, vector, count);
4773 tmp.iov_base = NULL;
4777 msg.msg_name = NULL; /* optional address */
4778 msg.msg_namelen = 0; /* size of address */
4779 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4780 msg.msg_iovlen = count; /* # elements in msg_iov */
4781 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4782 msg.msg_control = NULL; /* ancillary data, see below */
4783 msg.msg_controllen = 0; /* ancillary data buffer len */
4784 msg.msg_flags = 0; /* flags on received message */
4787 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4789 if (rc == -ENOTSOCK) {
4790 return libc_readv(s, vector, count);
4795 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4797 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4802 ssize_t writev(int s, const struct iovec *vector, int count)
4804 return swrap_writev(s, vector, count);
4807 /****************************
4809 ***************************/
4811 static int swrap_close(int fd)
4813 struct socket_info *si = find_socket_info(fd);
4814 struct socket_info_fd *fi;
4818 return libc_close(fd);
4821 for (fi = si->fds; fi; fi = fi->next) {
4823 SWRAP_DLIST_REMOVE(si->fds, fi);
4830 /* there are still references left */
4831 return libc_close(fd);
4834 SWRAP_DLIST_REMOVE(sockets, si);
4836 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4837 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4840 ret = libc_close(fd);
4842 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4843 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4844 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4847 if (si->un_addr.sun_path[0] != '\0') {
4848 unlink(si->un_addr.sun_path);
4857 return swrap_close(fd);
4860 /****************************
4862 ***************************/
4864 static int swrap_dup(int fd)
4866 struct socket_info *si;
4867 struct socket_info_fd *fi;
4869 si = find_socket_info(fd);
4872 return libc_dup(fd);
4875 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4881 fi->fd = libc_dup(fd);
4883 int saved_errno = errno;
4885 errno = saved_errno;
4889 /* Make sure we don't have an entry for the fd */
4890 swrap_remove_stale(fi->fd);
4892 SWRAP_DLIST_ADD(si->fds, fi);
4898 return swrap_dup(fd);
4901 /****************************
4903 ***************************/
4905 static int swrap_dup2(int fd, int newfd)
4907 struct socket_info *si;
4908 struct socket_info_fd *fi;
4910 si = find_socket_info(fd);
4913 return libc_dup2(fd, newfd);
4916 if (find_socket_info(newfd)) {
4917 /* dup2() does an implicit close of newfd, which we
4918 * need to emulate */
4922 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4928 fi->fd = libc_dup2(fd, newfd);
4930 int saved_errno = errno;
4932 errno = saved_errno;
4936 /* Make sure we don't have an entry for the fd */
4937 swrap_remove_stale(fi->fd);
4939 SWRAP_DLIST_ADD(si->fds, fi);
4943 int dup2(int fd, int newfd)
4945 return swrap_dup2(fd, newfd);
4948 /****************************
4950 ***************************/
4952 static int swrap_vfcntl(int fd, int cmd, va_list va)
4954 struct socket_info_fd *fi;
4955 struct socket_info *si;
4958 si = find_socket_info(fd);
4960 rc = libc_vfcntl(fd, cmd, va);
4967 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4973 fi->fd = libc_vfcntl(fd, cmd, va);
4975 int saved_errno = errno;
4977 errno = saved_errno;
4981 /* Make sure we don't have an entry for the fd */
4982 swrap_remove_stale(fi->fd);
4984 SWRAP_DLIST_ADD(si->fds, fi);
4989 rc = libc_vfcntl(fd, cmd, va);
4996 int fcntl(int fd, int cmd, ...)
5003 rc = swrap_vfcntl(fd, cmd, va);
5010 /****************************
5012 ***************************/
5015 static int swrap_eventfd(int count, int flags)
5019 fd = libc_eventfd(count, flags);
5021 swrap_remove_stale(fd);
5027 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5028 int eventfd(unsigned int count, int flags)
5030 int eventfd(int count, int flags)
5033 return swrap_eventfd(count, flags);
5037 /****************************
5039 ***************************/
5042 * This function is called when the library is unloaded and makes sure that
5043 * sockets get closed and the unix file for the socket are unlinked.
5045 void swrap_destructor(void)
5047 struct socket_info *s = sockets;
5050 struct socket_info_fd *f = s->fds;