SO_PROTOCOL is platform-dependent
[Samba.git] / lib / socket_wrapper / socket_wrapper.c
blob903eec21537429fc69ea4979094888cf71c244a0
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 #if 0 /* FIXME */
1271 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1273 struct socket_info *s;
1275 /* first catch invalid input */
1276 switch (sa->sa_family) {
1277 case AF_INET:
1278 if (len < sizeof(struct sockaddr_in)) {
1279 return false;
1281 break;
1282 #if HAVE_IPV6
1283 case AF_INET6:
1284 if (len < sizeof(struct sockaddr_in6)) {
1285 return false;
1287 break;
1288 #endif
1289 default:
1290 return false;
1291 break;
1294 for (s = sockets; s != NULL; s = s->next) {
1295 if (s->myname == NULL) {
1296 continue;
1298 if (s->myname->sa_family != sa->sa_family) {
1299 continue;
1301 switch (s->myname->sa_family) {
1302 case AF_INET: {
1303 struct sockaddr_in *sin1, *sin2;
1305 sin1 = (struct sockaddr_in *)s->myname;
1306 sin2 = (struct sockaddr_in *)sa;
1308 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1309 continue;
1311 if (sin1->sin_port != sin2->sin_port) {
1312 continue;
1314 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1315 continue;
1318 /* found */
1319 return true;
1320 break;
1322 #if HAVE_IPV6
1323 case AF_INET6: {
1324 struct sockaddr_in6 *sin1, *sin2;
1326 sin1 = (struct sockaddr_in6 *)s->myname;
1327 sin2 = (struct sockaddr_in6 *)sa;
1329 if (sin1->sin6_port != sin2->sin6_port) {
1330 continue;
1332 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1333 &sin2->sin6_addr))
1335 continue;
1338 /* found */
1339 return true;
1340 break;
1342 #endif
1343 default:
1344 continue;
1345 break;
1350 return false;
1352 #endif
1354 static void swrap_remove_stale(int fd)
1356 struct socket_info *si = find_socket_info(fd);
1357 struct socket_info_fd *fi;
1359 if (si != NULL) {
1360 for (fi = si->fds; fi; fi = fi->next) {
1361 if (fi->fd == fd) {
1362 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1363 SWRAP_DLIST_REMOVE(si->fds, fi);
1364 free(fi);
1365 break;
1369 if (si->fds == NULL) {
1370 SWRAP_DLIST_REMOVE(sockets, si);
1375 static int sockaddr_convert_to_un(struct socket_info *si,
1376 const struct sockaddr *in_addr,
1377 socklen_t in_len,
1378 struct sockaddr_un *out_addr,
1379 int alloc_sock,
1380 int *bcast)
1382 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1384 (void) in_len; /* unused */
1386 if (out_addr == NULL) {
1387 return 0;
1390 out->sa_family = AF_UNIX;
1391 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1392 out->sa_len = sizeof(*out_addr);
1393 #endif
1395 switch (in_addr->sa_family) {
1396 case AF_UNSPEC: {
1397 const struct sockaddr_in *sin;
1398 if (si->family != AF_INET) {
1399 break;
1401 if (in_len < sizeof(struct sockaddr_in)) {
1402 break;
1404 sin = (const struct sockaddr_in *)in_addr;
1405 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1406 break;
1410 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1411 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1414 /* FALL THROUGH */
1416 case AF_INET:
1417 #ifdef HAVE_IPV6
1418 case AF_INET6:
1419 #endif
1420 switch (si->type) {
1421 case SOCK_STREAM:
1422 case SOCK_DGRAM:
1423 break;
1424 default:
1425 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1426 errno = ESOCKTNOSUPPORT;
1427 return -1;
1429 if (alloc_sock) {
1430 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1431 } else {
1432 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1434 default:
1435 break;
1438 errno = EAFNOSUPPORT;
1439 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1440 return -1;
1443 static int sockaddr_convert_from_un(const struct socket_info *si,
1444 const struct sockaddr_un *in_addr,
1445 socklen_t un_addrlen,
1446 int family,
1447 struct sockaddr *out_addr,
1448 socklen_t *out_addrlen)
1450 int ret;
1452 if (out_addr == NULL || out_addrlen == NULL)
1453 return 0;
1455 if (un_addrlen == 0) {
1456 *out_addrlen = 0;
1457 return 0;
1460 switch (family) {
1461 case AF_INET:
1462 #ifdef HAVE_IPV6
1463 case AF_INET6:
1464 #endif
1465 switch (si->type) {
1466 case SOCK_STREAM:
1467 case SOCK_DGRAM:
1468 break;
1469 default:
1470 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1471 errno = ESOCKTNOSUPPORT;
1472 return -1;
1474 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1475 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1476 out_addr->sa_len = *out_addrlen;
1477 #endif
1478 return ret;
1479 default:
1480 break;
1483 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1484 errno = EAFNOSUPPORT;
1485 return -1;
1488 enum swrap_packet_type {
1489 SWRAP_CONNECT_SEND,
1490 SWRAP_CONNECT_UNREACH,
1491 SWRAP_CONNECT_RECV,
1492 SWRAP_CONNECT_ACK,
1493 SWRAP_ACCEPT_SEND,
1494 SWRAP_ACCEPT_RECV,
1495 SWRAP_ACCEPT_ACK,
1496 SWRAP_RECVFROM,
1497 SWRAP_SENDTO,
1498 SWRAP_SENDTO_UNREACH,
1499 SWRAP_PENDING_RST,
1500 SWRAP_RECV,
1501 SWRAP_RECV_RST,
1502 SWRAP_SEND,
1503 SWRAP_SEND_RST,
1504 SWRAP_CLOSE_SEND,
1505 SWRAP_CLOSE_RECV,
1506 SWRAP_CLOSE_ACK,
1509 struct swrap_file_hdr {
1510 uint32_t magic;
1511 uint16_t version_major;
1512 uint16_t version_minor;
1513 int32_t timezone;
1514 uint32_t sigfigs;
1515 uint32_t frame_max_len;
1516 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1517 uint32_t link_type;
1519 #define SWRAP_FILE_HDR_SIZE 24
1521 struct swrap_packet_frame {
1522 uint32_t seconds;
1523 uint32_t micro_seconds;
1524 uint32_t recorded_length;
1525 uint32_t full_length;
1527 #define SWRAP_PACKET_FRAME_SIZE 16
1529 union swrap_packet_ip {
1530 struct {
1531 uint8_t ver_hdrlen;
1532 uint8_t tos;
1533 uint16_t packet_length;
1534 uint16_t identification;
1535 uint8_t flags;
1536 uint8_t fragment;
1537 uint8_t ttl;
1538 uint8_t protocol;
1539 uint16_t hdr_checksum;
1540 uint32_t src_addr;
1541 uint32_t dest_addr;
1542 } v4;
1543 #define SWRAP_PACKET_IP_V4_SIZE 20
1544 struct {
1545 uint8_t ver_prio;
1546 uint8_t flow_label_high;
1547 uint16_t flow_label_low;
1548 uint16_t payload_length;
1549 uint8_t next_header;
1550 uint8_t hop_limit;
1551 uint8_t src_addr[16];
1552 uint8_t dest_addr[16];
1553 } v6;
1554 #define SWRAP_PACKET_IP_V6_SIZE 40
1556 #define SWRAP_PACKET_IP_SIZE 40
1558 union swrap_packet_payload {
1559 struct {
1560 uint16_t source_port;
1561 uint16_t dest_port;
1562 uint32_t seq_num;
1563 uint32_t ack_num;
1564 uint8_t hdr_length;
1565 uint8_t control;
1566 uint16_t window;
1567 uint16_t checksum;
1568 uint16_t urg;
1569 } tcp;
1570 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1571 struct {
1572 uint16_t source_port;
1573 uint16_t dest_port;
1574 uint16_t length;
1575 uint16_t checksum;
1576 } udp;
1577 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1578 struct {
1579 uint8_t type;
1580 uint8_t code;
1581 uint16_t checksum;
1582 uint32_t unused;
1583 } icmp4;
1584 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1585 struct {
1586 uint8_t type;
1587 uint8_t code;
1588 uint16_t checksum;
1589 uint32_t unused;
1590 } icmp6;
1591 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1593 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1595 #define SWRAP_PACKET_MIN_ALLOC \
1596 (SWRAP_PACKET_FRAME_SIZE + \
1597 SWRAP_PACKET_IP_SIZE + \
1598 SWRAP_PACKET_PAYLOAD_SIZE)
1600 static const char *socket_wrapper_pcap_file(void)
1602 static int initialized = 0;
1603 static const char *s = NULL;
1604 static const struct swrap_file_hdr h;
1605 static const struct swrap_packet_frame f;
1606 static const union swrap_packet_ip i;
1607 static const union swrap_packet_payload p;
1609 if (initialized == 1) {
1610 return s;
1612 initialized = 1;
1615 * TODO: don't use the structs use plain buffer offsets
1616 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1618 * for now make sure we disable PCAP support
1619 * if the struct has alignment!
1621 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1622 return NULL;
1624 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1625 return NULL;
1627 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1628 return NULL;
1630 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1631 return NULL;
1633 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1634 return NULL;
1636 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1637 return NULL;
1639 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1640 return NULL;
1642 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1643 return NULL;
1645 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1646 return NULL;
1648 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1649 return NULL;
1652 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1653 if (s == NULL) {
1654 return NULL;
1656 if (strncmp(s, "./", 2) == 0) {
1657 s += 2;
1659 return s;
1662 static uint8_t *swrap_packet_init(struct timeval *tval,
1663 const struct sockaddr *src,
1664 const struct sockaddr *dest,
1665 int socket_type,
1666 const uint8_t *payload,
1667 size_t payload_len,
1668 unsigned long tcp_seqno,
1669 unsigned long tcp_ack,
1670 unsigned char tcp_ctl,
1671 int unreachable,
1672 size_t *_packet_len)
1674 uint8_t *base;
1675 uint8_t *buf;
1676 struct swrap_packet_frame *frame;
1677 union swrap_packet_ip *ip;
1678 union swrap_packet_payload *pay;
1679 size_t packet_len;
1680 size_t alloc_len;
1681 size_t nonwire_len = sizeof(*frame);
1682 size_t wire_hdr_len = 0;
1683 size_t wire_len = 0;
1684 size_t ip_hdr_len = 0;
1685 size_t icmp_hdr_len = 0;
1686 size_t icmp_truncate_len = 0;
1687 uint8_t protocol = 0, icmp_protocol = 0;
1688 const struct sockaddr_in *src_in = NULL;
1689 const struct sockaddr_in *dest_in = NULL;
1690 #ifdef HAVE_IPV6
1691 const struct sockaddr_in6 *src_in6 = NULL;
1692 const struct sockaddr_in6 *dest_in6 = NULL;
1693 #endif
1694 uint16_t src_port;
1695 uint16_t dest_port;
1697 switch (src->sa_family) {
1698 case AF_INET:
1699 src_in = (const struct sockaddr_in *)src;
1700 dest_in = (const struct sockaddr_in *)dest;
1701 src_port = src_in->sin_port;
1702 dest_port = dest_in->sin_port;
1703 ip_hdr_len = sizeof(ip->v4);
1704 break;
1705 #ifdef HAVE_IPV6
1706 case AF_INET6:
1707 src_in6 = (const struct sockaddr_in6 *)src;
1708 dest_in6 = (const struct sockaddr_in6 *)dest;
1709 src_port = src_in6->sin6_port;
1710 dest_port = dest_in6->sin6_port;
1711 ip_hdr_len = sizeof(ip->v6);
1712 break;
1713 #endif
1714 default:
1715 return NULL;
1718 switch (socket_type) {
1719 case SOCK_STREAM:
1720 protocol = 0x06; /* TCP */
1721 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1722 wire_len = wire_hdr_len + payload_len;
1723 break;
1725 case SOCK_DGRAM:
1726 protocol = 0x11; /* UDP */
1727 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1728 wire_len = wire_hdr_len + payload_len;
1729 break;
1731 default:
1732 return NULL;
1735 if (unreachable) {
1736 icmp_protocol = protocol;
1737 switch (src->sa_family) {
1738 case AF_INET:
1739 protocol = 0x01; /* ICMPv4 */
1740 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1741 break;
1742 #ifdef HAVE_IPV6
1743 case AF_INET6:
1744 protocol = 0x3A; /* ICMPv6 */
1745 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1746 break;
1747 #endif
1749 if (wire_len > 64 ) {
1750 icmp_truncate_len = wire_len - 64;
1752 wire_hdr_len += icmp_hdr_len;
1753 wire_len += icmp_hdr_len;
1756 packet_len = nonwire_len + wire_len;
1757 alloc_len = packet_len;
1758 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1759 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1762 base = (uint8_t *)malloc(alloc_len);
1763 if (base == NULL) {
1764 return NULL;
1766 memset(base, 0x0, alloc_len);
1768 buf = base;
1770 frame = (struct swrap_packet_frame *)buf;
1771 frame->seconds = tval->tv_sec;
1772 frame->micro_seconds = tval->tv_usec;
1773 frame->recorded_length = wire_len - icmp_truncate_len;
1774 frame->full_length = wire_len - icmp_truncate_len;
1775 buf += SWRAP_PACKET_FRAME_SIZE;
1777 ip = (union swrap_packet_ip *)buf;
1778 switch (src->sa_family) {
1779 case AF_INET:
1780 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1781 ip->v4.tos = 0x00;
1782 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1783 ip->v4.identification = htons(0xFFFF);
1784 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1785 ip->v4.fragment = htons(0x0000);
1786 ip->v4.ttl = 0xFF;
1787 ip->v4.protocol = protocol;
1788 ip->v4.hdr_checksum = htons(0x0000);
1789 ip->v4.src_addr = src_in->sin_addr.s_addr;
1790 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1791 buf += SWRAP_PACKET_IP_V4_SIZE;
1792 break;
1793 #ifdef HAVE_IPV6
1794 case AF_INET6:
1795 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1796 ip->v6.flow_label_high = 0x00;
1797 ip->v6.flow_label_low = 0x0000;
1798 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1799 ip->v6.next_header = protocol;
1800 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1801 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1802 buf += SWRAP_PACKET_IP_V6_SIZE;
1803 break;
1804 #endif
1807 if (unreachable) {
1808 pay = (union swrap_packet_payload *)buf;
1809 switch (src->sa_family) {
1810 case AF_INET:
1811 pay->icmp4.type = 0x03; /* destination unreachable */
1812 pay->icmp4.code = 0x01; /* host unreachable */
1813 pay->icmp4.checksum = htons(0x0000);
1814 pay->icmp4.unused = htonl(0x00000000);
1815 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1817 /* set the ip header in the ICMP payload */
1818 ip = (union swrap_packet_ip *)buf;
1819 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1820 ip->v4.tos = 0x00;
1821 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1822 ip->v4.identification = htons(0xFFFF);
1823 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1824 ip->v4.fragment = htons(0x0000);
1825 ip->v4.ttl = 0xFF;
1826 ip->v4.protocol = icmp_protocol;
1827 ip->v4.hdr_checksum = htons(0x0000);
1828 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1829 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1830 buf += SWRAP_PACKET_IP_V4_SIZE;
1832 src_port = dest_in->sin_port;
1833 dest_port = src_in->sin_port;
1834 break;
1835 #ifdef HAVE_IPV6
1836 case AF_INET6:
1837 pay->icmp6.type = 0x01; /* destination unreachable */
1838 pay->icmp6.code = 0x03; /* address unreachable */
1839 pay->icmp6.checksum = htons(0x0000);
1840 pay->icmp6.unused = htonl(0x00000000);
1841 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1843 /* set the ip header in the ICMP payload */
1844 ip = (union swrap_packet_ip *)buf;
1845 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1846 ip->v6.flow_label_high = 0x00;
1847 ip->v6.flow_label_low = 0x0000;
1848 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1849 ip->v6.next_header = protocol;
1850 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1851 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1852 buf += SWRAP_PACKET_IP_V6_SIZE;
1854 src_port = dest_in6->sin6_port;
1855 dest_port = src_in6->sin6_port;
1856 break;
1857 #endif
1861 pay = (union swrap_packet_payload *)buf;
1863 switch (socket_type) {
1864 case SOCK_STREAM:
1865 pay->tcp.source_port = src_port;
1866 pay->tcp.dest_port = dest_port;
1867 pay->tcp.seq_num = htonl(tcp_seqno);
1868 pay->tcp.ack_num = htonl(tcp_ack);
1869 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1870 pay->tcp.control = tcp_ctl;
1871 pay->tcp.window = htons(0x7FFF);
1872 pay->tcp.checksum = htons(0x0000);
1873 pay->tcp.urg = htons(0x0000);
1874 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1876 break;
1878 case SOCK_DGRAM:
1879 pay->udp.source_port = src_port;
1880 pay->udp.dest_port = dest_port;
1881 pay->udp.length = htons(8 + payload_len);
1882 pay->udp.checksum = htons(0x0000);
1883 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1885 break;
1888 if (payload && payload_len > 0) {
1889 memcpy(buf, payload, payload_len);
1892 *_packet_len = packet_len - icmp_truncate_len;
1893 return base;
1896 static int swrap_get_pcap_fd(const char *fname)
1898 static int fd = -1;
1900 if (fd != -1) return fd;
1902 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1903 if (fd != -1) {
1904 struct swrap_file_hdr file_hdr;
1905 file_hdr.magic = 0xA1B2C3D4;
1906 file_hdr.version_major = 0x0002;
1907 file_hdr.version_minor = 0x0004;
1908 file_hdr.timezone = 0x00000000;
1909 file_hdr.sigfigs = 0x00000000;
1910 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1911 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1913 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1914 close(fd);
1915 fd = -1;
1917 return fd;
1920 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1922 return fd;
1925 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1926 const struct sockaddr *addr,
1927 enum swrap_packet_type type,
1928 const void *buf, size_t len,
1929 size_t *packet_len)
1931 const struct sockaddr *src_addr;
1932 const struct sockaddr *dest_addr;
1933 unsigned long tcp_seqno = 0;
1934 unsigned long tcp_ack = 0;
1935 unsigned char tcp_ctl = 0;
1936 int unreachable = 0;
1938 struct timeval tv;
1940 switch (si->family) {
1941 case AF_INET:
1942 break;
1943 #ifdef HAVE_IPV6
1944 case AF_INET6:
1945 break;
1946 #endif
1947 default:
1948 return NULL;
1951 switch (type) {
1952 case SWRAP_CONNECT_SEND:
1953 if (si->type != SOCK_STREAM) return NULL;
1955 src_addr = si->myname;
1956 dest_addr = addr;
1958 tcp_seqno = si->io.pck_snd;
1959 tcp_ack = si->io.pck_rcv;
1960 tcp_ctl = 0x02; /* SYN */
1962 si->io.pck_snd += 1;
1964 break;
1966 case SWRAP_CONNECT_RECV:
1967 if (si->type != SOCK_STREAM) return NULL;
1969 dest_addr = si->myname;
1970 src_addr = addr;
1972 tcp_seqno = si->io.pck_rcv;
1973 tcp_ack = si->io.pck_snd;
1974 tcp_ctl = 0x12; /** SYN,ACK */
1976 si->io.pck_rcv += 1;
1978 break;
1980 case SWRAP_CONNECT_UNREACH:
1981 if (si->type != SOCK_STREAM) return NULL;
1983 dest_addr = si->myname;
1984 src_addr = addr;
1986 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1987 tcp_seqno = si->io.pck_snd - 1;
1988 tcp_ack = si->io.pck_rcv;
1989 tcp_ctl = 0x02; /* SYN */
1990 unreachable = 1;
1992 break;
1994 case SWRAP_CONNECT_ACK:
1995 if (si->type != SOCK_STREAM) return NULL;
1997 src_addr = si->myname;
1998 dest_addr = addr;
2000 tcp_seqno = si->io.pck_snd;
2001 tcp_ack = si->io.pck_rcv;
2002 tcp_ctl = 0x10; /* ACK */
2004 break;
2006 case SWRAP_ACCEPT_SEND:
2007 if (si->type != SOCK_STREAM) return NULL;
2009 dest_addr = si->myname;
2010 src_addr = addr;
2012 tcp_seqno = si->io.pck_rcv;
2013 tcp_ack = si->io.pck_snd;
2014 tcp_ctl = 0x02; /* SYN */
2016 si->io.pck_rcv += 1;
2018 break;
2020 case SWRAP_ACCEPT_RECV:
2021 if (si->type != SOCK_STREAM) return NULL;
2023 src_addr = si->myname;
2024 dest_addr = addr;
2026 tcp_seqno = si->io.pck_snd;
2027 tcp_ack = si->io.pck_rcv;
2028 tcp_ctl = 0x12; /* SYN,ACK */
2030 si->io.pck_snd += 1;
2032 break;
2034 case SWRAP_ACCEPT_ACK:
2035 if (si->type != SOCK_STREAM) return NULL;
2037 dest_addr = si->myname;
2038 src_addr = addr;
2040 tcp_seqno = si->io.pck_rcv;
2041 tcp_ack = si->io.pck_snd;
2042 tcp_ctl = 0x10; /* ACK */
2044 break;
2046 case SWRAP_SEND:
2047 src_addr = si->myname;
2048 dest_addr = si->peername;
2050 tcp_seqno = si->io.pck_snd;
2051 tcp_ack = si->io.pck_rcv;
2052 tcp_ctl = 0x18; /* PSH,ACK */
2054 si->io.pck_snd += len;
2056 break;
2058 case SWRAP_SEND_RST:
2059 dest_addr = si->myname;
2060 src_addr = si->peername;
2062 if (si->type == SOCK_DGRAM) {
2063 return swrap_marshall_packet(si, si->peername,
2064 SWRAP_SENDTO_UNREACH,
2065 buf, len, packet_len);
2068 tcp_seqno = si->io.pck_rcv;
2069 tcp_ack = si->io.pck_snd;
2070 tcp_ctl = 0x14; /** RST,ACK */
2072 break;
2074 case SWRAP_PENDING_RST:
2075 dest_addr = si->myname;
2076 src_addr = si->peername;
2078 if (si->type == SOCK_DGRAM) {
2079 return NULL;
2082 tcp_seqno = si->io.pck_rcv;
2083 tcp_ack = si->io.pck_snd;
2084 tcp_ctl = 0x14; /* RST,ACK */
2086 break;
2088 case SWRAP_RECV:
2089 dest_addr = si->myname;
2090 src_addr = si->peername;
2092 tcp_seqno = si->io.pck_rcv;
2093 tcp_ack = si->io.pck_snd;
2094 tcp_ctl = 0x18; /* PSH,ACK */
2096 si->io.pck_rcv += len;
2098 break;
2100 case SWRAP_RECV_RST:
2101 dest_addr = si->myname;
2102 src_addr = si->peername;
2104 if (si->type == SOCK_DGRAM) {
2105 return NULL;
2108 tcp_seqno = si->io.pck_rcv;
2109 tcp_ack = si->io.pck_snd;
2110 tcp_ctl = 0x14; /* RST,ACK */
2112 break;
2114 case SWRAP_SENDTO:
2115 src_addr = si->myname;
2116 dest_addr = addr;
2118 si->io.pck_snd += len;
2120 break;
2122 case SWRAP_SENDTO_UNREACH:
2123 dest_addr = si->myname;
2124 src_addr = addr;
2126 unreachable = 1;
2128 break;
2130 case SWRAP_RECVFROM:
2131 dest_addr = si->myname;
2132 src_addr = addr;
2134 si->io.pck_rcv += len;
2136 break;
2138 case SWRAP_CLOSE_SEND:
2139 if (si->type != SOCK_STREAM) return NULL;
2141 src_addr = si->myname;
2142 dest_addr = si->peername;
2144 tcp_seqno = si->io.pck_snd;
2145 tcp_ack = si->io.pck_rcv;
2146 tcp_ctl = 0x11; /* FIN, ACK */
2148 si->io.pck_snd += 1;
2150 break;
2152 case SWRAP_CLOSE_RECV:
2153 if (si->type != SOCK_STREAM) return NULL;
2155 dest_addr = si->myname;
2156 src_addr = si->peername;
2158 tcp_seqno = si->io.pck_rcv;
2159 tcp_ack = si->io.pck_snd;
2160 tcp_ctl = 0x11; /* FIN,ACK */
2162 si->io.pck_rcv += 1;
2164 break;
2166 case SWRAP_CLOSE_ACK:
2167 if (si->type != SOCK_STREAM) return NULL;
2169 src_addr = si->myname;
2170 dest_addr = si->peername;
2172 tcp_seqno = si->io.pck_snd;
2173 tcp_ack = si->io.pck_rcv;
2174 tcp_ctl = 0x10; /* ACK */
2176 break;
2177 default:
2178 return NULL;
2181 swrapGetTimeOfDay(&tv);
2183 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2184 (const uint8_t *)buf, len,
2185 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2186 packet_len);
2189 static void swrap_dump_packet(struct socket_info *si,
2190 const struct sockaddr *addr,
2191 enum swrap_packet_type type,
2192 const void *buf, size_t len)
2194 const char *file_name;
2195 uint8_t *packet;
2196 size_t packet_len = 0;
2197 int fd;
2199 file_name = socket_wrapper_pcap_file();
2200 if (!file_name) {
2201 return;
2204 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2205 if (!packet) {
2206 return;
2209 fd = swrap_get_pcap_fd(file_name);
2210 if (fd != -1) {
2211 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2212 free(packet);
2213 return;
2217 free(packet);
2220 /****************************************************************************
2221 * SIGNALFD
2222 ***************************************************************************/
2224 #ifdef HAVE_SIGNALFD
2225 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2227 int rc;
2229 rc = libc_signalfd(fd, mask, flags);
2230 if (rc != -1) {
2231 swrap_remove_stale(fd);
2234 return rc;
2237 int signalfd(int fd, const sigset_t *mask, int flags)
2239 return swrap_signalfd(fd, mask, flags);
2241 #endif
2243 /****************************************************************************
2244 * SOCKET
2245 ***************************************************************************/
2247 static int swrap_socket(int family, int type, int protocol)
2249 struct socket_info *si;
2250 struct socket_info_fd *fi;
2251 int fd;
2252 int real_type = type;
2255 * Remove possible addition flags passed to socket() so
2256 * do not fail checking the type.
2257 * See https://lwn.net/Articles/281965/
2259 #ifdef SOCK_CLOEXEC
2260 real_type &= ~SOCK_CLOEXEC;
2261 #endif
2262 #ifdef SOCK_NONBLOCK
2263 real_type &= ~SOCK_NONBLOCK;
2264 #endif
2266 if (!socket_wrapper_enabled()) {
2267 return libc_socket(family, type, protocol);
2270 switch (family) {
2271 case AF_INET:
2272 #ifdef HAVE_IPV6
2273 case AF_INET6:
2274 #endif
2275 break;
2276 case AF_UNIX:
2277 return libc_socket(family, type, protocol);
2278 default:
2279 errno = EAFNOSUPPORT;
2280 return -1;
2283 switch (real_type) {
2284 case SOCK_STREAM:
2285 break;
2286 case SOCK_DGRAM:
2287 break;
2288 default:
2289 errno = EPROTONOSUPPORT;
2290 return -1;
2293 switch (protocol) {
2294 case 0:
2295 break;
2296 case 6:
2297 if (real_type == SOCK_STREAM) {
2298 break;
2300 /*fall through*/
2301 case 17:
2302 if (real_type == SOCK_DGRAM) {
2303 break;
2305 /*fall through*/
2306 default:
2307 errno = EPROTONOSUPPORT;
2308 return -1;
2312 * We must call libc_socket with type, from the caller, not the version
2313 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2315 fd = libc_socket(AF_UNIX, type, 0);
2317 if (fd == -1) {
2318 return -1;
2321 /* Check if we have a stale fd and remove it */
2322 si = find_socket_info(fd);
2323 if (si != NULL) {
2324 swrap_remove_stale(fd);
2327 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2328 memset(si, 0, sizeof(struct socket_info));
2329 if (si == NULL) {
2330 errno = ENOMEM;
2331 return -1;
2334 si->family = family;
2336 /* however, the rest of the socket_wrapper code expects just
2337 * the type, not the flags */
2338 si->type = real_type;
2339 si->protocol = protocol;
2342 * Setup myname so getsockname() can succeed to find out the socket
2343 * type.
2345 switch(si->family) {
2346 case AF_INET: {
2347 struct sockaddr_in sin = {
2348 .sin_family = AF_INET,
2351 si->myname_len = sizeof(struct sockaddr_in);
2352 si->myname = sockaddr_dup(&sin, si->myname_len);
2353 break;
2355 case AF_INET6: {
2356 struct sockaddr_in6 sin6 = {
2357 .sin6_family = AF_INET6,
2360 si->myname_len = sizeof(struct sockaddr_in6);
2361 si->myname = sockaddr_dup(&sin6, si->myname_len);
2362 break;
2364 default:
2365 free(si);
2366 errno = EINVAL;
2367 return -1;
2370 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2371 if (fi == NULL) {
2372 if (si->myname != NULL) {
2373 free (si->myname);
2375 free(si);
2376 errno = ENOMEM;
2377 return -1;
2380 fi->fd = fd;
2382 SWRAP_DLIST_ADD(si->fds, fi);
2383 SWRAP_DLIST_ADD(sockets, si);
2385 return fd;
2388 int socket(int family, int type, int protocol)
2390 return swrap_socket(family, type, protocol);
2393 /****************************************************************************
2394 * SOCKETPAIR
2395 ***************************************************************************/
2397 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2399 int rc;
2401 rc = libc_socketpair(family, type, protocol, sv);
2402 if (rc != -1) {
2403 swrap_remove_stale(sv[0]);
2404 swrap_remove_stale(sv[1]);
2407 return rc;
2410 int socketpair(int family, int type, int protocol, int sv[2])
2412 return swrap_socketpair(family, type, protocol, sv);
2415 /****************************************************************************
2416 * SOCKETPAIR
2417 ***************************************************************************/
2419 #ifdef HAVE_TIMERFD_CREATE
2420 static int swrap_timerfd_create(int clockid, int flags)
2422 int fd;
2424 fd = libc_timerfd_create(clockid, flags);
2425 if (fd != -1) {
2426 swrap_remove_stale(fd);
2429 return fd;
2432 int timerfd_create(int clockid, int flags)
2434 return swrap_timerfd_create(clockid, flags);
2436 #endif
2438 /****************************************************************************
2439 * PIPE
2440 ***************************************************************************/
2442 static int swrap_pipe(int pipefd[2])
2444 int rc;
2446 rc = libc_pipe(pipefd);
2447 if (rc != -1) {
2448 swrap_remove_stale(pipefd[0]);
2449 swrap_remove_stale(pipefd[1]);
2452 return rc;
2455 int pipe(int pipefd[2])
2457 return swrap_pipe(pipefd);
2460 /****************************************************************************
2461 * ACCEPT
2462 ***************************************************************************/
2464 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2466 struct socket_info *parent_si, *child_si;
2467 struct socket_info_fd *child_fi;
2468 int fd;
2469 struct sockaddr_un un_addr;
2470 socklen_t un_addrlen = sizeof(un_addr);
2471 struct sockaddr_un un_my_addr;
2472 socklen_t un_my_addrlen = sizeof(un_my_addr);
2473 struct sockaddr *my_addr;
2474 socklen_t my_addrlen, len;
2475 int ret;
2477 parent_si = find_socket_info(s);
2478 if (!parent_si) {
2479 return libc_accept(s, addr, addrlen);
2483 * assume out sockaddr have the same size as the in parent
2484 * socket family
2486 my_addrlen = socket_length(parent_si->family);
2487 if (my_addrlen <= 0) {
2488 errno = EINVAL;
2489 return -1;
2492 my_addr = (struct sockaddr *)malloc(my_addrlen);
2493 if (my_addr == NULL) {
2494 return -1;
2497 memset(&un_addr, 0, sizeof(un_addr));
2498 memset(&un_my_addr, 0, sizeof(un_my_addr));
2500 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2501 if (ret == -1) {
2502 if (errno == ENOTSOCK) {
2503 /* Remove stale fds */
2504 swrap_remove_stale(s);
2506 free(my_addr);
2507 return ret;
2510 fd = ret;
2512 len = my_addrlen;
2513 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2514 parent_si->family, my_addr, &len);
2515 if (ret == -1) {
2516 free(my_addr);
2517 close(fd);
2518 return ret;
2521 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2522 memset(child_si, 0, sizeof(struct socket_info));
2524 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2525 if (child_fi == NULL) {
2526 free(child_si);
2527 free(my_addr);
2528 close(fd);
2529 errno = ENOMEM;
2530 return -1;
2533 child_fi->fd = fd;
2535 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2537 child_si->family = parent_si->family;
2538 child_si->type = parent_si->type;
2539 child_si->protocol = parent_si->protocol;
2540 child_si->bound = 1;
2541 child_si->is_server = 1;
2542 child_si->connected = 1;
2544 child_si->peername_len = len;
2545 child_si->peername = sockaddr_dup(my_addr, len);
2547 if (addr != NULL && addrlen != NULL) {
2548 size_t copy_len = MIN(*addrlen, len);
2549 if (copy_len > 0) {
2550 memcpy(addr, my_addr, copy_len);
2552 *addrlen = len;
2555 ret = libc_getsockname(fd,
2556 (struct sockaddr *)(void *)&un_my_addr,
2557 &un_my_addrlen);
2558 if (ret == -1) {
2559 free(child_fi);
2560 free(child_si);
2561 free(my_addr);
2562 close(fd);
2563 return ret;
2566 len = my_addrlen;
2567 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2568 child_si->family, my_addr, &len);
2569 if (ret == -1) {
2570 free(child_fi);
2571 free(child_si);
2572 free(my_addr);
2573 close(fd);
2574 return ret;
2577 SWRAP_LOG(SWRAP_LOG_TRACE,
2578 "accept() path=%s, fd=%d",
2579 un_my_addr.sun_path, s);
2581 child_si->myname_len = len;
2582 child_si->myname = sockaddr_dup(my_addr, len);
2583 free(my_addr);
2585 SWRAP_DLIST_ADD(sockets, child_si);
2587 if (addr != NULL) {
2588 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2589 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2590 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2593 return fd;
2596 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2597 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2598 #else
2599 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2600 #endif
2602 return swrap_accept(s, addr, (socklen_t *)addrlen);
2605 static int autobind_start_init;
2606 static int autobind_start;
2608 /* using sendto() or connect() on an unbound socket would give the
2609 recipient no way to reply, as unlike UDP and TCP, a unix domain
2610 socket can't auto-assign ephemeral port numbers, so we need to
2611 assign it here.
2612 Note: this might change the family from ipv6 to ipv4
2614 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2616 struct sockaddr_un un_addr;
2617 int i;
2618 char type;
2619 int ret;
2620 int port;
2621 struct stat st;
2623 if (autobind_start_init != 1) {
2624 autobind_start_init = 1;
2625 autobind_start = getpid();
2626 autobind_start %= 50000;
2627 autobind_start += 10000;
2630 un_addr.sun_family = AF_UNIX;
2632 switch (family) {
2633 case AF_INET: {
2634 struct sockaddr_in in;
2636 switch (si->type) {
2637 case SOCK_STREAM:
2638 type = SOCKET_TYPE_CHAR_TCP;
2639 break;
2640 case SOCK_DGRAM:
2641 type = SOCKET_TYPE_CHAR_UDP;
2642 break;
2643 default:
2644 errno = ESOCKTNOSUPPORT;
2645 return -1;
2648 memset(&in, 0, sizeof(in));
2649 in.sin_family = AF_INET;
2650 in.sin_addr.s_addr = htonl(127<<24 |
2651 socket_wrapper_default_iface());
2653 free(si->myname);
2654 si->myname_len = sizeof(in);
2655 si->myname = sockaddr_dup(&in, si->myname_len);
2656 break;
2658 #ifdef HAVE_IPV6
2659 case AF_INET6: {
2660 struct sockaddr_in6 in6;
2662 if (si->family != family) {
2663 errno = ENETUNREACH;
2664 return -1;
2667 switch (si->type) {
2668 case SOCK_STREAM:
2669 type = SOCKET_TYPE_CHAR_TCP_V6;
2670 break;
2671 case SOCK_DGRAM:
2672 type = SOCKET_TYPE_CHAR_UDP_V6;
2673 break;
2674 default:
2675 errno = ESOCKTNOSUPPORT;
2676 return -1;
2679 memset(&in6, 0, sizeof(in6));
2680 in6.sin6_family = AF_INET6;
2681 in6.sin6_addr = *swrap_ipv6();
2682 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2683 free(si->myname);
2684 si->myname_len = sizeof(in6);
2685 si->myname = sockaddr_dup(&in6, si->myname_len);
2686 break;
2688 #endif
2689 default:
2690 errno = ESOCKTNOSUPPORT;
2691 return -1;
2694 if (autobind_start > 60000) {
2695 autobind_start = 10000;
2698 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2699 port = autobind_start + i;
2700 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2701 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2702 type, socket_wrapper_default_iface(), port);
2703 if (stat(un_addr.sun_path, &st) == 0) continue;
2705 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2706 sizeof(un_addr));
2707 if (ret == -1) return ret;
2709 si->tmp_path = strdup(un_addr.sun_path);
2710 si->bound = 1;
2711 autobind_start = port + 1;
2712 break;
2714 if (i == SOCKET_MAX_SOCKETS) {
2715 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2716 "interface "SOCKET_FORMAT,
2717 SOCKET_MAX_SOCKETS,
2718 type,
2719 socket_wrapper_default_iface(),
2721 errno = ENFILE;
2722 return -1;
2725 si->family = family;
2726 set_port(si->family, port, si->myname);
2728 return 0;
2731 /****************************************************************************
2732 * CONNECT
2733 ***************************************************************************/
2735 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2736 socklen_t addrlen)
2738 int ret;
2739 struct sockaddr_un un_addr;
2740 struct socket_info *si = find_socket_info(s);
2741 int bcast = 0;
2743 if (!si) {
2744 return libc_connect(s, serv_addr, addrlen);
2747 if (si->bound == 0) {
2748 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2749 if (ret == -1) return -1;
2752 if (si->family != serv_addr->sa_family) {
2753 errno = EINVAL;
2754 return -1;
2757 ret = sockaddr_convert_to_un(si, serv_addr,
2758 addrlen, &un_addr, 0, &bcast);
2759 if (ret == -1) return -1;
2761 if (bcast) {
2762 errno = ENETUNREACH;
2763 return -1;
2766 if (si->type == SOCK_DGRAM) {
2767 si->defer_connect = 1;
2768 ret = 0;
2769 } else {
2770 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2772 ret = libc_connect(s,
2773 (struct sockaddr *)(void *)&un_addr,
2774 sizeof(struct sockaddr_un));
2777 SWRAP_LOG(SWRAP_LOG_TRACE,
2778 "connect() path=%s, fd=%d",
2779 un_addr.sun_path, s);
2782 /* to give better errors */
2783 if (ret == -1 && errno == ENOENT) {
2784 errno = EHOSTUNREACH;
2787 if (ret == 0) {
2788 si->peername_len = addrlen;
2789 si->peername = sockaddr_dup(serv_addr, addrlen);
2790 si->connected = 1;
2793 * When we connect() on a socket than we have to bind the
2794 * outgoing connection on the interface we use for the
2795 * transport. We already bound it on the right interface
2796 * but here we have to update the name so getsockname()
2797 * returns correct information.
2799 if (si->bindname != NULL) {
2800 free(si->myname);
2802 si->myname = si->bindname;
2803 si->myname_len = si->bindname_len;
2805 si->bindname = NULL;
2806 si->bindname_len = 0;
2809 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2810 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2811 } else {
2812 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2815 return ret;
2818 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2820 return swrap_connect(s, serv_addr, addrlen);
2823 /****************************************************************************
2824 * BIND
2825 ***************************************************************************/
2827 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2829 int ret;
2830 struct sockaddr_un un_addr;
2831 struct socket_info *si = find_socket_info(s);
2832 int bind_error = 0;
2833 #if 0 /* FIXME */
2834 bool in_use;
2835 #endif
2837 if (!si) {
2838 return libc_bind(s, myaddr, addrlen);
2841 switch (si->family) {
2842 case AF_INET: {
2843 const struct sockaddr_in *sin;
2844 if (addrlen < sizeof(struct sockaddr_in)) {
2845 bind_error = EINVAL;
2846 break;
2849 sin = (const struct sockaddr_in *)myaddr;
2851 if (sin->sin_family != AF_INET) {
2852 bind_error = EAFNOSUPPORT;
2855 /* special case for AF_UNSPEC */
2856 if (sin->sin_family == AF_UNSPEC &&
2857 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2859 bind_error = 0;
2862 break;
2864 #ifdef HAVE_IPV6
2865 case AF_INET6: {
2866 const struct sockaddr_in6 *sin6;
2867 if (addrlen < sizeof(struct sockaddr_in6)) {
2868 bind_error = EINVAL;
2869 break;
2872 sin6 = (const struct sockaddr_in6 *)myaddr;
2874 if (sin6->sin6_family != AF_INET6) {
2875 bind_error = EAFNOSUPPORT;
2878 break;
2880 #endif
2881 default:
2882 bind_error = EINVAL;
2883 break;
2886 if (bind_error != 0) {
2887 errno = bind_error;
2888 return -1;
2891 #if 0 /* FIXME */
2892 in_use = check_addr_port_in_use(myaddr, addrlen);
2893 if (in_use) {
2894 errno = EADDRINUSE;
2895 return -1;
2897 #endif
2899 free(si->myname);
2900 si->myname_len = addrlen;
2901 si->myname = sockaddr_dup(myaddr, addrlen);
2903 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2904 if (ret == -1) return -1;
2906 unlink(un_addr.sun_path);
2908 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2909 sizeof(struct sockaddr_un));
2911 SWRAP_LOG(SWRAP_LOG_TRACE,
2912 "bind() path=%s, fd=%d",
2913 un_addr.sun_path, s);
2915 if (ret == 0) {
2916 si->bound = 1;
2919 return ret;
2922 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2924 return swrap_bind(s, myaddr, addrlen);
2927 /****************************************************************************
2928 * BINDRESVPORT
2929 ***************************************************************************/
2931 #ifdef HAVE_BINDRESVPORT
2932 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2934 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2936 struct sockaddr_storage myaddr;
2937 socklen_t salen;
2938 static uint16_t port;
2939 uint16_t i;
2940 int rc = -1;
2941 int af;
2943 #define SWRAP_STARTPORT 600
2944 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2945 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2947 if (port == 0) {
2948 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2951 if (sa == NULL) {
2952 salen = sizeof(struct sockaddr);
2953 sa = (struct sockaddr *)&myaddr;
2955 rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
2956 if (rc < 0) {
2957 return -1;
2960 af = sa->sa_family;
2961 memset(&myaddr, 0, salen);
2962 } else {
2963 af = sa->sa_family;
2966 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
2967 switch(af) {
2968 case AF_INET: {
2969 struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
2971 salen = sizeof(struct sockaddr_in);
2972 sinp->sin_port = htons(port);
2973 break;
2975 case AF_INET6: {
2976 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
2978 salen = sizeof(struct sockaddr_in6);
2979 sin6p->sin6_port = htons(port);
2980 break;
2982 default:
2983 errno = EAFNOSUPPORT;
2984 return -1;
2986 sa->sa_family = af;
2988 if (port > SWRAP_ENDPORT) {
2989 port = SWRAP_STARTPORT;
2992 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
2993 if (rc == 0 || errno != EADDRINUSE) {
2994 break;
2998 return rc;
3001 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3003 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3005 #endif
3007 /****************************************************************************
3008 * LISTEN
3009 ***************************************************************************/
3011 static int swrap_listen(int s, int backlog)
3013 int ret;
3014 struct socket_info *si = find_socket_info(s);
3016 if (!si) {
3017 return libc_listen(s, backlog);
3020 ret = libc_listen(s, backlog);
3022 return ret;
3025 int listen(int s, int backlog)
3027 return swrap_listen(s, backlog);
3030 /****************************************************************************
3031 * OPEN
3032 ***************************************************************************/
3034 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3036 int ret;
3038 ret = libc_vopen(pathname, flags, ap);
3039 if (ret != -1) {
3041 * There are methods for closing descriptors (libc-internal code
3042 * paths, direct syscalls) which close descriptors in ways that
3043 * we can't intercept, so try to recover when we notice that
3044 * that's happened
3046 swrap_remove_stale(ret);
3048 return ret;
3051 int open(const char *pathname, int flags, ...)
3053 va_list ap;
3054 int fd;
3056 va_start(ap, flags);
3057 fd = swrap_vopen(pathname, flags, ap);
3058 va_end(ap);
3060 return fd;
3063 /****************************************************************************
3064 * GETPEERNAME
3065 ***************************************************************************/
3067 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3069 struct socket_info *si = find_socket_info(s);
3070 socklen_t len;
3072 if (!si) {
3073 return libc_getpeername(s, name, addrlen);
3076 if (!si->peername)
3078 errno = ENOTCONN;
3079 return -1;
3082 len = MIN(*addrlen, si->peername_len);
3083 if (len == 0) {
3084 return 0;
3087 memcpy(name, si->peername, len);
3088 *addrlen = si->peername_len;
3090 return 0;
3093 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3094 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3095 #else
3096 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3097 #endif
3099 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3102 /****************************************************************************
3103 * GETSOCKNAME
3104 ***************************************************************************/
3106 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3108 struct socket_info *si = find_socket_info(s);
3109 socklen_t len;
3111 if (!si) {
3112 return libc_getsockname(s, name, addrlen);
3115 len = MIN(*addrlen, si->myname_len);
3116 if (len == 0) {
3117 return 0;
3120 memcpy(name, si->myname, len);
3121 *addrlen = si->myname_len;
3123 return 0;
3126 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3127 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3128 #else
3129 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3130 #endif
3132 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3135 /****************************************************************************
3136 * GETSOCKOPT
3137 ***************************************************************************/
3139 #ifndef SO_PROTOCOL
3140 # ifdef SO_PROTOTYPE /* The Solaris name */
3141 # define SO_PROTOCOL SO_PROTOTYPE
3142 # endif /* SO_PROTOTYPE */
3143 #endif /* SO_PROTOCOL */
3145 static int swrap_getsockopt(int s, int level, int optname,
3146 void *optval, socklen_t *optlen)
3148 struct socket_info *si = find_socket_info(s);
3150 if (!si) {
3151 return libc_getsockopt(s,
3152 level,
3153 optname,
3154 optval,
3155 optlen);
3158 if (level == SOL_SOCKET) {
3159 switch (optname) {
3160 #ifdef SO_DOMAIN
3161 case SO_DOMAIN:
3162 if (optval == NULL || optlen == NULL ||
3163 *optlen < (socklen_t)sizeof(int)) {
3164 errno = EINVAL;
3165 return -1;
3168 *optlen = sizeof(int);
3169 *(int *)optval = si->family;
3170 return 0;
3171 #endif /* SO_DOMAIN */
3173 #ifdef SO_PROTOCOL
3174 case SO_PROTOCOL:
3175 if (optval == NULL || optlen == NULL ||
3176 *optlen < (socklen_t)sizeof(int)) {
3177 errno = EINVAL;
3178 return -1;
3181 *optlen = sizeof(int);
3182 *(int *)optval = si->protocol;
3183 return 0;
3184 #endif /* SO_PROTOCOL */
3185 case SO_TYPE:
3186 if (optval == NULL || optlen == NULL ||
3187 *optlen < (socklen_t)sizeof(int)) {
3188 errno = EINVAL;
3189 return -1;
3192 *optlen = sizeof(int);
3193 *(int *)optval = si->type;
3194 return 0;
3195 default:
3196 return libc_getsockopt(s,
3197 level,
3198 optname,
3199 optval,
3200 optlen);
3204 errno = ENOPROTOOPT;
3205 return -1;
3208 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3209 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3210 #else
3211 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3212 #endif
3214 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3217 /****************************************************************************
3218 * SETSOCKOPT
3219 ***************************************************************************/
3221 static int swrap_setsockopt(int s, int level, int optname,
3222 const void *optval, socklen_t optlen)
3224 struct socket_info *si = find_socket_info(s);
3226 if (!si) {
3227 return libc_setsockopt(s,
3228 level,
3229 optname,
3230 optval,
3231 optlen);
3234 if (level == SOL_SOCKET) {
3235 return libc_setsockopt(s,
3236 level,
3237 optname,
3238 optval,
3239 optlen);
3242 switch (si->family) {
3243 case AF_INET:
3244 if (level == IPPROTO_IP) {
3245 #ifdef IP_PKTINFO
3246 if (optname == IP_PKTINFO) {
3247 si->pktinfo = AF_INET;
3249 #endif /* IP_PKTINFO */
3251 return 0;
3252 #ifdef HAVE_IPV6
3253 case AF_INET6:
3254 if (level == IPPROTO_IPV6) {
3255 #ifdef IPV6_RECVPKTINFO
3256 if (optname == IPV6_RECVPKTINFO) {
3257 si->pktinfo = AF_INET6;
3259 #endif /* IPV6_PKTINFO */
3261 return 0;
3262 #endif
3263 default:
3264 errno = ENOPROTOOPT;
3265 return -1;
3269 int setsockopt(int s, int level, int optname,
3270 const void *optval, socklen_t optlen)
3272 return swrap_setsockopt(s, level, optname, optval, optlen);
3275 /****************************************************************************
3276 * IOCTL
3277 ***************************************************************************/
3279 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3281 struct socket_info *si = find_socket_info(s);
3282 va_list ap;
3283 int value;
3284 int rc;
3286 if (!si) {
3287 return libc_vioctl(s, r, va);
3290 va_copy(ap, va);
3292 rc = libc_vioctl(s, r, va);
3294 switch (r) {
3295 case FIONREAD:
3296 value = *((int *)va_arg(ap, int *));
3298 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3299 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3300 } else if (value == 0) { /* END OF FILE */
3301 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3303 break;
3306 va_end(ap);
3308 return rc;
3311 #ifdef HAVE_IOCTL_INT
3312 int ioctl(int s, int r, ...)
3313 #else
3314 int ioctl(int s, unsigned long int r, ...)
3315 #endif
3317 va_list va;
3318 int rc;
3320 va_start(va, r);
3322 rc = swrap_vioctl(s, (unsigned long int) r, va);
3324 va_end(va);
3326 return rc;
3329 /*****************
3330 * CMSG
3331 *****************/
3333 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3335 #ifndef CMSG_ALIGN
3336 # ifdef _ALIGN /* BSD */
3337 #define CMSG_ALIGN _ALIGN
3338 # else
3339 #error NO_CMSG_ALIGN
3340 # endif /* _ALIGN */
3341 #endif /* CMSG_ALIGN */
3344 * @brief Add a cmsghdr to a msghdr.
3346 * This is an function to add any type of cmsghdr. It will operate on the
3347 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3348 * the buffer position after the added cmsg element. Hence, this function is
3349 * intended to be used with an intermediate msghdr and not on the original
3350 * one handed in by the client.
3352 * @param[in] msg The msghdr to which to add the cmsg.
3354 * @param[in] level The cmsg level to set.
3356 * @param[in] type The cmsg type to set.
3358 * @param[in] data The cmsg data to set.
3360 * @param[in] len the length of the data to set.
3362 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3363 int level,
3364 int type,
3365 const void *data,
3366 size_t len)
3368 size_t cmlen = CMSG_LEN(len);
3369 size_t cmspace = CMSG_SPACE(len);
3370 uint8_t cmbuf[cmspace];
3371 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3372 uint8_t *p;
3374 memset(cmbuf, 0, cmspace);
3376 if (msg->msg_controllen < cmlen) {
3377 cmlen = msg->msg_controllen;
3378 msg->msg_flags |= MSG_CTRUNC;
3381 if (msg->msg_controllen < cmspace) {
3382 cmspace = msg->msg_controllen;
3386 * We copy the full input data into an intermediate cmsghdr first
3387 * in order to more easily cope with truncation.
3389 cm->cmsg_len = cmlen;
3390 cm->cmsg_level = level;
3391 cm->cmsg_type = type;
3392 memcpy(CMSG_DATA(cm), data, len);
3395 * We now copy the possibly truncated buffer.
3396 * We copy cmlen bytes, but consume cmspace bytes,
3397 * leaving the possible padding uninitialiazed.
3399 p = (uint8_t *)msg->msg_control;
3400 memcpy(p, cm, cmlen);
3401 p += cmspace;
3402 msg->msg_control = p;
3403 msg->msg_controllen -= cmspace;
3405 return;
3408 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3409 struct msghdr *msg)
3411 /* Add packet info */
3412 switch (si->pktinfo) {
3413 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3414 case AF_INET: {
3415 struct sockaddr_in *sin;
3416 #if defined(HAVE_STRUCT_IN_PKTINFO)
3417 struct in_pktinfo pkt;
3418 #elif defined(IP_RECVDSTADDR)
3419 struct in_addr pkt;
3420 #endif
3422 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3423 sin = (struct sockaddr_in*)si->bindname;
3424 } else {
3425 if (si->myname_len != sizeof(struct sockaddr_in)) {
3426 return 0;
3428 sin = (struct sockaddr_in*)si->myname;
3431 ZERO_STRUCT(pkt);
3433 #if defined(HAVE_STRUCT_IN_PKTINFO)
3434 pkt.ipi_ifindex = socket_wrapper_default_iface();
3435 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3436 #elif defined(IP_RECVDSTADDR)
3437 pkt = sin->sin_addr;
3438 #endif
3440 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3441 &pkt, sizeof(pkt));
3443 break;
3445 #endif /* IP_PKTINFO */
3446 #if defined(HAVE_IPV6)
3447 case AF_INET6: {
3448 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3449 struct sockaddr_in6 *sin6;
3450 struct in6_pktinfo pkt6;
3452 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3453 sin6 = (struct sockaddr_in6*)si->bindname;
3454 } else {
3455 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3456 return 0;
3458 sin6 = (struct sockaddr_in6*)si->myname;
3461 ZERO_STRUCT(pkt6);
3463 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3464 pkt6.ipi6_addr = sin6->sin6_addr;
3466 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3467 &pkt6, sizeof(pkt6));
3468 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3470 break;
3472 #endif /* IPV6_PKTINFO */
3473 default:
3474 return -1;
3477 return 0;
3480 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3481 struct msghdr *omsg)
3483 int rc = 0;
3485 if (si->pktinfo > 0) {
3486 rc = swrap_msghdr_add_pktinfo(si, omsg);
3489 return rc;
3492 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3493 uint8_t **cm_data,
3494 size_t *cm_data_space);
3495 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3496 uint8_t **cm_data,
3497 size_t *cm_data_space);
3499 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3500 uint8_t **cm_data,
3501 size_t *cm_data_space) {
3502 struct cmsghdr *cmsg;
3503 int rc = -1;
3505 /* Nothing to do */
3506 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3507 return 0;
3510 for (cmsg = CMSG_FIRSTHDR(msg);
3511 cmsg != NULL;
3512 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3513 switch (cmsg->cmsg_level) {
3514 case IPPROTO_IP:
3515 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3516 cm_data,
3517 cm_data_space);
3518 break;
3519 default:
3520 rc = swrap_sendmsg_copy_cmsg(cmsg,
3521 cm_data,
3522 cm_data_space);
3523 break;
3527 return rc;
3530 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3531 uint8_t **cm_data,
3532 size_t *cm_data_space)
3534 size_t cmspace;
3535 uint8_t *p;
3537 cmspace =
3538 (*cm_data_space) +
3539 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3541 p = realloc((*cm_data), cmspace);
3542 if (p == NULL) {
3543 return -1;
3545 (*cm_data) = p;
3547 p = (*cm_data) + (*cm_data_space);
3548 *cm_data_space = cmspace;
3550 memcpy(p, cmsg, cmsg->cmsg_len);
3552 return 0;
3555 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3556 uint8_t **cm_data,
3557 size_t *cm_data_space);
3560 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3561 uint8_t **cm_data,
3562 size_t *cm_data_space)
3564 int rc = -1;
3566 switch(cmsg->cmsg_type) {
3567 #ifdef IP_PKTINFO
3568 case IP_PKTINFO:
3569 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3570 cm_data,
3571 cm_data_space);
3572 break;
3573 #endif
3574 #ifdef IPV6_PKTINFO
3575 case IPV6_PKTINFO:
3576 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3577 cm_data,
3578 cm_data_space);
3579 break;
3580 #endif
3581 default:
3582 break;
3585 return rc;
3588 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3589 uint8_t **cm_data,
3590 size_t *cm_data_space)
3592 (void)cmsg; /* unused */
3593 (void)cm_data; /* unused */
3594 (void)cm_data_space; /* unused */
3597 * Passing a IP pktinfo to a unix socket might be rejected by the
3598 * Kernel, at least on FreeBSD. So skip this cmsg.
3600 return 0;
3602 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3604 static ssize_t swrap_sendmsg_before(int fd,
3605 struct socket_info *si,
3606 struct msghdr *msg,
3607 struct iovec *tmp_iov,
3608 struct sockaddr_un *tmp_un,
3609 const struct sockaddr_un **to_un,
3610 const struct sockaddr **to,
3611 int *bcast)
3613 size_t i, len = 0;
3614 ssize_t ret;
3616 if (to_un) {
3617 *to_un = NULL;
3619 if (to) {
3620 *to = NULL;
3622 if (bcast) {
3623 *bcast = 0;
3626 switch (si->type) {
3627 case SOCK_STREAM:
3628 if (!si->connected) {
3629 errno = ENOTCONN;
3630 return -1;
3633 if (msg->msg_iovlen == 0) {
3634 break;
3637 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3638 size_t nlen;
3639 nlen = len + msg->msg_iov[i].iov_len;
3640 if (nlen > SOCKET_MAX_PACKET) {
3641 break;
3644 msg->msg_iovlen = i;
3645 if (msg->msg_iovlen == 0) {
3646 *tmp_iov = msg->msg_iov[0];
3647 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3648 msg->msg_iov = tmp_iov;
3649 msg->msg_iovlen = 1;
3651 break;
3653 case SOCK_DGRAM:
3654 if (si->connected) {
3655 if (msg->msg_name) {
3656 errno = EISCONN;
3657 return -1;
3659 } else {
3660 const struct sockaddr *msg_name;
3661 msg_name = (const struct sockaddr *)msg->msg_name;
3663 if (msg_name == NULL) {
3664 errno = ENOTCONN;
3665 return -1;
3669 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3670 tmp_un, 0, bcast);
3671 if (ret == -1) return -1;
3673 if (to_un) {
3674 *to_un = tmp_un;
3676 if (to) {
3677 *to = msg_name;
3679 msg->msg_name = tmp_un;
3680 msg->msg_namelen = sizeof(*tmp_un);
3683 if (si->bound == 0) {
3684 ret = swrap_auto_bind(fd, si, si->family);
3685 if (ret == -1) {
3686 if (errno == ENOTSOCK) {
3687 swrap_remove_stale(fd);
3688 return -ENOTSOCK;
3689 } else {
3690 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3691 return -1;
3696 if (!si->defer_connect) {
3697 break;
3700 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3701 tmp_un, 0, NULL);
3702 if (ret == -1) return -1;
3704 ret = libc_connect(fd,
3705 (struct sockaddr *)(void *)tmp_un,
3706 sizeof(*tmp_un));
3708 /* to give better errors */
3709 if (ret == -1 && errno == ENOENT) {
3710 errno = EHOSTUNREACH;
3713 if (ret == -1) {
3714 return ret;
3717 si->defer_connect = 0;
3718 break;
3719 default:
3720 errno = EHOSTUNREACH;
3721 return -1;
3724 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3725 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3726 uint8_t *cmbuf = NULL;
3727 size_t cmlen = 0;
3729 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3730 if (ret < 0) {
3731 free(cmbuf);
3732 return -1;
3735 if (cmlen == 0) {
3736 msg->msg_controllen = 0;
3737 msg->msg_control = NULL;
3738 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3739 memcpy(msg->msg_control, cmbuf, cmlen);
3740 msg->msg_controllen = cmlen;
3742 free(cmbuf);
3744 #endif
3746 return 0;
3749 static void swrap_sendmsg_after(int fd,
3750 struct socket_info *si,
3751 struct msghdr *msg,
3752 const struct sockaddr *to,
3753 ssize_t ret)
3755 int saved_errno = errno;
3756 size_t i, len = 0;
3757 uint8_t *buf;
3758 off_t ofs = 0;
3759 size_t avail = 0;
3760 size_t remain;
3762 /* to give better errors */
3763 if (ret == -1) {
3764 if (saved_errno == ENOENT) {
3765 saved_errno = EHOSTUNREACH;
3766 } else if (saved_errno == ENOTSOCK) {
3767 /* If the fd is not a socket, remove it */
3768 swrap_remove_stale(fd);
3772 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3773 avail += msg->msg_iov[i].iov_len;
3776 if (ret == -1) {
3777 remain = MIN(80, avail);
3778 } else {
3779 remain = ret;
3782 /* we capture it as one single packet */
3783 buf = (uint8_t *)malloc(remain);
3784 if (!buf) {
3785 /* we just not capture the packet */
3786 errno = saved_errno;
3787 return;
3790 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3791 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3792 memcpy(buf + ofs,
3793 msg->msg_iov[i].iov_base,
3794 this_time);
3795 ofs += this_time;
3796 remain -= this_time;
3798 len = ofs;
3800 switch (si->type) {
3801 case SOCK_STREAM:
3802 if (ret == -1) {
3803 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3804 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3805 } else {
3806 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3808 break;
3810 case SOCK_DGRAM:
3811 if (si->connected) {
3812 to = si->peername;
3814 if (ret == -1) {
3815 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3816 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3817 } else {
3818 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3820 break;
3823 free(buf);
3824 errno = saved_errno;
3827 static int swrap_recvmsg_before(int fd,
3828 struct socket_info *si,
3829 struct msghdr *msg,
3830 struct iovec *tmp_iov)
3832 size_t i, len = 0;
3833 ssize_t ret;
3835 (void)fd; /* unused */
3837 switch (si->type) {
3838 case SOCK_STREAM:
3839 if (!si->connected) {
3840 errno = ENOTCONN;
3841 return -1;
3844 if (msg->msg_iovlen == 0) {
3845 break;
3848 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3849 size_t nlen;
3850 nlen = len + msg->msg_iov[i].iov_len;
3851 if (nlen > SOCKET_MAX_PACKET) {
3852 break;
3855 msg->msg_iovlen = i;
3856 if (msg->msg_iovlen == 0) {
3857 *tmp_iov = msg->msg_iov[0];
3858 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3859 msg->msg_iov = tmp_iov;
3860 msg->msg_iovlen = 1;
3862 break;
3864 case SOCK_DGRAM:
3865 if (msg->msg_name == NULL) {
3866 errno = EINVAL;
3867 return -1;
3870 if (msg->msg_iovlen == 0) {
3871 break;
3874 if (si->bound == 0) {
3875 ret = swrap_auto_bind(fd, si, si->family);
3876 if (ret == -1) {
3878 * When attempting to read or write to a
3879 * descriptor, if an underlying autobind fails
3880 * because it's not a socket, stop intercepting
3881 * uses of that descriptor.
3883 if (errno == ENOTSOCK) {
3884 swrap_remove_stale(fd);
3885 return -ENOTSOCK;
3886 } else {
3887 SWRAP_LOG(SWRAP_LOG_ERROR,
3888 "swrap_recvmsg_before failed");
3889 return -1;
3893 break;
3894 default:
3895 errno = EHOSTUNREACH;
3896 return -1;
3899 return 0;
3902 static int swrap_recvmsg_after(int fd,
3903 struct socket_info *si,
3904 struct msghdr *msg,
3905 const struct sockaddr_un *un_addr,
3906 socklen_t un_addrlen,
3907 ssize_t ret)
3909 int saved_errno = errno;
3910 size_t i;
3911 uint8_t *buf = NULL;
3912 off_t ofs = 0;
3913 size_t avail = 0;
3914 size_t remain;
3915 int rc;
3917 /* to give better errors */
3918 if (ret == -1) {
3919 if (saved_errno == ENOENT) {
3920 saved_errno = EHOSTUNREACH;
3921 } else if (saved_errno == ENOTSOCK) {
3922 /* If the fd is not a socket, remove it */
3923 swrap_remove_stale(fd);
3927 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3928 avail += msg->msg_iov[i].iov_len;
3931 if (avail == 0) {
3932 rc = 0;
3933 goto done;
3936 if (ret == -1) {
3937 remain = MIN(80, avail);
3938 } else {
3939 remain = ret;
3942 /* we capture it as one single packet */
3943 buf = (uint8_t *)malloc(remain);
3944 if (buf == NULL) {
3945 /* we just not capture the packet */
3946 errno = saved_errno;
3947 return -1;
3950 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3951 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3952 memcpy(buf + ofs,
3953 msg->msg_iov[i].iov_base,
3954 this_time);
3955 ofs += this_time;
3956 remain -= this_time;
3959 switch (si->type) {
3960 case SOCK_STREAM:
3961 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3962 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3963 } else if (ret == 0) { /* END OF FILE */
3964 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3965 } else if (ret > 0) {
3966 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3968 break;
3970 case SOCK_DGRAM:
3971 if (ret == -1) {
3972 break;
3975 if (un_addr != NULL) {
3976 rc = sockaddr_convert_from_un(si,
3977 un_addr,
3978 un_addrlen,
3979 si->family,
3980 msg->msg_name,
3981 &msg->msg_namelen);
3982 if (rc == -1) {
3983 goto done;
3986 swrap_dump_packet(si,
3987 msg->msg_name,
3988 SWRAP_RECVFROM,
3989 buf,
3990 ret);
3991 } else {
3992 swrap_dump_packet(si,
3993 msg->msg_name,
3994 SWRAP_RECV,
3995 buf,
3996 ret);
3999 break;
4002 rc = 0;
4003 done:
4004 free(buf);
4005 errno = saved_errno;
4007 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4008 if (rc == 0 &&
4009 msg->msg_controllen > 0 &&
4010 msg->msg_control != NULL) {
4011 rc = swrap_msghdr_add_socket_info(si, msg);
4012 if (rc < 0) {
4013 return -1;
4016 #endif
4018 return rc;
4021 /****************************************************************************
4022 * RECVFROM
4023 ***************************************************************************/
4025 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4026 struct sockaddr *from, socklen_t *fromlen)
4028 struct sockaddr_un from_addr;
4029 socklen_t from_addrlen = sizeof(from_addr);
4030 ssize_t ret;
4031 struct socket_info *si = find_socket_info(s);
4032 struct sockaddr_storage ss;
4033 socklen_t ss_len = sizeof(ss);
4034 struct msghdr msg;
4035 struct iovec tmp;
4036 int tret;
4038 if (!si) {
4039 return libc_recvfrom(s,
4040 buf,
4041 len,
4042 flags,
4043 from,
4044 fromlen);
4047 tmp.iov_base = buf;
4048 tmp.iov_len = len;
4050 ZERO_STRUCT(msg);
4051 if (from != NULL && fromlen != NULL) {
4052 msg.msg_name = from; /* optional address */
4053 msg.msg_namelen = *fromlen; /* size of address */
4054 } else {
4055 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4056 msg.msg_namelen = ss_len; /* size of address */
4058 msg.msg_iov = &tmp; /* scatter/gather array */
4059 msg.msg_iovlen = 1; /* # elements in msg_iov */
4060 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4061 msg.msg_control = NULL; /* ancillary data, see below */
4062 msg.msg_controllen = 0; /* ancillary data buffer len */
4063 msg.msg_flags = 0; /* flags on received message */
4064 #endif
4066 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4067 if (tret < 0) {
4068 return -1;
4071 buf = msg.msg_iov[0].iov_base;
4072 len = msg.msg_iov[0].iov_len;
4074 /* irix 6.4 forgets to null terminate the sun_path string :-( */
4075 memset(&from_addr, 0, sizeof(from_addr));
4076 ret = libc_recvfrom(s,
4077 buf,
4078 len,
4079 flags,
4080 (struct sockaddr *)(void *)&from_addr,
4081 &from_addrlen);
4082 if (ret == -1) {
4083 return ret;
4086 tret = swrap_recvmsg_after(s,
4088 &msg,
4089 &from_addr,
4090 from_addrlen,
4091 ret);
4092 if (tret != 0) {
4093 return tret;
4096 if (from != NULL && fromlen != NULL) {
4097 *fromlen = msg.msg_namelen;
4100 return ret;
4103 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4104 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4105 struct sockaddr *from, Psocklen_t fromlen)
4106 #else
4107 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4108 struct sockaddr *from, socklen_t *fromlen)
4109 #endif
4111 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4114 /****************************************************************************
4115 * SENDTO
4116 ***************************************************************************/
4118 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4119 const struct sockaddr *to, socklen_t tolen)
4121 struct msghdr msg;
4122 struct iovec tmp;
4123 struct sockaddr_un un_addr;
4124 const struct sockaddr_un *to_un = NULL;
4125 ssize_t ret;
4126 int rc;
4127 struct socket_info *si = find_socket_info(s);
4128 int bcast = 0;
4130 if (!si) {
4131 return libc_sendto(s, buf, len, flags, to, tolen);
4134 tmp.iov_base = discard_const_p(char, buf);
4135 tmp.iov_len = len;
4137 ZERO_STRUCT(msg);
4138 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4139 msg.msg_namelen = tolen; /* size of address */
4140 msg.msg_iov = &tmp; /* scatter/gather array */
4141 msg.msg_iovlen = 1; /* # elements in msg_iov */
4142 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4143 msg.msg_control = NULL; /* ancillary data, see below */
4144 msg.msg_controllen = 0; /* ancillary data buffer len */
4145 msg.msg_flags = 0; /* flags on received message */
4146 #endif
4148 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4149 if (rc < 0) {
4150 return -1;
4153 buf = msg.msg_iov[0].iov_base;
4154 len = msg.msg_iov[0].iov_len;
4156 if (bcast) {
4157 struct stat st;
4158 unsigned int iface;
4159 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4160 char type;
4162 type = SOCKET_TYPE_CHAR_UDP;
4164 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4165 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4166 socket_wrapper_dir(), type, iface, prt);
4167 if (stat(un_addr.sun_path, &st) != 0) continue;
4169 /* ignore the any errors in broadcast sends */
4170 libc_sendto(s,
4171 buf,
4172 len,
4173 flags,
4174 (struct sockaddr *)(void *)&un_addr,
4175 sizeof(un_addr));
4178 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4180 return len;
4183 ret = libc_sendto(s,
4184 buf,
4185 len,
4186 flags,
4187 (struct sockaddr *)msg.msg_name,
4188 msg.msg_namelen);
4190 swrap_sendmsg_after(s, si, &msg, to, ret);
4192 return ret;
4195 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4196 const struct sockaddr *to, socklen_t tolen)
4198 return swrap_sendto(s, buf, len, flags, to, tolen);
4201 /****************************************************************************
4202 * READV
4203 ***************************************************************************/
4205 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4207 struct socket_info *si;
4208 struct msghdr msg;
4209 struct sockaddr_storage ss;
4210 socklen_t ss_len = sizeof(ss);
4211 struct iovec tmp;
4212 ssize_t ret;
4213 int tret;
4215 si = find_socket_info(s);
4216 if (si == NULL) {
4217 return libc_recv(s, buf, len, flags);
4220 tmp.iov_base = buf;
4221 tmp.iov_len = len;
4223 ZERO_STRUCT(msg);
4224 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4225 msg.msg_namelen = ss_len; /* size of address */
4226 msg.msg_iov = &tmp; /* scatter/gather array */
4227 msg.msg_iovlen = 1; /* # elements in msg_iov */
4228 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4229 msg.msg_control = NULL; /* ancillary data, see below */
4230 msg.msg_controllen = 0; /* ancillary data buffer len */
4231 msg.msg_flags = 0; /* flags on received message */
4232 #endif
4234 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4235 if (tret < 0) {
4236 return -1;
4239 buf = msg.msg_iov[0].iov_base;
4240 len = msg.msg_iov[0].iov_len;
4242 ret = libc_recv(s, buf, len, flags);
4244 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4245 if (tret != 0) {
4246 return tret;
4249 return ret;
4252 ssize_t recv(int s, void *buf, size_t len, int flags)
4254 return swrap_recv(s, buf, len, flags);
4257 /****************************************************************************
4258 * READ
4259 ***************************************************************************/
4261 static ssize_t swrap_read(int s, void *buf, size_t len)
4263 struct socket_info *si;
4264 struct msghdr msg;
4265 struct iovec tmp;
4266 struct sockaddr_storage ss;
4267 socklen_t ss_len = sizeof(ss);
4268 ssize_t ret;
4269 int tret;
4271 si = find_socket_info(s);
4272 if (si == NULL) {
4273 return libc_read(s, buf, len);
4276 tmp.iov_base = buf;
4277 tmp.iov_len = len;
4279 ZERO_STRUCT(msg);
4280 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4281 msg.msg_namelen = ss_len; /* size of address */
4282 msg.msg_iov = &tmp; /* scatter/gather array */
4283 msg.msg_iovlen = 1; /* # elements in msg_iov */
4284 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4285 msg.msg_control = NULL; /* ancillary data, see below */
4286 msg.msg_controllen = 0; /* ancillary data buffer len */
4287 msg.msg_flags = 0; /* flags on received message */
4288 #endif
4290 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4291 if (tret < 0) {
4292 if (tret == -ENOTSOCK) {
4293 return libc_read(s, buf, len);
4295 return -1;
4298 buf = msg.msg_iov[0].iov_base;
4299 len = msg.msg_iov[0].iov_len;
4301 ret = libc_read(s, buf, len);
4303 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4304 if (tret != 0) {
4305 return tret;
4308 return ret;
4311 ssize_t read(int s, void *buf, size_t len)
4313 return swrap_read(s, buf, len);
4316 /****************************************************************************
4317 * SEND
4318 ***************************************************************************/
4320 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4322 struct msghdr msg;
4323 struct iovec tmp;
4324 struct sockaddr_un un_addr;
4325 ssize_t ret;
4326 int rc;
4327 struct socket_info *si = find_socket_info(s);
4329 if (!si) {
4330 return libc_send(s, buf, len, flags);
4333 tmp.iov_base = discard_const_p(char, buf);
4334 tmp.iov_len = len;
4336 ZERO_STRUCT(msg);
4337 msg.msg_name = NULL; /* optional address */
4338 msg.msg_namelen = 0; /* size of address */
4339 msg.msg_iov = &tmp; /* scatter/gather array */
4340 msg.msg_iovlen = 1; /* # elements in msg_iov */
4341 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4342 msg.msg_control = NULL; /* ancillary data, see below */
4343 msg.msg_controllen = 0; /* ancillary data buffer len */
4344 msg.msg_flags = 0; /* flags on received message */
4345 #endif
4347 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4348 if (rc < 0) {
4349 return -1;
4352 buf = msg.msg_iov[0].iov_base;
4353 len = msg.msg_iov[0].iov_len;
4355 ret = libc_send(s, buf, len, flags);
4357 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4359 return ret;
4362 ssize_t send(int s, const void *buf, size_t len, int flags)
4364 return swrap_send(s, buf, len, flags);
4367 /****************************************************************************
4368 * RECVMSG
4369 ***************************************************************************/
4371 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4373 struct sockaddr_un from_addr;
4374 socklen_t from_addrlen = sizeof(from_addr);
4375 struct socket_info *si;
4376 struct msghdr msg;
4377 struct iovec tmp;
4378 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4379 size_t msg_ctrllen_filled;
4380 size_t msg_ctrllen_left;
4381 #endif
4383 ssize_t ret;
4384 int rc;
4386 si = find_socket_info(s);
4387 if (si == NULL) {
4388 return libc_recvmsg(s, omsg, flags);
4391 tmp.iov_base = NULL;
4392 tmp.iov_len = 0;
4394 ZERO_STRUCT(msg);
4395 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
4396 msg.msg_namelen = from_addrlen; /* size of address */
4397 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4398 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4399 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4400 msg_ctrllen_filled = 0;
4401 msg_ctrllen_left = omsg->msg_controllen;
4403 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4404 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_recvmsg_before(s, si, &msg, &tmp);
4409 if (rc < 0) {
4410 return -1;
4413 ret = libc_recvmsg(s, &msg, flags);
4415 msg.msg_name = omsg->msg_name;
4416 msg.msg_namelen = omsg->msg_namelen;
4418 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4419 msg_ctrllen_filled += msg.msg_controllen;
4420 msg_ctrllen_left -= msg.msg_controllen;
4422 if (omsg->msg_control != NULL) {
4423 uint8_t *p;
4425 p = omsg->msg_control;
4426 p += msg_ctrllen_filled;
4428 msg.msg_control = p;
4429 msg.msg_controllen = msg_ctrllen_left;
4430 } else {
4431 msg.msg_control = NULL;
4432 msg.msg_controllen = 0;
4434 #endif
4436 rc = swrap_recvmsg_after(s, si, &msg, &from_addr, from_addrlen, ret);
4437 if (rc != 0) {
4438 return rc;
4441 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4442 if (omsg->msg_control != NULL) {
4443 /* msg.msg_controllen = space left */
4444 msg_ctrllen_left = msg.msg_controllen;
4445 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4448 /* Update the original message length */
4449 omsg->msg_controllen = msg_ctrllen_filled;
4450 omsg->msg_flags = msg.msg_flags;
4451 #endif
4452 omsg->msg_iovlen = msg.msg_iovlen;
4454 return ret;
4457 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4459 return swrap_recvmsg(sockfd, msg, flags);
4462 /****************************************************************************
4463 * SENDMSG
4464 ***************************************************************************/
4466 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4468 struct msghdr msg;
4469 struct iovec tmp;
4470 struct sockaddr_un un_addr;
4471 const struct sockaddr_un *to_un = NULL;
4472 const struct sockaddr *to = NULL;
4473 ssize_t ret;
4474 int rc;
4475 struct socket_info *si = find_socket_info(s);
4476 int bcast = 0;
4478 if (!si) {
4479 return libc_sendmsg(s, omsg, flags);
4482 ZERO_STRUCT(un_addr);
4484 tmp.iov_base = NULL;
4485 tmp.iov_len = 0;
4487 ZERO_STRUCT(msg);
4488 msg.msg_name = omsg->msg_name; /* optional address */
4489 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4490 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4491 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4492 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4493 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4494 /* omsg is a const so use a local buffer for modifications */
4495 uint8_t cmbuf[omsg->msg_controllen];
4497 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4499 msg.msg_control = cmbuf; /* ancillary data, see below */
4500 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4502 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4503 #endif
4505 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4506 if (rc < 0) {
4507 return -1;
4510 if (bcast) {
4511 struct stat st;
4512 unsigned int iface;
4513 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4514 char type;
4515 size_t i, len = 0;
4516 uint8_t *buf;
4517 off_t ofs = 0;
4518 size_t avail = 0;
4519 size_t remain;
4521 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4522 avail += msg.msg_iov[i].iov_len;
4525 len = avail;
4526 remain = avail;
4528 /* we capture it as one single packet */
4529 buf = (uint8_t *)malloc(remain);
4530 if (!buf) {
4531 return -1;
4534 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4535 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4536 memcpy(buf + ofs,
4537 msg.msg_iov[i].iov_base,
4538 this_time);
4539 ofs += this_time;
4540 remain -= this_time;
4543 type = SOCKET_TYPE_CHAR_UDP;
4545 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4546 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4547 socket_wrapper_dir(), type, iface, prt);
4548 if (stat(un_addr.sun_path, &st) != 0) continue;
4550 msg.msg_name = &un_addr; /* optional address */
4551 msg.msg_namelen = sizeof(un_addr); /* size of address */
4553 /* ignore the any errors in broadcast sends */
4554 libc_sendmsg(s, &msg, flags);
4557 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4558 free(buf);
4560 return len;
4563 ret = libc_sendmsg(s, &msg, flags);
4565 swrap_sendmsg_after(s, si, &msg, to, ret);
4567 return ret;
4570 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4572 return swrap_sendmsg(s, omsg, flags);
4575 /****************************************************************************
4576 * READV
4577 ***************************************************************************/
4579 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4581 struct socket_info *si;
4582 struct msghdr msg;
4583 struct iovec tmp;
4584 struct sockaddr_storage ss;
4585 socklen_t ss_len = sizeof(ss);
4586 ssize_t ret;
4587 int rc;
4589 si = find_socket_info(s);
4590 if (si == NULL) {
4591 return libc_readv(s, vector, count);
4594 tmp.iov_base = NULL;
4595 tmp.iov_len = 0;
4597 ZERO_STRUCT(msg);
4598 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4599 msg.msg_namelen = ss_len; /* size of address */
4600 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4601 msg.msg_iovlen = count; /* # elements in msg_iov */
4602 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4603 msg.msg_control = NULL; /* ancillary data, see below */
4604 msg.msg_controllen = 0; /* ancillary data buffer len */
4605 msg.msg_flags = 0; /* flags on received message */
4606 #endif
4608 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4609 if (rc < 0) {
4610 if (rc == -ENOTSOCK) {
4611 return libc_readv(s, vector, count);
4613 return -1;
4616 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4618 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4619 if (rc != 0) {
4620 return rc;
4623 return ret;
4626 ssize_t readv(int s, const struct iovec *vector, int count)
4628 return swrap_readv(s, vector, count);
4631 /****************************************************************************
4632 * WRITEV
4633 ***************************************************************************/
4635 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4637 struct msghdr msg;
4638 struct iovec tmp;
4639 struct sockaddr_un un_addr;
4640 ssize_t ret;
4641 int rc;
4642 struct socket_info *si = find_socket_info(s);
4644 if (!si) {
4645 return libc_writev(s, vector, count);
4648 tmp.iov_base = NULL;
4649 tmp.iov_len = 0;
4651 ZERO_STRUCT(msg);
4652 msg.msg_name = NULL; /* optional address */
4653 msg.msg_namelen = 0; /* size of address */
4654 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4655 msg.msg_iovlen = count; /* # elements in msg_iov */
4656 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4657 msg.msg_control = NULL; /* ancillary data, see below */
4658 msg.msg_controllen = 0; /* ancillary data buffer len */
4659 msg.msg_flags = 0; /* flags on received message */
4660 #endif
4662 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4663 if (rc < 0) {
4664 if (rc == -ENOTSOCK) {
4665 return libc_readv(s, vector, count);
4667 return -1;
4670 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4672 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4674 return ret;
4677 ssize_t writev(int s, const struct iovec *vector, int count)
4679 return swrap_writev(s, vector, count);
4682 /****************************
4683 * CLOSE
4684 ***************************/
4686 static int swrap_close(int fd)
4688 struct socket_info *si = find_socket_info(fd);
4689 struct socket_info_fd *fi;
4690 int ret;
4692 if (!si) {
4693 return libc_close(fd);
4696 for (fi = si->fds; fi; fi = fi->next) {
4697 if (fi->fd == fd) {
4698 SWRAP_DLIST_REMOVE(si->fds, fi);
4699 free(fi);
4700 break;
4704 if (si->fds) {
4705 /* there are still references left */
4706 return libc_close(fd);
4709 SWRAP_DLIST_REMOVE(sockets, si);
4711 if (si->myname && si->peername) {
4712 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4715 ret = libc_close(fd);
4717 if (si->myname && si->peername) {
4718 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4719 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4722 if (si->bindname != NULL) {
4723 free(si->bindname);
4726 if (si->myname) free(si->myname);
4727 if (si->peername) free(si->peername);
4728 if (si->tmp_path) {
4729 unlink(si->tmp_path);
4730 free(si->tmp_path);
4732 free(si);
4734 return ret;
4737 int close(int fd)
4739 return swrap_close(fd);
4742 /****************************
4743 * DUP
4744 ***************************/
4746 static int swrap_dup(int fd)
4748 struct socket_info *si;
4749 struct socket_info_fd *fi;
4751 si = find_socket_info(fd);
4753 if (!si) {
4754 return libc_dup(fd);
4757 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4758 if (fi == NULL) {
4759 errno = ENOMEM;
4760 return -1;
4763 fi->fd = libc_dup(fd);
4764 if (fi->fd == -1) {
4765 int saved_errno = errno;
4766 free(fi);
4767 errno = saved_errno;
4768 return -1;
4771 /* Make sure we don't have an entry for the fd */
4772 swrap_remove_stale(fi->fd);
4774 SWRAP_DLIST_ADD(si->fds, fi);
4775 return fi->fd;
4778 int dup(int fd)
4780 return swrap_dup(fd);
4783 /****************************
4784 * DUP2
4785 ***************************/
4787 static int swrap_dup2(int fd, int newfd)
4789 struct socket_info *si;
4790 struct socket_info_fd *fi;
4792 si = find_socket_info(fd);
4794 if (!si) {
4795 return libc_dup2(fd, newfd);
4798 if (find_socket_info(newfd)) {
4799 /* dup2() does an implicit close of newfd, which we
4800 * need to emulate */
4801 swrap_close(newfd);
4804 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4805 if (fi == NULL) {
4806 errno = ENOMEM;
4807 return -1;
4810 fi->fd = libc_dup2(fd, newfd);
4811 if (fi->fd == -1) {
4812 int saved_errno = errno;
4813 free(fi);
4814 errno = saved_errno;
4815 return -1;
4818 /* Make sure we don't have an entry for the fd */
4819 swrap_remove_stale(fi->fd);
4821 SWRAP_DLIST_ADD(si->fds, fi);
4822 return fi->fd;
4825 int dup2(int fd, int newfd)
4827 return swrap_dup2(fd, newfd);
4830 /****************************
4831 * DUP2
4832 ***************************/
4834 #ifdef HAVE_EVENTFD
4835 static int swrap_eventfd(int count, int flags)
4837 int fd;
4839 fd = libc_eventfd(count, flags);
4840 if (fd != -1) {
4841 swrap_remove_stale(fd);
4844 return fd;
4847 int eventfd(int count, int flags)
4849 return swrap_eventfd(count, flags);
4851 #endif
4853 /****************************
4854 * DESTRUCTOR
4855 ***************************/
4858 * This function is called when the library is unloaded and makes sure that
4859 * sockets get closed and the unix file for the socket are unlinked.
4861 void swrap_destructor(void)
4863 struct socket_info *s = sockets;
4865 while (s != NULL) {
4866 struct socket_info_fd *f = s->fds;
4867 if (f != NULL) {
4868 swrap_close(f->fd);
4870 s = sockets;