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 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 256000
264 /* This limit is to avoid broadcast sendto() needing to stat too many
265 * files. It may be raised (with a performance cost) to up to 254
266 * without changing the format above */
267 #define MAX_WRAPPED_INTERFACES 40
269 struct swrap_address {
270 socklen_t sa_socklen;
273 struct sockaddr_in in;
275 struct sockaddr_in6 in6;
277 struct sockaddr_un un;
278 struct sockaddr_storage ss;
282 struct socket_info_fd {
283 struct socket_info_fd *prev, *next;
287 * Points to corresponding index in array of
288 * socket_info structures
297 unsigned int refcount;
312 /* The unix path so we can unlink it on close() */
313 struct sockaddr_un un_addr;
315 struct swrap_address bindname;
316 struct swrap_address myname;
317 struct swrap_address peername;
320 unsigned long pck_snd;
321 unsigned long pck_rcv;
325 static struct socket_info *sockets;
326 static size_t max_sockets = 0;
329 * While socket file descriptors are passed among different processes, the
330 * numerical value gets changed. So its better to store it locally to each
331 * process rather than including it within socket_info which will be shared.
333 static struct socket_info_fd *socket_fds;
335 /* The mutex for accessing the global libc.symbols */
336 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
338 /* Function prototypes */
340 bool socket_wrapper_enabled(void);
342 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
343 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
346 # define SWRAP_LOG(...)
349 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
350 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
352 static void swrap_log(enum swrap_dbglvl_e dbglvl,
354 const char *format, ...)
359 unsigned int lvl = 0;
361 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
366 va_start(va, format);
367 vsnprintf(buffer, sizeof(buffer), format, va);
372 case SWRAP_LOG_ERROR:
374 "SWRAP_ERROR(%d) - %s: %s\n",
375 (int)getpid(), func, buffer);
379 "SWRAP_WARN(%d) - %s: %s\n",
380 (int)getpid(), func, buffer);
382 case SWRAP_LOG_DEBUG:
384 "SWRAP_DEBUG(%d) - %s: %s\n",
385 (int)getpid(), func, buffer);
387 case SWRAP_LOG_TRACE:
389 "SWRAP_TRACE(%d) - %s: %s\n",
390 (int)getpid(), func, buffer);
397 /*********************************************************
398 * SWRAP LOADING LIBC FUNCTIONS
399 *********************************************************/
404 typedef int (*__libc_accept4)(int sockfd,
405 struct sockaddr *addr,
409 typedef int (*__libc_accept)(int sockfd,
410 struct sockaddr *addr,
413 typedef int (*__libc_bind)(int sockfd,
414 const struct sockaddr *addr,
416 typedef int (*__libc_close)(int fd);
417 typedef int (*__libc_connect)(int sockfd,
418 const struct sockaddr *addr,
420 typedef int (*__libc_dup)(int fd);
421 typedef int (*__libc_dup2)(int oldfd, int newfd);
422 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
423 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
425 typedef int (*__libc_eventfd)(int count, int flags);
427 typedef int (*__libc_getpeername)(int sockfd,
428 struct sockaddr *addr,
430 typedef int (*__libc_getsockname)(int sockfd,
431 struct sockaddr *addr,
433 typedef int (*__libc_getsockopt)(int sockfd,
438 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
439 typedef int (*__libc_listen)(int sockfd, int backlog);
440 typedef int (*__libc_open)(const char *pathname, int flags, mode_t mode);
441 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
442 typedef int (*__libc_pipe)(int pipefd[2]);
443 typedef int (*__libc_read)(int fd, void *buf, size_t count);
444 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
445 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
446 typedef int (*__libc_recvfrom)(int sockfd,
450 struct sockaddr *src_addr,
452 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
453 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
454 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
455 typedef int (*__libc_sendto)(int sockfd,
459 const struct sockaddr *dst_addr,
461 typedef int (*__libc_setsockopt)(int sockfd,
467 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
469 typedef int (*__libc_socket)(int domain, int type, int protocol);
470 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
471 #ifdef HAVE_TIMERFD_CREATE
472 typedef int (*__libc_timerfd_create)(int clockid, int flags);
474 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
475 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
477 #define SWRAP_SYMBOL_ENTRY(i) \
483 struct swrap_libc_symbols {
485 SWRAP_SYMBOL_ENTRY(accept4);
487 SWRAP_SYMBOL_ENTRY(accept);
489 SWRAP_SYMBOL_ENTRY(bind);
490 SWRAP_SYMBOL_ENTRY(close);
491 SWRAP_SYMBOL_ENTRY(connect);
492 SWRAP_SYMBOL_ENTRY(dup);
493 SWRAP_SYMBOL_ENTRY(dup2);
494 SWRAP_SYMBOL_ENTRY(fcntl);
495 SWRAP_SYMBOL_ENTRY(fopen);
497 SWRAP_SYMBOL_ENTRY(eventfd);
499 SWRAP_SYMBOL_ENTRY(getpeername);
500 SWRAP_SYMBOL_ENTRY(getsockname);
501 SWRAP_SYMBOL_ENTRY(getsockopt);
502 SWRAP_SYMBOL_ENTRY(ioctl);
503 SWRAP_SYMBOL_ENTRY(listen);
504 SWRAP_SYMBOL_ENTRY(open);
505 SWRAP_SYMBOL_ENTRY(openat);
506 SWRAP_SYMBOL_ENTRY(pipe);
507 SWRAP_SYMBOL_ENTRY(read);
508 SWRAP_SYMBOL_ENTRY(readv);
509 SWRAP_SYMBOL_ENTRY(recv);
510 SWRAP_SYMBOL_ENTRY(recvfrom);
511 SWRAP_SYMBOL_ENTRY(recvmsg);
512 SWRAP_SYMBOL_ENTRY(send);
513 SWRAP_SYMBOL_ENTRY(sendmsg);
514 SWRAP_SYMBOL_ENTRY(sendto);
515 SWRAP_SYMBOL_ENTRY(setsockopt);
517 SWRAP_SYMBOL_ENTRY(signalfd);
519 SWRAP_SYMBOL_ENTRY(socket);
520 SWRAP_SYMBOL_ENTRY(socketpair);
521 #ifdef HAVE_TIMERFD_CREATE
522 SWRAP_SYMBOL_ENTRY(timerfd_create);
524 SWRAP_SYMBOL_ENTRY(write);
525 SWRAP_SYMBOL_ENTRY(writev);
532 struct swrap_libc_symbols symbols;
536 static struct swrap swrap;
539 static const char *socket_wrapper_dir(void);
541 #define LIBC_NAME "libc.so"
550 static const char *swrap_str_lib(enum swrap_lib lib)
557 case SWRAP_LIBSOCKET:
561 /* Compiler would warn us about unhandled enum value if we get here */
566 static void *swrap_load_lib_handle(enum swrap_lib lib)
568 int flags = RTLD_LAZY;
573 flags |= RTLD_DEEPBIND;
579 case SWRAP_LIBSOCKET:
580 #ifdef HAVE_LIBSOCKET
581 handle = swrap.libc.socket_handle;
582 if (handle == NULL) {
583 for (i = 10; i >= 0; i--) {
584 char soname[256] = {0};
586 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
587 handle = dlopen(soname, flags);
588 if (handle != NULL) {
593 swrap.libc.socket_handle = handle;
599 handle = swrap.libc.handle;
601 if (handle == NULL) {
602 handle = dlopen(LIBC_SO, flags);
604 swrap.libc.handle = handle;
607 if (handle == NULL) {
608 for (i = 10; i >= 0; i--) {
609 char soname[256] = {0};
611 snprintf(soname, sizeof(soname), "libc.so.%d", i);
612 handle = dlopen(soname, flags);
613 if (handle != NULL) {
618 swrap.libc.handle = handle;
623 if (handle == NULL) {
625 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
627 SWRAP_LOG(SWRAP_LOG_ERROR,
628 "Failed to dlopen library: %s\n",
637 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
642 handle = swrap_load_lib_handle(lib);
644 func = dlsym(handle, fn_name);
646 SWRAP_LOG(SWRAP_LOG_ERROR,
647 "Failed to find %s: %s\n",
653 SWRAP_LOG(SWRAP_LOG_TRACE,
661 #define swrap_bind_symbol_libc(sym_name) \
662 SWRAP_LOCK(libc_symbol_binding); \
663 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
664 swrap.libc.symbols._libc_##sym_name.obj = \
665 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
667 SWRAP_UNLOCK(libc_symbol_binding)
669 #define swrap_bind_symbol_libsocket(sym_name) \
670 SWRAP_LOCK(libc_symbol_binding); \
671 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
672 swrap.libc.symbols._libc_##sym_name.obj = \
673 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
675 SWRAP_UNLOCK(libc_symbol_binding)
677 #define swrap_bind_symbol_libnsl(sym_name) \
678 SWRAP_LOCK(libc_symbol_binding); \
679 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
680 swrap.libc.symbols._libc_##sym_name.obj = \
681 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
683 SWRAP_UNLOCK(libc_symbol_binding)
688 * Functions especially from libc need to be loaded individually, you can't load
689 * all at once or gdb will segfault at startup. The same applies to valgrind and
690 * has probably something todo with with the linker.
691 * So we need load each function at the point it is called the first time.
694 static int libc_accept4(int sockfd,
695 struct sockaddr *addr,
699 swrap_bind_symbol_libsocket(accept4);
701 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
704 #else /* HAVE_ACCEPT4 */
706 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
708 swrap_bind_symbol_libsocket(accept);
710 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
712 #endif /* HAVE_ACCEPT4 */
714 static int libc_bind(int sockfd,
715 const struct sockaddr *addr,
718 swrap_bind_symbol_libsocket(bind);
720 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
723 static int libc_close(int fd)
725 swrap_bind_symbol_libc(close);
727 return swrap.libc.symbols._libc_close.f(fd);
730 static int libc_connect(int sockfd,
731 const struct sockaddr *addr,
734 swrap_bind_symbol_libsocket(connect);
736 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
739 static int libc_dup(int fd)
741 swrap_bind_symbol_libc(dup);
743 return swrap.libc.symbols._libc_dup.f(fd);
746 static int libc_dup2(int oldfd, int newfd)
748 swrap_bind_symbol_libc(dup2);
750 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
754 static int libc_eventfd(int count, int flags)
756 swrap_bind_symbol_libc(eventfd);
758 return swrap.libc.symbols._libc_eventfd.f(count, flags);
762 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
763 static int libc_vfcntl(int fd, int cmd, va_list ap)
769 swrap_bind_symbol_libc(fcntl);
771 for (i = 0; i < 4; i++) {
772 args[i] = va_arg(ap, long int);
775 rc = swrap.libc.symbols._libc_fcntl.f(fd,
785 static int libc_getpeername(int sockfd,
786 struct sockaddr *addr,
789 swrap_bind_symbol_libsocket(getpeername);
791 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
794 static int libc_getsockname(int sockfd,
795 struct sockaddr *addr,
798 swrap_bind_symbol_libsocket(getsockname);
800 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
803 static int libc_getsockopt(int sockfd,
809 swrap_bind_symbol_libsocket(getsockopt);
811 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
818 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
819 static int libc_vioctl(int d, unsigned long int request, va_list ap)
825 swrap_bind_symbol_libc(ioctl);
827 for (i = 0; i < 4; i++) {
828 args[i] = va_arg(ap, long int);
831 rc = swrap.libc.symbols._libc_ioctl.f(d,
841 static int libc_listen(int sockfd, int backlog)
843 swrap_bind_symbol_libsocket(listen);
845 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
848 static FILE *libc_fopen(const char *name, const char *mode)
850 swrap_bind_symbol_libc(fopen);
852 return swrap.libc.symbols._libc_fopen.f(name, mode);
855 static int libc_vopen(const char *pathname, int flags, va_list ap)
860 swrap_bind_symbol_libc(open);
862 mode = va_arg(ap, long int);
864 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
869 static int libc_open(const char *pathname, int flags, ...)
875 fd = libc_vopen(pathname, flags, ap);
881 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
886 swrap_bind_symbol_libc(openat);
888 mode = va_arg(ap, long int);
890 fd = swrap.libc.symbols._libc_openat.f(dirfd, path, flags, (mode_t)mode);
896 static int libc_openat(int dirfd, const char *path, int flags, ...)
902 fd = libc_vopenat(dirfd, path, flags, ap);
909 static int libc_pipe(int pipefd[2])
911 swrap_bind_symbol_libsocket(pipe);
913 return swrap.libc.symbols._libc_pipe.f(pipefd);
916 static int libc_read(int fd, void *buf, size_t count)
918 swrap_bind_symbol_libc(read);
920 return swrap.libc.symbols._libc_read.f(fd, buf, count);
923 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
925 swrap_bind_symbol_libsocket(readv);
927 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
930 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
932 swrap_bind_symbol_libsocket(recv);
934 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
937 static int libc_recvfrom(int sockfd,
941 struct sockaddr *src_addr,
944 swrap_bind_symbol_libsocket(recvfrom);
946 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
954 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
956 swrap_bind_symbol_libsocket(recvmsg);
958 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
961 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
963 swrap_bind_symbol_libsocket(send);
965 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
968 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
970 swrap_bind_symbol_libsocket(sendmsg);
972 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
975 static int libc_sendto(int sockfd,
979 const struct sockaddr *dst_addr,
982 swrap_bind_symbol_libsocket(sendto);
984 return swrap.libc.symbols._libc_sendto.f(sockfd,
992 static int libc_setsockopt(int sockfd,
998 swrap_bind_symbol_libsocket(setsockopt);
1000 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1007 #ifdef HAVE_SIGNALFD
1008 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1010 swrap_bind_symbol_libsocket(signalfd);
1012 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1016 static int libc_socket(int domain, int type, int protocol)
1018 swrap_bind_symbol_libsocket(socket);
1020 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1023 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1025 swrap_bind_symbol_libsocket(socketpair);
1027 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1030 #ifdef HAVE_TIMERFD_CREATE
1031 static int libc_timerfd_create(int clockid, int flags)
1033 swrap_bind_symbol_libc(timerfd_create);
1035 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1039 static ssize_t libc_write(int fd, const void *buf, size_t count)
1041 swrap_bind_symbol_libc(write);
1043 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1046 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1048 swrap_bind_symbol_libsocket(writev);
1050 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1053 /*********************************************************
1054 * SWRAP HELPER FUNCTIONS
1055 *********************************************************/
1061 static const struct in6_addr *swrap_ipv6(void)
1063 static struct in6_addr v;
1064 static int initialized;
1072 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1081 static void set_port(int family, int prt, struct swrap_address *addr)
1085 addr->sa.in.sin_port = htons(prt);
1089 addr->sa.in6.sin6_port = htons(prt);
1095 static size_t socket_length(int family)
1099 return sizeof(struct sockaddr_in);
1102 return sizeof(struct sockaddr_in6);
1108 static const char *socket_wrapper_dir(void)
1110 const char *s = getenv("SOCKET_WRAPPER_DIR");
1114 /* TODO use realpath(3) here, when we add support for threads */
1115 if (strncmp(s, "./", 2) == 0) {
1119 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1123 static unsigned int socket_wrapper_mtu(void)
1125 static unsigned int max_mtu = 0;
1134 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1136 s = getenv("SOCKET_WRAPPER_MTU");
1141 tmp = strtol(s, &endp, 10);
1146 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1155 static size_t socket_wrapper_max_sockets(void)
1161 if (max_sockets != 0) {
1165 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1167 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1168 if (s == NULL || s[0] == '\0') {
1172 tmp = strtoul(s, &endp, 10);
1176 if (tmp == 0 || tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1177 SWRAP_LOG(SWRAP_LOG_ERROR,
1178 "Invalid number of sockets specified, using default.");
1188 static void socket_wrapper_init_sockets(void)
1192 if (sockets != NULL) {
1196 max_sockets = socket_wrapper_max_sockets();
1198 sockets = (struct socket_info *)calloc(max_sockets,
1199 sizeof(struct socket_info));
1201 if (sockets == NULL) {
1202 SWRAP_LOG(SWRAP_LOG_ERROR,
1203 "Failed to allocate sockets array.\n");
1209 for (i = 0; i < max_sockets; i++) {
1210 sockets[i].next_free = i+1;
1213 sockets[max_sockets-1].next_free = -1;
1216 bool socket_wrapper_enabled(void)
1218 const char *s = socket_wrapper_dir();
1224 socket_wrapper_init_sockets();
1229 static unsigned int socket_wrapper_default_iface(void)
1231 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1234 if (sscanf(s, "%u", &iface) == 1) {
1235 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1241 return 1;/* 127.0.0.1 */
1245 * Return the first free entry (if any) and make
1246 * it re-usable again (by nulling it out)
1248 static int socket_wrapper_first_free_index(void)
1252 if (first_free == -1) {
1256 next_free = sockets[first_free].next_free;
1257 ZERO_STRUCT(sockets[first_free]);
1258 sockets[first_free].next_free = next_free;
1263 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1270 p = strrchr(un->sun_path, '/');
1271 if (p) p++; else p = un->sun_path;
1273 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1278 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1281 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1292 case SOCKET_TYPE_CHAR_TCP:
1293 case SOCKET_TYPE_CHAR_UDP: {
1294 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1296 if ((*len) < sizeof(*in2)) {
1301 memset(in2, 0, sizeof(*in2));
1302 in2->sin_family = AF_INET;
1303 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1304 in2->sin_port = htons(prt);
1306 *len = sizeof(*in2);
1310 case SOCKET_TYPE_CHAR_TCP_V6:
1311 case SOCKET_TYPE_CHAR_UDP_V6: {
1312 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1314 if ((*len) < sizeof(*in2)) {
1319 memset(in2, 0, sizeof(*in2));
1320 in2->sin6_family = AF_INET6;
1321 in2->sin6_addr = *swrap_ipv6();
1322 in2->sin6_addr.s6_addr[15] = iface;
1323 in2->sin6_port = htons(prt);
1325 *len = sizeof(*in2);
1337 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1345 if (bcast) *bcast = 0;
1347 switch (inaddr->sa_family) {
1349 const struct sockaddr_in *in =
1350 (const struct sockaddr_in *)(const void *)inaddr;
1351 unsigned int addr = ntohl(in->sin_addr.s_addr);
1358 u_type = SOCKET_TYPE_CHAR_TCP;
1361 u_type = SOCKET_TYPE_CHAR_UDP;
1362 a_type = SOCKET_TYPE_CHAR_UDP;
1363 b_type = SOCKET_TYPE_CHAR_UDP;
1366 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1367 errno = ESOCKTNOSUPPORT;
1371 prt = ntohs(in->sin_port);
1372 if (a_type && addr == 0xFFFFFFFF) {
1373 /* 255.255.255.255 only udp */
1376 iface = socket_wrapper_default_iface();
1377 } else if (b_type && addr == 0x7FFFFFFF) {
1378 /* 127.255.255.255 only udp */
1381 iface = socket_wrapper_default_iface();
1382 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1386 iface = (addr & 0x000000FF);
1388 errno = ENETUNREACH;
1391 if (bcast) *bcast = is_bcast;
1396 const struct sockaddr_in6 *in =
1397 (const struct sockaddr_in6 *)(const void *)inaddr;
1398 struct in6_addr cmp1, cmp2;
1402 type = SOCKET_TYPE_CHAR_TCP_V6;
1405 type = SOCKET_TYPE_CHAR_UDP_V6;
1408 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1409 errno = ESOCKTNOSUPPORT;
1413 /* XXX no multicast/broadcast */
1415 prt = ntohs(in->sin6_port);
1417 cmp1 = *swrap_ipv6();
1418 cmp2 = in->sin6_addr;
1419 cmp2.s6_addr[15] = 0;
1420 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1421 iface = in->sin6_addr.s6_addr[15];
1423 errno = ENETUNREACH;
1431 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1432 errno = ENETUNREACH;
1437 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1443 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1444 socket_wrapper_dir());
1445 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1446 /* the caller need to do more processing */
1450 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1451 socket_wrapper_dir(), type, iface, prt);
1452 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1457 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1466 if (bcast) *bcast = 0;
1468 switch (si->family) {
1470 const struct sockaddr_in *in =
1471 (const struct sockaddr_in *)(const void *)inaddr;
1472 unsigned int addr = ntohl(in->sin_addr.s_addr);
1478 prt = ntohs(in->sin_port);
1482 u_type = SOCKET_TYPE_CHAR_TCP;
1483 d_type = SOCKET_TYPE_CHAR_TCP;
1486 u_type = SOCKET_TYPE_CHAR_UDP;
1487 d_type = SOCKET_TYPE_CHAR_UDP;
1488 a_type = SOCKET_TYPE_CHAR_UDP;
1489 b_type = SOCKET_TYPE_CHAR_UDP;
1492 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1493 errno = ESOCKTNOSUPPORT;
1501 iface = socket_wrapper_default_iface();
1502 } else if (a_type && addr == 0xFFFFFFFF) {
1503 /* 255.255.255.255 only udp */
1506 iface = socket_wrapper_default_iface();
1507 } else if (b_type && addr == 0x7FFFFFFF) {
1508 /* 127.255.255.255 only udp */
1511 iface = socket_wrapper_default_iface();
1512 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1516 iface = (addr & 0x000000FF);
1518 errno = EADDRNOTAVAIL;
1522 /* Store the bind address for connect() */
1523 if (si->bindname.sa_socklen == 0) {
1524 struct sockaddr_in bind_in;
1525 socklen_t blen = sizeof(struct sockaddr_in);
1527 ZERO_STRUCT(bind_in);
1528 bind_in.sin_family = in->sin_family;
1529 bind_in.sin_port = in->sin_port;
1530 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1532 si->bindname.sa_socklen = blen;
1533 memcpy(&si->bindname.sa.in, &bind_in, blen);
1540 const struct sockaddr_in6 *in =
1541 (const struct sockaddr_in6 *)(const void *)inaddr;
1542 struct in6_addr cmp1, cmp2;
1546 type = SOCKET_TYPE_CHAR_TCP_V6;
1549 type = SOCKET_TYPE_CHAR_UDP_V6;
1552 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1553 errno = ESOCKTNOSUPPORT;
1557 /* XXX no multicast/broadcast */
1559 prt = ntohs(in->sin6_port);
1561 cmp1 = *swrap_ipv6();
1562 cmp2 = in->sin6_addr;
1563 cmp2.s6_addr[15] = 0;
1564 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1565 iface = socket_wrapper_default_iface();
1566 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1567 iface = in->sin6_addr.s6_addr[15];
1569 errno = EADDRNOTAVAIL;
1573 /* Store the bind address for connect() */
1574 if (si->bindname.sa_socklen == 0) {
1575 struct sockaddr_in6 bind_in;
1576 socklen_t blen = sizeof(struct sockaddr_in6);
1578 ZERO_STRUCT(bind_in);
1579 bind_in.sin6_family = in->sin6_family;
1580 bind_in.sin6_port = in->sin6_port;
1582 bind_in.sin6_addr = *swrap_ipv6();
1583 bind_in.sin6_addr.s6_addr[15] = iface;
1585 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1586 si->bindname.sa_socklen = blen;
1593 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1594 errno = EADDRNOTAVAIL;
1599 if (bcast) *bcast = is_bcast;
1601 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1607 /* handle auto-allocation of ephemeral ports */
1608 for (prt = 5001; prt < 10000; prt++) {
1609 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1610 socket_wrapper_dir(), type, iface, prt);
1611 if (stat(un->sun_path, &st) == 0) continue;
1613 set_port(si->family, prt, &si->myname);
1614 set_port(si->family, prt, &si->bindname);
1624 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1625 socket_wrapper_dir(), type, iface, prt);
1626 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1630 static struct socket_info_fd *find_socket_info_fd(int fd)
1632 struct socket_info_fd *f;
1634 for (f = socket_fds; f; f = f->next) {
1643 static int find_socket_info_index(int fd)
1645 struct socket_info_fd *fi = find_socket_info_fd(fd);
1651 return fi->si_index;
1654 static struct socket_info *find_socket_info(int fd)
1656 int idx = find_socket_info_index(fd);
1662 return &sockets[idx];
1666 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1668 struct socket_info_fd *f;
1669 const struct socket_info *last_s = NULL;
1671 /* first catch invalid input */
1672 switch (sa->sa_family) {
1674 if (len < sizeof(struct sockaddr_in)) {
1680 if (len < sizeof(struct sockaddr_in6)) {
1690 for (f = socket_fds; f; f = f->next) {
1691 struct socket_info *s = &sockets[f->si_index];
1698 if (s->myname == NULL) {
1701 if (s->myname->sa_family != sa->sa_family) {
1704 switch (s->myname->sa_family) {
1706 struct sockaddr_in *sin1, *sin2;
1708 sin1 = (struct sockaddr_in *)s->myname;
1709 sin2 = (struct sockaddr_in *)sa;
1711 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1714 if (sin1->sin_port != sin2->sin_port) {
1717 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1727 struct sockaddr_in6 *sin1, *sin2;
1729 sin1 = (struct sockaddr_in6 *)s->myname;
1730 sin2 = (struct sockaddr_in6 *)sa;
1732 if (sin1->sin6_port != sin2->sin6_port) {
1735 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1757 static void swrap_remove_stale(int fd)
1759 struct socket_info_fd *fi = find_socket_info_fd(fd);
1760 struct socket_info *si;
1767 si_index = fi->si_index;
1769 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1770 SWRAP_DLIST_REMOVE(socket_fds, fi);
1773 si = &sockets[si_index];
1776 if (si->refcount > 0) {
1780 if (si->un_addr.sun_path[0] != '\0') {
1781 unlink(si->un_addr.sun_path);
1784 si->next_free = first_free;
1785 first_free = si_index;
1788 static int sockaddr_convert_to_un(struct socket_info *si,
1789 const struct sockaddr *in_addr,
1791 struct sockaddr_un *out_addr,
1795 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1797 (void) in_len; /* unused */
1799 if (out_addr == NULL) {
1803 out->sa_family = AF_UNIX;
1804 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1805 out->sa_len = sizeof(*out_addr);
1808 switch (in_addr->sa_family) {
1810 const struct sockaddr_in *sin;
1811 if (si->family != AF_INET) {
1814 if (in_len < sizeof(struct sockaddr_in)) {
1817 sin = (const struct sockaddr_in *)(const void *)in_addr;
1818 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1823 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1824 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1838 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1839 errno = ESOCKTNOSUPPORT;
1843 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1845 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1851 errno = EAFNOSUPPORT;
1852 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1856 static int sockaddr_convert_from_un(const struct socket_info *si,
1857 const struct sockaddr_un *in_addr,
1858 socklen_t un_addrlen,
1860 struct sockaddr *out_addr,
1861 socklen_t *out_addrlen)
1865 if (out_addr == NULL || out_addrlen == NULL)
1868 if (un_addrlen == 0) {
1883 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1884 errno = ESOCKTNOSUPPORT;
1887 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1888 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1889 out_addr->sa_len = *out_addrlen;
1896 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1897 errno = EAFNOSUPPORT;
1901 enum swrap_packet_type {
1903 SWRAP_CONNECT_UNREACH,
1911 SWRAP_SENDTO_UNREACH,
1922 struct swrap_file_hdr {
1924 uint16_t version_major;
1925 uint16_t version_minor;
1928 uint32_t frame_max_len;
1929 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1932 #define SWRAP_FILE_HDR_SIZE 24
1934 struct swrap_packet_frame {
1936 uint32_t micro_seconds;
1937 uint32_t recorded_length;
1938 uint32_t full_length;
1940 #define SWRAP_PACKET_FRAME_SIZE 16
1942 union swrap_packet_ip {
1946 uint16_t packet_length;
1947 uint16_t identification;
1952 uint16_t hdr_checksum;
1956 #define SWRAP_PACKET_IP_V4_SIZE 20
1959 uint8_t flow_label_high;
1960 uint16_t flow_label_low;
1961 uint16_t payload_length;
1962 uint8_t next_header;
1964 uint8_t src_addr[16];
1965 uint8_t dest_addr[16];
1967 #define SWRAP_PACKET_IP_V6_SIZE 40
1969 #define SWRAP_PACKET_IP_SIZE 40
1971 union swrap_packet_payload {
1973 uint16_t source_port;
1983 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1985 uint16_t source_port;
1990 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1997 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2004 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2006 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2008 #define SWRAP_PACKET_MIN_ALLOC \
2009 (SWRAP_PACKET_FRAME_SIZE + \
2010 SWRAP_PACKET_IP_SIZE + \
2011 SWRAP_PACKET_PAYLOAD_SIZE)
2013 static const char *swrap_pcap_init_file(void)
2015 static int initialized = 0;
2016 static const char *s = NULL;
2017 static const struct swrap_file_hdr h;
2018 static const struct swrap_packet_frame f;
2019 static const union swrap_packet_ip i;
2020 static const union swrap_packet_payload p;
2022 if (initialized == 1) {
2028 * TODO: don't use the structs use plain buffer offsets
2029 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2031 * for now make sure we disable PCAP support
2032 * if the struct has alignment!
2034 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2037 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2040 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2043 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2046 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2049 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2052 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2055 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2058 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2061 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2065 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2069 if (strncmp(s, "./", 2) == 0) {
2075 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2076 const struct sockaddr *src,
2077 const struct sockaddr *dest,
2079 const uint8_t *payload,
2081 unsigned long tcp_seqno,
2082 unsigned long tcp_ack,
2083 unsigned char tcp_ctl,
2085 size_t *_packet_len)
2089 struct swrap_packet_frame *frame;
2090 union swrap_packet_ip *ip;
2091 union swrap_packet_payload *pay;
2094 size_t nonwire_len = sizeof(*frame);
2095 size_t wire_hdr_len = 0;
2096 size_t wire_len = 0;
2097 size_t ip_hdr_len = 0;
2098 size_t icmp_hdr_len = 0;
2099 size_t icmp_truncate_len = 0;
2100 uint8_t protocol = 0, icmp_protocol = 0;
2101 const struct sockaddr_in *src_in = NULL;
2102 const struct sockaddr_in *dest_in = NULL;
2104 const struct sockaddr_in6 *src_in6 = NULL;
2105 const struct sockaddr_in6 *dest_in6 = NULL;
2110 switch (src->sa_family) {
2112 src_in = (const struct sockaddr_in *)(const void *)src;
2113 dest_in = (const struct sockaddr_in *)(const void *)dest;
2114 src_port = src_in->sin_port;
2115 dest_port = dest_in->sin_port;
2116 ip_hdr_len = sizeof(ip->v4);
2120 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2121 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2122 src_port = src_in6->sin6_port;
2123 dest_port = dest_in6->sin6_port;
2124 ip_hdr_len = sizeof(ip->v6);
2131 switch (socket_type) {
2133 protocol = 0x06; /* TCP */
2134 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2135 wire_len = wire_hdr_len + payload_len;
2139 protocol = 0x11; /* UDP */
2140 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2141 wire_len = wire_hdr_len + payload_len;
2149 icmp_protocol = protocol;
2150 switch (src->sa_family) {
2152 protocol = 0x01; /* ICMPv4 */
2153 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2157 protocol = 0x3A; /* ICMPv6 */
2158 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2162 if (wire_len > 64 ) {
2163 icmp_truncate_len = wire_len - 64;
2165 wire_hdr_len += icmp_hdr_len;
2166 wire_len += icmp_hdr_len;
2169 packet_len = nonwire_len + wire_len;
2170 alloc_len = packet_len;
2171 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2172 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2175 base = (uint8_t *)calloc(1, alloc_len);
2182 frame = (struct swrap_packet_frame *)(void *)buf;
2183 frame->seconds = tval->tv_sec;
2184 frame->micro_seconds = tval->tv_usec;
2185 frame->recorded_length = wire_len - icmp_truncate_len;
2186 frame->full_length = wire_len - icmp_truncate_len;
2187 buf += SWRAP_PACKET_FRAME_SIZE;
2189 ip = (union swrap_packet_ip *)(void *)buf;
2190 switch (src->sa_family) {
2192 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2194 ip->v4.packet_length = htons(wire_len - icmp_truncate_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 = protocol;
2200 ip->v4.hdr_checksum = htons(0x0000);
2201 ip->v4.src_addr = src_in->sin_addr.s_addr;
2202 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2203 buf += SWRAP_PACKET_IP_V4_SIZE;
2207 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2208 ip->v6.flow_label_high = 0x00;
2209 ip->v6.flow_label_low = 0x0000;
2210 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2211 ip->v6.next_header = protocol;
2212 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2213 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2214 buf += SWRAP_PACKET_IP_V6_SIZE;
2220 pay = (union swrap_packet_payload *)(void *)buf;
2221 switch (src->sa_family) {
2223 pay->icmp4.type = 0x03; /* destination unreachable */
2224 pay->icmp4.code = 0x01; /* host unreachable */
2225 pay->icmp4.checksum = htons(0x0000);
2226 pay->icmp4.unused = htonl(0x00000000);
2227 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2229 /* set the ip header in the ICMP payload */
2230 ip = (union swrap_packet_ip *)(void *)buf;
2231 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2233 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2234 ip->v4.identification = htons(0xFFFF);
2235 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2236 ip->v4.fragment = htons(0x0000);
2238 ip->v4.protocol = icmp_protocol;
2239 ip->v4.hdr_checksum = htons(0x0000);
2240 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2241 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2242 buf += SWRAP_PACKET_IP_V4_SIZE;
2244 src_port = dest_in->sin_port;
2245 dest_port = src_in->sin_port;
2249 pay->icmp6.type = 0x01; /* destination unreachable */
2250 pay->icmp6.code = 0x03; /* address unreachable */
2251 pay->icmp6.checksum = htons(0x0000);
2252 pay->icmp6.unused = htonl(0x00000000);
2253 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2255 /* set the ip header in the ICMP payload */
2256 ip = (union swrap_packet_ip *)(void *)buf;
2257 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2258 ip->v6.flow_label_high = 0x00;
2259 ip->v6.flow_label_low = 0x0000;
2260 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2261 ip->v6.next_header = protocol;
2262 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2263 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2264 buf += SWRAP_PACKET_IP_V6_SIZE;
2266 src_port = dest_in6->sin6_port;
2267 dest_port = src_in6->sin6_port;
2273 pay = (union swrap_packet_payload *)(void *)buf;
2275 switch (socket_type) {
2277 pay->tcp.source_port = src_port;
2278 pay->tcp.dest_port = dest_port;
2279 pay->tcp.seq_num = htonl(tcp_seqno);
2280 pay->tcp.ack_num = htonl(tcp_ack);
2281 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2282 pay->tcp.control = tcp_ctl;
2283 pay->tcp.window = htons(0x7FFF);
2284 pay->tcp.checksum = htons(0x0000);
2285 pay->tcp.urg = htons(0x0000);
2286 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2291 pay->udp.source_port = src_port;
2292 pay->udp.dest_port = dest_port;
2293 pay->udp.length = htons(8 + payload_len);
2294 pay->udp.checksum = htons(0x0000);
2295 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2300 if (payload && payload_len > 0) {
2301 memcpy(buf, payload, payload_len);
2304 *_packet_len = packet_len - icmp_truncate_len;
2308 static int swrap_pcap_get_fd(const char *fname)
2312 if (fd != -1) return fd;
2314 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2316 struct swrap_file_hdr file_hdr;
2317 file_hdr.magic = 0xA1B2C3D4;
2318 file_hdr.version_major = 0x0002;
2319 file_hdr.version_minor = 0x0004;
2320 file_hdr.timezone = 0x00000000;
2321 file_hdr.sigfigs = 0x00000000;
2322 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2323 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2325 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2332 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2337 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2338 const struct sockaddr *addr,
2339 enum swrap_packet_type type,
2340 const void *buf, size_t len,
2343 const struct sockaddr *src_addr;
2344 const struct sockaddr *dest_addr;
2345 unsigned long tcp_seqno = 0;
2346 unsigned long tcp_ack = 0;
2347 unsigned char tcp_ctl = 0;
2348 int unreachable = 0;
2352 switch (si->family) {
2364 case SWRAP_CONNECT_SEND:
2365 if (si->type != SOCK_STREAM) return NULL;
2367 src_addr = &si->myname.sa.s;
2370 tcp_seqno = si->io.pck_snd;
2371 tcp_ack = si->io.pck_rcv;
2372 tcp_ctl = 0x02; /* SYN */
2374 si->io.pck_snd += 1;
2378 case SWRAP_CONNECT_RECV:
2379 if (si->type != SOCK_STREAM) return NULL;
2381 dest_addr = &si->myname.sa.s;
2384 tcp_seqno = si->io.pck_rcv;
2385 tcp_ack = si->io.pck_snd;
2386 tcp_ctl = 0x12; /** SYN,ACK */
2388 si->io.pck_rcv += 1;
2392 case SWRAP_CONNECT_UNREACH:
2393 if (si->type != SOCK_STREAM) return NULL;
2395 dest_addr = &si->myname.sa.s;
2398 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2399 tcp_seqno = si->io.pck_snd - 1;
2400 tcp_ack = si->io.pck_rcv;
2401 tcp_ctl = 0x02; /* SYN */
2406 case SWRAP_CONNECT_ACK:
2407 if (si->type != SOCK_STREAM) return NULL;
2409 src_addr = &si->myname.sa.s;
2412 tcp_seqno = si->io.pck_snd;
2413 tcp_ack = si->io.pck_rcv;
2414 tcp_ctl = 0x10; /* ACK */
2418 case SWRAP_ACCEPT_SEND:
2419 if (si->type != SOCK_STREAM) return NULL;
2421 dest_addr = &si->myname.sa.s;
2424 tcp_seqno = si->io.pck_rcv;
2425 tcp_ack = si->io.pck_snd;
2426 tcp_ctl = 0x02; /* SYN */
2428 si->io.pck_rcv += 1;
2432 case SWRAP_ACCEPT_RECV:
2433 if (si->type != SOCK_STREAM) return NULL;
2435 src_addr = &si->myname.sa.s;
2438 tcp_seqno = si->io.pck_snd;
2439 tcp_ack = si->io.pck_rcv;
2440 tcp_ctl = 0x12; /* SYN,ACK */
2442 si->io.pck_snd += 1;
2446 case SWRAP_ACCEPT_ACK:
2447 if (si->type != SOCK_STREAM) return NULL;
2449 dest_addr = &si->myname.sa.s;
2452 tcp_seqno = si->io.pck_rcv;
2453 tcp_ack = si->io.pck_snd;
2454 tcp_ctl = 0x10; /* ACK */
2459 src_addr = &si->myname.sa.s;
2460 dest_addr = &si->peername.sa.s;
2462 tcp_seqno = si->io.pck_snd;
2463 tcp_ack = si->io.pck_rcv;
2464 tcp_ctl = 0x18; /* PSH,ACK */
2466 si->io.pck_snd += len;
2470 case SWRAP_SEND_RST:
2471 dest_addr = &si->myname.sa.s;
2472 src_addr = &si->peername.sa.s;
2474 if (si->type == SOCK_DGRAM) {
2475 return swrap_pcap_marshall_packet(si,
2477 SWRAP_SENDTO_UNREACH,
2483 tcp_seqno = si->io.pck_rcv;
2484 tcp_ack = si->io.pck_snd;
2485 tcp_ctl = 0x14; /** RST,ACK */
2489 case SWRAP_PENDING_RST:
2490 dest_addr = &si->myname.sa.s;
2491 src_addr = &si->peername.sa.s;
2493 if (si->type == SOCK_DGRAM) {
2497 tcp_seqno = si->io.pck_rcv;
2498 tcp_ack = si->io.pck_snd;
2499 tcp_ctl = 0x14; /* RST,ACK */
2504 dest_addr = &si->myname.sa.s;
2505 src_addr = &si->peername.sa.s;
2507 tcp_seqno = si->io.pck_rcv;
2508 tcp_ack = si->io.pck_snd;
2509 tcp_ctl = 0x18; /* PSH,ACK */
2511 si->io.pck_rcv += len;
2515 case SWRAP_RECV_RST:
2516 dest_addr = &si->myname.sa.s;
2517 src_addr = &si->peername.sa.s;
2519 if (si->type == SOCK_DGRAM) {
2523 tcp_seqno = si->io.pck_rcv;
2524 tcp_ack = si->io.pck_snd;
2525 tcp_ctl = 0x14; /* RST,ACK */
2530 src_addr = &si->myname.sa.s;
2533 si->io.pck_snd += len;
2537 case SWRAP_SENDTO_UNREACH:
2538 dest_addr = &si->myname.sa.s;
2545 case SWRAP_RECVFROM:
2546 dest_addr = &si->myname.sa.s;
2549 si->io.pck_rcv += len;
2553 case SWRAP_CLOSE_SEND:
2554 if (si->type != SOCK_STREAM) return NULL;
2556 src_addr = &si->myname.sa.s;
2557 dest_addr = &si->peername.sa.s;
2559 tcp_seqno = si->io.pck_snd;
2560 tcp_ack = si->io.pck_rcv;
2561 tcp_ctl = 0x11; /* FIN, ACK */
2563 si->io.pck_snd += 1;
2567 case SWRAP_CLOSE_RECV:
2568 if (si->type != SOCK_STREAM) return NULL;
2570 dest_addr = &si->myname.sa.s;
2571 src_addr = &si->peername.sa.s;
2573 tcp_seqno = si->io.pck_rcv;
2574 tcp_ack = si->io.pck_snd;
2575 tcp_ctl = 0x11; /* FIN,ACK */
2577 si->io.pck_rcv += 1;
2581 case SWRAP_CLOSE_ACK:
2582 if (si->type != SOCK_STREAM) return NULL;
2584 src_addr = &si->myname.sa.s;
2585 dest_addr = &si->peername.sa.s;
2587 tcp_seqno = si->io.pck_snd;
2588 tcp_ack = si->io.pck_rcv;
2589 tcp_ctl = 0x10; /* ACK */
2596 swrapGetTimeOfDay(&tv);
2598 return swrap_pcap_packet_init(&tv,
2602 (const uint8_t *)buf,
2611 static void swrap_pcap_dump_packet(struct socket_info *si,
2612 const struct sockaddr *addr,
2613 enum swrap_packet_type type,
2614 const void *buf, size_t len)
2616 const char *file_name;
2618 size_t packet_len = 0;
2621 file_name = swrap_pcap_init_file();
2626 packet = swrap_pcap_marshall_packet(si,
2632 if (packet == NULL) {
2636 fd = swrap_pcap_get_fd(file_name);
2638 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2647 /****************************************************************************
2649 ***************************************************************************/
2651 #ifdef HAVE_SIGNALFD
2652 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2656 rc = libc_signalfd(fd, mask, flags);
2658 swrap_remove_stale(fd);
2664 int signalfd(int fd, const sigset_t *mask, int flags)
2666 return swrap_signalfd(fd, mask, flags);
2670 /****************************************************************************
2672 ***************************************************************************/
2674 static int swrap_socket(int family, int type, int protocol)
2676 struct socket_info *si;
2677 struct socket_info_fd *fi;
2680 int real_type = type;
2683 * Remove possible addition flags passed to socket() so
2684 * do not fail checking the type.
2685 * See https://lwn.net/Articles/281965/
2688 real_type &= ~SOCK_CLOEXEC;
2690 #ifdef SOCK_NONBLOCK
2691 real_type &= ~SOCK_NONBLOCK;
2694 if (!socket_wrapper_enabled()) {
2695 return libc_socket(family, type, protocol);
2706 #endif /* AF_NETLINK */
2709 #endif /* AF_PACKET */
2711 return libc_socket(family, type, protocol);
2713 errno = EAFNOSUPPORT;
2717 switch (real_type) {
2723 errno = EPROTONOSUPPORT;
2731 if (real_type == SOCK_STREAM) {
2736 if (real_type == SOCK_DGRAM) {
2741 errno = EPROTONOSUPPORT;
2746 * We must call libc_socket with type, from the caller, not the version
2747 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2749 fd = libc_socket(AF_UNIX, type, 0);
2755 /* Check if we have a stale fd and remove it */
2756 swrap_remove_stale(fd);
2758 idx = socket_wrapper_first_free_index();
2766 si->family = family;
2768 /* however, the rest of the socket_wrapper code expects just
2769 * the type, not the flags */
2770 si->type = real_type;
2771 si->protocol = protocol;
2774 * Setup myname so getsockname() can succeed to find out the socket
2777 switch(si->family) {
2779 struct sockaddr_in sin = {
2780 .sin_family = AF_INET,
2783 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2784 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2788 struct sockaddr_in6 sin6 = {
2789 .sin6_family = AF_INET6,
2792 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2793 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2801 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2808 first_free = si->next_free;
2814 SWRAP_DLIST_ADD(socket_fds, fi);
2816 SWRAP_LOG(SWRAP_LOG_TRACE,
2817 "Created %s socket for protocol %s",
2818 si->family == AF_INET ? "IPv4" : "IPv6",
2819 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2824 int socket(int family, int type, int protocol)
2826 return swrap_socket(family, type, protocol);
2829 /****************************************************************************
2831 ***************************************************************************/
2833 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2837 rc = libc_socketpair(family, type, protocol, sv);
2839 swrap_remove_stale(sv[0]);
2840 swrap_remove_stale(sv[1]);
2846 int socketpair(int family, int type, int protocol, int sv[2])
2848 return swrap_socketpair(family, type, protocol, sv);
2851 /****************************************************************************
2853 ***************************************************************************/
2855 #ifdef HAVE_TIMERFD_CREATE
2856 static int swrap_timerfd_create(int clockid, int flags)
2860 fd = libc_timerfd_create(clockid, flags);
2862 swrap_remove_stale(fd);
2868 int timerfd_create(int clockid, int flags)
2870 return swrap_timerfd_create(clockid, flags);
2874 /****************************************************************************
2876 ***************************************************************************/
2878 static int swrap_pipe(int pipefd[2])
2882 rc = libc_pipe(pipefd);
2884 swrap_remove_stale(pipefd[0]);
2885 swrap_remove_stale(pipefd[1]);
2891 int pipe(int pipefd[2])
2893 return swrap_pipe(pipefd);
2896 /****************************************************************************
2898 ***************************************************************************/
2900 static int swrap_accept(int s,
2901 struct sockaddr *addr,
2905 struct socket_info *parent_si, *child_si;
2906 struct socket_info_fd *child_fi;
2909 struct swrap_address un_addr = {
2910 .sa_socklen = sizeof(struct sockaddr_un),
2912 struct swrap_address un_my_addr = {
2913 .sa_socklen = sizeof(struct sockaddr_un),
2915 struct swrap_address in_addr = {
2916 .sa_socklen = sizeof(struct sockaddr_storage),
2918 struct swrap_address in_my_addr = {
2919 .sa_socklen = sizeof(struct sockaddr_storage),
2923 parent_si = find_socket_info(s);
2926 return libc_accept4(s, addr, addrlen, flags);
2929 return libc_accept(s, addr, addrlen);
2934 * assume out sockaddr have the same size as the in parent
2937 in_addr.sa_socklen = socket_length(parent_si->family);
2938 if (in_addr.sa_socklen <= 0) {
2944 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2947 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2950 if (errno == ENOTSOCK) {
2951 /* Remove stale fds */
2952 swrap_remove_stale(s);
2959 ret = sockaddr_convert_from_un(parent_si,
2964 &in_addr.sa_socklen);
2970 idx = socket_wrapper_first_free_index();
2976 child_si = &sockets[idx];
2978 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2979 if (child_fi == NULL) {
2987 child_si->family = parent_si->family;
2988 child_si->type = parent_si->type;
2989 child_si->protocol = parent_si->protocol;
2990 child_si->bound = 1;
2991 child_si->is_server = 1;
2992 child_si->connected = 1;
2994 child_si->peername = (struct swrap_address) {
2995 .sa_socklen = in_addr.sa_socklen,
2997 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2999 if (addr != NULL && addrlen != NULL) {
3000 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3002 memcpy(addr, &in_addr.sa.ss, copy_len);
3004 *addrlen = in_addr.sa_socklen;
3007 ret = libc_getsockname(fd,
3009 &un_my_addr.sa_socklen);
3016 ret = sockaddr_convert_from_un(child_si,
3018 un_my_addr.sa_socklen,
3021 &in_my_addr.sa_socklen);
3028 SWRAP_LOG(SWRAP_LOG_TRACE,
3029 "accept() path=%s, fd=%d",
3030 un_my_addr.sa.un.sun_path, s);
3032 child_si->myname = (struct swrap_address) {
3033 .sa_socklen = in_my_addr.sa_socklen,
3035 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3037 child_si->refcount = 1;
3038 first_free = child_si->next_free;
3039 child_si->next_free = 0;
3041 child_fi->si_index = idx;
3043 SWRAP_DLIST_ADD(socket_fds, child_fi);
3046 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3047 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3048 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3055 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3057 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3061 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3062 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3064 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3067 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3070 static int autobind_start_init;
3071 static int autobind_start;
3073 /* using sendto() or connect() on an unbound socket would give the
3074 recipient no way to reply, as unlike UDP and TCP, a unix domain
3075 socket can't auto-assign ephemeral port numbers, so we need to
3077 Note: this might change the family from ipv6 to ipv4
3079 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3081 struct swrap_address un_addr = {
3082 .sa_socklen = sizeof(struct sockaddr_un),
3090 if (autobind_start_init != 1) {
3091 autobind_start_init = 1;
3092 autobind_start = getpid();
3093 autobind_start %= 50000;
3094 autobind_start += 10000;
3097 un_addr.sa.un.sun_family = AF_UNIX;
3101 struct sockaddr_in in;
3105 type = SOCKET_TYPE_CHAR_TCP;
3108 type = SOCKET_TYPE_CHAR_UDP;
3111 errno = ESOCKTNOSUPPORT;
3115 memset(&in, 0, sizeof(in));
3116 in.sin_family = AF_INET;
3117 in.sin_addr.s_addr = htonl(127<<24 |
3118 socket_wrapper_default_iface());
3120 si->myname = (struct swrap_address) {
3121 .sa_socklen = sizeof(in),
3123 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3128 struct sockaddr_in6 in6;
3130 if (si->family != family) {
3131 errno = ENETUNREACH;
3137 type = SOCKET_TYPE_CHAR_TCP_V6;
3140 type = SOCKET_TYPE_CHAR_UDP_V6;
3143 errno = ESOCKTNOSUPPORT;
3147 memset(&in6, 0, sizeof(in6));
3148 in6.sin6_family = AF_INET6;
3149 in6.sin6_addr = *swrap_ipv6();
3150 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3152 si->myname = (struct swrap_address) {
3153 .sa_socklen = sizeof(in6),
3155 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3160 errno = ESOCKTNOSUPPORT;
3164 if (autobind_start > 60000) {
3165 autobind_start = 10000;
3168 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3169 port = autobind_start + i;
3170 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3171 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3172 type, socket_wrapper_default_iface(), port);
3173 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3175 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3176 if (ret == -1) return ret;
3178 si->un_addr = un_addr.sa.un;
3181 autobind_start = port + 1;
3184 if (i == SOCKET_MAX_SOCKETS) {
3185 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3186 "interface "SOCKET_FORMAT,
3189 socket_wrapper_default_iface(),
3195 si->family = family;
3196 set_port(si->family, port, &si->myname);
3201 /****************************************************************************
3203 ***************************************************************************/
3205 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3209 struct swrap_address un_addr = {
3210 .sa_socklen = sizeof(struct sockaddr_un),
3212 struct socket_info *si = find_socket_info(s);
3216 return libc_connect(s, serv_addr, addrlen);
3219 if (si->bound == 0) {
3220 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3221 if (ret == -1) return -1;
3224 if (si->family != serv_addr->sa_family) {
3229 ret = sockaddr_convert_to_un(si, serv_addr,
3230 addrlen, &un_addr.sa.un, 0, &bcast);
3231 if (ret == -1) return -1;
3234 errno = ENETUNREACH;
3238 if (si->type == SOCK_DGRAM) {
3239 si->defer_connect = 1;
3242 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3244 ret = libc_connect(s,
3246 un_addr.sa_socklen);
3249 SWRAP_LOG(SWRAP_LOG_TRACE,
3250 "connect() path=%s, fd=%d",
3251 un_addr.sa.un.sun_path, s);
3254 /* to give better errors */
3255 if (ret == -1 && errno == ENOENT) {
3256 errno = EHOSTUNREACH;
3260 si->peername = (struct swrap_address) {
3261 .sa_socklen = addrlen,
3264 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3268 * When we connect() on a socket than we have to bind the
3269 * outgoing connection on the interface we use for the
3270 * transport. We already bound it on the right interface
3271 * but here we have to update the name so getsockname()
3272 * returns correct information.
3274 if (si->bindname.sa_socklen > 0) {
3275 si->myname = (struct swrap_address) {
3276 .sa_socklen = si->bindname.sa_socklen,
3279 memcpy(&si->myname.sa.ss,
3280 &si->bindname.sa.ss,
3281 si->bindname.sa_socklen);
3283 /* Cleanup bindname */
3284 si->bindname = (struct swrap_address) {
3289 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3290 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3292 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3298 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3300 return swrap_connect(s, serv_addr, addrlen);
3303 /****************************************************************************
3305 ***************************************************************************/
3307 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3310 struct swrap_address un_addr = {
3311 .sa_socklen = sizeof(struct sockaddr_un),
3313 struct socket_info *si = find_socket_info(s);
3320 return libc_bind(s, myaddr, addrlen);
3323 switch (si->family) {
3325 const struct sockaddr_in *sin;
3326 if (addrlen < sizeof(struct sockaddr_in)) {
3327 bind_error = EINVAL;
3331 sin = (const struct sockaddr_in *)(const void *)myaddr;
3333 if (sin->sin_family != AF_INET) {
3334 bind_error = EAFNOSUPPORT;
3337 /* special case for AF_UNSPEC */
3338 if (sin->sin_family == AF_UNSPEC &&
3339 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3348 const struct sockaddr_in6 *sin6;
3349 if (addrlen < sizeof(struct sockaddr_in6)) {
3350 bind_error = EINVAL;
3354 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3356 if (sin6->sin6_family != AF_INET6) {
3357 bind_error = EAFNOSUPPORT;
3364 bind_error = EINVAL;
3368 if (bind_error != 0) {
3374 in_use = check_addr_port_in_use(myaddr, addrlen);
3381 si->myname.sa_socklen = addrlen;
3382 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3384 ret = sockaddr_convert_to_un(si,
3390 if (ret == -1) return -1;
3392 unlink(un_addr.sa.un.sun_path);
3394 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3396 SWRAP_LOG(SWRAP_LOG_TRACE,
3397 "bind() path=%s, fd=%d",
3398 un_addr.sa.un.sun_path, s);
3407 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3409 return swrap_bind(s, myaddr, addrlen);
3412 /****************************************************************************
3414 ***************************************************************************/
3416 #ifdef HAVE_BINDRESVPORT
3417 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3419 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3421 struct swrap_address myaddr = {
3422 .sa_socklen = sizeof(struct sockaddr_storage),
3425 static uint16_t port;
3430 #define SWRAP_STARTPORT 600
3431 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3432 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3435 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3439 salen = myaddr.sa_socklen;
3442 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3448 memset(&myaddr.sa.ss, 0, salen);
3453 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3456 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3458 salen = sizeof(struct sockaddr_in);
3459 sinp->sin_port = htons(port);
3463 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3465 salen = sizeof(struct sockaddr_in6);
3466 sin6p->sin6_port = htons(port);
3470 errno = EAFNOSUPPORT;
3475 if (port > SWRAP_ENDPORT) {
3476 port = SWRAP_STARTPORT;
3479 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3480 if (rc == 0 || errno != EADDRINUSE) {
3488 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3490 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3494 /****************************************************************************
3496 ***************************************************************************/
3498 static int swrap_listen(int s, int backlog)
3501 struct socket_info *si = find_socket_info(s);
3504 return libc_listen(s, backlog);
3507 if (si->bound == 0) {
3508 ret = swrap_auto_bind(s, si, si->family);
3515 ret = libc_listen(s, backlog);
3520 int listen(int s, int backlog)
3522 return swrap_listen(s, backlog);
3525 /****************************************************************************
3527 ***************************************************************************/
3529 static FILE *swrap_fopen(const char *name, const char *mode)
3533 fp = libc_fopen(name, mode);
3535 int fd = fileno(fp);
3537 swrap_remove_stale(fd);
3543 FILE *fopen(const char *name, const char *mode)
3545 return swrap_fopen(name, mode);
3548 /****************************************************************************
3550 ***************************************************************************/
3552 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3556 ret = libc_vopen(pathname, flags, ap);
3559 * There are methods for closing descriptors (libc-internal code
3560 * paths, direct syscalls) which close descriptors in ways that
3561 * we can't intercept, so try to recover when we notice that
3564 swrap_remove_stale(ret);
3569 int open(const char *pathname, int flags, ...)
3574 va_start(ap, flags);
3575 fd = swrap_vopen(pathname, flags, ap);
3581 /****************************************************************************
3583 ***************************************************************************/
3585 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3589 ret = libc_vopenat(dirfd, path, flags, ap);
3592 * There are methods for closing descriptors (libc-internal code
3593 * paths, direct syscalls) which close descriptors in ways that
3594 * we can't intercept, so try to recover when we notice that
3597 swrap_remove_stale(ret);
3603 int openat(int dirfd, const char *path, int flags, ...)
3608 va_start(ap, flags);
3609 fd = swrap_vopenat(dirfd, path, flags, ap);
3615 /****************************************************************************
3617 ***************************************************************************/
3619 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3621 struct socket_info *si = find_socket_info(s);
3625 return libc_getpeername(s, name, addrlen);
3628 if (si->peername.sa_socklen == 0)
3634 len = MIN(*addrlen, si->peername.sa_socklen);
3639 memcpy(name, &si->peername.sa.ss, len);
3640 *addrlen = si->peername.sa_socklen;
3645 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3646 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3648 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3651 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3654 /****************************************************************************
3656 ***************************************************************************/
3658 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3660 struct socket_info *si = find_socket_info(s);
3664 return libc_getsockname(s, name, addrlen);
3667 len = MIN(*addrlen, si->myname.sa_socklen);
3672 memcpy(name, &si->myname.sa.ss, len);
3673 *addrlen = si->myname.sa_socklen;
3678 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3679 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3681 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3684 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3687 /****************************************************************************
3689 ***************************************************************************/
3692 # ifdef SO_PROTOTYPE /* The Solaris name */
3693 # define SO_PROTOCOL SO_PROTOTYPE
3694 # endif /* SO_PROTOTYPE */
3695 #endif /* SO_PROTOCOL */
3697 static int swrap_getsockopt(int s, int level, int optname,
3698 void *optval, socklen_t *optlen)
3700 struct socket_info *si = find_socket_info(s);
3703 return libc_getsockopt(s,
3710 if (level == SOL_SOCKET) {
3714 if (optval == NULL || optlen == NULL ||
3715 *optlen < (socklen_t)sizeof(int)) {
3720 *optlen = sizeof(int);
3721 *(int *)optval = si->family;
3723 #endif /* SO_DOMAIN */
3727 if (optval == NULL || optlen == NULL ||
3728 *optlen < (socklen_t)sizeof(int)) {
3733 *optlen = sizeof(int);
3734 *(int *)optval = si->protocol;
3736 #endif /* SO_PROTOCOL */
3738 if (optval == NULL || optlen == NULL ||
3739 *optlen < (socklen_t)sizeof(int)) {
3744 *optlen = sizeof(int);
3745 *(int *)optval = si->type;
3748 return libc_getsockopt(s,
3754 } else if (level == IPPROTO_TCP) {
3759 * This enables sending packets directly out over TCP.
3760 * As a unix socket is doing that any way, report it as
3763 if (optval == NULL || optlen == NULL ||
3764 *optlen < (socklen_t)sizeof(int)) {
3769 *optlen = sizeof(int);
3770 *(int *)optval = si->tcp_nodelay;
3773 #endif /* TCP_NODELAY */
3779 errno = ENOPROTOOPT;
3783 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3784 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3786 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3789 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3792 /****************************************************************************
3794 ***************************************************************************/
3796 static int swrap_setsockopt(int s, int level, int optname,
3797 const void *optval, socklen_t optlen)
3799 struct socket_info *si = find_socket_info(s);
3802 return libc_setsockopt(s,
3809 if (level == SOL_SOCKET) {
3810 return libc_setsockopt(s,
3815 } else if (level == IPPROTO_TCP) {
3822 * This enables sending packets directly out over TCP.
3823 * A unix socket is doing that any way.
3825 if (optval == NULL || optlen == 0 ||
3826 optlen < (socklen_t)sizeof(int)) {
3831 i = *discard_const_p(int, optval);
3832 if (i != 0 && i != 1) {
3836 si->tcp_nodelay = i;
3840 #endif /* TCP_NODELAY */
3846 switch (si->family) {
3848 if (level == IPPROTO_IP) {
3850 if (optname == IP_PKTINFO) {
3851 si->pktinfo = AF_INET;
3853 #endif /* IP_PKTINFO */
3858 if (level == IPPROTO_IPV6) {
3859 #ifdef IPV6_RECVPKTINFO
3860 if (optname == IPV6_RECVPKTINFO) {
3861 si->pktinfo = AF_INET6;
3863 #endif /* IPV6_PKTINFO */
3868 errno = ENOPROTOOPT;
3873 int setsockopt(int s, int level, int optname,
3874 const void *optval, socklen_t optlen)
3876 return swrap_setsockopt(s, level, optname, optval, optlen);
3879 /****************************************************************************
3881 ***************************************************************************/
3883 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3885 struct socket_info *si = find_socket_info(s);
3891 return libc_vioctl(s, r, va);
3896 rc = libc_vioctl(s, r, va);
3900 value = *((int *)va_arg(ap, int *));
3902 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3903 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3904 } else if (value == 0) { /* END OF FILE */
3905 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3915 #ifdef HAVE_IOCTL_INT
3916 int ioctl(int s, int r, ...)
3918 int ioctl(int s, unsigned long int r, ...)
3926 rc = swrap_vioctl(s, (unsigned long int) r, va);
3937 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3940 # ifdef _ALIGN /* BSD */
3941 #define CMSG_ALIGN _ALIGN
3943 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3944 # endif /* _ALIGN */
3945 #endif /* CMSG_ALIGN */
3948 * @brief Add a cmsghdr to a msghdr.
3950 * This is an function to add any type of cmsghdr. It will operate on the
3951 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3952 * the buffer position after the added cmsg element. Hence, this function is
3953 * intended to be used with an intermediate msghdr and not on the original
3954 * one handed in by the client.
3956 * @param[in] msg The msghdr to which to add the cmsg.
3958 * @param[in] level The cmsg level to set.
3960 * @param[in] type The cmsg type to set.
3962 * @param[in] data The cmsg data to set.
3964 * @param[in] len the length of the data to set.
3966 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3972 size_t cmlen = CMSG_LEN(len);
3973 size_t cmspace = CMSG_SPACE(len);
3974 uint8_t cmbuf[cmspace];
3975 void *cast_ptr = (void *)cmbuf;
3976 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3979 memset(cmbuf, 0, cmspace);
3981 if (msg->msg_controllen < cmlen) {
3982 cmlen = msg->msg_controllen;
3983 msg->msg_flags |= MSG_CTRUNC;
3986 if (msg->msg_controllen < cmspace) {
3987 cmspace = msg->msg_controllen;
3991 * We copy the full input data into an intermediate cmsghdr first
3992 * in order to more easily cope with truncation.
3994 cm->cmsg_len = cmlen;
3995 cm->cmsg_level = level;
3996 cm->cmsg_type = type;
3997 memcpy(CMSG_DATA(cm), data, len);
4000 * We now copy the possibly truncated buffer.
4001 * We copy cmlen bytes, but consume cmspace bytes,
4002 * leaving the possible padding uninitialiazed.
4004 p = (uint8_t *)msg->msg_control;
4005 memcpy(p, cm, cmlen);
4007 msg->msg_control = p;
4008 msg->msg_controllen -= cmspace;
4013 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4016 /* Add packet info */
4017 switch (si->pktinfo) {
4018 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4020 struct sockaddr_in *sin;
4021 #if defined(HAVE_STRUCT_IN_PKTINFO)
4022 struct in_pktinfo pkt;
4023 #elif defined(IP_RECVDSTADDR)
4027 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4028 sin = &si->bindname.sa.in;
4030 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4033 sin = &si->myname.sa.in;
4038 #if defined(HAVE_STRUCT_IN_PKTINFO)
4039 pkt.ipi_ifindex = socket_wrapper_default_iface();
4040 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4041 #elif defined(IP_RECVDSTADDR)
4042 pkt = sin->sin_addr;
4045 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4050 #endif /* IP_PKTINFO */
4051 #if defined(HAVE_IPV6)
4053 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4054 struct sockaddr_in6 *sin6;
4055 struct in6_pktinfo pkt6;
4057 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4058 sin6 = &si->bindname.sa.in6;
4060 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4063 sin6 = &si->myname.sa.in6;
4068 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4069 pkt6.ipi6_addr = sin6->sin6_addr;
4071 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4072 &pkt6, sizeof(pkt6));
4073 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4077 #endif /* IPV6_PKTINFO */
4085 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4086 struct msghdr *omsg)
4090 if (si->pktinfo > 0) {
4091 rc = swrap_msghdr_add_pktinfo(si, omsg);
4097 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4099 size_t *cm_data_space);
4100 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4102 size_t *cm_data_space);
4104 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4106 size_t *cm_data_space) {
4107 struct cmsghdr *cmsg;
4111 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4115 for (cmsg = CMSG_FIRSTHDR(msg);
4117 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4118 switch (cmsg->cmsg_level) {
4120 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4125 rc = swrap_sendmsg_copy_cmsg(cmsg,
4135 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4137 size_t *cm_data_space)
4142 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4144 p = realloc((*cm_data), cmspace);
4150 p = (*cm_data) + (*cm_data_space);
4151 *cm_data_space = cmspace;
4153 memcpy(p, cmsg, cmsg->cmsg_len);
4158 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4160 size_t *cm_data_space);
4163 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4165 size_t *cm_data_space)
4169 switch(cmsg->cmsg_type) {
4172 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4179 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4191 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4193 size_t *cm_data_space)
4195 (void)cmsg; /* unused */
4196 (void)cm_data; /* unused */
4197 (void)cm_data_space; /* unused */
4200 * Passing a IP pktinfo to a unix socket might be rejected by the
4201 * Kernel, at least on FreeBSD. So skip this cmsg.
4205 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4207 static ssize_t swrap_sendmsg_before(int fd,
4208 struct socket_info *si,
4210 struct iovec *tmp_iov,
4211 struct sockaddr_un *tmp_un,
4212 const struct sockaddr_un **to_un,
4213 const struct sockaddr **to,
4233 if (!si->connected) {
4238 if (msg->msg_iovlen == 0) {
4242 mtu = socket_wrapper_mtu();
4243 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4245 nlen = len + msg->msg_iov[i].iov_len;
4250 msg->msg_iovlen = i;
4251 if (msg->msg_iovlen == 0) {
4252 *tmp_iov = msg->msg_iov[0];
4253 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4255 msg->msg_iov = tmp_iov;
4256 msg->msg_iovlen = 1;
4261 if (si->connected) {
4262 if (msg->msg_name != NULL) {
4264 * We are dealing with unix sockets and if we
4265 * are connected, we should only talk to the
4266 * connected unix path. Using the fd to send
4267 * to another server would be hard to achieve.
4269 msg->msg_name = NULL;
4270 msg->msg_namelen = 0;
4273 const struct sockaddr *msg_name;
4274 msg_name = (const struct sockaddr *)msg->msg_name;
4276 if (msg_name == NULL) {
4282 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4284 if (ret == -1) return -1;
4292 msg->msg_name = tmp_un;
4293 msg->msg_namelen = sizeof(*tmp_un);
4296 if (si->bound == 0) {
4297 ret = swrap_auto_bind(fd, si, si->family);
4299 if (errno == ENOTSOCK) {
4300 swrap_remove_stale(fd);
4303 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4309 if (!si->defer_connect) {
4313 ret = sockaddr_convert_to_un(si,
4315 si->peername.sa_socklen,
4319 if (ret == -1) return -1;
4321 ret = libc_connect(fd,
4322 (struct sockaddr *)(void *)tmp_un,
4325 /* to give better errors */
4326 if (ret == -1 && errno == ENOENT) {
4327 errno = EHOSTUNREACH;
4334 si->defer_connect = 0;
4337 errno = EHOSTUNREACH;
4341 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4342 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4343 uint8_t *cmbuf = NULL;
4346 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4353 msg->msg_controllen = 0;
4354 msg->msg_control = NULL;
4355 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4356 memcpy(msg->msg_control, cmbuf, cmlen);
4357 msg->msg_controllen = cmlen;
4366 static void swrap_sendmsg_after(int fd,
4367 struct socket_info *si,
4369 const struct sockaddr *to,
4372 int saved_errno = errno;
4379 /* to give better errors */
4381 if (saved_errno == ENOENT) {
4382 saved_errno = EHOSTUNREACH;
4383 } else if (saved_errno == ENOTSOCK) {
4384 /* If the fd is not a socket, remove it */
4385 swrap_remove_stale(fd);
4389 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4390 avail += msg->msg_iov[i].iov_len;
4394 remain = MIN(80, avail);
4399 /* we capture it as one single packet */
4400 buf = (uint8_t *)malloc(remain);
4402 /* we just not capture the packet */
4403 errno = saved_errno;
4407 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4408 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4410 msg->msg_iov[i].iov_base,
4413 remain -= this_time;
4420 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4421 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4423 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4428 if (si->connected) {
4429 to = &si->peername.sa.s;
4432 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4433 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4435 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4441 errno = saved_errno;
4444 static int swrap_recvmsg_before(int fd,
4445 struct socket_info *si,
4447 struct iovec *tmp_iov)
4452 (void)fd; /* unused */
4457 if (!si->connected) {
4462 if (msg->msg_iovlen == 0) {
4466 mtu = socket_wrapper_mtu();
4467 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4469 nlen = len + msg->msg_iov[i].iov_len;
4474 msg->msg_iovlen = i;
4475 if (msg->msg_iovlen == 0) {
4476 *tmp_iov = msg->msg_iov[0];
4477 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4479 msg->msg_iov = tmp_iov;
4480 msg->msg_iovlen = 1;
4485 if (msg->msg_name == NULL) {
4490 if (msg->msg_iovlen == 0) {
4494 if (si->bound == 0) {
4495 ret = swrap_auto_bind(fd, si, si->family);
4498 * When attempting to read or write to a
4499 * descriptor, if an underlying autobind fails
4500 * because it's not a socket, stop intercepting
4501 * uses of that descriptor.
4503 if (errno == ENOTSOCK) {
4504 swrap_remove_stale(fd);
4507 SWRAP_LOG(SWRAP_LOG_ERROR,
4508 "swrap_recvmsg_before failed");
4515 errno = EHOSTUNREACH;
4522 static int swrap_recvmsg_after(int fd,
4523 struct socket_info *si,
4525 const struct sockaddr_un *un_addr,
4526 socklen_t un_addrlen,
4529 int saved_errno = errno;
4531 uint8_t *buf = NULL;
4537 /* to give better errors */
4539 if (saved_errno == ENOENT) {
4540 saved_errno = EHOSTUNREACH;
4541 } else if (saved_errno == ENOTSOCK) {
4542 /* If the fd is not a socket, remove it */
4543 swrap_remove_stale(fd);
4547 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4548 avail += msg->msg_iov[i].iov_len;
4551 /* Convert the socket address before we leave */
4552 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4553 rc = sockaddr_convert_from_un(si,
4570 remain = MIN(80, avail);
4575 /* we capture it as one single packet */
4576 buf = (uint8_t *)malloc(remain);
4578 /* we just not capture the packet */
4579 errno = saved_errno;
4583 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4584 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4586 msg->msg_iov[i].iov_base,
4589 remain -= this_time;
4594 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4595 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4596 } else if (ret == 0) { /* END OF FILE */
4597 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4598 } else if (ret > 0) {
4599 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4608 if (un_addr != NULL) {
4609 swrap_pcap_dump_packet(si,
4615 swrap_pcap_dump_packet(si,
4628 errno = saved_errno;
4630 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4632 msg->msg_controllen > 0 &&
4633 msg->msg_control != NULL) {
4634 rc = swrap_msghdr_add_socket_info(si, msg);
4644 /****************************************************************************
4646 ***************************************************************************/
4648 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4649 struct sockaddr *from, socklen_t *fromlen)
4651 struct swrap_address from_addr = {
4652 .sa_socklen = sizeof(struct sockaddr_un),
4655 struct socket_info *si = find_socket_info(s);
4656 struct swrap_address saddr = {
4657 .sa_socklen = sizeof(struct sockaddr_storage),
4664 return libc_recvfrom(s,
4676 if (from != NULL && fromlen != NULL) {
4677 msg.msg_name = from; /* optional address */
4678 msg.msg_namelen = *fromlen; /* size of address */
4680 msg.msg_name = &saddr.sa.s; /* optional address */
4681 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4683 msg.msg_iov = &tmp; /* scatter/gather array */
4684 msg.msg_iovlen = 1; /* # elements in msg_iov */
4685 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4686 msg.msg_control = NULL; /* ancillary data, see below */
4687 msg.msg_controllen = 0; /* ancillary data buffer len */
4688 msg.msg_flags = 0; /* flags on received message */
4691 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4696 buf = msg.msg_iov[0].iov_base;
4697 len = msg.msg_iov[0].iov_len;
4699 ret = libc_recvfrom(s,
4704 &from_addr.sa_socklen);
4709 tret = swrap_recvmsg_after(s,
4713 from_addr.sa_socklen,
4719 if (from != NULL && fromlen != NULL) {
4720 *fromlen = msg.msg_namelen;
4726 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4727 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4728 struct sockaddr *from, Psocklen_t fromlen)
4730 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4731 struct sockaddr *from, socklen_t *fromlen)
4734 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4737 /****************************************************************************
4739 ***************************************************************************/
4741 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4742 const struct sockaddr *to, socklen_t tolen)
4746 struct swrap_address un_addr = {
4747 .sa_socklen = sizeof(struct sockaddr_un),
4749 const struct sockaddr_un *to_un = NULL;
4752 struct socket_info *si = find_socket_info(s);
4756 return libc_sendto(s, buf, len, flags, to, tolen);
4759 tmp.iov_base = discard_const_p(char, buf);
4763 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4764 msg.msg_namelen = tolen; /* size of address */
4765 msg.msg_iov = &tmp; /* scatter/gather array */
4766 msg.msg_iovlen = 1; /* # elements in msg_iov */
4767 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4768 msg.msg_control = NULL; /* ancillary data, see below */
4769 msg.msg_controllen = 0; /* ancillary data buffer len */
4770 msg.msg_flags = 0; /* flags on received message */
4773 rc = swrap_sendmsg_before(s,
4785 buf = msg.msg_iov[0].iov_base;
4786 len = msg.msg_iov[0].iov_len;
4791 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4794 type = SOCKET_TYPE_CHAR_UDP;
4796 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4797 snprintf(un_addr.sa.un.sun_path,
4798 sizeof(un_addr.sa.un.sun_path),
4800 socket_wrapper_dir(), type, iface, prt);
4801 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4803 /* ignore the any errors in broadcast sends */
4809 un_addr.sa_socklen);
4812 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4818 * If it is a dgram socket and we are connected, don't include the
4821 if (si->type == SOCK_DGRAM && si->connected) {
4822 ret = libc_sendto(s,
4829 ret = libc_sendto(s,
4833 (struct sockaddr *)msg.msg_name,
4837 swrap_sendmsg_after(s, si, &msg, to, ret);
4842 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4843 const struct sockaddr *to, socklen_t tolen)
4845 return swrap_sendto(s, buf, len, flags, to, tolen);
4848 /****************************************************************************
4850 ***************************************************************************/
4852 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4854 struct socket_info *si;
4856 struct swrap_address saddr = {
4857 .sa_socklen = sizeof(struct sockaddr_storage),
4863 si = find_socket_info(s);
4865 return libc_recv(s, buf, len, flags);
4872 msg.msg_name = &saddr.sa.s; /* optional address */
4873 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4874 msg.msg_iov = &tmp; /* scatter/gather array */
4875 msg.msg_iovlen = 1; /* # elements in msg_iov */
4876 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4877 msg.msg_control = NULL; /* ancillary data, see below */
4878 msg.msg_controllen = 0; /* ancillary data buffer len */
4879 msg.msg_flags = 0; /* flags on received message */
4882 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4887 buf = msg.msg_iov[0].iov_base;
4888 len = msg.msg_iov[0].iov_len;
4890 ret = libc_recv(s, buf, len, flags);
4892 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4900 ssize_t recv(int s, void *buf, size_t len, int flags)
4902 return swrap_recv(s, buf, len, flags);
4905 /****************************************************************************
4907 ***************************************************************************/
4909 static ssize_t swrap_read(int s, void *buf, size_t len)
4911 struct socket_info *si;
4914 struct swrap_address saddr = {
4915 .sa_socklen = sizeof(struct sockaddr_storage),
4920 si = find_socket_info(s);
4922 return libc_read(s, buf, len);
4929 msg.msg_name = &saddr.sa.ss; /* optional address */
4930 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4931 msg.msg_iov = &tmp; /* scatter/gather array */
4932 msg.msg_iovlen = 1; /* # elements in msg_iov */
4933 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4934 msg.msg_control = NULL; /* ancillary data, see below */
4935 msg.msg_controllen = 0; /* ancillary data buffer len */
4936 msg.msg_flags = 0; /* flags on received message */
4939 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4941 if (tret == -ENOTSOCK) {
4942 return libc_read(s, buf, len);
4947 buf = msg.msg_iov[0].iov_base;
4948 len = msg.msg_iov[0].iov_len;
4950 ret = libc_read(s, buf, len);
4952 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4960 ssize_t read(int s, void *buf, size_t len)
4962 return swrap_read(s, buf, len);
4965 /****************************************************************************
4967 ***************************************************************************/
4969 static ssize_t swrap_write(int s, const void *buf, size_t len)
4973 struct sockaddr_un un_addr;
4976 struct socket_info *si;
4978 si = find_socket_info(s);
4980 return libc_write(s, buf, len);
4983 tmp.iov_base = discard_const_p(char, buf);
4987 msg.msg_name = NULL; /* optional address */
4988 msg.msg_namelen = 0; /* size of address */
4989 msg.msg_iov = &tmp; /* scatter/gather array */
4990 msg.msg_iovlen = 1; /* # elements in msg_iov */
4991 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4992 msg.msg_control = NULL; /* ancillary data, see below */
4993 msg.msg_controllen = 0; /* ancillary data buffer len */
4994 msg.msg_flags = 0; /* flags on received message */
4997 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5002 buf = msg.msg_iov[0].iov_base;
5003 len = msg.msg_iov[0].iov_len;
5005 ret = libc_write(s, buf, len);
5007 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5012 ssize_t write(int s, const void *buf, size_t len)
5014 return swrap_write(s, buf, len);
5017 /****************************************************************************
5019 ***************************************************************************/
5021 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5025 struct sockaddr_un un_addr;
5028 struct socket_info *si = find_socket_info(s);
5031 return libc_send(s, buf, len, flags);
5034 tmp.iov_base = discard_const_p(char, buf);
5038 msg.msg_name = NULL; /* optional address */
5039 msg.msg_namelen = 0; /* size of address */
5040 msg.msg_iov = &tmp; /* scatter/gather array */
5041 msg.msg_iovlen = 1; /* # elements in msg_iov */
5042 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5043 msg.msg_control = NULL; /* ancillary data, see below */
5044 msg.msg_controllen = 0; /* ancillary data buffer len */
5045 msg.msg_flags = 0; /* flags on received message */
5048 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5053 buf = msg.msg_iov[0].iov_base;
5054 len = msg.msg_iov[0].iov_len;
5056 ret = libc_send(s, buf, len, flags);
5058 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5063 ssize_t send(int s, const void *buf, size_t len, int flags)
5065 return swrap_send(s, buf, len, flags);
5068 /****************************************************************************
5070 ***************************************************************************/
5072 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5074 struct swrap_address from_addr = {
5075 .sa_socklen = sizeof(struct sockaddr_un),
5077 struct swrap_address convert_addr = {
5078 .sa_socklen = sizeof(struct sockaddr_storage),
5080 struct socket_info *si;
5083 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5084 size_t msg_ctrllen_filled;
5085 size_t msg_ctrllen_left;
5091 si = find_socket_info(s);
5093 return libc_recvmsg(s, omsg, flags);
5096 tmp.iov_base = NULL;
5100 msg.msg_name = &from_addr.sa; /* optional address */
5101 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5102 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5103 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5104 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5105 msg_ctrllen_filled = 0;
5106 msg_ctrllen_left = omsg->msg_controllen;
5108 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5109 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5110 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5113 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5118 ret = libc_recvmsg(s, &msg, flags);
5120 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5121 msg_ctrllen_filled += msg.msg_controllen;
5122 msg_ctrllen_left -= msg.msg_controllen;
5124 if (omsg->msg_control != NULL) {
5127 p = omsg->msg_control;
5128 p += msg_ctrllen_filled;
5130 msg.msg_control = p;
5131 msg.msg_controllen = msg_ctrllen_left;
5133 msg.msg_control = NULL;
5134 msg.msg_controllen = 0;
5139 * We convert the unix address to a IP address so we need a buffer
5140 * which can store the address in case of SOCK_DGRAM, see below.
5142 msg.msg_name = &convert_addr.sa;
5143 msg.msg_namelen = convert_addr.sa_socklen;
5145 rc = swrap_recvmsg_after(s,
5149 from_addr.sa_socklen,
5155 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5156 if (omsg->msg_control != NULL) {
5157 /* msg.msg_controllen = space left */
5158 msg_ctrllen_left = msg.msg_controllen;
5159 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5162 /* Update the original message length */
5163 omsg->msg_controllen = msg_ctrllen_filled;
5164 omsg->msg_flags = msg.msg_flags;
5166 omsg->msg_iovlen = msg.msg_iovlen;
5171 * The msg_name field points to a caller-allocated buffer that is
5172 * used to return the source address if the socket is unconnected. The
5173 * caller should set msg_namelen to the size of this buffer before this
5174 * call; upon return from a successful call, msg_name will contain the
5175 * length of the returned address. If the application does not need
5176 * to know the source address, msg_name can be specified as NULL.
5178 if (si->type == SOCK_STREAM) {
5179 omsg->msg_namelen = 0;
5180 } else if (omsg->msg_name != NULL &&
5181 omsg->msg_namelen != 0 &&
5182 omsg->msg_namelen >= msg.msg_namelen) {
5183 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5184 omsg->msg_namelen = msg.msg_namelen;
5190 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5192 return swrap_recvmsg(sockfd, msg, flags);
5195 /****************************************************************************
5197 ***************************************************************************/
5199 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5203 struct sockaddr_un un_addr;
5204 const struct sockaddr_un *to_un = NULL;
5205 const struct sockaddr *to = NULL;
5208 struct socket_info *si = find_socket_info(s);
5212 return libc_sendmsg(s, omsg, flags);
5215 ZERO_STRUCT(un_addr);
5217 tmp.iov_base = NULL;
5222 if (si->connected == 0) {
5223 msg.msg_name = omsg->msg_name; /* optional address */
5224 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5226 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5227 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5228 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5229 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5230 /* omsg is a const so use a local buffer for modifications */
5231 uint8_t cmbuf[omsg->msg_controllen];
5233 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5235 msg.msg_control = cmbuf; /* ancillary data, see below */
5236 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5238 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5241 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5249 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5257 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5258 avail += msg.msg_iov[i].iov_len;
5264 /* we capture it as one single packet */
5265 buf = (uint8_t *)malloc(remain);
5270 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5271 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5273 msg.msg_iov[i].iov_base,
5276 remain -= this_time;
5279 type = SOCKET_TYPE_CHAR_UDP;
5281 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5282 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5283 socket_wrapper_dir(), type, iface, prt);
5284 if (stat(un_addr.sun_path, &st) != 0) continue;
5286 msg.msg_name = &un_addr; /* optional address */
5287 msg.msg_namelen = sizeof(un_addr); /* size of address */
5289 /* ignore the any errors in broadcast sends */
5290 libc_sendmsg(s, &msg, flags);
5293 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5299 ret = libc_sendmsg(s, &msg, flags);
5301 swrap_sendmsg_after(s, si, &msg, to, ret);
5306 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5308 return swrap_sendmsg(s, omsg, flags);
5311 /****************************************************************************
5313 ***************************************************************************/
5315 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5317 struct socket_info *si;
5320 struct swrap_address saddr = {
5321 .sa_socklen = sizeof(struct sockaddr_storage)
5326 si = find_socket_info(s);
5328 return libc_readv(s, vector, count);
5331 tmp.iov_base = NULL;
5335 msg.msg_name = &saddr.sa.s; /* optional address */
5336 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5337 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5338 msg.msg_iovlen = count; /* # elements in msg_iov */
5339 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5340 msg.msg_control = NULL; /* ancillary data, see below */
5341 msg.msg_controllen = 0; /* ancillary data buffer len */
5342 msg.msg_flags = 0; /* flags on received message */
5345 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5347 if (rc == -ENOTSOCK) {
5348 return libc_readv(s, vector, count);
5353 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5355 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5363 ssize_t readv(int s, const struct iovec *vector, int count)
5365 return swrap_readv(s, vector, count);
5368 /****************************************************************************
5370 ***************************************************************************/
5372 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5376 struct sockaddr_un un_addr;
5379 struct socket_info *si = find_socket_info(s);
5382 return libc_writev(s, vector, count);
5385 tmp.iov_base = NULL;
5389 msg.msg_name = NULL; /* optional address */
5390 msg.msg_namelen = 0; /* size of address */
5391 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5392 msg.msg_iovlen = count; /* # elements in msg_iov */
5393 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5394 msg.msg_control = NULL; /* ancillary data, see below */
5395 msg.msg_controllen = 0; /* ancillary data buffer len */
5396 msg.msg_flags = 0; /* flags on received message */
5399 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5401 if (rc == -ENOTSOCK) {
5402 return libc_readv(s, vector, count);
5407 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5409 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5414 ssize_t writev(int s, const struct iovec *vector, int count)
5416 return swrap_writev(s, vector, count);
5419 /****************************
5421 ***************************/
5423 static int swrap_close(int fd)
5425 struct socket_info_fd *fi = find_socket_info_fd(fd);
5426 struct socket_info *si = NULL;
5431 return libc_close(fd);
5434 si_index = fi->si_index;
5436 SWRAP_DLIST_REMOVE(socket_fds, fi);
5439 ret = libc_close(fd);
5441 si = &sockets[si_index];
5444 if (si->refcount > 0) {
5445 /* there are still references left */
5449 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5450 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5453 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5454 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5455 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5458 if (si->un_addr.sun_path[0] != '\0') {
5459 unlink(si->un_addr.sun_path);
5462 si->next_free = first_free;
5463 first_free = si_index;
5470 return swrap_close(fd);
5473 /****************************
5475 ***************************/
5477 static int swrap_dup(int fd)
5479 struct socket_info *si;
5480 struct socket_info_fd *src_fi, *fi;
5482 src_fi = find_socket_info_fd(fd);
5483 if (src_fi == NULL) {
5484 return libc_dup(fd);
5487 si = &sockets[src_fi->si_index];
5489 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5495 fi->fd = libc_dup(fd);
5497 int saved_errno = errno;
5499 errno = saved_errno;
5504 fi->si_index = src_fi->si_index;
5506 /* Make sure we don't have an entry for the fd */
5507 swrap_remove_stale(fi->fd);
5509 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5515 return swrap_dup(fd);
5518 /****************************
5520 ***************************/
5522 static int swrap_dup2(int fd, int newfd)
5524 struct socket_info *si;
5525 struct socket_info_fd *src_fi, *fi;
5527 src_fi = find_socket_info_fd(fd);
5528 if (src_fi == NULL) {
5529 return libc_dup2(fd, newfd);
5532 si = &sockets[src_fi->si_index];
5536 * According to the manpage:
5538 * "If oldfd is a valid file descriptor, and newfd has the same
5539 * value as oldfd, then dup2() does nothing, and returns newfd."
5544 if (find_socket_info(newfd)) {
5545 /* dup2() does an implicit close of newfd, which we
5546 * need to emulate */
5550 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5556 fi->fd = libc_dup2(fd, newfd);
5558 int saved_errno = errno;
5560 errno = saved_errno;
5565 fi->si_index = src_fi->si_index;
5567 /* Make sure we don't have an entry for the fd */
5568 swrap_remove_stale(fi->fd);
5570 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5574 int dup2(int fd, int newfd)
5576 return swrap_dup2(fd, newfd);
5579 /****************************
5581 ***************************/
5583 static int swrap_vfcntl(int fd, int cmd, va_list va)
5585 struct socket_info_fd *src_fi, *fi;
5586 struct socket_info *si;
5589 src_fi = find_socket_info_fd(fd);
5590 if (src_fi == NULL) {
5591 return libc_vfcntl(fd, cmd, va);
5594 si = &sockets[src_fi->si_index];
5598 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5604 fi->fd = libc_vfcntl(fd, cmd, va);
5606 int saved_errno = errno;
5608 errno = saved_errno;
5613 fi->si_index = src_fi->si_index;
5615 /* Make sure we don't have an entry for the fd */
5616 swrap_remove_stale(fi->fd);
5618 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5623 rc = libc_vfcntl(fd, cmd, va);
5630 int fcntl(int fd, int cmd, ...)
5637 rc = swrap_vfcntl(fd, cmd, va);
5644 /****************************
5646 ***************************/
5649 static int swrap_eventfd(int count, int flags)
5653 fd = libc_eventfd(count, flags);
5655 swrap_remove_stale(fd);
5661 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5662 int eventfd(unsigned int count, int flags)
5664 int eventfd(int count, int flags)
5667 return swrap_eventfd(count, flags);
5672 int pledge(const char *promises, const char *paths[])
5674 (void)promises; /* unused */
5675 (void)paths; /* unused */
5679 #endif /* HAVE_PLEDGE */
5681 static void swrap_thread_prepare(void)
5686 static void swrap_thread_parent(void)
5691 static void swrap_thread_child(void)
5696 /****************************
5698 ***************************/
5699 void swrap_constructor(void)
5702 * If we hold a lock and the application forks, then the child
5703 * is not able to unlock the mutex and we are in a deadlock.
5704 * This should prevent such deadlocks.
5706 pthread_atfork(&swrap_thread_prepare,
5707 &swrap_thread_parent,
5708 &swrap_thread_child);
5711 /****************************
5713 ***************************/
5716 * This function is called when the library is unloaded and makes sure that
5717 * sockets get closed and the unix file for the socket are unlinked.
5719 void swrap_destructor(void)
5721 struct socket_info_fd *s = socket_fds;
5730 if (swrap.libc.handle != NULL) {
5731 dlclose(swrap.libc.handle);
5733 if (swrap.libc.socket_handle) {
5734 dlclose(swrap.libc.socket_handle);