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;
1729 si = &sockets[fi->si_index];
1731 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1732 SWRAP_DLIST_REMOVE(socket_fds, fi);
1737 if (si->refcount > 0) {
1741 if (si->un_addr.sun_path[0] != '\0') {
1742 unlink(si->un_addr.sun_path);
1745 si->next_free = first_free;
1746 first_free = fi->si_index;
1749 static int sockaddr_convert_to_un(struct socket_info *si,
1750 const struct sockaddr *in_addr,
1752 struct sockaddr_un *out_addr,
1756 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1758 (void) in_len; /* unused */
1760 if (out_addr == NULL) {
1764 out->sa_family = AF_UNIX;
1765 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1766 out->sa_len = sizeof(*out_addr);
1769 switch (in_addr->sa_family) {
1771 const struct sockaddr_in *sin;
1772 if (si->family != AF_INET) {
1775 if (in_len < sizeof(struct sockaddr_in)) {
1778 sin = (const struct sockaddr_in *)(const void *)in_addr;
1779 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1784 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1785 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1799 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1800 errno = ESOCKTNOSUPPORT;
1804 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1806 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1812 errno = EAFNOSUPPORT;
1813 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1817 static int sockaddr_convert_from_un(const struct socket_info *si,
1818 const struct sockaddr_un *in_addr,
1819 socklen_t un_addrlen,
1821 struct sockaddr *out_addr,
1822 socklen_t *out_addrlen)
1826 if (out_addr == NULL || out_addrlen == NULL)
1829 if (un_addrlen == 0) {
1844 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1845 errno = ESOCKTNOSUPPORT;
1848 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1849 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1850 out_addr->sa_len = *out_addrlen;
1857 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1858 errno = EAFNOSUPPORT;
1862 enum swrap_packet_type {
1864 SWRAP_CONNECT_UNREACH,
1872 SWRAP_SENDTO_UNREACH,
1883 struct swrap_file_hdr {
1885 uint16_t version_major;
1886 uint16_t version_minor;
1889 uint32_t frame_max_len;
1890 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1893 #define SWRAP_FILE_HDR_SIZE 24
1895 struct swrap_packet_frame {
1897 uint32_t micro_seconds;
1898 uint32_t recorded_length;
1899 uint32_t full_length;
1901 #define SWRAP_PACKET_FRAME_SIZE 16
1903 union swrap_packet_ip {
1907 uint16_t packet_length;
1908 uint16_t identification;
1913 uint16_t hdr_checksum;
1917 #define SWRAP_PACKET_IP_V4_SIZE 20
1920 uint8_t flow_label_high;
1921 uint16_t flow_label_low;
1922 uint16_t payload_length;
1923 uint8_t next_header;
1925 uint8_t src_addr[16];
1926 uint8_t dest_addr[16];
1928 #define SWRAP_PACKET_IP_V6_SIZE 40
1930 #define SWRAP_PACKET_IP_SIZE 40
1932 union swrap_packet_payload {
1934 uint16_t source_port;
1944 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1946 uint16_t source_port;
1951 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1958 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1965 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1967 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1969 #define SWRAP_PACKET_MIN_ALLOC \
1970 (SWRAP_PACKET_FRAME_SIZE + \
1971 SWRAP_PACKET_IP_SIZE + \
1972 SWRAP_PACKET_PAYLOAD_SIZE)
1974 static const char *swrap_pcap_init_file(void)
1976 static int initialized = 0;
1977 static const char *s = NULL;
1978 static const struct swrap_file_hdr h;
1979 static const struct swrap_packet_frame f;
1980 static const union swrap_packet_ip i;
1981 static const union swrap_packet_payload p;
1983 if (initialized == 1) {
1989 * TODO: don't use the structs use plain buffer offsets
1990 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1992 * for now make sure we disable PCAP support
1993 * if the struct has alignment!
1995 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1998 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2001 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2004 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2007 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2010 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2013 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2016 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2019 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2022 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2026 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2030 if (strncmp(s, "./", 2) == 0) {
2036 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2037 const struct sockaddr *src,
2038 const struct sockaddr *dest,
2040 const uint8_t *payload,
2042 unsigned long tcp_seqno,
2043 unsigned long tcp_ack,
2044 unsigned char tcp_ctl,
2046 size_t *_packet_len)
2050 struct swrap_packet_frame *frame;
2051 union swrap_packet_ip *ip;
2052 union swrap_packet_payload *pay;
2055 size_t nonwire_len = sizeof(*frame);
2056 size_t wire_hdr_len = 0;
2057 size_t wire_len = 0;
2058 size_t ip_hdr_len = 0;
2059 size_t icmp_hdr_len = 0;
2060 size_t icmp_truncate_len = 0;
2061 uint8_t protocol = 0, icmp_protocol = 0;
2062 const struct sockaddr_in *src_in = NULL;
2063 const struct sockaddr_in *dest_in = NULL;
2065 const struct sockaddr_in6 *src_in6 = NULL;
2066 const struct sockaddr_in6 *dest_in6 = NULL;
2071 switch (src->sa_family) {
2073 src_in = (const struct sockaddr_in *)(const void *)src;
2074 dest_in = (const struct sockaddr_in *)(const void *)dest;
2075 src_port = src_in->sin_port;
2076 dest_port = dest_in->sin_port;
2077 ip_hdr_len = sizeof(ip->v4);
2081 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2082 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2083 src_port = src_in6->sin6_port;
2084 dest_port = dest_in6->sin6_port;
2085 ip_hdr_len = sizeof(ip->v6);
2092 switch (socket_type) {
2094 protocol = 0x06; /* TCP */
2095 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2096 wire_len = wire_hdr_len + payload_len;
2100 protocol = 0x11; /* UDP */
2101 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2102 wire_len = wire_hdr_len + payload_len;
2110 icmp_protocol = protocol;
2111 switch (src->sa_family) {
2113 protocol = 0x01; /* ICMPv4 */
2114 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2118 protocol = 0x3A; /* ICMPv6 */
2119 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2123 if (wire_len > 64 ) {
2124 icmp_truncate_len = wire_len - 64;
2126 wire_hdr_len += icmp_hdr_len;
2127 wire_len += icmp_hdr_len;
2130 packet_len = nonwire_len + wire_len;
2131 alloc_len = packet_len;
2132 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2133 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2136 base = (uint8_t *)calloc(1, alloc_len);
2143 frame = (struct swrap_packet_frame *)(void *)buf;
2144 frame->seconds = tval->tv_sec;
2145 frame->micro_seconds = tval->tv_usec;
2146 frame->recorded_length = wire_len - icmp_truncate_len;
2147 frame->full_length = wire_len - icmp_truncate_len;
2148 buf += SWRAP_PACKET_FRAME_SIZE;
2150 ip = (union swrap_packet_ip *)(void *)buf;
2151 switch (src->sa_family) {
2153 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2155 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2156 ip->v4.identification = htons(0xFFFF);
2157 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2158 ip->v4.fragment = htons(0x0000);
2160 ip->v4.protocol = protocol;
2161 ip->v4.hdr_checksum = htons(0x0000);
2162 ip->v4.src_addr = src_in->sin_addr.s_addr;
2163 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2164 buf += SWRAP_PACKET_IP_V4_SIZE;
2168 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2169 ip->v6.flow_label_high = 0x00;
2170 ip->v6.flow_label_low = 0x0000;
2171 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2172 ip->v6.next_header = protocol;
2173 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2174 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2175 buf += SWRAP_PACKET_IP_V6_SIZE;
2181 pay = (union swrap_packet_payload *)(void *)buf;
2182 switch (src->sa_family) {
2184 pay->icmp4.type = 0x03; /* destination unreachable */
2185 pay->icmp4.code = 0x01; /* host unreachable */
2186 pay->icmp4.checksum = htons(0x0000);
2187 pay->icmp4.unused = htonl(0x00000000);
2188 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2190 /* set the ip header in the ICMP payload */
2191 ip = (union swrap_packet_ip *)(void *)buf;
2192 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2194 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2195 ip->v4.identification = htons(0xFFFF);
2196 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2197 ip->v4.fragment = htons(0x0000);
2199 ip->v4.protocol = icmp_protocol;
2200 ip->v4.hdr_checksum = htons(0x0000);
2201 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2202 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2203 buf += SWRAP_PACKET_IP_V4_SIZE;
2205 src_port = dest_in->sin_port;
2206 dest_port = src_in->sin_port;
2210 pay->icmp6.type = 0x01; /* destination unreachable */
2211 pay->icmp6.code = 0x03; /* address unreachable */
2212 pay->icmp6.checksum = htons(0x0000);
2213 pay->icmp6.unused = htonl(0x00000000);
2214 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2216 /* set the ip header in the ICMP payload */
2217 ip = (union swrap_packet_ip *)(void *)buf;
2218 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2219 ip->v6.flow_label_high = 0x00;
2220 ip->v6.flow_label_low = 0x0000;
2221 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2222 ip->v6.next_header = protocol;
2223 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2224 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2225 buf += SWRAP_PACKET_IP_V6_SIZE;
2227 src_port = dest_in6->sin6_port;
2228 dest_port = src_in6->sin6_port;
2234 pay = (union swrap_packet_payload *)(void *)buf;
2236 switch (socket_type) {
2238 pay->tcp.source_port = src_port;
2239 pay->tcp.dest_port = dest_port;
2240 pay->tcp.seq_num = htonl(tcp_seqno);
2241 pay->tcp.ack_num = htonl(tcp_ack);
2242 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2243 pay->tcp.control = tcp_ctl;
2244 pay->tcp.window = htons(0x7FFF);
2245 pay->tcp.checksum = htons(0x0000);
2246 pay->tcp.urg = htons(0x0000);
2247 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2252 pay->udp.source_port = src_port;
2253 pay->udp.dest_port = dest_port;
2254 pay->udp.length = htons(8 + payload_len);
2255 pay->udp.checksum = htons(0x0000);
2256 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2261 if (payload && payload_len > 0) {
2262 memcpy(buf, payload, payload_len);
2265 *_packet_len = packet_len - icmp_truncate_len;
2269 static int swrap_pcap_get_fd(const char *fname)
2273 if (fd != -1) return fd;
2275 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2277 struct swrap_file_hdr file_hdr;
2278 file_hdr.magic = 0xA1B2C3D4;
2279 file_hdr.version_major = 0x0002;
2280 file_hdr.version_minor = 0x0004;
2281 file_hdr.timezone = 0x00000000;
2282 file_hdr.sigfigs = 0x00000000;
2283 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2284 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2286 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2293 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2298 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2299 const struct sockaddr *addr,
2300 enum swrap_packet_type type,
2301 const void *buf, size_t len,
2304 const struct sockaddr *src_addr;
2305 const struct sockaddr *dest_addr;
2306 unsigned long tcp_seqno = 0;
2307 unsigned long tcp_ack = 0;
2308 unsigned char tcp_ctl = 0;
2309 int unreachable = 0;
2313 switch (si->family) {
2325 case SWRAP_CONNECT_SEND:
2326 if (si->type != SOCK_STREAM) return NULL;
2328 src_addr = &si->myname.sa.s;
2331 tcp_seqno = si->io.pck_snd;
2332 tcp_ack = si->io.pck_rcv;
2333 tcp_ctl = 0x02; /* SYN */
2335 si->io.pck_snd += 1;
2339 case SWRAP_CONNECT_RECV:
2340 if (si->type != SOCK_STREAM) return NULL;
2342 dest_addr = &si->myname.sa.s;
2345 tcp_seqno = si->io.pck_rcv;
2346 tcp_ack = si->io.pck_snd;
2347 tcp_ctl = 0x12; /** SYN,ACK */
2349 si->io.pck_rcv += 1;
2353 case SWRAP_CONNECT_UNREACH:
2354 if (si->type != SOCK_STREAM) return NULL;
2356 dest_addr = &si->myname.sa.s;
2359 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2360 tcp_seqno = si->io.pck_snd - 1;
2361 tcp_ack = si->io.pck_rcv;
2362 tcp_ctl = 0x02; /* SYN */
2367 case SWRAP_CONNECT_ACK:
2368 if (si->type != SOCK_STREAM) return NULL;
2370 src_addr = &si->myname.sa.s;
2373 tcp_seqno = si->io.pck_snd;
2374 tcp_ack = si->io.pck_rcv;
2375 tcp_ctl = 0x10; /* ACK */
2379 case SWRAP_ACCEPT_SEND:
2380 if (si->type != SOCK_STREAM) return NULL;
2382 dest_addr = &si->myname.sa.s;
2385 tcp_seqno = si->io.pck_rcv;
2386 tcp_ack = si->io.pck_snd;
2387 tcp_ctl = 0x02; /* SYN */
2389 si->io.pck_rcv += 1;
2393 case SWRAP_ACCEPT_RECV:
2394 if (si->type != SOCK_STREAM) return NULL;
2396 src_addr = &si->myname.sa.s;
2399 tcp_seqno = si->io.pck_snd;
2400 tcp_ack = si->io.pck_rcv;
2401 tcp_ctl = 0x12; /* SYN,ACK */
2403 si->io.pck_snd += 1;
2407 case SWRAP_ACCEPT_ACK:
2408 if (si->type != SOCK_STREAM) return NULL;
2410 dest_addr = &si->myname.sa.s;
2413 tcp_seqno = si->io.pck_rcv;
2414 tcp_ack = si->io.pck_snd;
2415 tcp_ctl = 0x10; /* ACK */
2420 src_addr = &si->myname.sa.s;
2421 dest_addr = &si->peername.sa.s;
2423 tcp_seqno = si->io.pck_snd;
2424 tcp_ack = si->io.pck_rcv;
2425 tcp_ctl = 0x18; /* PSH,ACK */
2427 si->io.pck_snd += len;
2431 case SWRAP_SEND_RST:
2432 dest_addr = &si->myname.sa.s;
2433 src_addr = &si->peername.sa.s;
2435 if (si->type == SOCK_DGRAM) {
2436 return swrap_pcap_marshall_packet(si,
2438 SWRAP_SENDTO_UNREACH,
2444 tcp_seqno = si->io.pck_rcv;
2445 tcp_ack = si->io.pck_snd;
2446 tcp_ctl = 0x14; /** RST,ACK */
2450 case SWRAP_PENDING_RST:
2451 dest_addr = &si->myname.sa.s;
2452 src_addr = &si->peername.sa.s;
2454 if (si->type == SOCK_DGRAM) {
2458 tcp_seqno = si->io.pck_rcv;
2459 tcp_ack = si->io.pck_snd;
2460 tcp_ctl = 0x14; /* RST,ACK */
2465 dest_addr = &si->myname.sa.s;
2466 src_addr = &si->peername.sa.s;
2468 tcp_seqno = si->io.pck_rcv;
2469 tcp_ack = si->io.pck_snd;
2470 tcp_ctl = 0x18; /* PSH,ACK */
2472 si->io.pck_rcv += len;
2476 case SWRAP_RECV_RST:
2477 dest_addr = &si->myname.sa.s;
2478 src_addr = &si->peername.sa.s;
2480 if (si->type == SOCK_DGRAM) {
2484 tcp_seqno = si->io.pck_rcv;
2485 tcp_ack = si->io.pck_snd;
2486 tcp_ctl = 0x14; /* RST,ACK */
2491 src_addr = &si->myname.sa.s;
2494 si->io.pck_snd += len;
2498 case SWRAP_SENDTO_UNREACH:
2499 dest_addr = &si->myname.sa.s;
2506 case SWRAP_RECVFROM:
2507 dest_addr = &si->myname.sa.s;
2510 si->io.pck_rcv += len;
2514 case SWRAP_CLOSE_SEND:
2515 if (si->type != SOCK_STREAM) return NULL;
2517 src_addr = &si->myname.sa.s;
2518 dest_addr = &si->peername.sa.s;
2520 tcp_seqno = si->io.pck_snd;
2521 tcp_ack = si->io.pck_rcv;
2522 tcp_ctl = 0x11; /* FIN, ACK */
2524 si->io.pck_snd += 1;
2528 case SWRAP_CLOSE_RECV:
2529 if (si->type != SOCK_STREAM) return NULL;
2531 dest_addr = &si->myname.sa.s;
2532 src_addr = &si->peername.sa.s;
2534 tcp_seqno = si->io.pck_rcv;
2535 tcp_ack = si->io.pck_snd;
2536 tcp_ctl = 0x11; /* FIN,ACK */
2538 si->io.pck_rcv += 1;
2542 case SWRAP_CLOSE_ACK:
2543 if (si->type != SOCK_STREAM) return NULL;
2545 src_addr = &si->myname.sa.s;
2546 dest_addr = &si->peername.sa.s;
2548 tcp_seqno = si->io.pck_snd;
2549 tcp_ack = si->io.pck_rcv;
2550 tcp_ctl = 0x10; /* ACK */
2557 swrapGetTimeOfDay(&tv);
2559 return swrap_pcap_packet_init(&tv,
2563 (const uint8_t *)buf,
2572 static void swrap_pcap_dump_packet(struct socket_info *si,
2573 const struct sockaddr *addr,
2574 enum swrap_packet_type type,
2575 const void *buf, size_t len)
2577 const char *file_name;
2579 size_t packet_len = 0;
2582 file_name = swrap_pcap_init_file();
2587 packet = swrap_pcap_marshall_packet(si,
2593 if (packet == NULL) {
2597 fd = swrap_pcap_get_fd(file_name);
2599 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2608 /****************************************************************************
2610 ***************************************************************************/
2612 #ifdef HAVE_SIGNALFD
2613 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2617 rc = libc_signalfd(fd, mask, flags);
2619 swrap_remove_stale(fd);
2625 int signalfd(int fd, const sigset_t *mask, int flags)
2627 return swrap_signalfd(fd, mask, flags);
2631 /****************************************************************************
2633 ***************************************************************************/
2635 static int swrap_socket(int family, int type, int protocol)
2637 struct socket_info *si;
2638 struct socket_info_fd *fi;
2641 int real_type = type;
2644 * Remove possible addition flags passed to socket() so
2645 * do not fail checking the type.
2646 * See https://lwn.net/Articles/281965/
2649 real_type &= ~SOCK_CLOEXEC;
2651 #ifdef SOCK_NONBLOCK
2652 real_type &= ~SOCK_NONBLOCK;
2655 if (!socket_wrapper_enabled()) {
2656 return libc_socket(family, type, protocol);
2667 #endif /* AF_NETLINK */
2670 #endif /* AF_PACKET */
2672 return libc_socket(family, type, protocol);
2674 errno = EAFNOSUPPORT;
2678 switch (real_type) {
2684 errno = EPROTONOSUPPORT;
2692 if (real_type == SOCK_STREAM) {
2697 if (real_type == SOCK_DGRAM) {
2702 errno = EPROTONOSUPPORT;
2707 * We must call libc_socket with type, from the caller, not the version
2708 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2710 fd = libc_socket(AF_UNIX, type, 0);
2716 /* Check if we have a stale fd and remove it */
2717 swrap_remove_stale(fd);
2719 idx = socket_wrapper_first_free_index();
2727 si->family = family;
2729 /* however, the rest of the socket_wrapper code expects just
2730 * the type, not the flags */
2731 si->type = real_type;
2732 si->protocol = protocol;
2735 * Setup myname so getsockname() can succeed to find out the socket
2738 switch(si->family) {
2740 struct sockaddr_in sin = {
2741 .sin_family = AF_INET,
2744 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2745 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2749 struct sockaddr_in6 sin6 = {
2750 .sin6_family = AF_INET6,
2753 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2754 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2762 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2769 first_free = si->next_free;
2775 SWRAP_DLIST_ADD(socket_fds, fi);
2777 SWRAP_LOG(SWRAP_LOG_TRACE,
2778 "Created %s socket for protocol %s",
2779 si->family == AF_INET ? "IPv4" : "IPv6",
2780 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2785 int socket(int family, int type, int protocol)
2787 return swrap_socket(family, type, protocol);
2790 /****************************************************************************
2792 ***************************************************************************/
2794 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2798 rc = libc_socketpair(family, type, protocol, sv);
2800 swrap_remove_stale(sv[0]);
2801 swrap_remove_stale(sv[1]);
2807 int socketpair(int family, int type, int protocol, int sv[2])
2809 return swrap_socketpair(family, type, protocol, sv);
2812 /****************************************************************************
2814 ***************************************************************************/
2816 #ifdef HAVE_TIMERFD_CREATE
2817 static int swrap_timerfd_create(int clockid, int flags)
2821 fd = libc_timerfd_create(clockid, flags);
2823 swrap_remove_stale(fd);
2829 int timerfd_create(int clockid, int flags)
2831 return swrap_timerfd_create(clockid, flags);
2835 /****************************************************************************
2837 ***************************************************************************/
2839 static int swrap_pipe(int pipefd[2])
2843 rc = libc_pipe(pipefd);
2845 swrap_remove_stale(pipefd[0]);
2846 swrap_remove_stale(pipefd[1]);
2852 int pipe(int pipefd[2])
2854 return swrap_pipe(pipefd);
2857 /****************************************************************************
2859 ***************************************************************************/
2861 static int swrap_accept(int s,
2862 struct sockaddr *addr,
2866 struct socket_info *parent_si, *child_si;
2867 struct socket_info_fd *child_fi;
2870 struct swrap_address un_addr = {
2871 .sa_socklen = sizeof(struct sockaddr_un),
2873 struct swrap_address un_my_addr = {
2874 .sa_socklen = sizeof(struct sockaddr_un),
2876 struct swrap_address in_addr = {
2877 .sa_socklen = sizeof(struct sockaddr_storage),
2879 struct swrap_address in_my_addr = {
2880 .sa_socklen = sizeof(struct sockaddr_storage),
2884 parent_si = find_socket_info(s);
2887 return libc_accept4(s, addr, addrlen, flags);
2890 return libc_accept(s, addr, addrlen);
2895 * assume out sockaddr have the same size as the in parent
2898 in_addr.sa_socklen = socket_length(parent_si->family);
2899 if (in_addr.sa_socklen <= 0) {
2905 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2908 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2911 if (errno == ENOTSOCK) {
2912 /* Remove stale fds */
2913 swrap_remove_stale(s);
2920 ret = sockaddr_convert_from_un(parent_si,
2925 &in_addr.sa_socklen);
2931 idx = socket_wrapper_first_free_index();
2937 child_si = &sockets[idx];
2939 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2940 if (child_fi == NULL) {
2948 child_si->family = parent_si->family;
2949 child_si->type = parent_si->type;
2950 child_si->protocol = parent_si->protocol;
2951 child_si->bound = 1;
2952 child_si->is_server = 1;
2953 child_si->connected = 1;
2955 child_si->peername = (struct swrap_address) {
2956 .sa_socklen = in_addr.sa_socklen,
2958 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2960 if (addr != NULL && addrlen != NULL) {
2961 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2963 memcpy(addr, &in_addr.sa.ss, copy_len);
2965 *addrlen = in_addr.sa_socklen;
2968 ret = libc_getsockname(fd,
2970 &un_my_addr.sa_socklen);
2977 ret = sockaddr_convert_from_un(child_si,
2979 un_my_addr.sa_socklen,
2982 &in_my_addr.sa_socklen);
2989 SWRAP_LOG(SWRAP_LOG_TRACE,
2990 "accept() path=%s, fd=%d",
2991 un_my_addr.sa.un.sun_path, s);
2993 child_si->myname = (struct swrap_address) {
2994 .sa_socklen = in_my_addr.sa_socklen,
2996 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2998 child_si->refcount = 1;
2999 first_free = child_si->next_free;
3000 child_si->next_free = 0;
3002 child_fi->si_index = idx;
3004 SWRAP_DLIST_ADD(socket_fds, child_fi);
3007 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3008 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3009 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3016 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3018 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3022 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3023 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3025 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3028 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3031 static int autobind_start_init;
3032 static int autobind_start;
3034 /* using sendto() or connect() on an unbound socket would give the
3035 recipient no way to reply, as unlike UDP and TCP, a unix domain
3036 socket can't auto-assign ephemeral port numbers, so we need to
3038 Note: this might change the family from ipv6 to ipv4
3040 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3042 struct swrap_address un_addr = {
3043 .sa_socklen = sizeof(struct sockaddr_un),
3051 if (autobind_start_init != 1) {
3052 autobind_start_init = 1;
3053 autobind_start = getpid();
3054 autobind_start %= 50000;
3055 autobind_start += 10000;
3058 un_addr.sa.un.sun_family = AF_UNIX;
3062 struct sockaddr_in in;
3066 type = SOCKET_TYPE_CHAR_TCP;
3069 type = SOCKET_TYPE_CHAR_UDP;
3072 errno = ESOCKTNOSUPPORT;
3076 memset(&in, 0, sizeof(in));
3077 in.sin_family = AF_INET;
3078 in.sin_addr.s_addr = htonl(127<<24 |
3079 socket_wrapper_default_iface());
3081 si->myname = (struct swrap_address) {
3082 .sa_socklen = sizeof(in),
3084 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3089 struct sockaddr_in6 in6;
3091 if (si->family != family) {
3092 errno = ENETUNREACH;
3098 type = SOCKET_TYPE_CHAR_TCP_V6;
3101 type = SOCKET_TYPE_CHAR_UDP_V6;
3104 errno = ESOCKTNOSUPPORT;
3108 memset(&in6, 0, sizeof(in6));
3109 in6.sin6_family = AF_INET6;
3110 in6.sin6_addr = *swrap_ipv6();
3111 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3113 si->myname = (struct swrap_address) {
3114 .sa_socklen = sizeof(in6),
3116 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3121 errno = ESOCKTNOSUPPORT;
3125 if (autobind_start > 60000) {
3126 autobind_start = 10000;
3129 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3130 port = autobind_start + i;
3131 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3132 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3133 type, socket_wrapper_default_iface(), port);
3134 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3136 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3137 if (ret == -1) return ret;
3139 si->un_addr = un_addr.sa.un;
3142 autobind_start = port + 1;
3145 if (i == SOCKET_MAX_SOCKETS) {
3146 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3147 "interface "SOCKET_FORMAT,
3150 socket_wrapper_default_iface(),
3156 si->family = family;
3157 set_port(si->family, port, &si->myname);
3162 /****************************************************************************
3164 ***************************************************************************/
3166 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3170 struct swrap_address un_addr = {
3171 .sa_socklen = sizeof(struct sockaddr_un),
3173 struct socket_info *si = find_socket_info(s);
3177 return libc_connect(s, serv_addr, addrlen);
3180 if (si->bound == 0) {
3181 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3182 if (ret == -1) return -1;
3185 if (si->family != serv_addr->sa_family) {
3190 ret = sockaddr_convert_to_un(si, serv_addr,
3191 addrlen, &un_addr.sa.un, 0, &bcast);
3192 if (ret == -1) return -1;
3195 errno = ENETUNREACH;
3199 if (si->type == SOCK_DGRAM) {
3200 si->defer_connect = 1;
3203 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3205 ret = libc_connect(s,
3207 un_addr.sa_socklen);
3210 SWRAP_LOG(SWRAP_LOG_TRACE,
3211 "connect() path=%s, fd=%d",
3212 un_addr.sa.un.sun_path, s);
3215 /* to give better errors */
3216 if (ret == -1 && errno == ENOENT) {
3217 errno = EHOSTUNREACH;
3221 si->peername = (struct swrap_address) {
3222 .sa_socklen = addrlen,
3225 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3229 * When we connect() on a socket than we have to bind the
3230 * outgoing connection on the interface we use for the
3231 * transport. We already bound it on the right interface
3232 * but here we have to update the name so getsockname()
3233 * returns correct information.
3235 if (si->bindname.sa_socklen > 0) {
3236 si->myname = (struct swrap_address) {
3237 .sa_socklen = si->bindname.sa_socklen,
3240 memcpy(&si->myname.sa.ss,
3241 &si->bindname.sa.ss,
3242 si->bindname.sa_socklen);
3244 /* Cleanup bindname */
3245 si->bindname = (struct swrap_address) {
3250 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3251 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3253 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3259 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3261 return swrap_connect(s, serv_addr, addrlen);
3264 /****************************************************************************
3266 ***************************************************************************/
3268 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3271 struct swrap_address un_addr = {
3272 .sa_socklen = sizeof(struct sockaddr_un),
3274 struct socket_info *si = find_socket_info(s);
3281 return libc_bind(s, myaddr, addrlen);
3284 switch (si->family) {
3286 const struct sockaddr_in *sin;
3287 if (addrlen < sizeof(struct sockaddr_in)) {
3288 bind_error = EINVAL;
3292 sin = (const struct sockaddr_in *)(const void *)myaddr;
3294 if (sin->sin_family != AF_INET) {
3295 bind_error = EAFNOSUPPORT;
3298 /* special case for AF_UNSPEC */
3299 if (sin->sin_family == AF_UNSPEC &&
3300 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3309 const struct sockaddr_in6 *sin6;
3310 if (addrlen < sizeof(struct sockaddr_in6)) {
3311 bind_error = EINVAL;
3315 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3317 if (sin6->sin6_family != AF_INET6) {
3318 bind_error = EAFNOSUPPORT;
3325 bind_error = EINVAL;
3329 if (bind_error != 0) {
3335 in_use = check_addr_port_in_use(myaddr, addrlen);
3342 si->myname.sa_socklen = addrlen;
3343 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3345 ret = sockaddr_convert_to_un(si,
3351 if (ret == -1) return -1;
3353 unlink(un_addr.sa.un.sun_path);
3355 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3357 SWRAP_LOG(SWRAP_LOG_TRACE,
3358 "bind() path=%s, fd=%d",
3359 un_addr.sa.un.sun_path, s);
3368 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3370 return swrap_bind(s, myaddr, addrlen);
3373 /****************************************************************************
3375 ***************************************************************************/
3377 #ifdef HAVE_BINDRESVPORT
3378 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3380 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3382 struct swrap_address myaddr = {
3383 .sa_socklen = sizeof(struct sockaddr_storage),
3386 static uint16_t port;
3391 #define SWRAP_STARTPORT 600
3392 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3393 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3396 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3400 salen = myaddr.sa_socklen;
3403 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3409 memset(&myaddr.sa.ss, 0, salen);
3414 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3417 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3419 salen = sizeof(struct sockaddr_in);
3420 sinp->sin_port = htons(port);
3424 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3426 salen = sizeof(struct sockaddr_in6);
3427 sin6p->sin6_port = htons(port);
3431 errno = EAFNOSUPPORT;
3436 if (port > SWRAP_ENDPORT) {
3437 port = SWRAP_STARTPORT;
3440 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3441 if (rc == 0 || errno != EADDRINUSE) {
3449 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3451 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3455 /****************************************************************************
3457 ***************************************************************************/
3459 static int swrap_listen(int s, int backlog)
3462 struct socket_info *si = find_socket_info(s);
3465 return libc_listen(s, backlog);
3468 if (si->bound == 0) {
3469 ret = swrap_auto_bind(s, si, si->family);
3476 ret = libc_listen(s, backlog);
3481 int listen(int s, int backlog)
3483 return swrap_listen(s, backlog);
3486 /****************************************************************************
3488 ***************************************************************************/
3490 static FILE *swrap_fopen(const char *name, const char *mode)
3494 fp = libc_fopen(name, mode);
3496 int fd = fileno(fp);
3498 swrap_remove_stale(fd);
3504 FILE *fopen(const char *name, const char *mode)
3506 return swrap_fopen(name, mode);
3509 /****************************************************************************
3511 ***************************************************************************/
3513 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3517 ret = libc_vopen(pathname, flags, ap);
3520 * There are methods for closing descriptors (libc-internal code
3521 * paths, direct syscalls) which close descriptors in ways that
3522 * we can't intercept, so try to recover when we notice that
3525 swrap_remove_stale(ret);
3530 int open(const char *pathname, int flags, ...)
3535 va_start(ap, flags);
3536 fd = swrap_vopen(pathname, flags, ap);
3542 /****************************************************************************
3544 ***************************************************************************/
3546 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3548 struct socket_info *si = find_socket_info(s);
3552 return libc_getpeername(s, name, addrlen);
3555 if (si->peername.sa_socklen == 0)
3561 len = MIN(*addrlen, si->peername.sa_socklen);
3566 memcpy(name, &si->peername.sa.ss, len);
3567 *addrlen = si->peername.sa_socklen;
3572 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3573 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3575 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3578 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3581 /****************************************************************************
3583 ***************************************************************************/
3585 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3587 struct socket_info *si = find_socket_info(s);
3591 return libc_getsockname(s, name, addrlen);
3594 len = MIN(*addrlen, si->myname.sa_socklen);
3599 memcpy(name, &si->myname.sa.ss, len);
3600 *addrlen = si->myname.sa_socklen;
3605 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3606 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3608 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3611 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3614 /****************************************************************************
3616 ***************************************************************************/
3619 # ifdef SO_PROTOTYPE /* The Solaris name */
3620 # define SO_PROTOCOL SO_PROTOTYPE
3621 # endif /* SO_PROTOTYPE */
3622 #endif /* SO_PROTOCOL */
3624 static int swrap_getsockopt(int s, int level, int optname,
3625 void *optval, socklen_t *optlen)
3627 struct socket_info *si = find_socket_info(s);
3630 return libc_getsockopt(s,
3637 if (level == SOL_SOCKET) {
3641 if (optval == NULL || optlen == NULL ||
3642 *optlen < (socklen_t)sizeof(int)) {
3647 *optlen = sizeof(int);
3648 *(int *)optval = si->family;
3650 #endif /* SO_DOMAIN */
3654 if (optval == NULL || optlen == NULL ||
3655 *optlen < (socklen_t)sizeof(int)) {
3660 *optlen = sizeof(int);
3661 *(int *)optval = si->protocol;
3663 #endif /* SO_PROTOCOL */
3665 if (optval == NULL || optlen == NULL ||
3666 *optlen < (socklen_t)sizeof(int)) {
3671 *optlen = sizeof(int);
3672 *(int *)optval = si->type;
3675 return libc_getsockopt(s,
3681 } else if (level == IPPROTO_TCP) {
3686 * This enables sending packets directly out over TCP.
3687 * As a unix socket is doing that any way, report it as
3690 if (optval == NULL || optlen == NULL ||
3691 *optlen < (socklen_t)sizeof(int)) {
3696 *optlen = sizeof(int);
3697 *(int *)optval = si->tcp_nodelay;
3700 #endif /* TCP_NODELAY */
3706 errno = ENOPROTOOPT;
3710 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3711 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3713 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3716 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3719 /****************************************************************************
3721 ***************************************************************************/
3723 static int swrap_setsockopt(int s, int level, int optname,
3724 const void *optval, socklen_t optlen)
3726 struct socket_info *si = find_socket_info(s);
3729 return libc_setsockopt(s,
3736 if (level == SOL_SOCKET) {
3737 return libc_setsockopt(s,
3742 } else if (level == IPPROTO_TCP) {
3749 * This enables sending packets directly out over TCP.
3750 * A unix socket is doing that any way.
3752 if (optval == NULL || optlen == 0 ||
3753 optlen < (socklen_t)sizeof(int)) {
3758 i = *discard_const_p(int, optval);
3759 if (i != 0 && i != 1) {
3763 si->tcp_nodelay = i;
3767 #endif /* TCP_NODELAY */
3773 switch (si->family) {
3775 if (level == IPPROTO_IP) {
3777 if (optname == IP_PKTINFO) {
3778 si->pktinfo = AF_INET;
3780 #endif /* IP_PKTINFO */
3785 if (level == IPPROTO_IPV6) {
3786 #ifdef IPV6_RECVPKTINFO
3787 if (optname == IPV6_RECVPKTINFO) {
3788 si->pktinfo = AF_INET6;
3790 #endif /* IPV6_PKTINFO */
3795 errno = ENOPROTOOPT;
3800 int setsockopt(int s, int level, int optname,
3801 const void *optval, socklen_t optlen)
3803 return swrap_setsockopt(s, level, optname, optval, optlen);
3806 /****************************************************************************
3808 ***************************************************************************/
3810 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3812 struct socket_info *si = find_socket_info(s);
3818 return libc_vioctl(s, r, va);
3823 rc = libc_vioctl(s, r, va);
3827 value = *((int *)va_arg(ap, int *));
3829 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3830 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3831 } else if (value == 0) { /* END OF FILE */
3832 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3842 #ifdef HAVE_IOCTL_INT
3843 int ioctl(int s, int r, ...)
3845 int ioctl(int s, unsigned long int r, ...)
3853 rc = swrap_vioctl(s, (unsigned long int) r, va);
3864 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3867 # ifdef _ALIGN /* BSD */
3868 #define CMSG_ALIGN _ALIGN
3870 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3871 # endif /* _ALIGN */
3872 #endif /* CMSG_ALIGN */
3875 * @brief Add a cmsghdr to a msghdr.
3877 * This is an function to add any type of cmsghdr. It will operate on the
3878 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3879 * the buffer position after the added cmsg element. Hence, this function is
3880 * intended to be used with an intermediate msghdr and not on the original
3881 * one handed in by the client.
3883 * @param[in] msg The msghdr to which to add the cmsg.
3885 * @param[in] level The cmsg level to set.
3887 * @param[in] type The cmsg type to set.
3889 * @param[in] data The cmsg data to set.
3891 * @param[in] len the length of the data to set.
3893 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3899 size_t cmlen = CMSG_LEN(len);
3900 size_t cmspace = CMSG_SPACE(len);
3901 uint8_t cmbuf[cmspace];
3902 void *cast_ptr = (void *)cmbuf;
3903 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3906 memset(cmbuf, 0, cmspace);
3908 if (msg->msg_controllen < cmlen) {
3909 cmlen = msg->msg_controllen;
3910 msg->msg_flags |= MSG_CTRUNC;
3913 if (msg->msg_controllen < cmspace) {
3914 cmspace = msg->msg_controllen;
3918 * We copy the full input data into an intermediate cmsghdr first
3919 * in order to more easily cope with truncation.
3921 cm->cmsg_len = cmlen;
3922 cm->cmsg_level = level;
3923 cm->cmsg_type = type;
3924 memcpy(CMSG_DATA(cm), data, len);
3927 * We now copy the possibly truncated buffer.
3928 * We copy cmlen bytes, but consume cmspace bytes,
3929 * leaving the possible padding uninitialiazed.
3931 p = (uint8_t *)msg->msg_control;
3932 memcpy(p, cm, cmlen);
3934 msg->msg_control = p;
3935 msg->msg_controllen -= cmspace;
3940 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3943 /* Add packet info */
3944 switch (si->pktinfo) {
3945 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3947 struct sockaddr_in *sin;
3948 #if defined(HAVE_STRUCT_IN_PKTINFO)
3949 struct in_pktinfo pkt;
3950 #elif defined(IP_RECVDSTADDR)
3954 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3955 sin = &si->bindname.sa.in;
3957 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3960 sin = &si->myname.sa.in;
3965 #if defined(HAVE_STRUCT_IN_PKTINFO)
3966 pkt.ipi_ifindex = socket_wrapper_default_iface();
3967 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3968 #elif defined(IP_RECVDSTADDR)
3969 pkt = sin->sin_addr;
3972 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3977 #endif /* IP_PKTINFO */
3978 #if defined(HAVE_IPV6)
3980 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3981 struct sockaddr_in6 *sin6;
3982 struct in6_pktinfo pkt6;
3984 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3985 sin6 = &si->bindname.sa.in6;
3987 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3990 sin6 = &si->myname.sa.in6;
3995 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3996 pkt6.ipi6_addr = sin6->sin6_addr;
3998 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3999 &pkt6, sizeof(pkt6));
4000 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4004 #endif /* IPV6_PKTINFO */
4012 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4013 struct msghdr *omsg)
4017 if (si->pktinfo > 0) {
4018 rc = swrap_msghdr_add_pktinfo(si, omsg);
4024 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4026 size_t *cm_data_space);
4027 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4029 size_t *cm_data_space);
4031 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4033 size_t *cm_data_space) {
4034 struct cmsghdr *cmsg;
4038 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4042 for (cmsg = CMSG_FIRSTHDR(msg);
4044 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4045 switch (cmsg->cmsg_level) {
4047 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4052 rc = swrap_sendmsg_copy_cmsg(cmsg,
4062 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4064 size_t *cm_data_space)
4069 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4071 p = realloc((*cm_data), cmspace);
4077 p = (*cm_data) + (*cm_data_space);
4078 *cm_data_space = cmspace;
4080 memcpy(p, cmsg, cmsg->cmsg_len);
4085 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4087 size_t *cm_data_space);
4090 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4092 size_t *cm_data_space)
4096 switch(cmsg->cmsg_type) {
4099 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4106 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4118 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4120 size_t *cm_data_space)
4122 (void)cmsg; /* unused */
4123 (void)cm_data; /* unused */
4124 (void)cm_data_space; /* unused */
4127 * Passing a IP pktinfo to a unix socket might be rejected by the
4128 * Kernel, at least on FreeBSD. So skip this cmsg.
4132 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4134 static ssize_t swrap_sendmsg_before(int fd,
4135 struct socket_info *si,
4137 struct iovec *tmp_iov,
4138 struct sockaddr_un *tmp_un,
4139 const struct sockaddr_un **to_un,
4140 const struct sockaddr **to,
4160 if (!si->connected) {
4165 if (msg->msg_iovlen == 0) {
4169 mtu = socket_wrapper_mtu();
4170 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4172 nlen = len + msg->msg_iov[i].iov_len;
4177 msg->msg_iovlen = i;
4178 if (msg->msg_iovlen == 0) {
4179 *tmp_iov = msg->msg_iov[0];
4180 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4182 msg->msg_iov = tmp_iov;
4183 msg->msg_iovlen = 1;
4188 if (si->connected) {
4189 if (msg->msg_name != NULL) {
4191 * We are dealing with unix sockets and if we
4192 * are connected, we should only talk to the
4193 * connected unix path. Using the fd to send
4194 * to another server would be hard to achieve.
4196 msg->msg_name = NULL;
4197 msg->msg_namelen = 0;
4200 const struct sockaddr *msg_name;
4201 msg_name = (const struct sockaddr *)msg->msg_name;
4203 if (msg_name == NULL) {
4209 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4211 if (ret == -1) return -1;
4219 msg->msg_name = tmp_un;
4220 msg->msg_namelen = sizeof(*tmp_un);
4223 if (si->bound == 0) {
4224 ret = swrap_auto_bind(fd, si, si->family);
4226 if (errno == ENOTSOCK) {
4227 swrap_remove_stale(fd);
4230 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4236 if (!si->defer_connect) {
4240 ret = sockaddr_convert_to_un(si,
4242 si->peername.sa_socklen,
4246 if (ret == -1) return -1;
4248 ret = libc_connect(fd,
4249 (struct sockaddr *)(void *)tmp_un,
4252 /* to give better errors */
4253 if (ret == -1 && errno == ENOENT) {
4254 errno = EHOSTUNREACH;
4261 si->defer_connect = 0;
4264 errno = EHOSTUNREACH;
4268 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4269 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4270 uint8_t *cmbuf = NULL;
4273 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4280 msg->msg_controllen = 0;
4281 msg->msg_control = NULL;
4282 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4283 memcpy(msg->msg_control, cmbuf, cmlen);
4284 msg->msg_controllen = cmlen;
4293 static void swrap_sendmsg_after(int fd,
4294 struct socket_info *si,
4296 const struct sockaddr *to,
4299 int saved_errno = errno;
4306 /* to give better errors */
4308 if (saved_errno == ENOENT) {
4309 saved_errno = EHOSTUNREACH;
4310 } else if (saved_errno == ENOTSOCK) {
4311 /* If the fd is not a socket, remove it */
4312 swrap_remove_stale(fd);
4316 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4317 avail += msg->msg_iov[i].iov_len;
4321 remain = MIN(80, avail);
4326 /* we capture it as one single packet */
4327 buf = (uint8_t *)malloc(remain);
4329 /* we just not capture the packet */
4330 errno = saved_errno;
4334 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4335 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4337 msg->msg_iov[i].iov_base,
4340 remain -= this_time;
4347 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4348 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4350 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4355 if (si->connected) {
4356 to = &si->peername.sa.s;
4359 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4360 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4362 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4368 errno = saved_errno;
4371 static int swrap_recvmsg_before(int fd,
4372 struct socket_info *si,
4374 struct iovec *tmp_iov)
4379 (void)fd; /* unused */
4384 if (!si->connected) {
4389 if (msg->msg_iovlen == 0) {
4393 mtu = socket_wrapper_mtu();
4394 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4396 nlen = len + msg->msg_iov[i].iov_len;
4401 msg->msg_iovlen = i;
4402 if (msg->msg_iovlen == 0) {
4403 *tmp_iov = msg->msg_iov[0];
4404 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4406 msg->msg_iov = tmp_iov;
4407 msg->msg_iovlen = 1;
4412 if (msg->msg_name == NULL) {
4417 if (msg->msg_iovlen == 0) {
4421 if (si->bound == 0) {
4422 ret = swrap_auto_bind(fd, si, si->family);
4425 * When attempting to read or write to a
4426 * descriptor, if an underlying autobind fails
4427 * because it's not a socket, stop intercepting
4428 * uses of that descriptor.
4430 if (errno == ENOTSOCK) {
4431 swrap_remove_stale(fd);
4434 SWRAP_LOG(SWRAP_LOG_ERROR,
4435 "swrap_recvmsg_before failed");
4442 errno = EHOSTUNREACH;
4449 static int swrap_recvmsg_after(int fd,
4450 struct socket_info *si,
4452 const struct sockaddr_un *un_addr,
4453 socklen_t un_addrlen,
4456 int saved_errno = errno;
4458 uint8_t *buf = NULL;
4464 /* to give better errors */
4466 if (saved_errno == ENOENT) {
4467 saved_errno = EHOSTUNREACH;
4468 } else if (saved_errno == ENOTSOCK) {
4469 /* If the fd is not a socket, remove it */
4470 swrap_remove_stale(fd);
4474 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4475 avail += msg->msg_iov[i].iov_len;
4478 /* Convert the socket address before we leave */
4479 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4480 rc = sockaddr_convert_from_un(si,
4497 remain = MIN(80, avail);
4502 /* we capture it as one single packet */
4503 buf = (uint8_t *)malloc(remain);
4505 /* we just not capture the packet */
4506 errno = saved_errno;
4510 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4511 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4513 msg->msg_iov[i].iov_base,
4516 remain -= this_time;
4521 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4522 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4523 } else if (ret == 0) { /* END OF FILE */
4524 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4525 } else if (ret > 0) {
4526 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4535 if (un_addr != NULL) {
4536 swrap_pcap_dump_packet(si,
4542 swrap_pcap_dump_packet(si,
4555 errno = saved_errno;
4557 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4559 msg->msg_controllen > 0 &&
4560 msg->msg_control != NULL) {
4561 rc = swrap_msghdr_add_socket_info(si, msg);
4571 /****************************************************************************
4573 ***************************************************************************/
4575 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4576 struct sockaddr *from, socklen_t *fromlen)
4578 struct swrap_address from_addr = {
4579 .sa_socklen = sizeof(struct sockaddr_un),
4582 struct socket_info *si = find_socket_info(s);
4583 struct swrap_address saddr = {
4584 .sa_socklen = sizeof(struct sockaddr_storage),
4591 return libc_recvfrom(s,
4603 if (from != NULL && fromlen != NULL) {
4604 msg.msg_name = from; /* optional address */
4605 msg.msg_namelen = *fromlen; /* size of address */
4607 msg.msg_name = &saddr.sa.s; /* optional address */
4608 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4610 msg.msg_iov = &tmp; /* scatter/gather array */
4611 msg.msg_iovlen = 1; /* # elements in msg_iov */
4612 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4613 msg.msg_control = NULL; /* ancillary data, see below */
4614 msg.msg_controllen = 0; /* ancillary data buffer len */
4615 msg.msg_flags = 0; /* flags on received message */
4618 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4623 buf = msg.msg_iov[0].iov_base;
4624 len = msg.msg_iov[0].iov_len;
4626 ret = libc_recvfrom(s,
4631 &from_addr.sa_socklen);
4636 tret = swrap_recvmsg_after(s,
4640 from_addr.sa_socklen,
4646 if (from != NULL && fromlen != NULL) {
4647 *fromlen = msg.msg_namelen;
4653 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4654 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4655 struct sockaddr *from, Psocklen_t fromlen)
4657 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4658 struct sockaddr *from, socklen_t *fromlen)
4661 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4664 /****************************************************************************
4666 ***************************************************************************/
4668 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4669 const struct sockaddr *to, socklen_t tolen)
4673 struct swrap_address un_addr = {
4674 .sa_socklen = sizeof(struct sockaddr_un),
4676 const struct sockaddr_un *to_un = NULL;
4679 struct socket_info *si = find_socket_info(s);
4683 return libc_sendto(s, buf, len, flags, to, tolen);
4686 tmp.iov_base = discard_const_p(char, buf);
4690 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4691 msg.msg_namelen = tolen; /* size of address */
4692 msg.msg_iov = &tmp; /* scatter/gather array */
4693 msg.msg_iovlen = 1; /* # elements in msg_iov */
4694 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4695 msg.msg_control = NULL; /* ancillary data, see below */
4696 msg.msg_controllen = 0; /* ancillary data buffer len */
4697 msg.msg_flags = 0; /* flags on received message */
4700 rc = swrap_sendmsg_before(s,
4712 buf = msg.msg_iov[0].iov_base;
4713 len = msg.msg_iov[0].iov_len;
4718 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4721 type = SOCKET_TYPE_CHAR_UDP;
4723 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4724 snprintf(un_addr.sa.un.sun_path,
4725 sizeof(un_addr.sa.un.sun_path),
4727 socket_wrapper_dir(), type, iface, prt);
4728 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4730 /* ignore the any errors in broadcast sends */
4736 un_addr.sa_socklen);
4739 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4745 * If it is a dgram socket and we are connected, don't include the
4748 if (si->type == SOCK_DGRAM && si->connected) {
4749 ret = libc_sendto(s,
4756 ret = libc_sendto(s,
4760 (struct sockaddr *)msg.msg_name,
4764 swrap_sendmsg_after(s, si, &msg, to, ret);
4769 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4770 const struct sockaddr *to, socklen_t tolen)
4772 return swrap_sendto(s, buf, len, flags, to, tolen);
4775 /****************************************************************************
4777 ***************************************************************************/
4779 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4781 struct socket_info *si;
4783 struct swrap_address saddr = {
4784 .sa_socklen = sizeof(struct sockaddr_storage),
4790 si = find_socket_info(s);
4792 return libc_recv(s, buf, len, flags);
4799 msg.msg_name = &saddr.sa.s; /* optional address */
4800 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4801 msg.msg_iov = &tmp; /* scatter/gather array */
4802 msg.msg_iovlen = 1; /* # elements in msg_iov */
4803 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4804 msg.msg_control = NULL; /* ancillary data, see below */
4805 msg.msg_controllen = 0; /* ancillary data buffer len */
4806 msg.msg_flags = 0; /* flags on received message */
4809 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4814 buf = msg.msg_iov[0].iov_base;
4815 len = msg.msg_iov[0].iov_len;
4817 ret = libc_recv(s, buf, len, flags);
4819 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4827 ssize_t recv(int s, void *buf, size_t len, int flags)
4829 return swrap_recv(s, buf, len, flags);
4832 /****************************************************************************
4834 ***************************************************************************/
4836 static ssize_t swrap_read(int s, void *buf, size_t len)
4838 struct socket_info *si;
4841 struct swrap_address saddr = {
4842 .sa_socklen = sizeof(struct sockaddr_storage),
4847 si = find_socket_info(s);
4849 return libc_read(s, buf, len);
4856 msg.msg_name = &saddr.sa.ss; /* optional address */
4857 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4858 msg.msg_iov = &tmp; /* scatter/gather array */
4859 msg.msg_iovlen = 1; /* # elements in msg_iov */
4860 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4861 msg.msg_control = NULL; /* ancillary data, see below */
4862 msg.msg_controllen = 0; /* ancillary data buffer len */
4863 msg.msg_flags = 0; /* flags on received message */
4866 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4868 if (tret == -ENOTSOCK) {
4869 return libc_read(s, buf, len);
4874 buf = msg.msg_iov[0].iov_base;
4875 len = msg.msg_iov[0].iov_len;
4877 ret = libc_read(s, buf, len);
4879 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4887 ssize_t read(int s, void *buf, size_t len)
4889 return swrap_read(s, buf, len);
4892 /****************************************************************************
4894 ***************************************************************************/
4896 static ssize_t swrap_write(int s, const void *buf, size_t len)
4900 struct sockaddr_un un_addr;
4903 struct socket_info *si;
4905 si = find_socket_info(s);
4907 return libc_write(s, buf, len);
4910 tmp.iov_base = discard_const_p(char, buf);
4914 msg.msg_name = NULL; /* optional address */
4915 msg.msg_namelen = 0; /* size of address */
4916 msg.msg_iov = &tmp; /* scatter/gather array */
4917 msg.msg_iovlen = 1; /* # elements in msg_iov */
4918 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4919 msg.msg_control = NULL; /* ancillary data, see below */
4920 msg.msg_controllen = 0; /* ancillary data buffer len */
4921 msg.msg_flags = 0; /* flags on received message */
4924 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4929 buf = msg.msg_iov[0].iov_base;
4930 len = msg.msg_iov[0].iov_len;
4932 ret = libc_write(s, buf, len);
4934 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4939 ssize_t write(int s, const void *buf, size_t len)
4941 return swrap_write(s, buf, len);
4944 /****************************************************************************
4946 ***************************************************************************/
4948 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4952 struct sockaddr_un un_addr;
4955 struct socket_info *si = find_socket_info(s);
4958 return libc_send(s, buf, len, flags);
4961 tmp.iov_base = discard_const_p(char, buf);
4965 msg.msg_name = NULL; /* optional address */
4966 msg.msg_namelen = 0; /* size of address */
4967 msg.msg_iov = &tmp; /* scatter/gather array */
4968 msg.msg_iovlen = 1; /* # elements in msg_iov */
4969 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4970 msg.msg_control = NULL; /* ancillary data, see below */
4971 msg.msg_controllen = 0; /* ancillary data buffer len */
4972 msg.msg_flags = 0; /* flags on received message */
4975 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4980 buf = msg.msg_iov[0].iov_base;
4981 len = msg.msg_iov[0].iov_len;
4983 ret = libc_send(s, buf, len, flags);
4985 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4990 ssize_t send(int s, const void *buf, size_t len, int flags)
4992 return swrap_send(s, buf, len, flags);
4995 /****************************************************************************
4997 ***************************************************************************/
4999 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5001 struct swrap_address from_addr = {
5002 .sa_socklen = sizeof(struct sockaddr_un),
5004 struct swrap_address convert_addr = {
5005 .sa_socklen = sizeof(struct sockaddr_storage),
5007 struct socket_info *si;
5010 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5011 size_t msg_ctrllen_filled;
5012 size_t msg_ctrllen_left;
5018 si = find_socket_info(s);
5020 return libc_recvmsg(s, omsg, flags);
5023 tmp.iov_base = NULL;
5027 msg.msg_name = &from_addr.sa; /* optional address */
5028 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5029 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5030 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5031 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5032 msg_ctrllen_filled = 0;
5033 msg_ctrllen_left = omsg->msg_controllen;
5035 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5036 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5037 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5040 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5045 ret = libc_recvmsg(s, &msg, flags);
5047 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5048 msg_ctrllen_filled += msg.msg_controllen;
5049 msg_ctrllen_left -= msg.msg_controllen;
5051 if (omsg->msg_control != NULL) {
5054 p = omsg->msg_control;
5055 p += msg_ctrllen_filled;
5057 msg.msg_control = p;
5058 msg.msg_controllen = msg_ctrllen_left;
5060 msg.msg_control = NULL;
5061 msg.msg_controllen = 0;
5066 * We convert the unix address to a IP address so we need a buffer
5067 * which can store the address in case of SOCK_DGRAM, see below.
5069 msg.msg_name = &convert_addr.sa;
5070 msg.msg_namelen = convert_addr.sa_socklen;
5072 rc = swrap_recvmsg_after(s,
5076 from_addr.sa_socklen,
5082 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5083 if (omsg->msg_control != NULL) {
5084 /* msg.msg_controllen = space left */
5085 msg_ctrllen_left = msg.msg_controllen;
5086 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5089 /* Update the original message length */
5090 omsg->msg_controllen = msg_ctrllen_filled;
5091 omsg->msg_flags = msg.msg_flags;
5093 omsg->msg_iovlen = msg.msg_iovlen;
5098 * The msg_name field points to a caller-allocated buffer that is
5099 * used to return the source address if the socket is unconnected. The
5100 * caller should set msg_namelen to the size of this buffer before this
5101 * call; upon return from a successful call, msg_name will contain the
5102 * length of the returned address. If the application does not need
5103 * to know the source address, msg_name can be specified as NULL.
5105 if (si->type == SOCK_STREAM) {
5106 omsg->msg_namelen = 0;
5107 } else if (omsg->msg_name != NULL &&
5108 omsg->msg_namelen != 0 &&
5109 omsg->msg_namelen >= msg.msg_namelen) {
5110 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5111 omsg->msg_namelen = msg.msg_namelen;
5117 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5119 return swrap_recvmsg(sockfd, msg, flags);
5122 /****************************************************************************
5124 ***************************************************************************/
5126 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5130 struct sockaddr_un un_addr;
5131 const struct sockaddr_un *to_un = NULL;
5132 const struct sockaddr *to = NULL;
5135 struct socket_info *si = find_socket_info(s);
5139 return libc_sendmsg(s, omsg, flags);
5142 ZERO_STRUCT(un_addr);
5144 tmp.iov_base = NULL;
5149 if (si->connected == 0) {
5150 msg.msg_name = omsg->msg_name; /* optional address */
5151 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5153 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5154 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5155 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5156 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5157 /* omsg is a const so use a local buffer for modifications */
5158 uint8_t cmbuf[omsg->msg_controllen];
5160 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5162 msg.msg_control = cmbuf; /* ancillary data, see below */
5163 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5165 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5168 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5176 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5184 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5185 avail += msg.msg_iov[i].iov_len;
5191 /* we capture it as one single packet */
5192 buf = (uint8_t *)malloc(remain);
5197 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5198 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5200 msg.msg_iov[i].iov_base,
5203 remain -= this_time;
5206 type = SOCKET_TYPE_CHAR_UDP;
5208 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5209 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5210 socket_wrapper_dir(), type, iface, prt);
5211 if (stat(un_addr.sun_path, &st) != 0) continue;
5213 msg.msg_name = &un_addr; /* optional address */
5214 msg.msg_namelen = sizeof(un_addr); /* size of address */
5216 /* ignore the any errors in broadcast sends */
5217 libc_sendmsg(s, &msg, flags);
5220 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5226 ret = libc_sendmsg(s, &msg, flags);
5228 swrap_sendmsg_after(s, si, &msg, to, ret);
5233 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5235 return swrap_sendmsg(s, omsg, flags);
5238 /****************************************************************************
5240 ***************************************************************************/
5242 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5244 struct socket_info *si;
5247 struct swrap_address saddr = {
5248 .sa_socklen = sizeof(struct sockaddr_storage)
5253 si = find_socket_info(s);
5255 return libc_readv(s, vector, count);
5258 tmp.iov_base = NULL;
5262 msg.msg_name = &saddr.sa.s; /* optional address */
5263 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5264 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5265 msg.msg_iovlen = count; /* # elements in msg_iov */
5266 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5267 msg.msg_control = NULL; /* ancillary data, see below */
5268 msg.msg_controllen = 0; /* ancillary data buffer len */
5269 msg.msg_flags = 0; /* flags on received message */
5272 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5274 if (rc == -ENOTSOCK) {
5275 return libc_readv(s, vector, count);
5280 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5282 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5290 ssize_t readv(int s, const struct iovec *vector, int count)
5292 return swrap_readv(s, vector, count);
5295 /****************************************************************************
5297 ***************************************************************************/
5299 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5303 struct sockaddr_un un_addr;
5306 struct socket_info *si = find_socket_info(s);
5309 return libc_writev(s, vector, count);
5312 tmp.iov_base = NULL;
5316 msg.msg_name = NULL; /* optional address */
5317 msg.msg_namelen = 0; /* size of address */
5318 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5319 msg.msg_iovlen = count; /* # elements in msg_iov */
5320 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5321 msg.msg_control = NULL; /* ancillary data, see below */
5322 msg.msg_controllen = 0; /* ancillary data buffer len */
5323 msg.msg_flags = 0; /* flags on received message */
5326 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5328 if (rc == -ENOTSOCK) {
5329 return libc_readv(s, vector, count);
5334 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5336 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5341 ssize_t writev(int s, const struct iovec *vector, int count)
5343 return swrap_writev(s, vector, count);
5346 /****************************
5348 ***************************/
5350 static int swrap_close(int fd)
5352 struct socket_info_fd *fi = find_socket_info_fd(fd);
5353 struct socket_info *si = NULL;
5357 return libc_close(fd);
5360 si = &sockets[fi->si_index];
5362 SWRAP_DLIST_REMOVE(socket_fds, fi);
5367 if (si->refcount > 0) {
5368 /* there are still references left */
5369 return libc_close(fd);
5372 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5373 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5376 ret = libc_close(fd);
5378 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5379 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5380 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5383 if (si->un_addr.sun_path[0] != '\0') {
5384 unlink(si->un_addr.sun_path);
5387 si->next_free = first_free;
5388 first_free = fi->si_index;
5395 return swrap_close(fd);
5398 /****************************
5400 ***************************/
5402 static int swrap_dup(int fd)
5404 struct socket_info *si;
5405 struct socket_info_fd *src_fi, *fi;
5407 src_fi = find_socket_info_fd(fd);
5408 if (src_fi == NULL) {
5409 return libc_dup(fd);
5412 si = &sockets[src_fi->si_index];
5414 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5420 fi->fd = libc_dup(fd);
5422 int saved_errno = errno;
5424 errno = saved_errno;
5429 fi->si_index = src_fi->si_index;
5431 /* Make sure we don't have an entry for the fd */
5432 swrap_remove_stale(fi->fd);
5434 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5440 return swrap_dup(fd);
5443 /****************************
5445 ***************************/
5447 static int swrap_dup2(int fd, int newfd)
5449 struct socket_info *si;
5450 struct socket_info_fd *src_fi, *fi;
5452 src_fi = find_socket_info_fd(fd);
5453 if (src_fi == NULL) {
5454 return libc_dup2(fd, newfd);
5457 si = &sockets[src_fi->si_index];
5461 * According to the manpage:
5463 * "If oldfd is a valid file descriptor, and newfd has the same
5464 * value as oldfd, then dup2() does nothing, and returns newfd."
5469 if (find_socket_info(newfd)) {
5470 /* dup2() does an implicit close of newfd, which we
5471 * need to emulate */
5475 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5481 fi->fd = libc_dup2(fd, newfd);
5483 int saved_errno = errno;
5485 errno = saved_errno;
5490 fi->si_index = src_fi->si_index;
5492 /* Make sure we don't have an entry for the fd */
5493 swrap_remove_stale(fi->fd);
5495 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5499 int dup2(int fd, int newfd)
5501 return swrap_dup2(fd, newfd);
5504 /****************************
5506 ***************************/
5508 static int swrap_vfcntl(int fd, int cmd, va_list va)
5510 struct socket_info_fd *src_fi, *fi;
5511 struct socket_info *si;
5514 src_fi = find_socket_info_fd(fd);
5515 if (src_fi == NULL) {
5516 return libc_vfcntl(fd, cmd, va);
5519 si = &sockets[src_fi->si_index];
5523 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5529 fi->fd = libc_vfcntl(fd, cmd, va);
5531 int saved_errno = errno;
5533 errno = saved_errno;
5538 fi->si_index = src_fi->si_index;
5540 /* Make sure we don't have an entry for the fd */
5541 swrap_remove_stale(fi->fd);
5543 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5548 rc = libc_vfcntl(fd, cmd, va);
5555 int fcntl(int fd, int cmd, ...)
5562 rc = swrap_vfcntl(fd, cmd, va);
5569 /****************************
5571 ***************************/
5574 static int swrap_eventfd(int count, int flags)
5578 fd = libc_eventfd(count, flags);
5580 swrap_remove_stale(fd);
5586 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5587 int eventfd(unsigned int count, int flags)
5589 int eventfd(int count, int flags)
5592 return swrap_eventfd(count, flags);
5597 int pledge(const char *promises, const char *paths[])
5599 (void)promises; /* unused */
5600 (void)paths; /* unused */
5604 #endif /* HAVE_PLEDGE */
5606 static void swrap_thread_prepare(void)
5611 static void swrap_thread_parent(void)
5616 static void swrap_thread_child(void)
5621 /****************************
5623 ***************************/
5624 void swrap_constructor(void)
5627 * If we hold a lock and the application forks, then the child
5628 * is not able to unlock the mutex and we are in a deadlock.
5629 * This should prevent such deadlocks.
5631 pthread_atfork(&swrap_thread_prepare,
5632 &swrap_thread_parent,
5633 &swrap_thread_child);
5636 /****************************
5638 ***************************/
5641 * This function is called when the library is unloaded and makes sure that
5642 * sockets get closed and the unix file for the socket are unlinked.
5644 void swrap_destructor(void)
5646 struct socket_info_fd *s = socket_fds;
5657 if (swrap.libc.handle != NULL) {
5658 dlclose(swrap.libc.handle);
5660 if (swrap.libc.socket_handle) {
5661 dlclose(swrap.libc.socket_handle);