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>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <arpa/inet.h>
75 /* GCC have printf type attribute check. */
76 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
77 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
79 #define PRINTF_ATTRIBUTE(a,b)
80 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
82 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
83 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
85 #define DESTRUCTOR_ATTRIBUTE
88 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
89 # define SWRAP_THREAD __thread
95 #define MIN(a,b) ((a)<(b)?(a):(b))
99 # define SPRIpid PRIu64
100 #elif SIZEOF_UID_T == 4
101 # define SPRIpid PRIu32
103 # define SPRIpid "%d" /* Sane default for most platforms */
104 #endif /* SIZEOF_UID_T */
107 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
110 #ifndef discard_const
111 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
114 #ifndef discard_const_p
115 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
118 #define SWRAP_DLIST_ADD(list,item) do { \
120 (item)->prev = NULL; \
121 (item)->next = NULL; \
124 (item)->prev = NULL; \
125 (item)->next = (list); \
126 (list)->prev = (item); \
131 #define SWRAP_DLIST_REMOVE(list,item) do { \
132 if ((list) == (item)) { \
133 (list) = (item)->next; \
135 (list)->prev = NULL; \
138 if ((item)->prev) { \
139 (item)->prev->next = (item)->next; \
141 if ((item)->next) { \
142 (item)->next->prev = (item)->prev; \
145 (item)->prev = NULL; \
146 (item)->next = NULL; \
149 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
150 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
152 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
155 /* we need to use a very terse format here as IRIX 6.4 silently
156 truncates names to 16 chars, so if we use a longer name then we
157 can't tell which port a packet came from with recvfrom()
159 with this format we have 8 chars left for the directory name
161 #define SOCKET_FORMAT "%c%02X%04X"
162 #define SOCKET_TYPE_CHAR_TCP 'T'
163 #define SOCKET_TYPE_CHAR_UDP 'U'
164 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
165 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
168 * Cut down to 1500 byte packets for stream sockets,
169 * which makes it easier to format PCAP capture files
170 * (as the caller will simply continue from here)
172 #define SOCKET_MAX_PACKET 1500
174 #define SOCKET_MAX_SOCKETS 1024
176 /* This limit is to avoid broadcast sendto() needing to stat too many
177 * files. It may be raised (with a performance cost) to up to 254
178 * without changing the format above */
179 #define MAX_WRAPPED_INTERFACES 40
181 struct socket_info_fd {
182 struct socket_info_fd *prev, *next;
188 struct socket_info_fd *fds;
201 struct sockaddr *myname;
202 socklen_t myname_len;
204 struct sockaddr *peername;
205 socklen_t peername_len;
208 unsigned long pck_snd;
209 unsigned long pck_rcv;
212 struct socket_info *prev, *next;
216 * File descriptors are shared between threads so we should share socket
219 struct socket_info *sockets;
221 /* Function prototypes */
223 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
226 # define SWRAP_LOG(...)
229 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
230 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
232 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
237 unsigned int lvl = 0;
239 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
244 va_start(va, format);
245 vsnprintf(buffer, sizeof(buffer), format, va);
250 case SWRAP_LOG_ERROR:
252 "SWRAP_ERROR("SPRIpid"): %s\n",
257 "SWRAP_WARN("SPRIpid"): %s\n",
260 case SWRAP_LOG_DEBUG:
262 "SWRAP_DEBUG("SPRIpid"): %s\n",
265 case SWRAP_LOG_TRACE:
267 "SWRAP_TRACE("SPRIpid"): %s\n",
275 /*********************************************************
276 * SWRAP LOADING LIBC FUNCTIONS
277 *********************************************************/
281 struct swrap_libc_fns {
282 int (*libc_accept)(int sockfd,
283 struct sockaddr *addr,
285 int (*libc_bind)(int sockfd,
286 const struct sockaddr *addr,
288 int (*libc_close)(int fd);
289 int (*libc_connect)(int sockfd,
290 const struct sockaddr *addr,
292 int (*libc_dup)(int fd);
293 int (*libc_dup2)(int oldfd, int newfd);
294 int (*libc_getpeername)(int sockfd,
295 struct sockaddr *addr,
297 int (*libc_getsockname)(int sockfd,
298 struct sockaddr *addr,
300 int (*libc_getsockopt)(int sockfd,
305 int (*libc_ioctl)(int d, unsigned long int request, ...);
306 int (*libc_listen)(int sockfd, int backlog);
307 int (*libc_read)(int fd, void *buf, size_t count);
308 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
309 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
310 int (*libc_recvfrom)(int sockfd,
314 struct sockaddr *src_addr,
316 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
317 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
318 int (*libc_sendto)(int sockfd,
322 const struct sockaddr *dst_addr,
324 int (*libc_setsockopt)(int sockfd,
329 int (*libc_socket)(int domain, int type, int protocol);
330 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
335 void *libsocket_handle;
342 struct swrap_libc_fns fns;
345 static struct swrap swrap;
348 static const char *socket_wrapper_dir(void);
350 #define LIBC_NAME "libc.so"
359 static const char *swrap_str_lib(enum swrap_lib lib)
366 case SWRAP_LIBSOCKET:
370 /* Compiler would warn us about unhandled enum value if we get here */
375 static void *swrap_load_lib_handle(enum swrap_lib lib)
377 int flags = RTLD_LAZY;
386 flags |= RTLD_DEEPBIND;
392 case SWRAP_LIBSOCKET:
393 #ifdef HAVE_LIBSOCKET
394 handle = swrap.libsocket_handle;
395 if (handle == NULL) {
396 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
397 char soname[256] = {0};
399 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
400 handle = dlopen(soname, flags);
403 swrap.libsocket_handle = handle;
409 handle = swrap.libc_handle;
410 if (handle == NULL) {
411 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
412 char soname[256] = {0};
414 snprintf(soname, sizeof(soname), "libc.so.%d", i);
415 handle = dlopen(soname, flags);
418 swrap.libc_handle = handle;
423 if (handle == NULL) {
424 SWRAP_LOG(SWRAP_LOG_ERROR,
425 "Failed to dlopen library: %s\n",
433 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
438 handle = swrap_load_lib_handle(lib);
440 func = dlsym(handle, fn_name);
442 SWRAP_LOG(SWRAP_LOG_ERROR,
443 "Failed to find %s: %s\n",
448 SWRAP_LOG(SWRAP_LOG_TRACE,
450 fn_name, swrap_str_lib(lib));
454 #define swrap_load_lib_function(lib, fn_name) \
455 if (swrap.fns.libc_##fn_name == NULL) { \
456 *(void **) (&swrap.fns.libc_##fn_name) = \
457 _swrap_load_lib_function(lib, #fn_name); \
464 * Functions expeciall from libc need to be loaded individually, you can't load
465 * all at once or gdb will segfault at startup. The same applies to valgrind and
466 * has probably something todo with with the linker.
467 * So we need load each function at the point it is called the first time.
469 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
471 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
473 return swrap.fns.libc_accept(sockfd, addr, addrlen);
476 static int libc_bind(int sockfd,
477 const struct sockaddr *addr,
480 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
482 return swrap.fns.libc_bind(sockfd, addr, addrlen);
485 static int libc_close(int fd)
487 swrap_load_lib_function(SWRAP_LIBC, close);
489 return swrap.fns.libc_close(fd);
492 static int libc_connect(int sockfd,
493 const struct sockaddr *addr,
496 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
498 return swrap.fns.libc_connect(sockfd, addr, addrlen);
501 static int libc_dup(int fd)
503 swrap_load_lib_function(SWRAP_LIBC, dup);
505 return swrap.fns.libc_dup(fd);
508 static int libc_dup2(int oldfd, int newfd)
510 swrap_load_lib_function(SWRAP_LIBC, dup2);
512 return swrap.fns.libc_dup2(oldfd, newfd);
515 static int libc_getpeername(int sockfd,
516 struct sockaddr *addr,
519 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
521 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
524 static int libc_getsockname(int sockfd,
525 struct sockaddr *addr,
528 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
530 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
533 static int libc_getsockopt(int sockfd,
539 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
541 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
544 static int libc_vioctl(int d, unsigned long int request, va_list ap)
550 swrap_load_lib_function(SWRAP_LIBC, ioctl);
552 for (i = 0; i < 4; i++) {
553 args[i] = va_arg(ap, long int);
556 rc = swrap.fns.libc_ioctl(d,
566 static int libc_listen(int sockfd, int backlog)
568 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
570 return swrap.fns.libc_listen(sockfd, backlog);
573 static int libc_read(int fd, void *buf, size_t count)
575 swrap_load_lib_function(SWRAP_LIBC, read);
577 return swrap.fns.libc_read(fd, buf, count);
580 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
582 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
584 return swrap.fns.libc_readv(fd, iov, iovcnt);
587 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
589 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
591 return swrap.fns.libc_recv(sockfd, buf, len, flags);
594 static int libc_recvfrom(int sockfd,
598 struct sockaddr *src_addr,
601 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
603 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
606 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
608 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
610 return swrap.fns.libc_send(sockfd, buf, len, flags);
613 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
615 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
617 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
620 static int libc_sendto(int sockfd,
624 const struct sockaddr *dst_addr,
627 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
629 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
632 static int libc_setsockopt(int sockfd,
638 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
640 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
643 static int libc_socket(int domain, int type, int protocol)
645 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
647 return swrap.fns.libc_socket(domain, type, protocol);
650 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
652 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
654 return swrap.fns.libc_writev(fd, iov, iovcnt);
657 /*********************************************************
658 * SWRAP HELPER FUNCTIONS
659 *********************************************************/
665 static const struct in6_addr *swrap_ipv6(void)
667 static struct in6_addr v;
668 static int initialized;
676 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
685 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
687 struct sockaddr *ret = (struct sockaddr *)malloc(len);
688 memcpy(ret, data, len);
692 static void set_port(int family, int prt, struct sockaddr *addr)
696 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
700 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
706 static size_t socket_length(int family)
710 return sizeof(struct sockaddr_in);
713 return sizeof(struct sockaddr_in6);
719 static const char *socket_wrapper_dir(void)
721 const char *s = getenv("SOCKET_WRAPPER_DIR");
725 if (strncmp(s, "./", 2) == 0) {
729 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
733 static unsigned int socket_wrapper_default_iface(void)
735 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
738 if (sscanf(s, "%u", &iface) == 1) {
739 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
745 return 1;/* 127.0.0.1 */
748 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
755 p = strrchr(un->sun_path, '/');
756 if (p) p++; else p = un->sun_path;
758 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
763 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
766 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
777 case SOCKET_TYPE_CHAR_TCP:
778 case SOCKET_TYPE_CHAR_UDP: {
779 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
781 if ((*len) < sizeof(*in2)) {
786 memset(in2, 0, sizeof(*in2));
787 in2->sin_family = AF_INET;
788 in2->sin_addr.s_addr = htonl((127<<24) | iface);
789 in2->sin_port = htons(prt);
795 case SOCKET_TYPE_CHAR_TCP_V6:
796 case SOCKET_TYPE_CHAR_UDP_V6: {
797 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
799 if ((*len) < sizeof(*in2)) {
804 memset(in2, 0, sizeof(*in2));
805 in2->sin6_family = AF_INET6;
806 in2->sin6_addr = *swrap_ipv6();
807 in2->sin6_addr.s6_addr[15] = iface;
808 in2->sin6_port = htons(prt);
822 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
830 if (bcast) *bcast = 0;
832 switch (inaddr->sa_family) {
834 const struct sockaddr_in *in =
835 (const struct sockaddr_in *)(const void *)inaddr;
836 unsigned int addr = ntohl(in->sin_addr.s_addr);
843 u_type = SOCKET_TYPE_CHAR_TCP;
846 u_type = SOCKET_TYPE_CHAR_UDP;
847 a_type = SOCKET_TYPE_CHAR_UDP;
848 b_type = SOCKET_TYPE_CHAR_UDP;
851 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
852 errno = ESOCKTNOSUPPORT;
856 prt = ntohs(in->sin_port);
857 if (a_type && addr == 0xFFFFFFFF) {
858 /* 255.255.255.255 only udp */
861 iface = socket_wrapper_default_iface();
862 } else if (b_type && addr == 0x7FFFFFFF) {
863 /* 127.255.255.255 only udp */
866 iface = socket_wrapper_default_iface();
867 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
871 iface = (addr & 0x000000FF);
876 if (bcast) *bcast = is_bcast;
881 const struct sockaddr_in6 *in =
882 (const struct sockaddr_in6 *)(const void *)inaddr;
883 struct in6_addr cmp1, cmp2;
887 type = SOCKET_TYPE_CHAR_TCP_V6;
890 type = SOCKET_TYPE_CHAR_UDP_V6;
893 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
894 errno = ESOCKTNOSUPPORT;
898 /* XXX no multicast/broadcast */
900 prt = ntohs(in->sin6_port);
902 cmp1 = *swrap_ipv6();
903 cmp2 = in->sin6_addr;
904 cmp2.s6_addr[15] = 0;
905 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
906 iface = in->sin6_addr.s6_addr[15];
916 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
922 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
928 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
929 socket_wrapper_dir());
930 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
931 /* the caller need to do more processing */
935 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
936 socket_wrapper_dir(), type, iface, prt);
937 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
942 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
951 if (bcast) *bcast = 0;
953 switch (si->family) {
955 const struct sockaddr_in *in =
956 (const struct sockaddr_in *)(const void *)inaddr;
957 unsigned int addr = ntohl(in->sin_addr.s_addr);
963 prt = ntohs(in->sin_port);
967 u_type = SOCKET_TYPE_CHAR_TCP;
968 d_type = SOCKET_TYPE_CHAR_TCP;
971 u_type = SOCKET_TYPE_CHAR_UDP;
972 d_type = SOCKET_TYPE_CHAR_UDP;
973 a_type = SOCKET_TYPE_CHAR_UDP;
974 b_type = SOCKET_TYPE_CHAR_UDP;
977 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
978 errno = ESOCKTNOSUPPORT;
986 iface = socket_wrapper_default_iface();
987 } else if (a_type && addr == 0xFFFFFFFF) {
988 /* 255.255.255.255 only udp */
991 iface = socket_wrapper_default_iface();
992 } else if (b_type && addr == 0x7FFFFFFF) {
993 /* 127.255.255.255 only udp */
996 iface = socket_wrapper_default_iface();
997 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1001 iface = (addr & 0x000000FF);
1003 errno = EADDRNOTAVAIL;
1010 const struct sockaddr_in6 *in =
1011 (const struct sockaddr_in6 *)(const void *)inaddr;
1012 struct in6_addr cmp1, cmp2;
1016 type = SOCKET_TYPE_CHAR_TCP_V6;
1019 type = SOCKET_TYPE_CHAR_UDP_V6;
1022 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1023 errno = ESOCKTNOSUPPORT;
1027 /* XXX no multicast/broadcast */
1029 prt = ntohs(in->sin6_port);
1031 cmp1 = *swrap_ipv6();
1032 cmp2 = in->sin6_addr;
1033 cmp2.s6_addr[15] = 0;
1034 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1035 iface = socket_wrapper_default_iface();
1036 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1037 iface = in->sin6_addr.s6_addr[15];
1039 errno = EADDRNOTAVAIL;
1047 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1048 errno = EADDRNOTAVAIL;
1053 if (bcast) *bcast = is_bcast;
1055 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1061 /* handle auto-allocation of ephemeral ports */
1062 for (prt = 5001; prt < 10000; prt++) {
1063 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1064 socket_wrapper_dir(), type, iface, prt);
1065 if (stat(un->sun_path, &st) == 0) continue;
1067 set_port(si->family, prt, si->myname);
1076 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1077 socket_wrapper_dir(), type, iface, prt);
1078 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1082 static struct socket_info *find_socket_info(int fd)
1084 struct socket_info *i;
1086 for (i = sockets; i; i = i->next) {
1087 struct socket_info_fd *f;
1088 for (f = i->fds; f; f = f->next) {
1098 static int sockaddr_convert_to_un(struct socket_info *si,
1099 const struct sockaddr *in_addr,
1101 struct sockaddr_un *out_addr,
1105 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1107 (void) in_len; /* unused */
1109 if (out_addr == NULL) {
1113 out->sa_family = AF_UNIX;
1114 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1115 out->sa_len = sizeof(*out_addr);
1118 switch (in_addr->sa_family) {
1128 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1129 errno = ESOCKTNOSUPPORT;
1133 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1135 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1141 errno = EAFNOSUPPORT;
1142 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1146 static int sockaddr_convert_from_un(const struct socket_info *si,
1147 const struct sockaddr_un *in_addr,
1148 socklen_t un_addrlen,
1150 struct sockaddr *out_addr,
1151 socklen_t *out_addrlen)
1155 if (out_addr == NULL || out_addrlen == NULL)
1158 if (un_addrlen == 0) {
1173 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1174 errno = ESOCKTNOSUPPORT;
1177 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1178 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1179 out_addr->sa_len = *out_addrlen;
1186 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1187 errno = EAFNOSUPPORT;
1191 enum swrap_packet_type {
1193 SWRAP_CONNECT_UNREACH,
1201 SWRAP_SENDTO_UNREACH,
1212 struct swrap_file_hdr {
1214 uint16_t version_major;
1215 uint16_t version_minor;
1218 uint32_t frame_max_len;
1219 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1222 #define SWRAP_FILE_HDR_SIZE 24
1224 struct swrap_packet_frame {
1226 uint32_t micro_seconds;
1227 uint32_t recorded_length;
1228 uint32_t full_length;
1230 #define SWRAP_PACKET_FRAME_SIZE 16
1232 union swrap_packet_ip {
1236 uint16_t packet_length;
1237 uint16_t identification;
1242 uint16_t hdr_checksum;
1246 #define SWRAP_PACKET_IP_V4_SIZE 20
1249 uint8_t flow_label_high;
1250 uint16_t flow_label_low;
1251 uint16_t payload_length;
1252 uint8_t next_header;
1254 uint8_t src_addr[16];
1255 uint8_t dest_addr[16];
1257 #define SWRAP_PACKET_IP_V6_SIZE 40
1259 #define SWRAP_PACKET_IP_SIZE 40
1261 union swrap_packet_payload {
1263 uint16_t source_port;
1273 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1275 uint16_t source_port;
1280 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1287 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1294 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1296 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1298 #define SWRAP_PACKET_MIN_ALLOC \
1299 (SWRAP_PACKET_FRAME_SIZE + \
1300 SWRAP_PACKET_IP_SIZE + \
1301 SWRAP_PACKET_PAYLOAD_SIZE)
1303 static const char *socket_wrapper_pcap_file(void)
1305 static int initialized = 0;
1306 static const char *s = NULL;
1307 static const struct swrap_file_hdr h;
1308 static const struct swrap_packet_frame f;
1309 static const union swrap_packet_ip i;
1310 static const union swrap_packet_payload p;
1312 if (initialized == 1) {
1318 * TODO: don't use the structs use plain buffer offsets
1319 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1321 * for now make sure we disable PCAP support
1322 * if the struct has alignment!
1324 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1327 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1330 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1333 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1336 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1339 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1342 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1345 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1348 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1351 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1355 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1359 if (strncmp(s, "./", 2) == 0) {
1365 static uint8_t *swrap_packet_init(struct timeval *tval,
1366 const struct sockaddr *src,
1367 const struct sockaddr *dest,
1369 const uint8_t *payload,
1371 unsigned long tcp_seqno,
1372 unsigned long tcp_ack,
1373 unsigned char tcp_ctl,
1375 size_t *_packet_len)
1379 struct swrap_packet_frame *frame;
1380 union swrap_packet_ip *ip;
1381 union swrap_packet_payload *pay;
1384 size_t nonwire_len = sizeof(*frame);
1385 size_t wire_hdr_len = 0;
1386 size_t wire_len = 0;
1387 size_t ip_hdr_len = 0;
1388 size_t icmp_hdr_len = 0;
1389 size_t icmp_truncate_len = 0;
1390 uint8_t protocol = 0, icmp_protocol = 0;
1391 const struct sockaddr_in *src_in = NULL;
1392 const struct sockaddr_in *dest_in = NULL;
1394 const struct sockaddr_in6 *src_in6 = NULL;
1395 const struct sockaddr_in6 *dest_in6 = NULL;
1400 switch (src->sa_family) {
1402 src_in = (const struct sockaddr_in *)src;
1403 dest_in = (const struct sockaddr_in *)dest;
1404 src_port = src_in->sin_port;
1405 dest_port = dest_in->sin_port;
1406 ip_hdr_len = sizeof(ip->v4);
1410 src_in6 = (const struct sockaddr_in6 *)src;
1411 dest_in6 = (const struct sockaddr_in6 *)dest;
1412 src_port = src_in6->sin6_port;
1413 dest_port = dest_in6->sin6_port;
1414 ip_hdr_len = sizeof(ip->v6);
1421 switch (socket_type) {
1423 protocol = 0x06; /* TCP */
1424 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1425 wire_len = wire_hdr_len + payload_len;
1429 protocol = 0x11; /* UDP */
1430 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1431 wire_len = wire_hdr_len + payload_len;
1439 icmp_protocol = protocol;
1440 switch (src->sa_family) {
1442 protocol = 0x01; /* ICMPv4 */
1443 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1447 protocol = 0x3A; /* ICMPv6 */
1448 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1452 if (wire_len > 64 ) {
1453 icmp_truncate_len = wire_len - 64;
1455 wire_hdr_len += icmp_hdr_len;
1456 wire_len += icmp_hdr_len;
1459 packet_len = nonwire_len + wire_len;
1460 alloc_len = packet_len;
1461 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1462 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1465 base = (uint8_t *)malloc(alloc_len);
1466 if (!base) return NULL;
1470 frame = (struct swrap_packet_frame *)buf;
1471 frame->seconds = tval->tv_sec;
1472 frame->micro_seconds = tval->tv_usec;
1473 frame->recorded_length = wire_len - icmp_truncate_len;
1474 frame->full_length = wire_len - icmp_truncate_len;
1475 buf += SWRAP_PACKET_FRAME_SIZE;
1477 ip = (union swrap_packet_ip *)buf;
1478 switch (src->sa_family) {
1480 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1482 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1483 ip->v4.identification = htons(0xFFFF);
1484 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
1485 ip->v4.fragment = htons(0x0000);
1487 ip->v4.protocol = protocol;
1488 ip->v4.hdr_checksum = htons(0x0000);
1489 ip->v4.src_addr = src_in->sin_addr.s_addr;
1490 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1491 buf += SWRAP_PACKET_IP_V4_SIZE;
1495 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1496 ip->v6.flow_label_high = 0x00;
1497 ip->v6.flow_label_low = 0x0000;
1498 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1499 ip->v6.next_header = protocol;
1500 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1501 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1502 buf += SWRAP_PACKET_IP_V6_SIZE;
1508 pay = (union swrap_packet_payload *)buf;
1509 switch (src->sa_family) {
1511 pay->icmp4.type = 0x03; /* destination unreachable */
1512 pay->icmp4.code = 0x01; /* host unreachable */
1513 pay->icmp4.checksum = htons(0x0000);
1514 pay->icmp4.unused = htonl(0x00000000);
1515 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1517 /* set the ip header in the ICMP payload */
1518 ip = (union swrap_packet_ip *)buf;
1519 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1521 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1522 ip->v4.identification = htons(0xFFFF);
1523 ip->v4.flags = 0x40; /* BIT 1 set - means don't fraqment */
1524 ip->v4.fragment = htons(0x0000);
1526 ip->v4.protocol = icmp_protocol;
1527 ip->v4.hdr_checksum = htons(0x0000);
1528 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1529 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1530 buf += SWRAP_PACKET_IP_V4_SIZE;
1532 src_port = dest_in->sin_port;
1533 dest_port = src_in->sin_port;
1537 pay->icmp6.type = 0x01; /* destination unreachable */
1538 pay->icmp6.code = 0x03; /* address unreachable */
1539 pay->icmp6.checksum = htons(0x0000);
1540 pay->icmp6.unused = htonl(0x00000000);
1541 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1543 /* set the ip header in the ICMP payload */
1544 ip = (union swrap_packet_ip *)buf;
1545 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1546 ip->v6.flow_label_high = 0x00;
1547 ip->v6.flow_label_low = 0x0000;
1548 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1549 ip->v6.next_header = protocol;
1550 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1551 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1552 buf += SWRAP_PACKET_IP_V6_SIZE;
1554 src_port = dest_in6->sin6_port;
1555 dest_port = src_in6->sin6_port;
1561 pay = (union swrap_packet_payload *)buf;
1563 switch (socket_type) {
1565 pay->tcp.source_port = src_port;
1566 pay->tcp.dest_port = dest_port;
1567 pay->tcp.seq_num = htonl(tcp_seqno);
1568 pay->tcp.ack_num = htonl(tcp_ack);
1569 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1570 pay->tcp.control = tcp_ctl;
1571 pay->tcp.window = htons(0x7FFF);
1572 pay->tcp.checksum = htons(0x0000);
1573 pay->tcp.urg = htons(0x0000);
1574 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1579 pay->udp.source_port = src_port;
1580 pay->udp.dest_port = dest_port;
1581 pay->udp.length = htons(8 + payload_len);
1582 pay->udp.checksum = htons(0x0000);
1583 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1588 if (payload && payload_len > 0) {
1589 memcpy(buf, payload, payload_len);
1592 *_packet_len = packet_len - icmp_truncate_len;
1596 static int swrap_get_pcap_fd(const char *fname)
1600 if (fd != -1) return fd;
1602 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1604 struct swrap_file_hdr file_hdr;
1605 file_hdr.magic = 0xA1B2C3D4;
1606 file_hdr.version_major = 0x0002;
1607 file_hdr.version_minor = 0x0004;
1608 file_hdr.timezone = 0x00000000;
1609 file_hdr.sigfigs = 0x00000000;
1610 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1611 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1613 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1620 fd = open(fname, O_WRONLY|O_APPEND, 0644);
1625 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1626 const struct sockaddr *addr,
1627 enum swrap_packet_type type,
1628 const void *buf, size_t len,
1631 const struct sockaddr *src_addr;
1632 const struct sockaddr *dest_addr;
1633 unsigned long tcp_seqno = 0;
1634 unsigned long tcp_ack = 0;
1635 unsigned char tcp_ctl = 0;
1636 int unreachable = 0;
1640 switch (si->family) {
1652 case SWRAP_CONNECT_SEND:
1653 if (si->type != SOCK_STREAM) return NULL;
1655 src_addr = si->myname;
1658 tcp_seqno = si->io.pck_snd;
1659 tcp_ack = si->io.pck_rcv;
1660 tcp_ctl = 0x02; /* SYN */
1662 si->io.pck_snd += 1;
1666 case SWRAP_CONNECT_RECV:
1667 if (si->type != SOCK_STREAM) return NULL;
1669 dest_addr = si->myname;
1672 tcp_seqno = si->io.pck_rcv;
1673 tcp_ack = si->io.pck_snd;
1674 tcp_ctl = 0x12; /** SYN,ACK */
1676 si->io.pck_rcv += 1;
1680 case SWRAP_CONNECT_UNREACH:
1681 if (si->type != SOCK_STREAM) return NULL;
1683 dest_addr = si->myname;
1686 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1687 tcp_seqno = si->io.pck_snd - 1;
1688 tcp_ack = si->io.pck_rcv;
1689 tcp_ctl = 0x02; /* SYN */
1694 case SWRAP_CONNECT_ACK:
1695 if (si->type != SOCK_STREAM) return NULL;
1697 src_addr = si->myname;
1700 tcp_seqno = si->io.pck_snd;
1701 tcp_ack = si->io.pck_rcv;
1702 tcp_ctl = 0x10; /* ACK */
1706 case SWRAP_ACCEPT_SEND:
1707 if (si->type != SOCK_STREAM) return NULL;
1709 dest_addr = si->myname;
1712 tcp_seqno = si->io.pck_rcv;
1713 tcp_ack = si->io.pck_snd;
1714 tcp_ctl = 0x02; /* SYN */
1716 si->io.pck_rcv += 1;
1720 case SWRAP_ACCEPT_RECV:
1721 if (si->type != SOCK_STREAM) return NULL;
1723 src_addr = si->myname;
1726 tcp_seqno = si->io.pck_snd;
1727 tcp_ack = si->io.pck_rcv;
1728 tcp_ctl = 0x12; /* SYN,ACK */
1730 si->io.pck_snd += 1;
1734 case SWRAP_ACCEPT_ACK:
1735 if (si->type != SOCK_STREAM) return NULL;
1737 dest_addr = si->myname;
1740 tcp_seqno = si->io.pck_rcv;
1741 tcp_ack = si->io.pck_snd;
1742 tcp_ctl = 0x10; /* ACK */
1747 src_addr = si->myname;
1748 dest_addr = si->peername;
1750 tcp_seqno = si->io.pck_snd;
1751 tcp_ack = si->io.pck_rcv;
1752 tcp_ctl = 0x18; /* PSH,ACK */
1754 si->io.pck_snd += len;
1758 case SWRAP_SEND_RST:
1759 dest_addr = si->myname;
1760 src_addr = si->peername;
1762 if (si->type == SOCK_DGRAM) {
1763 return swrap_marshall_packet(si, si->peername,
1764 SWRAP_SENDTO_UNREACH,
1765 buf, len, packet_len);
1768 tcp_seqno = si->io.pck_rcv;
1769 tcp_ack = si->io.pck_snd;
1770 tcp_ctl = 0x14; /** RST,ACK */
1774 case SWRAP_PENDING_RST:
1775 dest_addr = si->myname;
1776 src_addr = si->peername;
1778 if (si->type == SOCK_DGRAM) {
1782 tcp_seqno = si->io.pck_rcv;
1783 tcp_ack = si->io.pck_snd;
1784 tcp_ctl = 0x14; /* RST,ACK */
1789 dest_addr = si->myname;
1790 src_addr = si->peername;
1792 tcp_seqno = si->io.pck_rcv;
1793 tcp_ack = si->io.pck_snd;
1794 tcp_ctl = 0x18; /* PSH,ACK */
1796 si->io.pck_rcv += len;
1800 case SWRAP_RECV_RST:
1801 dest_addr = si->myname;
1802 src_addr = si->peername;
1804 if (si->type == SOCK_DGRAM) {
1808 tcp_seqno = si->io.pck_rcv;
1809 tcp_ack = si->io.pck_snd;
1810 tcp_ctl = 0x14; /* RST,ACK */
1815 src_addr = si->myname;
1818 si->io.pck_snd += len;
1822 case SWRAP_SENDTO_UNREACH:
1823 dest_addr = si->myname;
1830 case SWRAP_RECVFROM:
1831 dest_addr = si->myname;
1834 si->io.pck_rcv += len;
1838 case SWRAP_CLOSE_SEND:
1839 if (si->type != SOCK_STREAM) return NULL;
1841 src_addr = si->myname;
1842 dest_addr = si->peername;
1844 tcp_seqno = si->io.pck_snd;
1845 tcp_ack = si->io.pck_rcv;
1846 tcp_ctl = 0x11; /* FIN, ACK */
1848 si->io.pck_snd += 1;
1852 case SWRAP_CLOSE_RECV:
1853 if (si->type != SOCK_STREAM) return NULL;
1855 dest_addr = si->myname;
1856 src_addr = si->peername;
1858 tcp_seqno = si->io.pck_rcv;
1859 tcp_ack = si->io.pck_snd;
1860 tcp_ctl = 0x11; /* FIN,ACK */
1862 si->io.pck_rcv += 1;
1866 case SWRAP_CLOSE_ACK:
1867 if (si->type != SOCK_STREAM) return NULL;
1869 src_addr = si->myname;
1870 dest_addr = si->peername;
1872 tcp_seqno = si->io.pck_snd;
1873 tcp_ack = si->io.pck_rcv;
1874 tcp_ctl = 0x10; /* ACK */
1881 swrapGetTimeOfDay(&tv);
1883 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1884 (const uint8_t *)buf, len,
1885 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1889 static void swrap_dump_packet(struct socket_info *si,
1890 const struct sockaddr *addr,
1891 enum swrap_packet_type type,
1892 const void *buf, size_t len)
1894 const char *file_name;
1896 size_t packet_len = 0;
1899 file_name = socket_wrapper_pcap_file();
1904 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1909 fd = swrap_get_pcap_fd(file_name);
1911 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
1920 /****************************************************************************
1922 ***************************************************************************/
1924 static int swrap_socket(int family, int type, int protocol)
1926 struct socket_info *si;
1927 struct socket_info_fd *fi;
1929 int real_type = type;
1932 * Remove possible addition flags passed to socket() so
1933 * do not fail checking the type.
1934 * See https://lwn.net/Articles/281965/
1937 real_type &= ~SOCK_CLOEXEC;
1939 #ifdef SOCK_NONBLOCK
1940 real_type &= ~SOCK_NONBLOCK;
1943 if (socket_wrapper_dir() == NULL) {
1944 return libc_socket(family, type, protocol);
1954 return libc_socket(family, type, protocol);
1956 errno = EAFNOSUPPORT;
1960 switch (real_type) {
1966 errno = EPROTONOSUPPORT;
1974 if (real_type == SOCK_STREAM) {
1979 if (real_type == SOCK_DGRAM) {
1984 errno = EPROTONOSUPPORT;
1989 * We must call libc_socket with type, from the caller, not the version
1990 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
1992 fd = libc_socket(AF_UNIX, type, 0);
1994 if (fd == -1) return -1;
1996 si = (struct socket_info *)malloc(sizeof(struct socket_info));
1997 memset(si, 0, sizeof(struct socket_info));
2003 si->family = family;
2005 /* however, the rest of the socket_wrapper code expects just
2006 * the type, not the flags */
2007 si->type = real_type;
2008 si->protocol = protocol;
2010 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2019 SWRAP_DLIST_ADD(si->fds, fi);
2020 SWRAP_DLIST_ADD(sockets, si);
2025 int socket(int family, int type, int protocol)
2027 return swrap_socket(family, type, protocol);
2030 /****************************************************************************
2032 ***************************************************************************/
2034 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2036 struct socket_info *parent_si, *child_si;
2037 struct socket_info_fd *child_fi;
2039 struct sockaddr_un un_addr;
2040 socklen_t un_addrlen = sizeof(un_addr);
2041 struct sockaddr_un un_my_addr;
2042 socklen_t un_my_addrlen = sizeof(un_my_addr);
2043 struct sockaddr *my_addr;
2044 socklen_t my_addrlen, len;
2047 parent_si = find_socket_info(s);
2049 return libc_accept(s, addr, addrlen);
2053 * assume out sockaddr have the same size as the in parent
2056 my_addrlen = socket_length(parent_si->family);
2057 if (my_addrlen <= 0) {
2062 my_addr = (struct sockaddr *)malloc(my_addrlen);
2063 if (my_addr == NULL) {
2067 memset(&un_addr, 0, sizeof(un_addr));
2068 memset(&un_my_addr, 0, sizeof(un_my_addr));
2070 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2079 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2080 parent_si->family, my_addr, &len);
2087 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2088 memset(child_si, 0, sizeof(struct socket_info));
2090 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2091 if (child_fi == NULL) {
2101 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2103 child_si->family = parent_si->family;
2104 child_si->type = parent_si->type;
2105 child_si->protocol = parent_si->protocol;
2106 child_si->bound = 1;
2107 child_si->is_server = 1;
2108 child_si->connected = 1;
2110 child_si->peername_len = len;
2111 child_si->peername = sockaddr_dup(my_addr, len);
2113 if (addr != NULL && addrlen != NULL) {
2114 size_t copy_len = MIN(*addrlen, len);
2116 memcpy(addr, my_addr, copy_len);
2121 ret = libc_getsockname(fd,
2122 (struct sockaddr *)(void *)&un_my_addr,
2133 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2134 child_si->family, my_addr, &len);
2143 SWRAP_LOG(SWRAP_LOG_TRACE,
2144 "accept() path=%s, fd=%d",
2145 un_my_addr.sun_path, s);
2147 child_si->myname_len = len;
2148 child_si->myname = sockaddr_dup(my_addr, len);
2151 SWRAP_DLIST_ADD(sockets, child_si);
2154 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2155 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2156 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2162 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2163 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2165 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2168 return swrap_accept(s, addr, (socklen_t *)addrlen);
2171 static int autobind_start_init;
2172 static int autobind_start;
2174 /* using sendto() or connect() on an unbound socket would give the
2175 recipient no way to reply, as unlike UDP and TCP, a unix domain
2176 socket can't auto-assign emphemeral port numbers, so we need to
2178 Note: this might change the family from ipv6 to ipv4
2180 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2182 struct sockaddr_un un_addr;
2189 if (autobind_start_init != 1) {
2190 autobind_start_init = 1;
2191 autobind_start = getpid();
2192 autobind_start %= 50000;
2193 autobind_start += 10000;
2196 un_addr.sun_family = AF_UNIX;
2200 struct sockaddr_in in;
2204 type = SOCKET_TYPE_CHAR_TCP;
2207 type = SOCKET_TYPE_CHAR_UDP;
2210 errno = ESOCKTNOSUPPORT;
2214 memset(&in, 0, sizeof(in));
2215 in.sin_family = AF_INET;
2216 in.sin_addr.s_addr = htonl(127<<24 |
2217 socket_wrapper_default_iface());
2219 si->myname_len = sizeof(in);
2220 si->myname = sockaddr_dup(&in, si->myname_len);
2225 struct sockaddr_in6 in6;
2227 if (si->family != family) {
2228 errno = ENETUNREACH;
2234 type = SOCKET_TYPE_CHAR_TCP_V6;
2237 type = SOCKET_TYPE_CHAR_UDP_V6;
2240 errno = ESOCKTNOSUPPORT;
2244 memset(&in6, 0, sizeof(in6));
2245 in6.sin6_family = AF_INET6;
2246 in6.sin6_addr = *swrap_ipv6();
2247 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2248 si->myname_len = sizeof(in6);
2249 si->myname = sockaddr_dup(&in6, si->myname_len);
2254 errno = ESOCKTNOSUPPORT;
2258 if (autobind_start > 60000) {
2259 autobind_start = 10000;
2262 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2263 port = autobind_start + i;
2264 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2265 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2266 type, socket_wrapper_default_iface(), port);
2267 if (stat(un_addr.sun_path, &st) == 0) continue;
2269 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2271 if (ret == -1) return ret;
2273 si->tmp_path = strdup(un_addr.sun_path);
2275 autobind_start = port + 1;
2278 if (i == SOCKET_MAX_SOCKETS) {
2279 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2280 "interface "SOCKET_FORMAT,
2283 socket_wrapper_default_iface(),
2289 si->family = family;
2290 set_port(si->family, port, si->myname);
2295 /****************************************************************************
2297 ***************************************************************************/
2299 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2303 struct sockaddr_un un_addr;
2304 struct socket_info *si = find_socket_info(s);
2308 return libc_connect(s, serv_addr, addrlen);
2311 if (si->bound == 0) {
2312 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2313 if (ret == -1) return -1;
2316 if (si->family != serv_addr->sa_family) {
2321 ret = sockaddr_convert_to_un(si, serv_addr,
2322 addrlen, &un_addr, 0, &bcast);
2323 if (ret == -1) return -1;
2326 errno = ENETUNREACH;
2330 if (si->type == SOCK_DGRAM) {
2331 si->defer_connect = 1;
2334 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2336 ret = libc_connect(s,
2337 (struct sockaddr *)(void *)&un_addr,
2338 sizeof(struct sockaddr_un));
2341 SWRAP_LOG(SWRAP_LOG_TRACE,
2342 "connect() path=%s, fd=%d",
2343 un_addr.sun_path, s);
2346 /* to give better errors */
2347 if (ret == -1 && errno == ENOENT) {
2348 errno = EHOSTUNREACH;
2352 si->peername_len = addrlen;
2353 si->peername = sockaddr_dup(serv_addr, addrlen);
2356 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2357 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2359 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2365 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2367 return swrap_connect(s, serv_addr, addrlen);
2370 /****************************************************************************
2372 ***************************************************************************/
2374 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2377 struct sockaddr_un un_addr;
2378 struct socket_info *si = find_socket_info(s);
2381 return libc_bind(s, myaddr, addrlen);
2384 si->myname_len = addrlen;
2385 si->myname = sockaddr_dup(myaddr, addrlen);
2387 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2388 if (ret == -1) return -1;
2390 unlink(un_addr.sun_path);
2392 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2393 sizeof(struct sockaddr_un));
2395 SWRAP_LOG(SWRAP_LOG_TRACE,
2396 "bind() path=%s, fd=%d",
2397 un_addr.sun_path, s);
2406 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2408 return swrap_bind(s, myaddr, addrlen);
2411 /****************************************************************************
2413 ***************************************************************************/
2415 static int swrap_listen(int s, int backlog)
2418 struct socket_info *si = find_socket_info(s);
2421 return libc_listen(s, backlog);
2424 ret = libc_listen(s, backlog);
2429 int listen(int s, int backlog)
2431 return swrap_listen(s, backlog);
2434 /****************************************************************************
2436 ***************************************************************************/
2438 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2440 struct socket_info *si = find_socket_info(s);
2443 return libc_getpeername(s, name, addrlen);
2452 memcpy(name, si->peername, si->peername_len);
2453 *addrlen = si->peername_len;
2458 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2459 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
2461 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2464 return swrap_getpeername(s, name, (socklen_t *)addrlen);
2467 /****************************************************************************
2469 ***************************************************************************/
2471 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2473 struct socket_info *si = find_socket_info(s);
2476 return libc_getsockname(s, name, addrlen);
2479 memcpy(name, si->myname, si->myname_len);
2480 *addrlen = si->myname_len;
2485 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2486 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
2488 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2491 return swrap_getsockname(s, name, (socklen_t *)addrlen);
2494 /****************************************************************************
2496 ***************************************************************************/
2498 static int swrap_getsockopt(int s, int level, int optname,
2499 void *optval, socklen_t *optlen)
2501 struct socket_info *si = find_socket_info(s);
2504 return libc_getsockopt(s,
2511 if (level == SOL_SOCKET) {
2512 return libc_getsockopt(s,
2519 errno = ENOPROTOOPT;
2523 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2524 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
2526 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
2529 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
2532 /****************************************************************************
2534 ***************************************************************************/
2536 static int swrap_setsockopt(int s, int level, int optname,
2537 const void *optval, socklen_t optlen)
2539 struct socket_info *si = find_socket_info(s);
2542 return libc_setsockopt(s,
2549 if (level == SOL_SOCKET) {
2550 return libc_setsockopt(s,
2557 switch (si->family) {
2565 errno = ENOPROTOOPT;
2570 int setsockopt(int s, int level, int optname,
2571 const void *optval, socklen_t optlen)
2573 return swrap_setsockopt(s, level, optname, optval, optlen);
2576 /****************************************************************************
2578 ***************************************************************************/
2580 static int swrap_vioctl(int s, unsigned long int r, va_list va)
2582 struct socket_info *si = find_socket_info(s);
2588 return libc_vioctl(s, r, va);
2593 rc = libc_vioctl(s, r, va);
2597 value = *((int *)va_arg(ap, int *));
2599 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
2600 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2601 } else if (value == 0) { /* END OF FILE */
2602 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2612 #ifdef HAVE_IOCTL_INT
2613 int ioctl(int s, int r, ...)
2615 int ioctl(int s, unsigned long int r, ...)
2623 rc = swrap_vioctl(s, (unsigned long int) r, va);
2630 static ssize_t swrap_sendmsg_before(int fd,
2631 struct socket_info *si,
2633 struct iovec *tmp_iov,
2634 struct sockaddr_un *tmp_un,
2635 const struct sockaddr_un **to_un,
2636 const struct sockaddr **to,
2654 if (!si->connected) {
2659 if (msg->msg_iovlen == 0) {
2663 for (i=0; i < msg->msg_iovlen; i++) {
2665 nlen = len + msg->msg_iov[i].iov_len;
2666 if (nlen > SOCKET_MAX_PACKET) {
2670 msg->msg_iovlen = i;
2671 if (msg->msg_iovlen == 0) {
2672 *tmp_iov = msg->msg_iov[0];
2673 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
2674 msg->msg_iov = tmp_iov;
2675 msg->msg_iovlen = 1;
2680 if (si->connected) {
2681 if (msg->msg_name) {
2686 const struct sockaddr *msg_name;
2687 msg_name = (const struct sockaddr *)msg->msg_name;
2689 if (msg_name == NULL) {
2695 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
2697 if (ret == -1) return -1;
2705 msg->msg_name = tmp_un;
2706 msg->msg_namelen = sizeof(*tmp_un);
2709 if (si->bound == 0) {
2710 ret = swrap_auto_bind(fd, si, si->family);
2711 if (ret == -1) return -1;
2714 if (!si->defer_connect) {
2718 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
2720 if (ret == -1) return -1;
2722 ret = libc_connect(fd,
2723 (struct sockaddr *)(void *)tmp_un,
2726 /* to give better errors */
2727 if (ret == -1 && errno == ENOENT) {
2728 errno = EHOSTUNREACH;
2735 si->defer_connect = 0;
2738 errno = EHOSTUNREACH;
2745 static void swrap_sendmsg_after(struct socket_info *si,
2747 const struct sockaddr *to,
2750 int saved_errno = errno;
2757 /* to give better errors */
2758 if (ret == -1 && saved_errno == ENOENT) {
2759 saved_errno = EHOSTUNREACH;
2762 for (i=0; i < msg->msg_iovlen; i++) {
2763 avail += msg->msg_iov[i].iov_len;
2767 remain = MIN(80, avail);
2772 /* we capture it as one single packet */
2773 buf = (uint8_t *)malloc(remain);
2775 /* we just not capture the packet */
2776 errno = saved_errno;
2780 for (i=0; i < msg->msg_iovlen; i++) {
2781 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
2783 msg->msg_iov[i].iov_base,
2786 remain -= this_time;
2793 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2794 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2796 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2801 if (si->connected) {
2805 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2806 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
2808 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
2814 errno = saved_errno;
2817 static int swrap_recvmsg_before(int fd,
2818 struct socket_info *si,
2820 struct iovec *tmp_iov)
2827 if (!si->connected) {
2832 if (msg->msg_iovlen == 0) {
2836 for (i=0; i < msg->msg_iovlen; i++) {
2838 nlen = len + msg->msg_iov[i].iov_len;
2839 if (nlen > SOCKET_MAX_PACKET) {
2843 msg->msg_iovlen = i;
2844 if (msg->msg_iovlen == 0) {
2845 *tmp_iov = msg->msg_iov[0];
2846 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
2847 msg->msg_iov = tmp_iov;
2848 msg->msg_iovlen = 1;
2853 if (si->bound == 0) {
2854 ret = swrap_auto_bind(fd, si, si->family);
2855 if (ret == -1) return -1;
2859 errno = EHOSTUNREACH;
2866 static int swrap_recvmsg_after(struct socket_info *si,
2868 const struct sockaddr_un *un_addr,
2869 socklen_t un_addrlen,
2870 struct sockaddr *from,
2874 int saved_errno = errno;
2881 /* to give better errors */
2882 if (ret == -1 && saved_errno == ENOENT) {
2883 saved_errno = EHOSTUNREACH;
2886 for (i=0; i < msg->msg_iovlen; i++) {
2887 avail += msg->msg_iov[i].iov_len;
2891 remain = MIN(80, avail);
2896 /* we capture it as one single packet */
2897 buf = (uint8_t *)malloc(remain);
2899 /* we just not capture the packet */
2900 errno = saved_errno;
2904 for (i=0; i < msg->msg_iovlen; i++) {
2905 size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
2907 msg->msg_iov[i].iov_base,
2910 remain -= this_time;
2915 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
2916 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2917 } else if (ret == 0) { /* END OF FILE */
2918 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2919 } else if (ret > 0) {
2920 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2929 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
2931 if (sockaddr_convert_from_un(si, un_addr, un_addrlen,
2932 si->family, from, fromlen) == -1) {
2940 errno = saved_errno;
2944 /****************************************************************************
2946 ***************************************************************************/
2948 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
2949 struct sockaddr *from, socklen_t *fromlen)
2951 struct sockaddr_un un_addr;
2952 socklen_t un_addrlen = sizeof(un_addr);
2954 struct socket_info *si = find_socket_info(s);
2955 struct sockaddr_storage ss;
2956 socklen_t ss_len = sizeof(ss);
2962 return libc_recvfrom(s,
2971 from = (struct sockaddr *)(void *)&ss;
2978 msg.msg_name = NULL; /* optional address */
2979 msg.msg_namelen = 0; /* size of address */
2980 msg.msg_iov = &tmp; /* scatter/gather array */
2981 msg.msg_iovlen = 1; /* # elements in msg_iov */
2982 msg.msg_control = NULL; /* ancillary data, see below */
2983 msg.msg_controllen = 0; /* ancillary data buffer len */
2984 msg.msg_flags = 0; /* flags on received message */
2986 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
2987 if (tret == -1) return -1;
2989 buf = msg.msg_iov[0].iov_base;
2990 len = msg.msg_iov[0].iov_len;
2992 /* irix 6.4 forgets to null terminate the sun_path string :-( */
2993 memset(&un_addr, 0, sizeof(un_addr));
2994 ret = libc_recvfrom(s,
2998 (struct sockaddr *)(void *)&un_addr,
3004 tret = swrap_recvmsg_after(si,
3018 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3019 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3020 struct sockaddr *from, Psocklen_t fromlen)
3022 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3023 struct sockaddr *from, socklen_t *fromlen)
3026 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
3029 /****************************************************************************
3031 ***************************************************************************/
3033 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
3034 const struct sockaddr *to, socklen_t tolen)
3038 struct sockaddr_un un_addr;
3039 const struct sockaddr_un *to_un = NULL;
3041 struct socket_info *si = find_socket_info(s);
3045 return libc_sendto(s, buf, len, flags, to, tolen);
3048 tmp.iov_base = discard_const_p(char, buf);
3052 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
3053 msg.msg_namelen = tolen; /* size of address */
3054 msg.msg_iov = &tmp; /* scatter/gather array */
3055 msg.msg_iovlen = 1; /* # elements in msg_iov */
3056 #if 0 /* not available on solaris */
3057 msg.msg_control = NULL; /* ancillary data, see below */
3058 msg.msg_controllen = 0; /* ancillary data buffer len */
3059 msg.msg_flags = 0; /* flags on received message */
3062 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3063 if (ret == -1) return -1;
3065 buf = msg.msg_iov[0].iov_base;
3066 len = msg.msg_iov[0].iov_len;
3071 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3074 type = SOCKET_TYPE_CHAR_UDP;
3076 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3077 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3078 socket_wrapper_dir(), type, iface, prt);
3079 if (stat(un_addr.sun_path, &st) != 0) continue;
3081 /* ignore the any errors in broadcast sends */
3086 (struct sockaddr *)(void *)&un_addr,
3090 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3095 ret = libc_sendto(s,
3099 (struct sockaddr *)msg.msg_name,
3102 swrap_sendmsg_after(si, &msg, to, ret);
3107 ssize_t sendto(int s, const void *buf, size_t len, int flags,
3108 const struct sockaddr *to, socklen_t tolen)
3110 return swrap_sendto(s, buf, len, flags, to, tolen);
3113 /****************************************************************************
3115 ***************************************************************************/
3117 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
3120 struct socket_info *si = find_socket_info(s);
3123 return libc_recv(s, buf, len, flags);
3126 if (si->type == SOCK_STREAM) {
3127 len = MIN(len, SOCKET_MAX_PACKET);
3130 ret = libc_recv(s, buf, len, flags);
3131 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
3132 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3133 } else if (ret == 0) { /* END OF FILE */
3134 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3135 } else if (ret > 0) {
3136 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3142 ssize_t recv(int s, void *buf, size_t len, int flags)
3144 return swrap_recv(s, buf, len, flags);
3147 /****************************************************************************
3149 ***************************************************************************/
3151 static ssize_t swrap_read(int s, void *buf, size_t len)
3154 struct socket_info *si = find_socket_info(s);
3157 return libc_read(s, buf, len);
3160 if (si->type == SOCK_STREAM) {
3161 len = MIN(len, SOCKET_MAX_PACKET);
3164 ret = libc_read(s, buf, len);
3165 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
3166 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3167 } else if (ret == 0) { /* END OF FILE */
3168 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3169 } else if (ret > 0) {
3170 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3176 ssize_t read(int s, void *buf, size_t len)
3178 return swrap_read(s, buf, len);
3181 /****************************************************************************
3183 ***************************************************************************/
3185 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
3189 struct sockaddr_un un_addr;
3191 struct socket_info *si = find_socket_info(s);
3194 return libc_send(s, buf, len, flags);
3197 tmp.iov_base = discard_const_p(char, buf);
3201 msg.msg_name = NULL; /* optional address */
3202 msg.msg_namelen = 0; /* size of address */
3203 msg.msg_iov = &tmp; /* scatter/gather array */
3204 msg.msg_iovlen = 1; /* # elements in msg_iov */
3205 #if 0 /* not available on solaris */
3206 msg.msg_control = NULL; /* ancillary data, see below */
3207 msg.msg_controllen = 0; /* ancillary data buffer len */
3208 msg.msg_flags = 0; /* flags on received message */
3211 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
3212 if (ret == -1) return -1;
3214 buf = msg.msg_iov[0].iov_base;
3215 len = msg.msg_iov[0].iov_len;
3217 ret = libc_send(s, buf, len, flags);
3219 swrap_sendmsg_after(si, &msg, NULL, ret);
3224 ssize_t send(int s, const void *buf, size_t len, int flags)
3226 return swrap_send(s, buf, len, flags);
3229 /****************************************************************************
3231 ***************************************************************************/
3235 /****************************************************************************
3237 ***************************************************************************/
3239 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
3243 struct sockaddr_un un_addr;
3244 const struct sockaddr_un *to_un = NULL;
3245 const struct sockaddr *to = NULL;
3247 struct socket_info *si = find_socket_info(s);
3251 return libc_sendmsg(s, omsg, flags);
3254 tmp.iov_base = NULL;
3259 msg.msg_name = omsg->msg_name; /* optional address */
3260 msg.msg_namelen = omsg->msg_namelen; /* size of address */
3261 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3262 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3263 /* the following is not available on solaris */
3264 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3265 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3266 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3269 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3270 if (ret == -1) return -1;
3275 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3283 for (i=0; i < msg.msg_iovlen; i++) {
3284 avail += msg.msg_iov[i].iov_len;
3290 /* we capture it as one single packet */
3291 buf = (uint8_t *)malloc(remain);
3296 for (i=0; i < msg.msg_iovlen; i++) {
3297 size_t this_time = MIN(remain, msg.msg_iov[i].iov_len);
3299 msg.msg_iov[i].iov_base,
3302 remain -= this_time;
3305 type = SOCKET_TYPE_CHAR_UDP;
3307 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3308 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3309 socket_wrapper_dir(), type, iface, prt);
3310 if (stat(un_addr.sun_path, &st) != 0) continue;
3312 msg.msg_name = &un_addr; /* optional address */
3313 msg.msg_namelen = sizeof(un_addr); /* size of address */
3315 /* ignore the any errors in broadcast sends */
3316 libc_sendmsg(s, &msg, flags);
3319 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3325 ret = libc_sendmsg(s, &msg, flags);
3327 swrap_sendmsg_after(si, &msg, to, ret);
3332 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
3334 return swrap_sendmsg(s, omsg, flags);
3337 /****************************************************************************
3339 ***************************************************************************/
3341 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
3344 struct socket_info *si = find_socket_info(s);
3348 return libc_readv(s, vector, count);
3351 if (!si->connected) {
3356 if (si->type == SOCK_STREAM && count > 0) {
3360 for (i = 0; i < count; i++) {
3362 nlen = len + vector[i].iov_len;
3363 if (nlen > SOCKET_MAX_PACKET) {
3370 v.iov_len = MIN(v.iov_len, SOCKET_MAX_PACKET);
3376 ret = libc_readv(s, vector, count);
3377 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
3378 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3379 } else if (ret == 0) { /* END OF FILE */
3380 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3381 } else if (ret > 0) {
3385 size_t remain = ret;
3387 /* we capture it as one single packet */
3388 buf = (uint8_t *)malloc(ret);
3390 /* we just not capture the packet */
3395 for (i=0; i < count; i++) {
3396 size_t this_time = MIN(remain, vector[i].iov_len);
3401 remain -= this_time;
3404 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3411 ssize_t readv(int s, const struct iovec *vector, int count)
3413 return swrap_readv(s, vector, count);
3416 /****************************************************************************
3418 ***************************************************************************/
3420 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
3424 struct sockaddr_un un_addr;
3426 struct socket_info *si = find_socket_info(s);
3429 return libc_writev(s, vector, count);
3432 tmp.iov_base = NULL;
3436 msg.msg_name = NULL; /* optional address */
3437 msg.msg_namelen = 0; /* size of address */
3438 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
3439 msg.msg_iovlen = count; /* # elements in msg_iov */
3440 #if 0 /* not available on solaris */
3441 msg.msg_control = NULL; /* ancillary data, see below */
3442 msg.msg_controllen = 0; /* ancillary data buffer len */
3443 msg.msg_flags = 0; /* flags on received message */
3446 ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
3447 if (ret == -1) return -1;
3449 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
3451 swrap_sendmsg_after(si, &msg, NULL, ret);
3456 ssize_t writev(int s, const struct iovec *vector, int count)
3458 return swrap_writev(s, vector, count);
3461 /****************************
3463 ***************************/
3465 static int swrap_close(int fd)
3467 struct socket_info *si = find_socket_info(fd);
3468 struct socket_info_fd *fi;
3472 return libc_close(fd);
3475 for (fi = si->fds; fi; fi = fi->next) {
3477 SWRAP_DLIST_REMOVE(si->fds, fi);
3484 /* there are still references left */
3485 return libc_close(fd);
3488 SWRAP_DLIST_REMOVE(sockets, si);
3490 if (si->myname && si->peername) {
3491 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
3494 ret = libc_close(fd);
3496 if (si->myname && si->peername) {
3497 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
3498 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
3501 if (si->myname) free(si->myname);
3502 if (si->peername) free(si->peername);
3504 unlink(si->tmp_path);
3514 return swrap_close(fd);
3517 /****************************
3519 ***************************/
3521 static int swrap_dup(int fd)
3523 struct socket_info *si;
3524 struct socket_info_fd *fi;
3526 si = find_socket_info(fd);
3529 return libc_dup(fd);
3532 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
3538 fi->fd = libc_dup(fd);
3540 int saved_errno = errno;
3542 errno = saved_errno;
3546 SWRAP_DLIST_ADD(si->fds, fi);
3552 return swrap_dup(fd);
3555 /****************************
3557 ***************************/
3559 static int swrap_dup2(int fd, int newfd)
3561 struct socket_info *si;
3562 struct socket_info_fd *fi;
3564 si = find_socket_info(fd);
3567 return libc_dup2(fd, newfd);
3570 if (find_socket_info(newfd)) {
3571 /* dup2() does an implicit close of newfd, which we
3572 * need to emulate */
3576 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
3582 fi->fd = libc_dup2(fd, newfd);
3584 int saved_errno = errno;
3586 errno = saved_errno;
3590 SWRAP_DLIST_ADD(si->fds, fi);
3594 int dup2(int fd, int newfd)
3596 return swrap_dup2(fd, newfd);
3599 /****************************
3601 ***************************/
3604 * This function is called when the library is unloaded and makes sure that
3605 * sockets get closed and the unix file for the socket are unlinked.
3607 void swrap_destructor(void)
3609 struct socket_info *s = sockets;
3612 struct socket_info_fd *f = s->fds;