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 {
338 int (*libc_accept)(int sockfd,
339 struct sockaddr *addr,
341 int (*libc_bind)(int sockfd,
342 const struct sockaddr *addr,
344 int (*libc_close)(int fd);
345 int (*libc_connect)(int sockfd,
346 const struct sockaddr *addr,
348 int (*libc_dup)(int fd);
349 int (*libc_dup2)(int oldfd, int newfd);
350 int (*libc_fcntl)(int fd, int cmd, ...);
351 FILE *(*libc_fopen)(const char *name, const char *mode);
353 int (*libc_eventfd)(int count, int flags);
355 int (*libc_getpeername)(int sockfd,
356 struct sockaddr *addr,
358 int (*libc_getsockname)(int sockfd,
359 struct sockaddr *addr,
361 int (*libc_getsockopt)(int sockfd,
366 int (*libc_ioctl)(int d, unsigned long int request, ...);
367 int (*libc_listen)(int sockfd, int backlog);
368 int (*libc_open)(const char *pathname, int flags, mode_t mode);
369 int (*libc_pipe)(int pipefd[2]);
370 int (*libc_read)(int fd, void *buf, size_t count);
371 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
372 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
373 int (*libc_recvfrom)(int sockfd,
377 struct sockaddr *src_addr,
379 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
380 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
381 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
382 int (*libc_sendto)(int sockfd,
386 const struct sockaddr *dst_addr,
388 int (*libc_setsockopt)(int sockfd,
394 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
396 int (*libc_socket)(int domain, int type, int protocol);
397 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
398 #ifdef HAVE_TIMERFD_CREATE
399 int (*libc_timerfd_create)(int clockid, int flags);
401 ssize_t (*libc_write)(int fd, const void *buf, size_t count);
402 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
407 void *libsocket_handle;
414 struct swrap_libc_fns fns;
417 static struct swrap swrap;
420 static const char *socket_wrapper_dir(void);
422 #define LIBC_NAME "libc.so"
431 static const char *swrap_str_lib(enum swrap_lib lib)
438 case SWRAP_LIBSOCKET:
442 /* Compiler would warn us about unhandled enum value if we get here */
447 static void *swrap_load_lib_handle(enum swrap_lib lib)
449 int flags = RTLD_LAZY;
454 flags |= RTLD_DEEPBIND;
460 case SWRAP_LIBSOCKET:
461 #ifdef HAVE_LIBSOCKET
462 handle = swrap.libsocket_handle;
463 if (handle == NULL) {
464 for (i = 10; i >= 0; i--) {
465 char soname[256] = {0};
467 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
468 handle = dlopen(soname, flags);
469 if (handle != NULL) {
474 swrap.libsocket_handle = handle;
480 handle = swrap.libc_handle;
482 if (handle == NULL) {
483 handle = dlopen(LIBC_SO, flags);
485 swrap.libc_handle = handle;
488 if (handle == NULL) {
489 for (i = 10; i >= 0; i--) {
490 char soname[256] = {0};
492 snprintf(soname, sizeof(soname), "libc.so.%d", i);
493 handle = dlopen(soname, flags);
494 if (handle != NULL) {
499 swrap.libc_handle = handle;
504 if (handle == NULL) {
506 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
508 SWRAP_LOG(SWRAP_LOG_ERROR,
509 "Failed to dlopen library: %s\n",
518 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
523 handle = swrap_load_lib_handle(lib);
525 func = dlsym(handle, fn_name);
527 SWRAP_LOG(SWRAP_LOG_ERROR,
528 "Failed to find %s: %s\n",
533 SWRAP_LOG(SWRAP_LOG_TRACE,
535 fn_name, swrap_str_lib(lib));
539 #define swrap_load_lib_function(lib, fn_name) \
540 if (swrap.fns.libc_##fn_name == NULL) { \
541 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
542 *(void **) (&swrap.fns.libc_##fn_name) = \
550 * Functions especially from libc need to be loaded individually, you can't load
551 * all at once or gdb will segfault at startup. The same applies to valgrind and
552 * has probably something todo with with the linker.
553 * So we need load each function at the point it is called the first time.
555 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
557 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
559 return swrap.fns.libc_accept(sockfd, addr, addrlen);
562 static int libc_bind(int sockfd,
563 const struct sockaddr *addr,
566 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
568 return swrap.fns.libc_bind(sockfd, addr, addrlen);
571 static int libc_close(int fd)
573 swrap_load_lib_function(SWRAP_LIBC, close);
575 return swrap.fns.libc_close(fd);
578 static int libc_connect(int sockfd,
579 const struct sockaddr *addr,
582 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
584 return swrap.fns.libc_connect(sockfd, addr, addrlen);
587 static int libc_dup(int fd)
589 swrap_load_lib_function(SWRAP_LIBC, dup);
591 return swrap.fns.libc_dup(fd);
594 static int libc_dup2(int oldfd, int newfd)
596 swrap_load_lib_function(SWRAP_LIBC, dup2);
598 return swrap.fns.libc_dup2(oldfd, newfd);
602 static int libc_eventfd(int count, int flags)
604 swrap_load_lib_function(SWRAP_LIBC, eventfd);
606 return swrap.fns.libc_eventfd(count, flags);
610 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
611 static int libc_vfcntl(int fd, int cmd, va_list ap)
617 swrap_load_lib_function(SWRAP_LIBC, fcntl);
619 for (i = 0; i < 4; i++) {
620 args[i] = va_arg(ap, long int);
623 rc = swrap.fns.libc_fcntl(fd,
633 static int libc_getpeername(int sockfd,
634 struct sockaddr *addr,
637 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
639 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
642 static int libc_getsockname(int sockfd,
643 struct sockaddr *addr,
646 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
648 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
651 static int libc_getsockopt(int sockfd,
657 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
659 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
662 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
663 static int libc_vioctl(int d, unsigned long int request, va_list ap)
669 swrap_load_lib_function(SWRAP_LIBC, ioctl);
671 for (i = 0; i < 4; i++) {
672 args[i] = va_arg(ap, long int);
675 rc = swrap.fns.libc_ioctl(d,
685 static int libc_listen(int sockfd, int backlog)
687 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
689 return swrap.fns.libc_listen(sockfd, backlog);
692 static FILE *libc_fopen(const char *name, const char *mode)
694 swrap_load_lib_function(SWRAP_LIBC, fopen);
696 return swrap.fns.libc_fopen(name, mode);
699 static int libc_vopen(const char *pathname, int flags, va_list ap)
704 swrap_load_lib_function(SWRAP_LIBC, open);
706 mode = va_arg(ap, long int);
708 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
713 static int libc_open(const char *pathname, int flags, ...)
719 fd = libc_vopen(pathname, flags, ap);
725 static int libc_pipe(int pipefd[2])
727 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
729 return swrap.fns.libc_pipe(pipefd);
732 static int libc_read(int fd, void *buf, size_t count)
734 swrap_load_lib_function(SWRAP_LIBC, read);
736 return swrap.fns.libc_read(fd, buf, count);
739 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
741 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
743 return swrap.fns.libc_readv(fd, iov, iovcnt);
746 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
748 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
750 return swrap.fns.libc_recv(sockfd, buf, len, flags);
753 static int libc_recvfrom(int sockfd,
757 struct sockaddr *src_addr,
760 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
762 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
765 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
767 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
769 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
772 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
774 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
776 return swrap.fns.libc_send(sockfd, buf, len, flags);
779 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
781 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
783 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
786 static int libc_sendto(int sockfd,
790 const struct sockaddr *dst_addr,
793 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
795 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
798 static int libc_setsockopt(int sockfd,
804 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
806 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
810 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
812 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
814 return swrap.fns.libc_signalfd(fd, mask, flags);
818 static int libc_socket(int domain, int type, int protocol)
820 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
822 return swrap.fns.libc_socket(domain, type, protocol);
825 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
827 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
829 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
832 #ifdef HAVE_TIMERFD_CREATE
833 static int libc_timerfd_create(int clockid, int flags)
835 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
837 return swrap.fns.libc_timerfd_create(clockid, flags);
841 static ssize_t libc_write(int fd, const void *buf, size_t count)
843 swrap_load_lib_function(SWRAP_LIBC, write);
845 return swrap.fns.libc_write(fd, buf, count);
848 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
850 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
852 return swrap.fns.libc_writev(fd, iov, iovcnt);
855 /*********************************************************
856 * SWRAP HELPER FUNCTIONS
857 *********************************************************/
863 static const struct in6_addr *swrap_ipv6(void)
865 static struct in6_addr v;
866 static int initialized;
874 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
883 static void set_port(int family, int prt, struct swrap_address *addr)
887 addr->sa.in.sin_port = htons(prt);
891 addr->sa.in6.sin6_port = htons(prt);
897 static size_t socket_length(int family)
901 return sizeof(struct sockaddr_in);
904 return sizeof(struct sockaddr_in6);
910 static const char *socket_wrapper_dir(void)
912 const char *s = getenv("SOCKET_WRAPPER_DIR");
916 /* TODO use realpath(3) here, when we add support for threads */
917 if (strncmp(s, "./", 2) == 0) {
921 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
925 static unsigned int socket_wrapper_mtu(void)
927 static unsigned int max_mtu = 0;
936 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
938 s = getenv("SOCKET_WRAPPER_MTU");
943 tmp = strtol(s, &endp, 10);
948 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
957 bool socket_wrapper_enabled(void)
959 const char *s = socket_wrapper_dir();
961 return s != NULL ? true : false;
964 static unsigned int socket_wrapper_default_iface(void)
966 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
969 if (sscanf(s, "%u", &iface) == 1) {
970 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
976 return 1;/* 127.0.0.1 */
979 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
986 p = strrchr(un->sun_path, '/');
987 if (p) p++; else p = un->sun_path;
989 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
994 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
997 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1008 case SOCKET_TYPE_CHAR_TCP:
1009 case SOCKET_TYPE_CHAR_UDP: {
1010 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1012 if ((*len) < sizeof(*in2)) {
1017 memset(in2, 0, sizeof(*in2));
1018 in2->sin_family = AF_INET;
1019 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1020 in2->sin_port = htons(prt);
1022 *len = sizeof(*in2);
1026 case SOCKET_TYPE_CHAR_TCP_V6:
1027 case SOCKET_TYPE_CHAR_UDP_V6: {
1028 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1030 if ((*len) < sizeof(*in2)) {
1035 memset(in2, 0, sizeof(*in2));
1036 in2->sin6_family = AF_INET6;
1037 in2->sin6_addr = *swrap_ipv6();
1038 in2->sin6_addr.s6_addr[15] = iface;
1039 in2->sin6_port = htons(prt);
1041 *len = sizeof(*in2);
1053 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1061 if (bcast) *bcast = 0;
1063 switch (inaddr->sa_family) {
1065 const struct sockaddr_in *in =
1066 (const struct sockaddr_in *)(const void *)inaddr;
1067 unsigned int addr = ntohl(in->sin_addr.s_addr);
1074 u_type = SOCKET_TYPE_CHAR_TCP;
1077 u_type = SOCKET_TYPE_CHAR_UDP;
1078 a_type = SOCKET_TYPE_CHAR_UDP;
1079 b_type = SOCKET_TYPE_CHAR_UDP;
1082 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1083 errno = ESOCKTNOSUPPORT;
1087 prt = ntohs(in->sin_port);
1088 if (a_type && addr == 0xFFFFFFFF) {
1089 /* 255.255.255.255 only udp */
1092 iface = socket_wrapper_default_iface();
1093 } else if (b_type && addr == 0x7FFFFFFF) {
1094 /* 127.255.255.255 only udp */
1097 iface = socket_wrapper_default_iface();
1098 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1102 iface = (addr & 0x000000FF);
1104 errno = ENETUNREACH;
1107 if (bcast) *bcast = is_bcast;
1112 const struct sockaddr_in6 *in =
1113 (const struct sockaddr_in6 *)(const void *)inaddr;
1114 struct in6_addr cmp1, cmp2;
1118 type = SOCKET_TYPE_CHAR_TCP_V6;
1121 type = SOCKET_TYPE_CHAR_UDP_V6;
1124 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1125 errno = ESOCKTNOSUPPORT;
1129 /* XXX no multicast/broadcast */
1131 prt = ntohs(in->sin6_port);
1133 cmp1 = *swrap_ipv6();
1134 cmp2 = in->sin6_addr;
1135 cmp2.s6_addr[15] = 0;
1136 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1137 iface = in->sin6_addr.s6_addr[15];
1139 errno = ENETUNREACH;
1147 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1148 errno = ENETUNREACH;
1153 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1159 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1160 socket_wrapper_dir());
1161 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1162 /* the caller need to do more processing */
1166 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1167 socket_wrapper_dir(), type, iface, prt);
1168 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1173 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1182 if (bcast) *bcast = 0;
1184 switch (si->family) {
1186 const struct sockaddr_in *in =
1187 (const struct sockaddr_in *)(const void *)inaddr;
1188 unsigned int addr = ntohl(in->sin_addr.s_addr);
1194 prt = ntohs(in->sin_port);
1198 u_type = SOCKET_TYPE_CHAR_TCP;
1199 d_type = SOCKET_TYPE_CHAR_TCP;
1202 u_type = SOCKET_TYPE_CHAR_UDP;
1203 d_type = SOCKET_TYPE_CHAR_UDP;
1204 a_type = SOCKET_TYPE_CHAR_UDP;
1205 b_type = SOCKET_TYPE_CHAR_UDP;
1208 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1209 errno = ESOCKTNOSUPPORT;
1217 iface = socket_wrapper_default_iface();
1218 } else if (a_type && addr == 0xFFFFFFFF) {
1219 /* 255.255.255.255 only udp */
1222 iface = socket_wrapper_default_iface();
1223 } else if (b_type && addr == 0x7FFFFFFF) {
1224 /* 127.255.255.255 only udp */
1227 iface = socket_wrapper_default_iface();
1228 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1232 iface = (addr & 0x000000FF);
1234 errno = EADDRNOTAVAIL;
1238 /* Store the bind address for connect() */
1239 if (si->bindname.sa_socklen == 0) {
1240 struct sockaddr_in bind_in;
1241 socklen_t blen = sizeof(struct sockaddr_in);
1243 ZERO_STRUCT(bind_in);
1244 bind_in.sin_family = in->sin_family;
1245 bind_in.sin_port = in->sin_port;
1246 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1248 si->bindname.sa_socklen = blen;
1249 memcpy(&si->bindname.sa.in, &bind_in, blen);
1256 const struct sockaddr_in6 *in =
1257 (const struct sockaddr_in6 *)(const void *)inaddr;
1258 struct in6_addr cmp1, cmp2;
1262 type = SOCKET_TYPE_CHAR_TCP_V6;
1265 type = SOCKET_TYPE_CHAR_UDP_V6;
1268 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1269 errno = ESOCKTNOSUPPORT;
1273 /* XXX no multicast/broadcast */
1275 prt = ntohs(in->sin6_port);
1277 cmp1 = *swrap_ipv6();
1278 cmp2 = in->sin6_addr;
1279 cmp2.s6_addr[15] = 0;
1280 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1281 iface = socket_wrapper_default_iface();
1282 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1283 iface = in->sin6_addr.s6_addr[15];
1285 errno = EADDRNOTAVAIL;
1289 /* Store the bind address for connect() */
1290 if (si->bindname.sa_socklen == 0) {
1291 struct sockaddr_in6 bind_in;
1292 socklen_t blen = sizeof(struct sockaddr_in6);
1294 ZERO_STRUCT(bind_in);
1295 bind_in.sin6_family = in->sin6_family;
1296 bind_in.sin6_port = in->sin6_port;
1298 bind_in.sin6_addr = *swrap_ipv6();
1299 bind_in.sin6_addr.s6_addr[15] = iface;
1301 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1302 si->bindname.sa_socklen = blen;
1309 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1310 errno = EADDRNOTAVAIL;
1315 if (bcast) *bcast = is_bcast;
1317 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1323 /* handle auto-allocation of ephemeral ports */
1324 for (prt = 5001; prt < 10000; prt++) {
1325 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1326 socket_wrapper_dir(), type, iface, prt);
1327 if (stat(un->sun_path, &st) == 0) continue;
1329 set_port(si->family, prt, &si->myname);
1330 set_port(si->family, prt, &si->bindname);
1340 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1341 socket_wrapper_dir(), type, iface, prt);
1342 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1346 static struct socket_info *find_socket_info(int fd)
1348 struct socket_info *i;
1350 for (i = sockets; i; i = i->next) {
1351 struct socket_info_fd *f;
1352 for (f = i->fds; f; f = f->next) {
1363 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1365 struct socket_info *s;
1367 /* first catch invalid input */
1368 switch (sa->sa_family) {
1370 if (len < sizeof(struct sockaddr_in)) {
1376 if (len < sizeof(struct sockaddr_in6)) {
1386 for (s = sockets; s != NULL; s = s->next) {
1387 if (s->myname == NULL) {
1390 if (s->myname->sa_family != sa->sa_family) {
1393 switch (s->myname->sa_family) {
1395 struct sockaddr_in *sin1, *sin2;
1397 sin1 = (struct sockaddr_in *)s->myname;
1398 sin2 = (struct sockaddr_in *)sa;
1400 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1403 if (sin1->sin_port != sin2->sin_port) {
1406 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1416 struct sockaddr_in6 *sin1, *sin2;
1418 sin1 = (struct sockaddr_in6 *)s->myname;
1419 sin2 = (struct sockaddr_in6 *)sa;
1421 if (sin1->sin6_port != sin2->sin6_port) {
1424 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1446 static void swrap_remove_stale(int fd)
1448 struct socket_info *si = find_socket_info(fd);
1449 struct socket_info_fd *fi;
1452 for (fi = si->fds; fi; fi = fi->next) {
1454 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1455 SWRAP_DLIST_REMOVE(si->fds, fi);
1461 if (si->fds == NULL) {
1462 SWRAP_DLIST_REMOVE(sockets, si);
1463 if (si->un_addr.sun_path[0] != '\0') {
1464 unlink(si->un_addr.sun_path);
1471 static int sockaddr_convert_to_un(struct socket_info *si,
1472 const struct sockaddr *in_addr,
1474 struct sockaddr_un *out_addr,
1478 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1480 (void) in_len; /* unused */
1482 if (out_addr == NULL) {
1486 out->sa_family = AF_UNIX;
1487 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1488 out->sa_len = sizeof(*out_addr);
1491 switch (in_addr->sa_family) {
1493 const struct sockaddr_in *sin;
1494 if (si->family != AF_INET) {
1497 if (in_len < sizeof(struct sockaddr_in)) {
1500 sin = (const struct sockaddr_in *)(const void *)in_addr;
1501 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1506 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1507 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1521 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1522 errno = ESOCKTNOSUPPORT;
1526 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1528 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1534 errno = EAFNOSUPPORT;
1535 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1539 static int sockaddr_convert_from_un(const struct socket_info *si,
1540 const struct sockaddr_un *in_addr,
1541 socklen_t un_addrlen,
1543 struct sockaddr *out_addr,
1544 socklen_t *out_addrlen)
1548 if (out_addr == NULL || out_addrlen == NULL)
1551 if (un_addrlen == 0) {
1566 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1567 errno = ESOCKTNOSUPPORT;
1570 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1571 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1572 out_addr->sa_len = *out_addrlen;
1579 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1580 errno = EAFNOSUPPORT;
1584 enum swrap_packet_type {
1586 SWRAP_CONNECT_UNREACH,
1594 SWRAP_SENDTO_UNREACH,
1605 struct swrap_file_hdr {
1607 uint16_t version_major;
1608 uint16_t version_minor;
1611 uint32_t frame_max_len;
1612 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1615 #define SWRAP_FILE_HDR_SIZE 24
1617 struct swrap_packet_frame {
1619 uint32_t micro_seconds;
1620 uint32_t recorded_length;
1621 uint32_t full_length;
1623 #define SWRAP_PACKET_FRAME_SIZE 16
1625 union swrap_packet_ip {
1629 uint16_t packet_length;
1630 uint16_t identification;
1635 uint16_t hdr_checksum;
1639 #define SWRAP_PACKET_IP_V4_SIZE 20
1642 uint8_t flow_label_high;
1643 uint16_t flow_label_low;
1644 uint16_t payload_length;
1645 uint8_t next_header;
1647 uint8_t src_addr[16];
1648 uint8_t dest_addr[16];
1650 #define SWRAP_PACKET_IP_V6_SIZE 40
1652 #define SWRAP_PACKET_IP_SIZE 40
1654 union swrap_packet_payload {
1656 uint16_t source_port;
1666 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1668 uint16_t source_port;
1673 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1680 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1687 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1689 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1691 #define SWRAP_PACKET_MIN_ALLOC \
1692 (SWRAP_PACKET_FRAME_SIZE + \
1693 SWRAP_PACKET_IP_SIZE + \
1694 SWRAP_PACKET_PAYLOAD_SIZE)
1696 static const char *swrap_pcap_init_file(void)
1698 static int initialized = 0;
1699 static const char *s = NULL;
1700 static const struct swrap_file_hdr h;
1701 static const struct swrap_packet_frame f;
1702 static const union swrap_packet_ip i;
1703 static const union swrap_packet_payload p;
1705 if (initialized == 1) {
1711 * TODO: don't use the structs use plain buffer offsets
1712 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1714 * for now make sure we disable PCAP support
1715 * if the struct has alignment!
1717 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1720 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1723 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1726 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1729 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1732 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1735 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1738 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1741 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1744 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1748 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1752 if (strncmp(s, "./", 2) == 0) {
1758 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1759 const struct sockaddr *src,
1760 const struct sockaddr *dest,
1762 const uint8_t *payload,
1764 unsigned long tcp_seqno,
1765 unsigned long tcp_ack,
1766 unsigned char tcp_ctl,
1768 size_t *_packet_len)
1772 struct swrap_packet_frame *frame;
1773 union swrap_packet_ip *ip;
1774 union swrap_packet_payload *pay;
1777 size_t nonwire_len = sizeof(*frame);
1778 size_t wire_hdr_len = 0;
1779 size_t wire_len = 0;
1780 size_t ip_hdr_len = 0;
1781 size_t icmp_hdr_len = 0;
1782 size_t icmp_truncate_len = 0;
1783 uint8_t protocol = 0, icmp_protocol = 0;
1784 const struct sockaddr_in *src_in = NULL;
1785 const struct sockaddr_in *dest_in = NULL;
1787 const struct sockaddr_in6 *src_in6 = NULL;
1788 const struct sockaddr_in6 *dest_in6 = NULL;
1793 switch (src->sa_family) {
1795 src_in = (const struct sockaddr_in *)(const void *)src;
1796 dest_in = (const struct sockaddr_in *)(const void *)dest;
1797 src_port = src_in->sin_port;
1798 dest_port = dest_in->sin_port;
1799 ip_hdr_len = sizeof(ip->v4);
1803 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1804 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1805 src_port = src_in6->sin6_port;
1806 dest_port = dest_in6->sin6_port;
1807 ip_hdr_len = sizeof(ip->v6);
1814 switch (socket_type) {
1816 protocol = 0x06; /* TCP */
1817 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1818 wire_len = wire_hdr_len + payload_len;
1822 protocol = 0x11; /* UDP */
1823 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1824 wire_len = wire_hdr_len + payload_len;
1832 icmp_protocol = protocol;
1833 switch (src->sa_family) {
1835 protocol = 0x01; /* ICMPv4 */
1836 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1840 protocol = 0x3A; /* ICMPv6 */
1841 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1845 if (wire_len > 64 ) {
1846 icmp_truncate_len = wire_len - 64;
1848 wire_hdr_len += icmp_hdr_len;
1849 wire_len += icmp_hdr_len;
1852 packet_len = nonwire_len + wire_len;
1853 alloc_len = packet_len;
1854 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1855 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1858 base = (uint8_t *)calloc(1, alloc_len);
1865 frame = (struct swrap_packet_frame *)(void *)buf;
1866 frame->seconds = tval->tv_sec;
1867 frame->micro_seconds = tval->tv_usec;
1868 frame->recorded_length = wire_len - icmp_truncate_len;
1869 frame->full_length = wire_len - icmp_truncate_len;
1870 buf += SWRAP_PACKET_FRAME_SIZE;
1872 ip = (union swrap_packet_ip *)(void *)buf;
1873 switch (src->sa_family) {
1875 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1877 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1878 ip->v4.identification = htons(0xFFFF);
1879 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1880 ip->v4.fragment = htons(0x0000);
1882 ip->v4.protocol = protocol;
1883 ip->v4.hdr_checksum = htons(0x0000);
1884 ip->v4.src_addr = src_in->sin_addr.s_addr;
1885 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1886 buf += SWRAP_PACKET_IP_V4_SIZE;
1890 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1891 ip->v6.flow_label_high = 0x00;
1892 ip->v6.flow_label_low = 0x0000;
1893 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1894 ip->v6.next_header = protocol;
1895 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1896 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1897 buf += SWRAP_PACKET_IP_V6_SIZE;
1903 pay = (union swrap_packet_payload *)(void *)buf;
1904 switch (src->sa_family) {
1906 pay->icmp4.type = 0x03; /* destination unreachable */
1907 pay->icmp4.code = 0x01; /* host unreachable */
1908 pay->icmp4.checksum = htons(0x0000);
1909 pay->icmp4.unused = htonl(0x00000000);
1910 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1912 /* set the ip header in the ICMP payload */
1913 ip = (union swrap_packet_ip *)(void *)buf;
1914 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1916 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1917 ip->v4.identification = htons(0xFFFF);
1918 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1919 ip->v4.fragment = htons(0x0000);
1921 ip->v4.protocol = icmp_protocol;
1922 ip->v4.hdr_checksum = htons(0x0000);
1923 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1924 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1925 buf += SWRAP_PACKET_IP_V4_SIZE;
1927 src_port = dest_in->sin_port;
1928 dest_port = src_in->sin_port;
1932 pay->icmp6.type = 0x01; /* destination unreachable */
1933 pay->icmp6.code = 0x03; /* address unreachable */
1934 pay->icmp6.checksum = htons(0x0000);
1935 pay->icmp6.unused = htonl(0x00000000);
1936 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1938 /* set the ip header in the ICMP payload */
1939 ip = (union swrap_packet_ip *)(void *)buf;
1940 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1941 ip->v6.flow_label_high = 0x00;
1942 ip->v6.flow_label_low = 0x0000;
1943 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1944 ip->v6.next_header = protocol;
1945 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1946 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1947 buf += SWRAP_PACKET_IP_V6_SIZE;
1949 src_port = dest_in6->sin6_port;
1950 dest_port = src_in6->sin6_port;
1956 pay = (union swrap_packet_payload *)(void *)buf;
1958 switch (socket_type) {
1960 pay->tcp.source_port = src_port;
1961 pay->tcp.dest_port = dest_port;
1962 pay->tcp.seq_num = htonl(tcp_seqno);
1963 pay->tcp.ack_num = htonl(tcp_ack);
1964 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1965 pay->tcp.control = tcp_ctl;
1966 pay->tcp.window = htons(0x7FFF);
1967 pay->tcp.checksum = htons(0x0000);
1968 pay->tcp.urg = htons(0x0000);
1969 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1974 pay->udp.source_port = src_port;
1975 pay->udp.dest_port = dest_port;
1976 pay->udp.length = htons(8 + payload_len);
1977 pay->udp.checksum = htons(0x0000);
1978 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1983 if (payload && payload_len > 0) {
1984 memcpy(buf, payload, payload_len);
1987 *_packet_len = packet_len - icmp_truncate_len;
1991 static int swrap_pcap_get_fd(const char *fname)
1995 if (fd != -1) return fd;
1997 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1999 struct swrap_file_hdr file_hdr;
2000 file_hdr.magic = 0xA1B2C3D4;
2001 file_hdr.version_major = 0x0002;
2002 file_hdr.version_minor = 0x0004;
2003 file_hdr.timezone = 0x00000000;
2004 file_hdr.sigfigs = 0x00000000;
2005 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2006 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2008 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2015 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2020 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2021 const struct sockaddr *addr,
2022 enum swrap_packet_type type,
2023 const void *buf, size_t len,
2026 const struct sockaddr *src_addr;
2027 const struct sockaddr *dest_addr;
2028 unsigned long tcp_seqno = 0;
2029 unsigned long tcp_ack = 0;
2030 unsigned char tcp_ctl = 0;
2031 int unreachable = 0;
2035 switch (si->family) {
2047 case SWRAP_CONNECT_SEND:
2048 if (si->type != SOCK_STREAM) return NULL;
2050 src_addr = &si->myname.sa.s;
2053 tcp_seqno = si->io.pck_snd;
2054 tcp_ack = si->io.pck_rcv;
2055 tcp_ctl = 0x02; /* SYN */
2057 si->io.pck_snd += 1;
2061 case SWRAP_CONNECT_RECV:
2062 if (si->type != SOCK_STREAM) return NULL;
2064 dest_addr = &si->myname.sa.s;
2067 tcp_seqno = si->io.pck_rcv;
2068 tcp_ack = si->io.pck_snd;
2069 tcp_ctl = 0x12; /** SYN,ACK */
2071 si->io.pck_rcv += 1;
2075 case SWRAP_CONNECT_UNREACH:
2076 if (si->type != SOCK_STREAM) return NULL;
2078 dest_addr = &si->myname.sa.s;
2081 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2082 tcp_seqno = si->io.pck_snd - 1;
2083 tcp_ack = si->io.pck_rcv;
2084 tcp_ctl = 0x02; /* SYN */
2089 case SWRAP_CONNECT_ACK:
2090 if (si->type != SOCK_STREAM) return NULL;
2092 src_addr = &si->myname.sa.s;
2095 tcp_seqno = si->io.pck_snd;
2096 tcp_ack = si->io.pck_rcv;
2097 tcp_ctl = 0x10; /* ACK */
2101 case SWRAP_ACCEPT_SEND:
2102 if (si->type != SOCK_STREAM) return NULL;
2104 dest_addr = &si->myname.sa.s;
2107 tcp_seqno = si->io.pck_rcv;
2108 tcp_ack = si->io.pck_snd;
2109 tcp_ctl = 0x02; /* SYN */
2111 si->io.pck_rcv += 1;
2115 case SWRAP_ACCEPT_RECV:
2116 if (si->type != SOCK_STREAM) return NULL;
2118 src_addr = &si->myname.sa.s;
2121 tcp_seqno = si->io.pck_snd;
2122 tcp_ack = si->io.pck_rcv;
2123 tcp_ctl = 0x12; /* SYN,ACK */
2125 si->io.pck_snd += 1;
2129 case SWRAP_ACCEPT_ACK:
2130 if (si->type != SOCK_STREAM) return NULL;
2132 dest_addr = &si->myname.sa.s;
2135 tcp_seqno = si->io.pck_rcv;
2136 tcp_ack = si->io.pck_snd;
2137 tcp_ctl = 0x10; /* ACK */
2142 src_addr = &si->myname.sa.s;
2143 dest_addr = &si->peername.sa.s;
2145 tcp_seqno = si->io.pck_snd;
2146 tcp_ack = si->io.pck_rcv;
2147 tcp_ctl = 0x18; /* PSH,ACK */
2149 si->io.pck_snd += len;
2153 case SWRAP_SEND_RST:
2154 dest_addr = &si->myname.sa.s;
2155 src_addr = &si->peername.sa.s;
2157 if (si->type == SOCK_DGRAM) {
2158 return swrap_pcap_marshall_packet(si,
2160 SWRAP_SENDTO_UNREACH,
2166 tcp_seqno = si->io.pck_rcv;
2167 tcp_ack = si->io.pck_snd;
2168 tcp_ctl = 0x14; /** RST,ACK */
2172 case SWRAP_PENDING_RST:
2173 dest_addr = &si->myname.sa.s;
2174 src_addr = &si->peername.sa.s;
2176 if (si->type == SOCK_DGRAM) {
2180 tcp_seqno = si->io.pck_rcv;
2181 tcp_ack = si->io.pck_snd;
2182 tcp_ctl = 0x14; /* RST,ACK */
2187 dest_addr = &si->myname.sa.s;
2188 src_addr = &si->peername.sa.s;
2190 tcp_seqno = si->io.pck_rcv;
2191 tcp_ack = si->io.pck_snd;
2192 tcp_ctl = 0x18; /* PSH,ACK */
2194 si->io.pck_rcv += len;
2198 case SWRAP_RECV_RST:
2199 dest_addr = &si->myname.sa.s;
2200 src_addr = &si->peername.sa.s;
2202 if (si->type == SOCK_DGRAM) {
2206 tcp_seqno = si->io.pck_rcv;
2207 tcp_ack = si->io.pck_snd;
2208 tcp_ctl = 0x14; /* RST,ACK */
2213 src_addr = &si->myname.sa.s;
2216 si->io.pck_snd += len;
2220 case SWRAP_SENDTO_UNREACH:
2221 dest_addr = &si->myname.sa.s;
2228 case SWRAP_RECVFROM:
2229 dest_addr = &si->myname.sa.s;
2232 si->io.pck_rcv += len;
2236 case SWRAP_CLOSE_SEND:
2237 if (si->type != SOCK_STREAM) return NULL;
2239 src_addr = &si->myname.sa.s;
2240 dest_addr = &si->peername.sa.s;
2242 tcp_seqno = si->io.pck_snd;
2243 tcp_ack = si->io.pck_rcv;
2244 tcp_ctl = 0x11; /* FIN, ACK */
2246 si->io.pck_snd += 1;
2250 case SWRAP_CLOSE_RECV:
2251 if (si->type != SOCK_STREAM) return NULL;
2253 dest_addr = &si->myname.sa.s;
2254 src_addr = &si->peername.sa.s;
2256 tcp_seqno = si->io.pck_rcv;
2257 tcp_ack = si->io.pck_snd;
2258 tcp_ctl = 0x11; /* FIN,ACK */
2260 si->io.pck_rcv += 1;
2264 case SWRAP_CLOSE_ACK:
2265 if (si->type != SOCK_STREAM) return NULL;
2267 src_addr = &si->myname.sa.s;
2268 dest_addr = &si->peername.sa.s;
2270 tcp_seqno = si->io.pck_snd;
2271 tcp_ack = si->io.pck_rcv;
2272 tcp_ctl = 0x10; /* ACK */
2279 swrapGetTimeOfDay(&tv);
2281 return swrap_pcap_packet_init(&tv,
2285 (const uint8_t *)buf,
2294 static void swrap_pcap_dump_packet(struct socket_info *si,
2295 const struct sockaddr *addr,
2296 enum swrap_packet_type type,
2297 const void *buf, size_t len)
2299 const char *file_name;
2301 size_t packet_len = 0;
2304 file_name = swrap_pcap_init_file();
2309 packet = swrap_pcap_marshall_packet(si,
2315 if (packet == NULL) {
2319 fd = swrap_pcap_get_fd(file_name);
2321 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2330 /****************************************************************************
2332 ***************************************************************************/
2334 #ifdef HAVE_SIGNALFD
2335 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2339 rc = libc_signalfd(fd, mask, flags);
2341 swrap_remove_stale(fd);
2347 int signalfd(int fd, const sigset_t *mask, int flags)
2349 return swrap_signalfd(fd, mask, flags);
2353 /****************************************************************************
2355 ***************************************************************************/
2357 static int swrap_socket(int family, int type, int protocol)
2359 struct socket_info *si;
2360 struct socket_info_fd *fi;
2362 int real_type = type;
2365 * Remove possible addition flags passed to socket() so
2366 * do not fail checking the type.
2367 * See https://lwn.net/Articles/281965/
2370 real_type &= ~SOCK_CLOEXEC;
2372 #ifdef SOCK_NONBLOCK
2373 real_type &= ~SOCK_NONBLOCK;
2376 if (!socket_wrapper_enabled()) {
2377 return libc_socket(family, type, protocol);
2388 #endif /* AF_NETLINK */
2390 return libc_socket(family, type, protocol);
2392 errno = EAFNOSUPPORT;
2396 switch (real_type) {
2402 errno = EPROTONOSUPPORT;
2410 if (real_type == SOCK_STREAM) {
2415 if (real_type == SOCK_DGRAM) {
2420 errno = EPROTONOSUPPORT;
2425 * We must call libc_socket with type, from the caller, not the version
2426 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2428 fd = libc_socket(AF_UNIX, type, 0);
2434 /* Check if we have a stale fd and remove it */
2435 si = find_socket_info(fd);
2437 swrap_remove_stale(fd);
2440 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
2446 si->family = family;
2448 /* however, the rest of the socket_wrapper code expects just
2449 * the type, not the flags */
2450 si->type = real_type;
2451 si->protocol = protocol;
2454 * Setup myname so getsockname() can succeed to find out the socket
2457 switch(si->family) {
2459 struct sockaddr_in sin = {
2460 .sin_family = AF_INET,
2463 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2464 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2468 struct sockaddr_in6 sin6 = {
2469 .sin6_family = AF_INET6,
2472 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2473 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2482 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2491 SWRAP_DLIST_ADD(si->fds, fi);
2492 SWRAP_DLIST_ADD(sockets, si);
2494 SWRAP_LOG(SWRAP_LOG_TRACE,
2495 "Created %s socket for protocol %s",
2496 si->family == AF_INET ? "IPv4" : "IPv6",
2497 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2502 int socket(int family, int type, int protocol)
2504 return swrap_socket(family, type, protocol);
2507 /****************************************************************************
2509 ***************************************************************************/
2511 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2515 rc = libc_socketpair(family, type, protocol, sv);
2517 swrap_remove_stale(sv[0]);
2518 swrap_remove_stale(sv[1]);
2524 int socketpair(int family, int type, int protocol, int sv[2])
2526 return swrap_socketpair(family, type, protocol, sv);
2529 /****************************************************************************
2531 ***************************************************************************/
2533 #ifdef HAVE_TIMERFD_CREATE
2534 static int swrap_timerfd_create(int clockid, int flags)
2538 fd = libc_timerfd_create(clockid, flags);
2540 swrap_remove_stale(fd);
2546 int timerfd_create(int clockid, int flags)
2548 return swrap_timerfd_create(clockid, flags);
2552 /****************************************************************************
2554 ***************************************************************************/
2556 static int swrap_pipe(int pipefd[2])
2560 rc = libc_pipe(pipefd);
2562 swrap_remove_stale(pipefd[0]);
2563 swrap_remove_stale(pipefd[1]);
2569 int pipe(int pipefd[2])
2571 return swrap_pipe(pipefd);
2574 /****************************************************************************
2576 ***************************************************************************/
2578 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2580 struct socket_info *parent_si, *child_si;
2581 struct socket_info_fd *child_fi;
2583 struct swrap_address un_addr = {
2584 .sa_socklen = sizeof(struct sockaddr_un),
2586 struct swrap_address un_my_addr = {
2587 .sa_socklen = sizeof(struct sockaddr_un),
2589 struct swrap_address in_addr = {
2590 .sa_socklen = sizeof(struct sockaddr_storage),
2592 struct swrap_address in_my_addr = {
2593 .sa_socklen = sizeof(struct sockaddr_storage),
2597 parent_si = find_socket_info(s);
2599 return libc_accept(s, addr, addrlen);
2603 * assume out sockaddr have the same size as the in parent
2606 in_addr.sa_socklen = socket_length(parent_si->family);
2607 if (in_addr.sa_socklen <= 0) {
2612 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2614 if (errno == ENOTSOCK) {
2615 /* Remove stale fds */
2616 swrap_remove_stale(s);
2623 ret = sockaddr_convert_from_un(parent_si,
2628 &in_addr.sa_socklen);
2634 child_si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
2635 if (child_si == NULL) {
2641 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2642 if (child_fi == NULL) {
2651 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2653 child_si->family = parent_si->family;
2654 child_si->type = parent_si->type;
2655 child_si->protocol = parent_si->protocol;
2656 child_si->bound = 1;
2657 child_si->is_server = 1;
2658 child_si->connected = 1;
2660 child_si->peername = (struct swrap_address) {
2661 .sa_socklen = in_addr.sa_socklen,
2663 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2665 if (addr != NULL && addrlen != NULL) {
2666 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2668 memcpy(addr, &in_addr.sa.ss, copy_len);
2670 *addrlen = in_addr.sa_socklen;
2673 ret = libc_getsockname(fd,
2675 &un_my_addr.sa_socklen);
2683 ret = sockaddr_convert_from_un(child_si,
2685 un_my_addr.sa_socklen,
2688 &in_my_addr.sa_socklen);
2696 SWRAP_LOG(SWRAP_LOG_TRACE,
2697 "accept() path=%s, fd=%d",
2698 un_my_addr.sa.un.sun_path, s);
2700 child_si->myname = (struct swrap_address) {
2701 .sa_socklen = in_my_addr.sa_socklen,
2703 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2705 SWRAP_DLIST_ADD(sockets, child_si);
2708 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2709 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2710 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2716 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2717 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2719 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2722 return swrap_accept(s, addr, (socklen_t *)addrlen);
2725 static int autobind_start_init;
2726 static int autobind_start;
2728 /* using sendto() or connect() on an unbound socket would give the
2729 recipient no way to reply, as unlike UDP and TCP, a unix domain
2730 socket can't auto-assign ephemeral port numbers, so we need to
2732 Note: this might change the family from ipv6 to ipv4
2734 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2736 struct swrap_address un_addr = {
2737 .sa_socklen = sizeof(struct sockaddr_un),
2745 if (autobind_start_init != 1) {
2746 autobind_start_init = 1;
2747 autobind_start = getpid();
2748 autobind_start %= 50000;
2749 autobind_start += 10000;
2752 un_addr.sa.un.sun_family = AF_UNIX;
2756 struct sockaddr_in in;
2760 type = SOCKET_TYPE_CHAR_TCP;
2763 type = SOCKET_TYPE_CHAR_UDP;
2766 errno = ESOCKTNOSUPPORT;
2770 memset(&in, 0, sizeof(in));
2771 in.sin_family = AF_INET;
2772 in.sin_addr.s_addr = htonl(127<<24 |
2773 socket_wrapper_default_iface());
2775 si->myname = (struct swrap_address) {
2776 .sa_socklen = sizeof(in),
2778 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2783 struct sockaddr_in6 in6;
2785 if (si->family != family) {
2786 errno = ENETUNREACH;
2792 type = SOCKET_TYPE_CHAR_TCP_V6;
2795 type = SOCKET_TYPE_CHAR_UDP_V6;
2798 errno = ESOCKTNOSUPPORT;
2802 memset(&in6, 0, sizeof(in6));
2803 in6.sin6_family = AF_INET6;
2804 in6.sin6_addr = *swrap_ipv6();
2805 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2807 si->myname = (struct swrap_address) {
2808 .sa_socklen = sizeof(in6),
2810 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2815 errno = ESOCKTNOSUPPORT;
2819 if (autobind_start > 60000) {
2820 autobind_start = 10000;
2823 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2824 port = autobind_start + i;
2825 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2826 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2827 type, socket_wrapper_default_iface(), port);
2828 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2830 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2831 if (ret == -1) return ret;
2833 si->un_addr = un_addr.sa.un;
2836 autobind_start = port + 1;
2839 if (i == SOCKET_MAX_SOCKETS) {
2840 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2841 "interface "SOCKET_FORMAT,
2844 socket_wrapper_default_iface(),
2850 si->family = family;
2851 set_port(si->family, port, &si->myname);
2856 /****************************************************************************
2858 ***************************************************************************/
2860 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2864 struct swrap_address un_addr = {
2865 .sa_socklen = sizeof(struct sockaddr_un),
2867 struct socket_info *si = find_socket_info(s);
2871 return libc_connect(s, serv_addr, addrlen);
2874 if (si->bound == 0) {
2875 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2876 if (ret == -1) return -1;
2879 if (si->family != serv_addr->sa_family) {
2884 ret = sockaddr_convert_to_un(si, serv_addr,
2885 addrlen, &un_addr.sa.un, 0, &bcast);
2886 if (ret == -1) return -1;
2889 errno = ENETUNREACH;
2893 if (si->type == SOCK_DGRAM) {
2894 si->defer_connect = 1;
2897 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2899 ret = libc_connect(s,
2901 un_addr.sa_socklen);
2904 SWRAP_LOG(SWRAP_LOG_TRACE,
2905 "connect() path=%s, fd=%d",
2906 un_addr.sa.un.sun_path, s);
2909 /* to give better errors */
2910 if (ret == -1 && errno == ENOENT) {
2911 errno = EHOSTUNREACH;
2915 si->peername = (struct swrap_address) {
2916 .sa_socklen = addrlen,
2919 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2923 * When we connect() on a socket than we have to bind the
2924 * outgoing connection on the interface we use for the
2925 * transport. We already bound it on the right interface
2926 * but here we have to update the name so getsockname()
2927 * returns correct information.
2929 if (si->bindname.sa_socklen > 0) {
2930 si->myname = (struct swrap_address) {
2931 .sa_socklen = si->bindname.sa_socklen,
2934 memcpy(&si->myname.sa.ss,
2935 &si->bindname.sa.ss,
2936 si->bindname.sa_socklen);
2938 /* Cleanup bindname */
2939 si->bindname = (struct swrap_address) {
2944 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2945 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2947 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2953 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2955 return swrap_connect(s, serv_addr, addrlen);
2958 /****************************************************************************
2960 ***************************************************************************/
2962 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2965 struct swrap_address un_addr = {
2966 .sa_socklen = sizeof(struct sockaddr_un),
2968 struct socket_info *si = find_socket_info(s);
2975 return libc_bind(s, myaddr, addrlen);
2978 switch (si->family) {
2980 const struct sockaddr_in *sin;
2981 if (addrlen < sizeof(struct sockaddr_in)) {
2982 bind_error = EINVAL;
2986 sin = (const struct sockaddr_in *)(const void *)myaddr;
2988 if (sin->sin_family != AF_INET) {
2989 bind_error = EAFNOSUPPORT;
2992 /* special case for AF_UNSPEC */
2993 if (sin->sin_family == AF_UNSPEC &&
2994 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3003 const struct sockaddr_in6 *sin6;
3004 if (addrlen < sizeof(struct sockaddr_in6)) {
3005 bind_error = EINVAL;
3009 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3011 if (sin6->sin6_family != AF_INET6) {
3012 bind_error = EAFNOSUPPORT;
3019 bind_error = EINVAL;
3023 if (bind_error != 0) {
3029 in_use = check_addr_port_in_use(myaddr, addrlen);
3036 si->myname.sa_socklen = addrlen;
3037 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3039 ret = sockaddr_convert_to_un(si,
3045 if (ret == -1) return -1;
3047 unlink(un_addr.sa.un.sun_path);
3049 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3051 SWRAP_LOG(SWRAP_LOG_TRACE,
3052 "bind() path=%s, fd=%d",
3053 un_addr.sa.un.sun_path, s);
3062 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3064 return swrap_bind(s, myaddr, addrlen);
3067 /****************************************************************************
3069 ***************************************************************************/
3071 #ifdef HAVE_BINDRESVPORT
3072 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3074 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3076 struct swrap_address myaddr = {
3077 .sa_socklen = sizeof(struct sockaddr_storage),
3080 static uint16_t port;
3085 #define SWRAP_STARTPORT 600
3086 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3087 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3090 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3094 salen = myaddr.sa_socklen;
3097 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3103 memset(&myaddr.sa.ss, 0, salen);
3108 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3111 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3113 salen = sizeof(struct sockaddr_in);
3114 sinp->sin_port = htons(port);
3118 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3120 salen = sizeof(struct sockaddr_in6);
3121 sin6p->sin6_port = htons(port);
3125 errno = EAFNOSUPPORT;
3130 if (port > SWRAP_ENDPORT) {
3131 port = SWRAP_STARTPORT;
3134 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3135 if (rc == 0 || errno != EADDRINUSE) {
3143 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3145 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3149 /****************************************************************************
3151 ***************************************************************************/
3153 static int swrap_listen(int s, int backlog)
3156 struct socket_info *si = find_socket_info(s);
3159 return libc_listen(s, backlog);
3162 if (si->bound == 0) {
3163 ret = swrap_auto_bind(s, si, si->family);
3170 ret = libc_listen(s, backlog);
3175 int listen(int s, int backlog)
3177 return swrap_listen(s, backlog);
3180 /****************************************************************************
3182 ***************************************************************************/
3184 static FILE *swrap_fopen(const char *name, const char *mode)
3188 fp = libc_fopen(name, mode);
3190 int fd = fileno(fp);
3192 swrap_remove_stale(fd);
3198 FILE *fopen(const char *name, const char *mode)
3200 return swrap_fopen(name, mode);
3203 /****************************************************************************
3205 ***************************************************************************/
3207 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3211 ret = libc_vopen(pathname, flags, ap);
3214 * There are methods for closing descriptors (libc-internal code
3215 * paths, direct syscalls) which close descriptors in ways that
3216 * we can't intercept, so try to recover when we notice that
3219 swrap_remove_stale(ret);
3224 int open(const char *pathname, int flags, ...)
3229 va_start(ap, flags);
3230 fd = swrap_vopen(pathname, flags, ap);
3236 /****************************************************************************
3238 ***************************************************************************/
3240 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3242 struct socket_info *si = find_socket_info(s);
3246 return libc_getpeername(s, name, addrlen);
3249 if (si->peername.sa_socklen == 0)
3255 len = MIN(*addrlen, si->peername.sa_socklen);
3260 memcpy(name, &si->peername.sa.ss, len);
3261 *addrlen = si->peername.sa_socklen;
3266 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3267 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3269 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3272 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3275 /****************************************************************************
3277 ***************************************************************************/
3279 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3281 struct socket_info *si = find_socket_info(s);
3285 return libc_getsockname(s, name, addrlen);
3288 len = MIN(*addrlen, si->myname.sa_socklen);
3293 memcpy(name, &si->myname.sa.ss, len);
3294 *addrlen = si->myname.sa_socklen;
3299 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3300 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3302 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3305 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3308 /****************************************************************************
3310 ***************************************************************************/
3313 # ifdef SO_PROTOTYPE /* The Solaris name */
3314 # define SO_PROTOCOL SO_PROTOTYPE
3315 # endif /* SO_PROTOTYPE */
3316 #endif /* SO_PROTOCOL */
3318 static int swrap_getsockopt(int s, int level, int optname,
3319 void *optval, socklen_t *optlen)
3321 struct socket_info *si = find_socket_info(s);
3324 return libc_getsockopt(s,
3331 if (level == SOL_SOCKET) {
3335 if (optval == NULL || optlen == NULL ||
3336 *optlen < (socklen_t)sizeof(int)) {
3341 *optlen = sizeof(int);
3342 *(int *)optval = si->family;
3344 #endif /* SO_DOMAIN */
3348 if (optval == NULL || optlen == NULL ||
3349 *optlen < (socklen_t)sizeof(int)) {
3354 *optlen = sizeof(int);
3355 *(int *)optval = si->protocol;
3357 #endif /* SO_PROTOCOL */
3359 if (optval == NULL || optlen == NULL ||
3360 *optlen < (socklen_t)sizeof(int)) {
3365 *optlen = sizeof(int);
3366 *(int *)optval = si->type;
3369 return libc_getsockopt(s,
3375 } else if (level == IPPROTO_TCP) {
3380 * This enables sending packets directly out over TCP.
3381 * As a unix socket is doing that any way, report it as
3384 if (optval == NULL || optlen == NULL ||
3385 *optlen < (socklen_t)sizeof(int)) {
3390 *optlen = sizeof(int);
3391 *(int *)optval = si->tcp_nodelay;
3394 #endif /* TCP_NODELAY */
3400 errno = ENOPROTOOPT;
3404 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3405 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3407 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3410 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3413 /****************************************************************************
3415 ***************************************************************************/
3417 static int swrap_setsockopt(int s, int level, int optname,
3418 const void *optval, socklen_t optlen)
3420 struct socket_info *si = find_socket_info(s);
3423 return libc_setsockopt(s,
3430 if (level == SOL_SOCKET) {
3431 return libc_setsockopt(s,
3436 } else if (level == IPPROTO_TCP) {
3443 * This enables sending packets directly out over TCP.
3444 * A unix socket is doing that any way.
3446 if (optval == NULL || optlen == 0 ||
3447 optlen < (socklen_t)sizeof(int)) {
3452 i = *discard_const_p(int, optval);
3453 if (i != 0 && i != 1) {
3457 si->tcp_nodelay = i;
3461 #endif /* TCP_NODELAY */
3467 switch (si->family) {
3469 if (level == IPPROTO_IP) {
3471 if (optname == IP_PKTINFO) {
3472 si->pktinfo = AF_INET;
3474 #endif /* IP_PKTINFO */
3479 if (level == IPPROTO_IPV6) {
3480 #ifdef IPV6_RECVPKTINFO
3481 if (optname == IPV6_RECVPKTINFO) {
3482 si->pktinfo = AF_INET6;
3484 #endif /* IPV6_PKTINFO */
3489 errno = ENOPROTOOPT;
3494 int setsockopt(int s, int level, int optname,
3495 const void *optval, socklen_t optlen)
3497 return swrap_setsockopt(s, level, optname, optval, optlen);
3500 /****************************************************************************
3502 ***************************************************************************/
3504 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3506 struct socket_info *si = find_socket_info(s);
3512 return libc_vioctl(s, r, va);
3517 rc = libc_vioctl(s, r, va);
3521 value = *((int *)va_arg(ap, int *));
3523 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3524 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3525 } else if (value == 0) { /* END OF FILE */
3526 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3536 #ifdef HAVE_IOCTL_INT
3537 int ioctl(int s, int r, ...)
3539 int ioctl(int s, unsigned long int r, ...)
3547 rc = swrap_vioctl(s, (unsigned long int) r, va);
3558 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3561 # ifdef _ALIGN /* BSD */
3562 #define CMSG_ALIGN _ALIGN
3564 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3565 # endif /* _ALIGN */
3566 #endif /* CMSG_ALIGN */
3569 * @brief Add a cmsghdr to a msghdr.
3571 * This is an function to add any type of cmsghdr. It will operate on the
3572 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3573 * the buffer position after the added cmsg element. Hence, this function is
3574 * intended to be used with an intermediate msghdr and not on the original
3575 * one handed in by the client.
3577 * @param[in] msg The msghdr to which to add the cmsg.
3579 * @param[in] level The cmsg level to set.
3581 * @param[in] type The cmsg type to set.
3583 * @param[in] data The cmsg data to set.
3585 * @param[in] len the length of the data to set.
3587 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3593 size_t cmlen = CMSG_LEN(len);
3594 size_t cmspace = CMSG_SPACE(len);
3595 uint8_t cmbuf[cmspace];
3596 void *cast_ptr = (void *)cmbuf;
3597 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3600 memset(cmbuf, 0, cmspace);
3602 if (msg->msg_controllen < cmlen) {
3603 cmlen = msg->msg_controllen;
3604 msg->msg_flags |= MSG_CTRUNC;
3607 if (msg->msg_controllen < cmspace) {
3608 cmspace = msg->msg_controllen;
3612 * We copy the full input data into an intermediate cmsghdr first
3613 * in order to more easily cope with truncation.
3615 cm->cmsg_len = cmlen;
3616 cm->cmsg_level = level;
3617 cm->cmsg_type = type;
3618 memcpy(CMSG_DATA(cm), data, len);
3621 * We now copy the possibly truncated buffer.
3622 * We copy cmlen bytes, but consume cmspace bytes,
3623 * leaving the possible padding uninitialiazed.
3625 p = (uint8_t *)msg->msg_control;
3626 memcpy(p, cm, cmlen);
3628 msg->msg_control = p;
3629 msg->msg_controllen -= cmspace;
3634 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3637 /* Add packet info */
3638 switch (si->pktinfo) {
3639 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3641 struct sockaddr_in *sin;
3642 #if defined(HAVE_STRUCT_IN_PKTINFO)
3643 struct in_pktinfo pkt;
3644 #elif defined(IP_RECVDSTADDR)
3648 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3649 sin = &si->bindname.sa.in;
3651 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3654 sin = &si->myname.sa.in;
3659 #if defined(HAVE_STRUCT_IN_PKTINFO)
3660 pkt.ipi_ifindex = socket_wrapper_default_iface();
3661 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3662 #elif defined(IP_RECVDSTADDR)
3663 pkt = sin->sin_addr;
3666 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3671 #endif /* IP_PKTINFO */
3672 #if defined(HAVE_IPV6)
3674 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3675 struct sockaddr_in6 *sin6;
3676 struct in6_pktinfo pkt6;
3678 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3679 sin6 = &si->bindname.sa.in6;
3681 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3684 sin6 = &si->myname.sa.in6;
3689 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3690 pkt6.ipi6_addr = sin6->sin6_addr;
3692 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3693 &pkt6, sizeof(pkt6));
3694 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3698 #endif /* IPV6_PKTINFO */
3706 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3707 struct msghdr *omsg)
3711 if (si->pktinfo > 0) {
3712 rc = swrap_msghdr_add_pktinfo(si, omsg);
3718 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3720 size_t *cm_data_space);
3721 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3723 size_t *cm_data_space);
3725 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3727 size_t *cm_data_space) {
3728 struct cmsghdr *cmsg;
3732 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3736 for (cmsg = CMSG_FIRSTHDR(msg);
3738 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3739 switch (cmsg->cmsg_level) {
3741 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3746 rc = swrap_sendmsg_copy_cmsg(cmsg,
3756 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3758 size_t *cm_data_space)
3763 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
3765 p = realloc((*cm_data), cmspace);
3771 p = (*cm_data) + (*cm_data_space);
3772 *cm_data_space = cmspace;
3774 memcpy(p, cmsg, cmsg->cmsg_len);
3779 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3781 size_t *cm_data_space);
3784 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3786 size_t *cm_data_space)
3790 switch(cmsg->cmsg_type) {
3793 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3800 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3812 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3814 size_t *cm_data_space)
3816 (void)cmsg; /* unused */
3817 (void)cm_data; /* unused */
3818 (void)cm_data_space; /* unused */
3821 * Passing a IP pktinfo to a unix socket might be rejected by the
3822 * Kernel, at least on FreeBSD. So skip this cmsg.
3826 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3828 static ssize_t swrap_sendmsg_before(int fd,
3829 struct socket_info *si,
3831 struct iovec *tmp_iov,
3832 struct sockaddr_un *tmp_un,
3833 const struct sockaddr_un **to_un,
3834 const struct sockaddr **to,
3854 if (!si->connected) {
3859 if (msg->msg_iovlen == 0) {
3863 mtu = socket_wrapper_mtu();
3864 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3866 nlen = len + msg->msg_iov[i].iov_len;
3871 msg->msg_iovlen = i;
3872 if (msg->msg_iovlen == 0) {
3873 *tmp_iov = msg->msg_iov[0];
3874 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
3876 msg->msg_iov = tmp_iov;
3877 msg->msg_iovlen = 1;
3882 if (si->connected) {
3883 if (msg->msg_name) {
3888 const struct sockaddr *msg_name;
3889 msg_name = (const struct sockaddr *)msg->msg_name;
3891 if (msg_name == NULL) {
3897 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3899 if (ret == -1) return -1;
3907 msg->msg_name = tmp_un;
3908 msg->msg_namelen = sizeof(*tmp_un);
3911 if (si->bound == 0) {
3912 ret = swrap_auto_bind(fd, si, si->family);
3914 if (errno == ENOTSOCK) {
3915 swrap_remove_stale(fd);
3918 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3924 if (!si->defer_connect) {
3928 ret = sockaddr_convert_to_un(si,
3930 si->peername.sa_socklen,
3934 if (ret == -1) return -1;
3936 ret = libc_connect(fd,
3937 (struct sockaddr *)(void *)tmp_un,
3940 /* to give better errors */
3941 if (ret == -1 && errno == ENOENT) {
3942 errno = EHOSTUNREACH;
3949 si->defer_connect = 0;
3952 errno = EHOSTUNREACH;
3956 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3957 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3958 uint8_t *cmbuf = NULL;
3961 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3968 msg->msg_controllen = 0;
3969 msg->msg_control = NULL;
3970 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3971 memcpy(msg->msg_control, cmbuf, cmlen);
3972 msg->msg_controllen = cmlen;
3981 static void swrap_sendmsg_after(int fd,
3982 struct socket_info *si,
3984 const struct sockaddr *to,
3987 int saved_errno = errno;
3994 /* to give better errors */
3996 if (saved_errno == ENOENT) {
3997 saved_errno = EHOSTUNREACH;
3998 } else if (saved_errno == ENOTSOCK) {
3999 /* If the fd is not a socket, remove it */
4000 swrap_remove_stale(fd);
4004 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4005 avail += msg->msg_iov[i].iov_len;
4009 remain = MIN(80, avail);
4014 /* we capture it as one single packet */
4015 buf = (uint8_t *)malloc(remain);
4017 /* we just not capture the packet */
4018 errno = saved_errno;
4022 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4023 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4025 msg->msg_iov[i].iov_base,
4028 remain -= this_time;
4035 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4036 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4038 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4043 if (si->connected) {
4044 to = &si->peername.sa.s;
4047 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4048 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4050 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4056 errno = saved_errno;
4059 static int swrap_recvmsg_before(int fd,
4060 struct socket_info *si,
4062 struct iovec *tmp_iov)
4067 (void)fd; /* unused */
4072 if (!si->connected) {
4077 if (msg->msg_iovlen == 0) {
4081 mtu = socket_wrapper_mtu();
4082 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4084 nlen = len + msg->msg_iov[i].iov_len;
4089 msg->msg_iovlen = i;
4090 if (msg->msg_iovlen == 0) {
4091 *tmp_iov = msg->msg_iov[0];
4092 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4094 msg->msg_iov = tmp_iov;
4095 msg->msg_iovlen = 1;
4100 if (msg->msg_name == NULL) {
4105 if (msg->msg_iovlen == 0) {
4109 if (si->bound == 0) {
4110 ret = swrap_auto_bind(fd, si, si->family);
4113 * When attempting to read or write to a
4114 * descriptor, if an underlying autobind fails
4115 * because it's not a socket, stop intercepting
4116 * uses of that descriptor.
4118 if (errno == ENOTSOCK) {
4119 swrap_remove_stale(fd);
4122 SWRAP_LOG(SWRAP_LOG_ERROR,
4123 "swrap_recvmsg_before failed");
4130 errno = EHOSTUNREACH;
4137 static int swrap_recvmsg_after(int fd,
4138 struct socket_info *si,
4140 const struct sockaddr_un *un_addr,
4141 socklen_t un_addrlen,
4144 int saved_errno = errno;
4146 uint8_t *buf = NULL;
4152 /* to give better errors */
4154 if (saved_errno == ENOENT) {
4155 saved_errno = EHOSTUNREACH;
4156 } else if (saved_errno == ENOTSOCK) {
4157 /* If the fd is not a socket, remove it */
4158 swrap_remove_stale(fd);
4162 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4163 avail += msg->msg_iov[i].iov_len;
4166 /* Convert the socket address before we leave */
4167 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4168 rc = sockaddr_convert_from_un(si,
4185 remain = MIN(80, avail);
4190 /* we capture it as one single packet */
4191 buf = (uint8_t *)malloc(remain);
4193 /* we just not capture the packet */
4194 errno = saved_errno;
4198 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4199 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4201 msg->msg_iov[i].iov_base,
4204 remain -= this_time;
4209 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4210 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4211 } else if (ret == 0) { /* END OF FILE */
4212 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4213 } else if (ret > 0) {
4214 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4223 if (un_addr != NULL) {
4224 swrap_pcap_dump_packet(si,
4230 swrap_pcap_dump_packet(si,
4243 errno = saved_errno;
4245 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4247 msg->msg_controllen > 0 &&
4248 msg->msg_control != NULL) {
4249 rc = swrap_msghdr_add_socket_info(si, msg);
4259 /****************************************************************************
4261 ***************************************************************************/
4263 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4264 struct sockaddr *from, socklen_t *fromlen)
4266 struct swrap_address from_addr = {
4267 .sa_socklen = sizeof(struct sockaddr_un),
4270 struct socket_info *si = find_socket_info(s);
4271 struct swrap_address saddr = {
4272 .sa_socklen = sizeof(struct sockaddr_storage),
4279 return libc_recvfrom(s,
4291 if (from != NULL && fromlen != NULL) {
4292 msg.msg_name = from; /* optional address */
4293 msg.msg_namelen = *fromlen; /* size of address */
4295 msg.msg_name = &saddr.sa.s; /* optional address */
4296 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4298 msg.msg_iov = &tmp; /* scatter/gather array */
4299 msg.msg_iovlen = 1; /* # elements in msg_iov */
4300 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4301 msg.msg_control = NULL; /* ancillary data, see below */
4302 msg.msg_controllen = 0; /* ancillary data buffer len */
4303 msg.msg_flags = 0; /* flags on received message */
4306 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4311 buf = msg.msg_iov[0].iov_base;
4312 len = msg.msg_iov[0].iov_len;
4314 ret = libc_recvfrom(s,
4319 &from_addr.sa_socklen);
4324 tret = swrap_recvmsg_after(s,
4328 from_addr.sa_socklen,
4334 if (from != NULL && fromlen != NULL) {
4335 *fromlen = msg.msg_namelen;
4341 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4342 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4343 struct sockaddr *from, Psocklen_t fromlen)
4345 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4346 struct sockaddr *from, socklen_t *fromlen)
4349 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4352 /****************************************************************************
4354 ***************************************************************************/
4356 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4357 const struct sockaddr *to, socklen_t tolen)
4361 struct swrap_address un_addr = {
4362 .sa_socklen = sizeof(struct sockaddr_un),
4364 const struct sockaddr_un *to_un = NULL;
4367 struct socket_info *si = find_socket_info(s);
4371 return libc_sendto(s, buf, len, flags, to, tolen);
4374 tmp.iov_base = discard_const_p(char, buf);
4378 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4379 msg.msg_namelen = tolen; /* size of address */
4380 msg.msg_iov = &tmp; /* scatter/gather array */
4381 msg.msg_iovlen = 1; /* # elements in msg_iov */
4382 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4383 msg.msg_control = NULL; /* ancillary data, see below */
4384 msg.msg_controllen = 0; /* ancillary data buffer len */
4385 msg.msg_flags = 0; /* flags on received message */
4388 rc = swrap_sendmsg_before(s,
4400 buf = msg.msg_iov[0].iov_base;
4401 len = msg.msg_iov[0].iov_len;
4406 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4409 type = SOCKET_TYPE_CHAR_UDP;
4411 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4412 snprintf(un_addr.sa.un.sun_path,
4413 sizeof(un_addr.sa.un.sun_path),
4415 socket_wrapper_dir(), type, iface, prt);
4416 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4418 /* ignore the any errors in broadcast sends */
4424 un_addr.sa_socklen);
4427 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4432 ret = libc_sendto(s,
4436 (struct sockaddr *)msg.msg_name,
4439 swrap_sendmsg_after(s, si, &msg, to, ret);
4444 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4445 const struct sockaddr *to, socklen_t tolen)
4447 return swrap_sendto(s, buf, len, flags, to, tolen);
4450 /****************************************************************************
4452 ***************************************************************************/
4454 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4456 struct socket_info *si;
4458 struct swrap_address saddr = {
4459 .sa_socklen = sizeof(struct sockaddr_storage),
4465 si = find_socket_info(s);
4467 return libc_recv(s, buf, len, flags);
4474 msg.msg_name = &saddr.sa.s; /* optional address */
4475 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4476 msg.msg_iov = &tmp; /* scatter/gather array */
4477 msg.msg_iovlen = 1; /* # elements in msg_iov */
4478 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4479 msg.msg_control = NULL; /* ancillary data, see below */
4480 msg.msg_controllen = 0; /* ancillary data buffer len */
4481 msg.msg_flags = 0; /* flags on received message */
4484 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4489 buf = msg.msg_iov[0].iov_base;
4490 len = msg.msg_iov[0].iov_len;
4492 ret = libc_recv(s, buf, len, flags);
4494 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4502 ssize_t recv(int s, void *buf, size_t len, int flags)
4504 return swrap_recv(s, buf, len, flags);
4507 /****************************************************************************
4509 ***************************************************************************/
4511 static ssize_t swrap_read(int s, void *buf, size_t len)
4513 struct socket_info *si;
4516 struct swrap_address saddr = {
4517 .sa_socklen = sizeof(struct sockaddr_storage),
4522 si = find_socket_info(s);
4524 return libc_read(s, buf, len);
4531 msg.msg_name = &saddr.sa.ss; /* optional address */
4532 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4533 msg.msg_iov = &tmp; /* scatter/gather array */
4534 msg.msg_iovlen = 1; /* # elements in msg_iov */
4535 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4536 msg.msg_control = NULL; /* ancillary data, see below */
4537 msg.msg_controllen = 0; /* ancillary data buffer len */
4538 msg.msg_flags = 0; /* flags on received message */
4541 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4543 if (tret == -ENOTSOCK) {
4544 return libc_read(s, buf, len);
4549 buf = msg.msg_iov[0].iov_base;
4550 len = msg.msg_iov[0].iov_len;
4552 ret = libc_read(s, buf, len);
4554 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4562 ssize_t read(int s, void *buf, size_t len)
4564 return swrap_read(s, buf, len);
4567 /****************************************************************************
4569 ***************************************************************************/
4571 static ssize_t swrap_write(int s, const void *buf, size_t len)
4575 struct sockaddr_un un_addr;
4578 struct socket_info *si;
4580 si = find_socket_info(s);
4582 return libc_write(s, buf, len);
4585 tmp.iov_base = discard_const_p(char, buf);
4589 msg.msg_name = NULL; /* optional address */
4590 msg.msg_namelen = 0; /* size of address */
4591 msg.msg_iov = &tmp; /* scatter/gather array */
4592 msg.msg_iovlen = 1; /* # elements in msg_iov */
4593 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4594 msg.msg_control = NULL; /* ancillary data, see below */
4595 msg.msg_controllen = 0; /* ancillary data buffer len */
4596 msg.msg_flags = 0; /* flags on received message */
4599 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4604 buf = msg.msg_iov[0].iov_base;
4605 len = msg.msg_iov[0].iov_len;
4607 ret = libc_write(s, buf, len);
4609 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4614 ssize_t write(int s, const void *buf, size_t len)
4616 return swrap_write(s, buf, len);
4619 /****************************************************************************
4621 ***************************************************************************/
4623 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4627 struct sockaddr_un un_addr;
4630 struct socket_info *si = find_socket_info(s);
4633 return libc_send(s, buf, len, flags);
4636 tmp.iov_base = discard_const_p(char, buf);
4640 msg.msg_name = NULL; /* optional address */
4641 msg.msg_namelen = 0; /* size of address */
4642 msg.msg_iov = &tmp; /* scatter/gather array */
4643 msg.msg_iovlen = 1; /* # elements in msg_iov */
4644 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4645 msg.msg_control = NULL; /* ancillary data, see below */
4646 msg.msg_controllen = 0; /* ancillary data buffer len */
4647 msg.msg_flags = 0; /* flags on received message */
4650 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4655 buf = msg.msg_iov[0].iov_base;
4656 len = msg.msg_iov[0].iov_len;
4658 ret = libc_send(s, buf, len, flags);
4660 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4665 ssize_t send(int s, const void *buf, size_t len, int flags)
4667 return swrap_send(s, buf, len, flags);
4670 /****************************************************************************
4672 ***************************************************************************/
4674 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4676 struct swrap_address from_addr = {
4677 .sa_socklen = sizeof(struct sockaddr_un),
4679 struct swrap_address convert_addr = {
4680 .sa_socklen = sizeof(struct sockaddr_storage),
4682 struct socket_info *si;
4685 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4686 size_t msg_ctrllen_filled;
4687 size_t msg_ctrllen_left;
4693 si = find_socket_info(s);
4695 return libc_recvmsg(s, omsg, flags);
4698 tmp.iov_base = NULL;
4702 msg.msg_name = &from_addr.sa; /* optional address */
4703 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4704 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4705 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4706 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4707 msg_ctrllen_filled = 0;
4708 msg_ctrllen_left = omsg->msg_controllen;
4710 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4711 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4712 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4715 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4720 ret = libc_recvmsg(s, &msg, flags);
4722 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4723 msg_ctrllen_filled += msg.msg_controllen;
4724 msg_ctrllen_left -= msg.msg_controllen;
4726 if (omsg->msg_control != NULL) {
4729 p = omsg->msg_control;
4730 p += msg_ctrllen_filled;
4732 msg.msg_control = p;
4733 msg.msg_controllen = msg_ctrllen_left;
4735 msg.msg_control = NULL;
4736 msg.msg_controllen = 0;
4741 * We convert the unix address to a IP address so we need a buffer
4742 * which can store the address in case of SOCK_DGRAM, see below.
4744 msg.msg_name = &convert_addr.sa;
4745 msg.msg_namelen = convert_addr.sa_socklen;
4747 rc = swrap_recvmsg_after(s,
4751 from_addr.sa_socklen,
4757 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4758 if (omsg->msg_control != NULL) {
4759 /* msg.msg_controllen = space left */
4760 msg_ctrllen_left = msg.msg_controllen;
4761 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4764 /* Update the original message length */
4765 omsg->msg_controllen = msg_ctrllen_filled;
4766 omsg->msg_flags = msg.msg_flags;
4768 omsg->msg_iovlen = msg.msg_iovlen;
4773 * The msg_name field points to a caller-allocated buffer that is
4774 * used to return the source address if the socket is unconnected. The
4775 * caller should set msg_namelen to the size of this buffer before this
4776 * call; upon return from a successful call, msg_name will contain the
4777 * length of the returned address. If the application does not need
4778 * to know the source address, msg_name can be specified as NULL.
4780 if (si->type == SOCK_STREAM) {
4781 omsg->msg_namelen = 0;
4782 } else if (omsg->msg_name != NULL &&
4783 omsg->msg_namelen != 0 &&
4784 omsg->msg_namelen >= msg.msg_namelen) {
4785 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
4786 omsg->msg_namelen = msg.msg_namelen;
4792 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4794 return swrap_recvmsg(sockfd, msg, flags);
4797 /****************************************************************************
4799 ***************************************************************************/
4801 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4805 struct sockaddr_un un_addr;
4806 const struct sockaddr_un *to_un = NULL;
4807 const struct sockaddr *to = NULL;
4810 struct socket_info *si = find_socket_info(s);
4814 return libc_sendmsg(s, omsg, flags);
4817 ZERO_STRUCT(un_addr);
4819 tmp.iov_base = NULL;
4824 if (si->connected == 0) {
4825 msg.msg_name = omsg->msg_name; /* optional address */
4826 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4828 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4829 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4830 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4831 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4832 /* omsg is a const so use a local buffer for modifications */
4833 uint8_t cmbuf[omsg->msg_controllen];
4835 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4837 msg.msg_control = cmbuf; /* ancillary data, see below */
4838 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4840 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4843 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4851 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4859 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4860 avail += msg.msg_iov[i].iov_len;
4866 /* we capture it as one single packet */
4867 buf = (uint8_t *)malloc(remain);
4872 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4873 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4875 msg.msg_iov[i].iov_base,
4878 remain -= this_time;
4881 type = SOCKET_TYPE_CHAR_UDP;
4883 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4884 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4885 socket_wrapper_dir(), type, iface, prt);
4886 if (stat(un_addr.sun_path, &st) != 0) continue;
4888 msg.msg_name = &un_addr; /* optional address */
4889 msg.msg_namelen = sizeof(un_addr); /* size of address */
4891 /* ignore the any errors in broadcast sends */
4892 libc_sendmsg(s, &msg, flags);
4895 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4901 ret = libc_sendmsg(s, &msg, flags);
4903 swrap_sendmsg_after(s, si, &msg, to, ret);
4908 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4910 return swrap_sendmsg(s, omsg, flags);
4913 /****************************************************************************
4915 ***************************************************************************/
4917 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4919 struct socket_info *si;
4922 struct swrap_address saddr = {
4923 .sa_socklen = sizeof(struct sockaddr_storage)
4928 si = find_socket_info(s);
4930 return libc_readv(s, vector, count);
4933 tmp.iov_base = NULL;
4937 msg.msg_name = &saddr.sa.s; /* optional address */
4938 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4939 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4940 msg.msg_iovlen = count; /* # elements in msg_iov */
4941 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4942 msg.msg_control = NULL; /* ancillary data, see below */
4943 msg.msg_controllen = 0; /* ancillary data buffer len */
4944 msg.msg_flags = 0; /* flags on received message */
4947 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4949 if (rc == -ENOTSOCK) {
4950 return libc_readv(s, vector, count);
4955 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4957 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4965 ssize_t readv(int s, const struct iovec *vector, int count)
4967 return swrap_readv(s, vector, count);
4970 /****************************************************************************
4972 ***************************************************************************/
4974 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4978 struct sockaddr_un un_addr;
4981 struct socket_info *si = find_socket_info(s);
4984 return libc_writev(s, vector, count);
4987 tmp.iov_base = NULL;
4991 msg.msg_name = NULL; /* optional address */
4992 msg.msg_namelen = 0; /* size of address */
4993 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4994 msg.msg_iovlen = count; /* # elements in msg_iov */
4995 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4996 msg.msg_control = NULL; /* ancillary data, see below */
4997 msg.msg_controllen = 0; /* ancillary data buffer len */
4998 msg.msg_flags = 0; /* flags on received message */
5001 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5003 if (rc == -ENOTSOCK) {
5004 return libc_readv(s, vector, count);
5009 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5011 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5016 ssize_t writev(int s, const struct iovec *vector, int count)
5018 return swrap_writev(s, vector, count);
5021 /****************************
5023 ***************************/
5025 static int swrap_close(int fd)
5027 struct socket_info *si = find_socket_info(fd);
5028 struct socket_info_fd *fi;
5032 return libc_close(fd);
5035 for (fi = si->fds; fi; fi = fi->next) {
5037 SWRAP_DLIST_REMOVE(si->fds, fi);
5044 /* there are still references left */
5045 return libc_close(fd);
5048 SWRAP_DLIST_REMOVE(sockets, si);
5050 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5051 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5054 ret = libc_close(fd);
5056 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5057 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5058 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5061 if (si->un_addr.sun_path[0] != '\0') {
5062 unlink(si->un_addr.sun_path);
5071 return swrap_close(fd);
5074 /****************************
5076 ***************************/
5078 static int swrap_dup(int fd)
5080 struct socket_info *si;
5081 struct socket_info_fd *fi;
5083 si = find_socket_info(fd);
5086 return libc_dup(fd);
5089 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5095 fi->fd = libc_dup(fd);
5097 int saved_errno = errno;
5099 errno = saved_errno;
5103 /* Make sure we don't have an entry for the fd */
5104 swrap_remove_stale(fi->fd);
5106 SWRAP_DLIST_ADD(si->fds, fi);
5112 return swrap_dup(fd);
5115 /****************************
5117 ***************************/
5119 static int swrap_dup2(int fd, int newfd)
5121 struct socket_info *si;
5122 struct socket_info_fd *fi;
5124 si = find_socket_info(fd);
5127 return libc_dup2(fd, newfd);
5130 if (find_socket_info(newfd)) {
5131 /* dup2() does an implicit close of newfd, which we
5132 * need to emulate */
5136 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5142 fi->fd = libc_dup2(fd, newfd);
5144 int saved_errno = errno;
5146 errno = saved_errno;
5150 /* Make sure we don't have an entry for the fd */
5151 swrap_remove_stale(fi->fd);
5153 SWRAP_DLIST_ADD(si->fds, fi);
5157 int dup2(int fd, int newfd)
5159 return swrap_dup2(fd, newfd);
5162 /****************************
5164 ***************************/
5166 static int swrap_vfcntl(int fd, int cmd, va_list va)
5168 struct socket_info_fd *fi;
5169 struct socket_info *si;
5172 si = find_socket_info(fd);
5174 rc = libc_vfcntl(fd, cmd, va);
5181 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5187 fi->fd = libc_vfcntl(fd, cmd, va);
5189 int saved_errno = errno;
5191 errno = saved_errno;
5195 /* Make sure we don't have an entry for the fd */
5196 swrap_remove_stale(fi->fd);
5198 SWRAP_DLIST_ADD(si->fds, fi);
5203 rc = libc_vfcntl(fd, cmd, va);
5210 int fcntl(int fd, int cmd, ...)
5217 rc = swrap_vfcntl(fd, cmd, va);
5224 /****************************
5226 ***************************/
5229 static int swrap_eventfd(int count, int flags)
5233 fd = libc_eventfd(count, flags);
5235 swrap_remove_stale(fd);
5241 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5242 int eventfd(unsigned int count, int flags)
5244 int eventfd(int count, int flags)
5247 return swrap_eventfd(count, flags);
5252 int pledge(const char *promises, const char *paths[])
5254 (void)promises; /* unused */
5255 (void)paths; /* unused */
5259 #endif /* HAVE_PLEDGE */
5261 /****************************
5263 ***************************/
5266 * This function is called when the library is unloaded and makes sure that
5267 * sockets get closed and the unix file for the socket are unlinked.
5269 void swrap_destructor(void)
5271 struct socket_info *s = sockets;
5274 struct socket_info_fd *f = s->fds;
5281 if (swrap.libc_handle != NULL) {
5282 dlclose(swrap.libc_handle);
5284 if (swrap.libsocket_handle) {
5285 dlclose(swrap.libsocket_handle);