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 child_si->family = parent_si->family;
2686 child_si->type = parent_si->type;
2687 child_si->protocol = parent_si->protocol;
2688 child_si->bound = 1;
2689 child_si->is_server = 1;
2690 child_si->connected = 1;
2692 child_si->peername = (struct swrap_address) {
2693 .sa_socklen = in_addr.sa_socklen,
2695 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2697 if (addr != NULL && addrlen != NULL) {
2698 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2700 memcpy(addr, &in_addr.sa.ss, copy_len);
2702 *addrlen = in_addr.sa_socklen;
2705 ret = libc_getsockname(fd,
2707 &un_my_addr.sa_socklen);
2715 ret = sockaddr_convert_from_un(child_si,
2717 un_my_addr.sa_socklen,
2720 &in_my_addr.sa_socklen);
2728 SWRAP_LOG(SWRAP_LOG_TRACE,
2729 "accept() path=%s, fd=%d",
2730 un_my_addr.sa.un.sun_path, s);
2732 child_si->myname = (struct swrap_address) {
2733 .sa_socklen = in_my_addr.sa_socklen,
2735 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2737 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2738 SWRAP_DLIST_ADD(sockets, child_si);
2741 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2742 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2743 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2750 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
2752 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
2756 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2757 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2759 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2762 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
2765 static int autobind_start_init;
2766 static int autobind_start;
2768 /* using sendto() or connect() on an unbound socket would give the
2769 recipient no way to reply, as unlike UDP and TCP, a unix domain
2770 socket can't auto-assign ephemeral port numbers, so we need to
2772 Note: this might change the family from ipv6 to ipv4
2774 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2776 struct swrap_address un_addr = {
2777 .sa_socklen = sizeof(struct sockaddr_un),
2785 if (autobind_start_init != 1) {
2786 autobind_start_init = 1;
2787 autobind_start = getpid();
2788 autobind_start %= 50000;
2789 autobind_start += 10000;
2792 un_addr.sa.un.sun_family = AF_UNIX;
2796 struct sockaddr_in in;
2800 type = SOCKET_TYPE_CHAR_TCP;
2803 type = SOCKET_TYPE_CHAR_UDP;
2806 errno = ESOCKTNOSUPPORT;
2810 memset(&in, 0, sizeof(in));
2811 in.sin_family = AF_INET;
2812 in.sin_addr.s_addr = htonl(127<<24 |
2813 socket_wrapper_default_iface());
2815 si->myname = (struct swrap_address) {
2816 .sa_socklen = sizeof(in),
2818 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2823 struct sockaddr_in6 in6;
2825 if (si->family != family) {
2826 errno = ENETUNREACH;
2832 type = SOCKET_TYPE_CHAR_TCP_V6;
2835 type = SOCKET_TYPE_CHAR_UDP_V6;
2838 errno = ESOCKTNOSUPPORT;
2842 memset(&in6, 0, sizeof(in6));
2843 in6.sin6_family = AF_INET6;
2844 in6.sin6_addr = *swrap_ipv6();
2845 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2847 si->myname = (struct swrap_address) {
2848 .sa_socklen = sizeof(in6),
2850 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2855 errno = ESOCKTNOSUPPORT;
2859 if (autobind_start > 60000) {
2860 autobind_start = 10000;
2863 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2864 port = autobind_start + i;
2865 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2866 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2867 type, socket_wrapper_default_iface(), port);
2868 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2870 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2871 if (ret == -1) return ret;
2873 si->un_addr = un_addr.sa.un;
2876 autobind_start = port + 1;
2879 if (i == SOCKET_MAX_SOCKETS) {
2880 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2881 "interface "SOCKET_FORMAT,
2884 socket_wrapper_default_iface(),
2890 si->family = family;
2891 set_port(si->family, port, &si->myname);
2896 /****************************************************************************
2898 ***************************************************************************/
2900 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2904 struct swrap_address un_addr = {
2905 .sa_socklen = sizeof(struct sockaddr_un),
2907 struct socket_info *si = find_socket_info(s);
2911 return libc_connect(s, serv_addr, addrlen);
2914 if (si->bound == 0) {
2915 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2916 if (ret == -1) return -1;
2919 if (si->family != serv_addr->sa_family) {
2924 ret = sockaddr_convert_to_un(si, serv_addr,
2925 addrlen, &un_addr.sa.un, 0, &bcast);
2926 if (ret == -1) return -1;
2929 errno = ENETUNREACH;
2933 if (si->type == SOCK_DGRAM) {
2934 si->defer_connect = 1;
2937 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2939 ret = libc_connect(s,
2941 un_addr.sa_socklen);
2944 SWRAP_LOG(SWRAP_LOG_TRACE,
2945 "connect() path=%s, fd=%d",
2946 un_addr.sa.un.sun_path, s);
2949 /* to give better errors */
2950 if (ret == -1 && errno == ENOENT) {
2951 errno = EHOSTUNREACH;
2955 si->peername = (struct swrap_address) {
2956 .sa_socklen = addrlen,
2959 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2963 * When we connect() on a socket than we have to bind the
2964 * outgoing connection on the interface we use for the
2965 * transport. We already bound it on the right interface
2966 * but here we have to update the name so getsockname()
2967 * returns correct information.
2969 if (si->bindname.sa_socklen > 0) {
2970 si->myname = (struct swrap_address) {
2971 .sa_socklen = si->bindname.sa_socklen,
2974 memcpy(&si->myname.sa.ss,
2975 &si->bindname.sa.ss,
2976 si->bindname.sa_socklen);
2978 /* Cleanup bindname */
2979 si->bindname = (struct swrap_address) {
2984 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2985 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2987 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2993 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2995 return swrap_connect(s, serv_addr, addrlen);
2998 /****************************************************************************
3000 ***************************************************************************/
3002 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3005 struct swrap_address un_addr = {
3006 .sa_socklen = sizeof(struct sockaddr_un),
3008 struct socket_info *si = find_socket_info(s);
3015 return libc_bind(s, myaddr, addrlen);
3018 switch (si->family) {
3020 const struct sockaddr_in *sin;
3021 if (addrlen < sizeof(struct sockaddr_in)) {
3022 bind_error = EINVAL;
3026 sin = (const struct sockaddr_in *)(const void *)myaddr;
3028 if (sin->sin_family != AF_INET) {
3029 bind_error = EAFNOSUPPORT;
3032 /* special case for AF_UNSPEC */
3033 if (sin->sin_family == AF_UNSPEC &&
3034 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3043 const struct sockaddr_in6 *sin6;
3044 if (addrlen < sizeof(struct sockaddr_in6)) {
3045 bind_error = EINVAL;
3049 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3051 if (sin6->sin6_family != AF_INET6) {
3052 bind_error = EAFNOSUPPORT;
3059 bind_error = EINVAL;
3063 if (bind_error != 0) {
3069 in_use = check_addr_port_in_use(myaddr, addrlen);
3076 si->myname.sa_socklen = addrlen;
3077 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3079 ret = sockaddr_convert_to_un(si,
3085 if (ret == -1) return -1;
3087 unlink(un_addr.sa.un.sun_path);
3089 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3091 SWRAP_LOG(SWRAP_LOG_TRACE,
3092 "bind() path=%s, fd=%d",
3093 un_addr.sa.un.sun_path, s);
3102 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3104 return swrap_bind(s, myaddr, addrlen);
3107 /****************************************************************************
3109 ***************************************************************************/
3111 #ifdef HAVE_BINDRESVPORT
3112 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3114 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3116 struct swrap_address myaddr = {
3117 .sa_socklen = sizeof(struct sockaddr_storage),
3120 static uint16_t port;
3125 #define SWRAP_STARTPORT 600
3126 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3127 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3130 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3134 salen = myaddr.sa_socklen;
3137 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3143 memset(&myaddr.sa.ss, 0, salen);
3148 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3151 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3153 salen = sizeof(struct sockaddr_in);
3154 sinp->sin_port = htons(port);
3158 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3160 salen = sizeof(struct sockaddr_in6);
3161 sin6p->sin6_port = htons(port);
3165 errno = EAFNOSUPPORT;
3170 if (port > SWRAP_ENDPORT) {
3171 port = SWRAP_STARTPORT;
3174 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3175 if (rc == 0 || errno != EADDRINUSE) {
3183 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3185 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3189 /****************************************************************************
3191 ***************************************************************************/
3193 static int swrap_listen(int s, int backlog)
3196 struct socket_info *si = find_socket_info(s);
3199 return libc_listen(s, backlog);
3202 if (si->bound == 0) {
3203 ret = swrap_auto_bind(s, si, si->family);
3210 ret = libc_listen(s, backlog);
3215 int listen(int s, int backlog)
3217 return swrap_listen(s, backlog);
3220 /****************************************************************************
3222 ***************************************************************************/
3224 static FILE *swrap_fopen(const char *name, const char *mode)
3228 fp = libc_fopen(name, mode);
3230 int fd = fileno(fp);
3232 swrap_remove_stale(fd);
3238 FILE *fopen(const char *name, const char *mode)
3240 return swrap_fopen(name, mode);
3243 /****************************************************************************
3245 ***************************************************************************/
3247 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3251 ret = libc_vopen(pathname, flags, ap);
3254 * There are methods for closing descriptors (libc-internal code
3255 * paths, direct syscalls) which close descriptors in ways that
3256 * we can't intercept, so try to recover when we notice that
3259 swrap_remove_stale(ret);
3264 int open(const char *pathname, int flags, ...)
3269 va_start(ap, flags);
3270 fd = swrap_vopen(pathname, flags, ap);
3276 /****************************************************************************
3278 ***************************************************************************/
3280 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3282 struct socket_info *si = find_socket_info(s);
3286 return libc_getpeername(s, name, addrlen);
3289 if (si->peername.sa_socklen == 0)
3295 len = MIN(*addrlen, si->peername.sa_socklen);
3300 memcpy(name, &si->peername.sa.ss, len);
3301 *addrlen = si->peername.sa_socklen;
3306 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3307 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3309 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3312 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3315 /****************************************************************************
3317 ***************************************************************************/
3319 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3321 struct socket_info *si = find_socket_info(s);
3325 return libc_getsockname(s, name, addrlen);
3328 len = MIN(*addrlen, si->myname.sa_socklen);
3333 memcpy(name, &si->myname.sa.ss, len);
3334 *addrlen = si->myname.sa_socklen;
3339 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3340 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3342 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3345 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3348 /****************************************************************************
3350 ***************************************************************************/
3353 # ifdef SO_PROTOTYPE /* The Solaris name */
3354 # define SO_PROTOCOL SO_PROTOTYPE
3355 # endif /* SO_PROTOTYPE */
3356 #endif /* SO_PROTOCOL */
3358 static int swrap_getsockopt(int s, int level, int optname,
3359 void *optval, socklen_t *optlen)
3361 struct socket_info *si = find_socket_info(s);
3364 return libc_getsockopt(s,
3371 if (level == SOL_SOCKET) {
3375 if (optval == NULL || optlen == NULL ||
3376 *optlen < (socklen_t)sizeof(int)) {
3381 *optlen = sizeof(int);
3382 *(int *)optval = si->family;
3384 #endif /* SO_DOMAIN */
3388 if (optval == NULL || optlen == NULL ||
3389 *optlen < (socklen_t)sizeof(int)) {
3394 *optlen = sizeof(int);
3395 *(int *)optval = si->protocol;
3397 #endif /* SO_PROTOCOL */
3399 if (optval == NULL || optlen == NULL ||
3400 *optlen < (socklen_t)sizeof(int)) {
3405 *optlen = sizeof(int);
3406 *(int *)optval = si->type;
3409 return libc_getsockopt(s,
3415 } else if (level == IPPROTO_TCP) {
3420 * This enables sending packets directly out over TCP.
3421 * As a unix socket is doing that any way, report it as
3424 if (optval == NULL || optlen == NULL ||
3425 *optlen < (socklen_t)sizeof(int)) {
3430 *optlen = sizeof(int);
3431 *(int *)optval = si->tcp_nodelay;
3434 #endif /* TCP_NODELAY */
3440 errno = ENOPROTOOPT;
3444 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3445 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3447 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3450 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3453 /****************************************************************************
3455 ***************************************************************************/
3457 static int swrap_setsockopt(int s, int level, int optname,
3458 const void *optval, socklen_t optlen)
3460 struct socket_info *si = find_socket_info(s);
3463 return libc_setsockopt(s,
3470 if (level == SOL_SOCKET) {
3471 return libc_setsockopt(s,
3476 } else if (level == IPPROTO_TCP) {
3483 * This enables sending packets directly out over TCP.
3484 * A unix socket is doing that any way.
3486 if (optval == NULL || optlen == 0 ||
3487 optlen < (socklen_t)sizeof(int)) {
3492 i = *discard_const_p(int, optval);
3493 if (i != 0 && i != 1) {
3497 si->tcp_nodelay = i;
3501 #endif /* TCP_NODELAY */
3507 switch (si->family) {
3509 if (level == IPPROTO_IP) {
3511 if (optname == IP_PKTINFO) {
3512 si->pktinfo = AF_INET;
3514 #endif /* IP_PKTINFO */
3519 if (level == IPPROTO_IPV6) {
3520 #ifdef IPV6_RECVPKTINFO
3521 if (optname == IPV6_RECVPKTINFO) {
3522 si->pktinfo = AF_INET6;
3524 #endif /* IPV6_PKTINFO */
3529 errno = ENOPROTOOPT;
3534 int setsockopt(int s, int level, int optname,
3535 const void *optval, socklen_t optlen)
3537 return swrap_setsockopt(s, level, optname, optval, optlen);
3540 /****************************************************************************
3542 ***************************************************************************/
3544 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3546 struct socket_info *si = find_socket_info(s);
3552 return libc_vioctl(s, r, va);
3557 rc = libc_vioctl(s, r, va);
3561 value = *((int *)va_arg(ap, int *));
3563 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3564 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3565 } else if (value == 0) { /* END OF FILE */
3566 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3576 #ifdef HAVE_IOCTL_INT
3577 int ioctl(int s, int r, ...)
3579 int ioctl(int s, unsigned long int r, ...)
3587 rc = swrap_vioctl(s, (unsigned long int) r, va);
3598 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3601 # ifdef _ALIGN /* BSD */
3602 #define CMSG_ALIGN _ALIGN
3604 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3605 # endif /* _ALIGN */
3606 #endif /* CMSG_ALIGN */
3609 * @brief Add a cmsghdr to a msghdr.
3611 * This is an function to add any type of cmsghdr. It will operate on the
3612 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3613 * the buffer position after the added cmsg element. Hence, this function is
3614 * intended to be used with an intermediate msghdr and not on the original
3615 * one handed in by the client.
3617 * @param[in] msg The msghdr to which to add the cmsg.
3619 * @param[in] level The cmsg level to set.
3621 * @param[in] type The cmsg type to set.
3623 * @param[in] data The cmsg data to set.
3625 * @param[in] len the length of the data to set.
3627 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3633 size_t cmlen = CMSG_LEN(len);
3634 size_t cmspace = CMSG_SPACE(len);
3635 uint8_t cmbuf[cmspace];
3636 void *cast_ptr = (void *)cmbuf;
3637 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3640 memset(cmbuf, 0, cmspace);
3642 if (msg->msg_controllen < cmlen) {
3643 cmlen = msg->msg_controllen;
3644 msg->msg_flags |= MSG_CTRUNC;
3647 if (msg->msg_controllen < cmspace) {
3648 cmspace = msg->msg_controllen;
3652 * We copy the full input data into an intermediate cmsghdr first
3653 * in order to more easily cope with truncation.
3655 cm->cmsg_len = cmlen;
3656 cm->cmsg_level = level;
3657 cm->cmsg_type = type;
3658 memcpy(CMSG_DATA(cm), data, len);
3661 * We now copy the possibly truncated buffer.
3662 * We copy cmlen bytes, but consume cmspace bytes,
3663 * leaving the possible padding uninitialiazed.
3665 p = (uint8_t *)msg->msg_control;
3666 memcpy(p, cm, cmlen);
3668 msg->msg_control = p;
3669 msg->msg_controllen -= cmspace;
3674 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3677 /* Add packet info */
3678 switch (si->pktinfo) {
3679 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3681 struct sockaddr_in *sin;
3682 #if defined(HAVE_STRUCT_IN_PKTINFO)
3683 struct in_pktinfo pkt;
3684 #elif defined(IP_RECVDSTADDR)
3688 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3689 sin = &si->bindname.sa.in;
3691 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3694 sin = &si->myname.sa.in;
3699 #if defined(HAVE_STRUCT_IN_PKTINFO)
3700 pkt.ipi_ifindex = socket_wrapper_default_iface();
3701 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3702 #elif defined(IP_RECVDSTADDR)
3703 pkt = sin->sin_addr;
3706 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3711 #endif /* IP_PKTINFO */
3712 #if defined(HAVE_IPV6)
3714 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3715 struct sockaddr_in6 *sin6;
3716 struct in6_pktinfo pkt6;
3718 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3719 sin6 = &si->bindname.sa.in6;
3721 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3724 sin6 = &si->myname.sa.in6;
3729 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3730 pkt6.ipi6_addr = sin6->sin6_addr;
3732 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3733 &pkt6, sizeof(pkt6));
3734 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3738 #endif /* IPV6_PKTINFO */
3746 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3747 struct msghdr *omsg)
3751 if (si->pktinfo > 0) {
3752 rc = swrap_msghdr_add_pktinfo(si, omsg);
3758 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3760 size_t *cm_data_space);
3761 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3763 size_t *cm_data_space);
3765 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3767 size_t *cm_data_space) {
3768 struct cmsghdr *cmsg;
3772 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3776 for (cmsg = CMSG_FIRSTHDR(msg);
3778 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3779 switch (cmsg->cmsg_level) {
3781 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3786 rc = swrap_sendmsg_copy_cmsg(cmsg,
3796 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3798 size_t *cm_data_space)
3803 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
3805 p = realloc((*cm_data), cmspace);
3811 p = (*cm_data) + (*cm_data_space);
3812 *cm_data_space = cmspace;
3814 memcpy(p, cmsg, cmsg->cmsg_len);
3819 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3821 size_t *cm_data_space);
3824 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3826 size_t *cm_data_space)
3830 switch(cmsg->cmsg_type) {
3833 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3840 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3852 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3854 size_t *cm_data_space)
3856 (void)cmsg; /* unused */
3857 (void)cm_data; /* unused */
3858 (void)cm_data_space; /* unused */
3861 * Passing a IP pktinfo to a unix socket might be rejected by the
3862 * Kernel, at least on FreeBSD. So skip this cmsg.
3866 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3868 static ssize_t swrap_sendmsg_before(int fd,
3869 struct socket_info *si,
3871 struct iovec *tmp_iov,
3872 struct sockaddr_un *tmp_un,
3873 const struct sockaddr_un **to_un,
3874 const struct sockaddr **to,
3894 if (!si->connected) {
3899 if (msg->msg_iovlen == 0) {
3903 mtu = socket_wrapper_mtu();
3904 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3906 nlen = len + msg->msg_iov[i].iov_len;
3911 msg->msg_iovlen = i;
3912 if (msg->msg_iovlen == 0) {
3913 *tmp_iov = msg->msg_iov[0];
3914 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
3916 msg->msg_iov = tmp_iov;
3917 msg->msg_iovlen = 1;
3922 if (si->connected) {
3923 if (msg->msg_name != NULL) {
3925 * We are dealing with unix sockets and if we
3926 * are connected, we should only talk to the
3927 * connected unix path. Using the fd to send
3928 * to another server would be hard to achieve.
3930 msg->msg_name = NULL;
3931 msg->msg_namelen = 0;
3934 const struct sockaddr *msg_name;
3935 msg_name = (const struct sockaddr *)msg->msg_name;
3937 if (msg_name == NULL) {
3943 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3945 if (ret == -1) return -1;
3953 msg->msg_name = tmp_un;
3954 msg->msg_namelen = sizeof(*tmp_un);
3957 if (si->bound == 0) {
3958 ret = swrap_auto_bind(fd, si, si->family);
3960 if (errno == ENOTSOCK) {
3961 swrap_remove_stale(fd);
3964 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3970 if (!si->defer_connect) {
3974 ret = sockaddr_convert_to_un(si,
3976 si->peername.sa_socklen,
3980 if (ret == -1) return -1;
3982 ret = libc_connect(fd,
3983 (struct sockaddr *)(void *)tmp_un,
3986 /* to give better errors */
3987 if (ret == -1 && errno == ENOENT) {
3988 errno = EHOSTUNREACH;
3995 si->defer_connect = 0;
3998 errno = EHOSTUNREACH;
4002 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4003 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4004 uint8_t *cmbuf = NULL;
4007 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4014 msg->msg_controllen = 0;
4015 msg->msg_control = NULL;
4016 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4017 memcpy(msg->msg_control, cmbuf, cmlen);
4018 msg->msg_controllen = cmlen;
4027 static void swrap_sendmsg_after(int fd,
4028 struct socket_info *si,
4030 const struct sockaddr *to,
4033 int saved_errno = errno;
4040 /* to give better errors */
4042 if (saved_errno == ENOENT) {
4043 saved_errno = EHOSTUNREACH;
4044 } else if (saved_errno == ENOTSOCK) {
4045 /* If the fd is not a socket, remove it */
4046 swrap_remove_stale(fd);
4050 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4051 avail += msg->msg_iov[i].iov_len;
4055 remain = MIN(80, avail);
4060 /* we capture it as one single packet */
4061 buf = (uint8_t *)malloc(remain);
4063 /* we just not capture the packet */
4064 errno = saved_errno;
4068 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4069 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4071 msg->msg_iov[i].iov_base,
4074 remain -= this_time;
4081 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4082 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4084 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4089 if (si->connected) {
4090 to = &si->peername.sa.s;
4093 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4094 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4096 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4102 errno = saved_errno;
4105 static int swrap_recvmsg_before(int fd,
4106 struct socket_info *si,
4108 struct iovec *tmp_iov)
4113 (void)fd; /* unused */
4118 if (!si->connected) {
4123 if (msg->msg_iovlen == 0) {
4127 mtu = socket_wrapper_mtu();
4128 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4130 nlen = len + msg->msg_iov[i].iov_len;
4135 msg->msg_iovlen = i;
4136 if (msg->msg_iovlen == 0) {
4137 *tmp_iov = msg->msg_iov[0];
4138 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4140 msg->msg_iov = tmp_iov;
4141 msg->msg_iovlen = 1;
4146 if (msg->msg_name == NULL) {
4151 if (msg->msg_iovlen == 0) {
4155 if (si->bound == 0) {
4156 ret = swrap_auto_bind(fd, si, si->family);
4159 * When attempting to read or write to a
4160 * descriptor, if an underlying autobind fails
4161 * because it's not a socket, stop intercepting
4162 * uses of that descriptor.
4164 if (errno == ENOTSOCK) {
4165 swrap_remove_stale(fd);
4168 SWRAP_LOG(SWRAP_LOG_ERROR,
4169 "swrap_recvmsg_before failed");
4176 errno = EHOSTUNREACH;
4183 static int swrap_recvmsg_after(int fd,
4184 struct socket_info *si,
4186 const struct sockaddr_un *un_addr,
4187 socklen_t un_addrlen,
4190 int saved_errno = errno;
4192 uint8_t *buf = NULL;
4198 /* to give better errors */
4200 if (saved_errno == ENOENT) {
4201 saved_errno = EHOSTUNREACH;
4202 } else if (saved_errno == ENOTSOCK) {
4203 /* If the fd is not a socket, remove it */
4204 swrap_remove_stale(fd);
4208 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4209 avail += msg->msg_iov[i].iov_len;
4212 /* Convert the socket address before we leave */
4213 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4214 rc = sockaddr_convert_from_un(si,
4231 remain = MIN(80, avail);
4236 /* we capture it as one single packet */
4237 buf = (uint8_t *)malloc(remain);
4239 /* we just not capture the packet */
4240 errno = saved_errno;
4244 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4245 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4247 msg->msg_iov[i].iov_base,
4250 remain -= this_time;
4255 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4256 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4257 } else if (ret == 0) { /* END OF FILE */
4258 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4259 } else if (ret > 0) {
4260 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4269 if (un_addr != NULL) {
4270 swrap_pcap_dump_packet(si,
4276 swrap_pcap_dump_packet(si,
4289 errno = saved_errno;
4291 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4293 msg->msg_controllen > 0 &&
4294 msg->msg_control != NULL) {
4295 rc = swrap_msghdr_add_socket_info(si, msg);
4305 /****************************************************************************
4307 ***************************************************************************/
4309 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4310 struct sockaddr *from, socklen_t *fromlen)
4312 struct swrap_address from_addr = {
4313 .sa_socklen = sizeof(struct sockaddr_un),
4316 struct socket_info *si = find_socket_info(s);
4317 struct swrap_address saddr = {
4318 .sa_socklen = sizeof(struct sockaddr_storage),
4325 return libc_recvfrom(s,
4337 if (from != NULL && fromlen != NULL) {
4338 msg.msg_name = from; /* optional address */
4339 msg.msg_namelen = *fromlen; /* size of address */
4341 msg.msg_name = &saddr.sa.s; /* optional address */
4342 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4344 msg.msg_iov = &tmp; /* scatter/gather array */
4345 msg.msg_iovlen = 1; /* # elements in msg_iov */
4346 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4347 msg.msg_control = NULL; /* ancillary data, see below */
4348 msg.msg_controllen = 0; /* ancillary data buffer len */
4349 msg.msg_flags = 0; /* flags on received message */
4352 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4357 buf = msg.msg_iov[0].iov_base;
4358 len = msg.msg_iov[0].iov_len;
4360 ret = libc_recvfrom(s,
4365 &from_addr.sa_socklen);
4370 tret = swrap_recvmsg_after(s,
4374 from_addr.sa_socklen,
4380 if (from != NULL && fromlen != NULL) {
4381 *fromlen = msg.msg_namelen;
4387 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4388 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4389 struct sockaddr *from, Psocklen_t fromlen)
4391 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4392 struct sockaddr *from, socklen_t *fromlen)
4395 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4398 /****************************************************************************
4400 ***************************************************************************/
4402 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4403 const struct sockaddr *to, socklen_t tolen)
4407 struct swrap_address un_addr = {
4408 .sa_socklen = sizeof(struct sockaddr_un),
4410 const struct sockaddr_un *to_un = NULL;
4413 struct socket_info *si = find_socket_info(s);
4417 return libc_sendto(s, buf, len, flags, to, tolen);
4420 tmp.iov_base = discard_const_p(char, buf);
4424 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4425 msg.msg_namelen = tolen; /* size of address */
4426 msg.msg_iov = &tmp; /* scatter/gather array */
4427 msg.msg_iovlen = 1; /* # elements in msg_iov */
4428 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4429 msg.msg_control = NULL; /* ancillary data, see below */
4430 msg.msg_controllen = 0; /* ancillary data buffer len */
4431 msg.msg_flags = 0; /* flags on received message */
4434 rc = swrap_sendmsg_before(s,
4446 buf = msg.msg_iov[0].iov_base;
4447 len = msg.msg_iov[0].iov_len;
4452 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4455 type = SOCKET_TYPE_CHAR_UDP;
4457 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4458 snprintf(un_addr.sa.un.sun_path,
4459 sizeof(un_addr.sa.un.sun_path),
4461 socket_wrapper_dir(), type, iface, prt);
4462 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4464 /* ignore the any errors in broadcast sends */
4470 un_addr.sa_socklen);
4473 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4479 * If it is a dgram socket and we are connected, don't include the
4482 if (si->type == SOCK_DGRAM && si->connected) {
4483 ret = libc_sendto(s,
4490 ret = libc_sendto(s,
4494 (struct sockaddr *)msg.msg_name,
4498 swrap_sendmsg_after(s, si, &msg, to, ret);
4503 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4504 const struct sockaddr *to, socklen_t tolen)
4506 return swrap_sendto(s, buf, len, flags, to, tolen);
4509 /****************************************************************************
4511 ***************************************************************************/
4513 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4515 struct socket_info *si;
4517 struct swrap_address saddr = {
4518 .sa_socklen = sizeof(struct sockaddr_storage),
4524 si = find_socket_info(s);
4526 return libc_recv(s, buf, len, flags);
4533 msg.msg_name = &saddr.sa.s; /* optional address */
4534 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4535 msg.msg_iov = &tmp; /* scatter/gather array */
4536 msg.msg_iovlen = 1; /* # elements in msg_iov */
4537 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4538 msg.msg_control = NULL; /* ancillary data, see below */
4539 msg.msg_controllen = 0; /* ancillary data buffer len */
4540 msg.msg_flags = 0; /* flags on received message */
4543 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4548 buf = msg.msg_iov[0].iov_base;
4549 len = msg.msg_iov[0].iov_len;
4551 ret = libc_recv(s, buf, len, flags);
4553 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4561 ssize_t recv(int s, void *buf, size_t len, int flags)
4563 return swrap_recv(s, buf, len, flags);
4566 /****************************************************************************
4568 ***************************************************************************/
4570 static ssize_t swrap_read(int s, void *buf, size_t len)
4572 struct socket_info *si;
4575 struct swrap_address saddr = {
4576 .sa_socklen = sizeof(struct sockaddr_storage),
4581 si = find_socket_info(s);
4583 return libc_read(s, buf, len);
4590 msg.msg_name = &saddr.sa.ss; /* optional address */
4591 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4592 msg.msg_iov = &tmp; /* scatter/gather array */
4593 msg.msg_iovlen = 1; /* # elements in msg_iov */
4594 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4595 msg.msg_control = NULL; /* ancillary data, see below */
4596 msg.msg_controllen = 0; /* ancillary data buffer len */
4597 msg.msg_flags = 0; /* flags on received message */
4600 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4602 if (tret == -ENOTSOCK) {
4603 return libc_read(s, buf, len);
4608 buf = msg.msg_iov[0].iov_base;
4609 len = msg.msg_iov[0].iov_len;
4611 ret = libc_read(s, buf, len);
4613 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4621 ssize_t read(int s, void *buf, size_t len)
4623 return swrap_read(s, buf, len);
4626 /****************************************************************************
4628 ***************************************************************************/
4630 static ssize_t swrap_write(int s, const void *buf, size_t len)
4634 struct sockaddr_un un_addr;
4637 struct socket_info *si;
4639 si = find_socket_info(s);
4641 return libc_write(s, buf, len);
4644 tmp.iov_base = discard_const_p(char, buf);
4648 msg.msg_name = NULL; /* optional address */
4649 msg.msg_namelen = 0; /* size of address */
4650 msg.msg_iov = &tmp; /* scatter/gather array */
4651 msg.msg_iovlen = 1; /* # elements in msg_iov */
4652 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4653 msg.msg_control = NULL; /* ancillary data, see below */
4654 msg.msg_controllen = 0; /* ancillary data buffer len */
4655 msg.msg_flags = 0; /* flags on received message */
4658 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4663 buf = msg.msg_iov[0].iov_base;
4664 len = msg.msg_iov[0].iov_len;
4666 ret = libc_write(s, buf, len);
4668 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4673 ssize_t write(int s, const void *buf, size_t len)
4675 return swrap_write(s, buf, len);
4678 /****************************************************************************
4680 ***************************************************************************/
4682 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4686 struct sockaddr_un un_addr;
4689 struct socket_info *si = find_socket_info(s);
4692 return libc_send(s, buf, len, flags);
4695 tmp.iov_base = discard_const_p(char, buf);
4699 msg.msg_name = NULL; /* optional address */
4700 msg.msg_namelen = 0; /* size of address */
4701 msg.msg_iov = &tmp; /* scatter/gather array */
4702 msg.msg_iovlen = 1; /* # elements in msg_iov */
4703 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4704 msg.msg_control = NULL; /* ancillary data, see below */
4705 msg.msg_controllen = 0; /* ancillary data buffer len */
4706 msg.msg_flags = 0; /* flags on received message */
4709 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4714 buf = msg.msg_iov[0].iov_base;
4715 len = msg.msg_iov[0].iov_len;
4717 ret = libc_send(s, buf, len, flags);
4719 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4724 ssize_t send(int s, const void *buf, size_t len, int flags)
4726 return swrap_send(s, buf, len, flags);
4729 /****************************************************************************
4731 ***************************************************************************/
4733 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4735 struct swrap_address from_addr = {
4736 .sa_socklen = sizeof(struct sockaddr_un),
4738 struct swrap_address convert_addr = {
4739 .sa_socklen = sizeof(struct sockaddr_storage),
4741 struct socket_info *si;
4744 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4745 size_t msg_ctrllen_filled;
4746 size_t msg_ctrllen_left;
4752 si = find_socket_info(s);
4754 return libc_recvmsg(s, omsg, flags);
4757 tmp.iov_base = NULL;
4761 msg.msg_name = &from_addr.sa; /* optional address */
4762 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4763 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4764 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4765 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4766 msg_ctrllen_filled = 0;
4767 msg_ctrllen_left = omsg->msg_controllen;
4769 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4770 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4771 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4774 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4779 ret = libc_recvmsg(s, &msg, flags);
4781 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4782 msg_ctrllen_filled += msg.msg_controllen;
4783 msg_ctrllen_left -= msg.msg_controllen;
4785 if (omsg->msg_control != NULL) {
4788 p = omsg->msg_control;
4789 p += msg_ctrllen_filled;
4791 msg.msg_control = p;
4792 msg.msg_controllen = msg_ctrllen_left;
4794 msg.msg_control = NULL;
4795 msg.msg_controllen = 0;
4800 * We convert the unix address to a IP address so we need a buffer
4801 * which can store the address in case of SOCK_DGRAM, see below.
4803 msg.msg_name = &convert_addr.sa;
4804 msg.msg_namelen = convert_addr.sa_socklen;
4806 rc = swrap_recvmsg_after(s,
4810 from_addr.sa_socklen,
4816 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4817 if (omsg->msg_control != NULL) {
4818 /* msg.msg_controllen = space left */
4819 msg_ctrllen_left = msg.msg_controllen;
4820 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4823 /* Update the original message length */
4824 omsg->msg_controllen = msg_ctrllen_filled;
4825 omsg->msg_flags = msg.msg_flags;
4827 omsg->msg_iovlen = msg.msg_iovlen;
4832 * The msg_name field points to a caller-allocated buffer that is
4833 * used to return the source address if the socket is unconnected. The
4834 * caller should set msg_namelen to the size of this buffer before this
4835 * call; upon return from a successful call, msg_name will contain the
4836 * length of the returned address. If the application does not need
4837 * to know the source address, msg_name can be specified as NULL.
4839 if (si->type == SOCK_STREAM) {
4840 omsg->msg_namelen = 0;
4841 } else if (omsg->msg_name != NULL &&
4842 omsg->msg_namelen != 0 &&
4843 omsg->msg_namelen >= msg.msg_namelen) {
4844 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
4845 omsg->msg_namelen = msg.msg_namelen;
4851 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4853 return swrap_recvmsg(sockfd, msg, flags);
4856 /****************************************************************************
4858 ***************************************************************************/
4860 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4864 struct sockaddr_un un_addr;
4865 const struct sockaddr_un *to_un = NULL;
4866 const struct sockaddr *to = NULL;
4869 struct socket_info *si = find_socket_info(s);
4873 return libc_sendmsg(s, omsg, flags);
4876 ZERO_STRUCT(un_addr);
4878 tmp.iov_base = NULL;
4883 if (si->connected == 0) {
4884 msg.msg_name = omsg->msg_name; /* optional address */
4885 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4887 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4888 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4889 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4890 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4891 /* omsg is a const so use a local buffer for modifications */
4892 uint8_t cmbuf[omsg->msg_controllen];
4894 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4896 msg.msg_control = cmbuf; /* ancillary data, see below */
4897 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4899 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4902 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4910 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4918 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4919 avail += msg.msg_iov[i].iov_len;
4925 /* we capture it as one single packet */
4926 buf = (uint8_t *)malloc(remain);
4931 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4932 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4934 msg.msg_iov[i].iov_base,
4937 remain -= this_time;
4940 type = SOCKET_TYPE_CHAR_UDP;
4942 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4943 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4944 socket_wrapper_dir(), type, iface, prt);
4945 if (stat(un_addr.sun_path, &st) != 0) continue;
4947 msg.msg_name = &un_addr; /* optional address */
4948 msg.msg_namelen = sizeof(un_addr); /* size of address */
4950 /* ignore the any errors in broadcast sends */
4951 libc_sendmsg(s, &msg, flags);
4954 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4960 ret = libc_sendmsg(s, &msg, flags);
4962 swrap_sendmsg_after(s, si, &msg, to, ret);
4967 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4969 return swrap_sendmsg(s, omsg, flags);
4972 /****************************************************************************
4974 ***************************************************************************/
4976 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4978 struct socket_info *si;
4981 struct swrap_address saddr = {
4982 .sa_socklen = sizeof(struct sockaddr_storage)
4987 si = find_socket_info(s);
4989 return libc_readv(s, vector, count);
4992 tmp.iov_base = NULL;
4996 msg.msg_name = &saddr.sa.s; /* optional address */
4997 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4998 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4999 msg.msg_iovlen = count; /* # elements in msg_iov */
5000 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5001 msg.msg_control = NULL; /* ancillary data, see below */
5002 msg.msg_controllen = 0; /* ancillary data buffer len */
5003 msg.msg_flags = 0; /* flags on received message */
5006 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5008 if (rc == -ENOTSOCK) {
5009 return libc_readv(s, vector, count);
5014 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5016 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5024 ssize_t readv(int s, const struct iovec *vector, int count)
5026 return swrap_readv(s, vector, count);
5029 /****************************************************************************
5031 ***************************************************************************/
5033 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5037 struct sockaddr_un un_addr;
5040 struct socket_info *si = find_socket_info(s);
5043 return libc_writev(s, vector, count);
5046 tmp.iov_base = NULL;
5050 msg.msg_name = NULL; /* optional address */
5051 msg.msg_namelen = 0; /* size of address */
5052 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5053 msg.msg_iovlen = count; /* # elements in msg_iov */
5054 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5055 msg.msg_control = NULL; /* ancillary data, see below */
5056 msg.msg_controllen = 0; /* ancillary data buffer len */
5057 msg.msg_flags = 0; /* flags on received message */
5060 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5062 if (rc == -ENOTSOCK) {
5063 return libc_readv(s, vector, count);
5068 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5070 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5075 ssize_t writev(int s, const struct iovec *vector, int count)
5077 return swrap_writev(s, vector, count);
5080 /****************************
5082 ***************************/
5084 static int swrap_close(int fd)
5086 struct socket_info *si = find_socket_info(fd);
5087 struct socket_info_fd *fi;
5091 return libc_close(fd);
5094 for (fi = si->fds; fi; fi = fi->next) {
5096 SWRAP_DLIST_REMOVE(si->fds, fi);
5103 /* there are still references left */
5104 return libc_close(fd);
5107 SWRAP_DLIST_REMOVE(sockets, si);
5109 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5110 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5113 ret = libc_close(fd);
5115 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5116 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5117 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5120 if (si->un_addr.sun_path[0] != '\0') {
5121 unlink(si->un_addr.sun_path);
5130 return swrap_close(fd);
5133 /****************************
5135 ***************************/
5137 static int swrap_dup(int fd)
5139 struct socket_info *si;
5140 struct socket_info_fd *fi;
5142 si = find_socket_info(fd);
5145 return libc_dup(fd);
5148 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5154 fi->fd = libc_dup(fd);
5156 int saved_errno = errno;
5158 errno = saved_errno;
5162 /* Make sure we don't have an entry for the fd */
5163 swrap_remove_stale(fi->fd);
5165 SWRAP_DLIST_ADD(si->fds, fi);
5171 return swrap_dup(fd);
5174 /****************************
5176 ***************************/
5178 static int swrap_dup2(int fd, int newfd)
5180 struct socket_info *si;
5181 struct socket_info_fd *fi;
5183 si = find_socket_info(fd);
5186 return libc_dup2(fd, newfd);
5191 * According to the manpage:
5193 * "If oldfd is a valid file descriptor, and newfd has the same
5194 * value as oldfd, then dup2() does nothing, and returns newfd."
5199 if (find_socket_info(newfd)) {
5200 /* dup2() does an implicit close of newfd, which we
5201 * need to emulate */
5205 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5211 fi->fd = libc_dup2(fd, newfd);
5213 int saved_errno = errno;
5215 errno = saved_errno;
5219 /* Make sure we don't have an entry for the fd */
5220 swrap_remove_stale(fi->fd);
5222 SWRAP_DLIST_ADD(si->fds, fi);
5226 int dup2(int fd, int newfd)
5228 return swrap_dup2(fd, newfd);
5231 /****************************
5233 ***************************/
5235 static int swrap_vfcntl(int fd, int cmd, va_list va)
5237 struct socket_info_fd *fi;
5238 struct socket_info *si;
5241 si = find_socket_info(fd);
5243 rc = libc_vfcntl(fd, cmd, va);
5250 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5256 fi->fd = libc_vfcntl(fd, cmd, va);
5258 int saved_errno = errno;
5260 errno = saved_errno;
5264 /* Make sure we don't have an entry for the fd */
5265 swrap_remove_stale(fi->fd);
5267 SWRAP_DLIST_ADD(si->fds, fi);
5272 rc = libc_vfcntl(fd, cmd, va);
5279 int fcntl(int fd, int cmd, ...)
5286 rc = swrap_vfcntl(fd, cmd, va);
5293 /****************************
5295 ***************************/
5298 static int swrap_eventfd(int count, int flags)
5302 fd = libc_eventfd(count, flags);
5304 swrap_remove_stale(fd);
5310 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5311 int eventfd(unsigned int count, int flags)
5313 int eventfd(int count, int flags)
5316 return swrap_eventfd(count, flags);
5321 int pledge(const char *promises, const char *paths[])
5323 (void)promises; /* unused */
5324 (void)paths; /* unused */
5328 #endif /* HAVE_PLEDGE */
5330 /****************************
5332 ***************************/
5335 * This function is called when the library is unloaded and makes sure that
5336 * sockets get closed and the unix file for the socket are unlinked.
5338 void swrap_destructor(void)
5340 struct socket_info *s = sockets;
5343 struct socket_info_fd *f = s->fds;
5350 if (swrap.libc_handle != NULL) {
5351 dlclose(swrap.libc_handle);
5353 if (swrap.libsocket_handle) {
5354 dlclose(swrap.libsocket_handle);