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
111 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
112 # define FALL_THROUGH __attribute__ ((fallthrough))
113 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
114 # define FALL_THROUGH ((void)0)
115 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
116 #endif /* FALL_THROUGH */
118 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
119 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
121 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
124 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
125 # define SWRAP_THREAD __thread
127 # define SWRAP_THREAD
131 #define MIN(a,b) ((a)<(b)?(a):(b))
135 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
139 #define ZERO_STRUCTP(x) do { \
141 memset((char *)(x), 0, sizeof(*(x))); \
145 #ifndef discard_const
146 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
149 #ifndef discard_const_p
150 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
153 #define UNUSED(x) (void)(x)
156 # ifndef IPV6_RECVPKTINFO
157 # define IPV6_RECVPKTINFO IPV6_PKTINFO
158 # endif /* IPV6_RECVPKTINFO */
159 #endif /* IPV6_PKTINFO */
162 * On BSD IP_PKTINFO has a different name because during
163 * the time when they implemented it, there was no RFC.
164 * The name for IPv6 is the same as on Linux.
167 # ifdef IP_RECVDSTADDR
168 # define IP_PKTINFO IP_RECVDSTADDR
172 /* Macros for accessing mutexes */
173 # define SWRAP_LOCK(m) do { \
174 pthread_mutex_lock(&(m ## _mutex)); \
177 # define SWRAP_UNLOCK(m) do { \
178 pthread_mutex_unlock(&(m ## _mutex)); \
181 /* Add new global locks here please */
182 # define SWRAP_LOCK_ALL \
183 SWRAP_LOCK(libc_symbol_binding); \
185 # define SWRAP_UNLOCK_ALL \
186 SWRAP_UNLOCK(libc_symbol_binding); \
188 #define SOCKET_INFO_CONTAINER(si) \
189 (struct socket_info_container *)(si)
191 #define SWRAP_DLIST_ADD(list,item) do { \
193 (item)->prev = NULL; \
194 (item)->next = NULL; \
197 (item)->prev = NULL; \
198 (item)->next = (list); \
199 (list)->prev = (item); \
204 #define SWRAP_DLIST_REMOVE(list,item) do { \
205 if ((list) == (item)) { \
206 (list) = (item)->next; \
208 (list)->prev = NULL; \
211 if ((item)->prev) { \
212 (item)->prev->next = (item)->next; \
214 if ((item)->next) { \
215 (item)->next->prev = (item)->prev; \
218 (item)->prev = NULL; \
219 (item)->next = NULL; \
222 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
224 if ((list) == NULL || (el) == NULL) { \
225 SWRAP_DLIST_ADD(list, item); \
227 (item)->prev = (el); \
228 (item)->next = (el)->next; \
229 (el)->next = (item); \
230 if ((item)->next != NULL) { \
231 (item)->next->prev = (item); \
236 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
237 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
239 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
242 /* we need to use a very terse format here as IRIX 6.4 silently
243 truncates names to 16 chars, so if we use a longer name then we
244 can't tell which port a packet came from with recvfrom()
246 with this format we have 8 chars left for the directory name
248 #define SOCKET_FORMAT "%c%02X%04X"
249 #define SOCKET_TYPE_CHAR_TCP 'T'
250 #define SOCKET_TYPE_CHAR_UDP 'U'
251 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
252 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
255 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
256 * format PCAP capture files (as the caller will simply continue from here).
258 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
259 #define SOCKET_WRAPPER_MTU_MIN 512
260 #define SOCKET_WRAPPER_MTU_MAX 32768
262 #define SOCKET_MAX_SOCKETS 1024
266 * Maximum number of socket_info structures that can
267 * be used. Can be overriden by the environment variable
268 * SOCKET_WRAPPER_MAX_SOCKETS.
270 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
272 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 256000
274 /* This limit is to avoid broadcast sendto() needing to stat too many
275 * files. It may be raised (with a performance cost) to up to 254
276 * without changing the format above */
277 #define MAX_WRAPPED_INTERFACES 64
279 struct swrap_address {
280 socklen_t sa_socklen;
283 struct sockaddr_in in;
285 struct sockaddr_in6 in6;
287 struct sockaddr_un un;
288 struct sockaddr_storage ss;
292 struct socket_info_fd {
293 struct socket_info_fd *prev, *next;
297 * Points to corresponding index in array of
298 * socket_info structures
318 /* The unix path so we can unlink it on close() */
319 struct sockaddr_un un_addr;
321 struct swrap_address bindname;
322 struct swrap_address myname;
323 struct swrap_address peername;
326 unsigned long pck_snd;
327 unsigned long pck_rcv;
331 struct socket_info_container
333 struct socket_info info;
334 unsigned int refcount;
338 static struct socket_info_container *sockets;
339 static size_t max_sockets = 0;
342 * While socket file descriptors are passed among different processes, the
343 * numerical value gets changed. So its better to store it locally to each
344 * process rather than including it within socket_info which will be shared.
346 static struct socket_info_fd *socket_fds;
348 /* The mutex for accessing the global libc.symbols */
349 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
351 /* Function prototypes */
353 bool socket_wrapper_enabled(void);
355 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
356 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
358 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
359 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
361 static void swrap_log(enum swrap_dbglvl_e dbglvl,
363 const char *format, ...)
368 unsigned int lvl = 0;
369 const char *prefix = "SWRAP";
371 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
380 va_start(va, format);
381 vsnprintf(buffer, sizeof(buffer), format, va);
385 case SWRAP_LOG_ERROR:
386 prefix = "SWRAP_ERROR";
389 prefix = "SWRAP_WARN";
391 case SWRAP_LOG_DEBUG:
392 prefix = "SWRAP_DEBUG";
394 case SWRAP_LOG_TRACE:
395 prefix = "SWRAP_TRACE";
401 prefix, (int)getpid(), func, buffer);
404 /*********************************************************
405 * SWRAP LOADING LIBC FUNCTIONS
406 *********************************************************/
411 typedef int (*__libc_accept4)(int sockfd,
412 struct sockaddr *addr,
416 typedef int (*__libc_accept)(int sockfd,
417 struct sockaddr *addr,
420 typedef int (*__libc_bind)(int sockfd,
421 const struct sockaddr *addr,
423 typedef int (*__libc_close)(int fd);
424 typedef int (*__libc_connect)(int sockfd,
425 const struct sockaddr *addr,
427 typedef int (*__libc_dup)(int fd);
428 typedef int (*__libc_dup2)(int oldfd, int newfd);
429 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
430 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
432 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
435 typedef int (*__libc_eventfd)(int count, int flags);
437 typedef int (*__libc_getpeername)(int sockfd,
438 struct sockaddr *addr,
440 typedef int (*__libc_getsockname)(int sockfd,
441 struct sockaddr *addr,
443 typedef int (*__libc_getsockopt)(int sockfd,
448 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
449 typedef int (*__libc_listen)(int sockfd, int backlog);
450 typedef int (*__libc_open)(const char *pathname, int flags, ...);
452 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
453 #endif /* HAVE_OPEN64 */
454 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
455 typedef int (*__libc_pipe)(int pipefd[2]);
456 typedef int (*__libc_read)(int fd, void *buf, size_t count);
457 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
458 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
459 typedef int (*__libc_recvfrom)(int sockfd,
463 struct sockaddr *src_addr,
465 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
466 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
467 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
468 typedef int (*__libc_sendto)(int sockfd,
472 const struct sockaddr *dst_addr,
474 typedef int (*__libc_setsockopt)(int sockfd,
480 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
482 typedef int (*__libc_socket)(int domain, int type, int protocol);
483 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
484 #ifdef HAVE_TIMERFD_CREATE
485 typedef int (*__libc_timerfd_create)(int clockid, int flags);
487 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
488 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
490 #define SWRAP_SYMBOL_ENTRY(i) \
496 struct swrap_libc_symbols {
498 SWRAP_SYMBOL_ENTRY(accept4);
500 SWRAP_SYMBOL_ENTRY(accept);
502 SWRAP_SYMBOL_ENTRY(bind);
503 SWRAP_SYMBOL_ENTRY(close);
504 SWRAP_SYMBOL_ENTRY(connect);
505 SWRAP_SYMBOL_ENTRY(dup);
506 SWRAP_SYMBOL_ENTRY(dup2);
507 SWRAP_SYMBOL_ENTRY(fcntl);
508 SWRAP_SYMBOL_ENTRY(fopen);
510 SWRAP_SYMBOL_ENTRY(fopen64);
513 SWRAP_SYMBOL_ENTRY(eventfd);
515 SWRAP_SYMBOL_ENTRY(getpeername);
516 SWRAP_SYMBOL_ENTRY(getsockname);
517 SWRAP_SYMBOL_ENTRY(getsockopt);
518 SWRAP_SYMBOL_ENTRY(ioctl);
519 SWRAP_SYMBOL_ENTRY(listen);
520 SWRAP_SYMBOL_ENTRY(open);
522 SWRAP_SYMBOL_ENTRY(open64);
524 SWRAP_SYMBOL_ENTRY(openat);
525 SWRAP_SYMBOL_ENTRY(pipe);
526 SWRAP_SYMBOL_ENTRY(read);
527 SWRAP_SYMBOL_ENTRY(readv);
528 SWRAP_SYMBOL_ENTRY(recv);
529 SWRAP_SYMBOL_ENTRY(recvfrom);
530 SWRAP_SYMBOL_ENTRY(recvmsg);
531 SWRAP_SYMBOL_ENTRY(send);
532 SWRAP_SYMBOL_ENTRY(sendmsg);
533 SWRAP_SYMBOL_ENTRY(sendto);
534 SWRAP_SYMBOL_ENTRY(setsockopt);
536 SWRAP_SYMBOL_ENTRY(signalfd);
538 SWRAP_SYMBOL_ENTRY(socket);
539 SWRAP_SYMBOL_ENTRY(socketpair);
540 #ifdef HAVE_TIMERFD_CREATE
541 SWRAP_SYMBOL_ENTRY(timerfd_create);
543 SWRAP_SYMBOL_ENTRY(write);
544 SWRAP_SYMBOL_ENTRY(writev);
551 struct swrap_libc_symbols symbols;
555 static struct swrap swrap;
558 static const char *socket_wrapper_dir(void);
560 #define LIBC_NAME "libc.so"
568 static const char *swrap_str_lib(enum swrap_lib lib)
575 case SWRAP_LIBSOCKET:
579 /* Compiler would warn us about unhandled enum value if we get here */
583 static void *swrap_load_lib_handle(enum swrap_lib lib)
585 int flags = RTLD_LAZY;
590 flags |= RTLD_DEEPBIND;
596 case SWRAP_LIBSOCKET:
597 #ifdef HAVE_LIBSOCKET
598 handle = swrap.libc.socket_handle;
599 if (handle == NULL) {
600 for (i = 10; i >= 0; i--) {
601 char soname[256] = {0};
603 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
604 handle = dlopen(soname, flags);
605 if (handle != NULL) {
610 swrap.libc.socket_handle = handle;
616 handle = swrap.libc.handle;
618 if (handle == NULL) {
619 handle = dlopen(LIBC_SO, flags);
621 swrap.libc.handle = handle;
624 if (handle == NULL) {
625 for (i = 10; i >= 0; i--) {
626 char soname[256] = {0};
628 snprintf(soname, sizeof(soname), "libc.so.%d", i);
629 handle = dlopen(soname, flags);
630 if (handle != NULL) {
635 swrap.libc.handle = handle;
640 if (handle == NULL) {
642 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
644 SWRAP_LOG(SWRAP_LOG_ERROR,
645 "Failed to dlopen library: %s\n",
654 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
659 handle = swrap_load_lib_handle(lib);
661 func = dlsym(handle, fn_name);
663 SWRAP_LOG(SWRAP_LOG_ERROR,
664 "Failed to find %s: %s\n",
670 SWRAP_LOG(SWRAP_LOG_TRACE,
678 #define swrap_bind_symbol_libc(sym_name) \
679 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
680 SWRAP_LOCK(libc_symbol_binding); \
681 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
682 swrap.libc.symbols._libc_##sym_name.obj = \
683 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
685 SWRAP_UNLOCK(libc_symbol_binding); \
688 #define swrap_bind_symbol_libsocket(sym_name) \
689 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
690 SWRAP_LOCK(libc_symbol_binding); \
691 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
692 swrap.libc.symbols._libc_##sym_name.obj = \
693 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
695 SWRAP_UNLOCK(libc_symbol_binding); \
698 #define swrap_bind_symbol_libnsl(sym_name) \
699 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
700 SWRAP_LOCK(libc_symbol_binding); \
701 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
702 swrap.libc.symbols._libc_##sym_name.obj = \
703 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
705 SWRAP_UNLOCK(libc_symbol_binding); \
708 /****************************************************************************
710 ****************************************************************************
712 * Functions especially from libc need to be loaded individually, you can't
713 * load all at once or gdb will segfault at startup. The same applies to
714 * valgrind and has probably something todo with with the linker. So we need
715 * load each function at the point it is called the first time.
717 ****************************************************************************/
720 static int libc_accept4(int sockfd,
721 struct sockaddr *addr,
725 swrap_bind_symbol_libsocket(accept4);
727 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
730 #else /* HAVE_ACCEPT4 */
732 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
734 swrap_bind_symbol_libsocket(accept);
736 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
738 #endif /* HAVE_ACCEPT4 */
740 static int libc_bind(int sockfd,
741 const struct sockaddr *addr,
744 swrap_bind_symbol_libsocket(bind);
746 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
749 static int libc_close(int fd)
751 swrap_bind_symbol_libc(close);
753 return swrap.libc.symbols._libc_close.f(fd);
756 static int libc_connect(int sockfd,
757 const struct sockaddr *addr,
760 swrap_bind_symbol_libsocket(connect);
762 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
765 static int libc_dup(int fd)
767 swrap_bind_symbol_libc(dup);
769 return swrap.libc.symbols._libc_dup.f(fd);
772 static int libc_dup2(int oldfd, int newfd)
774 swrap_bind_symbol_libc(dup2);
776 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
780 static int libc_eventfd(int count, int flags)
782 swrap_bind_symbol_libc(eventfd);
784 return swrap.libc.symbols._libc_eventfd.f(count, flags);
788 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
789 static int libc_vfcntl(int fd, int cmd, va_list ap)
794 swrap_bind_symbol_libc(fcntl);
796 arg = va_arg(ap, void *);
798 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
803 static int libc_getpeername(int sockfd,
804 struct sockaddr *addr,
807 swrap_bind_symbol_libsocket(getpeername);
809 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
812 static int libc_getsockname(int sockfd,
813 struct sockaddr *addr,
816 swrap_bind_symbol_libsocket(getsockname);
818 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
821 static int libc_getsockopt(int sockfd,
827 swrap_bind_symbol_libsocket(getsockopt);
829 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
836 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
837 static int libc_vioctl(int d, unsigned long int request, va_list ap)
842 swrap_bind_symbol_libc(ioctl);
844 arg = va_arg(ap, void *);
846 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
851 static int libc_listen(int sockfd, int backlog)
853 swrap_bind_symbol_libsocket(listen);
855 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
858 static FILE *libc_fopen(const char *name, const char *mode)
860 swrap_bind_symbol_libc(fopen);
862 return swrap.libc.symbols._libc_fopen.f(name, mode);
866 static FILE *libc_fopen64(const char *name, const char *mode)
868 swrap_bind_symbol_libc(fopen64);
870 return swrap.libc.symbols._libc_fopen64.f(name, mode);
872 #endif /* HAVE_FOPEN64 */
874 static int libc_vopen(const char *pathname, int flags, va_list ap)
879 swrap_bind_symbol_libc(open);
881 if (flags & O_CREAT) {
882 mode = va_arg(ap, int);
884 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
889 static int libc_open(const char *pathname, int flags, ...)
895 fd = libc_vopen(pathname, flags, ap);
902 static int libc_vopen64(const char *pathname, int flags, va_list ap)
907 swrap_bind_symbol_libc(open64);
909 if (flags & O_CREAT) {
910 mode = va_arg(ap, int);
912 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
916 #endif /* HAVE_OPEN64 */
918 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
923 swrap_bind_symbol_libc(openat);
925 if (flags & O_CREAT) {
926 mode = va_arg(ap, int);
928 fd = swrap.libc.symbols._libc_openat.f(dirfd,
937 static int libc_openat(int dirfd, const char *path, int flags, ...)
943 fd = libc_vopenat(dirfd, path, flags, ap);
950 static int libc_pipe(int pipefd[2])
952 swrap_bind_symbol_libsocket(pipe);
954 return swrap.libc.symbols._libc_pipe.f(pipefd);
957 static int libc_read(int fd, void *buf, size_t count)
959 swrap_bind_symbol_libc(read);
961 return swrap.libc.symbols._libc_read.f(fd, buf, count);
964 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
966 swrap_bind_symbol_libsocket(readv);
968 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
971 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
973 swrap_bind_symbol_libsocket(recv);
975 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
978 static int libc_recvfrom(int sockfd,
982 struct sockaddr *src_addr,
985 swrap_bind_symbol_libsocket(recvfrom);
987 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
995 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
997 swrap_bind_symbol_libsocket(recvmsg);
999 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1002 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1004 swrap_bind_symbol_libsocket(send);
1006 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1009 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1011 swrap_bind_symbol_libsocket(sendmsg);
1013 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1016 static int libc_sendto(int sockfd,
1020 const struct sockaddr *dst_addr,
1023 swrap_bind_symbol_libsocket(sendto);
1025 return swrap.libc.symbols._libc_sendto.f(sockfd,
1033 static int libc_setsockopt(int sockfd,
1039 swrap_bind_symbol_libsocket(setsockopt);
1041 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1048 #ifdef HAVE_SIGNALFD
1049 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1051 swrap_bind_symbol_libsocket(signalfd);
1053 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1057 static int libc_socket(int domain, int type, int protocol)
1059 swrap_bind_symbol_libsocket(socket);
1061 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1064 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1066 swrap_bind_symbol_libsocket(socketpair);
1068 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1071 #ifdef HAVE_TIMERFD_CREATE
1072 static int libc_timerfd_create(int clockid, int flags)
1074 swrap_bind_symbol_libc(timerfd_create);
1076 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1080 static ssize_t libc_write(int fd, const void *buf, size_t count)
1082 swrap_bind_symbol_libc(write);
1084 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1087 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1089 swrap_bind_symbol_libsocket(writev);
1091 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1094 /* DO NOT call this function during library initialization! */
1095 static void swrap_bind_symbol_all(void)
1098 swrap_bind_symbol_libsocket(accept4);
1100 swrap_bind_symbol_libsocket(accept);
1102 swrap_bind_symbol_libsocket(bind);
1103 swrap_bind_symbol_libc(close);
1104 swrap_bind_symbol_libsocket(connect);
1105 swrap_bind_symbol_libc(dup);
1106 swrap_bind_symbol_libc(dup2);
1107 swrap_bind_symbol_libc(fcntl);
1108 swrap_bind_symbol_libc(fopen);
1110 swrap_bind_symbol_libc(fopen64);
1113 swrap_bind_symbol_libc(eventfd);
1115 swrap_bind_symbol_libsocket(getpeername);
1116 swrap_bind_symbol_libsocket(getsockname);
1117 swrap_bind_symbol_libsocket(getsockopt);
1118 swrap_bind_symbol_libc(ioctl);
1119 swrap_bind_symbol_libsocket(listen);
1120 swrap_bind_symbol_libc(open);
1122 swrap_bind_symbol_libc(open64);
1124 swrap_bind_symbol_libc(openat);
1125 swrap_bind_symbol_libsocket(pipe);
1126 swrap_bind_symbol_libc(read);
1127 swrap_bind_symbol_libsocket(readv);
1128 swrap_bind_symbol_libsocket(recv);
1129 swrap_bind_symbol_libsocket(recvfrom);
1130 swrap_bind_symbol_libsocket(recvmsg);
1131 swrap_bind_symbol_libsocket(send);
1132 swrap_bind_symbol_libsocket(sendmsg);
1133 swrap_bind_symbol_libsocket(sendto);
1134 swrap_bind_symbol_libsocket(setsockopt);
1135 #ifdef HAVE_SIGNALFD
1136 swrap_bind_symbol_libsocket(signalfd);
1138 swrap_bind_symbol_libsocket(socket);
1139 swrap_bind_symbol_libsocket(socketpair);
1140 #ifdef HAVE_TIMERFD_CREATE
1141 swrap_bind_symbol_libc(timerfd_create);
1143 swrap_bind_symbol_libc(write);
1144 swrap_bind_symbol_libsocket(writev);
1147 /*********************************************************
1148 * SWRAP HELPER FUNCTIONS
1149 *********************************************************/
1155 static const struct in6_addr *swrap_ipv6(void)
1157 static struct in6_addr v;
1158 static int initialized;
1166 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1175 static void set_port(int family, int prt, struct swrap_address *addr)
1179 addr->sa.in.sin_port = htons(prt);
1183 addr->sa.in6.sin6_port = htons(prt);
1189 static size_t socket_length(int family)
1193 return sizeof(struct sockaddr_in);
1196 return sizeof(struct sockaddr_in6);
1202 static struct socket_info *swrap_get_socket_info(int si_index)
1204 return (struct socket_info *)(&(sockets[si_index].info));
1207 static int swrap_get_refcount(struct socket_info *si)
1209 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1210 return sic->refcount;
1213 static void swrap_inc_refcount(struct socket_info *si)
1215 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1220 static void swrap_dec_refcount(struct socket_info *si)
1222 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1227 static int swrap_get_next_free(struct socket_info *si)
1229 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1231 return sic->next_free;
1234 static void swrap_set_next_free(struct socket_info *si, int next_free)
1236 struct socket_info_container *sic = SOCKET_INFO_CONTAINER(si);
1237 sic->next_free = next_free;
1240 static const char *socket_wrapper_dir(void)
1242 const char *s = getenv("SOCKET_WRAPPER_DIR");
1246 /* TODO use realpath(3) here, when we add support for threads */
1247 if (strncmp(s, "./", 2) == 0) {
1251 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1255 static unsigned int socket_wrapper_mtu(void)
1257 static unsigned int max_mtu = 0;
1266 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1268 s = getenv("SOCKET_WRAPPER_MTU");
1273 tmp = strtol(s, &endp, 10);
1278 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1287 static size_t socket_wrapper_max_sockets(void)
1293 if (max_sockets != 0) {
1297 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1299 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1300 if (s == NULL || s[0] == '\0') {
1304 tmp = strtoul(s, &endp, 10);
1308 if (tmp == 0 || tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1309 SWRAP_LOG(SWRAP_LOG_ERROR,
1310 "Invalid number of sockets specified, using default.");
1320 static void socket_wrapper_init_sockets(void)
1324 if (sockets != NULL) {
1328 max_sockets = socket_wrapper_max_sockets();
1330 sockets = (struct socket_info_container *)calloc(max_sockets,
1331 sizeof(struct socket_info_container));
1333 if (sockets == NULL) {
1334 SWRAP_LOG(SWRAP_LOG_ERROR,
1335 "Failed to allocate sockets array.\n");
1341 for (i = 0; i < max_sockets; i++) {
1342 swrap_set_next_free(&sockets[i].info, i+1);
1345 /* mark the end of the free list */
1346 swrap_set_next_free(&sockets[max_sockets-1].info, -1);
1349 bool socket_wrapper_enabled(void)
1351 const char *s = socket_wrapper_dir();
1357 socket_wrapper_init_sockets();
1362 static unsigned int socket_wrapper_default_iface(void)
1364 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1367 if (sscanf(s, "%u", &iface) == 1) {
1368 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1374 return 1;/* 127.0.0.1 */
1378 * Return the first free entry (if any) and make
1379 * it re-usable again (by nulling it out)
1381 static int socket_wrapper_first_free_index(void)
1383 struct socket_info *si = NULL;
1386 if (first_free == -1) {
1391 si = swrap_get_socket_info(first_free);
1392 next_free = swrap_get_next_free(si);
1394 swrap_set_next_free(si, next_free);
1399 static int swrap_add_socket_info(struct socket_info *si_input)
1401 struct socket_info *si = NULL;
1404 if (si_input == NULL) {
1409 if (first_free == -1) {
1414 si_index = first_free;
1415 si = swrap_get_socket_info(si_index);
1417 first_free = swrap_get_next_free(si);
1419 swrap_inc_refcount(si);
1424 static int swrap_create_socket(struct socket_info *si, int fd)
1426 struct socket_info_fd *fi = NULL;
1429 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
1435 idx = swrap_add_socket_info(si);
1444 SWRAP_DLIST_ADD(socket_fds, fi);
1449 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1456 p = strrchr(un->sun_path, '/');
1457 if (p) p++; else p = un->sun_path;
1459 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1464 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1467 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1478 case SOCKET_TYPE_CHAR_TCP:
1479 case SOCKET_TYPE_CHAR_UDP: {
1480 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1482 if ((*len) < sizeof(*in2)) {
1487 memset(in2, 0, sizeof(*in2));
1488 in2->sin_family = AF_INET;
1489 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1490 in2->sin_port = htons(prt);
1492 *len = sizeof(*in2);
1496 case SOCKET_TYPE_CHAR_TCP_V6:
1497 case SOCKET_TYPE_CHAR_UDP_V6: {
1498 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1500 if ((*len) < sizeof(*in2)) {
1505 memset(in2, 0, sizeof(*in2));
1506 in2->sin6_family = AF_INET6;
1507 in2->sin6_addr = *swrap_ipv6();
1508 in2->sin6_addr.s6_addr[15] = iface;
1509 in2->sin6_port = htons(prt);
1511 *len = sizeof(*in2);
1523 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1531 if (bcast) *bcast = 0;
1533 switch (inaddr->sa_family) {
1535 const struct sockaddr_in *in =
1536 (const struct sockaddr_in *)(const void *)inaddr;
1537 unsigned int addr = ntohl(in->sin_addr.s_addr);
1544 u_type = SOCKET_TYPE_CHAR_TCP;
1547 u_type = SOCKET_TYPE_CHAR_UDP;
1548 a_type = SOCKET_TYPE_CHAR_UDP;
1549 b_type = SOCKET_TYPE_CHAR_UDP;
1552 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1553 errno = ESOCKTNOSUPPORT;
1557 prt = ntohs(in->sin_port);
1558 if (a_type && addr == 0xFFFFFFFF) {
1559 /* 255.255.255.255 only udp */
1562 iface = socket_wrapper_default_iface();
1563 } else if (b_type && addr == 0x7FFFFFFF) {
1564 /* 127.255.255.255 only udp */
1567 iface = socket_wrapper_default_iface();
1568 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1572 iface = (addr & 0x000000FF);
1574 errno = ENETUNREACH;
1577 if (bcast) *bcast = is_bcast;
1582 const struct sockaddr_in6 *in =
1583 (const struct sockaddr_in6 *)(const void *)inaddr;
1584 struct in6_addr cmp1, cmp2;
1588 type = SOCKET_TYPE_CHAR_TCP_V6;
1591 type = SOCKET_TYPE_CHAR_UDP_V6;
1594 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1595 errno = ESOCKTNOSUPPORT;
1599 /* XXX no multicast/broadcast */
1601 prt = ntohs(in->sin6_port);
1603 cmp1 = *swrap_ipv6();
1604 cmp2 = in->sin6_addr;
1605 cmp2.s6_addr[15] = 0;
1606 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1607 iface = in->sin6_addr.s6_addr[15];
1609 errno = ENETUNREACH;
1617 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1618 errno = ENETUNREACH;
1623 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1629 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1630 socket_wrapper_dir());
1631 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1632 /* the caller need to do more processing */
1636 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1637 socket_wrapper_dir(), type, iface, prt);
1638 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1643 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1652 if (bcast) *bcast = 0;
1654 switch (si->family) {
1656 const struct sockaddr_in *in =
1657 (const struct sockaddr_in *)(const void *)inaddr;
1658 unsigned int addr = ntohl(in->sin_addr.s_addr);
1664 prt = ntohs(in->sin_port);
1668 u_type = SOCKET_TYPE_CHAR_TCP;
1669 d_type = SOCKET_TYPE_CHAR_TCP;
1672 u_type = SOCKET_TYPE_CHAR_UDP;
1673 d_type = SOCKET_TYPE_CHAR_UDP;
1674 a_type = SOCKET_TYPE_CHAR_UDP;
1675 b_type = SOCKET_TYPE_CHAR_UDP;
1678 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1679 errno = ESOCKTNOSUPPORT;
1687 iface = socket_wrapper_default_iface();
1688 } else if (a_type && addr == 0xFFFFFFFF) {
1689 /* 255.255.255.255 only udp */
1692 iface = socket_wrapper_default_iface();
1693 } else if (b_type && addr == 0x7FFFFFFF) {
1694 /* 127.255.255.255 only udp */
1697 iface = socket_wrapper_default_iface();
1698 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1702 iface = (addr & 0x000000FF);
1704 errno = EADDRNOTAVAIL;
1708 /* Store the bind address for connect() */
1709 if (si->bindname.sa_socklen == 0) {
1710 struct sockaddr_in bind_in;
1711 socklen_t blen = sizeof(struct sockaddr_in);
1713 ZERO_STRUCT(bind_in);
1714 bind_in.sin_family = in->sin_family;
1715 bind_in.sin_port = in->sin_port;
1716 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1718 si->bindname.sa_socklen = blen;
1719 memcpy(&si->bindname.sa.in, &bind_in, blen);
1726 const struct sockaddr_in6 *in =
1727 (const struct sockaddr_in6 *)(const void *)inaddr;
1728 struct in6_addr cmp1, cmp2;
1732 type = SOCKET_TYPE_CHAR_TCP_V6;
1735 type = SOCKET_TYPE_CHAR_UDP_V6;
1738 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1739 errno = ESOCKTNOSUPPORT;
1743 /* XXX no multicast/broadcast */
1745 prt = ntohs(in->sin6_port);
1747 cmp1 = *swrap_ipv6();
1748 cmp2 = in->sin6_addr;
1749 cmp2.s6_addr[15] = 0;
1750 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1751 iface = socket_wrapper_default_iface();
1752 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1753 iface = in->sin6_addr.s6_addr[15];
1755 errno = EADDRNOTAVAIL;
1759 /* Store the bind address for connect() */
1760 if (si->bindname.sa_socklen == 0) {
1761 struct sockaddr_in6 bind_in;
1762 socklen_t blen = sizeof(struct sockaddr_in6);
1764 ZERO_STRUCT(bind_in);
1765 bind_in.sin6_family = in->sin6_family;
1766 bind_in.sin6_port = in->sin6_port;
1768 bind_in.sin6_addr = *swrap_ipv6();
1769 bind_in.sin6_addr.s6_addr[15] = iface;
1771 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1772 si->bindname.sa_socklen = blen;
1779 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1780 errno = EADDRNOTAVAIL;
1785 if (bcast) *bcast = is_bcast;
1787 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1793 /* handle auto-allocation of ephemeral ports */
1794 for (prt = 5001; prt < 10000; prt++) {
1795 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1796 socket_wrapper_dir(), type, iface, prt);
1797 if (stat(un->sun_path, &st) == 0) continue;
1799 set_port(si->family, prt, &si->myname);
1800 set_port(si->family, prt, &si->bindname);
1810 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1811 socket_wrapper_dir(), type, iface, prt);
1812 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1816 static struct socket_info_fd *find_socket_info_fd(int fd)
1818 struct socket_info_fd *f;
1820 for (f = socket_fds; f; f = f->next) {
1829 static int find_socket_info_index(int fd)
1831 struct socket_info_fd *fi = find_socket_info_fd(fd);
1837 return fi->si_index;
1840 static struct socket_info *find_socket_info(int fd)
1842 int idx = find_socket_info_index(fd);
1848 return swrap_get_socket_info(idx);
1852 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1854 struct socket_info_fd *f;
1855 const struct socket_info *last_s = NULL;
1857 /* first catch invalid input */
1858 switch (sa->sa_family) {
1860 if (len < sizeof(struct sockaddr_in)) {
1866 if (len < sizeof(struct sockaddr_in6)) {
1876 for (f = socket_fds; f; f = f->next) {
1877 struct socket_info *s = swrap_get_socket_info(f->si_index);
1884 if (s->myname == NULL) {
1887 if (s->myname->sa_family != sa->sa_family) {
1890 switch (s->myname->sa_family) {
1892 struct sockaddr_in *sin1, *sin2;
1894 sin1 = (struct sockaddr_in *)s->myname;
1895 sin2 = (struct sockaddr_in *)sa;
1897 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1900 if (sin1->sin_port != sin2->sin_port) {
1903 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1913 struct sockaddr_in6 *sin1, *sin2;
1915 sin1 = (struct sockaddr_in6 *)s->myname;
1916 sin2 = (struct sockaddr_in6 *)sa;
1918 if (sin1->sin6_port != sin2->sin6_port) {
1921 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1943 static void swrap_remove_stale(int fd)
1945 struct socket_info_fd *fi = find_socket_info_fd(fd);
1946 struct socket_info *si;
1953 si_index = fi->si_index;
1955 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1956 SWRAP_DLIST_REMOVE(socket_fds, fi);
1959 si = swrap_get_socket_info(si_index);
1960 swrap_dec_refcount(si);
1962 if (swrap_get_refcount(si) > 0) {
1966 if (si->un_addr.sun_path[0] != '\0') {
1967 unlink(si->un_addr.sun_path);
1970 swrap_set_next_free(si, first_free);
1971 first_free = si_index;
1974 static int sockaddr_convert_to_un(struct socket_info *si,
1975 const struct sockaddr *in_addr,
1977 struct sockaddr_un *out_addr,
1981 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1983 (void) in_len; /* unused */
1985 if (out_addr == NULL) {
1989 out->sa_family = AF_UNIX;
1990 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1991 out->sa_len = sizeof(*out_addr);
1994 switch (in_addr->sa_family) {
1996 const struct sockaddr_in *sin;
1997 if (si->family != AF_INET) {
2000 if (in_len < sizeof(struct sockaddr_in)) {
2003 sin = (const struct sockaddr_in *)(const void *)in_addr;
2004 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
2009 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
2010 * AF_UNSPEC is mapped to AF_INET and must be treated here.
2024 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2025 errno = ESOCKTNOSUPPORT;
2029 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
2031 return convert_in_un_remote(si, in_addr, out_addr, bcast);
2037 errno = EAFNOSUPPORT;
2038 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2042 static int sockaddr_convert_from_un(const struct socket_info *si,
2043 const struct sockaddr_un *in_addr,
2044 socklen_t un_addrlen,
2046 struct sockaddr *out_addr,
2047 socklen_t *out_addrlen)
2051 if (out_addr == NULL || out_addrlen == NULL)
2054 if (un_addrlen == 0) {
2069 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
2070 errno = ESOCKTNOSUPPORT;
2073 ret = convert_un_in(in_addr, out_addr, out_addrlen);
2074 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2075 out_addr->sa_len = *out_addrlen;
2082 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
2083 errno = EAFNOSUPPORT;
2087 enum swrap_packet_type {
2089 SWRAP_CONNECT_UNREACH,
2097 SWRAP_SENDTO_UNREACH,
2108 struct swrap_file_hdr {
2110 uint16_t version_major;
2111 uint16_t version_minor;
2114 uint32_t frame_max_len;
2115 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2118 #define SWRAP_FILE_HDR_SIZE 24
2120 struct swrap_packet_frame {
2122 uint32_t micro_seconds;
2123 uint32_t recorded_length;
2124 uint32_t full_length;
2126 #define SWRAP_PACKET_FRAME_SIZE 16
2128 union swrap_packet_ip {
2132 uint16_t packet_length;
2133 uint16_t identification;
2138 uint16_t hdr_checksum;
2142 #define SWRAP_PACKET_IP_V4_SIZE 20
2145 uint8_t flow_label_high;
2146 uint16_t flow_label_low;
2147 uint16_t payload_length;
2148 uint8_t next_header;
2150 uint8_t src_addr[16];
2151 uint8_t dest_addr[16];
2153 #define SWRAP_PACKET_IP_V6_SIZE 40
2155 #define SWRAP_PACKET_IP_SIZE 40
2157 union swrap_packet_payload {
2159 uint16_t source_port;
2169 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2171 uint16_t source_port;
2176 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2183 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2190 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2192 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2194 #define SWRAP_PACKET_MIN_ALLOC \
2195 (SWRAP_PACKET_FRAME_SIZE + \
2196 SWRAP_PACKET_IP_SIZE + \
2197 SWRAP_PACKET_PAYLOAD_SIZE)
2199 static const char *swrap_pcap_init_file(void)
2201 static int initialized = 0;
2202 static const char *s = NULL;
2203 static const struct swrap_file_hdr h;
2204 static const struct swrap_packet_frame f;
2205 static const union swrap_packet_ip i;
2206 static const union swrap_packet_payload p;
2208 if (initialized == 1) {
2214 * TODO: don't use the structs use plain buffer offsets
2215 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2217 * for now make sure we disable PCAP support
2218 * if the struct has alignment!
2220 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2223 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2226 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2229 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2232 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2235 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2238 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2241 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2244 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2247 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2251 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2255 if (strncmp(s, "./", 2) == 0) {
2261 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2262 const struct sockaddr *src,
2263 const struct sockaddr *dest,
2265 const uint8_t *payload,
2267 unsigned long tcp_seqno,
2268 unsigned long tcp_ack,
2269 unsigned char tcp_ctl,
2271 size_t *_packet_len)
2275 struct swrap_packet_frame *frame;
2276 union swrap_packet_ip *ip;
2277 union swrap_packet_payload *pay;
2280 size_t nonwire_len = sizeof(*frame);
2281 size_t wire_hdr_len = 0;
2282 size_t wire_len = 0;
2283 size_t ip_hdr_len = 0;
2284 size_t icmp_hdr_len = 0;
2285 size_t icmp_truncate_len = 0;
2286 uint8_t protocol = 0, icmp_protocol = 0;
2287 const struct sockaddr_in *src_in = NULL;
2288 const struct sockaddr_in *dest_in = NULL;
2290 const struct sockaddr_in6 *src_in6 = NULL;
2291 const struct sockaddr_in6 *dest_in6 = NULL;
2296 switch (src->sa_family) {
2298 src_in = (const struct sockaddr_in *)(const void *)src;
2299 dest_in = (const struct sockaddr_in *)(const void *)dest;
2300 src_port = src_in->sin_port;
2301 dest_port = dest_in->sin_port;
2302 ip_hdr_len = sizeof(ip->v4);
2306 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2307 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2308 src_port = src_in6->sin6_port;
2309 dest_port = dest_in6->sin6_port;
2310 ip_hdr_len = sizeof(ip->v6);
2317 switch (socket_type) {
2319 protocol = 0x06; /* TCP */
2320 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2321 wire_len = wire_hdr_len + payload_len;
2325 protocol = 0x11; /* UDP */
2326 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2327 wire_len = wire_hdr_len + payload_len;
2335 icmp_protocol = protocol;
2336 switch (src->sa_family) {
2338 protocol = 0x01; /* ICMPv4 */
2339 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2343 protocol = 0x3A; /* ICMPv6 */
2344 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2348 if (wire_len > 64 ) {
2349 icmp_truncate_len = wire_len - 64;
2351 wire_hdr_len += icmp_hdr_len;
2352 wire_len += icmp_hdr_len;
2355 packet_len = nonwire_len + wire_len;
2356 alloc_len = packet_len;
2357 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2358 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2361 base = (uint8_t *)calloc(1, alloc_len);
2368 frame = (struct swrap_packet_frame *)(void *)buf;
2369 frame->seconds = tval->tv_sec;
2370 frame->micro_seconds = tval->tv_usec;
2371 frame->recorded_length = wire_len - icmp_truncate_len;
2372 frame->full_length = wire_len - icmp_truncate_len;
2373 buf += SWRAP_PACKET_FRAME_SIZE;
2375 ip = (union swrap_packet_ip *)(void *)buf;
2376 switch (src->sa_family) {
2378 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2380 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2381 ip->v4.identification = htons(0xFFFF);
2382 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2383 ip->v4.fragment = htons(0x0000);
2385 ip->v4.protocol = protocol;
2386 ip->v4.hdr_checksum = htons(0x0000);
2387 ip->v4.src_addr = src_in->sin_addr.s_addr;
2388 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2389 buf += SWRAP_PACKET_IP_V4_SIZE;
2393 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2394 ip->v6.flow_label_high = 0x00;
2395 ip->v6.flow_label_low = 0x0000;
2396 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2397 ip->v6.next_header = protocol;
2398 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2399 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2400 buf += SWRAP_PACKET_IP_V6_SIZE;
2406 pay = (union swrap_packet_payload *)(void *)buf;
2407 switch (src->sa_family) {
2409 pay->icmp4.type = 0x03; /* destination unreachable */
2410 pay->icmp4.code = 0x01; /* host unreachable */
2411 pay->icmp4.checksum = htons(0x0000);
2412 pay->icmp4.unused = htonl(0x00000000);
2413 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2415 /* set the ip header in the ICMP payload */
2416 ip = (union swrap_packet_ip *)(void *)buf;
2417 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2419 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2420 ip->v4.identification = htons(0xFFFF);
2421 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2422 ip->v4.fragment = htons(0x0000);
2424 ip->v4.protocol = icmp_protocol;
2425 ip->v4.hdr_checksum = htons(0x0000);
2426 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2427 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2428 buf += SWRAP_PACKET_IP_V4_SIZE;
2430 src_port = dest_in->sin_port;
2431 dest_port = src_in->sin_port;
2435 pay->icmp6.type = 0x01; /* destination unreachable */
2436 pay->icmp6.code = 0x03; /* address unreachable */
2437 pay->icmp6.checksum = htons(0x0000);
2438 pay->icmp6.unused = htonl(0x00000000);
2439 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2441 /* set the ip header in the ICMP payload */
2442 ip = (union swrap_packet_ip *)(void *)buf;
2443 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2444 ip->v6.flow_label_high = 0x00;
2445 ip->v6.flow_label_low = 0x0000;
2446 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2447 ip->v6.next_header = protocol;
2448 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2449 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2450 buf += SWRAP_PACKET_IP_V6_SIZE;
2452 src_port = dest_in6->sin6_port;
2453 dest_port = src_in6->sin6_port;
2459 pay = (union swrap_packet_payload *)(void *)buf;
2461 switch (socket_type) {
2463 pay->tcp.source_port = src_port;
2464 pay->tcp.dest_port = dest_port;
2465 pay->tcp.seq_num = htonl(tcp_seqno);
2466 pay->tcp.ack_num = htonl(tcp_ack);
2467 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2468 pay->tcp.control = tcp_ctl;
2469 pay->tcp.window = htons(0x7FFF);
2470 pay->tcp.checksum = htons(0x0000);
2471 pay->tcp.urg = htons(0x0000);
2472 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2477 pay->udp.source_port = src_port;
2478 pay->udp.dest_port = dest_port;
2479 pay->udp.length = htons(8 + payload_len);
2480 pay->udp.checksum = htons(0x0000);
2481 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2486 if (payload && payload_len > 0) {
2487 memcpy(buf, payload, payload_len);
2490 *_packet_len = packet_len - icmp_truncate_len;
2494 static int swrap_pcap_get_fd(const char *fname)
2502 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2504 struct swrap_file_hdr file_hdr;
2505 file_hdr.magic = 0xA1B2C3D4;
2506 file_hdr.version_major = 0x0002;
2507 file_hdr.version_minor = 0x0004;
2508 file_hdr.timezone = 0x00000000;
2509 file_hdr.sigfigs = 0x00000000;
2510 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2511 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2513 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2520 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2525 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2526 const struct sockaddr *addr,
2527 enum swrap_packet_type type,
2528 const void *buf, size_t len,
2531 const struct sockaddr *src_addr;
2532 const struct sockaddr *dest_addr;
2533 unsigned long tcp_seqno = 0;
2534 unsigned long tcp_ack = 0;
2535 unsigned char tcp_ctl = 0;
2536 int unreachable = 0;
2540 switch (si->family) {
2552 case SWRAP_CONNECT_SEND:
2553 if (si->type != SOCK_STREAM) {
2557 src_addr = &si->myname.sa.s;
2560 tcp_seqno = si->io.pck_snd;
2561 tcp_ack = si->io.pck_rcv;
2562 tcp_ctl = 0x02; /* SYN */
2564 si->io.pck_snd += 1;
2568 case SWRAP_CONNECT_RECV:
2569 if (si->type != SOCK_STREAM) {
2573 dest_addr = &si->myname.sa.s;
2576 tcp_seqno = si->io.pck_rcv;
2577 tcp_ack = si->io.pck_snd;
2578 tcp_ctl = 0x12; /** SYN,ACK */
2580 si->io.pck_rcv += 1;
2584 case SWRAP_CONNECT_UNREACH:
2585 if (si->type != SOCK_STREAM) {
2589 dest_addr = &si->myname.sa.s;
2592 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2593 tcp_seqno = si->io.pck_snd - 1;
2594 tcp_ack = si->io.pck_rcv;
2595 tcp_ctl = 0x02; /* SYN */
2600 case SWRAP_CONNECT_ACK:
2601 if (si->type != SOCK_STREAM) {
2605 src_addr = &si->myname.sa.s;
2608 tcp_seqno = si->io.pck_snd;
2609 tcp_ack = si->io.pck_rcv;
2610 tcp_ctl = 0x10; /* ACK */
2614 case SWRAP_ACCEPT_SEND:
2615 if (si->type != SOCK_STREAM) {
2619 dest_addr = &si->myname.sa.s;
2622 tcp_seqno = si->io.pck_rcv;
2623 tcp_ack = si->io.pck_snd;
2624 tcp_ctl = 0x02; /* SYN */
2626 si->io.pck_rcv += 1;
2630 case SWRAP_ACCEPT_RECV:
2631 if (si->type != SOCK_STREAM) {
2635 src_addr = &si->myname.sa.s;
2638 tcp_seqno = si->io.pck_snd;
2639 tcp_ack = si->io.pck_rcv;
2640 tcp_ctl = 0x12; /* SYN,ACK */
2642 si->io.pck_snd += 1;
2646 case SWRAP_ACCEPT_ACK:
2647 if (si->type != SOCK_STREAM) {
2651 dest_addr = &si->myname.sa.s;
2654 tcp_seqno = si->io.pck_rcv;
2655 tcp_ack = si->io.pck_snd;
2656 tcp_ctl = 0x10; /* ACK */
2661 src_addr = &si->myname.sa.s;
2662 dest_addr = &si->peername.sa.s;
2664 tcp_seqno = si->io.pck_snd;
2665 tcp_ack = si->io.pck_rcv;
2666 tcp_ctl = 0x18; /* PSH,ACK */
2668 si->io.pck_snd += len;
2672 case SWRAP_SEND_RST:
2673 dest_addr = &si->myname.sa.s;
2674 src_addr = &si->peername.sa.s;
2676 if (si->type == SOCK_DGRAM) {
2677 return swrap_pcap_marshall_packet(si,
2679 SWRAP_SENDTO_UNREACH,
2685 tcp_seqno = si->io.pck_rcv;
2686 tcp_ack = si->io.pck_snd;
2687 tcp_ctl = 0x14; /** RST,ACK */
2691 case SWRAP_PENDING_RST:
2692 dest_addr = &si->myname.sa.s;
2693 src_addr = &si->peername.sa.s;
2695 if (si->type == SOCK_DGRAM) {
2699 tcp_seqno = si->io.pck_rcv;
2700 tcp_ack = si->io.pck_snd;
2701 tcp_ctl = 0x14; /* RST,ACK */
2706 dest_addr = &si->myname.sa.s;
2707 src_addr = &si->peername.sa.s;
2709 tcp_seqno = si->io.pck_rcv;
2710 tcp_ack = si->io.pck_snd;
2711 tcp_ctl = 0x18; /* PSH,ACK */
2713 si->io.pck_rcv += len;
2717 case SWRAP_RECV_RST:
2718 dest_addr = &si->myname.sa.s;
2719 src_addr = &si->peername.sa.s;
2721 if (si->type == SOCK_DGRAM) {
2725 tcp_seqno = si->io.pck_rcv;
2726 tcp_ack = si->io.pck_snd;
2727 tcp_ctl = 0x14; /* RST,ACK */
2732 src_addr = &si->myname.sa.s;
2735 si->io.pck_snd += len;
2739 case SWRAP_SENDTO_UNREACH:
2740 dest_addr = &si->myname.sa.s;
2747 case SWRAP_RECVFROM:
2748 dest_addr = &si->myname.sa.s;
2751 si->io.pck_rcv += len;
2755 case SWRAP_CLOSE_SEND:
2756 if (si->type != SOCK_STREAM) {
2760 src_addr = &si->myname.sa.s;
2761 dest_addr = &si->peername.sa.s;
2763 tcp_seqno = si->io.pck_snd;
2764 tcp_ack = si->io.pck_rcv;
2765 tcp_ctl = 0x11; /* FIN, ACK */
2767 si->io.pck_snd += 1;
2771 case SWRAP_CLOSE_RECV:
2772 if (si->type != SOCK_STREAM) {
2776 dest_addr = &si->myname.sa.s;
2777 src_addr = &si->peername.sa.s;
2779 tcp_seqno = si->io.pck_rcv;
2780 tcp_ack = si->io.pck_snd;
2781 tcp_ctl = 0x11; /* FIN,ACK */
2783 si->io.pck_rcv += 1;
2787 case SWRAP_CLOSE_ACK:
2788 if (si->type != SOCK_STREAM) {
2792 src_addr = &si->myname.sa.s;
2793 dest_addr = &si->peername.sa.s;
2795 tcp_seqno = si->io.pck_snd;
2796 tcp_ack = si->io.pck_rcv;
2797 tcp_ctl = 0x10; /* ACK */
2804 swrapGetTimeOfDay(&tv);
2806 return swrap_pcap_packet_init(&tv,
2810 (const uint8_t *)buf,
2819 static void swrap_pcap_dump_packet(struct socket_info *si,
2820 const struct sockaddr *addr,
2821 enum swrap_packet_type type,
2822 const void *buf, size_t len)
2824 const char *file_name;
2826 size_t packet_len = 0;
2829 file_name = swrap_pcap_init_file();
2834 packet = swrap_pcap_marshall_packet(si,
2840 if (packet == NULL) {
2844 fd = swrap_pcap_get_fd(file_name);
2846 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2855 /****************************************************************************
2857 ***************************************************************************/
2859 #ifdef HAVE_SIGNALFD
2860 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2864 rc = libc_signalfd(fd, mask, flags);
2866 swrap_remove_stale(fd);
2872 int signalfd(int fd, const sigset_t *mask, int flags)
2874 return swrap_signalfd(fd, mask, flags);
2878 /****************************************************************************
2880 ***************************************************************************/
2882 static int swrap_socket(int family, int type, int protocol)
2884 struct socket_info *si = NULL;
2885 struct socket_info _si = { 0 };
2888 int real_type = type;
2891 * Remove possible addition flags passed to socket() so
2892 * do not fail checking the type.
2893 * See https://lwn.net/Articles/281965/
2896 real_type &= ~SOCK_CLOEXEC;
2898 #ifdef SOCK_NONBLOCK
2899 real_type &= ~SOCK_NONBLOCK;
2902 if (!socket_wrapper_enabled()) {
2903 return libc_socket(family, type, protocol);
2914 #endif /* AF_NETLINK */
2917 #endif /* AF_PACKET */
2919 return libc_socket(family, type, protocol);
2921 errno = EAFNOSUPPORT;
2925 switch (real_type) {
2931 errno = EPROTONOSUPPORT;
2939 if (real_type == SOCK_STREAM) {
2944 if (real_type == SOCK_DGRAM) {
2949 errno = EPROTONOSUPPORT;
2954 * We must call libc_socket with type, from the caller, not the version
2955 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2957 fd = libc_socket(AF_UNIX, type, 0);
2963 /* Check if we have a stale fd and remove it */
2964 swrap_remove_stale(fd);
2967 si->family = family;
2969 /* however, the rest of the socket_wrapper code expects just
2970 * the type, not the flags */
2971 si->type = real_type;
2972 si->protocol = protocol;
2975 * Setup myname so getsockname() can succeed to find out the socket
2978 switch(si->family) {
2980 struct sockaddr_in sin = {
2981 .sin_family = AF_INET,
2984 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2985 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2989 struct sockaddr_in6 sin6 = {
2990 .sin6_family = AF_INET6,
2993 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2994 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
3002 ret = swrap_create_socket(si, fd);
3007 SWRAP_LOG(SWRAP_LOG_TRACE,
3008 "Created %s socket for protocol %s",
3009 family == AF_INET ? "IPv4" : "IPv6",
3010 real_type == SOCK_DGRAM ? "UDP" : "TCP");
3015 int socket(int family, int type, int protocol)
3017 return swrap_socket(family, type, protocol);
3020 /****************************************************************************
3022 ***************************************************************************/
3024 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
3028 rc = libc_socketpair(family, type, protocol, sv);
3030 swrap_remove_stale(sv[0]);
3031 swrap_remove_stale(sv[1]);
3037 int socketpair(int family, int type, int protocol, int sv[2])
3039 return swrap_socketpair(family, type, protocol, sv);
3042 /****************************************************************************
3044 ***************************************************************************/
3046 #ifdef HAVE_TIMERFD_CREATE
3047 static int swrap_timerfd_create(int clockid, int flags)
3051 fd = libc_timerfd_create(clockid, flags);
3053 swrap_remove_stale(fd);
3059 int timerfd_create(int clockid, int flags)
3061 return swrap_timerfd_create(clockid, flags);
3065 /****************************************************************************
3067 ***************************************************************************/
3069 static int swrap_pipe(int pipefd[2])
3073 rc = libc_pipe(pipefd);
3075 swrap_remove_stale(pipefd[0]);
3076 swrap_remove_stale(pipefd[1]);
3082 int pipe(int pipefd[2])
3084 return swrap_pipe(pipefd);
3087 /****************************************************************************
3089 ***************************************************************************/
3091 static int swrap_accept(int s,
3092 struct sockaddr *addr,
3096 struct socket_info *parent_si, *child_si;
3097 struct socket_info_fd *child_fi;
3100 struct swrap_address un_addr = {
3101 .sa_socklen = sizeof(struct sockaddr_un),
3103 struct swrap_address un_my_addr = {
3104 .sa_socklen = sizeof(struct sockaddr_un),
3106 struct swrap_address in_addr = {
3107 .sa_socklen = sizeof(struct sockaddr_storage),
3109 struct swrap_address in_my_addr = {
3110 .sa_socklen = sizeof(struct sockaddr_storage),
3114 parent_si = find_socket_info(s);
3117 return libc_accept4(s, addr, addrlen, flags);
3120 return libc_accept(s, addr, addrlen);
3125 * assume out sockaddr have the same size as the in parent
3128 in_addr.sa_socklen = socket_length(parent_si->family);
3129 if (in_addr.sa_socklen <= 0) {
3135 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3138 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3141 if (errno == ENOTSOCK) {
3142 /* Remove stale fds */
3143 swrap_remove_stale(s);
3150 ret = sockaddr_convert_from_un(parent_si,
3155 &in_addr.sa_socklen);
3161 idx = socket_wrapper_first_free_index();
3166 child_si = swrap_get_socket_info(idx);
3168 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
3169 if (child_fi == NULL) {
3177 child_si->family = parent_si->family;
3178 child_si->type = parent_si->type;
3179 child_si->protocol = parent_si->protocol;
3180 child_si->bound = 1;
3181 child_si->is_server = 1;
3182 child_si->connected = 1;
3184 child_si->peername = (struct swrap_address) {
3185 .sa_socklen = in_addr.sa_socklen,
3187 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3189 if (addr != NULL && addrlen != NULL) {
3190 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3192 memcpy(addr, &in_addr.sa.ss, copy_len);
3194 *addrlen = in_addr.sa_socklen;
3197 ret = libc_getsockname(fd,
3199 &un_my_addr.sa_socklen);
3206 ret = sockaddr_convert_from_un(child_si,
3208 un_my_addr.sa_socklen,
3211 &in_my_addr.sa_socklen);
3218 SWRAP_LOG(SWRAP_LOG_TRACE,
3219 "accept() path=%s, fd=%d",
3220 un_my_addr.sa.un.sun_path, s);
3222 child_si->myname = (struct swrap_address) {
3223 .sa_socklen = in_my_addr.sa_socklen,
3225 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3227 swrap_inc_refcount(child_si);
3228 first_free = swrap_get_next_free(child_si);
3229 swrap_set_next_free(child_si, 0);
3231 child_fi->si_index = idx;
3233 SWRAP_DLIST_ADD(socket_fds, child_fi);
3236 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3237 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3238 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3245 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3247 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3251 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3252 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3254 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3257 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3260 static int autobind_start_init;
3261 static int autobind_start;
3263 /* using sendto() or connect() on an unbound socket would give the
3264 recipient no way to reply, as unlike UDP and TCP, a unix domain
3265 socket can't auto-assign ephemeral port numbers, so we need to
3267 Note: this might change the family from ipv6 to ipv4
3269 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3271 struct swrap_address un_addr = {
3272 .sa_socklen = sizeof(struct sockaddr_un),
3280 if (autobind_start_init != 1) {
3281 autobind_start_init = 1;
3282 autobind_start = getpid();
3283 autobind_start %= 50000;
3284 autobind_start += 10000;
3287 un_addr.sa.un.sun_family = AF_UNIX;
3291 struct sockaddr_in in;
3295 type = SOCKET_TYPE_CHAR_TCP;
3298 type = SOCKET_TYPE_CHAR_UDP;
3301 errno = ESOCKTNOSUPPORT;
3306 memset(&in, 0, sizeof(in));
3307 in.sin_family = AF_INET;
3308 in.sin_addr.s_addr = htonl(127<<24 |
3309 socket_wrapper_default_iface());
3311 si->myname = (struct swrap_address) {
3312 .sa_socklen = sizeof(in),
3314 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3319 struct sockaddr_in6 in6;
3321 if (si->family != family) {
3322 errno = ENETUNREACH;
3329 type = SOCKET_TYPE_CHAR_TCP_V6;
3332 type = SOCKET_TYPE_CHAR_UDP_V6;
3335 errno = ESOCKTNOSUPPORT;
3340 memset(&in6, 0, sizeof(in6));
3341 in6.sin6_family = AF_INET6;
3342 in6.sin6_addr = *swrap_ipv6();
3343 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3345 si->myname = (struct swrap_address) {
3346 .sa_socklen = sizeof(in6),
3348 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3353 errno = ESOCKTNOSUPPORT;
3358 if (autobind_start > 60000) {
3359 autobind_start = 10000;
3362 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3363 port = autobind_start + i;
3364 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3365 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3366 type, socket_wrapper_default_iface(), port);
3367 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3369 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3374 si->un_addr = un_addr.sa.un;
3377 autobind_start = port + 1;
3380 if (i == SOCKET_MAX_SOCKETS) {
3381 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3382 "interface "SOCKET_FORMAT,
3385 socket_wrapper_default_iface(),
3392 si->family = family;
3393 set_port(si->family, port, &si->myname);
3401 /****************************************************************************
3403 ***************************************************************************/
3405 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3409 struct swrap_address un_addr = {
3410 .sa_socklen = sizeof(struct sockaddr_un),
3412 struct socket_info *si = find_socket_info(s);
3416 return libc_connect(s, serv_addr, addrlen);
3419 if (si->bound == 0) {
3420 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3426 if (si->family != serv_addr->sa_family) {
3432 ret = sockaddr_convert_to_un(si, serv_addr,
3433 addrlen, &un_addr.sa.un, 0, &bcast);
3439 errno = ENETUNREACH;
3444 if (si->type == SOCK_DGRAM) {
3445 si->defer_connect = 1;
3448 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3450 ret = libc_connect(s,
3452 un_addr.sa_socklen);
3455 SWRAP_LOG(SWRAP_LOG_TRACE,
3456 "connect() path=%s, fd=%d",
3457 un_addr.sa.un.sun_path, s);
3460 /* to give better errors */
3461 if (ret == -1 && errno == ENOENT) {
3462 errno = EHOSTUNREACH;
3466 si->peername = (struct swrap_address) {
3467 .sa_socklen = addrlen,
3470 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3474 * When we connect() on a socket than we have to bind the
3475 * outgoing connection on the interface we use for the
3476 * transport. We already bound it on the right interface
3477 * but here we have to update the name so getsockname()
3478 * returns correct information.
3480 if (si->bindname.sa_socklen > 0) {
3481 si->myname = (struct swrap_address) {
3482 .sa_socklen = si->bindname.sa_socklen,
3485 memcpy(&si->myname.sa.ss,
3486 &si->bindname.sa.ss,
3487 si->bindname.sa_socklen);
3489 /* Cleanup bindname */
3490 si->bindname = (struct swrap_address) {
3495 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3496 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3498 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3505 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3507 return swrap_connect(s, serv_addr, addrlen);
3510 /****************************************************************************
3512 ***************************************************************************/
3514 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3517 struct swrap_address un_addr = {
3518 .sa_socklen = sizeof(struct sockaddr_un),
3520 struct socket_info *si = find_socket_info(s);
3527 return libc_bind(s, myaddr, addrlen);
3530 switch (si->family) {
3532 const struct sockaddr_in *sin;
3533 if (addrlen < sizeof(struct sockaddr_in)) {
3534 bind_error = EINVAL;
3538 sin = (const struct sockaddr_in *)(const void *)myaddr;
3540 if (sin->sin_family != AF_INET) {
3541 bind_error = EAFNOSUPPORT;
3544 /* special case for AF_UNSPEC */
3545 if (sin->sin_family == AF_UNSPEC &&
3546 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3555 const struct sockaddr_in6 *sin6;
3556 if (addrlen < sizeof(struct sockaddr_in6)) {
3557 bind_error = EINVAL;
3561 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3563 if (sin6->sin6_family != AF_INET6) {
3564 bind_error = EAFNOSUPPORT;
3571 bind_error = EINVAL;
3575 if (bind_error != 0) {
3581 in_use = check_addr_port_in_use(myaddr, addrlen);
3588 si->myname.sa_socklen = addrlen;
3589 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3591 ret = sockaddr_convert_to_un(si,
3601 unlink(un_addr.sa.un.sun_path);
3603 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3605 SWRAP_LOG(SWRAP_LOG_TRACE,
3606 "bind() path=%s, fd=%d",
3607 un_addr.sa.un.sun_path, s);
3616 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3618 return swrap_bind(s, myaddr, addrlen);
3621 /****************************************************************************
3623 ***************************************************************************/
3625 #ifdef HAVE_BINDRESVPORT
3626 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3628 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3630 struct swrap_address myaddr = {
3631 .sa_socklen = sizeof(struct sockaddr_storage),
3634 static uint16_t port;
3639 #define SWRAP_STARTPORT 600
3640 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3641 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3644 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3648 salen = myaddr.sa_socklen;
3651 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3657 memset(&myaddr.sa.ss, 0, salen);
3662 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3665 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3667 salen = sizeof(struct sockaddr_in);
3668 sinp->sin_port = htons(port);
3672 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3674 salen = sizeof(struct sockaddr_in6);
3675 sin6p->sin6_port = htons(port);
3679 errno = EAFNOSUPPORT;
3684 if (port > SWRAP_ENDPORT) {
3685 port = SWRAP_STARTPORT;
3688 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3689 if (rc == 0 || errno != EADDRINUSE) {
3697 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3699 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3703 /****************************************************************************
3705 ***************************************************************************/
3707 static int swrap_listen(int s, int backlog)
3710 struct socket_info *si = find_socket_info(s);
3713 return libc_listen(s, backlog);
3716 if (si->bound == 0) {
3717 ret = swrap_auto_bind(s, si, si->family);
3724 ret = libc_listen(s, backlog);
3729 int listen(int s, int backlog)
3731 return swrap_listen(s, backlog);
3734 /****************************************************************************
3736 ***************************************************************************/
3738 static FILE *swrap_fopen(const char *name, const char *mode)
3742 fp = libc_fopen(name, mode);
3744 int fd = fileno(fp);
3746 swrap_remove_stale(fd);
3752 FILE *fopen(const char *name, const char *mode)
3754 return swrap_fopen(name, mode);
3757 /****************************************************************************
3759 ***************************************************************************/
3762 static FILE *swrap_fopen64(const char *name, const char *mode)
3766 fp = libc_fopen64(name, mode);
3768 int fd = fileno(fp);
3770 swrap_remove_stale(fd);
3776 FILE *fopen64(const char *name, const char *mode)
3778 return swrap_fopen64(name, mode);
3780 #endif /* HAVE_FOPEN64 */
3782 /****************************************************************************
3784 ***************************************************************************/
3786 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3790 ret = libc_vopen(pathname, flags, ap);
3793 * There are methods for closing descriptors (libc-internal code
3794 * paths, direct syscalls) which close descriptors in ways that
3795 * we can't intercept, so try to recover when we notice that
3798 swrap_remove_stale(ret);
3803 int open(const char *pathname, int flags, ...)
3808 va_start(ap, flags);
3809 fd = swrap_vopen(pathname, flags, ap);
3815 /****************************************************************************
3817 ***************************************************************************/
3820 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
3824 ret = libc_vopen64(pathname, flags, ap);
3827 * There are methods for closing descriptors (libc-internal code
3828 * paths, direct syscalls) which close descriptors in ways that
3829 * we can't intercept, so try to recover when we notice that
3832 swrap_remove_stale(ret);
3837 int open64(const char *pathname, int flags, ...)
3842 va_start(ap, flags);
3843 fd = swrap_vopen64(pathname, flags, ap);
3848 #endif /* HAVE_OPEN64 */
3850 /****************************************************************************
3852 ***************************************************************************/
3854 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3858 ret = libc_vopenat(dirfd, path, flags, ap);
3861 * There are methods for closing descriptors (libc-internal code
3862 * paths, direct syscalls) which close descriptors in ways that
3863 * we can't intercept, so try to recover when we notice that
3866 swrap_remove_stale(ret);
3872 int openat(int dirfd, const char *path, int flags, ...)
3877 va_start(ap, flags);
3878 fd = swrap_vopenat(dirfd, path, flags, ap);
3884 /****************************************************************************
3886 ***************************************************************************/
3888 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3890 struct socket_info *si = find_socket_info(s);
3894 return libc_getpeername(s, name, addrlen);
3897 if (si->peername.sa_socklen == 0)
3903 len = MIN(*addrlen, si->peername.sa_socklen);
3908 memcpy(name, &si->peername.sa.ss, len);
3909 *addrlen = si->peername.sa_socklen;
3914 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3915 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3917 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3920 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3923 /****************************************************************************
3925 ***************************************************************************/
3927 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3929 struct socket_info *si = find_socket_info(s);
3933 return libc_getsockname(s, name, addrlen);
3936 len = MIN(*addrlen, si->myname.sa_socklen);
3941 memcpy(name, &si->myname.sa.ss, len);
3942 *addrlen = si->myname.sa_socklen;
3947 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3948 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3950 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3953 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3956 /****************************************************************************
3958 ***************************************************************************/
3961 # ifdef SO_PROTOTYPE /* The Solaris name */
3962 # define SO_PROTOCOL SO_PROTOTYPE
3963 # endif /* SO_PROTOTYPE */
3964 #endif /* SO_PROTOCOL */
3966 static int swrap_getsockopt(int s, int level, int optname,
3967 void *optval, socklen_t *optlen)
3969 struct socket_info *si = find_socket_info(s);
3973 return libc_getsockopt(s,
3980 if (level == SOL_SOCKET) {
3984 if (optval == NULL || optlen == NULL ||
3985 *optlen < (socklen_t)sizeof(int)) {
3991 *optlen = sizeof(int);
3992 *(int *)optval = si->family;
3995 #endif /* SO_DOMAIN */
3999 if (optval == NULL || optlen == NULL ||
4000 *optlen < (socklen_t)sizeof(int)) {
4006 *optlen = sizeof(int);
4007 *(int *)optval = si->protocol;
4010 #endif /* SO_PROTOCOL */
4012 if (optval == NULL || optlen == NULL ||
4013 *optlen < (socklen_t)sizeof(int)) {
4019 *optlen = sizeof(int);
4020 *(int *)optval = si->type;
4024 ret = libc_getsockopt(s,
4031 } else if (level == IPPROTO_TCP) {
4036 * This enables sending packets directly out over TCP.
4037 * As a unix socket is doing that any way, report it as
4040 if (optval == NULL || optlen == NULL ||
4041 *optlen < (socklen_t)sizeof(int)) {
4047 *optlen = sizeof(int);
4048 *(int *)optval = si->tcp_nodelay;
4052 #endif /* TCP_NODELAY */
4058 errno = ENOPROTOOPT;
4065 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4066 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
4068 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
4071 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
4074 /****************************************************************************
4076 ***************************************************************************/
4078 static int swrap_setsockopt(int s, int level, int optname,
4079 const void *optval, socklen_t optlen)
4081 struct socket_info *si = find_socket_info(s);
4085 return libc_setsockopt(s,
4092 if (level == SOL_SOCKET) {
4093 return libc_setsockopt(s,
4100 if (level == IPPROTO_TCP) {
4107 * This enables sending packets directly out over TCP.
4108 * A unix socket is doing that any way.
4110 if (optval == NULL || optlen == 0 ||
4111 optlen < (socklen_t)sizeof(int)) {
4117 i = *discard_const_p(int, optval);
4118 if (i != 0 && i != 1) {
4123 si->tcp_nodelay = i;
4128 #endif /* TCP_NODELAY */
4134 switch (si->family) {
4136 if (level == IPPROTO_IP) {
4138 if (optname == IP_PKTINFO) {
4139 si->pktinfo = AF_INET;
4141 #endif /* IP_PKTINFO */
4147 if (level == IPPROTO_IPV6) {
4148 #ifdef IPV6_RECVPKTINFO
4149 if (optname == IPV6_RECVPKTINFO) {
4150 si->pktinfo = AF_INET6;
4152 #endif /* IPV6_PKTINFO */
4158 errno = ENOPROTOOPT;
4167 int setsockopt(int s, int level, int optname,
4168 const void *optval, socklen_t optlen)
4170 return swrap_setsockopt(s, level, optname, optval, optlen);
4173 /****************************************************************************
4175 ***************************************************************************/
4177 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4179 struct socket_info *si = find_socket_info(s);
4185 return libc_vioctl(s, r, va);
4190 rc = libc_vioctl(s, r, va);
4194 value = *((int *)va_arg(ap, int *));
4196 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4197 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4198 } else if (value == 0) { /* END OF FILE */
4199 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4209 #ifdef HAVE_IOCTL_INT
4210 int ioctl(int s, int r, ...)
4212 int ioctl(int s, unsigned long int r, ...)
4220 rc = swrap_vioctl(s, (unsigned long int) r, va);
4231 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4234 # ifdef _ALIGN /* BSD */
4235 #define CMSG_ALIGN _ALIGN
4237 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4238 # endif /* _ALIGN */
4239 #endif /* CMSG_ALIGN */
4242 * @brief Add a cmsghdr to a msghdr.
4244 * This is an function to add any type of cmsghdr. It will operate on the
4245 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4246 * the buffer position after the added cmsg element. Hence, this function is
4247 * intended to be used with an intermediate msghdr and not on the original
4248 * one handed in by the client.
4250 * @param[in] msg The msghdr to which to add the cmsg.
4252 * @param[in] level The cmsg level to set.
4254 * @param[in] type The cmsg type to set.
4256 * @param[in] data The cmsg data to set.
4258 * @param[in] len the length of the data to set.
4260 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4266 size_t cmlen = CMSG_LEN(len);
4267 size_t cmspace = CMSG_SPACE(len);
4268 uint8_t cmbuf[cmspace];
4269 void *cast_ptr = (void *)cmbuf;
4270 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4273 memset(cmbuf, 0, cmspace);
4275 if (msg->msg_controllen < cmlen) {
4276 cmlen = msg->msg_controllen;
4277 msg->msg_flags |= MSG_CTRUNC;
4280 if (msg->msg_controllen < cmspace) {
4281 cmspace = msg->msg_controllen;
4285 * We copy the full input data into an intermediate cmsghdr first
4286 * in order to more easily cope with truncation.
4288 cm->cmsg_len = cmlen;
4289 cm->cmsg_level = level;
4290 cm->cmsg_type = type;
4291 memcpy(CMSG_DATA(cm), data, len);
4294 * We now copy the possibly truncated buffer.
4295 * We copy cmlen bytes, but consume cmspace bytes,
4296 * leaving the possible padding uninitialiazed.
4298 p = (uint8_t *)msg->msg_control;
4299 memcpy(p, cm, cmlen);
4301 msg->msg_control = p;
4302 msg->msg_controllen -= cmspace;
4307 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4310 /* Add packet info */
4311 switch (si->pktinfo) {
4312 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4314 struct sockaddr_in *sin;
4315 #if defined(HAVE_STRUCT_IN_PKTINFO)
4316 struct in_pktinfo pkt;
4317 #elif defined(IP_RECVDSTADDR)
4321 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4322 sin = &si->bindname.sa.in;
4324 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4327 sin = &si->myname.sa.in;
4332 #if defined(HAVE_STRUCT_IN_PKTINFO)
4333 pkt.ipi_ifindex = socket_wrapper_default_iface();
4334 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4335 #elif defined(IP_RECVDSTADDR)
4336 pkt = sin->sin_addr;
4339 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4344 #endif /* IP_PKTINFO */
4345 #if defined(HAVE_IPV6)
4347 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4348 struct sockaddr_in6 *sin6;
4349 struct in6_pktinfo pkt6;
4351 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4352 sin6 = &si->bindname.sa.in6;
4354 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4357 sin6 = &si->myname.sa.in6;
4362 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4363 pkt6.ipi6_addr = sin6->sin6_addr;
4365 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4366 &pkt6, sizeof(pkt6));
4367 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4371 #endif /* IPV6_PKTINFO */
4379 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4380 struct msghdr *omsg)
4384 if (si->pktinfo > 0) {
4385 rc = swrap_msghdr_add_pktinfo(si, omsg);
4391 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4393 size_t *cm_data_space);
4394 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4396 size_t *cm_data_space);
4398 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4400 size_t *cm_data_space) {
4401 struct cmsghdr *cmsg;
4405 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4409 for (cmsg = CMSG_FIRSTHDR(msg);
4411 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4412 switch (cmsg->cmsg_level) {
4414 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4419 rc = swrap_sendmsg_copy_cmsg(cmsg,
4429 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4431 size_t *cm_data_space)
4436 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4438 p = realloc((*cm_data), cmspace);
4444 p = (*cm_data) + (*cm_data_space);
4445 *cm_data_space = cmspace;
4447 memcpy(p, cmsg, cmsg->cmsg_len);
4452 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4454 size_t *cm_data_space);
4457 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4459 size_t *cm_data_space)
4463 switch(cmsg->cmsg_type) {
4466 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4473 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4485 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4487 size_t *cm_data_space)
4489 (void)cmsg; /* unused */
4490 (void)cm_data; /* unused */
4491 (void)cm_data_space; /* unused */
4494 * Passing a IP pktinfo to a unix socket might be rejected by the
4495 * Kernel, at least on FreeBSD. So skip this cmsg.
4499 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4501 static ssize_t swrap_sendmsg_before(int fd,
4502 struct socket_info *si,
4504 struct iovec *tmp_iov,
4505 struct sockaddr_un *tmp_un,
4506 const struct sockaddr_un **to_un,
4507 const struct sockaddr **to,
4527 if (!si->connected) {
4532 if (msg->msg_iovlen == 0) {
4536 mtu = socket_wrapper_mtu();
4537 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4539 nlen = len + msg->msg_iov[i].iov_len;
4544 msg->msg_iovlen = i;
4545 if (msg->msg_iovlen == 0) {
4546 *tmp_iov = msg->msg_iov[0];
4547 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4549 msg->msg_iov = tmp_iov;
4550 msg->msg_iovlen = 1;
4555 if (si->connected) {
4556 if (msg->msg_name != NULL) {
4558 * We are dealing with unix sockets and if we
4559 * are connected, we should only talk to the
4560 * connected unix path. Using the fd to send
4561 * to another server would be hard to achieve.
4563 msg->msg_name = NULL;
4564 msg->msg_namelen = 0;
4567 const struct sockaddr *msg_name;
4568 msg_name = (const struct sockaddr *)msg->msg_name;
4570 if (msg_name == NULL) {
4576 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4588 msg->msg_name = tmp_un;
4589 msg->msg_namelen = sizeof(*tmp_un);
4592 if (si->bound == 0) {
4593 ret = swrap_auto_bind(fd, si, si->family);
4595 if (errno == ENOTSOCK) {
4596 swrap_remove_stale(fd);
4599 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4605 if (!si->defer_connect) {
4609 ret = sockaddr_convert_to_un(si,
4611 si->peername.sa_socklen,
4619 ret = libc_connect(fd,
4620 (struct sockaddr *)(void *)tmp_un,
4623 /* to give better errors */
4624 if (ret == -1 && errno == ENOENT) {
4625 errno = EHOSTUNREACH;
4632 si->defer_connect = 0;
4635 errno = EHOSTUNREACH;
4639 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4640 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4641 uint8_t *cmbuf = NULL;
4644 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4651 msg->msg_controllen = 0;
4652 msg->msg_control = NULL;
4653 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4654 memcpy(msg->msg_control, cmbuf, cmlen);
4655 msg->msg_controllen = cmlen;
4664 static void swrap_sendmsg_after(int fd,
4665 struct socket_info *si,
4667 const struct sockaddr *to,
4670 int saved_errno = errno;
4677 /* to give better errors */
4679 if (saved_errno == ENOENT) {
4680 saved_errno = EHOSTUNREACH;
4681 } else if (saved_errno == ENOTSOCK) {
4682 /* If the fd is not a socket, remove it */
4683 swrap_remove_stale(fd);
4687 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4688 avail += msg->msg_iov[i].iov_len;
4692 remain = MIN(80, avail);
4697 /* we capture it as one single packet */
4698 buf = (uint8_t *)malloc(remain);
4700 /* we just not capture the packet */
4701 errno = saved_errno;
4705 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4706 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4708 msg->msg_iov[i].iov_base,
4711 remain -= this_time;
4718 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4719 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4721 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4726 if (si->connected) {
4727 to = &si->peername.sa.s;
4730 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4731 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4733 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4739 errno = saved_errno;
4742 static int swrap_recvmsg_before(int fd,
4743 struct socket_info *si,
4745 struct iovec *tmp_iov)
4750 (void)fd; /* unused */
4755 if (!si->connected) {
4760 if (msg->msg_iovlen == 0) {
4764 mtu = socket_wrapper_mtu();
4765 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4767 nlen = len + msg->msg_iov[i].iov_len;
4772 msg->msg_iovlen = i;
4773 if (msg->msg_iovlen == 0) {
4774 *tmp_iov = msg->msg_iov[0];
4775 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4777 msg->msg_iov = tmp_iov;
4778 msg->msg_iovlen = 1;
4783 if (msg->msg_name == NULL) {
4788 if (msg->msg_iovlen == 0) {
4792 if (si->bound == 0) {
4793 ret = swrap_auto_bind(fd, si, si->family);
4796 * When attempting to read or write to a
4797 * descriptor, if an underlying autobind fails
4798 * because it's not a socket, stop intercepting
4799 * uses of that descriptor.
4801 if (errno == ENOTSOCK) {
4802 swrap_remove_stale(fd);
4805 SWRAP_LOG(SWRAP_LOG_ERROR,
4806 "swrap_recvmsg_before failed");
4813 errno = EHOSTUNREACH;
4820 static int swrap_recvmsg_after(int fd,
4821 struct socket_info *si,
4823 const struct sockaddr_un *un_addr,
4824 socklen_t un_addrlen,
4827 int saved_errno = errno;
4829 uint8_t *buf = NULL;
4835 /* to give better errors */
4837 if (saved_errno == ENOENT) {
4838 saved_errno = EHOSTUNREACH;
4839 } else if (saved_errno == ENOTSOCK) {
4840 /* If the fd is not a socket, remove it */
4841 swrap_remove_stale(fd);
4845 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4846 avail += msg->msg_iov[i].iov_len;
4849 /* Convert the socket address before we leave */
4850 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4851 rc = sockaddr_convert_from_un(si,
4868 remain = MIN(80, avail);
4873 /* we capture it as one single packet */
4874 buf = (uint8_t *)malloc(remain);
4876 /* we just not capture the packet */
4877 errno = saved_errno;
4881 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4882 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4884 msg->msg_iov[i].iov_base,
4887 remain -= this_time;
4892 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4893 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4894 } else if (ret == 0) { /* END OF FILE */
4895 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4896 } else if (ret > 0) {
4897 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4906 if (un_addr != NULL) {
4907 swrap_pcap_dump_packet(si,
4913 swrap_pcap_dump_packet(si,
4926 errno = saved_errno;
4928 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4930 msg->msg_controllen > 0 &&
4931 msg->msg_control != NULL) {
4932 rc = swrap_msghdr_add_socket_info(si, msg);
4942 /****************************************************************************
4944 ***************************************************************************/
4946 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4947 struct sockaddr *from, socklen_t *fromlen)
4949 struct swrap_address from_addr = {
4950 .sa_socklen = sizeof(struct sockaddr_un),
4953 struct socket_info *si = find_socket_info(s);
4954 struct swrap_address saddr = {
4955 .sa_socklen = sizeof(struct sockaddr_storage),
4962 return libc_recvfrom(s,
4974 if (from != NULL && fromlen != NULL) {
4975 msg.msg_name = from; /* optional address */
4976 msg.msg_namelen = *fromlen; /* size of address */
4978 msg.msg_name = &saddr.sa.s; /* optional address */
4979 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4981 msg.msg_iov = &tmp; /* scatter/gather array */
4982 msg.msg_iovlen = 1; /* # elements in msg_iov */
4983 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4984 msg.msg_control = NULL; /* ancillary data, see below */
4985 msg.msg_controllen = 0; /* ancillary data buffer len */
4986 msg.msg_flags = 0; /* flags on received message */
4989 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4994 buf = msg.msg_iov[0].iov_base;
4995 len = msg.msg_iov[0].iov_len;
4997 ret = libc_recvfrom(s,
5002 &from_addr.sa_socklen);
5007 tret = swrap_recvmsg_after(s,
5011 from_addr.sa_socklen,
5017 if (from != NULL && fromlen != NULL) {
5018 *fromlen = msg.msg_namelen;
5024 #ifdef HAVE_ACCEPT_PSOCKLEN_T
5025 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5026 struct sockaddr *from, Psocklen_t fromlen)
5028 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
5029 struct sockaddr *from, socklen_t *fromlen)
5032 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
5035 /****************************************************************************
5037 ***************************************************************************/
5039 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
5040 const struct sockaddr *to, socklen_t tolen)
5044 struct swrap_address un_addr = {
5045 .sa_socklen = sizeof(struct sockaddr_un),
5047 const struct sockaddr_un *to_un = NULL;
5050 struct socket_info *si = find_socket_info(s);
5054 return libc_sendto(s, buf, len, flags, to, tolen);
5057 tmp.iov_base = discard_const_p(char, buf);
5061 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
5062 msg.msg_namelen = tolen; /* size of address */
5063 msg.msg_iov = &tmp; /* scatter/gather array */
5064 msg.msg_iovlen = 1; /* # elements in msg_iov */
5065 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5066 msg.msg_control = NULL; /* ancillary data, see below */
5067 msg.msg_controllen = 0; /* ancillary data buffer len */
5068 msg.msg_flags = 0; /* flags on received message */
5071 rc = swrap_sendmsg_before(s,
5083 buf = msg.msg_iov[0].iov_base;
5084 len = msg.msg_iov[0].iov_len;
5089 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5092 type = SOCKET_TYPE_CHAR_UDP;
5094 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5095 snprintf(un_addr.sa.un.sun_path,
5096 sizeof(un_addr.sa.un.sun_path),
5098 socket_wrapper_dir(), type, iface, prt);
5099 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5101 /* ignore the any errors in broadcast sends */
5107 un_addr.sa_socklen);
5110 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5116 * If it is a dgram socket and we are connected, don't include the
5119 if (si->type == SOCK_DGRAM && si->connected) {
5120 ret = libc_sendto(s,
5127 ret = libc_sendto(s,
5131 (struct sockaddr *)msg.msg_name,
5135 swrap_sendmsg_after(s, si, &msg, to, ret);
5140 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5141 const struct sockaddr *to, socklen_t tolen)
5143 return swrap_sendto(s, buf, len, flags, to, tolen);
5146 /****************************************************************************
5148 ***************************************************************************/
5150 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5152 struct socket_info *si;
5154 struct swrap_address saddr = {
5155 .sa_socklen = sizeof(struct sockaddr_storage),
5161 si = find_socket_info(s);
5163 return libc_recv(s, buf, len, flags);
5170 msg.msg_name = &saddr.sa.s; /* optional address */
5171 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5172 msg.msg_iov = &tmp; /* scatter/gather array */
5173 msg.msg_iovlen = 1; /* # elements in msg_iov */
5174 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5175 msg.msg_control = NULL; /* ancillary data, see below */
5176 msg.msg_controllen = 0; /* ancillary data buffer len */
5177 msg.msg_flags = 0; /* flags on received message */
5180 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5185 buf = msg.msg_iov[0].iov_base;
5186 len = msg.msg_iov[0].iov_len;
5188 ret = libc_recv(s, buf, len, flags);
5190 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5198 ssize_t recv(int s, void *buf, size_t len, int flags)
5200 return swrap_recv(s, buf, len, flags);
5203 /****************************************************************************
5205 ***************************************************************************/
5207 static ssize_t swrap_read(int s, void *buf, size_t len)
5209 struct socket_info *si;
5212 struct swrap_address saddr = {
5213 .sa_socklen = sizeof(struct sockaddr_storage),
5218 si = find_socket_info(s);
5220 return libc_read(s, buf, len);
5227 msg.msg_name = &saddr.sa.ss; /* optional address */
5228 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5229 msg.msg_iov = &tmp; /* scatter/gather array */
5230 msg.msg_iovlen = 1; /* # elements in msg_iov */
5231 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5232 msg.msg_control = NULL; /* ancillary data, see below */
5233 msg.msg_controllen = 0; /* ancillary data buffer len */
5234 msg.msg_flags = 0; /* flags on received message */
5237 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5239 if (tret == -ENOTSOCK) {
5240 return libc_read(s, buf, len);
5245 buf = msg.msg_iov[0].iov_base;
5246 len = msg.msg_iov[0].iov_len;
5248 ret = libc_read(s, buf, len);
5250 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5258 ssize_t read(int s, void *buf, size_t len)
5260 return swrap_read(s, buf, len);
5263 /****************************************************************************
5265 ***************************************************************************/
5267 static ssize_t swrap_write(int s, const void *buf, size_t len)
5271 struct sockaddr_un un_addr;
5274 struct socket_info *si;
5276 si = find_socket_info(s);
5278 return libc_write(s, buf, len);
5281 tmp.iov_base = discard_const_p(char, buf);
5285 msg.msg_name = NULL; /* optional address */
5286 msg.msg_namelen = 0; /* size of address */
5287 msg.msg_iov = &tmp; /* scatter/gather array */
5288 msg.msg_iovlen = 1; /* # elements in msg_iov */
5289 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5290 msg.msg_control = NULL; /* ancillary data, see below */
5291 msg.msg_controllen = 0; /* ancillary data buffer len */
5292 msg.msg_flags = 0; /* flags on received message */
5295 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5300 buf = msg.msg_iov[0].iov_base;
5301 len = msg.msg_iov[0].iov_len;
5303 ret = libc_write(s, buf, len);
5305 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5310 ssize_t write(int s, const void *buf, size_t len)
5312 return swrap_write(s, buf, len);
5315 /****************************************************************************
5317 ***************************************************************************/
5319 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5323 struct sockaddr_un un_addr;
5326 struct socket_info *si = find_socket_info(s);
5329 return libc_send(s, buf, len, flags);
5332 tmp.iov_base = discard_const_p(char, buf);
5336 msg.msg_name = NULL; /* optional address */
5337 msg.msg_namelen = 0; /* size of address */
5338 msg.msg_iov = &tmp; /* scatter/gather array */
5339 msg.msg_iovlen = 1; /* # elements in msg_iov */
5340 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5341 msg.msg_control = NULL; /* ancillary data, see below */
5342 msg.msg_controllen = 0; /* ancillary data buffer len */
5343 msg.msg_flags = 0; /* flags on received message */
5346 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5351 buf = msg.msg_iov[0].iov_base;
5352 len = msg.msg_iov[0].iov_len;
5354 ret = libc_send(s, buf, len, flags);
5356 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5361 ssize_t send(int s, const void *buf, size_t len, int flags)
5363 return swrap_send(s, buf, len, flags);
5366 /****************************************************************************
5368 ***************************************************************************/
5370 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5372 struct swrap_address from_addr = {
5373 .sa_socklen = sizeof(struct sockaddr_un),
5375 struct swrap_address convert_addr = {
5376 .sa_socklen = sizeof(struct sockaddr_storage),
5378 struct socket_info *si;
5381 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5382 size_t msg_ctrllen_filled;
5383 size_t msg_ctrllen_left;
5389 si = find_socket_info(s);
5391 return libc_recvmsg(s, omsg, flags);
5394 tmp.iov_base = NULL;
5398 msg.msg_name = &from_addr.sa; /* optional address */
5399 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5400 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5401 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5402 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5403 msg_ctrllen_filled = 0;
5404 msg_ctrllen_left = omsg->msg_controllen;
5406 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5407 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5408 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5411 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5416 ret = libc_recvmsg(s, &msg, flags);
5418 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5419 msg_ctrllen_filled += msg.msg_controllen;
5420 msg_ctrllen_left -= msg.msg_controllen;
5422 if (omsg->msg_control != NULL) {
5425 p = omsg->msg_control;
5426 p += msg_ctrllen_filled;
5428 msg.msg_control = p;
5429 msg.msg_controllen = msg_ctrllen_left;
5431 msg.msg_control = NULL;
5432 msg.msg_controllen = 0;
5437 * We convert the unix address to a IP address so we need a buffer
5438 * which can store the address in case of SOCK_DGRAM, see below.
5440 msg.msg_name = &convert_addr.sa;
5441 msg.msg_namelen = convert_addr.sa_socklen;
5443 rc = swrap_recvmsg_after(s,
5447 from_addr.sa_socklen,
5453 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5454 if (omsg->msg_control != NULL) {
5455 /* msg.msg_controllen = space left */
5456 msg_ctrllen_left = msg.msg_controllen;
5457 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5460 /* Update the original message length */
5461 omsg->msg_controllen = msg_ctrllen_filled;
5462 omsg->msg_flags = msg.msg_flags;
5464 omsg->msg_iovlen = msg.msg_iovlen;
5469 * The msg_name field points to a caller-allocated buffer that is
5470 * used to return the source address if the socket is unconnected. The
5471 * caller should set msg_namelen to the size of this buffer before this
5472 * call; upon return from a successful call, msg_name will contain the
5473 * length of the returned address. If the application does not need
5474 * to know the source address, msg_name can be specified as NULL.
5476 if (si->type == SOCK_STREAM) {
5477 omsg->msg_namelen = 0;
5478 } else if (omsg->msg_name != NULL &&
5479 omsg->msg_namelen != 0 &&
5480 omsg->msg_namelen >= msg.msg_namelen) {
5481 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5482 omsg->msg_namelen = msg.msg_namelen;
5488 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5490 return swrap_recvmsg(sockfd, msg, flags);
5493 /****************************************************************************
5495 ***************************************************************************/
5497 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5501 struct sockaddr_un un_addr;
5502 const struct sockaddr_un *to_un = NULL;
5503 const struct sockaddr *to = NULL;
5506 struct socket_info *si = find_socket_info(s);
5510 return libc_sendmsg(s, omsg, flags);
5513 ZERO_STRUCT(un_addr);
5515 tmp.iov_base = NULL;
5520 if (si->connected == 0) {
5521 msg.msg_name = omsg->msg_name; /* optional address */
5522 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5524 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5525 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5526 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5527 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5528 /* omsg is a const so use a local buffer for modifications */
5529 uint8_t cmbuf[omsg->msg_controllen];
5531 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5533 msg.msg_control = cmbuf; /* ancillary data, see below */
5534 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5536 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5539 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5547 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5555 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5556 avail += msg.msg_iov[i].iov_len;
5562 /* we capture it as one single packet */
5563 buf = (uint8_t *)malloc(remain);
5568 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5569 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5571 msg.msg_iov[i].iov_base,
5574 remain -= this_time;
5577 type = SOCKET_TYPE_CHAR_UDP;
5579 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5580 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5581 socket_wrapper_dir(), type, iface, prt);
5582 if (stat(un_addr.sun_path, &st) != 0) continue;
5584 msg.msg_name = &un_addr; /* optional address */
5585 msg.msg_namelen = sizeof(un_addr); /* size of address */
5587 /* ignore the any errors in broadcast sends */
5588 libc_sendmsg(s, &msg, flags);
5591 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5597 ret = libc_sendmsg(s, &msg, flags);
5599 swrap_sendmsg_after(s, si, &msg, to, ret);
5604 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5606 return swrap_sendmsg(s, omsg, flags);
5609 /****************************************************************************
5611 ***************************************************************************/
5613 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5615 struct socket_info *si;
5618 struct swrap_address saddr = {
5619 .sa_socklen = sizeof(struct sockaddr_storage)
5624 si = find_socket_info(s);
5626 return libc_readv(s, vector, count);
5629 tmp.iov_base = NULL;
5633 msg.msg_name = &saddr.sa.s; /* optional address */
5634 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5635 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5636 msg.msg_iovlen = count; /* # elements in msg_iov */
5637 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5638 msg.msg_control = NULL; /* ancillary data, see below */
5639 msg.msg_controllen = 0; /* ancillary data buffer len */
5640 msg.msg_flags = 0; /* flags on received message */
5643 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5645 if (rc == -ENOTSOCK) {
5646 return libc_readv(s, vector, count);
5651 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5653 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5661 ssize_t readv(int s, const struct iovec *vector, int count)
5663 return swrap_readv(s, vector, count);
5666 /****************************************************************************
5668 ***************************************************************************/
5670 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5674 struct sockaddr_un un_addr;
5677 struct socket_info *si = find_socket_info(s);
5680 return libc_writev(s, vector, count);
5683 tmp.iov_base = NULL;
5687 msg.msg_name = NULL; /* optional address */
5688 msg.msg_namelen = 0; /* size of address */
5689 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5690 msg.msg_iovlen = count; /* # elements in msg_iov */
5691 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5692 msg.msg_control = NULL; /* ancillary data, see below */
5693 msg.msg_controllen = 0; /* ancillary data buffer len */
5694 msg.msg_flags = 0; /* flags on received message */
5697 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5699 if (rc == -ENOTSOCK) {
5700 return libc_readv(s, vector, count);
5705 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5707 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5712 ssize_t writev(int s, const struct iovec *vector, int count)
5714 return swrap_writev(s, vector, count);
5717 /****************************
5719 ***************************/
5721 static int swrap_close(int fd)
5723 struct socket_info_fd *fi = find_socket_info_fd(fd);
5724 struct socket_info *si = NULL;
5729 return libc_close(fd);
5732 si_index = fi->si_index;
5734 SWRAP_DLIST_REMOVE(socket_fds, fi);
5737 ret = libc_close(fd);
5739 si = swrap_get_socket_info(si_index);
5740 swrap_dec_refcount(si);
5742 if (swrap_get_refcount(si) > 0) {
5743 /* there are still references left */
5747 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5748 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5751 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5752 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5753 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5756 if (si->un_addr.sun_path[0] != '\0') {
5757 unlink(si->un_addr.sun_path);
5760 swrap_set_next_free(si, first_free);
5761 first_free = si_index;
5768 return swrap_close(fd);
5771 /****************************
5773 ***************************/
5775 static int swrap_dup(int fd)
5777 struct socket_info *si;
5778 struct socket_info_fd *src_fi, *fi;
5780 src_fi = find_socket_info_fd(fd);
5781 if (src_fi == NULL) {
5782 return libc_dup(fd);
5785 si = swrap_get_socket_info(src_fi->si_index);
5787 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5793 fi->fd = libc_dup(fd);
5795 int saved_errno = errno;
5797 errno = saved_errno;
5801 swrap_inc_refcount(si);
5802 fi->si_index = src_fi->si_index;
5804 /* Make sure we don't have an entry for the fd */
5805 swrap_remove_stale(fi->fd);
5807 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5813 return swrap_dup(fd);
5816 /****************************
5818 ***************************/
5820 static int swrap_dup2(int fd, int newfd)
5822 struct socket_info *si;
5823 struct socket_info_fd *src_fi, *fi;
5825 src_fi = find_socket_info_fd(fd);
5826 if (src_fi == NULL) {
5827 return libc_dup2(fd, newfd);
5830 si = swrap_get_socket_info(src_fi->si_index);
5834 * According to the manpage:
5836 * "If oldfd is a valid file descriptor, and newfd has the same
5837 * value as oldfd, then dup2() does nothing, and returns newfd."
5842 if (find_socket_info(newfd)) {
5843 /* dup2() does an implicit close of newfd, which we
5844 * need to emulate */
5848 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5854 fi->fd = libc_dup2(fd, newfd);
5856 int saved_errno = errno;
5858 errno = saved_errno;
5862 swrap_inc_refcount(si);
5863 fi->si_index = src_fi->si_index;
5865 /* Make sure we don't have an entry for the fd */
5866 swrap_remove_stale(fi->fd);
5868 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5872 int dup2(int fd, int newfd)
5874 return swrap_dup2(fd, newfd);
5877 /****************************
5879 ***************************/
5881 static int swrap_vfcntl(int fd, int cmd, va_list va)
5883 struct socket_info_fd *src_fi, *fi;
5884 struct socket_info *si;
5887 src_fi = find_socket_info_fd(fd);
5888 if (src_fi == NULL) {
5889 return libc_vfcntl(fd, cmd, va);
5892 si = swrap_get_socket_info(src_fi->si_index);
5896 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5902 fi->fd = libc_vfcntl(fd, cmd, va);
5904 int saved_errno = errno;
5906 errno = saved_errno;
5910 swrap_inc_refcount(si);
5911 fi->si_index = src_fi->si_index;
5913 /* Make sure we don't have an entry for the fd */
5914 swrap_remove_stale(fi->fd);
5916 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5921 rc = libc_vfcntl(fd, cmd, va);
5928 int fcntl(int fd, int cmd, ...)
5935 rc = swrap_vfcntl(fd, cmd, va);
5942 /****************************
5944 ***************************/
5947 static int swrap_eventfd(int count, int flags)
5951 fd = libc_eventfd(count, flags);
5953 swrap_remove_stale(fd);
5959 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5960 int eventfd(unsigned int count, int flags)
5962 int eventfd(int count, int flags)
5965 return swrap_eventfd(count, flags);
5970 int pledge(const char *promises, const char *paths[])
5972 (void)promises; /* unused */
5973 (void)paths; /* unused */
5977 #endif /* HAVE_PLEDGE */
5979 static void swrap_thread_prepare(void)
5982 * This function should only be called here!!
5984 * We bind all symobls to avoid deadlocks of the fork is
5985 * interrupted by a signal handler using a symbol of this
5988 swrap_bind_symbol_all();
5993 static void swrap_thread_parent(void)
5998 static void swrap_thread_child(void)
6003 /****************************
6005 ***************************/
6006 void swrap_constructor(void)
6009 * If we hold a lock and the application forks, then the child
6010 * is not able to unlock the mutex and we are in a deadlock.
6011 * This should prevent such deadlocks.
6013 pthread_atfork(&swrap_thread_prepare,
6014 &swrap_thread_parent,
6015 &swrap_thread_child);
6018 /****************************
6020 ***************************/
6023 * This function is called when the library is unloaded and makes sure that
6024 * sockets get closed and the unix file for the socket are unlinked.
6026 void swrap_destructor(void)
6028 struct socket_info_fd *s = socket_fds;
6037 if (swrap.libc.handle != NULL) {
6038 dlclose(swrap.libc.handle);
6040 if (swrap.libc.socket_handle) {
6041 dlclose(swrap.libc.socket_handle);