swrap: fix AF_UNSPEC special case in swrap_bind()
[Samba.git] / lib / socket_wrapper / socket_wrapper.c
blobb66b9510f471631b3274639d64fe7587849a4d13
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
79 #ifdef HAVE_RPC_RPC_H
80 #include <rpc/rpc.h>
81 #endif
83 enum swrap_dbglvl_e {
84 SWRAP_LOG_ERROR = 0,
85 SWRAP_LOG_WARN,
86 SWRAP_LOG_DEBUG,
87 SWRAP_LOG_TRACE
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
93 #else
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
99 #else
100 #define DESTRUCTOR_ATTRIBUTE
101 #endif
103 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
105 #else
106 # define SWRAP_THREAD
107 #endif
109 #ifndef MIN
110 #define MIN(a,b) ((a)<(b)?(a):(b))
111 #endif
113 #ifndef ZERO_STRUCT
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
115 #endif
117 #ifndef ZERO_STRUCTP
118 #define ZERO_STRUCTP(x) do { \
119 if ((x) != NULL) \
120 memset((char *)(x), 0, sizeof(*(x))); \
121 } while(0)
122 #endif
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
126 #endif
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
130 #endif
132 #ifdef IPV6_PKTINFO
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
143 #ifndef IP_PKTINFO
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
146 # endif
147 #endif
150 #define SWRAP_DLIST_ADD(list,item) do { \
151 if (!(list)) { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
154 (list) = (item); \
155 } else { \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
159 (list) = (item); \
161 } while (0)
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
166 if (list) { \
167 (list)->prev = NULL; \
169 } else { \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
179 } while (0)
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
183 #else
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
185 #endif
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct socket_info_fd {
214 struct socket_info_fd *prev, *next;
215 int fd;
218 struct socket_info
220 struct socket_info_fd *fds;
222 int family;
223 int type;
224 int protocol;
225 int bound;
226 int bcast;
227 int is_server;
228 int connected;
229 int defer_connect;
230 int pktinfo;
232 char *tmp_path;
234 struct sockaddr *bindname;
235 socklen_t bindname_len;
237 struct sockaddr *myname;
238 socklen_t myname_len;
240 struct sockaddr *peername;
241 socklen_t peername_len;
243 struct {
244 unsigned long pck_snd;
245 unsigned long pck_rcv;
246 } io;
248 struct socket_info *prev, *next;
252 * File descriptors are shared between threads so we should share socket
253 * information too.
255 struct socket_info *sockets;
257 /* Function prototypes */
259 bool socket_wrapper_enabled(void);
260 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
262 #ifdef NDEBUG
263 # define SWRAP_LOG(...)
264 #else
266 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
267 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
269 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
271 char buffer[1024];
272 va_list va;
273 const char *d;
274 unsigned int lvl = 0;
276 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
277 if (d != NULL) {
278 lvl = atoi(d);
281 va_start(va, format);
282 vsnprintf(buffer, sizeof(buffer), format, va);
283 va_end(va);
285 if (lvl >= dbglvl) {
286 switch (dbglvl) {
287 case SWRAP_LOG_ERROR:
288 fprintf(stderr,
289 "SWRAP_ERROR(%d): %s\n",
290 (int)getpid(), buffer);
291 break;
292 case SWRAP_LOG_WARN:
293 fprintf(stderr,
294 "SWRAP_WARN(%d): %s\n",
295 (int)getpid(), buffer);
296 break;
297 case SWRAP_LOG_DEBUG:
298 fprintf(stderr,
299 "SWRAP_DEBUG(%d): %s\n",
300 (int)getpid(), buffer);
301 break;
302 case SWRAP_LOG_TRACE:
303 fprintf(stderr,
304 "SWRAP_TRACE(%d): %s\n",
305 (int)getpid(), buffer);
306 break;
310 #endif
312 /*********************************************************
313 * SWRAP LOADING LIBC FUNCTIONS
314 *********************************************************/
316 #include <dlfcn.h>
318 struct swrap_libc_fns {
319 int (*libc_accept)(int sockfd,
320 struct sockaddr *addr,
321 socklen_t *addrlen);
322 int (*libc_bind)(int sockfd,
323 const struct sockaddr *addr,
324 socklen_t addrlen);
325 int (*libc_close)(int fd);
326 int (*libc_connect)(int sockfd,
327 const struct sockaddr *addr,
328 socklen_t addrlen);
329 int (*libc_dup)(int fd);
330 int (*libc_dup2)(int oldfd, int newfd);
331 #ifdef HAVE_EVENTFD
332 int (*libc_eventfd)(int count, int flags);
333 #endif
334 int (*libc_getpeername)(int sockfd,
335 struct sockaddr *addr,
336 socklen_t *addrlen);
337 int (*libc_getsockname)(int sockfd,
338 struct sockaddr *addr,
339 socklen_t *addrlen);
340 int (*libc_getsockopt)(int sockfd,
341 int level,
342 int optname,
343 void *optval,
344 socklen_t *optlen);
345 int (*libc_ioctl)(int d, unsigned long int request, ...);
346 int (*libc_listen)(int sockfd, int backlog);
347 int (*libc_open)(const char *pathname, int flags, mode_t mode);
348 int (*libc_pipe)(int pipefd[2]);
349 int (*libc_read)(int fd, void *buf, size_t count);
350 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
351 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
352 int (*libc_recvfrom)(int sockfd,
353 void *buf,
354 size_t len,
355 int flags,
356 struct sockaddr *src_addr,
357 socklen_t *addrlen);
358 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
359 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
360 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
361 int (*libc_sendto)(int sockfd,
362 const void *buf,
363 size_t len,
364 int flags,
365 const struct sockaddr *dst_addr,
366 socklen_t addrlen);
367 int (*libc_setsockopt)(int sockfd,
368 int level,
369 int optname,
370 const void *optval,
371 socklen_t optlen);
372 #ifdef HAVE_SIGNALFD
373 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
374 #endif
375 int (*libc_socket)(int domain, int type, int protocol);
376 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
377 #ifdef HAVE_TIMERFD_CREATE
378 int (*libc_timerfd_create)(int clockid, int flags);
379 #endif
380 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
383 struct swrap {
384 void *libc_handle;
385 void *libsocket_handle;
387 bool initialised;
388 bool enabled;
390 char *socket_dir;
392 struct swrap_libc_fns fns;
395 static struct swrap swrap;
397 /* prototypes */
398 static const char *socket_wrapper_dir(void);
400 #define LIBC_NAME "libc.so"
402 enum swrap_lib {
403 SWRAP_LIBC,
404 SWRAP_LIBNSL,
405 SWRAP_LIBSOCKET,
408 #ifndef NDEBUG
409 static const char *swrap_str_lib(enum swrap_lib lib)
411 switch (lib) {
412 case SWRAP_LIBC:
413 return "libc";
414 case SWRAP_LIBNSL:
415 return "libnsl";
416 case SWRAP_LIBSOCKET:
417 return "libsocket";
420 /* Compiler would warn us about unhandled enum value if we get here */
421 return "unknown";
423 #endif
425 static void *swrap_load_lib_handle(enum swrap_lib lib)
427 int flags = RTLD_LAZY;
428 void *handle = NULL;
429 int i;
431 #ifdef RTLD_DEEPBIND
432 flags |= RTLD_DEEPBIND;
433 #endif
435 switch (lib) {
436 case SWRAP_LIBNSL:
437 /* FALL TROUGH */
438 case SWRAP_LIBSOCKET:
439 #ifdef HAVE_LIBSOCKET
440 handle = swrap.libsocket_handle;
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), "libsocket.so.%d", i);
446 handle = dlopen(soname, flags);
449 swrap.libsocket_handle = handle;
451 break;
452 #endif
453 /* FALL TROUGH */
454 case SWRAP_LIBC:
455 handle = swrap.libc_handle;
456 #ifdef LIBC_SO
457 if (handle == NULL) {
458 handle = dlopen(LIBC_SO, flags);
460 swrap.libc_handle = handle;
462 #endif
463 if (handle == NULL) {
464 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
465 char soname[256] = {0};
467 snprintf(soname, sizeof(soname), "libc.so.%d", i);
468 handle = dlopen(soname, flags);
471 swrap.libc_handle = handle;
473 break;
476 if (handle == NULL) {
477 #ifdef RTLD_NEXT
478 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
479 #else
480 SWRAP_LOG(SWRAP_LOG_ERROR,
481 "Failed to dlopen library: %s\n",
482 dlerror());
483 exit(-1);
484 #endif
487 return handle;
490 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
492 void *handle;
493 void *func;
495 handle = swrap_load_lib_handle(lib);
497 func = dlsym(handle, fn_name);
498 if (func == NULL) {
499 SWRAP_LOG(SWRAP_LOG_ERROR,
500 "Failed to find %s: %s\n",
501 fn_name, dlerror());
502 exit(-1);
505 SWRAP_LOG(SWRAP_LOG_TRACE,
506 "Loaded %s from %s",
507 fn_name, swrap_str_lib(lib));
508 return func;
511 #define swrap_load_lib_function(lib, fn_name) \
512 if (swrap.fns.libc_##fn_name == NULL) { \
513 *(void **) (&swrap.fns.libc_##fn_name) = \
514 _swrap_load_lib_function(lib, #fn_name); \
519 * IMPORTANT
521 * Functions especially from libc need to be loaded individually, you can't load
522 * all at once or gdb will segfault at startup. The same applies to valgrind and
523 * has probably something todo with with the linker.
524 * So we need load each function at the point it is called the first time.
526 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
528 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
530 return swrap.fns.libc_accept(sockfd, addr, addrlen);
533 static int libc_bind(int sockfd,
534 const struct sockaddr *addr,
535 socklen_t addrlen)
537 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
539 return swrap.fns.libc_bind(sockfd, addr, addrlen);
542 static int libc_close(int fd)
544 swrap_load_lib_function(SWRAP_LIBC, close);
546 return swrap.fns.libc_close(fd);
549 static int libc_connect(int sockfd,
550 const struct sockaddr *addr,
551 socklen_t addrlen)
553 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
555 return swrap.fns.libc_connect(sockfd, addr, addrlen);
558 static int libc_dup(int fd)
560 swrap_load_lib_function(SWRAP_LIBC, dup);
562 return swrap.fns.libc_dup(fd);
565 static int libc_dup2(int oldfd, int newfd)
567 swrap_load_lib_function(SWRAP_LIBC, dup2);
569 return swrap.fns.libc_dup2(oldfd, newfd);
572 #ifdef HAVE_EVENTFD
573 static int libc_eventfd(int count, int flags)
575 swrap_load_lib_function(SWRAP_LIBC, eventfd);
577 return swrap.fns.libc_eventfd(count, flags);
579 #endif
581 static int libc_getpeername(int sockfd,
582 struct sockaddr *addr,
583 socklen_t *addrlen)
585 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
587 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
590 static int libc_getsockname(int sockfd,
591 struct sockaddr *addr,
592 socklen_t *addrlen)
594 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
596 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
599 static int libc_getsockopt(int sockfd,
600 int level,
601 int optname,
602 void *optval,
603 socklen_t *optlen)
605 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
607 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
610 static int libc_vioctl(int d, unsigned long int request, va_list ap)
612 long int args[4];
613 int rc;
614 int i;
616 swrap_load_lib_function(SWRAP_LIBC, ioctl);
618 for (i = 0; i < 4; i++) {
619 args[i] = va_arg(ap, long int);
622 rc = swrap.fns.libc_ioctl(d,
623 request,
624 args[0],
625 args[1],
626 args[2],
627 args[3]);
629 return rc;
632 static int libc_listen(int sockfd, int backlog)
634 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
636 return swrap.fns.libc_listen(sockfd, backlog);
639 static int libc_vopen(const char *pathname, int flags, va_list ap)
641 long int mode = 0;
642 int fd;
644 swrap_load_lib_function(SWRAP_LIBC, open);
646 mode = va_arg(ap, long int);
648 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
650 return fd;
653 static int libc_open(const char *pathname, int flags, ...)
655 va_list ap;
656 int fd;
658 va_start(ap, flags);
659 fd = libc_vopen(pathname, flags, ap);
660 va_end(ap);
662 return fd;
665 static int libc_pipe(int pipefd[2])
667 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
669 return swrap.fns.libc_pipe(pipefd);
672 static int libc_read(int fd, void *buf, size_t count)
674 swrap_load_lib_function(SWRAP_LIBC, read);
676 return swrap.fns.libc_read(fd, buf, count);
679 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
681 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
683 return swrap.fns.libc_readv(fd, iov, iovcnt);
686 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
688 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
690 return swrap.fns.libc_recv(sockfd, buf, len, flags);
693 static int libc_recvfrom(int sockfd,
694 void *buf,
695 size_t len,
696 int flags,
697 struct sockaddr *src_addr,
698 socklen_t *addrlen)
700 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
702 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
705 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
707 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
709 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
712 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
714 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
716 return swrap.fns.libc_send(sockfd, buf, len, flags);
719 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
721 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
723 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
726 static int libc_sendto(int sockfd,
727 const void *buf,
728 size_t len,
729 int flags,
730 const struct sockaddr *dst_addr,
731 socklen_t addrlen)
733 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
735 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
738 static int libc_setsockopt(int sockfd,
739 int level,
740 int optname,
741 const void *optval,
742 socklen_t optlen)
744 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
746 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
749 #ifdef HAVE_SIGNALFD
750 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
752 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
754 return swrap.fns.libc_signalfd(fd, mask, flags);
756 #endif
758 static int libc_socket(int domain, int type, int protocol)
760 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
762 return swrap.fns.libc_socket(domain, type, protocol);
765 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
767 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
769 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
772 #ifdef HAVE_TIMERFD_CREATE
773 static int libc_timerfd_create(int clockid, int flags)
775 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
777 return swrap.fns.libc_timerfd_create(clockid, flags);
779 #endif
781 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
783 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
785 return swrap.fns.libc_writev(fd, iov, iovcnt);
788 /*********************************************************
789 * SWRAP HELPER FUNCTIONS
790 *********************************************************/
792 #ifdef HAVE_IPV6
794 * FD00::5357:5FXX
796 static const struct in6_addr *swrap_ipv6(void)
798 static struct in6_addr v;
799 static int initialized;
800 int ret;
802 if (initialized) {
803 return &v;
805 initialized = 1;
807 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
808 if (ret <= 0) {
809 abort();
812 return &v;
814 #endif
816 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
818 struct sockaddr *ret = (struct sockaddr *)malloc(len);
819 memcpy(ret, data, len);
820 return ret;
823 static void set_port(int family, int prt, struct sockaddr *addr)
825 switch (family) {
826 case AF_INET:
827 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
828 break;
829 #ifdef HAVE_IPV6
830 case AF_INET6:
831 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
832 break;
833 #endif
837 static size_t socket_length(int family)
839 switch (family) {
840 case AF_INET:
841 return sizeof(struct sockaddr_in);
842 #ifdef HAVE_IPV6
843 case AF_INET6:
844 return sizeof(struct sockaddr_in6);
845 #endif
847 return 0;
850 static const char *socket_wrapper_dir(void)
852 const char *s = getenv("SOCKET_WRAPPER_DIR");
853 if (s == NULL) {
854 return NULL;
856 /* TODO use realpath(3) here, when we add support for threads */
857 if (strncmp(s, "./", 2) == 0) {
858 s += 2;
861 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
862 return s;
865 bool socket_wrapper_enabled(void)
867 const char *s = socket_wrapper_dir();
869 return s != NULL ? true : false;
872 static unsigned int socket_wrapper_default_iface(void)
874 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
875 if (s) {
876 unsigned int iface;
877 if (sscanf(s, "%u", &iface) == 1) {
878 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
879 return iface;
884 return 1;/* 127.0.0.1 */
887 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
889 unsigned int iface;
890 unsigned int prt;
891 const char *p;
892 char type;
894 p = strrchr(un->sun_path, '/');
895 if (p) p++; else p = un->sun_path;
897 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
898 errno = EINVAL;
899 return -1;
902 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
903 type, iface, prt);
905 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
906 errno = EINVAL;
907 return -1;
910 if (prt > 0xFFFF) {
911 errno = EINVAL;
912 return -1;
915 switch(type) {
916 case SOCKET_TYPE_CHAR_TCP:
917 case SOCKET_TYPE_CHAR_UDP: {
918 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
920 if ((*len) < sizeof(*in2)) {
921 errno = EINVAL;
922 return -1;
925 memset(in2, 0, sizeof(*in2));
926 in2->sin_family = AF_INET;
927 in2->sin_addr.s_addr = htonl((127<<24) | iface);
928 in2->sin_port = htons(prt);
930 *len = sizeof(*in2);
931 break;
933 #ifdef HAVE_IPV6
934 case SOCKET_TYPE_CHAR_TCP_V6:
935 case SOCKET_TYPE_CHAR_UDP_V6: {
936 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
938 if ((*len) < sizeof(*in2)) {
939 errno = EINVAL;
940 return -1;
943 memset(in2, 0, sizeof(*in2));
944 in2->sin6_family = AF_INET6;
945 in2->sin6_addr = *swrap_ipv6();
946 in2->sin6_addr.s6_addr[15] = iface;
947 in2->sin6_port = htons(prt);
949 *len = sizeof(*in2);
950 break;
952 #endif
953 default:
954 errno = EINVAL;
955 return -1;
958 return 0;
961 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
962 int *bcast)
964 char type = '\0';
965 unsigned int prt;
966 unsigned int iface;
967 int is_bcast = 0;
969 if (bcast) *bcast = 0;
971 switch (inaddr->sa_family) {
972 case AF_INET: {
973 const struct sockaddr_in *in =
974 (const struct sockaddr_in *)(const void *)inaddr;
975 unsigned int addr = ntohl(in->sin_addr.s_addr);
976 char u_type = '\0';
977 char b_type = '\0';
978 char a_type = '\0';
980 switch (si->type) {
981 case SOCK_STREAM:
982 u_type = SOCKET_TYPE_CHAR_TCP;
983 break;
984 case SOCK_DGRAM:
985 u_type = SOCKET_TYPE_CHAR_UDP;
986 a_type = SOCKET_TYPE_CHAR_UDP;
987 b_type = SOCKET_TYPE_CHAR_UDP;
988 break;
989 default:
990 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
991 errno = ESOCKTNOSUPPORT;
992 return -1;
995 prt = ntohs(in->sin_port);
996 if (a_type && addr == 0xFFFFFFFF) {
997 /* 255.255.255.255 only udp */
998 is_bcast = 2;
999 type = a_type;
1000 iface = socket_wrapper_default_iface();
1001 } else if (b_type && addr == 0x7FFFFFFF) {
1002 /* 127.255.255.255 only udp */
1003 is_bcast = 1;
1004 type = b_type;
1005 iface = socket_wrapper_default_iface();
1006 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1007 /* 127.0.0.X */
1008 is_bcast = 0;
1009 type = u_type;
1010 iface = (addr & 0x000000FF);
1011 } else {
1012 errno = ENETUNREACH;
1013 return -1;
1015 if (bcast) *bcast = is_bcast;
1016 break;
1018 #ifdef HAVE_IPV6
1019 case AF_INET6: {
1020 const struct sockaddr_in6 *in =
1021 (const struct sockaddr_in6 *)(const void *)inaddr;
1022 struct in6_addr cmp1, cmp2;
1024 switch (si->type) {
1025 case SOCK_STREAM:
1026 type = SOCKET_TYPE_CHAR_TCP_V6;
1027 break;
1028 case SOCK_DGRAM:
1029 type = SOCKET_TYPE_CHAR_UDP_V6;
1030 break;
1031 default:
1032 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1033 errno = ESOCKTNOSUPPORT;
1034 return -1;
1037 /* XXX no multicast/broadcast */
1039 prt = ntohs(in->sin6_port);
1041 cmp1 = *swrap_ipv6();
1042 cmp2 = in->sin6_addr;
1043 cmp2.s6_addr[15] = 0;
1044 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1045 iface = in->sin6_addr.s6_addr[15];
1046 } else {
1047 errno = ENETUNREACH;
1048 return -1;
1051 break;
1053 #endif
1054 default:
1055 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1056 errno = ENETUNREACH;
1057 return -1;
1060 if (prt == 0) {
1061 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1062 errno = EINVAL;
1063 return -1;
1066 if (is_bcast) {
1067 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1068 socket_wrapper_dir());
1069 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1070 /* the caller need to do more processing */
1071 return 0;
1074 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1075 socket_wrapper_dir(), type, iface, prt);
1076 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1078 return 0;
1081 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1082 int *bcast)
1084 char type = '\0';
1085 unsigned int prt;
1086 unsigned int iface;
1087 struct stat st;
1088 int is_bcast = 0;
1090 if (bcast) *bcast = 0;
1092 switch (si->family) {
1093 case AF_INET: {
1094 const struct sockaddr_in *in =
1095 (const struct sockaddr_in *)(const void *)inaddr;
1096 unsigned int addr = ntohl(in->sin_addr.s_addr);
1097 char u_type = '\0';
1098 char d_type = '\0';
1099 char b_type = '\0';
1100 char a_type = '\0';
1102 prt = ntohs(in->sin_port);
1104 switch (si->type) {
1105 case SOCK_STREAM:
1106 u_type = SOCKET_TYPE_CHAR_TCP;
1107 d_type = SOCKET_TYPE_CHAR_TCP;
1108 break;
1109 case SOCK_DGRAM:
1110 u_type = SOCKET_TYPE_CHAR_UDP;
1111 d_type = SOCKET_TYPE_CHAR_UDP;
1112 a_type = SOCKET_TYPE_CHAR_UDP;
1113 b_type = SOCKET_TYPE_CHAR_UDP;
1114 break;
1115 default:
1116 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1117 errno = ESOCKTNOSUPPORT;
1118 return -1;
1121 if (addr == 0) {
1122 /* 0.0.0.0 */
1123 is_bcast = 0;
1124 type = d_type;
1125 iface = socket_wrapper_default_iface();
1126 } else if (a_type && addr == 0xFFFFFFFF) {
1127 /* 255.255.255.255 only udp */
1128 is_bcast = 2;
1129 type = a_type;
1130 iface = socket_wrapper_default_iface();
1131 } else if (b_type && addr == 0x7FFFFFFF) {
1132 /* 127.255.255.255 only udp */
1133 is_bcast = 1;
1134 type = b_type;
1135 iface = socket_wrapper_default_iface();
1136 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1137 /* 127.0.0.X */
1138 is_bcast = 0;
1139 type = u_type;
1140 iface = (addr & 0x000000FF);
1141 } else {
1142 errno = EADDRNOTAVAIL;
1143 return -1;
1146 /* Store the bind address for connect() */
1147 if (si->bindname == NULL) {
1148 struct sockaddr_in bind_in;
1149 socklen_t blen = sizeof(struct sockaddr_in);
1151 ZERO_STRUCT(bind_in);
1152 bind_in.sin_family = in->sin_family;
1153 bind_in.sin_port = in->sin_port;
1154 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1156 si->bindname = sockaddr_dup(&bind_in, blen);
1157 si->bindname_len = blen;
1160 break;
1162 #ifdef HAVE_IPV6
1163 case AF_INET6: {
1164 const struct sockaddr_in6 *in =
1165 (const struct sockaddr_in6 *)(const void *)inaddr;
1166 struct in6_addr cmp1, cmp2;
1168 switch (si->type) {
1169 case SOCK_STREAM:
1170 type = SOCKET_TYPE_CHAR_TCP_V6;
1171 break;
1172 case SOCK_DGRAM:
1173 type = SOCKET_TYPE_CHAR_UDP_V6;
1174 break;
1175 default:
1176 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1177 errno = ESOCKTNOSUPPORT;
1178 return -1;
1181 /* XXX no multicast/broadcast */
1183 prt = ntohs(in->sin6_port);
1185 cmp1 = *swrap_ipv6();
1186 cmp2 = in->sin6_addr;
1187 cmp2.s6_addr[15] = 0;
1188 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1189 iface = socket_wrapper_default_iface();
1190 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1191 iface = in->sin6_addr.s6_addr[15];
1192 } else {
1193 errno = EADDRNOTAVAIL;
1194 return -1;
1197 /* Store the bind address for connect() */
1198 if (si->bindname == NULL) {
1199 struct sockaddr_in6 bind_in;
1200 socklen_t blen = sizeof(struct sockaddr_in6);
1202 ZERO_STRUCT(bind_in);
1203 bind_in.sin6_family = in->sin6_family;
1204 bind_in.sin6_port = in->sin6_port;
1206 bind_in.sin6_addr = *swrap_ipv6();
1207 bind_in.sin6_addr.s6_addr[15] = iface;
1209 si->bindname = sockaddr_dup(&bind_in, blen);
1210 si->bindname_len = blen;
1213 break;
1215 #endif
1216 default:
1217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1218 errno = EADDRNOTAVAIL;
1219 return -1;
1223 if (bcast) *bcast = is_bcast;
1225 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1226 errno = EINVAL;
1227 return -1;
1230 if (prt == 0) {
1231 /* handle auto-allocation of ephemeral ports */
1232 for (prt = 5001; prt < 10000; prt++) {
1233 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1234 socket_wrapper_dir(), type, iface, prt);
1235 if (stat(un->sun_path, &st) == 0) continue;
1237 set_port(si->family, prt, si->myname);
1238 set_port(si->family, prt, si->bindname);
1240 break;
1242 if (prt == 10000) {
1243 errno = ENFILE;
1244 return -1;
1248 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1249 socket_wrapper_dir(), type, iface, prt);
1250 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1251 return 0;
1254 static struct socket_info *find_socket_info(int fd)
1256 struct socket_info *i;
1258 for (i = sockets; i; i = i->next) {
1259 struct socket_info_fd *f;
1260 for (f = i->fds; f; f = f->next) {
1261 if (f->fd == fd) {
1262 return i;
1267 return NULL;
1270 static void swrap_remove_stale(int fd)
1272 struct socket_info *si = find_socket_info(fd);
1273 struct socket_info_fd *fi;
1275 if (si != NULL) {
1276 for (fi = si->fds; fi; fi = fi->next) {
1277 if (fi->fd == fd) {
1278 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1279 SWRAP_DLIST_REMOVE(si->fds, fi);
1280 free(fi);
1281 break;
1285 if (si->fds == NULL) {
1286 SWRAP_DLIST_REMOVE(sockets, si);
1291 static int sockaddr_convert_to_un(struct socket_info *si,
1292 const struct sockaddr *in_addr,
1293 socklen_t in_len,
1294 struct sockaddr_un *out_addr,
1295 int alloc_sock,
1296 int *bcast)
1298 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1300 (void) in_len; /* unused */
1302 if (out_addr == NULL) {
1303 return 0;
1306 out->sa_family = AF_UNIX;
1307 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1308 out->sa_len = sizeof(*out_addr);
1309 #endif
1311 switch (in_addr->sa_family) {
1312 case AF_UNSPEC: {
1313 struct sockaddr_in *sin;
1314 if (si->family != AF_INET) {
1315 break;
1317 if (in_len < sizeof(struct sockaddr_in)) {
1318 break;
1320 sin = (struct sockaddr_in *)in_addr;
1321 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1322 break;
1326 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1327 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1330 /* FALL THROUGH */
1332 case AF_INET:
1333 #ifdef HAVE_IPV6
1334 case AF_INET6:
1335 #endif
1336 switch (si->type) {
1337 case SOCK_STREAM:
1338 case SOCK_DGRAM:
1339 break;
1340 default:
1341 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1342 errno = ESOCKTNOSUPPORT;
1343 return -1;
1345 if (alloc_sock) {
1346 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1347 } else {
1348 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1350 default:
1351 break;
1354 errno = EAFNOSUPPORT;
1355 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1356 return -1;
1359 static int sockaddr_convert_from_un(const struct socket_info *si,
1360 const struct sockaddr_un *in_addr,
1361 socklen_t un_addrlen,
1362 int family,
1363 struct sockaddr *out_addr,
1364 socklen_t *out_addrlen)
1366 int ret;
1368 if (out_addr == NULL || out_addrlen == NULL)
1369 return 0;
1371 if (un_addrlen == 0) {
1372 *out_addrlen = 0;
1373 return 0;
1376 switch (family) {
1377 case AF_INET:
1378 #ifdef HAVE_IPV6
1379 case AF_INET6:
1380 #endif
1381 switch (si->type) {
1382 case SOCK_STREAM:
1383 case SOCK_DGRAM:
1384 break;
1385 default:
1386 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1387 errno = ESOCKTNOSUPPORT;
1388 return -1;
1390 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1391 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1392 out_addr->sa_len = *out_addrlen;
1393 #endif
1394 return ret;
1395 default:
1396 break;
1399 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1400 errno = EAFNOSUPPORT;
1401 return -1;
1404 enum swrap_packet_type {
1405 SWRAP_CONNECT_SEND,
1406 SWRAP_CONNECT_UNREACH,
1407 SWRAP_CONNECT_RECV,
1408 SWRAP_CONNECT_ACK,
1409 SWRAP_ACCEPT_SEND,
1410 SWRAP_ACCEPT_RECV,
1411 SWRAP_ACCEPT_ACK,
1412 SWRAP_RECVFROM,
1413 SWRAP_SENDTO,
1414 SWRAP_SENDTO_UNREACH,
1415 SWRAP_PENDING_RST,
1416 SWRAP_RECV,
1417 SWRAP_RECV_RST,
1418 SWRAP_SEND,
1419 SWRAP_SEND_RST,
1420 SWRAP_CLOSE_SEND,
1421 SWRAP_CLOSE_RECV,
1422 SWRAP_CLOSE_ACK,
1425 struct swrap_file_hdr {
1426 uint32_t magic;
1427 uint16_t version_major;
1428 uint16_t version_minor;
1429 int32_t timezone;
1430 uint32_t sigfigs;
1431 uint32_t frame_max_len;
1432 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1433 uint32_t link_type;
1435 #define SWRAP_FILE_HDR_SIZE 24
1437 struct swrap_packet_frame {
1438 uint32_t seconds;
1439 uint32_t micro_seconds;
1440 uint32_t recorded_length;
1441 uint32_t full_length;
1443 #define SWRAP_PACKET_FRAME_SIZE 16
1445 union swrap_packet_ip {
1446 struct {
1447 uint8_t ver_hdrlen;
1448 uint8_t tos;
1449 uint16_t packet_length;
1450 uint16_t identification;
1451 uint8_t flags;
1452 uint8_t fragment;
1453 uint8_t ttl;
1454 uint8_t protocol;
1455 uint16_t hdr_checksum;
1456 uint32_t src_addr;
1457 uint32_t dest_addr;
1458 } v4;
1459 #define SWRAP_PACKET_IP_V4_SIZE 20
1460 struct {
1461 uint8_t ver_prio;
1462 uint8_t flow_label_high;
1463 uint16_t flow_label_low;
1464 uint16_t payload_length;
1465 uint8_t next_header;
1466 uint8_t hop_limit;
1467 uint8_t src_addr[16];
1468 uint8_t dest_addr[16];
1469 } v6;
1470 #define SWRAP_PACKET_IP_V6_SIZE 40
1472 #define SWRAP_PACKET_IP_SIZE 40
1474 union swrap_packet_payload {
1475 struct {
1476 uint16_t source_port;
1477 uint16_t dest_port;
1478 uint32_t seq_num;
1479 uint32_t ack_num;
1480 uint8_t hdr_length;
1481 uint8_t control;
1482 uint16_t window;
1483 uint16_t checksum;
1484 uint16_t urg;
1485 } tcp;
1486 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1487 struct {
1488 uint16_t source_port;
1489 uint16_t dest_port;
1490 uint16_t length;
1491 uint16_t checksum;
1492 } udp;
1493 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1494 struct {
1495 uint8_t type;
1496 uint8_t code;
1497 uint16_t checksum;
1498 uint32_t unused;
1499 } icmp4;
1500 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1501 struct {
1502 uint8_t type;
1503 uint8_t code;
1504 uint16_t checksum;
1505 uint32_t unused;
1506 } icmp6;
1507 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1509 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1511 #define SWRAP_PACKET_MIN_ALLOC \
1512 (SWRAP_PACKET_FRAME_SIZE + \
1513 SWRAP_PACKET_IP_SIZE + \
1514 SWRAP_PACKET_PAYLOAD_SIZE)
1516 static const char *socket_wrapper_pcap_file(void)
1518 static int initialized = 0;
1519 static const char *s = NULL;
1520 static const struct swrap_file_hdr h;
1521 static const struct swrap_packet_frame f;
1522 static const union swrap_packet_ip i;
1523 static const union swrap_packet_payload p;
1525 if (initialized == 1) {
1526 return s;
1528 initialized = 1;
1531 * TODO: don't use the structs use plain buffer offsets
1532 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1534 * for now make sure we disable PCAP support
1535 * if the struct has alignment!
1537 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1538 return NULL;
1540 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1541 return NULL;
1543 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1544 return NULL;
1546 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1547 return NULL;
1549 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1550 return NULL;
1552 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1553 return NULL;
1555 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1556 return NULL;
1558 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1559 return NULL;
1561 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1562 return NULL;
1564 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1565 return NULL;
1568 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1569 if (s == NULL) {
1570 return NULL;
1572 if (strncmp(s, "./", 2) == 0) {
1573 s += 2;
1575 return s;
1578 static uint8_t *swrap_packet_init(struct timeval *tval,
1579 const struct sockaddr *src,
1580 const struct sockaddr *dest,
1581 int socket_type,
1582 const uint8_t *payload,
1583 size_t payload_len,
1584 unsigned long tcp_seqno,
1585 unsigned long tcp_ack,
1586 unsigned char tcp_ctl,
1587 int unreachable,
1588 size_t *_packet_len)
1590 uint8_t *base;
1591 uint8_t *buf;
1592 struct swrap_packet_frame *frame;
1593 union swrap_packet_ip *ip;
1594 union swrap_packet_payload *pay;
1595 size_t packet_len;
1596 size_t alloc_len;
1597 size_t nonwire_len = sizeof(*frame);
1598 size_t wire_hdr_len = 0;
1599 size_t wire_len = 0;
1600 size_t ip_hdr_len = 0;
1601 size_t icmp_hdr_len = 0;
1602 size_t icmp_truncate_len = 0;
1603 uint8_t protocol = 0, icmp_protocol = 0;
1604 const struct sockaddr_in *src_in = NULL;
1605 const struct sockaddr_in *dest_in = NULL;
1606 #ifdef HAVE_IPV6
1607 const struct sockaddr_in6 *src_in6 = NULL;
1608 const struct sockaddr_in6 *dest_in6 = NULL;
1609 #endif
1610 uint16_t src_port;
1611 uint16_t dest_port;
1613 switch (src->sa_family) {
1614 case AF_INET:
1615 src_in = (const struct sockaddr_in *)src;
1616 dest_in = (const struct sockaddr_in *)dest;
1617 src_port = src_in->sin_port;
1618 dest_port = dest_in->sin_port;
1619 ip_hdr_len = sizeof(ip->v4);
1620 break;
1621 #ifdef HAVE_IPV6
1622 case AF_INET6:
1623 src_in6 = (const struct sockaddr_in6 *)src;
1624 dest_in6 = (const struct sockaddr_in6 *)dest;
1625 src_port = src_in6->sin6_port;
1626 dest_port = dest_in6->sin6_port;
1627 ip_hdr_len = sizeof(ip->v6);
1628 break;
1629 #endif
1630 default:
1631 return NULL;
1634 switch (socket_type) {
1635 case SOCK_STREAM:
1636 protocol = 0x06; /* TCP */
1637 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1638 wire_len = wire_hdr_len + payload_len;
1639 break;
1641 case SOCK_DGRAM:
1642 protocol = 0x11; /* UDP */
1643 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1644 wire_len = wire_hdr_len + payload_len;
1645 break;
1647 default:
1648 return NULL;
1651 if (unreachable) {
1652 icmp_protocol = protocol;
1653 switch (src->sa_family) {
1654 case AF_INET:
1655 protocol = 0x01; /* ICMPv4 */
1656 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1657 break;
1658 #ifdef HAVE_IPV6
1659 case AF_INET6:
1660 protocol = 0x3A; /* ICMPv6 */
1661 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1662 break;
1663 #endif
1665 if (wire_len > 64 ) {
1666 icmp_truncate_len = wire_len - 64;
1668 wire_hdr_len += icmp_hdr_len;
1669 wire_len += icmp_hdr_len;
1672 packet_len = nonwire_len + wire_len;
1673 alloc_len = packet_len;
1674 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1675 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1678 base = (uint8_t *)malloc(alloc_len);
1679 if (base == NULL) {
1680 return NULL;
1682 memset(base, 0x0, alloc_len);
1684 buf = base;
1686 frame = (struct swrap_packet_frame *)buf;
1687 frame->seconds = tval->tv_sec;
1688 frame->micro_seconds = tval->tv_usec;
1689 frame->recorded_length = wire_len - icmp_truncate_len;
1690 frame->full_length = wire_len - icmp_truncate_len;
1691 buf += SWRAP_PACKET_FRAME_SIZE;
1693 ip = (union swrap_packet_ip *)buf;
1694 switch (src->sa_family) {
1695 case AF_INET:
1696 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1697 ip->v4.tos = 0x00;
1698 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1699 ip->v4.identification = htons(0xFFFF);
1700 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1701 ip->v4.fragment = htons(0x0000);
1702 ip->v4.ttl = 0xFF;
1703 ip->v4.protocol = protocol;
1704 ip->v4.hdr_checksum = htons(0x0000);
1705 ip->v4.src_addr = src_in->sin_addr.s_addr;
1706 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1707 buf += SWRAP_PACKET_IP_V4_SIZE;
1708 break;
1709 #ifdef HAVE_IPV6
1710 case AF_INET6:
1711 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1712 ip->v6.flow_label_high = 0x00;
1713 ip->v6.flow_label_low = 0x0000;
1714 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1715 ip->v6.next_header = protocol;
1716 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1717 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1718 buf += SWRAP_PACKET_IP_V6_SIZE;
1719 break;
1720 #endif
1723 if (unreachable) {
1724 pay = (union swrap_packet_payload *)buf;
1725 switch (src->sa_family) {
1726 case AF_INET:
1727 pay->icmp4.type = 0x03; /* destination unreachable */
1728 pay->icmp4.code = 0x01; /* host unreachable */
1729 pay->icmp4.checksum = htons(0x0000);
1730 pay->icmp4.unused = htonl(0x00000000);
1731 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1733 /* set the ip header in the ICMP payload */
1734 ip = (union swrap_packet_ip *)buf;
1735 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1736 ip->v4.tos = 0x00;
1737 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1738 ip->v4.identification = htons(0xFFFF);
1739 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1740 ip->v4.fragment = htons(0x0000);
1741 ip->v4.ttl = 0xFF;
1742 ip->v4.protocol = icmp_protocol;
1743 ip->v4.hdr_checksum = htons(0x0000);
1744 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1745 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1746 buf += SWRAP_PACKET_IP_V4_SIZE;
1748 src_port = dest_in->sin_port;
1749 dest_port = src_in->sin_port;
1750 break;
1751 #ifdef HAVE_IPV6
1752 case AF_INET6:
1753 pay->icmp6.type = 0x01; /* destination unreachable */
1754 pay->icmp6.code = 0x03; /* address unreachable */
1755 pay->icmp6.checksum = htons(0x0000);
1756 pay->icmp6.unused = htonl(0x00000000);
1757 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1759 /* set the ip header in the ICMP payload */
1760 ip = (union swrap_packet_ip *)buf;
1761 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1762 ip->v6.flow_label_high = 0x00;
1763 ip->v6.flow_label_low = 0x0000;
1764 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1765 ip->v6.next_header = protocol;
1766 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1767 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1768 buf += SWRAP_PACKET_IP_V6_SIZE;
1770 src_port = dest_in6->sin6_port;
1771 dest_port = src_in6->sin6_port;
1772 break;
1773 #endif
1777 pay = (union swrap_packet_payload *)buf;
1779 switch (socket_type) {
1780 case SOCK_STREAM:
1781 pay->tcp.source_port = src_port;
1782 pay->tcp.dest_port = dest_port;
1783 pay->tcp.seq_num = htonl(tcp_seqno);
1784 pay->tcp.ack_num = htonl(tcp_ack);
1785 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1786 pay->tcp.control = tcp_ctl;
1787 pay->tcp.window = htons(0x7FFF);
1788 pay->tcp.checksum = htons(0x0000);
1789 pay->tcp.urg = htons(0x0000);
1790 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1792 break;
1794 case SOCK_DGRAM:
1795 pay->udp.source_port = src_port;
1796 pay->udp.dest_port = dest_port;
1797 pay->udp.length = htons(8 + payload_len);
1798 pay->udp.checksum = htons(0x0000);
1799 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1801 break;
1804 if (payload && payload_len > 0) {
1805 memcpy(buf, payload, payload_len);
1808 *_packet_len = packet_len - icmp_truncate_len;
1809 return base;
1812 static int swrap_get_pcap_fd(const char *fname)
1814 static int fd = -1;
1816 if (fd != -1) return fd;
1818 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1819 if (fd != -1) {
1820 struct swrap_file_hdr file_hdr;
1821 file_hdr.magic = 0xA1B2C3D4;
1822 file_hdr.version_major = 0x0002;
1823 file_hdr.version_minor = 0x0004;
1824 file_hdr.timezone = 0x00000000;
1825 file_hdr.sigfigs = 0x00000000;
1826 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1827 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1829 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1830 close(fd);
1831 fd = -1;
1833 return fd;
1836 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1838 return fd;
1841 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1842 const struct sockaddr *addr,
1843 enum swrap_packet_type type,
1844 const void *buf, size_t len,
1845 size_t *packet_len)
1847 const struct sockaddr *src_addr;
1848 const struct sockaddr *dest_addr;
1849 unsigned long tcp_seqno = 0;
1850 unsigned long tcp_ack = 0;
1851 unsigned char tcp_ctl = 0;
1852 int unreachable = 0;
1854 struct timeval tv;
1856 switch (si->family) {
1857 case AF_INET:
1858 break;
1859 #ifdef HAVE_IPV6
1860 case AF_INET6:
1861 break;
1862 #endif
1863 default:
1864 return NULL;
1867 switch (type) {
1868 case SWRAP_CONNECT_SEND:
1869 if (si->type != SOCK_STREAM) return NULL;
1871 src_addr = si->myname;
1872 dest_addr = addr;
1874 tcp_seqno = si->io.pck_snd;
1875 tcp_ack = si->io.pck_rcv;
1876 tcp_ctl = 0x02; /* SYN */
1878 si->io.pck_snd += 1;
1880 break;
1882 case SWRAP_CONNECT_RECV:
1883 if (si->type != SOCK_STREAM) return NULL;
1885 dest_addr = si->myname;
1886 src_addr = addr;
1888 tcp_seqno = si->io.pck_rcv;
1889 tcp_ack = si->io.pck_snd;
1890 tcp_ctl = 0x12; /** SYN,ACK */
1892 si->io.pck_rcv += 1;
1894 break;
1896 case SWRAP_CONNECT_UNREACH:
1897 if (si->type != SOCK_STREAM) return NULL;
1899 dest_addr = si->myname;
1900 src_addr = addr;
1902 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1903 tcp_seqno = si->io.pck_snd - 1;
1904 tcp_ack = si->io.pck_rcv;
1905 tcp_ctl = 0x02; /* SYN */
1906 unreachable = 1;
1908 break;
1910 case SWRAP_CONNECT_ACK:
1911 if (si->type != SOCK_STREAM) return NULL;
1913 src_addr = si->myname;
1914 dest_addr = addr;
1916 tcp_seqno = si->io.pck_snd;
1917 tcp_ack = si->io.pck_rcv;
1918 tcp_ctl = 0x10; /* ACK */
1920 break;
1922 case SWRAP_ACCEPT_SEND:
1923 if (si->type != SOCK_STREAM) return NULL;
1925 dest_addr = si->myname;
1926 src_addr = addr;
1928 tcp_seqno = si->io.pck_rcv;
1929 tcp_ack = si->io.pck_snd;
1930 tcp_ctl = 0x02; /* SYN */
1932 si->io.pck_rcv += 1;
1934 break;
1936 case SWRAP_ACCEPT_RECV:
1937 if (si->type != SOCK_STREAM) return NULL;
1939 src_addr = si->myname;
1940 dest_addr = addr;
1942 tcp_seqno = si->io.pck_snd;
1943 tcp_ack = si->io.pck_rcv;
1944 tcp_ctl = 0x12; /* SYN,ACK */
1946 si->io.pck_snd += 1;
1948 break;
1950 case SWRAP_ACCEPT_ACK:
1951 if (si->type != SOCK_STREAM) return NULL;
1953 dest_addr = si->myname;
1954 src_addr = addr;
1956 tcp_seqno = si->io.pck_rcv;
1957 tcp_ack = si->io.pck_snd;
1958 tcp_ctl = 0x10; /* ACK */
1960 break;
1962 case SWRAP_SEND:
1963 src_addr = si->myname;
1964 dest_addr = si->peername;
1966 tcp_seqno = si->io.pck_snd;
1967 tcp_ack = si->io.pck_rcv;
1968 tcp_ctl = 0x18; /* PSH,ACK */
1970 si->io.pck_snd += len;
1972 break;
1974 case SWRAP_SEND_RST:
1975 dest_addr = si->myname;
1976 src_addr = si->peername;
1978 if (si->type == SOCK_DGRAM) {
1979 return swrap_marshall_packet(si, si->peername,
1980 SWRAP_SENDTO_UNREACH,
1981 buf, len, packet_len);
1984 tcp_seqno = si->io.pck_rcv;
1985 tcp_ack = si->io.pck_snd;
1986 tcp_ctl = 0x14; /** RST,ACK */
1988 break;
1990 case SWRAP_PENDING_RST:
1991 dest_addr = si->myname;
1992 src_addr = si->peername;
1994 if (si->type == SOCK_DGRAM) {
1995 return NULL;
1998 tcp_seqno = si->io.pck_rcv;
1999 tcp_ack = si->io.pck_snd;
2000 tcp_ctl = 0x14; /* RST,ACK */
2002 break;
2004 case SWRAP_RECV:
2005 dest_addr = si->myname;
2006 src_addr = si->peername;
2008 tcp_seqno = si->io.pck_rcv;
2009 tcp_ack = si->io.pck_snd;
2010 tcp_ctl = 0x18; /* PSH,ACK */
2012 si->io.pck_rcv += len;
2014 break;
2016 case SWRAP_RECV_RST:
2017 dest_addr = si->myname;
2018 src_addr = si->peername;
2020 if (si->type == SOCK_DGRAM) {
2021 return NULL;
2024 tcp_seqno = si->io.pck_rcv;
2025 tcp_ack = si->io.pck_snd;
2026 tcp_ctl = 0x14; /* RST,ACK */
2028 break;
2030 case SWRAP_SENDTO:
2031 src_addr = si->myname;
2032 dest_addr = addr;
2034 si->io.pck_snd += len;
2036 break;
2038 case SWRAP_SENDTO_UNREACH:
2039 dest_addr = si->myname;
2040 src_addr = addr;
2042 unreachable = 1;
2044 break;
2046 case SWRAP_RECVFROM:
2047 dest_addr = si->myname;
2048 src_addr = addr;
2050 si->io.pck_rcv += len;
2052 break;
2054 case SWRAP_CLOSE_SEND:
2055 if (si->type != SOCK_STREAM) return NULL;
2057 src_addr = si->myname;
2058 dest_addr = si->peername;
2060 tcp_seqno = si->io.pck_snd;
2061 tcp_ack = si->io.pck_rcv;
2062 tcp_ctl = 0x11; /* FIN, ACK */
2064 si->io.pck_snd += 1;
2066 break;
2068 case SWRAP_CLOSE_RECV:
2069 if (si->type != SOCK_STREAM) return NULL;
2071 dest_addr = si->myname;
2072 src_addr = si->peername;
2074 tcp_seqno = si->io.pck_rcv;
2075 tcp_ack = si->io.pck_snd;
2076 tcp_ctl = 0x11; /* FIN,ACK */
2078 si->io.pck_rcv += 1;
2080 break;
2082 case SWRAP_CLOSE_ACK:
2083 if (si->type != SOCK_STREAM) return NULL;
2085 src_addr = si->myname;
2086 dest_addr = si->peername;
2088 tcp_seqno = si->io.pck_snd;
2089 tcp_ack = si->io.pck_rcv;
2090 tcp_ctl = 0x10; /* ACK */
2092 break;
2093 default:
2094 return NULL;
2097 swrapGetTimeOfDay(&tv);
2099 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2100 (const uint8_t *)buf, len,
2101 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2102 packet_len);
2105 static void swrap_dump_packet(struct socket_info *si,
2106 const struct sockaddr *addr,
2107 enum swrap_packet_type type,
2108 const void *buf, size_t len)
2110 const char *file_name;
2111 uint8_t *packet;
2112 size_t packet_len = 0;
2113 int fd;
2115 file_name = socket_wrapper_pcap_file();
2116 if (!file_name) {
2117 return;
2120 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2121 if (!packet) {
2122 return;
2125 fd = swrap_get_pcap_fd(file_name);
2126 if (fd != -1) {
2127 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2128 free(packet);
2129 return;
2133 free(packet);
2136 /****************************************************************************
2137 * SIGNALFD
2138 ***************************************************************************/
2140 #ifdef HAVE_SIGNALFD
2141 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2143 int rc;
2145 rc = libc_signalfd(fd, mask, flags);
2146 if (rc != -1) {
2147 swrap_remove_stale(fd);
2150 return rc;
2153 int signalfd(int fd, const sigset_t *mask, int flags)
2155 return swrap_signalfd(fd, mask, flags);
2157 #endif
2159 /****************************************************************************
2160 * SOCKET
2161 ***************************************************************************/
2163 static int swrap_socket(int family, int type, int protocol)
2165 struct socket_info *si;
2166 struct socket_info_fd *fi;
2167 int fd;
2168 int real_type = type;
2171 * Remove possible addition flags passed to socket() so
2172 * do not fail checking the type.
2173 * See https://lwn.net/Articles/281965/
2175 #ifdef SOCK_CLOEXEC
2176 real_type &= ~SOCK_CLOEXEC;
2177 #endif
2178 #ifdef SOCK_NONBLOCK
2179 real_type &= ~SOCK_NONBLOCK;
2180 #endif
2182 if (!socket_wrapper_enabled()) {
2183 return libc_socket(family, type, protocol);
2186 switch (family) {
2187 case AF_INET:
2188 #ifdef HAVE_IPV6
2189 case AF_INET6:
2190 #endif
2191 break;
2192 case AF_UNIX:
2193 return libc_socket(family, type, protocol);
2194 default:
2195 errno = EAFNOSUPPORT;
2196 return -1;
2199 switch (real_type) {
2200 case SOCK_STREAM:
2201 break;
2202 case SOCK_DGRAM:
2203 break;
2204 default:
2205 errno = EPROTONOSUPPORT;
2206 return -1;
2209 switch (protocol) {
2210 case 0:
2211 break;
2212 case 6:
2213 if (real_type == SOCK_STREAM) {
2214 break;
2216 /*fall through*/
2217 case 17:
2218 if (real_type == SOCK_DGRAM) {
2219 break;
2221 /*fall through*/
2222 default:
2223 errno = EPROTONOSUPPORT;
2224 return -1;
2228 * We must call libc_socket with type, from the caller, not the version
2229 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2231 fd = libc_socket(AF_UNIX, type, 0);
2233 if (fd == -1) {
2234 return -1;
2237 /* Check if we have a stale fd and remove it */
2238 si = find_socket_info(fd);
2239 if (si != NULL) {
2240 swrap_remove_stale(fd);
2243 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2244 memset(si, 0, sizeof(struct socket_info));
2245 if (si == NULL) {
2246 errno = ENOMEM;
2247 return -1;
2250 si->family = family;
2252 /* however, the rest of the socket_wrapper code expects just
2253 * the type, not the flags */
2254 si->type = real_type;
2255 si->protocol = protocol;
2258 * Setup myname so getsockname() can succeed to find out the socket
2259 * type.
2261 switch(si->family) {
2262 case AF_INET: {
2263 struct sockaddr_in sin = {
2264 .sin_family = AF_INET,
2267 si->myname_len = sizeof(struct sockaddr_in);
2268 si->myname = sockaddr_dup(&sin, si->myname_len);
2269 break;
2271 case AF_INET6: {
2272 struct sockaddr_in6 sin6 = {
2273 .sin6_family = AF_INET6,
2276 si->myname_len = sizeof(struct sockaddr_in6);
2277 si->myname = sockaddr_dup(&sin6, si->myname_len);
2278 break;
2280 default:
2281 free(si);
2282 errno = EINVAL;
2283 return -1;
2286 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2287 if (fi == NULL) {
2288 if (si->myname != NULL) {
2289 free (si->myname);
2291 free(si);
2292 errno = ENOMEM;
2293 return -1;
2296 fi->fd = fd;
2298 SWRAP_DLIST_ADD(si->fds, fi);
2299 SWRAP_DLIST_ADD(sockets, si);
2301 return fd;
2304 int socket(int family, int type, int protocol)
2306 return swrap_socket(family, type, protocol);
2309 /****************************************************************************
2310 * SOCKETPAIR
2311 ***************************************************************************/
2313 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2315 int rc;
2317 rc = libc_socketpair(family, type, protocol, sv);
2318 if (rc != -1) {
2319 swrap_remove_stale(sv[0]);
2320 swrap_remove_stale(sv[1]);
2323 return rc;
2326 int socketpair(int family, int type, int protocol, int sv[2])
2328 return swrap_socketpair(family, type, protocol, sv);
2331 /****************************************************************************
2332 * SOCKETPAIR
2333 ***************************************************************************/
2335 #ifdef HAVE_TIMERFD_CREATE
2336 static int swrap_timerfd_create(int clockid, int flags)
2338 int fd;
2340 fd = libc_timerfd_create(clockid, flags);
2341 if (fd != -1) {
2342 swrap_remove_stale(fd);
2345 return fd;
2348 int timerfd_create(int clockid, int flags)
2350 return swrap_timerfd_create(clockid, flags);
2352 #endif
2354 /****************************************************************************
2355 * PIPE
2356 ***************************************************************************/
2358 static int swrap_pipe(int pipefd[2])
2360 int rc;
2362 rc = libc_pipe(pipefd);
2363 if (rc != -1) {
2364 swrap_remove_stale(pipefd[0]);
2365 swrap_remove_stale(pipefd[1]);
2368 return rc;
2371 int pipe(int pipefd[2])
2373 return swrap_pipe(pipefd);
2376 /****************************************************************************
2377 * ACCEPT
2378 ***************************************************************************/
2380 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2382 struct socket_info *parent_si, *child_si;
2383 struct socket_info_fd *child_fi;
2384 int fd;
2385 struct sockaddr_un un_addr;
2386 socklen_t un_addrlen = sizeof(un_addr);
2387 struct sockaddr_un un_my_addr;
2388 socklen_t un_my_addrlen = sizeof(un_my_addr);
2389 struct sockaddr *my_addr;
2390 socklen_t my_addrlen, len;
2391 int ret;
2393 parent_si = find_socket_info(s);
2394 if (!parent_si) {
2395 return libc_accept(s, addr, addrlen);
2399 * assume out sockaddr have the same size as the in parent
2400 * socket family
2402 my_addrlen = socket_length(parent_si->family);
2403 if (my_addrlen <= 0) {
2404 errno = EINVAL;
2405 return -1;
2408 my_addr = (struct sockaddr *)malloc(my_addrlen);
2409 if (my_addr == NULL) {
2410 return -1;
2413 memset(&un_addr, 0, sizeof(un_addr));
2414 memset(&un_my_addr, 0, sizeof(un_my_addr));
2416 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2417 if (ret == -1) {
2418 if (errno == ENOTSOCK) {
2419 /* Remove stale fds */
2420 swrap_remove_stale(s);
2422 free(my_addr);
2423 return ret;
2426 fd = ret;
2428 len = my_addrlen;
2429 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2430 parent_si->family, my_addr, &len);
2431 if (ret == -1) {
2432 free(my_addr);
2433 close(fd);
2434 return ret;
2437 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2438 memset(child_si, 0, sizeof(struct socket_info));
2440 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2441 if (child_fi == NULL) {
2442 free(child_si);
2443 free(my_addr);
2444 close(fd);
2445 errno = ENOMEM;
2446 return -1;
2449 child_fi->fd = fd;
2451 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2453 child_si->family = parent_si->family;
2454 child_si->type = parent_si->type;
2455 child_si->protocol = parent_si->protocol;
2456 child_si->bound = 1;
2457 child_si->is_server = 1;
2458 child_si->connected = 1;
2460 child_si->peername_len = len;
2461 child_si->peername = sockaddr_dup(my_addr, len);
2463 if (addr != NULL && addrlen != NULL) {
2464 size_t copy_len = MIN(*addrlen, len);
2465 if (copy_len > 0) {
2466 memcpy(addr, my_addr, copy_len);
2468 *addrlen = len;
2471 ret = libc_getsockname(fd,
2472 (struct sockaddr *)(void *)&un_my_addr,
2473 &un_my_addrlen);
2474 if (ret == -1) {
2475 free(child_fi);
2476 free(child_si);
2477 free(my_addr);
2478 close(fd);
2479 return ret;
2482 len = my_addrlen;
2483 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2484 child_si->family, my_addr, &len);
2485 if (ret == -1) {
2486 free(child_fi);
2487 free(child_si);
2488 free(my_addr);
2489 close(fd);
2490 return ret;
2493 SWRAP_LOG(SWRAP_LOG_TRACE,
2494 "accept() path=%s, fd=%d",
2495 un_my_addr.sun_path, s);
2497 child_si->myname_len = len;
2498 child_si->myname = sockaddr_dup(my_addr, len);
2499 free(my_addr);
2501 SWRAP_DLIST_ADD(sockets, child_si);
2503 if (addr != NULL) {
2504 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2505 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2506 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2509 return fd;
2512 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2513 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2514 #else
2515 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2516 #endif
2518 return swrap_accept(s, addr, (socklen_t *)addrlen);
2521 static int autobind_start_init;
2522 static int autobind_start;
2524 /* using sendto() or connect() on an unbound socket would give the
2525 recipient no way to reply, as unlike UDP and TCP, a unix domain
2526 socket can't auto-assign ephemeral port numbers, so we need to
2527 assign it here.
2528 Note: this might change the family from ipv6 to ipv4
2530 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2532 struct sockaddr_un un_addr;
2533 int i;
2534 char type;
2535 int ret;
2536 int port;
2537 struct stat st;
2539 if (autobind_start_init != 1) {
2540 autobind_start_init = 1;
2541 autobind_start = getpid();
2542 autobind_start %= 50000;
2543 autobind_start += 10000;
2546 un_addr.sun_family = AF_UNIX;
2548 switch (family) {
2549 case AF_INET: {
2550 struct sockaddr_in in;
2552 switch (si->type) {
2553 case SOCK_STREAM:
2554 type = SOCKET_TYPE_CHAR_TCP;
2555 break;
2556 case SOCK_DGRAM:
2557 type = SOCKET_TYPE_CHAR_UDP;
2558 break;
2559 default:
2560 errno = ESOCKTNOSUPPORT;
2561 return -1;
2564 memset(&in, 0, sizeof(in));
2565 in.sin_family = AF_INET;
2566 in.sin_addr.s_addr = htonl(127<<24 |
2567 socket_wrapper_default_iface());
2569 free(si->myname);
2570 si->myname_len = sizeof(in);
2571 si->myname = sockaddr_dup(&in, si->myname_len);
2572 break;
2574 #ifdef HAVE_IPV6
2575 case AF_INET6: {
2576 struct sockaddr_in6 in6;
2578 if (si->family != family) {
2579 errno = ENETUNREACH;
2580 return -1;
2583 switch (si->type) {
2584 case SOCK_STREAM:
2585 type = SOCKET_TYPE_CHAR_TCP_V6;
2586 break;
2587 case SOCK_DGRAM:
2588 type = SOCKET_TYPE_CHAR_UDP_V6;
2589 break;
2590 default:
2591 errno = ESOCKTNOSUPPORT;
2592 return -1;
2595 memset(&in6, 0, sizeof(in6));
2596 in6.sin6_family = AF_INET6;
2597 in6.sin6_addr = *swrap_ipv6();
2598 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2599 free(si->myname);
2600 si->myname_len = sizeof(in6);
2601 si->myname = sockaddr_dup(&in6, si->myname_len);
2602 break;
2604 #endif
2605 default:
2606 errno = ESOCKTNOSUPPORT;
2607 return -1;
2610 if (autobind_start > 60000) {
2611 autobind_start = 10000;
2614 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2615 port = autobind_start + i;
2616 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2617 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2618 type, socket_wrapper_default_iface(), port);
2619 if (stat(un_addr.sun_path, &st) == 0) continue;
2621 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2622 sizeof(un_addr));
2623 if (ret == -1) return ret;
2625 si->tmp_path = strdup(un_addr.sun_path);
2626 si->bound = 1;
2627 autobind_start = port + 1;
2628 break;
2630 if (i == SOCKET_MAX_SOCKETS) {
2631 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2632 "interface "SOCKET_FORMAT,
2633 SOCKET_MAX_SOCKETS,
2634 type,
2635 socket_wrapper_default_iface(),
2637 errno = ENFILE;
2638 return -1;
2641 si->family = family;
2642 set_port(si->family, port, si->myname);
2644 return 0;
2647 /****************************************************************************
2648 * CONNECT
2649 ***************************************************************************/
2651 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2652 socklen_t addrlen)
2654 int ret;
2655 struct sockaddr_un un_addr;
2656 struct socket_info *si = find_socket_info(s);
2657 int bcast = 0;
2659 if (!si) {
2660 return libc_connect(s, serv_addr, addrlen);
2663 if (si->bound == 0) {
2664 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2665 if (ret == -1) return -1;
2668 if (si->family != serv_addr->sa_family) {
2669 errno = EINVAL;
2670 return -1;
2673 ret = sockaddr_convert_to_un(si, serv_addr,
2674 addrlen, &un_addr, 0, &bcast);
2675 if (ret == -1) return -1;
2677 if (bcast) {
2678 errno = ENETUNREACH;
2679 return -1;
2682 if (si->type == SOCK_DGRAM) {
2683 si->defer_connect = 1;
2684 ret = 0;
2685 } else {
2686 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2688 ret = libc_connect(s,
2689 (struct sockaddr *)(void *)&un_addr,
2690 sizeof(struct sockaddr_un));
2693 SWRAP_LOG(SWRAP_LOG_TRACE,
2694 "connect() path=%s, fd=%d",
2695 un_addr.sun_path, s);
2698 /* to give better errors */
2699 if (ret == -1 && errno == ENOENT) {
2700 errno = EHOSTUNREACH;
2703 if (ret == 0) {
2704 si->peername_len = addrlen;
2705 si->peername = sockaddr_dup(serv_addr, addrlen);
2706 si->connected = 1;
2709 * When we connect() on a socket than we have to bind the
2710 * outgoing connection on the interface we use for the
2711 * transport. We already bound it on the right interface
2712 * but here we have to update the name so getsockname()
2713 * returns correct information.
2715 if (si->bindname != NULL) {
2716 free(si->myname);
2718 si->myname = si->bindname;
2719 si->myname_len = si->bindname_len;
2721 si->bindname = NULL;
2722 si->bindname_len = 0;
2725 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2726 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2727 } else {
2728 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2731 return ret;
2734 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2736 return swrap_connect(s, serv_addr, addrlen);
2739 /****************************************************************************
2740 * BIND
2741 ***************************************************************************/
2743 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2745 int ret;
2746 struct sockaddr_un un_addr;
2747 struct socket_info *si = find_socket_info(s);
2748 int bind_error = 0;
2750 if (!si) {
2751 return libc_bind(s, myaddr, addrlen);
2754 switch (si->family) {
2755 case AF_INET: {
2756 const struct sockaddr_in *sin;
2757 if (addrlen < sizeof(struct sockaddr_in)) {
2758 bind_error = EINVAL;
2759 break;
2762 sin = (struct sockaddr_in *)myaddr;
2764 if (sin->sin_family != AF_INET) {
2765 bind_error = EAFNOSUPPORT;
2768 /* special case for AF_UNSPEC */
2769 if (sin->sin_family == AF_UNSPEC &&
2770 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2772 bind_error = 0;
2775 break;
2777 #ifdef HAVE_IPV6
2778 case AF_INET6: {
2779 const struct sockaddr_in6 *sin6;
2780 if (addrlen < sizeof(struct sockaddr_in6)) {
2781 bind_error = EINVAL;
2782 break;
2785 sin6 = (struct sockaddr_in6 *)myaddr;
2787 if (sin6->sin6_family != AF_INET6) {
2788 bind_error = EAFNOSUPPORT;
2791 break;
2793 #endif
2794 default:
2795 bind_error = EINVAL;
2796 break;
2799 if (bind_error != 0) {
2800 errno = bind_error;
2801 return -1;
2804 free(si->myname);
2805 si->myname_len = addrlen;
2806 si->myname = sockaddr_dup(myaddr, addrlen);
2808 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2809 if (ret == -1) return -1;
2811 unlink(un_addr.sun_path);
2813 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2814 sizeof(struct sockaddr_un));
2816 SWRAP_LOG(SWRAP_LOG_TRACE,
2817 "bind() path=%s, fd=%d",
2818 un_addr.sun_path, s);
2820 if (ret == 0) {
2821 si->bound = 1;
2824 return ret;
2827 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2829 return swrap_bind(s, myaddr, addrlen);
2832 /****************************************************************************
2833 * BINDRESVPORT
2834 ***************************************************************************/
2836 #ifdef HAVE_BINDRESVPORT
2837 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2839 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2841 struct sockaddr_storage myaddr;
2842 socklen_t salen;
2843 static uint16_t port;
2844 uint16_t i;
2845 int rc = -1;
2846 int af;
2848 #define SWRAP_STARTPORT 600
2849 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2850 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2852 if (port == 0) {
2853 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2856 if (sa == NULL) {
2857 salen = sizeof(struct sockaddr);
2858 sa = (struct sockaddr *)&myaddr;
2860 rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
2861 if (rc < 0) {
2862 return -1;
2865 af = sa->sa_family;
2866 memset(&myaddr, 0, salen);
2867 } else {
2868 af = sa->sa_family;
2871 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
2872 switch(af) {
2873 case AF_INET: {
2874 struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
2876 salen = sizeof(struct sockaddr_in);
2877 sinp->sin_port = htons(port);
2878 break;
2880 case AF_INET6: {
2881 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
2883 salen = sizeof(struct sockaddr_in6);
2884 sin6p->sin6_port = htons(port);
2885 break;
2887 default:
2888 errno = EAFNOSUPPORT;
2889 return -1;
2891 sa->sa_family = af;
2893 if (port > SWRAP_ENDPORT) {
2894 port = SWRAP_STARTPORT;
2897 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
2898 if (rc == 0 || errno != EADDRINUSE) {
2899 break;
2903 return rc;
2906 int bindresvport(int sockfd, struct sockaddr_in *sinp)
2908 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
2910 #endif
2912 /****************************************************************************
2913 * LISTEN
2914 ***************************************************************************/
2916 static int swrap_listen(int s, int backlog)
2918 int ret;
2919 struct socket_info *si = find_socket_info(s);
2921 if (!si) {
2922 return libc_listen(s, backlog);
2925 ret = libc_listen(s, backlog);
2927 return ret;
2930 int listen(int s, int backlog)
2932 return swrap_listen(s, backlog);
2935 /****************************************************************************
2936 * OPEN
2937 ***************************************************************************/
2939 static int swrap_vopen(const char *pathname, int flags, va_list ap)
2941 int ret;
2943 ret = libc_vopen(pathname, flags, ap);
2944 if (ret != -1) {
2946 * There are methods for closing descriptors (libc-internal code
2947 * paths, direct syscalls) which close descriptors in ways that
2948 * we can't intercept, so try to recover when we notice that
2949 * that's happened
2951 swrap_remove_stale(ret);
2953 return ret;
2956 int open(const char *pathname, int flags, ...)
2958 va_list ap;
2959 int fd;
2961 va_start(ap, flags);
2962 fd = swrap_vopen(pathname, flags, ap);
2963 va_end(ap);
2965 return fd;
2968 /****************************************************************************
2969 * GETPEERNAME
2970 ***************************************************************************/
2972 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
2974 struct socket_info *si = find_socket_info(s);
2975 socklen_t len;
2977 if (!si) {
2978 return libc_getpeername(s, name, addrlen);
2981 if (!si->peername)
2983 errno = ENOTCONN;
2984 return -1;
2987 len = MIN(*addrlen, si->peername_len);
2988 if (len == 0) {
2989 return 0;
2992 memcpy(name, si->peername, len);
2993 *addrlen = si->peername_len;
2995 return 0;
2998 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2999 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3000 #else
3001 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3002 #endif
3004 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3007 /****************************************************************************
3008 * GETSOCKNAME
3009 ***************************************************************************/
3011 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3013 struct socket_info *si = find_socket_info(s);
3014 socklen_t len;
3016 if (!si) {
3017 return libc_getsockname(s, name, addrlen);
3020 len = MIN(*addrlen, si->myname_len);
3021 if (len == 0) {
3022 return 0;
3025 memcpy(name, si->myname, len);
3026 *addrlen = si->myname_len;
3028 return 0;
3031 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3032 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3033 #else
3034 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3035 #endif
3037 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3040 /****************************************************************************
3041 * GETSOCKOPT
3042 ***************************************************************************/
3044 #ifndef SO_PROTOCOL
3045 # ifdef SO_PROTOTYPE /* The Solaris name */
3046 # define SO_PROTOCOL SO_PROTOTYPE
3047 # endif /* SO_PROTOTYPE */
3048 #endif /* SO_PROTOCOL */
3050 static int swrap_getsockopt(int s, int level, int optname,
3051 void *optval, socklen_t *optlen)
3053 struct socket_info *si = find_socket_info(s);
3055 if (!si) {
3056 return libc_getsockopt(s,
3057 level,
3058 optname,
3059 optval,
3060 optlen);
3063 if (level == SOL_SOCKET) {
3064 switch (optname) {
3065 #ifdef SO_DOMAIN
3066 case SO_DOMAIN:
3067 if (optval == NULL || optlen == NULL ||
3068 *optlen < (socklen_t)sizeof(int)) {
3069 errno = EINVAL;
3070 return -1;
3073 *optlen = sizeof(int);
3074 *(int *)optval = si->family;
3075 return 0;
3076 #endif /* SO_DOMAIN */
3077 case SO_PROTOCOL:
3078 if (optval == NULL || optlen == NULL ||
3079 *optlen < (socklen_t)sizeof(int)) {
3080 errno = EINVAL;
3081 return -1;
3084 *optlen = sizeof(int);
3085 *(int *)optval = si->protocol;
3086 return 0;
3087 case SO_TYPE:
3088 if (optval == NULL || optlen == NULL ||
3089 *optlen < (socklen_t)sizeof(int)) {
3090 errno = EINVAL;
3091 return -1;
3094 *optlen = sizeof(int);
3095 *(int *)optval = si->type;
3096 return 0;
3097 default:
3098 return libc_getsockopt(s,
3099 level,
3100 optname,
3101 optval,
3102 optlen);
3106 errno = ENOPROTOOPT;
3107 return -1;
3110 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3111 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3112 #else
3113 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3114 #endif
3116 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3119 /****************************************************************************
3120 * SETSOCKOPT
3121 ***************************************************************************/
3123 static int swrap_setsockopt(int s, int level, int optname,
3124 const void *optval, socklen_t optlen)
3126 struct socket_info *si = find_socket_info(s);
3128 if (!si) {
3129 return libc_setsockopt(s,
3130 level,
3131 optname,
3132 optval,
3133 optlen);
3136 if (level == SOL_SOCKET) {
3137 return libc_setsockopt(s,
3138 level,
3139 optname,
3140 optval,
3141 optlen);
3144 switch (si->family) {
3145 case AF_INET:
3146 if (level == IPPROTO_IP) {
3147 #ifdef IP_PKTINFO
3148 if (optname == IP_PKTINFO) {
3149 si->pktinfo = AF_INET;
3151 #endif /* IP_PKTINFO */
3153 return 0;
3154 #ifdef HAVE_IPV6
3155 case AF_INET6:
3156 if (level == IPPROTO_IPV6) {
3157 #ifdef IPV6_RECVPKTINFO
3158 if (optname == IPV6_RECVPKTINFO) {
3159 si->pktinfo = AF_INET6;
3161 #endif /* IPV6_PKTINFO */
3163 return 0;
3164 #endif
3165 default:
3166 errno = ENOPROTOOPT;
3167 return -1;
3171 int setsockopt(int s, int level, int optname,
3172 const void *optval, socklen_t optlen)
3174 return swrap_setsockopt(s, level, optname, optval, optlen);
3177 /****************************************************************************
3178 * IOCTL
3179 ***************************************************************************/
3181 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3183 struct socket_info *si = find_socket_info(s);
3184 va_list ap;
3185 int value;
3186 int rc;
3188 if (!si) {
3189 return libc_vioctl(s, r, va);
3192 va_copy(ap, va);
3194 rc = libc_vioctl(s, r, va);
3196 switch (r) {
3197 case FIONREAD:
3198 value = *((int *)va_arg(ap, int *));
3200 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3201 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3202 } else if (value == 0) { /* END OF FILE */
3203 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3205 break;
3208 va_end(ap);
3210 return rc;
3213 #ifdef HAVE_IOCTL_INT
3214 int ioctl(int s, int r, ...)
3215 #else
3216 int ioctl(int s, unsigned long int r, ...)
3217 #endif
3219 va_list va;
3220 int rc;
3222 va_start(va, r);
3224 rc = swrap_vioctl(s, (unsigned long int) r, va);
3226 va_end(va);
3228 return rc;
3231 /*****************
3232 * CMSG
3233 *****************/
3235 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3237 #ifndef CMSG_ALIGN
3238 # ifdef _ALIGN /* BSD */
3239 #define CMSG_ALIGN _ALIGN
3240 # else
3241 #error NO_CMSG_ALIGN
3242 # endif /* _ALIGN */
3243 #endif /* CMSG_ALIGN */
3246 * @brief Add a cmsghdr to a msghdr.
3248 * This is an function to add any type of cmsghdr. It will operate on the
3249 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3250 * the buffer position after the added cmsg element. Hence, this function is
3251 * intended to be used with an intermediate msghdr and not on the original
3252 * one handed in by the client.
3254 * @param[in] msg The msghdr to which to add the cmsg.
3256 * @param[in] level The cmsg level to set.
3258 * @param[in] type The cmsg type to set.
3260 * @param[in] data The cmsg data to set.
3262 * @param[in] len the length of the data to set.
3264 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3265 int level,
3266 int type,
3267 const void *data,
3268 size_t len)
3270 size_t cmlen = CMSG_LEN(len);
3271 size_t cmspace = CMSG_SPACE(len);
3272 uint8_t cmbuf[cmspace];
3273 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3274 uint8_t *p;
3276 memset(cmbuf, 0, cmspace);
3278 if (msg->msg_controllen < cmlen) {
3279 cmlen = msg->msg_controllen;
3280 msg->msg_flags |= MSG_CTRUNC;
3283 if (msg->msg_controllen < cmspace) {
3284 cmspace = msg->msg_controllen;
3288 * We copy the full input data into an intermediate cmsghdr first
3289 * in order to more easily cope with truncation.
3291 cm->cmsg_len = cmlen;
3292 cm->cmsg_level = level;
3293 cm->cmsg_type = type;
3294 memcpy(CMSG_DATA(cm), data, len);
3297 * We now copy the possibly truncated buffer.
3298 * We copy cmlen bytes, but consume cmspace bytes,
3299 * leaving the possible padding uninitialiazed.
3301 p = (uint8_t *)msg->msg_control;
3302 memcpy(p, cm, cmlen);
3303 p += cmspace;
3304 msg->msg_control = p;
3305 msg->msg_controllen -= cmspace;
3307 return;
3310 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3311 struct msghdr *msg)
3313 /* Add packet info */
3314 switch (si->pktinfo) {
3315 #if defined(IP_PKTINFO)
3316 /* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
3317 case AF_INET: {
3318 struct sockaddr_in *sin;
3319 #if defined(HAVE_STRUCT_IN_PKTINFO)
3320 struct in_pktinfo pkt;
3321 #elif defined(IP_RECVDSTADDR)
3322 struct in_addr pkt;
3323 #endif
3325 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3326 sin = (struct sockaddr_in*)si->bindname;
3327 } else {
3328 if (si->myname_len != sizeof(struct sockaddr_in)) {
3329 return 0;
3331 sin = (struct sockaddr_in*)si->myname;
3334 ZERO_STRUCT(pkt);
3336 #if defined(HAVE_STRUCT_IN_PKTINFO)
3337 pkt.ipi_ifindex = socket_wrapper_default_iface();
3338 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3339 #elif defined(IP_RECVDSTADDR)
3340 pkt = sin->sin_addr;
3341 #endif
3343 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3344 &pkt, sizeof(pkt));
3346 break;
3348 #endif /* IP_PKTINFO */
3349 #if defined(HAVE_IPV6)
3350 case AF_INET6: {
3351 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3352 struct sockaddr_in6 *sin6;
3353 struct in6_pktinfo pkt6;
3355 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3356 sin6 = (struct sockaddr_in6*)si->bindname;
3357 } else {
3358 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3359 return 0;
3361 sin6 = (struct sockaddr_in6*)si->myname;
3364 ZERO_STRUCT(pkt6);
3366 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3367 pkt6.ipi6_addr = sin6->sin6_addr;
3369 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3370 &pkt6, sizeof(pkt6));
3371 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3373 break;
3375 #endif /* IPV6_PKTINFO */
3376 default:
3377 return -1;
3380 return 0;
3383 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3384 struct msghdr *omsg)
3386 int rc = 0;
3388 if (si->pktinfo > 0) {
3389 rc = swrap_msghdr_add_pktinfo(si, omsg);
3392 return rc;
3395 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3396 uint8_t **cm_data,
3397 size_t *cm_data_space);
3398 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3399 uint8_t **cm_data,
3400 size_t *cm_data_space);
3402 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3403 uint8_t **cm_data,
3404 size_t *cm_data_space) {
3405 struct cmsghdr *cmsg;
3406 int rc = -1;
3408 /* Nothing to do */
3409 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3410 return 0;
3413 for (cmsg = CMSG_FIRSTHDR(msg);
3414 cmsg != NULL;
3415 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3416 switch (cmsg->cmsg_level) {
3417 case IPPROTO_IP:
3418 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3419 cm_data,
3420 cm_data_space);
3421 break;
3422 default:
3423 rc = swrap_sendmsg_copy_cmsg(cmsg,
3424 cm_data,
3425 cm_data_space);
3426 break;
3430 return rc;
3433 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3434 uint8_t **cm_data,
3435 size_t *cm_data_space)
3437 size_t cmspace;
3438 uint8_t *p;
3440 cmspace =
3441 (*cm_data_space) +
3442 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3444 p = realloc((*cm_data), cmspace);
3445 if (p == NULL) {
3446 return -1;
3448 (*cm_data) = p;
3450 p = (*cm_data) + (*cm_data_space);
3451 *cm_data_space = cmspace;
3453 memcpy(p, cmsg, cmsg->cmsg_len);
3455 return 0;
3458 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3459 uint8_t **cm_data,
3460 size_t *cm_data_space);
3463 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3464 uint8_t **cm_data,
3465 size_t *cm_data_space)
3467 int rc = -1;
3469 switch(cmsg->cmsg_type) {
3470 #ifdef IP_PKTINFO
3471 case IP_PKTINFO:
3472 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3473 cm_data,
3474 cm_data_space);
3475 break;
3476 #endif
3477 #ifdef IPV6_PKTINFO
3478 case IPV6_PKTINFO:
3479 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3480 cm_data,
3481 cm_data_space);
3482 break;
3483 #endif
3484 default:
3485 break;
3488 return rc;
3491 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3492 uint8_t **cm_data,
3493 size_t *cm_data_space)
3495 (void)cmsg; /* unused */
3496 (void)cm_data; /* unused */
3497 (void)cm_data_space; /* unused */
3500 * Passing a IP pktinfo to a unix socket might be rejected by the
3501 * Kernel, at least on FreeBSD. So skip this cmsg.
3503 return 0;
3505 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3507 static ssize_t swrap_sendmsg_before(int fd,
3508 struct socket_info *si,
3509 struct msghdr *msg,
3510 struct iovec *tmp_iov,
3511 struct sockaddr_un *tmp_un,
3512 const struct sockaddr_un **to_un,
3513 const struct sockaddr **to,
3514 int *bcast)
3516 size_t i, len = 0;
3517 ssize_t ret;
3519 if (to_un) {
3520 *to_un = NULL;
3522 if (to) {
3523 *to = NULL;
3525 if (bcast) {
3526 *bcast = 0;
3529 switch (si->type) {
3530 case SOCK_STREAM:
3531 if (!si->connected) {
3532 errno = ENOTCONN;
3533 return -1;
3536 if (msg->msg_iovlen == 0) {
3537 break;
3540 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3541 size_t nlen;
3542 nlen = len + msg->msg_iov[i].iov_len;
3543 if (nlen > SOCKET_MAX_PACKET) {
3544 break;
3547 msg->msg_iovlen = i;
3548 if (msg->msg_iovlen == 0) {
3549 *tmp_iov = msg->msg_iov[0];
3550 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3551 msg->msg_iov = tmp_iov;
3552 msg->msg_iovlen = 1;
3554 break;
3556 case SOCK_DGRAM:
3557 if (si->connected) {
3558 if (msg->msg_name) {
3559 errno = EISCONN;
3560 return -1;
3562 } else {
3563 const struct sockaddr *msg_name;
3564 msg_name = (const struct sockaddr *)msg->msg_name;
3566 if (msg_name == NULL) {
3567 errno = ENOTCONN;
3568 return -1;
3572 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3573 tmp_un, 0, bcast);
3574 if (ret == -1) return -1;
3576 if (to_un) {
3577 *to_un = tmp_un;
3579 if (to) {
3580 *to = msg_name;
3582 msg->msg_name = tmp_un;
3583 msg->msg_namelen = sizeof(*tmp_un);
3586 if (si->bound == 0) {
3587 ret = swrap_auto_bind(fd, si, si->family);
3588 if (ret == -1) {
3589 if (errno == ENOTSOCK) {
3590 swrap_remove_stale(fd);
3591 return -ENOTSOCK;
3592 } else {
3593 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3594 return -1;
3599 if (!si->defer_connect) {
3600 break;
3603 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3604 tmp_un, 0, NULL);
3605 if (ret == -1) return -1;
3607 ret = libc_connect(fd,
3608 (struct sockaddr *)(void *)tmp_un,
3609 sizeof(*tmp_un));
3611 /* to give better errors */
3612 if (ret == -1 && errno == ENOENT) {
3613 errno = EHOSTUNREACH;
3616 if (ret == -1) {
3617 return ret;
3620 si->defer_connect = 0;
3621 break;
3622 default:
3623 errno = EHOSTUNREACH;
3624 return -1;
3627 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3628 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3629 uint8_t *cmbuf = NULL;
3630 size_t cmlen = 0;
3632 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3633 if (ret < 0) {
3634 free(cmbuf);
3635 return -1;
3638 if (cmlen == 0) {
3639 msg->msg_controllen = 0;
3640 msg->msg_control = NULL;
3641 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3642 memcpy(msg->msg_control, cmbuf, cmlen);
3643 msg->msg_controllen = cmlen;
3645 free(cmbuf);
3647 #endif
3649 return 0;
3652 static void swrap_sendmsg_after(int fd,
3653 struct socket_info *si,
3654 struct msghdr *msg,
3655 const struct sockaddr *to,
3656 ssize_t ret)
3658 int saved_errno = errno;
3659 size_t i, len = 0;
3660 uint8_t *buf;
3661 off_t ofs = 0;
3662 size_t avail = 0;
3663 size_t remain;
3665 /* to give better errors */
3666 if (ret == -1) {
3667 if (saved_errno == ENOENT) {
3668 saved_errno = EHOSTUNREACH;
3669 } else if (saved_errno == ENOTSOCK) {
3670 /* If the fd is not a socket, remove it */
3671 swrap_remove_stale(fd);
3675 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3676 avail += msg->msg_iov[i].iov_len;
3679 if (ret == -1) {
3680 remain = MIN(80, avail);
3681 } else {
3682 remain = ret;
3685 /* we capture it as one single packet */
3686 buf = (uint8_t *)malloc(remain);
3687 if (!buf) {
3688 /* we just not capture the packet */
3689 errno = saved_errno;
3690 return;
3693 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3694 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3695 memcpy(buf + ofs,
3696 msg->msg_iov[i].iov_base,
3697 this_time);
3698 ofs += this_time;
3699 remain -= this_time;
3701 len = ofs;
3703 switch (si->type) {
3704 case SOCK_STREAM:
3705 if (ret == -1) {
3706 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3707 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3708 } else {
3709 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3711 break;
3713 case SOCK_DGRAM:
3714 if (si->connected) {
3715 to = si->peername;
3717 if (ret == -1) {
3718 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3719 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3720 } else {
3721 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3723 break;
3726 free(buf);
3727 errno = saved_errno;
3730 static int swrap_recvmsg_before(int fd,
3731 struct socket_info *si,
3732 struct msghdr *msg,
3733 struct iovec *tmp_iov)
3735 size_t i, len = 0;
3736 ssize_t ret;
3738 (void)fd; /* unused */
3740 switch (si->type) {
3741 case SOCK_STREAM:
3742 if (!si->connected) {
3743 errno = ENOTCONN;
3744 return -1;
3747 if (msg->msg_iovlen == 0) {
3748 break;
3751 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3752 size_t nlen;
3753 nlen = len + msg->msg_iov[i].iov_len;
3754 if (nlen > SOCKET_MAX_PACKET) {
3755 break;
3758 msg->msg_iovlen = i;
3759 if (msg->msg_iovlen == 0) {
3760 *tmp_iov = msg->msg_iov[0];
3761 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3762 msg->msg_iov = tmp_iov;
3763 msg->msg_iovlen = 1;
3765 break;
3767 case SOCK_DGRAM:
3768 if (msg->msg_name == NULL) {
3769 errno = EINVAL;
3770 return -1;
3773 if (msg->msg_iovlen == 0) {
3774 break;
3777 if (si->bound == 0) {
3778 ret = swrap_auto_bind(fd, si, si->family);
3779 if (ret == -1) {
3781 * When attempting to read or write to a
3782 * descriptor, if an underlying autobind fails
3783 * because it's not a socket, stop intercepting
3784 * uses of that descriptor.
3786 if (errno == ENOTSOCK) {
3787 swrap_remove_stale(fd);
3788 return -ENOTSOCK;
3789 } else {
3790 SWRAP_LOG(SWRAP_LOG_ERROR,
3791 "swrap_recvmsg_before failed");
3792 return -1;
3796 break;
3797 default:
3798 errno = EHOSTUNREACH;
3799 return -1;
3802 return 0;
3805 static int swrap_recvmsg_after(int fd,
3806 struct socket_info *si,
3807 struct msghdr *msg,
3808 const struct sockaddr_un *un_addr,
3809 socklen_t un_addrlen,
3810 ssize_t ret)
3812 int saved_errno = errno;
3813 size_t i;
3814 uint8_t *buf = NULL;
3815 off_t ofs = 0;
3816 size_t avail = 0;
3817 size_t remain;
3818 int rc;
3820 /* to give better errors */
3821 if (ret == -1) {
3822 if (saved_errno == ENOENT) {
3823 saved_errno = EHOSTUNREACH;
3824 } else if (saved_errno == ENOTSOCK) {
3825 /* If the fd is not a socket, remove it */
3826 swrap_remove_stale(fd);
3830 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3831 avail += msg->msg_iov[i].iov_len;
3834 if (avail == 0) {
3835 rc = 0;
3836 goto done;
3839 if (ret == -1) {
3840 remain = MIN(80, avail);
3841 } else {
3842 remain = ret;
3845 /* we capture it as one single packet */
3846 buf = (uint8_t *)malloc(remain);
3847 if (buf == NULL) {
3848 /* we just not capture the packet */
3849 errno = saved_errno;
3850 return -1;
3853 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3854 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3855 memcpy(buf + ofs,
3856 msg->msg_iov[i].iov_base,
3857 this_time);
3858 ofs += this_time;
3859 remain -= this_time;
3862 switch (si->type) {
3863 case SOCK_STREAM:
3864 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3865 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3866 } else if (ret == 0) { /* END OF FILE */
3867 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3868 } else if (ret > 0) {
3869 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3871 break;
3873 case SOCK_DGRAM:
3874 if (ret == -1) {
3875 break;
3878 if (un_addr != NULL) {
3879 rc = sockaddr_convert_from_un(si,
3880 un_addr,
3881 un_addrlen,
3882 si->family,
3883 msg->msg_name,
3884 &msg->msg_namelen);
3885 if (rc == -1) {
3886 goto done;
3889 swrap_dump_packet(si,
3890 msg->msg_name,
3891 SWRAP_RECVFROM,
3892 buf,
3893 ret);
3894 } else {
3895 swrap_dump_packet(si,
3896 msg->msg_name,
3897 SWRAP_RECV,
3898 buf,
3899 ret);
3902 break;
3905 rc = 0;
3906 done:
3907 free(buf);
3908 errno = saved_errno;
3910 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3911 if (rc == 0 &&
3912 msg->msg_controllen > 0 &&
3913 msg->msg_control != NULL) {
3914 rc = swrap_msghdr_add_socket_info(si, msg);
3915 if (rc < 0) {
3916 return -1;
3919 #endif
3921 return rc;
3924 /****************************************************************************
3925 * RECVFROM
3926 ***************************************************************************/
3928 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
3929 struct sockaddr *from, socklen_t *fromlen)
3931 struct sockaddr_un from_addr;
3932 socklen_t from_addrlen = sizeof(from_addr);
3933 ssize_t ret;
3934 struct socket_info *si = find_socket_info(s);
3935 struct sockaddr_storage ss;
3936 socklen_t ss_len = sizeof(ss);
3937 struct msghdr msg;
3938 struct iovec tmp;
3939 int tret;
3941 if (!si) {
3942 return libc_recvfrom(s,
3943 buf,
3944 len,
3945 flags,
3946 from,
3947 fromlen);
3950 tmp.iov_base = buf;
3951 tmp.iov_len = len;
3953 ZERO_STRUCT(msg);
3954 if (from != NULL && fromlen != NULL) {
3955 msg.msg_name = from; /* optional address */
3956 msg.msg_namelen = *fromlen; /* size of address */
3957 } else {
3958 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
3959 msg.msg_namelen = ss_len; /* size of address */
3961 msg.msg_iov = &tmp; /* scatter/gather array */
3962 msg.msg_iovlen = 1; /* # elements in msg_iov */
3963 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3964 msg.msg_control = NULL; /* ancillary data, see below */
3965 msg.msg_controllen = 0; /* ancillary data buffer len */
3966 msg.msg_flags = 0; /* flags on received message */
3967 #endif
3969 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
3970 if (tret < 0) {
3971 return -1;
3974 buf = msg.msg_iov[0].iov_base;
3975 len = msg.msg_iov[0].iov_len;
3977 /* irix 6.4 forgets to null terminate the sun_path string :-( */
3978 memset(&from_addr, 0, sizeof(from_addr));
3979 ret = libc_recvfrom(s,
3980 buf,
3981 len,
3982 flags,
3983 (struct sockaddr *)(void *)&from_addr,
3984 &from_addrlen);
3985 if (ret == -1) {
3986 return ret;
3989 tret = swrap_recvmsg_after(s,
3991 &msg,
3992 &from_addr,
3993 from_addrlen,
3994 ret);
3995 if (tret != 0) {
3996 return tret;
3999 if (from != NULL && fromlen != NULL) {
4000 *fromlen = msg.msg_namelen;
4003 return ret;
4006 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4007 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4008 struct sockaddr *from, Psocklen_t fromlen)
4009 #else
4010 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4011 struct sockaddr *from, socklen_t *fromlen)
4012 #endif
4014 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4017 /****************************************************************************
4018 * SENDTO
4019 ***************************************************************************/
4021 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4022 const struct sockaddr *to, socklen_t tolen)
4024 struct msghdr msg;
4025 struct iovec tmp;
4026 struct sockaddr_un un_addr;
4027 const struct sockaddr_un *to_un = NULL;
4028 ssize_t ret;
4029 int rc;
4030 struct socket_info *si = find_socket_info(s);
4031 int bcast = 0;
4033 if (!si) {
4034 return libc_sendto(s, buf, len, flags, to, tolen);
4037 tmp.iov_base = discard_const_p(char, buf);
4038 tmp.iov_len = len;
4040 ZERO_STRUCT(msg);
4041 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4042 msg.msg_namelen = tolen; /* size of address */
4043 msg.msg_iov = &tmp; /* scatter/gather array */
4044 msg.msg_iovlen = 1; /* # elements in msg_iov */
4045 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4046 msg.msg_control = NULL; /* ancillary data, see below */
4047 msg.msg_controllen = 0; /* ancillary data buffer len */
4048 msg.msg_flags = 0; /* flags on received message */
4049 #endif
4051 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4052 if (rc < 0) {
4053 return -1;
4056 buf = msg.msg_iov[0].iov_base;
4057 len = msg.msg_iov[0].iov_len;
4059 if (bcast) {
4060 struct stat st;
4061 unsigned int iface;
4062 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4063 char type;
4065 type = SOCKET_TYPE_CHAR_UDP;
4067 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4068 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4069 socket_wrapper_dir(), type, iface, prt);
4070 if (stat(un_addr.sun_path, &st) != 0) continue;
4072 /* ignore the any errors in broadcast sends */
4073 libc_sendto(s,
4074 buf,
4075 len,
4076 flags,
4077 (struct sockaddr *)(void *)&un_addr,
4078 sizeof(un_addr));
4081 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4083 return len;
4086 ret = libc_sendto(s,
4087 buf,
4088 len,
4089 flags,
4090 (struct sockaddr *)msg.msg_name,
4091 msg.msg_namelen);
4093 swrap_sendmsg_after(s, si, &msg, to, ret);
4095 return ret;
4098 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4099 const struct sockaddr *to, socklen_t tolen)
4101 return swrap_sendto(s, buf, len, flags, to, tolen);
4104 /****************************************************************************
4105 * READV
4106 ***************************************************************************/
4108 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4110 struct socket_info *si;
4111 struct msghdr msg;
4112 struct sockaddr_storage ss;
4113 socklen_t ss_len = sizeof(ss);
4114 struct iovec tmp;
4115 ssize_t ret;
4116 int tret;
4118 si = find_socket_info(s);
4119 if (si == NULL) {
4120 return libc_recv(s, buf, len, flags);
4123 tmp.iov_base = buf;
4124 tmp.iov_len = len;
4126 ZERO_STRUCT(msg);
4127 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4128 msg.msg_namelen = ss_len; /* size of address */
4129 msg.msg_iov = &tmp; /* scatter/gather array */
4130 msg.msg_iovlen = 1; /* # elements in msg_iov */
4131 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4132 msg.msg_control = NULL; /* ancillary data, see below */
4133 msg.msg_controllen = 0; /* ancillary data buffer len */
4134 msg.msg_flags = 0; /* flags on received message */
4135 #endif
4137 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4138 if (tret < 0) {
4139 return -1;
4142 buf = msg.msg_iov[0].iov_base;
4143 len = msg.msg_iov[0].iov_len;
4145 ret = libc_recv(s, buf, len, flags);
4147 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4148 if (tret != 0) {
4149 return tret;
4152 return ret;
4155 ssize_t recv(int s, void *buf, size_t len, int flags)
4157 return swrap_recv(s, buf, len, flags);
4160 /****************************************************************************
4161 * READ
4162 ***************************************************************************/
4164 static ssize_t swrap_read(int s, void *buf, size_t len)
4166 struct socket_info *si;
4167 struct msghdr msg;
4168 struct iovec tmp;
4169 struct sockaddr_storage ss;
4170 socklen_t ss_len = sizeof(ss);
4171 ssize_t ret;
4172 int tret;
4174 si = find_socket_info(s);
4175 if (si == NULL) {
4176 return libc_read(s, buf, len);
4179 tmp.iov_base = buf;
4180 tmp.iov_len = len;
4182 ZERO_STRUCT(msg);
4183 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4184 msg.msg_namelen = ss_len; /* size of address */
4185 msg.msg_iov = &tmp; /* scatter/gather array */
4186 msg.msg_iovlen = 1; /* # elements in msg_iov */
4187 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4188 msg.msg_control = NULL; /* ancillary data, see below */
4189 msg.msg_controllen = 0; /* ancillary data buffer len */
4190 msg.msg_flags = 0; /* flags on received message */
4191 #endif
4193 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4194 if (tret < 0) {
4195 if (tret == -ENOTSOCK) {
4196 return libc_read(s, buf, len);
4198 return -1;
4201 buf = msg.msg_iov[0].iov_base;
4202 len = msg.msg_iov[0].iov_len;
4204 ret = libc_read(s, buf, len);
4206 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4207 if (tret != 0) {
4208 return tret;
4211 return ret;
4214 ssize_t read(int s, void *buf, size_t len)
4216 return swrap_read(s, buf, len);
4219 /****************************************************************************
4220 * SEND
4221 ***************************************************************************/
4223 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4225 struct msghdr msg;
4226 struct iovec tmp;
4227 struct sockaddr_un un_addr;
4228 ssize_t ret;
4229 int rc;
4230 struct socket_info *si = find_socket_info(s);
4232 if (!si) {
4233 return libc_send(s, buf, len, flags);
4236 tmp.iov_base = discard_const_p(char, buf);
4237 tmp.iov_len = len;
4239 ZERO_STRUCT(msg);
4240 msg.msg_name = NULL; /* optional address */
4241 msg.msg_namelen = 0; /* size of address */
4242 msg.msg_iov = &tmp; /* scatter/gather array */
4243 msg.msg_iovlen = 1; /* # elements in msg_iov */
4244 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4245 msg.msg_control = NULL; /* ancillary data, see below */
4246 msg.msg_controllen = 0; /* ancillary data buffer len */
4247 msg.msg_flags = 0; /* flags on received message */
4248 #endif
4250 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4251 if (rc < 0) {
4252 return -1;
4255 buf = msg.msg_iov[0].iov_base;
4256 len = msg.msg_iov[0].iov_len;
4258 ret = libc_send(s, buf, len, flags);
4260 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4262 return ret;
4265 ssize_t send(int s, const void *buf, size_t len, int flags)
4267 return swrap_send(s, buf, len, flags);
4270 /****************************************************************************
4271 * RECVMSG
4272 ***************************************************************************/
4274 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4276 struct sockaddr_un from_addr;
4277 socklen_t from_addrlen = sizeof(from_addr);
4278 struct socket_info *si;
4279 struct msghdr msg;
4280 struct iovec tmp;
4281 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4282 size_t msg_ctrllen_filled;
4283 size_t msg_ctrllen_left;
4284 #endif
4286 ssize_t ret;
4287 int rc;
4289 si = find_socket_info(s);
4290 if (si == NULL) {
4291 return libc_recvmsg(s, omsg, flags);
4294 tmp.iov_base = NULL;
4295 tmp.iov_len = 0;
4297 ZERO_STRUCT(msg);
4298 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
4299 msg.msg_namelen = from_addrlen; /* size of address */
4300 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4301 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4302 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4303 msg_ctrllen_filled = 0;
4304 msg_ctrllen_left = omsg->msg_controllen;
4306 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4307 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4308 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4309 #endif
4311 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4312 if (rc < 0) {
4313 return -1;
4316 ret = libc_recvmsg(s, &msg, flags);
4318 msg.msg_name = omsg->msg_name;
4319 msg.msg_namelen = omsg->msg_namelen;
4321 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4322 msg_ctrllen_filled += msg.msg_controllen;
4323 msg_ctrllen_left -= msg.msg_controllen;
4325 if (omsg->msg_control != NULL) {
4326 uint8_t *p;
4328 p = omsg->msg_control;
4329 p += msg_ctrllen_filled;
4331 msg.msg_control = p;
4332 msg.msg_controllen = msg_ctrllen_left;
4333 } else {
4334 msg.msg_control = NULL;
4335 msg.msg_controllen = 0;
4337 #endif
4339 rc = swrap_recvmsg_after(s, si, &msg, &from_addr, from_addrlen, ret);
4340 if (rc != 0) {
4341 return rc;
4344 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4345 if (omsg->msg_control != NULL) {
4346 /* msg.msg_controllen = space left */
4347 msg_ctrllen_left = msg.msg_controllen;
4348 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4351 /* Update the original message length */
4352 omsg->msg_controllen = msg_ctrllen_filled;
4353 omsg->msg_flags = msg.msg_flags;
4354 #endif
4355 omsg->msg_iovlen = msg.msg_iovlen;
4357 return ret;
4360 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4362 return swrap_recvmsg(sockfd, msg, flags);
4365 /****************************************************************************
4366 * SENDMSG
4367 ***************************************************************************/
4369 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4371 struct msghdr msg;
4372 struct iovec tmp;
4373 struct sockaddr_un un_addr;
4374 const struct sockaddr_un *to_un = NULL;
4375 const struct sockaddr *to = NULL;
4376 ssize_t ret;
4377 int rc;
4378 struct socket_info *si = find_socket_info(s);
4379 int bcast = 0;
4381 if (!si) {
4382 return libc_sendmsg(s, omsg, flags);
4385 ZERO_STRUCT(un_addr);
4387 tmp.iov_base = NULL;
4388 tmp.iov_len = 0;
4390 ZERO_STRUCT(msg);
4391 msg.msg_name = omsg->msg_name; /* optional address */
4392 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4393 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4394 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4395 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4396 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4397 /* omsg is a const so use a local buffer for modifications */
4398 uint8_t cmbuf[omsg->msg_controllen];
4400 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4402 msg.msg_control = cmbuf; /* ancillary data, see below */
4403 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4405 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4406 #endif
4408 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4409 if (rc < 0) {
4410 return -1;
4413 if (bcast) {
4414 struct stat st;
4415 unsigned int iface;
4416 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4417 char type;
4418 size_t i, len = 0;
4419 uint8_t *buf;
4420 off_t ofs = 0;
4421 size_t avail = 0;
4422 size_t remain;
4424 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4425 avail += msg.msg_iov[i].iov_len;
4428 len = avail;
4429 remain = avail;
4431 /* we capture it as one single packet */
4432 buf = (uint8_t *)malloc(remain);
4433 if (!buf) {
4434 return -1;
4437 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4438 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4439 memcpy(buf + ofs,
4440 msg.msg_iov[i].iov_base,
4441 this_time);
4442 ofs += this_time;
4443 remain -= this_time;
4446 type = SOCKET_TYPE_CHAR_UDP;
4448 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4449 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4450 socket_wrapper_dir(), type, iface, prt);
4451 if (stat(un_addr.sun_path, &st) != 0) continue;
4453 msg.msg_name = &un_addr; /* optional address */
4454 msg.msg_namelen = sizeof(un_addr); /* size of address */
4456 /* ignore the any errors in broadcast sends */
4457 libc_sendmsg(s, &msg, flags);
4460 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4461 free(buf);
4463 return len;
4466 ret = libc_sendmsg(s, &msg, flags);
4468 swrap_sendmsg_after(s, si, &msg, to, ret);
4470 return ret;
4473 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4475 return swrap_sendmsg(s, omsg, flags);
4478 /****************************************************************************
4479 * READV
4480 ***************************************************************************/
4482 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4484 struct socket_info *si;
4485 struct msghdr msg;
4486 struct iovec tmp;
4487 struct sockaddr_storage ss;
4488 socklen_t ss_len = sizeof(ss);
4489 ssize_t ret;
4490 int rc;
4492 si = find_socket_info(s);
4493 if (si == NULL) {
4494 return libc_readv(s, vector, count);
4497 tmp.iov_base = NULL;
4498 tmp.iov_len = 0;
4500 ZERO_STRUCT(msg);
4501 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4502 msg.msg_namelen = ss_len; /* size of address */
4503 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4504 msg.msg_iovlen = count; /* # elements in msg_iov */
4505 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4506 msg.msg_control = NULL; /* ancillary data, see below */
4507 msg.msg_controllen = 0; /* ancillary data buffer len */
4508 msg.msg_flags = 0; /* flags on received message */
4509 #endif
4511 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4512 if (rc < 0) {
4513 if (rc == -ENOTSOCK) {
4514 return libc_readv(s, vector, count);
4516 return -1;
4519 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4521 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4522 if (rc != 0) {
4523 return rc;
4526 return ret;
4529 ssize_t readv(int s, const struct iovec *vector, int count)
4531 return swrap_readv(s, vector, count);
4534 /****************************************************************************
4535 * WRITEV
4536 ***************************************************************************/
4538 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4540 struct msghdr msg;
4541 struct iovec tmp;
4542 struct sockaddr_un un_addr;
4543 ssize_t ret;
4544 int rc;
4545 struct socket_info *si = find_socket_info(s);
4547 if (!si) {
4548 return libc_writev(s, vector, count);
4551 tmp.iov_base = NULL;
4552 tmp.iov_len = 0;
4554 ZERO_STRUCT(msg);
4555 msg.msg_name = NULL; /* optional address */
4556 msg.msg_namelen = 0; /* size of address */
4557 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4558 msg.msg_iovlen = count; /* # elements in msg_iov */
4559 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4560 msg.msg_control = NULL; /* ancillary data, see below */
4561 msg.msg_controllen = 0; /* ancillary data buffer len */
4562 msg.msg_flags = 0; /* flags on received message */
4563 #endif
4565 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4566 if (rc < 0) {
4567 if (rc == -ENOTSOCK) {
4568 return libc_readv(s, vector, count);
4570 return -1;
4573 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4575 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4577 return ret;
4580 ssize_t writev(int s, const struct iovec *vector, int count)
4582 return swrap_writev(s, vector, count);
4585 /****************************
4586 * CLOSE
4587 ***************************/
4589 static int swrap_close(int fd)
4591 struct socket_info *si = find_socket_info(fd);
4592 struct socket_info_fd *fi;
4593 int ret;
4595 if (!si) {
4596 return libc_close(fd);
4599 for (fi = si->fds; fi; fi = fi->next) {
4600 if (fi->fd == fd) {
4601 SWRAP_DLIST_REMOVE(si->fds, fi);
4602 free(fi);
4603 break;
4607 if (si->fds) {
4608 /* there are still references left */
4609 return libc_close(fd);
4612 SWRAP_DLIST_REMOVE(sockets, si);
4614 if (si->myname && si->peername) {
4615 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4618 ret = libc_close(fd);
4620 if (si->myname && si->peername) {
4621 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4622 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4625 if (si->bindname != NULL) {
4626 free(si->bindname);
4629 if (si->myname) free(si->myname);
4630 if (si->peername) free(si->peername);
4631 if (si->tmp_path) {
4632 unlink(si->tmp_path);
4633 free(si->tmp_path);
4635 free(si);
4637 return ret;
4640 int close(int fd)
4642 return swrap_close(fd);
4645 /****************************
4646 * DUP
4647 ***************************/
4649 static int swrap_dup(int fd)
4651 struct socket_info *si;
4652 struct socket_info_fd *fi;
4654 si = find_socket_info(fd);
4656 if (!si) {
4657 return libc_dup(fd);
4660 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4661 if (fi == NULL) {
4662 errno = ENOMEM;
4663 return -1;
4666 fi->fd = libc_dup(fd);
4667 if (fi->fd == -1) {
4668 int saved_errno = errno;
4669 free(fi);
4670 errno = saved_errno;
4671 return -1;
4674 /* Make sure we don't have an entry for the fd */
4675 swrap_remove_stale(fi->fd);
4677 SWRAP_DLIST_ADD(si->fds, fi);
4678 return fi->fd;
4681 int dup(int fd)
4683 return swrap_dup(fd);
4686 /****************************
4687 * DUP2
4688 ***************************/
4690 static int swrap_dup2(int fd, int newfd)
4692 struct socket_info *si;
4693 struct socket_info_fd *fi;
4695 si = find_socket_info(fd);
4697 if (!si) {
4698 return libc_dup2(fd, newfd);
4701 if (find_socket_info(newfd)) {
4702 /* dup2() does an implicit close of newfd, which we
4703 * need to emulate */
4704 swrap_close(newfd);
4707 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4708 if (fi == NULL) {
4709 errno = ENOMEM;
4710 return -1;
4713 fi->fd = libc_dup2(fd, newfd);
4714 if (fi->fd == -1) {
4715 int saved_errno = errno;
4716 free(fi);
4717 errno = saved_errno;
4718 return -1;
4721 /* Make sure we don't have an entry for the fd */
4722 swrap_remove_stale(fi->fd);
4724 SWRAP_DLIST_ADD(si->fds, fi);
4725 return fi->fd;
4728 int dup2(int fd, int newfd)
4730 return swrap_dup2(fd, newfd);
4733 /****************************
4734 * DUP2
4735 ***************************/
4737 #ifdef HAVE_EVENTFD
4738 static int swrap_eventfd(int count, int flags)
4740 int fd;
4742 fd = libc_eventfd(count, flags);
4743 if (fd != -1) {
4744 swrap_remove_stale(fd);
4747 return fd;
4750 int eventfd(int count, int flags)
4752 return swrap_eventfd(count, flags);
4754 #endif
4756 /****************************
4757 * DESTRUCTOR
4758 ***************************/
4761 * This function is called when the library is unloaded and makes sure that
4762 * sockets get closed and the unix file for the socket are unlinked.
4764 void swrap_destructor(void)
4766 struct socket_info *s = sockets;
4768 while (s != NULL) {
4769 struct socket_info_fd *f = s->fds;
4770 if (f != NULL) {
4771 swrap_close(f->fd);
4773 s = sockets;