swrap: Check if the in_pktinfo structure is available.
[Samba/wip.git] / lib / socket_wrapper / socket_wrapper.c
blob56d1d966a0aa32b706d07dd12108f8953c5e2f64
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 swrap.libc_handle = handle;
440 #endif
441 if (handle == NULL) {
442 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
443 char soname[256] = {0};
445 snprintf(soname, sizeof(soname), "libc.so.%d", i);
446 handle = dlopen(soname, flags);
449 swrap.libc_handle = handle;
451 break;
454 if (handle == NULL) {
455 #ifdef RTLD_NEXT
456 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
457 #else
458 SWRAP_LOG(SWRAP_LOG_ERROR,
459 "Failed to dlopen library: %s\n",
460 dlerror());
461 exit(-1);
462 #endif
465 return handle;
468 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
470 void *handle;
471 void *func;
473 handle = swrap_load_lib_handle(lib);
475 func = dlsym(handle, fn_name);
476 if (func == NULL) {
477 SWRAP_LOG(SWRAP_LOG_ERROR,
478 "Failed to find %s: %s\n",
479 fn_name, dlerror());
480 exit(-1);
483 SWRAP_LOG(SWRAP_LOG_TRACE,
484 "Loaded %s from %s",
485 fn_name, swrap_str_lib(lib));
486 return func;
489 #define swrap_load_lib_function(lib, fn_name) \
490 if (swrap.fns.libc_##fn_name == NULL) { \
491 *(void **) (&swrap.fns.libc_##fn_name) = \
492 _swrap_load_lib_function(lib, #fn_name); \
497 * IMPORTANT
499 * Functions especially from libc need to be loaded individually, you can't load
500 * all at once or gdb will segfault at startup. The same applies to valgrind and
501 * has probably something todo with with the linker.
502 * So we need load each function at the point it is called the first time.
504 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
506 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
508 return swrap.fns.libc_accept(sockfd, addr, addrlen);
511 static int libc_bind(int sockfd,
512 const struct sockaddr *addr,
513 socklen_t addrlen)
515 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
517 return swrap.fns.libc_bind(sockfd, addr, addrlen);
520 static int libc_close(int fd)
522 swrap_load_lib_function(SWRAP_LIBC, close);
524 return swrap.fns.libc_close(fd);
527 static int libc_connect(int sockfd,
528 const struct sockaddr *addr,
529 socklen_t addrlen)
531 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
533 return swrap.fns.libc_connect(sockfd, addr, addrlen);
536 static int libc_dup(int fd)
538 swrap_load_lib_function(SWRAP_LIBC, dup);
540 return swrap.fns.libc_dup(fd);
543 static int libc_dup2(int oldfd, int newfd)
545 swrap_load_lib_function(SWRAP_LIBC, dup2);
547 return swrap.fns.libc_dup2(oldfd, newfd);
550 #ifdef HAVE_EVENTFD
551 static int libc_eventfd(int count, int flags)
553 swrap_load_lib_function(SWRAP_LIBC, eventfd);
555 return swrap.fns.libc_eventfd(count, flags);
557 #endif
559 static int libc_getpeername(int sockfd,
560 struct sockaddr *addr,
561 socklen_t *addrlen)
563 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
565 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
568 static int libc_getsockname(int sockfd,
569 struct sockaddr *addr,
570 socklen_t *addrlen)
572 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
574 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
577 static int libc_getsockopt(int sockfd,
578 int level,
579 int optname,
580 void *optval,
581 socklen_t *optlen)
583 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
585 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
588 static int libc_vioctl(int d, unsigned long int request, va_list ap)
590 long int args[4];
591 int rc;
592 int i;
594 swrap_load_lib_function(SWRAP_LIBC, ioctl);
596 for (i = 0; i < 4; i++) {
597 args[i] = va_arg(ap, long int);
600 rc = swrap.fns.libc_ioctl(d,
601 request,
602 args[0],
603 args[1],
604 args[2],
605 args[3]);
607 return rc;
610 static int libc_listen(int sockfd, int backlog)
612 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
614 return swrap.fns.libc_listen(sockfd, backlog);
617 static int libc_vopen(const char *pathname, int flags, va_list ap)
619 long int mode = 0;
620 int fd;
622 swrap_load_lib_function(SWRAP_LIBC, open);
624 mode = va_arg(ap, long int);
626 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
628 return fd;
631 static int libc_open(const char *pathname, int flags, ...)
633 va_list ap;
634 int fd;
636 va_start(ap, flags);
637 fd = libc_vopen(pathname, flags, ap);
638 va_end(ap);
640 return fd;
643 static int libc_pipe(int pipefd[2])
645 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
647 return swrap.fns.libc_pipe(pipefd);
650 static int libc_read(int fd, void *buf, size_t count)
652 swrap_load_lib_function(SWRAP_LIBC, read);
654 return swrap.fns.libc_read(fd, buf, count);
657 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
659 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
661 return swrap.fns.libc_readv(fd, iov, iovcnt);
664 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
666 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
668 return swrap.fns.libc_recv(sockfd, buf, len, flags);
671 static int libc_recvfrom(int sockfd,
672 void *buf,
673 size_t len,
674 int flags,
675 struct sockaddr *src_addr,
676 socklen_t *addrlen)
678 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
680 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
683 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
685 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
687 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
690 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
692 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
694 return swrap.fns.libc_send(sockfd, buf, len, flags);
697 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
699 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
701 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
704 static int libc_sendto(int sockfd,
705 const void *buf,
706 size_t len,
707 int flags,
708 const struct sockaddr *dst_addr,
709 socklen_t addrlen)
711 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
713 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
716 static int libc_setsockopt(int sockfd,
717 int level,
718 int optname,
719 const void *optval,
720 socklen_t optlen)
722 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
724 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
727 #ifdef HAVE_SIGNALFD
728 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
730 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
732 return swrap.fns.libc_signalfd(fd, mask, flags);
734 #endif
736 static int libc_socket(int domain, int type, int protocol)
738 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
740 return swrap.fns.libc_socket(domain, type, protocol);
743 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
745 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
747 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
750 #ifdef HAVE_TIMERFD_CREATE
751 static int libc_timerfd_create(int clockid, int flags)
753 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
755 return swrap.fns.libc_timerfd_create(clockid, flags);
757 #endif
759 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
761 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
763 return swrap.fns.libc_writev(fd, iov, iovcnt);
766 /*********************************************************
767 * SWRAP HELPER FUNCTIONS
768 *********************************************************/
770 #ifdef HAVE_IPV6
772 * FD00::5357:5FXX
774 static const struct in6_addr *swrap_ipv6(void)
776 static struct in6_addr v;
777 static int initialized;
778 int ret;
780 if (initialized) {
781 return &v;
783 initialized = 1;
785 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
786 if (ret <= 0) {
787 abort();
790 return &v;
792 #endif
794 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
796 struct sockaddr *ret = (struct sockaddr *)malloc(len);
797 memcpy(ret, data, len);
798 return ret;
801 static void set_port(int family, int prt, struct sockaddr *addr)
803 switch (family) {
804 case AF_INET:
805 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
806 break;
807 #ifdef HAVE_IPV6
808 case AF_INET6:
809 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
810 break;
811 #endif
815 static size_t socket_length(int family)
817 switch (family) {
818 case AF_INET:
819 return sizeof(struct sockaddr_in);
820 #ifdef HAVE_IPV6
821 case AF_INET6:
822 return sizeof(struct sockaddr_in6);
823 #endif
825 return 0;
828 static const char *socket_wrapper_dir(void)
830 const char *s = getenv("SOCKET_WRAPPER_DIR");
831 if (s == NULL) {
832 return NULL;
834 if (strncmp(s, "./", 2) == 0) {
835 s += 2;
838 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
839 return s;
842 bool socket_wrapper_enabled(void)
844 const char *s = socket_wrapper_dir();
846 return s != NULL ? true : false;
849 static unsigned int socket_wrapper_default_iface(void)
851 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
852 if (s) {
853 unsigned int iface;
854 if (sscanf(s, "%u", &iface) == 1) {
855 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
856 return iface;
861 return 1;/* 127.0.0.1 */
864 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
866 unsigned int iface;
867 unsigned int prt;
868 const char *p;
869 char type;
871 p = strrchr(un->sun_path, '/');
872 if (p) p++; else p = un->sun_path;
874 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
875 errno = EINVAL;
876 return -1;
879 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
880 type, iface, prt);
882 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
883 errno = EINVAL;
884 return -1;
887 if (prt > 0xFFFF) {
888 errno = EINVAL;
889 return -1;
892 switch(type) {
893 case SOCKET_TYPE_CHAR_TCP:
894 case SOCKET_TYPE_CHAR_UDP: {
895 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
897 if ((*len) < sizeof(*in2)) {
898 errno = EINVAL;
899 return -1;
902 memset(in2, 0, sizeof(*in2));
903 in2->sin_family = AF_INET;
904 in2->sin_addr.s_addr = htonl((127<<24) | iface);
905 in2->sin_port = htons(prt);
907 *len = sizeof(*in2);
908 break;
910 #ifdef HAVE_IPV6
911 case SOCKET_TYPE_CHAR_TCP_V6:
912 case SOCKET_TYPE_CHAR_UDP_V6: {
913 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
915 if ((*len) < sizeof(*in2)) {
916 errno = EINVAL;
917 return -1;
920 memset(in2, 0, sizeof(*in2));
921 in2->sin6_family = AF_INET6;
922 in2->sin6_addr = *swrap_ipv6();
923 in2->sin6_addr.s6_addr[15] = iface;
924 in2->sin6_port = htons(prt);
926 *len = sizeof(*in2);
927 break;
929 #endif
930 default:
931 errno = EINVAL;
932 return -1;
935 return 0;
938 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
939 int *bcast)
941 char type = '\0';
942 unsigned int prt;
943 unsigned int iface;
944 int is_bcast = 0;
946 if (bcast) *bcast = 0;
948 switch (inaddr->sa_family) {
949 case AF_INET: {
950 const struct sockaddr_in *in =
951 (const struct sockaddr_in *)(const void *)inaddr;
952 unsigned int addr = ntohl(in->sin_addr.s_addr);
953 char u_type = '\0';
954 char b_type = '\0';
955 char a_type = '\0';
957 switch (si->type) {
958 case SOCK_STREAM:
959 u_type = SOCKET_TYPE_CHAR_TCP;
960 break;
961 case SOCK_DGRAM:
962 u_type = SOCKET_TYPE_CHAR_UDP;
963 a_type = SOCKET_TYPE_CHAR_UDP;
964 b_type = SOCKET_TYPE_CHAR_UDP;
965 break;
966 default:
967 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
968 errno = ESOCKTNOSUPPORT;
969 return -1;
972 prt = ntohs(in->sin_port);
973 if (a_type && addr == 0xFFFFFFFF) {
974 /* 255.255.255.255 only udp */
975 is_bcast = 2;
976 type = a_type;
977 iface = socket_wrapper_default_iface();
978 } else if (b_type && addr == 0x7FFFFFFF) {
979 /* 127.255.255.255 only udp */
980 is_bcast = 1;
981 type = b_type;
982 iface = socket_wrapper_default_iface();
983 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
984 /* 127.0.0.X */
985 is_bcast = 0;
986 type = u_type;
987 iface = (addr & 0x000000FF);
988 } else {
989 errno = ENETUNREACH;
990 return -1;
992 if (bcast) *bcast = is_bcast;
993 break;
995 #ifdef HAVE_IPV6
996 case AF_INET6: {
997 const struct sockaddr_in6 *in =
998 (const struct sockaddr_in6 *)(const void *)inaddr;
999 struct in6_addr cmp1, cmp2;
1001 switch (si->type) {
1002 case SOCK_STREAM:
1003 type = SOCKET_TYPE_CHAR_TCP_V6;
1004 break;
1005 case SOCK_DGRAM:
1006 type = SOCKET_TYPE_CHAR_UDP_V6;
1007 break;
1008 default:
1009 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1010 errno = ESOCKTNOSUPPORT;
1011 return -1;
1014 /* XXX no multicast/broadcast */
1016 prt = ntohs(in->sin6_port);
1018 cmp1 = *swrap_ipv6();
1019 cmp2 = in->sin6_addr;
1020 cmp2.s6_addr[15] = 0;
1021 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1022 iface = in->sin6_addr.s6_addr[15];
1023 } else {
1024 errno = ENETUNREACH;
1025 return -1;
1028 break;
1030 #endif
1031 default:
1032 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1033 errno = ENETUNREACH;
1034 return -1;
1037 if (prt == 0) {
1038 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1039 errno = EINVAL;
1040 return -1;
1043 if (is_bcast) {
1044 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1045 socket_wrapper_dir());
1046 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1047 /* the caller need to do more processing */
1048 return 0;
1051 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1052 socket_wrapper_dir(), type, iface, prt);
1053 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1055 return 0;
1058 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1059 int *bcast)
1061 char type = '\0';
1062 unsigned int prt;
1063 unsigned int iface;
1064 struct stat st;
1065 int is_bcast = 0;
1067 if (bcast) *bcast = 0;
1069 switch (si->family) {
1070 case AF_INET: {
1071 const struct sockaddr_in *in =
1072 (const struct sockaddr_in *)(const void *)inaddr;
1073 unsigned int addr = ntohl(in->sin_addr.s_addr);
1074 char u_type = '\0';
1075 char d_type = '\0';
1076 char b_type = '\0';
1077 char a_type = '\0';
1079 prt = ntohs(in->sin_port);
1081 switch (si->type) {
1082 case SOCK_STREAM:
1083 u_type = SOCKET_TYPE_CHAR_TCP;
1084 d_type = SOCKET_TYPE_CHAR_TCP;
1085 break;
1086 case SOCK_DGRAM:
1087 u_type = SOCKET_TYPE_CHAR_UDP;
1088 d_type = SOCKET_TYPE_CHAR_UDP;
1089 a_type = SOCKET_TYPE_CHAR_UDP;
1090 b_type = SOCKET_TYPE_CHAR_UDP;
1091 break;
1092 default:
1093 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1094 errno = ESOCKTNOSUPPORT;
1095 return -1;
1098 if (addr == 0) {
1099 /* 0.0.0.0 */
1100 is_bcast = 0;
1101 type = d_type;
1102 iface = socket_wrapper_default_iface();
1103 } else if (a_type && addr == 0xFFFFFFFF) {
1104 /* 255.255.255.255 only udp */
1105 is_bcast = 2;
1106 type = a_type;
1107 iface = socket_wrapper_default_iface();
1108 } else if (b_type && addr == 0x7FFFFFFF) {
1109 /* 127.255.255.255 only udp */
1110 is_bcast = 1;
1111 type = b_type;
1112 iface = socket_wrapper_default_iface();
1113 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1114 /* 127.0.0.X */
1115 is_bcast = 0;
1116 type = u_type;
1117 iface = (addr & 0x000000FF);
1118 } else {
1119 errno = EADDRNOTAVAIL;
1120 return -1;
1123 /* Store the bind address for connect() */
1124 if (si->bindname == NULL) {
1125 struct sockaddr_in bind_in;
1126 socklen_t blen = sizeof(struct sockaddr_in);
1128 ZERO_STRUCT(bind_in);
1129 bind_in.sin_family = in->sin_family;
1130 bind_in.sin_port = in->sin_port;
1131 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1133 si->bindname = sockaddr_dup(&bind_in, blen);
1134 si->bindname_len = blen;
1137 break;
1139 #ifdef HAVE_IPV6
1140 case AF_INET6: {
1141 const struct sockaddr_in6 *in =
1142 (const struct sockaddr_in6 *)(const void *)inaddr;
1143 struct in6_addr cmp1, cmp2;
1145 switch (si->type) {
1146 case SOCK_STREAM:
1147 type = SOCKET_TYPE_CHAR_TCP_V6;
1148 break;
1149 case SOCK_DGRAM:
1150 type = SOCKET_TYPE_CHAR_UDP_V6;
1151 break;
1152 default:
1153 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1154 errno = ESOCKTNOSUPPORT;
1155 return -1;
1158 /* XXX no multicast/broadcast */
1160 prt = ntohs(in->sin6_port);
1162 cmp1 = *swrap_ipv6();
1163 cmp2 = in->sin6_addr;
1164 cmp2.s6_addr[15] = 0;
1165 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1166 iface = socket_wrapper_default_iface();
1167 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1168 iface = in->sin6_addr.s6_addr[15];
1169 } else {
1170 errno = EADDRNOTAVAIL;
1171 return -1;
1174 /* Store the bind address for connect() */
1175 if (si->bindname == NULL) {
1176 struct sockaddr_in6 bind_in;
1177 socklen_t blen = sizeof(struct sockaddr_in6);
1179 ZERO_STRUCT(bind_in);
1180 bind_in.sin6_family = in->sin6_family;
1181 bind_in.sin6_port = in->sin6_port;
1183 bind_in.sin6_addr = *swrap_ipv6();
1184 bind_in.sin6_addr.s6_addr[15] = iface;
1186 si->bindname = sockaddr_dup(&bind_in, blen);
1187 si->bindname_len = blen;
1190 break;
1192 #endif
1193 default:
1194 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1195 errno = EADDRNOTAVAIL;
1196 return -1;
1200 if (bcast) *bcast = is_bcast;
1202 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1203 errno = EINVAL;
1204 return -1;
1207 if (prt == 0) {
1208 /* handle auto-allocation of ephemeral ports */
1209 for (prt = 5001; prt < 10000; prt++) {
1210 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1211 socket_wrapper_dir(), type, iface, prt);
1212 if (stat(un->sun_path, &st) == 0) continue;
1214 set_port(si->family, prt, si->myname);
1215 set_port(si->family, prt, si->bindname);
1217 break;
1219 if (prt == 10000) {
1220 errno = ENFILE;
1221 return -1;
1225 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1226 socket_wrapper_dir(), type, iface, prt);
1227 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1228 return 0;
1231 static struct socket_info *find_socket_info(int fd)
1233 struct socket_info *i;
1235 for (i = sockets; i; i = i->next) {
1236 struct socket_info_fd *f;
1237 for (f = i->fds; f; f = f->next) {
1238 if (f->fd == fd) {
1239 return i;
1244 return NULL;
1247 static void swrap_remove_stale(int fd)
1249 struct socket_info *si = find_socket_info(fd);
1250 struct socket_info_fd *fi;
1252 if (si != NULL) {
1253 for (fi = si->fds; fi; fi = fi->next) {
1254 if (fi->fd == fd) {
1255 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1256 SWRAP_DLIST_REMOVE(si->fds, fi);
1257 free(fi);
1258 break;
1262 if (si->fds == NULL) {
1263 SWRAP_DLIST_REMOVE(sockets, si);
1268 static int sockaddr_convert_to_un(struct socket_info *si,
1269 const struct sockaddr *in_addr,
1270 socklen_t in_len,
1271 struct sockaddr_un *out_addr,
1272 int alloc_sock,
1273 int *bcast)
1275 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1277 (void) in_len; /* unused */
1279 if (out_addr == NULL) {
1280 return 0;
1283 out->sa_family = AF_UNIX;
1284 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1285 out->sa_len = sizeof(*out_addr);
1286 #endif
1288 switch (in_addr->sa_family) {
1289 case AF_INET:
1290 #ifdef HAVE_IPV6
1291 case AF_INET6:
1292 #endif
1293 switch (si->type) {
1294 case SOCK_STREAM:
1295 case SOCK_DGRAM:
1296 break;
1297 default:
1298 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1299 errno = ESOCKTNOSUPPORT;
1300 return -1;
1302 if (alloc_sock) {
1303 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1304 } else {
1305 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1307 default:
1308 break;
1311 errno = EAFNOSUPPORT;
1312 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1313 return -1;
1316 static int sockaddr_convert_from_un(const struct socket_info *si,
1317 const struct sockaddr_un *in_addr,
1318 socklen_t un_addrlen,
1319 int family,
1320 struct sockaddr *out_addr,
1321 socklen_t *out_addrlen)
1323 int ret;
1325 if (out_addr == NULL || out_addrlen == NULL)
1326 return 0;
1328 if (un_addrlen == 0) {
1329 *out_addrlen = 0;
1330 return 0;
1333 switch (family) {
1334 case AF_INET:
1335 #ifdef HAVE_IPV6
1336 case AF_INET6:
1337 #endif
1338 switch (si->type) {
1339 case SOCK_STREAM:
1340 case SOCK_DGRAM:
1341 break;
1342 default:
1343 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1344 errno = ESOCKTNOSUPPORT;
1345 return -1;
1347 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1348 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1349 out_addr->sa_len = *out_addrlen;
1350 #endif
1351 return ret;
1352 default:
1353 break;
1356 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1357 errno = EAFNOSUPPORT;
1358 return -1;
1361 enum swrap_packet_type {
1362 SWRAP_CONNECT_SEND,
1363 SWRAP_CONNECT_UNREACH,
1364 SWRAP_CONNECT_RECV,
1365 SWRAP_CONNECT_ACK,
1366 SWRAP_ACCEPT_SEND,
1367 SWRAP_ACCEPT_RECV,
1368 SWRAP_ACCEPT_ACK,
1369 SWRAP_RECVFROM,
1370 SWRAP_SENDTO,
1371 SWRAP_SENDTO_UNREACH,
1372 SWRAP_PENDING_RST,
1373 SWRAP_RECV,
1374 SWRAP_RECV_RST,
1375 SWRAP_SEND,
1376 SWRAP_SEND_RST,
1377 SWRAP_CLOSE_SEND,
1378 SWRAP_CLOSE_RECV,
1379 SWRAP_CLOSE_ACK,
1382 struct swrap_file_hdr {
1383 uint32_t magic;
1384 uint16_t version_major;
1385 uint16_t version_minor;
1386 int32_t timezone;
1387 uint32_t sigfigs;
1388 uint32_t frame_max_len;
1389 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1390 uint32_t link_type;
1392 #define SWRAP_FILE_HDR_SIZE 24
1394 struct swrap_packet_frame {
1395 uint32_t seconds;
1396 uint32_t micro_seconds;
1397 uint32_t recorded_length;
1398 uint32_t full_length;
1400 #define SWRAP_PACKET_FRAME_SIZE 16
1402 union swrap_packet_ip {
1403 struct {
1404 uint8_t ver_hdrlen;
1405 uint8_t tos;
1406 uint16_t packet_length;
1407 uint16_t identification;
1408 uint8_t flags;
1409 uint8_t fragment;
1410 uint8_t ttl;
1411 uint8_t protocol;
1412 uint16_t hdr_checksum;
1413 uint32_t src_addr;
1414 uint32_t dest_addr;
1415 } v4;
1416 #define SWRAP_PACKET_IP_V4_SIZE 20
1417 struct {
1418 uint8_t ver_prio;
1419 uint8_t flow_label_high;
1420 uint16_t flow_label_low;
1421 uint16_t payload_length;
1422 uint8_t next_header;
1423 uint8_t hop_limit;
1424 uint8_t src_addr[16];
1425 uint8_t dest_addr[16];
1426 } v6;
1427 #define SWRAP_PACKET_IP_V6_SIZE 40
1429 #define SWRAP_PACKET_IP_SIZE 40
1431 union swrap_packet_payload {
1432 struct {
1433 uint16_t source_port;
1434 uint16_t dest_port;
1435 uint32_t seq_num;
1436 uint32_t ack_num;
1437 uint8_t hdr_length;
1438 uint8_t control;
1439 uint16_t window;
1440 uint16_t checksum;
1441 uint16_t urg;
1442 } tcp;
1443 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1444 struct {
1445 uint16_t source_port;
1446 uint16_t dest_port;
1447 uint16_t length;
1448 uint16_t checksum;
1449 } udp;
1450 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1451 struct {
1452 uint8_t type;
1453 uint8_t code;
1454 uint16_t checksum;
1455 uint32_t unused;
1456 } icmp4;
1457 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1458 struct {
1459 uint8_t type;
1460 uint8_t code;
1461 uint16_t checksum;
1462 uint32_t unused;
1463 } icmp6;
1464 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1466 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1468 #define SWRAP_PACKET_MIN_ALLOC \
1469 (SWRAP_PACKET_FRAME_SIZE + \
1470 SWRAP_PACKET_IP_SIZE + \
1471 SWRAP_PACKET_PAYLOAD_SIZE)
1473 static const char *socket_wrapper_pcap_file(void)
1475 static int initialized = 0;
1476 static const char *s = NULL;
1477 static const struct swrap_file_hdr h;
1478 static const struct swrap_packet_frame f;
1479 static const union swrap_packet_ip i;
1480 static const union swrap_packet_payload p;
1482 if (initialized == 1) {
1483 return s;
1485 initialized = 1;
1488 * TODO: don't use the structs use plain buffer offsets
1489 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1491 * for now make sure we disable PCAP support
1492 * if the struct has alignment!
1494 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1495 return NULL;
1497 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1498 return NULL;
1500 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1501 return NULL;
1503 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1504 return NULL;
1506 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1507 return NULL;
1509 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1510 return NULL;
1512 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1513 return NULL;
1515 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1516 return NULL;
1518 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1519 return NULL;
1521 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1522 return NULL;
1525 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1526 if (s == NULL) {
1527 return NULL;
1529 if (strncmp(s, "./", 2) == 0) {
1530 s += 2;
1532 return s;
1535 static uint8_t *swrap_packet_init(struct timeval *tval,
1536 const struct sockaddr *src,
1537 const struct sockaddr *dest,
1538 int socket_type,
1539 const uint8_t *payload,
1540 size_t payload_len,
1541 unsigned long tcp_seqno,
1542 unsigned long tcp_ack,
1543 unsigned char tcp_ctl,
1544 int unreachable,
1545 size_t *_packet_len)
1547 uint8_t *base;
1548 uint8_t *buf;
1549 struct swrap_packet_frame *frame;
1550 union swrap_packet_ip *ip;
1551 union swrap_packet_payload *pay;
1552 size_t packet_len;
1553 size_t alloc_len;
1554 size_t nonwire_len = sizeof(*frame);
1555 size_t wire_hdr_len = 0;
1556 size_t wire_len = 0;
1557 size_t ip_hdr_len = 0;
1558 size_t icmp_hdr_len = 0;
1559 size_t icmp_truncate_len = 0;
1560 uint8_t protocol = 0, icmp_protocol = 0;
1561 const struct sockaddr_in *src_in = NULL;
1562 const struct sockaddr_in *dest_in = NULL;
1563 #ifdef HAVE_IPV6
1564 const struct sockaddr_in6 *src_in6 = NULL;
1565 const struct sockaddr_in6 *dest_in6 = NULL;
1566 #endif
1567 uint16_t src_port;
1568 uint16_t dest_port;
1570 switch (src->sa_family) {
1571 case AF_INET:
1572 src_in = (const struct sockaddr_in *)src;
1573 dest_in = (const struct sockaddr_in *)dest;
1574 src_port = src_in->sin_port;
1575 dest_port = dest_in->sin_port;
1576 ip_hdr_len = sizeof(ip->v4);
1577 break;
1578 #ifdef HAVE_IPV6
1579 case AF_INET6:
1580 src_in6 = (const struct sockaddr_in6 *)src;
1581 dest_in6 = (const struct sockaddr_in6 *)dest;
1582 src_port = src_in6->sin6_port;
1583 dest_port = dest_in6->sin6_port;
1584 ip_hdr_len = sizeof(ip->v6);
1585 break;
1586 #endif
1587 default:
1588 return NULL;
1591 switch (socket_type) {
1592 case SOCK_STREAM:
1593 protocol = 0x06; /* TCP */
1594 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1595 wire_len = wire_hdr_len + payload_len;
1596 break;
1598 case SOCK_DGRAM:
1599 protocol = 0x11; /* UDP */
1600 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1601 wire_len = wire_hdr_len + payload_len;
1602 break;
1604 default:
1605 return NULL;
1608 if (unreachable) {
1609 icmp_protocol = protocol;
1610 switch (src->sa_family) {
1611 case AF_INET:
1612 protocol = 0x01; /* ICMPv4 */
1613 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1614 break;
1615 #ifdef HAVE_IPV6
1616 case AF_INET6:
1617 protocol = 0x3A; /* ICMPv6 */
1618 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1619 break;
1620 #endif
1622 if (wire_len > 64 ) {
1623 icmp_truncate_len = wire_len - 64;
1625 wire_hdr_len += icmp_hdr_len;
1626 wire_len += icmp_hdr_len;
1629 packet_len = nonwire_len + wire_len;
1630 alloc_len = packet_len;
1631 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1632 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1635 base = (uint8_t *)malloc(alloc_len);
1636 if (base == NULL) {
1637 return NULL;
1639 memset(base, 0x0, alloc_len);
1641 buf = base;
1643 frame = (struct swrap_packet_frame *)buf;
1644 frame->seconds = tval->tv_sec;
1645 frame->micro_seconds = tval->tv_usec;
1646 frame->recorded_length = wire_len - icmp_truncate_len;
1647 frame->full_length = wire_len - icmp_truncate_len;
1648 buf += SWRAP_PACKET_FRAME_SIZE;
1650 ip = (union swrap_packet_ip *)buf;
1651 switch (src->sa_family) {
1652 case AF_INET:
1653 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1654 ip->v4.tos = 0x00;
1655 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1656 ip->v4.identification = htons(0xFFFF);
1657 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1658 ip->v4.fragment = htons(0x0000);
1659 ip->v4.ttl = 0xFF;
1660 ip->v4.protocol = protocol;
1661 ip->v4.hdr_checksum = htons(0x0000);
1662 ip->v4.src_addr = src_in->sin_addr.s_addr;
1663 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1664 buf += SWRAP_PACKET_IP_V4_SIZE;
1665 break;
1666 #ifdef HAVE_IPV6
1667 case AF_INET6:
1668 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1669 ip->v6.flow_label_high = 0x00;
1670 ip->v6.flow_label_low = 0x0000;
1671 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1672 ip->v6.next_header = protocol;
1673 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1674 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1675 buf += SWRAP_PACKET_IP_V6_SIZE;
1676 break;
1677 #endif
1680 if (unreachable) {
1681 pay = (union swrap_packet_payload *)buf;
1682 switch (src->sa_family) {
1683 case AF_INET:
1684 pay->icmp4.type = 0x03; /* destination unreachable */
1685 pay->icmp4.code = 0x01; /* host unreachable */
1686 pay->icmp4.checksum = htons(0x0000);
1687 pay->icmp4.unused = htonl(0x00000000);
1688 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1690 /* set the ip header in the ICMP payload */
1691 ip = (union swrap_packet_ip *)buf;
1692 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1693 ip->v4.tos = 0x00;
1694 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1695 ip->v4.identification = htons(0xFFFF);
1696 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1697 ip->v4.fragment = htons(0x0000);
1698 ip->v4.ttl = 0xFF;
1699 ip->v4.protocol = icmp_protocol;
1700 ip->v4.hdr_checksum = htons(0x0000);
1701 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1702 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1703 buf += SWRAP_PACKET_IP_V4_SIZE;
1705 src_port = dest_in->sin_port;
1706 dest_port = src_in->sin_port;
1707 break;
1708 #ifdef HAVE_IPV6
1709 case AF_INET6:
1710 pay->icmp6.type = 0x01; /* destination unreachable */
1711 pay->icmp6.code = 0x03; /* address unreachable */
1712 pay->icmp6.checksum = htons(0x0000);
1713 pay->icmp6.unused = htonl(0x00000000);
1714 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1716 /* set the ip header in the ICMP payload */
1717 ip = (union swrap_packet_ip *)buf;
1718 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1719 ip->v6.flow_label_high = 0x00;
1720 ip->v6.flow_label_low = 0x0000;
1721 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1722 ip->v6.next_header = protocol;
1723 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1724 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1725 buf += SWRAP_PACKET_IP_V6_SIZE;
1727 src_port = dest_in6->sin6_port;
1728 dest_port = src_in6->sin6_port;
1729 break;
1730 #endif
1734 pay = (union swrap_packet_payload *)buf;
1736 switch (socket_type) {
1737 case SOCK_STREAM:
1738 pay->tcp.source_port = src_port;
1739 pay->tcp.dest_port = dest_port;
1740 pay->tcp.seq_num = htonl(tcp_seqno);
1741 pay->tcp.ack_num = htonl(tcp_ack);
1742 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1743 pay->tcp.control = tcp_ctl;
1744 pay->tcp.window = htons(0x7FFF);
1745 pay->tcp.checksum = htons(0x0000);
1746 pay->tcp.urg = htons(0x0000);
1747 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1749 break;
1751 case SOCK_DGRAM:
1752 pay->udp.source_port = src_port;
1753 pay->udp.dest_port = dest_port;
1754 pay->udp.length = htons(8 + payload_len);
1755 pay->udp.checksum = htons(0x0000);
1756 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1758 break;
1761 if (payload && payload_len > 0) {
1762 memcpy(buf, payload, payload_len);
1765 *_packet_len = packet_len - icmp_truncate_len;
1766 return base;
1769 static int swrap_get_pcap_fd(const char *fname)
1771 static int fd = -1;
1773 if (fd != -1) return fd;
1775 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1776 if (fd != -1) {
1777 struct swrap_file_hdr file_hdr;
1778 file_hdr.magic = 0xA1B2C3D4;
1779 file_hdr.version_major = 0x0002;
1780 file_hdr.version_minor = 0x0004;
1781 file_hdr.timezone = 0x00000000;
1782 file_hdr.sigfigs = 0x00000000;
1783 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1784 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1786 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1787 close(fd);
1788 fd = -1;
1790 return fd;
1793 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1795 return fd;
1798 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1799 const struct sockaddr *addr,
1800 enum swrap_packet_type type,
1801 const void *buf, size_t len,
1802 size_t *packet_len)
1804 const struct sockaddr *src_addr;
1805 const struct sockaddr *dest_addr;
1806 unsigned long tcp_seqno = 0;
1807 unsigned long tcp_ack = 0;
1808 unsigned char tcp_ctl = 0;
1809 int unreachable = 0;
1811 struct timeval tv;
1813 switch (si->family) {
1814 case AF_INET:
1815 break;
1816 #ifdef HAVE_IPV6
1817 case AF_INET6:
1818 break;
1819 #endif
1820 default:
1821 return NULL;
1824 switch (type) {
1825 case SWRAP_CONNECT_SEND:
1826 if (si->type != SOCK_STREAM) return NULL;
1828 src_addr = si->myname;
1829 dest_addr = addr;
1831 tcp_seqno = si->io.pck_snd;
1832 tcp_ack = si->io.pck_rcv;
1833 tcp_ctl = 0x02; /* SYN */
1835 si->io.pck_snd += 1;
1837 break;
1839 case SWRAP_CONNECT_RECV:
1840 if (si->type != SOCK_STREAM) return NULL;
1842 dest_addr = si->myname;
1843 src_addr = addr;
1845 tcp_seqno = si->io.pck_rcv;
1846 tcp_ack = si->io.pck_snd;
1847 tcp_ctl = 0x12; /** SYN,ACK */
1849 si->io.pck_rcv += 1;
1851 break;
1853 case SWRAP_CONNECT_UNREACH:
1854 if (si->type != SOCK_STREAM) return NULL;
1856 dest_addr = si->myname;
1857 src_addr = addr;
1859 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1860 tcp_seqno = si->io.pck_snd - 1;
1861 tcp_ack = si->io.pck_rcv;
1862 tcp_ctl = 0x02; /* SYN */
1863 unreachable = 1;
1865 break;
1867 case SWRAP_CONNECT_ACK:
1868 if (si->type != SOCK_STREAM) return NULL;
1870 src_addr = si->myname;
1871 dest_addr = addr;
1873 tcp_seqno = si->io.pck_snd;
1874 tcp_ack = si->io.pck_rcv;
1875 tcp_ctl = 0x10; /* ACK */
1877 break;
1879 case SWRAP_ACCEPT_SEND:
1880 if (si->type != SOCK_STREAM) return NULL;
1882 dest_addr = si->myname;
1883 src_addr = addr;
1885 tcp_seqno = si->io.pck_rcv;
1886 tcp_ack = si->io.pck_snd;
1887 tcp_ctl = 0x02; /* SYN */
1889 si->io.pck_rcv += 1;
1891 break;
1893 case SWRAP_ACCEPT_RECV:
1894 if (si->type != SOCK_STREAM) return NULL;
1896 src_addr = si->myname;
1897 dest_addr = addr;
1899 tcp_seqno = si->io.pck_snd;
1900 tcp_ack = si->io.pck_rcv;
1901 tcp_ctl = 0x12; /* SYN,ACK */
1903 si->io.pck_snd += 1;
1905 break;
1907 case SWRAP_ACCEPT_ACK:
1908 if (si->type != SOCK_STREAM) return NULL;
1910 dest_addr = si->myname;
1911 src_addr = addr;
1913 tcp_seqno = si->io.pck_rcv;
1914 tcp_ack = si->io.pck_snd;
1915 tcp_ctl = 0x10; /* ACK */
1917 break;
1919 case SWRAP_SEND:
1920 src_addr = si->myname;
1921 dest_addr = si->peername;
1923 tcp_seqno = si->io.pck_snd;
1924 tcp_ack = si->io.pck_rcv;
1925 tcp_ctl = 0x18; /* PSH,ACK */
1927 si->io.pck_snd += len;
1929 break;
1931 case SWRAP_SEND_RST:
1932 dest_addr = si->myname;
1933 src_addr = si->peername;
1935 if (si->type == SOCK_DGRAM) {
1936 return swrap_marshall_packet(si, si->peername,
1937 SWRAP_SENDTO_UNREACH,
1938 buf, len, packet_len);
1941 tcp_seqno = si->io.pck_rcv;
1942 tcp_ack = si->io.pck_snd;
1943 tcp_ctl = 0x14; /** RST,ACK */
1945 break;
1947 case SWRAP_PENDING_RST:
1948 dest_addr = si->myname;
1949 src_addr = si->peername;
1951 if (si->type == SOCK_DGRAM) {
1952 return NULL;
1955 tcp_seqno = si->io.pck_rcv;
1956 tcp_ack = si->io.pck_snd;
1957 tcp_ctl = 0x14; /* RST,ACK */
1959 break;
1961 case SWRAP_RECV:
1962 dest_addr = si->myname;
1963 src_addr = si->peername;
1965 tcp_seqno = si->io.pck_rcv;
1966 tcp_ack = si->io.pck_snd;
1967 tcp_ctl = 0x18; /* PSH,ACK */
1969 si->io.pck_rcv += len;
1971 break;
1973 case SWRAP_RECV_RST:
1974 dest_addr = si->myname;
1975 src_addr = si->peername;
1977 if (si->type == SOCK_DGRAM) {
1978 return NULL;
1981 tcp_seqno = si->io.pck_rcv;
1982 tcp_ack = si->io.pck_snd;
1983 tcp_ctl = 0x14; /* RST,ACK */
1985 break;
1987 case SWRAP_SENDTO:
1988 src_addr = si->myname;
1989 dest_addr = addr;
1991 si->io.pck_snd += len;
1993 break;
1995 case SWRAP_SENDTO_UNREACH:
1996 dest_addr = si->myname;
1997 src_addr = addr;
1999 unreachable = 1;
2001 break;
2003 case SWRAP_RECVFROM:
2004 dest_addr = si->myname;
2005 src_addr = addr;
2007 si->io.pck_rcv += len;
2009 break;
2011 case SWRAP_CLOSE_SEND:
2012 if (si->type != SOCK_STREAM) return NULL;
2014 src_addr = si->myname;
2015 dest_addr = si->peername;
2017 tcp_seqno = si->io.pck_snd;
2018 tcp_ack = si->io.pck_rcv;
2019 tcp_ctl = 0x11; /* FIN, ACK */
2021 si->io.pck_snd += 1;
2023 break;
2025 case SWRAP_CLOSE_RECV:
2026 if (si->type != SOCK_STREAM) return NULL;
2028 dest_addr = si->myname;
2029 src_addr = si->peername;
2031 tcp_seqno = si->io.pck_rcv;
2032 tcp_ack = si->io.pck_snd;
2033 tcp_ctl = 0x11; /* FIN,ACK */
2035 si->io.pck_rcv += 1;
2037 break;
2039 case SWRAP_CLOSE_ACK:
2040 if (si->type != SOCK_STREAM) return NULL;
2042 src_addr = si->myname;
2043 dest_addr = si->peername;
2045 tcp_seqno = si->io.pck_snd;
2046 tcp_ack = si->io.pck_rcv;
2047 tcp_ctl = 0x10; /* ACK */
2049 break;
2050 default:
2051 return NULL;
2054 swrapGetTimeOfDay(&tv);
2056 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2057 (const uint8_t *)buf, len,
2058 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2059 packet_len);
2062 static void swrap_dump_packet(struct socket_info *si,
2063 const struct sockaddr *addr,
2064 enum swrap_packet_type type,
2065 const void *buf, size_t len)
2067 const char *file_name;
2068 uint8_t *packet;
2069 size_t packet_len = 0;
2070 int fd;
2072 file_name = socket_wrapper_pcap_file();
2073 if (!file_name) {
2074 return;
2077 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2078 if (!packet) {
2079 return;
2082 fd = swrap_get_pcap_fd(file_name);
2083 if (fd != -1) {
2084 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2085 free(packet);
2086 return;
2090 free(packet);
2093 /****************************************************************************
2094 * SIGNALFD
2095 ***************************************************************************/
2097 #ifdef HAVE_SIGNALFD
2098 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2100 int rc;
2102 rc = libc_signalfd(fd, mask, flags);
2103 if (rc != -1) {
2104 swrap_remove_stale(fd);
2107 return rc;
2110 int signalfd(int fd, const sigset_t *mask, int flags)
2112 return swrap_signalfd(fd, mask, flags);
2114 #endif
2116 /****************************************************************************
2117 * SOCKET
2118 ***************************************************************************/
2120 static int swrap_socket(int family, int type, int protocol)
2122 struct socket_info *si;
2123 struct socket_info_fd *fi;
2124 int fd;
2125 int real_type = type;
2128 * Remove possible addition flags passed to socket() so
2129 * do not fail checking the type.
2130 * See https://lwn.net/Articles/281965/
2132 #ifdef SOCK_CLOEXEC
2133 real_type &= ~SOCK_CLOEXEC;
2134 #endif
2135 #ifdef SOCK_NONBLOCK
2136 real_type &= ~SOCK_NONBLOCK;
2137 #endif
2139 if (!socket_wrapper_enabled()) {
2140 return libc_socket(family, type, protocol);
2143 switch (family) {
2144 case AF_INET:
2145 #ifdef HAVE_IPV6
2146 case AF_INET6:
2147 #endif
2148 break;
2149 case AF_UNIX:
2150 return libc_socket(family, type, protocol);
2151 default:
2152 errno = EAFNOSUPPORT;
2153 return -1;
2156 switch (real_type) {
2157 case SOCK_STREAM:
2158 break;
2159 case SOCK_DGRAM:
2160 break;
2161 default:
2162 errno = EPROTONOSUPPORT;
2163 return -1;
2166 switch (protocol) {
2167 case 0:
2168 break;
2169 case 6:
2170 if (real_type == SOCK_STREAM) {
2171 break;
2173 /*fall through*/
2174 case 17:
2175 if (real_type == SOCK_DGRAM) {
2176 break;
2178 /*fall through*/
2179 default:
2180 errno = EPROTONOSUPPORT;
2181 return -1;
2185 * We must call libc_socket with type, from the caller, not the version
2186 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2188 fd = libc_socket(AF_UNIX, type, 0);
2190 if (fd == -1) {
2191 return -1;
2194 /* Check if we have a stale fd and remove it */
2195 si = find_socket_info(fd);
2196 if (si != NULL) {
2197 swrap_remove_stale(fd);
2200 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2201 memset(si, 0, sizeof(struct socket_info));
2202 if (si == NULL) {
2203 errno = ENOMEM;
2204 return -1;
2207 si->family = family;
2209 /* however, the rest of the socket_wrapper code expects just
2210 * the type, not the flags */
2211 si->type = real_type;
2212 si->protocol = protocol;
2214 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2215 if (fi == NULL) {
2216 free(si);
2217 errno = ENOMEM;
2218 return -1;
2221 fi->fd = fd;
2223 SWRAP_DLIST_ADD(si->fds, fi);
2224 SWRAP_DLIST_ADD(sockets, si);
2226 return fd;
2229 int socket(int family, int type, int protocol)
2231 return swrap_socket(family, type, protocol);
2234 /****************************************************************************
2235 * SOCKETPAIR
2236 ***************************************************************************/
2238 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2240 int rc;
2242 rc = libc_socketpair(family, type, protocol, sv);
2243 if (rc != -1) {
2244 swrap_remove_stale(sv[0]);
2245 swrap_remove_stale(sv[1]);
2248 return rc;
2251 int socketpair(int family, int type, int protocol, int sv[2])
2253 return swrap_socketpair(family, type, protocol, sv);
2256 /****************************************************************************
2257 * SOCKETPAIR
2258 ***************************************************************************/
2260 #ifdef HAVE_TIMERFD_CREATE
2261 static int swrap_timerfd_create(int clockid, int flags)
2263 int fd;
2265 fd = libc_timerfd_create(clockid, flags);
2266 if (fd != -1) {
2267 swrap_remove_stale(fd);
2270 return fd;
2273 int timerfd_create(int clockid, int flags)
2275 return swrap_timerfd_create(clockid, flags);
2277 #endif
2279 /****************************************************************************
2280 * PIPE
2281 ***************************************************************************/
2283 static int swrap_pipe(int pipefd[2])
2285 int rc;
2287 rc = libc_pipe(pipefd);
2288 if (rc != -1) {
2289 swrap_remove_stale(pipefd[0]);
2290 swrap_remove_stale(pipefd[1]);
2293 return rc;
2296 int pipe(int pipefd[2])
2298 return swrap_pipe(pipefd);
2301 /****************************************************************************
2302 * ACCEPT
2303 ***************************************************************************/
2305 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2307 struct socket_info *parent_si, *child_si;
2308 struct socket_info_fd *child_fi;
2309 int fd;
2310 struct sockaddr_un un_addr;
2311 socklen_t un_addrlen = sizeof(un_addr);
2312 struct sockaddr_un un_my_addr;
2313 socklen_t un_my_addrlen = sizeof(un_my_addr);
2314 struct sockaddr *my_addr;
2315 socklen_t my_addrlen, len;
2316 int ret;
2318 parent_si = find_socket_info(s);
2319 if (!parent_si) {
2320 return libc_accept(s, addr, addrlen);
2324 * assume out sockaddr have the same size as the in parent
2325 * socket family
2327 my_addrlen = socket_length(parent_si->family);
2328 if (my_addrlen <= 0) {
2329 errno = EINVAL;
2330 return -1;
2333 my_addr = (struct sockaddr *)malloc(my_addrlen);
2334 if (my_addr == NULL) {
2335 return -1;
2338 memset(&un_addr, 0, sizeof(un_addr));
2339 memset(&un_my_addr, 0, sizeof(un_my_addr));
2341 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2342 if (ret == -1) {
2343 if (errno == ENOTSOCK) {
2344 /* Remove stale fds */
2345 swrap_remove_stale(s);
2347 free(my_addr);
2348 return ret;
2351 fd = ret;
2353 len = my_addrlen;
2354 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2355 parent_si->family, my_addr, &len);
2356 if (ret == -1) {
2357 free(my_addr);
2358 close(fd);
2359 return ret;
2362 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2363 memset(child_si, 0, sizeof(struct socket_info));
2365 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2366 if (child_fi == NULL) {
2367 free(child_si);
2368 free(my_addr);
2369 close(fd);
2370 errno = ENOMEM;
2371 return -1;
2374 child_fi->fd = fd;
2376 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2378 child_si->family = parent_si->family;
2379 child_si->type = parent_si->type;
2380 child_si->protocol = parent_si->protocol;
2381 child_si->bound = 1;
2382 child_si->is_server = 1;
2383 child_si->connected = 1;
2385 child_si->peername_len = len;
2386 child_si->peername = sockaddr_dup(my_addr, len);
2388 if (addr != NULL && addrlen != NULL) {
2389 size_t copy_len = MIN(*addrlen, len);
2390 if (copy_len > 0) {
2391 memcpy(addr, my_addr, copy_len);
2393 *addrlen = len;
2396 ret = libc_getsockname(fd,
2397 (struct sockaddr *)(void *)&un_my_addr,
2398 &un_my_addrlen);
2399 if (ret == -1) {
2400 free(child_fi);
2401 free(child_si);
2402 free(my_addr);
2403 close(fd);
2404 return ret;
2407 len = my_addrlen;
2408 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2409 child_si->family, my_addr, &len);
2410 if (ret == -1) {
2411 free(child_fi);
2412 free(child_si);
2413 free(my_addr);
2414 close(fd);
2415 return ret;
2418 SWRAP_LOG(SWRAP_LOG_TRACE,
2419 "accept() path=%s, fd=%d",
2420 un_my_addr.sun_path, s);
2422 child_si->myname_len = len;
2423 child_si->myname = sockaddr_dup(my_addr, len);
2424 free(my_addr);
2426 SWRAP_DLIST_ADD(sockets, child_si);
2428 if (addr != NULL) {
2429 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2430 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2431 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2434 return fd;
2437 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2438 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2439 #else
2440 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2441 #endif
2443 return swrap_accept(s, addr, (socklen_t *)addrlen);
2446 static int autobind_start_init;
2447 static int autobind_start;
2449 /* using sendto() or connect() on an unbound socket would give the
2450 recipient no way to reply, as unlike UDP and TCP, a unix domain
2451 socket can't auto-assign ephemeral port numbers, so we need to
2452 assign it here.
2453 Note: this might change the family from ipv6 to ipv4
2455 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2457 struct sockaddr_un un_addr;
2458 int i;
2459 char type;
2460 int ret;
2461 int port;
2462 struct stat st;
2464 if (autobind_start_init != 1) {
2465 autobind_start_init = 1;
2466 autobind_start = getpid();
2467 autobind_start %= 50000;
2468 autobind_start += 10000;
2471 un_addr.sun_family = AF_UNIX;
2473 switch (family) {
2474 case AF_INET: {
2475 struct sockaddr_in in;
2477 switch (si->type) {
2478 case SOCK_STREAM:
2479 type = SOCKET_TYPE_CHAR_TCP;
2480 break;
2481 case SOCK_DGRAM:
2482 type = SOCKET_TYPE_CHAR_UDP;
2483 break;
2484 default:
2485 errno = ESOCKTNOSUPPORT;
2486 return -1;
2489 memset(&in, 0, sizeof(in));
2490 in.sin_family = AF_INET;
2491 in.sin_addr.s_addr = htonl(127<<24 |
2492 socket_wrapper_default_iface());
2494 si->myname_len = sizeof(in);
2495 si->myname = sockaddr_dup(&in, si->myname_len);
2496 break;
2498 #ifdef HAVE_IPV6
2499 case AF_INET6: {
2500 struct sockaddr_in6 in6;
2502 if (si->family != family) {
2503 errno = ENETUNREACH;
2504 return -1;
2507 switch (si->type) {
2508 case SOCK_STREAM:
2509 type = SOCKET_TYPE_CHAR_TCP_V6;
2510 break;
2511 case SOCK_DGRAM:
2512 type = SOCKET_TYPE_CHAR_UDP_V6;
2513 break;
2514 default:
2515 errno = ESOCKTNOSUPPORT;
2516 return -1;
2519 memset(&in6, 0, sizeof(in6));
2520 in6.sin6_family = AF_INET6;
2521 in6.sin6_addr = *swrap_ipv6();
2522 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2523 si->myname_len = sizeof(in6);
2524 si->myname = sockaddr_dup(&in6, si->myname_len);
2525 break;
2527 #endif
2528 default:
2529 errno = ESOCKTNOSUPPORT;
2530 return -1;
2533 if (autobind_start > 60000) {
2534 autobind_start = 10000;
2537 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2538 port = autobind_start + i;
2539 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2540 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2541 type, socket_wrapper_default_iface(), port);
2542 if (stat(un_addr.sun_path, &st) == 0) continue;
2544 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2545 sizeof(un_addr));
2546 if (ret == -1) return ret;
2548 si->tmp_path = strdup(un_addr.sun_path);
2549 si->bound = 1;
2550 autobind_start = port + 1;
2551 break;
2553 if (i == SOCKET_MAX_SOCKETS) {
2554 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2555 "interface "SOCKET_FORMAT,
2556 SOCKET_MAX_SOCKETS,
2557 type,
2558 socket_wrapper_default_iface(),
2560 errno = ENFILE;
2561 return -1;
2564 si->family = family;
2565 set_port(si->family, port, si->myname);
2567 return 0;
2570 /****************************************************************************
2571 * CONNECT
2572 ***************************************************************************/
2574 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2575 socklen_t addrlen)
2577 int ret;
2578 struct sockaddr_un un_addr;
2579 struct socket_info *si = find_socket_info(s);
2580 int bcast = 0;
2582 if (!si) {
2583 return libc_connect(s, serv_addr, addrlen);
2586 if (si->bound == 0) {
2587 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2588 if (ret == -1) return -1;
2591 if (si->family != serv_addr->sa_family) {
2592 errno = EINVAL;
2593 return -1;
2596 ret = sockaddr_convert_to_un(si, serv_addr,
2597 addrlen, &un_addr, 0, &bcast);
2598 if (ret == -1) return -1;
2600 if (bcast) {
2601 errno = ENETUNREACH;
2602 return -1;
2605 if (si->type == SOCK_DGRAM) {
2606 si->defer_connect = 1;
2607 ret = 0;
2608 } else {
2609 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2611 ret = libc_connect(s,
2612 (struct sockaddr *)(void *)&un_addr,
2613 sizeof(struct sockaddr_un));
2616 SWRAP_LOG(SWRAP_LOG_TRACE,
2617 "connect() path=%s, fd=%d",
2618 un_addr.sun_path, s);
2621 /* to give better errors */
2622 if (ret == -1 && errno == ENOENT) {
2623 errno = EHOSTUNREACH;
2626 if (ret == 0) {
2627 si->peername_len = addrlen;
2628 si->peername = sockaddr_dup(serv_addr, addrlen);
2629 si->connected = 1;
2632 * When we connect() on a socket than we have to bind the
2633 * outgoing connection on the interface we use for the
2634 * transport. We already bound it on the right interface
2635 * but here we have to update the name so getsockname()
2636 * returns correct information.
2638 if (si->bindname != NULL) {
2639 free(si->myname);
2641 si->myname = si->bindname;
2642 si->myname_len = si->bindname_len;
2644 si->bindname = NULL;
2645 si->bindname_len = 0;
2648 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2649 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2650 } else {
2651 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2654 return ret;
2657 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2659 return swrap_connect(s, serv_addr, addrlen);
2662 /****************************************************************************
2663 * BIND
2664 ***************************************************************************/
2666 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2668 int ret;
2669 struct sockaddr_un un_addr;
2670 struct socket_info *si = find_socket_info(s);
2672 if (!si) {
2673 return libc_bind(s, myaddr, addrlen);
2676 si->myname_len = addrlen;
2677 si->myname = sockaddr_dup(myaddr, addrlen);
2679 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2680 if (ret == -1) return -1;
2682 unlink(un_addr.sun_path);
2684 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2685 sizeof(struct sockaddr_un));
2687 SWRAP_LOG(SWRAP_LOG_TRACE,
2688 "bind() path=%s, fd=%d",
2689 un_addr.sun_path, s);
2691 if (ret == 0) {
2692 si->bound = 1;
2695 return ret;
2698 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2700 return swrap_bind(s, myaddr, addrlen);
2703 /****************************************************************************
2704 * LISTEN
2705 ***************************************************************************/
2707 static int swrap_listen(int s, int backlog)
2709 int ret;
2710 struct socket_info *si = find_socket_info(s);
2712 if (!si) {
2713 return libc_listen(s, backlog);
2716 ret = libc_listen(s, backlog);
2718 return ret;
2721 int listen(int s, int backlog)
2723 return swrap_listen(s, backlog);
2726 /****************************************************************************
2727 * OPEN
2728 ***************************************************************************/
2730 static int swrap_vopen(const char *pathname, int flags, va_list ap)
2732 int ret;
2734 ret = libc_vopen(pathname, flags, ap);
2735 if (ret != -1) {
2737 * There are methods for closing descriptors (libc-internal code
2738 * paths, direct syscalls) which close descriptors in ways that
2739 * we can't intercept, so try to recover when we notice that
2740 * that's happened
2742 swrap_remove_stale(ret);
2744 return ret;
2747 int open(const char *pathname, int flags, ...)
2749 va_list ap;
2750 int fd;
2752 va_start(ap, flags);
2753 fd = swrap_vopen(pathname, flags, ap);
2754 va_end(ap);
2756 return fd;
2759 /****************************************************************************
2760 * GETPEERNAME
2761 ***************************************************************************/
2763 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2765 struct socket_info *si = find_socket_info(s);
2766 socklen_t len;
2768 if (!si) {
2769 return libc_getpeername(s, name, addrlen);
2772 if (!si->peername)
2774 errno = ENOTCONN;
2775 return -1;
2778 len = MIN(*addrlen, si->peername_len);
2779 if (len == 0) {
2780 return 0;
2783 memcpy(name, si->peername, len);
2784 *addrlen = si->peername_len;
2786 return 0;
2789 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2790 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
2791 #else
2792 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2793 #endif
2795 return swrap_getpeername(s, name, (socklen_t *)addrlen);
2798 /****************************************************************************
2799 * GETSOCKNAME
2800 ***************************************************************************/
2802 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2804 struct socket_info *si = find_socket_info(s);
2805 socklen_t len;
2807 if (!si) {
2808 return libc_getsockname(s, name, addrlen);
2811 len = MIN(*addrlen, si->myname_len);
2812 if (len == 0) {
2813 return 0;
2816 memcpy(name, si->myname, len);
2817 *addrlen = si->myname_len;
2819 return 0;
2822 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2823 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
2824 #else
2825 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
2826 #endif
2828 return swrap_getsockname(s, name, (socklen_t *)addrlen);
2831 /****************************************************************************
2832 * GETSOCKOPT
2833 ***************************************************************************/
2835 static int swrap_getsockopt(int s, int level, int optname,
2836 void *optval, socklen_t *optlen)
2838 struct socket_info *si = find_socket_info(s);
2840 if (!si) {
2841 return libc_getsockopt(s,
2842 level,
2843 optname,
2844 optval,
2845 optlen);
2848 if (level == SOL_SOCKET) {
2849 return libc_getsockopt(s,
2850 level,
2851 optname,
2852 optval,
2853 optlen);
2856 errno = ENOPROTOOPT;
2857 return -1;
2860 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2861 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
2862 #else
2863 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
2864 #endif
2866 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
2869 /****************************************************************************
2870 * SETSOCKOPT
2871 ***************************************************************************/
2873 static int swrap_setsockopt(int s, int level, int optname,
2874 const void *optval, socklen_t optlen)
2876 struct socket_info *si = find_socket_info(s);
2878 if (!si) {
2879 return libc_setsockopt(s,
2880 level,
2881 optname,
2882 optval,
2883 optlen);
2886 if (level == SOL_SOCKET) {
2887 return libc_setsockopt(s,
2888 level,
2889 optname,
2890 optval,
2891 optlen);
2894 switch (si->family) {
2895 case AF_INET:
2896 if (level == IPPROTO_IP) {
2897 #ifdef IP_PKTINFO
2898 if (optname == IP_PKTINFO) {
2899 si->pktinfo = AF_INET;
2901 #endif /* IP_PKTINFO */
2903 return 0;
2904 #ifdef HAVE_IPV6
2905 case AF_INET6:
2906 if (level == IPPROTO_IPV6) {
2907 #ifdef IPV6_RECVPKTINFO
2908 if (optname == IPV6_RECVPKTINFO) {
2909 si->pktinfo = AF_INET6;
2911 #endif /* IPV6_PKTINFO */
2913 return 0;
2914 #endif
2915 default:
2916 errno = ENOPROTOOPT;
2917 return -1;
2921 int setsockopt(int s, int level, int optname,
2922 const void *optval, socklen_t optlen)
2924 return swrap_setsockopt(s, level, optname, optval, optlen);
2927 /****************************************************************************
2928 * IOCTL
2929 ***************************************************************************/
2931 static int swrap_vioctl(int s, unsigned long int r, va_list va)
2933 struct socket_info *si = find_socket_info(s);
2934 va_list ap;
2935 int value;
2936 int rc;
2938 if (!si) {
2939 return libc_vioctl(s, r, va);
2942 va_copy(ap, va);
2944 rc = libc_vioctl(s, r, va);
2946 switch (r) {
2947 case FIONREAD:
2948 value = *((int *)va_arg(ap, int *));
2950 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
2951 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2952 } else if (value == 0) { /* END OF FILE */
2953 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
2955 break;
2958 va_end(ap);
2960 return rc;
2963 #ifdef HAVE_IOCTL_INT
2964 int ioctl(int s, int r, ...)
2965 #else
2966 int ioctl(int s, unsigned long int r, ...)
2967 #endif
2969 va_list va;
2970 int rc;
2972 va_start(va, r);
2974 rc = swrap_vioctl(s, (unsigned long int) r, va);
2976 va_end(va);
2978 return rc;
2981 /*****************
2982 * CMSG
2983 *****************/
2985 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
2987 * @brief Add a cmsghdr to a msghdr.
2989 * This is an function to add any type of cmsghdr. It will operate on the
2990 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
2991 * the buffer position after the added cmsg element. Hence, this function is
2992 * intended to be used with an intermediate msghdr and not on the original
2993 * one handed in by the client.
2995 * @param[in] msg The msghdr to which to add the cmsg.
2997 * @param[in] level The cmsg level to set.
2999 * @param[in] type The cmsg type to set.
3001 * @param[in] data The cmsg data to set.
3003 * @param[in] len the length of the data to set.
3005 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3006 int level,
3007 int type,
3008 const void *data,
3009 size_t len)
3011 size_t cmlen = CMSG_LEN(len);
3012 size_t cmspace = CMSG_SPACE(len);
3013 uint8_t cmbuf[cmspace];
3014 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3015 uint8_t *p;
3017 memset(cmbuf, 0, cmspace);
3019 if (msg->msg_controllen < cmlen) {
3020 cmlen = msg->msg_controllen;
3021 msg->msg_flags |= MSG_CTRUNC;
3024 if (msg->msg_controllen < cmspace) {
3025 cmspace = msg->msg_controllen;
3029 * We copy the full input data into an intermediate cmsghdr first
3030 * in order to more easily cope with truncation.
3032 cm->cmsg_len = cmlen;
3033 cm->cmsg_level = level;
3034 cm->cmsg_type = type;
3035 memcpy(CMSG_DATA(cm), data, len);
3038 * We now copy the possibly truncated buffer.
3039 * We copy cmlen bytes, but consume cmspace bytes,
3040 * leaving the possible padding uninitialiazed.
3042 p = (uint8_t *)msg->msg_control;
3043 memcpy(p, cm, cmlen);
3044 p += cmspace;
3045 msg->msg_control = p;
3046 msg->msg_controllen -= cmspace;
3048 return;
3051 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3052 struct msghdr *msg)
3054 /* Add packet info */
3055 switch (si->pktinfo) {
3056 #if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
3057 case AF_INET: {
3058 struct sockaddr_in *sin;
3059 struct in_pktinfo pkt;
3061 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3062 sin = (struct sockaddr_in*)si->bindname;
3063 } else {
3064 if (si->myname_len != sizeof(struct sockaddr_in)) {
3065 return 0;
3067 sin = (struct sockaddr_in*)si->myname;
3070 ZERO_STRUCT(pkt);
3072 pkt.ipi_ifindex = socket_wrapper_default_iface();
3073 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3075 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3076 &pkt, sizeof(pkt));
3078 break;
3080 #endif /* IP_PKTINFO */
3081 #if defined(HAVE_IPV6)
3082 case AF_INET6: {
3083 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3084 struct sockaddr_in6 *sin6;
3085 struct in6_pktinfo pkt6;
3087 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3088 sin6 = (struct sockaddr_in6*)si->bindname;
3089 } else {
3090 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3091 return 0;
3093 sin6 = (struct sockaddr_in6*)si->myname;
3096 ZERO_STRUCT(pkt6);
3098 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3099 pkt6.ipi6_addr = sin6->sin6_addr;
3101 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3102 &pkt6, sizeof(pkt6));
3103 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3105 break;
3107 #endif /* IPV6_PKTINFO */
3108 default:
3109 return -1;
3112 return 0;
3115 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3116 struct msghdr *omsg)
3118 int rc = 0;
3120 if (si->pktinfo > 0) {
3121 rc = swrap_msghdr_add_pktinfo(si, omsg);
3124 return rc;
3126 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3128 static ssize_t swrap_sendmsg_before(int fd,
3129 struct socket_info *si,
3130 struct msghdr *msg,
3131 struct iovec *tmp_iov,
3132 struct sockaddr_un *tmp_un,
3133 const struct sockaddr_un **to_un,
3134 const struct sockaddr **to,
3135 int *bcast)
3137 size_t i, len = 0;
3138 ssize_t ret;
3140 if (to_un) {
3141 *to_un = NULL;
3143 if (to) {
3144 *to = NULL;
3146 if (bcast) {
3147 *bcast = 0;
3150 switch (si->type) {
3151 case SOCK_STREAM:
3152 if (!si->connected) {
3153 errno = ENOTCONN;
3154 return -1;
3157 if (msg->msg_iovlen == 0) {
3158 break;
3161 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3162 size_t nlen;
3163 nlen = len + msg->msg_iov[i].iov_len;
3164 if (nlen > SOCKET_MAX_PACKET) {
3165 break;
3168 msg->msg_iovlen = i;
3169 if (msg->msg_iovlen == 0) {
3170 *tmp_iov = msg->msg_iov[0];
3171 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3172 msg->msg_iov = tmp_iov;
3173 msg->msg_iovlen = 1;
3175 break;
3177 case SOCK_DGRAM:
3178 if (si->connected) {
3179 if (msg->msg_name) {
3180 errno = EISCONN;
3181 return -1;
3183 } else {
3184 const struct sockaddr *msg_name;
3185 msg_name = (const struct sockaddr *)msg->msg_name;
3187 if (msg_name == NULL) {
3188 errno = ENOTCONN;
3189 return -1;
3193 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3194 tmp_un, 0, bcast);
3195 if (ret == -1) return -1;
3197 if (to_un) {
3198 *to_un = tmp_un;
3200 if (to) {
3201 *to = msg_name;
3203 msg->msg_name = tmp_un;
3204 msg->msg_namelen = sizeof(*tmp_un);
3207 if (si->bound == 0) {
3208 ret = swrap_auto_bind(fd, si, si->family);
3209 if (ret == -1) {
3210 if (errno == ENOTSOCK) {
3211 swrap_remove_stale(fd);
3212 return -ENOTSOCK;
3213 } else {
3214 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3215 return -1;
3220 if (!si->defer_connect) {
3221 break;
3224 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3225 tmp_un, 0, NULL);
3226 if (ret == -1) return -1;
3228 ret = libc_connect(fd,
3229 (struct sockaddr *)(void *)tmp_un,
3230 sizeof(*tmp_un));
3232 /* to give better errors */
3233 if (ret == -1 && errno == ENOENT) {
3234 errno = EHOSTUNREACH;
3237 if (ret == -1) {
3238 return ret;
3241 si->defer_connect = 0;
3242 break;
3243 default:
3244 errno = EHOSTUNREACH;
3245 return -1;
3248 return 0;
3251 static void swrap_sendmsg_after(int fd,
3252 struct socket_info *si,
3253 struct msghdr *msg,
3254 const struct sockaddr *to,
3255 ssize_t ret)
3257 int saved_errno = errno;
3258 size_t i, len = 0;
3259 uint8_t *buf;
3260 off_t ofs = 0;
3261 size_t avail = 0;
3262 size_t remain;
3264 /* to give better errors */
3265 if (ret == -1) {
3266 if (saved_errno == ENOENT) {
3267 saved_errno = EHOSTUNREACH;
3268 } else if (saved_errno == ENOTSOCK) {
3269 /* If the fd is not a socket, remove it */
3270 swrap_remove_stale(fd);
3274 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3275 avail += msg->msg_iov[i].iov_len;
3278 if (ret == -1) {
3279 remain = MIN(80, avail);
3280 } else {
3281 remain = ret;
3284 /* we capture it as one single packet */
3285 buf = (uint8_t *)malloc(remain);
3286 if (!buf) {
3287 /* we just not capture the packet */
3288 errno = saved_errno;
3289 return;
3292 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3293 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3294 memcpy(buf + ofs,
3295 msg->msg_iov[i].iov_base,
3296 this_time);
3297 ofs += this_time;
3298 remain -= this_time;
3300 len = ofs;
3302 switch (si->type) {
3303 case SOCK_STREAM:
3304 if (ret == -1) {
3305 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3306 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3307 } else {
3308 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3310 break;
3312 case SOCK_DGRAM:
3313 if (si->connected) {
3314 to = si->peername;
3316 if (ret == -1) {
3317 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3318 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3319 } else {
3320 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3322 break;
3325 free(buf);
3326 errno = saved_errno;
3329 static int swrap_recvmsg_before(int fd,
3330 struct socket_info *si,
3331 struct msghdr *msg,
3332 struct iovec *tmp_iov)
3334 size_t i, len = 0;
3335 ssize_t ret;
3337 (void)fd; /* unused */
3339 switch (si->type) {
3340 case SOCK_STREAM:
3341 if (!si->connected) {
3342 errno = ENOTCONN;
3343 return -1;
3346 if (msg->msg_iovlen == 0) {
3347 break;
3350 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3351 size_t nlen;
3352 nlen = len + msg->msg_iov[i].iov_len;
3353 if (nlen > SOCKET_MAX_PACKET) {
3354 break;
3357 msg->msg_iovlen = i;
3358 if (msg->msg_iovlen == 0) {
3359 *tmp_iov = msg->msg_iov[0];
3360 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3361 msg->msg_iov = tmp_iov;
3362 msg->msg_iovlen = 1;
3364 break;
3366 case SOCK_DGRAM:
3367 if (msg->msg_name == NULL) {
3368 errno = EINVAL;
3369 return -1;
3372 if (msg->msg_iovlen == 0) {
3373 break;
3376 if (si->bound == 0) {
3377 ret = swrap_auto_bind(fd, si, si->family);
3378 if (ret == -1) {
3380 * When attempting to read or write to a
3381 * descriptor, if an underlying autobind fails
3382 * because it's not a socket, stop intercepting
3383 * uses of that descriptor.
3385 if (errno == ENOTSOCK) {
3386 swrap_remove_stale(fd);
3387 return -ENOTSOCK;
3388 } else {
3389 SWRAP_LOG(SWRAP_LOG_ERROR,
3390 "swrap_recvmsg_before failed");
3391 return -1;
3395 break;
3396 default:
3397 errno = EHOSTUNREACH;
3398 return -1;
3401 return 0;
3404 static int swrap_recvmsg_after(int fd,
3405 struct socket_info *si,
3406 struct msghdr *msg,
3407 const struct sockaddr_un *un_addr,
3408 socklen_t un_addrlen,
3409 ssize_t ret)
3411 int saved_errno = errno;
3412 size_t i;
3413 uint8_t *buf = NULL;
3414 off_t ofs = 0;
3415 size_t avail = 0;
3416 size_t remain;
3417 int rc;
3419 /* to give better errors */
3420 if (ret == -1) {
3421 if (saved_errno == ENOENT) {
3422 saved_errno = EHOSTUNREACH;
3423 } else if (saved_errno == ENOTSOCK) {
3424 /* If the fd is not a socket, remove it */
3425 swrap_remove_stale(fd);
3429 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3430 avail += msg->msg_iov[i].iov_len;
3433 if (avail == 0) {
3434 rc = 0;
3435 goto done;
3438 if (ret == -1) {
3439 remain = MIN(80, avail);
3440 } else {
3441 remain = ret;
3444 /* we capture it as one single packet */
3445 buf = (uint8_t *)malloc(remain);
3446 if (buf == NULL) {
3447 /* we just not capture the packet */
3448 errno = saved_errno;
3449 return -1;
3452 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3453 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3454 memcpy(buf + ofs,
3455 msg->msg_iov[i].iov_base,
3456 this_time);
3457 ofs += this_time;
3458 remain -= this_time;
3461 switch (si->type) {
3462 case SOCK_STREAM:
3463 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3464 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3465 } else if (ret == 0) { /* END OF FILE */
3466 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3467 } else if (ret > 0) {
3468 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3470 break;
3472 case SOCK_DGRAM:
3473 if (ret == -1) {
3474 break;
3477 if (un_addr != NULL) {
3478 rc = sockaddr_convert_from_un(si,
3479 un_addr,
3480 un_addrlen,
3481 si->family,
3482 msg->msg_name,
3483 &msg->msg_namelen);
3484 if (rc == -1) {
3485 goto done;
3488 swrap_dump_packet(si,
3489 msg->msg_name,
3490 SWRAP_RECVFROM,
3491 buf,
3492 ret);
3493 } else {
3494 swrap_dump_packet(si,
3495 msg->msg_name,
3496 SWRAP_RECV,
3497 buf,
3498 ret);
3501 break;
3504 rc = 0;
3505 done:
3506 free(buf);
3507 errno = saved_errno;
3509 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3510 if (rc == 0 &&
3511 msg->msg_controllen > 0 &&
3512 msg->msg_control != NULL) {
3513 rc = swrap_msghdr_add_socket_info(si, msg);
3514 if (rc < 0) {
3515 return -1;
3518 #endif
3520 return rc;
3523 /****************************************************************************
3524 * RECVFROM
3525 ***************************************************************************/
3527 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
3528 struct sockaddr *from, socklen_t *fromlen)
3530 struct sockaddr_un from_addr;
3531 socklen_t from_addrlen = sizeof(from_addr);
3532 ssize_t ret;
3533 struct socket_info *si = find_socket_info(s);
3534 struct sockaddr_storage ss;
3535 socklen_t ss_len = sizeof(ss);
3536 struct msghdr msg;
3537 struct iovec tmp;
3538 int tret;
3540 if (!si) {
3541 return libc_recvfrom(s,
3542 buf,
3543 len,
3544 flags,
3545 from,
3546 fromlen);
3549 tmp.iov_base = buf;
3550 tmp.iov_len = len;
3552 ZERO_STRUCT(msg);
3553 if (from != NULL && fromlen != NULL) {
3554 msg.msg_name = from; /* optional address */
3555 msg.msg_namelen = *fromlen; /* size of address */
3556 } else {
3557 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3558 msg.msg_namelen = ss_len; /* size of address */
3560 msg.msg_iov = &tmp; /* scatter/gather array */
3561 msg.msg_iovlen = 1; /* # elements in msg_iov */
3562 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3563 msg.msg_control = NULL; /* ancillary data, see below */
3564 msg.msg_controllen = 0; /* ancillary data buffer len */
3565 msg.msg_flags = 0; /* flags on received message */
3566 #endif
3568 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3569 if (tret < 0) {
3570 return -1;
3573 buf = msg.msg_iov[0].iov_base;
3574 len = msg.msg_iov[0].iov_len;
3576 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3577 memset(&from_addr, 0, sizeof(from_addr));
3578 ret = libc_recvfrom(s,
3579 buf,
3580 len,
3581 flags,
3582 (struct sockaddr *)(void *)&from_addr,
3583 &from_addrlen);
3584 if (ret == -1) {
3585 return ret;
3588 tret = swrap_recvmsg_after(s,
3590 &msg,
3591 &from_addr,
3592 from_addrlen,
3593 ret);
3594 if (tret != 0) {
3595 return tret;
3598 if (from != NULL && fromlen != NULL) {
3599 *fromlen = msg.msg_namelen;
3602 return ret;
3605 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3606 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3607 struct sockaddr *from, Psocklen_t fromlen)
3608 #else
3609 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
3610 struct sockaddr *from, socklen_t *fromlen)
3611 #endif
3613 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
3616 /****************************************************************************
3617 * SENDTO
3618 ***************************************************************************/
3620 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
3621 const struct sockaddr *to, socklen_t tolen)
3623 struct msghdr msg;
3624 struct iovec tmp;
3625 struct sockaddr_un un_addr;
3626 const struct sockaddr_un *to_un = NULL;
3627 ssize_t ret;
3628 int rc;
3629 struct socket_info *si = find_socket_info(s);
3630 int bcast = 0;
3632 if (!si) {
3633 return libc_sendto(s, buf, len, flags, to, tolen);
3636 tmp.iov_base = discard_const_p(char, buf);
3637 tmp.iov_len = len;
3639 ZERO_STRUCT(msg);
3640 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
3641 msg.msg_namelen = tolen; /* size of address */
3642 msg.msg_iov = &tmp; /* scatter/gather array */
3643 msg.msg_iovlen = 1; /* # elements in msg_iov */
3644 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3645 msg.msg_control = NULL; /* ancillary data, see below */
3646 msg.msg_controllen = 0; /* ancillary data buffer len */
3647 msg.msg_flags = 0; /* flags on received message */
3648 #endif
3650 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
3651 if (rc < 0) {
3652 return -1;
3655 buf = msg.msg_iov[0].iov_base;
3656 len = msg.msg_iov[0].iov_len;
3658 if (bcast) {
3659 struct stat st;
3660 unsigned int iface;
3661 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
3662 char type;
3664 type = SOCKET_TYPE_CHAR_UDP;
3666 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
3667 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
3668 socket_wrapper_dir(), type, iface, prt);
3669 if (stat(un_addr.sun_path, &st) != 0) continue;
3671 /* ignore the any errors in broadcast sends */
3672 libc_sendto(s,
3673 buf,
3674 len,
3675 flags,
3676 (struct sockaddr *)(void *)&un_addr,
3677 sizeof(un_addr));
3680 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3682 return len;
3685 ret = libc_sendto(s,
3686 buf,
3687 len,
3688 flags,
3689 (struct sockaddr *)msg.msg_name,
3690 msg.msg_namelen);
3692 swrap_sendmsg_after(s, si, &msg, to, ret);
3694 return ret;
3697 ssize_t sendto(int s, const void *buf, size_t len, int flags,
3698 const struct sockaddr *to, socklen_t tolen)
3700 return swrap_sendto(s, buf, len, flags, to, tolen);
3703 /****************************************************************************
3704 * READV
3705 ***************************************************************************/
3707 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
3709 struct socket_info *si;
3710 struct msghdr msg;
3711 struct sockaddr_storage ss;
3712 socklen_t ss_len = sizeof(ss);
3713 struct iovec tmp;
3714 ssize_t ret;
3715 int tret;
3717 si = find_socket_info(s);
3718 if (si == NULL) {
3719 return libc_recv(s, buf, len, flags);
3722 tmp.iov_base = buf;
3723 tmp.iov_len = len;
3725 ZERO_STRUCT(msg);
3726 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3727 msg.msg_namelen = ss_len; /* size of address */
3728 msg.msg_iov = &tmp; /* scatter/gather array */
3729 msg.msg_iovlen = 1; /* # elements in msg_iov */
3730 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3731 msg.msg_control = NULL; /* ancillary data, see below */
3732 msg.msg_controllen = 0; /* ancillary data buffer len */
3733 msg.msg_flags = 0; /* flags on received message */
3734 #endif
3736 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3737 if (tret < 0) {
3738 return -1;
3741 buf = msg.msg_iov[0].iov_base;
3742 len = msg.msg_iov[0].iov_len;
3744 ret = libc_recv(s, buf, len, flags);
3746 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
3747 if (tret != 0) {
3748 return tret;
3751 return ret;
3754 ssize_t recv(int s, void *buf, size_t len, int flags)
3756 return swrap_recv(s, buf, len, flags);
3759 /****************************************************************************
3760 * READ
3761 ***************************************************************************/
3763 static ssize_t swrap_read(int s, void *buf, size_t len)
3765 struct socket_info *si;
3766 struct msghdr msg;
3767 struct iovec tmp;
3768 struct sockaddr_storage ss;
3769 socklen_t ss_len = sizeof(ss);
3770 ssize_t ret;
3771 int tret;
3773 si = find_socket_info(s);
3774 if (si == NULL) {
3775 return libc_read(s, buf, len);
3778 tmp.iov_base = buf;
3779 tmp.iov_len = len;
3781 ZERO_STRUCT(msg);
3782 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3783 msg.msg_namelen = ss_len; /* size of address */
3784 msg.msg_iov = &tmp; /* scatter/gather array */
3785 msg.msg_iovlen = 1; /* # elements in msg_iov */
3786 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3787 msg.msg_control = NULL; /* ancillary data, see below */
3788 msg.msg_controllen = 0; /* ancillary data buffer len */
3789 msg.msg_flags = 0; /* flags on received message */
3790 #endif
3792 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3793 if (tret < 0) {
3794 if (tret == -ENOTSOCK) {
3795 return libc_read(s, buf, len);
3797 return -1;
3800 buf = msg.msg_iov[0].iov_base;
3801 len = msg.msg_iov[0].iov_len;
3803 ret = libc_read(s, buf, len);
3805 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
3806 if (tret != 0) {
3807 return tret;
3810 return ret;
3813 ssize_t read(int s, void *buf, size_t len)
3815 return swrap_read(s, buf, len);
3818 /****************************************************************************
3819 * SEND
3820 ***************************************************************************/
3822 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
3824 struct msghdr msg;
3825 struct iovec tmp;
3826 struct sockaddr_un un_addr;
3827 ssize_t ret;
3828 int rc;
3829 struct socket_info *si = find_socket_info(s);
3831 if (!si) {
3832 return libc_send(s, buf, len, flags);
3835 tmp.iov_base = discard_const_p(char, buf);
3836 tmp.iov_len = len;
3838 ZERO_STRUCT(msg);
3839 msg.msg_name = NULL; /* optional address */
3840 msg.msg_namelen = 0; /* size of address */
3841 msg.msg_iov = &tmp; /* scatter/gather array */
3842 msg.msg_iovlen = 1; /* # elements in msg_iov */
3843 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
3844 msg.msg_control = NULL; /* ancillary data, see below */
3845 msg.msg_controllen = 0; /* ancillary data buffer len */
3846 msg.msg_flags = 0; /* flags on received message */
3847 #endif
3849 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
3850 if (rc < 0) {
3851 return -1;
3854 buf = msg.msg_iov[0].iov_base;
3855 len = msg.msg_iov[0].iov_len;
3857 ret = libc_send(s, buf, len, flags);
3859 swrap_sendmsg_after(s, si, &msg, NULL, ret);
3861 return ret;
3864 ssize_t send(int s, const void *buf, size_t len, int flags)
3866 return swrap_send(s, buf, len, flags);
3869 /****************************************************************************
3870 * RECVMSG
3871 ***************************************************************************/
3873 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
3875 struct sockaddr_un from_addr;
3876 socklen_t from_addrlen = sizeof(from_addr);
3877 struct socket_info *si;
3878 struct msghdr msg;
3879 struct iovec tmp;
3880 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3881 size_t msg_ctrllen_filled;
3882 size_t msg_ctrllen_left;
3883 #endif
3885 ssize_t ret;
3886 int rc;
3888 si = find_socket_info(s);
3889 if (si == NULL) {
3890 return libc_recvmsg(s, omsg, flags);
3893 tmp.iov_base = NULL;
3894 tmp.iov_len = 0;
3896 ZERO_STRUCT(msg);
3897 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
3898 msg.msg_namelen = from_addrlen; /* size of address */
3899 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3900 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3901 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3902 msg_ctrllen_filled = 0;
3903 msg_ctrllen_left = omsg->msg_controllen;
3905 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3906 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3907 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3908 #endif
3910 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
3911 if (rc < 0) {
3912 return -1;
3915 ret = libc_recvmsg(s, &msg, flags);
3917 msg.msg_name = omsg->msg_name;
3918 msg.msg_namelen = omsg->msg_namelen;
3920 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3921 msg_ctrllen_filled += msg.msg_controllen;
3922 msg_ctrllen_left -= msg.msg_controllen;
3924 if (omsg->msg_control != NULL) {
3925 uint8_t *p;
3927 p = omsg->msg_control;
3928 p += msg_ctrllen_filled;
3930 msg.msg_control = p;
3931 msg.msg_controllen = msg_ctrllen_left;
3932 } else {
3933 msg.msg_control = NULL;
3934 msg.msg_controllen = 0;
3936 #endif
3938 rc = swrap_recvmsg_after(s, si, &msg, &from_addr, from_addrlen, ret);
3939 if (rc != 0) {
3940 return rc;
3943 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3944 if (omsg->msg_control != NULL) {
3945 /* msg.msg_controllen = space left */
3946 msg_ctrllen_left = msg.msg_controllen;
3947 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
3950 /* Update the original message length */
3951 omsg->msg_controllen = msg_ctrllen_filled;
3952 omsg->msg_flags = msg.msg_flags;
3953 #endif
3954 omsg->msg_iovlen = msg.msg_iovlen;
3956 return ret;
3959 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
3961 return swrap_recvmsg(sockfd, msg, flags);
3964 /****************************************************************************
3965 * SENDMSG
3966 ***************************************************************************/
3968 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
3970 struct msghdr msg;
3971 struct iovec tmp;
3972 struct sockaddr_un un_addr;
3973 const struct sockaddr_un *to_un = NULL;
3974 const struct sockaddr *to = NULL;
3975 ssize_t ret;
3976 int rc;
3977 struct socket_info *si = find_socket_info(s);
3978 int bcast = 0;
3980 if (!si) {
3981 return libc_sendmsg(s, omsg, flags);
3984 ZERO_STRUCT(un_addr);
3986 tmp.iov_base = NULL;
3987 tmp.iov_len = 0;
3989 ZERO_STRUCT(msg);
3990 msg.msg_name = omsg->msg_name; /* optional address */
3991 msg.msg_namelen = omsg->msg_namelen; /* size of address */
3992 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
3993 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
3994 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3995 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
3996 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
3997 msg.msg_flags = omsg->msg_flags; /* flags on received message */
3998 #endif
4000 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4001 if (rc < 0) {
4002 return -1;
4005 if (bcast) {
4006 struct stat st;
4007 unsigned int iface;
4008 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4009 char type;
4010 size_t i, len = 0;
4011 uint8_t *buf;
4012 off_t ofs = 0;
4013 size_t avail = 0;
4014 size_t remain;
4016 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4017 avail += msg.msg_iov[i].iov_len;
4020 len = avail;
4021 remain = avail;
4023 /* we capture it as one single packet */
4024 buf = (uint8_t *)malloc(remain);
4025 if (!buf) {
4026 return -1;
4029 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4030 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4031 memcpy(buf + ofs,
4032 msg.msg_iov[i].iov_base,
4033 this_time);
4034 ofs += this_time;
4035 remain -= this_time;
4038 type = SOCKET_TYPE_CHAR_UDP;
4040 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4041 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4042 socket_wrapper_dir(), type, iface, prt);
4043 if (stat(un_addr.sun_path, &st) != 0) continue;
4045 msg.msg_name = &un_addr; /* optional address */
4046 msg.msg_namelen = sizeof(un_addr); /* size of address */
4048 /* ignore the any errors in broadcast sends */
4049 libc_sendmsg(s, &msg, flags);
4052 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4053 free(buf);
4055 return len;
4058 ret = libc_sendmsg(s, &msg, flags);
4060 swrap_sendmsg_after(s, si, &msg, to, ret);
4062 return ret;
4065 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4067 return swrap_sendmsg(s, omsg, flags);
4070 /****************************************************************************
4071 * READV
4072 ***************************************************************************/
4074 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4076 struct socket_info *si;
4077 struct msghdr msg;
4078 struct iovec tmp;
4079 struct sockaddr_storage ss;
4080 socklen_t ss_len = sizeof(ss);
4081 ssize_t ret;
4082 int rc;
4084 si = find_socket_info(s);
4085 if (si == NULL) {
4086 return libc_readv(s, vector, count);
4089 tmp.iov_base = NULL;
4090 tmp.iov_len = 0;
4092 ZERO_STRUCT(msg);
4093 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4094 msg.msg_namelen = ss_len; /* size of address */
4095 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4096 msg.msg_iovlen = count; /* # elements in msg_iov */
4097 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4098 msg.msg_control = NULL; /* ancillary data, see below */
4099 msg.msg_controllen = 0; /* ancillary data buffer len */
4100 msg.msg_flags = 0; /* flags on received message */
4101 #endif
4103 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4104 if (rc < 0) {
4105 if (rc == -ENOTSOCK) {
4106 return libc_readv(s, vector, count);
4108 return -1;
4111 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4113 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4114 if (rc != 0) {
4115 return rc;
4118 return ret;
4121 ssize_t readv(int s, const struct iovec *vector, int count)
4123 return swrap_readv(s, vector, count);
4126 /****************************************************************************
4127 * WRITEV
4128 ***************************************************************************/
4130 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4132 struct msghdr msg;
4133 struct iovec tmp;
4134 struct sockaddr_un un_addr;
4135 ssize_t ret;
4136 int rc;
4137 struct socket_info *si = find_socket_info(s);
4139 if (!si) {
4140 return libc_writev(s, vector, count);
4143 tmp.iov_base = NULL;
4144 tmp.iov_len = 0;
4146 ZERO_STRUCT(msg);
4147 msg.msg_name = NULL; /* optional address */
4148 msg.msg_namelen = 0; /* size of address */
4149 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4150 msg.msg_iovlen = count; /* # elements in msg_iov */
4151 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4152 msg.msg_control = NULL; /* ancillary data, see below */
4153 msg.msg_controllen = 0; /* ancillary data buffer len */
4154 msg.msg_flags = 0; /* flags on received message */
4155 #endif
4157 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4158 if (rc < 0) {
4159 if (rc == -ENOTSOCK) {
4160 return libc_readv(s, vector, count);
4162 return -1;
4165 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4167 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4169 return ret;
4172 ssize_t writev(int s, const struct iovec *vector, int count)
4174 return swrap_writev(s, vector, count);
4177 /****************************
4178 * CLOSE
4179 ***************************/
4181 static int swrap_close(int fd)
4183 struct socket_info *si = find_socket_info(fd);
4184 struct socket_info_fd *fi;
4185 int ret;
4187 if (!si) {
4188 return libc_close(fd);
4191 for (fi = si->fds; fi; fi = fi->next) {
4192 if (fi->fd == fd) {
4193 SWRAP_DLIST_REMOVE(si->fds, fi);
4194 free(fi);
4195 break;
4199 if (si->fds) {
4200 /* there are still references left */
4201 return libc_close(fd);
4204 SWRAP_DLIST_REMOVE(sockets, si);
4206 if (si->myname && si->peername) {
4207 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4210 ret = libc_close(fd);
4212 if (si->myname && si->peername) {
4213 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4214 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4217 if (si->bindname != NULL) {
4218 free(si->bindname);
4221 if (si->myname) free(si->myname);
4222 if (si->peername) free(si->peername);
4223 if (si->tmp_path) {
4224 unlink(si->tmp_path);
4225 free(si->tmp_path);
4227 free(si);
4229 return ret;
4232 int close(int fd)
4234 return swrap_close(fd);
4237 /****************************
4238 * DUP
4239 ***************************/
4241 static int swrap_dup(int fd)
4243 struct socket_info *si;
4244 struct socket_info_fd *fi;
4246 si = find_socket_info(fd);
4248 if (!si) {
4249 return libc_dup(fd);
4252 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4253 if (fi == NULL) {
4254 errno = ENOMEM;
4255 return -1;
4258 fi->fd = libc_dup(fd);
4259 if (fi->fd == -1) {
4260 int saved_errno = errno;
4261 free(fi);
4262 errno = saved_errno;
4263 return -1;
4266 /* Make sure we don't have an entry for the fd */
4267 swrap_remove_stale(fi->fd);
4269 SWRAP_DLIST_ADD(si->fds, fi);
4270 return fi->fd;
4273 int dup(int fd)
4275 return swrap_dup(fd);
4278 /****************************
4279 * DUP2
4280 ***************************/
4282 static int swrap_dup2(int fd, int newfd)
4284 struct socket_info *si;
4285 struct socket_info_fd *fi;
4287 si = find_socket_info(fd);
4289 if (!si) {
4290 return libc_dup2(fd, newfd);
4293 if (find_socket_info(newfd)) {
4294 /* dup2() does an implicit close of newfd, which we
4295 * need to emulate */
4296 swrap_close(newfd);
4299 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4300 if (fi == NULL) {
4301 errno = ENOMEM;
4302 return -1;
4305 fi->fd = libc_dup2(fd, newfd);
4306 if (fi->fd == -1) {
4307 int saved_errno = errno;
4308 free(fi);
4309 errno = saved_errno;
4310 return -1;
4313 /* Make sure we don't have an entry for the fd */
4314 swrap_remove_stale(fi->fd);
4316 SWRAP_DLIST_ADD(si->fds, fi);
4317 return fi->fd;
4320 int dup2(int fd, int newfd)
4322 return swrap_dup2(fd, newfd);
4325 /****************************
4326 * DUP2
4327 ***************************/
4329 #ifdef HAVE_EVENTFD
4330 static int swrap_eventfd(int count, int flags)
4332 int fd;
4334 fd = libc_eventfd(count, flags);
4335 if (fd != -1) {
4336 swrap_remove_stale(fd);
4339 return fd;
4342 int eventfd(int count, int flags)
4344 return swrap_eventfd(count, flags);
4346 #endif
4348 /****************************
4349 * DESTRUCTOR
4350 ***************************/
4353 * This function is called when the library is unloaded and makes sure that
4354 * sockets get closed and the unix file for the socket are unlinked.
4356 void swrap_destructor(void)
4358 struct socket_info *s = sockets;
4360 while (s != NULL) {
4361 struct socket_info_fd *f = s->fds;
4362 if (f != NULL) {
4363 swrap_close(f->fd);
4365 s = sockets;