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_ADDRESS_SANITIZER_ATTRIBUTE
104 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
106 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
109 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
110 # define SWRAP_THREAD __thread
112 # define SWRAP_THREAD
116 #define MIN(a,b) ((a)<(b)?(a):(b))
120 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
124 #define ZERO_STRUCTP(x) do { \
126 memset((char *)(x), 0, sizeof(*(x))); \
130 #ifndef discard_const
131 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
134 #ifndef discard_const_p
135 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
139 # ifndef IPV6_RECVPKTINFO
140 # define IPV6_RECVPKTINFO IPV6_PKTINFO
141 # endif /* IPV6_RECVPKTINFO */
142 #endif /* IPV6_PKTINFO */
145 * On BSD IP_PKTINFO has a different name because during
146 * the time when they implemented it, there was no RFC.
147 * The name for IPv6 is the same as on Linux.
150 # ifdef IP_RECVDSTADDR
151 # define IP_PKTINFO IP_RECVDSTADDR
156 #define SWRAP_DLIST_ADD(list,item) do { \
158 (item)->prev = NULL; \
159 (item)->next = NULL; \
162 (item)->prev = NULL; \
163 (item)->next = (list); \
164 (list)->prev = (item); \
169 #define SWRAP_DLIST_REMOVE(list,item) do { \
170 if ((list) == (item)) { \
171 (list) = (item)->next; \
173 (list)->prev = NULL; \
176 if ((item)->prev) { \
177 (item)->prev->next = (item)->next; \
179 if ((item)->next) { \
180 (item)->next->prev = (item)->prev; \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
187 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
188 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
190 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
193 /* we need to use a very terse format here as IRIX 6.4 silently
194 truncates names to 16 chars, so if we use a longer name then we
195 can't tell which port a packet came from with recvfrom()
197 with this format we have 8 chars left for the directory name
199 #define SOCKET_FORMAT "%c%02X%04X"
200 #define SOCKET_TYPE_CHAR_TCP 'T'
201 #define SOCKET_TYPE_CHAR_UDP 'U'
202 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
203 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
206 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
207 * format PCAP capture files (as the caller will simply continue from here).
209 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
210 #define SOCKET_WRAPPER_MTU_MIN 512
211 #define SOCKET_WRAPPER_MTU_MAX 32768
213 #define SOCKET_MAX_SOCKETS 1024
215 /* This limit is to avoid broadcast sendto() needing to stat too many
216 * files. It may be raised (with a performance cost) to up to 254
217 * without changing the format above */
218 #define MAX_WRAPPED_INTERFACES 40
220 struct swrap_address {
221 socklen_t sa_socklen;
224 struct sockaddr_in in;
226 struct sockaddr_in6 in6;
228 struct sockaddr_un un;
229 struct sockaddr_storage ss;
233 struct socket_info_fd {
234 struct socket_info_fd *prev, *next;
240 struct socket_info_fd *fds;
253 /* The unix path so we can unlink it on close() */
254 struct sockaddr_un un_addr;
256 struct swrap_address bindname;
257 struct swrap_address myname;
258 struct swrap_address peername;
261 unsigned long pck_snd;
262 unsigned long pck_rcv;
265 struct socket_info *prev, *next;
269 * File descriptors are shared between threads so we should share socket
272 struct socket_info *sockets;
274 /* Function prototypes */
276 bool socket_wrapper_enabled(void);
277 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
280 # define SWRAP_LOG(...)
283 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
284 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
286 static void swrap_log(enum swrap_dbglvl_e dbglvl,
288 const char *format, ...)
293 unsigned int lvl = 0;
295 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
300 va_start(va, format);
301 vsnprintf(buffer, sizeof(buffer), format, va);
306 case SWRAP_LOG_ERROR:
308 "SWRAP_ERROR(%d) - %s: %s\n",
309 (int)getpid(), func, buffer);
313 "SWRAP_WARN(%d) - %s: %s\n",
314 (int)getpid(), func, buffer);
316 case SWRAP_LOG_DEBUG:
318 "SWRAP_DEBUG(%d) - %s: %s\n",
319 (int)getpid(), func, buffer);
321 case SWRAP_LOG_TRACE:
323 "SWRAP_TRACE(%d) - %s: %s\n",
324 (int)getpid(), func, buffer);
331 /*********************************************************
332 * SWRAP LOADING LIBC FUNCTIONS
333 *********************************************************/
337 struct swrap_libc_fns {
339 int (*libc_accept4)(int sockfd,
340 struct sockaddr *addr,
344 int (*libc_accept)(int sockfd,
345 struct sockaddr *addr,
348 int (*libc_bind)(int sockfd,
349 const struct sockaddr *addr,
351 int (*libc_close)(int fd);
352 int (*libc_connect)(int sockfd,
353 const struct sockaddr *addr,
355 int (*libc_dup)(int fd);
356 int (*libc_dup2)(int oldfd, int newfd);
357 int (*libc_fcntl)(int fd, int cmd, ...);
358 FILE *(*libc_fopen)(const char *name, const char *mode);
360 int (*libc_eventfd)(int count, int flags);
362 int (*libc_getpeername)(int sockfd,
363 struct sockaddr *addr,
365 int (*libc_getsockname)(int sockfd,
366 struct sockaddr *addr,
368 int (*libc_getsockopt)(int sockfd,
373 int (*libc_ioctl)(int d, unsigned long int request, ...);
374 int (*libc_listen)(int sockfd, int backlog);
375 int (*libc_open)(const char *pathname, int flags, mode_t mode);
376 int (*libc_pipe)(int pipefd[2]);
377 int (*libc_read)(int fd, void *buf, size_t count);
378 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
379 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
380 int (*libc_recvfrom)(int sockfd,
384 struct sockaddr *src_addr,
386 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
387 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
388 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
389 int (*libc_sendto)(int sockfd,
393 const struct sockaddr *dst_addr,
395 int (*libc_setsockopt)(int sockfd,
401 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
403 int (*libc_socket)(int domain, int type, int protocol);
404 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
405 #ifdef HAVE_TIMERFD_CREATE
406 int (*libc_timerfd_create)(int clockid, int flags);
408 ssize_t (*libc_write)(int fd, const void *buf, size_t count);
409 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
414 void *libsocket_handle;
421 struct swrap_libc_fns fns;
424 static struct swrap swrap;
427 static const char *socket_wrapper_dir(void);
429 #define LIBC_NAME "libc.so"
438 static const char *swrap_str_lib(enum swrap_lib lib)
445 case SWRAP_LIBSOCKET:
449 /* Compiler would warn us about unhandled enum value if we get here */
454 static void *swrap_load_lib_handle(enum swrap_lib lib)
456 int flags = RTLD_LAZY;
461 flags |= RTLD_DEEPBIND;
467 case SWRAP_LIBSOCKET:
468 #ifdef HAVE_LIBSOCKET
469 handle = swrap.libsocket_handle;
470 if (handle == NULL) {
471 for (i = 10; i >= 0; i--) {
472 char soname[256] = {0};
474 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
475 handle = dlopen(soname, flags);
476 if (handle != NULL) {
481 swrap.libsocket_handle = handle;
487 handle = swrap.libc_handle;
489 if (handle == NULL) {
490 handle = dlopen(LIBC_SO, flags);
492 swrap.libc_handle = handle;
495 if (handle == NULL) {
496 for (i = 10; i >= 0; i--) {
497 char soname[256] = {0};
499 snprintf(soname, sizeof(soname), "libc.so.%d", i);
500 handle = dlopen(soname, flags);
501 if (handle != NULL) {
506 swrap.libc_handle = handle;
511 if (handle == NULL) {
513 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
515 SWRAP_LOG(SWRAP_LOG_ERROR,
516 "Failed to dlopen library: %s\n",
525 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
530 handle = swrap_load_lib_handle(lib);
532 func = dlsym(handle, fn_name);
534 SWRAP_LOG(SWRAP_LOG_ERROR,
535 "Failed to find %s: %s\n",
540 SWRAP_LOG(SWRAP_LOG_TRACE,
542 fn_name, swrap_str_lib(lib));
546 #define swrap_load_lib_function(lib, fn_name) \
547 if (swrap.fns.libc_##fn_name == NULL) { \
548 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
549 *(void **) (&swrap.fns.libc_##fn_name) = \
557 * Functions especially from libc need to be loaded individually, you can't load
558 * all at once or gdb will segfault at startup. The same applies to valgrind and
559 * has probably something todo with with the linker.
560 * So we need load each function at the point it is called the first time.
563 static int libc_accept4(int sockfd,
564 struct sockaddr *addr,
568 swrap_load_lib_function(SWRAP_LIBSOCKET, accept4);
570 return swrap.fns.libc_accept4(sockfd, addr, addrlen, flags);
573 #else /* HAVE_ACCEPT4 */
575 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
577 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
579 return swrap.fns.libc_accept(sockfd, addr, addrlen);
581 #endif /* HAVE_ACCEPT4 */
583 static int libc_bind(int sockfd,
584 const struct sockaddr *addr,
587 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
589 return swrap.fns.libc_bind(sockfd, addr, addrlen);
592 static int libc_close(int fd)
594 swrap_load_lib_function(SWRAP_LIBC, close);
596 return swrap.fns.libc_close(fd);
599 static int libc_connect(int sockfd,
600 const struct sockaddr *addr,
603 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
605 return swrap.fns.libc_connect(sockfd, addr, addrlen);
608 static int libc_dup(int fd)
610 swrap_load_lib_function(SWRAP_LIBC, dup);
612 return swrap.fns.libc_dup(fd);
615 static int libc_dup2(int oldfd, int newfd)
617 swrap_load_lib_function(SWRAP_LIBC, dup2);
619 return swrap.fns.libc_dup2(oldfd, newfd);
623 static int libc_eventfd(int count, int flags)
625 swrap_load_lib_function(SWRAP_LIBC, eventfd);
627 return swrap.fns.libc_eventfd(count, flags);
631 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
632 static int libc_vfcntl(int fd, int cmd, va_list ap)
638 swrap_load_lib_function(SWRAP_LIBC, fcntl);
640 for (i = 0; i < 4; i++) {
641 args[i] = va_arg(ap, long int);
644 rc = swrap.fns.libc_fcntl(fd,
654 static int libc_getpeername(int sockfd,
655 struct sockaddr *addr,
658 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
660 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
663 static int libc_getsockname(int sockfd,
664 struct sockaddr *addr,
667 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
669 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
672 static int libc_getsockopt(int sockfd,
678 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
680 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
683 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
684 static int libc_vioctl(int d, unsigned long int request, va_list ap)
690 swrap_load_lib_function(SWRAP_LIBC, ioctl);
692 for (i = 0; i < 4; i++) {
693 args[i] = va_arg(ap, long int);
696 rc = swrap.fns.libc_ioctl(d,
706 static int libc_listen(int sockfd, int backlog)
708 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
710 return swrap.fns.libc_listen(sockfd, backlog);
713 static FILE *libc_fopen(const char *name, const char *mode)
715 swrap_load_lib_function(SWRAP_LIBC, fopen);
717 return swrap.fns.libc_fopen(name, mode);
720 static int libc_vopen(const char *pathname, int flags, va_list ap)
725 swrap_load_lib_function(SWRAP_LIBC, open);
727 mode = va_arg(ap, long int);
729 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
734 static int libc_open(const char *pathname, int flags, ...)
740 fd = libc_vopen(pathname, flags, ap);
746 static int libc_pipe(int pipefd[2])
748 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
750 return swrap.fns.libc_pipe(pipefd);
753 static int libc_read(int fd, void *buf, size_t count)
755 swrap_load_lib_function(SWRAP_LIBC, read);
757 return swrap.fns.libc_read(fd, buf, count);
760 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
762 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
764 return swrap.fns.libc_readv(fd, iov, iovcnt);
767 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
769 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
771 return swrap.fns.libc_recv(sockfd, buf, len, flags);
774 static int libc_recvfrom(int sockfd,
778 struct sockaddr *src_addr,
781 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
783 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
786 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
788 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
790 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
793 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
795 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
797 return swrap.fns.libc_send(sockfd, buf, len, flags);
800 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
802 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
804 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
807 static int libc_sendto(int sockfd,
811 const struct sockaddr *dst_addr,
814 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
816 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
819 static int libc_setsockopt(int sockfd,
825 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
827 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
831 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
833 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
835 return swrap.fns.libc_signalfd(fd, mask, flags);
839 static int libc_socket(int domain, int type, int protocol)
841 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
843 return swrap.fns.libc_socket(domain, type, protocol);
846 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
848 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
850 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
853 #ifdef HAVE_TIMERFD_CREATE
854 static int libc_timerfd_create(int clockid, int flags)
856 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
858 return swrap.fns.libc_timerfd_create(clockid, flags);
862 static ssize_t libc_write(int fd, const void *buf, size_t count)
864 swrap_load_lib_function(SWRAP_LIBC, write);
866 return swrap.fns.libc_write(fd, buf, count);
869 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
871 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
873 return swrap.fns.libc_writev(fd, iov, iovcnt);
876 /*********************************************************
877 * SWRAP HELPER FUNCTIONS
878 *********************************************************/
884 static const struct in6_addr *swrap_ipv6(void)
886 static struct in6_addr v;
887 static int initialized;
895 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
904 static void set_port(int family, int prt, struct swrap_address *addr)
908 addr->sa.in.sin_port = htons(prt);
912 addr->sa.in6.sin6_port = htons(prt);
918 static size_t socket_length(int family)
922 return sizeof(struct sockaddr_in);
925 return sizeof(struct sockaddr_in6);
931 static const char *socket_wrapper_dir(void)
933 const char *s = getenv("SOCKET_WRAPPER_DIR");
937 /* TODO use realpath(3) here, when we add support for threads */
938 if (strncmp(s, "./", 2) == 0) {
942 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
946 static unsigned int socket_wrapper_mtu(void)
948 static unsigned int max_mtu = 0;
957 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
959 s = getenv("SOCKET_WRAPPER_MTU");
964 tmp = strtol(s, &endp, 10);
969 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
978 bool socket_wrapper_enabled(void)
980 const char *s = socket_wrapper_dir();
982 return s != NULL ? true : false;
985 static unsigned int socket_wrapper_default_iface(void)
987 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
990 if (sscanf(s, "%u", &iface) == 1) {
991 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
997 return 1;/* 127.0.0.1 */
1000 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1007 p = strrchr(un->sun_path, '/');
1008 if (p) p++; else p = un->sun_path;
1010 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1015 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1018 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1029 case SOCKET_TYPE_CHAR_TCP:
1030 case SOCKET_TYPE_CHAR_UDP: {
1031 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1033 if ((*len) < sizeof(*in2)) {
1038 memset(in2, 0, sizeof(*in2));
1039 in2->sin_family = AF_INET;
1040 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1041 in2->sin_port = htons(prt);
1043 *len = sizeof(*in2);
1047 case SOCKET_TYPE_CHAR_TCP_V6:
1048 case SOCKET_TYPE_CHAR_UDP_V6: {
1049 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1051 if ((*len) < sizeof(*in2)) {
1056 memset(in2, 0, sizeof(*in2));
1057 in2->sin6_family = AF_INET6;
1058 in2->sin6_addr = *swrap_ipv6();
1059 in2->sin6_addr.s6_addr[15] = iface;
1060 in2->sin6_port = htons(prt);
1062 *len = sizeof(*in2);
1074 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1082 if (bcast) *bcast = 0;
1084 switch (inaddr->sa_family) {
1086 const struct sockaddr_in *in =
1087 (const struct sockaddr_in *)(const void *)inaddr;
1088 unsigned int addr = ntohl(in->sin_addr.s_addr);
1095 u_type = SOCKET_TYPE_CHAR_TCP;
1098 u_type = SOCKET_TYPE_CHAR_UDP;
1099 a_type = SOCKET_TYPE_CHAR_UDP;
1100 b_type = SOCKET_TYPE_CHAR_UDP;
1103 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1104 errno = ESOCKTNOSUPPORT;
1108 prt = ntohs(in->sin_port);
1109 if (a_type && addr == 0xFFFFFFFF) {
1110 /* 255.255.255.255 only udp */
1113 iface = socket_wrapper_default_iface();
1114 } else if (b_type && addr == 0x7FFFFFFF) {
1115 /* 127.255.255.255 only udp */
1118 iface = socket_wrapper_default_iface();
1119 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1123 iface = (addr & 0x000000FF);
1125 errno = ENETUNREACH;
1128 if (bcast) *bcast = is_bcast;
1133 const struct sockaddr_in6 *in =
1134 (const struct sockaddr_in6 *)(const void *)inaddr;
1135 struct in6_addr cmp1, cmp2;
1139 type = SOCKET_TYPE_CHAR_TCP_V6;
1142 type = SOCKET_TYPE_CHAR_UDP_V6;
1145 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1146 errno = ESOCKTNOSUPPORT;
1150 /* XXX no multicast/broadcast */
1152 prt = ntohs(in->sin6_port);
1154 cmp1 = *swrap_ipv6();
1155 cmp2 = in->sin6_addr;
1156 cmp2.s6_addr[15] = 0;
1157 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1158 iface = in->sin6_addr.s6_addr[15];
1160 errno = ENETUNREACH;
1168 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1169 errno = ENETUNREACH;
1174 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1180 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1181 socket_wrapper_dir());
1182 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1183 /* the caller need to do more processing */
1187 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1188 socket_wrapper_dir(), type, iface, prt);
1189 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1194 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1203 if (bcast) *bcast = 0;
1205 switch (si->family) {
1207 const struct sockaddr_in *in =
1208 (const struct sockaddr_in *)(const void *)inaddr;
1209 unsigned int addr = ntohl(in->sin_addr.s_addr);
1215 prt = ntohs(in->sin_port);
1219 u_type = SOCKET_TYPE_CHAR_TCP;
1220 d_type = SOCKET_TYPE_CHAR_TCP;
1223 u_type = SOCKET_TYPE_CHAR_UDP;
1224 d_type = SOCKET_TYPE_CHAR_UDP;
1225 a_type = SOCKET_TYPE_CHAR_UDP;
1226 b_type = SOCKET_TYPE_CHAR_UDP;
1229 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1230 errno = ESOCKTNOSUPPORT;
1238 iface = socket_wrapper_default_iface();
1239 } else if (a_type && addr == 0xFFFFFFFF) {
1240 /* 255.255.255.255 only udp */
1243 iface = socket_wrapper_default_iface();
1244 } else if (b_type && addr == 0x7FFFFFFF) {
1245 /* 127.255.255.255 only udp */
1248 iface = socket_wrapper_default_iface();
1249 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1253 iface = (addr & 0x000000FF);
1255 errno = EADDRNOTAVAIL;
1259 /* Store the bind address for connect() */
1260 if (si->bindname.sa_socklen == 0) {
1261 struct sockaddr_in bind_in;
1262 socklen_t blen = sizeof(struct sockaddr_in);
1264 ZERO_STRUCT(bind_in);
1265 bind_in.sin_family = in->sin_family;
1266 bind_in.sin_port = in->sin_port;
1267 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1269 si->bindname.sa_socklen = blen;
1270 memcpy(&si->bindname.sa.in, &bind_in, blen);
1277 const struct sockaddr_in6 *in =
1278 (const struct sockaddr_in6 *)(const void *)inaddr;
1279 struct in6_addr cmp1, cmp2;
1283 type = SOCKET_TYPE_CHAR_TCP_V6;
1286 type = SOCKET_TYPE_CHAR_UDP_V6;
1289 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1290 errno = ESOCKTNOSUPPORT;
1294 /* XXX no multicast/broadcast */
1296 prt = ntohs(in->sin6_port);
1298 cmp1 = *swrap_ipv6();
1299 cmp2 = in->sin6_addr;
1300 cmp2.s6_addr[15] = 0;
1301 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1302 iface = socket_wrapper_default_iface();
1303 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1304 iface = in->sin6_addr.s6_addr[15];
1306 errno = EADDRNOTAVAIL;
1310 /* Store the bind address for connect() */
1311 if (si->bindname.sa_socklen == 0) {
1312 struct sockaddr_in6 bind_in;
1313 socklen_t blen = sizeof(struct sockaddr_in6);
1315 ZERO_STRUCT(bind_in);
1316 bind_in.sin6_family = in->sin6_family;
1317 bind_in.sin6_port = in->sin6_port;
1319 bind_in.sin6_addr = *swrap_ipv6();
1320 bind_in.sin6_addr.s6_addr[15] = iface;
1322 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1323 si->bindname.sa_socklen = blen;
1330 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1331 errno = EADDRNOTAVAIL;
1336 if (bcast) *bcast = is_bcast;
1338 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1344 /* handle auto-allocation of ephemeral ports */
1345 for (prt = 5001; prt < 10000; prt++) {
1346 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1347 socket_wrapper_dir(), type, iface, prt);
1348 if (stat(un->sun_path, &st) == 0) continue;
1350 set_port(si->family, prt, &si->myname);
1351 set_port(si->family, prt, &si->bindname);
1361 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1362 socket_wrapper_dir(), type, iface, prt);
1363 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1367 static struct socket_info *find_socket_info(int fd)
1369 struct socket_info *i;
1371 for (i = sockets; i; i = i->next) {
1372 struct socket_info_fd *f;
1373 for (f = i->fds; f; f = f->next) {
1384 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1386 struct socket_info *s;
1388 /* first catch invalid input */
1389 switch (sa->sa_family) {
1391 if (len < sizeof(struct sockaddr_in)) {
1397 if (len < sizeof(struct sockaddr_in6)) {
1407 for (s = sockets; s != NULL; s = s->next) {
1408 if (s->myname == NULL) {
1411 if (s->myname->sa_family != sa->sa_family) {
1414 switch (s->myname->sa_family) {
1416 struct sockaddr_in *sin1, *sin2;
1418 sin1 = (struct sockaddr_in *)s->myname;
1419 sin2 = (struct sockaddr_in *)sa;
1421 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1424 if (sin1->sin_port != sin2->sin_port) {
1427 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1437 struct sockaddr_in6 *sin1, *sin2;
1439 sin1 = (struct sockaddr_in6 *)s->myname;
1440 sin2 = (struct sockaddr_in6 *)sa;
1442 if (sin1->sin6_port != sin2->sin6_port) {
1445 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1467 static void swrap_remove_stale(int fd)
1469 struct socket_info *si = find_socket_info(fd);
1470 struct socket_info_fd *fi;
1476 for (fi = si->fds; fi; fi = fi->next) {
1478 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1479 SWRAP_DLIST_REMOVE(si->fds, fi);
1485 if (si->fds == NULL) {
1486 SWRAP_DLIST_REMOVE(sockets, si);
1487 if (si->un_addr.sun_path[0] != '\0') {
1488 unlink(si->un_addr.sun_path);
1494 static int sockaddr_convert_to_un(struct socket_info *si,
1495 const struct sockaddr *in_addr,
1497 struct sockaddr_un *out_addr,
1501 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1503 (void) in_len; /* unused */
1505 if (out_addr == NULL) {
1509 out->sa_family = AF_UNIX;
1510 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1511 out->sa_len = sizeof(*out_addr);
1514 switch (in_addr->sa_family) {
1516 const struct sockaddr_in *sin;
1517 if (si->family != AF_INET) {
1520 if (in_len < sizeof(struct sockaddr_in)) {
1523 sin = (const struct sockaddr_in *)(const void *)in_addr;
1524 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1529 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1530 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1544 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1545 errno = ESOCKTNOSUPPORT;
1549 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1551 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1557 errno = EAFNOSUPPORT;
1558 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1562 static int sockaddr_convert_from_un(const struct socket_info *si,
1563 const struct sockaddr_un *in_addr,
1564 socklen_t un_addrlen,
1566 struct sockaddr *out_addr,
1567 socklen_t *out_addrlen)
1571 if (out_addr == NULL || out_addrlen == NULL)
1574 if (un_addrlen == 0) {
1589 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1590 errno = ESOCKTNOSUPPORT;
1593 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1594 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1595 out_addr->sa_len = *out_addrlen;
1602 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1603 errno = EAFNOSUPPORT;
1607 enum swrap_packet_type {
1609 SWRAP_CONNECT_UNREACH,
1617 SWRAP_SENDTO_UNREACH,
1628 struct swrap_file_hdr {
1630 uint16_t version_major;
1631 uint16_t version_minor;
1634 uint32_t frame_max_len;
1635 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1638 #define SWRAP_FILE_HDR_SIZE 24
1640 struct swrap_packet_frame {
1642 uint32_t micro_seconds;
1643 uint32_t recorded_length;
1644 uint32_t full_length;
1646 #define SWRAP_PACKET_FRAME_SIZE 16
1648 union swrap_packet_ip {
1652 uint16_t packet_length;
1653 uint16_t identification;
1658 uint16_t hdr_checksum;
1662 #define SWRAP_PACKET_IP_V4_SIZE 20
1665 uint8_t flow_label_high;
1666 uint16_t flow_label_low;
1667 uint16_t payload_length;
1668 uint8_t next_header;
1670 uint8_t src_addr[16];
1671 uint8_t dest_addr[16];
1673 #define SWRAP_PACKET_IP_V6_SIZE 40
1675 #define SWRAP_PACKET_IP_SIZE 40
1677 union swrap_packet_payload {
1679 uint16_t source_port;
1689 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1691 uint16_t source_port;
1696 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1703 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1710 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1712 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1714 #define SWRAP_PACKET_MIN_ALLOC \
1715 (SWRAP_PACKET_FRAME_SIZE + \
1716 SWRAP_PACKET_IP_SIZE + \
1717 SWRAP_PACKET_PAYLOAD_SIZE)
1719 static const char *swrap_pcap_init_file(void)
1721 static int initialized = 0;
1722 static const char *s = NULL;
1723 static const struct swrap_file_hdr h;
1724 static const struct swrap_packet_frame f;
1725 static const union swrap_packet_ip i;
1726 static const union swrap_packet_payload p;
1728 if (initialized == 1) {
1734 * TODO: don't use the structs use plain buffer offsets
1735 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1737 * for now make sure we disable PCAP support
1738 * if the struct has alignment!
1740 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1743 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1746 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1749 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1752 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1755 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1758 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1761 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1764 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1767 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1771 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1775 if (strncmp(s, "./", 2) == 0) {
1781 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1782 const struct sockaddr *src,
1783 const struct sockaddr *dest,
1785 const uint8_t *payload,
1787 unsigned long tcp_seqno,
1788 unsigned long tcp_ack,
1789 unsigned char tcp_ctl,
1791 size_t *_packet_len)
1795 struct swrap_packet_frame *frame;
1796 union swrap_packet_ip *ip;
1797 union swrap_packet_payload *pay;
1800 size_t nonwire_len = sizeof(*frame);
1801 size_t wire_hdr_len = 0;
1802 size_t wire_len = 0;
1803 size_t ip_hdr_len = 0;
1804 size_t icmp_hdr_len = 0;
1805 size_t icmp_truncate_len = 0;
1806 uint8_t protocol = 0, icmp_protocol = 0;
1807 const struct sockaddr_in *src_in = NULL;
1808 const struct sockaddr_in *dest_in = NULL;
1810 const struct sockaddr_in6 *src_in6 = NULL;
1811 const struct sockaddr_in6 *dest_in6 = NULL;
1816 switch (src->sa_family) {
1818 src_in = (const struct sockaddr_in *)(const void *)src;
1819 dest_in = (const struct sockaddr_in *)(const void *)dest;
1820 src_port = src_in->sin_port;
1821 dest_port = dest_in->sin_port;
1822 ip_hdr_len = sizeof(ip->v4);
1826 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1827 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1828 src_port = src_in6->sin6_port;
1829 dest_port = dest_in6->sin6_port;
1830 ip_hdr_len = sizeof(ip->v6);
1837 switch (socket_type) {
1839 protocol = 0x06; /* TCP */
1840 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1841 wire_len = wire_hdr_len + payload_len;
1845 protocol = 0x11; /* UDP */
1846 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1847 wire_len = wire_hdr_len + payload_len;
1855 icmp_protocol = protocol;
1856 switch (src->sa_family) {
1858 protocol = 0x01; /* ICMPv4 */
1859 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1863 protocol = 0x3A; /* ICMPv6 */
1864 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1868 if (wire_len > 64 ) {
1869 icmp_truncate_len = wire_len - 64;
1871 wire_hdr_len += icmp_hdr_len;
1872 wire_len += icmp_hdr_len;
1875 packet_len = nonwire_len + wire_len;
1876 alloc_len = packet_len;
1877 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1878 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1881 base = (uint8_t *)calloc(1, alloc_len);
1888 frame = (struct swrap_packet_frame *)(void *)buf;
1889 frame->seconds = tval->tv_sec;
1890 frame->micro_seconds = tval->tv_usec;
1891 frame->recorded_length = wire_len - icmp_truncate_len;
1892 frame->full_length = wire_len - icmp_truncate_len;
1893 buf += SWRAP_PACKET_FRAME_SIZE;
1895 ip = (union swrap_packet_ip *)(void *)buf;
1896 switch (src->sa_family) {
1898 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1900 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1901 ip->v4.identification = htons(0xFFFF);
1902 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1903 ip->v4.fragment = htons(0x0000);
1905 ip->v4.protocol = protocol;
1906 ip->v4.hdr_checksum = htons(0x0000);
1907 ip->v4.src_addr = src_in->sin_addr.s_addr;
1908 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1909 buf += SWRAP_PACKET_IP_V4_SIZE;
1913 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1914 ip->v6.flow_label_high = 0x00;
1915 ip->v6.flow_label_low = 0x0000;
1916 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1917 ip->v6.next_header = protocol;
1918 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1919 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1920 buf += SWRAP_PACKET_IP_V6_SIZE;
1926 pay = (union swrap_packet_payload *)(void *)buf;
1927 switch (src->sa_family) {
1929 pay->icmp4.type = 0x03; /* destination unreachable */
1930 pay->icmp4.code = 0x01; /* host unreachable */
1931 pay->icmp4.checksum = htons(0x0000);
1932 pay->icmp4.unused = htonl(0x00000000);
1933 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1935 /* set the ip header in the ICMP payload */
1936 ip = (union swrap_packet_ip *)(void *)buf;
1937 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1939 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1940 ip->v4.identification = htons(0xFFFF);
1941 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1942 ip->v4.fragment = htons(0x0000);
1944 ip->v4.protocol = icmp_protocol;
1945 ip->v4.hdr_checksum = htons(0x0000);
1946 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1947 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1948 buf += SWRAP_PACKET_IP_V4_SIZE;
1950 src_port = dest_in->sin_port;
1951 dest_port = src_in->sin_port;
1955 pay->icmp6.type = 0x01; /* destination unreachable */
1956 pay->icmp6.code = 0x03; /* address unreachable */
1957 pay->icmp6.checksum = htons(0x0000);
1958 pay->icmp6.unused = htonl(0x00000000);
1959 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1961 /* set the ip header in the ICMP payload */
1962 ip = (union swrap_packet_ip *)(void *)buf;
1963 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1964 ip->v6.flow_label_high = 0x00;
1965 ip->v6.flow_label_low = 0x0000;
1966 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1967 ip->v6.next_header = protocol;
1968 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1969 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1970 buf += SWRAP_PACKET_IP_V6_SIZE;
1972 src_port = dest_in6->sin6_port;
1973 dest_port = src_in6->sin6_port;
1979 pay = (union swrap_packet_payload *)(void *)buf;
1981 switch (socket_type) {
1983 pay->tcp.source_port = src_port;
1984 pay->tcp.dest_port = dest_port;
1985 pay->tcp.seq_num = htonl(tcp_seqno);
1986 pay->tcp.ack_num = htonl(tcp_ack);
1987 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1988 pay->tcp.control = tcp_ctl;
1989 pay->tcp.window = htons(0x7FFF);
1990 pay->tcp.checksum = htons(0x0000);
1991 pay->tcp.urg = htons(0x0000);
1992 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1997 pay->udp.source_port = src_port;
1998 pay->udp.dest_port = dest_port;
1999 pay->udp.length = htons(8 + payload_len);
2000 pay->udp.checksum = htons(0x0000);
2001 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2006 if (payload && payload_len > 0) {
2007 memcpy(buf, payload, payload_len);
2010 *_packet_len = packet_len - icmp_truncate_len;
2014 static int swrap_pcap_get_fd(const char *fname)
2018 if (fd != -1) return fd;
2020 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2022 struct swrap_file_hdr file_hdr;
2023 file_hdr.magic = 0xA1B2C3D4;
2024 file_hdr.version_major = 0x0002;
2025 file_hdr.version_minor = 0x0004;
2026 file_hdr.timezone = 0x00000000;
2027 file_hdr.sigfigs = 0x00000000;
2028 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2029 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2031 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2038 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2043 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2044 const struct sockaddr *addr,
2045 enum swrap_packet_type type,
2046 const void *buf, size_t len,
2049 const struct sockaddr *src_addr;
2050 const struct sockaddr *dest_addr;
2051 unsigned long tcp_seqno = 0;
2052 unsigned long tcp_ack = 0;
2053 unsigned char tcp_ctl = 0;
2054 int unreachable = 0;
2058 switch (si->family) {
2070 case SWRAP_CONNECT_SEND:
2071 if (si->type != SOCK_STREAM) return NULL;
2073 src_addr = &si->myname.sa.s;
2076 tcp_seqno = si->io.pck_snd;
2077 tcp_ack = si->io.pck_rcv;
2078 tcp_ctl = 0x02; /* SYN */
2080 si->io.pck_snd += 1;
2084 case SWRAP_CONNECT_RECV:
2085 if (si->type != SOCK_STREAM) return NULL;
2087 dest_addr = &si->myname.sa.s;
2090 tcp_seqno = si->io.pck_rcv;
2091 tcp_ack = si->io.pck_snd;
2092 tcp_ctl = 0x12; /** SYN,ACK */
2094 si->io.pck_rcv += 1;
2098 case SWRAP_CONNECT_UNREACH:
2099 if (si->type != SOCK_STREAM) return NULL;
2101 dest_addr = &si->myname.sa.s;
2104 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2105 tcp_seqno = si->io.pck_snd - 1;
2106 tcp_ack = si->io.pck_rcv;
2107 tcp_ctl = 0x02; /* SYN */
2112 case SWRAP_CONNECT_ACK:
2113 if (si->type != SOCK_STREAM) return NULL;
2115 src_addr = &si->myname.sa.s;
2118 tcp_seqno = si->io.pck_snd;
2119 tcp_ack = si->io.pck_rcv;
2120 tcp_ctl = 0x10; /* ACK */
2124 case SWRAP_ACCEPT_SEND:
2125 if (si->type != SOCK_STREAM) return NULL;
2127 dest_addr = &si->myname.sa.s;
2130 tcp_seqno = si->io.pck_rcv;
2131 tcp_ack = si->io.pck_snd;
2132 tcp_ctl = 0x02; /* SYN */
2134 si->io.pck_rcv += 1;
2138 case SWRAP_ACCEPT_RECV:
2139 if (si->type != SOCK_STREAM) return NULL;
2141 src_addr = &si->myname.sa.s;
2144 tcp_seqno = si->io.pck_snd;
2145 tcp_ack = si->io.pck_rcv;
2146 tcp_ctl = 0x12; /* SYN,ACK */
2148 si->io.pck_snd += 1;
2152 case SWRAP_ACCEPT_ACK:
2153 if (si->type != SOCK_STREAM) return NULL;
2155 dest_addr = &si->myname.sa.s;
2158 tcp_seqno = si->io.pck_rcv;
2159 tcp_ack = si->io.pck_snd;
2160 tcp_ctl = 0x10; /* ACK */
2165 src_addr = &si->myname.sa.s;
2166 dest_addr = &si->peername.sa.s;
2168 tcp_seqno = si->io.pck_snd;
2169 tcp_ack = si->io.pck_rcv;
2170 tcp_ctl = 0x18; /* PSH,ACK */
2172 si->io.pck_snd += len;
2176 case SWRAP_SEND_RST:
2177 dest_addr = &si->myname.sa.s;
2178 src_addr = &si->peername.sa.s;
2180 if (si->type == SOCK_DGRAM) {
2181 return swrap_pcap_marshall_packet(si,
2183 SWRAP_SENDTO_UNREACH,
2189 tcp_seqno = si->io.pck_rcv;
2190 tcp_ack = si->io.pck_snd;
2191 tcp_ctl = 0x14; /** RST,ACK */
2195 case SWRAP_PENDING_RST:
2196 dest_addr = &si->myname.sa.s;
2197 src_addr = &si->peername.sa.s;
2199 if (si->type == SOCK_DGRAM) {
2203 tcp_seqno = si->io.pck_rcv;
2204 tcp_ack = si->io.pck_snd;
2205 tcp_ctl = 0x14; /* RST,ACK */
2210 dest_addr = &si->myname.sa.s;
2211 src_addr = &si->peername.sa.s;
2213 tcp_seqno = si->io.pck_rcv;
2214 tcp_ack = si->io.pck_snd;
2215 tcp_ctl = 0x18; /* PSH,ACK */
2217 si->io.pck_rcv += len;
2221 case SWRAP_RECV_RST:
2222 dest_addr = &si->myname.sa.s;
2223 src_addr = &si->peername.sa.s;
2225 if (si->type == SOCK_DGRAM) {
2229 tcp_seqno = si->io.pck_rcv;
2230 tcp_ack = si->io.pck_snd;
2231 tcp_ctl = 0x14; /* RST,ACK */
2236 src_addr = &si->myname.sa.s;
2239 si->io.pck_snd += len;
2243 case SWRAP_SENDTO_UNREACH:
2244 dest_addr = &si->myname.sa.s;
2251 case SWRAP_RECVFROM:
2252 dest_addr = &si->myname.sa.s;
2255 si->io.pck_rcv += len;
2259 case SWRAP_CLOSE_SEND:
2260 if (si->type != SOCK_STREAM) return NULL;
2262 src_addr = &si->myname.sa.s;
2263 dest_addr = &si->peername.sa.s;
2265 tcp_seqno = si->io.pck_snd;
2266 tcp_ack = si->io.pck_rcv;
2267 tcp_ctl = 0x11; /* FIN, ACK */
2269 si->io.pck_snd += 1;
2273 case SWRAP_CLOSE_RECV:
2274 if (si->type != SOCK_STREAM) return NULL;
2276 dest_addr = &si->myname.sa.s;
2277 src_addr = &si->peername.sa.s;
2279 tcp_seqno = si->io.pck_rcv;
2280 tcp_ack = si->io.pck_snd;
2281 tcp_ctl = 0x11; /* FIN,ACK */
2283 si->io.pck_rcv += 1;
2287 case SWRAP_CLOSE_ACK:
2288 if (si->type != SOCK_STREAM) return NULL;
2290 src_addr = &si->myname.sa.s;
2291 dest_addr = &si->peername.sa.s;
2293 tcp_seqno = si->io.pck_snd;
2294 tcp_ack = si->io.pck_rcv;
2295 tcp_ctl = 0x10; /* ACK */
2302 swrapGetTimeOfDay(&tv);
2304 return swrap_pcap_packet_init(&tv,
2308 (const uint8_t *)buf,
2317 static void swrap_pcap_dump_packet(struct socket_info *si,
2318 const struct sockaddr *addr,
2319 enum swrap_packet_type type,
2320 const void *buf, size_t len)
2322 const char *file_name;
2324 size_t packet_len = 0;
2327 file_name = swrap_pcap_init_file();
2332 packet = swrap_pcap_marshall_packet(si,
2338 if (packet == NULL) {
2342 fd = swrap_pcap_get_fd(file_name);
2344 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2353 /****************************************************************************
2355 ***************************************************************************/
2357 #ifdef HAVE_SIGNALFD
2358 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2362 rc = libc_signalfd(fd, mask, flags);
2364 swrap_remove_stale(fd);
2370 int signalfd(int fd, const sigset_t *mask, int flags)
2372 return swrap_signalfd(fd, mask, flags);
2376 /****************************************************************************
2378 ***************************************************************************/
2380 static int swrap_socket(int family, int type, int protocol)
2382 struct socket_info *si;
2383 struct socket_info_fd *fi;
2385 int real_type = type;
2388 * Remove possible addition flags passed to socket() so
2389 * do not fail checking the type.
2390 * See https://lwn.net/Articles/281965/
2393 real_type &= ~SOCK_CLOEXEC;
2395 #ifdef SOCK_NONBLOCK
2396 real_type &= ~SOCK_NONBLOCK;
2399 if (!socket_wrapper_enabled()) {
2400 return libc_socket(family, type, protocol);
2411 #endif /* AF_NETLINK */
2414 #endif /* AF_PACKET */
2416 return libc_socket(family, type, protocol);
2418 errno = EAFNOSUPPORT;
2422 switch (real_type) {
2428 errno = EPROTONOSUPPORT;
2436 if (real_type == SOCK_STREAM) {
2441 if (real_type == SOCK_DGRAM) {
2446 errno = EPROTONOSUPPORT;
2451 * We must call libc_socket with type, from the caller, not the version
2452 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2454 fd = libc_socket(AF_UNIX, type, 0);
2460 /* Check if we have a stale fd and remove it */
2461 swrap_remove_stale(fd);
2463 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
2469 si->family = family;
2471 /* however, the rest of the socket_wrapper code expects just
2472 * the type, not the flags */
2473 si->type = real_type;
2474 si->protocol = protocol;
2477 * Setup myname so getsockname() can succeed to find out the socket
2480 switch(si->family) {
2482 struct sockaddr_in sin = {
2483 .sin_family = AF_INET,
2486 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2487 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2491 struct sockaddr_in6 sin6 = {
2492 .sin6_family = AF_INET6,
2495 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2496 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2505 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2514 SWRAP_DLIST_ADD(si->fds, fi);
2515 SWRAP_DLIST_ADD(sockets, si);
2517 SWRAP_LOG(SWRAP_LOG_TRACE,
2518 "Created %s socket for protocol %s",
2519 si->family == AF_INET ? "IPv4" : "IPv6",
2520 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2525 int socket(int family, int type, int protocol)
2527 return swrap_socket(family, type, protocol);
2530 /****************************************************************************
2532 ***************************************************************************/
2534 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2538 rc = libc_socketpair(family, type, protocol, sv);
2540 swrap_remove_stale(sv[0]);
2541 swrap_remove_stale(sv[1]);
2547 int socketpair(int family, int type, int protocol, int sv[2])
2549 return swrap_socketpair(family, type, protocol, sv);
2552 /****************************************************************************
2554 ***************************************************************************/
2556 #ifdef HAVE_TIMERFD_CREATE
2557 static int swrap_timerfd_create(int clockid, int flags)
2561 fd = libc_timerfd_create(clockid, flags);
2563 swrap_remove_stale(fd);
2569 int timerfd_create(int clockid, int flags)
2571 return swrap_timerfd_create(clockid, flags);
2575 /****************************************************************************
2577 ***************************************************************************/
2579 static int swrap_pipe(int pipefd[2])
2583 rc = libc_pipe(pipefd);
2585 swrap_remove_stale(pipefd[0]);
2586 swrap_remove_stale(pipefd[1]);
2592 int pipe(int pipefd[2])
2594 return swrap_pipe(pipefd);
2597 /****************************************************************************
2599 ***************************************************************************/
2601 static int swrap_accept(int s,
2602 struct sockaddr *addr,
2606 struct socket_info *parent_si, *child_si;
2607 struct socket_info_fd *child_fi;
2609 struct swrap_address un_addr = {
2610 .sa_socklen = sizeof(struct sockaddr_un),
2612 struct swrap_address un_my_addr = {
2613 .sa_socklen = sizeof(struct sockaddr_un),
2615 struct swrap_address in_addr = {
2616 .sa_socklen = sizeof(struct sockaddr_storage),
2618 struct swrap_address in_my_addr = {
2619 .sa_socklen = sizeof(struct sockaddr_storage),
2623 parent_si = find_socket_info(s);
2626 return libc_accept4(s, addr, addrlen, flags);
2628 return libc_accept(s, addr, addrlen);
2633 * assume out sockaddr have the same size as the in parent
2636 in_addr.sa_socklen = socket_length(parent_si->family);
2637 if (in_addr.sa_socklen <= 0) {
2643 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2645 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2648 if (errno == ENOTSOCK) {
2649 /* Remove stale fds */
2650 swrap_remove_stale(s);
2657 ret = sockaddr_convert_from_un(parent_si,
2662 &in_addr.sa_socklen);
2668 child_si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
2669 if (child_si == NULL) {
2675 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2676 if (child_fi == NULL) {
2685 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2687 child_si->family = parent_si->family;
2688 child_si->type = parent_si->type;
2689 child_si->protocol = parent_si->protocol;
2690 child_si->bound = 1;
2691 child_si->is_server = 1;
2692 child_si->connected = 1;
2694 child_si->peername = (struct swrap_address) {
2695 .sa_socklen = in_addr.sa_socklen,
2697 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2699 if (addr != NULL && addrlen != NULL) {
2700 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2702 memcpy(addr, &in_addr.sa.ss, copy_len);
2704 *addrlen = in_addr.sa_socklen;
2707 ret = libc_getsockname(fd,
2709 &un_my_addr.sa_socklen);
2717 ret = sockaddr_convert_from_un(child_si,
2719 un_my_addr.sa_socklen,
2722 &in_my_addr.sa_socklen);
2730 SWRAP_LOG(SWRAP_LOG_TRACE,
2731 "accept() path=%s, fd=%d",
2732 un_my_addr.sa.un.sun_path, s);
2734 child_si->myname = (struct swrap_address) {
2735 .sa_socklen = in_my_addr.sa_socklen,
2737 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2739 SWRAP_DLIST_ADD(sockets, child_si);
2742 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2743 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2744 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2751 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
2753 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
2757 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2758 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2760 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2763 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
2766 static int autobind_start_init;
2767 static int autobind_start;
2769 /* using sendto() or connect() on an unbound socket would give the
2770 recipient no way to reply, as unlike UDP and TCP, a unix domain
2771 socket can't auto-assign ephemeral port numbers, so we need to
2773 Note: this might change the family from ipv6 to ipv4
2775 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2777 struct swrap_address un_addr = {
2778 .sa_socklen = sizeof(struct sockaddr_un),
2786 if (autobind_start_init != 1) {
2787 autobind_start_init = 1;
2788 autobind_start = getpid();
2789 autobind_start %= 50000;
2790 autobind_start += 10000;
2793 un_addr.sa.un.sun_family = AF_UNIX;
2797 struct sockaddr_in in;
2801 type = SOCKET_TYPE_CHAR_TCP;
2804 type = SOCKET_TYPE_CHAR_UDP;
2807 errno = ESOCKTNOSUPPORT;
2811 memset(&in, 0, sizeof(in));
2812 in.sin_family = AF_INET;
2813 in.sin_addr.s_addr = htonl(127<<24 |
2814 socket_wrapper_default_iface());
2816 si->myname = (struct swrap_address) {
2817 .sa_socklen = sizeof(in),
2819 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2824 struct sockaddr_in6 in6;
2826 if (si->family != family) {
2827 errno = ENETUNREACH;
2833 type = SOCKET_TYPE_CHAR_TCP_V6;
2836 type = SOCKET_TYPE_CHAR_UDP_V6;
2839 errno = ESOCKTNOSUPPORT;
2843 memset(&in6, 0, sizeof(in6));
2844 in6.sin6_family = AF_INET6;
2845 in6.sin6_addr = *swrap_ipv6();
2846 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2848 si->myname = (struct swrap_address) {
2849 .sa_socklen = sizeof(in6),
2851 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2856 errno = ESOCKTNOSUPPORT;
2860 if (autobind_start > 60000) {
2861 autobind_start = 10000;
2864 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2865 port = autobind_start + i;
2866 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2867 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2868 type, socket_wrapper_default_iface(), port);
2869 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2871 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2872 if (ret == -1) return ret;
2874 si->un_addr = un_addr.sa.un;
2877 autobind_start = port + 1;
2880 if (i == SOCKET_MAX_SOCKETS) {
2881 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2882 "interface "SOCKET_FORMAT,
2885 socket_wrapper_default_iface(),
2891 si->family = family;
2892 set_port(si->family, port, &si->myname);
2897 /****************************************************************************
2899 ***************************************************************************/
2901 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2905 struct swrap_address un_addr = {
2906 .sa_socklen = sizeof(struct sockaddr_un),
2908 struct socket_info *si = find_socket_info(s);
2912 return libc_connect(s, serv_addr, addrlen);
2915 if (si->bound == 0) {
2916 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2917 if (ret == -1) return -1;
2920 if (si->family != serv_addr->sa_family) {
2925 ret = sockaddr_convert_to_un(si, serv_addr,
2926 addrlen, &un_addr.sa.un, 0, &bcast);
2927 if (ret == -1) return -1;
2930 errno = ENETUNREACH;
2934 if (si->type == SOCK_DGRAM) {
2935 si->defer_connect = 1;
2938 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2940 ret = libc_connect(s,
2942 un_addr.sa_socklen);
2945 SWRAP_LOG(SWRAP_LOG_TRACE,
2946 "connect() path=%s, fd=%d",
2947 un_addr.sa.un.sun_path, s);
2950 /* to give better errors */
2951 if (ret == -1 && errno == ENOENT) {
2952 errno = EHOSTUNREACH;
2956 si->peername = (struct swrap_address) {
2957 .sa_socklen = addrlen,
2960 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2964 * When we connect() on a socket than we have to bind the
2965 * outgoing connection on the interface we use for the
2966 * transport. We already bound it on the right interface
2967 * but here we have to update the name so getsockname()
2968 * returns correct information.
2970 if (si->bindname.sa_socklen > 0) {
2971 si->myname = (struct swrap_address) {
2972 .sa_socklen = si->bindname.sa_socklen,
2975 memcpy(&si->myname.sa.ss,
2976 &si->bindname.sa.ss,
2977 si->bindname.sa_socklen);
2979 /* Cleanup bindname */
2980 si->bindname = (struct swrap_address) {
2985 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2986 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2988 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2994 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2996 return swrap_connect(s, serv_addr, addrlen);
2999 /****************************************************************************
3001 ***************************************************************************/
3003 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3006 struct swrap_address un_addr = {
3007 .sa_socklen = sizeof(struct sockaddr_un),
3009 struct socket_info *si = find_socket_info(s);
3016 return libc_bind(s, myaddr, addrlen);
3019 switch (si->family) {
3021 const struct sockaddr_in *sin;
3022 if (addrlen < sizeof(struct sockaddr_in)) {
3023 bind_error = EINVAL;
3027 sin = (const struct sockaddr_in *)(const void *)myaddr;
3029 if (sin->sin_family != AF_INET) {
3030 bind_error = EAFNOSUPPORT;
3033 /* special case for AF_UNSPEC */
3034 if (sin->sin_family == AF_UNSPEC &&
3035 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3044 const struct sockaddr_in6 *sin6;
3045 if (addrlen < sizeof(struct sockaddr_in6)) {
3046 bind_error = EINVAL;
3050 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3052 if (sin6->sin6_family != AF_INET6) {
3053 bind_error = EAFNOSUPPORT;
3060 bind_error = EINVAL;
3064 if (bind_error != 0) {
3070 in_use = check_addr_port_in_use(myaddr, addrlen);
3077 si->myname.sa_socklen = addrlen;
3078 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3080 ret = sockaddr_convert_to_un(si,
3086 if (ret == -1) return -1;
3088 unlink(un_addr.sa.un.sun_path);
3090 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3092 SWRAP_LOG(SWRAP_LOG_TRACE,
3093 "bind() path=%s, fd=%d",
3094 un_addr.sa.un.sun_path, s);
3103 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3105 return swrap_bind(s, myaddr, addrlen);
3108 /****************************************************************************
3110 ***************************************************************************/
3112 #ifdef HAVE_BINDRESVPORT
3113 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3115 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3117 struct swrap_address myaddr = {
3118 .sa_socklen = sizeof(struct sockaddr_storage),
3121 static uint16_t port;
3126 #define SWRAP_STARTPORT 600
3127 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3128 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3131 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3135 salen = myaddr.sa_socklen;
3138 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3144 memset(&myaddr.sa.ss, 0, salen);
3149 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3152 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3154 salen = sizeof(struct sockaddr_in);
3155 sinp->sin_port = htons(port);
3159 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3161 salen = sizeof(struct sockaddr_in6);
3162 sin6p->sin6_port = htons(port);
3166 errno = EAFNOSUPPORT;
3171 if (port > SWRAP_ENDPORT) {
3172 port = SWRAP_STARTPORT;
3175 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3176 if (rc == 0 || errno != EADDRINUSE) {
3184 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3186 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3190 /****************************************************************************
3192 ***************************************************************************/
3194 static int swrap_listen(int s, int backlog)
3197 struct socket_info *si = find_socket_info(s);
3200 return libc_listen(s, backlog);
3203 if (si->bound == 0) {
3204 ret = swrap_auto_bind(s, si, si->family);
3211 ret = libc_listen(s, backlog);
3216 int listen(int s, int backlog)
3218 return swrap_listen(s, backlog);
3221 /****************************************************************************
3223 ***************************************************************************/
3225 static FILE *swrap_fopen(const char *name, const char *mode)
3229 fp = libc_fopen(name, mode);
3231 int fd = fileno(fp);
3233 swrap_remove_stale(fd);
3239 FILE *fopen(const char *name, const char *mode)
3241 return swrap_fopen(name, mode);
3244 /****************************************************************************
3246 ***************************************************************************/
3248 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3252 ret = libc_vopen(pathname, flags, ap);
3255 * There are methods for closing descriptors (libc-internal code
3256 * paths, direct syscalls) which close descriptors in ways that
3257 * we can't intercept, so try to recover when we notice that
3260 swrap_remove_stale(ret);
3265 int open(const char *pathname, int flags, ...)
3270 va_start(ap, flags);
3271 fd = swrap_vopen(pathname, flags, ap);
3277 /****************************************************************************
3279 ***************************************************************************/
3281 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3283 struct socket_info *si = find_socket_info(s);
3287 return libc_getpeername(s, name, addrlen);
3290 if (si->peername.sa_socklen == 0)
3296 len = MIN(*addrlen, si->peername.sa_socklen);
3301 memcpy(name, &si->peername.sa.ss, len);
3302 *addrlen = si->peername.sa_socklen;
3307 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3308 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3310 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3313 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3316 /****************************************************************************
3318 ***************************************************************************/
3320 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3322 struct socket_info *si = find_socket_info(s);
3326 return libc_getsockname(s, name, addrlen);
3329 len = MIN(*addrlen, si->myname.sa_socklen);
3334 memcpy(name, &si->myname.sa.ss, len);
3335 *addrlen = si->myname.sa_socklen;
3340 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3341 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3343 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3346 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3349 /****************************************************************************
3351 ***************************************************************************/
3354 # ifdef SO_PROTOTYPE /* The Solaris name */
3355 # define SO_PROTOCOL SO_PROTOTYPE
3356 # endif /* SO_PROTOTYPE */
3357 #endif /* SO_PROTOCOL */
3359 static int swrap_getsockopt(int s, int level, int optname,
3360 void *optval, socklen_t *optlen)
3362 struct socket_info *si = find_socket_info(s);
3365 return libc_getsockopt(s,
3372 if (level == SOL_SOCKET) {
3376 if (optval == NULL || optlen == NULL ||
3377 *optlen < (socklen_t)sizeof(int)) {
3382 *optlen = sizeof(int);
3383 *(int *)optval = si->family;
3385 #endif /* SO_DOMAIN */
3389 if (optval == NULL || optlen == NULL ||
3390 *optlen < (socklen_t)sizeof(int)) {
3395 *optlen = sizeof(int);
3396 *(int *)optval = si->protocol;
3398 #endif /* SO_PROTOCOL */
3400 if (optval == NULL || optlen == NULL ||
3401 *optlen < (socklen_t)sizeof(int)) {
3406 *optlen = sizeof(int);
3407 *(int *)optval = si->type;
3410 return libc_getsockopt(s,
3416 } else if (level == IPPROTO_TCP) {
3421 * This enables sending packets directly out over TCP.
3422 * As a unix socket is doing that any way, report it as
3425 if (optval == NULL || optlen == NULL ||
3426 *optlen < (socklen_t)sizeof(int)) {
3431 *optlen = sizeof(int);
3432 *(int *)optval = si->tcp_nodelay;
3435 #endif /* TCP_NODELAY */
3441 errno = ENOPROTOOPT;
3445 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3446 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3448 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3451 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3454 /****************************************************************************
3456 ***************************************************************************/
3458 static int swrap_setsockopt(int s, int level, int optname,
3459 const void *optval, socklen_t optlen)
3461 struct socket_info *si = find_socket_info(s);
3464 return libc_setsockopt(s,
3471 if (level == SOL_SOCKET) {
3472 return libc_setsockopt(s,
3477 } else if (level == IPPROTO_TCP) {
3484 * This enables sending packets directly out over TCP.
3485 * A unix socket is doing that any way.
3487 if (optval == NULL || optlen == 0 ||
3488 optlen < (socklen_t)sizeof(int)) {
3493 i = *discard_const_p(int, optval);
3494 if (i != 0 && i != 1) {
3498 si->tcp_nodelay = i;
3502 #endif /* TCP_NODELAY */
3508 switch (si->family) {
3510 if (level == IPPROTO_IP) {
3512 if (optname == IP_PKTINFO) {
3513 si->pktinfo = AF_INET;
3515 #endif /* IP_PKTINFO */
3520 if (level == IPPROTO_IPV6) {
3521 #ifdef IPV6_RECVPKTINFO
3522 if (optname == IPV6_RECVPKTINFO) {
3523 si->pktinfo = AF_INET6;
3525 #endif /* IPV6_PKTINFO */
3530 errno = ENOPROTOOPT;
3535 int setsockopt(int s, int level, int optname,
3536 const void *optval, socklen_t optlen)
3538 return swrap_setsockopt(s, level, optname, optval, optlen);
3541 /****************************************************************************
3543 ***************************************************************************/
3545 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3547 struct socket_info *si = find_socket_info(s);
3553 return libc_vioctl(s, r, va);
3558 rc = libc_vioctl(s, r, va);
3562 value = *((int *)va_arg(ap, int *));
3564 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3565 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3566 } else if (value == 0) { /* END OF FILE */
3567 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3577 #ifdef HAVE_IOCTL_INT
3578 int ioctl(int s, int r, ...)
3580 int ioctl(int s, unsigned long int r, ...)
3588 rc = swrap_vioctl(s, (unsigned long int) r, va);
3599 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3602 # ifdef _ALIGN /* BSD */
3603 #define CMSG_ALIGN _ALIGN
3605 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3606 # endif /* _ALIGN */
3607 #endif /* CMSG_ALIGN */
3610 * @brief Add a cmsghdr to a msghdr.
3612 * This is an function to add any type of cmsghdr. It will operate on the
3613 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3614 * the buffer position after the added cmsg element. Hence, this function is
3615 * intended to be used with an intermediate msghdr and not on the original
3616 * one handed in by the client.
3618 * @param[in] msg The msghdr to which to add the cmsg.
3620 * @param[in] level The cmsg level to set.
3622 * @param[in] type The cmsg type to set.
3624 * @param[in] data The cmsg data to set.
3626 * @param[in] len the length of the data to set.
3628 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3634 size_t cmlen = CMSG_LEN(len);
3635 size_t cmspace = CMSG_SPACE(len);
3636 uint8_t cmbuf[cmspace];
3637 void *cast_ptr = (void *)cmbuf;
3638 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3641 memset(cmbuf, 0, cmspace);
3643 if (msg->msg_controllen < cmlen) {
3644 cmlen = msg->msg_controllen;
3645 msg->msg_flags |= MSG_CTRUNC;
3648 if (msg->msg_controllen < cmspace) {
3649 cmspace = msg->msg_controllen;
3653 * We copy the full input data into an intermediate cmsghdr first
3654 * in order to more easily cope with truncation.
3656 cm->cmsg_len = cmlen;
3657 cm->cmsg_level = level;
3658 cm->cmsg_type = type;
3659 memcpy(CMSG_DATA(cm), data, len);
3662 * We now copy the possibly truncated buffer.
3663 * We copy cmlen bytes, but consume cmspace bytes,
3664 * leaving the possible padding uninitialiazed.
3666 p = (uint8_t *)msg->msg_control;
3667 memcpy(p, cm, cmlen);
3669 msg->msg_control = p;
3670 msg->msg_controllen -= cmspace;
3675 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3678 /* Add packet info */
3679 switch (si->pktinfo) {
3680 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3682 struct sockaddr_in *sin;
3683 #if defined(HAVE_STRUCT_IN_PKTINFO)
3684 struct in_pktinfo pkt;
3685 #elif defined(IP_RECVDSTADDR)
3689 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3690 sin = &si->bindname.sa.in;
3692 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3695 sin = &si->myname.sa.in;
3700 #if defined(HAVE_STRUCT_IN_PKTINFO)
3701 pkt.ipi_ifindex = socket_wrapper_default_iface();
3702 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3703 #elif defined(IP_RECVDSTADDR)
3704 pkt = sin->sin_addr;
3707 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3712 #endif /* IP_PKTINFO */
3713 #if defined(HAVE_IPV6)
3715 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3716 struct sockaddr_in6 *sin6;
3717 struct in6_pktinfo pkt6;
3719 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3720 sin6 = &si->bindname.sa.in6;
3722 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3725 sin6 = &si->myname.sa.in6;
3730 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3731 pkt6.ipi6_addr = sin6->sin6_addr;
3733 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3734 &pkt6, sizeof(pkt6));
3735 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3739 #endif /* IPV6_PKTINFO */
3747 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3748 struct msghdr *omsg)
3752 if (si->pktinfo > 0) {
3753 rc = swrap_msghdr_add_pktinfo(si, omsg);
3759 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3761 size_t *cm_data_space);
3762 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3764 size_t *cm_data_space);
3766 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3768 size_t *cm_data_space) {
3769 struct cmsghdr *cmsg;
3773 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3777 for (cmsg = CMSG_FIRSTHDR(msg);
3779 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3780 switch (cmsg->cmsg_level) {
3782 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3787 rc = swrap_sendmsg_copy_cmsg(cmsg,
3797 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3799 size_t *cm_data_space)
3804 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
3806 p = realloc((*cm_data), cmspace);
3812 p = (*cm_data) + (*cm_data_space);
3813 *cm_data_space = cmspace;
3815 memcpy(p, cmsg, cmsg->cmsg_len);
3820 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3822 size_t *cm_data_space);
3825 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3827 size_t *cm_data_space)
3831 switch(cmsg->cmsg_type) {
3834 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3841 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3853 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3855 size_t *cm_data_space)
3857 (void)cmsg; /* unused */
3858 (void)cm_data; /* unused */
3859 (void)cm_data_space; /* unused */
3862 * Passing a IP pktinfo to a unix socket might be rejected by the
3863 * Kernel, at least on FreeBSD. So skip this cmsg.
3867 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3869 static ssize_t swrap_sendmsg_before(int fd,
3870 struct socket_info *si,
3872 struct iovec *tmp_iov,
3873 struct sockaddr_un *tmp_un,
3874 const struct sockaddr_un **to_un,
3875 const struct sockaddr **to,
3895 if (!si->connected) {
3900 if (msg->msg_iovlen == 0) {
3904 mtu = socket_wrapper_mtu();
3905 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3907 nlen = len + msg->msg_iov[i].iov_len;
3912 msg->msg_iovlen = i;
3913 if (msg->msg_iovlen == 0) {
3914 *tmp_iov = msg->msg_iov[0];
3915 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
3917 msg->msg_iov = tmp_iov;
3918 msg->msg_iovlen = 1;
3923 if (si->connected) {
3924 if (msg->msg_name != NULL) {
3926 * We are dealing with unix sockets and if we
3927 * are connected, we should only talk to the
3928 * connected unix path. Using the fd to send
3929 * to another server would be hard to achieve.
3931 msg->msg_name = NULL;
3932 msg->msg_namelen = 0;
3935 const struct sockaddr *msg_name;
3936 msg_name = (const struct sockaddr *)msg->msg_name;
3938 if (msg_name == NULL) {
3944 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3946 if (ret == -1) return -1;
3954 msg->msg_name = tmp_un;
3955 msg->msg_namelen = sizeof(*tmp_un);
3958 if (si->bound == 0) {
3959 ret = swrap_auto_bind(fd, si, si->family);
3961 if (errno == ENOTSOCK) {
3962 swrap_remove_stale(fd);
3965 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3971 if (!si->defer_connect) {
3975 ret = sockaddr_convert_to_un(si,
3977 si->peername.sa_socklen,
3981 if (ret == -1) return -1;
3983 ret = libc_connect(fd,
3984 (struct sockaddr *)(void *)tmp_un,
3987 /* to give better errors */
3988 if (ret == -1 && errno == ENOENT) {
3989 errno = EHOSTUNREACH;
3996 si->defer_connect = 0;
3999 errno = EHOSTUNREACH;
4003 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4004 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4005 uint8_t *cmbuf = NULL;
4008 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4015 msg->msg_controllen = 0;
4016 msg->msg_control = NULL;
4017 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4018 memcpy(msg->msg_control, cmbuf, cmlen);
4019 msg->msg_controllen = cmlen;
4028 static void swrap_sendmsg_after(int fd,
4029 struct socket_info *si,
4031 const struct sockaddr *to,
4034 int saved_errno = errno;
4041 /* to give better errors */
4043 if (saved_errno == ENOENT) {
4044 saved_errno = EHOSTUNREACH;
4045 } else if (saved_errno == ENOTSOCK) {
4046 /* If the fd is not a socket, remove it */
4047 swrap_remove_stale(fd);
4051 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4052 avail += msg->msg_iov[i].iov_len;
4056 remain = MIN(80, avail);
4061 /* we capture it as one single packet */
4062 buf = (uint8_t *)malloc(remain);
4064 /* we just not capture the packet */
4065 errno = saved_errno;
4069 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4070 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4072 msg->msg_iov[i].iov_base,
4075 remain -= this_time;
4082 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4083 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4085 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4090 if (si->connected) {
4091 to = &si->peername.sa.s;
4094 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4095 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4097 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4103 errno = saved_errno;
4106 static int swrap_recvmsg_before(int fd,
4107 struct socket_info *si,
4109 struct iovec *tmp_iov)
4114 (void)fd; /* unused */
4119 if (!si->connected) {
4124 if (msg->msg_iovlen == 0) {
4128 mtu = socket_wrapper_mtu();
4129 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4131 nlen = len + msg->msg_iov[i].iov_len;
4136 msg->msg_iovlen = i;
4137 if (msg->msg_iovlen == 0) {
4138 *tmp_iov = msg->msg_iov[0];
4139 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4141 msg->msg_iov = tmp_iov;
4142 msg->msg_iovlen = 1;
4147 if (msg->msg_name == NULL) {
4152 if (msg->msg_iovlen == 0) {
4156 if (si->bound == 0) {
4157 ret = swrap_auto_bind(fd, si, si->family);
4160 * When attempting to read or write to a
4161 * descriptor, if an underlying autobind fails
4162 * because it's not a socket, stop intercepting
4163 * uses of that descriptor.
4165 if (errno == ENOTSOCK) {
4166 swrap_remove_stale(fd);
4169 SWRAP_LOG(SWRAP_LOG_ERROR,
4170 "swrap_recvmsg_before failed");
4177 errno = EHOSTUNREACH;
4184 static int swrap_recvmsg_after(int fd,
4185 struct socket_info *si,
4187 const struct sockaddr_un *un_addr,
4188 socklen_t un_addrlen,
4191 int saved_errno = errno;
4193 uint8_t *buf = NULL;
4199 /* to give better errors */
4201 if (saved_errno == ENOENT) {
4202 saved_errno = EHOSTUNREACH;
4203 } else if (saved_errno == ENOTSOCK) {
4204 /* If the fd is not a socket, remove it */
4205 swrap_remove_stale(fd);
4209 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4210 avail += msg->msg_iov[i].iov_len;
4213 /* Convert the socket address before we leave */
4214 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4215 rc = sockaddr_convert_from_un(si,
4232 remain = MIN(80, avail);
4237 /* we capture it as one single packet */
4238 buf = (uint8_t *)malloc(remain);
4240 /* we just not capture the packet */
4241 errno = saved_errno;
4245 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4246 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4248 msg->msg_iov[i].iov_base,
4251 remain -= this_time;
4256 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4257 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4258 } else if (ret == 0) { /* END OF FILE */
4259 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4260 } else if (ret > 0) {
4261 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4270 if (un_addr != NULL) {
4271 swrap_pcap_dump_packet(si,
4277 swrap_pcap_dump_packet(si,
4290 errno = saved_errno;
4292 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4294 msg->msg_controllen > 0 &&
4295 msg->msg_control != NULL) {
4296 rc = swrap_msghdr_add_socket_info(si, msg);
4306 /****************************************************************************
4308 ***************************************************************************/
4310 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4311 struct sockaddr *from, socklen_t *fromlen)
4313 struct swrap_address from_addr = {
4314 .sa_socklen = sizeof(struct sockaddr_un),
4317 struct socket_info *si = find_socket_info(s);
4318 struct swrap_address saddr = {
4319 .sa_socklen = sizeof(struct sockaddr_storage),
4326 return libc_recvfrom(s,
4338 if (from != NULL && fromlen != NULL) {
4339 msg.msg_name = from; /* optional address */
4340 msg.msg_namelen = *fromlen; /* size of address */
4342 msg.msg_name = &saddr.sa.s; /* optional address */
4343 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4345 msg.msg_iov = &tmp; /* scatter/gather array */
4346 msg.msg_iovlen = 1; /* # elements in msg_iov */
4347 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4348 msg.msg_control = NULL; /* ancillary data, see below */
4349 msg.msg_controllen = 0; /* ancillary data buffer len */
4350 msg.msg_flags = 0; /* flags on received message */
4353 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4358 buf = msg.msg_iov[0].iov_base;
4359 len = msg.msg_iov[0].iov_len;
4361 ret = libc_recvfrom(s,
4366 &from_addr.sa_socklen);
4371 tret = swrap_recvmsg_after(s,
4375 from_addr.sa_socklen,
4381 if (from != NULL && fromlen != NULL) {
4382 *fromlen = msg.msg_namelen;
4388 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4389 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4390 struct sockaddr *from, Psocklen_t fromlen)
4392 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4393 struct sockaddr *from, socklen_t *fromlen)
4396 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4399 /****************************************************************************
4401 ***************************************************************************/
4403 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4404 const struct sockaddr *to, socklen_t tolen)
4408 struct swrap_address un_addr = {
4409 .sa_socklen = sizeof(struct sockaddr_un),
4411 const struct sockaddr_un *to_un = NULL;
4414 struct socket_info *si = find_socket_info(s);
4418 return libc_sendto(s, buf, len, flags, to, tolen);
4421 tmp.iov_base = discard_const_p(char, buf);
4425 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4426 msg.msg_namelen = tolen; /* size of address */
4427 msg.msg_iov = &tmp; /* scatter/gather array */
4428 msg.msg_iovlen = 1; /* # elements in msg_iov */
4429 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4430 msg.msg_control = NULL; /* ancillary data, see below */
4431 msg.msg_controllen = 0; /* ancillary data buffer len */
4432 msg.msg_flags = 0; /* flags on received message */
4435 rc = swrap_sendmsg_before(s,
4447 buf = msg.msg_iov[0].iov_base;
4448 len = msg.msg_iov[0].iov_len;
4453 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4456 type = SOCKET_TYPE_CHAR_UDP;
4458 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4459 snprintf(un_addr.sa.un.sun_path,
4460 sizeof(un_addr.sa.un.sun_path),
4462 socket_wrapper_dir(), type, iface, prt);
4463 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4465 /* ignore the any errors in broadcast sends */
4471 un_addr.sa_socklen);
4474 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4480 * If it is a dgram socket and we are connected, don't include the
4483 if (si->type == SOCK_DGRAM && si->connected) {
4484 ret = libc_sendto(s,
4491 ret = libc_sendto(s,
4495 (struct sockaddr *)msg.msg_name,
4499 swrap_sendmsg_after(s, si, &msg, to, ret);
4504 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4505 const struct sockaddr *to, socklen_t tolen)
4507 return swrap_sendto(s, buf, len, flags, to, tolen);
4510 /****************************************************************************
4512 ***************************************************************************/
4514 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4516 struct socket_info *si;
4518 struct swrap_address saddr = {
4519 .sa_socklen = sizeof(struct sockaddr_storage),
4525 si = find_socket_info(s);
4527 return libc_recv(s, buf, len, flags);
4534 msg.msg_name = &saddr.sa.s; /* optional address */
4535 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4536 msg.msg_iov = &tmp; /* scatter/gather array */
4537 msg.msg_iovlen = 1; /* # elements in msg_iov */
4538 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4539 msg.msg_control = NULL; /* ancillary data, see below */
4540 msg.msg_controllen = 0; /* ancillary data buffer len */
4541 msg.msg_flags = 0; /* flags on received message */
4544 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4549 buf = msg.msg_iov[0].iov_base;
4550 len = msg.msg_iov[0].iov_len;
4552 ret = libc_recv(s, buf, len, flags);
4554 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4562 ssize_t recv(int s, void *buf, size_t len, int flags)
4564 return swrap_recv(s, buf, len, flags);
4567 /****************************************************************************
4569 ***************************************************************************/
4571 static ssize_t swrap_read(int s, void *buf, size_t len)
4573 struct socket_info *si;
4576 struct swrap_address saddr = {
4577 .sa_socklen = sizeof(struct sockaddr_storage),
4582 si = find_socket_info(s);
4584 return libc_read(s, buf, len);
4591 msg.msg_name = &saddr.sa.ss; /* optional address */
4592 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4593 msg.msg_iov = &tmp; /* scatter/gather array */
4594 msg.msg_iovlen = 1; /* # elements in msg_iov */
4595 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4596 msg.msg_control = NULL; /* ancillary data, see below */
4597 msg.msg_controllen = 0; /* ancillary data buffer len */
4598 msg.msg_flags = 0; /* flags on received message */
4601 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4603 if (tret == -ENOTSOCK) {
4604 return libc_read(s, buf, len);
4609 buf = msg.msg_iov[0].iov_base;
4610 len = msg.msg_iov[0].iov_len;
4612 ret = libc_read(s, buf, len);
4614 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4622 ssize_t read(int s, void *buf, size_t len)
4624 return swrap_read(s, buf, len);
4627 /****************************************************************************
4629 ***************************************************************************/
4631 static ssize_t swrap_write(int s, const void *buf, size_t len)
4635 struct sockaddr_un un_addr;
4638 struct socket_info *si;
4640 si = find_socket_info(s);
4642 return libc_write(s, buf, len);
4645 tmp.iov_base = discard_const_p(char, buf);
4649 msg.msg_name = NULL; /* optional address */
4650 msg.msg_namelen = 0; /* size of address */
4651 msg.msg_iov = &tmp; /* scatter/gather array */
4652 msg.msg_iovlen = 1; /* # elements in msg_iov */
4653 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4654 msg.msg_control = NULL; /* ancillary data, see below */
4655 msg.msg_controllen = 0; /* ancillary data buffer len */
4656 msg.msg_flags = 0; /* flags on received message */
4659 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4664 buf = msg.msg_iov[0].iov_base;
4665 len = msg.msg_iov[0].iov_len;
4667 ret = libc_write(s, buf, len);
4669 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4674 ssize_t write(int s, const void *buf, size_t len)
4676 return swrap_write(s, buf, len);
4679 /****************************************************************************
4681 ***************************************************************************/
4683 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4687 struct sockaddr_un un_addr;
4690 struct socket_info *si = find_socket_info(s);
4693 return libc_send(s, buf, len, flags);
4696 tmp.iov_base = discard_const_p(char, buf);
4700 msg.msg_name = NULL; /* optional address */
4701 msg.msg_namelen = 0; /* size of address */
4702 msg.msg_iov = &tmp; /* scatter/gather array */
4703 msg.msg_iovlen = 1; /* # elements in msg_iov */
4704 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4705 msg.msg_control = NULL; /* ancillary data, see below */
4706 msg.msg_controllen = 0; /* ancillary data buffer len */
4707 msg.msg_flags = 0; /* flags on received message */
4710 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4715 buf = msg.msg_iov[0].iov_base;
4716 len = msg.msg_iov[0].iov_len;
4718 ret = libc_send(s, buf, len, flags);
4720 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4725 ssize_t send(int s, const void *buf, size_t len, int flags)
4727 return swrap_send(s, buf, len, flags);
4730 /****************************************************************************
4732 ***************************************************************************/
4734 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4736 struct swrap_address from_addr = {
4737 .sa_socklen = sizeof(struct sockaddr_un),
4739 struct swrap_address convert_addr = {
4740 .sa_socklen = sizeof(struct sockaddr_storage),
4742 struct socket_info *si;
4745 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4746 size_t msg_ctrllen_filled;
4747 size_t msg_ctrllen_left;
4753 si = find_socket_info(s);
4755 return libc_recvmsg(s, omsg, flags);
4758 tmp.iov_base = NULL;
4762 msg.msg_name = &from_addr.sa; /* optional address */
4763 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4764 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4765 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4766 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4767 msg_ctrllen_filled = 0;
4768 msg_ctrllen_left = omsg->msg_controllen;
4770 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4771 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4772 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4775 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4780 ret = libc_recvmsg(s, &msg, flags);
4782 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4783 msg_ctrllen_filled += msg.msg_controllen;
4784 msg_ctrllen_left -= msg.msg_controllen;
4786 if (omsg->msg_control != NULL) {
4789 p = omsg->msg_control;
4790 p += msg_ctrllen_filled;
4792 msg.msg_control = p;
4793 msg.msg_controllen = msg_ctrllen_left;
4795 msg.msg_control = NULL;
4796 msg.msg_controllen = 0;
4801 * We convert the unix address to a IP address so we need a buffer
4802 * which can store the address in case of SOCK_DGRAM, see below.
4804 msg.msg_name = &convert_addr.sa;
4805 msg.msg_namelen = convert_addr.sa_socklen;
4807 rc = swrap_recvmsg_after(s,
4811 from_addr.sa_socklen,
4817 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4818 if (omsg->msg_control != NULL) {
4819 /* msg.msg_controllen = space left */
4820 msg_ctrllen_left = msg.msg_controllen;
4821 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4824 /* Update the original message length */
4825 omsg->msg_controllen = msg_ctrllen_filled;
4826 omsg->msg_flags = msg.msg_flags;
4828 omsg->msg_iovlen = msg.msg_iovlen;
4833 * The msg_name field points to a caller-allocated buffer that is
4834 * used to return the source address if the socket is unconnected. The
4835 * caller should set msg_namelen to the size of this buffer before this
4836 * call; upon return from a successful call, msg_name will contain the
4837 * length of the returned address. If the application does not need
4838 * to know the source address, msg_name can be specified as NULL.
4840 if (si->type == SOCK_STREAM) {
4841 omsg->msg_namelen = 0;
4842 } else if (omsg->msg_name != NULL &&
4843 omsg->msg_namelen != 0 &&
4844 omsg->msg_namelen >= msg.msg_namelen) {
4845 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
4846 omsg->msg_namelen = msg.msg_namelen;
4852 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4854 return swrap_recvmsg(sockfd, msg, flags);
4857 /****************************************************************************
4859 ***************************************************************************/
4861 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4865 struct sockaddr_un un_addr;
4866 const struct sockaddr_un *to_un = NULL;
4867 const struct sockaddr *to = NULL;
4870 struct socket_info *si = find_socket_info(s);
4874 return libc_sendmsg(s, omsg, flags);
4877 ZERO_STRUCT(un_addr);
4879 tmp.iov_base = NULL;
4884 if (si->connected == 0) {
4885 msg.msg_name = omsg->msg_name; /* optional address */
4886 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4888 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4889 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4890 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4891 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4892 /* omsg is a const so use a local buffer for modifications */
4893 uint8_t cmbuf[omsg->msg_controllen];
4895 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4897 msg.msg_control = cmbuf; /* ancillary data, see below */
4898 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4900 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4903 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4911 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4919 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4920 avail += msg.msg_iov[i].iov_len;
4926 /* we capture it as one single packet */
4927 buf = (uint8_t *)malloc(remain);
4932 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4933 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4935 msg.msg_iov[i].iov_base,
4938 remain -= this_time;
4941 type = SOCKET_TYPE_CHAR_UDP;
4943 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4944 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4945 socket_wrapper_dir(), type, iface, prt);
4946 if (stat(un_addr.sun_path, &st) != 0) continue;
4948 msg.msg_name = &un_addr; /* optional address */
4949 msg.msg_namelen = sizeof(un_addr); /* size of address */
4951 /* ignore the any errors in broadcast sends */
4952 libc_sendmsg(s, &msg, flags);
4955 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4961 ret = libc_sendmsg(s, &msg, flags);
4963 swrap_sendmsg_after(s, si, &msg, to, ret);
4968 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4970 return swrap_sendmsg(s, omsg, flags);
4973 /****************************************************************************
4975 ***************************************************************************/
4977 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4979 struct socket_info *si;
4982 struct swrap_address saddr = {
4983 .sa_socklen = sizeof(struct sockaddr_storage)
4988 si = find_socket_info(s);
4990 return libc_readv(s, vector, count);
4993 tmp.iov_base = NULL;
4997 msg.msg_name = &saddr.sa.s; /* optional address */
4998 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4999 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5000 msg.msg_iovlen = count; /* # elements in msg_iov */
5001 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5002 msg.msg_control = NULL; /* ancillary data, see below */
5003 msg.msg_controllen = 0; /* ancillary data buffer len */
5004 msg.msg_flags = 0; /* flags on received message */
5007 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5009 if (rc == -ENOTSOCK) {
5010 return libc_readv(s, vector, count);
5015 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5017 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5025 ssize_t readv(int s, const struct iovec *vector, int count)
5027 return swrap_readv(s, vector, count);
5030 /****************************************************************************
5032 ***************************************************************************/
5034 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5038 struct sockaddr_un un_addr;
5041 struct socket_info *si = find_socket_info(s);
5044 return libc_writev(s, vector, count);
5047 tmp.iov_base = NULL;
5051 msg.msg_name = NULL; /* optional address */
5052 msg.msg_namelen = 0; /* size of address */
5053 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5054 msg.msg_iovlen = count; /* # elements in msg_iov */
5055 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5056 msg.msg_control = NULL; /* ancillary data, see below */
5057 msg.msg_controllen = 0; /* ancillary data buffer len */
5058 msg.msg_flags = 0; /* flags on received message */
5061 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5063 if (rc == -ENOTSOCK) {
5064 return libc_readv(s, vector, count);
5069 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5071 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5076 ssize_t writev(int s, const struct iovec *vector, int count)
5078 return swrap_writev(s, vector, count);
5081 /****************************
5083 ***************************/
5085 static int swrap_close(int fd)
5087 struct socket_info *si = find_socket_info(fd);
5088 struct socket_info_fd *fi;
5092 return libc_close(fd);
5095 for (fi = si->fds; fi; fi = fi->next) {
5097 SWRAP_DLIST_REMOVE(si->fds, fi);
5104 /* there are still references left */
5105 return libc_close(fd);
5108 SWRAP_DLIST_REMOVE(sockets, si);
5110 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5111 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5114 ret = libc_close(fd);
5116 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5117 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5118 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5121 if (si->un_addr.sun_path[0] != '\0') {
5122 unlink(si->un_addr.sun_path);
5131 return swrap_close(fd);
5134 /****************************
5136 ***************************/
5138 static int swrap_dup(int fd)
5140 struct socket_info *si;
5141 struct socket_info_fd *fi;
5143 si = find_socket_info(fd);
5146 return libc_dup(fd);
5149 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5155 fi->fd = libc_dup(fd);
5157 int saved_errno = errno;
5159 errno = saved_errno;
5163 /* Make sure we don't have an entry for the fd */
5164 swrap_remove_stale(fi->fd);
5166 SWRAP_DLIST_ADD(si->fds, fi);
5172 return swrap_dup(fd);
5175 /****************************
5177 ***************************/
5179 static int swrap_dup2(int fd, int newfd)
5181 struct socket_info *si;
5182 struct socket_info_fd *fi;
5184 si = find_socket_info(fd);
5187 return libc_dup2(fd, newfd);
5190 if (find_socket_info(newfd)) {
5191 /* dup2() does an implicit close of newfd, which we
5192 * need to emulate */
5196 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5202 fi->fd = libc_dup2(fd, newfd);
5204 int saved_errno = errno;
5206 errno = saved_errno;
5210 /* Make sure we don't have an entry for the fd */
5211 swrap_remove_stale(fi->fd);
5213 SWRAP_DLIST_ADD(si->fds, fi);
5217 int dup2(int fd, int newfd)
5219 return swrap_dup2(fd, newfd);
5222 /****************************
5224 ***************************/
5226 static int swrap_vfcntl(int fd, int cmd, va_list va)
5228 struct socket_info_fd *fi;
5229 struct socket_info *si;
5232 si = find_socket_info(fd);
5234 rc = libc_vfcntl(fd, cmd, va);
5241 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5247 fi->fd = libc_vfcntl(fd, cmd, va);
5249 int saved_errno = errno;
5251 errno = saved_errno;
5255 /* Make sure we don't have an entry for the fd */
5256 swrap_remove_stale(fi->fd);
5258 SWRAP_DLIST_ADD(si->fds, fi);
5263 rc = libc_vfcntl(fd, cmd, va);
5270 int fcntl(int fd, int cmd, ...)
5277 rc = swrap_vfcntl(fd, cmd, va);
5284 /****************************
5286 ***************************/
5289 static int swrap_eventfd(int count, int flags)
5293 fd = libc_eventfd(count, flags);
5295 swrap_remove_stale(fd);
5301 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5302 int eventfd(unsigned int count, int flags)
5304 int eventfd(int count, int flags)
5307 return swrap_eventfd(count, flags);
5312 int pledge(const char *promises, const char *paths[])
5314 (void)promises; /* unused */
5315 (void)paths; /* unused */
5319 #endif /* HAVE_PLEDGE */
5321 /****************************
5323 ***************************/
5326 * This function is called when the library is unloaded and makes sure that
5327 * sockets get closed and the unix file for the socket are unlinked.
5329 void swrap_destructor(void)
5331 struct socket_info *s = sockets;
5334 struct socket_info_fd *f = s->fds;
5341 if (swrap.libc_handle != NULL) {
5342 dlclose(swrap.libc_handle);
5344 if (swrap.libsocket_handle) {
5345 dlclose(swrap.libsocket_handle);