2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
45 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
100 #define DESTRUCTOR_ATTRIBUTE
103 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
104 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
106 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
109 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
110 # define SWRAP_THREAD __thread
112 # define SWRAP_THREAD
116 #define MIN(a,b) ((a)<(b)?(a):(b))
120 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
124 #define ZERO_STRUCTP(x) do { \
126 memset((char *)(x), 0, sizeof(*(x))); \
130 #ifndef discard_const
131 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
134 #ifndef discard_const_p
135 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
139 # ifndef IPV6_RECVPKTINFO
140 # define IPV6_RECVPKTINFO IPV6_PKTINFO
141 # endif /* IPV6_RECVPKTINFO */
142 #endif /* IPV6_PKTINFO */
145 * On BSD IP_PKTINFO has a different name because during
146 * the time when they implemented it, there was no RFC.
147 * The name for IPv6 is the same as on Linux.
150 # ifdef IP_RECVDSTADDR
151 # define IP_PKTINFO IP_RECVDSTADDR
156 #define SWRAP_DLIST_ADD(list,item) do { \
158 (item)->prev = NULL; \
159 (item)->next = NULL; \
162 (item)->prev = NULL; \
163 (item)->next = (list); \
164 (list)->prev = (item); \
169 #define SWRAP_DLIST_REMOVE(list,item) do { \
170 if ((list) == (item)) { \
171 (list) = (item)->next; \
173 (list)->prev = NULL; \
176 if ((item)->prev) { \
177 (item)->prev->next = (item)->next; \
179 if ((item)->next) { \
180 (item)->next->prev = (item)->prev; \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
187 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
189 if ((list) != NULL || (el) != NULL) { \
190 SWRAP_DLIST_ADD(list, item); \
192 (item)->prev = (el); \
193 (item)->next = (el)->next; \
194 (el)->next = (item); \
195 if ((item)->next != NULL) { \
196 (item)->next->prev = (item); \
201 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
202 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
204 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
207 /* we need to use a very terse format here as IRIX 6.4 silently
208 truncates names to 16 chars, so if we use a longer name then we
209 can't tell which port a packet came from with recvfrom()
211 with this format we have 8 chars left for the directory name
213 #define SOCKET_FORMAT "%c%02X%04X"
214 #define SOCKET_TYPE_CHAR_TCP 'T'
215 #define SOCKET_TYPE_CHAR_UDP 'U'
216 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
217 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
220 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
221 * format PCAP capture files (as the caller will simply continue from here).
223 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
224 #define SOCKET_WRAPPER_MTU_MIN 512
225 #define SOCKET_WRAPPER_MTU_MAX 32768
227 #define SOCKET_MAX_SOCKETS 1024
231 * Maximum number of socket_info structures that can
232 * be used. Can be overriden by the environment variable
233 * SOCKET_WRAPPER_MAX_SOCKETS.
235 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
237 /* This limit is to avoid broadcast sendto() needing to stat too many
238 * files. It may be raised (with a performance cost) to up to 254
239 * without changing the format above */
240 #define MAX_WRAPPED_INTERFACES 40
242 struct swrap_address {
243 socklen_t sa_socklen;
246 struct sockaddr_in in;
248 struct sockaddr_in6 in6;
250 struct sockaddr_un un;
251 struct sockaddr_storage ss;
255 struct socket_info_fd {
256 struct socket_info_fd *prev, *next;
260 * Points to corresponding index in array of
261 * socket_info structures
268 unsigned int refcount;
281 /* The unix path so we can unlink it on close() */
282 struct sockaddr_un un_addr;
284 struct swrap_address bindname;
285 struct swrap_address myname;
286 struct swrap_address peername;
289 unsigned long pck_snd;
290 unsigned long pck_rcv;
294 static struct socket_info *sockets;
295 static size_t max_sockets = 0;
298 * While socket file descriptors are passed among different processes, the
299 * numerical value gets changed. So its better to store it locally to each
300 * process rather than including it within socket_info which will be shared.
302 static struct socket_info_fd *socket_fds;
304 /* Function prototypes */
306 bool socket_wrapper_enabled(void);
307 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
310 # define SWRAP_LOG(...)
313 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
314 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
316 static void swrap_log(enum swrap_dbglvl_e dbglvl,
318 const char *format, ...)
323 unsigned int lvl = 0;
325 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
330 va_start(va, format);
331 vsnprintf(buffer, sizeof(buffer), format, va);
336 case SWRAP_LOG_ERROR:
338 "SWRAP_ERROR(%d) - %s: %s\n",
339 (int)getpid(), func, buffer);
343 "SWRAP_WARN(%d) - %s: %s\n",
344 (int)getpid(), func, buffer);
346 case SWRAP_LOG_DEBUG:
348 "SWRAP_DEBUG(%d) - %s: %s\n",
349 (int)getpid(), func, buffer);
351 case SWRAP_LOG_TRACE:
353 "SWRAP_TRACE(%d) - %s: %s\n",
354 (int)getpid(), func, buffer);
361 /*********************************************************
362 * SWRAP LOADING LIBC FUNCTIONS
363 *********************************************************/
367 struct swrap_libc_fns {
369 int (*libc_accept4)(int sockfd,
370 struct sockaddr *addr,
374 int (*libc_accept)(int sockfd,
375 struct sockaddr *addr,
378 int (*libc_bind)(int sockfd,
379 const struct sockaddr *addr,
381 int (*libc_close)(int fd);
382 int (*libc_connect)(int sockfd,
383 const struct sockaddr *addr,
385 int (*libc_dup)(int fd);
386 int (*libc_dup2)(int oldfd, int newfd);
387 int (*libc_fcntl)(int fd, int cmd, ...);
388 FILE *(*libc_fopen)(const char *name, const char *mode);
390 int (*libc_eventfd)(int count, int flags);
392 int (*libc_getpeername)(int sockfd,
393 struct sockaddr *addr,
395 int (*libc_getsockname)(int sockfd,
396 struct sockaddr *addr,
398 int (*libc_getsockopt)(int sockfd,
403 int (*libc_ioctl)(int d, unsigned long int request, ...);
404 int (*libc_listen)(int sockfd, int backlog);
405 int (*libc_open)(const char *pathname, int flags, mode_t mode);
406 int (*libc_pipe)(int pipefd[2]);
407 int (*libc_read)(int fd, void *buf, size_t count);
408 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
409 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
410 int (*libc_recvfrom)(int sockfd,
414 struct sockaddr *src_addr,
416 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
417 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
418 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
419 int (*libc_sendto)(int sockfd,
423 const struct sockaddr *dst_addr,
425 int (*libc_setsockopt)(int sockfd,
431 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
433 int (*libc_socket)(int domain, int type, int protocol);
434 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
435 #ifdef HAVE_TIMERFD_CREATE
436 int (*libc_timerfd_create)(int clockid, int flags);
438 ssize_t (*libc_write)(int fd, const void *buf, size_t count);
439 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
444 void *libsocket_handle;
446 struct swrap_libc_fns fns;
449 static struct swrap swrap;
452 static const char *socket_wrapper_dir(void);
454 #define LIBC_NAME "libc.so"
463 static const char *swrap_str_lib(enum swrap_lib lib)
470 case SWRAP_LIBSOCKET:
474 /* Compiler would warn us about unhandled enum value if we get here */
479 static void *swrap_load_lib_handle(enum swrap_lib lib)
481 int flags = RTLD_LAZY;
486 flags |= RTLD_DEEPBIND;
492 case SWRAP_LIBSOCKET:
493 #ifdef HAVE_LIBSOCKET
494 handle = swrap.libsocket_handle;
495 if (handle == NULL) {
496 for (i = 10; i >= 0; i--) {
497 char soname[256] = {0};
499 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
500 handle = dlopen(soname, flags);
501 if (handle != NULL) {
506 swrap.libsocket_handle = handle;
512 handle = swrap.libc_handle;
514 if (handle == NULL) {
515 handle = dlopen(LIBC_SO, flags);
517 swrap.libc_handle = handle;
520 if (handle == NULL) {
521 for (i = 10; i >= 0; i--) {
522 char soname[256] = {0};
524 snprintf(soname, sizeof(soname), "libc.so.%d", i);
525 handle = dlopen(soname, flags);
526 if (handle != NULL) {
531 swrap.libc_handle = handle;
536 if (handle == NULL) {
538 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
540 SWRAP_LOG(SWRAP_LOG_ERROR,
541 "Failed to dlopen library: %s\n",
550 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
555 handle = swrap_load_lib_handle(lib);
557 func = dlsym(handle, fn_name);
559 SWRAP_LOG(SWRAP_LOG_ERROR,
560 "Failed to find %s: %s\n",
565 SWRAP_LOG(SWRAP_LOG_TRACE,
567 fn_name, swrap_str_lib(lib));
571 #define swrap_load_lib_function(lib, fn_name) \
572 if (swrap.fns.libc_##fn_name == NULL) { \
573 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
574 *(void **) (&swrap.fns.libc_##fn_name) = \
582 * Functions especially from libc need to be loaded individually, you can't load
583 * all at once or gdb will segfault at startup. The same applies to valgrind and
584 * has probably something todo with with the linker.
585 * So we need load each function at the point it is called the first time.
588 static int libc_accept4(int sockfd,
589 struct sockaddr *addr,
593 swrap_load_lib_function(SWRAP_LIBSOCKET, accept4);
595 return swrap.fns.libc_accept4(sockfd, addr, addrlen, flags);
598 #else /* HAVE_ACCEPT4 */
600 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
602 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
604 return swrap.fns.libc_accept(sockfd, addr, addrlen);
606 #endif /* HAVE_ACCEPT4 */
608 static int libc_bind(int sockfd,
609 const struct sockaddr *addr,
612 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
614 return swrap.fns.libc_bind(sockfd, addr, addrlen);
617 static int libc_close(int fd)
619 swrap_load_lib_function(SWRAP_LIBC, close);
621 return swrap.fns.libc_close(fd);
624 static int libc_connect(int sockfd,
625 const struct sockaddr *addr,
628 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
630 return swrap.fns.libc_connect(sockfd, addr, addrlen);
633 static int libc_dup(int fd)
635 swrap_load_lib_function(SWRAP_LIBC, dup);
637 return swrap.fns.libc_dup(fd);
640 static int libc_dup2(int oldfd, int newfd)
642 swrap_load_lib_function(SWRAP_LIBC, dup2);
644 return swrap.fns.libc_dup2(oldfd, newfd);
648 static int libc_eventfd(int count, int flags)
650 swrap_load_lib_function(SWRAP_LIBC, eventfd);
652 return swrap.fns.libc_eventfd(count, flags);
656 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
657 static int libc_vfcntl(int fd, int cmd, va_list ap)
663 swrap_load_lib_function(SWRAP_LIBC, fcntl);
665 for (i = 0; i < 4; i++) {
666 args[i] = va_arg(ap, long int);
669 rc = swrap.fns.libc_fcntl(fd,
679 static int libc_getpeername(int sockfd,
680 struct sockaddr *addr,
683 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
685 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
688 static int libc_getsockname(int sockfd,
689 struct sockaddr *addr,
692 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
694 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
697 static int libc_getsockopt(int sockfd,
703 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
705 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
708 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
709 static int libc_vioctl(int d, unsigned long int request, va_list ap)
715 swrap_load_lib_function(SWRAP_LIBC, ioctl);
717 for (i = 0; i < 4; i++) {
718 args[i] = va_arg(ap, long int);
721 rc = swrap.fns.libc_ioctl(d,
731 static int libc_listen(int sockfd, int backlog)
733 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
735 return swrap.fns.libc_listen(sockfd, backlog);
738 static FILE *libc_fopen(const char *name, const char *mode)
740 swrap_load_lib_function(SWRAP_LIBC, fopen);
742 return swrap.fns.libc_fopen(name, mode);
745 static int libc_vopen(const char *pathname, int flags, va_list ap)
750 swrap_load_lib_function(SWRAP_LIBC, open);
752 mode = va_arg(ap, long int);
754 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
759 static int libc_open(const char *pathname, int flags, ...)
765 fd = libc_vopen(pathname, flags, ap);
771 static int libc_pipe(int pipefd[2])
773 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
775 return swrap.fns.libc_pipe(pipefd);
778 static int libc_read(int fd, void *buf, size_t count)
780 swrap_load_lib_function(SWRAP_LIBC, read);
782 return swrap.fns.libc_read(fd, buf, count);
785 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
787 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
789 return swrap.fns.libc_readv(fd, iov, iovcnt);
792 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
794 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
796 return swrap.fns.libc_recv(sockfd, buf, len, flags);
799 static int libc_recvfrom(int sockfd,
803 struct sockaddr *src_addr,
806 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
808 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
811 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
813 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
815 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
818 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
820 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
822 return swrap.fns.libc_send(sockfd, buf, len, flags);
825 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
827 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
829 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
832 static int libc_sendto(int sockfd,
836 const struct sockaddr *dst_addr,
839 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
841 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
844 static int libc_setsockopt(int sockfd,
850 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
852 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
856 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
858 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
860 return swrap.fns.libc_signalfd(fd, mask, flags);
864 static int libc_socket(int domain, int type, int protocol)
866 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
868 return swrap.fns.libc_socket(domain, type, protocol);
871 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
873 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
875 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
878 #ifdef HAVE_TIMERFD_CREATE
879 static int libc_timerfd_create(int clockid, int flags)
881 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
883 return swrap.fns.libc_timerfd_create(clockid, flags);
887 static ssize_t libc_write(int fd, const void *buf, size_t count)
889 swrap_load_lib_function(SWRAP_LIBC, write);
891 return swrap.fns.libc_write(fd, buf, count);
894 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
896 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
898 return swrap.fns.libc_writev(fd, iov, iovcnt);
901 /*********************************************************
902 * SWRAP HELPER FUNCTIONS
903 *********************************************************/
909 static const struct in6_addr *swrap_ipv6(void)
911 static struct in6_addr v;
912 static int initialized;
920 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
929 static void set_port(int family, int prt, struct swrap_address *addr)
933 addr->sa.in.sin_port = htons(prt);
937 addr->sa.in6.sin6_port = htons(prt);
943 static size_t socket_length(int family)
947 return sizeof(struct sockaddr_in);
950 return sizeof(struct sockaddr_in6);
956 static const char *socket_wrapper_dir(void)
958 const char *s = getenv("SOCKET_WRAPPER_DIR");
962 /* TODO use realpath(3) here, when we add support for threads */
963 if (strncmp(s, "./", 2) == 0) {
967 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
971 static unsigned int socket_wrapper_mtu(void)
973 static unsigned int max_mtu = 0;
982 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
984 s = getenv("SOCKET_WRAPPER_MTU");
989 tmp = strtol(s, &endp, 10);
994 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1003 static size_t socket_wrapper_max_sockets(void)
1009 if (max_sockets != 0) {
1013 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1015 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1016 if (s == NULL || s[0] == '\0') {
1020 tmp = strtoul(s, &endp, 10);
1031 static void socket_wrapper_init_sockets(void)
1034 if (sockets != NULL) {
1038 max_sockets = socket_wrapper_max_sockets();
1040 sockets = (struct socket_info *)calloc(max_sockets,
1041 sizeof(struct socket_info));
1043 if (sockets == NULL) {
1044 SWRAP_LOG(SWRAP_LOG_ERROR,
1045 "Failed to allocate sockets array.\n");
1050 bool socket_wrapper_enabled(void)
1052 const char *s = socket_wrapper_dir();
1058 socket_wrapper_init_sockets();
1063 static unsigned int socket_wrapper_default_iface(void)
1065 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1068 if (sscanf(s, "%u", &iface) == 1) {
1069 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1075 return 1;/* 127.0.0.1 */
1078 static int socket_wrapper_first_free_index(void)
1082 for (i = 0; i < max_sockets; ++i) {
1083 if (sockets[i].refcount == 0) {
1084 ZERO_STRUCT(sockets[i]);
1092 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1099 p = strrchr(un->sun_path, '/');
1100 if (p) p++; else p = un->sun_path;
1102 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1107 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1110 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1121 case SOCKET_TYPE_CHAR_TCP:
1122 case SOCKET_TYPE_CHAR_UDP: {
1123 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1125 if ((*len) < sizeof(*in2)) {
1130 memset(in2, 0, sizeof(*in2));
1131 in2->sin_family = AF_INET;
1132 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1133 in2->sin_port = htons(prt);
1135 *len = sizeof(*in2);
1139 case SOCKET_TYPE_CHAR_TCP_V6:
1140 case SOCKET_TYPE_CHAR_UDP_V6: {
1141 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1143 if ((*len) < sizeof(*in2)) {
1148 memset(in2, 0, sizeof(*in2));
1149 in2->sin6_family = AF_INET6;
1150 in2->sin6_addr = *swrap_ipv6();
1151 in2->sin6_addr.s6_addr[15] = iface;
1152 in2->sin6_port = htons(prt);
1154 *len = sizeof(*in2);
1166 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1174 if (bcast) *bcast = 0;
1176 switch (inaddr->sa_family) {
1178 const struct sockaddr_in *in =
1179 (const struct sockaddr_in *)(const void *)inaddr;
1180 unsigned int addr = ntohl(in->sin_addr.s_addr);
1187 u_type = SOCKET_TYPE_CHAR_TCP;
1190 u_type = SOCKET_TYPE_CHAR_UDP;
1191 a_type = SOCKET_TYPE_CHAR_UDP;
1192 b_type = SOCKET_TYPE_CHAR_UDP;
1195 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1196 errno = ESOCKTNOSUPPORT;
1200 prt = ntohs(in->sin_port);
1201 if (a_type && addr == 0xFFFFFFFF) {
1202 /* 255.255.255.255 only udp */
1205 iface = socket_wrapper_default_iface();
1206 } else if (b_type && addr == 0x7FFFFFFF) {
1207 /* 127.255.255.255 only udp */
1210 iface = socket_wrapper_default_iface();
1211 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1215 iface = (addr & 0x000000FF);
1217 errno = ENETUNREACH;
1220 if (bcast) *bcast = is_bcast;
1225 const struct sockaddr_in6 *in =
1226 (const struct sockaddr_in6 *)(const void *)inaddr;
1227 struct in6_addr cmp1, cmp2;
1231 type = SOCKET_TYPE_CHAR_TCP_V6;
1234 type = SOCKET_TYPE_CHAR_UDP_V6;
1237 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1238 errno = ESOCKTNOSUPPORT;
1242 /* XXX no multicast/broadcast */
1244 prt = ntohs(in->sin6_port);
1246 cmp1 = *swrap_ipv6();
1247 cmp2 = in->sin6_addr;
1248 cmp2.s6_addr[15] = 0;
1249 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1250 iface = in->sin6_addr.s6_addr[15];
1252 errno = ENETUNREACH;
1260 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1261 errno = ENETUNREACH;
1266 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1272 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1273 socket_wrapper_dir());
1274 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1275 /* the caller need to do more processing */
1279 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1280 socket_wrapper_dir(), type, iface, prt);
1281 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1286 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1295 if (bcast) *bcast = 0;
1297 switch (si->family) {
1299 const struct sockaddr_in *in =
1300 (const struct sockaddr_in *)(const void *)inaddr;
1301 unsigned int addr = ntohl(in->sin_addr.s_addr);
1307 prt = ntohs(in->sin_port);
1311 u_type = SOCKET_TYPE_CHAR_TCP;
1312 d_type = SOCKET_TYPE_CHAR_TCP;
1315 u_type = SOCKET_TYPE_CHAR_UDP;
1316 d_type = SOCKET_TYPE_CHAR_UDP;
1317 a_type = SOCKET_TYPE_CHAR_UDP;
1318 b_type = SOCKET_TYPE_CHAR_UDP;
1321 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1322 errno = ESOCKTNOSUPPORT;
1330 iface = socket_wrapper_default_iface();
1331 } else if (a_type && addr == 0xFFFFFFFF) {
1332 /* 255.255.255.255 only udp */
1335 iface = socket_wrapper_default_iface();
1336 } else if (b_type && addr == 0x7FFFFFFF) {
1337 /* 127.255.255.255 only udp */
1340 iface = socket_wrapper_default_iface();
1341 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1345 iface = (addr & 0x000000FF);
1347 errno = EADDRNOTAVAIL;
1351 /* Store the bind address for connect() */
1352 if (si->bindname.sa_socklen == 0) {
1353 struct sockaddr_in bind_in;
1354 socklen_t blen = sizeof(struct sockaddr_in);
1356 ZERO_STRUCT(bind_in);
1357 bind_in.sin_family = in->sin_family;
1358 bind_in.sin_port = in->sin_port;
1359 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1361 si->bindname.sa_socklen = blen;
1362 memcpy(&si->bindname.sa.in, &bind_in, blen);
1369 const struct sockaddr_in6 *in =
1370 (const struct sockaddr_in6 *)(const void *)inaddr;
1371 struct in6_addr cmp1, cmp2;
1375 type = SOCKET_TYPE_CHAR_TCP_V6;
1378 type = SOCKET_TYPE_CHAR_UDP_V6;
1381 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1382 errno = ESOCKTNOSUPPORT;
1386 /* XXX no multicast/broadcast */
1388 prt = ntohs(in->sin6_port);
1390 cmp1 = *swrap_ipv6();
1391 cmp2 = in->sin6_addr;
1392 cmp2.s6_addr[15] = 0;
1393 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1394 iface = socket_wrapper_default_iface();
1395 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1396 iface = in->sin6_addr.s6_addr[15];
1398 errno = EADDRNOTAVAIL;
1402 /* Store the bind address for connect() */
1403 if (si->bindname.sa_socklen == 0) {
1404 struct sockaddr_in6 bind_in;
1405 socklen_t blen = sizeof(struct sockaddr_in6);
1407 ZERO_STRUCT(bind_in);
1408 bind_in.sin6_family = in->sin6_family;
1409 bind_in.sin6_port = in->sin6_port;
1411 bind_in.sin6_addr = *swrap_ipv6();
1412 bind_in.sin6_addr.s6_addr[15] = iface;
1414 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1415 si->bindname.sa_socklen = blen;
1422 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1423 errno = EADDRNOTAVAIL;
1428 if (bcast) *bcast = is_bcast;
1430 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1436 /* handle auto-allocation of ephemeral ports */
1437 for (prt = 5001; prt < 10000; prt++) {
1438 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1439 socket_wrapper_dir(), type, iface, prt);
1440 if (stat(un->sun_path, &st) == 0) continue;
1442 set_port(si->family, prt, &si->myname);
1443 set_port(si->family, prt, &si->bindname);
1453 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1454 socket_wrapper_dir(), type, iface, prt);
1455 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1459 static struct socket_info_fd *find_socket_info_fd(int fd)
1461 struct socket_info_fd *f;
1463 for (f = socket_fds; f; f = f->next) {
1472 static int find_socket_info_index(int fd)
1474 struct socket_info_fd *fi = find_socket_info_fd(fd);
1480 return fi->si_index;
1483 static struct socket_info *find_socket_info(int fd)
1485 int idx = find_socket_info_index(fd);
1491 return &sockets[idx];
1495 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1497 struct socket_info_fd *f;
1498 const struct socket_info *last_s = NULL;
1500 /* first catch invalid input */
1501 switch (sa->sa_family) {
1503 if (len < sizeof(struct sockaddr_in)) {
1509 if (len < sizeof(struct sockaddr_in6)) {
1519 for (f = socket_fds; f; f = f->next) {
1520 struct socket_info *s = &sockets[f->si_index];
1527 if (s->myname == NULL) {
1530 if (s->myname->sa_family != sa->sa_family) {
1533 switch (s->myname->sa_family) {
1535 struct sockaddr_in *sin1, *sin2;
1537 sin1 = (struct sockaddr_in *)s->myname;
1538 sin2 = (struct sockaddr_in *)sa;
1540 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1543 if (sin1->sin_port != sin2->sin_port) {
1546 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1556 struct sockaddr_in6 *sin1, *sin2;
1558 sin1 = (struct sockaddr_in6 *)s->myname;
1559 sin2 = (struct sockaddr_in6 *)sa;
1561 if (sin1->sin6_port != sin2->sin6_port) {
1564 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1586 static void swrap_remove_stale(int fd)
1588 struct socket_info_fd *fi = find_socket_info_fd(fd);
1589 struct socket_info *si;
1595 si = &sockets[fi->si_index];
1597 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1598 SWRAP_DLIST_REMOVE(socket_fds, fi);
1603 if (si->refcount > 0) {
1607 if (si->un_addr.sun_path[0] != '\0') {
1608 unlink(si->un_addr.sun_path);
1612 static int sockaddr_convert_to_un(struct socket_info *si,
1613 const struct sockaddr *in_addr,
1615 struct sockaddr_un *out_addr,
1619 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1621 (void) in_len; /* unused */
1623 if (out_addr == NULL) {
1627 out->sa_family = AF_UNIX;
1628 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1629 out->sa_len = sizeof(*out_addr);
1632 switch (in_addr->sa_family) {
1634 const struct sockaddr_in *sin;
1635 if (si->family != AF_INET) {
1638 if (in_len < sizeof(struct sockaddr_in)) {
1641 sin = (const struct sockaddr_in *)(const void *)in_addr;
1642 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1647 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1648 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1662 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1663 errno = ESOCKTNOSUPPORT;
1667 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1669 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1675 errno = EAFNOSUPPORT;
1676 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1680 static int sockaddr_convert_from_un(const struct socket_info *si,
1681 const struct sockaddr_un *in_addr,
1682 socklen_t un_addrlen,
1684 struct sockaddr *out_addr,
1685 socklen_t *out_addrlen)
1689 if (out_addr == NULL || out_addrlen == NULL)
1692 if (un_addrlen == 0) {
1707 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1708 errno = ESOCKTNOSUPPORT;
1711 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1712 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1713 out_addr->sa_len = *out_addrlen;
1720 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1721 errno = EAFNOSUPPORT;
1725 enum swrap_packet_type {
1727 SWRAP_CONNECT_UNREACH,
1735 SWRAP_SENDTO_UNREACH,
1746 struct swrap_file_hdr {
1748 uint16_t version_major;
1749 uint16_t version_minor;
1752 uint32_t frame_max_len;
1753 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1756 #define SWRAP_FILE_HDR_SIZE 24
1758 struct swrap_packet_frame {
1760 uint32_t micro_seconds;
1761 uint32_t recorded_length;
1762 uint32_t full_length;
1764 #define SWRAP_PACKET_FRAME_SIZE 16
1766 union swrap_packet_ip {
1770 uint16_t packet_length;
1771 uint16_t identification;
1776 uint16_t hdr_checksum;
1780 #define SWRAP_PACKET_IP_V4_SIZE 20
1783 uint8_t flow_label_high;
1784 uint16_t flow_label_low;
1785 uint16_t payload_length;
1786 uint8_t next_header;
1788 uint8_t src_addr[16];
1789 uint8_t dest_addr[16];
1791 #define SWRAP_PACKET_IP_V6_SIZE 40
1793 #define SWRAP_PACKET_IP_SIZE 40
1795 union swrap_packet_payload {
1797 uint16_t source_port;
1807 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1809 uint16_t source_port;
1814 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1821 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1828 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1830 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1832 #define SWRAP_PACKET_MIN_ALLOC \
1833 (SWRAP_PACKET_FRAME_SIZE + \
1834 SWRAP_PACKET_IP_SIZE + \
1835 SWRAP_PACKET_PAYLOAD_SIZE)
1837 static const char *swrap_pcap_init_file(void)
1839 static int initialized = 0;
1840 static const char *s = NULL;
1841 static const struct swrap_file_hdr h;
1842 static const struct swrap_packet_frame f;
1843 static const union swrap_packet_ip i;
1844 static const union swrap_packet_payload p;
1846 if (initialized == 1) {
1852 * TODO: don't use the structs use plain buffer offsets
1853 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1855 * for now make sure we disable PCAP support
1856 * if the struct has alignment!
1858 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1861 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1864 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1867 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1870 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1873 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1876 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1879 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1882 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1885 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1889 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1893 if (strncmp(s, "./", 2) == 0) {
1899 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1900 const struct sockaddr *src,
1901 const struct sockaddr *dest,
1903 const uint8_t *payload,
1905 unsigned long tcp_seqno,
1906 unsigned long tcp_ack,
1907 unsigned char tcp_ctl,
1909 size_t *_packet_len)
1913 struct swrap_packet_frame *frame;
1914 union swrap_packet_ip *ip;
1915 union swrap_packet_payload *pay;
1918 size_t nonwire_len = sizeof(*frame);
1919 size_t wire_hdr_len = 0;
1920 size_t wire_len = 0;
1921 size_t ip_hdr_len = 0;
1922 size_t icmp_hdr_len = 0;
1923 size_t icmp_truncate_len = 0;
1924 uint8_t protocol = 0, icmp_protocol = 0;
1925 const struct sockaddr_in *src_in = NULL;
1926 const struct sockaddr_in *dest_in = NULL;
1928 const struct sockaddr_in6 *src_in6 = NULL;
1929 const struct sockaddr_in6 *dest_in6 = NULL;
1934 switch (src->sa_family) {
1936 src_in = (const struct sockaddr_in *)(const void *)src;
1937 dest_in = (const struct sockaddr_in *)(const void *)dest;
1938 src_port = src_in->sin_port;
1939 dest_port = dest_in->sin_port;
1940 ip_hdr_len = sizeof(ip->v4);
1944 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1945 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1946 src_port = src_in6->sin6_port;
1947 dest_port = dest_in6->sin6_port;
1948 ip_hdr_len = sizeof(ip->v6);
1955 switch (socket_type) {
1957 protocol = 0x06; /* TCP */
1958 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1959 wire_len = wire_hdr_len + payload_len;
1963 protocol = 0x11; /* UDP */
1964 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1965 wire_len = wire_hdr_len + payload_len;
1973 icmp_protocol = protocol;
1974 switch (src->sa_family) {
1976 protocol = 0x01; /* ICMPv4 */
1977 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1981 protocol = 0x3A; /* ICMPv6 */
1982 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1986 if (wire_len > 64 ) {
1987 icmp_truncate_len = wire_len - 64;
1989 wire_hdr_len += icmp_hdr_len;
1990 wire_len += icmp_hdr_len;
1993 packet_len = nonwire_len + wire_len;
1994 alloc_len = packet_len;
1995 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1996 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1999 base = (uint8_t *)calloc(1, alloc_len);
2006 frame = (struct swrap_packet_frame *)(void *)buf;
2007 frame->seconds = tval->tv_sec;
2008 frame->micro_seconds = tval->tv_usec;
2009 frame->recorded_length = wire_len - icmp_truncate_len;
2010 frame->full_length = wire_len - icmp_truncate_len;
2011 buf += SWRAP_PACKET_FRAME_SIZE;
2013 ip = (union swrap_packet_ip *)(void *)buf;
2014 switch (src->sa_family) {
2016 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2018 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2019 ip->v4.identification = htons(0xFFFF);
2020 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2021 ip->v4.fragment = htons(0x0000);
2023 ip->v4.protocol = protocol;
2024 ip->v4.hdr_checksum = htons(0x0000);
2025 ip->v4.src_addr = src_in->sin_addr.s_addr;
2026 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2027 buf += SWRAP_PACKET_IP_V4_SIZE;
2031 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2032 ip->v6.flow_label_high = 0x00;
2033 ip->v6.flow_label_low = 0x0000;
2034 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2035 ip->v6.next_header = protocol;
2036 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2037 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2038 buf += SWRAP_PACKET_IP_V6_SIZE;
2044 pay = (union swrap_packet_payload *)(void *)buf;
2045 switch (src->sa_family) {
2047 pay->icmp4.type = 0x03; /* destination unreachable */
2048 pay->icmp4.code = 0x01; /* host unreachable */
2049 pay->icmp4.checksum = htons(0x0000);
2050 pay->icmp4.unused = htonl(0x00000000);
2051 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2053 /* set the ip header in the ICMP payload */
2054 ip = (union swrap_packet_ip *)(void *)buf;
2055 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2057 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2058 ip->v4.identification = htons(0xFFFF);
2059 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2060 ip->v4.fragment = htons(0x0000);
2062 ip->v4.protocol = icmp_protocol;
2063 ip->v4.hdr_checksum = htons(0x0000);
2064 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2065 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2066 buf += SWRAP_PACKET_IP_V4_SIZE;
2068 src_port = dest_in->sin_port;
2069 dest_port = src_in->sin_port;
2073 pay->icmp6.type = 0x01; /* destination unreachable */
2074 pay->icmp6.code = 0x03; /* address unreachable */
2075 pay->icmp6.checksum = htons(0x0000);
2076 pay->icmp6.unused = htonl(0x00000000);
2077 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2079 /* set the ip header in the ICMP payload */
2080 ip = (union swrap_packet_ip *)(void *)buf;
2081 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2082 ip->v6.flow_label_high = 0x00;
2083 ip->v6.flow_label_low = 0x0000;
2084 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2085 ip->v6.next_header = protocol;
2086 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2087 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2088 buf += SWRAP_PACKET_IP_V6_SIZE;
2090 src_port = dest_in6->sin6_port;
2091 dest_port = src_in6->sin6_port;
2097 pay = (union swrap_packet_payload *)(void *)buf;
2099 switch (socket_type) {
2101 pay->tcp.source_port = src_port;
2102 pay->tcp.dest_port = dest_port;
2103 pay->tcp.seq_num = htonl(tcp_seqno);
2104 pay->tcp.ack_num = htonl(tcp_ack);
2105 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2106 pay->tcp.control = tcp_ctl;
2107 pay->tcp.window = htons(0x7FFF);
2108 pay->tcp.checksum = htons(0x0000);
2109 pay->tcp.urg = htons(0x0000);
2110 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2115 pay->udp.source_port = src_port;
2116 pay->udp.dest_port = dest_port;
2117 pay->udp.length = htons(8 + payload_len);
2118 pay->udp.checksum = htons(0x0000);
2119 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2124 if (payload && payload_len > 0) {
2125 memcpy(buf, payload, payload_len);
2128 *_packet_len = packet_len - icmp_truncate_len;
2132 static int swrap_pcap_get_fd(const char *fname)
2136 if (fd != -1) return fd;
2138 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2140 struct swrap_file_hdr file_hdr;
2141 file_hdr.magic = 0xA1B2C3D4;
2142 file_hdr.version_major = 0x0002;
2143 file_hdr.version_minor = 0x0004;
2144 file_hdr.timezone = 0x00000000;
2145 file_hdr.sigfigs = 0x00000000;
2146 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2147 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2149 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2156 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2161 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2162 const struct sockaddr *addr,
2163 enum swrap_packet_type type,
2164 const void *buf, size_t len,
2167 const struct sockaddr *src_addr;
2168 const struct sockaddr *dest_addr;
2169 unsigned long tcp_seqno = 0;
2170 unsigned long tcp_ack = 0;
2171 unsigned char tcp_ctl = 0;
2172 int unreachable = 0;
2176 switch (si->family) {
2188 case SWRAP_CONNECT_SEND:
2189 if (si->type != SOCK_STREAM) return NULL;
2191 src_addr = &si->myname.sa.s;
2194 tcp_seqno = si->io.pck_snd;
2195 tcp_ack = si->io.pck_rcv;
2196 tcp_ctl = 0x02; /* SYN */
2198 si->io.pck_snd += 1;
2202 case SWRAP_CONNECT_RECV:
2203 if (si->type != SOCK_STREAM) return NULL;
2205 dest_addr = &si->myname.sa.s;
2208 tcp_seqno = si->io.pck_rcv;
2209 tcp_ack = si->io.pck_snd;
2210 tcp_ctl = 0x12; /** SYN,ACK */
2212 si->io.pck_rcv += 1;
2216 case SWRAP_CONNECT_UNREACH:
2217 if (si->type != SOCK_STREAM) return NULL;
2219 dest_addr = &si->myname.sa.s;
2222 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2223 tcp_seqno = si->io.pck_snd - 1;
2224 tcp_ack = si->io.pck_rcv;
2225 tcp_ctl = 0x02; /* SYN */
2230 case SWRAP_CONNECT_ACK:
2231 if (si->type != SOCK_STREAM) return NULL;
2233 src_addr = &si->myname.sa.s;
2236 tcp_seqno = si->io.pck_snd;
2237 tcp_ack = si->io.pck_rcv;
2238 tcp_ctl = 0x10; /* ACK */
2242 case SWRAP_ACCEPT_SEND:
2243 if (si->type != SOCK_STREAM) return NULL;
2245 dest_addr = &si->myname.sa.s;
2248 tcp_seqno = si->io.pck_rcv;
2249 tcp_ack = si->io.pck_snd;
2250 tcp_ctl = 0x02; /* SYN */
2252 si->io.pck_rcv += 1;
2256 case SWRAP_ACCEPT_RECV:
2257 if (si->type != SOCK_STREAM) return NULL;
2259 src_addr = &si->myname.sa.s;
2262 tcp_seqno = si->io.pck_snd;
2263 tcp_ack = si->io.pck_rcv;
2264 tcp_ctl = 0x12; /* SYN,ACK */
2266 si->io.pck_snd += 1;
2270 case SWRAP_ACCEPT_ACK:
2271 if (si->type != SOCK_STREAM) return NULL;
2273 dest_addr = &si->myname.sa.s;
2276 tcp_seqno = si->io.pck_rcv;
2277 tcp_ack = si->io.pck_snd;
2278 tcp_ctl = 0x10; /* ACK */
2283 src_addr = &si->myname.sa.s;
2284 dest_addr = &si->peername.sa.s;
2286 tcp_seqno = si->io.pck_snd;
2287 tcp_ack = si->io.pck_rcv;
2288 tcp_ctl = 0x18; /* PSH,ACK */
2290 si->io.pck_snd += len;
2294 case SWRAP_SEND_RST:
2295 dest_addr = &si->myname.sa.s;
2296 src_addr = &si->peername.sa.s;
2298 if (si->type == SOCK_DGRAM) {
2299 return swrap_pcap_marshall_packet(si,
2301 SWRAP_SENDTO_UNREACH,
2307 tcp_seqno = si->io.pck_rcv;
2308 tcp_ack = si->io.pck_snd;
2309 tcp_ctl = 0x14; /** RST,ACK */
2313 case SWRAP_PENDING_RST:
2314 dest_addr = &si->myname.sa.s;
2315 src_addr = &si->peername.sa.s;
2317 if (si->type == SOCK_DGRAM) {
2321 tcp_seqno = si->io.pck_rcv;
2322 tcp_ack = si->io.pck_snd;
2323 tcp_ctl = 0x14; /* RST,ACK */
2328 dest_addr = &si->myname.sa.s;
2329 src_addr = &si->peername.sa.s;
2331 tcp_seqno = si->io.pck_rcv;
2332 tcp_ack = si->io.pck_snd;
2333 tcp_ctl = 0x18; /* PSH,ACK */
2335 si->io.pck_rcv += len;
2339 case SWRAP_RECV_RST:
2340 dest_addr = &si->myname.sa.s;
2341 src_addr = &si->peername.sa.s;
2343 if (si->type == SOCK_DGRAM) {
2347 tcp_seqno = si->io.pck_rcv;
2348 tcp_ack = si->io.pck_snd;
2349 tcp_ctl = 0x14; /* RST,ACK */
2354 src_addr = &si->myname.sa.s;
2357 si->io.pck_snd += len;
2361 case SWRAP_SENDTO_UNREACH:
2362 dest_addr = &si->myname.sa.s;
2369 case SWRAP_RECVFROM:
2370 dest_addr = &si->myname.sa.s;
2373 si->io.pck_rcv += len;
2377 case SWRAP_CLOSE_SEND:
2378 if (si->type != SOCK_STREAM) return NULL;
2380 src_addr = &si->myname.sa.s;
2381 dest_addr = &si->peername.sa.s;
2383 tcp_seqno = si->io.pck_snd;
2384 tcp_ack = si->io.pck_rcv;
2385 tcp_ctl = 0x11; /* FIN, ACK */
2387 si->io.pck_snd += 1;
2391 case SWRAP_CLOSE_RECV:
2392 if (si->type != SOCK_STREAM) return NULL;
2394 dest_addr = &si->myname.sa.s;
2395 src_addr = &si->peername.sa.s;
2397 tcp_seqno = si->io.pck_rcv;
2398 tcp_ack = si->io.pck_snd;
2399 tcp_ctl = 0x11; /* FIN,ACK */
2401 si->io.pck_rcv += 1;
2405 case SWRAP_CLOSE_ACK:
2406 if (si->type != SOCK_STREAM) return NULL;
2408 src_addr = &si->myname.sa.s;
2409 dest_addr = &si->peername.sa.s;
2411 tcp_seqno = si->io.pck_snd;
2412 tcp_ack = si->io.pck_rcv;
2413 tcp_ctl = 0x10; /* ACK */
2420 swrapGetTimeOfDay(&tv);
2422 return swrap_pcap_packet_init(&tv,
2426 (const uint8_t *)buf,
2435 static void swrap_pcap_dump_packet(struct socket_info *si,
2436 const struct sockaddr *addr,
2437 enum swrap_packet_type type,
2438 const void *buf, size_t len)
2440 const char *file_name;
2442 size_t packet_len = 0;
2445 file_name = swrap_pcap_init_file();
2450 packet = swrap_pcap_marshall_packet(si,
2456 if (packet == NULL) {
2460 fd = swrap_pcap_get_fd(file_name);
2462 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2471 /****************************************************************************
2473 ***************************************************************************/
2475 #ifdef HAVE_SIGNALFD
2476 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2480 rc = libc_signalfd(fd, mask, flags);
2482 swrap_remove_stale(fd);
2488 int signalfd(int fd, const sigset_t *mask, int flags)
2490 return swrap_signalfd(fd, mask, flags);
2494 /****************************************************************************
2496 ***************************************************************************/
2498 static int swrap_socket(int family, int type, int protocol)
2500 struct socket_info *si;
2501 struct socket_info_fd *fi;
2504 int real_type = type;
2507 * Remove possible addition flags passed to socket() so
2508 * do not fail checking the type.
2509 * See https://lwn.net/Articles/281965/
2512 real_type &= ~SOCK_CLOEXEC;
2514 #ifdef SOCK_NONBLOCK
2515 real_type &= ~SOCK_NONBLOCK;
2518 if (!socket_wrapper_enabled()) {
2519 return libc_socket(family, type, protocol);
2530 #endif /* AF_NETLINK */
2533 #endif /* AF_PACKET */
2535 return libc_socket(family, type, protocol);
2537 errno = EAFNOSUPPORT;
2541 switch (real_type) {
2547 errno = EPROTONOSUPPORT;
2555 if (real_type == SOCK_STREAM) {
2560 if (real_type == SOCK_DGRAM) {
2565 errno = EPROTONOSUPPORT;
2570 * We must call libc_socket with type, from the caller, not the version
2571 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2573 fd = libc_socket(AF_UNIX, type, 0);
2579 /* Check if we have a stale fd and remove it */
2580 swrap_remove_stale(fd);
2582 idx = socket_wrapper_first_free_index();
2590 si->family = family;
2592 /* however, the rest of the socket_wrapper code expects just
2593 * the type, not the flags */
2594 si->type = real_type;
2595 si->protocol = protocol;
2598 * Setup myname so getsockname() can succeed to find out the socket
2601 switch(si->family) {
2603 struct sockaddr_in sin = {
2604 .sin_family = AF_INET,
2607 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2608 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2612 struct sockaddr_in6 sin6 = {
2613 .sin6_family = AF_INET6,
2616 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2617 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2625 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2635 SWRAP_DLIST_ADD(socket_fds, fi);
2637 SWRAP_LOG(SWRAP_LOG_TRACE,
2638 "Created %s socket for protocol %s",
2639 si->family == AF_INET ? "IPv4" : "IPv6",
2640 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2645 int socket(int family, int type, int protocol)
2647 return swrap_socket(family, type, protocol);
2650 /****************************************************************************
2652 ***************************************************************************/
2654 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2658 rc = libc_socketpair(family, type, protocol, sv);
2660 swrap_remove_stale(sv[0]);
2661 swrap_remove_stale(sv[1]);
2667 int socketpair(int family, int type, int protocol, int sv[2])
2669 return swrap_socketpair(family, type, protocol, sv);
2672 /****************************************************************************
2674 ***************************************************************************/
2676 #ifdef HAVE_TIMERFD_CREATE
2677 static int swrap_timerfd_create(int clockid, int flags)
2681 fd = libc_timerfd_create(clockid, flags);
2683 swrap_remove_stale(fd);
2689 int timerfd_create(int clockid, int flags)
2691 return swrap_timerfd_create(clockid, flags);
2695 /****************************************************************************
2697 ***************************************************************************/
2699 static int swrap_pipe(int pipefd[2])
2703 rc = libc_pipe(pipefd);
2705 swrap_remove_stale(pipefd[0]);
2706 swrap_remove_stale(pipefd[1]);
2712 int pipe(int pipefd[2])
2714 return swrap_pipe(pipefd);
2717 /****************************************************************************
2719 ***************************************************************************/
2721 static int swrap_accept(int s,
2722 struct sockaddr *addr,
2726 struct socket_info *parent_si, *child_si;
2727 struct socket_info_fd *child_fi;
2730 struct swrap_address un_addr = {
2731 .sa_socklen = sizeof(struct sockaddr_un),
2733 struct swrap_address un_my_addr = {
2734 .sa_socklen = sizeof(struct sockaddr_un),
2736 struct swrap_address in_addr = {
2737 .sa_socklen = sizeof(struct sockaddr_storage),
2739 struct swrap_address in_my_addr = {
2740 .sa_socklen = sizeof(struct sockaddr_storage),
2744 parent_si = find_socket_info(s);
2747 return libc_accept4(s, addr, addrlen, flags);
2749 return libc_accept(s, addr, addrlen);
2754 * assume out sockaddr have the same size as the in parent
2757 in_addr.sa_socklen = socket_length(parent_si->family);
2758 if (in_addr.sa_socklen <= 0) {
2764 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2766 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2769 if (errno == ENOTSOCK) {
2770 /* Remove stale fds */
2771 swrap_remove_stale(s);
2778 ret = sockaddr_convert_from_un(parent_si,
2783 &in_addr.sa_socklen);
2789 idx = socket_wrapper_first_free_index();
2795 child_si = &sockets[idx];
2797 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2798 if (child_fi == NULL) {
2806 child_si->family = parent_si->family;
2807 child_si->type = parent_si->type;
2808 child_si->protocol = parent_si->protocol;
2809 child_si->bound = 1;
2810 child_si->is_server = 1;
2811 child_si->connected = 1;
2813 child_si->peername = (struct swrap_address) {
2814 .sa_socklen = in_addr.sa_socklen,
2816 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2818 if (addr != NULL && addrlen != NULL) {
2819 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2821 memcpy(addr, &in_addr.sa.ss, copy_len);
2823 *addrlen = in_addr.sa_socklen;
2826 ret = libc_getsockname(fd,
2828 &un_my_addr.sa_socklen);
2835 ret = sockaddr_convert_from_un(child_si,
2837 un_my_addr.sa_socklen,
2840 &in_my_addr.sa_socklen);
2847 SWRAP_LOG(SWRAP_LOG_TRACE,
2848 "accept() path=%s, fd=%d",
2849 un_my_addr.sa.un.sun_path, s);
2851 child_si->myname = (struct swrap_address) {
2852 .sa_socklen = in_my_addr.sa_socklen,
2854 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2856 child_si->refcount = 1;
2857 child_fi->si_index = idx;
2859 SWRAP_DLIST_ADD(socket_fds, child_fi);
2862 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2863 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2864 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2871 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
2873 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
2877 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2878 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2880 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2883 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
2886 static int autobind_start_init;
2887 static int autobind_start;
2889 /* using sendto() or connect() on an unbound socket would give the
2890 recipient no way to reply, as unlike UDP and TCP, a unix domain
2891 socket can't auto-assign ephemeral port numbers, so we need to
2893 Note: this might change the family from ipv6 to ipv4
2895 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2897 struct swrap_address un_addr = {
2898 .sa_socklen = sizeof(struct sockaddr_un),
2906 if (autobind_start_init != 1) {
2907 autobind_start_init = 1;
2908 autobind_start = getpid();
2909 autobind_start %= 50000;
2910 autobind_start += 10000;
2913 un_addr.sa.un.sun_family = AF_UNIX;
2917 struct sockaddr_in in;
2921 type = SOCKET_TYPE_CHAR_TCP;
2924 type = SOCKET_TYPE_CHAR_UDP;
2927 errno = ESOCKTNOSUPPORT;
2931 memset(&in, 0, sizeof(in));
2932 in.sin_family = AF_INET;
2933 in.sin_addr.s_addr = htonl(127<<24 |
2934 socket_wrapper_default_iface());
2936 si->myname = (struct swrap_address) {
2937 .sa_socklen = sizeof(in),
2939 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2944 struct sockaddr_in6 in6;
2946 if (si->family != family) {
2947 errno = ENETUNREACH;
2953 type = SOCKET_TYPE_CHAR_TCP_V6;
2956 type = SOCKET_TYPE_CHAR_UDP_V6;
2959 errno = ESOCKTNOSUPPORT;
2963 memset(&in6, 0, sizeof(in6));
2964 in6.sin6_family = AF_INET6;
2965 in6.sin6_addr = *swrap_ipv6();
2966 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2968 si->myname = (struct swrap_address) {
2969 .sa_socklen = sizeof(in6),
2971 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2976 errno = ESOCKTNOSUPPORT;
2980 if (autobind_start > 60000) {
2981 autobind_start = 10000;
2984 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2985 port = autobind_start + i;
2986 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2987 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2988 type, socket_wrapper_default_iface(), port);
2989 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2991 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2992 if (ret == -1) return ret;
2994 si->un_addr = un_addr.sa.un;
2997 autobind_start = port + 1;
3000 if (i == SOCKET_MAX_SOCKETS) {
3001 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3002 "interface "SOCKET_FORMAT,
3005 socket_wrapper_default_iface(),
3011 si->family = family;
3012 set_port(si->family, port, &si->myname);
3017 /****************************************************************************
3019 ***************************************************************************/
3021 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3025 struct swrap_address un_addr = {
3026 .sa_socklen = sizeof(struct sockaddr_un),
3028 struct socket_info *si = find_socket_info(s);
3032 return libc_connect(s, serv_addr, addrlen);
3035 if (si->bound == 0) {
3036 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3037 if (ret == -1) return -1;
3040 if (si->family != serv_addr->sa_family) {
3045 ret = sockaddr_convert_to_un(si, serv_addr,
3046 addrlen, &un_addr.sa.un, 0, &bcast);
3047 if (ret == -1) return -1;
3050 errno = ENETUNREACH;
3054 if (si->type == SOCK_DGRAM) {
3055 si->defer_connect = 1;
3058 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3060 ret = libc_connect(s,
3062 un_addr.sa_socklen);
3065 SWRAP_LOG(SWRAP_LOG_TRACE,
3066 "connect() path=%s, fd=%d",
3067 un_addr.sa.un.sun_path, s);
3070 /* to give better errors */
3071 if (ret == -1 && errno == ENOENT) {
3072 errno = EHOSTUNREACH;
3076 si->peername = (struct swrap_address) {
3077 .sa_socklen = addrlen,
3080 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3084 * When we connect() on a socket than we have to bind the
3085 * outgoing connection on the interface we use for the
3086 * transport. We already bound it on the right interface
3087 * but here we have to update the name so getsockname()
3088 * returns correct information.
3090 if (si->bindname.sa_socklen > 0) {
3091 si->myname = (struct swrap_address) {
3092 .sa_socklen = si->bindname.sa_socklen,
3095 memcpy(&si->myname.sa.ss,
3096 &si->bindname.sa.ss,
3097 si->bindname.sa_socklen);
3099 /* Cleanup bindname */
3100 si->bindname = (struct swrap_address) {
3105 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3106 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3108 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3114 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3116 return swrap_connect(s, serv_addr, addrlen);
3119 /****************************************************************************
3121 ***************************************************************************/
3123 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3126 struct swrap_address un_addr = {
3127 .sa_socklen = sizeof(struct sockaddr_un),
3129 struct socket_info *si = find_socket_info(s);
3136 return libc_bind(s, myaddr, addrlen);
3139 switch (si->family) {
3141 const struct sockaddr_in *sin;
3142 if (addrlen < sizeof(struct sockaddr_in)) {
3143 bind_error = EINVAL;
3147 sin = (const struct sockaddr_in *)(const void *)myaddr;
3149 if (sin->sin_family != AF_INET) {
3150 bind_error = EAFNOSUPPORT;
3153 /* special case for AF_UNSPEC */
3154 if (sin->sin_family == AF_UNSPEC &&
3155 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3164 const struct sockaddr_in6 *sin6;
3165 if (addrlen < sizeof(struct sockaddr_in6)) {
3166 bind_error = EINVAL;
3170 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3172 if (sin6->sin6_family != AF_INET6) {
3173 bind_error = EAFNOSUPPORT;
3180 bind_error = EINVAL;
3184 if (bind_error != 0) {
3190 in_use = check_addr_port_in_use(myaddr, addrlen);
3197 si->myname.sa_socklen = addrlen;
3198 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3200 ret = sockaddr_convert_to_un(si,
3206 if (ret == -1) return -1;
3208 unlink(un_addr.sa.un.sun_path);
3210 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3212 SWRAP_LOG(SWRAP_LOG_TRACE,
3213 "bind() path=%s, fd=%d",
3214 un_addr.sa.un.sun_path, s);
3223 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3225 return swrap_bind(s, myaddr, addrlen);
3228 /****************************************************************************
3230 ***************************************************************************/
3232 #ifdef HAVE_BINDRESVPORT
3233 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3235 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3237 struct swrap_address myaddr = {
3238 .sa_socklen = sizeof(struct sockaddr_storage),
3241 static uint16_t port;
3246 #define SWRAP_STARTPORT 600
3247 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3248 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3251 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3255 salen = myaddr.sa_socklen;
3258 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3264 memset(&myaddr.sa.ss, 0, salen);
3269 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3272 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3274 salen = sizeof(struct sockaddr_in);
3275 sinp->sin_port = htons(port);
3279 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3281 salen = sizeof(struct sockaddr_in6);
3282 sin6p->sin6_port = htons(port);
3286 errno = EAFNOSUPPORT;
3291 if (port > SWRAP_ENDPORT) {
3292 port = SWRAP_STARTPORT;
3295 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3296 if (rc == 0 || errno != EADDRINUSE) {
3304 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3306 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3310 /****************************************************************************
3312 ***************************************************************************/
3314 static int swrap_listen(int s, int backlog)
3317 struct socket_info *si = find_socket_info(s);
3320 return libc_listen(s, backlog);
3323 if (si->bound == 0) {
3324 ret = swrap_auto_bind(s, si, si->family);
3331 ret = libc_listen(s, backlog);
3336 int listen(int s, int backlog)
3338 return swrap_listen(s, backlog);
3341 /****************************************************************************
3343 ***************************************************************************/
3345 static FILE *swrap_fopen(const char *name, const char *mode)
3349 fp = libc_fopen(name, mode);
3351 int fd = fileno(fp);
3353 swrap_remove_stale(fd);
3359 FILE *fopen(const char *name, const char *mode)
3361 return swrap_fopen(name, mode);
3364 /****************************************************************************
3366 ***************************************************************************/
3368 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3372 ret = libc_vopen(pathname, flags, ap);
3375 * There are methods for closing descriptors (libc-internal code
3376 * paths, direct syscalls) which close descriptors in ways that
3377 * we can't intercept, so try to recover when we notice that
3380 swrap_remove_stale(ret);
3385 int open(const char *pathname, int flags, ...)
3390 va_start(ap, flags);
3391 fd = swrap_vopen(pathname, flags, ap);
3397 /****************************************************************************
3399 ***************************************************************************/
3401 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3403 struct socket_info *si = find_socket_info(s);
3407 return libc_getpeername(s, name, addrlen);
3410 if (si->peername.sa_socklen == 0)
3416 len = MIN(*addrlen, si->peername.sa_socklen);
3421 memcpy(name, &si->peername.sa.ss, len);
3422 *addrlen = si->peername.sa_socklen;
3427 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3428 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3430 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3433 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3436 /****************************************************************************
3438 ***************************************************************************/
3440 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3442 struct socket_info *si = find_socket_info(s);
3446 return libc_getsockname(s, name, addrlen);
3449 len = MIN(*addrlen, si->myname.sa_socklen);
3454 memcpy(name, &si->myname.sa.ss, len);
3455 *addrlen = si->myname.sa_socklen;
3460 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3461 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3463 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3466 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3469 /****************************************************************************
3471 ***************************************************************************/
3474 # ifdef SO_PROTOTYPE /* The Solaris name */
3475 # define SO_PROTOCOL SO_PROTOTYPE
3476 # endif /* SO_PROTOTYPE */
3477 #endif /* SO_PROTOCOL */
3479 static int swrap_getsockopt(int s, int level, int optname,
3480 void *optval, socklen_t *optlen)
3482 struct socket_info *si = find_socket_info(s);
3485 return libc_getsockopt(s,
3492 if (level == SOL_SOCKET) {
3496 if (optval == NULL || optlen == NULL ||
3497 *optlen < (socklen_t)sizeof(int)) {
3502 *optlen = sizeof(int);
3503 *(int *)optval = si->family;
3505 #endif /* SO_DOMAIN */
3509 if (optval == NULL || optlen == NULL ||
3510 *optlen < (socklen_t)sizeof(int)) {
3515 *optlen = sizeof(int);
3516 *(int *)optval = si->protocol;
3518 #endif /* SO_PROTOCOL */
3520 if (optval == NULL || optlen == NULL ||
3521 *optlen < (socklen_t)sizeof(int)) {
3526 *optlen = sizeof(int);
3527 *(int *)optval = si->type;
3530 return libc_getsockopt(s,
3536 } else if (level == IPPROTO_TCP) {
3541 * This enables sending packets directly out over TCP.
3542 * As a unix socket is doing that any way, report it as
3545 if (optval == NULL || optlen == NULL ||
3546 *optlen < (socklen_t)sizeof(int)) {
3551 *optlen = sizeof(int);
3552 *(int *)optval = si->tcp_nodelay;
3555 #endif /* TCP_NODELAY */
3561 errno = ENOPROTOOPT;
3565 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3566 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3568 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3571 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3574 /****************************************************************************
3576 ***************************************************************************/
3578 static int swrap_setsockopt(int s, int level, int optname,
3579 const void *optval, socklen_t optlen)
3581 struct socket_info *si = find_socket_info(s);
3584 return libc_setsockopt(s,
3591 if (level == SOL_SOCKET) {
3592 return libc_setsockopt(s,
3597 } else if (level == IPPROTO_TCP) {
3604 * This enables sending packets directly out over TCP.
3605 * A unix socket is doing that any way.
3607 if (optval == NULL || optlen == 0 ||
3608 optlen < (socklen_t)sizeof(int)) {
3613 i = *discard_const_p(int, optval);
3614 if (i != 0 && i != 1) {
3618 si->tcp_nodelay = i;
3622 #endif /* TCP_NODELAY */
3628 switch (si->family) {
3630 if (level == IPPROTO_IP) {
3632 if (optname == IP_PKTINFO) {
3633 si->pktinfo = AF_INET;
3635 #endif /* IP_PKTINFO */
3640 if (level == IPPROTO_IPV6) {
3641 #ifdef IPV6_RECVPKTINFO
3642 if (optname == IPV6_RECVPKTINFO) {
3643 si->pktinfo = AF_INET6;
3645 #endif /* IPV6_PKTINFO */
3650 errno = ENOPROTOOPT;
3655 int setsockopt(int s, int level, int optname,
3656 const void *optval, socklen_t optlen)
3658 return swrap_setsockopt(s, level, optname, optval, optlen);
3661 /****************************************************************************
3663 ***************************************************************************/
3665 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3667 struct socket_info *si = find_socket_info(s);
3673 return libc_vioctl(s, r, va);
3678 rc = libc_vioctl(s, r, va);
3682 value = *((int *)va_arg(ap, int *));
3684 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3685 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3686 } else if (value == 0) { /* END OF FILE */
3687 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3697 #ifdef HAVE_IOCTL_INT
3698 int ioctl(int s, int r, ...)
3700 int ioctl(int s, unsigned long int r, ...)
3708 rc = swrap_vioctl(s, (unsigned long int) r, va);
3719 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3722 # ifdef _ALIGN /* BSD */
3723 #define CMSG_ALIGN _ALIGN
3725 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3726 # endif /* _ALIGN */
3727 #endif /* CMSG_ALIGN */
3730 * @brief Add a cmsghdr to a msghdr.
3732 * This is an function to add any type of cmsghdr. It will operate on the
3733 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3734 * the buffer position after the added cmsg element. Hence, this function is
3735 * intended to be used with an intermediate msghdr and not on the original
3736 * one handed in by the client.
3738 * @param[in] msg The msghdr to which to add the cmsg.
3740 * @param[in] level The cmsg level to set.
3742 * @param[in] type The cmsg type to set.
3744 * @param[in] data The cmsg data to set.
3746 * @param[in] len the length of the data to set.
3748 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3754 size_t cmlen = CMSG_LEN(len);
3755 size_t cmspace = CMSG_SPACE(len);
3756 uint8_t cmbuf[cmspace];
3757 void *cast_ptr = (void *)cmbuf;
3758 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3761 memset(cmbuf, 0, cmspace);
3763 if (msg->msg_controllen < cmlen) {
3764 cmlen = msg->msg_controllen;
3765 msg->msg_flags |= MSG_CTRUNC;
3768 if (msg->msg_controllen < cmspace) {
3769 cmspace = msg->msg_controllen;
3773 * We copy the full input data into an intermediate cmsghdr first
3774 * in order to more easily cope with truncation.
3776 cm->cmsg_len = cmlen;
3777 cm->cmsg_level = level;
3778 cm->cmsg_type = type;
3779 memcpy(CMSG_DATA(cm), data, len);
3782 * We now copy the possibly truncated buffer.
3783 * We copy cmlen bytes, but consume cmspace bytes,
3784 * leaving the possible padding uninitialiazed.
3786 p = (uint8_t *)msg->msg_control;
3787 memcpy(p, cm, cmlen);
3789 msg->msg_control = p;
3790 msg->msg_controllen -= cmspace;
3795 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3798 /* Add packet info */
3799 switch (si->pktinfo) {
3800 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3802 struct sockaddr_in *sin;
3803 #if defined(HAVE_STRUCT_IN_PKTINFO)
3804 struct in_pktinfo pkt;
3805 #elif defined(IP_RECVDSTADDR)
3809 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3810 sin = &si->bindname.sa.in;
3812 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3815 sin = &si->myname.sa.in;
3820 #if defined(HAVE_STRUCT_IN_PKTINFO)
3821 pkt.ipi_ifindex = socket_wrapper_default_iface();
3822 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3823 #elif defined(IP_RECVDSTADDR)
3824 pkt = sin->sin_addr;
3827 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3832 #endif /* IP_PKTINFO */
3833 #if defined(HAVE_IPV6)
3835 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3836 struct sockaddr_in6 *sin6;
3837 struct in6_pktinfo pkt6;
3839 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3840 sin6 = &si->bindname.sa.in6;
3842 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3845 sin6 = &si->myname.sa.in6;
3850 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3851 pkt6.ipi6_addr = sin6->sin6_addr;
3853 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3854 &pkt6, sizeof(pkt6));
3855 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3859 #endif /* IPV6_PKTINFO */
3867 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3868 struct msghdr *omsg)
3872 if (si->pktinfo > 0) {
3873 rc = swrap_msghdr_add_pktinfo(si, omsg);
3879 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3881 size_t *cm_data_space);
3882 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3884 size_t *cm_data_space);
3886 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3888 size_t *cm_data_space) {
3889 struct cmsghdr *cmsg;
3893 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3897 for (cmsg = CMSG_FIRSTHDR(msg);
3899 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3900 switch (cmsg->cmsg_level) {
3902 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3907 rc = swrap_sendmsg_copy_cmsg(cmsg,
3917 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3919 size_t *cm_data_space)
3924 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
3926 p = realloc((*cm_data), cmspace);
3932 p = (*cm_data) + (*cm_data_space);
3933 *cm_data_space = cmspace;
3935 memcpy(p, cmsg, cmsg->cmsg_len);
3940 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3942 size_t *cm_data_space);
3945 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3947 size_t *cm_data_space)
3951 switch(cmsg->cmsg_type) {
3954 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3961 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3973 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3975 size_t *cm_data_space)
3977 (void)cmsg; /* unused */
3978 (void)cm_data; /* unused */
3979 (void)cm_data_space; /* unused */
3982 * Passing a IP pktinfo to a unix socket might be rejected by the
3983 * Kernel, at least on FreeBSD. So skip this cmsg.
3987 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3989 static ssize_t swrap_sendmsg_before(int fd,
3990 struct socket_info *si,
3992 struct iovec *tmp_iov,
3993 struct sockaddr_un *tmp_un,
3994 const struct sockaddr_un **to_un,
3995 const struct sockaddr **to,
4015 if (!si->connected) {
4020 if (msg->msg_iovlen == 0) {
4024 mtu = socket_wrapper_mtu();
4025 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4027 nlen = len + msg->msg_iov[i].iov_len;
4032 msg->msg_iovlen = i;
4033 if (msg->msg_iovlen == 0) {
4034 *tmp_iov = msg->msg_iov[0];
4035 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4037 msg->msg_iov = tmp_iov;
4038 msg->msg_iovlen = 1;
4043 if (si->connected) {
4044 if (msg->msg_name != NULL) {
4046 * We are dealing with unix sockets and if we
4047 * are connected, we should only talk to the
4048 * connected unix path. Using the fd to send
4049 * to another server would be hard to achieve.
4051 msg->msg_name = NULL;
4052 msg->msg_namelen = 0;
4055 const struct sockaddr *msg_name;
4056 msg_name = (const struct sockaddr *)msg->msg_name;
4058 if (msg_name == NULL) {
4064 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4066 if (ret == -1) return -1;
4074 msg->msg_name = tmp_un;
4075 msg->msg_namelen = sizeof(*tmp_un);
4078 if (si->bound == 0) {
4079 ret = swrap_auto_bind(fd, si, si->family);
4081 if (errno == ENOTSOCK) {
4082 swrap_remove_stale(fd);
4085 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4091 if (!si->defer_connect) {
4095 ret = sockaddr_convert_to_un(si,
4097 si->peername.sa_socklen,
4101 if (ret == -1) return -1;
4103 ret = libc_connect(fd,
4104 (struct sockaddr *)(void *)tmp_un,
4107 /* to give better errors */
4108 if (ret == -1 && errno == ENOENT) {
4109 errno = EHOSTUNREACH;
4116 si->defer_connect = 0;
4119 errno = EHOSTUNREACH;
4123 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4124 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4125 uint8_t *cmbuf = NULL;
4128 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4135 msg->msg_controllen = 0;
4136 msg->msg_control = NULL;
4137 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4138 memcpy(msg->msg_control, cmbuf, cmlen);
4139 msg->msg_controllen = cmlen;
4148 static void swrap_sendmsg_after(int fd,
4149 struct socket_info *si,
4151 const struct sockaddr *to,
4154 int saved_errno = errno;
4161 /* to give better errors */
4163 if (saved_errno == ENOENT) {
4164 saved_errno = EHOSTUNREACH;
4165 } else if (saved_errno == ENOTSOCK) {
4166 /* If the fd is not a socket, remove it */
4167 swrap_remove_stale(fd);
4171 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4172 avail += msg->msg_iov[i].iov_len;
4176 remain = MIN(80, avail);
4181 /* we capture it as one single packet */
4182 buf = (uint8_t *)malloc(remain);
4184 /* we just not capture the packet */
4185 errno = saved_errno;
4189 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4190 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4192 msg->msg_iov[i].iov_base,
4195 remain -= this_time;
4202 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4203 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4205 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4210 if (si->connected) {
4211 to = &si->peername.sa.s;
4214 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4215 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4217 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4223 errno = saved_errno;
4226 static int swrap_recvmsg_before(int fd,
4227 struct socket_info *si,
4229 struct iovec *tmp_iov)
4234 (void)fd; /* unused */
4239 if (!si->connected) {
4244 if (msg->msg_iovlen == 0) {
4248 mtu = socket_wrapper_mtu();
4249 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4251 nlen = len + msg->msg_iov[i].iov_len;
4256 msg->msg_iovlen = i;
4257 if (msg->msg_iovlen == 0) {
4258 *tmp_iov = msg->msg_iov[0];
4259 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4261 msg->msg_iov = tmp_iov;
4262 msg->msg_iovlen = 1;
4267 if (msg->msg_name == NULL) {
4272 if (msg->msg_iovlen == 0) {
4276 if (si->bound == 0) {
4277 ret = swrap_auto_bind(fd, si, si->family);
4280 * When attempting to read or write to a
4281 * descriptor, if an underlying autobind fails
4282 * because it's not a socket, stop intercepting
4283 * uses of that descriptor.
4285 if (errno == ENOTSOCK) {
4286 swrap_remove_stale(fd);
4289 SWRAP_LOG(SWRAP_LOG_ERROR,
4290 "swrap_recvmsg_before failed");
4297 errno = EHOSTUNREACH;
4304 static int swrap_recvmsg_after(int fd,
4305 struct socket_info *si,
4307 const struct sockaddr_un *un_addr,
4308 socklen_t un_addrlen,
4311 int saved_errno = errno;
4313 uint8_t *buf = NULL;
4319 /* to give better errors */
4321 if (saved_errno == ENOENT) {
4322 saved_errno = EHOSTUNREACH;
4323 } else if (saved_errno == ENOTSOCK) {
4324 /* If the fd is not a socket, remove it */
4325 swrap_remove_stale(fd);
4329 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4330 avail += msg->msg_iov[i].iov_len;
4333 /* Convert the socket address before we leave */
4334 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4335 rc = sockaddr_convert_from_un(si,
4352 remain = MIN(80, avail);
4357 /* we capture it as one single packet */
4358 buf = (uint8_t *)malloc(remain);
4360 /* we just not capture the packet */
4361 errno = saved_errno;
4365 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4366 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4368 msg->msg_iov[i].iov_base,
4371 remain -= this_time;
4376 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4377 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4378 } else if (ret == 0) { /* END OF FILE */
4379 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4380 } else if (ret > 0) {
4381 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4390 if (un_addr != NULL) {
4391 swrap_pcap_dump_packet(si,
4397 swrap_pcap_dump_packet(si,
4410 errno = saved_errno;
4412 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4414 msg->msg_controllen > 0 &&
4415 msg->msg_control != NULL) {
4416 rc = swrap_msghdr_add_socket_info(si, msg);
4426 /****************************************************************************
4428 ***************************************************************************/
4430 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4431 struct sockaddr *from, socklen_t *fromlen)
4433 struct swrap_address from_addr = {
4434 .sa_socklen = sizeof(struct sockaddr_un),
4437 struct socket_info *si = find_socket_info(s);
4438 struct swrap_address saddr = {
4439 .sa_socklen = sizeof(struct sockaddr_storage),
4446 return libc_recvfrom(s,
4458 if (from != NULL && fromlen != NULL) {
4459 msg.msg_name = from; /* optional address */
4460 msg.msg_namelen = *fromlen; /* size of address */
4462 msg.msg_name = &saddr.sa.s; /* optional address */
4463 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4465 msg.msg_iov = &tmp; /* scatter/gather array */
4466 msg.msg_iovlen = 1; /* # elements in msg_iov */
4467 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4468 msg.msg_control = NULL; /* ancillary data, see below */
4469 msg.msg_controllen = 0; /* ancillary data buffer len */
4470 msg.msg_flags = 0; /* flags on received message */
4473 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4478 buf = msg.msg_iov[0].iov_base;
4479 len = msg.msg_iov[0].iov_len;
4481 ret = libc_recvfrom(s,
4486 &from_addr.sa_socklen);
4491 tret = swrap_recvmsg_after(s,
4495 from_addr.sa_socklen,
4501 if (from != NULL && fromlen != NULL) {
4502 *fromlen = msg.msg_namelen;
4508 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4509 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4510 struct sockaddr *from, Psocklen_t fromlen)
4512 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4513 struct sockaddr *from, socklen_t *fromlen)
4516 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4519 /****************************************************************************
4521 ***************************************************************************/
4523 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4524 const struct sockaddr *to, socklen_t tolen)
4528 struct swrap_address un_addr = {
4529 .sa_socklen = sizeof(struct sockaddr_un),
4531 const struct sockaddr_un *to_un = NULL;
4534 struct socket_info *si = find_socket_info(s);
4538 return libc_sendto(s, buf, len, flags, to, tolen);
4541 tmp.iov_base = discard_const_p(char, buf);
4545 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4546 msg.msg_namelen = tolen; /* size of address */
4547 msg.msg_iov = &tmp; /* scatter/gather array */
4548 msg.msg_iovlen = 1; /* # elements in msg_iov */
4549 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4550 msg.msg_control = NULL; /* ancillary data, see below */
4551 msg.msg_controllen = 0; /* ancillary data buffer len */
4552 msg.msg_flags = 0; /* flags on received message */
4555 rc = swrap_sendmsg_before(s,
4567 buf = msg.msg_iov[0].iov_base;
4568 len = msg.msg_iov[0].iov_len;
4573 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4576 type = SOCKET_TYPE_CHAR_UDP;
4578 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4579 snprintf(un_addr.sa.un.sun_path,
4580 sizeof(un_addr.sa.un.sun_path),
4582 socket_wrapper_dir(), type, iface, prt);
4583 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4585 /* ignore the any errors in broadcast sends */
4591 un_addr.sa_socklen);
4594 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4600 * If it is a dgram socket and we are connected, don't include the
4603 if (si->type == SOCK_DGRAM && si->connected) {
4604 ret = libc_sendto(s,
4611 ret = libc_sendto(s,
4615 (struct sockaddr *)msg.msg_name,
4619 swrap_sendmsg_after(s, si, &msg, to, ret);
4624 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4625 const struct sockaddr *to, socklen_t tolen)
4627 return swrap_sendto(s, buf, len, flags, to, tolen);
4630 /****************************************************************************
4632 ***************************************************************************/
4634 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4636 struct socket_info *si;
4638 struct swrap_address saddr = {
4639 .sa_socklen = sizeof(struct sockaddr_storage),
4645 si = find_socket_info(s);
4647 return libc_recv(s, buf, len, flags);
4654 msg.msg_name = &saddr.sa.s; /* optional address */
4655 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4656 msg.msg_iov = &tmp; /* scatter/gather array */
4657 msg.msg_iovlen = 1; /* # elements in msg_iov */
4658 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4659 msg.msg_control = NULL; /* ancillary data, see below */
4660 msg.msg_controllen = 0; /* ancillary data buffer len */
4661 msg.msg_flags = 0; /* flags on received message */
4664 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4669 buf = msg.msg_iov[0].iov_base;
4670 len = msg.msg_iov[0].iov_len;
4672 ret = libc_recv(s, buf, len, flags);
4674 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4682 ssize_t recv(int s, void *buf, size_t len, int flags)
4684 return swrap_recv(s, buf, len, flags);
4687 /****************************************************************************
4689 ***************************************************************************/
4691 static ssize_t swrap_read(int s, void *buf, size_t len)
4693 struct socket_info *si;
4696 struct swrap_address saddr = {
4697 .sa_socklen = sizeof(struct sockaddr_storage),
4702 si = find_socket_info(s);
4704 return libc_read(s, buf, len);
4711 msg.msg_name = &saddr.sa.ss; /* optional address */
4712 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4713 msg.msg_iov = &tmp; /* scatter/gather array */
4714 msg.msg_iovlen = 1; /* # elements in msg_iov */
4715 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4716 msg.msg_control = NULL; /* ancillary data, see below */
4717 msg.msg_controllen = 0; /* ancillary data buffer len */
4718 msg.msg_flags = 0; /* flags on received message */
4721 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4723 if (tret == -ENOTSOCK) {
4724 return libc_read(s, buf, len);
4729 buf = msg.msg_iov[0].iov_base;
4730 len = msg.msg_iov[0].iov_len;
4732 ret = libc_read(s, buf, len);
4734 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4742 ssize_t read(int s, void *buf, size_t len)
4744 return swrap_read(s, buf, len);
4747 /****************************************************************************
4749 ***************************************************************************/
4751 static ssize_t swrap_write(int s, const void *buf, size_t len)
4755 struct sockaddr_un un_addr;
4758 struct socket_info *si;
4760 si = find_socket_info(s);
4762 return libc_write(s, buf, len);
4765 tmp.iov_base = discard_const_p(char, buf);
4769 msg.msg_name = NULL; /* optional address */
4770 msg.msg_namelen = 0; /* size of address */
4771 msg.msg_iov = &tmp; /* scatter/gather array */
4772 msg.msg_iovlen = 1; /* # elements in msg_iov */
4773 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4774 msg.msg_control = NULL; /* ancillary data, see below */
4775 msg.msg_controllen = 0; /* ancillary data buffer len */
4776 msg.msg_flags = 0; /* flags on received message */
4779 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4784 buf = msg.msg_iov[0].iov_base;
4785 len = msg.msg_iov[0].iov_len;
4787 ret = libc_write(s, buf, len);
4789 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4794 ssize_t write(int s, const void *buf, size_t len)
4796 return swrap_write(s, buf, len);
4799 /****************************************************************************
4801 ***************************************************************************/
4803 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4807 struct sockaddr_un un_addr;
4810 struct socket_info *si = find_socket_info(s);
4813 return libc_send(s, buf, len, flags);
4816 tmp.iov_base = discard_const_p(char, buf);
4820 msg.msg_name = NULL; /* optional address */
4821 msg.msg_namelen = 0; /* size of address */
4822 msg.msg_iov = &tmp; /* scatter/gather array */
4823 msg.msg_iovlen = 1; /* # elements in msg_iov */
4824 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4825 msg.msg_control = NULL; /* ancillary data, see below */
4826 msg.msg_controllen = 0; /* ancillary data buffer len */
4827 msg.msg_flags = 0; /* flags on received message */
4830 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4835 buf = msg.msg_iov[0].iov_base;
4836 len = msg.msg_iov[0].iov_len;
4838 ret = libc_send(s, buf, len, flags);
4840 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4845 ssize_t send(int s, const void *buf, size_t len, int flags)
4847 return swrap_send(s, buf, len, flags);
4850 /****************************************************************************
4852 ***************************************************************************/
4854 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4856 struct swrap_address from_addr = {
4857 .sa_socklen = sizeof(struct sockaddr_un),
4859 struct swrap_address convert_addr = {
4860 .sa_socklen = sizeof(struct sockaddr_storage),
4862 struct socket_info *si;
4865 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4866 size_t msg_ctrllen_filled;
4867 size_t msg_ctrllen_left;
4873 si = find_socket_info(s);
4875 return libc_recvmsg(s, omsg, flags);
4878 tmp.iov_base = NULL;
4882 msg.msg_name = &from_addr.sa; /* optional address */
4883 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4884 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4885 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4886 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4887 msg_ctrllen_filled = 0;
4888 msg_ctrllen_left = omsg->msg_controllen;
4890 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4891 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4892 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4895 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4900 ret = libc_recvmsg(s, &msg, flags);
4902 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4903 msg_ctrllen_filled += msg.msg_controllen;
4904 msg_ctrllen_left -= msg.msg_controllen;
4906 if (omsg->msg_control != NULL) {
4909 p = omsg->msg_control;
4910 p += msg_ctrllen_filled;
4912 msg.msg_control = p;
4913 msg.msg_controllen = msg_ctrllen_left;
4915 msg.msg_control = NULL;
4916 msg.msg_controllen = 0;
4921 * We convert the unix address to a IP address so we need a buffer
4922 * which can store the address in case of SOCK_DGRAM, see below.
4924 msg.msg_name = &convert_addr.sa;
4925 msg.msg_namelen = convert_addr.sa_socklen;
4927 rc = swrap_recvmsg_after(s,
4931 from_addr.sa_socklen,
4937 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4938 if (omsg->msg_control != NULL) {
4939 /* msg.msg_controllen = space left */
4940 msg_ctrllen_left = msg.msg_controllen;
4941 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4944 /* Update the original message length */
4945 omsg->msg_controllen = msg_ctrllen_filled;
4946 omsg->msg_flags = msg.msg_flags;
4948 omsg->msg_iovlen = msg.msg_iovlen;
4953 * The msg_name field points to a caller-allocated buffer that is
4954 * used to return the source address if the socket is unconnected. The
4955 * caller should set msg_namelen to the size of this buffer before this
4956 * call; upon return from a successful call, msg_name will contain the
4957 * length of the returned address. If the application does not need
4958 * to know the source address, msg_name can be specified as NULL.
4960 if (si->type == SOCK_STREAM) {
4961 omsg->msg_namelen = 0;
4962 } else if (omsg->msg_name != NULL &&
4963 omsg->msg_namelen != 0 &&
4964 omsg->msg_namelen >= msg.msg_namelen) {
4965 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
4966 omsg->msg_namelen = msg.msg_namelen;
4972 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4974 return swrap_recvmsg(sockfd, msg, flags);
4977 /****************************************************************************
4979 ***************************************************************************/
4981 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4985 struct sockaddr_un un_addr;
4986 const struct sockaddr_un *to_un = NULL;
4987 const struct sockaddr *to = NULL;
4990 struct socket_info *si = find_socket_info(s);
4994 return libc_sendmsg(s, omsg, flags);
4997 ZERO_STRUCT(un_addr);
4999 tmp.iov_base = NULL;
5004 if (si->connected == 0) {
5005 msg.msg_name = omsg->msg_name; /* optional address */
5006 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5008 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5009 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5010 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5011 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5012 /* omsg is a const so use a local buffer for modifications */
5013 uint8_t cmbuf[omsg->msg_controllen];
5015 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5017 msg.msg_control = cmbuf; /* ancillary data, see below */
5018 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5020 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5023 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5031 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5039 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5040 avail += msg.msg_iov[i].iov_len;
5046 /* we capture it as one single packet */
5047 buf = (uint8_t *)malloc(remain);
5052 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5053 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5055 msg.msg_iov[i].iov_base,
5058 remain -= this_time;
5061 type = SOCKET_TYPE_CHAR_UDP;
5063 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5064 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5065 socket_wrapper_dir(), type, iface, prt);
5066 if (stat(un_addr.sun_path, &st) != 0) continue;
5068 msg.msg_name = &un_addr; /* optional address */
5069 msg.msg_namelen = sizeof(un_addr); /* size of address */
5071 /* ignore the any errors in broadcast sends */
5072 libc_sendmsg(s, &msg, flags);
5075 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5081 ret = libc_sendmsg(s, &msg, flags);
5083 swrap_sendmsg_after(s, si, &msg, to, ret);
5088 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5090 return swrap_sendmsg(s, omsg, flags);
5093 /****************************************************************************
5095 ***************************************************************************/
5097 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5099 struct socket_info *si;
5102 struct swrap_address saddr = {
5103 .sa_socklen = sizeof(struct sockaddr_storage)
5108 si = find_socket_info(s);
5110 return libc_readv(s, vector, count);
5113 tmp.iov_base = NULL;
5117 msg.msg_name = &saddr.sa.s; /* optional address */
5118 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5119 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5120 msg.msg_iovlen = count; /* # elements in msg_iov */
5121 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5122 msg.msg_control = NULL; /* ancillary data, see below */
5123 msg.msg_controllen = 0; /* ancillary data buffer len */
5124 msg.msg_flags = 0; /* flags on received message */
5127 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5129 if (rc == -ENOTSOCK) {
5130 return libc_readv(s, vector, count);
5135 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5137 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5145 ssize_t readv(int s, const struct iovec *vector, int count)
5147 return swrap_readv(s, vector, count);
5150 /****************************************************************************
5152 ***************************************************************************/
5154 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5158 struct sockaddr_un un_addr;
5161 struct socket_info *si = find_socket_info(s);
5164 return libc_writev(s, vector, count);
5167 tmp.iov_base = NULL;
5171 msg.msg_name = NULL; /* optional address */
5172 msg.msg_namelen = 0; /* size of address */
5173 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5174 msg.msg_iovlen = count; /* # elements in msg_iov */
5175 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5176 msg.msg_control = NULL; /* ancillary data, see below */
5177 msg.msg_controllen = 0; /* ancillary data buffer len */
5178 msg.msg_flags = 0; /* flags on received message */
5181 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5183 if (rc == -ENOTSOCK) {
5184 return libc_readv(s, vector, count);
5189 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5191 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5196 ssize_t writev(int s, const struct iovec *vector, int count)
5198 return swrap_writev(s, vector, count);
5201 /****************************
5203 ***************************/
5205 static int swrap_close(int fd)
5207 struct socket_info_fd *fi = find_socket_info_fd(fd);
5208 struct socket_info *si = NULL;
5212 return libc_close(fd);
5215 si = &sockets[fi->si_index];
5217 SWRAP_DLIST_REMOVE(socket_fds, fi);
5222 if (si->refcount > 0) {
5223 /* there are still references left */
5224 return libc_close(fd);
5227 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5228 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5231 ret = libc_close(fd);
5233 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5234 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5235 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5238 if (si->un_addr.sun_path[0] != '\0') {
5239 unlink(si->un_addr.sun_path);
5247 return swrap_close(fd);
5250 /****************************
5252 ***************************/
5254 static int swrap_dup(int fd)
5256 struct socket_info *si;
5257 struct socket_info_fd *src_fi, *fi;
5259 src_fi = find_socket_info_fd(fd);
5260 if (src_fi == NULL) {
5261 return libc_dup(fd);
5264 si = &sockets[src_fi->si_index];
5266 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5272 fi->fd = libc_dup(fd);
5274 int saved_errno = errno;
5276 errno = saved_errno;
5281 fi->si_index = src_fi->si_index;
5283 /* Make sure we don't have an entry for the fd */
5284 swrap_remove_stale(fi->fd);
5286 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5292 return swrap_dup(fd);
5295 /****************************
5297 ***************************/
5299 static int swrap_dup2(int fd, int newfd)
5301 struct socket_info *si;
5302 struct socket_info_fd *src_fi, *fi;
5304 src_fi = find_socket_info_fd(fd);
5305 if (src_fi == NULL) {
5306 return libc_dup2(fd, newfd);
5309 si = &sockets[src_fi->si_index];
5313 * According to the manpage:
5315 * "If oldfd is a valid file descriptor, and newfd has the same
5316 * value as oldfd, then dup2() does nothing, and returns newfd."
5321 if (find_socket_info(newfd)) {
5322 /* dup2() does an implicit close of newfd, which we
5323 * need to emulate */
5327 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5333 fi->fd = libc_dup2(fd, newfd);
5335 int saved_errno = errno;
5337 errno = saved_errno;
5342 fi->si_index = src_fi->si_index;
5344 /* Make sure we don't have an entry for the fd */
5345 swrap_remove_stale(fi->fd);
5347 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5351 int dup2(int fd, int newfd)
5353 return swrap_dup2(fd, newfd);
5356 /****************************
5358 ***************************/
5360 static int swrap_vfcntl(int fd, int cmd, va_list va)
5362 struct socket_info_fd *src_fi, *fi;
5363 struct socket_info *si;
5366 src_fi = find_socket_info_fd(fd);
5367 if (src_fi == NULL) {
5368 return libc_vfcntl(fd, cmd, va);
5371 si = &sockets[src_fi->si_index];
5375 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5381 fi->fd = libc_vfcntl(fd, cmd, va);
5383 int saved_errno = errno;
5385 errno = saved_errno;
5390 fi->si_index = src_fi->si_index;
5392 /* Make sure we don't have an entry for the fd */
5393 swrap_remove_stale(fi->fd);
5395 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5400 rc = libc_vfcntl(fd, cmd, va);
5407 int fcntl(int fd, int cmd, ...)
5414 rc = swrap_vfcntl(fd, cmd, va);
5421 /****************************
5423 ***************************/
5426 static int swrap_eventfd(int count, int flags)
5430 fd = libc_eventfd(count, flags);
5432 swrap_remove_stale(fd);
5438 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5439 int eventfd(unsigned int count, int flags)
5441 int eventfd(int count, int flags)
5444 return swrap_eventfd(count, flags);
5449 int pledge(const char *promises, const char *paths[])
5451 (void)promises; /* unused */
5452 (void)paths; /* unused */
5456 #endif /* HAVE_PLEDGE */
5458 /****************************
5460 ***************************/
5463 * This function is called when the library is unloaded and makes sure that
5464 * sockets get closed and the unix file for the socket are unlinked.
5466 void swrap_destructor(void)
5468 struct socket_info_fd *s = socket_fds;
5477 if (swrap.libc_handle != NULL) {
5478 dlclose(swrap.libc_handle);
5480 if (swrap.libsocket_handle) {
5481 dlclose(swrap.libsocket_handle);