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
270 unsigned int refcount;
285 /* The unix path so we can unlink it on close() */
286 struct sockaddr_un un_addr;
288 struct swrap_address bindname;
289 struct swrap_address myname;
290 struct swrap_address peername;
293 unsigned long pck_snd;
294 unsigned long pck_rcv;
298 static struct socket_info *sockets;
299 static size_t max_sockets = 0;
302 * While socket file descriptors are passed among different processes, the
303 * numerical value gets changed. So its better to store it locally to each
304 * process rather than including it within socket_info which will be shared.
306 static struct socket_info_fd *socket_fds;
308 /* Function prototypes */
310 bool socket_wrapper_enabled(void);
311 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
314 # define SWRAP_LOG(...)
317 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
318 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
320 static void swrap_log(enum swrap_dbglvl_e dbglvl,
322 const char *format, ...)
327 unsigned int lvl = 0;
329 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
334 va_start(va, format);
335 vsnprintf(buffer, sizeof(buffer), format, va);
340 case SWRAP_LOG_ERROR:
342 "SWRAP_ERROR(%d) - %s: %s\n",
343 (int)getpid(), func, buffer);
347 "SWRAP_WARN(%d) - %s: %s\n",
348 (int)getpid(), func, buffer);
350 case SWRAP_LOG_DEBUG:
352 "SWRAP_DEBUG(%d) - %s: %s\n",
353 (int)getpid(), func, buffer);
355 case SWRAP_LOG_TRACE:
357 "SWRAP_TRACE(%d) - %s: %s\n",
358 (int)getpid(), func, buffer);
365 /*********************************************************
366 * SWRAP LOADING LIBC FUNCTIONS
367 *********************************************************/
371 struct swrap_libc_fns {
373 int (*libc_accept4)(int sockfd,
374 struct sockaddr *addr,
378 int (*libc_accept)(int sockfd,
379 struct sockaddr *addr,
382 int (*libc_bind)(int sockfd,
383 const struct sockaddr *addr,
385 int (*libc_close)(int fd);
386 int (*libc_connect)(int sockfd,
387 const struct sockaddr *addr,
389 int (*libc_dup)(int fd);
390 int (*libc_dup2)(int oldfd, int newfd);
391 int (*libc_fcntl)(int fd, int cmd, ...);
392 FILE *(*libc_fopen)(const char *name, const char *mode);
394 int (*libc_eventfd)(int count, int flags);
396 int (*libc_getpeername)(int sockfd,
397 struct sockaddr *addr,
399 int (*libc_getsockname)(int sockfd,
400 struct sockaddr *addr,
402 int (*libc_getsockopt)(int sockfd,
407 int (*libc_ioctl)(int d, unsigned long int request, ...);
408 int (*libc_listen)(int sockfd, int backlog);
409 int (*libc_open)(const char *pathname, int flags, mode_t mode);
410 int (*libc_pipe)(int pipefd[2]);
411 int (*libc_read)(int fd, void *buf, size_t count);
412 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
413 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
414 int (*libc_recvfrom)(int sockfd,
418 struct sockaddr *src_addr,
420 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
421 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
422 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
423 int (*libc_sendto)(int sockfd,
427 const struct sockaddr *dst_addr,
429 int (*libc_setsockopt)(int sockfd,
435 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
437 int (*libc_socket)(int domain, int type, int protocol);
438 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
439 #ifdef HAVE_TIMERFD_CREATE
440 int (*libc_timerfd_create)(int clockid, int flags);
442 ssize_t (*libc_write)(int fd, const void *buf, size_t count);
443 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
448 void *libsocket_handle;
450 struct swrap_libc_fns fns;
453 static struct swrap swrap;
456 static const char *socket_wrapper_dir(void);
458 #define LIBC_NAME "libc.so"
467 static const char *swrap_str_lib(enum swrap_lib lib)
474 case SWRAP_LIBSOCKET:
478 /* Compiler would warn us about unhandled enum value if we get here */
483 static void *swrap_load_lib_handle(enum swrap_lib lib)
485 int flags = RTLD_LAZY;
490 flags |= RTLD_DEEPBIND;
496 case SWRAP_LIBSOCKET:
497 #ifdef HAVE_LIBSOCKET
498 handle = swrap.libsocket_handle;
499 if (handle == NULL) {
500 for (i = 10; i >= 0; i--) {
501 char soname[256] = {0};
503 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
504 handle = dlopen(soname, flags);
505 if (handle != NULL) {
510 swrap.libsocket_handle = handle;
516 handle = swrap.libc_handle;
518 if (handle == NULL) {
519 handle = dlopen(LIBC_SO, flags);
521 swrap.libc_handle = handle;
524 if (handle == NULL) {
525 for (i = 10; i >= 0; i--) {
526 char soname[256] = {0};
528 snprintf(soname, sizeof(soname), "libc.so.%d", i);
529 handle = dlopen(soname, flags);
530 if (handle != NULL) {
535 swrap.libc_handle = handle;
540 if (handle == NULL) {
542 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
544 SWRAP_LOG(SWRAP_LOG_ERROR,
545 "Failed to dlopen library: %s\n",
554 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
559 handle = swrap_load_lib_handle(lib);
561 func = dlsym(handle, fn_name);
563 SWRAP_LOG(SWRAP_LOG_ERROR,
564 "Failed to find %s: %s\n",
569 SWRAP_LOG(SWRAP_LOG_TRACE,
571 fn_name, swrap_str_lib(lib));
575 #define swrap_load_lib_function(lib, fn_name) \
576 if (swrap.fns.libc_##fn_name == NULL) { \
577 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
578 *(void **) (&swrap.fns.libc_##fn_name) = \
586 * Functions especially from libc need to be loaded individually, you can't load
587 * all at once or gdb will segfault at startup. The same applies to valgrind and
588 * has probably something todo with with the linker.
589 * So we need load each function at the point it is called the first time.
592 static int libc_accept4(int sockfd,
593 struct sockaddr *addr,
597 swrap_load_lib_function(SWRAP_LIBSOCKET, accept4);
599 return swrap.fns.libc_accept4(sockfd, addr, addrlen, flags);
602 #else /* HAVE_ACCEPT4 */
604 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
606 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
608 return swrap.fns.libc_accept(sockfd, addr, addrlen);
610 #endif /* HAVE_ACCEPT4 */
612 static int libc_bind(int sockfd,
613 const struct sockaddr *addr,
616 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
618 return swrap.fns.libc_bind(sockfd, addr, addrlen);
621 static int libc_close(int fd)
623 swrap_load_lib_function(SWRAP_LIBC, close);
625 return swrap.fns.libc_close(fd);
628 static int libc_connect(int sockfd,
629 const struct sockaddr *addr,
632 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
634 return swrap.fns.libc_connect(sockfd, addr, addrlen);
637 static int libc_dup(int fd)
639 swrap_load_lib_function(SWRAP_LIBC, dup);
641 return swrap.fns.libc_dup(fd);
644 static int libc_dup2(int oldfd, int newfd)
646 swrap_load_lib_function(SWRAP_LIBC, dup2);
648 return swrap.fns.libc_dup2(oldfd, newfd);
652 static int libc_eventfd(int count, int flags)
654 swrap_load_lib_function(SWRAP_LIBC, eventfd);
656 return swrap.fns.libc_eventfd(count, flags);
660 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
661 static int libc_vfcntl(int fd, int cmd, va_list ap)
667 swrap_load_lib_function(SWRAP_LIBC, fcntl);
669 for (i = 0; i < 4; i++) {
670 args[i] = va_arg(ap, long int);
673 rc = swrap.fns.libc_fcntl(fd,
683 static int libc_getpeername(int sockfd,
684 struct sockaddr *addr,
687 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
689 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
692 static int libc_getsockname(int sockfd,
693 struct sockaddr *addr,
696 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
698 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
701 static int libc_getsockopt(int sockfd,
707 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
709 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
712 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
713 static int libc_vioctl(int d, unsigned long int request, va_list ap)
719 swrap_load_lib_function(SWRAP_LIBC, ioctl);
721 for (i = 0; i < 4; i++) {
722 args[i] = va_arg(ap, long int);
725 rc = swrap.fns.libc_ioctl(d,
735 static int libc_listen(int sockfd, int backlog)
737 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
739 return swrap.fns.libc_listen(sockfd, backlog);
742 static FILE *libc_fopen(const char *name, const char *mode)
744 swrap_load_lib_function(SWRAP_LIBC, fopen);
746 return swrap.fns.libc_fopen(name, mode);
749 static int libc_vopen(const char *pathname, int flags, va_list ap)
754 swrap_load_lib_function(SWRAP_LIBC, open);
756 mode = va_arg(ap, long int);
758 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
763 static int libc_open(const char *pathname, int flags, ...)
769 fd = libc_vopen(pathname, flags, ap);
775 static int libc_pipe(int pipefd[2])
777 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
779 return swrap.fns.libc_pipe(pipefd);
782 static int libc_read(int fd, void *buf, size_t count)
784 swrap_load_lib_function(SWRAP_LIBC, read);
786 return swrap.fns.libc_read(fd, buf, count);
789 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
791 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
793 return swrap.fns.libc_readv(fd, iov, iovcnt);
796 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
798 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
800 return swrap.fns.libc_recv(sockfd, buf, len, flags);
803 static int libc_recvfrom(int sockfd,
807 struct sockaddr *src_addr,
810 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
812 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
815 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
817 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
819 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
822 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
824 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
826 return swrap.fns.libc_send(sockfd, buf, len, flags);
829 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
831 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
833 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
836 static int libc_sendto(int sockfd,
840 const struct sockaddr *dst_addr,
843 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
845 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
848 static int libc_setsockopt(int sockfd,
854 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
856 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
860 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
862 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
864 return swrap.fns.libc_signalfd(fd, mask, flags);
868 static int libc_socket(int domain, int type, int protocol)
870 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
872 return swrap.fns.libc_socket(domain, type, protocol);
875 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
877 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
879 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
882 #ifdef HAVE_TIMERFD_CREATE
883 static int libc_timerfd_create(int clockid, int flags)
885 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
887 return swrap.fns.libc_timerfd_create(clockid, flags);
891 static ssize_t libc_write(int fd, const void *buf, size_t count)
893 swrap_load_lib_function(SWRAP_LIBC, write);
895 return swrap.fns.libc_write(fd, buf, count);
898 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
900 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
902 return swrap.fns.libc_writev(fd, iov, iovcnt);
905 /*********************************************************
906 * SWRAP HELPER FUNCTIONS
907 *********************************************************/
913 static const struct in6_addr *swrap_ipv6(void)
915 static struct in6_addr v;
916 static int initialized;
924 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
933 static void set_port(int family, int prt, struct swrap_address *addr)
937 addr->sa.in.sin_port = htons(prt);
941 addr->sa.in6.sin6_port = htons(prt);
947 static size_t socket_length(int family)
951 return sizeof(struct sockaddr_in);
954 return sizeof(struct sockaddr_in6);
960 static const char *socket_wrapper_dir(void)
962 const char *s = getenv("SOCKET_WRAPPER_DIR");
966 /* TODO use realpath(3) here, when we add support for threads */
967 if (strncmp(s, "./", 2) == 0) {
971 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
975 static unsigned int socket_wrapper_mtu(void)
977 static unsigned int max_mtu = 0;
986 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
988 s = getenv("SOCKET_WRAPPER_MTU");
993 tmp = strtol(s, &endp, 10);
998 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1007 static size_t socket_wrapper_max_sockets(void)
1013 if (max_sockets != 0) {
1017 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1019 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1020 if (s == NULL || s[0] == '\0') {
1024 tmp = strtoul(s, &endp, 10);
1035 static void socket_wrapper_init_sockets(void)
1039 if (sockets != NULL) {
1043 max_sockets = socket_wrapper_max_sockets();
1045 sockets = (struct socket_info *)calloc(max_sockets,
1046 sizeof(struct socket_info));
1048 if (sockets == NULL) {
1049 SWRAP_LOG(SWRAP_LOG_ERROR,
1050 "Failed to allocate sockets array.\n");
1056 for (i = 0; i < max_sockets; i++) {
1057 sockets[i].next_free = i+1;
1060 sockets[max_sockets-1].next_free = -1;
1063 bool socket_wrapper_enabled(void)
1065 const char *s = socket_wrapper_dir();
1071 socket_wrapper_init_sockets();
1076 static unsigned int socket_wrapper_default_iface(void)
1078 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1081 if (sscanf(s, "%u", &iface) == 1) {
1082 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1088 return 1;/* 127.0.0.1 */
1092 * Return the first free entry (if any) and make
1093 * it re-usable again (by nulling it out)
1095 static int socket_wrapper_first_free_index(void)
1099 if (first_free == -1) {
1103 next_free = sockets[first_free].next_free;
1104 ZERO_STRUCT(sockets[first_free]);
1105 sockets[first_free].next_free = next_free;
1110 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1117 p = strrchr(un->sun_path, '/');
1118 if (p) p++; else p = un->sun_path;
1120 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1125 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1128 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1139 case SOCKET_TYPE_CHAR_TCP:
1140 case SOCKET_TYPE_CHAR_UDP: {
1141 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1143 if ((*len) < sizeof(*in2)) {
1148 memset(in2, 0, sizeof(*in2));
1149 in2->sin_family = AF_INET;
1150 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1151 in2->sin_port = htons(prt);
1153 *len = sizeof(*in2);
1157 case SOCKET_TYPE_CHAR_TCP_V6:
1158 case SOCKET_TYPE_CHAR_UDP_V6: {
1159 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1161 if ((*len) < sizeof(*in2)) {
1166 memset(in2, 0, sizeof(*in2));
1167 in2->sin6_family = AF_INET6;
1168 in2->sin6_addr = *swrap_ipv6();
1169 in2->sin6_addr.s6_addr[15] = iface;
1170 in2->sin6_port = htons(prt);
1172 *len = sizeof(*in2);
1184 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1192 if (bcast) *bcast = 0;
1194 switch (inaddr->sa_family) {
1196 const struct sockaddr_in *in =
1197 (const struct sockaddr_in *)(const void *)inaddr;
1198 unsigned int addr = ntohl(in->sin_addr.s_addr);
1205 u_type = SOCKET_TYPE_CHAR_TCP;
1208 u_type = SOCKET_TYPE_CHAR_UDP;
1209 a_type = SOCKET_TYPE_CHAR_UDP;
1210 b_type = SOCKET_TYPE_CHAR_UDP;
1213 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1214 errno = ESOCKTNOSUPPORT;
1218 prt = ntohs(in->sin_port);
1219 if (a_type && addr == 0xFFFFFFFF) {
1220 /* 255.255.255.255 only udp */
1223 iface = socket_wrapper_default_iface();
1224 } else if (b_type && addr == 0x7FFFFFFF) {
1225 /* 127.255.255.255 only udp */
1228 iface = socket_wrapper_default_iface();
1229 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1233 iface = (addr & 0x000000FF);
1235 errno = ENETUNREACH;
1238 if (bcast) *bcast = is_bcast;
1243 const struct sockaddr_in6 *in =
1244 (const struct sockaddr_in6 *)(const void *)inaddr;
1245 struct in6_addr cmp1, cmp2;
1249 type = SOCKET_TYPE_CHAR_TCP_V6;
1252 type = SOCKET_TYPE_CHAR_UDP_V6;
1255 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1256 errno = ESOCKTNOSUPPORT;
1260 /* XXX no multicast/broadcast */
1262 prt = ntohs(in->sin6_port);
1264 cmp1 = *swrap_ipv6();
1265 cmp2 = in->sin6_addr;
1266 cmp2.s6_addr[15] = 0;
1267 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1268 iface = in->sin6_addr.s6_addr[15];
1270 errno = ENETUNREACH;
1278 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1279 errno = ENETUNREACH;
1284 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1290 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1291 socket_wrapper_dir());
1292 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1293 /* the caller need to do more processing */
1297 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1298 socket_wrapper_dir(), type, iface, prt);
1299 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1304 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1313 if (bcast) *bcast = 0;
1315 switch (si->family) {
1317 const struct sockaddr_in *in =
1318 (const struct sockaddr_in *)(const void *)inaddr;
1319 unsigned int addr = ntohl(in->sin_addr.s_addr);
1325 prt = ntohs(in->sin_port);
1329 u_type = SOCKET_TYPE_CHAR_TCP;
1330 d_type = SOCKET_TYPE_CHAR_TCP;
1333 u_type = SOCKET_TYPE_CHAR_UDP;
1334 d_type = SOCKET_TYPE_CHAR_UDP;
1335 a_type = SOCKET_TYPE_CHAR_UDP;
1336 b_type = SOCKET_TYPE_CHAR_UDP;
1339 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1340 errno = ESOCKTNOSUPPORT;
1348 iface = socket_wrapper_default_iface();
1349 } else if (a_type && addr == 0xFFFFFFFF) {
1350 /* 255.255.255.255 only udp */
1353 iface = socket_wrapper_default_iface();
1354 } else if (b_type && addr == 0x7FFFFFFF) {
1355 /* 127.255.255.255 only udp */
1358 iface = socket_wrapper_default_iface();
1359 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1363 iface = (addr & 0x000000FF);
1365 errno = EADDRNOTAVAIL;
1369 /* Store the bind address for connect() */
1370 if (si->bindname.sa_socklen == 0) {
1371 struct sockaddr_in bind_in;
1372 socklen_t blen = sizeof(struct sockaddr_in);
1374 ZERO_STRUCT(bind_in);
1375 bind_in.sin_family = in->sin_family;
1376 bind_in.sin_port = in->sin_port;
1377 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1379 si->bindname.sa_socklen = blen;
1380 memcpy(&si->bindname.sa.in, &bind_in, blen);
1387 const struct sockaddr_in6 *in =
1388 (const struct sockaddr_in6 *)(const void *)inaddr;
1389 struct in6_addr cmp1, cmp2;
1393 type = SOCKET_TYPE_CHAR_TCP_V6;
1396 type = SOCKET_TYPE_CHAR_UDP_V6;
1399 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1400 errno = ESOCKTNOSUPPORT;
1404 /* XXX no multicast/broadcast */
1406 prt = ntohs(in->sin6_port);
1408 cmp1 = *swrap_ipv6();
1409 cmp2 = in->sin6_addr;
1410 cmp2.s6_addr[15] = 0;
1411 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1412 iface = socket_wrapper_default_iface();
1413 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1414 iface = in->sin6_addr.s6_addr[15];
1416 errno = EADDRNOTAVAIL;
1420 /* Store the bind address for connect() */
1421 if (si->bindname.sa_socklen == 0) {
1422 struct sockaddr_in6 bind_in;
1423 socklen_t blen = sizeof(struct sockaddr_in6);
1425 ZERO_STRUCT(bind_in);
1426 bind_in.sin6_family = in->sin6_family;
1427 bind_in.sin6_port = in->sin6_port;
1429 bind_in.sin6_addr = *swrap_ipv6();
1430 bind_in.sin6_addr.s6_addr[15] = iface;
1432 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1433 si->bindname.sa_socklen = blen;
1440 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1441 errno = EADDRNOTAVAIL;
1446 if (bcast) *bcast = is_bcast;
1448 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1454 /* handle auto-allocation of ephemeral ports */
1455 for (prt = 5001; prt < 10000; prt++) {
1456 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1457 socket_wrapper_dir(), type, iface, prt);
1458 if (stat(un->sun_path, &st) == 0) continue;
1460 set_port(si->family, prt, &si->myname);
1461 set_port(si->family, prt, &si->bindname);
1471 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1472 socket_wrapper_dir(), type, iface, prt);
1473 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1477 static struct socket_info_fd *find_socket_info_fd(int fd)
1479 struct socket_info_fd *f;
1481 for (f = socket_fds; f; f = f->next) {
1490 static int find_socket_info_index(int fd)
1492 struct socket_info_fd *fi = find_socket_info_fd(fd);
1498 return fi->si_index;
1501 static struct socket_info *find_socket_info(int fd)
1503 int idx = find_socket_info_index(fd);
1509 return &sockets[idx];
1513 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1515 struct socket_info_fd *f;
1516 const struct socket_info *last_s = NULL;
1518 /* first catch invalid input */
1519 switch (sa->sa_family) {
1521 if (len < sizeof(struct sockaddr_in)) {
1527 if (len < sizeof(struct sockaddr_in6)) {
1537 for (f = socket_fds; f; f = f->next) {
1538 struct socket_info *s = &sockets[f->si_index];
1545 if (s->myname == NULL) {
1548 if (s->myname->sa_family != sa->sa_family) {
1551 switch (s->myname->sa_family) {
1553 struct sockaddr_in *sin1, *sin2;
1555 sin1 = (struct sockaddr_in *)s->myname;
1556 sin2 = (struct sockaddr_in *)sa;
1558 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1561 if (sin1->sin_port != sin2->sin_port) {
1564 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1574 struct sockaddr_in6 *sin1, *sin2;
1576 sin1 = (struct sockaddr_in6 *)s->myname;
1577 sin2 = (struct sockaddr_in6 *)sa;
1579 if (sin1->sin6_port != sin2->sin6_port) {
1582 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1604 static void swrap_remove_stale(int fd)
1606 struct socket_info_fd *fi = find_socket_info_fd(fd);
1607 struct socket_info *si;
1613 si = &sockets[fi->si_index];
1615 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1616 SWRAP_DLIST_REMOVE(socket_fds, fi);
1621 if (si->refcount > 0) {
1625 if (si->un_addr.sun_path[0] != '\0') {
1626 unlink(si->un_addr.sun_path);
1629 si->next_free = first_free;
1630 first_free = fi->si_index;
1633 static int sockaddr_convert_to_un(struct socket_info *si,
1634 const struct sockaddr *in_addr,
1636 struct sockaddr_un *out_addr,
1640 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1642 (void) in_len; /* unused */
1644 if (out_addr == NULL) {
1648 out->sa_family = AF_UNIX;
1649 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1650 out->sa_len = sizeof(*out_addr);
1653 switch (in_addr->sa_family) {
1655 const struct sockaddr_in *sin;
1656 if (si->family != AF_INET) {
1659 if (in_len < sizeof(struct sockaddr_in)) {
1662 sin = (const struct sockaddr_in *)(const void *)in_addr;
1663 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1668 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1669 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1683 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1684 errno = ESOCKTNOSUPPORT;
1688 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1690 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1696 errno = EAFNOSUPPORT;
1697 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1701 static int sockaddr_convert_from_un(const struct socket_info *si,
1702 const struct sockaddr_un *in_addr,
1703 socklen_t un_addrlen,
1705 struct sockaddr *out_addr,
1706 socklen_t *out_addrlen)
1710 if (out_addr == NULL || out_addrlen == NULL)
1713 if (un_addrlen == 0) {
1728 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1729 errno = ESOCKTNOSUPPORT;
1732 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1733 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1734 out_addr->sa_len = *out_addrlen;
1741 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1742 errno = EAFNOSUPPORT;
1746 enum swrap_packet_type {
1748 SWRAP_CONNECT_UNREACH,
1756 SWRAP_SENDTO_UNREACH,
1767 struct swrap_file_hdr {
1769 uint16_t version_major;
1770 uint16_t version_minor;
1773 uint32_t frame_max_len;
1774 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1777 #define SWRAP_FILE_HDR_SIZE 24
1779 struct swrap_packet_frame {
1781 uint32_t micro_seconds;
1782 uint32_t recorded_length;
1783 uint32_t full_length;
1785 #define SWRAP_PACKET_FRAME_SIZE 16
1787 union swrap_packet_ip {
1791 uint16_t packet_length;
1792 uint16_t identification;
1797 uint16_t hdr_checksum;
1801 #define SWRAP_PACKET_IP_V4_SIZE 20
1804 uint8_t flow_label_high;
1805 uint16_t flow_label_low;
1806 uint16_t payload_length;
1807 uint8_t next_header;
1809 uint8_t src_addr[16];
1810 uint8_t dest_addr[16];
1812 #define SWRAP_PACKET_IP_V6_SIZE 40
1814 #define SWRAP_PACKET_IP_SIZE 40
1816 union swrap_packet_payload {
1818 uint16_t source_port;
1828 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1830 uint16_t source_port;
1835 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1842 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1849 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1851 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1853 #define SWRAP_PACKET_MIN_ALLOC \
1854 (SWRAP_PACKET_FRAME_SIZE + \
1855 SWRAP_PACKET_IP_SIZE + \
1856 SWRAP_PACKET_PAYLOAD_SIZE)
1858 static const char *swrap_pcap_init_file(void)
1860 static int initialized = 0;
1861 static const char *s = NULL;
1862 static const struct swrap_file_hdr h;
1863 static const struct swrap_packet_frame f;
1864 static const union swrap_packet_ip i;
1865 static const union swrap_packet_payload p;
1867 if (initialized == 1) {
1873 * TODO: don't use the structs use plain buffer offsets
1874 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1876 * for now make sure we disable PCAP support
1877 * if the struct has alignment!
1879 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1882 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1885 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1888 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1891 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1894 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1897 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1900 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1903 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1906 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1910 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1914 if (strncmp(s, "./", 2) == 0) {
1920 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1921 const struct sockaddr *src,
1922 const struct sockaddr *dest,
1924 const uint8_t *payload,
1926 unsigned long tcp_seqno,
1927 unsigned long tcp_ack,
1928 unsigned char tcp_ctl,
1930 size_t *_packet_len)
1934 struct swrap_packet_frame *frame;
1935 union swrap_packet_ip *ip;
1936 union swrap_packet_payload *pay;
1939 size_t nonwire_len = sizeof(*frame);
1940 size_t wire_hdr_len = 0;
1941 size_t wire_len = 0;
1942 size_t ip_hdr_len = 0;
1943 size_t icmp_hdr_len = 0;
1944 size_t icmp_truncate_len = 0;
1945 uint8_t protocol = 0, icmp_protocol = 0;
1946 const struct sockaddr_in *src_in = NULL;
1947 const struct sockaddr_in *dest_in = NULL;
1949 const struct sockaddr_in6 *src_in6 = NULL;
1950 const struct sockaddr_in6 *dest_in6 = NULL;
1955 switch (src->sa_family) {
1957 src_in = (const struct sockaddr_in *)(const void *)src;
1958 dest_in = (const struct sockaddr_in *)(const void *)dest;
1959 src_port = src_in->sin_port;
1960 dest_port = dest_in->sin_port;
1961 ip_hdr_len = sizeof(ip->v4);
1965 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1966 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1967 src_port = src_in6->sin6_port;
1968 dest_port = dest_in6->sin6_port;
1969 ip_hdr_len = sizeof(ip->v6);
1976 switch (socket_type) {
1978 protocol = 0x06; /* TCP */
1979 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1980 wire_len = wire_hdr_len + payload_len;
1984 protocol = 0x11; /* UDP */
1985 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1986 wire_len = wire_hdr_len + payload_len;
1994 icmp_protocol = protocol;
1995 switch (src->sa_family) {
1997 protocol = 0x01; /* ICMPv4 */
1998 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2002 protocol = 0x3A; /* ICMPv6 */
2003 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2007 if (wire_len > 64 ) {
2008 icmp_truncate_len = wire_len - 64;
2010 wire_hdr_len += icmp_hdr_len;
2011 wire_len += icmp_hdr_len;
2014 packet_len = nonwire_len + wire_len;
2015 alloc_len = packet_len;
2016 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2017 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2020 base = (uint8_t *)calloc(1, alloc_len);
2027 frame = (struct swrap_packet_frame *)(void *)buf;
2028 frame->seconds = tval->tv_sec;
2029 frame->micro_seconds = tval->tv_usec;
2030 frame->recorded_length = wire_len - icmp_truncate_len;
2031 frame->full_length = wire_len - icmp_truncate_len;
2032 buf += SWRAP_PACKET_FRAME_SIZE;
2034 ip = (union swrap_packet_ip *)(void *)buf;
2035 switch (src->sa_family) {
2037 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2039 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2040 ip->v4.identification = htons(0xFFFF);
2041 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2042 ip->v4.fragment = htons(0x0000);
2044 ip->v4.protocol = protocol;
2045 ip->v4.hdr_checksum = htons(0x0000);
2046 ip->v4.src_addr = src_in->sin_addr.s_addr;
2047 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2048 buf += SWRAP_PACKET_IP_V4_SIZE;
2052 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2053 ip->v6.flow_label_high = 0x00;
2054 ip->v6.flow_label_low = 0x0000;
2055 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2056 ip->v6.next_header = protocol;
2057 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2058 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2059 buf += SWRAP_PACKET_IP_V6_SIZE;
2065 pay = (union swrap_packet_payload *)(void *)buf;
2066 switch (src->sa_family) {
2068 pay->icmp4.type = 0x03; /* destination unreachable */
2069 pay->icmp4.code = 0x01; /* host unreachable */
2070 pay->icmp4.checksum = htons(0x0000);
2071 pay->icmp4.unused = htonl(0x00000000);
2072 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2074 /* set the ip header in the ICMP payload */
2075 ip = (union swrap_packet_ip *)(void *)buf;
2076 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2078 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2079 ip->v4.identification = htons(0xFFFF);
2080 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2081 ip->v4.fragment = htons(0x0000);
2083 ip->v4.protocol = icmp_protocol;
2084 ip->v4.hdr_checksum = htons(0x0000);
2085 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2086 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2087 buf += SWRAP_PACKET_IP_V4_SIZE;
2089 src_port = dest_in->sin_port;
2090 dest_port = src_in->sin_port;
2094 pay->icmp6.type = 0x01; /* destination unreachable */
2095 pay->icmp6.code = 0x03; /* address unreachable */
2096 pay->icmp6.checksum = htons(0x0000);
2097 pay->icmp6.unused = htonl(0x00000000);
2098 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2100 /* set the ip header in the ICMP payload */
2101 ip = (union swrap_packet_ip *)(void *)buf;
2102 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2103 ip->v6.flow_label_high = 0x00;
2104 ip->v6.flow_label_low = 0x0000;
2105 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2106 ip->v6.next_header = protocol;
2107 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2108 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2109 buf += SWRAP_PACKET_IP_V6_SIZE;
2111 src_port = dest_in6->sin6_port;
2112 dest_port = src_in6->sin6_port;
2118 pay = (union swrap_packet_payload *)(void *)buf;
2120 switch (socket_type) {
2122 pay->tcp.source_port = src_port;
2123 pay->tcp.dest_port = dest_port;
2124 pay->tcp.seq_num = htonl(tcp_seqno);
2125 pay->tcp.ack_num = htonl(tcp_ack);
2126 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2127 pay->tcp.control = tcp_ctl;
2128 pay->tcp.window = htons(0x7FFF);
2129 pay->tcp.checksum = htons(0x0000);
2130 pay->tcp.urg = htons(0x0000);
2131 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2136 pay->udp.source_port = src_port;
2137 pay->udp.dest_port = dest_port;
2138 pay->udp.length = htons(8 + payload_len);
2139 pay->udp.checksum = htons(0x0000);
2140 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2145 if (payload && payload_len > 0) {
2146 memcpy(buf, payload, payload_len);
2149 *_packet_len = packet_len - icmp_truncate_len;
2153 static int swrap_pcap_get_fd(const char *fname)
2157 if (fd != -1) return fd;
2159 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2161 struct swrap_file_hdr file_hdr;
2162 file_hdr.magic = 0xA1B2C3D4;
2163 file_hdr.version_major = 0x0002;
2164 file_hdr.version_minor = 0x0004;
2165 file_hdr.timezone = 0x00000000;
2166 file_hdr.sigfigs = 0x00000000;
2167 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2168 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2170 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2177 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2182 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2183 const struct sockaddr *addr,
2184 enum swrap_packet_type type,
2185 const void *buf, size_t len,
2188 const struct sockaddr *src_addr;
2189 const struct sockaddr *dest_addr;
2190 unsigned long tcp_seqno = 0;
2191 unsigned long tcp_ack = 0;
2192 unsigned char tcp_ctl = 0;
2193 int unreachable = 0;
2197 switch (si->family) {
2209 case SWRAP_CONNECT_SEND:
2210 if (si->type != SOCK_STREAM) return NULL;
2212 src_addr = &si->myname.sa.s;
2215 tcp_seqno = si->io.pck_snd;
2216 tcp_ack = si->io.pck_rcv;
2217 tcp_ctl = 0x02; /* SYN */
2219 si->io.pck_snd += 1;
2223 case SWRAP_CONNECT_RECV:
2224 if (si->type != SOCK_STREAM) return NULL;
2226 dest_addr = &si->myname.sa.s;
2229 tcp_seqno = si->io.pck_rcv;
2230 tcp_ack = si->io.pck_snd;
2231 tcp_ctl = 0x12; /** SYN,ACK */
2233 si->io.pck_rcv += 1;
2237 case SWRAP_CONNECT_UNREACH:
2238 if (si->type != SOCK_STREAM) return NULL;
2240 dest_addr = &si->myname.sa.s;
2243 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2244 tcp_seqno = si->io.pck_snd - 1;
2245 tcp_ack = si->io.pck_rcv;
2246 tcp_ctl = 0x02; /* SYN */
2251 case SWRAP_CONNECT_ACK:
2252 if (si->type != SOCK_STREAM) return NULL;
2254 src_addr = &si->myname.sa.s;
2257 tcp_seqno = si->io.pck_snd;
2258 tcp_ack = si->io.pck_rcv;
2259 tcp_ctl = 0x10; /* ACK */
2263 case SWRAP_ACCEPT_SEND:
2264 if (si->type != SOCK_STREAM) return NULL;
2266 dest_addr = &si->myname.sa.s;
2269 tcp_seqno = si->io.pck_rcv;
2270 tcp_ack = si->io.pck_snd;
2271 tcp_ctl = 0x02; /* SYN */
2273 si->io.pck_rcv += 1;
2277 case SWRAP_ACCEPT_RECV:
2278 if (si->type != SOCK_STREAM) return NULL;
2280 src_addr = &si->myname.sa.s;
2283 tcp_seqno = si->io.pck_snd;
2284 tcp_ack = si->io.pck_rcv;
2285 tcp_ctl = 0x12; /* SYN,ACK */
2287 si->io.pck_snd += 1;
2291 case SWRAP_ACCEPT_ACK:
2292 if (si->type != SOCK_STREAM) return NULL;
2294 dest_addr = &si->myname.sa.s;
2297 tcp_seqno = si->io.pck_rcv;
2298 tcp_ack = si->io.pck_snd;
2299 tcp_ctl = 0x10; /* ACK */
2304 src_addr = &si->myname.sa.s;
2305 dest_addr = &si->peername.sa.s;
2307 tcp_seqno = si->io.pck_snd;
2308 tcp_ack = si->io.pck_rcv;
2309 tcp_ctl = 0x18; /* PSH,ACK */
2311 si->io.pck_snd += len;
2315 case SWRAP_SEND_RST:
2316 dest_addr = &si->myname.sa.s;
2317 src_addr = &si->peername.sa.s;
2319 if (si->type == SOCK_DGRAM) {
2320 return swrap_pcap_marshall_packet(si,
2322 SWRAP_SENDTO_UNREACH,
2328 tcp_seqno = si->io.pck_rcv;
2329 tcp_ack = si->io.pck_snd;
2330 tcp_ctl = 0x14; /** RST,ACK */
2334 case SWRAP_PENDING_RST:
2335 dest_addr = &si->myname.sa.s;
2336 src_addr = &si->peername.sa.s;
2338 if (si->type == SOCK_DGRAM) {
2342 tcp_seqno = si->io.pck_rcv;
2343 tcp_ack = si->io.pck_snd;
2344 tcp_ctl = 0x14; /* RST,ACK */
2349 dest_addr = &si->myname.sa.s;
2350 src_addr = &si->peername.sa.s;
2352 tcp_seqno = si->io.pck_rcv;
2353 tcp_ack = si->io.pck_snd;
2354 tcp_ctl = 0x18; /* PSH,ACK */
2356 si->io.pck_rcv += len;
2360 case SWRAP_RECV_RST:
2361 dest_addr = &si->myname.sa.s;
2362 src_addr = &si->peername.sa.s;
2364 if (si->type == SOCK_DGRAM) {
2368 tcp_seqno = si->io.pck_rcv;
2369 tcp_ack = si->io.pck_snd;
2370 tcp_ctl = 0x14; /* RST,ACK */
2375 src_addr = &si->myname.sa.s;
2378 si->io.pck_snd += len;
2382 case SWRAP_SENDTO_UNREACH:
2383 dest_addr = &si->myname.sa.s;
2390 case SWRAP_RECVFROM:
2391 dest_addr = &si->myname.sa.s;
2394 si->io.pck_rcv += len;
2398 case SWRAP_CLOSE_SEND:
2399 if (si->type != SOCK_STREAM) return NULL;
2401 src_addr = &si->myname.sa.s;
2402 dest_addr = &si->peername.sa.s;
2404 tcp_seqno = si->io.pck_snd;
2405 tcp_ack = si->io.pck_rcv;
2406 tcp_ctl = 0x11; /* FIN, ACK */
2408 si->io.pck_snd += 1;
2412 case SWRAP_CLOSE_RECV:
2413 if (si->type != SOCK_STREAM) return NULL;
2415 dest_addr = &si->myname.sa.s;
2416 src_addr = &si->peername.sa.s;
2418 tcp_seqno = si->io.pck_rcv;
2419 tcp_ack = si->io.pck_snd;
2420 tcp_ctl = 0x11; /* FIN,ACK */
2422 si->io.pck_rcv += 1;
2426 case SWRAP_CLOSE_ACK:
2427 if (si->type != SOCK_STREAM) return NULL;
2429 src_addr = &si->myname.sa.s;
2430 dest_addr = &si->peername.sa.s;
2432 tcp_seqno = si->io.pck_snd;
2433 tcp_ack = si->io.pck_rcv;
2434 tcp_ctl = 0x10; /* ACK */
2441 swrapGetTimeOfDay(&tv);
2443 return swrap_pcap_packet_init(&tv,
2447 (const uint8_t *)buf,
2456 static void swrap_pcap_dump_packet(struct socket_info *si,
2457 const struct sockaddr *addr,
2458 enum swrap_packet_type type,
2459 const void *buf, size_t len)
2461 const char *file_name;
2463 size_t packet_len = 0;
2466 file_name = swrap_pcap_init_file();
2471 packet = swrap_pcap_marshall_packet(si,
2477 if (packet == NULL) {
2481 fd = swrap_pcap_get_fd(file_name);
2483 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2492 /****************************************************************************
2494 ***************************************************************************/
2496 #ifdef HAVE_SIGNALFD
2497 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2501 rc = libc_signalfd(fd, mask, flags);
2503 swrap_remove_stale(fd);
2509 int signalfd(int fd, const sigset_t *mask, int flags)
2511 return swrap_signalfd(fd, mask, flags);
2515 /****************************************************************************
2517 ***************************************************************************/
2519 static int swrap_socket(int family, int type, int protocol)
2521 struct socket_info *si;
2522 struct socket_info_fd *fi;
2525 int real_type = type;
2528 * Remove possible addition flags passed to socket() so
2529 * do not fail checking the type.
2530 * See https://lwn.net/Articles/281965/
2533 real_type &= ~SOCK_CLOEXEC;
2535 #ifdef SOCK_NONBLOCK
2536 real_type &= ~SOCK_NONBLOCK;
2539 if (!socket_wrapper_enabled()) {
2540 return libc_socket(family, type, protocol);
2551 #endif /* AF_NETLINK */
2554 #endif /* AF_PACKET */
2556 return libc_socket(family, type, protocol);
2558 errno = EAFNOSUPPORT;
2562 switch (real_type) {
2568 errno = EPROTONOSUPPORT;
2576 if (real_type == SOCK_STREAM) {
2581 if (real_type == SOCK_DGRAM) {
2586 errno = EPROTONOSUPPORT;
2591 * We must call libc_socket with type, from the caller, not the version
2592 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2594 fd = libc_socket(AF_UNIX, type, 0);
2600 /* Check if we have a stale fd and remove it */
2601 swrap_remove_stale(fd);
2603 idx = socket_wrapper_first_free_index();
2611 si->family = family;
2613 /* however, the rest of the socket_wrapper code expects just
2614 * the type, not the flags */
2615 si->type = real_type;
2616 si->protocol = protocol;
2619 * Setup myname so getsockname() can succeed to find out the socket
2622 switch(si->family) {
2624 struct sockaddr_in sin = {
2625 .sin_family = AF_INET,
2628 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2629 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2633 struct sockaddr_in6 sin6 = {
2634 .sin6_family = AF_INET6,
2637 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2638 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2646 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2653 first_free = si->next_free;
2659 SWRAP_DLIST_ADD(socket_fds, fi);
2661 SWRAP_LOG(SWRAP_LOG_TRACE,
2662 "Created %s socket for protocol %s",
2663 si->family == AF_INET ? "IPv4" : "IPv6",
2664 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2669 int socket(int family, int type, int protocol)
2671 return swrap_socket(family, type, protocol);
2674 /****************************************************************************
2676 ***************************************************************************/
2678 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2682 rc = libc_socketpair(family, type, protocol, sv);
2684 swrap_remove_stale(sv[0]);
2685 swrap_remove_stale(sv[1]);
2691 int socketpair(int family, int type, int protocol, int sv[2])
2693 return swrap_socketpair(family, type, protocol, sv);
2696 /****************************************************************************
2698 ***************************************************************************/
2700 #ifdef HAVE_TIMERFD_CREATE
2701 static int swrap_timerfd_create(int clockid, int flags)
2705 fd = libc_timerfd_create(clockid, flags);
2707 swrap_remove_stale(fd);
2713 int timerfd_create(int clockid, int flags)
2715 return swrap_timerfd_create(clockid, flags);
2719 /****************************************************************************
2721 ***************************************************************************/
2723 static int swrap_pipe(int pipefd[2])
2727 rc = libc_pipe(pipefd);
2729 swrap_remove_stale(pipefd[0]);
2730 swrap_remove_stale(pipefd[1]);
2736 int pipe(int pipefd[2])
2738 return swrap_pipe(pipefd);
2741 /****************************************************************************
2743 ***************************************************************************/
2745 static int swrap_accept(int s,
2746 struct sockaddr *addr,
2750 struct socket_info *parent_si, *child_si;
2751 struct socket_info_fd *child_fi;
2754 struct swrap_address un_addr = {
2755 .sa_socklen = sizeof(struct sockaddr_un),
2757 struct swrap_address un_my_addr = {
2758 .sa_socklen = sizeof(struct sockaddr_un),
2760 struct swrap_address in_addr = {
2761 .sa_socklen = sizeof(struct sockaddr_storage),
2763 struct swrap_address in_my_addr = {
2764 .sa_socklen = sizeof(struct sockaddr_storage),
2768 parent_si = find_socket_info(s);
2771 return libc_accept4(s, addr, addrlen, flags);
2773 return libc_accept(s, addr, addrlen);
2778 * assume out sockaddr have the same size as the in parent
2781 in_addr.sa_socklen = socket_length(parent_si->family);
2782 if (in_addr.sa_socklen <= 0) {
2788 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2790 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2793 if (errno == ENOTSOCK) {
2794 /* Remove stale fds */
2795 swrap_remove_stale(s);
2802 ret = sockaddr_convert_from_un(parent_si,
2807 &in_addr.sa_socklen);
2813 idx = socket_wrapper_first_free_index();
2819 child_si = &sockets[idx];
2821 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2822 if (child_fi == NULL) {
2830 child_si->family = parent_si->family;
2831 child_si->type = parent_si->type;
2832 child_si->protocol = parent_si->protocol;
2833 child_si->bound = 1;
2834 child_si->is_server = 1;
2835 child_si->connected = 1;
2837 child_si->peername = (struct swrap_address) {
2838 .sa_socklen = in_addr.sa_socklen,
2840 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2842 if (addr != NULL && addrlen != NULL) {
2843 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2845 memcpy(addr, &in_addr.sa.ss, copy_len);
2847 *addrlen = in_addr.sa_socklen;
2850 ret = libc_getsockname(fd,
2852 &un_my_addr.sa_socklen);
2859 ret = sockaddr_convert_from_un(child_si,
2861 un_my_addr.sa_socklen,
2864 &in_my_addr.sa_socklen);
2871 SWRAP_LOG(SWRAP_LOG_TRACE,
2872 "accept() path=%s, fd=%d",
2873 un_my_addr.sa.un.sun_path, s);
2875 child_si->myname = (struct swrap_address) {
2876 .sa_socklen = in_my_addr.sa_socklen,
2878 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2880 child_si->refcount = 1;
2881 first_free = child_si->next_free;
2882 child_si->next_free = 0;
2884 child_fi->si_index = idx;
2886 SWRAP_DLIST_ADD(socket_fds, child_fi);
2889 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2890 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2891 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2898 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
2900 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
2904 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2905 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2907 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2910 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
2913 static int autobind_start_init;
2914 static int autobind_start;
2916 /* using sendto() or connect() on an unbound socket would give the
2917 recipient no way to reply, as unlike UDP and TCP, a unix domain
2918 socket can't auto-assign ephemeral port numbers, so we need to
2920 Note: this might change the family from ipv6 to ipv4
2922 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2924 struct swrap_address un_addr = {
2925 .sa_socklen = sizeof(struct sockaddr_un),
2933 if (autobind_start_init != 1) {
2934 autobind_start_init = 1;
2935 autobind_start = getpid();
2936 autobind_start %= 50000;
2937 autobind_start += 10000;
2940 un_addr.sa.un.sun_family = AF_UNIX;
2944 struct sockaddr_in in;
2948 type = SOCKET_TYPE_CHAR_TCP;
2951 type = SOCKET_TYPE_CHAR_UDP;
2954 errno = ESOCKTNOSUPPORT;
2958 memset(&in, 0, sizeof(in));
2959 in.sin_family = AF_INET;
2960 in.sin_addr.s_addr = htonl(127<<24 |
2961 socket_wrapper_default_iface());
2963 si->myname = (struct swrap_address) {
2964 .sa_socklen = sizeof(in),
2966 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2971 struct sockaddr_in6 in6;
2973 if (si->family != family) {
2974 errno = ENETUNREACH;
2980 type = SOCKET_TYPE_CHAR_TCP_V6;
2983 type = SOCKET_TYPE_CHAR_UDP_V6;
2986 errno = ESOCKTNOSUPPORT;
2990 memset(&in6, 0, sizeof(in6));
2991 in6.sin6_family = AF_INET6;
2992 in6.sin6_addr = *swrap_ipv6();
2993 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2995 si->myname = (struct swrap_address) {
2996 .sa_socklen = sizeof(in6),
2998 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3003 errno = ESOCKTNOSUPPORT;
3007 if (autobind_start > 60000) {
3008 autobind_start = 10000;
3011 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3012 port = autobind_start + i;
3013 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3014 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3015 type, socket_wrapper_default_iface(), port);
3016 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3018 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3019 if (ret == -1) return ret;
3021 si->un_addr = un_addr.sa.un;
3024 autobind_start = port + 1;
3027 if (i == SOCKET_MAX_SOCKETS) {
3028 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3029 "interface "SOCKET_FORMAT,
3032 socket_wrapper_default_iface(),
3038 si->family = family;
3039 set_port(si->family, port, &si->myname);
3044 /****************************************************************************
3046 ***************************************************************************/
3048 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3052 struct swrap_address un_addr = {
3053 .sa_socklen = sizeof(struct sockaddr_un),
3055 struct socket_info *si = find_socket_info(s);
3059 return libc_connect(s, serv_addr, addrlen);
3062 if (si->bound == 0) {
3063 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3064 if (ret == -1) return -1;
3067 if (si->family != serv_addr->sa_family) {
3072 ret = sockaddr_convert_to_un(si, serv_addr,
3073 addrlen, &un_addr.sa.un, 0, &bcast);
3074 if (ret == -1) return -1;
3077 errno = ENETUNREACH;
3081 if (si->type == SOCK_DGRAM) {
3082 si->defer_connect = 1;
3085 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3087 ret = libc_connect(s,
3089 un_addr.sa_socklen);
3092 SWRAP_LOG(SWRAP_LOG_TRACE,
3093 "connect() path=%s, fd=%d",
3094 un_addr.sa.un.sun_path, s);
3097 /* to give better errors */
3098 if (ret == -1 && errno == ENOENT) {
3099 errno = EHOSTUNREACH;
3103 si->peername = (struct swrap_address) {
3104 .sa_socklen = addrlen,
3107 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3111 * When we connect() on a socket than we have to bind the
3112 * outgoing connection on the interface we use for the
3113 * transport. We already bound it on the right interface
3114 * but here we have to update the name so getsockname()
3115 * returns correct information.
3117 if (si->bindname.sa_socklen > 0) {
3118 si->myname = (struct swrap_address) {
3119 .sa_socklen = si->bindname.sa_socklen,
3122 memcpy(&si->myname.sa.ss,
3123 &si->bindname.sa.ss,
3124 si->bindname.sa_socklen);
3126 /* Cleanup bindname */
3127 si->bindname = (struct swrap_address) {
3132 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3133 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3135 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3141 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3143 return swrap_connect(s, serv_addr, addrlen);
3146 /****************************************************************************
3148 ***************************************************************************/
3150 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3153 struct swrap_address un_addr = {
3154 .sa_socklen = sizeof(struct sockaddr_un),
3156 struct socket_info *si = find_socket_info(s);
3163 return libc_bind(s, myaddr, addrlen);
3166 switch (si->family) {
3168 const struct sockaddr_in *sin;
3169 if (addrlen < sizeof(struct sockaddr_in)) {
3170 bind_error = EINVAL;
3174 sin = (const struct sockaddr_in *)(const void *)myaddr;
3176 if (sin->sin_family != AF_INET) {
3177 bind_error = EAFNOSUPPORT;
3180 /* special case for AF_UNSPEC */
3181 if (sin->sin_family == AF_UNSPEC &&
3182 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3191 const struct sockaddr_in6 *sin6;
3192 if (addrlen < sizeof(struct sockaddr_in6)) {
3193 bind_error = EINVAL;
3197 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3199 if (sin6->sin6_family != AF_INET6) {
3200 bind_error = EAFNOSUPPORT;
3207 bind_error = EINVAL;
3211 if (bind_error != 0) {
3217 in_use = check_addr_port_in_use(myaddr, addrlen);
3224 si->myname.sa_socklen = addrlen;
3225 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3227 ret = sockaddr_convert_to_un(si,
3233 if (ret == -1) return -1;
3235 unlink(un_addr.sa.un.sun_path);
3237 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3239 SWRAP_LOG(SWRAP_LOG_TRACE,
3240 "bind() path=%s, fd=%d",
3241 un_addr.sa.un.sun_path, s);
3250 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3252 return swrap_bind(s, myaddr, addrlen);
3255 /****************************************************************************
3257 ***************************************************************************/
3259 #ifdef HAVE_BINDRESVPORT
3260 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3262 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3264 struct swrap_address myaddr = {
3265 .sa_socklen = sizeof(struct sockaddr_storage),
3268 static uint16_t port;
3273 #define SWRAP_STARTPORT 600
3274 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3275 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3278 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3282 salen = myaddr.sa_socklen;
3285 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3291 memset(&myaddr.sa.ss, 0, salen);
3296 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3299 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3301 salen = sizeof(struct sockaddr_in);
3302 sinp->sin_port = htons(port);
3306 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3308 salen = sizeof(struct sockaddr_in6);
3309 sin6p->sin6_port = htons(port);
3313 errno = EAFNOSUPPORT;
3318 if (port > SWRAP_ENDPORT) {
3319 port = SWRAP_STARTPORT;
3322 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3323 if (rc == 0 || errno != EADDRINUSE) {
3331 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3333 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3337 /****************************************************************************
3339 ***************************************************************************/
3341 static int swrap_listen(int s, int backlog)
3344 struct socket_info *si = find_socket_info(s);
3347 return libc_listen(s, backlog);
3350 if (si->bound == 0) {
3351 ret = swrap_auto_bind(s, si, si->family);
3358 ret = libc_listen(s, backlog);
3363 int listen(int s, int backlog)
3365 return swrap_listen(s, backlog);
3368 /****************************************************************************
3370 ***************************************************************************/
3372 static FILE *swrap_fopen(const char *name, const char *mode)
3376 fp = libc_fopen(name, mode);
3378 int fd = fileno(fp);
3380 swrap_remove_stale(fd);
3386 FILE *fopen(const char *name, const char *mode)
3388 return swrap_fopen(name, mode);
3391 /****************************************************************************
3393 ***************************************************************************/
3395 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3399 ret = libc_vopen(pathname, flags, ap);
3402 * There are methods for closing descriptors (libc-internal code
3403 * paths, direct syscalls) which close descriptors in ways that
3404 * we can't intercept, so try to recover when we notice that
3407 swrap_remove_stale(ret);
3412 int open(const char *pathname, int flags, ...)
3417 va_start(ap, flags);
3418 fd = swrap_vopen(pathname, flags, ap);
3424 /****************************************************************************
3426 ***************************************************************************/
3428 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3430 struct socket_info *si = find_socket_info(s);
3434 return libc_getpeername(s, name, addrlen);
3437 if (si->peername.sa_socklen == 0)
3443 len = MIN(*addrlen, si->peername.sa_socklen);
3448 memcpy(name, &si->peername.sa.ss, len);
3449 *addrlen = si->peername.sa_socklen;
3454 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3455 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3457 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3460 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3463 /****************************************************************************
3465 ***************************************************************************/
3467 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3469 struct socket_info *si = find_socket_info(s);
3473 return libc_getsockname(s, name, addrlen);
3476 len = MIN(*addrlen, si->myname.sa_socklen);
3481 memcpy(name, &si->myname.sa.ss, len);
3482 *addrlen = si->myname.sa_socklen;
3487 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3488 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3490 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3493 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3496 /****************************************************************************
3498 ***************************************************************************/
3501 # ifdef SO_PROTOTYPE /* The Solaris name */
3502 # define SO_PROTOCOL SO_PROTOTYPE
3503 # endif /* SO_PROTOTYPE */
3504 #endif /* SO_PROTOCOL */
3506 static int swrap_getsockopt(int s, int level, int optname,
3507 void *optval, socklen_t *optlen)
3509 struct socket_info *si = find_socket_info(s);
3512 return libc_getsockopt(s,
3519 if (level == SOL_SOCKET) {
3523 if (optval == NULL || optlen == NULL ||
3524 *optlen < (socklen_t)sizeof(int)) {
3529 *optlen = sizeof(int);
3530 *(int *)optval = si->family;
3532 #endif /* SO_DOMAIN */
3536 if (optval == NULL || optlen == NULL ||
3537 *optlen < (socklen_t)sizeof(int)) {
3542 *optlen = sizeof(int);
3543 *(int *)optval = si->protocol;
3545 #endif /* SO_PROTOCOL */
3547 if (optval == NULL || optlen == NULL ||
3548 *optlen < (socklen_t)sizeof(int)) {
3553 *optlen = sizeof(int);
3554 *(int *)optval = si->type;
3557 return libc_getsockopt(s,
3563 } else if (level == IPPROTO_TCP) {
3568 * This enables sending packets directly out over TCP.
3569 * As a unix socket is doing that any way, report it as
3572 if (optval == NULL || optlen == NULL ||
3573 *optlen < (socklen_t)sizeof(int)) {
3578 *optlen = sizeof(int);
3579 *(int *)optval = si->tcp_nodelay;
3582 #endif /* TCP_NODELAY */
3588 errno = ENOPROTOOPT;
3592 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3593 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3595 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3598 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3601 /****************************************************************************
3603 ***************************************************************************/
3605 static int swrap_setsockopt(int s, int level, int optname,
3606 const void *optval, socklen_t optlen)
3608 struct socket_info *si = find_socket_info(s);
3611 return libc_setsockopt(s,
3618 if (level == SOL_SOCKET) {
3619 return libc_setsockopt(s,
3624 } else if (level == IPPROTO_TCP) {
3631 * This enables sending packets directly out over TCP.
3632 * A unix socket is doing that any way.
3634 if (optval == NULL || optlen == 0 ||
3635 optlen < (socklen_t)sizeof(int)) {
3640 i = *discard_const_p(int, optval);
3641 if (i != 0 && i != 1) {
3645 si->tcp_nodelay = i;
3649 #endif /* TCP_NODELAY */
3655 switch (si->family) {
3657 if (level == IPPROTO_IP) {
3659 if (optname == IP_PKTINFO) {
3660 si->pktinfo = AF_INET;
3662 #endif /* IP_PKTINFO */
3667 if (level == IPPROTO_IPV6) {
3668 #ifdef IPV6_RECVPKTINFO
3669 if (optname == IPV6_RECVPKTINFO) {
3670 si->pktinfo = AF_INET6;
3672 #endif /* IPV6_PKTINFO */
3677 errno = ENOPROTOOPT;
3682 int setsockopt(int s, int level, int optname,
3683 const void *optval, socklen_t optlen)
3685 return swrap_setsockopt(s, level, optname, optval, optlen);
3688 /****************************************************************************
3690 ***************************************************************************/
3692 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3694 struct socket_info *si = find_socket_info(s);
3700 return libc_vioctl(s, r, va);
3705 rc = libc_vioctl(s, r, va);
3709 value = *((int *)va_arg(ap, int *));
3711 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3712 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3713 } else if (value == 0) { /* END OF FILE */
3714 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3724 #ifdef HAVE_IOCTL_INT
3725 int ioctl(int s, int r, ...)
3727 int ioctl(int s, unsigned long int r, ...)
3735 rc = swrap_vioctl(s, (unsigned long int) r, va);
3746 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3749 # ifdef _ALIGN /* BSD */
3750 #define CMSG_ALIGN _ALIGN
3752 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3753 # endif /* _ALIGN */
3754 #endif /* CMSG_ALIGN */
3757 * @brief Add a cmsghdr to a msghdr.
3759 * This is an function to add any type of cmsghdr. It will operate on the
3760 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3761 * the buffer position after the added cmsg element. Hence, this function is
3762 * intended to be used with an intermediate msghdr and not on the original
3763 * one handed in by the client.
3765 * @param[in] msg The msghdr to which to add the cmsg.
3767 * @param[in] level The cmsg level to set.
3769 * @param[in] type The cmsg type to set.
3771 * @param[in] data The cmsg data to set.
3773 * @param[in] len the length of the data to set.
3775 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3781 size_t cmlen = CMSG_LEN(len);
3782 size_t cmspace = CMSG_SPACE(len);
3783 uint8_t cmbuf[cmspace];
3784 void *cast_ptr = (void *)cmbuf;
3785 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3788 memset(cmbuf, 0, cmspace);
3790 if (msg->msg_controllen < cmlen) {
3791 cmlen = msg->msg_controllen;
3792 msg->msg_flags |= MSG_CTRUNC;
3795 if (msg->msg_controllen < cmspace) {
3796 cmspace = msg->msg_controllen;
3800 * We copy the full input data into an intermediate cmsghdr first
3801 * in order to more easily cope with truncation.
3803 cm->cmsg_len = cmlen;
3804 cm->cmsg_level = level;
3805 cm->cmsg_type = type;
3806 memcpy(CMSG_DATA(cm), data, len);
3809 * We now copy the possibly truncated buffer.
3810 * We copy cmlen bytes, but consume cmspace bytes,
3811 * leaving the possible padding uninitialiazed.
3813 p = (uint8_t *)msg->msg_control;
3814 memcpy(p, cm, cmlen);
3816 msg->msg_control = p;
3817 msg->msg_controllen -= cmspace;
3822 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3825 /* Add packet info */
3826 switch (si->pktinfo) {
3827 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3829 struct sockaddr_in *sin;
3830 #if defined(HAVE_STRUCT_IN_PKTINFO)
3831 struct in_pktinfo pkt;
3832 #elif defined(IP_RECVDSTADDR)
3836 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3837 sin = &si->bindname.sa.in;
3839 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3842 sin = &si->myname.sa.in;
3847 #if defined(HAVE_STRUCT_IN_PKTINFO)
3848 pkt.ipi_ifindex = socket_wrapper_default_iface();
3849 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3850 #elif defined(IP_RECVDSTADDR)
3851 pkt = sin->sin_addr;
3854 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3859 #endif /* IP_PKTINFO */
3860 #if defined(HAVE_IPV6)
3862 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3863 struct sockaddr_in6 *sin6;
3864 struct in6_pktinfo pkt6;
3866 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3867 sin6 = &si->bindname.sa.in6;
3869 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3872 sin6 = &si->myname.sa.in6;
3877 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3878 pkt6.ipi6_addr = sin6->sin6_addr;
3880 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3881 &pkt6, sizeof(pkt6));
3882 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3886 #endif /* IPV6_PKTINFO */
3894 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3895 struct msghdr *omsg)
3899 if (si->pktinfo > 0) {
3900 rc = swrap_msghdr_add_pktinfo(si, omsg);
3906 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3908 size_t *cm_data_space);
3909 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3911 size_t *cm_data_space);
3913 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3915 size_t *cm_data_space) {
3916 struct cmsghdr *cmsg;
3920 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3924 for (cmsg = CMSG_FIRSTHDR(msg);
3926 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3927 switch (cmsg->cmsg_level) {
3929 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3934 rc = swrap_sendmsg_copy_cmsg(cmsg,
3944 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3946 size_t *cm_data_space)
3951 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
3953 p = realloc((*cm_data), cmspace);
3959 p = (*cm_data) + (*cm_data_space);
3960 *cm_data_space = cmspace;
3962 memcpy(p, cmsg, cmsg->cmsg_len);
3967 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3969 size_t *cm_data_space);
3972 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3974 size_t *cm_data_space)
3978 switch(cmsg->cmsg_type) {
3981 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3988 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4000 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4002 size_t *cm_data_space)
4004 (void)cmsg; /* unused */
4005 (void)cm_data; /* unused */
4006 (void)cm_data_space; /* unused */
4009 * Passing a IP pktinfo to a unix socket might be rejected by the
4010 * Kernel, at least on FreeBSD. So skip this cmsg.
4014 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4016 static ssize_t swrap_sendmsg_before(int fd,
4017 struct socket_info *si,
4019 struct iovec *tmp_iov,
4020 struct sockaddr_un *tmp_un,
4021 const struct sockaddr_un **to_un,
4022 const struct sockaddr **to,
4042 if (!si->connected) {
4047 if (msg->msg_iovlen == 0) {
4051 mtu = socket_wrapper_mtu();
4052 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4054 nlen = len + msg->msg_iov[i].iov_len;
4059 msg->msg_iovlen = i;
4060 if (msg->msg_iovlen == 0) {
4061 *tmp_iov = msg->msg_iov[0];
4062 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4064 msg->msg_iov = tmp_iov;
4065 msg->msg_iovlen = 1;
4070 if (si->connected) {
4071 if (msg->msg_name != NULL) {
4073 * We are dealing with unix sockets and if we
4074 * are connected, we should only talk to the
4075 * connected unix path. Using the fd to send
4076 * to another server would be hard to achieve.
4078 msg->msg_name = NULL;
4079 msg->msg_namelen = 0;
4082 const struct sockaddr *msg_name;
4083 msg_name = (const struct sockaddr *)msg->msg_name;
4085 if (msg_name == NULL) {
4091 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4093 if (ret == -1) return -1;
4101 msg->msg_name = tmp_un;
4102 msg->msg_namelen = sizeof(*tmp_un);
4105 if (si->bound == 0) {
4106 ret = swrap_auto_bind(fd, si, si->family);
4108 if (errno == ENOTSOCK) {
4109 swrap_remove_stale(fd);
4112 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4118 if (!si->defer_connect) {
4122 ret = sockaddr_convert_to_un(si,
4124 si->peername.sa_socklen,
4128 if (ret == -1) return -1;
4130 ret = libc_connect(fd,
4131 (struct sockaddr *)(void *)tmp_un,
4134 /* to give better errors */
4135 if (ret == -1 && errno == ENOENT) {
4136 errno = EHOSTUNREACH;
4143 si->defer_connect = 0;
4146 errno = EHOSTUNREACH;
4150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4151 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4152 uint8_t *cmbuf = NULL;
4155 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4162 msg->msg_controllen = 0;
4163 msg->msg_control = NULL;
4164 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4165 memcpy(msg->msg_control, cmbuf, cmlen);
4166 msg->msg_controllen = cmlen;
4175 static void swrap_sendmsg_after(int fd,
4176 struct socket_info *si,
4178 const struct sockaddr *to,
4181 int saved_errno = errno;
4188 /* to give better errors */
4190 if (saved_errno == ENOENT) {
4191 saved_errno = EHOSTUNREACH;
4192 } else if (saved_errno == ENOTSOCK) {
4193 /* If the fd is not a socket, remove it */
4194 swrap_remove_stale(fd);
4198 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4199 avail += msg->msg_iov[i].iov_len;
4203 remain = MIN(80, avail);
4208 /* we capture it as one single packet */
4209 buf = (uint8_t *)malloc(remain);
4211 /* we just not capture the packet */
4212 errno = saved_errno;
4216 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4217 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4219 msg->msg_iov[i].iov_base,
4222 remain -= this_time;
4229 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4230 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4232 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4237 if (si->connected) {
4238 to = &si->peername.sa.s;
4241 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4242 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4244 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4250 errno = saved_errno;
4253 static int swrap_recvmsg_before(int fd,
4254 struct socket_info *si,
4256 struct iovec *tmp_iov)
4261 (void)fd; /* unused */
4266 if (!si->connected) {
4271 if (msg->msg_iovlen == 0) {
4275 mtu = socket_wrapper_mtu();
4276 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4278 nlen = len + msg->msg_iov[i].iov_len;
4283 msg->msg_iovlen = i;
4284 if (msg->msg_iovlen == 0) {
4285 *tmp_iov = msg->msg_iov[0];
4286 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4288 msg->msg_iov = tmp_iov;
4289 msg->msg_iovlen = 1;
4294 if (msg->msg_name == NULL) {
4299 if (msg->msg_iovlen == 0) {
4303 if (si->bound == 0) {
4304 ret = swrap_auto_bind(fd, si, si->family);
4307 * When attempting to read or write to a
4308 * descriptor, if an underlying autobind fails
4309 * because it's not a socket, stop intercepting
4310 * uses of that descriptor.
4312 if (errno == ENOTSOCK) {
4313 swrap_remove_stale(fd);
4316 SWRAP_LOG(SWRAP_LOG_ERROR,
4317 "swrap_recvmsg_before failed");
4324 errno = EHOSTUNREACH;
4331 static int swrap_recvmsg_after(int fd,
4332 struct socket_info *si,
4334 const struct sockaddr_un *un_addr,
4335 socklen_t un_addrlen,
4338 int saved_errno = errno;
4340 uint8_t *buf = NULL;
4346 /* to give better errors */
4348 if (saved_errno == ENOENT) {
4349 saved_errno = EHOSTUNREACH;
4350 } else if (saved_errno == ENOTSOCK) {
4351 /* If the fd is not a socket, remove it */
4352 swrap_remove_stale(fd);
4356 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4357 avail += msg->msg_iov[i].iov_len;
4360 /* Convert the socket address before we leave */
4361 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4362 rc = sockaddr_convert_from_un(si,
4379 remain = MIN(80, avail);
4384 /* we capture it as one single packet */
4385 buf = (uint8_t *)malloc(remain);
4387 /* we just not capture the packet */
4388 errno = saved_errno;
4392 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4393 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4395 msg->msg_iov[i].iov_base,
4398 remain -= this_time;
4403 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4404 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4405 } else if (ret == 0) { /* END OF FILE */
4406 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4407 } else if (ret > 0) {
4408 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4417 if (un_addr != NULL) {
4418 swrap_pcap_dump_packet(si,
4424 swrap_pcap_dump_packet(si,
4437 errno = saved_errno;
4439 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4441 msg->msg_controllen > 0 &&
4442 msg->msg_control != NULL) {
4443 rc = swrap_msghdr_add_socket_info(si, msg);
4453 /****************************************************************************
4455 ***************************************************************************/
4457 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4458 struct sockaddr *from, socklen_t *fromlen)
4460 struct swrap_address from_addr = {
4461 .sa_socklen = sizeof(struct sockaddr_un),
4464 struct socket_info *si = find_socket_info(s);
4465 struct swrap_address saddr = {
4466 .sa_socklen = sizeof(struct sockaddr_storage),
4473 return libc_recvfrom(s,
4485 if (from != NULL && fromlen != NULL) {
4486 msg.msg_name = from; /* optional address */
4487 msg.msg_namelen = *fromlen; /* size of address */
4489 msg.msg_name = &saddr.sa.s; /* optional address */
4490 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4492 msg.msg_iov = &tmp; /* scatter/gather array */
4493 msg.msg_iovlen = 1; /* # elements in msg_iov */
4494 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4495 msg.msg_control = NULL; /* ancillary data, see below */
4496 msg.msg_controllen = 0; /* ancillary data buffer len */
4497 msg.msg_flags = 0; /* flags on received message */
4500 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4505 buf = msg.msg_iov[0].iov_base;
4506 len = msg.msg_iov[0].iov_len;
4508 ret = libc_recvfrom(s,
4513 &from_addr.sa_socklen);
4518 tret = swrap_recvmsg_after(s,
4522 from_addr.sa_socklen,
4528 if (from != NULL && fromlen != NULL) {
4529 *fromlen = msg.msg_namelen;
4535 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4536 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4537 struct sockaddr *from, Psocklen_t fromlen)
4539 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4540 struct sockaddr *from, socklen_t *fromlen)
4543 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4546 /****************************************************************************
4548 ***************************************************************************/
4550 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4551 const struct sockaddr *to, socklen_t tolen)
4555 struct swrap_address un_addr = {
4556 .sa_socklen = sizeof(struct sockaddr_un),
4558 const struct sockaddr_un *to_un = NULL;
4561 struct socket_info *si = find_socket_info(s);
4565 return libc_sendto(s, buf, len, flags, to, tolen);
4568 tmp.iov_base = discard_const_p(char, buf);
4572 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4573 msg.msg_namelen = tolen; /* size of address */
4574 msg.msg_iov = &tmp; /* scatter/gather array */
4575 msg.msg_iovlen = 1; /* # elements in msg_iov */
4576 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4577 msg.msg_control = NULL; /* ancillary data, see below */
4578 msg.msg_controllen = 0; /* ancillary data buffer len */
4579 msg.msg_flags = 0; /* flags on received message */
4582 rc = swrap_sendmsg_before(s,
4594 buf = msg.msg_iov[0].iov_base;
4595 len = msg.msg_iov[0].iov_len;
4600 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4603 type = SOCKET_TYPE_CHAR_UDP;
4605 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4606 snprintf(un_addr.sa.un.sun_path,
4607 sizeof(un_addr.sa.un.sun_path),
4609 socket_wrapper_dir(), type, iface, prt);
4610 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4612 /* ignore the any errors in broadcast sends */
4618 un_addr.sa_socklen);
4621 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4627 * If it is a dgram socket and we are connected, don't include the
4630 if (si->type == SOCK_DGRAM && si->connected) {
4631 ret = libc_sendto(s,
4638 ret = libc_sendto(s,
4642 (struct sockaddr *)msg.msg_name,
4646 swrap_sendmsg_after(s, si, &msg, to, ret);
4651 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4652 const struct sockaddr *to, socklen_t tolen)
4654 return swrap_sendto(s, buf, len, flags, to, tolen);
4657 /****************************************************************************
4659 ***************************************************************************/
4661 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4663 struct socket_info *si;
4665 struct swrap_address saddr = {
4666 .sa_socklen = sizeof(struct sockaddr_storage),
4672 si = find_socket_info(s);
4674 return libc_recv(s, buf, len, flags);
4681 msg.msg_name = &saddr.sa.s; /* optional address */
4682 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4683 msg.msg_iov = &tmp; /* scatter/gather array */
4684 msg.msg_iovlen = 1; /* # elements in msg_iov */
4685 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4686 msg.msg_control = NULL; /* ancillary data, see below */
4687 msg.msg_controllen = 0; /* ancillary data buffer len */
4688 msg.msg_flags = 0; /* flags on received message */
4691 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4696 buf = msg.msg_iov[0].iov_base;
4697 len = msg.msg_iov[0].iov_len;
4699 ret = libc_recv(s, buf, len, flags);
4701 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4709 ssize_t recv(int s, void *buf, size_t len, int flags)
4711 return swrap_recv(s, buf, len, flags);
4714 /****************************************************************************
4716 ***************************************************************************/
4718 static ssize_t swrap_read(int s, void *buf, size_t len)
4720 struct socket_info *si;
4723 struct swrap_address saddr = {
4724 .sa_socklen = sizeof(struct sockaddr_storage),
4729 si = find_socket_info(s);
4731 return libc_read(s, buf, len);
4738 msg.msg_name = &saddr.sa.ss; /* optional address */
4739 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4740 msg.msg_iov = &tmp; /* scatter/gather array */
4741 msg.msg_iovlen = 1; /* # elements in msg_iov */
4742 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4743 msg.msg_control = NULL; /* ancillary data, see below */
4744 msg.msg_controllen = 0; /* ancillary data buffer len */
4745 msg.msg_flags = 0; /* flags on received message */
4748 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4750 if (tret == -ENOTSOCK) {
4751 return libc_read(s, buf, len);
4756 buf = msg.msg_iov[0].iov_base;
4757 len = msg.msg_iov[0].iov_len;
4759 ret = libc_read(s, buf, len);
4761 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4769 ssize_t read(int s, void *buf, size_t len)
4771 return swrap_read(s, buf, len);
4774 /****************************************************************************
4776 ***************************************************************************/
4778 static ssize_t swrap_write(int s, const void *buf, size_t len)
4782 struct sockaddr_un un_addr;
4785 struct socket_info *si;
4787 si = find_socket_info(s);
4789 return libc_write(s, buf, len);
4792 tmp.iov_base = discard_const_p(char, buf);
4796 msg.msg_name = NULL; /* optional address */
4797 msg.msg_namelen = 0; /* size of address */
4798 msg.msg_iov = &tmp; /* scatter/gather array */
4799 msg.msg_iovlen = 1; /* # elements in msg_iov */
4800 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4801 msg.msg_control = NULL; /* ancillary data, see below */
4802 msg.msg_controllen = 0; /* ancillary data buffer len */
4803 msg.msg_flags = 0; /* flags on received message */
4806 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4811 buf = msg.msg_iov[0].iov_base;
4812 len = msg.msg_iov[0].iov_len;
4814 ret = libc_write(s, buf, len);
4816 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4821 ssize_t write(int s, const void *buf, size_t len)
4823 return swrap_write(s, buf, len);
4826 /****************************************************************************
4828 ***************************************************************************/
4830 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4834 struct sockaddr_un un_addr;
4837 struct socket_info *si = find_socket_info(s);
4840 return libc_send(s, buf, len, flags);
4843 tmp.iov_base = discard_const_p(char, buf);
4847 msg.msg_name = NULL; /* optional address */
4848 msg.msg_namelen = 0; /* size of address */
4849 msg.msg_iov = &tmp; /* scatter/gather array */
4850 msg.msg_iovlen = 1; /* # elements in msg_iov */
4851 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4852 msg.msg_control = NULL; /* ancillary data, see below */
4853 msg.msg_controllen = 0; /* ancillary data buffer len */
4854 msg.msg_flags = 0; /* flags on received message */
4857 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4862 buf = msg.msg_iov[0].iov_base;
4863 len = msg.msg_iov[0].iov_len;
4865 ret = libc_send(s, buf, len, flags);
4867 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4872 ssize_t send(int s, const void *buf, size_t len, int flags)
4874 return swrap_send(s, buf, len, flags);
4877 /****************************************************************************
4879 ***************************************************************************/
4881 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4883 struct swrap_address from_addr = {
4884 .sa_socklen = sizeof(struct sockaddr_un),
4886 struct swrap_address convert_addr = {
4887 .sa_socklen = sizeof(struct sockaddr_storage),
4889 struct socket_info *si;
4892 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4893 size_t msg_ctrllen_filled;
4894 size_t msg_ctrllen_left;
4900 si = find_socket_info(s);
4902 return libc_recvmsg(s, omsg, flags);
4905 tmp.iov_base = NULL;
4909 msg.msg_name = &from_addr.sa; /* optional address */
4910 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4911 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4912 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4913 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4914 msg_ctrllen_filled = 0;
4915 msg_ctrllen_left = omsg->msg_controllen;
4917 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4918 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4919 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4922 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4927 ret = libc_recvmsg(s, &msg, flags);
4929 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4930 msg_ctrllen_filled += msg.msg_controllen;
4931 msg_ctrllen_left -= msg.msg_controllen;
4933 if (omsg->msg_control != NULL) {
4936 p = omsg->msg_control;
4937 p += msg_ctrllen_filled;
4939 msg.msg_control = p;
4940 msg.msg_controllen = msg_ctrllen_left;
4942 msg.msg_control = NULL;
4943 msg.msg_controllen = 0;
4948 * We convert the unix address to a IP address so we need a buffer
4949 * which can store the address in case of SOCK_DGRAM, see below.
4951 msg.msg_name = &convert_addr.sa;
4952 msg.msg_namelen = convert_addr.sa_socklen;
4954 rc = swrap_recvmsg_after(s,
4958 from_addr.sa_socklen,
4964 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4965 if (omsg->msg_control != NULL) {
4966 /* msg.msg_controllen = space left */
4967 msg_ctrllen_left = msg.msg_controllen;
4968 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4971 /* Update the original message length */
4972 omsg->msg_controllen = msg_ctrllen_filled;
4973 omsg->msg_flags = msg.msg_flags;
4975 omsg->msg_iovlen = msg.msg_iovlen;
4980 * The msg_name field points to a caller-allocated buffer that is
4981 * used to return the source address if the socket is unconnected. The
4982 * caller should set msg_namelen to the size of this buffer before this
4983 * call; upon return from a successful call, msg_name will contain the
4984 * length of the returned address. If the application does not need
4985 * to know the source address, msg_name can be specified as NULL.
4987 if (si->type == SOCK_STREAM) {
4988 omsg->msg_namelen = 0;
4989 } else if (omsg->msg_name != NULL &&
4990 omsg->msg_namelen != 0 &&
4991 omsg->msg_namelen >= msg.msg_namelen) {
4992 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
4993 omsg->msg_namelen = msg.msg_namelen;
4999 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5001 return swrap_recvmsg(sockfd, msg, flags);
5004 /****************************************************************************
5006 ***************************************************************************/
5008 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5012 struct sockaddr_un un_addr;
5013 const struct sockaddr_un *to_un = NULL;
5014 const struct sockaddr *to = NULL;
5017 struct socket_info *si = find_socket_info(s);
5021 return libc_sendmsg(s, omsg, flags);
5024 ZERO_STRUCT(un_addr);
5026 tmp.iov_base = NULL;
5031 if (si->connected == 0) {
5032 msg.msg_name = omsg->msg_name; /* optional address */
5033 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5035 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5036 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5037 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5038 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5039 /* omsg is a const so use a local buffer for modifications */
5040 uint8_t cmbuf[omsg->msg_controllen];
5042 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5044 msg.msg_control = cmbuf; /* ancillary data, see below */
5045 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5047 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5050 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5058 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5066 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5067 avail += msg.msg_iov[i].iov_len;
5073 /* we capture it as one single packet */
5074 buf = (uint8_t *)malloc(remain);
5079 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5080 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5082 msg.msg_iov[i].iov_base,
5085 remain -= this_time;
5088 type = SOCKET_TYPE_CHAR_UDP;
5090 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5091 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5092 socket_wrapper_dir(), type, iface, prt);
5093 if (stat(un_addr.sun_path, &st) != 0) continue;
5095 msg.msg_name = &un_addr; /* optional address */
5096 msg.msg_namelen = sizeof(un_addr); /* size of address */
5098 /* ignore the any errors in broadcast sends */
5099 libc_sendmsg(s, &msg, flags);
5102 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5108 ret = libc_sendmsg(s, &msg, flags);
5110 swrap_sendmsg_after(s, si, &msg, to, ret);
5115 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5117 return swrap_sendmsg(s, omsg, flags);
5120 /****************************************************************************
5122 ***************************************************************************/
5124 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5126 struct socket_info *si;
5129 struct swrap_address saddr = {
5130 .sa_socklen = sizeof(struct sockaddr_storage)
5135 si = find_socket_info(s);
5137 return libc_readv(s, vector, count);
5140 tmp.iov_base = NULL;
5144 msg.msg_name = &saddr.sa.s; /* optional address */
5145 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5146 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5147 msg.msg_iovlen = count; /* # elements in msg_iov */
5148 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5149 msg.msg_control = NULL; /* ancillary data, see below */
5150 msg.msg_controllen = 0; /* ancillary data buffer len */
5151 msg.msg_flags = 0; /* flags on received message */
5154 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5156 if (rc == -ENOTSOCK) {
5157 return libc_readv(s, vector, count);
5162 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5164 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5172 ssize_t readv(int s, const struct iovec *vector, int count)
5174 return swrap_readv(s, vector, count);
5177 /****************************************************************************
5179 ***************************************************************************/
5181 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5185 struct sockaddr_un un_addr;
5188 struct socket_info *si = find_socket_info(s);
5191 return libc_writev(s, vector, count);
5194 tmp.iov_base = NULL;
5198 msg.msg_name = NULL; /* optional address */
5199 msg.msg_namelen = 0; /* size of address */
5200 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5201 msg.msg_iovlen = count; /* # elements in msg_iov */
5202 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5203 msg.msg_control = NULL; /* ancillary data, see below */
5204 msg.msg_controllen = 0; /* ancillary data buffer len */
5205 msg.msg_flags = 0; /* flags on received message */
5208 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5210 if (rc == -ENOTSOCK) {
5211 return libc_readv(s, vector, count);
5216 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5218 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5223 ssize_t writev(int s, const struct iovec *vector, int count)
5225 return swrap_writev(s, vector, count);
5228 /****************************
5230 ***************************/
5232 static int swrap_close(int fd)
5234 struct socket_info_fd *fi = find_socket_info_fd(fd);
5235 struct socket_info *si = NULL;
5239 return libc_close(fd);
5242 si = &sockets[fi->si_index];
5244 SWRAP_DLIST_REMOVE(socket_fds, fi);
5249 if (si->refcount > 0) {
5250 /* there are still references left */
5251 return libc_close(fd);
5254 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5255 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5258 ret = libc_close(fd);
5260 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5261 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5262 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5265 if (si->un_addr.sun_path[0] != '\0') {
5266 unlink(si->un_addr.sun_path);
5269 si->next_free = first_free;
5270 first_free = fi->si_index;
5277 return swrap_close(fd);
5280 /****************************
5282 ***************************/
5284 static int swrap_dup(int fd)
5286 struct socket_info *si;
5287 struct socket_info_fd *src_fi, *fi;
5289 src_fi = find_socket_info_fd(fd);
5290 if (src_fi == NULL) {
5291 return libc_dup(fd);
5294 si = &sockets[src_fi->si_index];
5296 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5302 fi->fd = libc_dup(fd);
5304 int saved_errno = errno;
5306 errno = saved_errno;
5311 fi->si_index = src_fi->si_index;
5313 /* Make sure we don't have an entry for the fd */
5314 swrap_remove_stale(fi->fd);
5316 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5322 return swrap_dup(fd);
5325 /****************************
5327 ***************************/
5329 static int swrap_dup2(int fd, int newfd)
5331 struct socket_info *si;
5332 struct socket_info_fd *src_fi, *fi;
5334 src_fi = find_socket_info_fd(fd);
5335 if (src_fi == NULL) {
5336 return libc_dup2(fd, newfd);
5339 si = &sockets[src_fi->si_index];
5343 * According to the manpage:
5345 * "If oldfd is a valid file descriptor, and newfd has the same
5346 * value as oldfd, then dup2() does nothing, and returns newfd."
5351 if (find_socket_info(newfd)) {
5352 /* dup2() does an implicit close of newfd, which we
5353 * need to emulate */
5357 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5363 fi->fd = libc_dup2(fd, newfd);
5365 int saved_errno = errno;
5367 errno = saved_errno;
5372 fi->si_index = src_fi->si_index;
5374 /* Make sure we don't have an entry for the fd */
5375 swrap_remove_stale(fi->fd);
5377 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5381 int dup2(int fd, int newfd)
5383 return swrap_dup2(fd, newfd);
5386 /****************************
5388 ***************************/
5390 static int swrap_vfcntl(int fd, int cmd, va_list va)
5392 struct socket_info_fd *src_fi, *fi;
5393 struct socket_info *si;
5396 src_fi = find_socket_info_fd(fd);
5397 if (src_fi == NULL) {
5398 return libc_vfcntl(fd, cmd, va);
5401 si = &sockets[src_fi->si_index];
5405 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5411 fi->fd = libc_vfcntl(fd, cmd, va);
5413 int saved_errno = errno;
5415 errno = saved_errno;
5420 fi->si_index = src_fi->si_index;
5422 /* Make sure we don't have an entry for the fd */
5423 swrap_remove_stale(fi->fd);
5425 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5430 rc = libc_vfcntl(fd, cmd, va);
5437 int fcntl(int fd, int cmd, ...)
5444 rc = swrap_vfcntl(fd, cmd, va);
5451 /****************************
5453 ***************************/
5456 static int swrap_eventfd(int count, int flags)
5460 fd = libc_eventfd(count, flags);
5462 swrap_remove_stale(fd);
5468 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5469 int eventfd(unsigned int count, int flags)
5471 int eventfd(int count, int flags)
5474 return swrap_eventfd(count, flags);
5479 int pledge(const char *promises, const char *paths[])
5481 (void)promises; /* unused */
5482 (void)paths; /* unused */
5486 #endif /* HAVE_PLEDGE */
5488 /****************************
5490 ***************************/
5493 * This function is called when the library is unloaded and makes sure that
5494 * sockets get closed and the unix file for the socket are unlinked.
5496 void swrap_destructor(void)
5498 struct socket_info_fd *s = socket_fds;
5507 if (swrap.libc_handle != NULL) {
5508 dlclose(swrap.libc_handle);
5510 if (swrap.libsocket_handle) {
5511 dlclose(swrap.libsocket_handle);