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;
3180 memset(&in, 0, sizeof(in));
3181 in.sin_family = AF_INET;
3182 in.sin_addr.s_addr = htonl(127<<24 |
3183 socket_wrapper_default_iface());
3185 si->myname = (struct swrap_address) {
3186 .sa_socklen = sizeof(in),
3188 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3193 struct sockaddr_in6 in6;
3195 if (si->family != family) {
3196 errno = ENETUNREACH;
3202 type = SOCKET_TYPE_CHAR_TCP_V6;
3205 type = SOCKET_TYPE_CHAR_UDP_V6;
3208 errno = ESOCKTNOSUPPORT;
3212 memset(&in6, 0, sizeof(in6));
3213 in6.sin6_family = AF_INET6;
3214 in6.sin6_addr = *swrap_ipv6();
3215 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3217 si->myname = (struct swrap_address) {
3218 .sa_socklen = sizeof(in6),
3220 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3225 errno = ESOCKTNOSUPPORT;
3229 if (autobind_start > 60000) {
3230 autobind_start = 10000;
3233 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3234 port = autobind_start + i;
3235 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3236 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3237 type, socket_wrapper_default_iface(), port);
3238 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3240 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3245 si->un_addr = un_addr.sa.un;
3248 autobind_start = port + 1;
3251 if (i == SOCKET_MAX_SOCKETS) {
3252 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3253 "interface "SOCKET_FORMAT,
3256 socket_wrapper_default_iface(),
3262 si->family = family;
3263 set_port(si->family, port, &si->myname);
3268 /****************************************************************************
3270 ***************************************************************************/
3272 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3276 struct swrap_address un_addr = {
3277 .sa_socklen = sizeof(struct sockaddr_un),
3279 struct socket_info *si = find_socket_info(s);
3283 return libc_connect(s, serv_addr, addrlen);
3286 if (si->bound == 0) {
3287 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3293 if (si->family != serv_addr->sa_family) {
3298 ret = sockaddr_convert_to_un(si, serv_addr,
3299 addrlen, &un_addr.sa.un, 0, &bcast);
3305 errno = ENETUNREACH;
3309 if (si->type == SOCK_DGRAM) {
3310 si->defer_connect = 1;
3313 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3315 ret = libc_connect(s,
3317 un_addr.sa_socklen);
3320 SWRAP_LOG(SWRAP_LOG_TRACE,
3321 "connect() path=%s, fd=%d",
3322 un_addr.sa.un.sun_path, s);
3325 /* to give better errors */
3326 if (ret == -1 && errno == ENOENT) {
3327 errno = EHOSTUNREACH;
3331 si->peername = (struct swrap_address) {
3332 .sa_socklen = addrlen,
3335 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3339 * When we connect() on a socket than we have to bind the
3340 * outgoing connection on the interface we use for the
3341 * transport. We already bound it on the right interface
3342 * but here we have to update the name so getsockname()
3343 * returns correct information.
3345 if (si->bindname.sa_socklen > 0) {
3346 si->myname = (struct swrap_address) {
3347 .sa_socklen = si->bindname.sa_socklen,
3350 memcpy(&si->myname.sa.ss,
3351 &si->bindname.sa.ss,
3352 si->bindname.sa_socklen);
3354 /* Cleanup bindname */
3355 si->bindname = (struct swrap_address) {
3360 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3361 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3363 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3369 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3371 return swrap_connect(s, serv_addr, addrlen);
3374 /****************************************************************************
3376 ***************************************************************************/
3378 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3381 struct swrap_address un_addr = {
3382 .sa_socklen = sizeof(struct sockaddr_un),
3384 struct socket_info *si = find_socket_info(s);
3391 return libc_bind(s, myaddr, addrlen);
3394 switch (si->family) {
3396 const struct sockaddr_in *sin;
3397 if (addrlen < sizeof(struct sockaddr_in)) {
3398 bind_error = EINVAL;
3402 sin = (const struct sockaddr_in *)(const void *)myaddr;
3404 if (sin->sin_family != AF_INET) {
3405 bind_error = EAFNOSUPPORT;
3408 /* special case for AF_UNSPEC */
3409 if (sin->sin_family == AF_UNSPEC &&
3410 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3419 const struct sockaddr_in6 *sin6;
3420 if (addrlen < sizeof(struct sockaddr_in6)) {
3421 bind_error = EINVAL;
3425 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3427 if (sin6->sin6_family != AF_INET6) {
3428 bind_error = EAFNOSUPPORT;
3435 bind_error = EINVAL;
3439 if (bind_error != 0) {
3445 in_use = check_addr_port_in_use(myaddr, addrlen);
3452 si->myname.sa_socklen = addrlen;
3453 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3455 ret = sockaddr_convert_to_un(si,
3465 unlink(un_addr.sa.un.sun_path);
3467 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3469 SWRAP_LOG(SWRAP_LOG_TRACE,
3470 "bind() path=%s, fd=%d",
3471 un_addr.sa.un.sun_path, s);
3480 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3482 return swrap_bind(s, myaddr, addrlen);
3485 /****************************************************************************
3487 ***************************************************************************/
3489 #ifdef HAVE_BINDRESVPORT
3490 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3492 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3494 struct swrap_address myaddr = {
3495 .sa_socklen = sizeof(struct sockaddr_storage),
3498 static uint16_t port;
3503 #define SWRAP_STARTPORT 600
3504 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3505 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3508 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3512 salen = myaddr.sa_socklen;
3515 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3521 memset(&myaddr.sa.ss, 0, salen);
3526 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3529 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3531 salen = sizeof(struct sockaddr_in);
3532 sinp->sin_port = htons(port);
3536 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3538 salen = sizeof(struct sockaddr_in6);
3539 sin6p->sin6_port = htons(port);
3543 errno = EAFNOSUPPORT;
3548 if (port > SWRAP_ENDPORT) {
3549 port = SWRAP_STARTPORT;
3552 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3553 if (rc == 0 || errno != EADDRINUSE) {
3561 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3563 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3567 /****************************************************************************
3569 ***************************************************************************/
3571 static int swrap_listen(int s, int backlog)
3574 struct socket_info *si = find_socket_info(s);
3577 return libc_listen(s, backlog);
3580 if (si->bound == 0) {
3581 ret = swrap_auto_bind(s, si, si->family);
3588 ret = libc_listen(s, backlog);
3593 int listen(int s, int backlog)
3595 return swrap_listen(s, backlog);
3598 /****************************************************************************
3600 ***************************************************************************/
3602 static FILE *swrap_fopen(const char *name, const char *mode)
3606 fp = libc_fopen(name, mode);
3608 int fd = fileno(fp);
3610 swrap_remove_stale(fd);
3616 FILE *fopen(const char *name, const char *mode)
3618 return swrap_fopen(name, mode);
3621 /****************************************************************************
3623 ***************************************************************************/
3626 static FILE *swrap_fopen64(const char *name, const char *mode)
3630 fp = libc_fopen64(name, mode);
3632 int fd = fileno(fp);
3634 swrap_remove_stale(fd);
3640 FILE *fopen64(const char *name, const char *mode)
3642 return swrap_fopen64(name, mode);
3644 #endif /* HAVE_FOPEN64 */
3646 /****************************************************************************
3648 ***************************************************************************/
3650 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3654 ret = libc_vopen(pathname, flags, ap);
3657 * There are methods for closing descriptors (libc-internal code
3658 * paths, direct syscalls) which close descriptors in ways that
3659 * we can't intercept, so try to recover when we notice that
3662 swrap_remove_stale(ret);
3667 int open(const char *pathname, int flags, ...)
3672 va_start(ap, flags);
3673 fd = swrap_vopen(pathname, flags, ap);
3679 /****************************************************************************
3681 ***************************************************************************/
3684 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
3688 ret = libc_vopen64(pathname, flags, ap);
3691 * There are methods for closing descriptors (libc-internal code
3692 * paths, direct syscalls) which close descriptors in ways that
3693 * we can't intercept, so try to recover when we notice that
3696 swrap_remove_stale(ret);
3701 int open64(const char *pathname, int flags, ...)
3706 va_start(ap, flags);
3707 fd = swrap_vopen64(pathname, flags, ap);
3712 #endif /* HAVE_OPEN64 */
3714 /****************************************************************************
3716 ***************************************************************************/
3718 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3722 ret = libc_vopenat(dirfd, path, flags, ap);
3725 * There are methods for closing descriptors (libc-internal code
3726 * paths, direct syscalls) which close descriptors in ways that
3727 * we can't intercept, so try to recover when we notice that
3730 swrap_remove_stale(ret);
3736 int openat(int dirfd, const char *path, int flags, ...)
3741 va_start(ap, flags);
3742 fd = swrap_vopenat(dirfd, path, flags, ap);
3748 /****************************************************************************
3750 ***************************************************************************/
3752 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3754 struct socket_info *si = find_socket_info(s);
3758 return libc_getpeername(s, name, addrlen);
3761 if (si->peername.sa_socklen == 0)
3767 len = MIN(*addrlen, si->peername.sa_socklen);
3772 memcpy(name, &si->peername.sa.ss, len);
3773 *addrlen = si->peername.sa_socklen;
3778 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3779 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3781 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3784 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3787 /****************************************************************************
3789 ***************************************************************************/
3791 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3793 struct socket_info *si = find_socket_info(s);
3797 return libc_getsockname(s, name, addrlen);
3800 len = MIN(*addrlen, si->myname.sa_socklen);
3805 memcpy(name, &si->myname.sa.ss, len);
3806 *addrlen = si->myname.sa_socklen;
3811 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3812 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3814 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3817 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3820 /****************************************************************************
3822 ***************************************************************************/
3825 # ifdef SO_PROTOTYPE /* The Solaris name */
3826 # define SO_PROTOCOL SO_PROTOTYPE
3827 # endif /* SO_PROTOTYPE */
3828 #endif /* SO_PROTOCOL */
3830 static int swrap_getsockopt(int s, int level, int optname,
3831 void *optval, socklen_t *optlen)
3833 struct socket_info *si = find_socket_info(s);
3836 return libc_getsockopt(s,
3843 if (level == SOL_SOCKET) {
3847 if (optval == NULL || optlen == NULL ||
3848 *optlen < (socklen_t)sizeof(int)) {
3853 *optlen = sizeof(int);
3854 *(int *)optval = si->family;
3856 #endif /* SO_DOMAIN */
3860 if (optval == NULL || optlen == NULL ||
3861 *optlen < (socklen_t)sizeof(int)) {
3866 *optlen = sizeof(int);
3867 *(int *)optval = si->protocol;
3869 #endif /* SO_PROTOCOL */
3871 if (optval == NULL || optlen == NULL ||
3872 *optlen < (socklen_t)sizeof(int)) {
3877 *optlen = sizeof(int);
3878 *(int *)optval = si->type;
3881 return libc_getsockopt(s,
3887 } else if (level == IPPROTO_TCP) {
3892 * This enables sending packets directly out over TCP.
3893 * As a unix socket is doing that any way, report it as
3896 if (optval == NULL || optlen == NULL ||
3897 *optlen < (socklen_t)sizeof(int)) {
3902 *optlen = sizeof(int);
3903 *(int *)optval = si->tcp_nodelay;
3906 #endif /* TCP_NODELAY */
3912 errno = ENOPROTOOPT;
3916 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3917 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3919 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3922 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3925 /****************************************************************************
3927 ***************************************************************************/
3929 static int swrap_setsockopt(int s, int level, int optname,
3930 const void *optval, socklen_t optlen)
3932 struct socket_info *si = find_socket_info(s);
3935 return libc_setsockopt(s,
3942 if (level == SOL_SOCKET) {
3943 return libc_setsockopt(s,
3948 } else if (level == IPPROTO_TCP) {
3955 * This enables sending packets directly out over TCP.
3956 * A unix socket is doing that any way.
3958 if (optval == NULL || optlen == 0 ||
3959 optlen < (socklen_t)sizeof(int)) {
3964 i = *discard_const_p(int, optval);
3965 if (i != 0 && i != 1) {
3969 si->tcp_nodelay = i;
3973 #endif /* TCP_NODELAY */
3979 switch (si->family) {
3981 if (level == IPPROTO_IP) {
3983 if (optname == IP_PKTINFO) {
3984 si->pktinfo = AF_INET;
3986 #endif /* IP_PKTINFO */
3991 if (level == IPPROTO_IPV6) {
3992 #ifdef IPV6_RECVPKTINFO
3993 if (optname == IPV6_RECVPKTINFO) {
3994 si->pktinfo = AF_INET6;
3996 #endif /* IPV6_PKTINFO */
4001 errno = ENOPROTOOPT;
4006 int setsockopt(int s, int level, int optname,
4007 const void *optval, socklen_t optlen)
4009 return swrap_setsockopt(s, level, optname, optval, optlen);
4012 /****************************************************************************
4014 ***************************************************************************/
4016 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4018 struct socket_info *si = find_socket_info(s);
4024 return libc_vioctl(s, r, va);
4029 rc = libc_vioctl(s, r, va);
4033 value = *((int *)va_arg(ap, int *));
4035 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4036 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4037 } else if (value == 0) { /* END OF FILE */
4038 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4048 #ifdef HAVE_IOCTL_INT
4049 int ioctl(int s, int r, ...)
4051 int ioctl(int s, unsigned long int r, ...)
4059 rc = swrap_vioctl(s, (unsigned long int) r, va);
4070 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4073 # ifdef _ALIGN /* BSD */
4074 #define CMSG_ALIGN _ALIGN
4076 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4077 # endif /* _ALIGN */
4078 #endif /* CMSG_ALIGN */
4081 * @brief Add a cmsghdr to a msghdr.
4083 * This is an function to add any type of cmsghdr. It will operate on the
4084 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4085 * the buffer position after the added cmsg element. Hence, this function is
4086 * intended to be used with an intermediate msghdr and not on the original
4087 * one handed in by the client.
4089 * @param[in] msg The msghdr to which to add the cmsg.
4091 * @param[in] level The cmsg level to set.
4093 * @param[in] type The cmsg type to set.
4095 * @param[in] data The cmsg data to set.
4097 * @param[in] len the length of the data to set.
4099 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4105 size_t cmlen = CMSG_LEN(len);
4106 size_t cmspace = CMSG_SPACE(len);
4107 uint8_t cmbuf[cmspace];
4108 void *cast_ptr = (void *)cmbuf;
4109 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4112 memset(cmbuf, 0, cmspace);
4114 if (msg->msg_controllen < cmlen) {
4115 cmlen = msg->msg_controllen;
4116 msg->msg_flags |= MSG_CTRUNC;
4119 if (msg->msg_controllen < cmspace) {
4120 cmspace = msg->msg_controllen;
4124 * We copy the full input data into an intermediate cmsghdr first
4125 * in order to more easily cope with truncation.
4127 cm->cmsg_len = cmlen;
4128 cm->cmsg_level = level;
4129 cm->cmsg_type = type;
4130 memcpy(CMSG_DATA(cm), data, len);
4133 * We now copy the possibly truncated buffer.
4134 * We copy cmlen bytes, but consume cmspace bytes,
4135 * leaving the possible padding uninitialiazed.
4137 p = (uint8_t *)msg->msg_control;
4138 memcpy(p, cm, cmlen);
4140 msg->msg_control = p;
4141 msg->msg_controllen -= cmspace;
4146 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4149 /* Add packet info */
4150 switch (si->pktinfo) {
4151 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4153 struct sockaddr_in *sin;
4154 #if defined(HAVE_STRUCT_IN_PKTINFO)
4155 struct in_pktinfo pkt;
4156 #elif defined(IP_RECVDSTADDR)
4160 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4161 sin = &si->bindname.sa.in;
4163 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4166 sin = &si->myname.sa.in;
4171 #if defined(HAVE_STRUCT_IN_PKTINFO)
4172 pkt.ipi_ifindex = socket_wrapper_default_iface();
4173 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4174 #elif defined(IP_RECVDSTADDR)
4175 pkt = sin->sin_addr;
4178 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4183 #endif /* IP_PKTINFO */
4184 #if defined(HAVE_IPV6)
4186 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4187 struct sockaddr_in6 *sin6;
4188 struct in6_pktinfo pkt6;
4190 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4191 sin6 = &si->bindname.sa.in6;
4193 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4196 sin6 = &si->myname.sa.in6;
4201 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4202 pkt6.ipi6_addr = sin6->sin6_addr;
4204 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4205 &pkt6, sizeof(pkt6));
4206 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4210 #endif /* IPV6_PKTINFO */
4218 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4219 struct msghdr *omsg)
4223 if (si->pktinfo > 0) {
4224 rc = swrap_msghdr_add_pktinfo(si, omsg);
4230 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4232 size_t *cm_data_space);
4233 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4235 size_t *cm_data_space);
4237 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4239 size_t *cm_data_space) {
4240 struct cmsghdr *cmsg;
4244 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4248 for (cmsg = CMSG_FIRSTHDR(msg);
4250 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4251 switch (cmsg->cmsg_level) {
4253 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4258 rc = swrap_sendmsg_copy_cmsg(cmsg,
4268 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4270 size_t *cm_data_space)
4275 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4277 p = realloc((*cm_data), cmspace);
4283 p = (*cm_data) + (*cm_data_space);
4284 *cm_data_space = cmspace;
4286 memcpy(p, cmsg, cmsg->cmsg_len);
4291 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4293 size_t *cm_data_space);
4296 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4298 size_t *cm_data_space)
4302 switch(cmsg->cmsg_type) {
4305 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4312 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4324 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4326 size_t *cm_data_space)
4328 (void)cmsg; /* unused */
4329 (void)cm_data; /* unused */
4330 (void)cm_data_space; /* unused */
4333 * Passing a IP pktinfo to a unix socket might be rejected by the
4334 * Kernel, at least on FreeBSD. So skip this cmsg.
4338 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4340 static ssize_t swrap_sendmsg_before(int fd,
4341 struct socket_info *si,
4343 struct iovec *tmp_iov,
4344 struct sockaddr_un *tmp_un,
4345 const struct sockaddr_un **to_un,
4346 const struct sockaddr **to,
4366 if (!si->connected) {
4371 if (msg->msg_iovlen == 0) {
4375 mtu = socket_wrapper_mtu();
4376 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4378 nlen = len + msg->msg_iov[i].iov_len;
4383 msg->msg_iovlen = i;
4384 if (msg->msg_iovlen == 0) {
4385 *tmp_iov = msg->msg_iov[0];
4386 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4388 msg->msg_iov = tmp_iov;
4389 msg->msg_iovlen = 1;
4394 if (si->connected) {
4395 if (msg->msg_name != NULL) {
4397 * We are dealing with unix sockets and if we
4398 * are connected, we should only talk to the
4399 * connected unix path. Using the fd to send
4400 * to another server would be hard to achieve.
4402 msg->msg_name = NULL;
4403 msg->msg_namelen = 0;
4406 const struct sockaddr *msg_name;
4407 msg_name = (const struct sockaddr *)msg->msg_name;
4409 if (msg_name == NULL) {
4415 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4427 msg->msg_name = tmp_un;
4428 msg->msg_namelen = sizeof(*tmp_un);
4431 if (si->bound == 0) {
4432 ret = swrap_auto_bind(fd, si, si->family);
4434 if (errno == ENOTSOCK) {
4435 swrap_remove_stale(fd);
4438 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4444 if (!si->defer_connect) {
4448 ret = sockaddr_convert_to_un(si,
4450 si->peername.sa_socklen,
4458 ret = libc_connect(fd,
4459 (struct sockaddr *)(void *)tmp_un,
4462 /* to give better errors */
4463 if (ret == -1 && errno == ENOENT) {
4464 errno = EHOSTUNREACH;
4471 si->defer_connect = 0;
4474 errno = EHOSTUNREACH;
4478 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4479 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4480 uint8_t *cmbuf = NULL;
4483 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4490 msg->msg_controllen = 0;
4491 msg->msg_control = NULL;
4492 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4493 memcpy(msg->msg_control, cmbuf, cmlen);
4494 msg->msg_controllen = cmlen;
4503 static void swrap_sendmsg_after(int fd,
4504 struct socket_info *si,
4506 const struct sockaddr *to,
4509 int saved_errno = errno;
4516 /* to give better errors */
4518 if (saved_errno == ENOENT) {
4519 saved_errno = EHOSTUNREACH;
4520 } else if (saved_errno == ENOTSOCK) {
4521 /* If the fd is not a socket, remove it */
4522 swrap_remove_stale(fd);
4526 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4527 avail += msg->msg_iov[i].iov_len;
4531 remain = MIN(80, avail);
4536 /* we capture it as one single packet */
4537 buf = (uint8_t *)malloc(remain);
4539 /* we just not capture the packet */
4540 errno = saved_errno;
4544 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4545 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4547 msg->msg_iov[i].iov_base,
4550 remain -= this_time;
4557 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4558 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4560 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4565 if (si->connected) {
4566 to = &si->peername.sa.s;
4569 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4570 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4572 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4578 errno = saved_errno;
4581 static int swrap_recvmsg_before(int fd,
4582 struct socket_info *si,
4584 struct iovec *tmp_iov)
4589 (void)fd; /* unused */
4594 if (!si->connected) {
4599 if (msg->msg_iovlen == 0) {
4603 mtu = socket_wrapper_mtu();
4604 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4606 nlen = len + msg->msg_iov[i].iov_len;
4611 msg->msg_iovlen = i;
4612 if (msg->msg_iovlen == 0) {
4613 *tmp_iov = msg->msg_iov[0];
4614 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4616 msg->msg_iov = tmp_iov;
4617 msg->msg_iovlen = 1;
4622 if (msg->msg_name == NULL) {
4627 if (msg->msg_iovlen == 0) {
4631 if (si->bound == 0) {
4632 ret = swrap_auto_bind(fd, si, si->family);
4635 * When attempting to read or write to a
4636 * descriptor, if an underlying autobind fails
4637 * because it's not a socket, stop intercepting
4638 * uses of that descriptor.
4640 if (errno == ENOTSOCK) {
4641 swrap_remove_stale(fd);
4644 SWRAP_LOG(SWRAP_LOG_ERROR,
4645 "swrap_recvmsg_before failed");
4652 errno = EHOSTUNREACH;
4659 static int swrap_recvmsg_after(int fd,
4660 struct socket_info *si,
4662 const struct sockaddr_un *un_addr,
4663 socklen_t un_addrlen,
4666 int saved_errno = errno;
4668 uint8_t *buf = NULL;
4674 /* to give better errors */
4676 if (saved_errno == ENOENT) {
4677 saved_errno = EHOSTUNREACH;
4678 } else if (saved_errno == ENOTSOCK) {
4679 /* If the fd is not a socket, remove it */
4680 swrap_remove_stale(fd);
4684 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4685 avail += msg->msg_iov[i].iov_len;
4688 /* Convert the socket address before we leave */
4689 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4690 rc = sockaddr_convert_from_un(si,
4707 remain = MIN(80, avail);
4712 /* we capture it as one single packet */
4713 buf = (uint8_t *)malloc(remain);
4715 /* we just not capture the packet */
4716 errno = saved_errno;
4720 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4721 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4723 msg->msg_iov[i].iov_base,
4726 remain -= this_time;
4731 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4732 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4733 } else if (ret == 0) { /* END OF FILE */
4734 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4735 } else if (ret > 0) {
4736 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4745 if (un_addr != NULL) {
4746 swrap_pcap_dump_packet(si,
4752 swrap_pcap_dump_packet(si,
4765 errno = saved_errno;
4767 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4769 msg->msg_controllen > 0 &&
4770 msg->msg_control != NULL) {
4771 rc = swrap_msghdr_add_socket_info(si, msg);
4781 /****************************************************************************
4783 ***************************************************************************/
4785 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4786 struct sockaddr *from, socklen_t *fromlen)
4788 struct swrap_address from_addr = {
4789 .sa_socklen = sizeof(struct sockaddr_un),
4792 struct socket_info *si = find_socket_info(s);
4793 struct swrap_address saddr = {
4794 .sa_socklen = sizeof(struct sockaddr_storage),
4801 return libc_recvfrom(s,
4813 if (from != NULL && fromlen != NULL) {
4814 msg.msg_name = from; /* optional address */
4815 msg.msg_namelen = *fromlen; /* size of address */
4817 msg.msg_name = &saddr.sa.s; /* optional address */
4818 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4820 msg.msg_iov = &tmp; /* scatter/gather array */
4821 msg.msg_iovlen = 1; /* # elements in msg_iov */
4822 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4823 msg.msg_control = NULL; /* ancillary data, see below */
4824 msg.msg_controllen = 0; /* ancillary data buffer len */
4825 msg.msg_flags = 0; /* flags on received message */
4828 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4833 buf = msg.msg_iov[0].iov_base;
4834 len = msg.msg_iov[0].iov_len;
4836 ret = libc_recvfrom(s,
4841 &from_addr.sa_socklen);
4846 tret = swrap_recvmsg_after(s,
4850 from_addr.sa_socklen,
4856 if (from != NULL && fromlen != NULL) {
4857 *fromlen = msg.msg_namelen;
4863 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4864 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4865 struct sockaddr *from, Psocklen_t fromlen)
4867 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4868 struct sockaddr *from, socklen_t *fromlen)
4871 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4874 /****************************************************************************
4876 ***************************************************************************/
4878 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4879 const struct sockaddr *to, socklen_t tolen)
4883 struct swrap_address un_addr = {
4884 .sa_socklen = sizeof(struct sockaddr_un),
4886 const struct sockaddr_un *to_un = NULL;
4889 struct socket_info *si = find_socket_info(s);
4893 return libc_sendto(s, buf, len, flags, to, tolen);
4896 tmp.iov_base = discard_const_p(char, buf);
4900 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4901 msg.msg_namelen = tolen; /* size of address */
4902 msg.msg_iov = &tmp; /* scatter/gather array */
4903 msg.msg_iovlen = 1; /* # elements in msg_iov */
4904 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4905 msg.msg_control = NULL; /* ancillary data, see below */
4906 msg.msg_controllen = 0; /* ancillary data buffer len */
4907 msg.msg_flags = 0; /* flags on received message */
4910 rc = swrap_sendmsg_before(s,
4922 buf = msg.msg_iov[0].iov_base;
4923 len = msg.msg_iov[0].iov_len;
4928 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4931 type = SOCKET_TYPE_CHAR_UDP;
4933 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4934 snprintf(un_addr.sa.un.sun_path,
4935 sizeof(un_addr.sa.un.sun_path),
4937 socket_wrapper_dir(), type, iface, prt);
4938 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4940 /* ignore the any errors in broadcast sends */
4946 un_addr.sa_socklen);
4949 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4955 * If it is a dgram socket and we are connected, don't include the
4958 if (si->type == SOCK_DGRAM && si->connected) {
4959 ret = libc_sendto(s,
4966 ret = libc_sendto(s,
4970 (struct sockaddr *)msg.msg_name,
4974 swrap_sendmsg_after(s, si, &msg, to, ret);
4979 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4980 const struct sockaddr *to, socklen_t tolen)
4982 return swrap_sendto(s, buf, len, flags, to, tolen);
4985 /****************************************************************************
4987 ***************************************************************************/
4989 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4991 struct socket_info *si;
4993 struct swrap_address saddr = {
4994 .sa_socklen = sizeof(struct sockaddr_storage),
5000 si = find_socket_info(s);
5002 return libc_recv(s, buf, len, flags);
5009 msg.msg_name = &saddr.sa.s; /* optional address */
5010 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5011 msg.msg_iov = &tmp; /* scatter/gather array */
5012 msg.msg_iovlen = 1; /* # elements in msg_iov */
5013 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5014 msg.msg_control = NULL; /* ancillary data, see below */
5015 msg.msg_controllen = 0; /* ancillary data buffer len */
5016 msg.msg_flags = 0; /* flags on received message */
5019 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5024 buf = msg.msg_iov[0].iov_base;
5025 len = msg.msg_iov[0].iov_len;
5027 ret = libc_recv(s, buf, len, flags);
5029 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5037 ssize_t recv(int s, void *buf, size_t len, int flags)
5039 return swrap_recv(s, buf, len, flags);
5042 /****************************************************************************
5044 ***************************************************************************/
5046 static ssize_t swrap_read(int s, void *buf, size_t len)
5048 struct socket_info *si;
5051 struct swrap_address saddr = {
5052 .sa_socklen = sizeof(struct sockaddr_storage),
5057 si = find_socket_info(s);
5059 return libc_read(s, buf, len);
5066 msg.msg_name = &saddr.sa.ss; /* optional address */
5067 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5068 msg.msg_iov = &tmp; /* scatter/gather array */
5069 msg.msg_iovlen = 1; /* # elements in msg_iov */
5070 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5071 msg.msg_control = NULL; /* ancillary data, see below */
5072 msg.msg_controllen = 0; /* ancillary data buffer len */
5073 msg.msg_flags = 0; /* flags on received message */
5076 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5078 if (tret == -ENOTSOCK) {
5079 return libc_read(s, buf, len);
5084 buf = msg.msg_iov[0].iov_base;
5085 len = msg.msg_iov[0].iov_len;
5087 ret = libc_read(s, buf, len);
5089 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5097 ssize_t read(int s, void *buf, size_t len)
5099 return swrap_read(s, buf, len);
5102 /****************************************************************************
5104 ***************************************************************************/
5106 static ssize_t swrap_write(int s, const void *buf, size_t len)
5110 struct sockaddr_un un_addr;
5113 struct socket_info *si;
5115 si = find_socket_info(s);
5117 return libc_write(s, buf, len);
5120 tmp.iov_base = discard_const_p(char, buf);
5124 msg.msg_name = NULL; /* optional address */
5125 msg.msg_namelen = 0; /* size of address */
5126 msg.msg_iov = &tmp; /* scatter/gather array */
5127 msg.msg_iovlen = 1; /* # elements in msg_iov */
5128 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5129 msg.msg_control = NULL; /* ancillary data, see below */
5130 msg.msg_controllen = 0; /* ancillary data buffer len */
5131 msg.msg_flags = 0; /* flags on received message */
5134 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5139 buf = msg.msg_iov[0].iov_base;
5140 len = msg.msg_iov[0].iov_len;
5142 ret = libc_write(s, buf, len);
5144 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5149 ssize_t write(int s, const void *buf, size_t len)
5151 return swrap_write(s, buf, len);
5154 /****************************************************************************
5156 ***************************************************************************/
5158 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5162 struct sockaddr_un un_addr;
5165 struct socket_info *si = find_socket_info(s);
5168 return libc_send(s, buf, len, flags);
5171 tmp.iov_base = discard_const_p(char, buf);
5175 msg.msg_name = NULL; /* optional address */
5176 msg.msg_namelen = 0; /* size of address */
5177 msg.msg_iov = &tmp; /* scatter/gather array */
5178 msg.msg_iovlen = 1; /* # elements in msg_iov */
5179 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5180 msg.msg_control = NULL; /* ancillary data, see below */
5181 msg.msg_controllen = 0; /* ancillary data buffer len */
5182 msg.msg_flags = 0; /* flags on received message */
5185 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5190 buf = msg.msg_iov[0].iov_base;
5191 len = msg.msg_iov[0].iov_len;
5193 ret = libc_send(s, buf, len, flags);
5195 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5200 ssize_t send(int s, const void *buf, size_t len, int flags)
5202 return swrap_send(s, buf, len, flags);
5205 /****************************************************************************
5207 ***************************************************************************/
5209 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5211 struct swrap_address from_addr = {
5212 .sa_socklen = sizeof(struct sockaddr_un),
5214 struct swrap_address convert_addr = {
5215 .sa_socklen = sizeof(struct sockaddr_storage),
5217 struct socket_info *si;
5220 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5221 size_t msg_ctrllen_filled;
5222 size_t msg_ctrllen_left;
5228 si = find_socket_info(s);
5230 return libc_recvmsg(s, omsg, flags);
5233 tmp.iov_base = NULL;
5237 msg.msg_name = &from_addr.sa; /* optional address */
5238 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5239 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5240 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5241 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5242 msg_ctrllen_filled = 0;
5243 msg_ctrllen_left = omsg->msg_controllen;
5245 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5246 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5247 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5250 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5255 ret = libc_recvmsg(s, &msg, flags);
5257 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5258 msg_ctrllen_filled += msg.msg_controllen;
5259 msg_ctrllen_left -= msg.msg_controllen;
5261 if (omsg->msg_control != NULL) {
5264 p = omsg->msg_control;
5265 p += msg_ctrllen_filled;
5267 msg.msg_control = p;
5268 msg.msg_controllen = msg_ctrllen_left;
5270 msg.msg_control = NULL;
5271 msg.msg_controllen = 0;
5276 * We convert the unix address to a IP address so we need a buffer
5277 * which can store the address in case of SOCK_DGRAM, see below.
5279 msg.msg_name = &convert_addr.sa;
5280 msg.msg_namelen = convert_addr.sa_socklen;
5282 rc = swrap_recvmsg_after(s,
5286 from_addr.sa_socklen,
5292 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5293 if (omsg->msg_control != NULL) {
5294 /* msg.msg_controllen = space left */
5295 msg_ctrllen_left = msg.msg_controllen;
5296 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5299 /* Update the original message length */
5300 omsg->msg_controllen = msg_ctrllen_filled;
5301 omsg->msg_flags = msg.msg_flags;
5303 omsg->msg_iovlen = msg.msg_iovlen;
5308 * The msg_name field points to a caller-allocated buffer that is
5309 * used to return the source address if the socket is unconnected. The
5310 * caller should set msg_namelen to the size of this buffer before this
5311 * call; upon return from a successful call, msg_name will contain the
5312 * length of the returned address. If the application does not need
5313 * to know the source address, msg_name can be specified as NULL.
5315 if (si->type == SOCK_STREAM) {
5316 omsg->msg_namelen = 0;
5317 } else if (omsg->msg_name != NULL &&
5318 omsg->msg_namelen != 0 &&
5319 omsg->msg_namelen >= msg.msg_namelen) {
5320 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5321 omsg->msg_namelen = msg.msg_namelen;
5327 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5329 return swrap_recvmsg(sockfd, msg, flags);
5332 /****************************************************************************
5334 ***************************************************************************/
5336 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5340 struct sockaddr_un un_addr;
5341 const struct sockaddr_un *to_un = NULL;
5342 const struct sockaddr *to = NULL;
5345 struct socket_info *si = find_socket_info(s);
5349 return libc_sendmsg(s, omsg, flags);
5352 ZERO_STRUCT(un_addr);
5354 tmp.iov_base = NULL;
5359 if (si->connected == 0) {
5360 msg.msg_name = omsg->msg_name; /* optional address */
5361 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5363 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5364 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5365 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5366 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5367 /* omsg is a const so use a local buffer for modifications */
5368 uint8_t cmbuf[omsg->msg_controllen];
5370 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5372 msg.msg_control = cmbuf; /* ancillary data, see below */
5373 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5375 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5378 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5386 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5394 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5395 avail += msg.msg_iov[i].iov_len;
5401 /* we capture it as one single packet */
5402 buf = (uint8_t *)malloc(remain);
5407 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5408 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5410 msg.msg_iov[i].iov_base,
5413 remain -= this_time;
5416 type = SOCKET_TYPE_CHAR_UDP;
5418 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5419 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5420 socket_wrapper_dir(), type, iface, prt);
5421 if (stat(un_addr.sun_path, &st) != 0) continue;
5423 msg.msg_name = &un_addr; /* optional address */
5424 msg.msg_namelen = sizeof(un_addr); /* size of address */
5426 /* ignore the any errors in broadcast sends */
5427 libc_sendmsg(s, &msg, flags);
5430 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5436 ret = libc_sendmsg(s, &msg, flags);
5438 swrap_sendmsg_after(s, si, &msg, to, ret);
5443 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5445 return swrap_sendmsg(s, omsg, flags);
5448 /****************************************************************************
5450 ***************************************************************************/
5452 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5454 struct socket_info *si;
5457 struct swrap_address saddr = {
5458 .sa_socklen = sizeof(struct sockaddr_storage)
5463 si = find_socket_info(s);
5465 return libc_readv(s, vector, count);
5468 tmp.iov_base = NULL;
5472 msg.msg_name = &saddr.sa.s; /* optional address */
5473 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5474 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5475 msg.msg_iovlen = count; /* # elements in msg_iov */
5476 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5477 msg.msg_control = NULL; /* ancillary data, see below */
5478 msg.msg_controllen = 0; /* ancillary data buffer len */
5479 msg.msg_flags = 0; /* flags on received message */
5482 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5484 if (rc == -ENOTSOCK) {
5485 return libc_readv(s, vector, count);
5490 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5492 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5500 ssize_t readv(int s, const struct iovec *vector, int count)
5502 return swrap_readv(s, vector, count);
5505 /****************************************************************************
5507 ***************************************************************************/
5509 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5513 struct sockaddr_un un_addr;
5516 struct socket_info *si = find_socket_info(s);
5519 return libc_writev(s, vector, count);
5522 tmp.iov_base = NULL;
5526 msg.msg_name = NULL; /* optional address */
5527 msg.msg_namelen = 0; /* size of address */
5528 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5529 msg.msg_iovlen = count; /* # elements in msg_iov */
5530 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5531 msg.msg_control = NULL; /* ancillary data, see below */
5532 msg.msg_controllen = 0; /* ancillary data buffer len */
5533 msg.msg_flags = 0; /* flags on received message */
5536 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5538 if (rc == -ENOTSOCK) {
5539 return libc_readv(s, vector, count);
5544 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5546 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5551 ssize_t writev(int s, const struct iovec *vector, int count)
5553 return swrap_writev(s, vector, count);
5556 /****************************
5558 ***************************/
5560 static int swrap_close(int fd)
5562 struct socket_info_fd *fi = find_socket_info_fd(fd);
5563 struct socket_info *si = NULL;
5568 return libc_close(fd);
5571 si_index = fi->si_index;
5573 SWRAP_DLIST_REMOVE(socket_fds, fi);
5576 ret = libc_close(fd);
5578 si = &sockets[si_index];
5581 if (si->refcount > 0) {
5582 /* there are still references left */
5586 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5587 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5590 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5591 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5592 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5595 if (si->un_addr.sun_path[0] != '\0') {
5596 unlink(si->un_addr.sun_path);
5599 si->next_free = first_free;
5600 first_free = si_index;
5607 return swrap_close(fd);
5610 /****************************
5612 ***************************/
5614 static int swrap_dup(int fd)
5616 struct socket_info *si;
5617 struct socket_info_fd *src_fi, *fi;
5619 src_fi = find_socket_info_fd(fd);
5620 if (src_fi == NULL) {
5621 return libc_dup(fd);
5624 si = &sockets[src_fi->si_index];
5626 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5632 fi->fd = libc_dup(fd);
5634 int saved_errno = errno;
5636 errno = saved_errno;
5641 fi->si_index = src_fi->si_index;
5643 /* Make sure we don't have an entry for the fd */
5644 swrap_remove_stale(fi->fd);
5646 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5652 return swrap_dup(fd);
5655 /****************************
5657 ***************************/
5659 static int swrap_dup2(int fd, int newfd)
5661 struct socket_info *si;
5662 struct socket_info_fd *src_fi, *fi;
5664 src_fi = find_socket_info_fd(fd);
5665 if (src_fi == NULL) {
5666 return libc_dup2(fd, newfd);
5669 si = &sockets[src_fi->si_index];
5673 * According to the manpage:
5675 * "If oldfd is a valid file descriptor, and newfd has the same
5676 * value as oldfd, then dup2() does nothing, and returns newfd."
5681 if (find_socket_info(newfd)) {
5682 /* dup2() does an implicit close of newfd, which we
5683 * need to emulate */
5687 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5693 fi->fd = libc_dup2(fd, newfd);
5695 int saved_errno = errno;
5697 errno = saved_errno;
5702 fi->si_index = src_fi->si_index;
5704 /* Make sure we don't have an entry for the fd */
5705 swrap_remove_stale(fi->fd);
5707 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5711 int dup2(int fd, int newfd)
5713 return swrap_dup2(fd, newfd);
5716 /****************************
5718 ***************************/
5720 static int swrap_vfcntl(int fd, int cmd, va_list va)
5722 struct socket_info_fd *src_fi, *fi;
5723 struct socket_info *si;
5726 src_fi = find_socket_info_fd(fd);
5727 if (src_fi == NULL) {
5728 return libc_vfcntl(fd, cmd, va);
5731 si = &sockets[src_fi->si_index];
5735 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5741 fi->fd = libc_vfcntl(fd, cmd, va);
5743 int saved_errno = errno;
5745 errno = saved_errno;
5750 fi->si_index = src_fi->si_index;
5752 /* Make sure we don't have an entry for the fd */
5753 swrap_remove_stale(fi->fd);
5755 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5760 rc = libc_vfcntl(fd, cmd, va);
5767 int fcntl(int fd, int cmd, ...)
5774 rc = swrap_vfcntl(fd, cmd, va);
5781 /****************************
5783 ***************************/
5786 static int swrap_eventfd(int count, int flags)
5790 fd = libc_eventfd(count, flags);
5792 swrap_remove_stale(fd);
5798 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5799 int eventfd(unsigned int count, int flags)
5801 int eventfd(int count, int flags)
5804 return swrap_eventfd(count, flags);
5809 int pledge(const char *promises, const char *paths[])
5811 (void)promises; /* unused */
5812 (void)paths; /* unused */
5816 #endif /* HAVE_PLEDGE */
5818 static void swrap_thread_prepare(void)
5823 static void swrap_thread_parent(void)
5828 static void swrap_thread_child(void)
5833 /****************************
5835 ***************************/
5836 void swrap_constructor(void)
5839 * If we hold a lock and the application forks, then the child
5840 * is not able to unlock the mutex and we are in a deadlock.
5841 * This should prevent such deadlocks.
5843 pthread_atfork(&swrap_thread_prepare,
5844 &swrap_thread_parent,
5845 &swrap_thread_child);
5848 /****************************
5850 ***************************/
5853 * This function is called when the library is unloaded and makes sure that
5854 * sockets get closed and the unix file for the socket are unlinked.
5856 void swrap_destructor(void)
5858 struct socket_info_fd *s = socket_fds;
5867 if (swrap.libc.handle != NULL) {
5868 dlclose(swrap.libc.handle);
5870 if (swrap.libc.socket_handle) {
5871 dlclose(swrap.libc.socket_handle);