2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
45 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
91 /* GCC have printf type attribute check. */
92 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
93 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
95 #define PRINTF_ATTRIBUTE(a,b)
96 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
98 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
99 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
101 #define CONSTRUCTOR_ATTRIBUTE
102 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
104 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
105 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
107 #define DESTRUCTOR_ATTRIBUTE
110 #ifdef HAVE_FALLTHROUGH_ATTRIBUTE
111 #define FALL_THROUGH __attribute__ ((fallthrough))
116 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
117 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
119 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
122 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
123 # define SWRAP_THREAD __thread
125 # define SWRAP_THREAD
129 #define MIN(a,b) ((a)<(b)?(a):(b))
133 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
137 #define ZERO_STRUCTP(x) do { \
139 memset((char *)(x), 0, sizeof(*(x))); \
143 #ifndef discard_const
144 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
147 #ifndef discard_const_p
148 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
151 #define UNUSED(x) (void)(x)
154 # ifndef IPV6_RECVPKTINFO
155 # define IPV6_RECVPKTINFO IPV6_PKTINFO
156 # endif /* IPV6_RECVPKTINFO */
157 #endif /* IPV6_PKTINFO */
160 * On BSD IP_PKTINFO has a different name because during
161 * the time when they implemented it, there was no RFC.
162 * The name for IPv6 is the same as on Linux.
165 # ifdef IP_RECVDSTADDR
166 # define IP_PKTINFO IP_RECVDSTADDR
170 /* Macros for accessing mutexes */
171 # define SWRAP_LOCK(m) do { \
172 pthread_mutex_lock(&(m ## _mutex)); \
175 # define SWRAP_UNLOCK(m) do { \
176 pthread_mutex_unlock(&(m ## _mutex)); \
179 /* Add new global locks here please */
180 # define SWRAP_LOCK_ALL \
181 SWRAP_LOCK(libc_symbol_binding); \
183 # define SWRAP_UNLOCK_ALL \
184 SWRAP_UNLOCK(libc_symbol_binding); \
187 #define SWRAP_DLIST_ADD(list,item) do { \
189 (item)->prev = NULL; \
190 (item)->next = NULL; \
193 (item)->prev = NULL; \
194 (item)->next = (list); \
195 (list)->prev = (item); \
200 #define SWRAP_DLIST_REMOVE(list,item) do { \
201 if ((list) == (item)) { \
202 (list) = (item)->next; \
204 (list)->prev = NULL; \
207 if ((item)->prev) { \
208 (item)->prev->next = (item)->next; \
210 if ((item)->next) { \
211 (item)->next->prev = (item)->prev; \
214 (item)->prev = NULL; \
215 (item)->next = NULL; \
218 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
220 if ((list) == NULL || (el) == NULL) { \
221 SWRAP_DLIST_ADD(list, item); \
223 (item)->prev = (el); \
224 (item)->next = (el)->next; \
225 (el)->next = (item); \
226 if ((item)->next != NULL) { \
227 (item)->next->prev = (item); \
232 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
233 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
235 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
238 /* we need to use a very terse format here as IRIX 6.4 silently
239 truncates names to 16 chars, so if we use a longer name then we
240 can't tell which port a packet came from with recvfrom()
242 with this format we have 8 chars left for the directory name
244 #define SOCKET_FORMAT "%c%02X%04X"
245 #define SOCKET_TYPE_CHAR_TCP 'T'
246 #define SOCKET_TYPE_CHAR_UDP 'U'
247 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
248 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
251 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
252 * format PCAP capture files (as the caller will simply continue from here).
254 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
255 #define SOCKET_WRAPPER_MTU_MIN 512
256 #define SOCKET_WRAPPER_MTU_MAX 32768
258 #define SOCKET_MAX_SOCKETS 1024
262 * Maximum number of socket_info structures that can
263 * be used. Can be overriden by the environment variable
264 * SOCKET_WRAPPER_MAX_SOCKETS.
266 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
268 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 256000
270 /* This limit is to avoid broadcast sendto() needing to stat too many
271 * files. It may be raised (with a performance cost) to up to 254
272 * without changing the format above */
273 #define MAX_WRAPPED_INTERFACES 64
275 struct swrap_address {
276 socklen_t sa_socklen;
279 struct sockaddr_in in;
281 struct sockaddr_in6 in6;
283 struct sockaddr_un un;
284 struct sockaddr_storage ss;
288 struct socket_info_fd {
289 struct socket_info_fd *prev, *next;
293 * Points to corresponding index in array of
294 * socket_info structures
303 unsigned int refcount;
318 /* The unix path so we can unlink it on close() */
319 struct sockaddr_un un_addr;
321 struct swrap_address bindname;
322 struct swrap_address myname;
323 struct swrap_address peername;
326 unsigned long pck_snd;
327 unsigned long pck_rcv;
331 static struct socket_info *sockets;
332 static size_t max_sockets = 0;
335 * While socket file descriptors are passed among different processes, the
336 * numerical value gets changed. So its better to store it locally to each
337 * process rather than including it within socket_info which will be shared.
339 static struct socket_info_fd *socket_fds;
341 /* The mutex for accessing the global libc.symbols */
342 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
344 /* Function prototypes */
346 bool socket_wrapper_enabled(void);
348 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
349 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
352 # define SWRAP_LOG(...)
355 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
356 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
358 static void swrap_log(enum swrap_dbglvl_e dbglvl,
360 const char *format, ...)
365 unsigned int lvl = 0;
367 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
372 va_start(va, format);
373 vsnprintf(buffer, sizeof(buffer), format, va);
378 case SWRAP_LOG_ERROR:
380 "SWRAP_ERROR(%d) - %s: %s\n",
381 (int)getpid(), func, buffer);
385 "SWRAP_WARN(%d) - %s: %s\n",
386 (int)getpid(), func, buffer);
388 case SWRAP_LOG_DEBUG:
390 "SWRAP_DEBUG(%d) - %s: %s\n",
391 (int)getpid(), func, buffer);
393 case SWRAP_LOG_TRACE:
395 "SWRAP_TRACE(%d) - %s: %s\n",
396 (int)getpid(), func, buffer);
403 /*********************************************************
404 * SWRAP LOADING LIBC FUNCTIONS
405 *********************************************************/
410 typedef int (*__libc_accept4)(int sockfd,
411 struct sockaddr *addr,
415 typedef int (*__libc_accept)(int sockfd,
416 struct sockaddr *addr,
419 typedef int (*__libc_bind)(int sockfd,
420 const struct sockaddr *addr,
422 typedef int (*__libc_close)(int fd);
423 typedef int (*__libc_connect)(int sockfd,
424 const struct sockaddr *addr,
426 typedef int (*__libc_dup)(int fd);
427 typedef int (*__libc_dup2)(int oldfd, int newfd);
428 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
429 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
431 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
434 typedef int (*__libc_eventfd)(int count, int flags);
436 typedef int (*__libc_getpeername)(int sockfd,
437 struct sockaddr *addr,
439 typedef int (*__libc_getsockname)(int sockfd,
440 struct sockaddr *addr,
442 typedef int (*__libc_getsockopt)(int sockfd,
447 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
448 typedef int (*__libc_listen)(int sockfd, int backlog);
449 typedef int (*__libc_open)(const char *pathname, int flags, mode_t mode);
451 typedef int (*__libc_open64)(const char *pathname, int flags, mode_t mode);
452 #endif /* HAVE_OPEN64 */
453 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
454 typedef int (*__libc_pipe)(int pipefd[2]);
455 typedef int (*__libc_read)(int fd, void *buf, size_t count);
456 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
457 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
458 typedef int (*__libc_recvfrom)(int sockfd,
462 struct sockaddr *src_addr,
464 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
465 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
466 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
467 typedef int (*__libc_sendto)(int sockfd,
471 const struct sockaddr *dst_addr,
473 typedef int (*__libc_setsockopt)(int sockfd,
479 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
481 typedef int (*__libc_socket)(int domain, int type, int protocol);
482 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
483 #ifdef HAVE_TIMERFD_CREATE
484 typedef int (*__libc_timerfd_create)(int clockid, int flags);
486 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
487 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
489 #define SWRAP_SYMBOL_ENTRY(i) \
495 struct swrap_libc_symbols {
497 SWRAP_SYMBOL_ENTRY(accept4);
499 SWRAP_SYMBOL_ENTRY(accept);
501 SWRAP_SYMBOL_ENTRY(bind);
502 SWRAP_SYMBOL_ENTRY(close);
503 SWRAP_SYMBOL_ENTRY(connect);
504 SWRAP_SYMBOL_ENTRY(dup);
505 SWRAP_SYMBOL_ENTRY(dup2);
506 SWRAP_SYMBOL_ENTRY(fcntl);
507 SWRAP_SYMBOL_ENTRY(fopen);
509 SWRAP_SYMBOL_ENTRY(fopen64);
512 SWRAP_SYMBOL_ENTRY(eventfd);
514 SWRAP_SYMBOL_ENTRY(getpeername);
515 SWRAP_SYMBOL_ENTRY(getsockname);
516 SWRAP_SYMBOL_ENTRY(getsockopt);
517 SWRAP_SYMBOL_ENTRY(ioctl);
518 SWRAP_SYMBOL_ENTRY(listen);
519 SWRAP_SYMBOL_ENTRY(open);
521 SWRAP_SYMBOL_ENTRY(open64);
523 SWRAP_SYMBOL_ENTRY(openat);
524 SWRAP_SYMBOL_ENTRY(pipe);
525 SWRAP_SYMBOL_ENTRY(read);
526 SWRAP_SYMBOL_ENTRY(readv);
527 SWRAP_SYMBOL_ENTRY(recv);
528 SWRAP_SYMBOL_ENTRY(recvfrom);
529 SWRAP_SYMBOL_ENTRY(recvmsg);
530 SWRAP_SYMBOL_ENTRY(send);
531 SWRAP_SYMBOL_ENTRY(sendmsg);
532 SWRAP_SYMBOL_ENTRY(sendto);
533 SWRAP_SYMBOL_ENTRY(setsockopt);
535 SWRAP_SYMBOL_ENTRY(signalfd);
537 SWRAP_SYMBOL_ENTRY(socket);
538 SWRAP_SYMBOL_ENTRY(socketpair);
539 #ifdef HAVE_TIMERFD_CREATE
540 SWRAP_SYMBOL_ENTRY(timerfd_create);
542 SWRAP_SYMBOL_ENTRY(write);
543 SWRAP_SYMBOL_ENTRY(writev);
550 struct swrap_libc_symbols symbols;
554 static struct swrap swrap;
557 static const char *socket_wrapper_dir(void);
559 #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 */
584 static void *swrap_load_lib_handle(enum swrap_lib lib)
586 int flags = RTLD_LAZY;
591 flags |= RTLD_DEEPBIND;
597 case SWRAP_LIBSOCKET:
598 #ifdef HAVE_LIBSOCKET
599 handle = swrap.libc.socket_handle;
600 if (handle == NULL) {
601 for (i = 10; i >= 0; i--) {
602 char soname[256] = {0};
604 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
605 handle = dlopen(soname, flags);
606 if (handle != NULL) {
611 swrap.libc.socket_handle = handle;
617 handle = swrap.libc.handle;
619 if (handle == NULL) {
620 handle = dlopen(LIBC_SO, flags);
622 swrap.libc.handle = handle;
625 if (handle == NULL) {
626 for (i = 10; i >= 0; i--) {
627 char soname[256] = {0};
629 snprintf(soname, sizeof(soname), "libc.so.%d", i);
630 handle = dlopen(soname, flags);
631 if (handle != NULL) {
636 swrap.libc.handle = handle;
641 if (handle == NULL) {
643 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
645 SWRAP_LOG(SWRAP_LOG_ERROR,
646 "Failed to dlopen library: %s\n",
655 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
660 handle = swrap_load_lib_handle(lib);
662 func = dlsym(handle, fn_name);
664 SWRAP_LOG(SWRAP_LOG_ERROR,
665 "Failed to find %s: %s\n",
671 SWRAP_LOG(SWRAP_LOG_TRACE,
679 #define swrap_bind_symbol_libc(sym_name) \
680 SWRAP_LOCK(libc_symbol_binding); \
681 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
682 swrap.libc.symbols._libc_##sym_name.obj = \
683 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
685 SWRAP_UNLOCK(libc_symbol_binding)
687 #define swrap_bind_symbol_libsocket(sym_name) \
688 SWRAP_LOCK(libc_symbol_binding); \
689 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
690 swrap.libc.symbols._libc_##sym_name.obj = \
691 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
693 SWRAP_UNLOCK(libc_symbol_binding)
695 #define swrap_bind_symbol_libnsl(sym_name) \
696 SWRAP_LOCK(libc_symbol_binding); \
697 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
698 swrap.libc.symbols._libc_##sym_name.obj = \
699 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
701 SWRAP_UNLOCK(libc_symbol_binding)
706 * Functions especially from libc need to be loaded individually, you can't load
707 * all at once or gdb will segfault at startup. The same applies to valgrind and
708 * has probably something todo with with the linker.
709 * So we need load each function at the point it is called the first time.
712 static int libc_accept4(int sockfd,
713 struct sockaddr *addr,
717 swrap_bind_symbol_libsocket(accept4);
719 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
722 #else /* HAVE_ACCEPT4 */
724 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
726 swrap_bind_symbol_libsocket(accept);
728 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
730 #endif /* HAVE_ACCEPT4 */
732 static int libc_bind(int sockfd,
733 const struct sockaddr *addr,
736 swrap_bind_symbol_libsocket(bind);
738 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
741 static int libc_close(int fd)
743 swrap_bind_symbol_libc(close);
745 return swrap.libc.symbols._libc_close.f(fd);
748 static int libc_connect(int sockfd,
749 const struct sockaddr *addr,
752 swrap_bind_symbol_libsocket(connect);
754 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
757 static int libc_dup(int fd)
759 swrap_bind_symbol_libc(dup);
761 return swrap.libc.symbols._libc_dup.f(fd);
764 static int libc_dup2(int oldfd, int newfd)
766 swrap_bind_symbol_libc(dup2);
768 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
772 static int libc_eventfd(int count, int flags)
774 swrap_bind_symbol_libc(eventfd);
776 return swrap.libc.symbols._libc_eventfd.f(count, flags);
780 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
781 static int libc_vfcntl(int fd, int cmd, va_list ap)
787 swrap_bind_symbol_libc(fcntl);
789 for (i = 0; i < 4; i++) {
790 args[i] = va_arg(ap, long int);
793 rc = swrap.libc.symbols._libc_fcntl.f(fd,
803 static int libc_getpeername(int sockfd,
804 struct sockaddr *addr,
807 swrap_bind_symbol_libsocket(getpeername);
809 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
812 static int libc_getsockname(int sockfd,
813 struct sockaddr *addr,
816 swrap_bind_symbol_libsocket(getsockname);
818 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
821 static int libc_getsockopt(int sockfd,
827 swrap_bind_symbol_libsocket(getsockopt);
829 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
836 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
837 static int libc_vioctl(int d, unsigned long int request, va_list ap)
843 swrap_bind_symbol_libc(ioctl);
845 for (i = 0; i < 4; i++) {
846 args[i] = va_arg(ap, long int);
849 rc = swrap.libc.symbols._libc_ioctl.f(d,
859 static int libc_listen(int sockfd, int backlog)
861 swrap_bind_symbol_libsocket(listen);
863 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
866 static FILE *libc_fopen(const char *name, const char *mode)
868 swrap_bind_symbol_libc(fopen);
870 return swrap.libc.symbols._libc_fopen.f(name, mode);
874 static FILE *libc_fopen64(const char *name, const char *mode)
876 swrap_bind_symbol_libc(fopen64);
878 return swrap.libc.symbols._libc_fopen64.f(name, mode);
880 #endif /* HAVE_FOPEN64 */
882 static int libc_vopen(const char *pathname, int flags, va_list ap)
887 swrap_bind_symbol_libc(open);
889 mode = va_arg(ap, long int);
891 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
896 static int libc_open(const char *pathname, int flags, ...)
902 fd = libc_vopen(pathname, flags, ap);
909 static int libc_vopen64(const char *pathname, int flags, va_list ap)
914 swrap_bind_symbol_libc(open64);
916 mode = va_arg(ap, long int);
918 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
922 #endif /* HAVE_OPEN64 */
924 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
929 swrap_bind_symbol_libc(openat);
931 mode = va_arg(ap, long int);
933 fd = swrap.libc.symbols._libc_openat.f(dirfd, path, flags, (mode_t)mode);
939 static int libc_openat(int dirfd, const char *path, int flags, ...)
945 fd = libc_vopenat(dirfd, path, flags, ap);
952 static int libc_pipe(int pipefd[2])
954 swrap_bind_symbol_libsocket(pipe);
956 return swrap.libc.symbols._libc_pipe.f(pipefd);
959 static int libc_read(int fd, void *buf, size_t count)
961 swrap_bind_symbol_libc(read);
963 return swrap.libc.symbols._libc_read.f(fd, buf, count);
966 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
968 swrap_bind_symbol_libsocket(readv);
970 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
973 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
975 swrap_bind_symbol_libsocket(recv);
977 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
980 static int libc_recvfrom(int sockfd,
984 struct sockaddr *src_addr,
987 swrap_bind_symbol_libsocket(recvfrom);
989 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
997 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
999 swrap_bind_symbol_libsocket(recvmsg);
1001 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
1004 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
1006 swrap_bind_symbol_libsocket(send);
1008 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1011 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1013 swrap_bind_symbol_libsocket(sendmsg);
1015 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1018 static int libc_sendto(int sockfd,
1022 const struct sockaddr *dst_addr,
1025 swrap_bind_symbol_libsocket(sendto);
1027 return swrap.libc.symbols._libc_sendto.f(sockfd,
1035 static int libc_setsockopt(int sockfd,
1041 swrap_bind_symbol_libsocket(setsockopt);
1043 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1050 #ifdef HAVE_SIGNALFD
1051 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1053 swrap_bind_symbol_libsocket(signalfd);
1055 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1059 static int libc_socket(int domain, int type, int protocol)
1061 swrap_bind_symbol_libsocket(socket);
1063 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1066 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1068 swrap_bind_symbol_libsocket(socketpair);
1070 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1073 #ifdef HAVE_TIMERFD_CREATE
1074 static int libc_timerfd_create(int clockid, int flags)
1076 swrap_bind_symbol_libc(timerfd_create);
1078 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1082 static ssize_t libc_write(int fd, const void *buf, size_t count)
1084 swrap_bind_symbol_libc(write);
1086 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1089 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1091 swrap_bind_symbol_libsocket(writev);
1093 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1096 /*********************************************************
1097 * SWRAP HELPER FUNCTIONS
1098 *********************************************************/
1104 static const struct in6_addr *swrap_ipv6(void)
1106 static struct in6_addr v;
1107 static int initialized;
1115 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1124 static void set_port(int family, int prt, struct swrap_address *addr)
1128 addr->sa.in.sin_port = htons(prt);
1132 addr->sa.in6.sin6_port = htons(prt);
1138 static size_t socket_length(int family)
1142 return sizeof(struct sockaddr_in);
1145 return sizeof(struct sockaddr_in6);
1151 static const char *socket_wrapper_dir(void)
1153 const char *s = getenv("SOCKET_WRAPPER_DIR");
1157 /* TODO use realpath(3) here, when we add support for threads */
1158 if (strncmp(s, "./", 2) == 0) {
1162 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1166 static unsigned int socket_wrapper_mtu(void)
1168 static unsigned int max_mtu = 0;
1177 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1179 s = getenv("SOCKET_WRAPPER_MTU");
1184 tmp = strtol(s, &endp, 10);
1189 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1198 static size_t socket_wrapper_max_sockets(void)
1204 if (max_sockets != 0) {
1208 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1210 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1211 if (s == NULL || s[0] == '\0') {
1215 tmp = strtoul(s, &endp, 10);
1219 if (tmp == 0 || tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1220 SWRAP_LOG(SWRAP_LOG_ERROR,
1221 "Invalid number of sockets specified, using default.");
1231 static void socket_wrapper_init_sockets(void)
1235 if (sockets != NULL) {
1239 max_sockets = socket_wrapper_max_sockets();
1241 sockets = (struct socket_info *)calloc(max_sockets,
1242 sizeof(struct socket_info));
1244 if (sockets == NULL) {
1245 SWRAP_LOG(SWRAP_LOG_ERROR,
1246 "Failed to allocate sockets array.\n");
1252 for (i = 0; i < max_sockets; i++) {
1253 sockets[i].next_free = i+1;
1256 sockets[max_sockets-1].next_free = -1;
1259 bool socket_wrapper_enabled(void)
1261 const char *s = socket_wrapper_dir();
1267 socket_wrapper_init_sockets();
1272 static unsigned int socket_wrapper_default_iface(void)
1274 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1277 if (sscanf(s, "%u", &iface) == 1) {
1278 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1284 return 1;/* 127.0.0.1 */
1288 * Return the first free entry (if any) and make
1289 * it re-usable again (by nulling it out)
1291 static int socket_wrapper_first_free_index(void)
1295 if (first_free == -1) {
1299 next_free = sockets[first_free].next_free;
1300 ZERO_STRUCT(sockets[first_free]);
1301 sockets[first_free].next_free = next_free;
1306 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1313 p = strrchr(un->sun_path, '/');
1314 if (p) p++; else p = un->sun_path;
1316 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1321 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1324 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1335 case SOCKET_TYPE_CHAR_TCP:
1336 case SOCKET_TYPE_CHAR_UDP: {
1337 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1339 if ((*len) < sizeof(*in2)) {
1344 memset(in2, 0, sizeof(*in2));
1345 in2->sin_family = AF_INET;
1346 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1347 in2->sin_port = htons(prt);
1349 *len = sizeof(*in2);
1353 case SOCKET_TYPE_CHAR_TCP_V6:
1354 case SOCKET_TYPE_CHAR_UDP_V6: {
1355 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1357 if ((*len) < sizeof(*in2)) {
1362 memset(in2, 0, sizeof(*in2));
1363 in2->sin6_family = AF_INET6;
1364 in2->sin6_addr = *swrap_ipv6();
1365 in2->sin6_addr.s6_addr[15] = iface;
1366 in2->sin6_port = htons(prt);
1368 *len = sizeof(*in2);
1380 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1388 if (bcast) *bcast = 0;
1390 switch (inaddr->sa_family) {
1392 const struct sockaddr_in *in =
1393 (const struct sockaddr_in *)(const void *)inaddr;
1394 unsigned int addr = ntohl(in->sin_addr.s_addr);
1401 u_type = SOCKET_TYPE_CHAR_TCP;
1404 u_type = SOCKET_TYPE_CHAR_UDP;
1405 a_type = SOCKET_TYPE_CHAR_UDP;
1406 b_type = SOCKET_TYPE_CHAR_UDP;
1409 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1410 errno = ESOCKTNOSUPPORT;
1414 prt = ntohs(in->sin_port);
1415 if (a_type && addr == 0xFFFFFFFF) {
1416 /* 255.255.255.255 only udp */
1419 iface = socket_wrapper_default_iface();
1420 } else if (b_type && addr == 0x7FFFFFFF) {
1421 /* 127.255.255.255 only udp */
1424 iface = socket_wrapper_default_iface();
1425 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1429 iface = (addr & 0x000000FF);
1431 errno = ENETUNREACH;
1434 if (bcast) *bcast = is_bcast;
1439 const struct sockaddr_in6 *in =
1440 (const struct sockaddr_in6 *)(const void *)inaddr;
1441 struct in6_addr cmp1, cmp2;
1445 type = SOCKET_TYPE_CHAR_TCP_V6;
1448 type = SOCKET_TYPE_CHAR_UDP_V6;
1451 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1452 errno = ESOCKTNOSUPPORT;
1456 /* XXX no multicast/broadcast */
1458 prt = ntohs(in->sin6_port);
1460 cmp1 = *swrap_ipv6();
1461 cmp2 = in->sin6_addr;
1462 cmp2.s6_addr[15] = 0;
1463 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1464 iface = in->sin6_addr.s6_addr[15];
1466 errno = ENETUNREACH;
1474 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1475 errno = ENETUNREACH;
1480 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1486 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1487 socket_wrapper_dir());
1488 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1489 /* the caller need to do more processing */
1493 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1494 socket_wrapper_dir(), type, iface, prt);
1495 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1500 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1509 if (bcast) *bcast = 0;
1511 switch (si->family) {
1513 const struct sockaddr_in *in =
1514 (const struct sockaddr_in *)(const void *)inaddr;
1515 unsigned int addr = ntohl(in->sin_addr.s_addr);
1521 prt = ntohs(in->sin_port);
1525 u_type = SOCKET_TYPE_CHAR_TCP;
1526 d_type = SOCKET_TYPE_CHAR_TCP;
1529 u_type = SOCKET_TYPE_CHAR_UDP;
1530 d_type = SOCKET_TYPE_CHAR_UDP;
1531 a_type = SOCKET_TYPE_CHAR_UDP;
1532 b_type = SOCKET_TYPE_CHAR_UDP;
1535 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1536 errno = ESOCKTNOSUPPORT;
1544 iface = socket_wrapper_default_iface();
1545 } else if (a_type && addr == 0xFFFFFFFF) {
1546 /* 255.255.255.255 only udp */
1549 iface = socket_wrapper_default_iface();
1550 } else if (b_type && addr == 0x7FFFFFFF) {
1551 /* 127.255.255.255 only udp */
1554 iface = socket_wrapper_default_iface();
1555 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1559 iface = (addr & 0x000000FF);
1561 errno = EADDRNOTAVAIL;
1565 /* Store the bind address for connect() */
1566 if (si->bindname.sa_socklen == 0) {
1567 struct sockaddr_in bind_in;
1568 socklen_t blen = sizeof(struct sockaddr_in);
1570 ZERO_STRUCT(bind_in);
1571 bind_in.sin_family = in->sin_family;
1572 bind_in.sin_port = in->sin_port;
1573 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1575 si->bindname.sa_socklen = blen;
1576 memcpy(&si->bindname.sa.in, &bind_in, blen);
1583 const struct sockaddr_in6 *in =
1584 (const struct sockaddr_in6 *)(const void *)inaddr;
1585 struct in6_addr cmp1, cmp2;
1589 type = SOCKET_TYPE_CHAR_TCP_V6;
1592 type = SOCKET_TYPE_CHAR_UDP_V6;
1595 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1596 errno = ESOCKTNOSUPPORT;
1600 /* XXX no multicast/broadcast */
1602 prt = ntohs(in->sin6_port);
1604 cmp1 = *swrap_ipv6();
1605 cmp2 = in->sin6_addr;
1606 cmp2.s6_addr[15] = 0;
1607 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1608 iface = socket_wrapper_default_iface();
1609 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1610 iface = in->sin6_addr.s6_addr[15];
1612 errno = EADDRNOTAVAIL;
1616 /* Store the bind address for connect() */
1617 if (si->bindname.sa_socklen == 0) {
1618 struct sockaddr_in6 bind_in;
1619 socklen_t blen = sizeof(struct sockaddr_in6);
1621 ZERO_STRUCT(bind_in);
1622 bind_in.sin6_family = in->sin6_family;
1623 bind_in.sin6_port = in->sin6_port;
1625 bind_in.sin6_addr = *swrap_ipv6();
1626 bind_in.sin6_addr.s6_addr[15] = iface;
1628 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1629 si->bindname.sa_socklen = blen;
1636 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1637 errno = EADDRNOTAVAIL;
1642 if (bcast) *bcast = is_bcast;
1644 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1650 /* handle auto-allocation of ephemeral ports */
1651 for (prt = 5001; prt < 10000; prt++) {
1652 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1653 socket_wrapper_dir(), type, iface, prt);
1654 if (stat(un->sun_path, &st) == 0) continue;
1656 set_port(si->family, prt, &si->myname);
1657 set_port(si->family, prt, &si->bindname);
1667 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1668 socket_wrapper_dir(), type, iface, prt);
1669 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1673 static struct socket_info_fd *find_socket_info_fd(int fd)
1675 struct socket_info_fd *f;
1677 for (f = socket_fds; f; f = f->next) {
1686 static int find_socket_info_index(int fd)
1688 struct socket_info_fd *fi = find_socket_info_fd(fd);
1694 return fi->si_index;
1697 static struct socket_info *find_socket_info(int fd)
1699 int idx = find_socket_info_index(fd);
1705 return &sockets[idx];
1709 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1711 struct socket_info_fd *f;
1712 const struct socket_info *last_s = NULL;
1714 /* first catch invalid input */
1715 switch (sa->sa_family) {
1717 if (len < sizeof(struct sockaddr_in)) {
1723 if (len < sizeof(struct sockaddr_in6)) {
1733 for (f = socket_fds; f; f = f->next) {
1734 struct socket_info *s = &sockets[f->si_index];
1741 if (s->myname == NULL) {
1744 if (s->myname->sa_family != sa->sa_family) {
1747 switch (s->myname->sa_family) {
1749 struct sockaddr_in *sin1, *sin2;
1751 sin1 = (struct sockaddr_in *)s->myname;
1752 sin2 = (struct sockaddr_in *)sa;
1754 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1757 if (sin1->sin_port != sin2->sin_port) {
1760 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1770 struct sockaddr_in6 *sin1, *sin2;
1772 sin1 = (struct sockaddr_in6 *)s->myname;
1773 sin2 = (struct sockaddr_in6 *)sa;
1775 if (sin1->sin6_port != sin2->sin6_port) {
1778 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1800 static void swrap_remove_stale(int fd)
1802 struct socket_info_fd *fi = find_socket_info_fd(fd);
1803 struct socket_info *si;
1810 si_index = fi->si_index;
1812 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1813 SWRAP_DLIST_REMOVE(socket_fds, fi);
1816 si = &sockets[si_index];
1819 if (si->refcount > 0) {
1823 if (si->un_addr.sun_path[0] != '\0') {
1824 unlink(si->un_addr.sun_path);
1827 si->next_free = first_free;
1828 first_free = si_index;
1831 static int sockaddr_convert_to_un(struct socket_info *si,
1832 const struct sockaddr *in_addr,
1834 struct sockaddr_un *out_addr,
1838 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1840 (void) in_len; /* unused */
1842 if (out_addr == NULL) {
1846 out->sa_family = AF_UNIX;
1847 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1848 out->sa_len = sizeof(*out_addr);
1851 switch (in_addr->sa_family) {
1853 const struct sockaddr_in *sin;
1854 if (si->family != AF_INET) {
1857 if (in_len < sizeof(struct sockaddr_in)) {
1860 sin = (const struct sockaddr_in *)(const void *)in_addr;
1861 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1866 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1867 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1881 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1882 errno = ESOCKTNOSUPPORT;
1886 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1888 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1894 errno = EAFNOSUPPORT;
1895 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1899 static int sockaddr_convert_from_un(const struct socket_info *si,
1900 const struct sockaddr_un *in_addr,
1901 socklen_t un_addrlen,
1903 struct sockaddr *out_addr,
1904 socklen_t *out_addrlen)
1908 if (out_addr == NULL || out_addrlen == NULL)
1911 if (un_addrlen == 0) {
1926 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1927 errno = ESOCKTNOSUPPORT;
1930 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1931 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1932 out_addr->sa_len = *out_addrlen;
1939 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1940 errno = EAFNOSUPPORT;
1944 enum swrap_packet_type {
1946 SWRAP_CONNECT_UNREACH,
1954 SWRAP_SENDTO_UNREACH,
1965 struct swrap_file_hdr {
1967 uint16_t version_major;
1968 uint16_t version_minor;
1971 uint32_t frame_max_len;
1972 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1975 #define SWRAP_FILE_HDR_SIZE 24
1977 struct swrap_packet_frame {
1979 uint32_t micro_seconds;
1980 uint32_t recorded_length;
1981 uint32_t full_length;
1983 #define SWRAP_PACKET_FRAME_SIZE 16
1985 union swrap_packet_ip {
1989 uint16_t packet_length;
1990 uint16_t identification;
1995 uint16_t hdr_checksum;
1999 #define SWRAP_PACKET_IP_V4_SIZE 20
2002 uint8_t flow_label_high;
2003 uint16_t flow_label_low;
2004 uint16_t payload_length;
2005 uint8_t next_header;
2007 uint8_t src_addr[16];
2008 uint8_t dest_addr[16];
2010 #define SWRAP_PACKET_IP_V6_SIZE 40
2012 #define SWRAP_PACKET_IP_SIZE 40
2014 union swrap_packet_payload {
2016 uint16_t source_port;
2026 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2028 uint16_t source_port;
2033 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2040 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2047 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2049 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2051 #define SWRAP_PACKET_MIN_ALLOC \
2052 (SWRAP_PACKET_FRAME_SIZE + \
2053 SWRAP_PACKET_IP_SIZE + \
2054 SWRAP_PACKET_PAYLOAD_SIZE)
2056 static const char *swrap_pcap_init_file(void)
2058 static int initialized = 0;
2059 static const char *s = NULL;
2060 static const struct swrap_file_hdr h;
2061 static const struct swrap_packet_frame f;
2062 static const union swrap_packet_ip i;
2063 static const union swrap_packet_payload p;
2065 if (initialized == 1) {
2071 * TODO: don't use the structs use plain buffer offsets
2072 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2074 * for now make sure we disable PCAP support
2075 * if the struct has alignment!
2077 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2080 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2083 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2086 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2089 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2092 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2095 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2098 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2101 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2104 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2108 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2112 if (strncmp(s, "./", 2) == 0) {
2118 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2119 const struct sockaddr *src,
2120 const struct sockaddr *dest,
2122 const uint8_t *payload,
2124 unsigned long tcp_seqno,
2125 unsigned long tcp_ack,
2126 unsigned char tcp_ctl,
2128 size_t *_packet_len)
2132 struct swrap_packet_frame *frame;
2133 union swrap_packet_ip *ip;
2134 union swrap_packet_payload *pay;
2137 size_t nonwire_len = sizeof(*frame);
2138 size_t wire_hdr_len = 0;
2139 size_t wire_len = 0;
2140 size_t ip_hdr_len = 0;
2141 size_t icmp_hdr_len = 0;
2142 size_t icmp_truncate_len = 0;
2143 uint8_t protocol = 0, icmp_protocol = 0;
2144 const struct sockaddr_in *src_in = NULL;
2145 const struct sockaddr_in *dest_in = NULL;
2147 const struct sockaddr_in6 *src_in6 = NULL;
2148 const struct sockaddr_in6 *dest_in6 = NULL;
2153 switch (src->sa_family) {
2155 src_in = (const struct sockaddr_in *)(const void *)src;
2156 dest_in = (const struct sockaddr_in *)(const void *)dest;
2157 src_port = src_in->sin_port;
2158 dest_port = dest_in->sin_port;
2159 ip_hdr_len = sizeof(ip->v4);
2163 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2164 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2165 src_port = src_in6->sin6_port;
2166 dest_port = dest_in6->sin6_port;
2167 ip_hdr_len = sizeof(ip->v6);
2174 switch (socket_type) {
2176 protocol = 0x06; /* TCP */
2177 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2178 wire_len = wire_hdr_len + payload_len;
2182 protocol = 0x11; /* UDP */
2183 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2184 wire_len = wire_hdr_len + payload_len;
2192 icmp_protocol = protocol;
2193 switch (src->sa_family) {
2195 protocol = 0x01; /* ICMPv4 */
2196 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2200 protocol = 0x3A; /* ICMPv6 */
2201 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2205 if (wire_len > 64 ) {
2206 icmp_truncate_len = wire_len - 64;
2208 wire_hdr_len += icmp_hdr_len;
2209 wire_len += icmp_hdr_len;
2212 packet_len = nonwire_len + wire_len;
2213 alloc_len = packet_len;
2214 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2215 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2218 base = (uint8_t *)calloc(1, alloc_len);
2225 frame = (struct swrap_packet_frame *)(void *)buf;
2226 frame->seconds = tval->tv_sec;
2227 frame->micro_seconds = tval->tv_usec;
2228 frame->recorded_length = wire_len - icmp_truncate_len;
2229 frame->full_length = wire_len - icmp_truncate_len;
2230 buf += SWRAP_PACKET_FRAME_SIZE;
2232 ip = (union swrap_packet_ip *)(void *)buf;
2233 switch (src->sa_family) {
2235 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2237 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2238 ip->v4.identification = htons(0xFFFF);
2239 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2240 ip->v4.fragment = htons(0x0000);
2242 ip->v4.protocol = protocol;
2243 ip->v4.hdr_checksum = htons(0x0000);
2244 ip->v4.src_addr = src_in->sin_addr.s_addr;
2245 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2246 buf += SWRAP_PACKET_IP_V4_SIZE;
2250 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2251 ip->v6.flow_label_high = 0x00;
2252 ip->v6.flow_label_low = 0x0000;
2253 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2254 ip->v6.next_header = protocol;
2255 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2256 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2257 buf += SWRAP_PACKET_IP_V6_SIZE;
2263 pay = (union swrap_packet_payload *)(void *)buf;
2264 switch (src->sa_family) {
2266 pay->icmp4.type = 0x03; /* destination unreachable */
2267 pay->icmp4.code = 0x01; /* host unreachable */
2268 pay->icmp4.checksum = htons(0x0000);
2269 pay->icmp4.unused = htonl(0x00000000);
2270 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2272 /* set the ip header in the ICMP payload */
2273 ip = (union swrap_packet_ip *)(void *)buf;
2274 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2276 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2277 ip->v4.identification = htons(0xFFFF);
2278 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2279 ip->v4.fragment = htons(0x0000);
2281 ip->v4.protocol = icmp_protocol;
2282 ip->v4.hdr_checksum = htons(0x0000);
2283 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2284 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2285 buf += SWRAP_PACKET_IP_V4_SIZE;
2287 src_port = dest_in->sin_port;
2288 dest_port = src_in->sin_port;
2292 pay->icmp6.type = 0x01; /* destination unreachable */
2293 pay->icmp6.code = 0x03; /* address unreachable */
2294 pay->icmp6.checksum = htons(0x0000);
2295 pay->icmp6.unused = htonl(0x00000000);
2296 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2298 /* set the ip header in the ICMP payload */
2299 ip = (union swrap_packet_ip *)(void *)buf;
2300 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2301 ip->v6.flow_label_high = 0x00;
2302 ip->v6.flow_label_low = 0x0000;
2303 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2304 ip->v6.next_header = protocol;
2305 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2306 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2307 buf += SWRAP_PACKET_IP_V6_SIZE;
2309 src_port = dest_in6->sin6_port;
2310 dest_port = src_in6->sin6_port;
2316 pay = (union swrap_packet_payload *)(void *)buf;
2318 switch (socket_type) {
2320 pay->tcp.source_port = src_port;
2321 pay->tcp.dest_port = dest_port;
2322 pay->tcp.seq_num = htonl(tcp_seqno);
2323 pay->tcp.ack_num = htonl(tcp_ack);
2324 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2325 pay->tcp.control = tcp_ctl;
2326 pay->tcp.window = htons(0x7FFF);
2327 pay->tcp.checksum = htons(0x0000);
2328 pay->tcp.urg = htons(0x0000);
2329 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2334 pay->udp.source_port = src_port;
2335 pay->udp.dest_port = dest_port;
2336 pay->udp.length = htons(8 + payload_len);
2337 pay->udp.checksum = htons(0x0000);
2338 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2343 if (payload && payload_len > 0) {
2344 memcpy(buf, payload, payload_len);
2347 *_packet_len = packet_len - icmp_truncate_len;
2351 static int swrap_pcap_get_fd(const char *fname)
2359 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2361 struct swrap_file_hdr file_hdr;
2362 file_hdr.magic = 0xA1B2C3D4;
2363 file_hdr.version_major = 0x0002;
2364 file_hdr.version_minor = 0x0004;
2365 file_hdr.timezone = 0x00000000;
2366 file_hdr.sigfigs = 0x00000000;
2367 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2368 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2370 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2377 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2382 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2383 const struct sockaddr *addr,
2384 enum swrap_packet_type type,
2385 const void *buf, size_t len,
2388 const struct sockaddr *src_addr;
2389 const struct sockaddr *dest_addr;
2390 unsigned long tcp_seqno = 0;
2391 unsigned long tcp_ack = 0;
2392 unsigned char tcp_ctl = 0;
2393 int unreachable = 0;
2397 switch (si->family) {
2409 case SWRAP_CONNECT_SEND:
2410 if (si->type != SOCK_STREAM) {
2414 src_addr = &si->myname.sa.s;
2417 tcp_seqno = si->io.pck_snd;
2418 tcp_ack = si->io.pck_rcv;
2419 tcp_ctl = 0x02; /* SYN */
2421 si->io.pck_snd += 1;
2425 case SWRAP_CONNECT_RECV:
2426 if (si->type != SOCK_STREAM) {
2430 dest_addr = &si->myname.sa.s;
2433 tcp_seqno = si->io.pck_rcv;
2434 tcp_ack = si->io.pck_snd;
2435 tcp_ctl = 0x12; /** SYN,ACK */
2437 si->io.pck_rcv += 1;
2441 case SWRAP_CONNECT_UNREACH:
2442 if (si->type != SOCK_STREAM) {
2446 dest_addr = &si->myname.sa.s;
2449 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2450 tcp_seqno = si->io.pck_snd - 1;
2451 tcp_ack = si->io.pck_rcv;
2452 tcp_ctl = 0x02; /* SYN */
2457 case SWRAP_CONNECT_ACK:
2458 if (si->type != SOCK_STREAM) {
2462 src_addr = &si->myname.sa.s;
2465 tcp_seqno = si->io.pck_snd;
2466 tcp_ack = si->io.pck_rcv;
2467 tcp_ctl = 0x10; /* ACK */
2471 case SWRAP_ACCEPT_SEND:
2472 if (si->type != SOCK_STREAM) {
2476 dest_addr = &si->myname.sa.s;
2479 tcp_seqno = si->io.pck_rcv;
2480 tcp_ack = si->io.pck_snd;
2481 tcp_ctl = 0x02; /* SYN */
2483 si->io.pck_rcv += 1;
2487 case SWRAP_ACCEPT_RECV:
2488 if (si->type != SOCK_STREAM) {
2492 src_addr = &si->myname.sa.s;
2495 tcp_seqno = si->io.pck_snd;
2496 tcp_ack = si->io.pck_rcv;
2497 tcp_ctl = 0x12; /* SYN,ACK */
2499 si->io.pck_snd += 1;
2503 case SWRAP_ACCEPT_ACK:
2504 if (si->type != SOCK_STREAM) {
2508 dest_addr = &si->myname.sa.s;
2511 tcp_seqno = si->io.pck_rcv;
2512 tcp_ack = si->io.pck_snd;
2513 tcp_ctl = 0x10; /* ACK */
2518 src_addr = &si->myname.sa.s;
2519 dest_addr = &si->peername.sa.s;
2521 tcp_seqno = si->io.pck_snd;
2522 tcp_ack = si->io.pck_rcv;
2523 tcp_ctl = 0x18; /* PSH,ACK */
2525 si->io.pck_snd += len;
2529 case SWRAP_SEND_RST:
2530 dest_addr = &si->myname.sa.s;
2531 src_addr = &si->peername.sa.s;
2533 if (si->type == SOCK_DGRAM) {
2534 return swrap_pcap_marshall_packet(si,
2536 SWRAP_SENDTO_UNREACH,
2542 tcp_seqno = si->io.pck_rcv;
2543 tcp_ack = si->io.pck_snd;
2544 tcp_ctl = 0x14; /** RST,ACK */
2548 case SWRAP_PENDING_RST:
2549 dest_addr = &si->myname.sa.s;
2550 src_addr = &si->peername.sa.s;
2552 if (si->type == SOCK_DGRAM) {
2556 tcp_seqno = si->io.pck_rcv;
2557 tcp_ack = si->io.pck_snd;
2558 tcp_ctl = 0x14; /* RST,ACK */
2563 dest_addr = &si->myname.sa.s;
2564 src_addr = &si->peername.sa.s;
2566 tcp_seqno = si->io.pck_rcv;
2567 tcp_ack = si->io.pck_snd;
2568 tcp_ctl = 0x18; /* PSH,ACK */
2570 si->io.pck_rcv += len;
2574 case SWRAP_RECV_RST:
2575 dest_addr = &si->myname.sa.s;
2576 src_addr = &si->peername.sa.s;
2578 if (si->type == SOCK_DGRAM) {
2582 tcp_seqno = si->io.pck_rcv;
2583 tcp_ack = si->io.pck_snd;
2584 tcp_ctl = 0x14; /* RST,ACK */
2589 src_addr = &si->myname.sa.s;
2592 si->io.pck_snd += len;
2596 case SWRAP_SENDTO_UNREACH:
2597 dest_addr = &si->myname.sa.s;
2604 case SWRAP_RECVFROM:
2605 dest_addr = &si->myname.sa.s;
2608 si->io.pck_rcv += len;
2612 case SWRAP_CLOSE_SEND:
2613 if (si->type != SOCK_STREAM) {
2617 src_addr = &si->myname.sa.s;
2618 dest_addr = &si->peername.sa.s;
2620 tcp_seqno = si->io.pck_snd;
2621 tcp_ack = si->io.pck_rcv;
2622 tcp_ctl = 0x11; /* FIN, ACK */
2624 si->io.pck_snd += 1;
2628 case SWRAP_CLOSE_RECV:
2629 if (si->type != SOCK_STREAM) {
2633 dest_addr = &si->myname.sa.s;
2634 src_addr = &si->peername.sa.s;
2636 tcp_seqno = si->io.pck_rcv;
2637 tcp_ack = si->io.pck_snd;
2638 tcp_ctl = 0x11; /* FIN,ACK */
2640 si->io.pck_rcv += 1;
2644 case SWRAP_CLOSE_ACK:
2645 if (si->type != SOCK_STREAM) {
2649 src_addr = &si->myname.sa.s;
2650 dest_addr = &si->peername.sa.s;
2652 tcp_seqno = si->io.pck_snd;
2653 tcp_ack = si->io.pck_rcv;
2654 tcp_ctl = 0x10; /* ACK */
2661 swrapGetTimeOfDay(&tv);
2663 return swrap_pcap_packet_init(&tv,
2667 (const uint8_t *)buf,
2676 static void swrap_pcap_dump_packet(struct socket_info *si,
2677 const struct sockaddr *addr,
2678 enum swrap_packet_type type,
2679 const void *buf, size_t len)
2681 const char *file_name;
2683 size_t packet_len = 0;
2686 file_name = swrap_pcap_init_file();
2691 packet = swrap_pcap_marshall_packet(si,
2697 if (packet == NULL) {
2701 fd = swrap_pcap_get_fd(file_name);
2703 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2712 /****************************************************************************
2714 ***************************************************************************/
2716 #ifdef HAVE_SIGNALFD
2717 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2721 rc = libc_signalfd(fd, mask, flags);
2723 swrap_remove_stale(fd);
2729 int signalfd(int fd, const sigset_t *mask, int flags)
2731 return swrap_signalfd(fd, mask, flags);
2735 /****************************************************************************
2737 ***************************************************************************/
2739 static int swrap_socket(int family, int type, int protocol)
2741 struct socket_info *si;
2742 struct socket_info_fd *fi;
2745 int real_type = type;
2748 * Remove possible addition flags passed to socket() so
2749 * do not fail checking the type.
2750 * See https://lwn.net/Articles/281965/
2753 real_type &= ~SOCK_CLOEXEC;
2755 #ifdef SOCK_NONBLOCK
2756 real_type &= ~SOCK_NONBLOCK;
2759 if (!socket_wrapper_enabled()) {
2760 return libc_socket(family, type, protocol);
2771 #endif /* AF_NETLINK */
2774 #endif /* AF_PACKET */
2776 return libc_socket(family, type, protocol);
2778 errno = EAFNOSUPPORT;
2782 switch (real_type) {
2788 errno = EPROTONOSUPPORT;
2796 if (real_type == SOCK_STREAM) {
2801 if (real_type == SOCK_DGRAM) {
2806 errno = EPROTONOSUPPORT;
2811 * We must call libc_socket with type, from the caller, not the version
2812 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2814 fd = libc_socket(AF_UNIX, type, 0);
2820 /* Check if we have a stale fd and remove it */
2821 swrap_remove_stale(fd);
2823 idx = socket_wrapper_first_free_index();
2831 si->family = family;
2833 /* however, the rest of the socket_wrapper code expects just
2834 * the type, not the flags */
2835 si->type = real_type;
2836 si->protocol = protocol;
2839 * Setup myname so getsockname() can succeed to find out the socket
2842 switch(si->family) {
2844 struct sockaddr_in sin = {
2845 .sin_family = AF_INET,
2848 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2849 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2853 struct sockaddr_in6 sin6 = {
2854 .sin6_family = AF_INET6,
2857 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2858 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2866 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2873 first_free = si->next_free;
2879 SWRAP_DLIST_ADD(socket_fds, fi);
2881 SWRAP_LOG(SWRAP_LOG_TRACE,
2882 "Created %s socket for protocol %s",
2883 si->family == AF_INET ? "IPv4" : "IPv6",
2884 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2889 int socket(int family, int type, int protocol)
2891 return swrap_socket(family, type, protocol);
2894 /****************************************************************************
2896 ***************************************************************************/
2898 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2902 rc = libc_socketpair(family, type, protocol, sv);
2904 swrap_remove_stale(sv[0]);
2905 swrap_remove_stale(sv[1]);
2911 int socketpair(int family, int type, int protocol, int sv[2])
2913 return swrap_socketpair(family, type, protocol, sv);
2916 /****************************************************************************
2918 ***************************************************************************/
2920 #ifdef HAVE_TIMERFD_CREATE
2921 static int swrap_timerfd_create(int clockid, int flags)
2925 fd = libc_timerfd_create(clockid, flags);
2927 swrap_remove_stale(fd);
2933 int timerfd_create(int clockid, int flags)
2935 return swrap_timerfd_create(clockid, flags);
2939 /****************************************************************************
2941 ***************************************************************************/
2943 static int swrap_pipe(int pipefd[2])
2947 rc = libc_pipe(pipefd);
2949 swrap_remove_stale(pipefd[0]);
2950 swrap_remove_stale(pipefd[1]);
2956 int pipe(int pipefd[2])
2958 return swrap_pipe(pipefd);
2961 /****************************************************************************
2963 ***************************************************************************/
2965 static int swrap_accept(int s,
2966 struct sockaddr *addr,
2970 struct socket_info *parent_si, *child_si;
2971 struct socket_info_fd *child_fi;
2974 struct swrap_address un_addr = {
2975 .sa_socklen = sizeof(struct sockaddr_un),
2977 struct swrap_address un_my_addr = {
2978 .sa_socklen = sizeof(struct sockaddr_un),
2980 struct swrap_address in_addr = {
2981 .sa_socklen = sizeof(struct sockaddr_storage),
2983 struct swrap_address in_my_addr = {
2984 .sa_socklen = sizeof(struct sockaddr_storage),
2988 parent_si = find_socket_info(s);
2991 return libc_accept4(s, addr, addrlen, flags);
2994 return libc_accept(s, addr, addrlen);
2999 * assume out sockaddr have the same size as the in parent
3002 in_addr.sa_socklen = socket_length(parent_si->family);
3003 if (in_addr.sa_socklen <= 0) {
3009 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3012 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3015 if (errno == ENOTSOCK) {
3016 /* Remove stale fds */
3017 swrap_remove_stale(s);
3024 ret = sockaddr_convert_from_un(parent_si,
3029 &in_addr.sa_socklen);
3035 idx = socket_wrapper_first_free_index();
3041 child_si = &sockets[idx];
3043 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
3044 if (child_fi == NULL) {
3052 child_si->family = parent_si->family;
3053 child_si->type = parent_si->type;
3054 child_si->protocol = parent_si->protocol;
3055 child_si->bound = 1;
3056 child_si->is_server = 1;
3057 child_si->connected = 1;
3059 child_si->peername = (struct swrap_address) {
3060 .sa_socklen = in_addr.sa_socklen,
3062 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3064 if (addr != NULL && addrlen != NULL) {
3065 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3067 memcpy(addr, &in_addr.sa.ss, copy_len);
3069 *addrlen = in_addr.sa_socklen;
3072 ret = libc_getsockname(fd,
3074 &un_my_addr.sa_socklen);
3081 ret = sockaddr_convert_from_un(child_si,
3083 un_my_addr.sa_socklen,
3086 &in_my_addr.sa_socklen);
3093 SWRAP_LOG(SWRAP_LOG_TRACE,
3094 "accept() path=%s, fd=%d",
3095 un_my_addr.sa.un.sun_path, s);
3097 child_si->myname = (struct swrap_address) {
3098 .sa_socklen = in_my_addr.sa_socklen,
3100 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3102 child_si->refcount = 1;
3103 first_free = child_si->next_free;
3104 child_si->next_free = 0;
3106 child_fi->si_index = idx;
3108 SWRAP_DLIST_ADD(socket_fds, child_fi);
3111 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3112 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3113 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3120 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3122 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3126 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3127 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3129 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3132 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3135 static int autobind_start_init;
3136 static int autobind_start;
3138 /* using sendto() or connect() on an unbound socket would give the
3139 recipient no way to reply, as unlike UDP and TCP, a unix domain
3140 socket can't auto-assign ephemeral port numbers, so we need to
3142 Note: this might change the family from ipv6 to ipv4
3144 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3146 struct swrap_address un_addr = {
3147 .sa_socklen = sizeof(struct sockaddr_un),
3155 if (autobind_start_init != 1) {
3156 autobind_start_init = 1;
3157 autobind_start = getpid();
3158 autobind_start %= 50000;
3159 autobind_start += 10000;
3162 un_addr.sa.un.sun_family = AF_UNIX;
3166 struct sockaddr_in in;
3170 type = SOCKET_TYPE_CHAR_TCP;
3173 type = SOCKET_TYPE_CHAR_UDP;
3176 errno = ESOCKTNOSUPPORT;
3181 memset(&in, 0, sizeof(in));
3182 in.sin_family = AF_INET;
3183 in.sin_addr.s_addr = htonl(127<<24 |
3184 socket_wrapper_default_iface());
3186 si->myname = (struct swrap_address) {
3187 .sa_socklen = sizeof(in),
3189 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3194 struct sockaddr_in6 in6;
3196 if (si->family != family) {
3197 errno = ENETUNREACH;
3204 type = SOCKET_TYPE_CHAR_TCP_V6;
3207 type = SOCKET_TYPE_CHAR_UDP_V6;
3210 errno = ESOCKTNOSUPPORT;
3215 memset(&in6, 0, sizeof(in6));
3216 in6.sin6_family = AF_INET6;
3217 in6.sin6_addr = *swrap_ipv6();
3218 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3220 si->myname = (struct swrap_address) {
3221 .sa_socklen = sizeof(in6),
3223 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3228 errno = ESOCKTNOSUPPORT;
3233 if (autobind_start > 60000) {
3234 autobind_start = 10000;
3237 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3238 port = autobind_start + i;
3239 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3240 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3241 type, socket_wrapper_default_iface(), port);
3242 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3244 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3249 si->un_addr = un_addr.sa.un;
3252 autobind_start = port + 1;
3255 if (i == SOCKET_MAX_SOCKETS) {
3256 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3257 "interface "SOCKET_FORMAT,
3260 socket_wrapper_default_iface(),
3267 si->family = family;
3268 set_port(si->family, port, &si->myname);
3276 /****************************************************************************
3278 ***************************************************************************/
3280 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3284 struct swrap_address un_addr = {
3285 .sa_socklen = sizeof(struct sockaddr_un),
3287 struct socket_info *si = find_socket_info(s);
3291 return libc_connect(s, serv_addr, addrlen);
3294 if (si->bound == 0) {
3295 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3301 if (si->family != serv_addr->sa_family) {
3307 ret = sockaddr_convert_to_un(si, serv_addr,
3308 addrlen, &un_addr.sa.un, 0, &bcast);
3314 errno = ENETUNREACH;
3319 if (si->type == SOCK_DGRAM) {
3320 si->defer_connect = 1;
3323 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3325 ret = libc_connect(s,
3327 un_addr.sa_socklen);
3330 SWRAP_LOG(SWRAP_LOG_TRACE,
3331 "connect() path=%s, fd=%d",
3332 un_addr.sa.un.sun_path, s);
3335 /* to give better errors */
3336 if (ret == -1 && errno == ENOENT) {
3337 errno = EHOSTUNREACH;
3341 si->peername = (struct swrap_address) {
3342 .sa_socklen = addrlen,
3345 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3349 * When we connect() on a socket than we have to bind the
3350 * outgoing connection on the interface we use for the
3351 * transport. We already bound it on the right interface
3352 * but here we have to update the name so getsockname()
3353 * returns correct information.
3355 if (si->bindname.sa_socklen > 0) {
3356 si->myname = (struct swrap_address) {
3357 .sa_socklen = si->bindname.sa_socklen,
3360 memcpy(&si->myname.sa.ss,
3361 &si->bindname.sa.ss,
3362 si->bindname.sa_socklen);
3364 /* Cleanup bindname */
3365 si->bindname = (struct swrap_address) {
3370 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3371 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3373 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3380 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3382 return swrap_connect(s, serv_addr, addrlen);
3385 /****************************************************************************
3387 ***************************************************************************/
3389 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3392 struct swrap_address un_addr = {
3393 .sa_socklen = sizeof(struct sockaddr_un),
3395 struct socket_info *si = find_socket_info(s);
3402 return libc_bind(s, myaddr, addrlen);
3405 switch (si->family) {
3407 const struct sockaddr_in *sin;
3408 if (addrlen < sizeof(struct sockaddr_in)) {
3409 bind_error = EINVAL;
3413 sin = (const struct sockaddr_in *)(const void *)myaddr;
3415 if (sin->sin_family != AF_INET) {
3416 bind_error = EAFNOSUPPORT;
3419 /* special case for AF_UNSPEC */
3420 if (sin->sin_family == AF_UNSPEC &&
3421 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3430 const struct sockaddr_in6 *sin6;
3431 if (addrlen < sizeof(struct sockaddr_in6)) {
3432 bind_error = EINVAL;
3436 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3438 if (sin6->sin6_family != AF_INET6) {
3439 bind_error = EAFNOSUPPORT;
3446 bind_error = EINVAL;
3450 if (bind_error != 0) {
3456 in_use = check_addr_port_in_use(myaddr, addrlen);
3463 si->myname.sa_socklen = addrlen;
3464 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3466 ret = sockaddr_convert_to_un(si,
3476 unlink(un_addr.sa.un.sun_path);
3478 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3480 SWRAP_LOG(SWRAP_LOG_TRACE,
3481 "bind() path=%s, fd=%d",
3482 un_addr.sa.un.sun_path, s);
3491 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3493 return swrap_bind(s, myaddr, addrlen);
3496 /****************************************************************************
3498 ***************************************************************************/
3500 #ifdef HAVE_BINDRESVPORT
3501 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3503 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3505 struct swrap_address myaddr = {
3506 .sa_socklen = sizeof(struct sockaddr_storage),
3509 static uint16_t port;
3514 #define SWRAP_STARTPORT 600
3515 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3516 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3519 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3523 salen = myaddr.sa_socklen;
3526 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3532 memset(&myaddr.sa.ss, 0, salen);
3537 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3540 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3542 salen = sizeof(struct sockaddr_in);
3543 sinp->sin_port = htons(port);
3547 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3549 salen = sizeof(struct sockaddr_in6);
3550 sin6p->sin6_port = htons(port);
3554 errno = EAFNOSUPPORT;
3559 if (port > SWRAP_ENDPORT) {
3560 port = SWRAP_STARTPORT;
3563 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3564 if (rc == 0 || errno != EADDRINUSE) {
3572 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3574 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3578 /****************************************************************************
3580 ***************************************************************************/
3582 static int swrap_listen(int s, int backlog)
3585 struct socket_info *si = find_socket_info(s);
3588 return libc_listen(s, backlog);
3591 if (si->bound == 0) {
3592 ret = swrap_auto_bind(s, si, si->family);
3599 ret = libc_listen(s, backlog);
3604 int listen(int s, int backlog)
3606 return swrap_listen(s, backlog);
3609 /****************************************************************************
3611 ***************************************************************************/
3613 static FILE *swrap_fopen(const char *name, const char *mode)
3617 fp = libc_fopen(name, mode);
3619 int fd = fileno(fp);
3621 swrap_remove_stale(fd);
3627 FILE *fopen(const char *name, const char *mode)
3629 return swrap_fopen(name, mode);
3632 /****************************************************************************
3634 ***************************************************************************/
3637 static FILE *swrap_fopen64(const char *name, const char *mode)
3641 fp = libc_fopen64(name, mode);
3643 int fd = fileno(fp);
3645 swrap_remove_stale(fd);
3651 FILE *fopen64(const char *name, const char *mode)
3653 return swrap_fopen64(name, mode);
3655 #endif /* HAVE_FOPEN64 */
3657 /****************************************************************************
3659 ***************************************************************************/
3661 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3665 ret = libc_vopen(pathname, flags, ap);
3668 * There are methods for closing descriptors (libc-internal code
3669 * paths, direct syscalls) which close descriptors in ways that
3670 * we can't intercept, so try to recover when we notice that
3673 swrap_remove_stale(ret);
3678 int open(const char *pathname, int flags, ...)
3683 va_start(ap, flags);
3684 fd = swrap_vopen(pathname, flags, ap);
3690 /****************************************************************************
3692 ***************************************************************************/
3695 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
3699 ret = libc_vopen64(pathname, flags, ap);
3702 * There are methods for closing descriptors (libc-internal code
3703 * paths, direct syscalls) which close descriptors in ways that
3704 * we can't intercept, so try to recover when we notice that
3707 swrap_remove_stale(ret);
3712 int open64(const char *pathname, int flags, ...)
3717 va_start(ap, flags);
3718 fd = swrap_vopen64(pathname, flags, ap);
3723 #endif /* HAVE_OPEN64 */
3725 /****************************************************************************
3727 ***************************************************************************/
3729 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3733 ret = libc_vopenat(dirfd, path, flags, ap);
3736 * There are methods for closing descriptors (libc-internal code
3737 * paths, direct syscalls) which close descriptors in ways that
3738 * we can't intercept, so try to recover when we notice that
3741 swrap_remove_stale(ret);
3747 int openat(int dirfd, const char *path, int flags, ...)
3752 va_start(ap, flags);
3753 fd = swrap_vopenat(dirfd, path, flags, ap);
3759 /****************************************************************************
3761 ***************************************************************************/
3763 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3765 struct socket_info *si = find_socket_info(s);
3769 return libc_getpeername(s, name, addrlen);
3772 if (si->peername.sa_socklen == 0)
3778 len = MIN(*addrlen, si->peername.sa_socklen);
3783 memcpy(name, &si->peername.sa.ss, len);
3784 *addrlen = si->peername.sa_socklen;
3789 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3790 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3792 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3795 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3798 /****************************************************************************
3800 ***************************************************************************/
3802 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3804 struct socket_info *si = find_socket_info(s);
3808 return libc_getsockname(s, name, addrlen);
3811 len = MIN(*addrlen, si->myname.sa_socklen);
3816 memcpy(name, &si->myname.sa.ss, len);
3817 *addrlen = si->myname.sa_socklen;
3822 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3823 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3825 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3828 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3831 /****************************************************************************
3833 ***************************************************************************/
3836 # ifdef SO_PROTOTYPE /* The Solaris name */
3837 # define SO_PROTOCOL SO_PROTOTYPE
3838 # endif /* SO_PROTOTYPE */
3839 #endif /* SO_PROTOCOL */
3841 static int swrap_getsockopt(int s, int level, int optname,
3842 void *optval, socklen_t *optlen)
3844 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)) {
3864 *optlen = sizeof(int);
3865 *(int *)optval = si->family;
3867 #endif /* SO_DOMAIN */
3871 if (optval == NULL || optlen == NULL ||
3872 *optlen < (socklen_t)sizeof(int)) {
3877 *optlen = sizeof(int);
3878 *(int *)optval = si->protocol;
3880 #endif /* SO_PROTOCOL */
3882 if (optval == NULL || optlen == NULL ||
3883 *optlen < (socklen_t)sizeof(int)) {
3888 *optlen = sizeof(int);
3889 *(int *)optval = si->type;
3892 return libc_getsockopt(s,
3898 } else if (level == IPPROTO_TCP) {
3903 * This enables sending packets directly out over TCP.
3904 * As a unix socket is doing that any way, report it as
3907 if (optval == NULL || optlen == NULL ||
3908 *optlen < (socklen_t)sizeof(int)) {
3913 *optlen = sizeof(int);
3914 *(int *)optval = si->tcp_nodelay;
3917 #endif /* TCP_NODELAY */
3923 errno = ENOPROTOOPT;
3927 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3928 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3930 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3933 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3936 /****************************************************************************
3938 ***************************************************************************/
3940 static int swrap_setsockopt(int s, int level, int optname,
3941 const void *optval, socklen_t optlen)
3943 struct socket_info *si = find_socket_info(s);
3946 return libc_setsockopt(s,
3953 if (level == SOL_SOCKET) {
3954 return libc_setsockopt(s,
3959 } else if (level == IPPROTO_TCP) {
3966 * This enables sending packets directly out over TCP.
3967 * A unix socket is doing that any way.
3969 if (optval == NULL || optlen == 0 ||
3970 optlen < (socklen_t)sizeof(int)) {
3975 i = *discard_const_p(int, optval);
3976 if (i != 0 && i != 1) {
3980 si->tcp_nodelay = i;
3984 #endif /* TCP_NODELAY */
3990 switch (si->family) {
3992 if (level == IPPROTO_IP) {
3994 if (optname == IP_PKTINFO) {
3995 si->pktinfo = AF_INET;
3997 #endif /* IP_PKTINFO */
4002 if (level == IPPROTO_IPV6) {
4003 #ifdef IPV6_RECVPKTINFO
4004 if (optname == IPV6_RECVPKTINFO) {
4005 si->pktinfo = AF_INET6;
4007 #endif /* IPV6_PKTINFO */
4012 errno = ENOPROTOOPT;
4017 int setsockopt(int s, int level, int optname,
4018 const void *optval, socklen_t optlen)
4020 return swrap_setsockopt(s, level, optname, optval, optlen);
4023 /****************************************************************************
4025 ***************************************************************************/
4027 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4029 struct socket_info *si = find_socket_info(s);
4035 return libc_vioctl(s, r, va);
4040 rc = libc_vioctl(s, r, va);
4044 value = *((int *)va_arg(ap, int *));
4046 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4047 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4048 } else if (value == 0) { /* END OF FILE */
4049 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4059 #ifdef HAVE_IOCTL_INT
4060 int ioctl(int s, int r, ...)
4062 int ioctl(int s, unsigned long int r, ...)
4070 rc = swrap_vioctl(s, (unsigned long int) r, va);
4081 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4084 # ifdef _ALIGN /* BSD */
4085 #define CMSG_ALIGN _ALIGN
4087 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4088 # endif /* _ALIGN */
4089 #endif /* CMSG_ALIGN */
4092 * @brief Add a cmsghdr to a msghdr.
4094 * This is an function to add any type of cmsghdr. It will operate on the
4095 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4096 * the buffer position after the added cmsg element. Hence, this function is
4097 * intended to be used with an intermediate msghdr and not on the original
4098 * one handed in by the client.
4100 * @param[in] msg The msghdr to which to add the cmsg.
4102 * @param[in] level The cmsg level to set.
4104 * @param[in] type The cmsg type to set.
4106 * @param[in] data The cmsg data to set.
4108 * @param[in] len the length of the data to set.
4110 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4116 size_t cmlen = CMSG_LEN(len);
4117 size_t cmspace = CMSG_SPACE(len);
4118 uint8_t cmbuf[cmspace];
4119 void *cast_ptr = (void *)cmbuf;
4120 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4123 memset(cmbuf, 0, cmspace);
4125 if (msg->msg_controllen < cmlen) {
4126 cmlen = msg->msg_controllen;
4127 msg->msg_flags |= MSG_CTRUNC;
4130 if (msg->msg_controllen < cmspace) {
4131 cmspace = msg->msg_controllen;
4135 * We copy the full input data into an intermediate cmsghdr first
4136 * in order to more easily cope with truncation.
4138 cm->cmsg_len = cmlen;
4139 cm->cmsg_level = level;
4140 cm->cmsg_type = type;
4141 memcpy(CMSG_DATA(cm), data, len);
4144 * We now copy the possibly truncated buffer.
4145 * We copy cmlen bytes, but consume cmspace bytes,
4146 * leaving the possible padding uninitialiazed.
4148 p = (uint8_t *)msg->msg_control;
4149 memcpy(p, cm, cmlen);
4151 msg->msg_control = p;
4152 msg->msg_controllen -= cmspace;
4157 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4160 /* Add packet info */
4161 switch (si->pktinfo) {
4162 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4164 struct sockaddr_in *sin;
4165 #if defined(HAVE_STRUCT_IN_PKTINFO)
4166 struct in_pktinfo pkt;
4167 #elif defined(IP_RECVDSTADDR)
4171 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4172 sin = &si->bindname.sa.in;
4174 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4177 sin = &si->myname.sa.in;
4182 #if defined(HAVE_STRUCT_IN_PKTINFO)
4183 pkt.ipi_ifindex = socket_wrapper_default_iface();
4184 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4185 #elif defined(IP_RECVDSTADDR)
4186 pkt = sin->sin_addr;
4189 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4194 #endif /* IP_PKTINFO */
4195 #if defined(HAVE_IPV6)
4197 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4198 struct sockaddr_in6 *sin6;
4199 struct in6_pktinfo pkt6;
4201 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4202 sin6 = &si->bindname.sa.in6;
4204 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4207 sin6 = &si->myname.sa.in6;
4212 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4213 pkt6.ipi6_addr = sin6->sin6_addr;
4215 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4216 &pkt6, sizeof(pkt6));
4217 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4221 #endif /* IPV6_PKTINFO */
4229 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4230 struct msghdr *omsg)
4234 if (si->pktinfo > 0) {
4235 rc = swrap_msghdr_add_pktinfo(si, omsg);
4241 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4243 size_t *cm_data_space);
4244 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4246 size_t *cm_data_space);
4248 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4250 size_t *cm_data_space) {
4251 struct cmsghdr *cmsg;
4255 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4259 for (cmsg = CMSG_FIRSTHDR(msg);
4261 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4262 switch (cmsg->cmsg_level) {
4264 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4269 rc = swrap_sendmsg_copy_cmsg(cmsg,
4279 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4281 size_t *cm_data_space)
4286 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4288 p = realloc((*cm_data), cmspace);
4294 p = (*cm_data) + (*cm_data_space);
4295 *cm_data_space = cmspace;
4297 memcpy(p, cmsg, cmsg->cmsg_len);
4302 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4304 size_t *cm_data_space);
4307 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4309 size_t *cm_data_space)
4313 switch(cmsg->cmsg_type) {
4316 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4323 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4335 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4337 size_t *cm_data_space)
4339 (void)cmsg; /* unused */
4340 (void)cm_data; /* unused */
4341 (void)cm_data_space; /* unused */
4344 * Passing a IP pktinfo to a unix socket might be rejected by the
4345 * Kernel, at least on FreeBSD. So skip this cmsg.
4349 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4351 static ssize_t swrap_sendmsg_before(int fd,
4352 struct socket_info *si,
4354 struct iovec *tmp_iov,
4355 struct sockaddr_un *tmp_un,
4356 const struct sockaddr_un **to_un,
4357 const struct sockaddr **to,
4377 if (!si->connected) {
4382 if (msg->msg_iovlen == 0) {
4386 mtu = socket_wrapper_mtu();
4387 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4389 nlen = len + msg->msg_iov[i].iov_len;
4394 msg->msg_iovlen = i;
4395 if (msg->msg_iovlen == 0) {
4396 *tmp_iov = msg->msg_iov[0];
4397 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4399 msg->msg_iov = tmp_iov;
4400 msg->msg_iovlen = 1;
4405 if (si->connected) {
4406 if (msg->msg_name != NULL) {
4408 * We are dealing with unix sockets and if we
4409 * are connected, we should only talk to the
4410 * connected unix path. Using the fd to send
4411 * to another server would be hard to achieve.
4413 msg->msg_name = NULL;
4414 msg->msg_namelen = 0;
4417 const struct sockaddr *msg_name;
4418 msg_name = (const struct sockaddr *)msg->msg_name;
4420 if (msg_name == NULL) {
4426 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4438 msg->msg_name = tmp_un;
4439 msg->msg_namelen = sizeof(*tmp_un);
4442 if (si->bound == 0) {
4443 ret = swrap_auto_bind(fd, si, si->family);
4445 if (errno == ENOTSOCK) {
4446 swrap_remove_stale(fd);
4449 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4455 if (!si->defer_connect) {
4459 ret = sockaddr_convert_to_un(si,
4461 si->peername.sa_socklen,
4469 ret = libc_connect(fd,
4470 (struct sockaddr *)(void *)tmp_un,
4473 /* to give better errors */
4474 if (ret == -1 && errno == ENOENT) {
4475 errno = EHOSTUNREACH;
4482 si->defer_connect = 0;
4485 errno = EHOSTUNREACH;
4489 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4490 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4491 uint8_t *cmbuf = NULL;
4494 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4501 msg->msg_controllen = 0;
4502 msg->msg_control = NULL;
4503 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4504 memcpy(msg->msg_control, cmbuf, cmlen);
4505 msg->msg_controllen = cmlen;
4514 static void swrap_sendmsg_after(int fd,
4515 struct socket_info *si,
4517 const struct sockaddr *to,
4520 int saved_errno = errno;
4527 /* to give better errors */
4529 if (saved_errno == ENOENT) {
4530 saved_errno = EHOSTUNREACH;
4531 } else if (saved_errno == ENOTSOCK) {
4532 /* If the fd is not a socket, remove it */
4533 swrap_remove_stale(fd);
4537 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4538 avail += msg->msg_iov[i].iov_len;
4542 remain = MIN(80, avail);
4547 /* we capture it as one single packet */
4548 buf = (uint8_t *)malloc(remain);
4550 /* we just not capture the packet */
4551 errno = saved_errno;
4555 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4556 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4558 msg->msg_iov[i].iov_base,
4561 remain -= this_time;
4568 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4569 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4571 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4576 if (si->connected) {
4577 to = &si->peername.sa.s;
4580 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4581 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4583 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4589 errno = saved_errno;
4592 static int swrap_recvmsg_before(int fd,
4593 struct socket_info *si,
4595 struct iovec *tmp_iov)
4600 (void)fd; /* unused */
4605 if (!si->connected) {
4610 if (msg->msg_iovlen == 0) {
4614 mtu = socket_wrapper_mtu();
4615 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4617 nlen = len + msg->msg_iov[i].iov_len;
4622 msg->msg_iovlen = i;
4623 if (msg->msg_iovlen == 0) {
4624 *tmp_iov = msg->msg_iov[0];
4625 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4627 msg->msg_iov = tmp_iov;
4628 msg->msg_iovlen = 1;
4633 if (msg->msg_name == NULL) {
4638 if (msg->msg_iovlen == 0) {
4642 if (si->bound == 0) {
4643 ret = swrap_auto_bind(fd, si, si->family);
4646 * When attempting to read or write to a
4647 * descriptor, if an underlying autobind fails
4648 * because it's not a socket, stop intercepting
4649 * uses of that descriptor.
4651 if (errno == ENOTSOCK) {
4652 swrap_remove_stale(fd);
4655 SWRAP_LOG(SWRAP_LOG_ERROR,
4656 "swrap_recvmsg_before failed");
4663 errno = EHOSTUNREACH;
4670 static int swrap_recvmsg_after(int fd,
4671 struct socket_info *si,
4673 const struct sockaddr_un *un_addr,
4674 socklen_t un_addrlen,
4677 int saved_errno = errno;
4679 uint8_t *buf = NULL;
4685 /* to give better errors */
4687 if (saved_errno == ENOENT) {
4688 saved_errno = EHOSTUNREACH;
4689 } else if (saved_errno == ENOTSOCK) {
4690 /* If the fd is not a socket, remove it */
4691 swrap_remove_stale(fd);
4695 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4696 avail += msg->msg_iov[i].iov_len;
4699 /* Convert the socket address before we leave */
4700 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4701 rc = sockaddr_convert_from_un(si,
4718 remain = MIN(80, avail);
4723 /* we capture it as one single packet */
4724 buf = (uint8_t *)malloc(remain);
4726 /* we just not capture the packet */
4727 errno = saved_errno;
4731 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4732 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4734 msg->msg_iov[i].iov_base,
4737 remain -= this_time;
4742 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4743 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4744 } else if (ret == 0) { /* END OF FILE */
4745 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4746 } else if (ret > 0) {
4747 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4756 if (un_addr != NULL) {
4757 swrap_pcap_dump_packet(si,
4763 swrap_pcap_dump_packet(si,
4776 errno = saved_errno;
4778 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4780 msg->msg_controllen > 0 &&
4781 msg->msg_control != NULL) {
4782 rc = swrap_msghdr_add_socket_info(si, msg);
4792 /****************************************************************************
4794 ***************************************************************************/
4796 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4797 struct sockaddr *from, socklen_t *fromlen)
4799 struct swrap_address from_addr = {
4800 .sa_socklen = sizeof(struct sockaddr_un),
4803 struct socket_info *si = find_socket_info(s);
4804 struct swrap_address saddr = {
4805 .sa_socklen = sizeof(struct sockaddr_storage),
4812 return libc_recvfrom(s,
4824 if (from != NULL && fromlen != NULL) {
4825 msg.msg_name = from; /* optional address */
4826 msg.msg_namelen = *fromlen; /* size of address */
4828 msg.msg_name = &saddr.sa.s; /* optional address */
4829 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4831 msg.msg_iov = &tmp; /* scatter/gather array */
4832 msg.msg_iovlen = 1; /* # elements in msg_iov */
4833 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4834 msg.msg_control = NULL; /* ancillary data, see below */
4835 msg.msg_controllen = 0; /* ancillary data buffer len */
4836 msg.msg_flags = 0; /* flags on received message */
4839 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4844 buf = msg.msg_iov[0].iov_base;
4845 len = msg.msg_iov[0].iov_len;
4847 ret = libc_recvfrom(s,
4852 &from_addr.sa_socklen);
4857 tret = swrap_recvmsg_after(s,
4861 from_addr.sa_socklen,
4867 if (from != NULL && fromlen != NULL) {
4868 *fromlen = msg.msg_namelen;
4874 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4875 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4876 struct sockaddr *from, Psocklen_t fromlen)
4878 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4879 struct sockaddr *from, socklen_t *fromlen)
4882 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4885 /****************************************************************************
4887 ***************************************************************************/
4889 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4890 const struct sockaddr *to, socklen_t tolen)
4894 struct swrap_address un_addr = {
4895 .sa_socklen = sizeof(struct sockaddr_un),
4897 const struct sockaddr_un *to_un = NULL;
4900 struct socket_info *si = find_socket_info(s);
4904 return libc_sendto(s, buf, len, flags, to, tolen);
4907 tmp.iov_base = discard_const_p(char, buf);
4911 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4912 msg.msg_namelen = tolen; /* size of address */
4913 msg.msg_iov = &tmp; /* scatter/gather array */
4914 msg.msg_iovlen = 1; /* # elements in msg_iov */
4915 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4916 msg.msg_control = NULL; /* ancillary data, see below */
4917 msg.msg_controllen = 0; /* ancillary data buffer len */
4918 msg.msg_flags = 0; /* flags on received message */
4921 rc = swrap_sendmsg_before(s,
4933 buf = msg.msg_iov[0].iov_base;
4934 len = msg.msg_iov[0].iov_len;
4939 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4942 type = SOCKET_TYPE_CHAR_UDP;
4944 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4945 snprintf(un_addr.sa.un.sun_path,
4946 sizeof(un_addr.sa.un.sun_path),
4948 socket_wrapper_dir(), type, iface, prt);
4949 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4951 /* ignore the any errors in broadcast sends */
4957 un_addr.sa_socklen);
4960 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4966 * If it is a dgram socket and we are connected, don't include the
4969 if (si->type == SOCK_DGRAM && si->connected) {
4970 ret = libc_sendto(s,
4977 ret = libc_sendto(s,
4981 (struct sockaddr *)msg.msg_name,
4985 swrap_sendmsg_after(s, si, &msg, to, ret);
4990 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4991 const struct sockaddr *to, socklen_t tolen)
4993 return swrap_sendto(s, buf, len, flags, to, tolen);
4996 /****************************************************************************
4998 ***************************************************************************/
5000 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5002 struct socket_info *si;
5004 struct swrap_address saddr = {
5005 .sa_socklen = sizeof(struct sockaddr_storage),
5011 si = find_socket_info(s);
5013 return libc_recv(s, buf, len, flags);
5020 msg.msg_name = &saddr.sa.s; /* optional address */
5021 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5022 msg.msg_iov = &tmp; /* scatter/gather array */
5023 msg.msg_iovlen = 1; /* # elements in msg_iov */
5024 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5025 msg.msg_control = NULL; /* ancillary data, see below */
5026 msg.msg_controllen = 0; /* ancillary data buffer len */
5027 msg.msg_flags = 0; /* flags on received message */
5030 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5035 buf = msg.msg_iov[0].iov_base;
5036 len = msg.msg_iov[0].iov_len;
5038 ret = libc_recv(s, buf, len, flags);
5040 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5048 ssize_t recv(int s, void *buf, size_t len, int flags)
5050 return swrap_recv(s, buf, len, flags);
5053 /****************************************************************************
5055 ***************************************************************************/
5057 static ssize_t swrap_read(int s, void *buf, size_t len)
5059 struct socket_info *si;
5062 struct swrap_address saddr = {
5063 .sa_socklen = sizeof(struct sockaddr_storage),
5068 si = find_socket_info(s);
5070 return libc_read(s, buf, len);
5077 msg.msg_name = &saddr.sa.ss; /* optional address */
5078 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5079 msg.msg_iov = &tmp; /* scatter/gather array */
5080 msg.msg_iovlen = 1; /* # elements in msg_iov */
5081 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5082 msg.msg_control = NULL; /* ancillary data, see below */
5083 msg.msg_controllen = 0; /* ancillary data buffer len */
5084 msg.msg_flags = 0; /* flags on received message */
5087 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5089 if (tret == -ENOTSOCK) {
5090 return libc_read(s, buf, len);
5095 buf = msg.msg_iov[0].iov_base;
5096 len = msg.msg_iov[0].iov_len;
5098 ret = libc_read(s, buf, len);
5100 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5108 ssize_t read(int s, void *buf, size_t len)
5110 return swrap_read(s, buf, len);
5113 /****************************************************************************
5115 ***************************************************************************/
5117 static ssize_t swrap_write(int s, const void *buf, size_t len)
5121 struct sockaddr_un un_addr;
5124 struct socket_info *si;
5126 si = find_socket_info(s);
5128 return libc_write(s, buf, len);
5131 tmp.iov_base = discard_const_p(char, buf);
5135 msg.msg_name = NULL; /* optional address */
5136 msg.msg_namelen = 0; /* size of address */
5137 msg.msg_iov = &tmp; /* scatter/gather array */
5138 msg.msg_iovlen = 1; /* # elements in msg_iov */
5139 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5140 msg.msg_control = NULL; /* ancillary data, see below */
5141 msg.msg_controllen = 0; /* ancillary data buffer len */
5142 msg.msg_flags = 0; /* flags on received message */
5145 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5150 buf = msg.msg_iov[0].iov_base;
5151 len = msg.msg_iov[0].iov_len;
5153 ret = libc_write(s, buf, len);
5155 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5160 ssize_t write(int s, const void *buf, size_t len)
5162 return swrap_write(s, buf, len);
5165 /****************************************************************************
5167 ***************************************************************************/
5169 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5173 struct sockaddr_un un_addr;
5176 struct socket_info *si = find_socket_info(s);
5179 return libc_send(s, buf, len, flags);
5182 tmp.iov_base = discard_const_p(char, buf);
5186 msg.msg_name = NULL; /* optional address */
5187 msg.msg_namelen = 0; /* size of address */
5188 msg.msg_iov = &tmp; /* scatter/gather array */
5189 msg.msg_iovlen = 1; /* # elements in msg_iov */
5190 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5191 msg.msg_control = NULL; /* ancillary data, see below */
5192 msg.msg_controllen = 0; /* ancillary data buffer len */
5193 msg.msg_flags = 0; /* flags on received message */
5196 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5201 buf = msg.msg_iov[0].iov_base;
5202 len = msg.msg_iov[0].iov_len;
5204 ret = libc_send(s, buf, len, flags);
5206 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5211 ssize_t send(int s, const void *buf, size_t len, int flags)
5213 return swrap_send(s, buf, len, flags);
5216 /****************************************************************************
5218 ***************************************************************************/
5220 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5222 struct swrap_address from_addr = {
5223 .sa_socklen = sizeof(struct sockaddr_un),
5225 struct swrap_address convert_addr = {
5226 .sa_socklen = sizeof(struct sockaddr_storage),
5228 struct socket_info *si;
5231 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5232 size_t msg_ctrllen_filled;
5233 size_t msg_ctrllen_left;
5239 si = find_socket_info(s);
5241 return libc_recvmsg(s, omsg, flags);
5244 tmp.iov_base = NULL;
5248 msg.msg_name = &from_addr.sa; /* optional address */
5249 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5250 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5251 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5252 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5253 msg_ctrllen_filled = 0;
5254 msg_ctrllen_left = omsg->msg_controllen;
5256 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5257 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5258 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5261 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5266 ret = libc_recvmsg(s, &msg, flags);
5268 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5269 msg_ctrllen_filled += msg.msg_controllen;
5270 msg_ctrllen_left -= msg.msg_controllen;
5272 if (omsg->msg_control != NULL) {
5275 p = omsg->msg_control;
5276 p += msg_ctrllen_filled;
5278 msg.msg_control = p;
5279 msg.msg_controllen = msg_ctrllen_left;
5281 msg.msg_control = NULL;
5282 msg.msg_controllen = 0;
5287 * We convert the unix address to a IP address so we need a buffer
5288 * which can store the address in case of SOCK_DGRAM, see below.
5290 msg.msg_name = &convert_addr.sa;
5291 msg.msg_namelen = convert_addr.sa_socklen;
5293 rc = swrap_recvmsg_after(s,
5297 from_addr.sa_socklen,
5303 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5304 if (omsg->msg_control != NULL) {
5305 /* msg.msg_controllen = space left */
5306 msg_ctrllen_left = msg.msg_controllen;
5307 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5310 /* Update the original message length */
5311 omsg->msg_controllen = msg_ctrllen_filled;
5312 omsg->msg_flags = msg.msg_flags;
5314 omsg->msg_iovlen = msg.msg_iovlen;
5319 * The msg_name field points to a caller-allocated buffer that is
5320 * used to return the source address if the socket is unconnected. The
5321 * caller should set msg_namelen to the size of this buffer before this
5322 * call; upon return from a successful call, msg_name will contain the
5323 * length of the returned address. If the application does not need
5324 * to know the source address, msg_name can be specified as NULL.
5326 if (si->type == SOCK_STREAM) {
5327 omsg->msg_namelen = 0;
5328 } else if (omsg->msg_name != NULL &&
5329 omsg->msg_namelen != 0 &&
5330 omsg->msg_namelen >= msg.msg_namelen) {
5331 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5332 omsg->msg_namelen = msg.msg_namelen;
5338 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5340 return swrap_recvmsg(sockfd, msg, flags);
5343 /****************************************************************************
5345 ***************************************************************************/
5347 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5351 struct sockaddr_un un_addr;
5352 const struct sockaddr_un *to_un = NULL;
5353 const struct sockaddr *to = NULL;
5356 struct socket_info *si = find_socket_info(s);
5360 return libc_sendmsg(s, omsg, flags);
5363 ZERO_STRUCT(un_addr);
5365 tmp.iov_base = NULL;
5370 if (si->connected == 0) {
5371 msg.msg_name = omsg->msg_name; /* optional address */
5372 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5374 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5375 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5376 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5377 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5378 /* omsg is a const so use a local buffer for modifications */
5379 uint8_t cmbuf[omsg->msg_controllen];
5381 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5383 msg.msg_control = cmbuf; /* ancillary data, see below */
5384 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5386 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5389 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5397 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5405 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5406 avail += msg.msg_iov[i].iov_len;
5412 /* we capture it as one single packet */
5413 buf = (uint8_t *)malloc(remain);
5418 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5419 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5421 msg.msg_iov[i].iov_base,
5424 remain -= this_time;
5427 type = SOCKET_TYPE_CHAR_UDP;
5429 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5430 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5431 socket_wrapper_dir(), type, iface, prt);
5432 if (stat(un_addr.sun_path, &st) != 0) continue;
5434 msg.msg_name = &un_addr; /* optional address */
5435 msg.msg_namelen = sizeof(un_addr); /* size of address */
5437 /* ignore the any errors in broadcast sends */
5438 libc_sendmsg(s, &msg, flags);
5441 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5447 ret = libc_sendmsg(s, &msg, flags);
5449 swrap_sendmsg_after(s, si, &msg, to, ret);
5454 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5456 return swrap_sendmsg(s, omsg, flags);
5459 /****************************************************************************
5461 ***************************************************************************/
5463 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5465 struct socket_info *si;
5468 struct swrap_address saddr = {
5469 .sa_socklen = sizeof(struct sockaddr_storage)
5474 si = find_socket_info(s);
5476 return libc_readv(s, vector, count);
5479 tmp.iov_base = NULL;
5483 msg.msg_name = &saddr.sa.s; /* optional address */
5484 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5485 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5486 msg.msg_iovlen = count; /* # elements in msg_iov */
5487 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5488 msg.msg_control = NULL; /* ancillary data, see below */
5489 msg.msg_controllen = 0; /* ancillary data buffer len */
5490 msg.msg_flags = 0; /* flags on received message */
5493 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5495 if (rc == -ENOTSOCK) {
5496 return libc_readv(s, vector, count);
5501 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5503 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5511 ssize_t readv(int s, const struct iovec *vector, int count)
5513 return swrap_readv(s, vector, count);
5516 /****************************************************************************
5518 ***************************************************************************/
5520 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5524 struct sockaddr_un un_addr;
5527 struct socket_info *si = find_socket_info(s);
5530 return libc_writev(s, vector, count);
5533 tmp.iov_base = NULL;
5537 msg.msg_name = NULL; /* optional address */
5538 msg.msg_namelen = 0; /* size of address */
5539 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5540 msg.msg_iovlen = count; /* # elements in msg_iov */
5541 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5542 msg.msg_control = NULL; /* ancillary data, see below */
5543 msg.msg_controllen = 0; /* ancillary data buffer len */
5544 msg.msg_flags = 0; /* flags on received message */
5547 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5549 if (rc == -ENOTSOCK) {
5550 return libc_readv(s, vector, count);
5555 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5557 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5562 ssize_t writev(int s, const struct iovec *vector, int count)
5564 return swrap_writev(s, vector, count);
5567 /****************************
5569 ***************************/
5571 static int swrap_close(int fd)
5573 struct socket_info_fd *fi = find_socket_info_fd(fd);
5574 struct socket_info *si = NULL;
5579 return libc_close(fd);
5582 si_index = fi->si_index;
5584 SWRAP_DLIST_REMOVE(socket_fds, fi);
5587 ret = libc_close(fd);
5589 si = &sockets[si_index];
5592 if (si->refcount > 0) {
5593 /* there are still references left */
5597 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5598 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5601 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5602 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5603 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5606 if (si->un_addr.sun_path[0] != '\0') {
5607 unlink(si->un_addr.sun_path);
5610 si->next_free = first_free;
5611 first_free = si_index;
5618 return swrap_close(fd);
5621 /****************************
5623 ***************************/
5625 static int swrap_dup(int fd)
5627 struct socket_info *si;
5628 struct socket_info_fd *src_fi, *fi;
5630 src_fi = find_socket_info_fd(fd);
5631 if (src_fi == NULL) {
5632 return libc_dup(fd);
5635 si = &sockets[src_fi->si_index];
5637 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5643 fi->fd = libc_dup(fd);
5645 int saved_errno = errno;
5647 errno = saved_errno;
5652 fi->si_index = src_fi->si_index;
5654 /* Make sure we don't have an entry for the fd */
5655 swrap_remove_stale(fi->fd);
5657 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5663 return swrap_dup(fd);
5666 /****************************
5668 ***************************/
5670 static int swrap_dup2(int fd, int newfd)
5672 struct socket_info *si;
5673 struct socket_info_fd *src_fi, *fi;
5675 src_fi = find_socket_info_fd(fd);
5676 if (src_fi == NULL) {
5677 return libc_dup2(fd, newfd);
5680 si = &sockets[src_fi->si_index];
5684 * According to the manpage:
5686 * "If oldfd is a valid file descriptor, and newfd has the same
5687 * value as oldfd, then dup2() does nothing, and returns newfd."
5692 if (find_socket_info(newfd)) {
5693 /* dup2() does an implicit close of newfd, which we
5694 * need to emulate */
5698 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5704 fi->fd = libc_dup2(fd, newfd);
5706 int saved_errno = errno;
5708 errno = saved_errno;
5713 fi->si_index = src_fi->si_index;
5715 /* Make sure we don't have an entry for the fd */
5716 swrap_remove_stale(fi->fd);
5718 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5722 int dup2(int fd, int newfd)
5724 return swrap_dup2(fd, newfd);
5727 /****************************
5729 ***************************/
5731 static int swrap_vfcntl(int fd, int cmd, va_list va)
5733 struct socket_info_fd *src_fi, *fi;
5734 struct socket_info *si;
5737 src_fi = find_socket_info_fd(fd);
5738 if (src_fi == NULL) {
5739 return libc_vfcntl(fd, cmd, va);
5742 si = &sockets[src_fi->si_index];
5746 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5752 fi->fd = libc_vfcntl(fd, cmd, va);
5754 int saved_errno = errno;
5756 errno = saved_errno;
5761 fi->si_index = src_fi->si_index;
5763 /* Make sure we don't have an entry for the fd */
5764 swrap_remove_stale(fi->fd);
5766 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5771 rc = libc_vfcntl(fd, cmd, va);
5778 int fcntl(int fd, int cmd, ...)
5785 rc = swrap_vfcntl(fd, cmd, va);
5792 /****************************
5794 ***************************/
5797 static int swrap_eventfd(int count, int flags)
5801 fd = libc_eventfd(count, flags);
5803 swrap_remove_stale(fd);
5809 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5810 int eventfd(unsigned int count, int flags)
5812 int eventfd(int count, int flags)
5815 return swrap_eventfd(count, flags);
5820 int pledge(const char *promises, const char *paths[])
5822 (void)promises; /* unused */
5823 (void)paths; /* unused */
5827 #endif /* HAVE_PLEDGE */
5829 static void swrap_thread_prepare(void)
5834 static void swrap_thread_parent(void)
5839 static void swrap_thread_child(void)
5844 /****************************
5846 ***************************/
5847 void swrap_constructor(void)
5850 * If we hold a lock and the application forks, then the child
5851 * is not able to unlock the mutex and we are in a deadlock.
5852 * This should prevent such deadlocks.
5854 pthread_atfork(&swrap_thread_prepare,
5855 &swrap_thread_parent,
5856 &swrap_thread_child);
5859 /****************************
5861 ***************************/
5864 * This function is called when the library is unloaded and makes sure that
5865 * sockets get closed and the unix file for the socket are unlinked.
5867 void swrap_destructor(void)
5869 struct socket_info_fd *s = socket_fds;
5878 if (swrap.libc.handle != NULL) {
5879 dlclose(swrap.libc.handle);
5881 if (swrap.libc.socket_handle) {
5882 dlclose(swrap.libc.socket_handle);