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>
91 /* GCC have printf type attribute check. */
92 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
93 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
95 #define PRINTF_ATTRIBUTE(a,b)
96 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
98 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
99 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
101 #define CONSTRUCTOR_ATTRIBUTE
102 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
104 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
105 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
107 #define DESTRUCTOR_ATTRIBUTE
110 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
111 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
113 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
116 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
117 # define SWRAP_THREAD __thread
119 # define SWRAP_THREAD
123 #define MIN(a,b) ((a)<(b)?(a):(b))
127 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
131 #define ZERO_STRUCTP(x) do { \
133 memset((char *)(x), 0, sizeof(*(x))); \
137 #ifndef discard_const
138 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
141 #ifndef discard_const_p
142 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
145 #define UNUSED(x) (void)(x)
148 # ifndef IPV6_RECVPKTINFO
149 # define IPV6_RECVPKTINFO IPV6_PKTINFO
150 # endif /* IPV6_RECVPKTINFO */
151 #endif /* IPV6_PKTINFO */
154 * On BSD IP_PKTINFO has a different name because during
155 * the time when they implemented it, there was no RFC.
156 * The name for IPv6 is the same as on Linux.
159 # ifdef IP_RECVDSTADDR
160 # define IP_PKTINFO IP_RECVDSTADDR
164 /* Macros for accessing mutexes */
165 # define SWRAP_LOCK(m) do { \
166 pthread_mutex_lock(&(m ## _mutex)); \
169 # define SWRAP_UNLOCK(m) do { \
170 pthread_mutex_unlock(&(m ## _mutex)); \
173 /* Add new global locks here please */
174 # define SWRAP_LOCK_ALL \
175 SWRAP_LOCK(libc_symbol_binding); \
177 # define SWRAP_UNLOCK_ALL \
178 SWRAP_UNLOCK(libc_symbol_binding); \
181 #define SWRAP_DLIST_ADD(list,item) do { \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
187 (item)->prev = NULL; \
188 (item)->next = (list); \
189 (list)->prev = (item); \
194 #define SWRAP_DLIST_REMOVE(list,item) do { \
195 if ((list) == (item)) { \
196 (list) = (item)->next; \
198 (list)->prev = NULL; \
201 if ((item)->prev) { \
202 (item)->prev->next = (item)->next; \
204 if ((item)->next) { \
205 (item)->next->prev = (item)->prev; \
208 (item)->prev = NULL; \
209 (item)->next = NULL; \
212 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
214 if ((list) == NULL || (el) == NULL) { \
215 SWRAP_DLIST_ADD(list, item); \
217 (item)->prev = (el); \
218 (item)->next = (el)->next; \
219 (el)->next = (item); \
220 if ((item)->next != NULL) { \
221 (item)->next->prev = (item); \
226 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
227 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
229 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
232 /* we need to use a very terse format here as IRIX 6.4 silently
233 truncates names to 16 chars, so if we use a longer name then we
234 can't tell which port a packet came from with recvfrom()
236 with this format we have 8 chars left for the directory name
238 #define SOCKET_FORMAT "%c%02X%04X"
239 #define SOCKET_TYPE_CHAR_TCP 'T'
240 #define SOCKET_TYPE_CHAR_UDP 'U'
241 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
242 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
245 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
246 * format PCAP capture files (as the caller will simply continue from here).
248 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
249 #define SOCKET_WRAPPER_MTU_MIN 512
250 #define SOCKET_WRAPPER_MTU_MAX 32768
252 #define SOCKET_MAX_SOCKETS 1024
256 * Maximum number of socket_info structures that can
257 * be used. Can be overriden by the environment variable
258 * SOCKET_WRAPPER_MAX_SOCKETS.
260 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
262 /* This limit is to avoid broadcast sendto() needing to stat too many
263 * files. It may be raised (with a performance cost) to up to 254
264 * without changing the format above */
265 #define MAX_WRAPPED_INTERFACES 40
267 struct swrap_address {
268 socklen_t sa_socklen;
271 struct sockaddr_in in;
273 struct sockaddr_in6 in6;
275 struct sockaddr_un un;
276 struct sockaddr_storage ss;
280 struct socket_info_fd {
281 struct socket_info_fd *prev, *next;
285 * Points to corresponding index in array of
286 * socket_info structures
295 unsigned int refcount;
310 /* The unix path so we can unlink it on close() */
311 struct sockaddr_un un_addr;
313 struct swrap_address bindname;
314 struct swrap_address myname;
315 struct swrap_address peername;
318 unsigned long pck_snd;
319 unsigned long pck_rcv;
323 static struct socket_info *sockets;
324 static size_t max_sockets = 0;
327 * While socket file descriptors are passed among different processes, the
328 * numerical value gets changed. So its better to store it locally to each
329 * process rather than including it within socket_info which will be shared.
331 static struct socket_info_fd *socket_fds;
333 /* The mutex for accessing the global libc.symbols */
334 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
336 /* Function prototypes */
338 bool socket_wrapper_enabled(void);
340 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
341 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
344 # define SWRAP_LOG(...)
347 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
348 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
350 static void swrap_log(enum swrap_dbglvl_e dbglvl,
352 const char *format, ...)
357 unsigned int lvl = 0;
359 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
364 va_start(va, format);
365 vsnprintf(buffer, sizeof(buffer), format, va);
370 case SWRAP_LOG_ERROR:
372 "SWRAP_ERROR(%d) - %s: %s\n",
373 (int)getpid(), func, buffer);
377 "SWRAP_WARN(%d) - %s: %s\n",
378 (int)getpid(), func, buffer);
380 case SWRAP_LOG_DEBUG:
382 "SWRAP_DEBUG(%d) - %s: %s\n",
383 (int)getpid(), func, buffer);
385 case SWRAP_LOG_TRACE:
387 "SWRAP_TRACE(%d) - %s: %s\n",
388 (int)getpid(), func, buffer);
395 /*********************************************************
396 * SWRAP LOADING LIBC FUNCTIONS
397 *********************************************************/
402 typedef int (*__libc_accept4)(int sockfd,
403 struct sockaddr *addr,
407 typedef int (*__libc_accept)(int sockfd,
408 struct sockaddr *addr,
411 typedef int (*__libc_bind)(int sockfd,
412 const struct sockaddr *addr,
414 typedef int (*__libc_close)(int fd);
415 typedef int (*__libc_connect)(int sockfd,
416 const struct sockaddr *addr,
418 typedef int (*__libc_dup)(int fd);
419 typedef int (*__libc_dup2)(int oldfd, int newfd);
420 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
421 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
423 typedef int (*__libc_eventfd)(int count, int flags);
425 typedef int (*__libc_getpeername)(int sockfd,
426 struct sockaddr *addr,
428 typedef int (*__libc_getsockname)(int sockfd,
429 struct sockaddr *addr,
431 typedef int (*__libc_getsockopt)(int sockfd,
436 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
437 typedef int (*__libc_listen)(int sockfd, int backlog);
438 typedef int (*__libc_open)(const char *pathname, int flags, mode_t mode);
439 typedef int (*__libc_pipe)(int pipefd[2]);
440 typedef int (*__libc_read)(int fd, void *buf, size_t count);
441 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
442 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
443 typedef int (*__libc_recvfrom)(int sockfd,
447 struct sockaddr *src_addr,
449 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
450 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
451 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
452 typedef int (*__libc_sendto)(int sockfd,
456 const struct sockaddr *dst_addr,
458 typedef int (*__libc_setsockopt)(int sockfd,
464 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
466 typedef int (*__libc_socket)(int domain, int type, int protocol);
467 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
468 #ifdef HAVE_TIMERFD_CREATE
469 typedef int (*__libc_timerfd_create)(int clockid, int flags);
471 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
472 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
474 #define SWRAP_SYMBOL_ENTRY(i) \
480 struct swrap_libc_symbols {
482 SWRAP_SYMBOL_ENTRY(accept4);
484 SWRAP_SYMBOL_ENTRY(accept);
486 SWRAP_SYMBOL_ENTRY(bind);
487 SWRAP_SYMBOL_ENTRY(close);
488 SWRAP_SYMBOL_ENTRY(connect);
489 SWRAP_SYMBOL_ENTRY(dup);
490 SWRAP_SYMBOL_ENTRY(dup2);
491 SWRAP_SYMBOL_ENTRY(fcntl);
492 SWRAP_SYMBOL_ENTRY(fopen);
494 SWRAP_SYMBOL_ENTRY(eventfd);
496 SWRAP_SYMBOL_ENTRY(getpeername);
497 SWRAP_SYMBOL_ENTRY(getsockname);
498 SWRAP_SYMBOL_ENTRY(getsockopt);
499 SWRAP_SYMBOL_ENTRY(ioctl);
500 SWRAP_SYMBOL_ENTRY(listen);
501 SWRAP_SYMBOL_ENTRY(open);
502 SWRAP_SYMBOL_ENTRY(pipe);
503 SWRAP_SYMBOL_ENTRY(read);
504 SWRAP_SYMBOL_ENTRY(readv);
505 SWRAP_SYMBOL_ENTRY(recv);
506 SWRAP_SYMBOL_ENTRY(recvfrom);
507 SWRAP_SYMBOL_ENTRY(recvmsg);
508 SWRAP_SYMBOL_ENTRY(send);
509 SWRAP_SYMBOL_ENTRY(sendmsg);
510 SWRAP_SYMBOL_ENTRY(sendto);
511 SWRAP_SYMBOL_ENTRY(setsockopt);
513 SWRAP_SYMBOL_ENTRY(signalfd);
515 SWRAP_SYMBOL_ENTRY(socket);
516 SWRAP_SYMBOL_ENTRY(socketpair);
517 #ifdef HAVE_TIMERFD_CREATE
518 SWRAP_SYMBOL_ENTRY(timerfd_create);
520 SWRAP_SYMBOL_ENTRY(write);
521 SWRAP_SYMBOL_ENTRY(writev);
528 struct swrap_libc_symbols symbols;
532 static struct swrap swrap;
535 static const char *socket_wrapper_dir(void);
537 #define LIBC_NAME "libc.so"
546 static const char *swrap_str_lib(enum swrap_lib lib)
553 case SWRAP_LIBSOCKET:
557 /* Compiler would warn us about unhandled enum value if we get here */
562 static void *swrap_load_lib_handle(enum swrap_lib lib)
564 int flags = RTLD_LAZY;
569 flags |= RTLD_DEEPBIND;
575 case SWRAP_LIBSOCKET:
576 #ifdef HAVE_LIBSOCKET
577 handle = swrap.libc.socket_handle;
578 if (handle == NULL) {
579 for (i = 10; i >= 0; i--) {
580 char soname[256] = {0};
582 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
583 handle = dlopen(soname, flags);
584 if (handle != NULL) {
589 swrap.libc.socket_handle = handle;
595 handle = swrap.libc.handle;
597 if (handle == NULL) {
598 handle = dlopen(LIBC_SO, flags);
600 swrap.libc.handle = handle;
603 if (handle == NULL) {
604 for (i = 10; i >= 0; i--) {
605 char soname[256] = {0};
607 snprintf(soname, sizeof(soname), "libc.so.%d", i);
608 handle = dlopen(soname, flags);
609 if (handle != NULL) {
614 swrap.libc.handle = handle;
619 if (handle == NULL) {
621 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
623 SWRAP_LOG(SWRAP_LOG_ERROR,
624 "Failed to dlopen library: %s\n",
633 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
638 handle = swrap_load_lib_handle(lib);
640 func = dlsym(handle, fn_name);
642 SWRAP_LOG(SWRAP_LOG_ERROR,
643 "Failed to find %s: %s\n",
649 SWRAP_LOG(SWRAP_LOG_TRACE,
657 #define swrap_bind_symbol_libc(sym_name) \
658 SWRAP_LOCK(libc_symbol_binding); \
659 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
660 swrap.libc.symbols._libc_##sym_name.obj = \
661 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
663 SWRAP_UNLOCK(libc_symbol_binding)
665 #define swrap_bind_symbol_libsocket(sym_name) \
666 SWRAP_LOCK(libc_symbol_binding); \
667 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
668 swrap.libc.symbols._libc_##sym_name.obj = \
669 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
671 SWRAP_UNLOCK(libc_symbol_binding)
673 #define swrap_bind_symbol_libnsl(sym_name) \
674 SWRAP_LOCK(libc_symbol_binding); \
675 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
676 swrap.libc.symbols._libc_##sym_name.obj = \
677 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
679 SWRAP_UNLOCK(libc_symbol_binding)
684 * Functions especially from libc need to be loaded individually, you can't load
685 * all at once or gdb will segfault at startup. The same applies to valgrind and
686 * has probably something todo with with the linker.
687 * So we need load each function at the point it is called the first time.
690 static int libc_accept4(int sockfd,
691 struct sockaddr *addr,
695 swrap_bind_symbol_libsocket(accept4);
697 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
700 #else /* HAVE_ACCEPT4 */
702 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
704 swrap_bind_symbol_libsocket(accept);
706 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
708 #endif /* HAVE_ACCEPT4 */
710 static int libc_bind(int sockfd,
711 const struct sockaddr *addr,
714 swrap_bind_symbol_libsocket(bind);
716 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
719 static int libc_close(int fd)
721 swrap_bind_symbol_libc(close);
723 return swrap.libc.symbols._libc_close.f(fd);
726 static int libc_connect(int sockfd,
727 const struct sockaddr *addr,
730 swrap_bind_symbol_libsocket(connect);
732 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
735 static int libc_dup(int fd)
737 swrap_bind_symbol_libc(dup);
739 return swrap.libc.symbols._libc_dup.f(fd);
742 static int libc_dup2(int oldfd, int newfd)
744 swrap_bind_symbol_libc(dup2);
746 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
750 static int libc_eventfd(int count, int flags)
752 swrap_bind_symbol_libc(eventfd);
754 return swrap.libc.symbols._libc_eventfd.f(count, flags);
758 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
759 static int libc_vfcntl(int fd, int cmd, va_list ap)
765 swrap_bind_symbol_libc(fcntl);
767 for (i = 0; i < 4; i++) {
768 args[i] = va_arg(ap, long int);
771 rc = swrap.libc.symbols._libc_fcntl.f(fd,
781 static int libc_getpeername(int sockfd,
782 struct sockaddr *addr,
785 swrap_bind_symbol_libsocket(getpeername);
787 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
790 static int libc_getsockname(int sockfd,
791 struct sockaddr *addr,
794 swrap_bind_symbol_libsocket(getsockname);
796 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
799 static int libc_getsockopt(int sockfd,
805 swrap_bind_symbol_libsocket(getsockopt);
807 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
814 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
815 static int libc_vioctl(int d, unsigned long int request, va_list ap)
821 swrap_bind_symbol_libc(ioctl);
823 for (i = 0; i < 4; i++) {
824 args[i] = va_arg(ap, long int);
827 rc = swrap.libc.symbols._libc_ioctl.f(d,
837 static int libc_listen(int sockfd, int backlog)
839 swrap_bind_symbol_libsocket(listen);
841 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
844 static FILE *libc_fopen(const char *name, const char *mode)
846 swrap_bind_symbol_libc(fopen);
848 return swrap.libc.symbols._libc_fopen.f(name, mode);
851 static int libc_vopen(const char *pathname, int flags, va_list ap)
856 swrap_bind_symbol_libc(open);
858 mode = va_arg(ap, long int);
860 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
865 static int libc_open(const char *pathname, int flags, ...)
871 fd = libc_vopen(pathname, flags, ap);
877 static int libc_pipe(int pipefd[2])
879 swrap_bind_symbol_libsocket(pipe);
881 return swrap.libc.symbols._libc_pipe.f(pipefd);
884 static int libc_read(int fd, void *buf, size_t count)
886 swrap_bind_symbol_libc(read);
888 return swrap.libc.symbols._libc_read.f(fd, buf, count);
891 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
893 swrap_bind_symbol_libsocket(readv);
895 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
898 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
900 swrap_bind_symbol_libsocket(recv);
902 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
905 static int libc_recvfrom(int sockfd,
909 struct sockaddr *src_addr,
912 swrap_bind_symbol_libsocket(recvfrom);
914 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
922 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
924 swrap_bind_symbol_libsocket(recvmsg);
926 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
929 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
931 swrap_bind_symbol_libsocket(send);
933 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
936 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
938 swrap_bind_symbol_libsocket(sendmsg);
940 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
943 static int libc_sendto(int sockfd,
947 const struct sockaddr *dst_addr,
950 swrap_bind_symbol_libsocket(sendto);
952 return swrap.libc.symbols._libc_sendto.f(sockfd,
960 static int libc_setsockopt(int sockfd,
966 swrap_bind_symbol_libsocket(setsockopt);
968 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
976 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
978 swrap_bind_symbol_libsocket(signalfd);
980 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
984 static int libc_socket(int domain, int type, int protocol)
986 swrap_bind_symbol_libsocket(socket);
988 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
991 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
993 swrap_bind_symbol_libsocket(socketpair);
995 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
998 #ifdef HAVE_TIMERFD_CREATE
999 static int libc_timerfd_create(int clockid, int flags)
1001 swrap_bind_symbol_libc(timerfd_create);
1003 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1007 static ssize_t libc_write(int fd, const void *buf, size_t count)
1009 swrap_bind_symbol_libc(write);
1011 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1014 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1016 swrap_bind_symbol_libsocket(writev);
1018 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1021 /*********************************************************
1022 * SWRAP HELPER FUNCTIONS
1023 *********************************************************/
1029 static const struct in6_addr *swrap_ipv6(void)
1031 static struct in6_addr v;
1032 static int initialized;
1040 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1049 static void set_port(int family, int prt, struct swrap_address *addr)
1053 addr->sa.in.sin_port = htons(prt);
1057 addr->sa.in6.sin6_port = htons(prt);
1063 static size_t socket_length(int family)
1067 return sizeof(struct sockaddr_in);
1070 return sizeof(struct sockaddr_in6);
1076 static const char *socket_wrapper_dir(void)
1078 const char *s = getenv("SOCKET_WRAPPER_DIR");
1082 /* TODO use realpath(3) here, when we add support for threads */
1083 if (strncmp(s, "./", 2) == 0) {
1087 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1091 static unsigned int socket_wrapper_mtu(void)
1093 static unsigned int max_mtu = 0;
1102 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1104 s = getenv("SOCKET_WRAPPER_MTU");
1109 tmp = strtol(s, &endp, 10);
1114 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1123 static size_t socket_wrapper_max_sockets(void)
1129 if (max_sockets != 0) {
1133 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1135 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1136 if (s == NULL || s[0] == '\0') {
1140 tmp = strtoul(s, &endp, 10);
1151 static void socket_wrapper_init_sockets(void)
1155 if (sockets != NULL) {
1159 max_sockets = socket_wrapper_max_sockets();
1161 sockets = (struct socket_info *)calloc(max_sockets,
1162 sizeof(struct socket_info));
1164 if (sockets == NULL) {
1165 SWRAP_LOG(SWRAP_LOG_ERROR,
1166 "Failed to allocate sockets array.\n");
1172 for (i = 0; i < max_sockets; i++) {
1173 sockets[i].next_free = i+1;
1176 sockets[max_sockets-1].next_free = -1;
1179 bool socket_wrapper_enabled(void)
1181 const char *s = socket_wrapper_dir();
1187 socket_wrapper_init_sockets();
1192 static unsigned int socket_wrapper_default_iface(void)
1194 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1197 if (sscanf(s, "%u", &iface) == 1) {
1198 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1204 return 1;/* 127.0.0.1 */
1208 * Return the first free entry (if any) and make
1209 * it re-usable again (by nulling it out)
1211 static int socket_wrapper_first_free_index(void)
1215 if (first_free == -1) {
1219 next_free = sockets[first_free].next_free;
1220 ZERO_STRUCT(sockets[first_free]);
1221 sockets[first_free].next_free = next_free;
1226 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1233 p = strrchr(un->sun_path, '/');
1234 if (p) p++; else p = un->sun_path;
1236 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1241 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1244 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1255 case SOCKET_TYPE_CHAR_TCP:
1256 case SOCKET_TYPE_CHAR_UDP: {
1257 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1259 if ((*len) < sizeof(*in2)) {
1264 memset(in2, 0, sizeof(*in2));
1265 in2->sin_family = AF_INET;
1266 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1267 in2->sin_port = htons(prt);
1269 *len = sizeof(*in2);
1273 case SOCKET_TYPE_CHAR_TCP_V6:
1274 case SOCKET_TYPE_CHAR_UDP_V6: {
1275 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1277 if ((*len) < sizeof(*in2)) {
1282 memset(in2, 0, sizeof(*in2));
1283 in2->sin6_family = AF_INET6;
1284 in2->sin6_addr = *swrap_ipv6();
1285 in2->sin6_addr.s6_addr[15] = iface;
1286 in2->sin6_port = htons(prt);
1288 *len = sizeof(*in2);
1300 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1308 if (bcast) *bcast = 0;
1310 switch (inaddr->sa_family) {
1312 const struct sockaddr_in *in =
1313 (const struct sockaddr_in *)(const void *)inaddr;
1314 unsigned int addr = ntohl(in->sin_addr.s_addr);
1321 u_type = SOCKET_TYPE_CHAR_TCP;
1324 u_type = SOCKET_TYPE_CHAR_UDP;
1325 a_type = SOCKET_TYPE_CHAR_UDP;
1326 b_type = SOCKET_TYPE_CHAR_UDP;
1329 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1330 errno = ESOCKTNOSUPPORT;
1334 prt = ntohs(in->sin_port);
1335 if (a_type && addr == 0xFFFFFFFF) {
1336 /* 255.255.255.255 only udp */
1339 iface = socket_wrapper_default_iface();
1340 } else if (b_type && addr == 0x7FFFFFFF) {
1341 /* 127.255.255.255 only udp */
1344 iface = socket_wrapper_default_iface();
1345 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1349 iface = (addr & 0x000000FF);
1351 errno = ENETUNREACH;
1354 if (bcast) *bcast = is_bcast;
1359 const struct sockaddr_in6 *in =
1360 (const struct sockaddr_in6 *)(const void *)inaddr;
1361 struct in6_addr cmp1, cmp2;
1365 type = SOCKET_TYPE_CHAR_TCP_V6;
1368 type = SOCKET_TYPE_CHAR_UDP_V6;
1371 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1372 errno = ESOCKTNOSUPPORT;
1376 /* XXX no multicast/broadcast */
1378 prt = ntohs(in->sin6_port);
1380 cmp1 = *swrap_ipv6();
1381 cmp2 = in->sin6_addr;
1382 cmp2.s6_addr[15] = 0;
1383 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1384 iface = in->sin6_addr.s6_addr[15];
1386 errno = ENETUNREACH;
1394 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1395 errno = ENETUNREACH;
1400 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1406 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1407 socket_wrapper_dir());
1408 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1409 /* the caller need to do more processing */
1413 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1414 socket_wrapper_dir(), type, iface, prt);
1415 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1420 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1429 if (bcast) *bcast = 0;
1431 switch (si->family) {
1433 const struct sockaddr_in *in =
1434 (const struct sockaddr_in *)(const void *)inaddr;
1435 unsigned int addr = ntohl(in->sin_addr.s_addr);
1441 prt = ntohs(in->sin_port);
1445 u_type = SOCKET_TYPE_CHAR_TCP;
1446 d_type = SOCKET_TYPE_CHAR_TCP;
1449 u_type = SOCKET_TYPE_CHAR_UDP;
1450 d_type = SOCKET_TYPE_CHAR_UDP;
1451 a_type = SOCKET_TYPE_CHAR_UDP;
1452 b_type = SOCKET_TYPE_CHAR_UDP;
1455 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1456 errno = ESOCKTNOSUPPORT;
1464 iface = socket_wrapper_default_iface();
1465 } else if (a_type && addr == 0xFFFFFFFF) {
1466 /* 255.255.255.255 only udp */
1469 iface = socket_wrapper_default_iface();
1470 } else if (b_type && addr == 0x7FFFFFFF) {
1471 /* 127.255.255.255 only udp */
1474 iface = socket_wrapper_default_iface();
1475 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1479 iface = (addr & 0x000000FF);
1481 errno = EADDRNOTAVAIL;
1485 /* Store the bind address for connect() */
1486 if (si->bindname.sa_socklen == 0) {
1487 struct sockaddr_in bind_in;
1488 socklen_t blen = sizeof(struct sockaddr_in);
1490 ZERO_STRUCT(bind_in);
1491 bind_in.sin_family = in->sin_family;
1492 bind_in.sin_port = in->sin_port;
1493 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1495 si->bindname.sa_socklen = blen;
1496 memcpy(&si->bindname.sa.in, &bind_in, blen);
1503 const struct sockaddr_in6 *in =
1504 (const struct sockaddr_in6 *)(const void *)inaddr;
1505 struct in6_addr cmp1, cmp2;
1509 type = SOCKET_TYPE_CHAR_TCP_V6;
1512 type = SOCKET_TYPE_CHAR_UDP_V6;
1515 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1516 errno = ESOCKTNOSUPPORT;
1520 /* XXX no multicast/broadcast */
1522 prt = ntohs(in->sin6_port);
1524 cmp1 = *swrap_ipv6();
1525 cmp2 = in->sin6_addr;
1526 cmp2.s6_addr[15] = 0;
1527 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1528 iface = socket_wrapper_default_iface();
1529 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1530 iface = in->sin6_addr.s6_addr[15];
1532 errno = EADDRNOTAVAIL;
1536 /* Store the bind address for connect() */
1537 if (si->bindname.sa_socklen == 0) {
1538 struct sockaddr_in6 bind_in;
1539 socklen_t blen = sizeof(struct sockaddr_in6);
1541 ZERO_STRUCT(bind_in);
1542 bind_in.sin6_family = in->sin6_family;
1543 bind_in.sin6_port = in->sin6_port;
1545 bind_in.sin6_addr = *swrap_ipv6();
1546 bind_in.sin6_addr.s6_addr[15] = iface;
1548 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1549 si->bindname.sa_socklen = blen;
1556 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1557 errno = EADDRNOTAVAIL;
1562 if (bcast) *bcast = is_bcast;
1564 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1570 /* handle auto-allocation of ephemeral ports */
1571 for (prt = 5001; prt < 10000; prt++) {
1572 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1573 socket_wrapper_dir(), type, iface, prt);
1574 if (stat(un->sun_path, &st) == 0) continue;
1576 set_port(si->family, prt, &si->myname);
1577 set_port(si->family, prt, &si->bindname);
1587 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1588 socket_wrapper_dir(), type, iface, prt);
1589 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1593 static struct socket_info_fd *find_socket_info_fd(int fd)
1595 struct socket_info_fd *f;
1597 for (f = socket_fds; f; f = f->next) {
1606 static int find_socket_info_index(int fd)
1608 struct socket_info_fd *fi = find_socket_info_fd(fd);
1614 return fi->si_index;
1617 static struct socket_info *find_socket_info(int fd)
1619 int idx = find_socket_info_index(fd);
1625 return &sockets[idx];
1629 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1631 struct socket_info_fd *f;
1632 const struct socket_info *last_s = NULL;
1634 /* first catch invalid input */
1635 switch (sa->sa_family) {
1637 if (len < sizeof(struct sockaddr_in)) {
1643 if (len < sizeof(struct sockaddr_in6)) {
1653 for (f = socket_fds; f; f = f->next) {
1654 struct socket_info *s = &sockets[f->si_index];
1661 if (s->myname == NULL) {
1664 if (s->myname->sa_family != sa->sa_family) {
1667 switch (s->myname->sa_family) {
1669 struct sockaddr_in *sin1, *sin2;
1671 sin1 = (struct sockaddr_in *)s->myname;
1672 sin2 = (struct sockaddr_in *)sa;
1674 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1677 if (sin1->sin_port != sin2->sin_port) {
1680 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1690 struct sockaddr_in6 *sin1, *sin2;
1692 sin1 = (struct sockaddr_in6 *)s->myname;
1693 sin2 = (struct sockaddr_in6 *)sa;
1695 if (sin1->sin6_port != sin2->sin6_port) {
1698 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1720 static void swrap_remove_stale(int fd)
1722 struct socket_info_fd *fi = find_socket_info_fd(fd);
1723 struct socket_info *si;
1730 si_index = fi->si_index;
1732 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1733 SWRAP_DLIST_REMOVE(socket_fds, fi);
1736 si = &sockets[fi->si_index];
1739 if (si->refcount > 0) {
1743 if (si->un_addr.sun_path[0] != '\0') {
1744 unlink(si->un_addr.sun_path);
1747 si->next_free = first_free;
1748 first_free = si_index;
1751 static int sockaddr_convert_to_un(struct socket_info *si,
1752 const struct sockaddr *in_addr,
1754 struct sockaddr_un *out_addr,
1758 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1760 (void) in_len; /* unused */
1762 if (out_addr == NULL) {
1766 out->sa_family = AF_UNIX;
1767 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1768 out->sa_len = sizeof(*out_addr);
1771 switch (in_addr->sa_family) {
1773 const struct sockaddr_in *sin;
1774 if (si->family != AF_INET) {
1777 if (in_len < sizeof(struct sockaddr_in)) {
1780 sin = (const struct sockaddr_in *)(const void *)in_addr;
1781 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1786 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1787 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1801 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1802 errno = ESOCKTNOSUPPORT;
1806 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1808 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1814 errno = EAFNOSUPPORT;
1815 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1819 static int sockaddr_convert_from_un(const struct socket_info *si,
1820 const struct sockaddr_un *in_addr,
1821 socklen_t un_addrlen,
1823 struct sockaddr *out_addr,
1824 socklen_t *out_addrlen)
1828 if (out_addr == NULL || out_addrlen == NULL)
1831 if (un_addrlen == 0) {
1846 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1847 errno = ESOCKTNOSUPPORT;
1850 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1851 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1852 out_addr->sa_len = *out_addrlen;
1859 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1860 errno = EAFNOSUPPORT;
1864 enum swrap_packet_type {
1866 SWRAP_CONNECT_UNREACH,
1874 SWRAP_SENDTO_UNREACH,
1885 struct swrap_file_hdr {
1887 uint16_t version_major;
1888 uint16_t version_minor;
1891 uint32_t frame_max_len;
1892 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1895 #define SWRAP_FILE_HDR_SIZE 24
1897 struct swrap_packet_frame {
1899 uint32_t micro_seconds;
1900 uint32_t recorded_length;
1901 uint32_t full_length;
1903 #define SWRAP_PACKET_FRAME_SIZE 16
1905 union swrap_packet_ip {
1909 uint16_t packet_length;
1910 uint16_t identification;
1915 uint16_t hdr_checksum;
1919 #define SWRAP_PACKET_IP_V4_SIZE 20
1922 uint8_t flow_label_high;
1923 uint16_t flow_label_low;
1924 uint16_t payload_length;
1925 uint8_t next_header;
1927 uint8_t src_addr[16];
1928 uint8_t dest_addr[16];
1930 #define SWRAP_PACKET_IP_V6_SIZE 40
1932 #define SWRAP_PACKET_IP_SIZE 40
1934 union swrap_packet_payload {
1936 uint16_t source_port;
1946 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1948 uint16_t source_port;
1953 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1960 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1967 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1969 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1971 #define SWRAP_PACKET_MIN_ALLOC \
1972 (SWRAP_PACKET_FRAME_SIZE + \
1973 SWRAP_PACKET_IP_SIZE + \
1974 SWRAP_PACKET_PAYLOAD_SIZE)
1976 static const char *swrap_pcap_init_file(void)
1978 static int initialized = 0;
1979 static const char *s = NULL;
1980 static const struct swrap_file_hdr h;
1981 static const struct swrap_packet_frame f;
1982 static const union swrap_packet_ip i;
1983 static const union swrap_packet_payload p;
1985 if (initialized == 1) {
1991 * TODO: don't use the structs use plain buffer offsets
1992 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1994 * for now make sure we disable PCAP support
1995 * if the struct has alignment!
1997 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2000 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2003 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2006 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2009 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2012 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2015 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2018 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2021 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2024 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2028 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2032 if (strncmp(s, "./", 2) == 0) {
2038 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2039 const struct sockaddr *src,
2040 const struct sockaddr *dest,
2042 const uint8_t *payload,
2044 unsigned long tcp_seqno,
2045 unsigned long tcp_ack,
2046 unsigned char tcp_ctl,
2048 size_t *_packet_len)
2052 struct swrap_packet_frame *frame;
2053 union swrap_packet_ip *ip;
2054 union swrap_packet_payload *pay;
2057 size_t nonwire_len = sizeof(*frame);
2058 size_t wire_hdr_len = 0;
2059 size_t wire_len = 0;
2060 size_t ip_hdr_len = 0;
2061 size_t icmp_hdr_len = 0;
2062 size_t icmp_truncate_len = 0;
2063 uint8_t protocol = 0, icmp_protocol = 0;
2064 const struct sockaddr_in *src_in = NULL;
2065 const struct sockaddr_in *dest_in = NULL;
2067 const struct sockaddr_in6 *src_in6 = NULL;
2068 const struct sockaddr_in6 *dest_in6 = NULL;
2073 switch (src->sa_family) {
2075 src_in = (const struct sockaddr_in *)(const void *)src;
2076 dest_in = (const struct sockaddr_in *)(const void *)dest;
2077 src_port = src_in->sin_port;
2078 dest_port = dest_in->sin_port;
2079 ip_hdr_len = sizeof(ip->v4);
2083 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2084 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2085 src_port = src_in6->sin6_port;
2086 dest_port = dest_in6->sin6_port;
2087 ip_hdr_len = sizeof(ip->v6);
2094 switch (socket_type) {
2096 protocol = 0x06; /* TCP */
2097 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2098 wire_len = wire_hdr_len + payload_len;
2102 protocol = 0x11; /* UDP */
2103 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2104 wire_len = wire_hdr_len + payload_len;
2112 icmp_protocol = protocol;
2113 switch (src->sa_family) {
2115 protocol = 0x01; /* ICMPv4 */
2116 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2120 protocol = 0x3A; /* ICMPv6 */
2121 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2125 if (wire_len > 64 ) {
2126 icmp_truncate_len = wire_len - 64;
2128 wire_hdr_len += icmp_hdr_len;
2129 wire_len += icmp_hdr_len;
2132 packet_len = nonwire_len + wire_len;
2133 alloc_len = packet_len;
2134 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2135 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2138 base = (uint8_t *)calloc(1, alloc_len);
2145 frame = (struct swrap_packet_frame *)(void *)buf;
2146 frame->seconds = tval->tv_sec;
2147 frame->micro_seconds = tval->tv_usec;
2148 frame->recorded_length = wire_len - icmp_truncate_len;
2149 frame->full_length = wire_len - icmp_truncate_len;
2150 buf += SWRAP_PACKET_FRAME_SIZE;
2152 ip = (union swrap_packet_ip *)(void *)buf;
2153 switch (src->sa_family) {
2155 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2157 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2158 ip->v4.identification = htons(0xFFFF);
2159 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2160 ip->v4.fragment = htons(0x0000);
2162 ip->v4.protocol = protocol;
2163 ip->v4.hdr_checksum = htons(0x0000);
2164 ip->v4.src_addr = src_in->sin_addr.s_addr;
2165 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2166 buf += SWRAP_PACKET_IP_V4_SIZE;
2170 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2171 ip->v6.flow_label_high = 0x00;
2172 ip->v6.flow_label_low = 0x0000;
2173 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2174 ip->v6.next_header = protocol;
2175 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2176 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2177 buf += SWRAP_PACKET_IP_V6_SIZE;
2183 pay = (union swrap_packet_payload *)(void *)buf;
2184 switch (src->sa_family) {
2186 pay->icmp4.type = 0x03; /* destination unreachable */
2187 pay->icmp4.code = 0x01; /* host unreachable */
2188 pay->icmp4.checksum = htons(0x0000);
2189 pay->icmp4.unused = htonl(0x00000000);
2190 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2192 /* set the ip header in the ICMP payload */
2193 ip = (union swrap_packet_ip *)(void *)buf;
2194 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2196 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2197 ip->v4.identification = htons(0xFFFF);
2198 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2199 ip->v4.fragment = htons(0x0000);
2201 ip->v4.protocol = icmp_protocol;
2202 ip->v4.hdr_checksum = htons(0x0000);
2203 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2204 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2205 buf += SWRAP_PACKET_IP_V4_SIZE;
2207 src_port = dest_in->sin_port;
2208 dest_port = src_in->sin_port;
2212 pay->icmp6.type = 0x01; /* destination unreachable */
2213 pay->icmp6.code = 0x03; /* address unreachable */
2214 pay->icmp6.checksum = htons(0x0000);
2215 pay->icmp6.unused = htonl(0x00000000);
2216 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2218 /* set the ip header in the ICMP payload */
2219 ip = (union swrap_packet_ip *)(void *)buf;
2220 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2221 ip->v6.flow_label_high = 0x00;
2222 ip->v6.flow_label_low = 0x0000;
2223 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2224 ip->v6.next_header = protocol;
2225 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2226 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2227 buf += SWRAP_PACKET_IP_V6_SIZE;
2229 src_port = dest_in6->sin6_port;
2230 dest_port = src_in6->sin6_port;
2236 pay = (union swrap_packet_payload *)(void *)buf;
2238 switch (socket_type) {
2240 pay->tcp.source_port = src_port;
2241 pay->tcp.dest_port = dest_port;
2242 pay->tcp.seq_num = htonl(tcp_seqno);
2243 pay->tcp.ack_num = htonl(tcp_ack);
2244 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2245 pay->tcp.control = tcp_ctl;
2246 pay->tcp.window = htons(0x7FFF);
2247 pay->tcp.checksum = htons(0x0000);
2248 pay->tcp.urg = htons(0x0000);
2249 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2254 pay->udp.source_port = src_port;
2255 pay->udp.dest_port = dest_port;
2256 pay->udp.length = htons(8 + payload_len);
2257 pay->udp.checksum = htons(0x0000);
2258 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2263 if (payload && payload_len > 0) {
2264 memcpy(buf, payload, payload_len);
2267 *_packet_len = packet_len - icmp_truncate_len;
2271 static int swrap_pcap_get_fd(const char *fname)
2275 if (fd != -1) return fd;
2277 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2279 struct swrap_file_hdr file_hdr;
2280 file_hdr.magic = 0xA1B2C3D4;
2281 file_hdr.version_major = 0x0002;
2282 file_hdr.version_minor = 0x0004;
2283 file_hdr.timezone = 0x00000000;
2284 file_hdr.sigfigs = 0x00000000;
2285 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2286 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2288 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2295 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2300 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2301 const struct sockaddr *addr,
2302 enum swrap_packet_type type,
2303 const void *buf, size_t len,
2306 const struct sockaddr *src_addr;
2307 const struct sockaddr *dest_addr;
2308 unsigned long tcp_seqno = 0;
2309 unsigned long tcp_ack = 0;
2310 unsigned char tcp_ctl = 0;
2311 int unreachable = 0;
2315 switch (si->family) {
2327 case SWRAP_CONNECT_SEND:
2328 if (si->type != SOCK_STREAM) return NULL;
2330 src_addr = &si->myname.sa.s;
2333 tcp_seqno = si->io.pck_snd;
2334 tcp_ack = si->io.pck_rcv;
2335 tcp_ctl = 0x02; /* SYN */
2337 si->io.pck_snd += 1;
2341 case SWRAP_CONNECT_RECV:
2342 if (si->type != SOCK_STREAM) return NULL;
2344 dest_addr = &si->myname.sa.s;
2347 tcp_seqno = si->io.pck_rcv;
2348 tcp_ack = si->io.pck_snd;
2349 tcp_ctl = 0x12; /** SYN,ACK */
2351 si->io.pck_rcv += 1;
2355 case SWRAP_CONNECT_UNREACH:
2356 if (si->type != SOCK_STREAM) return NULL;
2358 dest_addr = &si->myname.sa.s;
2361 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2362 tcp_seqno = si->io.pck_snd - 1;
2363 tcp_ack = si->io.pck_rcv;
2364 tcp_ctl = 0x02; /* SYN */
2369 case SWRAP_CONNECT_ACK:
2370 if (si->type != SOCK_STREAM) return NULL;
2372 src_addr = &si->myname.sa.s;
2375 tcp_seqno = si->io.pck_snd;
2376 tcp_ack = si->io.pck_rcv;
2377 tcp_ctl = 0x10; /* ACK */
2381 case SWRAP_ACCEPT_SEND:
2382 if (si->type != SOCK_STREAM) return NULL;
2384 dest_addr = &si->myname.sa.s;
2387 tcp_seqno = si->io.pck_rcv;
2388 tcp_ack = si->io.pck_snd;
2389 tcp_ctl = 0x02; /* SYN */
2391 si->io.pck_rcv += 1;
2395 case SWRAP_ACCEPT_RECV:
2396 if (si->type != SOCK_STREAM) return NULL;
2398 src_addr = &si->myname.sa.s;
2401 tcp_seqno = si->io.pck_snd;
2402 tcp_ack = si->io.pck_rcv;
2403 tcp_ctl = 0x12; /* SYN,ACK */
2405 si->io.pck_snd += 1;
2409 case SWRAP_ACCEPT_ACK:
2410 if (si->type != SOCK_STREAM) return NULL;
2412 dest_addr = &si->myname.sa.s;
2415 tcp_seqno = si->io.pck_rcv;
2416 tcp_ack = si->io.pck_snd;
2417 tcp_ctl = 0x10; /* ACK */
2422 src_addr = &si->myname.sa.s;
2423 dest_addr = &si->peername.sa.s;
2425 tcp_seqno = si->io.pck_snd;
2426 tcp_ack = si->io.pck_rcv;
2427 tcp_ctl = 0x18; /* PSH,ACK */
2429 si->io.pck_snd += len;
2433 case SWRAP_SEND_RST:
2434 dest_addr = &si->myname.sa.s;
2435 src_addr = &si->peername.sa.s;
2437 if (si->type == SOCK_DGRAM) {
2438 return swrap_pcap_marshall_packet(si,
2440 SWRAP_SENDTO_UNREACH,
2446 tcp_seqno = si->io.pck_rcv;
2447 tcp_ack = si->io.pck_snd;
2448 tcp_ctl = 0x14; /** RST,ACK */
2452 case SWRAP_PENDING_RST:
2453 dest_addr = &si->myname.sa.s;
2454 src_addr = &si->peername.sa.s;
2456 if (si->type == SOCK_DGRAM) {
2460 tcp_seqno = si->io.pck_rcv;
2461 tcp_ack = si->io.pck_snd;
2462 tcp_ctl = 0x14; /* RST,ACK */
2467 dest_addr = &si->myname.sa.s;
2468 src_addr = &si->peername.sa.s;
2470 tcp_seqno = si->io.pck_rcv;
2471 tcp_ack = si->io.pck_snd;
2472 tcp_ctl = 0x18; /* PSH,ACK */
2474 si->io.pck_rcv += len;
2478 case SWRAP_RECV_RST:
2479 dest_addr = &si->myname.sa.s;
2480 src_addr = &si->peername.sa.s;
2482 if (si->type == SOCK_DGRAM) {
2486 tcp_seqno = si->io.pck_rcv;
2487 tcp_ack = si->io.pck_snd;
2488 tcp_ctl = 0x14; /* RST,ACK */
2493 src_addr = &si->myname.sa.s;
2496 si->io.pck_snd += len;
2500 case SWRAP_SENDTO_UNREACH:
2501 dest_addr = &si->myname.sa.s;
2508 case SWRAP_RECVFROM:
2509 dest_addr = &si->myname.sa.s;
2512 si->io.pck_rcv += len;
2516 case SWRAP_CLOSE_SEND:
2517 if (si->type != SOCK_STREAM) return NULL;
2519 src_addr = &si->myname.sa.s;
2520 dest_addr = &si->peername.sa.s;
2522 tcp_seqno = si->io.pck_snd;
2523 tcp_ack = si->io.pck_rcv;
2524 tcp_ctl = 0x11; /* FIN, ACK */
2526 si->io.pck_snd += 1;
2530 case SWRAP_CLOSE_RECV:
2531 if (si->type != SOCK_STREAM) return NULL;
2533 dest_addr = &si->myname.sa.s;
2534 src_addr = &si->peername.sa.s;
2536 tcp_seqno = si->io.pck_rcv;
2537 tcp_ack = si->io.pck_snd;
2538 tcp_ctl = 0x11; /* FIN,ACK */
2540 si->io.pck_rcv += 1;
2544 case SWRAP_CLOSE_ACK:
2545 if (si->type != SOCK_STREAM) return NULL;
2547 src_addr = &si->myname.sa.s;
2548 dest_addr = &si->peername.sa.s;
2550 tcp_seqno = si->io.pck_snd;
2551 tcp_ack = si->io.pck_rcv;
2552 tcp_ctl = 0x10; /* ACK */
2559 swrapGetTimeOfDay(&tv);
2561 return swrap_pcap_packet_init(&tv,
2565 (const uint8_t *)buf,
2574 static void swrap_pcap_dump_packet(struct socket_info *si,
2575 const struct sockaddr *addr,
2576 enum swrap_packet_type type,
2577 const void *buf, size_t len)
2579 const char *file_name;
2581 size_t packet_len = 0;
2584 file_name = swrap_pcap_init_file();
2589 packet = swrap_pcap_marshall_packet(si,
2595 if (packet == NULL) {
2599 fd = swrap_pcap_get_fd(file_name);
2601 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2610 /****************************************************************************
2612 ***************************************************************************/
2614 #ifdef HAVE_SIGNALFD
2615 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2619 rc = libc_signalfd(fd, mask, flags);
2621 swrap_remove_stale(fd);
2627 int signalfd(int fd, const sigset_t *mask, int flags)
2629 return swrap_signalfd(fd, mask, flags);
2633 /****************************************************************************
2635 ***************************************************************************/
2637 static int swrap_socket(int family, int type, int protocol)
2639 struct socket_info *si;
2640 struct socket_info_fd *fi;
2643 int real_type = type;
2646 * Remove possible addition flags passed to socket() so
2647 * do not fail checking the type.
2648 * See https://lwn.net/Articles/281965/
2651 real_type &= ~SOCK_CLOEXEC;
2653 #ifdef SOCK_NONBLOCK
2654 real_type &= ~SOCK_NONBLOCK;
2657 if (!socket_wrapper_enabled()) {
2658 return libc_socket(family, type, protocol);
2669 #endif /* AF_NETLINK */
2672 #endif /* AF_PACKET */
2674 return libc_socket(family, type, protocol);
2676 errno = EAFNOSUPPORT;
2680 switch (real_type) {
2686 errno = EPROTONOSUPPORT;
2694 if (real_type == SOCK_STREAM) {
2699 if (real_type == SOCK_DGRAM) {
2704 errno = EPROTONOSUPPORT;
2709 * We must call libc_socket with type, from the caller, not the version
2710 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2712 fd = libc_socket(AF_UNIX, type, 0);
2718 /* Check if we have a stale fd and remove it */
2719 swrap_remove_stale(fd);
2721 idx = socket_wrapper_first_free_index();
2729 si->family = family;
2731 /* however, the rest of the socket_wrapper code expects just
2732 * the type, not the flags */
2733 si->type = real_type;
2734 si->protocol = protocol;
2737 * Setup myname so getsockname() can succeed to find out the socket
2740 switch(si->family) {
2742 struct sockaddr_in sin = {
2743 .sin_family = AF_INET,
2746 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2747 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2751 struct sockaddr_in6 sin6 = {
2752 .sin6_family = AF_INET6,
2755 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2756 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2764 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2771 first_free = si->next_free;
2777 SWRAP_DLIST_ADD(socket_fds, fi);
2779 SWRAP_LOG(SWRAP_LOG_TRACE,
2780 "Created %s socket for protocol %s",
2781 si->family == AF_INET ? "IPv4" : "IPv6",
2782 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2787 int socket(int family, int type, int protocol)
2789 return swrap_socket(family, type, protocol);
2792 /****************************************************************************
2794 ***************************************************************************/
2796 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2800 rc = libc_socketpair(family, type, protocol, sv);
2802 swrap_remove_stale(sv[0]);
2803 swrap_remove_stale(sv[1]);
2809 int socketpair(int family, int type, int protocol, int sv[2])
2811 return swrap_socketpair(family, type, protocol, sv);
2814 /****************************************************************************
2816 ***************************************************************************/
2818 #ifdef HAVE_TIMERFD_CREATE
2819 static int swrap_timerfd_create(int clockid, int flags)
2823 fd = libc_timerfd_create(clockid, flags);
2825 swrap_remove_stale(fd);
2831 int timerfd_create(int clockid, int flags)
2833 return swrap_timerfd_create(clockid, flags);
2837 /****************************************************************************
2839 ***************************************************************************/
2841 static int swrap_pipe(int pipefd[2])
2845 rc = libc_pipe(pipefd);
2847 swrap_remove_stale(pipefd[0]);
2848 swrap_remove_stale(pipefd[1]);
2854 int pipe(int pipefd[2])
2856 return swrap_pipe(pipefd);
2859 /****************************************************************************
2861 ***************************************************************************/
2863 static int swrap_accept(int s,
2864 struct sockaddr *addr,
2868 struct socket_info *parent_si, *child_si;
2869 struct socket_info_fd *child_fi;
2872 struct swrap_address un_addr = {
2873 .sa_socklen = sizeof(struct sockaddr_un),
2875 struct swrap_address un_my_addr = {
2876 .sa_socklen = sizeof(struct sockaddr_un),
2878 struct swrap_address in_addr = {
2879 .sa_socklen = sizeof(struct sockaddr_storage),
2881 struct swrap_address in_my_addr = {
2882 .sa_socklen = sizeof(struct sockaddr_storage),
2886 parent_si = find_socket_info(s);
2889 return libc_accept4(s, addr, addrlen, flags);
2892 return libc_accept(s, addr, addrlen);
2897 * assume out sockaddr have the same size as the in parent
2900 in_addr.sa_socklen = socket_length(parent_si->family);
2901 if (in_addr.sa_socklen <= 0) {
2907 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2910 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2913 if (errno == ENOTSOCK) {
2914 /* Remove stale fds */
2915 swrap_remove_stale(s);
2922 ret = sockaddr_convert_from_un(parent_si,
2927 &in_addr.sa_socklen);
2933 idx = socket_wrapper_first_free_index();
2939 child_si = &sockets[idx];
2941 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2942 if (child_fi == NULL) {
2950 child_si->family = parent_si->family;
2951 child_si->type = parent_si->type;
2952 child_si->protocol = parent_si->protocol;
2953 child_si->bound = 1;
2954 child_si->is_server = 1;
2955 child_si->connected = 1;
2957 child_si->peername = (struct swrap_address) {
2958 .sa_socklen = in_addr.sa_socklen,
2960 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2962 if (addr != NULL && addrlen != NULL) {
2963 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2965 memcpy(addr, &in_addr.sa.ss, copy_len);
2967 *addrlen = in_addr.sa_socklen;
2970 ret = libc_getsockname(fd,
2972 &un_my_addr.sa_socklen);
2979 ret = sockaddr_convert_from_un(child_si,
2981 un_my_addr.sa_socklen,
2984 &in_my_addr.sa_socklen);
2991 SWRAP_LOG(SWRAP_LOG_TRACE,
2992 "accept() path=%s, fd=%d",
2993 un_my_addr.sa.un.sun_path, s);
2995 child_si->myname = (struct swrap_address) {
2996 .sa_socklen = in_my_addr.sa_socklen,
2998 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3000 child_si->refcount = 1;
3001 first_free = child_si->next_free;
3002 child_si->next_free = 0;
3004 child_fi->si_index = idx;
3006 SWRAP_DLIST_ADD(socket_fds, child_fi);
3009 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3010 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3011 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3018 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3020 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3024 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3025 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3027 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3030 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3033 static int autobind_start_init;
3034 static int autobind_start;
3036 /* using sendto() or connect() on an unbound socket would give the
3037 recipient no way to reply, as unlike UDP and TCP, a unix domain
3038 socket can't auto-assign ephemeral port numbers, so we need to
3040 Note: this might change the family from ipv6 to ipv4
3042 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3044 struct swrap_address un_addr = {
3045 .sa_socklen = sizeof(struct sockaddr_un),
3053 if (autobind_start_init != 1) {
3054 autobind_start_init = 1;
3055 autobind_start = getpid();
3056 autobind_start %= 50000;
3057 autobind_start += 10000;
3060 un_addr.sa.un.sun_family = AF_UNIX;
3064 struct sockaddr_in in;
3068 type = SOCKET_TYPE_CHAR_TCP;
3071 type = SOCKET_TYPE_CHAR_UDP;
3074 errno = ESOCKTNOSUPPORT;
3078 memset(&in, 0, sizeof(in));
3079 in.sin_family = AF_INET;
3080 in.sin_addr.s_addr = htonl(127<<24 |
3081 socket_wrapper_default_iface());
3083 si->myname = (struct swrap_address) {
3084 .sa_socklen = sizeof(in),
3086 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3091 struct sockaddr_in6 in6;
3093 if (si->family != family) {
3094 errno = ENETUNREACH;
3100 type = SOCKET_TYPE_CHAR_TCP_V6;
3103 type = SOCKET_TYPE_CHAR_UDP_V6;
3106 errno = ESOCKTNOSUPPORT;
3110 memset(&in6, 0, sizeof(in6));
3111 in6.sin6_family = AF_INET6;
3112 in6.sin6_addr = *swrap_ipv6();
3113 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3115 si->myname = (struct swrap_address) {
3116 .sa_socklen = sizeof(in6),
3118 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3123 errno = ESOCKTNOSUPPORT;
3127 if (autobind_start > 60000) {
3128 autobind_start = 10000;
3131 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3132 port = autobind_start + i;
3133 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3134 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3135 type, socket_wrapper_default_iface(), port);
3136 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3138 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3139 if (ret == -1) return ret;
3141 si->un_addr = un_addr.sa.un;
3144 autobind_start = port + 1;
3147 if (i == SOCKET_MAX_SOCKETS) {
3148 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3149 "interface "SOCKET_FORMAT,
3152 socket_wrapper_default_iface(),
3158 si->family = family;
3159 set_port(si->family, port, &si->myname);
3164 /****************************************************************************
3166 ***************************************************************************/
3168 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3172 struct swrap_address un_addr = {
3173 .sa_socklen = sizeof(struct sockaddr_un),
3175 struct socket_info *si = find_socket_info(s);
3179 return libc_connect(s, serv_addr, addrlen);
3182 if (si->bound == 0) {
3183 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3184 if (ret == -1) return -1;
3187 if (si->family != serv_addr->sa_family) {
3192 ret = sockaddr_convert_to_un(si, serv_addr,
3193 addrlen, &un_addr.sa.un, 0, &bcast);
3194 if (ret == -1) return -1;
3197 errno = ENETUNREACH;
3201 if (si->type == SOCK_DGRAM) {
3202 si->defer_connect = 1;
3205 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3207 ret = libc_connect(s,
3209 un_addr.sa_socklen);
3212 SWRAP_LOG(SWRAP_LOG_TRACE,
3213 "connect() path=%s, fd=%d",
3214 un_addr.sa.un.sun_path, s);
3217 /* to give better errors */
3218 if (ret == -1 && errno == ENOENT) {
3219 errno = EHOSTUNREACH;
3223 si->peername = (struct swrap_address) {
3224 .sa_socklen = addrlen,
3227 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3231 * When we connect() on a socket than we have to bind the
3232 * outgoing connection on the interface we use for the
3233 * transport. We already bound it on the right interface
3234 * but here we have to update the name so getsockname()
3235 * returns correct information.
3237 if (si->bindname.sa_socklen > 0) {
3238 si->myname = (struct swrap_address) {
3239 .sa_socklen = si->bindname.sa_socklen,
3242 memcpy(&si->myname.sa.ss,
3243 &si->bindname.sa.ss,
3244 si->bindname.sa_socklen);
3246 /* Cleanup bindname */
3247 si->bindname = (struct swrap_address) {
3252 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3253 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3255 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3261 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3263 return swrap_connect(s, serv_addr, addrlen);
3266 /****************************************************************************
3268 ***************************************************************************/
3270 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3273 struct swrap_address un_addr = {
3274 .sa_socklen = sizeof(struct sockaddr_un),
3276 struct socket_info *si = find_socket_info(s);
3283 return libc_bind(s, myaddr, addrlen);
3286 switch (si->family) {
3288 const struct sockaddr_in *sin;
3289 if (addrlen < sizeof(struct sockaddr_in)) {
3290 bind_error = EINVAL;
3294 sin = (const struct sockaddr_in *)(const void *)myaddr;
3296 if (sin->sin_family != AF_INET) {
3297 bind_error = EAFNOSUPPORT;
3300 /* special case for AF_UNSPEC */
3301 if (sin->sin_family == AF_UNSPEC &&
3302 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3311 const struct sockaddr_in6 *sin6;
3312 if (addrlen < sizeof(struct sockaddr_in6)) {
3313 bind_error = EINVAL;
3317 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3319 if (sin6->sin6_family != AF_INET6) {
3320 bind_error = EAFNOSUPPORT;
3327 bind_error = EINVAL;
3331 if (bind_error != 0) {
3337 in_use = check_addr_port_in_use(myaddr, addrlen);
3344 si->myname.sa_socklen = addrlen;
3345 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3347 ret = sockaddr_convert_to_un(si,
3353 if (ret == -1) return -1;
3355 unlink(un_addr.sa.un.sun_path);
3357 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3359 SWRAP_LOG(SWRAP_LOG_TRACE,
3360 "bind() path=%s, fd=%d",
3361 un_addr.sa.un.sun_path, s);
3370 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3372 return swrap_bind(s, myaddr, addrlen);
3375 /****************************************************************************
3377 ***************************************************************************/
3379 #ifdef HAVE_BINDRESVPORT
3380 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3382 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3384 struct swrap_address myaddr = {
3385 .sa_socklen = sizeof(struct sockaddr_storage),
3388 static uint16_t port;
3393 #define SWRAP_STARTPORT 600
3394 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3395 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3398 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3402 salen = myaddr.sa_socklen;
3405 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3411 memset(&myaddr.sa.ss, 0, salen);
3416 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3419 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3421 salen = sizeof(struct sockaddr_in);
3422 sinp->sin_port = htons(port);
3426 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3428 salen = sizeof(struct sockaddr_in6);
3429 sin6p->sin6_port = htons(port);
3433 errno = EAFNOSUPPORT;
3438 if (port > SWRAP_ENDPORT) {
3439 port = SWRAP_STARTPORT;
3442 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3443 if (rc == 0 || errno != EADDRINUSE) {
3451 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3453 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3457 /****************************************************************************
3459 ***************************************************************************/
3461 static int swrap_listen(int s, int backlog)
3464 struct socket_info *si = find_socket_info(s);
3467 return libc_listen(s, backlog);
3470 if (si->bound == 0) {
3471 ret = swrap_auto_bind(s, si, si->family);
3478 ret = libc_listen(s, backlog);
3483 int listen(int s, int backlog)
3485 return swrap_listen(s, backlog);
3488 /****************************************************************************
3490 ***************************************************************************/
3492 static FILE *swrap_fopen(const char *name, const char *mode)
3496 fp = libc_fopen(name, mode);
3498 int fd = fileno(fp);
3500 swrap_remove_stale(fd);
3506 FILE *fopen(const char *name, const char *mode)
3508 return swrap_fopen(name, mode);
3511 /****************************************************************************
3513 ***************************************************************************/
3515 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3519 ret = libc_vopen(pathname, flags, ap);
3522 * There are methods for closing descriptors (libc-internal code
3523 * paths, direct syscalls) which close descriptors in ways that
3524 * we can't intercept, so try to recover when we notice that
3527 swrap_remove_stale(ret);
3532 int open(const char *pathname, int flags, ...)
3537 va_start(ap, flags);
3538 fd = swrap_vopen(pathname, flags, ap);
3544 /****************************************************************************
3546 ***************************************************************************/
3548 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3550 struct socket_info *si = find_socket_info(s);
3554 return libc_getpeername(s, name, addrlen);
3557 if (si->peername.sa_socklen == 0)
3563 len = MIN(*addrlen, si->peername.sa_socklen);
3568 memcpy(name, &si->peername.sa.ss, len);
3569 *addrlen = si->peername.sa_socklen;
3574 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3575 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3577 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3580 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3583 /****************************************************************************
3585 ***************************************************************************/
3587 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3589 struct socket_info *si = find_socket_info(s);
3593 return libc_getsockname(s, name, addrlen);
3596 len = MIN(*addrlen, si->myname.sa_socklen);
3601 memcpy(name, &si->myname.sa.ss, len);
3602 *addrlen = si->myname.sa_socklen;
3607 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3608 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3610 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3613 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3616 /****************************************************************************
3618 ***************************************************************************/
3621 # ifdef SO_PROTOTYPE /* The Solaris name */
3622 # define SO_PROTOCOL SO_PROTOTYPE
3623 # endif /* SO_PROTOTYPE */
3624 #endif /* SO_PROTOCOL */
3626 static int swrap_getsockopt(int s, int level, int optname,
3627 void *optval, socklen_t *optlen)
3629 struct socket_info *si = find_socket_info(s);
3632 return libc_getsockopt(s,
3639 if (level == SOL_SOCKET) {
3643 if (optval == NULL || optlen == NULL ||
3644 *optlen < (socklen_t)sizeof(int)) {
3649 *optlen = sizeof(int);
3650 *(int *)optval = si->family;
3652 #endif /* SO_DOMAIN */
3656 if (optval == NULL || optlen == NULL ||
3657 *optlen < (socklen_t)sizeof(int)) {
3662 *optlen = sizeof(int);
3663 *(int *)optval = si->protocol;
3665 #endif /* SO_PROTOCOL */
3667 if (optval == NULL || optlen == NULL ||
3668 *optlen < (socklen_t)sizeof(int)) {
3673 *optlen = sizeof(int);
3674 *(int *)optval = si->type;
3677 return libc_getsockopt(s,
3683 } else if (level == IPPROTO_TCP) {
3688 * This enables sending packets directly out over TCP.
3689 * As a unix socket is doing that any way, report it as
3692 if (optval == NULL || optlen == NULL ||
3693 *optlen < (socklen_t)sizeof(int)) {
3698 *optlen = sizeof(int);
3699 *(int *)optval = si->tcp_nodelay;
3702 #endif /* TCP_NODELAY */
3708 errno = ENOPROTOOPT;
3712 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3713 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3715 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3718 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3721 /****************************************************************************
3723 ***************************************************************************/
3725 static int swrap_setsockopt(int s, int level, int optname,
3726 const void *optval, socklen_t optlen)
3728 struct socket_info *si = find_socket_info(s);
3731 return libc_setsockopt(s,
3738 if (level == SOL_SOCKET) {
3739 return libc_setsockopt(s,
3744 } else if (level == IPPROTO_TCP) {
3751 * This enables sending packets directly out over TCP.
3752 * A unix socket is doing that any way.
3754 if (optval == NULL || optlen == 0 ||
3755 optlen < (socklen_t)sizeof(int)) {
3760 i = *discard_const_p(int, optval);
3761 if (i != 0 && i != 1) {
3765 si->tcp_nodelay = i;
3769 #endif /* TCP_NODELAY */
3775 switch (si->family) {
3777 if (level == IPPROTO_IP) {
3779 if (optname == IP_PKTINFO) {
3780 si->pktinfo = AF_INET;
3782 #endif /* IP_PKTINFO */
3787 if (level == IPPROTO_IPV6) {
3788 #ifdef IPV6_RECVPKTINFO
3789 if (optname == IPV6_RECVPKTINFO) {
3790 si->pktinfo = AF_INET6;
3792 #endif /* IPV6_PKTINFO */
3797 errno = ENOPROTOOPT;
3802 int setsockopt(int s, int level, int optname,
3803 const void *optval, socklen_t optlen)
3805 return swrap_setsockopt(s, level, optname, optval, optlen);
3808 /****************************************************************************
3810 ***************************************************************************/
3812 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3814 struct socket_info *si = find_socket_info(s);
3820 return libc_vioctl(s, r, va);
3825 rc = libc_vioctl(s, r, va);
3829 value = *((int *)va_arg(ap, int *));
3831 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3832 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3833 } else if (value == 0) { /* END OF FILE */
3834 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3844 #ifdef HAVE_IOCTL_INT
3845 int ioctl(int s, int r, ...)
3847 int ioctl(int s, unsigned long int r, ...)
3855 rc = swrap_vioctl(s, (unsigned long int) r, va);
3866 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3869 # ifdef _ALIGN /* BSD */
3870 #define CMSG_ALIGN _ALIGN
3872 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3873 # endif /* _ALIGN */
3874 #endif /* CMSG_ALIGN */
3877 * @brief Add a cmsghdr to a msghdr.
3879 * This is an function to add any type of cmsghdr. It will operate on the
3880 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3881 * the buffer position after the added cmsg element. Hence, this function is
3882 * intended to be used with an intermediate msghdr and not on the original
3883 * one handed in by the client.
3885 * @param[in] msg The msghdr to which to add the cmsg.
3887 * @param[in] level The cmsg level to set.
3889 * @param[in] type The cmsg type to set.
3891 * @param[in] data The cmsg data to set.
3893 * @param[in] len the length of the data to set.
3895 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3901 size_t cmlen = CMSG_LEN(len);
3902 size_t cmspace = CMSG_SPACE(len);
3903 uint8_t cmbuf[cmspace];
3904 void *cast_ptr = (void *)cmbuf;
3905 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3908 memset(cmbuf, 0, cmspace);
3910 if (msg->msg_controllen < cmlen) {
3911 cmlen = msg->msg_controllen;
3912 msg->msg_flags |= MSG_CTRUNC;
3915 if (msg->msg_controllen < cmspace) {
3916 cmspace = msg->msg_controllen;
3920 * We copy the full input data into an intermediate cmsghdr first
3921 * in order to more easily cope with truncation.
3923 cm->cmsg_len = cmlen;
3924 cm->cmsg_level = level;
3925 cm->cmsg_type = type;
3926 memcpy(CMSG_DATA(cm), data, len);
3929 * We now copy the possibly truncated buffer.
3930 * We copy cmlen bytes, but consume cmspace bytes,
3931 * leaving the possible padding uninitialiazed.
3933 p = (uint8_t *)msg->msg_control;
3934 memcpy(p, cm, cmlen);
3936 msg->msg_control = p;
3937 msg->msg_controllen -= cmspace;
3942 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3945 /* Add packet info */
3946 switch (si->pktinfo) {
3947 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3949 struct sockaddr_in *sin;
3950 #if defined(HAVE_STRUCT_IN_PKTINFO)
3951 struct in_pktinfo pkt;
3952 #elif defined(IP_RECVDSTADDR)
3956 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3957 sin = &si->bindname.sa.in;
3959 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3962 sin = &si->myname.sa.in;
3967 #if defined(HAVE_STRUCT_IN_PKTINFO)
3968 pkt.ipi_ifindex = socket_wrapper_default_iface();
3969 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3970 #elif defined(IP_RECVDSTADDR)
3971 pkt = sin->sin_addr;
3974 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3979 #endif /* IP_PKTINFO */
3980 #if defined(HAVE_IPV6)
3982 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3983 struct sockaddr_in6 *sin6;
3984 struct in6_pktinfo pkt6;
3986 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3987 sin6 = &si->bindname.sa.in6;
3989 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3992 sin6 = &si->myname.sa.in6;
3997 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3998 pkt6.ipi6_addr = sin6->sin6_addr;
4000 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4001 &pkt6, sizeof(pkt6));
4002 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4006 #endif /* IPV6_PKTINFO */
4014 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4015 struct msghdr *omsg)
4019 if (si->pktinfo > 0) {
4020 rc = swrap_msghdr_add_pktinfo(si, omsg);
4026 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4028 size_t *cm_data_space);
4029 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4031 size_t *cm_data_space);
4033 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4035 size_t *cm_data_space) {
4036 struct cmsghdr *cmsg;
4040 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4044 for (cmsg = CMSG_FIRSTHDR(msg);
4046 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4047 switch (cmsg->cmsg_level) {
4049 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4054 rc = swrap_sendmsg_copy_cmsg(cmsg,
4064 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4066 size_t *cm_data_space)
4071 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4073 p = realloc((*cm_data), cmspace);
4079 p = (*cm_data) + (*cm_data_space);
4080 *cm_data_space = cmspace;
4082 memcpy(p, cmsg, cmsg->cmsg_len);
4087 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4089 size_t *cm_data_space);
4092 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4094 size_t *cm_data_space)
4098 switch(cmsg->cmsg_type) {
4101 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4108 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4120 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4122 size_t *cm_data_space)
4124 (void)cmsg; /* unused */
4125 (void)cm_data; /* unused */
4126 (void)cm_data_space; /* unused */
4129 * Passing a IP pktinfo to a unix socket might be rejected by the
4130 * Kernel, at least on FreeBSD. So skip this cmsg.
4134 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4136 static ssize_t swrap_sendmsg_before(int fd,
4137 struct socket_info *si,
4139 struct iovec *tmp_iov,
4140 struct sockaddr_un *tmp_un,
4141 const struct sockaddr_un **to_un,
4142 const struct sockaddr **to,
4162 if (!si->connected) {
4167 if (msg->msg_iovlen == 0) {
4171 mtu = socket_wrapper_mtu();
4172 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4174 nlen = len + msg->msg_iov[i].iov_len;
4179 msg->msg_iovlen = i;
4180 if (msg->msg_iovlen == 0) {
4181 *tmp_iov = msg->msg_iov[0];
4182 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4184 msg->msg_iov = tmp_iov;
4185 msg->msg_iovlen = 1;
4190 if (si->connected) {
4191 if (msg->msg_name != NULL) {
4193 * We are dealing with unix sockets and if we
4194 * are connected, we should only talk to the
4195 * connected unix path. Using the fd to send
4196 * to another server would be hard to achieve.
4198 msg->msg_name = NULL;
4199 msg->msg_namelen = 0;
4202 const struct sockaddr *msg_name;
4203 msg_name = (const struct sockaddr *)msg->msg_name;
4205 if (msg_name == NULL) {
4211 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4213 if (ret == -1) return -1;
4221 msg->msg_name = tmp_un;
4222 msg->msg_namelen = sizeof(*tmp_un);
4225 if (si->bound == 0) {
4226 ret = swrap_auto_bind(fd, si, si->family);
4228 if (errno == ENOTSOCK) {
4229 swrap_remove_stale(fd);
4232 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4238 if (!si->defer_connect) {
4242 ret = sockaddr_convert_to_un(si,
4244 si->peername.sa_socklen,
4248 if (ret == -1) return -1;
4250 ret = libc_connect(fd,
4251 (struct sockaddr *)(void *)tmp_un,
4254 /* to give better errors */
4255 if (ret == -1 && errno == ENOENT) {
4256 errno = EHOSTUNREACH;
4263 si->defer_connect = 0;
4266 errno = EHOSTUNREACH;
4270 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4271 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4272 uint8_t *cmbuf = NULL;
4275 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4282 msg->msg_controllen = 0;
4283 msg->msg_control = NULL;
4284 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4285 memcpy(msg->msg_control, cmbuf, cmlen);
4286 msg->msg_controllen = cmlen;
4295 static void swrap_sendmsg_after(int fd,
4296 struct socket_info *si,
4298 const struct sockaddr *to,
4301 int saved_errno = errno;
4308 /* to give better errors */
4310 if (saved_errno == ENOENT) {
4311 saved_errno = EHOSTUNREACH;
4312 } else if (saved_errno == ENOTSOCK) {
4313 /* If the fd is not a socket, remove it */
4314 swrap_remove_stale(fd);
4318 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4319 avail += msg->msg_iov[i].iov_len;
4323 remain = MIN(80, avail);
4328 /* we capture it as one single packet */
4329 buf = (uint8_t *)malloc(remain);
4331 /* we just not capture the packet */
4332 errno = saved_errno;
4336 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4337 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4339 msg->msg_iov[i].iov_base,
4342 remain -= this_time;
4349 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4350 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4352 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4357 if (si->connected) {
4358 to = &si->peername.sa.s;
4361 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4362 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4364 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4370 errno = saved_errno;
4373 static int swrap_recvmsg_before(int fd,
4374 struct socket_info *si,
4376 struct iovec *tmp_iov)
4381 (void)fd; /* unused */
4386 if (!si->connected) {
4391 if (msg->msg_iovlen == 0) {
4395 mtu = socket_wrapper_mtu();
4396 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4398 nlen = len + msg->msg_iov[i].iov_len;
4403 msg->msg_iovlen = i;
4404 if (msg->msg_iovlen == 0) {
4405 *tmp_iov = msg->msg_iov[0];
4406 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4408 msg->msg_iov = tmp_iov;
4409 msg->msg_iovlen = 1;
4414 if (msg->msg_name == NULL) {
4419 if (msg->msg_iovlen == 0) {
4423 if (si->bound == 0) {
4424 ret = swrap_auto_bind(fd, si, si->family);
4427 * When attempting to read or write to a
4428 * descriptor, if an underlying autobind fails
4429 * because it's not a socket, stop intercepting
4430 * uses of that descriptor.
4432 if (errno == ENOTSOCK) {
4433 swrap_remove_stale(fd);
4436 SWRAP_LOG(SWRAP_LOG_ERROR,
4437 "swrap_recvmsg_before failed");
4444 errno = EHOSTUNREACH;
4451 static int swrap_recvmsg_after(int fd,
4452 struct socket_info *si,
4454 const struct sockaddr_un *un_addr,
4455 socklen_t un_addrlen,
4458 int saved_errno = errno;
4460 uint8_t *buf = NULL;
4466 /* to give better errors */
4468 if (saved_errno == ENOENT) {
4469 saved_errno = EHOSTUNREACH;
4470 } else if (saved_errno == ENOTSOCK) {
4471 /* If the fd is not a socket, remove it */
4472 swrap_remove_stale(fd);
4476 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4477 avail += msg->msg_iov[i].iov_len;
4480 /* Convert the socket address before we leave */
4481 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4482 rc = sockaddr_convert_from_un(si,
4499 remain = MIN(80, avail);
4504 /* we capture it as one single packet */
4505 buf = (uint8_t *)malloc(remain);
4507 /* we just not capture the packet */
4508 errno = saved_errno;
4512 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4513 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4515 msg->msg_iov[i].iov_base,
4518 remain -= this_time;
4523 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4524 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4525 } else if (ret == 0) { /* END OF FILE */
4526 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4527 } else if (ret > 0) {
4528 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4537 if (un_addr != NULL) {
4538 swrap_pcap_dump_packet(si,
4544 swrap_pcap_dump_packet(si,
4557 errno = saved_errno;
4559 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4561 msg->msg_controllen > 0 &&
4562 msg->msg_control != NULL) {
4563 rc = swrap_msghdr_add_socket_info(si, msg);
4573 /****************************************************************************
4575 ***************************************************************************/
4577 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4578 struct sockaddr *from, socklen_t *fromlen)
4580 struct swrap_address from_addr = {
4581 .sa_socklen = sizeof(struct sockaddr_un),
4584 struct socket_info *si = find_socket_info(s);
4585 struct swrap_address saddr = {
4586 .sa_socklen = sizeof(struct sockaddr_storage),
4593 return libc_recvfrom(s,
4605 if (from != NULL && fromlen != NULL) {
4606 msg.msg_name = from; /* optional address */
4607 msg.msg_namelen = *fromlen; /* size of address */
4609 msg.msg_name = &saddr.sa.s; /* optional address */
4610 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4612 msg.msg_iov = &tmp; /* scatter/gather array */
4613 msg.msg_iovlen = 1; /* # elements in msg_iov */
4614 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4615 msg.msg_control = NULL; /* ancillary data, see below */
4616 msg.msg_controllen = 0; /* ancillary data buffer len */
4617 msg.msg_flags = 0; /* flags on received message */
4620 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4625 buf = msg.msg_iov[0].iov_base;
4626 len = msg.msg_iov[0].iov_len;
4628 ret = libc_recvfrom(s,
4633 &from_addr.sa_socklen);
4638 tret = swrap_recvmsg_after(s,
4642 from_addr.sa_socklen,
4648 if (from != NULL && fromlen != NULL) {
4649 *fromlen = msg.msg_namelen;
4655 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4656 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4657 struct sockaddr *from, Psocklen_t fromlen)
4659 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4660 struct sockaddr *from, socklen_t *fromlen)
4663 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4666 /****************************************************************************
4668 ***************************************************************************/
4670 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4671 const struct sockaddr *to, socklen_t tolen)
4675 struct swrap_address un_addr = {
4676 .sa_socklen = sizeof(struct sockaddr_un),
4678 const struct sockaddr_un *to_un = NULL;
4681 struct socket_info *si = find_socket_info(s);
4685 return libc_sendto(s, buf, len, flags, to, tolen);
4688 tmp.iov_base = discard_const_p(char, buf);
4692 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4693 msg.msg_namelen = tolen; /* size of address */
4694 msg.msg_iov = &tmp; /* scatter/gather array */
4695 msg.msg_iovlen = 1; /* # elements in msg_iov */
4696 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4697 msg.msg_control = NULL; /* ancillary data, see below */
4698 msg.msg_controllen = 0; /* ancillary data buffer len */
4699 msg.msg_flags = 0; /* flags on received message */
4702 rc = swrap_sendmsg_before(s,
4714 buf = msg.msg_iov[0].iov_base;
4715 len = msg.msg_iov[0].iov_len;
4720 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4723 type = SOCKET_TYPE_CHAR_UDP;
4725 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4726 snprintf(un_addr.sa.un.sun_path,
4727 sizeof(un_addr.sa.un.sun_path),
4729 socket_wrapper_dir(), type, iface, prt);
4730 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4732 /* ignore the any errors in broadcast sends */
4738 un_addr.sa_socklen);
4741 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4747 * If it is a dgram socket and we are connected, don't include the
4750 if (si->type == SOCK_DGRAM && si->connected) {
4751 ret = libc_sendto(s,
4758 ret = libc_sendto(s,
4762 (struct sockaddr *)msg.msg_name,
4766 swrap_sendmsg_after(s, si, &msg, to, ret);
4771 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4772 const struct sockaddr *to, socklen_t tolen)
4774 return swrap_sendto(s, buf, len, flags, to, tolen);
4777 /****************************************************************************
4779 ***************************************************************************/
4781 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4783 struct socket_info *si;
4785 struct swrap_address saddr = {
4786 .sa_socklen = sizeof(struct sockaddr_storage),
4792 si = find_socket_info(s);
4794 return libc_recv(s, buf, len, flags);
4801 msg.msg_name = &saddr.sa.s; /* optional address */
4802 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4803 msg.msg_iov = &tmp; /* scatter/gather array */
4804 msg.msg_iovlen = 1; /* # elements in msg_iov */
4805 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4806 msg.msg_control = NULL; /* ancillary data, see below */
4807 msg.msg_controllen = 0; /* ancillary data buffer len */
4808 msg.msg_flags = 0; /* flags on received message */
4811 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4816 buf = msg.msg_iov[0].iov_base;
4817 len = msg.msg_iov[0].iov_len;
4819 ret = libc_recv(s, buf, len, flags);
4821 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4829 ssize_t recv(int s, void *buf, size_t len, int flags)
4831 return swrap_recv(s, buf, len, flags);
4834 /****************************************************************************
4836 ***************************************************************************/
4838 static ssize_t swrap_read(int s, void *buf, size_t len)
4840 struct socket_info *si;
4843 struct swrap_address saddr = {
4844 .sa_socklen = sizeof(struct sockaddr_storage),
4849 si = find_socket_info(s);
4851 return libc_read(s, buf, len);
4858 msg.msg_name = &saddr.sa.ss; /* optional address */
4859 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4860 msg.msg_iov = &tmp; /* scatter/gather array */
4861 msg.msg_iovlen = 1; /* # elements in msg_iov */
4862 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4863 msg.msg_control = NULL; /* ancillary data, see below */
4864 msg.msg_controllen = 0; /* ancillary data buffer len */
4865 msg.msg_flags = 0; /* flags on received message */
4868 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4870 if (tret == -ENOTSOCK) {
4871 return libc_read(s, buf, len);
4876 buf = msg.msg_iov[0].iov_base;
4877 len = msg.msg_iov[0].iov_len;
4879 ret = libc_read(s, buf, len);
4881 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4889 ssize_t read(int s, void *buf, size_t len)
4891 return swrap_read(s, buf, len);
4894 /****************************************************************************
4896 ***************************************************************************/
4898 static ssize_t swrap_write(int s, const void *buf, size_t len)
4902 struct sockaddr_un un_addr;
4905 struct socket_info *si;
4907 si = find_socket_info(s);
4909 return libc_write(s, buf, len);
4912 tmp.iov_base = discard_const_p(char, buf);
4916 msg.msg_name = NULL; /* optional address */
4917 msg.msg_namelen = 0; /* size of address */
4918 msg.msg_iov = &tmp; /* scatter/gather array */
4919 msg.msg_iovlen = 1; /* # elements in msg_iov */
4920 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4921 msg.msg_control = NULL; /* ancillary data, see below */
4922 msg.msg_controllen = 0; /* ancillary data buffer len */
4923 msg.msg_flags = 0; /* flags on received message */
4926 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4931 buf = msg.msg_iov[0].iov_base;
4932 len = msg.msg_iov[0].iov_len;
4934 ret = libc_write(s, buf, len);
4936 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4941 ssize_t write(int s, const void *buf, size_t len)
4943 return swrap_write(s, buf, len);
4946 /****************************************************************************
4948 ***************************************************************************/
4950 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4954 struct sockaddr_un un_addr;
4957 struct socket_info *si = find_socket_info(s);
4960 return libc_send(s, buf, len, flags);
4963 tmp.iov_base = discard_const_p(char, buf);
4967 msg.msg_name = NULL; /* optional address */
4968 msg.msg_namelen = 0; /* size of address */
4969 msg.msg_iov = &tmp; /* scatter/gather array */
4970 msg.msg_iovlen = 1; /* # elements in msg_iov */
4971 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4972 msg.msg_control = NULL; /* ancillary data, see below */
4973 msg.msg_controllen = 0; /* ancillary data buffer len */
4974 msg.msg_flags = 0; /* flags on received message */
4977 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4982 buf = msg.msg_iov[0].iov_base;
4983 len = msg.msg_iov[0].iov_len;
4985 ret = libc_send(s, buf, len, flags);
4987 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4992 ssize_t send(int s, const void *buf, size_t len, int flags)
4994 return swrap_send(s, buf, len, flags);
4997 /****************************************************************************
4999 ***************************************************************************/
5001 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5003 struct swrap_address from_addr = {
5004 .sa_socklen = sizeof(struct sockaddr_un),
5006 struct swrap_address convert_addr = {
5007 .sa_socklen = sizeof(struct sockaddr_storage),
5009 struct socket_info *si;
5012 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5013 size_t msg_ctrllen_filled;
5014 size_t msg_ctrllen_left;
5020 si = find_socket_info(s);
5022 return libc_recvmsg(s, omsg, flags);
5025 tmp.iov_base = NULL;
5029 msg.msg_name = &from_addr.sa; /* optional address */
5030 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5031 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5032 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5033 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5034 msg_ctrllen_filled = 0;
5035 msg_ctrllen_left = omsg->msg_controllen;
5037 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5038 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5039 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5042 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5047 ret = libc_recvmsg(s, &msg, flags);
5049 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5050 msg_ctrllen_filled += msg.msg_controllen;
5051 msg_ctrllen_left -= msg.msg_controllen;
5053 if (omsg->msg_control != NULL) {
5056 p = omsg->msg_control;
5057 p += msg_ctrllen_filled;
5059 msg.msg_control = p;
5060 msg.msg_controllen = msg_ctrllen_left;
5062 msg.msg_control = NULL;
5063 msg.msg_controllen = 0;
5068 * We convert the unix address to a IP address so we need a buffer
5069 * which can store the address in case of SOCK_DGRAM, see below.
5071 msg.msg_name = &convert_addr.sa;
5072 msg.msg_namelen = convert_addr.sa_socklen;
5074 rc = swrap_recvmsg_after(s,
5078 from_addr.sa_socklen,
5084 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5085 if (omsg->msg_control != NULL) {
5086 /* msg.msg_controllen = space left */
5087 msg_ctrllen_left = msg.msg_controllen;
5088 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5091 /* Update the original message length */
5092 omsg->msg_controllen = msg_ctrllen_filled;
5093 omsg->msg_flags = msg.msg_flags;
5095 omsg->msg_iovlen = msg.msg_iovlen;
5100 * The msg_name field points to a caller-allocated buffer that is
5101 * used to return the source address if the socket is unconnected. The
5102 * caller should set msg_namelen to the size of this buffer before this
5103 * call; upon return from a successful call, msg_name will contain the
5104 * length of the returned address. If the application does not need
5105 * to know the source address, msg_name can be specified as NULL.
5107 if (si->type == SOCK_STREAM) {
5108 omsg->msg_namelen = 0;
5109 } else if (omsg->msg_name != NULL &&
5110 omsg->msg_namelen != 0 &&
5111 omsg->msg_namelen >= msg.msg_namelen) {
5112 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5113 omsg->msg_namelen = msg.msg_namelen;
5119 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5121 return swrap_recvmsg(sockfd, msg, flags);
5124 /****************************************************************************
5126 ***************************************************************************/
5128 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5132 struct sockaddr_un un_addr;
5133 const struct sockaddr_un *to_un = NULL;
5134 const struct sockaddr *to = NULL;
5137 struct socket_info *si = find_socket_info(s);
5141 return libc_sendmsg(s, omsg, flags);
5144 ZERO_STRUCT(un_addr);
5146 tmp.iov_base = NULL;
5151 if (si->connected == 0) {
5152 msg.msg_name = omsg->msg_name; /* optional address */
5153 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5155 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5156 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5157 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5158 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5159 /* omsg is a const so use a local buffer for modifications */
5160 uint8_t cmbuf[omsg->msg_controllen];
5162 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5164 msg.msg_control = cmbuf; /* ancillary data, see below */
5165 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5167 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5170 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5178 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5186 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5187 avail += msg.msg_iov[i].iov_len;
5193 /* we capture it as one single packet */
5194 buf = (uint8_t *)malloc(remain);
5199 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5200 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5202 msg.msg_iov[i].iov_base,
5205 remain -= this_time;
5208 type = SOCKET_TYPE_CHAR_UDP;
5210 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5211 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5212 socket_wrapper_dir(), type, iface, prt);
5213 if (stat(un_addr.sun_path, &st) != 0) continue;
5215 msg.msg_name = &un_addr; /* optional address */
5216 msg.msg_namelen = sizeof(un_addr); /* size of address */
5218 /* ignore the any errors in broadcast sends */
5219 libc_sendmsg(s, &msg, flags);
5222 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5228 ret = libc_sendmsg(s, &msg, flags);
5230 swrap_sendmsg_after(s, si, &msg, to, ret);
5235 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5237 return swrap_sendmsg(s, omsg, flags);
5240 /****************************************************************************
5242 ***************************************************************************/
5244 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5246 struct socket_info *si;
5249 struct swrap_address saddr = {
5250 .sa_socklen = sizeof(struct sockaddr_storage)
5255 si = find_socket_info(s);
5257 return libc_readv(s, vector, count);
5260 tmp.iov_base = NULL;
5264 msg.msg_name = &saddr.sa.s; /* optional address */
5265 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5266 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5267 msg.msg_iovlen = count; /* # elements in msg_iov */
5268 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5269 msg.msg_control = NULL; /* ancillary data, see below */
5270 msg.msg_controllen = 0; /* ancillary data buffer len */
5271 msg.msg_flags = 0; /* flags on received message */
5274 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5276 if (rc == -ENOTSOCK) {
5277 return libc_readv(s, vector, count);
5282 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5284 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5292 ssize_t readv(int s, const struct iovec *vector, int count)
5294 return swrap_readv(s, vector, count);
5297 /****************************************************************************
5299 ***************************************************************************/
5301 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5305 struct sockaddr_un un_addr;
5308 struct socket_info *si = find_socket_info(s);
5311 return libc_writev(s, vector, count);
5314 tmp.iov_base = NULL;
5318 msg.msg_name = NULL; /* optional address */
5319 msg.msg_namelen = 0; /* size of address */
5320 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5321 msg.msg_iovlen = count; /* # elements in msg_iov */
5322 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5323 msg.msg_control = NULL; /* ancillary data, see below */
5324 msg.msg_controllen = 0; /* ancillary data buffer len */
5325 msg.msg_flags = 0; /* flags on received message */
5328 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5330 if (rc == -ENOTSOCK) {
5331 return libc_readv(s, vector, count);
5336 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5338 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5343 ssize_t writev(int s, const struct iovec *vector, int count)
5345 return swrap_writev(s, vector, count);
5348 /****************************
5350 ***************************/
5352 static int swrap_close(int fd)
5354 struct socket_info_fd *fi = find_socket_info_fd(fd);
5355 struct socket_info *si = NULL;
5360 return libc_close(fd);
5363 si_index = fi->si_index;
5365 SWRAP_DLIST_REMOVE(socket_fds, fi);
5368 ret = libc_close(fd);
5370 si = &sockets[si_index];
5373 if (si->refcount > 0) {
5374 /* there are still references left */
5378 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5379 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5382 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5383 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5384 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5387 if (si->un_addr.sun_path[0] != '\0') {
5388 unlink(si->un_addr.sun_path);
5391 si->next_free = first_free;
5392 first_free = si_index;
5399 return swrap_close(fd);
5402 /****************************
5404 ***************************/
5406 static int swrap_dup(int fd)
5408 struct socket_info *si;
5409 struct socket_info_fd *src_fi, *fi;
5411 src_fi = find_socket_info_fd(fd);
5412 if (src_fi == NULL) {
5413 return libc_dup(fd);
5416 si = &sockets[src_fi->si_index];
5418 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5424 fi->fd = libc_dup(fd);
5426 int saved_errno = errno;
5428 errno = saved_errno;
5433 fi->si_index = src_fi->si_index;
5435 /* Make sure we don't have an entry for the fd */
5436 swrap_remove_stale(fi->fd);
5438 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5444 return swrap_dup(fd);
5447 /****************************
5449 ***************************/
5451 static int swrap_dup2(int fd, int newfd)
5453 struct socket_info *si;
5454 struct socket_info_fd *src_fi, *fi;
5456 src_fi = find_socket_info_fd(fd);
5457 if (src_fi == NULL) {
5458 return libc_dup2(fd, newfd);
5461 si = &sockets[src_fi->si_index];
5465 * According to the manpage:
5467 * "If oldfd is a valid file descriptor, and newfd has the same
5468 * value as oldfd, then dup2() does nothing, and returns newfd."
5473 if (find_socket_info(newfd)) {
5474 /* dup2() does an implicit close of newfd, which we
5475 * need to emulate */
5479 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5485 fi->fd = libc_dup2(fd, newfd);
5487 int saved_errno = errno;
5489 errno = saved_errno;
5494 fi->si_index = src_fi->si_index;
5496 /* Make sure we don't have an entry for the fd */
5497 swrap_remove_stale(fi->fd);
5499 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5503 int dup2(int fd, int newfd)
5505 return swrap_dup2(fd, newfd);
5508 /****************************
5510 ***************************/
5512 static int swrap_vfcntl(int fd, int cmd, va_list va)
5514 struct socket_info_fd *src_fi, *fi;
5515 struct socket_info *si;
5518 src_fi = find_socket_info_fd(fd);
5519 if (src_fi == NULL) {
5520 return libc_vfcntl(fd, cmd, va);
5523 si = &sockets[src_fi->si_index];
5527 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5533 fi->fd = libc_vfcntl(fd, cmd, va);
5535 int saved_errno = errno;
5537 errno = saved_errno;
5542 fi->si_index = src_fi->si_index;
5544 /* Make sure we don't have an entry for the fd */
5545 swrap_remove_stale(fi->fd);
5547 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5552 rc = libc_vfcntl(fd, cmd, va);
5559 int fcntl(int fd, int cmd, ...)
5566 rc = swrap_vfcntl(fd, cmd, va);
5573 /****************************
5575 ***************************/
5578 static int swrap_eventfd(int count, int flags)
5582 fd = libc_eventfd(count, flags);
5584 swrap_remove_stale(fd);
5590 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5591 int eventfd(unsigned int count, int flags)
5593 int eventfd(int count, int flags)
5596 return swrap_eventfd(count, flags);
5601 int pledge(const char *promises, const char *paths[])
5603 (void)promises; /* unused */
5604 (void)paths; /* unused */
5608 #endif /* HAVE_PLEDGE */
5610 static void swrap_thread_prepare(void)
5615 static void swrap_thread_parent(void)
5620 static void swrap_thread_child(void)
5625 /****************************
5627 ***************************/
5628 void swrap_constructor(void)
5631 * If we hold a lock and the application forks, then the child
5632 * is not able to unlock the mutex and we are in a deadlock.
5633 * This should prevent such deadlocks.
5635 pthread_atfork(&swrap_thread_prepare,
5636 &swrap_thread_parent,
5637 &swrap_thread_child);
5640 /****************************
5642 ***************************/
5645 * This function is called when the library is unloaded and makes sure that
5646 * sockets get closed and the unix file for the socket are unlinked.
5648 void swrap_destructor(void)
5650 struct socket_info_fd *s = socket_fds;
5661 if (swrap.libc.handle != NULL) {
5662 dlclose(swrap.libc.handle);
5664 if (swrap.libc.socket_handle) {
5665 dlclose(swrap.libc.socket_handle);