swrap: Add swrap_msghdr_add_pktinfo().
[Samba/wip.git] / lib / socket_wrapper / socket_wrapper.c
blob288ca13c83ad5ff6779cb9a979c2f777bbe781b4
1 /*
2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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
33 * SUCH DAMAGE.
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
40 is set.
43 #include "config.h"
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
52 #endif
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
55 #endif
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
58 #endif
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
61 #endif
62 #include <sys/uio.h>
63 #include <errno.h>
64 #include <sys/un.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
68 #include <fcntl.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <stdio.h>
72 #include <stdint.h>
73 #include <stdarg.h>
74 #include <stdbool.h>
75 #include <unistd.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
78 #endif
80 enum swrap_dbglvl_e {
81 SWRAP_LOG_ERROR = 0,
82 SWRAP_LOG_WARN,
83 SWRAP_LOG_DEBUG,
84 SWRAP_LOG_TRACE
87 /* GCC have printf type attribute check. */
88 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
89 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
90 #else
91 #define PRINTF_ATTRIBUTE(a,b)
92 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
94 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
95 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
96 #else
97 #define DESTRUCTOR_ATTRIBUTE
98 #endif
100 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
101 # define SWRAP_THREAD __thread
102 #else
103 # define SWRAP_THREAD
104 #endif
106 #ifndef MIN
107 #define MIN(a,b) ((a)<(b)?(a):(b))
108 #endif
110 #ifndef ZERO_STRUCT
111 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
112 #endif
114 #ifndef discard_const
115 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
116 #endif
118 #ifndef discard_const_p
119 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
120 #endif
122 #ifdef IPV6_PKTINFO
123 # ifndef IPV6_RECVPKTINFO
124 # define IPV6_RECVPKTINFO IPV6_PKTINFO
125 # endif /* IPV6_RECVPKTINFO */
126 #endif /* IPV6_PKTINFO */
128 #define SWRAP_DLIST_ADD(list,item) do { \
129 if (!(list)) { \
130 (item)->prev = NULL; \
131 (item)->next = NULL; \
132 (list) = (item); \
133 } else { \
134 (item)->prev = NULL; \
135 (item)->next = (list); \
136 (list)->prev = (item); \
137 (list) = (item); \
139 } while (0)
141 #define SWRAP_DLIST_REMOVE(list,item) do { \
142 if ((list) == (item)) { \
143 (list) = (item)->next; \
144 if (list) { \
145 (list)->prev = NULL; \
147 } else { \
148 if ((item)->prev) { \
149 (item)->prev->next = (item)->next; \
151 if ((item)->next) { \
152 (item)->next->prev = (item)->prev; \
155 (item)->prev = NULL; \
156 (item)->next = NULL; \
157 } while (0)
159 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
160 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
161 #else
162 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
163 #endif
165 /* we need to use a very terse format here as IRIX 6.4 silently
166 truncates names to 16 chars, so if we use a longer name then we
167 can't tell which port a packet came from with recvfrom()
169 with this format we have 8 chars left for the directory name
171 #define SOCKET_FORMAT "%c%02X%04X"
172 #define SOCKET_TYPE_CHAR_TCP 'T'
173 #define SOCKET_TYPE_CHAR_UDP 'U'
174 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
175 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
178 * Cut down to 1500 byte packets for stream sockets,
179 * which makes it easier to format PCAP capture files
180 * (as the caller will simply continue from here)
182 #define SOCKET_MAX_PACKET 1500
184 #define SOCKET_MAX_SOCKETS 1024
186 /* This limit is to avoid broadcast sendto() needing to stat too many
187 * files. It may be raised (with a performance cost) to up to 254
188 * without changing the format above */
189 #define MAX_WRAPPED_INTERFACES 40
191 struct socket_info_fd {
192 struct socket_info_fd *prev, *next;
193 int fd;
196 struct socket_info
198 struct socket_info_fd *fds;
200 int family;
201 int type;
202 int protocol;
203 int bound;
204 int bcast;
205 int is_server;
206 int connected;
207 int defer_connect;
208 int pktinfo;
210 char *tmp_path;
212 struct sockaddr *bindname;
213 socklen_t bindname_len;
215 struct sockaddr *myname;
216 socklen_t myname_len;
218 struct sockaddr *peername;
219 socklen_t peername_len;
221 struct {
222 unsigned long pck_snd;
223 unsigned long pck_rcv;
224 } io;
226 struct socket_info *prev, *next;
230 * File descriptors are shared between threads so we should share socket
231 * information too.
233 struct socket_info *sockets;
235 /* Function prototypes */
237 bool socket_wrapper_enabled(void);
238 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
240 #ifdef NDEBUG
241 # define SWRAP_LOG(...)
242 #else
244 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
245 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
247 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
249 char buffer[1024];
250 va_list va;
251 const char *d;
252 unsigned int lvl = 0;
254 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
255 if (d != NULL) {
256 lvl = atoi(d);
259 va_start(va, format);
260 vsnprintf(buffer, sizeof(buffer), format, va);
261 va_end(va);
263 if (lvl >= dbglvl) {
264 switch (dbglvl) {
265 case SWRAP_LOG_ERROR:
266 fprintf(stderr,
267 "SWRAP_ERROR(%d): %s\n",
268 (int)getpid(), buffer);
269 break;
270 case SWRAP_LOG_WARN:
271 fprintf(stderr,
272 "SWRAP_WARN(%d): %s\n",
273 (int)getpid(), buffer);
274 break;
275 case SWRAP_LOG_DEBUG:
276 fprintf(stderr,
277 "SWRAP_DEBUG(%d): %s\n",
278 (int)getpid(), buffer);
279 break;
280 case SWRAP_LOG_TRACE:
281 fprintf(stderr,
282 "SWRAP_TRACE(%d): %s\n",
283 (int)getpid(), buffer);
284 break;
288 #endif
290 /*********************************************************
291 * SWRAP LOADING LIBC FUNCTIONS
292 *********************************************************/
294 #include <dlfcn.h>
296 struct swrap_libc_fns {
297 int (*libc_accept)(int sockfd,
298 struct sockaddr *addr,
299 socklen_t *addrlen);
300 int (*libc_bind)(int sockfd,
301 const struct sockaddr *addr,
302 socklen_t addrlen);
303 int (*libc_close)(int fd);
304 int (*libc_connect)(int sockfd,
305 const struct sockaddr *addr,
306 socklen_t addrlen);
307 int (*libc_dup)(int fd);
308 int (*libc_dup2)(int oldfd, int newfd);
309 #ifdef HAVE_EVENTFD
310 int (*libc_eventfd)(int count, int flags);
311 #endif
312 int (*libc_getpeername)(int sockfd,
313 struct sockaddr *addr,
314 socklen_t *addrlen);
315 int (*libc_getsockname)(int sockfd,
316 struct sockaddr *addr,
317 socklen_t *addrlen);
318 int (*libc_getsockopt)(int sockfd,
319 int level,
320 int optname,
321 void *optval,
322 socklen_t *optlen);
323 int (*libc_ioctl)(int d, unsigned long int request, ...);
324 int (*libc_listen)(int sockfd, int backlog);
325 int (*libc_open)(const char *pathname, int flags, mode_t mode);
326 int (*libc_pipe)(int pipefd[2]);
327 int (*libc_read)(int fd, void *buf, size_t count);
328 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
329 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
330 int (*libc_recvfrom)(int sockfd,
331 void *buf,
332 size_t len,
333 int flags,
334 struct sockaddr *src_addr,
335 socklen_t *addrlen);
336 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
337 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
338 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
339 int (*libc_sendto)(int sockfd,
340 const void *buf,
341 size_t len,
342 int flags,
343 const struct sockaddr *dst_addr,
344 socklen_t addrlen);
345 int (*libc_setsockopt)(int sockfd,
346 int level,
347 int optname,
348 const void *optval,
349 socklen_t optlen);
350 #ifdef HAVE_SIGNALFD
351 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
352 #endif
353 int (*libc_socket)(int domain, int type, int protocol);
354 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
355 #ifdef HAVE_TIMERFD_CREATE
356 int (*libc_timerfd_create)(int clockid, int flags);
357 #endif
358 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
361 struct swrap {
362 void *libc_handle;
363 void *libsocket_handle;
365 bool initialised;
366 bool enabled;
368 char *socket_dir;
370 struct swrap_libc_fns fns;
373 static struct swrap swrap;
375 /* prototypes */
376 static const char *socket_wrapper_dir(void);
378 #define LIBC_NAME "libc.so"
380 enum swrap_lib {
381 SWRAP_LIBC,
382 SWRAP_LIBNSL,
383 SWRAP_LIBSOCKET,
386 #ifndef NDEBUG
387 static const char *swrap_str_lib(enum swrap_lib lib)
389 switch (lib) {
390 case SWRAP_LIBC:
391 return "libc";
392 case SWRAP_LIBNSL:
393 return "libnsl";
394 case SWRAP_LIBSOCKET:
395 return "libsocket";
398 /* Compiler would warn us about unhandled enum value if we get here */
399 return "unknown";
401 #endif
403 static void *swrap_load_lib_handle(enum swrap_lib lib)
405 int flags = RTLD_LAZY;
406 void *handle = NULL;
407 int i;
409 #ifdef RTLD_DEEPBIND
410 flags |= RTLD_DEEPBIND;
411 #endif
413 switch (lib) {
414 case SWRAP_LIBNSL:
415 /* FALL TROUGH */
416 case SWRAP_LIBSOCKET:
417 #ifdef HAVE_LIBSOCKET
418 handle = swrap.libsocket_handle;
419 if (handle == NULL) {
420 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
421 char soname[256] = {0};
423 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
424 handle = dlopen(soname, flags);
427 swrap.libsocket_handle = handle;
429 break;
430 #endif
431 /* FALL TROUGH */
432 case SWRAP_LIBC:
433 handle = swrap.libc_handle;
434 #ifdef LIBC_SO
435 if (handle == NULL) {
436 handle = dlopen(LIBC_SO, flags);
438 #endif
439 if (handle == NULL) {
440 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
441 char soname[256] = {0};
443 snprintf(soname, sizeof(soname), "libc.so.%d", i);
444 handle = dlopen(soname, flags);
447 swrap.libc_handle = handle;
449 break;
452 if (handle == NULL) {
453 #ifdef RTLD_NEXT
454 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
455 #else
456 SWRAP_LOG(SWRAP_LOG_ERROR,
457 "Failed to dlopen library: %s\n",
458 dlerror());
459 exit(-1);
460 #endif
463 return handle;
466 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
468 void *handle;
469 void *func;
471 handle = swrap_load_lib_handle(lib);
473 func = dlsym(handle, fn_name);
474 if (func == NULL) {
475 SWRAP_LOG(SWRAP_LOG_ERROR,
476 "Failed to find %s: %s\n",
477 fn_name, dlerror());
478 exit(-1);
481 SWRAP_LOG(SWRAP_LOG_TRACE,
482 "Loaded %s from %s",
483 fn_name, swrap_str_lib(lib));
484 return func;
487 #define swrap_load_lib_function(lib, fn_name) \
488 if (swrap.fns.libc_##fn_name == NULL) { \
489 *(void **) (&swrap.fns.libc_##fn_name) = \
490 _swrap_load_lib_function(lib, #fn_name); \
495 * IMPORTANT
497 * Functions especially from libc need to be loaded individually, you can't load
498 * all at once or gdb will segfault at startup. The same applies to valgrind and
499 * has probably something todo with with the linker.
500 * So we need load each function at the point it is called the first time.
502 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
504 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
506 return swrap.fns.libc_accept(sockfd, addr, addrlen);
509 static int libc_bind(int sockfd,
510 const struct sockaddr *addr,
511 socklen_t addrlen)
513 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
515 return swrap.fns.libc_bind(sockfd, addr, addrlen);
518 static int libc_close(int fd)
520 swrap_load_lib_function(SWRAP_LIBC, close);
522 return swrap.fns.libc_close(fd);
525 static int libc_connect(int sockfd,
526 const struct sockaddr *addr,
527 socklen_t addrlen)
529 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
531 return swrap.fns.libc_connect(sockfd, addr, addrlen);
534 static int libc_dup(int fd)
536 swrap_load_lib_function(SWRAP_LIBC, dup);
538 return swrap.fns.libc_dup(fd);
541 static int libc_dup2(int oldfd, int newfd)
543 swrap_load_lib_function(SWRAP_LIBC, dup2);
545 return swrap.fns.libc_dup2(oldfd, newfd);
548 #ifdef HAVE_EVENTFD
549 static int libc_eventfd(int count, int flags)
551 swrap_load_lib_function(SWRAP_LIBC, eventfd);
553 return swrap.fns.libc_eventfd(count, flags);
555 #endif
557 static int libc_getpeername(int sockfd,
558 struct sockaddr *addr,
559 socklen_t *addrlen)
561 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
563 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
566 static int libc_getsockname(int sockfd,
567 struct sockaddr *addr,
568 socklen_t *addrlen)
570 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
572 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
575 static int libc_getsockopt(int sockfd,
576 int level,
577 int optname,
578 void *optval,
579 socklen_t *optlen)
581 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
583 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
586 static int libc_vioctl(int d, unsigned long int request, va_list ap)
588 long int args[4];
589 int rc;
590 int i;
592 swrap_load_lib_function(SWRAP_LIBC, ioctl);
594 for (i = 0; i < 4; i++) {
595 args[i] = va_arg(ap, long int);
598 rc = swrap.fns.libc_ioctl(d,
599 request,
600 args[0],
601 args[1],
602 args[2],
603 args[3]);
605 return rc;
608 static int libc_listen(int sockfd, int backlog)
610 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
612 return swrap.fns.libc_listen(sockfd, backlog);
615 static int libc_vopen(const char *pathname, int flags, va_list ap)
617 long int mode = 0;
618 int fd;
620 swrap_load_lib_function(SWRAP_LIBC, open);
622 mode = va_arg(ap, long int);
624 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
626 return fd;
629 static int libc_open(const char *pathname, int flags, ...)
631 va_list ap;
632 int fd;
634 va_start(ap, flags);
635 fd = libc_vopen(pathname, flags, ap);
636 va_end(ap);
638 return fd;
641 static int libc_pipe(int pipefd[2])
643 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
645 return swrap.fns.libc_pipe(pipefd);
648 static int libc_read(int fd, void *buf, size_t count)
650 swrap_load_lib_function(SWRAP_LIBC, read);
652 return swrap.fns.libc_read(fd, buf, count);
655 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
657 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
659 return swrap.fns.libc_readv(fd, iov, iovcnt);
662 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
664 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
666 return swrap.fns.libc_recv(sockfd, buf, len, flags);
669 static int libc_recvfrom(int sockfd,
670 void *buf,
671 size_t len,
672 int flags,
673 struct sockaddr *src_addr,
674 socklen_t *addrlen)
676 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
678 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
681 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
683 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
685 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
688 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
690 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
692 return swrap.fns.libc_send(sockfd, buf, len, flags);
695 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
697 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
699 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
702 static int libc_sendto(int sockfd,
703 const void *buf,
704 size_t len,
705 int flags,
706 const struct sockaddr *dst_addr,
707 socklen_t addrlen)
709 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
711 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
714 static int libc_setsockopt(int sockfd,
715 int level,
716 int optname,
717 const void *optval,
718 socklen_t optlen)
720 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
722 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
725 #ifdef HAVE_SIGNALFD
726 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
728 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
730 return swrap.fns.libc_signalfd(fd, mask, flags);
732 #endif
734 static int libc_socket(int domain, int type, int protocol)
736 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
738 return swrap.fns.libc_socket(domain, type, protocol);
741 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
743 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
745 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
748 #ifdef HAVE_TIMERFD_CREATE
749 static int libc_timerfd_create(int clockid, int flags)
751 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
753 return swrap.fns.libc_timerfd_create(clockid, flags);
755 #endif
757 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
759 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
761 return swrap.fns.libc_writev(fd, iov, iovcnt);
764 /*********************************************************
765 * SWRAP HELPER FUNCTIONS
766 *********************************************************/
768 #ifdef HAVE_IPV6
770 * FD00::5357:5FXX
772 static const struct in6_addr *swrap_ipv6(void)
774 static struct in6_addr v;
775 static int initialized;
776 int ret;
778 if (initialized) {
779 return &v;
781 initialized = 1;
783 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
784 if (ret <= 0) {
785 abort();
788 return &v;
790 #endif
792 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
794 struct sockaddr *ret = (struct sockaddr *)malloc(len);
795 memcpy(ret, data, len);
796 return ret;
799 static void set_port(int family, int prt, struct sockaddr *addr)
801 switch (family) {
802 case AF_INET:
803 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
804 break;
805 #ifdef HAVE_IPV6
806 case AF_INET6:
807 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
808 break;
809 #endif
813 static size_t socket_length(int family)
815 switch (family) {
816 case AF_INET:
817 return sizeof(struct sockaddr_in);
818 #ifdef HAVE_IPV6
819 case AF_INET6:
820 return sizeof(struct sockaddr_in6);
821 #endif
823 return 0;
826 static const char *socket_wrapper_dir(void)
828 const char *s = getenv("SOCKET_WRAPPER_DIR");
829 if (s == NULL) {
830 return NULL;
832 if (strncmp(s, "./", 2) == 0) {
833 s += 2;
836 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
837 return s;
840 bool socket_wrapper_enabled(void)
842 const char *s = socket_wrapper_dir();
844 return s != NULL ? true : false;
847 static unsigned int socket_wrapper_default_iface(void)
849 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
850 if (s) {
851 unsigned int iface;
852 if (sscanf(s, "%u", &iface) == 1) {
853 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
854 return iface;
859 return 1;/* 127.0.0.1 */
862 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
864 unsigned int iface;
865 unsigned int prt;
866 const char *p;
867 char type;
869 p = strrchr(un->sun_path, '/');
870 if (p) p++; else p = un->sun_path;
872 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
873 errno = EINVAL;
874 return -1;
877 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
878 type, iface, prt);
880 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
881 errno = EINVAL;
882 return -1;
885 if (prt > 0xFFFF) {
886 errno = EINVAL;
887 return -1;
890 switch(type) {
891 case SOCKET_TYPE_CHAR_TCP:
892 case SOCKET_TYPE_CHAR_UDP: {
893 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
895 if ((*len) < sizeof(*in2)) {
896 errno = EINVAL;
897 return -1;
900 memset(in2, 0, sizeof(*in2));
901 in2->sin_family = AF_INET;
902 in2->sin_addr.s_addr = htonl((127<<24) | iface);
903 in2->sin_port = htons(prt);
905 *len = sizeof(*in2);
906 break;
908 #ifdef HAVE_IPV6
909 case SOCKET_TYPE_CHAR_TCP_V6:
910 case SOCKET_TYPE_CHAR_UDP_V6: {
911 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
913 if ((*len) < sizeof(*in2)) {
914 errno = EINVAL;
915 return -1;
918 memset(in2, 0, sizeof(*in2));
919 in2->sin6_family = AF_INET6;
920 in2->sin6_addr = *swrap_ipv6();
921 in2->sin6_addr.s6_addr[15] = iface;
922 in2->sin6_port = htons(prt);
924 *len = sizeof(*in2);
925 break;
927 #endif
928 default:
929 errno = EINVAL;
930 return -1;
933 return 0;
936 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
937 int *bcast)
939 char type = '\0';
940 unsigned int prt;
941 unsigned int iface;
942 int is_bcast = 0;
944 if (bcast) *bcast = 0;
946 switch (inaddr->sa_family) {
947 case AF_INET: {
948 const struct sockaddr_in *in =
949 (const struct sockaddr_in *)(const void *)inaddr;
950 unsigned int addr = ntohl(in->sin_addr.s_addr);
951 char u_type = '\0';
952 char b_type = '\0';
953 char a_type = '\0';
955 switch (si->type) {
956 case SOCK_STREAM:
957 u_type = SOCKET_TYPE_CHAR_TCP;
958 break;
959 case SOCK_DGRAM:
960 u_type = SOCKET_TYPE_CHAR_UDP;
961 a_type = SOCKET_TYPE_CHAR_UDP;
962 b_type = SOCKET_TYPE_CHAR_UDP;
963 break;
964 default:
965 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
966 errno = ESOCKTNOSUPPORT;
967 return -1;
970 prt = ntohs(in->sin_port);
971 if (a_type && addr == 0xFFFFFFFF) {
972 /* 255.255.255.255 only udp */
973 is_bcast = 2;
974 type = a_type;
975 iface = socket_wrapper_default_iface();
976 } else if (b_type && addr == 0x7FFFFFFF) {
977 /* 127.255.255.255 only udp */
978 is_bcast = 1;
979 type = b_type;
980 iface = socket_wrapper_default_iface();
981 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
982 /* 127.0.0.X */
983 is_bcast = 0;
984 type = u_type;
985 iface = (addr & 0x000000FF);
986 } else {
987 errno = ENETUNREACH;
988 return -1;
990 if (bcast) *bcast = is_bcast;
991 break;
993 #ifdef HAVE_IPV6
994 case AF_INET6: {
995 const struct sockaddr_in6 *in =
996 (const struct sockaddr_in6 *)(const void *)inaddr;
997 struct in6_addr cmp1, cmp2;
999 switch (si->type) {
1000 case SOCK_STREAM:
1001 type = SOCKET_TYPE_CHAR_TCP_V6;
1002 break;
1003 case SOCK_DGRAM:
1004 type = SOCKET_TYPE_CHAR_UDP_V6;
1005 break;
1006 default:
1007 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1008 errno = ESOCKTNOSUPPORT;
1009 return -1;
1012 /* XXX no multicast/broadcast */
1014 prt = ntohs(in->sin6_port);
1016 cmp1 = *swrap_ipv6();
1017 cmp2 = in->sin6_addr;
1018 cmp2.s6_addr[15] = 0;
1019 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1020 iface = in->sin6_addr.s6_addr[15];
1021 } else {
1022 errno = ENETUNREACH;
1023 return -1;
1026 break;
1028 #endif
1029 default:
1030 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1031 errno = ENETUNREACH;
1032 return -1;
1035 if (prt == 0) {
1036 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1037 errno = EINVAL;
1038 return -1;
1041 if (is_bcast) {
1042 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1043 socket_wrapper_dir());
1044 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1045 /* the caller need to do more processing */
1046 return 0;
1049 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1050 socket_wrapper_dir(), type, iface, prt);
1051 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1053 return 0;
1056 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1057 int *bcast)
1059 char type = '\0';
1060 unsigned int prt;
1061 unsigned int iface;
1062 struct stat st;
1063 int is_bcast = 0;
1065 if (bcast) *bcast = 0;
1067 switch (si->family) {
1068 case AF_INET: {
1069 const struct sockaddr_in *in =
1070 (const struct sockaddr_in *)(const void *)inaddr;
1071 unsigned int addr = ntohl(in->sin_addr.s_addr);
1072 char u_type = '\0';
1073 char d_type = '\0';
1074 char b_type = '\0';
1075 char a_type = '\0';
1077 prt = ntohs(in->sin_port);
1079 switch (si->type) {
1080 case SOCK_STREAM:
1081 u_type = SOCKET_TYPE_CHAR_TCP;
1082 d_type = SOCKET_TYPE_CHAR_TCP;
1083 break;
1084 case SOCK_DGRAM:
1085 u_type = SOCKET_TYPE_CHAR_UDP;
1086 d_type = SOCKET_TYPE_CHAR_UDP;
1087 a_type = SOCKET_TYPE_CHAR_UDP;
1088 b_type = SOCKET_TYPE_CHAR_UDP;
1089 break;
1090 default:
1091 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1092 errno = ESOCKTNOSUPPORT;
1093 return -1;
1096 if (addr == 0) {
1097 /* 0.0.0.0 */
1098 is_bcast = 0;
1099 type = d_type;
1100 iface = socket_wrapper_default_iface();
1101 } else if (a_type && addr == 0xFFFFFFFF) {
1102 /* 255.255.255.255 only udp */
1103 is_bcast = 2;
1104 type = a_type;
1105 iface = socket_wrapper_default_iface();
1106 } else if (b_type && addr == 0x7FFFFFFF) {
1107 /* 127.255.255.255 only udp */
1108 is_bcast = 1;
1109 type = b_type;
1110 iface = socket_wrapper_default_iface();
1111 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1112 /* 127.0.0.X */
1113 is_bcast = 0;
1114 type = u_type;
1115 iface = (addr & 0x000000FF);
1116 } else {
1117 errno = EADDRNOTAVAIL;
1118 return -1;
1121 /* Store the bind address for connect() */
1122 if (si->bindname == NULL) {
1123 struct sockaddr_in bind_in;
1124 socklen_t blen = sizeof(struct sockaddr_in);
1126 ZERO_STRUCT(bind_in);
1127 bind_in.sin_family = in->sin_family;
1128 bind_in.sin_port = in->sin_port;
1129 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1131 si->bindname = sockaddr_dup(&bind_in, blen);
1132 si->bindname_len = blen;
1135 break;
1137 #ifdef HAVE_IPV6
1138 case AF_INET6: {
1139 const struct sockaddr_in6 *in =
1140 (const struct sockaddr_in6 *)(const void *)inaddr;
1141 struct in6_addr cmp1, cmp2;
1143 switch (si->type) {
1144 case SOCK_STREAM:
1145 type = SOCKET_TYPE_CHAR_TCP_V6;
1146 break;
1147 case SOCK_DGRAM:
1148 type = SOCKET_TYPE_CHAR_UDP_V6;
1149 break;
1150 default:
1151 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1152 errno = ESOCKTNOSUPPORT;
1153 return -1;
1156 /* XXX no multicast/broadcast */
1158 prt = ntohs(in->sin6_port);
1160 cmp1 = *swrap_ipv6();
1161 cmp2 = in->sin6_addr;
1162 cmp2.s6_addr[15] = 0;
1163 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1164 iface = socket_wrapper_default_iface();
1165 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1166 iface = in->sin6_addr.s6_addr[15];
1167 } else {
1168 errno = EADDRNOTAVAIL;
1169 return -1;
1172 /* Store the bind address for connect() */
1173 if (si->bindname == NULL) {
1174 struct sockaddr_in6 bind_in;
1175 socklen_t blen = sizeof(struct sockaddr_in6);
1177 ZERO_STRUCT(bind_in);
1178 bind_in.sin6_family = in->sin6_family;
1179 bind_in.sin6_port = in->sin6_port;
1181 bind_in.sin6_addr = *swrap_ipv6();
1182 bind_in.sin6_addr.s6_addr[15] = iface;
1184 si->bindname = sockaddr_dup(&bind_in, blen);
1185 si->bindname_len = blen;
1188 break;
1190 #endif
1191 default:
1192 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1193 errno = EADDRNOTAVAIL;
1194 return -1;
1198 if (bcast) *bcast = is_bcast;
1200 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1201 errno = EINVAL;
1202 return -1;
1205 if (prt == 0) {
1206 /* handle auto-allocation of ephemeral ports */
1207 for (prt = 5001; prt < 10000; prt++) {
1208 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1209 socket_wrapper_dir(), type, iface, prt);
1210 if (stat(un->sun_path, &st) == 0) continue;
1212 set_port(si->family, prt, si->myname);
1213 set_port(si->family, prt, si->bindname);
1215 break;
1217 if (prt == 10000) {
1218 errno = ENFILE;
1219 return -1;
1223 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1224 socket_wrapper_dir(), type, iface, prt);
1225 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1226 return 0;
1229 static struct socket_info *find_socket_info(int fd)
1231 struct socket_info *i;
1233 for (i = sockets; i; i = i->next) {
1234 struct socket_info_fd *f;
1235 for (f = i->fds; f; f = f->next) {
1236 if (f->fd == fd) {
1237 return i;
1242 return NULL;
1245 static void swrap_remove_stale(int fd)
1247 struct socket_info *si = find_socket_info(fd);
1248 struct socket_info_fd *fi;
1250 if (si != NULL) {
1251 for (fi = si->fds; fi; fi = fi->next) {
1252 if (fi->fd == fd) {
1253 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1254 SWRAP_DLIST_REMOVE(si->fds, fi);
1255 free(fi);
1256 break;
1260 if (si->fds == NULL) {
1261 SWRAP_DLIST_REMOVE(sockets, si);
1266 static int sockaddr_convert_to_un(struct socket_info *si,
1267 const struct sockaddr *in_addr,
1268 socklen_t in_len,
1269 struct sockaddr_un *out_addr,
1270 int alloc_sock,
1271 int *bcast)
1273 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1275 (void) in_len; /* unused */
1277 if (out_addr == NULL) {
1278 return 0;
1281 out->sa_family = AF_UNIX;
1282 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1283 out->sa_len = sizeof(*out_addr);
1284 #endif
1286 switch (in_addr->sa_family) {
1287 case AF_INET:
1288 #ifdef HAVE_IPV6
1289 case AF_INET6:
1290 #endif
1291 switch (si->type) {
1292 case SOCK_STREAM:
1293 case SOCK_DGRAM:
1294 break;
1295 default:
1296 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1297 errno = ESOCKTNOSUPPORT;
1298 return -1;
1300 if (alloc_sock) {
1301 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1302 } else {
1303 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1305 default:
1306 break;
1309 errno = EAFNOSUPPORT;
1310 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1311 return -1;
1314 static int sockaddr_convert_from_un(const struct socket_info *si,
1315 const struct sockaddr_un *in_addr,
1316 socklen_t un_addrlen,
1317 int family,
1318 struct sockaddr *out_addr,
1319 socklen_t *out_addrlen)
1321 int ret;
1323 if (out_addr == NULL || out_addrlen == NULL)
1324 return 0;
1326 if (un_addrlen == 0) {
1327 *out_addrlen = 0;
1328 return 0;
1331 switch (family) {
1332 case AF_INET:
1333 #ifdef HAVE_IPV6
1334 case AF_INET6:
1335 #endif
1336 switch (si->type) {
1337 case SOCK_STREAM:
1338 case SOCK_DGRAM:
1339 break;
1340 default:
1341 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1342 errno = ESOCKTNOSUPPORT;
1343 return -1;
1345 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1346 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1347 out_addr->sa_len = *out_addrlen;
1348 #endif
1349 return ret;
1350 default:
1351 break;
1354 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1355 errno = EAFNOSUPPORT;
1356 return -1;
1359 enum swrap_packet_type {
1360 SWRAP_CONNECT_SEND,
1361 SWRAP_CONNECT_UNREACH,
1362 SWRAP_CONNECT_RECV,
1363 SWRAP_CONNECT_ACK,
1364 SWRAP_ACCEPT_SEND,
1365 SWRAP_ACCEPT_RECV,
1366 SWRAP_ACCEPT_ACK,
1367 SWRAP_RECVFROM,
1368 SWRAP_SENDTO,
1369 SWRAP_SENDTO_UNREACH,
1370 SWRAP_PENDING_RST,
1371 SWRAP_RECV,
1372 SWRAP_RECV_RST,
1373 SWRAP_SEND,
1374 SWRAP_SEND_RST,
1375 SWRAP_CLOSE_SEND,
1376 SWRAP_CLOSE_RECV,
1377 SWRAP_CLOSE_ACK,
1380 struct swrap_file_hdr {
1381 uint32_t magic;
1382 uint16_t version_major;
1383 uint16_t version_minor;
1384 int32_t timezone;
1385 uint32_t sigfigs;
1386 uint32_t frame_max_len;
1387 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1388 uint32_t link_type;
1390 #define SWRAP_FILE_HDR_SIZE 24
1392 struct swrap_packet_frame {
1393 uint32_t seconds;
1394 uint32_t micro_seconds;
1395 uint32_t recorded_length;
1396 uint32_t full_length;
1398 #define SWRAP_PACKET_FRAME_SIZE 16
1400 union swrap_packet_ip {
1401 struct {
1402 uint8_t ver_hdrlen;
1403 uint8_t tos;
1404 uint16_t packet_length;
1405 uint16_t identification;
1406 uint8_t flags;
1407 uint8_t fragment;
1408 uint8_t ttl;
1409 uint8_t protocol;
1410 uint16_t hdr_checksum;
1411 uint32_t src_addr;
1412 uint32_t dest_addr;
1413 } v4;
1414 #define SWRAP_PACKET_IP_V4_SIZE 20
1415 struct {
1416 uint8_t ver_prio;
1417 uint8_t flow_label_high;
1418 uint16_t flow_label_low;
1419 uint16_t payload_length;
1420 uint8_t next_header;
1421 uint8_t hop_limit;
1422 uint8_t src_addr[16];
1423 uint8_t dest_addr[16];
1424 } v6;
1425 #define SWRAP_PACKET_IP_V6_SIZE 40
1427 #define SWRAP_PACKET_IP_SIZE 40
1429 union swrap_packet_payload {
1430 struct {
1431 uint16_t source_port;
1432 uint16_t dest_port;
1433 uint32_t seq_num;
1434 uint32_t ack_num;
1435 uint8_t hdr_length;
1436 uint8_t control;
1437 uint16_t window;
1438 uint16_t checksum;
1439 uint16_t urg;
1440 } tcp;
1441 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1442 struct {
1443 uint16_t source_port;
1444 uint16_t dest_port;
1445 uint16_t length;
1446 uint16_t checksum;
1447 } udp;
1448 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1449 struct {
1450 uint8_t type;
1451 uint8_t code;
1452 uint16_t checksum;
1453 uint32_t unused;
1454 } icmp4;
1455 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1456 struct {
1457 uint8_t type;
1458 uint8_t code;
1459 uint16_t checksum;
1460 uint32_t unused;
1461 } icmp6;
1462 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1464 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1466 #define SWRAP_PACKET_MIN_ALLOC \
1467 (SWRAP_PACKET_FRAME_SIZE + \
1468 SWRAP_PACKET_IP_SIZE + \
1469 SWRAP_PACKET_PAYLOAD_SIZE)
1471 static const char *socket_wrapper_pcap_file(void)
1473 static int initialized = 0;
1474 static const char *s = NULL;
1475 static const struct swrap_file_hdr h;
1476 static const struct swrap_packet_frame f;
1477 static const union swrap_packet_ip i;
1478 static const union swrap_packet_payload p;
1480 if (initialized == 1) {
1481 return s;
1483 initialized = 1;
1486 * TODO: don't use the structs use plain buffer offsets
1487 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1489 * for now make sure we disable PCAP support
1490 * if the struct has alignment!
1492 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1493 return NULL;
1495 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1496 return NULL;
1498 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1499 return NULL;
1501 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1502 return NULL;
1504 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1505 return NULL;
1507 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1508 return NULL;
1510 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1511 return NULL;
1513 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1514 return NULL;
1516 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1517 return NULL;
1519 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1520 return NULL;
1523 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1524 if (s == NULL) {
1525 return NULL;
1527 if (strncmp(s, "./", 2) == 0) {
1528 s += 2;
1530 return s;
1533 static uint8_t *swrap_packet_init(struct timeval *tval,
1534 const struct sockaddr *src,
1535 const struct sockaddr *dest,
1536 int socket_type,
1537 const uint8_t *payload,
1538 size_t payload_len,
1539 unsigned long tcp_seqno,
1540 unsigned long tcp_ack,
1541 unsigned char tcp_ctl,
1542 int unreachable,
1543 size_t *_packet_len)
1545 uint8_t *base;
1546 uint8_t *buf;
1547 struct swrap_packet_frame *frame;
1548 union swrap_packet_ip *ip;
1549 union swrap_packet_payload *pay;
1550 size_t packet_len;
1551 size_t alloc_len;
1552 size_t nonwire_len = sizeof(*frame);
1553 size_t wire_hdr_len = 0;
1554 size_t wire_len = 0;
1555 size_t ip_hdr_len = 0;
1556 size_t icmp_hdr_len = 0;
1557 size_t icmp_truncate_len = 0;
1558 uint8_t protocol = 0, icmp_protocol = 0;
1559 const struct sockaddr_in *src_in = NULL;
1560 const struct sockaddr_in *dest_in = NULL;
1561 #ifdef HAVE_IPV6
1562 const struct sockaddr_in6 *src_in6 = NULL;
1563 const struct sockaddr_in6 *dest_in6 = NULL;
1564 #endif
1565 uint16_t src_port;
1566 uint16_t dest_port;
1568 switch (src->sa_family) {
1569 case AF_INET:
1570 src_in = (const struct sockaddr_in *)src;
1571 dest_in = (const struct sockaddr_in *)dest;
1572 src_port = src_in->sin_port;
1573 dest_port = dest_in->sin_port;
1574 ip_hdr_len = sizeof(ip->v4);
1575 break;
1576 #ifdef HAVE_IPV6
1577 case AF_INET6:
1578 src_in6 = (const struct sockaddr_in6 *)src;
1579 dest_in6 = (const struct sockaddr_in6 *)dest;
1580 src_port = src_in6->sin6_port;
1581 dest_port = dest_in6->sin6_port;
1582 ip_hdr_len = sizeof(ip->v6);
1583 break;
1584 #endif
1585 default:
1586 return NULL;
1589 switch (socket_type) {
1590 case SOCK_STREAM:
1591 protocol = 0x06; /* TCP */
1592 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1593 wire_len = wire_hdr_len + payload_len;
1594 break;
1596 case SOCK_DGRAM:
1597 protocol = 0x11; /* UDP */
1598 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1599 wire_len = wire_hdr_len + payload_len;
1600 break;
1602 default:
1603 return NULL;
1606 if (unreachable) {
1607 icmp_protocol = protocol;
1608 switch (src->sa_family) {
1609 case AF_INET:
1610 protocol = 0x01; /* ICMPv4 */
1611 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1612 break;
1613 #ifdef HAVE_IPV6
1614 case AF_INET6:
1615 protocol = 0x3A; /* ICMPv6 */
1616 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1617 break;
1618 #endif
1620 if (wire_len > 64 ) {
1621 icmp_truncate_len = wire_len - 64;
1623 wire_hdr_len += icmp_hdr_len;
1624 wire_len += icmp_hdr_len;
1627 packet_len = nonwire_len + wire_len;
1628 alloc_len = packet_len;
1629 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1630 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1633 base = (uint8_t *)malloc(alloc_len);
1634 if (base == NULL) {
1635 return NULL;
1637 memset(base, 0x0, alloc_len);
1639 buf = base;
1641 frame = (struct swrap_packet_frame *)buf;
1642 frame->seconds = tval->tv_sec;
1643 frame->micro_seconds = tval->tv_usec;
1644 frame->recorded_length = wire_len - icmp_truncate_len;
1645 frame->full_length = wire_len - icmp_truncate_len;
1646 buf += SWRAP_PACKET_FRAME_SIZE;
1648 ip = (union swrap_packet_ip *)buf;
1649 switch (src->sa_family) {
1650 case AF_INET:
1651 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1652 ip->v4.tos = 0x00;
1653 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1654 ip->v4.identification = htons(0xFFFF);
1655 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1656 ip->v4.fragment = htons(0x0000);
1657 ip->v4.ttl = 0xFF;
1658 ip->v4.protocol = protocol;
1659 ip->v4.hdr_checksum = htons(0x0000);
1660 ip->v4.src_addr = src_in->sin_addr.s_addr;
1661 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1662 buf += SWRAP_PACKET_IP_V4_SIZE;
1663 break;
1664 #ifdef HAVE_IPV6
1665 case AF_INET6:
1666 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1667 ip->v6.flow_label_high = 0x00;
1668 ip->v6.flow_label_low = 0x0000;
1669 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1670 ip->v6.next_header = protocol;
1671 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1672 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1673 buf += SWRAP_PACKET_IP_V6_SIZE;
1674 break;
1675 #endif
1678 if (unreachable) {
1679 pay = (union swrap_packet_payload *)buf;
1680 switch (src->sa_family) {
1681 case AF_INET:
1682 pay->icmp4.type = 0x03; /* destination unreachable */
1683 pay->icmp4.code = 0x01; /* host unreachable */
1684 pay->icmp4.checksum = htons(0x0000);
1685 pay->icmp4.unused = htonl(0x00000000);
1686 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1688 /* set the ip header in the ICMP payload */
1689 ip = (union swrap_packet_ip *)buf;
1690 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1691 ip->v4.tos = 0x00;
1692 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1693 ip->v4.identification = htons(0xFFFF);
1694 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1695 ip->v4.fragment = htons(0x0000);
1696 ip->v4.ttl = 0xFF;
1697 ip->v4.protocol = icmp_protocol;
1698 ip->v4.hdr_checksum = htons(0x0000);
1699 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1700 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1701 buf += SWRAP_PACKET_IP_V4_SIZE;
1703 src_port = dest_in->sin_port;
1704 dest_port = src_in->sin_port;
1705 break;
1706 #ifdef HAVE_IPV6
1707 case AF_INET6:
1708 pay->icmp6.type = 0x01; /* destination unreachable */
1709 pay->icmp6.code = 0x03; /* address unreachable */
1710 pay->icmp6.checksum = htons(0x0000);
1711 pay->icmp6.unused = htonl(0x00000000);
1712 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1714 /* set the ip header in the ICMP payload */
1715 ip = (union swrap_packet_ip *)buf;
1716 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1717 ip->v6.flow_label_high = 0x00;
1718 ip->v6.flow_label_low = 0x0000;
1719 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1720 ip->v6.next_header = protocol;
1721 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1722 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1723 buf += SWRAP_PACKET_IP_V6_SIZE;
1725 src_port = dest_in6->sin6_port;
1726 dest_port = src_in6->sin6_port;
1727 break;
1728 #endif
1732 pay = (union swrap_packet_payload *)buf;
1734 switch (socket_type) {
1735 case SOCK_STREAM:
1736 pay->tcp.source_port = src_port;
1737 pay->tcp.dest_port = dest_port;
1738 pay->tcp.seq_num = htonl(tcp_seqno);
1739 pay->tcp.ack_num = htonl(tcp_ack);
1740 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1741 pay->tcp.control = tcp_ctl;
1742 pay->tcp.window = htons(0x7FFF);
1743 pay->tcp.checksum = htons(0x0000);
1744 pay->tcp.urg = htons(0x0000);
1745 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1747 break;
1749 case SOCK_DGRAM:
1750 pay->udp.source_port = src_port;
1751 pay->udp.dest_port = dest_port;
1752 pay->udp.length = htons(8 + payload_len);
1753 pay->udp.checksum = htons(0x0000);
1754 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1756 break;
1759 if (payload && payload_len > 0) {
1760 memcpy(buf, payload, payload_len);
1763 *_packet_len = packet_len - icmp_truncate_len;
1764 return base;
1767 static int swrap_get_pcap_fd(const char *fname)
1769 static int fd = -1;
1771 if (fd != -1) return fd;
1773 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1774 if (fd != -1) {
1775 struct swrap_file_hdr file_hdr;
1776 file_hdr.magic = 0xA1B2C3D4;
1777 file_hdr.version_major = 0x0002;
1778 file_hdr.version_minor = 0x0004;
1779 file_hdr.timezone = 0x00000000;
1780 file_hdr.sigfigs = 0x00000000;
1781 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1782 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1784 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1785 close(fd);
1786 fd = -1;
1788 return fd;
1791 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1793 return fd;
1796 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1797 const struct sockaddr *addr,
1798 enum swrap_packet_type type,
1799 const void *buf, size_t len,
1800 size_t *packet_len)
1802 const struct sockaddr *src_addr;
1803 const struct sockaddr *dest_addr;
1804 unsigned long tcp_seqno = 0;
1805 unsigned long tcp_ack = 0;
1806 unsigned char tcp_ctl = 0;
1807 int unreachable = 0;
1809 struct timeval tv;
1811 switch (si->family) {
1812 case AF_INET:
1813 break;
1814 #ifdef HAVE_IPV6
1815 case AF_INET6:
1816 break;
1817 #endif
1818 default:
1819 return NULL;
1822 switch (type) {
1823 case SWRAP_CONNECT_SEND:
1824 if (si->type != SOCK_STREAM) return NULL;
1826 src_addr = si->myname;
1827 dest_addr = addr;
1829 tcp_seqno = si->io.pck_snd;
1830 tcp_ack = si->io.pck_rcv;
1831 tcp_ctl = 0x02; /* SYN */
1833 si->io.pck_snd += 1;
1835 break;
1837 case SWRAP_CONNECT_RECV:
1838 if (si->type != SOCK_STREAM) return NULL;
1840 dest_addr = si->myname;
1841 src_addr = addr;
1843 tcp_seqno = si->io.pck_rcv;
1844 tcp_ack = si->io.pck_snd;
1845 tcp_ctl = 0x12; /** SYN,ACK */
1847 si->io.pck_rcv += 1;
1849 break;
1851 case SWRAP_CONNECT_UNREACH:
1852 if (si->type != SOCK_STREAM) return NULL;
1854 dest_addr = si->myname;
1855 src_addr = addr;
1857 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1858 tcp_seqno = si->io.pck_snd - 1;
1859 tcp_ack = si->io.pck_rcv;
1860 tcp_ctl = 0x02; /* SYN */
1861 unreachable = 1;
1863 break;
1865 case SWRAP_CONNECT_ACK:
1866 if (si->type != SOCK_STREAM) return NULL;
1868 src_addr = si->myname;
1869 dest_addr = addr;
1871 tcp_seqno = si->io.pck_snd;
1872 tcp_ack = si->io.pck_rcv;
1873 tcp_ctl = 0x10; /* ACK */
1875 break;
1877 case SWRAP_ACCEPT_SEND:
1878 if (si->type != SOCK_STREAM) return NULL;
1880 dest_addr = si->myname;
1881 src_addr = addr;
1883 tcp_seqno = si->io.pck_rcv;
1884 tcp_ack = si->io.pck_snd;
1885 tcp_ctl = 0x02; /* SYN */
1887 si->io.pck_rcv += 1;
1889 break;
1891 case SWRAP_ACCEPT_RECV:
1892 if (si->type != SOCK_STREAM) return NULL;
1894 src_addr = si->myname;
1895 dest_addr = addr;
1897 tcp_seqno = si->io.pck_snd;
1898 tcp_ack = si->io.pck_rcv;
1899 tcp_ctl = 0x12; /* SYN,ACK */
1901 si->io.pck_snd += 1;
1903 break;
1905 case SWRAP_ACCEPT_ACK:
1906 if (si->type != SOCK_STREAM) return NULL;
1908 dest_addr = si->myname;
1909 src_addr = addr;
1911 tcp_seqno = si->io.pck_rcv;
1912 tcp_ack = si->io.pck_snd;
1913 tcp_ctl = 0x10; /* ACK */
1915 break;
1917 case SWRAP_SEND:
1918 src_addr = si->myname;
1919 dest_addr = si->peername;
1921 tcp_seqno = si->io.pck_snd;
1922 tcp_ack = si->io.pck_rcv;
1923 tcp_ctl = 0x18; /* PSH,ACK */
1925 si->io.pck_snd += len;
1927 break;
1929 case SWRAP_SEND_RST:
1930 dest_addr = si->myname;
1931 src_addr = si->peername;
1933 if (si->type == SOCK_DGRAM) {
1934 return swrap_marshall_packet(si, si->peername,
1935 SWRAP_SENDTO_UNREACH,
1936 buf, len, packet_len);
1939 tcp_seqno = si->io.pck_rcv;
1940 tcp_ack = si->io.pck_snd;
1941 tcp_ctl = 0x14; /** RST,ACK */
1943 break;
1945 case SWRAP_PENDING_RST:
1946 dest_addr = si->myname;
1947 src_addr = si->peername;
1949 if (si->type == SOCK_DGRAM) {
1950 return NULL;
1953 tcp_seqno = si->io.pck_rcv;
1954 tcp_ack = si->io.pck_snd;
1955 tcp_ctl = 0x14; /* RST,ACK */
1957 break;
1959 case SWRAP_RECV:
1960 dest_addr = si->myname;
1961 src_addr = si->peername;
1963 tcp_seqno = si->io.pck_rcv;
1964 tcp_ack = si->io.pck_snd;
1965 tcp_ctl = 0x18; /* PSH,ACK */
1967 si->io.pck_rcv += len;
1969 break;
1971 case SWRAP_RECV_RST:
1972 dest_addr = si->myname;
1973 src_addr = si->peername;
1975 if (si->type == SOCK_DGRAM) {
1976 return NULL;
1979 tcp_seqno = si->io.pck_rcv;
1980 tcp_ack = si->io.pck_snd;
1981 tcp_ctl = 0x14; /* RST,ACK */
1983 break;
1985 case SWRAP_SENDTO:
1986 src_addr = si->myname;
1987 dest_addr = addr;
1989 si->io.pck_snd += len;
1991 break;
1993 case SWRAP_SENDTO_UNREACH:
1994 dest_addr = si->myname;
1995 src_addr = addr;
1997 unreachable = 1;
1999 break;
2001 case SWRAP_RECVFROM:
2002 dest_addr = si->myname;
2003 src_addr = addr;
2005 si->io.pck_rcv += len;
2007 break;
2009 case SWRAP_CLOSE_SEND:
2010 if (si->type != SOCK_STREAM) return NULL;
2012 src_addr = si->myname;
2013 dest_addr = si->peername;
2015 tcp_seqno = si->io.pck_snd;
2016 tcp_ack = si->io.pck_rcv;
2017 tcp_ctl = 0x11; /* FIN, ACK */
2019 si->io.pck_snd += 1;
2021 break;
2023 case SWRAP_CLOSE_RECV:
2024 if (si->type != SOCK_STREAM) return NULL;
2026 dest_addr = si->myname;
2027 src_addr = si->peername;
2029 tcp_seqno = si->io.pck_rcv;
2030 tcp_ack = si->io.pck_snd;
2031 tcp_ctl = 0x11; /* FIN,ACK */
2033 si->io.pck_rcv += 1;
2035 break;
2037 case SWRAP_CLOSE_ACK:
2038 if (si->type != SOCK_STREAM) return NULL;
2040 src_addr = si->myname;
2041 dest_addr = si->peername;
2043 tcp_seqno = si->io.pck_snd;
2044 tcp_ack = si->io.pck_rcv;
2045 tcp_ctl = 0x10; /* ACK */
2047 break;
2048 default:
2049 return NULL;
2052 swrapGetTimeOfDay(&tv);
2054 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2055 (const uint8_t *)buf, len,
2056 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2057 packet_len);
2060 static void swrap_dump_packet(struct socket_info *si,
2061 const struct sockaddr *addr,
2062 enum swrap_packet_type type,
2063 const void *buf, size_t len)
2065 const char *file_name;
2066 uint8_t *packet;
2067 size_t packet_len = 0;
2068 int fd;
2070 file_name = socket_wrapper_pcap_file();
2071 if (!file_name) {
2072 return;
2075 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2076 if (!packet) {
2077 return;
2080 fd = swrap_get_pcap_fd(file_name);
2081 if (fd != -1) {
2082 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2083 free(packet);
2084 return;
2088 free(packet);
2091 /****************************************************************************
2092 * SIGNALFD
2093 ***************************************************************************/
2095 #ifdef HAVE_SIGNALFD
2096 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2098 int rc;
2100 rc = libc_signalfd(fd, mask, flags);
2101 if (rc != -1) {
2102 swrap_remove_stale(fd);
2105 return rc;
2108 int signalfd(int fd, const sigset_t *mask, int flags)
2110 return swrap_signalfd(fd, mask, flags);
2112 #endif
2114 /****************************************************************************
2115 * SOCKET
2116 ***************************************************************************/
2118 static int swrap_socket(int family, int type, int protocol)
2120 struct socket_info *si;
2121 struct socket_info_fd *fi;
2122 int fd;
2123 int real_type = type;
2126 * Remove possible addition flags passed to socket() so
2127 * do not fail checking the type.
2128 * See https://lwn.net/Articles/281965/
2130 #ifdef SOCK_CLOEXEC
2131 real_type &= ~SOCK_CLOEXEC;
2132 #endif
2133 #ifdef SOCK_NONBLOCK
2134 real_type &= ~SOCK_NONBLOCK;
2135 #endif
2137 if (!socket_wrapper_enabled()) {
2138 return libc_socket(family, type, protocol);
2141 switch (family) {
2142 case AF_INET:
2143 #ifdef HAVE_IPV6
2144 case AF_INET6:
2145 #endif
2146 break;
2147 case AF_UNIX:
2148 return libc_socket(family, type, protocol);
2149 default:
2150 errno = EAFNOSUPPORT;
2151 return -1;
2154 switch (real_type) {
2155 case SOCK_STREAM:
2156 break;
2157 case SOCK_DGRAM:
2158 break;
2159 default:
2160 errno = EPROTONOSUPPORT;
2161 return -1;
2164 switch (protocol) {
2165 case 0:
2166 break;
2167 case 6:
2168 if (real_type == SOCK_STREAM) {
2169 break;
2171 /*fall through*/
2172 case 17:
2173 if (real_type == SOCK_DGRAM) {
2174 break;
2176 /*fall through*/
2177 default:
2178 errno = EPROTONOSUPPORT;
2179 return -1;
2183 * We must call libc_socket with type, from the caller, not the version
2184 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2186 fd = libc_socket(AF_UNIX, type, 0);
2188 if (fd == -1) {
2189 return -1;
2192 /* Check if we have a stale fd and remove it */
2193 si = find_socket_info(fd);
2194 if (si != NULL) {
2195 swrap_remove_stale(fd);
2198 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2199 memset(si, 0, sizeof(struct socket_info));
2200 if (si == NULL) {
2201 errno = ENOMEM;
2202 return -1;
2205 si->family = family;
2207 /* however, the rest of the socket_wrapper code expects just
2208 * the type, not the flags */
2209 si->type = real_type;
2210 si->protocol = protocol;
2212 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2213 if (fi == NULL) {
2214 free(si);
2215 errno = ENOMEM;
2216 return -1;
2219 fi->fd = fd;
2221 SWRAP_DLIST_ADD(si->fds, fi);
2222 SWRAP_DLIST_ADD(sockets, si);
2224 return fd;
2227 int socket(int family, int type, int protocol)
2229 return swrap_socket(family, type, protocol);
2232 /****************************************************************************
2233 * SOCKETPAIR
2234 ***************************************************************************/
2236 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2238 int rc;
2240 rc = libc_socketpair(family, type, protocol, sv);
2241 if (rc != -1) {
2242 swrap_remove_stale(sv[0]);
2243 swrap_remove_stale(sv[1]);
2246 return rc;
2249 int socketpair(int family, int type, int protocol, int sv[2])
2251 return swrap_socketpair(family, type, protocol, sv);
2254 /****************************************************************************
2255 * SOCKETPAIR
2256 ***************************************************************************/
2258 #ifdef HAVE_TIMERFD_CREATE
2259 static int swrap_timerfd_create(int clockid, int flags)
2261 int fd;
2263 fd = libc_timerfd_create(clockid, flags);
2264 if (fd != -1) {
2265 swrap_remove_stale(fd);
2268 return fd;
2271 int timerfd_create(int clockid, int flags)
2273 return swrap_timerfd_create(clockid, flags);
2275 #endif
2277 /****************************************************************************
2278 * PIPE
2279 ***************************************************************************/
2281 static int swrap_pipe(int pipefd[2])
2283 int rc;
2285 rc = libc_pipe(pipefd);
2286 if (rc != -1) {
2287 swrap_remove_stale(pipefd[0]);
2288 swrap_remove_stale(pipefd[1]);
2291 return rc;
2294 int pipe(int pipefd[2])
2296 return swrap_pipe(pipefd);
2299 /****************************************************************************
2300 * ACCEPT
2301 ***************************************************************************/
2303 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2305 struct socket_info *parent_si, *child_si;
2306 struct socket_info_fd *child_fi;
2307 int fd;
2308 struct sockaddr_un un_addr;
2309 socklen_t un_addrlen = sizeof(un_addr);
2310 struct sockaddr_un un_my_addr;
2311 socklen_t un_my_addrlen = sizeof(un_my_addr);
2312 struct sockaddr *my_addr;
2313 socklen_t my_addrlen, len;
2314 int ret;
2316 parent_si = find_socket_info(s);
2317 if (!parent_si) {
2318 return libc_accept(s, addr, addrlen);
2322 * assume out sockaddr have the same size as the in parent
2323 * socket family
2325 my_addrlen = socket_length(parent_si->family);
2326 if (my_addrlen <= 0) {
2327 errno = EINVAL;
2328 return -1;
2331 my_addr = (struct sockaddr *)malloc(my_addrlen);
2332 if (my_addr == NULL) {
2333 return -1;
2336 memset(&un_addr, 0, sizeof(un_addr));
2337 memset(&un_my_addr, 0, sizeof(un_my_addr));
2339 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2340 if (ret == -1) {
2341 if (errno == ENOTSOCK) {
2342 /* Remove stale fds */
2343 swrap_remove_stale(s);
2345 free(my_addr);
2346 return ret;
2349 fd = ret;
2351 len = my_addrlen;
2352 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2353 parent_si->family, my_addr, &len);
2354 if (ret == -1) {
2355 free(my_addr);
2356 close(fd);
2357 return ret;
2360 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2361 memset(child_si, 0, sizeof(struct socket_info));
2363 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2364 if (child_fi == NULL) {
2365 free(child_si);
2366 free(my_addr);
2367 close(fd);
2368 errno = ENOMEM;
2369 return -1;
2372 child_fi->fd = fd;
2374 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2376 child_si->family = parent_si->family;
2377 child_si->type = parent_si->type;
2378 child_si->protocol = parent_si->protocol;
2379 child_si->bound = 1;
2380 child_si->is_server = 1;
2381 child_si->connected = 1;
2383 child_si->peername_len = len;
2384 child_si->peername = sockaddr_dup(my_addr, len);
2386 if (addr != NULL && addrlen != NULL) {
2387 size_t copy_len = MIN(*addrlen, len);
2388 if (copy_len > 0) {
2389 memcpy(addr, my_addr, copy_len);
2391 *addrlen = len;
2394 ret = libc_getsockname(fd,
2395 (struct sockaddr *)(void *)&un_my_addr,
2396 &un_my_addrlen);
2397 if (ret == -1) {
2398 free(child_fi);
2399 free(child_si);
2400 free(my_addr);
2401 close(fd);
2402 return ret;
2405 len = my_addrlen;
2406 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2407 child_si->family, my_addr, &len);
2408 if (ret == -1) {
2409 free(child_fi);
2410 free(child_si);
2411 free(my_addr);
2412 close(fd);
2413 return ret;
2416 SWRAP_LOG(SWRAP_LOG_TRACE,
2417 "accept() path=%s, fd=%d",
2418 un_my_addr.sun_path, s);
2420 child_si->myname_len = len;
2421 child_si->myname = sockaddr_dup(my_addr, len);
2422 free(my_addr);
2424 SWRAP_DLIST_ADD(sockets, child_si);
2426 if (addr != NULL) {
2427 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2428 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2429 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2432 return fd;
2435 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2436 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2437 #else
2438 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2439 #endif
2441 return swrap_accept(s, addr, (socklen_t *)addrlen);
2444 static int autobind_start_init;
2445 static int autobind_start;
2447 /* using sendto() or connect() on an unbound socket would give the
2448 recipient no way to reply, as unlike UDP and TCP, a unix domain
2449 socket can't auto-assign ephemeral port numbers, so we need to
2450 assign it here.
2451 Note: this might change the family from ipv6 to ipv4
2453 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2455 struct sockaddr_un un_addr;
2456 int i;
2457 char type;
2458 int ret;
2459 int port;
2460 struct stat st;
2462 if (autobind_start_init != 1) {
2463 autobind_start_init = 1;
2464 autobind_start = getpid();
2465 autobind_start %= 50000;
2466 autobind_start += 10000;
2469 un_addr.sun_family = AF_UNIX;
2471 switch (family) {
2472 case AF_INET: {
2473 struct sockaddr_in in;
2475 switch (si->type) {
2476 case SOCK_STREAM:
2477 type = SOCKET_TYPE_CHAR_TCP;
2478 break;
2479 case SOCK_DGRAM:
2480 type = SOCKET_TYPE_CHAR_UDP;
2481 break;
2482 default:
2483 errno = ESOCKTNOSUPPORT;
2484 return -1;
2487 memset(&in, 0, sizeof(in));
2488 in.sin_family = AF_INET;
2489 in.sin_addr.s_addr = htonl(127<<24 |
2490 socket_wrapper_default_iface());
2492 si->myname_len = sizeof(in);
2493 si->myname = sockaddr_dup(&in, si->myname_len);
2494 break;
2496 #ifdef HAVE_IPV6
2497 case AF_INET6: {
2498 struct sockaddr_in6 in6;
2500 if (si->family != family) {
2501 errno = ENETUNREACH;
2502 return -1;
2505 switch (si->type) {
2506 case SOCK_STREAM:
2507 type = SOCKET_TYPE_CHAR_TCP_V6;
2508 break;
2509 case SOCK_DGRAM:
2510 type = SOCKET_TYPE_CHAR_UDP_V6;
2511 break;
2512 default:
2513 errno = ESOCKTNOSUPPORT;
2514 return -1;
2517 memset(&in6, 0, sizeof(in6));
2518 in6.sin6_family = AF_INET6;
2519 in6.sin6_addr = *swrap_ipv6();
2520 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2521 si->myname_len = sizeof(in6);
2522 si->myname = sockaddr_dup(&in6, si->myname_len);
2523 break;
2525 #endif
2526 default:
2527 errno = ESOCKTNOSUPPORT;
2528 return -1;
2531 if (autobind_start > 60000) {
2532 autobind_start = 10000;
2535 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2536 port = autobind_start + i;
2537 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2538 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2539 type, socket_wrapper_default_iface(), port);
2540 if (stat(un_addr.sun_path, &st) == 0) continue;
2542 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2543 sizeof(un_addr));
2544 if (ret == -1) return ret;
2546 si->tmp_path = strdup(un_addr.sun_path);
2547 si->bound = 1;
2548 autobind_start = port + 1;
2549 break;
2551 if (i == SOCKET_MAX_SOCKETS) {
2552 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2553 "interface "SOCKET_FORMAT,
2554 SOCKET_MAX_SOCKETS,
2555 type,
2556 socket_wrapper_default_iface(),
2558 errno = ENFILE;
2559 return -1;
2562 si->family = family;
2563 set_port(si->family, port, si->myname);
2565 return 0;
2568 /****************************************************************************
2569 * CONNECT
2570 ***************************************************************************/
2572 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2573 socklen_t addrlen)
2575 int ret;
2576 struct sockaddr_un un_addr;
2577 struct socket_info *si = find_socket_info(s);
2578 int bcast = 0;
2580 if (!si) {
2581 return libc_connect(s, serv_addr, addrlen);
2584 if (si->bound == 0) {
2585 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2586 if (ret == -1) return -1;
2589 if (si->family != serv_addr->sa_family) {
2590 errno = EINVAL;
2591 return -1;
2594 ret = sockaddr_convert_to_un(si, serv_addr,
2595 addrlen, &un_addr, 0, &bcast);
2596 if (ret == -1) return -1;
2598 if (bcast) {
2599 errno = ENETUNREACH;
2600 return -1;
2603 if (si->type == SOCK_DGRAM) {
2604 si->defer_connect = 1;
2605 ret = 0;
2606 } else {
2607 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2609 ret = libc_connect(s,
2610 (struct sockaddr *)(void *)&un_addr,
2611 sizeof(struct sockaddr_un));
2614 SWRAP_LOG(SWRAP_LOG_TRACE,
2615 "connect() path=%s, fd=%d",
2616 un_addr.sun_path, s);
2619 /* to give better errors */
2620 if (ret == -1 && errno == ENOENT) {
2621 errno = EHOSTUNREACH;
2624 if (ret == 0) {
2625 si->peername_len = addrlen;
2626 si->peername = sockaddr_dup(serv_addr, addrlen);
2627 si->connected = 1;
2630 * When we connect() on a socket than we have to bind the
2631 * outgoing connection on the interface we use for the
2632 * transport. We already bound it on the right interface
2633 * but here we have to update the name so getsockname()
2634 * returns correct information.
2636 if (si->bindname != NULL) {
2637 free(si->myname);
2639 si->myname = si->bindname;
2640 si->myname_len = si->bindname_len;
2642 si->bindname = NULL;
2643 si->bindname_len = 0;
2646 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2647 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2648 } else {
2649 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2652 return ret;
2655 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2657 return swrap_connect(s, serv_addr, addrlen);
2660 /****************************************************************************
2661 * BIND
2662 ***************************************************************************/
2664 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2666 int ret;
2667 struct sockaddr_un un_addr;
2668 struct socket_info *si = find_socket_info(s);
2670 if (!si) {
2671 return libc_bind(s, myaddr, addrlen);
2674 si->myname_len = addrlen;
2675 si->myname = sockaddr_dup(myaddr, addrlen);
2677 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2678 if (ret == -1) return -1;
2680 unlink(un_addr.sun_path);
2682 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2683 sizeof(struct sockaddr_un));
2685 SWRAP_LOG(SWRAP_LOG_TRACE,
2686 "bind() path=%s, fd=%d",
2687 un_addr.sun_path, s);
2689 if (ret == 0) {
2690 si->bound = 1;
2693 return ret;
2696 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2698 return swrap_bind(s, myaddr, addrlen);
2701 /****************************************************************************
2702 * LISTEN
2703 ***************************************************************************/
2705 static int swrap_listen(int s, int backlog)
2707 int ret;
2708 struct socket_info *si = find_socket_info(s);
2710 if (!si) {
2711 return libc_listen(s, backlog);
2714 ret = libc_listen(s, backlog);
2716 return ret;
2719 int listen(int s, int backlog)
2721 return swrap_listen(s, backlog);
2724 /****************************************************************************
2725 * OPEN
2726 ***************************************************************************/
2728 static int swrap_vopen(const char *pathname, int flags, va_list ap)
2730 int ret;
2732 ret = libc_vopen(pathname, flags, ap);
2733 if (ret != -1) {
2735 * There are methods for closing descriptors (libc-internal code
2736 * paths, direct syscalls) which close descriptors in ways that
2737 * we can't intercept, so try to recover when we notice that
2738 * that's happened
2740 swrap_remove_stale(ret);
2742 return ret;
2745 int open(const char *pathname, int flags, ...)
2747 va_list ap;
2748 int fd;
2750 va_start(ap, flags);
2751 fd = swrap_vopen(pathname, flags, ap);
2752 va_end(ap);
2754 return fd;
2757 /****************************************************************************
2758 * GETPEERNAME
2759 ***************************************************************************/
2761 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2763 struct socket_info *si = find_socket_info(s);
2765 if (!si) {
2766 return libc_getpeername(s, name, addrlen);
2769 if (!si->peername)
2771 errno = ENOTCONN;
2772 return -1;
2775 memcpy(name, si->peername, si->peername_len);
2776 *addrlen = si->peername_len;
2778 return 0;
2781 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2782 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
2783 #else
2784 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2785 #endif
2787 return swrap_getpeername(s, name, (socklen_t *)addrlen);
2790 /****************************************************************************
2791 * GETSOCKNAME
2792 ***************************************************************************/
2794 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2796 struct socket_info *si = find_socket_info(s);
2798 if (!si) {
2799 return libc_getsockname(s, name, addrlen);
2802 memcpy(name, si->myname, si->myname_len);
2803 *addrlen = si->myname_len;
2805 return 0;
2808 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2809 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
2810 #else
2811 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2812 #endif
2814 return swrap_getsockname(s, name, (socklen_t *)addrlen);
2817 /****************************************************************************
2818 * GETSOCKOPT
2819 ***************************************************************************/
2821 static int swrap_getsockopt(int s, int level, int optname,
2822 void *optval, socklen_t *optlen)
2824 struct socket_info *si = find_socket_info(s);
2826 if (!si) {
2827 return libc_getsockopt(s,
2828 level,
2829 optname,
2830 optval,
2831 optlen);
2834 if (level == SOL_SOCKET) {
2835 return libc_getsockopt(s,
2836 level,
2837 optname,
2838 optval,
2839 optlen);
2842 errno = ENOPROTOOPT;
2843 return -1;
2846 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2847 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
2848 #else
2849 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
2850 #endif
2852 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
2855 /****************************************************************************
2856 * SETSOCKOPT
2857 ***************************************************************************/
2859 static int swrap_setsockopt(int s, int level, int optname,
2860 const void *optval, socklen_t optlen)
2862 struct socket_info *si = find_socket_info(s);
2864 if (!si) {
2865 return libc_setsockopt(s,
2866 level,
2867 optname,
2868 optval,
2869 optlen);
2872 if (level == SOL_SOCKET) {
2873 return libc_setsockopt(s,
2874 level,
2875 optname,
2876 optval,
2877 optlen);
2880 switch (si->family) {
2881 case AF_INET:
2882 if (level == IPPROTO_IP) {
2883 #ifdef IP_PKTINFO
2884 if (optname == IP_PKTINFO) {
2885 si->pktinfo = AF_INET;
2887 #endif /* IP_PKTINFO */
2889 return 0;
2890 #ifdef HAVE_IPV6
2891 case AF_INET6:
2892 if (level == IPPROTO_IPV6) {
2893 #ifdef IPV6_RECVPKTINFO
2894 if (optname == IPV6_RECVPKTINFO) {
2895 si->pktinfo = AF_INET6;
2897 #endif /* IPV6_PKTINFO */
2899 return 0;
2900 #endif
2901 default:
2902 errno = ENOPROTOOPT;
2903 return -1;
2907 int setsockopt(int s, int level, int optname,
2908 const void *optval, socklen_t optlen)
2910 return swrap_setsockopt(s, level, optname, optval, optlen);
2913 /****************************************************************************
2914 * IOCTL
2915 ***************************************************************************/
2917 static int swrap_vioctl(int s, unsigned long int r, va_list va)
2919 struct socket_info *si = find_socket_info(s);
2920 va_list ap;
2921 int value;
2922 int rc;
2924 if (!si) {
2925 return libc_vioctl(s, r, va);
2928 va_copy(ap, va);
2930 rc = libc_vioctl(s, r, va);
2932 switch (r) {
2933 case FIONREAD:
2934 value = *((int *)va_arg(ap, int *));
2936 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
2937 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2938 } else if (value == 0) { /* END OF FILE */
2939 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2941 break;
2944 va_end(ap);
2946 return rc;
2949 #ifdef HAVE_IOCTL_INT
2950 int ioctl(int s, int r, ...)
2951 #else
2952 int ioctl(int s, unsigned long int r, ...)
2953 #endif
2955 va_list va;
2956 int rc;
2958 va_start(va, r);
2960 rc = swrap_vioctl(s, (unsigned long int) r, va);
2962 va_end(va);
2964 return rc;
2967 /*****************
2968 * CMSG
2969 *****************/
2971 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2973 * @brief Add a cmsghdr to a msghdr.
2975 * This is an function to add any type of cmsghdr. It will operate on the
2976 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
2977 * the buffer position after the added cmsg element. Hence, this function is
2978 * intended to be used with an intermediate msghdr and not on the original
2979 * one handed in by the client.
2981 * @param[in] msg The msghdr to which to add the cmsg.
2983 * @param[in] level The cmsg level to set.
2985 * @param[in] type The cmsg type to set.
2987 * @param[in] data The cmsg data to set.
2989 * @param[in] len the length of the data to set.
2991 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
2992 int level,
2993 int type,
2994 const void *data,
2995 size_t len)
2997 size_t cmlen = CMSG_LEN(len);
2998 size_t cmspace = CMSG_SPACE(len);
2999 uint8_t cmbuf[cmspace];
3000 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3001 uint8_t *p;
3003 memset(cmbuf, 0, cmspace);
3005 if (msg->msg_controllen < cmlen) {
3006 cmlen = msg->msg_controllen;
3007 msg->msg_flags |= MSG_CTRUNC;
3010 if (msg->msg_controllen < cmspace) {
3011 cmspace = msg->msg_controllen;
3015 * We copy the full input data into an intermediate cmsghdr first
3016 * in order to more easily cope with truncation.
3018 cm->cmsg_len = cmlen;
3019 cm->cmsg_level = level;
3020 cm->cmsg_type = type;
3021 memcpy(CMSG_DATA(cm), data, len);
3024 * We now copy the possibly truncated buffer.
3025 * We copy cmlen bytes, but consume cmspace bytes,
3026 * leaving the possible padding uninitialiazed.
3028 p = (uint8_t *)msg->msg_control;
3029 memcpy(p, cm, cmlen);
3030 p += cmspace;
3031 msg->msg_control = p;
3032 msg->msg_controllen -= cmspace;
3034 return;
3037 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3038 struct msghdr *msg)
3040 /* Add packet info */
3041 switch (si->pktinfo) {
3042 #ifdef IP_PKTINFO
3043 case AF_INET: {
3044 struct sockaddr_in *sin;
3045 struct in_pktinfo pkt;
3047 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3048 sin = (struct sockaddr_in*)si->bindname;
3049 } else {
3050 if (si->myname_len != sizeof(struct sockaddr_in)) {
3051 return 0;
3053 sin = (struct sockaddr_in*)si->myname;
3056 ZERO_STRUCT(pkt);
3058 pkt.ipi_ifindex = socket_wrapper_default_iface();
3059 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3061 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3062 &pkt, sizeof(pkt));
3064 break;
3066 #endif /* IP_PKTINFO */
3067 #if defined(HAVE_IPV6)
3068 case AF_INET6: {
3069 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3070 struct sockaddr_in6 *sin6;
3071 struct in6_pktinfo pkt6;
3073 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3074 sin6 = (struct sockaddr_in6*)si->bindname;
3075 } else {
3076 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3077 return 0;
3079 sin6 = (struct sockaddr_in6*)si->myname;
3082 ZERO_STRUCT(pkt6);
3084 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3085 pkt6.ipi6_addr = sin6->sin6_addr;
3087 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3088 &pkt6, sizeof(pkt6));
3089 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3091 break;
3093 #endif /* IPV6_PKTINFO */
3094 default:
3095 return -1;
3098 return 0;
3101 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3103 static ssize_t swrap_sendmsg_before(int fd,
3104 struct socket_info *si,
3105 struct msghdr *msg,
3106 struct iovec *tmp_iov,
3107 struct sockaddr_un *tmp_un,
3108 const struct sockaddr_un **to_un,
3109 const struct sockaddr **to,
3110 int *bcast)
3112 size_t i, len = 0;
3113 ssize_t ret;
3115 if (to_un) {
3116 *to_un = NULL;
3118 if (to) {
3119 *to = NULL;
3121 if (bcast) {
3122 *bcast = 0;
3125 switch (si->type) {
3126 case SOCK_STREAM:
3127 if (!si->connected) {
3128 errno = ENOTCONN;
3129 return -1;
3132 if (msg->msg_iovlen == 0) {
3133 break;
3136 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3137 size_t nlen;
3138 nlen = len + msg->msg_iov[i].iov_len;
3139 if (nlen > SOCKET_MAX_PACKET) {
3140 break;
3143 msg->msg_iovlen = i;
3144 if (msg->msg_iovlen == 0) {
3145 *tmp_iov = msg->msg_iov[0];
3146 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3147 msg->msg_iov = tmp_iov;
3148 msg->msg_iovlen = 1;
3150 break;
3152 case SOCK_DGRAM:
3153 if (si->connected) {
3154 if (msg->msg_name) {
3155 errno = EISCONN;
3156 return -1;
3158 } else {
3159 const struct sockaddr *msg_name;
3160 msg_name = (const struct sockaddr *)msg->msg_name;
3162 if (msg_name == NULL) {
3163 errno = ENOTCONN;
3164 return -1;
3168 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3169 tmp_un, 0, bcast);
3170 if (ret == -1) return -1;
3172 if (to_un) {
3173 *to_un = tmp_un;
3175 if (to) {
3176 *to = msg_name;
3178 msg->msg_name = tmp_un;
3179 msg->msg_namelen = sizeof(*tmp_un);
3182 if (si->bound == 0) {
3183 ret = swrap_auto_bind(fd, si, si->family);
3184 if (ret == -1) {
3185 if (errno == ENOTSOCK) {
3186 swrap_remove_stale(fd);
3187 return -ENOTSOCK;
3188 } else {
3189 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3190 return -1;
3195 if (!si->defer_connect) {
3196 break;
3199 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3200 tmp_un, 0, NULL);
3201 if (ret == -1) return -1;
3203 ret = libc_connect(fd,
3204 (struct sockaddr *)(void *)tmp_un,
3205 sizeof(*tmp_un));
3207 /* to give better errors */
3208 if (ret == -1 && errno == ENOENT) {
3209 errno = EHOSTUNREACH;
3212 if (ret == -1) {
3213 return ret;
3216 si->defer_connect = 0;
3217 break;
3218 default:
3219 errno = EHOSTUNREACH;
3220 return -1;
3223 return 0;
3226 static void swrap_sendmsg_after(int fd,
3227 struct socket_info *si,
3228 struct msghdr *msg,
3229 const struct sockaddr *to,
3230 ssize_t ret)
3232 int saved_errno = errno;
3233 size_t i, len = 0;
3234 uint8_t *buf;
3235 off_t ofs = 0;
3236 size_t avail = 0;
3237 size_t remain;
3239 /* to give better errors */
3240 if (ret == -1) {
3241 if (saved_errno == ENOENT) {
3242 saved_errno = EHOSTUNREACH;
3243 } else if (saved_errno == ENOTSOCK) {
3244 /* If the fd is not a socket, remove it */
3245 swrap_remove_stale(fd);
3249 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3250 avail += msg->msg_iov[i].iov_len;
3253 if (ret == -1) {
3254 remain = MIN(80, avail);
3255 } else {
3256 remain = ret;
3259 /* we capture it as one single packet */
3260 buf = (uint8_t *)malloc(remain);
3261 if (!buf) {
3262 /* we just not capture the packet */
3263 errno = saved_errno;
3264 return;
3267 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3268 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3269 memcpy(buf + ofs,
3270 msg->msg_iov[i].iov_base,
3271 this_time);
3272 ofs += this_time;
3273 remain -= this_time;
3275 len = ofs;
3277 switch (si->type) {
3278 case SOCK_STREAM:
3279 if (ret == -1) {
3280 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3281 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3282 } else {
3283 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3285 break;
3287 case SOCK_DGRAM:
3288 if (si->connected) {
3289 to = si->peername;
3291 if (ret == -1) {
3292 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3293 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3294 } else {
3295 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3297 break;
3300 free(buf);
3301 errno = saved_errno;
3304 static int swrap_recvmsg_before(int fd,
3305 struct socket_info *si,
3306 struct msghdr *msg,
3307 struct iovec *tmp_iov)
3309 size_t i, len = 0;
3310 ssize_t ret;
3312 (void)fd; /* unused */
3314 switch (si->type) {
3315 case SOCK_STREAM:
3316 if (!si->connected) {
3317 errno = ENOTCONN;
3318 return -1;
3321 if (msg->msg_iovlen == 0) {
3322 break;
3325 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3326 size_t nlen;
3327 nlen = len + msg->msg_iov[i].iov_len;
3328 if (nlen > SOCKET_MAX_PACKET) {
3329 break;
3332 msg->msg_iovlen = i;
3333 if (msg->msg_iovlen == 0) {
3334 *tmp_iov = msg->msg_iov[0];
3335 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3336 msg->msg_iov = tmp_iov;
3337 msg->msg_iovlen = 1;
3339 break;
3341 case SOCK_DGRAM:
3342 if (msg->msg_name == NULL) {
3343 errno = EINVAL;
3344 return -1;
3347 if (msg->msg_iovlen == 0) {
3348 break;
3351 if (si->bound == 0) {
3352 ret = swrap_auto_bind(fd, si, si->family);
3353 if (ret == -1) {
3355 * When attempting to read or write to a
3356 * descriptor, if an underlying autobind fails
3357 * because it's not a socket, stop intercepting
3358 * uses of that descriptor.
3360 if (errno == ENOTSOCK) {
3361 swrap_remove_stale(fd);
3362 return -ENOTSOCK;
3363 } else {
3364 SWRAP_LOG(SWRAP_LOG_ERROR,
3365 "swrap_recvmsg_before failed");
3366 return -1;
3370 break;
3371 default:
3372 errno = EHOSTUNREACH;
3373 return -1;
3376 return 0;
3379 static int swrap_recvmsg_after(int fd,
3380 struct socket_info *si,
3381 struct msghdr *msg,
3382 const struct sockaddr_un *un_addr,
3383 socklen_t un_addrlen,
3384 ssize_t ret)
3386 int saved_errno = errno;
3387 size_t i;
3388 uint8_t *buf = NULL;
3389 off_t ofs = 0;
3390 size_t avail = 0;
3391 size_t remain;
3393 /* to give better errors */
3394 if (ret == -1) {
3395 if (saved_errno == ENOENT) {
3396 saved_errno = EHOSTUNREACH;
3397 } else if (saved_errno == ENOTSOCK) {
3398 /* If the fd is not a socket, remove it */
3399 swrap_remove_stale(fd);
3403 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3404 avail += msg->msg_iov[i].iov_len;
3407 if (avail == 0) {
3408 errno = saved_errno;
3409 return 0;
3412 if (ret == -1) {
3413 remain = MIN(80, avail);
3414 } else {
3415 remain = ret;
3418 /* we capture it as one single packet */
3419 buf = (uint8_t *)malloc(remain);
3420 if (buf == NULL) {
3421 /* we just not capture the packet */
3422 errno = saved_errno;
3423 return -1;
3426 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3427 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3428 memcpy(buf + ofs,
3429 msg->msg_iov[i].iov_base,
3430 this_time);
3431 ofs += this_time;
3432 remain -= this_time;
3435 switch (si->type) {
3436 case SOCK_STREAM:
3437 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3438 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3439 } else if (ret == 0) { /* END OF FILE */
3440 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3441 } else if (ret > 0) {
3442 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3444 break;
3446 case SOCK_DGRAM:
3447 if (ret == -1) {
3448 break;
3451 if (un_addr != NULL) {
3452 int rc;
3454 rc = sockaddr_convert_from_un(si,
3455 un_addr,
3456 un_addrlen,
3457 si->family,
3458 msg->msg_name,
3459 &msg->msg_namelen);
3460 if (rc == -1) {
3461 goto done;
3464 swrap_dump_packet(si,
3465 msg->msg_name,
3466 SWRAP_RECVFROM,
3467 buf,
3468 ret);
3469 } else {
3470 swrap_dump_packet(si,
3471 msg->msg_name,
3472 SWRAP_RECV,
3473 buf,
3474 ret);
3477 break;
3480 done:
3481 free(buf);
3482 errno = saved_errno;
3483 return 0;
3486 /****************************************************************************
3487 * RECVFROM
3488 ***************************************************************************/
3490 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
3491 struct sockaddr *from, socklen_t *fromlen)
3493 struct sockaddr_un from_addr;
3494 socklen_t from_addrlen = sizeof(from_addr);
3495 ssize_t ret;
3496 struct socket_info *si = find_socket_info(s);
3497 struct sockaddr_storage ss;
3498 socklen_t ss_len = sizeof(ss);
3499 struct msghdr msg;
3500 struct iovec tmp;
3501 int tret;
3503 if (!si) {
3504 return libc_recvfrom(s,
3505 buf,
3506 len,
3507 flags,
3508 from,
3509 fromlen);
3512 tmp.iov_base = buf;
3513 tmp.iov_len = len;
3515 ZERO_STRUCT(msg);
3516 if (from != NULL && fromlen != NULL) {
3517 msg.msg_name = from; /* optional address */
3518 msg.msg_namelen = *fromlen; /* size of address */
3519 } else {
3520 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3521 msg.msg_namelen = ss_len; /* size of address */
3523 msg.msg_iov = &tmp; /* scatter/gather array */
3524 msg.msg_iovlen = 1; /* # elements in msg_iov */
3525 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3526 msg.msg_control = NULL; /* ancillary data, see below */
3527 msg.msg_controllen = 0; /* ancillary data buffer len */
3528 msg.msg_flags = 0; /* flags on received message */
3529 #endif
3531 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3532 if (tret < 0) {
3533 return -1;
3536 buf = msg.msg_iov[0].iov_base;
3537 len = msg.msg_iov[0].iov_len;
3539 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3540 memset(&from_addr, 0, sizeof(from_addr));
3541 ret = libc_recvfrom(s,
3542 buf,
3543 len,
3544 flags,
3545 (struct sockaddr *)(void *)&from_addr,
3546 &from_addrlen);
3547 if (ret == -1) {
3548 return ret;
3551 tret = swrap_recvmsg_after(s,
3553 &msg,
3554 &from_addr,
3555 from_addrlen,
3556 ret);
3557 if (tret != 0) {
3558 return tret;
3561 if (from != NULL && fromlen != NULL) {
3562 *fromlen = msg.msg_namelen;
3565 return ret;
3568 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3569 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3570 struct sockaddr *from, Psocklen_t fromlen)
3571 #else
3572 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3573 struct sockaddr *from, socklen_t *fromlen)
3574 #endif
3576 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
3579 /****************************************************************************
3580 * SENDTO
3581 ***************************************************************************/
3583 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
3584 const struct sockaddr *to, socklen_t tolen)
3586 struct msghdr msg;
3587 struct iovec tmp;
3588 struct sockaddr_un un_addr;
3589 const struct sockaddr_un *to_un = NULL;
3590 ssize_t ret;
3591 int rc;
3592 struct socket_info *si = find_socket_info(s);
3593 int bcast = 0;
3595 if (!si) {
3596 return libc_sendto(s, buf, len, flags, to, tolen);
3599 tmp.iov_base = discard_const_p(char, buf);
3600 tmp.iov_len = len;
3602 ZERO_STRUCT(msg);
3603 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
3604 msg.msg_namelen = tolen; /* size of address */
3605 msg.msg_iov = &tmp; /* scatter/gather array */
3606 msg.msg_iovlen = 1; /* # elements in msg_iov */
3607 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3608 msg.msg_control = NULL; /* ancillary data, see below */
3609 msg.msg_controllen = 0; /* ancillary data buffer len */
3610 msg.msg_flags = 0; /* flags on received message */
3611 #endif
3613 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3614 if (rc < 0) {
3615 return -1;
3618 buf = msg.msg_iov[0].iov_base;
3619 len = msg.msg_iov[0].iov_len;
3621 if (bcast) {
3622 struct stat st;
3623 unsigned int iface;
3624 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3625 char type;
3627 type = SOCKET_TYPE_CHAR_UDP;
3629 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3630 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3631 socket_wrapper_dir(), type, iface, prt);
3632 if (stat(un_addr.sun_path, &st) != 0) continue;
3634 /* ignore the any errors in broadcast sends */
3635 libc_sendto(s,
3636 buf,
3637 len,
3638 flags,
3639 (struct sockaddr *)(void *)&un_addr,
3640 sizeof(un_addr));
3643 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3645 return len;
3648 ret = libc_sendto(s,
3649 buf,
3650 len,
3651 flags,
3652 (struct sockaddr *)msg.msg_name,
3653 msg.msg_namelen);
3655 swrap_sendmsg_after(s, si, &msg, to, ret);
3657 return ret;
3660 ssize_t sendto(int s, const void *buf, size_t len, int flags,
3661 const struct sockaddr *to, socklen_t tolen)
3663 return swrap_sendto(s, buf, len, flags, to, tolen);
3666 /****************************************************************************
3667 * READV
3668 ***************************************************************************/
3670 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
3672 struct socket_info *si;
3673 struct msghdr msg;
3674 struct sockaddr_storage ss;
3675 socklen_t ss_len = sizeof(ss);
3676 struct iovec tmp;
3677 ssize_t ret;
3678 int tret;
3680 si = find_socket_info(s);
3681 if (si == NULL) {
3682 return libc_recv(s, buf, len, flags);
3685 tmp.iov_base = buf;
3686 tmp.iov_len = len;
3688 ZERO_STRUCT(msg);
3689 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3690 msg.msg_namelen = ss_len; /* size of address */
3691 msg.msg_iov = &tmp; /* scatter/gather array */
3692 msg.msg_iovlen = 1; /* # elements in msg_iov */
3693 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3694 msg.msg_control = NULL; /* ancillary data, see below */
3695 msg.msg_controllen = 0; /* ancillary data buffer len */
3696 msg.msg_flags = 0; /* flags on received message */
3697 #endif
3699 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3700 if (tret < 0) {
3701 return -1;
3704 buf = msg.msg_iov[0].iov_base;
3705 len = msg.msg_iov[0].iov_len;
3707 ret = libc_recv(s, buf, len, flags);
3709 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
3710 if (tret != 0) {
3711 return tret;
3714 return ret;
3717 ssize_t recv(int s, void *buf, size_t len, int flags)
3719 return swrap_recv(s, buf, len, flags);
3722 /****************************************************************************
3723 * READ
3724 ***************************************************************************/
3726 static ssize_t swrap_read(int s, void *buf, size_t len)
3728 struct socket_info *si;
3729 struct msghdr msg;
3730 struct iovec tmp;
3731 struct sockaddr_storage ss;
3732 socklen_t ss_len = sizeof(ss);
3733 ssize_t ret;
3734 int tret;
3736 si = find_socket_info(s);
3737 if (si == NULL) {
3738 return libc_read(s, buf, len);
3741 tmp.iov_base = buf;
3742 tmp.iov_len = len;
3744 ZERO_STRUCT(msg);
3745 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3746 msg.msg_namelen = ss_len; /* size of address */
3747 msg.msg_iov = &tmp; /* scatter/gather array */
3748 msg.msg_iovlen = 1; /* # elements in msg_iov */
3749 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3750 msg.msg_control = NULL; /* ancillary data, see below */
3751 msg.msg_controllen = 0; /* ancillary data buffer len */
3752 msg.msg_flags = 0; /* flags on received message */
3753 #endif
3755 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3756 if (tret < 0) {
3757 if (tret == -ENOTSOCK) {
3758 return libc_read(s, buf, len);
3760 return -1;
3763 buf = msg.msg_iov[0].iov_base;
3764 len = msg.msg_iov[0].iov_len;
3766 ret = libc_read(s, buf, len);
3768 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
3769 if (tret != 0) {
3770 return tret;
3773 return ret;
3776 ssize_t read(int s, void *buf, size_t len)
3778 return swrap_read(s, buf, len);
3781 /****************************************************************************
3782 * SEND
3783 ***************************************************************************/
3785 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
3787 struct msghdr msg;
3788 struct iovec tmp;
3789 struct sockaddr_un un_addr;
3790 ssize_t ret;
3791 int rc;
3792 struct socket_info *si = find_socket_info(s);
3794 if (!si) {
3795 return libc_send(s, buf, len, flags);
3798 tmp.iov_base = discard_const_p(char, buf);
3799 tmp.iov_len = len;
3801 ZERO_STRUCT(msg);
3802 msg.msg_name = NULL; /* optional address */
3803 msg.msg_namelen = 0; /* size of address */
3804 msg.msg_iov = &tmp; /* scatter/gather array */
3805 msg.msg_iovlen = 1; /* # elements in msg_iov */
3806 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3807 msg.msg_control = NULL; /* ancillary data, see below */
3808 msg.msg_controllen = 0; /* ancillary data buffer len */
3809 msg.msg_flags = 0; /* flags on received message */
3810 #endif
3812 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
3813 if (rc < 0) {
3814 return -1;
3817 buf = msg.msg_iov[0].iov_base;
3818 len = msg.msg_iov[0].iov_len;
3820 ret = libc_send(s, buf, len, flags);
3822 swrap_sendmsg_after(s, si, &msg, NULL, ret);
3824 return ret;
3827 ssize_t send(int s, const void *buf, size_t len, int flags)
3829 return swrap_send(s, buf, len, flags);
3832 /****************************************************************************
3833 * RECVMSG
3834 ***************************************************************************/
3836 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
3838 struct sockaddr_un from_addr;
3839 socklen_t from_addrlen = sizeof(from_addr);
3840 struct socket_info *si;
3841 struct msghdr msg;
3842 struct iovec tmp;
3844 ssize_t ret;
3845 int rc;
3847 si = find_socket_info(s);
3848 if (si == NULL) {
3849 return libc_recvmsg(s, omsg, flags);
3852 tmp.iov_base = NULL;
3853 tmp.iov_len = 0;
3855 ZERO_STRUCT(msg);
3856 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
3857 msg.msg_namelen = from_addrlen; /* size of address */
3858 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3859 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3860 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3861 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3862 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3863 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3864 #endif
3866 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
3867 if (rc < 0) {
3868 return -1;
3871 ret = libc_recvmsg(s, &msg, flags);
3873 rc = swrap_recvmsg_after(s, si, omsg, &from_addr, from_addrlen, ret);
3874 if (rc != 0) {
3875 return rc;
3878 return ret;
3881 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
3883 return swrap_recvmsg(sockfd, msg, flags);
3886 /****************************************************************************
3887 * SENDMSG
3888 ***************************************************************************/
3890 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
3892 struct msghdr msg;
3893 struct iovec tmp;
3894 struct sockaddr_un un_addr;
3895 const struct sockaddr_un *to_un = NULL;
3896 const struct sockaddr *to = NULL;
3897 ssize_t ret;
3898 int rc;
3899 struct socket_info *si = find_socket_info(s);
3900 int bcast = 0;
3902 if (!si) {
3903 return libc_sendmsg(s, omsg, flags);
3906 ZERO_STRUCT(un_addr);
3908 tmp.iov_base = NULL;
3909 tmp.iov_len = 0;
3911 ZERO_STRUCT(msg);
3912 msg.msg_name = omsg->msg_name; /* optional address */
3913 msg.msg_namelen = omsg->msg_namelen; /* size of address */
3914 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3915 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3916 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3917 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3918 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3919 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3920 #endif
3922 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3923 if (rc < 0) {
3924 return -1;
3927 if (bcast) {
3928 struct stat st;
3929 unsigned int iface;
3930 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3931 char type;
3932 size_t i, len = 0;
3933 uint8_t *buf;
3934 off_t ofs = 0;
3935 size_t avail = 0;
3936 size_t remain;
3938 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
3939 avail += msg.msg_iov[i].iov_len;
3942 len = avail;
3943 remain = avail;
3945 /* we capture it as one single packet */
3946 buf = (uint8_t *)malloc(remain);
3947 if (!buf) {
3948 return -1;
3951 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
3952 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
3953 memcpy(buf + ofs,
3954 msg.msg_iov[i].iov_base,
3955 this_time);
3956 ofs += this_time;
3957 remain -= this_time;
3960 type = SOCKET_TYPE_CHAR_UDP;
3962 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3963 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3964 socket_wrapper_dir(), type, iface, prt);
3965 if (stat(un_addr.sun_path, &st) != 0) continue;
3967 msg.msg_name = &un_addr; /* optional address */
3968 msg.msg_namelen = sizeof(un_addr); /* size of address */
3970 /* ignore the any errors in broadcast sends */
3971 libc_sendmsg(s, &msg, flags);
3974 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3975 free(buf);
3977 return len;
3980 ret = libc_sendmsg(s, &msg, flags);
3982 swrap_sendmsg_after(s, si, &msg, to, ret);
3984 return ret;
3987 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
3989 return swrap_sendmsg(s, omsg, flags);
3992 /****************************************************************************
3993 * READV
3994 ***************************************************************************/
3996 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
3998 struct socket_info *si;
3999 struct msghdr msg;
4000 struct iovec tmp;
4001 struct sockaddr_storage ss;
4002 socklen_t ss_len = sizeof(ss);
4003 ssize_t ret;
4004 int rc;
4006 si = find_socket_info(s);
4007 if (si == NULL) {
4008 return libc_readv(s, vector, count);
4011 tmp.iov_base = NULL;
4012 tmp.iov_len = 0;
4014 ZERO_STRUCT(msg);
4015 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4016 msg.msg_namelen = ss_len; /* size of address */
4017 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4018 msg.msg_iovlen = count; /* # elements in msg_iov */
4019 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4020 msg.msg_control = NULL; /* ancillary data, see below */
4021 msg.msg_controllen = 0; /* ancillary data buffer len */
4022 msg.msg_flags = 0; /* flags on received message */
4023 #endif
4025 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4026 if (rc < 0) {
4027 if (rc == -ENOTSOCK) {
4028 return libc_readv(s, vector, count);
4030 return -1;
4033 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4035 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4036 if (rc != 0) {
4037 return rc;
4040 return ret;
4043 ssize_t readv(int s, const struct iovec *vector, int count)
4045 return swrap_readv(s, vector, count);
4048 /****************************************************************************
4049 * WRITEV
4050 ***************************************************************************/
4052 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4054 struct msghdr msg;
4055 struct iovec tmp;
4056 struct sockaddr_un un_addr;
4057 ssize_t ret;
4058 int rc;
4059 struct socket_info *si = find_socket_info(s);
4061 if (!si) {
4062 return libc_writev(s, vector, count);
4065 tmp.iov_base = NULL;
4066 tmp.iov_len = 0;
4068 ZERO_STRUCT(msg);
4069 msg.msg_name = NULL; /* optional address */
4070 msg.msg_namelen = 0; /* size of address */
4071 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4072 msg.msg_iovlen = count; /* # elements in msg_iov */
4073 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4074 msg.msg_control = NULL; /* ancillary data, see below */
4075 msg.msg_controllen = 0; /* ancillary data buffer len */
4076 msg.msg_flags = 0; /* flags on received message */
4077 #endif
4079 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4080 if (rc < 0) {
4081 if (rc == -ENOTSOCK) {
4082 return libc_readv(s, vector, count);
4084 return -1;
4087 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4089 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4091 return ret;
4094 ssize_t writev(int s, const struct iovec *vector, int count)
4096 return swrap_writev(s, vector, count);
4099 /****************************
4100 * CLOSE
4101 ***************************/
4103 static int swrap_close(int fd)
4105 struct socket_info *si = find_socket_info(fd);
4106 struct socket_info_fd *fi;
4107 int ret;
4109 if (!si) {
4110 return libc_close(fd);
4113 for (fi = si->fds; fi; fi = fi->next) {
4114 if (fi->fd == fd) {
4115 SWRAP_DLIST_REMOVE(si->fds, fi);
4116 free(fi);
4117 break;
4121 if (si->fds) {
4122 /* there are still references left */
4123 return libc_close(fd);
4126 SWRAP_DLIST_REMOVE(sockets, si);
4128 if (si->myname && si->peername) {
4129 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4132 ret = libc_close(fd);
4134 if (si->myname && si->peername) {
4135 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4136 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4139 if (si->bindname != NULL) {
4140 free(si->bindname);
4143 if (si->myname) free(si->myname);
4144 if (si->peername) free(si->peername);
4145 if (si->tmp_path) {
4146 unlink(si->tmp_path);
4147 free(si->tmp_path);
4149 free(si);
4151 return ret;
4154 int close(int fd)
4156 return swrap_close(fd);
4159 /****************************
4160 * DUP
4161 ***************************/
4163 static int swrap_dup(int fd)
4165 struct socket_info *si;
4166 struct socket_info_fd *fi;
4168 si = find_socket_info(fd);
4170 if (!si) {
4171 return libc_dup(fd);
4174 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4175 if (fi == NULL) {
4176 errno = ENOMEM;
4177 return -1;
4180 fi->fd = libc_dup(fd);
4181 if (fi->fd == -1) {
4182 int saved_errno = errno;
4183 free(fi);
4184 errno = saved_errno;
4185 return -1;
4188 /* Make sure we don't have an entry for the fd */
4189 swrap_remove_stale(fi->fd);
4191 SWRAP_DLIST_ADD(si->fds, fi);
4192 return fi->fd;
4195 int dup(int fd)
4197 return swrap_dup(fd);
4200 /****************************
4201 * DUP2
4202 ***************************/
4204 static int swrap_dup2(int fd, int newfd)
4206 struct socket_info *si;
4207 struct socket_info_fd *fi;
4209 si = find_socket_info(fd);
4211 if (!si) {
4212 return libc_dup2(fd, newfd);
4215 if (find_socket_info(newfd)) {
4216 /* dup2() does an implicit close of newfd, which we
4217 * need to emulate */
4218 swrap_close(newfd);
4221 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4222 if (fi == NULL) {
4223 errno = ENOMEM;
4224 return -1;
4227 fi->fd = libc_dup2(fd, newfd);
4228 if (fi->fd == -1) {
4229 int saved_errno = errno;
4230 free(fi);
4231 errno = saved_errno;
4232 return -1;
4235 /* Make sure we don't have an entry for the fd */
4236 swrap_remove_stale(fi->fd);
4238 SWRAP_DLIST_ADD(si->fds, fi);
4239 return fi->fd;
4242 int dup2(int fd, int newfd)
4244 return swrap_dup2(fd, newfd);
4247 /****************************
4248 * DUP2
4249 ***************************/
4251 #ifdef HAVE_EVENTFD
4252 static int swrap_eventfd(int count, int flags)
4254 int fd;
4256 fd = libc_eventfd(count, flags);
4257 if (fd != -1) {
4258 swrap_remove_stale(fd);
4261 return fd;
4264 int eventfd(int count, int flags)
4266 return swrap_eventfd(count, flags);
4268 #endif
4270 /****************************
4271 * DESTRUCTOR
4272 ***************************/
4275 * This function is called when the library is unloaded and makes sure that
4276 * sockets get closed and the unix file for the socket are unlinked.
4278 void swrap_destructor(void)
4280 struct socket_info *s = sockets;
4282 while (s != NULL) {
4283 struct socket_info_fd *f = s->fds;
4284 if (f != NULL) {
4285 swrap_close(f->fd);
4287 s = sockets;