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
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); \
189 #define SWRAP_DLIST_ADD(list,item) do { \
191 (item)->prev = NULL; \
192 (item)->next = NULL; \
195 (item)->prev = NULL; \
196 (item)->next = (list); \
197 (list)->prev = (item); \
202 #define SWRAP_DLIST_REMOVE(list,item) do { \
203 if ((list) == (item)) { \
204 (list) = (item)->next; \
206 (list)->prev = NULL; \
209 if ((item)->prev) { \
210 (item)->prev->next = (item)->next; \
212 if ((item)->next) { \
213 (item)->next->prev = (item)->prev; \
216 (item)->prev = NULL; \
217 (item)->next = NULL; \
220 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
222 if ((list) == NULL || (el) == NULL) { \
223 SWRAP_DLIST_ADD(list, item); \
225 (item)->prev = (el); \
226 (item)->next = (el)->next; \
227 (el)->next = (item); \
228 if ((item)->next != NULL) { \
229 (item)->next->prev = (item); \
234 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
235 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
237 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
240 /* we need to use a very terse format here as IRIX 6.4 silently
241 truncates names to 16 chars, so if we use a longer name then we
242 can't tell which port a packet came from with recvfrom()
244 with this format we have 8 chars left for the directory name
246 #define SOCKET_FORMAT "%c%02X%04X"
247 #define SOCKET_TYPE_CHAR_TCP 'T'
248 #define SOCKET_TYPE_CHAR_UDP 'U'
249 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
250 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
253 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
254 * format PCAP capture files (as the caller will simply continue from here).
256 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
257 #define SOCKET_WRAPPER_MTU_MIN 512
258 #define SOCKET_WRAPPER_MTU_MAX 32768
260 #define SOCKET_MAX_SOCKETS 1024
264 * Maximum number of socket_info structures that can
265 * be used. Can be overriden by the environment variable
266 * SOCKET_WRAPPER_MAX_SOCKETS.
268 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
270 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 256000
272 /* This limit is to avoid broadcast sendto() needing to stat too many
273 * files. It may be raised (with a performance cost) to up to 254
274 * without changing the format above */
275 #define MAX_WRAPPED_INTERFACES 64
277 struct swrap_address {
278 socklen_t sa_socklen;
281 struct sockaddr_in in;
283 struct sockaddr_in6 in6;
285 struct sockaddr_un un;
286 struct sockaddr_storage ss;
290 struct socket_info_fd {
291 struct socket_info_fd *prev, *next;
295 * Points to corresponding index in array of
296 * socket_info structures
305 unsigned int refcount;
320 /* The unix path so we can unlink it on close() */
321 struct sockaddr_un un_addr;
323 struct swrap_address bindname;
324 struct swrap_address myname;
325 struct swrap_address peername;
328 unsigned long pck_snd;
329 unsigned long pck_rcv;
333 static struct socket_info *sockets;
334 static size_t max_sockets = 0;
337 * While socket file descriptors are passed among different processes, the
338 * numerical value gets changed. So its better to store it locally to each
339 * process rather than including it within socket_info which will be shared.
341 static struct socket_info_fd *socket_fds;
343 /* The mutex for accessing the global libc.symbols */
344 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
346 /* Function prototypes */
348 bool socket_wrapper_enabled(void);
350 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
351 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
353 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
354 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
356 static void swrap_log(enum swrap_dbglvl_e dbglvl,
358 const char *format, ...)
363 unsigned int lvl = 0;
365 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
374 va_start(va, format);
375 vsnprintf(buffer, sizeof(buffer), format, va);
380 case SWRAP_LOG_ERROR:
382 "SWRAP_ERROR(%d) - %s: %s\n",
383 (int)getpid(), func, buffer);
387 "SWRAP_WARN(%d) - %s: %s\n",
388 (int)getpid(), func, buffer);
390 case SWRAP_LOG_DEBUG:
392 "SWRAP_DEBUG(%d) - %s: %s\n",
393 (int)getpid(), func, buffer);
395 case SWRAP_LOG_TRACE:
397 "SWRAP_TRACE(%d) - %s: %s\n",
398 (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, mode_t mode);
452 typedef int (*__libc_open64)(const char *pathname, int flags, mode_t mode);
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 SWRAP_LOCK(libc_symbol_binding); \
680 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
681 swrap.libc.symbols._libc_##sym_name.obj = \
682 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
684 SWRAP_UNLOCK(libc_symbol_binding)
686 #define swrap_bind_symbol_libsocket(sym_name) \
687 SWRAP_LOCK(libc_symbol_binding); \
688 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
689 swrap.libc.symbols._libc_##sym_name.obj = \
690 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
692 SWRAP_UNLOCK(libc_symbol_binding)
694 #define swrap_bind_symbol_libnsl(sym_name) \
695 SWRAP_LOCK(libc_symbol_binding); \
696 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
697 swrap.libc.symbols._libc_##sym_name.obj = \
698 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
700 SWRAP_UNLOCK(libc_symbol_binding)
705 * Functions especially from libc need to be loaded individually, you can't load
706 * all at once or gdb will segfault at startup. The same applies to valgrind and
707 * has probably something todo with with the linker.
708 * So we need load each function at the point it is called the first time.
711 static int libc_accept4(int sockfd,
712 struct sockaddr *addr,
716 swrap_bind_symbol_libsocket(accept4);
718 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
721 #else /* HAVE_ACCEPT4 */
723 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
725 swrap_bind_symbol_libsocket(accept);
727 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
729 #endif /* HAVE_ACCEPT4 */
731 static int libc_bind(int sockfd,
732 const struct sockaddr *addr,
735 swrap_bind_symbol_libsocket(bind);
737 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
740 static int libc_close(int fd)
742 swrap_bind_symbol_libc(close);
744 return swrap.libc.symbols._libc_close.f(fd);
747 static int libc_connect(int sockfd,
748 const struct sockaddr *addr,
751 swrap_bind_symbol_libsocket(connect);
753 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
756 static int libc_dup(int fd)
758 swrap_bind_symbol_libc(dup);
760 return swrap.libc.symbols._libc_dup.f(fd);
763 static int libc_dup2(int oldfd, int newfd)
765 swrap_bind_symbol_libc(dup2);
767 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
771 static int libc_eventfd(int count, int flags)
773 swrap_bind_symbol_libc(eventfd);
775 return swrap.libc.symbols._libc_eventfd.f(count, flags);
779 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
780 static int libc_vfcntl(int fd, int cmd, va_list ap)
786 swrap_bind_symbol_libc(fcntl);
788 for (i = 0; i < 4; i++) {
789 args[i] = va_arg(ap, long int);
792 rc = swrap.libc.symbols._libc_fcntl.f(fd,
802 static int libc_getpeername(int sockfd,
803 struct sockaddr *addr,
806 swrap_bind_symbol_libsocket(getpeername);
808 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
811 static int libc_getsockname(int sockfd,
812 struct sockaddr *addr,
815 swrap_bind_symbol_libsocket(getsockname);
817 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
820 static int libc_getsockopt(int sockfd,
826 swrap_bind_symbol_libsocket(getsockopt);
828 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
835 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
836 static int libc_vioctl(int d, unsigned long int request, va_list ap)
842 swrap_bind_symbol_libc(ioctl);
844 for (i = 0; i < 4; i++) {
845 args[i] = va_arg(ap, long int);
848 rc = swrap.libc.symbols._libc_ioctl.f(d,
858 static int libc_listen(int sockfd, int backlog)
860 swrap_bind_symbol_libsocket(listen);
862 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
865 static FILE *libc_fopen(const char *name, const char *mode)
867 swrap_bind_symbol_libc(fopen);
869 return swrap.libc.symbols._libc_fopen.f(name, mode);
873 static FILE *libc_fopen64(const char *name, const char *mode)
875 swrap_bind_symbol_libc(fopen64);
877 return swrap.libc.symbols._libc_fopen64.f(name, mode);
879 #endif /* HAVE_FOPEN64 */
881 static int libc_vopen(const char *pathname, int flags, va_list ap)
886 swrap_bind_symbol_libc(open);
888 mode = va_arg(ap, long int);
890 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
895 static int libc_open(const char *pathname, int flags, ...)
901 fd = libc_vopen(pathname, flags, ap);
908 static int libc_vopen64(const char *pathname, int flags, va_list ap)
913 swrap_bind_symbol_libc(open64);
915 mode = va_arg(ap, long int);
917 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
921 #endif /* HAVE_OPEN64 */
923 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
928 swrap_bind_symbol_libc(openat);
930 mode = va_arg(ap, long int);
932 fd = swrap.libc.symbols._libc_openat.f(dirfd, path, flags, (mode_t)mode);
938 static int libc_openat(int dirfd, const char *path, int flags, ...)
944 fd = libc_vopenat(dirfd, path, flags, ap);
951 static int libc_pipe(int pipefd[2])
953 swrap_bind_symbol_libsocket(pipe);
955 return swrap.libc.symbols._libc_pipe.f(pipefd);
958 static int libc_read(int fd, void *buf, size_t count)
960 swrap_bind_symbol_libc(read);
962 return swrap.libc.symbols._libc_read.f(fd, buf, count);
965 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
967 swrap_bind_symbol_libsocket(readv);
969 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
972 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
974 swrap_bind_symbol_libsocket(recv);
976 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
979 static int libc_recvfrom(int sockfd,
983 struct sockaddr *src_addr,
986 swrap_bind_symbol_libsocket(recvfrom);
988 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
996 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
998 swrap_bind_symbol_libsocket(recvmsg);
1000 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1003 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1005 swrap_bind_symbol_libsocket(send);
1007 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1010 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1012 swrap_bind_symbol_libsocket(sendmsg);
1014 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1017 static int libc_sendto(int sockfd,
1021 const struct sockaddr *dst_addr,
1024 swrap_bind_symbol_libsocket(sendto);
1026 return swrap.libc.symbols._libc_sendto.f(sockfd,
1034 static int libc_setsockopt(int sockfd,
1040 swrap_bind_symbol_libsocket(setsockopt);
1042 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1049 #ifdef HAVE_SIGNALFD
1050 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1052 swrap_bind_symbol_libsocket(signalfd);
1054 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1058 static int libc_socket(int domain, int type, int protocol)
1060 swrap_bind_symbol_libsocket(socket);
1062 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1065 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1067 swrap_bind_symbol_libsocket(socketpair);
1069 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1072 #ifdef HAVE_TIMERFD_CREATE
1073 static int libc_timerfd_create(int clockid, int flags)
1075 swrap_bind_symbol_libc(timerfd_create);
1077 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1081 static ssize_t libc_write(int fd, const void *buf, size_t count)
1083 swrap_bind_symbol_libc(write);
1085 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1088 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1090 swrap_bind_symbol_libsocket(writev);
1092 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1095 /*********************************************************
1096 * SWRAP HELPER FUNCTIONS
1097 *********************************************************/
1103 static const struct in6_addr *swrap_ipv6(void)
1105 static struct in6_addr v;
1106 static int initialized;
1114 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1123 static void set_port(int family, int prt, struct swrap_address *addr)
1127 addr->sa.in.sin_port = htons(prt);
1131 addr->sa.in6.sin6_port = htons(prt);
1137 static size_t socket_length(int family)
1141 return sizeof(struct sockaddr_in);
1144 return sizeof(struct sockaddr_in6);
1150 static const char *socket_wrapper_dir(void)
1152 const char *s = getenv("SOCKET_WRAPPER_DIR");
1156 /* TODO use realpath(3) here, when we add support for threads */
1157 if (strncmp(s, "./", 2) == 0) {
1161 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1165 static unsigned int socket_wrapper_mtu(void)
1167 static unsigned int max_mtu = 0;
1176 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1178 s = getenv("SOCKET_WRAPPER_MTU");
1183 tmp = strtol(s, &endp, 10);
1188 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1197 static size_t socket_wrapper_max_sockets(void)
1203 if (max_sockets != 0) {
1207 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1209 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1210 if (s == NULL || s[0] == '\0') {
1214 tmp = strtoul(s, &endp, 10);
1218 if (tmp == 0 || tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1219 SWRAP_LOG(SWRAP_LOG_ERROR,
1220 "Invalid number of sockets specified, using default.");
1230 static void socket_wrapper_init_sockets(void)
1234 if (sockets != NULL) {
1238 max_sockets = socket_wrapper_max_sockets();
1240 sockets = (struct socket_info *)calloc(max_sockets,
1241 sizeof(struct socket_info));
1243 if (sockets == NULL) {
1244 SWRAP_LOG(SWRAP_LOG_ERROR,
1245 "Failed to allocate sockets array.\n");
1251 for (i = 0; i < max_sockets; i++) {
1252 sockets[i].next_free = i+1;
1255 sockets[max_sockets-1].next_free = -1;
1258 bool socket_wrapper_enabled(void)
1260 const char *s = socket_wrapper_dir();
1266 socket_wrapper_init_sockets();
1271 static unsigned int socket_wrapper_default_iface(void)
1273 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1276 if (sscanf(s, "%u", &iface) == 1) {
1277 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1283 return 1;/* 127.0.0.1 */
1287 * Return the first free entry (if any) and make
1288 * it re-usable again (by nulling it out)
1290 static int socket_wrapper_first_free_index(void)
1294 if (first_free == -1) {
1298 next_free = sockets[first_free].next_free;
1299 ZERO_STRUCT(sockets[first_free]);
1300 sockets[first_free].next_free = next_free;
1305 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1312 p = strrchr(un->sun_path, '/');
1313 if (p) p++; else p = un->sun_path;
1315 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1320 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1323 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1334 case SOCKET_TYPE_CHAR_TCP:
1335 case SOCKET_TYPE_CHAR_UDP: {
1336 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1338 if ((*len) < sizeof(*in2)) {
1343 memset(in2, 0, sizeof(*in2));
1344 in2->sin_family = AF_INET;
1345 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1346 in2->sin_port = htons(prt);
1348 *len = sizeof(*in2);
1352 case SOCKET_TYPE_CHAR_TCP_V6:
1353 case SOCKET_TYPE_CHAR_UDP_V6: {
1354 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1356 if ((*len) < sizeof(*in2)) {
1361 memset(in2, 0, sizeof(*in2));
1362 in2->sin6_family = AF_INET6;
1363 in2->sin6_addr = *swrap_ipv6();
1364 in2->sin6_addr.s6_addr[15] = iface;
1365 in2->sin6_port = htons(prt);
1367 *len = sizeof(*in2);
1379 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1387 if (bcast) *bcast = 0;
1389 switch (inaddr->sa_family) {
1391 const struct sockaddr_in *in =
1392 (const struct sockaddr_in *)(const void *)inaddr;
1393 unsigned int addr = ntohl(in->sin_addr.s_addr);
1400 u_type = SOCKET_TYPE_CHAR_TCP;
1403 u_type = SOCKET_TYPE_CHAR_UDP;
1404 a_type = SOCKET_TYPE_CHAR_UDP;
1405 b_type = SOCKET_TYPE_CHAR_UDP;
1408 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1409 errno = ESOCKTNOSUPPORT;
1413 prt = ntohs(in->sin_port);
1414 if (a_type && addr == 0xFFFFFFFF) {
1415 /* 255.255.255.255 only udp */
1418 iface = socket_wrapper_default_iface();
1419 } else if (b_type && addr == 0x7FFFFFFF) {
1420 /* 127.255.255.255 only udp */
1423 iface = socket_wrapper_default_iface();
1424 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1428 iface = (addr & 0x000000FF);
1430 errno = ENETUNREACH;
1433 if (bcast) *bcast = is_bcast;
1438 const struct sockaddr_in6 *in =
1439 (const struct sockaddr_in6 *)(const void *)inaddr;
1440 struct in6_addr cmp1, cmp2;
1444 type = SOCKET_TYPE_CHAR_TCP_V6;
1447 type = SOCKET_TYPE_CHAR_UDP_V6;
1450 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1451 errno = ESOCKTNOSUPPORT;
1455 /* XXX no multicast/broadcast */
1457 prt = ntohs(in->sin6_port);
1459 cmp1 = *swrap_ipv6();
1460 cmp2 = in->sin6_addr;
1461 cmp2.s6_addr[15] = 0;
1462 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1463 iface = in->sin6_addr.s6_addr[15];
1465 errno = ENETUNREACH;
1473 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1474 errno = ENETUNREACH;
1479 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1485 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1486 socket_wrapper_dir());
1487 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1488 /* the caller need to do more processing */
1492 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1493 socket_wrapper_dir(), type, iface, prt);
1494 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1499 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1508 if (bcast) *bcast = 0;
1510 switch (si->family) {
1512 const struct sockaddr_in *in =
1513 (const struct sockaddr_in *)(const void *)inaddr;
1514 unsigned int addr = ntohl(in->sin_addr.s_addr);
1520 prt = ntohs(in->sin_port);
1524 u_type = SOCKET_TYPE_CHAR_TCP;
1525 d_type = SOCKET_TYPE_CHAR_TCP;
1528 u_type = SOCKET_TYPE_CHAR_UDP;
1529 d_type = SOCKET_TYPE_CHAR_UDP;
1530 a_type = SOCKET_TYPE_CHAR_UDP;
1531 b_type = SOCKET_TYPE_CHAR_UDP;
1534 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1535 errno = ESOCKTNOSUPPORT;
1543 iface = socket_wrapper_default_iface();
1544 } else if (a_type && addr == 0xFFFFFFFF) {
1545 /* 255.255.255.255 only udp */
1548 iface = socket_wrapper_default_iface();
1549 } else if (b_type && addr == 0x7FFFFFFF) {
1550 /* 127.255.255.255 only udp */
1553 iface = socket_wrapper_default_iface();
1554 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1558 iface = (addr & 0x000000FF);
1560 errno = EADDRNOTAVAIL;
1564 /* Store the bind address for connect() */
1565 if (si->bindname.sa_socklen == 0) {
1566 struct sockaddr_in bind_in;
1567 socklen_t blen = sizeof(struct sockaddr_in);
1569 ZERO_STRUCT(bind_in);
1570 bind_in.sin_family = in->sin_family;
1571 bind_in.sin_port = in->sin_port;
1572 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1574 si->bindname.sa_socklen = blen;
1575 memcpy(&si->bindname.sa.in, &bind_in, blen);
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_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1607 iface = socket_wrapper_default_iface();
1608 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1609 iface = in->sin6_addr.s6_addr[15];
1611 errno = EADDRNOTAVAIL;
1615 /* Store the bind address for connect() */
1616 if (si->bindname.sa_socklen == 0) {
1617 struct sockaddr_in6 bind_in;
1618 socklen_t blen = sizeof(struct sockaddr_in6);
1620 ZERO_STRUCT(bind_in);
1621 bind_in.sin6_family = in->sin6_family;
1622 bind_in.sin6_port = in->sin6_port;
1624 bind_in.sin6_addr = *swrap_ipv6();
1625 bind_in.sin6_addr.s6_addr[15] = iface;
1627 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1628 si->bindname.sa_socklen = blen;
1635 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1636 errno = EADDRNOTAVAIL;
1641 if (bcast) *bcast = is_bcast;
1643 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1649 /* handle auto-allocation of ephemeral ports */
1650 for (prt = 5001; prt < 10000; prt++) {
1651 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1652 socket_wrapper_dir(), type, iface, prt);
1653 if (stat(un->sun_path, &st) == 0) continue;
1655 set_port(si->family, prt, &si->myname);
1656 set_port(si->family, prt, &si->bindname);
1666 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1667 socket_wrapper_dir(), type, iface, prt);
1668 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1672 static struct socket_info_fd *find_socket_info_fd(int fd)
1674 struct socket_info_fd *f;
1676 for (f = socket_fds; f; f = f->next) {
1685 static int find_socket_info_index(int fd)
1687 struct socket_info_fd *fi = find_socket_info_fd(fd);
1693 return fi->si_index;
1696 static struct socket_info *find_socket_info(int fd)
1698 int idx = find_socket_info_index(fd);
1704 return &sockets[idx];
1708 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1710 struct socket_info_fd *f;
1711 const struct socket_info *last_s = NULL;
1713 /* first catch invalid input */
1714 switch (sa->sa_family) {
1716 if (len < sizeof(struct sockaddr_in)) {
1722 if (len < sizeof(struct sockaddr_in6)) {
1732 for (f = socket_fds; f; f = f->next) {
1733 struct socket_info *s = &sockets[f->si_index];
1740 if (s->myname == NULL) {
1743 if (s->myname->sa_family != sa->sa_family) {
1746 switch (s->myname->sa_family) {
1748 struct sockaddr_in *sin1, *sin2;
1750 sin1 = (struct sockaddr_in *)s->myname;
1751 sin2 = (struct sockaddr_in *)sa;
1753 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1756 if (sin1->sin_port != sin2->sin_port) {
1759 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1769 struct sockaddr_in6 *sin1, *sin2;
1771 sin1 = (struct sockaddr_in6 *)s->myname;
1772 sin2 = (struct sockaddr_in6 *)sa;
1774 if (sin1->sin6_port != sin2->sin6_port) {
1777 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1799 static void swrap_remove_stale(int fd)
1801 struct socket_info_fd *fi = find_socket_info_fd(fd);
1802 struct socket_info *si;
1809 si_index = fi->si_index;
1811 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1812 SWRAP_DLIST_REMOVE(socket_fds, fi);
1815 si = &sockets[si_index];
1818 if (si->refcount > 0) {
1822 if (si->un_addr.sun_path[0] != '\0') {
1823 unlink(si->un_addr.sun_path);
1826 si->next_free = first_free;
1827 first_free = si_index;
1830 static int sockaddr_convert_to_un(struct socket_info *si,
1831 const struct sockaddr *in_addr,
1833 struct sockaddr_un *out_addr,
1837 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1839 (void) in_len; /* unused */
1841 if (out_addr == NULL) {
1845 out->sa_family = AF_UNIX;
1846 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1847 out->sa_len = sizeof(*out_addr);
1850 switch (in_addr->sa_family) {
1852 const struct sockaddr_in *sin;
1853 if (si->family != AF_INET) {
1856 if (in_len < sizeof(struct sockaddr_in)) {
1859 sin = (const struct sockaddr_in *)(const void *)in_addr;
1860 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1865 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1866 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1880 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1881 errno = ESOCKTNOSUPPORT;
1885 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1887 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1893 errno = EAFNOSUPPORT;
1894 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1898 static int sockaddr_convert_from_un(const struct socket_info *si,
1899 const struct sockaddr_un *in_addr,
1900 socklen_t un_addrlen,
1902 struct sockaddr *out_addr,
1903 socklen_t *out_addrlen)
1907 if (out_addr == NULL || out_addrlen == NULL)
1910 if (un_addrlen == 0) {
1925 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1926 errno = ESOCKTNOSUPPORT;
1929 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1930 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1931 out_addr->sa_len = *out_addrlen;
1938 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1939 errno = EAFNOSUPPORT;
1943 enum swrap_packet_type {
1945 SWRAP_CONNECT_UNREACH,
1953 SWRAP_SENDTO_UNREACH,
1964 struct swrap_file_hdr {
1966 uint16_t version_major;
1967 uint16_t version_minor;
1970 uint32_t frame_max_len;
1971 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1974 #define SWRAP_FILE_HDR_SIZE 24
1976 struct swrap_packet_frame {
1978 uint32_t micro_seconds;
1979 uint32_t recorded_length;
1980 uint32_t full_length;
1982 #define SWRAP_PACKET_FRAME_SIZE 16
1984 union swrap_packet_ip {
1988 uint16_t packet_length;
1989 uint16_t identification;
1994 uint16_t hdr_checksum;
1998 #define SWRAP_PACKET_IP_V4_SIZE 20
2001 uint8_t flow_label_high;
2002 uint16_t flow_label_low;
2003 uint16_t payload_length;
2004 uint8_t next_header;
2006 uint8_t src_addr[16];
2007 uint8_t dest_addr[16];
2009 #define SWRAP_PACKET_IP_V6_SIZE 40
2011 #define SWRAP_PACKET_IP_SIZE 40
2013 union swrap_packet_payload {
2015 uint16_t source_port;
2025 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2027 uint16_t source_port;
2032 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2039 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2046 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2048 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2050 #define SWRAP_PACKET_MIN_ALLOC \
2051 (SWRAP_PACKET_FRAME_SIZE + \
2052 SWRAP_PACKET_IP_SIZE + \
2053 SWRAP_PACKET_PAYLOAD_SIZE)
2055 static const char *swrap_pcap_init_file(void)
2057 static int initialized = 0;
2058 static const char *s = NULL;
2059 static const struct swrap_file_hdr h;
2060 static const struct swrap_packet_frame f;
2061 static const union swrap_packet_ip i;
2062 static const union swrap_packet_payload p;
2064 if (initialized == 1) {
2070 * TODO: don't use the structs use plain buffer offsets
2071 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2073 * for now make sure we disable PCAP support
2074 * if the struct has alignment!
2076 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2079 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2082 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2085 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2088 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2091 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2094 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2097 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2100 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2103 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2107 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2111 if (strncmp(s, "./", 2) == 0) {
2117 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2118 const struct sockaddr *src,
2119 const struct sockaddr *dest,
2121 const uint8_t *payload,
2123 unsigned long tcp_seqno,
2124 unsigned long tcp_ack,
2125 unsigned char tcp_ctl,
2127 size_t *_packet_len)
2131 struct swrap_packet_frame *frame;
2132 union swrap_packet_ip *ip;
2133 union swrap_packet_payload *pay;
2136 size_t nonwire_len = sizeof(*frame);
2137 size_t wire_hdr_len = 0;
2138 size_t wire_len = 0;
2139 size_t ip_hdr_len = 0;
2140 size_t icmp_hdr_len = 0;
2141 size_t icmp_truncate_len = 0;
2142 uint8_t protocol = 0, icmp_protocol = 0;
2143 const struct sockaddr_in *src_in = NULL;
2144 const struct sockaddr_in *dest_in = NULL;
2146 const struct sockaddr_in6 *src_in6 = NULL;
2147 const struct sockaddr_in6 *dest_in6 = NULL;
2152 switch (src->sa_family) {
2154 src_in = (const struct sockaddr_in *)(const void *)src;
2155 dest_in = (const struct sockaddr_in *)(const void *)dest;
2156 src_port = src_in->sin_port;
2157 dest_port = dest_in->sin_port;
2158 ip_hdr_len = sizeof(ip->v4);
2162 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2163 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2164 src_port = src_in6->sin6_port;
2165 dest_port = dest_in6->sin6_port;
2166 ip_hdr_len = sizeof(ip->v6);
2173 switch (socket_type) {
2175 protocol = 0x06; /* TCP */
2176 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2177 wire_len = wire_hdr_len + payload_len;
2181 protocol = 0x11; /* UDP */
2182 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2183 wire_len = wire_hdr_len + payload_len;
2191 icmp_protocol = protocol;
2192 switch (src->sa_family) {
2194 protocol = 0x01; /* ICMPv4 */
2195 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2199 protocol = 0x3A; /* ICMPv6 */
2200 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2204 if (wire_len > 64 ) {
2205 icmp_truncate_len = wire_len - 64;
2207 wire_hdr_len += icmp_hdr_len;
2208 wire_len += icmp_hdr_len;
2211 packet_len = nonwire_len + wire_len;
2212 alloc_len = packet_len;
2213 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2214 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2217 base = (uint8_t *)calloc(1, alloc_len);
2224 frame = (struct swrap_packet_frame *)(void *)buf;
2225 frame->seconds = tval->tv_sec;
2226 frame->micro_seconds = tval->tv_usec;
2227 frame->recorded_length = wire_len - icmp_truncate_len;
2228 frame->full_length = wire_len - icmp_truncate_len;
2229 buf += SWRAP_PACKET_FRAME_SIZE;
2231 ip = (union swrap_packet_ip *)(void *)buf;
2232 switch (src->sa_family) {
2234 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2236 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2237 ip->v4.identification = htons(0xFFFF);
2238 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2239 ip->v4.fragment = htons(0x0000);
2241 ip->v4.protocol = protocol;
2242 ip->v4.hdr_checksum = htons(0x0000);
2243 ip->v4.src_addr = src_in->sin_addr.s_addr;
2244 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2245 buf += SWRAP_PACKET_IP_V4_SIZE;
2249 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2250 ip->v6.flow_label_high = 0x00;
2251 ip->v6.flow_label_low = 0x0000;
2252 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2253 ip->v6.next_header = protocol;
2254 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2255 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2256 buf += SWRAP_PACKET_IP_V6_SIZE;
2262 pay = (union swrap_packet_payload *)(void *)buf;
2263 switch (src->sa_family) {
2265 pay->icmp4.type = 0x03; /* destination unreachable */
2266 pay->icmp4.code = 0x01; /* host unreachable */
2267 pay->icmp4.checksum = htons(0x0000);
2268 pay->icmp4.unused = htonl(0x00000000);
2269 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2271 /* set the ip header in the ICMP payload */
2272 ip = (union swrap_packet_ip *)(void *)buf;
2273 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2275 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2276 ip->v4.identification = htons(0xFFFF);
2277 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2278 ip->v4.fragment = htons(0x0000);
2280 ip->v4.protocol = icmp_protocol;
2281 ip->v4.hdr_checksum = htons(0x0000);
2282 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2283 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2284 buf += SWRAP_PACKET_IP_V4_SIZE;
2286 src_port = dest_in->sin_port;
2287 dest_port = src_in->sin_port;
2291 pay->icmp6.type = 0x01; /* destination unreachable */
2292 pay->icmp6.code = 0x03; /* address unreachable */
2293 pay->icmp6.checksum = htons(0x0000);
2294 pay->icmp6.unused = htonl(0x00000000);
2295 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2297 /* set the ip header in the ICMP payload */
2298 ip = (union swrap_packet_ip *)(void *)buf;
2299 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2300 ip->v6.flow_label_high = 0x00;
2301 ip->v6.flow_label_low = 0x0000;
2302 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2303 ip->v6.next_header = protocol;
2304 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2305 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2306 buf += SWRAP_PACKET_IP_V6_SIZE;
2308 src_port = dest_in6->sin6_port;
2309 dest_port = src_in6->sin6_port;
2315 pay = (union swrap_packet_payload *)(void *)buf;
2317 switch (socket_type) {
2319 pay->tcp.source_port = src_port;
2320 pay->tcp.dest_port = dest_port;
2321 pay->tcp.seq_num = htonl(tcp_seqno);
2322 pay->tcp.ack_num = htonl(tcp_ack);
2323 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2324 pay->tcp.control = tcp_ctl;
2325 pay->tcp.window = htons(0x7FFF);
2326 pay->tcp.checksum = htons(0x0000);
2327 pay->tcp.urg = htons(0x0000);
2328 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2333 pay->udp.source_port = src_port;
2334 pay->udp.dest_port = dest_port;
2335 pay->udp.length = htons(8 + payload_len);
2336 pay->udp.checksum = htons(0x0000);
2337 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2342 if (payload && payload_len > 0) {
2343 memcpy(buf, payload, payload_len);
2346 *_packet_len = packet_len - icmp_truncate_len;
2350 static int swrap_pcap_get_fd(const char *fname)
2358 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2360 struct swrap_file_hdr file_hdr;
2361 file_hdr.magic = 0xA1B2C3D4;
2362 file_hdr.version_major = 0x0002;
2363 file_hdr.version_minor = 0x0004;
2364 file_hdr.timezone = 0x00000000;
2365 file_hdr.sigfigs = 0x00000000;
2366 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2367 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2369 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2376 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2381 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2382 const struct sockaddr *addr,
2383 enum swrap_packet_type type,
2384 const void *buf, size_t len,
2387 const struct sockaddr *src_addr;
2388 const struct sockaddr *dest_addr;
2389 unsigned long tcp_seqno = 0;
2390 unsigned long tcp_ack = 0;
2391 unsigned char tcp_ctl = 0;
2392 int unreachable = 0;
2396 switch (si->family) {
2408 case SWRAP_CONNECT_SEND:
2409 if (si->type != SOCK_STREAM) {
2413 src_addr = &si->myname.sa.s;
2416 tcp_seqno = si->io.pck_snd;
2417 tcp_ack = si->io.pck_rcv;
2418 tcp_ctl = 0x02; /* SYN */
2420 si->io.pck_snd += 1;
2424 case SWRAP_CONNECT_RECV:
2425 if (si->type != SOCK_STREAM) {
2429 dest_addr = &si->myname.sa.s;
2432 tcp_seqno = si->io.pck_rcv;
2433 tcp_ack = si->io.pck_snd;
2434 tcp_ctl = 0x12; /** SYN,ACK */
2436 si->io.pck_rcv += 1;
2440 case SWRAP_CONNECT_UNREACH:
2441 if (si->type != SOCK_STREAM) {
2445 dest_addr = &si->myname.sa.s;
2448 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2449 tcp_seqno = si->io.pck_snd - 1;
2450 tcp_ack = si->io.pck_rcv;
2451 tcp_ctl = 0x02; /* SYN */
2456 case SWRAP_CONNECT_ACK:
2457 if (si->type != SOCK_STREAM) {
2461 src_addr = &si->myname.sa.s;
2464 tcp_seqno = si->io.pck_snd;
2465 tcp_ack = si->io.pck_rcv;
2466 tcp_ctl = 0x10; /* ACK */
2470 case SWRAP_ACCEPT_SEND:
2471 if (si->type != SOCK_STREAM) {
2475 dest_addr = &si->myname.sa.s;
2478 tcp_seqno = si->io.pck_rcv;
2479 tcp_ack = si->io.pck_snd;
2480 tcp_ctl = 0x02; /* SYN */
2482 si->io.pck_rcv += 1;
2486 case SWRAP_ACCEPT_RECV:
2487 if (si->type != SOCK_STREAM) {
2491 src_addr = &si->myname.sa.s;
2494 tcp_seqno = si->io.pck_snd;
2495 tcp_ack = si->io.pck_rcv;
2496 tcp_ctl = 0x12; /* SYN,ACK */
2498 si->io.pck_snd += 1;
2502 case SWRAP_ACCEPT_ACK:
2503 if (si->type != SOCK_STREAM) {
2507 dest_addr = &si->myname.sa.s;
2510 tcp_seqno = si->io.pck_rcv;
2511 tcp_ack = si->io.pck_snd;
2512 tcp_ctl = 0x10; /* ACK */
2517 src_addr = &si->myname.sa.s;
2518 dest_addr = &si->peername.sa.s;
2520 tcp_seqno = si->io.pck_snd;
2521 tcp_ack = si->io.pck_rcv;
2522 tcp_ctl = 0x18; /* PSH,ACK */
2524 si->io.pck_snd += len;
2528 case SWRAP_SEND_RST:
2529 dest_addr = &si->myname.sa.s;
2530 src_addr = &si->peername.sa.s;
2532 if (si->type == SOCK_DGRAM) {
2533 return swrap_pcap_marshall_packet(si,
2535 SWRAP_SENDTO_UNREACH,
2541 tcp_seqno = si->io.pck_rcv;
2542 tcp_ack = si->io.pck_snd;
2543 tcp_ctl = 0x14; /** RST,ACK */
2547 case SWRAP_PENDING_RST:
2548 dest_addr = &si->myname.sa.s;
2549 src_addr = &si->peername.sa.s;
2551 if (si->type == SOCK_DGRAM) {
2555 tcp_seqno = si->io.pck_rcv;
2556 tcp_ack = si->io.pck_snd;
2557 tcp_ctl = 0x14; /* RST,ACK */
2562 dest_addr = &si->myname.sa.s;
2563 src_addr = &si->peername.sa.s;
2565 tcp_seqno = si->io.pck_rcv;
2566 tcp_ack = si->io.pck_snd;
2567 tcp_ctl = 0x18; /* PSH,ACK */
2569 si->io.pck_rcv += len;
2573 case SWRAP_RECV_RST:
2574 dest_addr = &si->myname.sa.s;
2575 src_addr = &si->peername.sa.s;
2577 if (si->type == SOCK_DGRAM) {
2581 tcp_seqno = si->io.pck_rcv;
2582 tcp_ack = si->io.pck_snd;
2583 tcp_ctl = 0x14; /* RST,ACK */
2588 src_addr = &si->myname.sa.s;
2591 si->io.pck_snd += len;
2595 case SWRAP_SENDTO_UNREACH:
2596 dest_addr = &si->myname.sa.s;
2603 case SWRAP_RECVFROM:
2604 dest_addr = &si->myname.sa.s;
2607 si->io.pck_rcv += len;
2611 case SWRAP_CLOSE_SEND:
2612 if (si->type != SOCK_STREAM) {
2616 src_addr = &si->myname.sa.s;
2617 dest_addr = &si->peername.sa.s;
2619 tcp_seqno = si->io.pck_snd;
2620 tcp_ack = si->io.pck_rcv;
2621 tcp_ctl = 0x11; /* FIN, ACK */
2623 si->io.pck_snd += 1;
2627 case SWRAP_CLOSE_RECV:
2628 if (si->type != SOCK_STREAM) {
2632 dest_addr = &si->myname.sa.s;
2633 src_addr = &si->peername.sa.s;
2635 tcp_seqno = si->io.pck_rcv;
2636 tcp_ack = si->io.pck_snd;
2637 tcp_ctl = 0x11; /* FIN,ACK */
2639 si->io.pck_rcv += 1;
2643 case SWRAP_CLOSE_ACK:
2644 if (si->type != SOCK_STREAM) {
2648 src_addr = &si->myname.sa.s;
2649 dest_addr = &si->peername.sa.s;
2651 tcp_seqno = si->io.pck_snd;
2652 tcp_ack = si->io.pck_rcv;
2653 tcp_ctl = 0x10; /* ACK */
2660 swrapGetTimeOfDay(&tv);
2662 return swrap_pcap_packet_init(&tv,
2666 (const uint8_t *)buf,
2675 static void swrap_pcap_dump_packet(struct socket_info *si,
2676 const struct sockaddr *addr,
2677 enum swrap_packet_type type,
2678 const void *buf, size_t len)
2680 const char *file_name;
2682 size_t packet_len = 0;
2685 file_name = swrap_pcap_init_file();
2690 packet = swrap_pcap_marshall_packet(si,
2696 if (packet == NULL) {
2700 fd = swrap_pcap_get_fd(file_name);
2702 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2711 /****************************************************************************
2713 ***************************************************************************/
2715 #ifdef HAVE_SIGNALFD
2716 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2720 rc = libc_signalfd(fd, mask, flags);
2722 swrap_remove_stale(fd);
2728 int signalfd(int fd, const sigset_t *mask, int flags)
2730 return swrap_signalfd(fd, mask, flags);
2734 /****************************************************************************
2736 ***************************************************************************/
2738 static int swrap_socket(int family, int type, int protocol)
2740 struct socket_info *si;
2741 struct socket_info_fd *fi;
2744 int real_type = type;
2747 * Remove possible addition flags passed to socket() so
2748 * do not fail checking the type.
2749 * See https://lwn.net/Articles/281965/
2752 real_type &= ~SOCK_CLOEXEC;
2754 #ifdef SOCK_NONBLOCK
2755 real_type &= ~SOCK_NONBLOCK;
2758 if (!socket_wrapper_enabled()) {
2759 return libc_socket(family, type, protocol);
2770 #endif /* AF_NETLINK */
2773 #endif /* AF_PACKET */
2775 return libc_socket(family, type, protocol);
2777 errno = EAFNOSUPPORT;
2781 switch (real_type) {
2787 errno = EPROTONOSUPPORT;
2795 if (real_type == SOCK_STREAM) {
2800 if (real_type == SOCK_DGRAM) {
2805 errno = EPROTONOSUPPORT;
2810 * We must call libc_socket with type, from the caller, not the version
2811 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2813 fd = libc_socket(AF_UNIX, type, 0);
2819 /* Check if we have a stale fd and remove it */
2820 swrap_remove_stale(fd);
2822 idx = socket_wrapper_first_free_index();
2830 si->family = family;
2832 /* however, the rest of the socket_wrapper code expects just
2833 * the type, not the flags */
2834 si->type = real_type;
2835 si->protocol = protocol;
2838 * Setup myname so getsockname() can succeed to find out the socket
2841 switch(si->family) {
2843 struct sockaddr_in sin = {
2844 .sin_family = AF_INET,
2847 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2848 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2852 struct sockaddr_in6 sin6 = {
2853 .sin6_family = AF_INET6,
2856 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2857 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2865 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2872 first_free = si->next_free;
2878 SWRAP_DLIST_ADD(socket_fds, fi);
2880 SWRAP_LOG(SWRAP_LOG_TRACE,
2881 "Created %s socket for protocol %s",
2882 si->family == AF_INET ? "IPv4" : "IPv6",
2883 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2888 int socket(int family, int type, int protocol)
2890 return swrap_socket(family, type, protocol);
2893 /****************************************************************************
2895 ***************************************************************************/
2897 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2901 rc = libc_socketpair(family, type, protocol, sv);
2903 swrap_remove_stale(sv[0]);
2904 swrap_remove_stale(sv[1]);
2910 int socketpair(int family, int type, int protocol, int sv[2])
2912 return swrap_socketpair(family, type, protocol, sv);
2915 /****************************************************************************
2917 ***************************************************************************/
2919 #ifdef HAVE_TIMERFD_CREATE
2920 static int swrap_timerfd_create(int clockid, int flags)
2924 fd = libc_timerfd_create(clockid, flags);
2926 swrap_remove_stale(fd);
2932 int timerfd_create(int clockid, int flags)
2934 return swrap_timerfd_create(clockid, flags);
2938 /****************************************************************************
2940 ***************************************************************************/
2942 static int swrap_pipe(int pipefd[2])
2946 rc = libc_pipe(pipefd);
2948 swrap_remove_stale(pipefd[0]);
2949 swrap_remove_stale(pipefd[1]);
2955 int pipe(int pipefd[2])
2957 return swrap_pipe(pipefd);
2960 /****************************************************************************
2962 ***************************************************************************/
2964 static int swrap_accept(int s,
2965 struct sockaddr *addr,
2969 struct socket_info *parent_si, *child_si;
2970 struct socket_info_fd *child_fi;
2973 struct swrap_address un_addr = {
2974 .sa_socklen = sizeof(struct sockaddr_un),
2976 struct swrap_address un_my_addr = {
2977 .sa_socklen = sizeof(struct sockaddr_un),
2979 struct swrap_address in_addr = {
2980 .sa_socklen = sizeof(struct sockaddr_storage),
2982 struct swrap_address in_my_addr = {
2983 .sa_socklen = sizeof(struct sockaddr_storage),
2987 parent_si = find_socket_info(s);
2990 return libc_accept4(s, addr, addrlen, flags);
2993 return libc_accept(s, addr, addrlen);
2998 * assume out sockaddr have the same size as the in parent
3001 in_addr.sa_socklen = socket_length(parent_si->family);
3002 if (in_addr.sa_socklen <= 0) {
3008 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3011 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3014 if (errno == ENOTSOCK) {
3015 /* Remove stale fds */
3016 swrap_remove_stale(s);
3023 ret = sockaddr_convert_from_un(parent_si,
3028 &in_addr.sa_socklen);
3034 idx = socket_wrapper_first_free_index();
3040 child_si = &sockets[idx];
3042 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
3043 if (child_fi == NULL) {
3051 child_si->family = parent_si->family;
3052 child_si->type = parent_si->type;
3053 child_si->protocol = parent_si->protocol;
3054 child_si->bound = 1;
3055 child_si->is_server = 1;
3056 child_si->connected = 1;
3058 child_si->peername = (struct swrap_address) {
3059 .sa_socklen = in_addr.sa_socklen,
3061 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3063 if (addr != NULL && addrlen != NULL) {
3064 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3066 memcpy(addr, &in_addr.sa.ss, copy_len);
3068 *addrlen = in_addr.sa_socklen;
3071 ret = libc_getsockname(fd,
3073 &un_my_addr.sa_socklen);
3080 ret = sockaddr_convert_from_un(child_si,
3082 un_my_addr.sa_socklen,
3085 &in_my_addr.sa_socklen);
3092 SWRAP_LOG(SWRAP_LOG_TRACE,
3093 "accept() path=%s, fd=%d",
3094 un_my_addr.sa.un.sun_path, s);
3096 child_si->myname = (struct swrap_address) {
3097 .sa_socklen = in_my_addr.sa_socklen,
3099 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3101 child_si->refcount = 1;
3102 first_free = child_si->next_free;
3103 child_si->next_free = 0;
3105 child_fi->si_index = idx;
3107 SWRAP_DLIST_ADD(socket_fds, child_fi);
3110 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3111 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3112 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3119 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3121 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3125 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3126 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3128 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3131 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3134 static int autobind_start_init;
3135 static int autobind_start;
3137 /* using sendto() or connect() on an unbound socket would give the
3138 recipient no way to reply, as unlike UDP and TCP, a unix domain
3139 socket can't auto-assign ephemeral port numbers, so we need to
3141 Note: this might change the family from ipv6 to ipv4
3143 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3145 struct swrap_address un_addr = {
3146 .sa_socklen = sizeof(struct sockaddr_un),
3154 if (autobind_start_init != 1) {
3155 autobind_start_init = 1;
3156 autobind_start = getpid();
3157 autobind_start %= 50000;
3158 autobind_start += 10000;
3161 un_addr.sa.un.sun_family = AF_UNIX;
3165 struct sockaddr_in in;
3169 type = SOCKET_TYPE_CHAR_TCP;
3172 type = SOCKET_TYPE_CHAR_UDP;
3175 errno = ESOCKTNOSUPPORT;
3180 memset(&in, 0, sizeof(in));
3181 in.sin_family = AF_INET;
3182 in.sin_addr.s_addr = htonl(127<<24 |
3183 socket_wrapper_default_iface());
3185 si->myname = (struct swrap_address) {
3186 .sa_socklen = sizeof(in),
3188 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3193 struct sockaddr_in6 in6;
3195 if (si->family != family) {
3196 errno = ENETUNREACH;
3203 type = SOCKET_TYPE_CHAR_TCP_V6;
3206 type = SOCKET_TYPE_CHAR_UDP_V6;
3209 errno = ESOCKTNOSUPPORT;
3214 memset(&in6, 0, sizeof(in6));
3215 in6.sin6_family = AF_INET6;
3216 in6.sin6_addr = *swrap_ipv6();
3217 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3219 si->myname = (struct swrap_address) {
3220 .sa_socklen = sizeof(in6),
3222 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3227 errno = ESOCKTNOSUPPORT;
3232 if (autobind_start > 60000) {
3233 autobind_start = 10000;
3236 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3237 port = autobind_start + i;
3238 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3239 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3240 type, socket_wrapper_default_iface(), port);
3241 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3243 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3248 si->un_addr = un_addr.sa.un;
3251 autobind_start = port + 1;
3254 if (i == SOCKET_MAX_SOCKETS) {
3255 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3256 "interface "SOCKET_FORMAT,
3259 socket_wrapper_default_iface(),
3266 si->family = family;
3267 set_port(si->family, port, &si->myname);
3275 /****************************************************************************
3277 ***************************************************************************/
3279 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3283 struct swrap_address un_addr = {
3284 .sa_socklen = sizeof(struct sockaddr_un),
3286 struct socket_info *si = find_socket_info(s);
3290 return libc_connect(s, serv_addr, addrlen);
3293 if (si->bound == 0) {
3294 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3300 if (si->family != serv_addr->sa_family) {
3306 ret = sockaddr_convert_to_un(si, serv_addr,
3307 addrlen, &un_addr.sa.un, 0, &bcast);
3313 errno = ENETUNREACH;
3318 if (si->type == SOCK_DGRAM) {
3319 si->defer_connect = 1;
3322 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3324 ret = libc_connect(s,
3326 un_addr.sa_socklen);
3329 SWRAP_LOG(SWRAP_LOG_TRACE,
3330 "connect() path=%s, fd=%d",
3331 un_addr.sa.un.sun_path, s);
3334 /* to give better errors */
3335 if (ret == -1 && errno == ENOENT) {
3336 errno = EHOSTUNREACH;
3340 si->peername = (struct swrap_address) {
3341 .sa_socklen = addrlen,
3344 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3348 * When we connect() on a socket than we have to bind the
3349 * outgoing connection on the interface we use for the
3350 * transport. We already bound it on the right interface
3351 * but here we have to update the name so getsockname()
3352 * returns correct information.
3354 if (si->bindname.sa_socklen > 0) {
3355 si->myname = (struct swrap_address) {
3356 .sa_socklen = si->bindname.sa_socklen,
3359 memcpy(&si->myname.sa.ss,
3360 &si->bindname.sa.ss,
3361 si->bindname.sa_socklen);
3363 /* Cleanup bindname */
3364 si->bindname = (struct swrap_address) {
3369 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3370 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3372 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3379 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3381 return swrap_connect(s, serv_addr, addrlen);
3384 /****************************************************************************
3386 ***************************************************************************/
3388 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3391 struct swrap_address un_addr = {
3392 .sa_socklen = sizeof(struct sockaddr_un),
3394 struct socket_info *si = find_socket_info(s);
3401 return libc_bind(s, myaddr, addrlen);
3404 switch (si->family) {
3406 const struct sockaddr_in *sin;
3407 if (addrlen < sizeof(struct sockaddr_in)) {
3408 bind_error = EINVAL;
3412 sin = (const struct sockaddr_in *)(const void *)myaddr;
3414 if (sin->sin_family != AF_INET) {
3415 bind_error = EAFNOSUPPORT;
3418 /* special case for AF_UNSPEC */
3419 if (sin->sin_family == AF_UNSPEC &&
3420 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3429 const struct sockaddr_in6 *sin6;
3430 if (addrlen < sizeof(struct sockaddr_in6)) {
3431 bind_error = EINVAL;
3435 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3437 if (sin6->sin6_family != AF_INET6) {
3438 bind_error = EAFNOSUPPORT;
3445 bind_error = EINVAL;
3449 if (bind_error != 0) {
3455 in_use = check_addr_port_in_use(myaddr, addrlen);
3462 si->myname.sa_socklen = addrlen;
3463 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3465 ret = sockaddr_convert_to_un(si,
3475 unlink(un_addr.sa.un.sun_path);
3477 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3479 SWRAP_LOG(SWRAP_LOG_TRACE,
3480 "bind() path=%s, fd=%d",
3481 un_addr.sa.un.sun_path, s);
3490 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3492 return swrap_bind(s, myaddr, addrlen);
3495 /****************************************************************************
3497 ***************************************************************************/
3499 #ifdef HAVE_BINDRESVPORT
3500 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3502 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3504 struct swrap_address myaddr = {
3505 .sa_socklen = sizeof(struct sockaddr_storage),
3508 static uint16_t port;
3513 #define SWRAP_STARTPORT 600
3514 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3515 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3518 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3522 salen = myaddr.sa_socklen;
3525 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3531 memset(&myaddr.sa.ss, 0, salen);
3536 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3539 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3541 salen = sizeof(struct sockaddr_in);
3542 sinp->sin_port = htons(port);
3546 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3548 salen = sizeof(struct sockaddr_in6);
3549 sin6p->sin6_port = htons(port);
3553 errno = EAFNOSUPPORT;
3558 if (port > SWRAP_ENDPORT) {
3559 port = SWRAP_STARTPORT;
3562 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3563 if (rc == 0 || errno != EADDRINUSE) {
3571 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3573 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3577 /****************************************************************************
3579 ***************************************************************************/
3581 static int swrap_listen(int s, int backlog)
3584 struct socket_info *si = find_socket_info(s);
3587 return libc_listen(s, backlog);
3590 if (si->bound == 0) {
3591 ret = swrap_auto_bind(s, si, si->family);
3598 ret = libc_listen(s, backlog);
3603 int listen(int s, int backlog)
3605 return swrap_listen(s, backlog);
3608 /****************************************************************************
3610 ***************************************************************************/
3612 static FILE *swrap_fopen(const char *name, const char *mode)
3616 fp = libc_fopen(name, mode);
3618 int fd = fileno(fp);
3620 swrap_remove_stale(fd);
3626 FILE *fopen(const char *name, const char *mode)
3628 return swrap_fopen(name, mode);
3631 /****************************************************************************
3633 ***************************************************************************/
3636 static FILE *swrap_fopen64(const char *name, const char *mode)
3640 fp = libc_fopen64(name, mode);
3642 int fd = fileno(fp);
3644 swrap_remove_stale(fd);
3650 FILE *fopen64(const char *name, const char *mode)
3652 return swrap_fopen64(name, mode);
3654 #endif /* HAVE_FOPEN64 */
3656 /****************************************************************************
3658 ***************************************************************************/
3660 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3664 ret = libc_vopen(pathname, flags, ap);
3667 * There are methods for closing descriptors (libc-internal code
3668 * paths, direct syscalls) which close descriptors in ways that
3669 * we can't intercept, so try to recover when we notice that
3672 swrap_remove_stale(ret);
3677 int open(const char *pathname, int flags, ...)
3682 va_start(ap, flags);
3683 fd = swrap_vopen(pathname, flags, ap);
3689 /****************************************************************************
3691 ***************************************************************************/
3694 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
3698 ret = libc_vopen64(pathname, flags, ap);
3701 * There are methods for closing descriptors (libc-internal code
3702 * paths, direct syscalls) which close descriptors in ways that
3703 * we can't intercept, so try to recover when we notice that
3706 swrap_remove_stale(ret);
3711 int open64(const char *pathname, int flags, ...)
3716 va_start(ap, flags);
3717 fd = swrap_vopen64(pathname, flags, ap);
3722 #endif /* HAVE_OPEN64 */
3724 /****************************************************************************
3726 ***************************************************************************/
3728 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3732 ret = libc_vopenat(dirfd, path, flags, ap);
3735 * There are methods for closing descriptors (libc-internal code
3736 * paths, direct syscalls) which close descriptors in ways that
3737 * we can't intercept, so try to recover when we notice that
3740 swrap_remove_stale(ret);
3746 int openat(int dirfd, const char *path, int flags, ...)
3751 va_start(ap, flags);
3752 fd = swrap_vopenat(dirfd, path, flags, ap);
3758 /****************************************************************************
3760 ***************************************************************************/
3762 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3764 struct socket_info *si = find_socket_info(s);
3768 return libc_getpeername(s, name, addrlen);
3771 if (si->peername.sa_socklen == 0)
3777 len = MIN(*addrlen, si->peername.sa_socklen);
3782 memcpy(name, &si->peername.sa.ss, len);
3783 *addrlen = si->peername.sa_socklen;
3788 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3789 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3791 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3794 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3797 /****************************************************************************
3799 ***************************************************************************/
3801 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3803 struct socket_info *si = find_socket_info(s);
3807 return libc_getsockname(s, name, addrlen);
3810 len = MIN(*addrlen, si->myname.sa_socklen);
3815 memcpy(name, &si->myname.sa.ss, len);
3816 *addrlen = si->myname.sa_socklen;
3821 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3822 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3824 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3827 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3830 /****************************************************************************
3832 ***************************************************************************/
3835 # ifdef SO_PROTOTYPE /* The Solaris name */
3836 # define SO_PROTOCOL SO_PROTOTYPE
3837 # endif /* SO_PROTOTYPE */
3838 #endif /* SO_PROTOCOL */
3840 static int swrap_getsockopt(int s, int level, int optname,
3841 void *optval, socklen_t *optlen)
3843 struct socket_info *si = find_socket_info(s);
3847 return libc_getsockopt(s,
3854 if (level == SOL_SOCKET) {
3858 if (optval == NULL || optlen == NULL ||
3859 *optlen < (socklen_t)sizeof(int)) {
3865 *optlen = sizeof(int);
3866 *(int *)optval = si->family;
3869 #endif /* SO_DOMAIN */
3873 if (optval == NULL || optlen == NULL ||
3874 *optlen < (socklen_t)sizeof(int)) {
3880 *optlen = sizeof(int);
3881 *(int *)optval = si->protocol;
3884 #endif /* SO_PROTOCOL */
3886 if (optval == NULL || optlen == NULL ||
3887 *optlen < (socklen_t)sizeof(int)) {
3893 *optlen = sizeof(int);
3894 *(int *)optval = si->type;
3898 ret = libc_getsockopt(s,
3905 } else if (level == IPPROTO_TCP) {
3910 * This enables sending packets directly out over TCP.
3911 * As a unix socket is doing that any way, report it as
3914 if (optval == NULL || optlen == NULL ||
3915 *optlen < (socklen_t)sizeof(int)) {
3921 *optlen = sizeof(int);
3922 *(int *)optval = si->tcp_nodelay;
3926 #endif /* TCP_NODELAY */
3932 errno = ENOPROTOOPT;
3939 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3940 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3942 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3945 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3948 /****************************************************************************
3950 ***************************************************************************/
3952 static int swrap_setsockopt(int s, int level, int optname,
3953 const void *optval, socklen_t optlen)
3955 struct socket_info *si = find_socket_info(s);
3959 return libc_setsockopt(s,
3966 if (level == SOL_SOCKET) {
3967 return libc_setsockopt(s,
3972 } else if (level == IPPROTO_TCP) {
3979 * This enables sending packets directly out over TCP.
3980 * A unix socket is doing that any way.
3982 if (optval == NULL || optlen == 0 ||
3983 optlen < (socklen_t)sizeof(int)) {
3989 i = *discard_const_p(int, optval);
3990 if (i != 0 && i != 1) {
3995 si->tcp_nodelay = i;
4000 #endif /* TCP_NODELAY */
4006 switch (si->family) {
4008 if (level == IPPROTO_IP) {
4010 if (optname == IP_PKTINFO) {
4011 si->pktinfo = AF_INET;
4013 #endif /* IP_PKTINFO */
4019 if (level == IPPROTO_IPV6) {
4020 #ifdef IPV6_RECVPKTINFO
4021 if (optname == IPV6_RECVPKTINFO) {
4022 si->pktinfo = AF_INET6;
4024 #endif /* IPV6_PKTINFO */
4030 errno = ENOPROTOOPT;
4039 int setsockopt(int s, int level, int optname,
4040 const void *optval, socklen_t optlen)
4042 return swrap_setsockopt(s, level, optname, optval, optlen);
4045 /****************************************************************************
4047 ***************************************************************************/
4049 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4051 struct socket_info *si = find_socket_info(s);
4057 return libc_vioctl(s, r, va);
4062 rc = libc_vioctl(s, r, va);
4066 value = *((int *)va_arg(ap, int *));
4068 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4069 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4070 } else if (value == 0) { /* END OF FILE */
4071 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4081 #ifdef HAVE_IOCTL_INT
4082 int ioctl(int s, int r, ...)
4084 int ioctl(int s, unsigned long int r, ...)
4092 rc = swrap_vioctl(s, (unsigned long int) r, va);
4103 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4106 # ifdef _ALIGN /* BSD */
4107 #define CMSG_ALIGN _ALIGN
4109 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4110 # endif /* _ALIGN */
4111 #endif /* CMSG_ALIGN */
4114 * @brief Add a cmsghdr to a msghdr.
4116 * This is an function to add any type of cmsghdr. It will operate on the
4117 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4118 * the buffer position after the added cmsg element. Hence, this function is
4119 * intended to be used with an intermediate msghdr and not on the original
4120 * one handed in by the client.
4122 * @param[in] msg The msghdr to which to add the cmsg.
4124 * @param[in] level The cmsg level to set.
4126 * @param[in] type The cmsg type to set.
4128 * @param[in] data The cmsg data to set.
4130 * @param[in] len the length of the data to set.
4132 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4138 size_t cmlen = CMSG_LEN(len);
4139 size_t cmspace = CMSG_SPACE(len);
4140 uint8_t cmbuf[cmspace];
4141 void *cast_ptr = (void *)cmbuf;
4142 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4145 memset(cmbuf, 0, cmspace);
4147 if (msg->msg_controllen < cmlen) {
4148 cmlen = msg->msg_controllen;
4149 msg->msg_flags |= MSG_CTRUNC;
4152 if (msg->msg_controllen < cmspace) {
4153 cmspace = msg->msg_controllen;
4157 * We copy the full input data into an intermediate cmsghdr first
4158 * in order to more easily cope with truncation.
4160 cm->cmsg_len = cmlen;
4161 cm->cmsg_level = level;
4162 cm->cmsg_type = type;
4163 memcpy(CMSG_DATA(cm), data, len);
4166 * We now copy the possibly truncated buffer.
4167 * We copy cmlen bytes, but consume cmspace bytes,
4168 * leaving the possible padding uninitialiazed.
4170 p = (uint8_t *)msg->msg_control;
4171 memcpy(p, cm, cmlen);
4173 msg->msg_control = p;
4174 msg->msg_controllen -= cmspace;
4179 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4182 /* Add packet info */
4183 switch (si->pktinfo) {
4184 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4186 struct sockaddr_in *sin;
4187 #if defined(HAVE_STRUCT_IN_PKTINFO)
4188 struct in_pktinfo pkt;
4189 #elif defined(IP_RECVDSTADDR)
4193 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4194 sin = &si->bindname.sa.in;
4196 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4199 sin = &si->myname.sa.in;
4204 #if defined(HAVE_STRUCT_IN_PKTINFO)
4205 pkt.ipi_ifindex = socket_wrapper_default_iface();
4206 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4207 #elif defined(IP_RECVDSTADDR)
4208 pkt = sin->sin_addr;
4211 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4216 #endif /* IP_PKTINFO */
4217 #if defined(HAVE_IPV6)
4219 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4220 struct sockaddr_in6 *sin6;
4221 struct in6_pktinfo pkt6;
4223 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4224 sin6 = &si->bindname.sa.in6;
4226 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4229 sin6 = &si->myname.sa.in6;
4234 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4235 pkt6.ipi6_addr = sin6->sin6_addr;
4237 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4238 &pkt6, sizeof(pkt6));
4239 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4243 #endif /* IPV6_PKTINFO */
4251 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4252 struct msghdr *omsg)
4256 if (si->pktinfo > 0) {
4257 rc = swrap_msghdr_add_pktinfo(si, omsg);
4263 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4265 size_t *cm_data_space);
4266 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4268 size_t *cm_data_space);
4270 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4272 size_t *cm_data_space) {
4273 struct cmsghdr *cmsg;
4277 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4281 for (cmsg = CMSG_FIRSTHDR(msg);
4283 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4284 switch (cmsg->cmsg_level) {
4286 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4291 rc = swrap_sendmsg_copy_cmsg(cmsg,
4301 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4303 size_t *cm_data_space)
4308 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4310 p = realloc((*cm_data), cmspace);
4316 p = (*cm_data) + (*cm_data_space);
4317 *cm_data_space = cmspace;
4319 memcpy(p, cmsg, cmsg->cmsg_len);
4324 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4326 size_t *cm_data_space);
4329 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4331 size_t *cm_data_space)
4335 switch(cmsg->cmsg_type) {
4338 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4345 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4357 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4359 size_t *cm_data_space)
4361 (void)cmsg; /* unused */
4362 (void)cm_data; /* unused */
4363 (void)cm_data_space; /* unused */
4366 * Passing a IP pktinfo to a unix socket might be rejected by the
4367 * Kernel, at least on FreeBSD. So skip this cmsg.
4371 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4373 static ssize_t swrap_sendmsg_before(int fd,
4374 struct socket_info *si,
4376 struct iovec *tmp_iov,
4377 struct sockaddr_un *tmp_un,
4378 const struct sockaddr_un **to_un,
4379 const struct sockaddr **to,
4399 if (!si->connected) {
4404 if (msg->msg_iovlen == 0) {
4408 mtu = socket_wrapper_mtu();
4409 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4411 nlen = len + msg->msg_iov[i].iov_len;
4416 msg->msg_iovlen = i;
4417 if (msg->msg_iovlen == 0) {
4418 *tmp_iov = msg->msg_iov[0];
4419 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4421 msg->msg_iov = tmp_iov;
4422 msg->msg_iovlen = 1;
4427 if (si->connected) {
4428 if (msg->msg_name != NULL) {
4430 * We are dealing with unix sockets and if we
4431 * are connected, we should only talk to the
4432 * connected unix path. Using the fd to send
4433 * to another server would be hard to achieve.
4435 msg->msg_name = NULL;
4436 msg->msg_namelen = 0;
4439 const struct sockaddr *msg_name;
4440 msg_name = (const struct sockaddr *)msg->msg_name;
4442 if (msg_name == NULL) {
4448 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4460 msg->msg_name = tmp_un;
4461 msg->msg_namelen = sizeof(*tmp_un);
4464 if (si->bound == 0) {
4465 ret = swrap_auto_bind(fd, si, si->family);
4467 if (errno == ENOTSOCK) {
4468 swrap_remove_stale(fd);
4471 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4477 if (!si->defer_connect) {
4481 ret = sockaddr_convert_to_un(si,
4483 si->peername.sa_socklen,
4491 ret = libc_connect(fd,
4492 (struct sockaddr *)(void *)tmp_un,
4495 /* to give better errors */
4496 if (ret == -1 && errno == ENOENT) {
4497 errno = EHOSTUNREACH;
4504 si->defer_connect = 0;
4507 errno = EHOSTUNREACH;
4511 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4512 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4513 uint8_t *cmbuf = NULL;
4516 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4523 msg->msg_controllen = 0;
4524 msg->msg_control = NULL;
4525 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4526 memcpy(msg->msg_control, cmbuf, cmlen);
4527 msg->msg_controllen = cmlen;
4536 static void swrap_sendmsg_after(int fd,
4537 struct socket_info *si,
4539 const struct sockaddr *to,
4542 int saved_errno = errno;
4549 /* to give better errors */
4551 if (saved_errno == ENOENT) {
4552 saved_errno = EHOSTUNREACH;
4553 } else if (saved_errno == ENOTSOCK) {
4554 /* If the fd is not a socket, remove it */
4555 swrap_remove_stale(fd);
4559 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4560 avail += msg->msg_iov[i].iov_len;
4564 remain = MIN(80, avail);
4569 /* we capture it as one single packet */
4570 buf = (uint8_t *)malloc(remain);
4572 /* we just not capture the packet */
4573 errno = saved_errno;
4577 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4578 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4580 msg->msg_iov[i].iov_base,
4583 remain -= this_time;
4590 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4591 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4593 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4598 if (si->connected) {
4599 to = &si->peername.sa.s;
4602 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4603 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4605 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4611 errno = saved_errno;
4614 static int swrap_recvmsg_before(int fd,
4615 struct socket_info *si,
4617 struct iovec *tmp_iov)
4622 (void)fd; /* unused */
4627 if (!si->connected) {
4632 if (msg->msg_iovlen == 0) {
4636 mtu = socket_wrapper_mtu();
4637 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4639 nlen = len + msg->msg_iov[i].iov_len;
4644 msg->msg_iovlen = i;
4645 if (msg->msg_iovlen == 0) {
4646 *tmp_iov = msg->msg_iov[0];
4647 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4649 msg->msg_iov = tmp_iov;
4650 msg->msg_iovlen = 1;
4655 if (msg->msg_name == NULL) {
4660 if (msg->msg_iovlen == 0) {
4664 if (si->bound == 0) {
4665 ret = swrap_auto_bind(fd, si, si->family);
4668 * When attempting to read or write to a
4669 * descriptor, if an underlying autobind fails
4670 * because it's not a socket, stop intercepting
4671 * uses of that descriptor.
4673 if (errno == ENOTSOCK) {
4674 swrap_remove_stale(fd);
4677 SWRAP_LOG(SWRAP_LOG_ERROR,
4678 "swrap_recvmsg_before failed");
4685 errno = EHOSTUNREACH;
4692 static int swrap_recvmsg_after(int fd,
4693 struct socket_info *si,
4695 const struct sockaddr_un *un_addr,
4696 socklen_t un_addrlen,
4699 int saved_errno = errno;
4701 uint8_t *buf = NULL;
4707 /* to give better errors */
4709 if (saved_errno == ENOENT) {
4710 saved_errno = EHOSTUNREACH;
4711 } else if (saved_errno == ENOTSOCK) {
4712 /* If the fd is not a socket, remove it */
4713 swrap_remove_stale(fd);
4717 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4718 avail += msg->msg_iov[i].iov_len;
4721 /* Convert the socket address before we leave */
4722 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4723 rc = sockaddr_convert_from_un(si,
4740 remain = MIN(80, avail);
4745 /* we capture it as one single packet */
4746 buf = (uint8_t *)malloc(remain);
4748 /* we just not capture the packet */
4749 errno = saved_errno;
4753 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4754 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4756 msg->msg_iov[i].iov_base,
4759 remain -= this_time;
4764 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4765 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4766 } else if (ret == 0) { /* END OF FILE */
4767 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4768 } else if (ret > 0) {
4769 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4778 if (un_addr != NULL) {
4779 swrap_pcap_dump_packet(si,
4785 swrap_pcap_dump_packet(si,
4798 errno = saved_errno;
4800 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4802 msg->msg_controllen > 0 &&
4803 msg->msg_control != NULL) {
4804 rc = swrap_msghdr_add_socket_info(si, msg);
4814 /****************************************************************************
4816 ***************************************************************************/
4818 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4819 struct sockaddr *from, socklen_t *fromlen)
4821 struct swrap_address from_addr = {
4822 .sa_socklen = sizeof(struct sockaddr_un),
4825 struct socket_info *si = find_socket_info(s);
4826 struct swrap_address saddr = {
4827 .sa_socklen = sizeof(struct sockaddr_storage),
4834 return libc_recvfrom(s,
4846 if (from != NULL && fromlen != NULL) {
4847 msg.msg_name = from; /* optional address */
4848 msg.msg_namelen = *fromlen; /* size of address */
4850 msg.msg_name = &saddr.sa.s; /* optional address */
4851 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4853 msg.msg_iov = &tmp; /* scatter/gather array */
4854 msg.msg_iovlen = 1; /* # elements in msg_iov */
4855 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4856 msg.msg_control = NULL; /* ancillary data, see below */
4857 msg.msg_controllen = 0; /* ancillary data buffer len */
4858 msg.msg_flags = 0; /* flags on received message */
4861 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4866 buf = msg.msg_iov[0].iov_base;
4867 len = msg.msg_iov[0].iov_len;
4869 ret = libc_recvfrom(s,
4874 &from_addr.sa_socklen);
4879 tret = swrap_recvmsg_after(s,
4883 from_addr.sa_socklen,
4889 if (from != NULL && fromlen != NULL) {
4890 *fromlen = msg.msg_namelen;
4896 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4897 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4898 struct sockaddr *from, Psocklen_t fromlen)
4900 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4901 struct sockaddr *from, socklen_t *fromlen)
4904 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4907 /****************************************************************************
4909 ***************************************************************************/
4911 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4912 const struct sockaddr *to, socklen_t tolen)
4916 struct swrap_address un_addr = {
4917 .sa_socklen = sizeof(struct sockaddr_un),
4919 const struct sockaddr_un *to_un = NULL;
4922 struct socket_info *si = find_socket_info(s);
4926 return libc_sendto(s, buf, len, flags, to, tolen);
4929 tmp.iov_base = discard_const_p(char, buf);
4933 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4934 msg.msg_namelen = tolen; /* size of address */
4935 msg.msg_iov = &tmp; /* scatter/gather array */
4936 msg.msg_iovlen = 1; /* # elements in msg_iov */
4937 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4938 msg.msg_control = NULL; /* ancillary data, see below */
4939 msg.msg_controllen = 0; /* ancillary data buffer len */
4940 msg.msg_flags = 0; /* flags on received message */
4943 rc = swrap_sendmsg_before(s,
4955 buf = msg.msg_iov[0].iov_base;
4956 len = msg.msg_iov[0].iov_len;
4961 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4964 type = SOCKET_TYPE_CHAR_UDP;
4966 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4967 snprintf(un_addr.sa.un.sun_path,
4968 sizeof(un_addr.sa.un.sun_path),
4970 socket_wrapper_dir(), type, iface, prt);
4971 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4973 /* ignore the any errors in broadcast sends */
4979 un_addr.sa_socklen);
4982 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4988 * If it is a dgram socket and we are connected, don't include the
4991 if (si->type == SOCK_DGRAM && si->connected) {
4992 ret = libc_sendto(s,
4999 ret = libc_sendto(s,
5003 (struct sockaddr *)msg.msg_name,
5007 swrap_sendmsg_after(s, si, &msg, to, ret);
5012 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5013 const struct sockaddr *to, socklen_t tolen)
5015 return swrap_sendto(s, buf, len, flags, to, tolen);
5018 /****************************************************************************
5020 ***************************************************************************/
5022 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5024 struct socket_info *si;
5026 struct swrap_address saddr = {
5027 .sa_socklen = sizeof(struct sockaddr_storage),
5033 si = find_socket_info(s);
5035 return libc_recv(s, buf, len, flags);
5042 msg.msg_name = &saddr.sa.s; /* optional address */
5043 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5044 msg.msg_iov = &tmp; /* scatter/gather array */
5045 msg.msg_iovlen = 1; /* # elements in msg_iov */
5046 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5047 msg.msg_control = NULL; /* ancillary data, see below */
5048 msg.msg_controllen = 0; /* ancillary data buffer len */
5049 msg.msg_flags = 0; /* flags on received message */
5052 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5057 buf = msg.msg_iov[0].iov_base;
5058 len = msg.msg_iov[0].iov_len;
5060 ret = libc_recv(s, buf, len, flags);
5062 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5070 ssize_t recv(int s, void *buf, size_t len, int flags)
5072 return swrap_recv(s, buf, len, flags);
5075 /****************************************************************************
5077 ***************************************************************************/
5079 static ssize_t swrap_read(int s, void *buf, size_t len)
5081 struct socket_info *si;
5084 struct swrap_address saddr = {
5085 .sa_socklen = sizeof(struct sockaddr_storage),
5090 si = find_socket_info(s);
5092 return libc_read(s, buf, len);
5099 msg.msg_name = &saddr.sa.ss; /* optional address */
5100 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5101 msg.msg_iov = &tmp; /* scatter/gather array */
5102 msg.msg_iovlen = 1; /* # elements in msg_iov */
5103 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5104 msg.msg_control = NULL; /* ancillary data, see below */
5105 msg.msg_controllen = 0; /* ancillary data buffer len */
5106 msg.msg_flags = 0; /* flags on received message */
5109 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5111 if (tret == -ENOTSOCK) {
5112 return libc_read(s, buf, len);
5117 buf = msg.msg_iov[0].iov_base;
5118 len = msg.msg_iov[0].iov_len;
5120 ret = libc_read(s, buf, len);
5122 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5130 ssize_t read(int s, void *buf, size_t len)
5132 return swrap_read(s, buf, len);
5135 /****************************************************************************
5137 ***************************************************************************/
5139 static ssize_t swrap_write(int s, const void *buf, size_t len)
5143 struct sockaddr_un un_addr;
5146 struct socket_info *si;
5148 si = find_socket_info(s);
5150 return libc_write(s, buf, len);
5153 tmp.iov_base = discard_const_p(char, buf);
5157 msg.msg_name = NULL; /* optional address */
5158 msg.msg_namelen = 0; /* size of address */
5159 msg.msg_iov = &tmp; /* scatter/gather array */
5160 msg.msg_iovlen = 1; /* # elements in msg_iov */
5161 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5162 msg.msg_control = NULL; /* ancillary data, see below */
5163 msg.msg_controllen = 0; /* ancillary data buffer len */
5164 msg.msg_flags = 0; /* flags on received message */
5167 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5172 buf = msg.msg_iov[0].iov_base;
5173 len = msg.msg_iov[0].iov_len;
5175 ret = libc_write(s, buf, len);
5177 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5182 ssize_t write(int s, const void *buf, size_t len)
5184 return swrap_write(s, buf, len);
5187 /****************************************************************************
5189 ***************************************************************************/
5191 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5195 struct sockaddr_un un_addr;
5198 struct socket_info *si = find_socket_info(s);
5201 return libc_send(s, buf, len, flags);
5204 tmp.iov_base = discard_const_p(char, buf);
5208 msg.msg_name = NULL; /* optional address */
5209 msg.msg_namelen = 0; /* size of address */
5210 msg.msg_iov = &tmp; /* scatter/gather array */
5211 msg.msg_iovlen = 1; /* # elements in msg_iov */
5212 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5213 msg.msg_control = NULL; /* ancillary data, see below */
5214 msg.msg_controllen = 0; /* ancillary data buffer len */
5215 msg.msg_flags = 0; /* flags on received message */
5218 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5223 buf = msg.msg_iov[0].iov_base;
5224 len = msg.msg_iov[0].iov_len;
5226 ret = libc_send(s, buf, len, flags);
5228 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5233 ssize_t send(int s, const void *buf, size_t len, int flags)
5235 return swrap_send(s, buf, len, flags);
5238 /****************************************************************************
5240 ***************************************************************************/
5242 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5244 struct swrap_address from_addr = {
5245 .sa_socklen = sizeof(struct sockaddr_un),
5247 struct swrap_address convert_addr = {
5248 .sa_socklen = sizeof(struct sockaddr_storage),
5250 struct socket_info *si;
5253 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5254 size_t msg_ctrllen_filled;
5255 size_t msg_ctrllen_left;
5261 si = find_socket_info(s);
5263 return libc_recvmsg(s, omsg, flags);
5266 tmp.iov_base = NULL;
5270 msg.msg_name = &from_addr.sa; /* optional address */
5271 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5272 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5273 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5274 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5275 msg_ctrllen_filled = 0;
5276 msg_ctrllen_left = omsg->msg_controllen;
5278 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5279 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5280 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5283 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5288 ret = libc_recvmsg(s, &msg, flags);
5290 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5291 msg_ctrllen_filled += msg.msg_controllen;
5292 msg_ctrllen_left -= msg.msg_controllen;
5294 if (omsg->msg_control != NULL) {
5297 p = omsg->msg_control;
5298 p += msg_ctrllen_filled;
5300 msg.msg_control = p;
5301 msg.msg_controllen = msg_ctrllen_left;
5303 msg.msg_control = NULL;
5304 msg.msg_controllen = 0;
5309 * We convert the unix address to a IP address so we need a buffer
5310 * which can store the address in case of SOCK_DGRAM, see below.
5312 msg.msg_name = &convert_addr.sa;
5313 msg.msg_namelen = convert_addr.sa_socklen;
5315 rc = swrap_recvmsg_after(s,
5319 from_addr.sa_socklen,
5325 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5326 if (omsg->msg_control != NULL) {
5327 /* msg.msg_controllen = space left */
5328 msg_ctrllen_left = msg.msg_controllen;
5329 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5332 /* Update the original message length */
5333 omsg->msg_controllen = msg_ctrllen_filled;
5334 omsg->msg_flags = msg.msg_flags;
5336 omsg->msg_iovlen = msg.msg_iovlen;
5341 * The msg_name field points to a caller-allocated buffer that is
5342 * used to return the source address if the socket is unconnected. The
5343 * caller should set msg_namelen to the size of this buffer before this
5344 * call; upon return from a successful call, msg_name will contain the
5345 * length of the returned address. If the application does not need
5346 * to know the source address, msg_name can be specified as NULL.
5348 if (si->type == SOCK_STREAM) {
5349 omsg->msg_namelen = 0;
5350 } else if (omsg->msg_name != NULL &&
5351 omsg->msg_namelen != 0 &&
5352 omsg->msg_namelen >= msg.msg_namelen) {
5353 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5354 omsg->msg_namelen = msg.msg_namelen;
5360 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5362 return swrap_recvmsg(sockfd, msg, flags);
5365 /****************************************************************************
5367 ***************************************************************************/
5369 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5373 struct sockaddr_un un_addr;
5374 const struct sockaddr_un *to_un = NULL;
5375 const struct sockaddr *to = NULL;
5378 struct socket_info *si = find_socket_info(s);
5382 return libc_sendmsg(s, omsg, flags);
5385 ZERO_STRUCT(un_addr);
5387 tmp.iov_base = NULL;
5392 if (si->connected == 0) {
5393 msg.msg_name = omsg->msg_name; /* optional address */
5394 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5396 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5397 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5398 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5399 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5400 /* omsg is a const so use a local buffer for modifications */
5401 uint8_t cmbuf[omsg->msg_controllen];
5403 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5405 msg.msg_control = cmbuf; /* ancillary data, see below */
5406 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5408 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5411 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5419 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5427 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5428 avail += msg.msg_iov[i].iov_len;
5434 /* we capture it as one single packet */
5435 buf = (uint8_t *)malloc(remain);
5440 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5441 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5443 msg.msg_iov[i].iov_base,
5446 remain -= this_time;
5449 type = SOCKET_TYPE_CHAR_UDP;
5451 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5452 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5453 socket_wrapper_dir(), type, iface, prt);
5454 if (stat(un_addr.sun_path, &st) != 0) continue;
5456 msg.msg_name = &un_addr; /* optional address */
5457 msg.msg_namelen = sizeof(un_addr); /* size of address */
5459 /* ignore the any errors in broadcast sends */
5460 libc_sendmsg(s, &msg, flags);
5463 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5469 ret = libc_sendmsg(s, &msg, flags);
5471 swrap_sendmsg_after(s, si, &msg, to, ret);
5476 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5478 return swrap_sendmsg(s, omsg, flags);
5481 /****************************************************************************
5483 ***************************************************************************/
5485 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5487 struct socket_info *si;
5490 struct swrap_address saddr = {
5491 .sa_socklen = sizeof(struct sockaddr_storage)
5496 si = find_socket_info(s);
5498 return libc_readv(s, vector, count);
5501 tmp.iov_base = NULL;
5505 msg.msg_name = &saddr.sa.s; /* optional address */
5506 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5507 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5508 msg.msg_iovlen = count; /* # elements in msg_iov */
5509 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5510 msg.msg_control = NULL; /* ancillary data, see below */
5511 msg.msg_controllen = 0; /* ancillary data buffer len */
5512 msg.msg_flags = 0; /* flags on received message */
5515 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5517 if (rc == -ENOTSOCK) {
5518 return libc_readv(s, vector, count);
5523 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5525 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5533 ssize_t readv(int s, const struct iovec *vector, int count)
5535 return swrap_readv(s, vector, count);
5538 /****************************************************************************
5540 ***************************************************************************/
5542 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5546 struct sockaddr_un un_addr;
5549 struct socket_info *si = find_socket_info(s);
5552 return libc_writev(s, vector, count);
5555 tmp.iov_base = NULL;
5559 msg.msg_name = NULL; /* optional address */
5560 msg.msg_namelen = 0; /* size of address */
5561 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5562 msg.msg_iovlen = count; /* # elements in msg_iov */
5563 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5564 msg.msg_control = NULL; /* ancillary data, see below */
5565 msg.msg_controllen = 0; /* ancillary data buffer len */
5566 msg.msg_flags = 0; /* flags on received message */
5569 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5571 if (rc == -ENOTSOCK) {
5572 return libc_readv(s, vector, count);
5577 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5579 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5584 ssize_t writev(int s, const struct iovec *vector, int count)
5586 return swrap_writev(s, vector, count);
5589 /****************************
5591 ***************************/
5593 static int swrap_close(int fd)
5595 struct socket_info_fd *fi = find_socket_info_fd(fd);
5596 struct socket_info *si = NULL;
5601 return libc_close(fd);
5604 si_index = fi->si_index;
5606 SWRAP_DLIST_REMOVE(socket_fds, fi);
5609 ret = libc_close(fd);
5611 si = &sockets[si_index];
5614 if (si->refcount > 0) {
5615 /* there are still references left */
5619 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5620 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5623 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5624 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5625 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5628 if (si->un_addr.sun_path[0] != '\0') {
5629 unlink(si->un_addr.sun_path);
5632 si->next_free = first_free;
5633 first_free = si_index;
5640 return swrap_close(fd);
5643 /****************************
5645 ***************************/
5647 static int swrap_dup(int fd)
5649 struct socket_info *si;
5650 struct socket_info_fd *src_fi, *fi;
5652 src_fi = find_socket_info_fd(fd);
5653 if (src_fi == NULL) {
5654 return libc_dup(fd);
5657 si = &sockets[src_fi->si_index];
5659 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5665 fi->fd = libc_dup(fd);
5667 int saved_errno = errno;
5669 errno = saved_errno;
5674 fi->si_index = src_fi->si_index;
5676 /* Make sure we don't have an entry for the fd */
5677 swrap_remove_stale(fi->fd);
5679 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5685 return swrap_dup(fd);
5688 /****************************
5690 ***************************/
5692 static int swrap_dup2(int fd, int newfd)
5694 struct socket_info *si;
5695 struct socket_info_fd *src_fi, *fi;
5697 src_fi = find_socket_info_fd(fd);
5698 if (src_fi == NULL) {
5699 return libc_dup2(fd, newfd);
5702 si = &sockets[src_fi->si_index];
5706 * According to the manpage:
5708 * "If oldfd is a valid file descriptor, and newfd has the same
5709 * value as oldfd, then dup2() does nothing, and returns newfd."
5714 if (find_socket_info(newfd)) {
5715 /* dup2() does an implicit close of newfd, which we
5716 * need to emulate */
5720 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5726 fi->fd = libc_dup2(fd, newfd);
5728 int saved_errno = errno;
5730 errno = saved_errno;
5735 fi->si_index = src_fi->si_index;
5737 /* Make sure we don't have an entry for the fd */
5738 swrap_remove_stale(fi->fd);
5740 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5744 int dup2(int fd, int newfd)
5746 return swrap_dup2(fd, newfd);
5749 /****************************
5751 ***************************/
5753 static int swrap_vfcntl(int fd, int cmd, va_list va)
5755 struct socket_info_fd *src_fi, *fi;
5756 struct socket_info *si;
5759 src_fi = find_socket_info_fd(fd);
5760 if (src_fi == NULL) {
5761 return libc_vfcntl(fd, cmd, va);
5764 si = &sockets[src_fi->si_index];
5768 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5774 fi->fd = libc_vfcntl(fd, cmd, va);
5776 int saved_errno = errno;
5778 errno = saved_errno;
5783 fi->si_index = src_fi->si_index;
5785 /* Make sure we don't have an entry for the fd */
5786 swrap_remove_stale(fi->fd);
5788 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5793 rc = libc_vfcntl(fd, cmd, va);
5800 int fcntl(int fd, int cmd, ...)
5807 rc = swrap_vfcntl(fd, cmd, va);
5814 /****************************
5816 ***************************/
5819 static int swrap_eventfd(int count, int flags)
5823 fd = libc_eventfd(count, flags);
5825 swrap_remove_stale(fd);
5831 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5832 int eventfd(unsigned int count, int flags)
5834 int eventfd(int count, int flags)
5837 return swrap_eventfd(count, flags);
5842 int pledge(const char *promises, const char *paths[])
5844 (void)promises; /* unused */
5845 (void)paths; /* unused */
5849 #endif /* HAVE_PLEDGE */
5851 static void swrap_thread_prepare(void)
5856 static void swrap_thread_parent(void)
5861 static void swrap_thread_child(void)
5866 /****************************
5868 ***************************/
5869 void swrap_constructor(void)
5872 * If we hold a lock and the application forks, then the child
5873 * is not able to unlock the mutex and we are in a deadlock.
5874 * This should prevent such deadlocks.
5876 pthread_atfork(&swrap_thread_prepare,
5877 &swrap_thread_parent,
5878 &swrap_thread_child);
5881 /****************************
5883 ***************************/
5886 * This function is called when the library is unloaded and makes sure that
5887 * sockets get closed and the unix file for the socket are unlinked.
5889 void swrap_destructor(void)
5891 struct socket_info_fd *s = socket_fds;
5900 if (swrap.libc.handle != NULL) {
5901 dlclose(swrap.libc.handle);
5903 if (swrap.libc.socket_handle) {
5904 dlclose(swrap.libc.socket_handle);