2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
45 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
100 #define DESTRUCTOR_ATTRIBUTE
103 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
106 # define SWRAP_THREAD
110 #define MIN(a,b) ((a)<(b)?(a):(b))
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
118 #define ZERO_STRUCTP(x) do { \
120 memset((char *)(x), 0, sizeof(*(x))); \
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
150 #define SWRAP_DLIST_ADD(list,item) do { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
167 (list)->prev = NULL; \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct swrap_address {
214 socklen_t sa_socklen;
217 struct sockaddr_in in;
219 struct sockaddr_in6 in6;
221 struct sockaddr_un un;
222 struct sockaddr_storage ss;
226 struct socket_info_fd {
227 struct socket_info_fd *prev, *next;
233 struct socket_info_fd *fds;
245 /* The unix path so we can unlink it on close() */
246 struct sockaddr_un un_addr;
248 struct swrap_address bindname;
249 struct swrap_address myname;
250 struct swrap_address peername;
253 unsigned long pck_snd;
254 unsigned long pck_rcv;
257 struct socket_info *prev, *next;
261 * File descriptors are shared between threads so we should share socket
264 struct socket_info *sockets;
266 /* Function prototypes */
268 bool socket_wrapper_enabled(void);
269 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
272 # define SWRAP_LOG(...)
275 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
276 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
278 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
283 unsigned int lvl = 0;
285 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
290 va_start(va, format);
291 vsnprintf(buffer, sizeof(buffer), format, va);
296 case SWRAP_LOG_ERROR:
298 "SWRAP_ERROR(%d): %s\n",
299 (int)getpid(), buffer);
303 "SWRAP_WARN(%d): %s\n",
304 (int)getpid(), buffer);
306 case SWRAP_LOG_DEBUG:
308 "SWRAP_DEBUG(%d): %s\n",
309 (int)getpid(), buffer);
311 case SWRAP_LOG_TRACE:
313 "SWRAP_TRACE(%d): %s\n",
314 (int)getpid(), buffer);
321 /*********************************************************
322 * SWRAP LOADING LIBC FUNCTIONS
323 *********************************************************/
327 struct swrap_libc_fns {
328 int (*libc_accept)(int sockfd,
329 struct sockaddr *addr,
331 int (*libc_bind)(int sockfd,
332 const struct sockaddr *addr,
334 int (*libc_close)(int fd);
335 int (*libc_connect)(int sockfd,
336 const struct sockaddr *addr,
338 int (*libc_dup)(int fd);
339 int (*libc_dup2)(int oldfd, int newfd);
340 FILE *(*libc_fopen)(const char *name, const char *mode);
342 int (*libc_eventfd)(int count, int flags);
344 int (*libc_getpeername)(int sockfd,
345 struct sockaddr *addr,
347 int (*libc_getsockname)(int sockfd,
348 struct sockaddr *addr,
350 int (*libc_getsockopt)(int sockfd,
355 int (*libc_ioctl)(int d, unsigned long int request, ...);
356 int (*libc_listen)(int sockfd, int backlog);
357 int (*libc_open)(const char *pathname, int flags, mode_t mode);
358 int (*libc_pipe)(int pipefd[2]);
359 int (*libc_read)(int fd, void *buf, size_t count);
360 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
361 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
362 int (*libc_recvfrom)(int sockfd,
366 struct sockaddr *src_addr,
368 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
369 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
370 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
371 int (*libc_sendto)(int sockfd,
375 const struct sockaddr *dst_addr,
377 int (*libc_setsockopt)(int sockfd,
383 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
385 int (*libc_socket)(int domain, int type, int protocol);
386 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
387 #ifdef HAVE_TIMERFD_CREATE
388 int (*libc_timerfd_create)(int clockid, int flags);
390 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
395 void *libsocket_handle;
402 struct swrap_libc_fns fns;
405 static struct swrap swrap;
408 static const char *socket_wrapper_dir(void);
410 #define LIBC_NAME "libc.so"
419 static const char *swrap_str_lib(enum swrap_lib lib)
426 case SWRAP_LIBSOCKET:
430 /* Compiler would warn us about unhandled enum value if we get here */
435 static void *swrap_load_lib_handle(enum swrap_lib lib)
437 int flags = RTLD_LAZY;
442 flags |= RTLD_DEEPBIND;
448 case SWRAP_LIBSOCKET:
449 #ifdef HAVE_LIBSOCKET
450 handle = swrap.libsocket_handle;
451 if (handle == NULL) {
452 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
453 char soname[256] = {0};
455 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
456 handle = dlopen(soname, flags);
459 swrap.libsocket_handle = handle;
465 handle = swrap.libc_handle;
467 if (handle == NULL) {
468 handle = dlopen(LIBC_SO, flags);
470 swrap.libc_handle = handle;
473 if (handle == NULL) {
474 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
475 char soname[256] = {0};
477 snprintf(soname, sizeof(soname), "libc.so.%d", i);
478 handle = dlopen(soname, flags);
481 swrap.libc_handle = handle;
486 if (handle == NULL) {
488 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
490 SWRAP_LOG(SWRAP_LOG_ERROR,
491 "Failed to dlopen library: %s\n",
500 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
505 handle = swrap_load_lib_handle(lib);
507 func = dlsym(handle, fn_name);
509 SWRAP_LOG(SWRAP_LOG_ERROR,
510 "Failed to find %s: %s\n",
515 SWRAP_LOG(SWRAP_LOG_TRACE,
517 fn_name, swrap_str_lib(lib));
521 #define swrap_load_lib_function(lib, fn_name) \
522 if (swrap.fns.libc_##fn_name == NULL) { \
523 *(void **) (&swrap.fns.libc_##fn_name) = \
524 _swrap_load_lib_function(lib, #fn_name); \
531 * Functions especially from libc need to be loaded individually, you can't load
532 * all at once or gdb will segfault at startup. The same applies to valgrind and
533 * has probably something todo with with the linker.
534 * So we need load each function at the point it is called the first time.
536 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
538 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
540 return swrap.fns.libc_accept(sockfd, addr, addrlen);
543 static int libc_bind(int sockfd,
544 const struct sockaddr *addr,
547 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
549 return swrap.fns.libc_bind(sockfd, addr, addrlen);
552 static int libc_close(int fd)
554 swrap_load_lib_function(SWRAP_LIBC, close);
556 return swrap.fns.libc_close(fd);
559 static int libc_connect(int sockfd,
560 const struct sockaddr *addr,
563 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
565 return swrap.fns.libc_connect(sockfd, addr, addrlen);
568 static int libc_dup(int fd)
570 swrap_load_lib_function(SWRAP_LIBC, dup);
572 return swrap.fns.libc_dup(fd);
575 static int libc_dup2(int oldfd, int newfd)
577 swrap_load_lib_function(SWRAP_LIBC, dup2);
579 return swrap.fns.libc_dup2(oldfd, newfd);
583 static int libc_eventfd(int count, int flags)
585 swrap_load_lib_function(SWRAP_LIBC, eventfd);
587 return swrap.fns.libc_eventfd(count, flags);
591 static int libc_getpeername(int sockfd,
592 struct sockaddr *addr,
595 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
597 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
600 static int libc_getsockname(int sockfd,
601 struct sockaddr *addr,
604 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
606 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
609 static int libc_getsockopt(int sockfd,
615 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
617 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
620 static int libc_vioctl(int d, unsigned long int request, va_list ap)
626 swrap_load_lib_function(SWRAP_LIBC, ioctl);
628 for (i = 0; i < 4; i++) {
629 args[i] = va_arg(ap, long int);
632 rc = swrap.fns.libc_ioctl(d,
642 static int libc_listen(int sockfd, int backlog)
644 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
646 return swrap.fns.libc_listen(sockfd, backlog);
649 static FILE *libc_fopen(const char *name, const char *mode)
651 swrap_load_lib_function(SWRAP_LIBC, fopen);
653 return swrap.fns.libc_fopen(name, mode);
656 static int libc_vopen(const char *pathname, int flags, va_list ap)
661 swrap_load_lib_function(SWRAP_LIBC, open);
663 mode = va_arg(ap, long int);
665 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
670 static int libc_open(const char *pathname, int flags, ...)
676 fd = libc_vopen(pathname, flags, ap);
682 static int libc_pipe(int pipefd[2])
684 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
686 return swrap.fns.libc_pipe(pipefd);
689 static int libc_read(int fd, void *buf, size_t count)
691 swrap_load_lib_function(SWRAP_LIBC, read);
693 return swrap.fns.libc_read(fd, buf, count);
696 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
698 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
700 return swrap.fns.libc_readv(fd, iov, iovcnt);
703 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
705 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
707 return swrap.fns.libc_recv(sockfd, buf, len, flags);
710 static int libc_recvfrom(int sockfd,
714 struct sockaddr *src_addr,
717 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
719 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
722 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
724 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
726 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
729 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
731 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
733 return swrap.fns.libc_send(sockfd, buf, len, flags);
736 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
738 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
740 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
743 static int libc_sendto(int sockfd,
747 const struct sockaddr *dst_addr,
750 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
752 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
755 static int libc_setsockopt(int sockfd,
761 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
763 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
767 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
769 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
771 return swrap.fns.libc_signalfd(fd, mask, flags);
775 static int libc_socket(int domain, int type, int protocol)
777 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
779 return swrap.fns.libc_socket(domain, type, protocol);
782 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
784 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
786 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
789 #ifdef HAVE_TIMERFD_CREATE
790 static int libc_timerfd_create(int clockid, int flags)
792 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
794 return swrap.fns.libc_timerfd_create(clockid, flags);
798 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
800 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
802 return swrap.fns.libc_writev(fd, iov, iovcnt);
805 /*********************************************************
806 * SWRAP HELPER FUNCTIONS
807 *********************************************************/
813 static const struct in6_addr *swrap_ipv6(void)
815 static struct in6_addr v;
816 static int initialized;
824 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
833 static void set_port(int family, int prt, struct swrap_address *addr)
837 addr->sa.in.sin_port = htons(prt);
841 addr->sa.in6.sin6_port = htons(prt);
847 static size_t socket_length(int family)
851 return sizeof(struct sockaddr_in);
854 return sizeof(struct sockaddr_in6);
860 static const char *socket_wrapper_dir(void)
862 const char *s = getenv("SOCKET_WRAPPER_DIR");
866 /* TODO use realpath(3) here, when we add support for threads */
867 if (strncmp(s, "./", 2) == 0) {
871 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
875 bool socket_wrapper_enabled(void)
877 const char *s = socket_wrapper_dir();
879 return s != NULL ? true : false;
882 static unsigned int socket_wrapper_default_iface(void)
884 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
887 if (sscanf(s, "%u", &iface) == 1) {
888 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
894 return 1;/* 127.0.0.1 */
897 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
904 p = strrchr(un->sun_path, '/');
905 if (p) p++; else p = un->sun_path;
907 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
912 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
915 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
926 case SOCKET_TYPE_CHAR_TCP:
927 case SOCKET_TYPE_CHAR_UDP: {
928 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
930 if ((*len) < sizeof(*in2)) {
935 memset(in2, 0, sizeof(*in2));
936 in2->sin_family = AF_INET;
937 in2->sin_addr.s_addr = htonl((127<<24) | iface);
938 in2->sin_port = htons(prt);
944 case SOCKET_TYPE_CHAR_TCP_V6:
945 case SOCKET_TYPE_CHAR_UDP_V6: {
946 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
948 if ((*len) < sizeof(*in2)) {
953 memset(in2, 0, sizeof(*in2));
954 in2->sin6_family = AF_INET6;
955 in2->sin6_addr = *swrap_ipv6();
956 in2->sin6_addr.s6_addr[15] = iface;
957 in2->sin6_port = htons(prt);
971 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
979 if (bcast) *bcast = 0;
981 switch (inaddr->sa_family) {
983 const struct sockaddr_in *in =
984 (const struct sockaddr_in *)(const void *)inaddr;
985 unsigned int addr = ntohl(in->sin_addr.s_addr);
992 u_type = SOCKET_TYPE_CHAR_TCP;
995 u_type = SOCKET_TYPE_CHAR_UDP;
996 a_type = SOCKET_TYPE_CHAR_UDP;
997 b_type = SOCKET_TYPE_CHAR_UDP;
1000 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1001 errno = ESOCKTNOSUPPORT;
1005 prt = ntohs(in->sin_port);
1006 if (a_type && addr == 0xFFFFFFFF) {
1007 /* 255.255.255.255 only udp */
1010 iface = socket_wrapper_default_iface();
1011 } else if (b_type && addr == 0x7FFFFFFF) {
1012 /* 127.255.255.255 only udp */
1015 iface = socket_wrapper_default_iface();
1016 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1020 iface = (addr & 0x000000FF);
1022 errno = ENETUNREACH;
1025 if (bcast) *bcast = is_bcast;
1030 const struct sockaddr_in6 *in =
1031 (const struct sockaddr_in6 *)(const void *)inaddr;
1032 struct in6_addr cmp1, cmp2;
1036 type = SOCKET_TYPE_CHAR_TCP_V6;
1039 type = SOCKET_TYPE_CHAR_UDP_V6;
1042 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1043 errno = ESOCKTNOSUPPORT;
1047 /* XXX no multicast/broadcast */
1049 prt = ntohs(in->sin6_port);
1051 cmp1 = *swrap_ipv6();
1052 cmp2 = in->sin6_addr;
1053 cmp2.s6_addr[15] = 0;
1054 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1055 iface = in->sin6_addr.s6_addr[15];
1057 errno = ENETUNREACH;
1065 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1066 errno = ENETUNREACH;
1071 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1077 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1078 socket_wrapper_dir());
1079 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1080 /* the caller need to do more processing */
1084 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1085 socket_wrapper_dir(), type, iface, prt);
1086 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1091 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1100 if (bcast) *bcast = 0;
1102 switch (si->family) {
1104 const struct sockaddr_in *in =
1105 (const struct sockaddr_in *)(const void *)inaddr;
1106 unsigned int addr = ntohl(in->sin_addr.s_addr);
1112 prt = ntohs(in->sin_port);
1116 u_type = SOCKET_TYPE_CHAR_TCP;
1117 d_type = SOCKET_TYPE_CHAR_TCP;
1120 u_type = SOCKET_TYPE_CHAR_UDP;
1121 d_type = SOCKET_TYPE_CHAR_UDP;
1122 a_type = SOCKET_TYPE_CHAR_UDP;
1123 b_type = SOCKET_TYPE_CHAR_UDP;
1126 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1127 errno = ESOCKTNOSUPPORT;
1135 iface = socket_wrapper_default_iface();
1136 } else if (a_type && addr == 0xFFFFFFFF) {
1137 /* 255.255.255.255 only udp */
1140 iface = socket_wrapper_default_iface();
1141 } else if (b_type && addr == 0x7FFFFFFF) {
1142 /* 127.255.255.255 only udp */
1145 iface = socket_wrapper_default_iface();
1146 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1150 iface = (addr & 0x000000FF);
1152 errno = EADDRNOTAVAIL;
1156 /* Store the bind address for connect() */
1157 if (si->bindname.sa_socklen == 0) {
1158 struct sockaddr_in bind_in;
1159 socklen_t blen = sizeof(struct sockaddr_in);
1161 ZERO_STRUCT(bind_in);
1162 bind_in.sin_family = in->sin_family;
1163 bind_in.sin_port = in->sin_port;
1164 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1166 si->bindname.sa_socklen = blen;
1167 memcpy(&si->bindname.sa.in, &bind_in, blen);
1174 const struct sockaddr_in6 *in =
1175 (const struct sockaddr_in6 *)(const void *)inaddr;
1176 struct in6_addr cmp1, cmp2;
1180 type = SOCKET_TYPE_CHAR_TCP_V6;
1183 type = SOCKET_TYPE_CHAR_UDP_V6;
1186 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1187 errno = ESOCKTNOSUPPORT;
1191 /* XXX no multicast/broadcast */
1193 prt = ntohs(in->sin6_port);
1195 cmp1 = *swrap_ipv6();
1196 cmp2 = in->sin6_addr;
1197 cmp2.s6_addr[15] = 0;
1198 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1199 iface = socket_wrapper_default_iface();
1200 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1201 iface = in->sin6_addr.s6_addr[15];
1203 errno = EADDRNOTAVAIL;
1207 /* Store the bind address for connect() */
1208 if (si->bindname.sa_socklen == 0) {
1209 struct sockaddr_in6 bind_in;
1210 socklen_t blen = sizeof(struct sockaddr_in6);
1212 ZERO_STRUCT(bind_in);
1213 bind_in.sin6_family = in->sin6_family;
1214 bind_in.sin6_port = in->sin6_port;
1216 bind_in.sin6_addr = *swrap_ipv6();
1217 bind_in.sin6_addr.s6_addr[15] = iface;
1219 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1220 si->bindname.sa_socklen = blen;
1227 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1228 errno = EADDRNOTAVAIL;
1233 if (bcast) *bcast = is_bcast;
1235 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1241 /* handle auto-allocation of ephemeral ports */
1242 for (prt = 5001; prt < 10000; prt++) {
1243 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1244 socket_wrapper_dir(), type, iface, prt);
1245 if (stat(un->sun_path, &st) == 0) continue;
1247 set_port(si->family, prt, &si->myname);
1248 set_port(si->family, prt, &si->bindname);
1258 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1259 socket_wrapper_dir(), type, iface, prt);
1260 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1264 static struct socket_info *find_socket_info(int fd)
1266 struct socket_info *i;
1268 for (i = sockets; i; i = i->next) {
1269 struct socket_info_fd *f;
1270 for (f = i->fds; f; f = f->next) {
1281 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1283 struct socket_info *s;
1285 /* first catch invalid input */
1286 switch (sa->sa_family) {
1288 if (len < sizeof(struct sockaddr_in)) {
1294 if (len < sizeof(struct sockaddr_in6)) {
1304 for (s = sockets; s != NULL; s = s->next) {
1305 if (s->myname == NULL) {
1308 if (s->myname->sa_family != sa->sa_family) {
1311 switch (s->myname->sa_family) {
1313 struct sockaddr_in *sin1, *sin2;
1315 sin1 = (struct sockaddr_in *)s->myname;
1316 sin2 = (struct sockaddr_in *)sa;
1318 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1321 if (sin1->sin_port != sin2->sin_port) {
1324 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1334 struct sockaddr_in6 *sin1, *sin2;
1336 sin1 = (struct sockaddr_in6 *)s->myname;
1337 sin2 = (struct sockaddr_in6 *)sa;
1339 if (sin1->sin6_port != sin2->sin6_port) {
1342 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1364 static void swrap_remove_stale(int fd)
1366 struct socket_info *si = find_socket_info(fd);
1367 struct socket_info_fd *fi;
1370 for (fi = si->fds; fi; fi = fi->next) {
1372 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1373 SWRAP_DLIST_REMOVE(si->fds, fi);
1379 if (si->fds == NULL) {
1380 SWRAP_DLIST_REMOVE(sockets, si);
1385 static int sockaddr_convert_to_un(struct socket_info *si,
1386 const struct sockaddr *in_addr,
1388 struct sockaddr_un *out_addr,
1392 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1394 (void) in_len; /* unused */
1396 if (out_addr == NULL) {
1400 out->sa_family = AF_UNIX;
1401 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1402 out->sa_len = sizeof(*out_addr);
1405 switch (in_addr->sa_family) {
1407 const struct sockaddr_in *sin;
1408 if (si->family != AF_INET) {
1411 if (in_len < sizeof(struct sockaddr_in)) {
1414 sin = (const struct sockaddr_in *)in_addr;
1415 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1420 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1421 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1435 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1436 errno = ESOCKTNOSUPPORT;
1440 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1442 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1448 errno = EAFNOSUPPORT;
1449 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1453 static int sockaddr_convert_from_un(const struct socket_info *si,
1454 const struct sockaddr_un *in_addr,
1455 socklen_t un_addrlen,
1457 struct sockaddr *out_addr,
1458 socklen_t *out_addrlen)
1462 if (out_addr == NULL || out_addrlen == NULL)
1465 if (un_addrlen == 0) {
1480 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1481 errno = ESOCKTNOSUPPORT;
1484 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1485 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1486 out_addr->sa_len = *out_addrlen;
1493 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1494 errno = EAFNOSUPPORT;
1498 enum swrap_packet_type {
1500 SWRAP_CONNECT_UNREACH,
1508 SWRAP_SENDTO_UNREACH,
1519 struct swrap_file_hdr {
1521 uint16_t version_major;
1522 uint16_t version_minor;
1525 uint32_t frame_max_len;
1526 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1529 #define SWRAP_FILE_HDR_SIZE 24
1531 struct swrap_packet_frame {
1533 uint32_t micro_seconds;
1534 uint32_t recorded_length;
1535 uint32_t full_length;
1537 #define SWRAP_PACKET_FRAME_SIZE 16
1539 union swrap_packet_ip {
1543 uint16_t packet_length;
1544 uint16_t identification;
1549 uint16_t hdr_checksum;
1553 #define SWRAP_PACKET_IP_V4_SIZE 20
1556 uint8_t flow_label_high;
1557 uint16_t flow_label_low;
1558 uint16_t payload_length;
1559 uint8_t next_header;
1561 uint8_t src_addr[16];
1562 uint8_t dest_addr[16];
1564 #define SWRAP_PACKET_IP_V6_SIZE 40
1566 #define SWRAP_PACKET_IP_SIZE 40
1568 union swrap_packet_payload {
1570 uint16_t source_port;
1580 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1582 uint16_t source_port;
1587 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1594 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1601 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1603 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1605 #define SWRAP_PACKET_MIN_ALLOC \
1606 (SWRAP_PACKET_FRAME_SIZE + \
1607 SWRAP_PACKET_IP_SIZE + \
1608 SWRAP_PACKET_PAYLOAD_SIZE)
1610 static const char *swrap_pcap_init_file(void)
1612 static int initialized = 0;
1613 static const char *s = NULL;
1614 static const struct swrap_file_hdr h;
1615 static const struct swrap_packet_frame f;
1616 static const union swrap_packet_ip i;
1617 static const union swrap_packet_payload p;
1619 if (initialized == 1) {
1625 * TODO: don't use the structs use plain buffer offsets
1626 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1628 * for now make sure we disable PCAP support
1629 * if the struct has alignment!
1631 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1634 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1637 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1640 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1643 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1646 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1649 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1652 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1655 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1658 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1662 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1666 if (strncmp(s, "./", 2) == 0) {
1672 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1673 const struct sockaddr *src,
1674 const struct sockaddr *dest,
1676 const uint8_t *payload,
1678 unsigned long tcp_seqno,
1679 unsigned long tcp_ack,
1680 unsigned char tcp_ctl,
1682 size_t *_packet_len)
1686 struct swrap_packet_frame *frame;
1687 union swrap_packet_ip *ip;
1688 union swrap_packet_payload *pay;
1691 size_t nonwire_len = sizeof(*frame);
1692 size_t wire_hdr_len = 0;
1693 size_t wire_len = 0;
1694 size_t ip_hdr_len = 0;
1695 size_t icmp_hdr_len = 0;
1696 size_t icmp_truncate_len = 0;
1697 uint8_t protocol = 0, icmp_protocol = 0;
1698 const struct sockaddr_in *src_in = NULL;
1699 const struct sockaddr_in *dest_in = NULL;
1701 const struct sockaddr_in6 *src_in6 = NULL;
1702 const struct sockaddr_in6 *dest_in6 = NULL;
1707 switch (src->sa_family) {
1709 src_in = (const struct sockaddr_in *)src;
1710 dest_in = (const struct sockaddr_in *)dest;
1711 src_port = src_in->sin_port;
1712 dest_port = dest_in->sin_port;
1713 ip_hdr_len = sizeof(ip->v4);
1717 src_in6 = (const struct sockaddr_in6 *)src;
1718 dest_in6 = (const struct sockaddr_in6 *)dest;
1719 src_port = src_in6->sin6_port;
1720 dest_port = dest_in6->sin6_port;
1721 ip_hdr_len = sizeof(ip->v6);
1728 switch (socket_type) {
1730 protocol = 0x06; /* TCP */
1731 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1732 wire_len = wire_hdr_len + payload_len;
1736 protocol = 0x11; /* UDP */
1737 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1738 wire_len = wire_hdr_len + payload_len;
1746 icmp_protocol = protocol;
1747 switch (src->sa_family) {
1749 protocol = 0x01; /* ICMPv4 */
1750 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1754 protocol = 0x3A; /* ICMPv6 */
1755 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1759 if (wire_len > 64 ) {
1760 icmp_truncate_len = wire_len - 64;
1762 wire_hdr_len += icmp_hdr_len;
1763 wire_len += icmp_hdr_len;
1766 packet_len = nonwire_len + wire_len;
1767 alloc_len = packet_len;
1768 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1769 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1772 base = (uint8_t *)malloc(alloc_len);
1776 memset(base, 0x0, alloc_len);
1780 frame = (struct swrap_packet_frame *)buf;
1781 frame->seconds = tval->tv_sec;
1782 frame->micro_seconds = tval->tv_usec;
1783 frame->recorded_length = wire_len - icmp_truncate_len;
1784 frame->full_length = wire_len - icmp_truncate_len;
1785 buf += SWRAP_PACKET_FRAME_SIZE;
1787 ip = (union swrap_packet_ip *)buf;
1788 switch (src->sa_family) {
1790 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1792 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1793 ip->v4.identification = htons(0xFFFF);
1794 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1795 ip->v4.fragment = htons(0x0000);
1797 ip->v4.protocol = protocol;
1798 ip->v4.hdr_checksum = htons(0x0000);
1799 ip->v4.src_addr = src_in->sin_addr.s_addr;
1800 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1801 buf += SWRAP_PACKET_IP_V4_SIZE;
1805 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1806 ip->v6.flow_label_high = 0x00;
1807 ip->v6.flow_label_low = 0x0000;
1808 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1809 ip->v6.next_header = protocol;
1810 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1811 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1812 buf += SWRAP_PACKET_IP_V6_SIZE;
1818 pay = (union swrap_packet_payload *)buf;
1819 switch (src->sa_family) {
1821 pay->icmp4.type = 0x03; /* destination unreachable */
1822 pay->icmp4.code = 0x01; /* host unreachable */
1823 pay->icmp4.checksum = htons(0x0000);
1824 pay->icmp4.unused = htonl(0x00000000);
1825 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1827 /* set the ip header in the ICMP payload */
1828 ip = (union swrap_packet_ip *)buf;
1829 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1831 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1832 ip->v4.identification = htons(0xFFFF);
1833 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1834 ip->v4.fragment = htons(0x0000);
1836 ip->v4.protocol = icmp_protocol;
1837 ip->v4.hdr_checksum = htons(0x0000);
1838 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1839 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1840 buf += SWRAP_PACKET_IP_V4_SIZE;
1842 src_port = dest_in->sin_port;
1843 dest_port = src_in->sin_port;
1847 pay->icmp6.type = 0x01; /* destination unreachable */
1848 pay->icmp6.code = 0x03; /* address unreachable */
1849 pay->icmp6.checksum = htons(0x0000);
1850 pay->icmp6.unused = htonl(0x00000000);
1851 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1853 /* set the ip header in the ICMP payload */
1854 ip = (union swrap_packet_ip *)buf;
1855 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1856 ip->v6.flow_label_high = 0x00;
1857 ip->v6.flow_label_low = 0x0000;
1858 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1859 ip->v6.next_header = protocol;
1860 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1861 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1862 buf += SWRAP_PACKET_IP_V6_SIZE;
1864 src_port = dest_in6->sin6_port;
1865 dest_port = src_in6->sin6_port;
1871 pay = (union swrap_packet_payload *)buf;
1873 switch (socket_type) {
1875 pay->tcp.source_port = src_port;
1876 pay->tcp.dest_port = dest_port;
1877 pay->tcp.seq_num = htonl(tcp_seqno);
1878 pay->tcp.ack_num = htonl(tcp_ack);
1879 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1880 pay->tcp.control = tcp_ctl;
1881 pay->tcp.window = htons(0x7FFF);
1882 pay->tcp.checksum = htons(0x0000);
1883 pay->tcp.urg = htons(0x0000);
1884 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1889 pay->udp.source_port = src_port;
1890 pay->udp.dest_port = dest_port;
1891 pay->udp.length = htons(8 + payload_len);
1892 pay->udp.checksum = htons(0x0000);
1893 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1898 if (payload && payload_len > 0) {
1899 memcpy(buf, payload, payload_len);
1902 *_packet_len = packet_len - icmp_truncate_len;
1906 static int swrap_pcap_get_fd(const char *fname)
1910 if (fd != -1) return fd;
1912 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1914 struct swrap_file_hdr file_hdr;
1915 file_hdr.magic = 0xA1B2C3D4;
1916 file_hdr.version_major = 0x0002;
1917 file_hdr.version_minor = 0x0004;
1918 file_hdr.timezone = 0x00000000;
1919 file_hdr.sigfigs = 0x00000000;
1920 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1921 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1923 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1930 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1935 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
1936 const struct sockaddr *addr,
1937 enum swrap_packet_type type,
1938 const void *buf, size_t len,
1941 const struct sockaddr *src_addr;
1942 const struct sockaddr *dest_addr;
1943 unsigned long tcp_seqno = 0;
1944 unsigned long tcp_ack = 0;
1945 unsigned char tcp_ctl = 0;
1946 int unreachable = 0;
1950 switch (si->family) {
1962 case SWRAP_CONNECT_SEND:
1963 if (si->type != SOCK_STREAM) return NULL;
1965 src_addr = &si->myname.sa.s;
1968 tcp_seqno = si->io.pck_snd;
1969 tcp_ack = si->io.pck_rcv;
1970 tcp_ctl = 0x02; /* SYN */
1972 si->io.pck_snd += 1;
1976 case SWRAP_CONNECT_RECV:
1977 if (si->type != SOCK_STREAM) return NULL;
1979 dest_addr = &si->myname.sa.s;
1982 tcp_seqno = si->io.pck_rcv;
1983 tcp_ack = si->io.pck_snd;
1984 tcp_ctl = 0x12; /** SYN,ACK */
1986 si->io.pck_rcv += 1;
1990 case SWRAP_CONNECT_UNREACH:
1991 if (si->type != SOCK_STREAM) return NULL;
1993 dest_addr = &si->myname.sa.s;
1996 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1997 tcp_seqno = si->io.pck_snd - 1;
1998 tcp_ack = si->io.pck_rcv;
1999 tcp_ctl = 0x02; /* SYN */
2004 case SWRAP_CONNECT_ACK:
2005 if (si->type != SOCK_STREAM) return NULL;
2007 src_addr = &si->myname.sa.s;
2010 tcp_seqno = si->io.pck_snd;
2011 tcp_ack = si->io.pck_rcv;
2012 tcp_ctl = 0x10; /* ACK */
2016 case SWRAP_ACCEPT_SEND:
2017 if (si->type != SOCK_STREAM) return NULL;
2019 dest_addr = &si->myname.sa.s;
2022 tcp_seqno = si->io.pck_rcv;
2023 tcp_ack = si->io.pck_snd;
2024 tcp_ctl = 0x02; /* SYN */
2026 si->io.pck_rcv += 1;
2030 case SWRAP_ACCEPT_RECV:
2031 if (si->type != SOCK_STREAM) return NULL;
2033 src_addr = &si->myname.sa.s;
2036 tcp_seqno = si->io.pck_snd;
2037 tcp_ack = si->io.pck_rcv;
2038 tcp_ctl = 0x12; /* SYN,ACK */
2040 si->io.pck_snd += 1;
2044 case SWRAP_ACCEPT_ACK:
2045 if (si->type != SOCK_STREAM) return NULL;
2047 dest_addr = &si->myname.sa.s;
2050 tcp_seqno = si->io.pck_rcv;
2051 tcp_ack = si->io.pck_snd;
2052 tcp_ctl = 0x10; /* ACK */
2057 src_addr = &si->myname.sa.s;
2058 dest_addr = &si->peername.sa.s;
2060 tcp_seqno = si->io.pck_snd;
2061 tcp_ack = si->io.pck_rcv;
2062 tcp_ctl = 0x18; /* PSH,ACK */
2064 si->io.pck_snd += len;
2068 case SWRAP_SEND_RST:
2069 dest_addr = &si->myname.sa.s;
2070 src_addr = &si->peername.sa.s;
2072 if (si->type == SOCK_DGRAM) {
2073 return swrap_pcap_marshall_packet(si,
2075 SWRAP_SENDTO_UNREACH,
2081 tcp_seqno = si->io.pck_rcv;
2082 tcp_ack = si->io.pck_snd;
2083 tcp_ctl = 0x14; /** RST,ACK */
2087 case SWRAP_PENDING_RST:
2088 dest_addr = &si->myname.sa.s;
2089 src_addr = &si->peername.sa.s;
2091 if (si->type == SOCK_DGRAM) {
2095 tcp_seqno = si->io.pck_rcv;
2096 tcp_ack = si->io.pck_snd;
2097 tcp_ctl = 0x14; /* RST,ACK */
2102 dest_addr = &si->myname.sa.s;
2103 src_addr = &si->peername.sa.s;
2105 tcp_seqno = si->io.pck_rcv;
2106 tcp_ack = si->io.pck_snd;
2107 tcp_ctl = 0x18; /* PSH,ACK */
2109 si->io.pck_rcv += len;
2113 case SWRAP_RECV_RST:
2114 dest_addr = &si->myname.sa.s;
2115 src_addr = &si->peername.sa.s;
2117 if (si->type == SOCK_DGRAM) {
2121 tcp_seqno = si->io.pck_rcv;
2122 tcp_ack = si->io.pck_snd;
2123 tcp_ctl = 0x14; /* RST,ACK */
2128 src_addr = &si->myname.sa.s;
2131 si->io.pck_snd += len;
2135 case SWRAP_SENDTO_UNREACH:
2136 dest_addr = &si->myname.sa.s;
2143 case SWRAP_RECVFROM:
2144 dest_addr = &si->myname.sa.s;
2147 si->io.pck_rcv += len;
2151 case SWRAP_CLOSE_SEND:
2152 if (si->type != SOCK_STREAM) return NULL;
2154 src_addr = &si->myname.sa.s;
2155 dest_addr = &si->peername.sa.s;
2157 tcp_seqno = si->io.pck_snd;
2158 tcp_ack = si->io.pck_rcv;
2159 tcp_ctl = 0x11; /* FIN, ACK */
2161 si->io.pck_snd += 1;
2165 case SWRAP_CLOSE_RECV:
2166 if (si->type != SOCK_STREAM) return NULL;
2168 dest_addr = &si->myname.sa.s;
2169 src_addr = &si->peername.sa.s;
2171 tcp_seqno = si->io.pck_rcv;
2172 tcp_ack = si->io.pck_snd;
2173 tcp_ctl = 0x11; /* FIN,ACK */
2175 si->io.pck_rcv += 1;
2179 case SWRAP_CLOSE_ACK:
2180 if (si->type != SOCK_STREAM) return NULL;
2182 src_addr = &si->myname.sa.s;
2183 dest_addr = &si->peername.sa.s;
2185 tcp_seqno = si->io.pck_snd;
2186 tcp_ack = si->io.pck_rcv;
2187 tcp_ctl = 0x10; /* ACK */
2194 swrapGetTimeOfDay(&tv);
2196 return swrap_pcap_packet_init(&tv,
2200 (const uint8_t *)buf,
2209 static void swrap_pcap_dump_packet(struct socket_info *si,
2210 const struct sockaddr *addr,
2211 enum swrap_packet_type type,
2212 const void *buf, size_t len)
2214 const char *file_name;
2216 size_t packet_len = 0;
2219 file_name = swrap_pcap_init_file();
2224 packet = swrap_pcap_marshall_packet(si,
2230 if (packet == NULL) {
2234 fd = swrap_pcap_get_fd(file_name);
2236 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2245 /****************************************************************************
2247 ***************************************************************************/
2249 #ifdef HAVE_SIGNALFD
2250 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2254 rc = libc_signalfd(fd, mask, flags);
2256 swrap_remove_stale(fd);
2262 int signalfd(int fd, const sigset_t *mask, int flags)
2264 return swrap_signalfd(fd, mask, flags);
2268 /****************************************************************************
2270 ***************************************************************************/
2272 static int swrap_socket(int family, int type, int protocol)
2274 struct socket_info *si;
2275 struct socket_info_fd *fi;
2277 int real_type = type;
2280 * Remove possible addition flags passed to socket() so
2281 * do not fail checking the type.
2282 * See https://lwn.net/Articles/281965/
2285 real_type &= ~SOCK_CLOEXEC;
2287 #ifdef SOCK_NONBLOCK
2288 real_type &= ~SOCK_NONBLOCK;
2291 if (!socket_wrapper_enabled()) {
2292 return libc_socket(family, type, protocol);
2302 return libc_socket(family, type, protocol);
2304 errno = EAFNOSUPPORT;
2308 switch (real_type) {
2314 errno = EPROTONOSUPPORT;
2322 if (real_type == SOCK_STREAM) {
2327 if (real_type == SOCK_DGRAM) {
2332 errno = EPROTONOSUPPORT;
2337 * We must call libc_socket with type, from the caller, not the version
2338 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2340 fd = libc_socket(AF_UNIX, type, 0);
2346 /* Check if we have a stale fd and remove it */
2347 si = find_socket_info(fd);
2349 swrap_remove_stale(fd);
2352 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2353 memset(si, 0, sizeof(struct socket_info));
2359 si->family = family;
2361 /* however, the rest of the socket_wrapper code expects just
2362 * the type, not the flags */
2363 si->type = real_type;
2364 si->protocol = protocol;
2367 * Setup myname so getsockname() can succeed to find out the socket
2370 switch(si->family) {
2372 struct sockaddr_in sin = {
2373 .sin_family = AF_INET,
2376 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2377 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2381 struct sockaddr_in6 sin6 = {
2382 .sin6_family = AF_INET6,
2385 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2386 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2395 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2404 SWRAP_DLIST_ADD(si->fds, fi);
2405 SWRAP_DLIST_ADD(sockets, si);
2410 int socket(int family, int type, int protocol)
2412 return swrap_socket(family, type, protocol);
2415 /****************************************************************************
2417 ***************************************************************************/
2419 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2423 rc = libc_socketpair(family, type, protocol, sv);
2425 swrap_remove_stale(sv[0]);
2426 swrap_remove_stale(sv[1]);
2432 int socketpair(int family, int type, int protocol, int sv[2])
2434 return swrap_socketpair(family, type, protocol, sv);
2437 /****************************************************************************
2439 ***************************************************************************/
2441 #ifdef HAVE_TIMERFD_CREATE
2442 static int swrap_timerfd_create(int clockid, int flags)
2446 fd = libc_timerfd_create(clockid, flags);
2448 swrap_remove_stale(fd);
2454 int timerfd_create(int clockid, int flags)
2456 return swrap_timerfd_create(clockid, flags);
2460 /****************************************************************************
2462 ***************************************************************************/
2464 static int swrap_pipe(int pipefd[2])
2468 rc = libc_pipe(pipefd);
2470 swrap_remove_stale(pipefd[0]);
2471 swrap_remove_stale(pipefd[1]);
2477 int pipe(int pipefd[2])
2479 return swrap_pipe(pipefd);
2482 /****************************************************************************
2484 ***************************************************************************/
2486 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2488 struct socket_info *parent_si, *child_si;
2489 struct socket_info_fd *child_fi;
2491 struct swrap_address un_addr = {
2492 .sa_socklen = sizeof(struct sockaddr_un),
2494 struct swrap_address un_my_addr = {
2495 .sa_socklen = sizeof(struct sockaddr_un),
2497 struct swrap_address in_addr = {
2498 .sa_socklen = sizeof(struct sockaddr_storage),
2500 struct swrap_address in_my_addr = {
2501 .sa_socklen = sizeof(struct sockaddr_storage),
2505 parent_si = find_socket_info(s);
2507 return libc_accept(s, addr, addrlen);
2511 * assume out sockaddr have the same size as the in parent
2514 in_addr.sa_socklen = socket_length(parent_si->family);
2515 if (in_addr.sa_socklen <= 0) {
2520 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2522 if (errno == ENOTSOCK) {
2523 /* Remove stale fds */
2524 swrap_remove_stale(s);
2531 ret = sockaddr_convert_from_un(parent_si,
2536 &in_addr.sa_socklen);
2542 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2543 memset(child_si, 0, sizeof(struct socket_info));
2545 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2546 if (child_fi == NULL) {
2555 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2557 child_si->family = parent_si->family;
2558 child_si->type = parent_si->type;
2559 child_si->protocol = parent_si->protocol;
2560 child_si->bound = 1;
2561 child_si->is_server = 1;
2562 child_si->connected = 1;
2564 child_si->peername = (struct swrap_address) {
2565 .sa_socklen = in_addr.sa_socklen,
2567 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2569 if (addr != NULL && addrlen != NULL) {
2570 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2572 memcpy(addr, &in_addr.sa.ss, copy_len);
2574 *addrlen = in_addr.sa_socklen;
2577 ret = libc_getsockname(fd,
2579 &un_my_addr.sa_socklen);
2587 ret = sockaddr_convert_from_un(child_si,
2589 un_my_addr.sa_socklen,
2592 &in_my_addr.sa_socklen);
2600 SWRAP_LOG(SWRAP_LOG_TRACE,
2601 "accept() path=%s, fd=%d",
2602 un_my_addr.sa.un.sun_path, s);
2604 child_si->myname = (struct swrap_address) {
2605 .sa_socklen = in_my_addr.sa_socklen,
2607 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2609 SWRAP_DLIST_ADD(sockets, child_si);
2612 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2613 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2614 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2620 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2621 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2623 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2626 return swrap_accept(s, addr, (socklen_t *)addrlen);
2629 static int autobind_start_init;
2630 static int autobind_start;
2632 /* using sendto() or connect() on an unbound socket would give the
2633 recipient no way to reply, as unlike UDP and TCP, a unix domain
2634 socket can't auto-assign ephemeral port numbers, so we need to
2636 Note: this might change the family from ipv6 to ipv4
2638 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2640 struct swrap_address un_addr = {
2641 .sa_socklen = sizeof(struct sockaddr_un),
2649 if (autobind_start_init != 1) {
2650 autobind_start_init = 1;
2651 autobind_start = getpid();
2652 autobind_start %= 50000;
2653 autobind_start += 10000;
2656 un_addr.sa.un.sun_family = AF_UNIX;
2660 struct sockaddr_in in;
2664 type = SOCKET_TYPE_CHAR_TCP;
2667 type = SOCKET_TYPE_CHAR_UDP;
2670 errno = ESOCKTNOSUPPORT;
2674 memset(&in, 0, sizeof(in));
2675 in.sin_family = AF_INET;
2676 in.sin_addr.s_addr = htonl(127<<24 |
2677 socket_wrapper_default_iface());
2679 si->myname = (struct swrap_address) {
2680 .sa_socklen = sizeof(in),
2682 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2687 struct sockaddr_in6 in6;
2689 if (si->family != family) {
2690 errno = ENETUNREACH;
2696 type = SOCKET_TYPE_CHAR_TCP_V6;
2699 type = SOCKET_TYPE_CHAR_UDP_V6;
2702 errno = ESOCKTNOSUPPORT;
2706 memset(&in6, 0, sizeof(in6));
2707 in6.sin6_family = AF_INET6;
2708 in6.sin6_addr = *swrap_ipv6();
2709 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2711 si->myname = (struct swrap_address) {
2712 .sa_socklen = sizeof(in6),
2714 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2719 errno = ESOCKTNOSUPPORT;
2723 if (autobind_start > 60000) {
2724 autobind_start = 10000;
2727 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2728 port = autobind_start + i;
2729 snprintf(un_addr.sa.un.sun_path, un_addr.sa_socklen,
2730 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2731 type, socket_wrapper_default_iface(), port);
2732 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2734 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2735 if (ret == -1) return ret;
2737 si->un_addr = un_addr.sa.un;
2740 autobind_start = port + 1;
2743 if (i == SOCKET_MAX_SOCKETS) {
2744 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2745 "interface "SOCKET_FORMAT,
2748 socket_wrapper_default_iface(),
2754 si->family = family;
2755 set_port(si->family, port, &si->myname);
2760 /****************************************************************************
2762 ***************************************************************************/
2764 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2768 struct swrap_address un_addr = {
2769 .sa_socklen = sizeof(struct sockaddr_un),
2771 struct socket_info *si = find_socket_info(s);
2775 return libc_connect(s, serv_addr, addrlen);
2778 if (si->bound == 0) {
2779 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2780 if (ret == -1) return -1;
2783 if (si->family != serv_addr->sa_family) {
2788 ret = sockaddr_convert_to_un(si, serv_addr,
2789 addrlen, &un_addr.sa.un, 0, &bcast);
2790 if (ret == -1) return -1;
2793 errno = ENETUNREACH;
2797 if (si->type == SOCK_DGRAM) {
2798 si->defer_connect = 1;
2801 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2803 ret = libc_connect(s,
2805 un_addr.sa_socklen);
2808 SWRAP_LOG(SWRAP_LOG_TRACE,
2809 "connect() path=%s, fd=%d",
2810 un_addr.un.sun_path, s);
2813 /* to give better errors */
2814 if (ret == -1 && errno == ENOENT) {
2815 errno = EHOSTUNREACH;
2819 si->peername = (struct swrap_address) {
2820 .sa_socklen = addrlen,
2823 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2827 * When we connect() on a socket than we have to bind the
2828 * outgoing connection on the interface we use for the
2829 * transport. We already bound it on the right interface
2830 * but here we have to update the name so getsockname()
2831 * returns correct information.
2833 if (si->bindname.sa_socklen > 0) {
2834 si->myname = (struct swrap_address) {
2835 .sa_socklen = si->bindname.sa_socklen,
2838 memcpy(&si->myname.sa.ss,
2839 &si->bindname.sa.ss,
2840 si->bindname.sa_socklen);
2842 /* Cleanup bindname */
2843 si->bindname = (struct swrap_address) {
2848 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2849 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2851 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2857 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2859 return swrap_connect(s, serv_addr, addrlen);
2862 /****************************************************************************
2864 ***************************************************************************/
2866 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2869 struct swrap_address un_addr = {
2870 .sa_socklen = sizeof(struct sockaddr_un),
2872 struct socket_info *si = find_socket_info(s);
2879 return libc_bind(s, myaddr, addrlen);
2882 switch (si->family) {
2884 const struct sockaddr_in *sin;
2885 if (addrlen < sizeof(struct sockaddr_in)) {
2886 bind_error = EINVAL;
2890 sin = (const struct sockaddr_in *)myaddr;
2892 if (sin->sin_family != AF_INET) {
2893 bind_error = EAFNOSUPPORT;
2896 /* special case for AF_UNSPEC */
2897 if (sin->sin_family == AF_UNSPEC &&
2898 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2907 const struct sockaddr_in6 *sin6;
2908 if (addrlen < sizeof(struct sockaddr_in6)) {
2909 bind_error = EINVAL;
2913 sin6 = (const struct sockaddr_in6 *)myaddr;
2915 if (sin6->sin6_family != AF_INET6) {
2916 bind_error = EAFNOSUPPORT;
2923 bind_error = EINVAL;
2927 if (bind_error != 0) {
2933 in_use = check_addr_port_in_use(myaddr, addrlen);
2940 si->myname.sa_socklen = addrlen;
2941 memcpy(&si->myname.sa.ss, myaddr, addrlen);
2943 ret = sockaddr_convert_to_un(si,
2949 if (ret == -1) return -1;
2951 unlink(un_addr.sa.un.sun_path);
2953 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
2955 SWRAP_LOG(SWRAP_LOG_TRACE,
2956 "bind() path=%s, fd=%d",
2957 un_addr.sa_un.sun_path, s);
2966 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2968 return swrap_bind(s, myaddr, addrlen);
2971 /****************************************************************************
2973 ***************************************************************************/
2975 #ifdef HAVE_BINDRESVPORT
2976 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2978 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2980 struct swrap_address myaddr = {
2981 .sa_socklen = sizeof(struct sockaddr_storage),
2984 static uint16_t port;
2989 #define SWRAP_STARTPORT 600
2990 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2991 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2994 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2998 salen = myaddr.sa_socklen;
3001 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3007 memset(&myaddr.sa.ss, 0, salen);
3012 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3015 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3017 salen = sizeof(struct sockaddr_in);
3018 sinp->sin_port = htons(port);
3022 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
3024 salen = sizeof(struct sockaddr_in6);
3025 sin6p->sin6_port = htons(port);
3029 errno = EAFNOSUPPORT;
3034 if (port > SWRAP_ENDPORT) {
3035 port = SWRAP_STARTPORT;
3038 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3039 if (rc == 0 || errno != EADDRINUSE) {
3047 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3049 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3053 /****************************************************************************
3055 ***************************************************************************/
3057 static int swrap_listen(int s, int backlog)
3060 struct socket_info *si = find_socket_info(s);
3063 return libc_listen(s, backlog);
3066 ret = libc_listen(s, backlog);
3071 int listen(int s, int backlog)
3073 return swrap_listen(s, backlog);
3076 /****************************************************************************
3078 ***************************************************************************/
3080 static FILE *swrap_fopen(const char *name, const char *mode)
3084 fp = libc_fopen(name, mode);
3086 int fd = fileno(fp);
3088 swrap_remove_stale(fd);
3094 FILE *fopen(const char *name, const char *mode)
3096 return swrap_fopen(name, mode);
3099 /****************************************************************************
3101 ***************************************************************************/
3103 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3107 ret = libc_vopen(pathname, flags, ap);
3110 * There are methods for closing descriptors (libc-internal code
3111 * paths, direct syscalls) which close descriptors in ways that
3112 * we can't intercept, so try to recover when we notice that
3115 swrap_remove_stale(ret);
3120 int open(const char *pathname, int flags, ...)
3125 va_start(ap, flags);
3126 fd = swrap_vopen(pathname, flags, ap);
3132 /****************************************************************************
3134 ***************************************************************************/
3136 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3138 struct socket_info *si = find_socket_info(s);
3142 return libc_getpeername(s, name, addrlen);
3145 if (si->peername.sa_socklen == 0)
3151 len = MIN(*addrlen, si->peername.sa_socklen);
3156 memcpy(name, &si->peername.sa.ss, len);
3157 *addrlen = si->peername.sa_socklen;
3162 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3163 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3165 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3168 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3171 /****************************************************************************
3173 ***************************************************************************/
3175 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3177 struct socket_info *si = find_socket_info(s);
3181 return libc_getsockname(s, name, addrlen);
3184 len = MIN(*addrlen, si->myname.sa_socklen);
3189 memcpy(name, &si->myname.sa.ss, len);
3190 *addrlen = si->myname.sa_socklen;
3195 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3196 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3198 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3201 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3204 /****************************************************************************
3206 ***************************************************************************/
3209 # ifdef SO_PROTOTYPE /* The Solaris name */
3210 # define SO_PROTOCOL SO_PROTOTYPE
3211 # endif /* SO_PROTOTYPE */
3212 #endif /* SO_PROTOCOL */
3214 static int swrap_getsockopt(int s, int level, int optname,
3215 void *optval, socklen_t *optlen)
3217 struct socket_info *si = find_socket_info(s);
3220 return libc_getsockopt(s,
3227 if (level == SOL_SOCKET) {
3231 if (optval == NULL || optlen == NULL ||
3232 *optlen < (socklen_t)sizeof(int)) {
3237 *optlen = sizeof(int);
3238 *(int *)optval = si->family;
3240 #endif /* SO_DOMAIN */
3244 if (optval == NULL || optlen == NULL ||
3245 *optlen < (socklen_t)sizeof(int)) {
3250 *optlen = sizeof(int);
3251 *(int *)optval = si->protocol;
3253 #endif /* SO_PROTOCOL */
3255 if (optval == NULL || optlen == NULL ||
3256 *optlen < (socklen_t)sizeof(int)) {
3261 *optlen = sizeof(int);
3262 *(int *)optval = si->type;
3265 return libc_getsockopt(s,
3273 errno = ENOPROTOOPT;
3277 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3278 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3280 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3283 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3286 /****************************************************************************
3288 ***************************************************************************/
3290 static int swrap_setsockopt(int s, int level, int optname,
3291 const void *optval, socklen_t optlen)
3293 struct socket_info *si = find_socket_info(s);
3296 return libc_setsockopt(s,
3303 if (level == SOL_SOCKET) {
3304 return libc_setsockopt(s,
3311 switch (si->family) {
3313 if (level == IPPROTO_IP) {
3315 if (optname == IP_PKTINFO) {
3316 si->pktinfo = AF_INET;
3318 #endif /* IP_PKTINFO */
3323 if (level == IPPROTO_IPV6) {
3324 #ifdef IPV6_RECVPKTINFO
3325 if (optname == IPV6_RECVPKTINFO) {
3326 si->pktinfo = AF_INET6;
3328 #endif /* IPV6_PKTINFO */
3333 errno = ENOPROTOOPT;
3338 int setsockopt(int s, int level, int optname,
3339 const void *optval, socklen_t optlen)
3341 return swrap_setsockopt(s, level, optname, optval, optlen);
3344 /****************************************************************************
3346 ***************************************************************************/
3348 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3350 struct socket_info *si = find_socket_info(s);
3356 return libc_vioctl(s, r, va);
3361 rc = libc_vioctl(s, r, va);
3365 value = *((int *)va_arg(ap, int *));
3367 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3368 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3369 } else if (value == 0) { /* END OF FILE */
3370 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3380 #ifdef HAVE_IOCTL_INT
3381 int ioctl(int s, int r, ...)
3383 int ioctl(int s, unsigned long int r, ...)
3391 rc = swrap_vioctl(s, (unsigned long int) r, va);
3402 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3405 # ifdef _ALIGN /* BSD */
3406 #define CMSG_ALIGN _ALIGN
3408 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3409 # endif /* _ALIGN */
3410 #endif /* CMSG_ALIGN */
3413 * @brief Add a cmsghdr to a msghdr.
3415 * This is an function to add any type of cmsghdr. It will operate on the
3416 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3417 * the buffer position after the added cmsg element. Hence, this function is
3418 * intended to be used with an intermediate msghdr and not on the original
3419 * one handed in by the client.
3421 * @param[in] msg The msghdr to which to add the cmsg.
3423 * @param[in] level The cmsg level to set.
3425 * @param[in] type The cmsg type to set.
3427 * @param[in] data The cmsg data to set.
3429 * @param[in] len the length of the data to set.
3431 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3437 size_t cmlen = CMSG_LEN(len);
3438 size_t cmspace = CMSG_SPACE(len);
3439 uint8_t cmbuf[cmspace];
3440 void *cast_ptr = (void *)cmbuf;
3441 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3444 memset(cmbuf, 0, cmspace);
3446 if (msg->msg_controllen < cmlen) {
3447 cmlen = msg->msg_controllen;
3448 msg->msg_flags |= MSG_CTRUNC;
3451 if (msg->msg_controllen < cmspace) {
3452 cmspace = msg->msg_controllen;
3456 * We copy the full input data into an intermediate cmsghdr first
3457 * in order to more easily cope with truncation.
3459 cm->cmsg_len = cmlen;
3460 cm->cmsg_level = level;
3461 cm->cmsg_type = type;
3462 memcpy(CMSG_DATA(cm), data, len);
3465 * We now copy the possibly truncated buffer.
3466 * We copy cmlen bytes, but consume cmspace bytes,
3467 * leaving the possible padding uninitialiazed.
3469 p = (uint8_t *)msg->msg_control;
3470 memcpy(p, cm, cmlen);
3472 msg->msg_control = p;
3473 msg->msg_controllen -= cmspace;
3478 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3481 /* Add packet info */
3482 switch (si->pktinfo) {
3483 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3485 struct sockaddr_in *sin;
3486 #if defined(HAVE_STRUCT_IN_PKTINFO)
3487 struct in_pktinfo pkt;
3488 #elif defined(IP_RECVDSTADDR)
3492 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3493 sin = &si->bindname.sa.in;
3495 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3498 sin = &si->myname.sa.in;
3503 #if defined(HAVE_STRUCT_IN_PKTINFO)
3504 pkt.ipi_ifindex = socket_wrapper_default_iface();
3505 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3506 #elif defined(IP_RECVDSTADDR)
3507 pkt = sin->sin_addr;
3510 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3515 #endif /* IP_PKTINFO */
3516 #if defined(HAVE_IPV6)
3518 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3519 struct sockaddr_in6 *sin6;
3520 struct in6_pktinfo pkt6;
3522 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3523 sin6 = &si->bindname.sa.in6;
3525 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3528 sin6 = &si->myname.sa.in6;
3533 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3534 pkt6.ipi6_addr = sin6->sin6_addr;
3536 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3537 &pkt6, sizeof(pkt6));
3538 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3542 #endif /* IPV6_PKTINFO */
3550 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3551 struct msghdr *omsg)
3555 if (si->pktinfo > 0) {
3556 rc = swrap_msghdr_add_pktinfo(si, omsg);
3562 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3564 size_t *cm_data_space);
3565 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3567 size_t *cm_data_space);
3569 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3571 size_t *cm_data_space) {
3572 struct cmsghdr *cmsg;
3576 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3580 for (cmsg = CMSG_FIRSTHDR(msg);
3582 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3583 switch (cmsg->cmsg_level) {
3585 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3590 rc = swrap_sendmsg_copy_cmsg(cmsg,
3600 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3602 size_t *cm_data_space)
3609 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3611 p = realloc((*cm_data), cmspace);
3617 p = (*cm_data) + (*cm_data_space);
3618 *cm_data_space = cmspace;
3620 memcpy(p, cmsg, cmsg->cmsg_len);
3625 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3627 size_t *cm_data_space);
3630 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3632 size_t *cm_data_space)
3636 switch(cmsg->cmsg_type) {
3639 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3646 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3658 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3660 size_t *cm_data_space)
3662 (void)cmsg; /* unused */
3663 (void)cm_data; /* unused */
3664 (void)cm_data_space; /* unused */
3667 * Passing a IP pktinfo to a unix socket might be rejected by the
3668 * Kernel, at least on FreeBSD. So skip this cmsg.
3672 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3674 static ssize_t swrap_sendmsg_before(int fd,
3675 struct socket_info *si,
3677 struct iovec *tmp_iov,
3678 struct sockaddr_un *tmp_un,
3679 const struct sockaddr_un **to_un,
3680 const struct sockaddr **to,
3698 if (!si->connected) {
3703 if (msg->msg_iovlen == 0) {
3707 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3709 nlen = len + msg->msg_iov[i].iov_len;
3710 if (nlen > SOCKET_MAX_PACKET) {
3714 msg->msg_iovlen = i;
3715 if (msg->msg_iovlen == 0) {
3716 *tmp_iov = msg->msg_iov[0];
3717 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3718 msg->msg_iov = tmp_iov;
3719 msg->msg_iovlen = 1;
3724 if (si->connected) {
3725 if (msg->msg_name) {
3730 const struct sockaddr *msg_name;
3731 msg_name = (const struct sockaddr *)msg->msg_name;
3733 if (msg_name == NULL) {
3739 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3741 if (ret == -1) return -1;
3749 msg->msg_name = tmp_un;
3750 msg->msg_namelen = sizeof(*tmp_un);
3753 if (si->bound == 0) {
3754 ret = swrap_auto_bind(fd, si, si->family);
3756 if (errno == ENOTSOCK) {
3757 swrap_remove_stale(fd);
3760 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3766 if (!si->defer_connect) {
3770 ret = sockaddr_convert_to_un(si,
3772 si->peername.sa_socklen,
3776 if (ret == -1) return -1;
3778 ret = libc_connect(fd,
3779 (struct sockaddr *)(void *)tmp_un,
3782 /* to give better errors */
3783 if (ret == -1 && errno == ENOENT) {
3784 errno = EHOSTUNREACH;
3791 si->defer_connect = 0;
3794 errno = EHOSTUNREACH;
3798 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3799 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3800 uint8_t *cmbuf = NULL;
3803 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3810 msg->msg_controllen = 0;
3811 msg->msg_control = NULL;
3812 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3813 memcpy(msg->msg_control, cmbuf, cmlen);
3814 msg->msg_controllen = cmlen;
3823 static void swrap_sendmsg_after(int fd,
3824 struct socket_info *si,
3826 const struct sockaddr *to,
3829 int saved_errno = errno;
3836 /* to give better errors */
3838 if (saved_errno == ENOENT) {
3839 saved_errno = EHOSTUNREACH;
3840 } else if (saved_errno == ENOTSOCK) {
3841 /* If the fd is not a socket, remove it */
3842 swrap_remove_stale(fd);
3846 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3847 avail += msg->msg_iov[i].iov_len;
3851 remain = MIN(80, avail);
3856 /* we capture it as one single packet */
3857 buf = (uint8_t *)malloc(remain);
3859 /* we just not capture the packet */
3860 errno = saved_errno;
3864 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3865 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3867 msg->msg_iov[i].iov_base,
3870 remain -= this_time;
3877 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3878 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3880 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3885 if (si->connected) {
3886 to = &si->peername.sa.s;
3889 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3890 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3892 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3898 errno = saved_errno;
3901 static int swrap_recvmsg_before(int fd,
3902 struct socket_info *si,
3904 struct iovec *tmp_iov)
3909 (void)fd; /* unused */
3913 if (!si->connected) {
3918 if (msg->msg_iovlen == 0) {
3922 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3924 nlen = len + msg->msg_iov[i].iov_len;
3925 if (nlen > SOCKET_MAX_PACKET) {
3929 msg->msg_iovlen = i;
3930 if (msg->msg_iovlen == 0) {
3931 *tmp_iov = msg->msg_iov[0];
3932 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3933 msg->msg_iov = tmp_iov;
3934 msg->msg_iovlen = 1;
3939 if (msg->msg_name == NULL) {
3944 if (msg->msg_iovlen == 0) {
3948 if (si->bound == 0) {
3949 ret = swrap_auto_bind(fd, si, si->family);
3952 * When attempting to read or write to a
3953 * descriptor, if an underlying autobind fails
3954 * because it's not a socket, stop intercepting
3955 * uses of that descriptor.
3957 if (errno == ENOTSOCK) {
3958 swrap_remove_stale(fd);
3961 SWRAP_LOG(SWRAP_LOG_ERROR,
3962 "swrap_recvmsg_before failed");
3969 errno = EHOSTUNREACH;
3976 static int swrap_recvmsg_after(int fd,
3977 struct socket_info *si,
3979 const struct sockaddr_un *un_addr,
3980 socklen_t un_addrlen,
3983 int saved_errno = errno;
3985 uint8_t *buf = NULL;
3991 /* to give better errors */
3993 if (saved_errno == ENOENT) {
3994 saved_errno = EHOSTUNREACH;
3995 } else if (saved_errno == ENOTSOCK) {
3996 /* If the fd is not a socket, remove it */
3997 swrap_remove_stale(fd);
4001 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4002 avail += msg->msg_iov[i].iov_len;
4011 remain = MIN(80, avail);
4016 /* we capture it as one single packet */
4017 buf = (uint8_t *)malloc(remain);
4019 /* we just not capture the packet */
4020 errno = saved_errno;
4024 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4025 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4027 msg->msg_iov[i].iov_base,
4030 remain -= this_time;
4035 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4036 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4037 } else if (ret == 0) { /* END OF FILE */
4038 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4039 } else if (ret > 0) {
4040 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4049 if (un_addr != NULL) {
4050 rc = sockaddr_convert_from_un(si,
4060 swrap_pcap_dump_packet(si,
4066 swrap_pcap_dump_packet(si,
4079 errno = saved_errno;
4081 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4083 msg->msg_controllen > 0 &&
4084 msg->msg_control != NULL) {
4085 rc = swrap_msghdr_add_socket_info(si, msg);
4095 /****************************************************************************
4097 ***************************************************************************/
4099 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4100 struct sockaddr *from, socklen_t *fromlen)
4102 struct swrap_address from_addr = {
4103 .sa_socklen = sizeof(struct sockaddr_un),
4106 struct socket_info *si = find_socket_info(s);
4107 struct swrap_address saddr = {
4108 .sa_socklen = sizeof(struct sockaddr_storage),
4115 return libc_recvfrom(s,
4127 if (from != NULL && fromlen != NULL) {
4128 msg.msg_name = from; /* optional address */
4129 msg.msg_namelen = *fromlen; /* size of address */
4131 msg.msg_name = &saddr.sa.s; /* optional address */
4132 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4134 msg.msg_iov = &tmp; /* scatter/gather array */
4135 msg.msg_iovlen = 1; /* # elements in msg_iov */
4136 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4137 msg.msg_control = NULL; /* ancillary data, see below */
4138 msg.msg_controllen = 0; /* ancillary data buffer len */
4139 msg.msg_flags = 0; /* flags on received message */
4142 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4147 buf = msg.msg_iov[0].iov_base;
4148 len = msg.msg_iov[0].iov_len;
4150 ret = libc_recvfrom(s,
4155 &from_addr.sa_socklen);
4160 tret = swrap_recvmsg_after(s,
4164 from_addr.sa_socklen,
4170 if (from != NULL && fromlen != NULL) {
4171 *fromlen = msg.msg_namelen;
4177 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4178 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4179 struct sockaddr *from, Psocklen_t fromlen)
4181 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4182 struct sockaddr *from, socklen_t *fromlen)
4185 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4188 /****************************************************************************
4190 ***************************************************************************/
4192 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4193 const struct sockaddr *to, socklen_t tolen)
4197 struct swrap_address un_addr = {
4198 .sa_socklen = sizeof(struct sockaddr_un),
4200 const struct sockaddr_un *to_un = NULL;
4203 struct socket_info *si = find_socket_info(s);
4207 return libc_sendto(s, buf, len, flags, to, tolen);
4210 tmp.iov_base = discard_const_p(char, buf);
4214 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4215 msg.msg_namelen = tolen; /* size of address */
4216 msg.msg_iov = &tmp; /* scatter/gather array */
4217 msg.msg_iovlen = 1; /* # elements in msg_iov */
4218 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4219 msg.msg_control = NULL; /* ancillary data, see below */
4220 msg.msg_controllen = 0; /* ancillary data buffer len */
4221 msg.msg_flags = 0; /* flags on received message */
4224 rc = swrap_sendmsg_before(s,
4236 buf = msg.msg_iov[0].iov_base;
4237 len = msg.msg_iov[0].iov_len;
4242 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4245 type = SOCKET_TYPE_CHAR_UDP;
4247 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4248 snprintf(un_addr.sa.un.sun_path,
4249 sizeof(un_addr.sa.un.sun_path),
4251 socket_wrapper_dir(), type, iface, prt);
4252 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4254 /* ignore the any errors in broadcast sends */
4260 un_addr.sa_socklen);
4263 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4268 ret = libc_sendto(s,
4272 (struct sockaddr *)msg.msg_name,
4275 swrap_sendmsg_after(s, si, &msg, to, ret);
4280 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4281 const struct sockaddr *to, socklen_t tolen)
4283 return swrap_sendto(s, buf, len, flags, to, tolen);
4286 /****************************************************************************
4288 ***************************************************************************/
4290 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4292 struct socket_info *si;
4294 struct swrap_address saddr = {
4295 .sa_socklen = sizeof(struct sockaddr_storage),
4301 si = find_socket_info(s);
4303 return libc_recv(s, buf, len, flags);
4310 msg.msg_name = &saddr.sa.s; /* optional address */
4311 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4312 msg.msg_iov = &tmp; /* scatter/gather array */
4313 msg.msg_iovlen = 1; /* # elements in msg_iov */
4314 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4315 msg.msg_control = NULL; /* ancillary data, see below */
4316 msg.msg_controllen = 0; /* ancillary data buffer len */
4317 msg.msg_flags = 0; /* flags on received message */
4320 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4325 buf = msg.msg_iov[0].iov_base;
4326 len = msg.msg_iov[0].iov_len;
4328 ret = libc_recv(s, buf, len, flags);
4330 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4338 ssize_t recv(int s, void *buf, size_t len, int flags)
4340 return swrap_recv(s, buf, len, flags);
4343 /****************************************************************************
4345 ***************************************************************************/
4347 static ssize_t swrap_read(int s, void *buf, size_t len)
4349 struct socket_info *si;
4352 struct swrap_address saddr = {
4353 .sa_socklen = sizeof(struct sockaddr_storage),
4358 si = find_socket_info(s);
4360 return libc_read(s, buf, len);
4367 msg.msg_name = &saddr.sa.ss; /* optional address */
4368 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4369 msg.msg_iov = &tmp; /* scatter/gather array */
4370 msg.msg_iovlen = 1; /* # elements in msg_iov */
4371 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4372 msg.msg_control = NULL; /* ancillary data, see below */
4373 msg.msg_controllen = 0; /* ancillary data buffer len */
4374 msg.msg_flags = 0; /* flags on received message */
4377 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4379 if (tret == -ENOTSOCK) {
4380 return libc_read(s, buf, len);
4385 buf = msg.msg_iov[0].iov_base;
4386 len = msg.msg_iov[0].iov_len;
4388 ret = libc_read(s, buf, len);
4390 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4398 ssize_t read(int s, void *buf, size_t len)
4400 return swrap_read(s, buf, len);
4403 /****************************************************************************
4405 ***************************************************************************/
4407 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4411 struct sockaddr_un un_addr;
4414 struct socket_info *si = find_socket_info(s);
4417 return libc_send(s, buf, len, flags);
4420 tmp.iov_base = discard_const_p(char, buf);
4424 msg.msg_name = NULL; /* optional address */
4425 msg.msg_namelen = 0; /* size of address */
4426 msg.msg_iov = &tmp; /* scatter/gather array */
4427 msg.msg_iovlen = 1; /* # elements in msg_iov */
4428 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4429 msg.msg_control = NULL; /* ancillary data, see below */
4430 msg.msg_controllen = 0; /* ancillary data buffer len */
4431 msg.msg_flags = 0; /* flags on received message */
4434 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4439 buf = msg.msg_iov[0].iov_base;
4440 len = msg.msg_iov[0].iov_len;
4442 ret = libc_send(s, buf, len, flags);
4444 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4449 ssize_t send(int s, const void *buf, size_t len, int flags)
4451 return swrap_send(s, buf, len, flags);
4454 /****************************************************************************
4456 ***************************************************************************/
4458 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4460 struct swrap_address from_addr = {
4461 .sa_socklen = sizeof(struct sockaddr_un),
4463 struct socket_info *si;
4466 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4467 size_t msg_ctrllen_filled;
4468 size_t msg_ctrllen_left;
4474 si = find_socket_info(s);
4476 return libc_recvmsg(s, omsg, flags);
4479 tmp.iov_base = NULL;
4483 msg.msg_name = &from_addr.sa; /* optional address */
4484 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4485 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4486 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4487 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4488 msg_ctrllen_filled = 0;
4489 msg_ctrllen_left = omsg->msg_controllen;
4491 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4492 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4493 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4496 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4501 ret = libc_recvmsg(s, &msg, flags);
4503 msg.msg_name = omsg->msg_name;
4504 msg.msg_namelen = omsg->msg_namelen;
4506 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4507 msg_ctrllen_filled += msg.msg_controllen;
4508 msg_ctrllen_left -= msg.msg_controllen;
4510 if (omsg->msg_control != NULL) {
4513 p = omsg->msg_control;
4514 p += msg_ctrllen_filled;
4516 msg.msg_control = p;
4517 msg.msg_controllen = msg_ctrllen_left;
4519 msg.msg_control = NULL;
4520 msg.msg_controllen = 0;
4524 rc = swrap_recvmsg_after(s,
4528 from_addr.sa_socklen,
4534 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4535 if (omsg->msg_control != NULL) {
4536 /* msg.msg_controllen = space left */
4537 msg_ctrllen_left = msg.msg_controllen;
4538 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4541 /* Update the original message length */
4542 omsg->msg_controllen = msg_ctrllen_filled;
4543 omsg->msg_flags = msg.msg_flags;
4545 omsg->msg_iovlen = msg.msg_iovlen;
4550 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4552 return swrap_recvmsg(sockfd, msg, flags);
4555 /****************************************************************************
4557 ***************************************************************************/
4559 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4563 struct sockaddr_un un_addr;
4564 const struct sockaddr_un *to_un = NULL;
4565 const struct sockaddr *to = NULL;
4568 struct socket_info *si = find_socket_info(s);
4572 return libc_sendmsg(s, omsg, flags);
4575 ZERO_STRUCT(un_addr);
4577 tmp.iov_base = NULL;
4581 msg.msg_name = omsg->msg_name; /* optional address */
4582 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4583 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4584 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4585 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4586 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4587 /* omsg is a const so use a local buffer for modifications */
4588 uint8_t cmbuf[omsg->msg_controllen];
4590 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4592 msg.msg_control = cmbuf; /* ancillary data, see below */
4593 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4595 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4598 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4606 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4614 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4615 avail += msg.msg_iov[i].iov_len;
4621 /* we capture it as one single packet */
4622 buf = (uint8_t *)malloc(remain);
4627 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4628 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4630 msg.msg_iov[i].iov_base,
4633 remain -= this_time;
4636 type = SOCKET_TYPE_CHAR_UDP;
4638 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4639 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4640 socket_wrapper_dir(), type, iface, prt);
4641 if (stat(un_addr.sun_path, &st) != 0) continue;
4643 msg.msg_name = &un_addr; /* optional address */
4644 msg.msg_namelen = sizeof(un_addr); /* size of address */
4646 /* ignore the any errors in broadcast sends */
4647 libc_sendmsg(s, &msg, flags);
4650 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4656 ret = libc_sendmsg(s, &msg, flags);
4658 swrap_sendmsg_after(s, si, &msg, to, ret);
4663 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4665 return swrap_sendmsg(s, omsg, flags);
4668 /****************************************************************************
4670 ***************************************************************************/
4672 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4674 struct socket_info *si;
4677 struct swrap_address saddr = {
4678 .sa_socklen = sizeof(struct sockaddr_storage)
4683 si = find_socket_info(s);
4685 return libc_readv(s, vector, count);
4688 tmp.iov_base = NULL;
4692 msg.msg_name = &saddr.sa.s; /* optional address */
4693 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4694 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4695 msg.msg_iovlen = count; /* # elements in msg_iov */
4696 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4697 msg.msg_control = NULL; /* ancillary data, see below */
4698 msg.msg_controllen = 0; /* ancillary data buffer len */
4699 msg.msg_flags = 0; /* flags on received message */
4702 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4704 if (rc == -ENOTSOCK) {
4705 return libc_readv(s, vector, count);
4710 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4712 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4720 ssize_t readv(int s, const struct iovec *vector, int count)
4722 return swrap_readv(s, vector, count);
4725 /****************************************************************************
4727 ***************************************************************************/
4729 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4733 struct sockaddr_un un_addr;
4736 struct socket_info *si = find_socket_info(s);
4739 return libc_writev(s, vector, count);
4742 tmp.iov_base = NULL;
4746 msg.msg_name = NULL; /* optional address */
4747 msg.msg_namelen = 0; /* size of address */
4748 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4749 msg.msg_iovlen = count; /* # elements in msg_iov */
4750 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4751 msg.msg_control = NULL; /* ancillary data, see below */
4752 msg.msg_controllen = 0; /* ancillary data buffer len */
4753 msg.msg_flags = 0; /* flags on received message */
4756 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4758 if (rc == -ENOTSOCK) {
4759 return libc_readv(s, vector, count);
4764 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4766 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4771 ssize_t writev(int s, const struct iovec *vector, int count)
4773 return swrap_writev(s, vector, count);
4776 /****************************
4778 ***************************/
4780 static int swrap_close(int fd)
4782 struct socket_info *si = find_socket_info(fd);
4783 struct socket_info_fd *fi;
4787 return libc_close(fd);
4790 for (fi = si->fds; fi; fi = fi->next) {
4792 SWRAP_DLIST_REMOVE(si->fds, fi);
4799 /* there are still references left */
4800 return libc_close(fd);
4803 SWRAP_DLIST_REMOVE(sockets, si);
4805 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4806 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4809 ret = libc_close(fd);
4811 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
4812 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4813 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4816 if (si->un_addr.sun_path[0] != '\0') {
4817 unlink(si->un_addr.sun_path);
4826 return swrap_close(fd);
4829 /****************************
4831 ***************************/
4833 static int swrap_dup(int fd)
4835 struct socket_info *si;
4836 struct socket_info_fd *fi;
4838 si = find_socket_info(fd);
4841 return libc_dup(fd);
4844 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4850 fi->fd = libc_dup(fd);
4852 int saved_errno = errno;
4854 errno = saved_errno;
4858 /* Make sure we don't have an entry for the fd */
4859 swrap_remove_stale(fi->fd);
4861 SWRAP_DLIST_ADD(si->fds, fi);
4867 return swrap_dup(fd);
4870 /****************************
4872 ***************************/
4874 static int swrap_dup2(int fd, int newfd)
4876 struct socket_info *si;
4877 struct socket_info_fd *fi;
4879 si = find_socket_info(fd);
4882 return libc_dup2(fd, newfd);
4885 if (find_socket_info(newfd)) {
4886 /* dup2() does an implicit close of newfd, which we
4887 * need to emulate */
4891 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4897 fi->fd = libc_dup2(fd, newfd);
4899 int saved_errno = errno;
4901 errno = saved_errno;
4905 /* Make sure we don't have an entry for the fd */
4906 swrap_remove_stale(fi->fd);
4908 SWRAP_DLIST_ADD(si->fds, fi);
4912 int dup2(int fd, int newfd)
4914 return swrap_dup2(fd, newfd);
4917 /****************************
4919 ***************************/
4922 static int swrap_eventfd(int count, int flags)
4926 fd = libc_eventfd(count, flags);
4928 swrap_remove_stale(fd);
4934 int eventfd(int count, int flags)
4936 return swrap_eventfd(count, flags);
4940 /****************************
4942 ***************************/
4945 * This function is called when the library is unloaded and makes sure that
4946 * sockets get closed and the unix file for the socket are unlinked.
4948 void swrap_destructor(void)
4950 struct socket_info *s = sockets;
4953 struct socket_info_fd *f = s->fds;