swrap: implement check_addr_port_in_use()
[Samba/wip.git] / lib / socket_wrapper / socket_wrapper.c
blob477f1159715e8f2fdd7b5b233782f85603e77442
1 /*
2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
40 is set.
43 #include "config.h"
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
52 #endif
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
55 #endif
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
58 #endif
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
61 #endif
62 #include <sys/uio.h>
63 #include <errno.h>
64 #include <sys/un.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
68 #include <fcntl.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <stdio.h>
72 #include <stdint.h>
73 #include <stdarg.h>
74 #include <stdbool.h>
75 #include <unistd.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
78 #endif
79 #ifdef HAVE_RPC_RPC_H
80 #include <rpc/rpc.h>
81 #endif
83 enum swrap_dbglvl_e {
84 SWRAP_LOG_ERROR = 0,
85 SWRAP_LOG_WARN,
86 SWRAP_LOG_DEBUG,
87 SWRAP_LOG_TRACE
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
93 #else
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
99 #else
100 #define DESTRUCTOR_ATTRIBUTE
101 #endif
103 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
105 #else
106 # define SWRAP_THREAD
107 #endif
109 #ifndef MIN
110 #define MIN(a,b) ((a)<(b)?(a):(b))
111 #endif
113 #ifndef ZERO_STRUCT
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
115 #endif
117 #ifndef ZERO_STRUCTP
118 #define ZERO_STRUCTP(x) do { \
119 if ((x) != NULL) \
120 memset((char *)(x), 0, sizeof(*(x))); \
121 } while(0)
122 #endif
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
126 #endif
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
130 #endif
132 #ifdef IPV6_PKTINFO
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
143 #ifndef IP_PKTINFO
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
146 # endif
147 #endif
150 #define SWRAP_DLIST_ADD(list,item) do { \
151 if (!(list)) { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
154 (list) = (item); \
155 } else { \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
159 (list) = (item); \
161 } while (0)
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
166 if (list) { \
167 (list)->prev = NULL; \
169 } else { \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
179 } while (0)
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
183 #else
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
185 #endif
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct socket_info_fd {
214 struct socket_info_fd *prev, *next;
215 int fd;
218 struct socket_info
220 struct socket_info_fd *fds;
222 int family;
223 int type;
224 int protocol;
225 int bound;
226 int bcast;
227 int is_server;
228 int connected;
229 int defer_connect;
230 int pktinfo;
232 char *tmp_path;
234 struct sockaddr *bindname;
235 socklen_t bindname_len;
237 struct sockaddr *myname;
238 socklen_t myname_len;
240 struct sockaddr *peername;
241 socklen_t peername_len;
243 struct {
244 unsigned long pck_snd;
245 unsigned long pck_rcv;
246 } io;
248 struct socket_info *prev, *next;
252 * File descriptors are shared between threads so we should share socket
253 * information too.
255 struct socket_info *sockets;
257 /* Function prototypes */
259 bool socket_wrapper_enabled(void);
260 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
262 #ifdef NDEBUG
263 # define SWRAP_LOG(...)
264 #else
266 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
267 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
269 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
271 char buffer[1024];
272 va_list va;
273 const char *d;
274 unsigned int lvl = 0;
276 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
277 if (d != NULL) {
278 lvl = atoi(d);
281 va_start(va, format);
282 vsnprintf(buffer, sizeof(buffer), format, va);
283 va_end(va);
285 if (lvl >= dbglvl) {
286 switch (dbglvl) {
287 case SWRAP_LOG_ERROR:
288 fprintf(stderr,
289 "SWRAP_ERROR(%d): %s\n",
290 (int)getpid(), buffer);
291 break;
292 case SWRAP_LOG_WARN:
293 fprintf(stderr,
294 "SWRAP_WARN(%d): %s\n",
295 (int)getpid(), buffer);
296 break;
297 case SWRAP_LOG_DEBUG:
298 fprintf(stderr,
299 "SWRAP_DEBUG(%d): %s\n",
300 (int)getpid(), buffer);
301 break;
302 case SWRAP_LOG_TRACE:
303 fprintf(stderr,
304 "SWRAP_TRACE(%d): %s\n",
305 (int)getpid(), buffer);
306 break;
310 #endif
312 /*********************************************************
313 * SWRAP LOADING LIBC FUNCTIONS
314 *********************************************************/
316 #include <dlfcn.h>
318 struct swrap_libc_fns {
319 int (*libc_accept)(int sockfd,
320 struct sockaddr *addr,
321 socklen_t *addrlen);
322 int (*libc_bind)(int sockfd,
323 const struct sockaddr *addr,
324 socklen_t addrlen);
325 int (*libc_close)(int fd);
326 int (*libc_connect)(int sockfd,
327 const struct sockaddr *addr,
328 socklen_t addrlen);
329 int (*libc_dup)(int fd);
330 int (*libc_dup2)(int oldfd, int newfd);
331 #ifdef HAVE_EVENTFD
332 int (*libc_eventfd)(int count, int flags);
333 #endif
334 int (*libc_getpeername)(int sockfd,
335 struct sockaddr *addr,
336 socklen_t *addrlen);
337 int (*libc_getsockname)(int sockfd,
338 struct sockaddr *addr,
339 socklen_t *addrlen);
340 int (*libc_getsockopt)(int sockfd,
341 int level,
342 int optname,
343 void *optval,
344 socklen_t *optlen);
345 int (*libc_ioctl)(int d, unsigned long int request, ...);
346 int (*libc_listen)(int sockfd, int backlog);
347 int (*libc_open)(const char *pathname, int flags, mode_t mode);
348 int (*libc_pipe)(int pipefd[2]);
349 int (*libc_read)(int fd, void *buf, size_t count);
350 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
351 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
352 int (*libc_recvfrom)(int sockfd,
353 void *buf,
354 size_t len,
355 int flags,
356 struct sockaddr *src_addr,
357 socklen_t *addrlen);
358 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
359 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
360 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
361 int (*libc_sendto)(int sockfd,
362 const void *buf,
363 size_t len,
364 int flags,
365 const struct sockaddr *dst_addr,
366 socklen_t addrlen);
367 int (*libc_setsockopt)(int sockfd,
368 int level,
369 int optname,
370 const void *optval,
371 socklen_t optlen);
372 #ifdef HAVE_SIGNALFD
373 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
374 #endif
375 int (*libc_socket)(int domain, int type, int protocol);
376 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
377 #ifdef HAVE_TIMERFD_CREATE
378 int (*libc_timerfd_create)(int clockid, int flags);
379 #endif
380 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
383 struct swrap {
384 void *libc_handle;
385 void *libsocket_handle;
387 bool initialised;
388 bool enabled;
390 char *socket_dir;
392 struct swrap_libc_fns fns;
395 static struct swrap swrap;
397 /* prototypes */
398 static const char *socket_wrapper_dir(void);
400 #define LIBC_NAME "libc.so"
402 enum swrap_lib {
403 SWRAP_LIBC,
404 SWRAP_LIBNSL,
405 SWRAP_LIBSOCKET,
408 #ifndef NDEBUG
409 static const char *swrap_str_lib(enum swrap_lib lib)
411 switch (lib) {
412 case SWRAP_LIBC:
413 return "libc";
414 case SWRAP_LIBNSL:
415 return "libnsl";
416 case SWRAP_LIBSOCKET:
417 return "libsocket";
420 /* Compiler would warn us about unhandled enum value if we get here */
421 return "unknown";
423 #endif
425 static void *swrap_load_lib_handle(enum swrap_lib lib)
427 int flags = RTLD_LAZY;
428 void *handle = NULL;
429 int i;
431 #ifdef RTLD_DEEPBIND
432 flags |= RTLD_DEEPBIND;
433 #endif
435 switch (lib) {
436 case SWRAP_LIBNSL:
437 /* FALL TROUGH */
438 case SWRAP_LIBSOCKET:
439 #ifdef HAVE_LIBSOCKET
440 handle = swrap.libsocket_handle;
441 if (handle == NULL) {
442 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
443 char soname[256] = {0};
445 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
446 handle = dlopen(soname, flags);
449 swrap.libsocket_handle = handle;
451 break;
452 #endif
453 /* FALL TROUGH */
454 case SWRAP_LIBC:
455 handle = swrap.libc_handle;
456 #ifdef LIBC_SO
457 if (handle == NULL) {
458 handle = dlopen(LIBC_SO, flags);
460 swrap.libc_handle = handle;
462 #endif
463 if (handle == NULL) {
464 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
465 char soname[256] = {0};
467 snprintf(soname, sizeof(soname), "libc.so.%d", i);
468 handle = dlopen(soname, flags);
471 swrap.libc_handle = handle;
473 break;
476 if (handle == NULL) {
477 #ifdef RTLD_NEXT
478 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
479 #else
480 SWRAP_LOG(SWRAP_LOG_ERROR,
481 "Failed to dlopen library: %s\n",
482 dlerror());
483 exit(-1);
484 #endif
487 return handle;
490 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
492 void *handle;
493 void *func;
495 handle = swrap_load_lib_handle(lib);
497 func = dlsym(handle, fn_name);
498 if (func == NULL) {
499 SWRAP_LOG(SWRAP_LOG_ERROR,
500 "Failed to find %s: %s\n",
501 fn_name, dlerror());
502 exit(-1);
505 SWRAP_LOG(SWRAP_LOG_TRACE,
506 "Loaded %s from %s",
507 fn_name, swrap_str_lib(lib));
508 return func;
511 #define swrap_load_lib_function(lib, fn_name) \
512 if (swrap.fns.libc_##fn_name == NULL) { \
513 *(void **) (&swrap.fns.libc_##fn_name) = \
514 _swrap_load_lib_function(lib, #fn_name); \
519 * IMPORTANT
521 * Functions especially from libc need to be loaded individually, you can't load
522 * all at once or gdb will segfault at startup. The same applies to valgrind and
523 * has probably something todo with with the linker.
524 * So we need load each function at the point it is called the first time.
526 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
528 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
530 return swrap.fns.libc_accept(sockfd, addr, addrlen);
533 static int libc_bind(int sockfd,
534 const struct sockaddr *addr,
535 socklen_t addrlen)
537 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
539 return swrap.fns.libc_bind(sockfd, addr, addrlen);
542 static int libc_close(int fd)
544 swrap_load_lib_function(SWRAP_LIBC, close);
546 return swrap.fns.libc_close(fd);
549 static int libc_connect(int sockfd,
550 const struct sockaddr *addr,
551 socklen_t addrlen)
553 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
555 return swrap.fns.libc_connect(sockfd, addr, addrlen);
558 static int libc_dup(int fd)
560 swrap_load_lib_function(SWRAP_LIBC, dup);
562 return swrap.fns.libc_dup(fd);
565 static int libc_dup2(int oldfd, int newfd)
567 swrap_load_lib_function(SWRAP_LIBC, dup2);
569 return swrap.fns.libc_dup2(oldfd, newfd);
572 #ifdef HAVE_EVENTFD
573 static int libc_eventfd(int count, int flags)
575 swrap_load_lib_function(SWRAP_LIBC, eventfd);
577 return swrap.fns.libc_eventfd(count, flags);
579 #endif
581 static int libc_getpeername(int sockfd,
582 struct sockaddr *addr,
583 socklen_t *addrlen)
585 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
587 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
590 static int libc_getsockname(int sockfd,
591 struct sockaddr *addr,
592 socklen_t *addrlen)
594 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
596 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
599 static int libc_getsockopt(int sockfd,
600 int level,
601 int optname,
602 void *optval,
603 socklen_t *optlen)
605 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
607 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
610 static int libc_vioctl(int d, unsigned long int request, va_list ap)
612 long int args[4];
613 int rc;
614 int i;
616 swrap_load_lib_function(SWRAP_LIBC, ioctl);
618 for (i = 0; i < 4; i++) {
619 args[i] = va_arg(ap, long int);
622 rc = swrap.fns.libc_ioctl(d,
623 request,
624 args[0],
625 args[1],
626 args[2],
627 args[3]);
629 return rc;
632 static int libc_listen(int sockfd, int backlog)
634 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
636 return swrap.fns.libc_listen(sockfd, backlog);
639 static int libc_vopen(const char *pathname, int flags, va_list ap)
641 long int mode = 0;
642 int fd;
644 swrap_load_lib_function(SWRAP_LIBC, open);
646 mode = va_arg(ap, long int);
648 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
650 return fd;
653 static int libc_open(const char *pathname, int flags, ...)
655 va_list ap;
656 int fd;
658 va_start(ap, flags);
659 fd = libc_vopen(pathname, flags, ap);
660 va_end(ap);
662 return fd;
665 static int libc_pipe(int pipefd[2])
667 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
669 return swrap.fns.libc_pipe(pipefd);
672 static int libc_read(int fd, void *buf, size_t count)
674 swrap_load_lib_function(SWRAP_LIBC, read);
676 return swrap.fns.libc_read(fd, buf, count);
679 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
681 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
683 return swrap.fns.libc_readv(fd, iov, iovcnt);
686 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
688 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
690 return swrap.fns.libc_recv(sockfd, buf, len, flags);
693 static int libc_recvfrom(int sockfd,
694 void *buf,
695 size_t len,
696 int flags,
697 struct sockaddr *src_addr,
698 socklen_t *addrlen)
700 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
702 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
705 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
707 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
709 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
712 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
714 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
716 return swrap.fns.libc_send(sockfd, buf, len, flags);
719 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
721 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
723 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
726 static int libc_sendto(int sockfd,
727 const void *buf,
728 size_t len,
729 int flags,
730 const struct sockaddr *dst_addr,
731 socklen_t addrlen)
733 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
735 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
738 static int libc_setsockopt(int sockfd,
739 int level,
740 int optname,
741 const void *optval,
742 socklen_t optlen)
744 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
746 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
749 #ifdef HAVE_SIGNALFD
750 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
752 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
754 return swrap.fns.libc_signalfd(fd, mask, flags);
756 #endif
758 static int libc_socket(int domain, int type, int protocol)
760 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
762 return swrap.fns.libc_socket(domain, type, protocol);
765 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
767 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
769 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
772 #ifdef HAVE_TIMERFD_CREATE
773 static int libc_timerfd_create(int clockid, int flags)
775 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
777 return swrap.fns.libc_timerfd_create(clockid, flags);
779 #endif
781 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
783 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
785 return swrap.fns.libc_writev(fd, iov, iovcnt);
788 /*********************************************************
789 * SWRAP HELPER FUNCTIONS
790 *********************************************************/
792 #ifdef HAVE_IPV6
794 * FD00::5357:5FXX
796 static const struct in6_addr *swrap_ipv6(void)
798 static struct in6_addr v;
799 static int initialized;
800 int ret;
802 if (initialized) {
803 return &v;
805 initialized = 1;
807 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
808 if (ret <= 0) {
809 abort();
812 return &v;
814 #endif
816 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
818 struct sockaddr *ret = (struct sockaddr *)malloc(len);
819 memcpy(ret, data, len);
820 return ret;
823 static void set_port(int family, int prt, struct sockaddr *addr)
825 switch (family) {
826 case AF_INET:
827 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
828 break;
829 #ifdef HAVE_IPV6
830 case AF_INET6:
831 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
832 break;
833 #endif
837 static size_t socket_length(int family)
839 switch (family) {
840 case AF_INET:
841 return sizeof(struct sockaddr_in);
842 #ifdef HAVE_IPV6
843 case AF_INET6:
844 return sizeof(struct sockaddr_in6);
845 #endif
847 return 0;
850 static const char *socket_wrapper_dir(void)
852 const char *s = getenv("SOCKET_WRAPPER_DIR");
853 if (s == NULL) {
854 return NULL;
856 /* TODO use realpath(3) here, when we add support for threads */
857 if (strncmp(s, "./", 2) == 0) {
858 s += 2;
861 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
862 return s;
865 bool socket_wrapper_enabled(void)
867 const char *s = socket_wrapper_dir();
869 return s != NULL ? true : false;
872 static unsigned int socket_wrapper_default_iface(void)
874 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
875 if (s) {
876 unsigned int iface;
877 if (sscanf(s, "%u", &iface) == 1) {
878 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
879 return iface;
884 return 1;/* 127.0.0.1 */
887 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
889 unsigned int iface;
890 unsigned int prt;
891 const char *p;
892 char type;
894 p = strrchr(un->sun_path, '/');
895 if (p) p++; else p = un->sun_path;
897 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
898 errno = EINVAL;
899 return -1;
902 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
903 type, iface, prt);
905 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
906 errno = EINVAL;
907 return -1;
910 if (prt > 0xFFFF) {
911 errno = EINVAL;
912 return -1;
915 switch(type) {
916 case SOCKET_TYPE_CHAR_TCP:
917 case SOCKET_TYPE_CHAR_UDP: {
918 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
920 if ((*len) < sizeof(*in2)) {
921 errno = EINVAL;
922 return -1;
925 memset(in2, 0, sizeof(*in2));
926 in2->sin_family = AF_INET;
927 in2->sin_addr.s_addr = htonl((127<<24) | iface);
928 in2->sin_port = htons(prt);
930 *len = sizeof(*in2);
931 break;
933 #ifdef HAVE_IPV6
934 case SOCKET_TYPE_CHAR_TCP_V6:
935 case SOCKET_TYPE_CHAR_UDP_V6: {
936 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
938 if ((*len) < sizeof(*in2)) {
939 errno = EINVAL;
940 return -1;
943 memset(in2, 0, sizeof(*in2));
944 in2->sin6_family = AF_INET6;
945 in2->sin6_addr = *swrap_ipv6();
946 in2->sin6_addr.s6_addr[15] = iface;
947 in2->sin6_port = htons(prt);
949 *len = sizeof(*in2);
950 break;
952 #endif
953 default:
954 errno = EINVAL;
955 return -1;
958 return 0;
961 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
962 int *bcast)
964 char type = '\0';
965 unsigned int prt;
966 unsigned int iface;
967 int is_bcast = 0;
969 if (bcast) *bcast = 0;
971 switch (inaddr->sa_family) {
972 case AF_INET: {
973 const struct sockaddr_in *in =
974 (const struct sockaddr_in *)(const void *)inaddr;
975 unsigned int addr = ntohl(in->sin_addr.s_addr);
976 char u_type = '\0';
977 char b_type = '\0';
978 char a_type = '\0';
980 switch (si->type) {
981 case SOCK_STREAM:
982 u_type = SOCKET_TYPE_CHAR_TCP;
983 break;
984 case SOCK_DGRAM:
985 u_type = SOCKET_TYPE_CHAR_UDP;
986 a_type = SOCKET_TYPE_CHAR_UDP;
987 b_type = SOCKET_TYPE_CHAR_UDP;
988 break;
989 default:
990 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
991 errno = ESOCKTNOSUPPORT;
992 return -1;
995 prt = ntohs(in->sin_port);
996 if (a_type && addr == 0xFFFFFFFF) {
997 /* 255.255.255.255 only udp */
998 is_bcast = 2;
999 type = a_type;
1000 iface = socket_wrapper_default_iface();
1001 } else if (b_type && addr == 0x7FFFFFFF) {
1002 /* 127.255.255.255 only udp */
1003 is_bcast = 1;
1004 type = b_type;
1005 iface = socket_wrapper_default_iface();
1006 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1007 /* 127.0.0.X */
1008 is_bcast = 0;
1009 type = u_type;
1010 iface = (addr & 0x000000FF);
1011 } else {
1012 errno = ENETUNREACH;
1013 return -1;
1015 if (bcast) *bcast = is_bcast;
1016 break;
1018 #ifdef HAVE_IPV6
1019 case AF_INET6: {
1020 const struct sockaddr_in6 *in =
1021 (const struct sockaddr_in6 *)(const void *)inaddr;
1022 struct in6_addr cmp1, cmp2;
1024 switch (si->type) {
1025 case SOCK_STREAM:
1026 type = SOCKET_TYPE_CHAR_TCP_V6;
1027 break;
1028 case SOCK_DGRAM:
1029 type = SOCKET_TYPE_CHAR_UDP_V6;
1030 break;
1031 default:
1032 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1033 errno = ESOCKTNOSUPPORT;
1034 return -1;
1037 /* XXX no multicast/broadcast */
1039 prt = ntohs(in->sin6_port);
1041 cmp1 = *swrap_ipv6();
1042 cmp2 = in->sin6_addr;
1043 cmp2.s6_addr[15] = 0;
1044 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1045 iface = in->sin6_addr.s6_addr[15];
1046 } else {
1047 errno = ENETUNREACH;
1048 return -1;
1051 break;
1053 #endif
1054 default:
1055 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1056 errno = ENETUNREACH;
1057 return -1;
1060 if (prt == 0) {
1061 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1062 errno = EINVAL;
1063 return -1;
1066 if (is_bcast) {
1067 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1068 socket_wrapper_dir());
1069 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1070 /* the caller need to do more processing */
1071 return 0;
1074 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1075 socket_wrapper_dir(), type, iface, prt);
1076 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1078 return 0;
1081 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1082 int *bcast)
1084 char type = '\0';
1085 unsigned int prt;
1086 unsigned int iface;
1087 struct stat st;
1088 int is_bcast = 0;
1090 if (bcast) *bcast = 0;
1092 switch (si->family) {
1093 case AF_INET: {
1094 const struct sockaddr_in *in =
1095 (const struct sockaddr_in *)(const void *)inaddr;
1096 unsigned int addr = ntohl(in->sin_addr.s_addr);
1097 char u_type = '\0';
1098 char d_type = '\0';
1099 char b_type = '\0';
1100 char a_type = '\0';
1102 prt = ntohs(in->sin_port);
1104 switch (si->type) {
1105 case SOCK_STREAM:
1106 u_type = SOCKET_TYPE_CHAR_TCP;
1107 d_type = SOCKET_TYPE_CHAR_TCP;
1108 break;
1109 case SOCK_DGRAM:
1110 u_type = SOCKET_TYPE_CHAR_UDP;
1111 d_type = SOCKET_TYPE_CHAR_UDP;
1112 a_type = SOCKET_TYPE_CHAR_UDP;
1113 b_type = SOCKET_TYPE_CHAR_UDP;
1114 break;
1115 default:
1116 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1117 errno = ESOCKTNOSUPPORT;
1118 return -1;
1121 if (addr == 0) {
1122 /* 0.0.0.0 */
1123 is_bcast = 0;
1124 type = d_type;
1125 iface = socket_wrapper_default_iface();
1126 } else if (a_type && addr == 0xFFFFFFFF) {
1127 /* 255.255.255.255 only udp */
1128 is_bcast = 2;
1129 type = a_type;
1130 iface = socket_wrapper_default_iface();
1131 } else if (b_type && addr == 0x7FFFFFFF) {
1132 /* 127.255.255.255 only udp */
1133 is_bcast = 1;
1134 type = b_type;
1135 iface = socket_wrapper_default_iface();
1136 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1137 /* 127.0.0.X */
1138 is_bcast = 0;
1139 type = u_type;
1140 iface = (addr & 0x000000FF);
1141 } else {
1142 errno = EADDRNOTAVAIL;
1143 return -1;
1146 /* Store the bind address for connect() */
1147 if (si->bindname == NULL) {
1148 struct sockaddr_in bind_in;
1149 socklen_t blen = sizeof(struct sockaddr_in);
1151 ZERO_STRUCT(bind_in);
1152 bind_in.sin_family = in->sin_family;
1153 bind_in.sin_port = in->sin_port;
1154 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1156 si->bindname = sockaddr_dup(&bind_in, blen);
1157 si->bindname_len = blen;
1160 break;
1162 #ifdef HAVE_IPV6
1163 case AF_INET6: {
1164 const struct sockaddr_in6 *in =
1165 (const struct sockaddr_in6 *)(const void *)inaddr;
1166 struct in6_addr cmp1, cmp2;
1168 switch (si->type) {
1169 case SOCK_STREAM:
1170 type = SOCKET_TYPE_CHAR_TCP_V6;
1171 break;
1172 case SOCK_DGRAM:
1173 type = SOCKET_TYPE_CHAR_UDP_V6;
1174 break;
1175 default:
1176 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1177 errno = ESOCKTNOSUPPORT;
1178 return -1;
1181 /* XXX no multicast/broadcast */
1183 prt = ntohs(in->sin6_port);
1185 cmp1 = *swrap_ipv6();
1186 cmp2 = in->sin6_addr;
1187 cmp2.s6_addr[15] = 0;
1188 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1189 iface = socket_wrapper_default_iface();
1190 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1191 iface = in->sin6_addr.s6_addr[15];
1192 } else {
1193 errno = EADDRNOTAVAIL;
1194 return -1;
1197 /* Store the bind address for connect() */
1198 if (si->bindname == NULL) {
1199 struct sockaddr_in6 bind_in;
1200 socklen_t blen = sizeof(struct sockaddr_in6);
1202 ZERO_STRUCT(bind_in);
1203 bind_in.sin6_family = in->sin6_family;
1204 bind_in.sin6_port = in->sin6_port;
1206 bind_in.sin6_addr = *swrap_ipv6();
1207 bind_in.sin6_addr.s6_addr[15] = iface;
1209 si->bindname = sockaddr_dup(&bind_in, blen);
1210 si->bindname_len = blen;
1213 break;
1215 #endif
1216 default:
1217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1218 errno = EADDRNOTAVAIL;
1219 return -1;
1223 if (bcast) *bcast = is_bcast;
1225 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1226 errno = EINVAL;
1227 return -1;
1230 if (prt == 0) {
1231 /* handle auto-allocation of ephemeral ports */
1232 for (prt = 5001; prt < 10000; prt++) {
1233 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1234 socket_wrapper_dir(), type, iface, prt);
1235 if (stat(un->sun_path, &st) == 0) continue;
1237 set_port(si->family, prt, si->myname);
1238 set_port(si->family, prt, si->bindname);
1240 break;
1242 if (prt == 10000) {
1243 errno = ENFILE;
1244 return -1;
1248 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1249 socket_wrapper_dir(), type, iface, prt);
1250 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1251 return 0;
1254 static struct socket_info *find_socket_info(int fd)
1256 struct socket_info *i;
1258 for (i = sockets; i; i = i->next) {
1259 struct socket_info_fd *f;
1260 for (f = i->fds; f; f = f->next) {
1261 if (f->fd == fd) {
1262 return i;
1267 return NULL;
1270 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1272 struct socket_info *s;
1274 /* first catch invalid input */
1275 switch (sa->sa_family) {
1276 case AF_INET:
1277 if (len < sizeof(struct sockaddr_in)) {
1278 return false;
1280 break;
1281 #if HAVE_IPV6
1282 case AF_INET6:
1283 if (len < sizeof(struct sockaddr_in6)) {
1284 return false;
1286 break;
1287 #endif
1288 default:
1289 return false;
1290 break;
1293 for (s = sockets; s != NULL; s = s->next) {
1294 if (s->myname == NULL) {
1295 continue;
1297 if (s->myname->sa_family != sa->sa_family) {
1298 continue;
1300 switch (s->myname->sa_family) {
1301 case AF_INET: {
1302 struct sockaddr_in *sin1, *sin2;
1304 sin1 = (struct sockaddr_in *)s->myname;
1305 sin2 = (struct sockaddr_in *)sa;
1307 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1308 continue;
1310 if (sin1->sin_port != sin2->sin_port) {
1311 continue;
1313 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1314 continue;
1317 /* found */
1318 return true;
1319 break;
1321 #if HAVE_IPV6
1322 case AF_INET6: {
1323 struct sockaddr_in6 *sin1, *sin2;
1325 sin1 = (struct sockaddr_in6 *)s->myname;
1326 sin2 = (struct sockaddr_in6 *)sa;
1328 if (sin1->sin6_port != sin2->sin6_port) {
1329 continue;
1331 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1332 &sin2->sin6_addr))
1334 continue;
1337 /* found */
1338 return true;
1339 break;
1341 #endif
1342 default:
1343 continue;
1344 break;
1349 return false;
1353 static void swrap_remove_stale(int fd)
1355 struct socket_info *si = find_socket_info(fd);
1356 struct socket_info_fd *fi;
1358 if (si != NULL) {
1359 for (fi = si->fds; fi; fi = fi->next) {
1360 if (fi->fd == fd) {
1361 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1362 SWRAP_DLIST_REMOVE(si->fds, fi);
1363 free(fi);
1364 break;
1368 if (si->fds == NULL) {
1369 SWRAP_DLIST_REMOVE(sockets, si);
1374 static int sockaddr_convert_to_un(struct socket_info *si,
1375 const struct sockaddr *in_addr,
1376 socklen_t in_len,
1377 struct sockaddr_un *out_addr,
1378 int alloc_sock,
1379 int *bcast)
1381 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1383 (void) in_len; /* unused */
1385 if (out_addr == NULL) {
1386 return 0;
1389 out->sa_family = AF_UNIX;
1390 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1391 out->sa_len = sizeof(*out_addr);
1392 #endif
1394 switch (in_addr->sa_family) {
1395 case AF_UNSPEC: {
1396 struct sockaddr_in *sin;
1397 if (si->family != AF_INET) {
1398 break;
1400 if (in_len < sizeof(struct sockaddr_in)) {
1401 break;
1403 sin = (struct sockaddr_in *)in_addr;
1404 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1405 break;
1409 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1410 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1413 /* FALL THROUGH */
1415 case AF_INET:
1416 #ifdef HAVE_IPV6
1417 case AF_INET6:
1418 #endif
1419 switch (si->type) {
1420 case SOCK_STREAM:
1421 case SOCK_DGRAM:
1422 break;
1423 default:
1424 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1425 errno = ESOCKTNOSUPPORT;
1426 return -1;
1428 if (alloc_sock) {
1429 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1430 } else {
1431 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1433 default:
1434 break;
1437 errno = EAFNOSUPPORT;
1438 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1439 return -1;
1442 static int sockaddr_convert_from_un(const struct socket_info *si,
1443 const struct sockaddr_un *in_addr,
1444 socklen_t un_addrlen,
1445 int family,
1446 struct sockaddr *out_addr,
1447 socklen_t *out_addrlen)
1449 int ret;
1451 if (out_addr == NULL || out_addrlen == NULL)
1452 return 0;
1454 if (un_addrlen == 0) {
1455 *out_addrlen = 0;
1456 return 0;
1459 switch (family) {
1460 case AF_INET:
1461 #ifdef HAVE_IPV6
1462 case AF_INET6:
1463 #endif
1464 switch (si->type) {
1465 case SOCK_STREAM:
1466 case SOCK_DGRAM:
1467 break;
1468 default:
1469 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1470 errno = ESOCKTNOSUPPORT;
1471 return -1;
1473 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1474 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1475 out_addr->sa_len = *out_addrlen;
1476 #endif
1477 return ret;
1478 default:
1479 break;
1482 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1483 errno = EAFNOSUPPORT;
1484 return -1;
1487 enum swrap_packet_type {
1488 SWRAP_CONNECT_SEND,
1489 SWRAP_CONNECT_UNREACH,
1490 SWRAP_CONNECT_RECV,
1491 SWRAP_CONNECT_ACK,
1492 SWRAP_ACCEPT_SEND,
1493 SWRAP_ACCEPT_RECV,
1494 SWRAP_ACCEPT_ACK,
1495 SWRAP_RECVFROM,
1496 SWRAP_SENDTO,
1497 SWRAP_SENDTO_UNREACH,
1498 SWRAP_PENDING_RST,
1499 SWRAP_RECV,
1500 SWRAP_RECV_RST,
1501 SWRAP_SEND,
1502 SWRAP_SEND_RST,
1503 SWRAP_CLOSE_SEND,
1504 SWRAP_CLOSE_RECV,
1505 SWRAP_CLOSE_ACK,
1508 struct swrap_file_hdr {
1509 uint32_t magic;
1510 uint16_t version_major;
1511 uint16_t version_minor;
1512 int32_t timezone;
1513 uint32_t sigfigs;
1514 uint32_t frame_max_len;
1515 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1516 uint32_t link_type;
1518 #define SWRAP_FILE_HDR_SIZE 24
1520 struct swrap_packet_frame {
1521 uint32_t seconds;
1522 uint32_t micro_seconds;
1523 uint32_t recorded_length;
1524 uint32_t full_length;
1526 #define SWRAP_PACKET_FRAME_SIZE 16
1528 union swrap_packet_ip {
1529 struct {
1530 uint8_t ver_hdrlen;
1531 uint8_t tos;
1532 uint16_t packet_length;
1533 uint16_t identification;
1534 uint8_t flags;
1535 uint8_t fragment;
1536 uint8_t ttl;
1537 uint8_t protocol;
1538 uint16_t hdr_checksum;
1539 uint32_t src_addr;
1540 uint32_t dest_addr;
1541 } v4;
1542 #define SWRAP_PACKET_IP_V4_SIZE 20
1543 struct {
1544 uint8_t ver_prio;
1545 uint8_t flow_label_high;
1546 uint16_t flow_label_low;
1547 uint16_t payload_length;
1548 uint8_t next_header;
1549 uint8_t hop_limit;
1550 uint8_t src_addr[16];
1551 uint8_t dest_addr[16];
1552 } v6;
1553 #define SWRAP_PACKET_IP_V6_SIZE 40
1555 #define SWRAP_PACKET_IP_SIZE 40
1557 union swrap_packet_payload {
1558 struct {
1559 uint16_t source_port;
1560 uint16_t dest_port;
1561 uint32_t seq_num;
1562 uint32_t ack_num;
1563 uint8_t hdr_length;
1564 uint8_t control;
1565 uint16_t window;
1566 uint16_t checksum;
1567 uint16_t urg;
1568 } tcp;
1569 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1570 struct {
1571 uint16_t source_port;
1572 uint16_t dest_port;
1573 uint16_t length;
1574 uint16_t checksum;
1575 } udp;
1576 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1577 struct {
1578 uint8_t type;
1579 uint8_t code;
1580 uint16_t checksum;
1581 uint32_t unused;
1582 } icmp4;
1583 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1584 struct {
1585 uint8_t type;
1586 uint8_t code;
1587 uint16_t checksum;
1588 uint32_t unused;
1589 } icmp6;
1590 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1592 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1594 #define SWRAP_PACKET_MIN_ALLOC \
1595 (SWRAP_PACKET_FRAME_SIZE + \
1596 SWRAP_PACKET_IP_SIZE + \
1597 SWRAP_PACKET_PAYLOAD_SIZE)
1599 static const char *socket_wrapper_pcap_file(void)
1601 static int initialized = 0;
1602 static const char *s = NULL;
1603 static const struct swrap_file_hdr h;
1604 static const struct swrap_packet_frame f;
1605 static const union swrap_packet_ip i;
1606 static const union swrap_packet_payload p;
1608 if (initialized == 1) {
1609 return s;
1611 initialized = 1;
1614 * TODO: don't use the structs use plain buffer offsets
1615 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1617 * for now make sure we disable PCAP support
1618 * if the struct has alignment!
1620 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1621 return NULL;
1623 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1624 return NULL;
1626 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1627 return NULL;
1629 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1630 return NULL;
1632 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1633 return NULL;
1635 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1636 return NULL;
1638 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1639 return NULL;
1641 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1642 return NULL;
1644 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1645 return NULL;
1647 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1648 return NULL;
1651 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1652 if (s == NULL) {
1653 return NULL;
1655 if (strncmp(s, "./", 2) == 0) {
1656 s += 2;
1658 return s;
1661 static uint8_t *swrap_packet_init(struct timeval *tval,
1662 const struct sockaddr *src,
1663 const struct sockaddr *dest,
1664 int socket_type,
1665 const uint8_t *payload,
1666 size_t payload_len,
1667 unsigned long tcp_seqno,
1668 unsigned long tcp_ack,
1669 unsigned char tcp_ctl,
1670 int unreachable,
1671 size_t *_packet_len)
1673 uint8_t *base;
1674 uint8_t *buf;
1675 struct swrap_packet_frame *frame;
1676 union swrap_packet_ip *ip;
1677 union swrap_packet_payload *pay;
1678 size_t packet_len;
1679 size_t alloc_len;
1680 size_t nonwire_len = sizeof(*frame);
1681 size_t wire_hdr_len = 0;
1682 size_t wire_len = 0;
1683 size_t ip_hdr_len = 0;
1684 size_t icmp_hdr_len = 0;
1685 size_t icmp_truncate_len = 0;
1686 uint8_t protocol = 0, icmp_protocol = 0;
1687 const struct sockaddr_in *src_in = NULL;
1688 const struct sockaddr_in *dest_in = NULL;
1689 #ifdef HAVE_IPV6
1690 const struct sockaddr_in6 *src_in6 = NULL;
1691 const struct sockaddr_in6 *dest_in6 = NULL;
1692 #endif
1693 uint16_t src_port;
1694 uint16_t dest_port;
1696 switch (src->sa_family) {
1697 case AF_INET:
1698 src_in = (const struct sockaddr_in *)src;
1699 dest_in = (const struct sockaddr_in *)dest;
1700 src_port = src_in->sin_port;
1701 dest_port = dest_in->sin_port;
1702 ip_hdr_len = sizeof(ip->v4);
1703 break;
1704 #ifdef HAVE_IPV6
1705 case AF_INET6:
1706 src_in6 = (const struct sockaddr_in6 *)src;
1707 dest_in6 = (const struct sockaddr_in6 *)dest;
1708 src_port = src_in6->sin6_port;
1709 dest_port = dest_in6->sin6_port;
1710 ip_hdr_len = sizeof(ip->v6);
1711 break;
1712 #endif
1713 default:
1714 return NULL;
1717 switch (socket_type) {
1718 case SOCK_STREAM:
1719 protocol = 0x06; /* TCP */
1720 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1721 wire_len = wire_hdr_len + payload_len;
1722 break;
1724 case SOCK_DGRAM:
1725 protocol = 0x11; /* UDP */
1726 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1727 wire_len = wire_hdr_len + payload_len;
1728 break;
1730 default:
1731 return NULL;
1734 if (unreachable) {
1735 icmp_protocol = protocol;
1736 switch (src->sa_family) {
1737 case AF_INET:
1738 protocol = 0x01; /* ICMPv4 */
1739 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1740 break;
1741 #ifdef HAVE_IPV6
1742 case AF_INET6:
1743 protocol = 0x3A; /* ICMPv6 */
1744 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1745 break;
1746 #endif
1748 if (wire_len > 64 ) {
1749 icmp_truncate_len = wire_len - 64;
1751 wire_hdr_len += icmp_hdr_len;
1752 wire_len += icmp_hdr_len;
1755 packet_len = nonwire_len + wire_len;
1756 alloc_len = packet_len;
1757 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1758 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1761 base = (uint8_t *)malloc(alloc_len);
1762 if (base == NULL) {
1763 return NULL;
1765 memset(base, 0x0, alloc_len);
1767 buf = base;
1769 frame = (struct swrap_packet_frame *)buf;
1770 frame->seconds = tval->tv_sec;
1771 frame->micro_seconds = tval->tv_usec;
1772 frame->recorded_length = wire_len - icmp_truncate_len;
1773 frame->full_length = wire_len - icmp_truncate_len;
1774 buf += SWRAP_PACKET_FRAME_SIZE;
1776 ip = (union swrap_packet_ip *)buf;
1777 switch (src->sa_family) {
1778 case AF_INET:
1779 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1780 ip->v4.tos = 0x00;
1781 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1782 ip->v4.identification = htons(0xFFFF);
1783 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1784 ip->v4.fragment = htons(0x0000);
1785 ip->v4.ttl = 0xFF;
1786 ip->v4.protocol = protocol;
1787 ip->v4.hdr_checksum = htons(0x0000);
1788 ip->v4.src_addr = src_in->sin_addr.s_addr;
1789 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1790 buf += SWRAP_PACKET_IP_V4_SIZE;
1791 break;
1792 #ifdef HAVE_IPV6
1793 case AF_INET6:
1794 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1795 ip->v6.flow_label_high = 0x00;
1796 ip->v6.flow_label_low = 0x0000;
1797 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1798 ip->v6.next_header = protocol;
1799 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1800 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1801 buf += SWRAP_PACKET_IP_V6_SIZE;
1802 break;
1803 #endif
1806 if (unreachable) {
1807 pay = (union swrap_packet_payload *)buf;
1808 switch (src->sa_family) {
1809 case AF_INET:
1810 pay->icmp4.type = 0x03; /* destination unreachable */
1811 pay->icmp4.code = 0x01; /* host unreachable */
1812 pay->icmp4.checksum = htons(0x0000);
1813 pay->icmp4.unused = htonl(0x00000000);
1814 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1816 /* set the ip header in the ICMP payload */
1817 ip = (union swrap_packet_ip *)buf;
1818 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1819 ip->v4.tos = 0x00;
1820 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1821 ip->v4.identification = htons(0xFFFF);
1822 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1823 ip->v4.fragment = htons(0x0000);
1824 ip->v4.ttl = 0xFF;
1825 ip->v4.protocol = icmp_protocol;
1826 ip->v4.hdr_checksum = htons(0x0000);
1827 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1828 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1829 buf += SWRAP_PACKET_IP_V4_SIZE;
1831 src_port = dest_in->sin_port;
1832 dest_port = src_in->sin_port;
1833 break;
1834 #ifdef HAVE_IPV6
1835 case AF_INET6:
1836 pay->icmp6.type = 0x01; /* destination unreachable */
1837 pay->icmp6.code = 0x03; /* address unreachable */
1838 pay->icmp6.checksum = htons(0x0000);
1839 pay->icmp6.unused = htonl(0x00000000);
1840 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1842 /* set the ip header in the ICMP payload */
1843 ip = (union swrap_packet_ip *)buf;
1844 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1845 ip->v6.flow_label_high = 0x00;
1846 ip->v6.flow_label_low = 0x0000;
1847 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1848 ip->v6.next_header = protocol;
1849 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1850 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1851 buf += SWRAP_PACKET_IP_V6_SIZE;
1853 src_port = dest_in6->sin6_port;
1854 dest_port = src_in6->sin6_port;
1855 break;
1856 #endif
1860 pay = (union swrap_packet_payload *)buf;
1862 switch (socket_type) {
1863 case SOCK_STREAM:
1864 pay->tcp.source_port = src_port;
1865 pay->tcp.dest_port = dest_port;
1866 pay->tcp.seq_num = htonl(tcp_seqno);
1867 pay->tcp.ack_num = htonl(tcp_ack);
1868 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1869 pay->tcp.control = tcp_ctl;
1870 pay->tcp.window = htons(0x7FFF);
1871 pay->tcp.checksum = htons(0x0000);
1872 pay->tcp.urg = htons(0x0000);
1873 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1875 break;
1877 case SOCK_DGRAM:
1878 pay->udp.source_port = src_port;
1879 pay->udp.dest_port = dest_port;
1880 pay->udp.length = htons(8 + payload_len);
1881 pay->udp.checksum = htons(0x0000);
1882 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1884 break;
1887 if (payload && payload_len > 0) {
1888 memcpy(buf, payload, payload_len);
1891 *_packet_len = packet_len - icmp_truncate_len;
1892 return base;
1895 static int swrap_get_pcap_fd(const char *fname)
1897 static int fd = -1;
1899 if (fd != -1) return fd;
1901 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1902 if (fd != -1) {
1903 struct swrap_file_hdr file_hdr;
1904 file_hdr.magic = 0xA1B2C3D4;
1905 file_hdr.version_major = 0x0002;
1906 file_hdr.version_minor = 0x0004;
1907 file_hdr.timezone = 0x00000000;
1908 file_hdr.sigfigs = 0x00000000;
1909 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1910 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1912 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1913 close(fd);
1914 fd = -1;
1916 return fd;
1919 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1921 return fd;
1924 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1925 const struct sockaddr *addr,
1926 enum swrap_packet_type type,
1927 const void *buf, size_t len,
1928 size_t *packet_len)
1930 const struct sockaddr *src_addr;
1931 const struct sockaddr *dest_addr;
1932 unsigned long tcp_seqno = 0;
1933 unsigned long tcp_ack = 0;
1934 unsigned char tcp_ctl = 0;
1935 int unreachable = 0;
1937 struct timeval tv;
1939 switch (si->family) {
1940 case AF_INET:
1941 break;
1942 #ifdef HAVE_IPV6
1943 case AF_INET6:
1944 break;
1945 #endif
1946 default:
1947 return NULL;
1950 switch (type) {
1951 case SWRAP_CONNECT_SEND:
1952 if (si->type != SOCK_STREAM) return NULL;
1954 src_addr = si->myname;
1955 dest_addr = addr;
1957 tcp_seqno = si->io.pck_snd;
1958 tcp_ack = si->io.pck_rcv;
1959 tcp_ctl = 0x02; /* SYN */
1961 si->io.pck_snd += 1;
1963 break;
1965 case SWRAP_CONNECT_RECV:
1966 if (si->type != SOCK_STREAM) return NULL;
1968 dest_addr = si->myname;
1969 src_addr = addr;
1971 tcp_seqno = si->io.pck_rcv;
1972 tcp_ack = si->io.pck_snd;
1973 tcp_ctl = 0x12; /** SYN,ACK */
1975 si->io.pck_rcv += 1;
1977 break;
1979 case SWRAP_CONNECT_UNREACH:
1980 if (si->type != SOCK_STREAM) return NULL;
1982 dest_addr = si->myname;
1983 src_addr = addr;
1985 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1986 tcp_seqno = si->io.pck_snd - 1;
1987 tcp_ack = si->io.pck_rcv;
1988 tcp_ctl = 0x02; /* SYN */
1989 unreachable = 1;
1991 break;
1993 case SWRAP_CONNECT_ACK:
1994 if (si->type != SOCK_STREAM) return NULL;
1996 src_addr = si->myname;
1997 dest_addr = addr;
1999 tcp_seqno = si->io.pck_snd;
2000 tcp_ack = si->io.pck_rcv;
2001 tcp_ctl = 0x10; /* ACK */
2003 break;
2005 case SWRAP_ACCEPT_SEND:
2006 if (si->type != SOCK_STREAM) return NULL;
2008 dest_addr = si->myname;
2009 src_addr = addr;
2011 tcp_seqno = si->io.pck_rcv;
2012 tcp_ack = si->io.pck_snd;
2013 tcp_ctl = 0x02; /* SYN */
2015 si->io.pck_rcv += 1;
2017 break;
2019 case SWRAP_ACCEPT_RECV:
2020 if (si->type != SOCK_STREAM) return NULL;
2022 src_addr = si->myname;
2023 dest_addr = addr;
2025 tcp_seqno = si->io.pck_snd;
2026 tcp_ack = si->io.pck_rcv;
2027 tcp_ctl = 0x12; /* SYN,ACK */
2029 si->io.pck_snd += 1;
2031 break;
2033 case SWRAP_ACCEPT_ACK:
2034 if (si->type != SOCK_STREAM) return NULL;
2036 dest_addr = si->myname;
2037 src_addr = addr;
2039 tcp_seqno = si->io.pck_rcv;
2040 tcp_ack = si->io.pck_snd;
2041 tcp_ctl = 0x10; /* ACK */
2043 break;
2045 case SWRAP_SEND:
2046 src_addr = si->myname;
2047 dest_addr = si->peername;
2049 tcp_seqno = si->io.pck_snd;
2050 tcp_ack = si->io.pck_rcv;
2051 tcp_ctl = 0x18; /* PSH,ACK */
2053 si->io.pck_snd += len;
2055 break;
2057 case SWRAP_SEND_RST:
2058 dest_addr = si->myname;
2059 src_addr = si->peername;
2061 if (si->type == SOCK_DGRAM) {
2062 return swrap_marshall_packet(si, si->peername,
2063 SWRAP_SENDTO_UNREACH,
2064 buf, len, packet_len);
2067 tcp_seqno = si->io.pck_rcv;
2068 tcp_ack = si->io.pck_snd;
2069 tcp_ctl = 0x14; /** RST,ACK */
2071 break;
2073 case SWRAP_PENDING_RST:
2074 dest_addr = si->myname;
2075 src_addr = si->peername;
2077 if (si->type == SOCK_DGRAM) {
2078 return NULL;
2081 tcp_seqno = si->io.pck_rcv;
2082 tcp_ack = si->io.pck_snd;
2083 tcp_ctl = 0x14; /* RST,ACK */
2085 break;
2087 case SWRAP_RECV:
2088 dest_addr = si->myname;
2089 src_addr = si->peername;
2091 tcp_seqno = si->io.pck_rcv;
2092 tcp_ack = si->io.pck_snd;
2093 tcp_ctl = 0x18; /* PSH,ACK */
2095 si->io.pck_rcv += len;
2097 break;
2099 case SWRAP_RECV_RST:
2100 dest_addr = si->myname;
2101 src_addr = si->peername;
2103 if (si->type == SOCK_DGRAM) {
2104 return NULL;
2107 tcp_seqno = si->io.pck_rcv;
2108 tcp_ack = si->io.pck_snd;
2109 tcp_ctl = 0x14; /* RST,ACK */
2111 break;
2113 case SWRAP_SENDTO:
2114 src_addr = si->myname;
2115 dest_addr = addr;
2117 si->io.pck_snd += len;
2119 break;
2121 case SWRAP_SENDTO_UNREACH:
2122 dest_addr = si->myname;
2123 src_addr = addr;
2125 unreachable = 1;
2127 break;
2129 case SWRAP_RECVFROM:
2130 dest_addr = si->myname;
2131 src_addr = addr;
2133 si->io.pck_rcv += len;
2135 break;
2137 case SWRAP_CLOSE_SEND:
2138 if (si->type != SOCK_STREAM) return NULL;
2140 src_addr = si->myname;
2141 dest_addr = si->peername;
2143 tcp_seqno = si->io.pck_snd;
2144 tcp_ack = si->io.pck_rcv;
2145 tcp_ctl = 0x11; /* FIN, ACK */
2147 si->io.pck_snd += 1;
2149 break;
2151 case SWRAP_CLOSE_RECV:
2152 if (si->type != SOCK_STREAM) return NULL;
2154 dest_addr = si->myname;
2155 src_addr = si->peername;
2157 tcp_seqno = si->io.pck_rcv;
2158 tcp_ack = si->io.pck_snd;
2159 tcp_ctl = 0x11; /* FIN,ACK */
2161 si->io.pck_rcv += 1;
2163 break;
2165 case SWRAP_CLOSE_ACK:
2166 if (si->type != SOCK_STREAM) return NULL;
2168 src_addr = si->myname;
2169 dest_addr = si->peername;
2171 tcp_seqno = si->io.pck_snd;
2172 tcp_ack = si->io.pck_rcv;
2173 tcp_ctl = 0x10; /* ACK */
2175 break;
2176 default:
2177 return NULL;
2180 swrapGetTimeOfDay(&tv);
2182 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2183 (const uint8_t *)buf, len,
2184 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2185 packet_len);
2188 static void swrap_dump_packet(struct socket_info *si,
2189 const struct sockaddr *addr,
2190 enum swrap_packet_type type,
2191 const void *buf, size_t len)
2193 const char *file_name;
2194 uint8_t *packet;
2195 size_t packet_len = 0;
2196 int fd;
2198 file_name = socket_wrapper_pcap_file();
2199 if (!file_name) {
2200 return;
2203 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2204 if (!packet) {
2205 return;
2208 fd = swrap_get_pcap_fd(file_name);
2209 if (fd != -1) {
2210 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2211 free(packet);
2212 return;
2216 free(packet);
2219 /****************************************************************************
2220 * SIGNALFD
2221 ***************************************************************************/
2223 #ifdef HAVE_SIGNALFD
2224 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2226 int rc;
2228 rc = libc_signalfd(fd, mask, flags);
2229 if (rc != -1) {
2230 swrap_remove_stale(fd);
2233 return rc;
2236 int signalfd(int fd, const sigset_t *mask, int flags)
2238 return swrap_signalfd(fd, mask, flags);
2240 #endif
2242 /****************************************************************************
2243 * SOCKET
2244 ***************************************************************************/
2246 static int swrap_socket(int family, int type, int protocol)
2248 struct socket_info *si;
2249 struct socket_info_fd *fi;
2250 int fd;
2251 int real_type = type;
2254 * Remove possible addition flags passed to socket() so
2255 * do not fail checking the type.
2256 * See https://lwn.net/Articles/281965/
2258 #ifdef SOCK_CLOEXEC
2259 real_type &= ~SOCK_CLOEXEC;
2260 #endif
2261 #ifdef SOCK_NONBLOCK
2262 real_type &= ~SOCK_NONBLOCK;
2263 #endif
2265 if (!socket_wrapper_enabled()) {
2266 return libc_socket(family, type, protocol);
2269 switch (family) {
2270 case AF_INET:
2271 #ifdef HAVE_IPV6
2272 case AF_INET6:
2273 #endif
2274 break;
2275 case AF_UNIX:
2276 return libc_socket(family, type, protocol);
2277 default:
2278 errno = EAFNOSUPPORT;
2279 return -1;
2282 switch (real_type) {
2283 case SOCK_STREAM:
2284 break;
2285 case SOCK_DGRAM:
2286 break;
2287 default:
2288 errno = EPROTONOSUPPORT;
2289 return -1;
2292 switch (protocol) {
2293 case 0:
2294 break;
2295 case 6:
2296 if (real_type == SOCK_STREAM) {
2297 break;
2299 /*fall through*/
2300 case 17:
2301 if (real_type == SOCK_DGRAM) {
2302 break;
2304 /*fall through*/
2305 default:
2306 errno = EPROTONOSUPPORT;
2307 return -1;
2311 * We must call libc_socket with type, from the caller, not the version
2312 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2314 fd = libc_socket(AF_UNIX, type, 0);
2316 if (fd == -1) {
2317 return -1;
2320 /* Check if we have a stale fd and remove it */
2321 si = find_socket_info(fd);
2322 if (si != NULL) {
2323 swrap_remove_stale(fd);
2326 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2327 memset(si, 0, sizeof(struct socket_info));
2328 if (si == NULL) {
2329 errno = ENOMEM;
2330 return -1;
2333 si->family = family;
2335 /* however, the rest of the socket_wrapper code expects just
2336 * the type, not the flags */
2337 si->type = real_type;
2338 si->protocol = protocol;
2341 * Setup myname so getsockname() can succeed to find out the socket
2342 * type.
2344 switch(si->family) {
2345 case AF_INET: {
2346 struct sockaddr_in sin = {
2347 .sin_family = AF_INET,
2350 si->myname_len = sizeof(struct sockaddr_in);
2351 si->myname = sockaddr_dup(&sin, si->myname_len);
2352 break;
2354 case AF_INET6: {
2355 struct sockaddr_in6 sin6 = {
2356 .sin6_family = AF_INET6,
2359 si->myname_len = sizeof(struct sockaddr_in6);
2360 si->myname = sockaddr_dup(&sin6, si->myname_len);
2361 break;
2363 default:
2364 free(si);
2365 errno = EINVAL;
2366 return -1;
2369 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2370 if (fi == NULL) {
2371 if (si->myname != NULL) {
2372 free (si->myname);
2374 free(si);
2375 errno = ENOMEM;
2376 return -1;
2379 fi->fd = fd;
2381 SWRAP_DLIST_ADD(si->fds, fi);
2382 SWRAP_DLIST_ADD(sockets, si);
2384 return fd;
2387 int socket(int family, int type, int protocol)
2389 return swrap_socket(family, type, protocol);
2392 /****************************************************************************
2393 * SOCKETPAIR
2394 ***************************************************************************/
2396 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2398 int rc;
2400 rc = libc_socketpair(family, type, protocol, sv);
2401 if (rc != -1) {
2402 swrap_remove_stale(sv[0]);
2403 swrap_remove_stale(sv[1]);
2406 return rc;
2409 int socketpair(int family, int type, int protocol, int sv[2])
2411 return swrap_socketpair(family, type, protocol, sv);
2414 /****************************************************************************
2415 * SOCKETPAIR
2416 ***************************************************************************/
2418 #ifdef HAVE_TIMERFD_CREATE
2419 static int swrap_timerfd_create(int clockid, int flags)
2421 int fd;
2423 fd = libc_timerfd_create(clockid, flags);
2424 if (fd != -1) {
2425 swrap_remove_stale(fd);
2428 return fd;
2431 int timerfd_create(int clockid, int flags)
2433 return swrap_timerfd_create(clockid, flags);
2435 #endif
2437 /****************************************************************************
2438 * PIPE
2439 ***************************************************************************/
2441 static int swrap_pipe(int pipefd[2])
2443 int rc;
2445 rc = libc_pipe(pipefd);
2446 if (rc != -1) {
2447 swrap_remove_stale(pipefd[0]);
2448 swrap_remove_stale(pipefd[1]);
2451 return rc;
2454 int pipe(int pipefd[2])
2456 return swrap_pipe(pipefd);
2459 /****************************************************************************
2460 * ACCEPT
2461 ***************************************************************************/
2463 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2465 struct socket_info *parent_si, *child_si;
2466 struct socket_info_fd *child_fi;
2467 int fd;
2468 struct sockaddr_un un_addr;
2469 socklen_t un_addrlen = sizeof(un_addr);
2470 struct sockaddr_un un_my_addr;
2471 socklen_t un_my_addrlen = sizeof(un_my_addr);
2472 struct sockaddr *my_addr;
2473 socklen_t my_addrlen, len;
2474 int ret;
2476 parent_si = find_socket_info(s);
2477 if (!parent_si) {
2478 return libc_accept(s, addr, addrlen);
2482 * assume out sockaddr have the same size as the in parent
2483 * socket family
2485 my_addrlen = socket_length(parent_si->family);
2486 if (my_addrlen <= 0) {
2487 errno = EINVAL;
2488 return -1;
2491 my_addr = (struct sockaddr *)malloc(my_addrlen);
2492 if (my_addr == NULL) {
2493 return -1;
2496 memset(&un_addr, 0, sizeof(un_addr));
2497 memset(&un_my_addr, 0, sizeof(un_my_addr));
2499 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2500 if (ret == -1) {
2501 if (errno == ENOTSOCK) {
2502 /* Remove stale fds */
2503 swrap_remove_stale(s);
2505 free(my_addr);
2506 return ret;
2509 fd = ret;
2511 len = my_addrlen;
2512 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2513 parent_si->family, my_addr, &len);
2514 if (ret == -1) {
2515 free(my_addr);
2516 close(fd);
2517 return ret;
2520 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2521 memset(child_si, 0, sizeof(struct socket_info));
2523 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2524 if (child_fi == NULL) {
2525 free(child_si);
2526 free(my_addr);
2527 close(fd);
2528 errno = ENOMEM;
2529 return -1;
2532 child_fi->fd = fd;
2534 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2536 child_si->family = parent_si->family;
2537 child_si->type = parent_si->type;
2538 child_si->protocol = parent_si->protocol;
2539 child_si->bound = 1;
2540 child_si->is_server = 1;
2541 child_si->connected = 1;
2543 child_si->peername_len = len;
2544 child_si->peername = sockaddr_dup(my_addr, len);
2546 if (addr != NULL && addrlen != NULL) {
2547 size_t copy_len = MIN(*addrlen, len);
2548 if (copy_len > 0) {
2549 memcpy(addr, my_addr, copy_len);
2551 *addrlen = len;
2554 ret = libc_getsockname(fd,
2555 (struct sockaddr *)(void *)&un_my_addr,
2556 &un_my_addrlen);
2557 if (ret == -1) {
2558 free(child_fi);
2559 free(child_si);
2560 free(my_addr);
2561 close(fd);
2562 return ret;
2565 len = my_addrlen;
2566 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2567 child_si->family, my_addr, &len);
2568 if (ret == -1) {
2569 free(child_fi);
2570 free(child_si);
2571 free(my_addr);
2572 close(fd);
2573 return ret;
2576 SWRAP_LOG(SWRAP_LOG_TRACE,
2577 "accept() path=%s, fd=%d",
2578 un_my_addr.sun_path, s);
2580 child_si->myname_len = len;
2581 child_si->myname = sockaddr_dup(my_addr, len);
2582 free(my_addr);
2584 SWRAP_DLIST_ADD(sockets, child_si);
2586 if (addr != NULL) {
2587 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2588 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2589 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2592 return fd;
2595 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2596 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2597 #else
2598 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2599 #endif
2601 return swrap_accept(s, addr, (socklen_t *)addrlen);
2604 static int autobind_start_init;
2605 static int autobind_start;
2607 /* using sendto() or connect() on an unbound socket would give the
2608 recipient no way to reply, as unlike UDP and TCP, a unix domain
2609 socket can't auto-assign ephemeral port numbers, so we need to
2610 assign it here.
2611 Note: this might change the family from ipv6 to ipv4
2613 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2615 struct sockaddr_un un_addr;
2616 int i;
2617 char type;
2618 int ret;
2619 int port;
2620 struct stat st;
2622 if (autobind_start_init != 1) {
2623 autobind_start_init = 1;
2624 autobind_start = getpid();
2625 autobind_start %= 50000;
2626 autobind_start += 10000;
2629 un_addr.sun_family = AF_UNIX;
2631 switch (family) {
2632 case AF_INET: {
2633 struct sockaddr_in in;
2635 switch (si->type) {
2636 case SOCK_STREAM:
2637 type = SOCKET_TYPE_CHAR_TCP;
2638 break;
2639 case SOCK_DGRAM:
2640 type = SOCKET_TYPE_CHAR_UDP;
2641 break;
2642 default:
2643 errno = ESOCKTNOSUPPORT;
2644 return -1;
2647 memset(&in, 0, sizeof(in));
2648 in.sin_family = AF_INET;
2649 in.sin_addr.s_addr = htonl(127<<24 |
2650 socket_wrapper_default_iface());
2652 free(si->myname);
2653 si->myname_len = sizeof(in);
2654 si->myname = sockaddr_dup(&in, si->myname_len);
2655 break;
2657 #ifdef HAVE_IPV6
2658 case AF_INET6: {
2659 struct sockaddr_in6 in6;
2661 if (si->family != family) {
2662 errno = ENETUNREACH;
2663 return -1;
2666 switch (si->type) {
2667 case SOCK_STREAM:
2668 type = SOCKET_TYPE_CHAR_TCP_V6;
2669 break;
2670 case SOCK_DGRAM:
2671 type = SOCKET_TYPE_CHAR_UDP_V6;
2672 break;
2673 default:
2674 errno = ESOCKTNOSUPPORT;
2675 return -1;
2678 memset(&in6, 0, sizeof(in6));
2679 in6.sin6_family = AF_INET6;
2680 in6.sin6_addr = *swrap_ipv6();
2681 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2682 free(si->myname);
2683 si->myname_len = sizeof(in6);
2684 si->myname = sockaddr_dup(&in6, si->myname_len);
2685 break;
2687 #endif
2688 default:
2689 errno = ESOCKTNOSUPPORT;
2690 return -1;
2693 if (autobind_start > 60000) {
2694 autobind_start = 10000;
2697 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2698 port = autobind_start + i;
2699 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2700 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2701 type, socket_wrapper_default_iface(), port);
2702 if (stat(un_addr.sun_path, &st) == 0) continue;
2704 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2705 sizeof(un_addr));
2706 if (ret == -1) return ret;
2708 si->tmp_path = strdup(un_addr.sun_path);
2709 si->bound = 1;
2710 autobind_start = port + 1;
2711 break;
2713 if (i == SOCKET_MAX_SOCKETS) {
2714 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2715 "interface "SOCKET_FORMAT,
2716 SOCKET_MAX_SOCKETS,
2717 type,
2718 socket_wrapper_default_iface(),
2720 errno = ENFILE;
2721 return -1;
2724 si->family = family;
2725 set_port(si->family, port, si->myname);
2727 return 0;
2730 /****************************************************************************
2731 * CONNECT
2732 ***************************************************************************/
2734 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2735 socklen_t addrlen)
2737 int ret;
2738 struct sockaddr_un un_addr;
2739 struct socket_info *si = find_socket_info(s);
2740 int bcast = 0;
2742 if (!si) {
2743 return libc_connect(s, serv_addr, addrlen);
2746 if (si->bound == 0) {
2747 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2748 if (ret == -1) return -1;
2751 if (si->family != serv_addr->sa_family) {
2752 errno = EINVAL;
2753 return -1;
2756 ret = sockaddr_convert_to_un(si, serv_addr,
2757 addrlen, &un_addr, 0, &bcast);
2758 if (ret == -1) return -1;
2760 if (bcast) {
2761 errno = ENETUNREACH;
2762 return -1;
2765 if (si->type == SOCK_DGRAM) {
2766 si->defer_connect = 1;
2767 ret = 0;
2768 } else {
2769 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2771 ret = libc_connect(s,
2772 (struct sockaddr *)(void *)&un_addr,
2773 sizeof(struct sockaddr_un));
2776 SWRAP_LOG(SWRAP_LOG_TRACE,
2777 "connect() path=%s, fd=%d",
2778 un_addr.sun_path, s);
2781 /* to give better errors */
2782 if (ret == -1 && errno == ENOENT) {
2783 errno = EHOSTUNREACH;
2786 if (ret == 0) {
2787 si->peername_len = addrlen;
2788 si->peername = sockaddr_dup(serv_addr, addrlen);
2789 si->connected = 1;
2792 * When we connect() on a socket than we have to bind the
2793 * outgoing connection on the interface we use for the
2794 * transport. We already bound it on the right interface
2795 * but here we have to update the name so getsockname()
2796 * returns correct information.
2798 if (si->bindname != NULL) {
2799 free(si->myname);
2801 si->myname = si->bindname;
2802 si->myname_len = si->bindname_len;
2804 si->bindname = NULL;
2805 si->bindname_len = 0;
2808 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2809 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2810 } else {
2811 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2814 return ret;
2817 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2819 return swrap_connect(s, serv_addr, addrlen);
2822 /****************************************************************************
2823 * BIND
2824 ***************************************************************************/
2826 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2828 int ret;
2829 struct sockaddr_un un_addr;
2830 struct socket_info *si = find_socket_info(s);
2831 int bind_error = 0;
2833 if (!si) {
2834 return libc_bind(s, myaddr, addrlen);
2837 switch (si->family) {
2838 case AF_INET: {
2839 const struct sockaddr_in *sin;
2840 if (addrlen < sizeof(struct sockaddr_in)) {
2841 bind_error = EINVAL;
2842 break;
2845 sin = (struct sockaddr_in *)myaddr;
2847 if (sin->sin_family != AF_INET) {
2848 bind_error = EAFNOSUPPORT;
2851 /* special case for AF_UNSPEC */
2852 if (sin->sin_family == AF_UNSPEC &&
2853 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2855 bind_error = 0;
2858 break;
2860 #ifdef HAVE_IPV6
2861 case AF_INET6: {
2862 const struct sockaddr_in6 *sin6;
2863 if (addrlen < sizeof(struct sockaddr_in6)) {
2864 bind_error = EINVAL;
2865 break;
2868 sin6 = (struct sockaddr_in6 *)myaddr;
2870 if (sin6->sin6_family != AF_INET6) {
2871 bind_error = EAFNOSUPPORT;
2874 break;
2876 #endif
2877 default:
2878 bind_error = EINVAL;
2879 break;
2882 if (bind_error != 0) {
2883 errno = bind_error;
2884 return -1;
2887 free(si->myname);
2888 si->myname_len = addrlen;
2889 si->myname = sockaddr_dup(myaddr, addrlen);
2891 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2892 if (ret == -1) return -1;
2894 unlink(un_addr.sun_path);
2896 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2897 sizeof(struct sockaddr_un));
2899 SWRAP_LOG(SWRAP_LOG_TRACE,
2900 "bind() path=%s, fd=%d",
2901 un_addr.sun_path, s);
2903 if (ret == 0) {
2904 si->bound = 1;
2907 return ret;
2910 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2912 return swrap_bind(s, myaddr, addrlen);
2915 /****************************************************************************
2916 * BINDRESVPORT
2917 ***************************************************************************/
2919 #ifdef HAVE_BINDRESVPORT
2920 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2922 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2924 struct sockaddr_storage myaddr;
2925 socklen_t salen;
2926 static uint16_t port;
2927 uint16_t i;
2928 int rc = -1;
2929 int af;
2931 #define SWRAP_STARTPORT 600
2932 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2933 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2935 if (port == 0) {
2936 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2939 if (sa == NULL) {
2940 salen = sizeof(struct sockaddr);
2941 sa = (struct sockaddr *)&myaddr;
2943 rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
2944 if (rc < 0) {
2945 return -1;
2948 af = sa->sa_family;
2949 memset(&myaddr, 0, salen);
2950 } else {
2951 af = sa->sa_family;
2954 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
2955 switch(af) {
2956 case AF_INET: {
2957 struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
2959 salen = sizeof(struct sockaddr_in);
2960 sinp->sin_port = htons(port);
2961 break;
2963 case AF_INET6: {
2964 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
2966 salen = sizeof(struct sockaddr_in6);
2967 sin6p->sin6_port = htons(port);
2968 break;
2970 default:
2971 errno = EAFNOSUPPORT;
2972 return -1;
2974 sa->sa_family = af;
2976 if (port > SWRAP_ENDPORT) {
2977 port = SWRAP_STARTPORT;
2980 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
2981 if (rc == 0 || errno != EADDRINUSE) {
2982 break;
2986 return rc;
2989 int bindresvport(int sockfd, struct sockaddr_in *sinp)
2991 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
2993 #endif
2995 /****************************************************************************
2996 * LISTEN
2997 ***************************************************************************/
2999 static int swrap_listen(int s, int backlog)
3001 int ret;
3002 struct socket_info *si = find_socket_info(s);
3004 if (!si) {
3005 return libc_listen(s, backlog);
3008 ret = libc_listen(s, backlog);
3010 return ret;
3013 int listen(int s, int backlog)
3015 return swrap_listen(s, backlog);
3018 /****************************************************************************
3019 * OPEN
3020 ***************************************************************************/
3022 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3024 int ret;
3026 ret = libc_vopen(pathname, flags, ap);
3027 if (ret != -1) {
3029 * There are methods for closing descriptors (libc-internal code
3030 * paths, direct syscalls) which close descriptors in ways that
3031 * we can't intercept, so try to recover when we notice that
3032 * that's happened
3034 swrap_remove_stale(ret);
3036 return ret;
3039 int open(const char *pathname, int flags, ...)
3041 va_list ap;
3042 int fd;
3044 va_start(ap, flags);
3045 fd = swrap_vopen(pathname, flags, ap);
3046 va_end(ap);
3048 return fd;
3051 /****************************************************************************
3052 * GETPEERNAME
3053 ***************************************************************************/
3055 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3057 struct socket_info *si = find_socket_info(s);
3058 socklen_t len;
3060 if (!si) {
3061 return libc_getpeername(s, name, addrlen);
3064 if (!si->peername)
3066 errno = ENOTCONN;
3067 return -1;
3070 len = MIN(*addrlen, si->peername_len);
3071 if (len == 0) {
3072 return 0;
3075 memcpy(name, si->peername, len);
3076 *addrlen = si->peername_len;
3078 return 0;
3081 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3082 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3083 #else
3084 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3085 #endif
3087 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3090 /****************************************************************************
3091 * GETSOCKNAME
3092 ***************************************************************************/
3094 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3096 struct socket_info *si = find_socket_info(s);
3097 socklen_t len;
3099 if (!si) {
3100 return libc_getsockname(s, name, addrlen);
3103 len = MIN(*addrlen, si->myname_len);
3104 if (len == 0) {
3105 return 0;
3108 memcpy(name, si->myname, len);
3109 *addrlen = si->myname_len;
3111 return 0;
3114 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3115 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3116 #else
3117 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3118 #endif
3120 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3123 /****************************************************************************
3124 * GETSOCKOPT
3125 ***************************************************************************/
3127 #ifndef SO_PROTOCOL
3128 # ifdef SO_PROTOTYPE /* The Solaris name */
3129 # define SO_PROTOCOL SO_PROTOTYPE
3130 # endif /* SO_PROTOTYPE */
3131 #endif /* SO_PROTOCOL */
3133 static int swrap_getsockopt(int s, int level, int optname,
3134 void *optval, socklen_t *optlen)
3136 struct socket_info *si = find_socket_info(s);
3138 if (!si) {
3139 return libc_getsockopt(s,
3140 level,
3141 optname,
3142 optval,
3143 optlen);
3146 if (level == SOL_SOCKET) {
3147 switch (optname) {
3148 #ifdef SO_DOMAIN
3149 case SO_DOMAIN:
3150 if (optval == NULL || optlen == NULL ||
3151 *optlen < (socklen_t)sizeof(int)) {
3152 errno = EINVAL;
3153 return -1;
3156 *optlen = sizeof(int);
3157 *(int *)optval = si->family;
3158 return 0;
3159 #endif /* SO_DOMAIN */
3160 case SO_PROTOCOL:
3161 if (optval == NULL || optlen == NULL ||
3162 *optlen < (socklen_t)sizeof(int)) {
3163 errno = EINVAL;
3164 return -1;
3167 *optlen = sizeof(int);
3168 *(int *)optval = si->protocol;
3169 return 0;
3170 case SO_TYPE:
3171 if (optval == NULL || optlen == NULL ||
3172 *optlen < (socklen_t)sizeof(int)) {
3173 errno = EINVAL;
3174 return -1;
3177 *optlen = sizeof(int);
3178 *(int *)optval = si->type;
3179 return 0;
3180 default:
3181 return libc_getsockopt(s,
3182 level,
3183 optname,
3184 optval,
3185 optlen);
3189 errno = ENOPROTOOPT;
3190 return -1;
3193 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3194 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3195 #else
3196 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3197 #endif
3199 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3202 /****************************************************************************
3203 * SETSOCKOPT
3204 ***************************************************************************/
3206 static int swrap_setsockopt(int s, int level, int optname,
3207 const void *optval, socklen_t optlen)
3209 struct socket_info *si = find_socket_info(s);
3211 if (!si) {
3212 return libc_setsockopt(s,
3213 level,
3214 optname,
3215 optval,
3216 optlen);
3219 if (level == SOL_SOCKET) {
3220 return libc_setsockopt(s,
3221 level,
3222 optname,
3223 optval,
3224 optlen);
3227 switch (si->family) {
3228 case AF_INET:
3229 if (level == IPPROTO_IP) {
3230 #ifdef IP_PKTINFO
3231 if (optname == IP_PKTINFO) {
3232 si->pktinfo = AF_INET;
3234 #endif /* IP_PKTINFO */
3236 return 0;
3237 #ifdef HAVE_IPV6
3238 case AF_INET6:
3239 if (level == IPPROTO_IPV6) {
3240 #ifdef IPV6_RECVPKTINFO
3241 if (optname == IPV6_RECVPKTINFO) {
3242 si->pktinfo = AF_INET6;
3244 #endif /* IPV6_PKTINFO */
3246 return 0;
3247 #endif
3248 default:
3249 errno = ENOPROTOOPT;
3250 return -1;
3254 int setsockopt(int s, int level, int optname,
3255 const void *optval, socklen_t optlen)
3257 return swrap_setsockopt(s, level, optname, optval, optlen);
3260 /****************************************************************************
3261 * IOCTL
3262 ***************************************************************************/
3264 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3266 struct socket_info *si = find_socket_info(s);
3267 va_list ap;
3268 int value;
3269 int rc;
3271 if (!si) {
3272 return libc_vioctl(s, r, va);
3275 va_copy(ap, va);
3277 rc = libc_vioctl(s, r, va);
3279 switch (r) {
3280 case FIONREAD:
3281 value = *((int *)va_arg(ap, int *));
3283 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3284 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3285 } else if (value == 0) { /* END OF FILE */
3286 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3288 break;
3291 va_end(ap);
3293 return rc;
3296 #ifdef HAVE_IOCTL_INT
3297 int ioctl(int s, int r, ...)
3298 #else
3299 int ioctl(int s, unsigned long int r, ...)
3300 #endif
3302 va_list va;
3303 int rc;
3305 va_start(va, r);
3307 rc = swrap_vioctl(s, (unsigned long int) r, va);
3309 va_end(va);
3311 return rc;
3314 /*****************
3315 * CMSG
3316 *****************/
3318 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3320 #ifndef CMSG_ALIGN
3321 # ifdef _ALIGN /* BSD */
3322 #define CMSG_ALIGN _ALIGN
3323 # else
3324 #error NO_CMSG_ALIGN
3325 # endif /* _ALIGN */
3326 #endif /* CMSG_ALIGN */
3329 * @brief Add a cmsghdr to a msghdr.
3331 * This is an function to add any type of cmsghdr. It will operate on the
3332 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3333 * the buffer position after the added cmsg element. Hence, this function is
3334 * intended to be used with an intermediate msghdr and not on the original
3335 * one handed in by the client.
3337 * @param[in] msg The msghdr to which to add the cmsg.
3339 * @param[in] level The cmsg level to set.
3341 * @param[in] type The cmsg type to set.
3343 * @param[in] data The cmsg data to set.
3345 * @param[in] len the length of the data to set.
3347 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3348 int level,
3349 int type,
3350 const void *data,
3351 size_t len)
3353 size_t cmlen = CMSG_LEN(len);
3354 size_t cmspace = CMSG_SPACE(len);
3355 uint8_t cmbuf[cmspace];
3356 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3357 uint8_t *p;
3359 memset(cmbuf, 0, cmspace);
3361 if (msg->msg_controllen < cmlen) {
3362 cmlen = msg->msg_controllen;
3363 msg->msg_flags |= MSG_CTRUNC;
3366 if (msg->msg_controllen < cmspace) {
3367 cmspace = msg->msg_controllen;
3371 * We copy the full input data into an intermediate cmsghdr first
3372 * in order to more easily cope with truncation.
3374 cm->cmsg_len = cmlen;
3375 cm->cmsg_level = level;
3376 cm->cmsg_type = type;
3377 memcpy(CMSG_DATA(cm), data, len);
3380 * We now copy the possibly truncated buffer.
3381 * We copy cmlen bytes, but consume cmspace bytes,
3382 * leaving the possible padding uninitialiazed.
3384 p = (uint8_t *)msg->msg_control;
3385 memcpy(p, cm, cmlen);
3386 p += cmspace;
3387 msg->msg_control = p;
3388 msg->msg_controllen -= cmspace;
3390 return;
3393 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3394 struct msghdr *msg)
3396 /* Add packet info */
3397 switch (si->pktinfo) {
3398 #if defined(IP_PKTINFO)
3399 /* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
3400 case AF_INET: {
3401 struct sockaddr_in *sin;
3402 #if defined(HAVE_STRUCT_IN_PKTINFO)
3403 struct in_pktinfo pkt;
3404 #elif defined(IP_RECVDSTADDR)
3405 struct in_addr pkt;
3406 #endif
3408 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3409 sin = (struct sockaddr_in*)si->bindname;
3410 } else {
3411 if (si->myname_len != sizeof(struct sockaddr_in)) {
3412 return 0;
3414 sin = (struct sockaddr_in*)si->myname;
3417 ZERO_STRUCT(pkt);
3419 #if defined(HAVE_STRUCT_IN_PKTINFO)
3420 pkt.ipi_ifindex = socket_wrapper_default_iface();
3421 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3422 #elif defined(IP_RECVDSTADDR)
3423 pkt = sin->sin_addr;
3424 #endif
3426 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3427 &pkt, sizeof(pkt));
3429 break;
3431 #endif /* IP_PKTINFO */
3432 #if defined(HAVE_IPV6)
3433 case AF_INET6: {
3434 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3435 struct sockaddr_in6 *sin6;
3436 struct in6_pktinfo pkt6;
3438 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3439 sin6 = (struct sockaddr_in6*)si->bindname;
3440 } else {
3441 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3442 return 0;
3444 sin6 = (struct sockaddr_in6*)si->myname;
3447 ZERO_STRUCT(pkt6);
3449 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3450 pkt6.ipi6_addr = sin6->sin6_addr;
3452 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3453 &pkt6, sizeof(pkt6));
3454 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3456 break;
3458 #endif /* IPV6_PKTINFO */
3459 default:
3460 return -1;
3463 return 0;
3466 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3467 struct msghdr *omsg)
3469 int rc = 0;
3471 if (si->pktinfo > 0) {
3472 rc = swrap_msghdr_add_pktinfo(si, omsg);
3475 return rc;
3478 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3479 uint8_t **cm_data,
3480 size_t *cm_data_space);
3481 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3482 uint8_t **cm_data,
3483 size_t *cm_data_space);
3485 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3486 uint8_t **cm_data,
3487 size_t *cm_data_space) {
3488 struct cmsghdr *cmsg;
3489 int rc = -1;
3491 /* Nothing to do */
3492 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3493 return 0;
3496 for (cmsg = CMSG_FIRSTHDR(msg);
3497 cmsg != NULL;
3498 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3499 switch (cmsg->cmsg_level) {
3500 case IPPROTO_IP:
3501 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3502 cm_data,
3503 cm_data_space);
3504 break;
3505 default:
3506 rc = swrap_sendmsg_copy_cmsg(cmsg,
3507 cm_data,
3508 cm_data_space);
3509 break;
3513 return rc;
3516 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3517 uint8_t **cm_data,
3518 size_t *cm_data_space)
3520 size_t cmspace;
3521 uint8_t *p;
3523 cmspace =
3524 (*cm_data_space) +
3525 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3527 p = realloc((*cm_data), cmspace);
3528 if (p == NULL) {
3529 return -1;
3531 (*cm_data) = p;
3533 p = (*cm_data) + (*cm_data_space);
3534 *cm_data_space = cmspace;
3536 memcpy(p, cmsg, cmsg->cmsg_len);
3538 return 0;
3541 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3542 uint8_t **cm_data,
3543 size_t *cm_data_space);
3546 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3547 uint8_t **cm_data,
3548 size_t *cm_data_space)
3550 int rc = -1;
3552 switch(cmsg->cmsg_type) {
3553 #ifdef IP_PKTINFO
3554 case IP_PKTINFO:
3555 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3556 cm_data,
3557 cm_data_space);
3558 break;
3559 #endif
3560 #ifdef IPV6_PKTINFO
3561 case IPV6_PKTINFO:
3562 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3563 cm_data,
3564 cm_data_space);
3565 break;
3566 #endif
3567 default:
3568 break;
3571 return rc;
3574 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3575 uint8_t **cm_data,
3576 size_t *cm_data_space)
3578 (void)cmsg; /* unused */
3579 (void)cm_data; /* unused */
3580 (void)cm_data_space; /* unused */
3583 * Passing a IP pktinfo to a unix socket might be rejected by the
3584 * Kernel, at least on FreeBSD. So skip this cmsg.
3586 return 0;
3588 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3590 static ssize_t swrap_sendmsg_before(int fd,
3591 struct socket_info *si,
3592 struct msghdr *msg,
3593 struct iovec *tmp_iov,
3594 struct sockaddr_un *tmp_un,
3595 const struct sockaddr_un **to_un,
3596 const struct sockaddr **to,
3597 int *bcast)
3599 size_t i, len = 0;
3600 ssize_t ret;
3602 if (to_un) {
3603 *to_un = NULL;
3605 if (to) {
3606 *to = NULL;
3608 if (bcast) {
3609 *bcast = 0;
3612 switch (si->type) {
3613 case SOCK_STREAM:
3614 if (!si->connected) {
3615 errno = ENOTCONN;
3616 return -1;
3619 if (msg->msg_iovlen == 0) {
3620 break;
3623 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3624 size_t nlen;
3625 nlen = len + msg->msg_iov[i].iov_len;
3626 if (nlen > SOCKET_MAX_PACKET) {
3627 break;
3630 msg->msg_iovlen = i;
3631 if (msg->msg_iovlen == 0) {
3632 *tmp_iov = msg->msg_iov[0];
3633 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3634 msg->msg_iov = tmp_iov;
3635 msg->msg_iovlen = 1;
3637 break;
3639 case SOCK_DGRAM:
3640 if (si->connected) {
3641 if (msg->msg_name) {
3642 errno = EISCONN;
3643 return -1;
3645 } else {
3646 const struct sockaddr *msg_name;
3647 msg_name = (const struct sockaddr *)msg->msg_name;
3649 if (msg_name == NULL) {
3650 errno = ENOTCONN;
3651 return -1;
3655 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3656 tmp_un, 0, bcast);
3657 if (ret == -1) return -1;
3659 if (to_un) {
3660 *to_un = tmp_un;
3662 if (to) {
3663 *to = msg_name;
3665 msg->msg_name = tmp_un;
3666 msg->msg_namelen = sizeof(*tmp_un);
3669 if (si->bound == 0) {
3670 ret = swrap_auto_bind(fd, si, si->family);
3671 if (ret == -1) {
3672 if (errno == ENOTSOCK) {
3673 swrap_remove_stale(fd);
3674 return -ENOTSOCK;
3675 } else {
3676 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3677 return -1;
3682 if (!si->defer_connect) {
3683 break;
3686 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3687 tmp_un, 0, NULL);
3688 if (ret == -1) return -1;
3690 ret = libc_connect(fd,
3691 (struct sockaddr *)(void *)tmp_un,
3692 sizeof(*tmp_un));
3694 /* to give better errors */
3695 if (ret == -1 && errno == ENOENT) {
3696 errno = EHOSTUNREACH;
3699 if (ret == -1) {
3700 return ret;
3703 si->defer_connect = 0;
3704 break;
3705 default:
3706 errno = EHOSTUNREACH;
3707 return -1;
3710 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3711 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3712 uint8_t *cmbuf = NULL;
3713 size_t cmlen = 0;
3715 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3716 if (ret < 0) {
3717 free(cmbuf);
3718 return -1;
3721 if (cmlen == 0) {
3722 msg->msg_controllen = 0;
3723 msg->msg_control = NULL;
3724 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3725 memcpy(msg->msg_control, cmbuf, cmlen);
3726 msg->msg_controllen = cmlen;
3728 free(cmbuf);
3730 #endif
3732 return 0;
3735 static void swrap_sendmsg_after(int fd,
3736 struct socket_info *si,
3737 struct msghdr *msg,
3738 const struct sockaddr *to,
3739 ssize_t ret)
3741 int saved_errno = errno;
3742 size_t i, len = 0;
3743 uint8_t *buf;
3744 off_t ofs = 0;
3745 size_t avail = 0;
3746 size_t remain;
3748 /* to give better errors */
3749 if (ret == -1) {
3750 if (saved_errno == ENOENT) {
3751 saved_errno = EHOSTUNREACH;
3752 } else if (saved_errno == ENOTSOCK) {
3753 /* If the fd is not a socket, remove it */
3754 swrap_remove_stale(fd);
3758 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3759 avail += msg->msg_iov[i].iov_len;
3762 if (ret == -1) {
3763 remain = MIN(80, avail);
3764 } else {
3765 remain = ret;
3768 /* we capture it as one single packet */
3769 buf = (uint8_t *)malloc(remain);
3770 if (!buf) {
3771 /* we just not capture the packet */
3772 errno = saved_errno;
3773 return;
3776 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3777 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3778 memcpy(buf + ofs,
3779 msg->msg_iov[i].iov_base,
3780 this_time);
3781 ofs += this_time;
3782 remain -= this_time;
3784 len = ofs;
3786 switch (si->type) {
3787 case SOCK_STREAM:
3788 if (ret == -1) {
3789 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3790 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3791 } else {
3792 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3794 break;
3796 case SOCK_DGRAM:
3797 if (si->connected) {
3798 to = si->peername;
3800 if (ret == -1) {
3801 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3802 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3803 } else {
3804 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3806 break;
3809 free(buf);
3810 errno = saved_errno;
3813 static int swrap_recvmsg_before(int fd,
3814 struct socket_info *si,
3815 struct msghdr *msg,
3816 struct iovec *tmp_iov)
3818 size_t i, len = 0;
3819 ssize_t ret;
3821 (void)fd; /* unused */
3823 switch (si->type) {
3824 case SOCK_STREAM:
3825 if (!si->connected) {
3826 errno = ENOTCONN;
3827 return -1;
3830 if (msg->msg_iovlen == 0) {
3831 break;
3834 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3835 size_t nlen;
3836 nlen = len + msg->msg_iov[i].iov_len;
3837 if (nlen > SOCKET_MAX_PACKET) {
3838 break;
3841 msg->msg_iovlen = i;
3842 if (msg->msg_iovlen == 0) {
3843 *tmp_iov = msg->msg_iov[0];
3844 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3845 msg->msg_iov = tmp_iov;
3846 msg->msg_iovlen = 1;
3848 break;
3850 case SOCK_DGRAM:
3851 if (msg->msg_name == NULL) {
3852 errno = EINVAL;
3853 return -1;
3856 if (msg->msg_iovlen == 0) {
3857 break;
3860 if (si->bound == 0) {
3861 ret = swrap_auto_bind(fd, si, si->family);
3862 if (ret == -1) {
3864 * When attempting to read or write to a
3865 * descriptor, if an underlying autobind fails
3866 * because it's not a socket, stop intercepting
3867 * uses of that descriptor.
3869 if (errno == ENOTSOCK) {
3870 swrap_remove_stale(fd);
3871 return -ENOTSOCK;
3872 } else {
3873 SWRAP_LOG(SWRAP_LOG_ERROR,
3874 "swrap_recvmsg_before failed");
3875 return -1;
3879 break;
3880 default:
3881 errno = EHOSTUNREACH;
3882 return -1;
3885 return 0;
3888 static int swrap_recvmsg_after(int fd,
3889 struct socket_info *si,
3890 struct msghdr *msg,
3891 const struct sockaddr_un *un_addr,
3892 socklen_t un_addrlen,
3893 ssize_t ret)
3895 int saved_errno = errno;
3896 size_t i;
3897 uint8_t *buf = NULL;
3898 off_t ofs = 0;
3899 size_t avail = 0;
3900 size_t remain;
3901 int rc;
3903 /* to give better errors */
3904 if (ret == -1) {
3905 if (saved_errno == ENOENT) {
3906 saved_errno = EHOSTUNREACH;
3907 } else if (saved_errno == ENOTSOCK) {
3908 /* If the fd is not a socket, remove it */
3909 swrap_remove_stale(fd);
3913 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3914 avail += msg->msg_iov[i].iov_len;
3917 if (avail == 0) {
3918 rc = 0;
3919 goto done;
3922 if (ret == -1) {
3923 remain = MIN(80, avail);
3924 } else {
3925 remain = ret;
3928 /* we capture it as one single packet */
3929 buf = (uint8_t *)malloc(remain);
3930 if (buf == NULL) {
3931 /* we just not capture the packet */
3932 errno = saved_errno;
3933 return -1;
3936 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3937 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3938 memcpy(buf + ofs,
3939 msg->msg_iov[i].iov_base,
3940 this_time);
3941 ofs += this_time;
3942 remain -= this_time;
3945 switch (si->type) {
3946 case SOCK_STREAM:
3947 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3948 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3949 } else if (ret == 0) { /* END OF FILE */
3950 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3951 } else if (ret > 0) {
3952 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3954 break;
3956 case SOCK_DGRAM:
3957 if (ret == -1) {
3958 break;
3961 if (un_addr != NULL) {
3962 rc = sockaddr_convert_from_un(si,
3963 un_addr,
3964 un_addrlen,
3965 si->family,
3966 msg->msg_name,
3967 &msg->msg_namelen);
3968 if (rc == -1) {
3969 goto done;
3972 swrap_dump_packet(si,
3973 msg->msg_name,
3974 SWRAP_RECVFROM,
3975 buf,
3976 ret);
3977 } else {
3978 swrap_dump_packet(si,
3979 msg->msg_name,
3980 SWRAP_RECV,
3981 buf,
3982 ret);
3985 break;
3988 rc = 0;
3989 done:
3990 free(buf);
3991 errno = saved_errno;
3993 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3994 if (rc == 0 &&
3995 msg->msg_controllen > 0 &&
3996 msg->msg_control != NULL) {
3997 rc = swrap_msghdr_add_socket_info(si, msg);
3998 if (rc < 0) {
3999 return -1;
4002 #endif
4004 return rc;
4007 /****************************************************************************
4008 * RECVFROM
4009 ***************************************************************************/
4011 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4012 struct sockaddr *from, socklen_t *fromlen)
4014 struct sockaddr_un from_addr;
4015 socklen_t from_addrlen = sizeof(from_addr);
4016 ssize_t ret;
4017 struct socket_info *si = find_socket_info(s);
4018 struct sockaddr_storage ss;
4019 socklen_t ss_len = sizeof(ss);
4020 struct msghdr msg;
4021 struct iovec tmp;
4022 int tret;
4024 if (!si) {
4025 return libc_recvfrom(s,
4026 buf,
4027 len,
4028 flags,
4029 from,
4030 fromlen);
4033 tmp.iov_base = buf;
4034 tmp.iov_len = len;
4036 ZERO_STRUCT(msg);
4037 if (from != NULL && fromlen != NULL) {
4038 msg.msg_name = from; /* optional address */
4039 msg.msg_namelen = *fromlen; /* size of address */
4040 } else {
4041 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4042 msg.msg_namelen = ss_len; /* size of address */
4044 msg.msg_iov = &tmp; /* scatter/gather array */
4045 msg.msg_iovlen = 1; /* # elements in msg_iov */
4046 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4047 msg.msg_control = NULL; /* ancillary data, see below */
4048 msg.msg_controllen = 0; /* ancillary data buffer len */
4049 msg.msg_flags = 0; /* flags on received message */
4050 #endif
4052 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4053 if (tret < 0) {
4054 return -1;
4057 buf = msg.msg_iov[0].iov_base;
4058 len = msg.msg_iov[0].iov_len;
4060 /* irix 6.4 forgets to null terminate the sun_path string :-( */
4061 memset(&from_addr, 0, sizeof(from_addr));
4062 ret = libc_recvfrom(s,
4063 buf,
4064 len,
4065 flags,
4066 (struct sockaddr *)(void *)&from_addr,
4067 &from_addrlen);
4068 if (ret == -1) {
4069 return ret;
4072 tret = swrap_recvmsg_after(s,
4074 &msg,
4075 &from_addr,
4076 from_addrlen,
4077 ret);
4078 if (tret != 0) {
4079 return tret;
4082 if (from != NULL && fromlen != NULL) {
4083 *fromlen = msg.msg_namelen;
4086 return ret;
4089 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4090 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4091 struct sockaddr *from, Psocklen_t fromlen)
4092 #else
4093 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4094 struct sockaddr *from, socklen_t *fromlen)
4095 #endif
4097 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4100 /****************************************************************************
4101 * SENDTO
4102 ***************************************************************************/
4104 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4105 const struct sockaddr *to, socklen_t tolen)
4107 struct msghdr msg;
4108 struct iovec tmp;
4109 struct sockaddr_un un_addr;
4110 const struct sockaddr_un *to_un = NULL;
4111 ssize_t ret;
4112 int rc;
4113 struct socket_info *si = find_socket_info(s);
4114 int bcast = 0;
4116 if (!si) {
4117 return libc_sendto(s, buf, len, flags, to, tolen);
4120 tmp.iov_base = discard_const_p(char, buf);
4121 tmp.iov_len = len;
4123 ZERO_STRUCT(msg);
4124 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4125 msg.msg_namelen = tolen; /* size of address */
4126 msg.msg_iov = &tmp; /* scatter/gather array */
4127 msg.msg_iovlen = 1; /* # elements in msg_iov */
4128 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4129 msg.msg_control = NULL; /* ancillary data, see below */
4130 msg.msg_controllen = 0; /* ancillary data buffer len */
4131 msg.msg_flags = 0; /* flags on received message */
4132 #endif
4134 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4135 if (rc < 0) {
4136 return -1;
4139 buf = msg.msg_iov[0].iov_base;
4140 len = msg.msg_iov[0].iov_len;
4142 if (bcast) {
4143 struct stat st;
4144 unsigned int iface;
4145 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4146 char type;
4148 type = SOCKET_TYPE_CHAR_UDP;
4150 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4151 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4152 socket_wrapper_dir(), type, iface, prt);
4153 if (stat(un_addr.sun_path, &st) != 0) continue;
4155 /* ignore the any errors in broadcast sends */
4156 libc_sendto(s,
4157 buf,
4158 len,
4159 flags,
4160 (struct sockaddr *)(void *)&un_addr,
4161 sizeof(un_addr));
4164 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4166 return len;
4169 ret = libc_sendto(s,
4170 buf,
4171 len,
4172 flags,
4173 (struct sockaddr *)msg.msg_name,
4174 msg.msg_namelen);
4176 swrap_sendmsg_after(s, si, &msg, to, ret);
4178 return ret;
4181 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4182 const struct sockaddr *to, socklen_t tolen)
4184 return swrap_sendto(s, buf, len, flags, to, tolen);
4187 /****************************************************************************
4188 * READV
4189 ***************************************************************************/
4191 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4193 struct socket_info *si;
4194 struct msghdr msg;
4195 struct sockaddr_storage ss;
4196 socklen_t ss_len = sizeof(ss);
4197 struct iovec tmp;
4198 ssize_t ret;
4199 int tret;
4201 si = find_socket_info(s);
4202 if (si == NULL) {
4203 return libc_recv(s, buf, len, flags);
4206 tmp.iov_base = buf;
4207 tmp.iov_len = len;
4209 ZERO_STRUCT(msg);
4210 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4211 msg.msg_namelen = ss_len; /* size of address */
4212 msg.msg_iov = &tmp; /* scatter/gather array */
4213 msg.msg_iovlen = 1; /* # elements in msg_iov */
4214 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4215 msg.msg_control = NULL; /* ancillary data, see below */
4216 msg.msg_controllen = 0; /* ancillary data buffer len */
4217 msg.msg_flags = 0; /* flags on received message */
4218 #endif
4220 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4221 if (tret < 0) {
4222 return -1;
4225 buf = msg.msg_iov[0].iov_base;
4226 len = msg.msg_iov[0].iov_len;
4228 ret = libc_recv(s, buf, len, flags);
4230 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4231 if (tret != 0) {
4232 return tret;
4235 return ret;
4238 ssize_t recv(int s, void *buf, size_t len, int flags)
4240 return swrap_recv(s, buf, len, flags);
4243 /****************************************************************************
4244 * READ
4245 ***************************************************************************/
4247 static ssize_t swrap_read(int s, void *buf, size_t len)
4249 struct socket_info *si;
4250 struct msghdr msg;
4251 struct iovec tmp;
4252 struct sockaddr_storage ss;
4253 socklen_t ss_len = sizeof(ss);
4254 ssize_t ret;
4255 int tret;
4257 si = find_socket_info(s);
4258 if (si == NULL) {
4259 return libc_read(s, buf, len);
4262 tmp.iov_base = buf;
4263 tmp.iov_len = len;
4265 ZERO_STRUCT(msg);
4266 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4267 msg.msg_namelen = ss_len; /* size of address */
4268 msg.msg_iov = &tmp; /* scatter/gather array */
4269 msg.msg_iovlen = 1; /* # elements in msg_iov */
4270 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4271 msg.msg_control = NULL; /* ancillary data, see below */
4272 msg.msg_controllen = 0; /* ancillary data buffer len */
4273 msg.msg_flags = 0; /* flags on received message */
4274 #endif
4276 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4277 if (tret < 0) {
4278 if (tret == -ENOTSOCK) {
4279 return libc_read(s, buf, len);
4281 return -1;
4284 buf = msg.msg_iov[0].iov_base;
4285 len = msg.msg_iov[0].iov_len;
4287 ret = libc_read(s, buf, len);
4289 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4290 if (tret != 0) {
4291 return tret;
4294 return ret;
4297 ssize_t read(int s, void *buf, size_t len)
4299 return swrap_read(s, buf, len);
4302 /****************************************************************************
4303 * SEND
4304 ***************************************************************************/
4306 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4308 struct msghdr msg;
4309 struct iovec tmp;
4310 struct sockaddr_un un_addr;
4311 ssize_t ret;
4312 int rc;
4313 struct socket_info *si = find_socket_info(s);
4315 if (!si) {
4316 return libc_send(s, buf, len, flags);
4319 tmp.iov_base = discard_const_p(char, buf);
4320 tmp.iov_len = len;
4322 ZERO_STRUCT(msg);
4323 msg.msg_name = NULL; /* optional address */
4324 msg.msg_namelen = 0; /* size of address */
4325 msg.msg_iov = &tmp; /* scatter/gather array */
4326 msg.msg_iovlen = 1; /* # elements in msg_iov */
4327 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4328 msg.msg_control = NULL; /* ancillary data, see below */
4329 msg.msg_controllen = 0; /* ancillary data buffer len */
4330 msg.msg_flags = 0; /* flags on received message */
4331 #endif
4333 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4334 if (rc < 0) {
4335 return -1;
4338 buf = msg.msg_iov[0].iov_base;
4339 len = msg.msg_iov[0].iov_len;
4341 ret = libc_send(s, buf, len, flags);
4343 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4345 return ret;
4348 ssize_t send(int s, const void *buf, size_t len, int flags)
4350 return swrap_send(s, buf, len, flags);
4353 /****************************************************************************
4354 * RECVMSG
4355 ***************************************************************************/
4357 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4359 struct sockaddr_un from_addr;
4360 socklen_t from_addrlen = sizeof(from_addr);
4361 struct socket_info *si;
4362 struct msghdr msg;
4363 struct iovec tmp;
4364 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4365 size_t msg_ctrllen_filled;
4366 size_t msg_ctrllen_left;
4367 #endif
4369 ssize_t ret;
4370 int rc;
4372 si = find_socket_info(s);
4373 if (si == NULL) {
4374 return libc_recvmsg(s, omsg, flags);
4377 tmp.iov_base = NULL;
4378 tmp.iov_len = 0;
4380 ZERO_STRUCT(msg);
4381 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
4382 msg.msg_namelen = from_addrlen; /* size of address */
4383 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4384 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4385 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4386 msg_ctrllen_filled = 0;
4387 msg_ctrllen_left = omsg->msg_controllen;
4389 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4390 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4391 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4392 #endif
4394 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4395 if (rc < 0) {
4396 return -1;
4399 ret = libc_recvmsg(s, &msg, flags);
4401 msg.msg_name = omsg->msg_name;
4402 msg.msg_namelen = omsg->msg_namelen;
4404 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4405 msg_ctrllen_filled += msg.msg_controllen;
4406 msg_ctrllen_left -= msg.msg_controllen;
4408 if (omsg->msg_control != NULL) {
4409 uint8_t *p;
4411 p = omsg->msg_control;
4412 p += msg_ctrllen_filled;
4414 msg.msg_control = p;
4415 msg.msg_controllen = msg_ctrllen_left;
4416 } else {
4417 msg.msg_control = NULL;
4418 msg.msg_controllen = 0;
4420 #endif
4422 rc = swrap_recvmsg_after(s, si, &msg, &from_addr, from_addrlen, ret);
4423 if (rc != 0) {
4424 return rc;
4427 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4428 if (omsg->msg_control != NULL) {
4429 /* msg.msg_controllen = space left */
4430 msg_ctrllen_left = msg.msg_controllen;
4431 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4434 /* Update the original message length */
4435 omsg->msg_controllen = msg_ctrllen_filled;
4436 omsg->msg_flags = msg.msg_flags;
4437 #endif
4438 omsg->msg_iovlen = msg.msg_iovlen;
4440 return ret;
4443 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4445 return swrap_recvmsg(sockfd, msg, flags);
4448 /****************************************************************************
4449 * SENDMSG
4450 ***************************************************************************/
4452 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4454 struct msghdr msg;
4455 struct iovec tmp;
4456 struct sockaddr_un un_addr;
4457 const struct sockaddr_un *to_un = NULL;
4458 const struct sockaddr *to = NULL;
4459 ssize_t ret;
4460 int rc;
4461 struct socket_info *si = find_socket_info(s);
4462 int bcast = 0;
4464 if (!si) {
4465 return libc_sendmsg(s, omsg, flags);
4468 ZERO_STRUCT(un_addr);
4470 tmp.iov_base = NULL;
4471 tmp.iov_len = 0;
4473 ZERO_STRUCT(msg);
4474 msg.msg_name = omsg->msg_name; /* optional address */
4475 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4476 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4477 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4478 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4479 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4480 /* omsg is a const so use a local buffer for modifications */
4481 uint8_t cmbuf[omsg->msg_controllen];
4483 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4485 msg.msg_control = cmbuf; /* ancillary data, see below */
4486 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4488 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4489 #endif
4491 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4492 if (rc < 0) {
4493 return -1;
4496 if (bcast) {
4497 struct stat st;
4498 unsigned int iface;
4499 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4500 char type;
4501 size_t i, len = 0;
4502 uint8_t *buf;
4503 off_t ofs = 0;
4504 size_t avail = 0;
4505 size_t remain;
4507 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4508 avail += msg.msg_iov[i].iov_len;
4511 len = avail;
4512 remain = avail;
4514 /* we capture it as one single packet */
4515 buf = (uint8_t *)malloc(remain);
4516 if (!buf) {
4517 return -1;
4520 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4521 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4522 memcpy(buf + ofs,
4523 msg.msg_iov[i].iov_base,
4524 this_time);
4525 ofs += this_time;
4526 remain -= this_time;
4529 type = SOCKET_TYPE_CHAR_UDP;
4531 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4532 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4533 socket_wrapper_dir(), type, iface, prt);
4534 if (stat(un_addr.sun_path, &st) != 0) continue;
4536 msg.msg_name = &un_addr; /* optional address */
4537 msg.msg_namelen = sizeof(un_addr); /* size of address */
4539 /* ignore the any errors in broadcast sends */
4540 libc_sendmsg(s, &msg, flags);
4543 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4544 free(buf);
4546 return len;
4549 ret = libc_sendmsg(s, &msg, flags);
4551 swrap_sendmsg_after(s, si, &msg, to, ret);
4553 return ret;
4556 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4558 return swrap_sendmsg(s, omsg, flags);
4561 /****************************************************************************
4562 * READV
4563 ***************************************************************************/
4565 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4567 struct socket_info *si;
4568 struct msghdr msg;
4569 struct iovec tmp;
4570 struct sockaddr_storage ss;
4571 socklen_t ss_len = sizeof(ss);
4572 ssize_t ret;
4573 int rc;
4575 si = find_socket_info(s);
4576 if (si == NULL) {
4577 return libc_readv(s, vector, count);
4580 tmp.iov_base = NULL;
4581 tmp.iov_len = 0;
4583 ZERO_STRUCT(msg);
4584 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4585 msg.msg_namelen = ss_len; /* size of address */
4586 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4587 msg.msg_iovlen = count; /* # elements in msg_iov */
4588 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4589 msg.msg_control = NULL; /* ancillary data, see below */
4590 msg.msg_controllen = 0; /* ancillary data buffer len */
4591 msg.msg_flags = 0; /* flags on received message */
4592 #endif
4594 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4595 if (rc < 0) {
4596 if (rc == -ENOTSOCK) {
4597 return libc_readv(s, vector, count);
4599 return -1;
4602 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4604 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4605 if (rc != 0) {
4606 return rc;
4609 return ret;
4612 ssize_t readv(int s, const struct iovec *vector, int count)
4614 return swrap_readv(s, vector, count);
4617 /****************************************************************************
4618 * WRITEV
4619 ***************************************************************************/
4621 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4623 struct msghdr msg;
4624 struct iovec tmp;
4625 struct sockaddr_un un_addr;
4626 ssize_t ret;
4627 int rc;
4628 struct socket_info *si = find_socket_info(s);
4630 if (!si) {
4631 return libc_writev(s, vector, count);
4634 tmp.iov_base = NULL;
4635 tmp.iov_len = 0;
4637 ZERO_STRUCT(msg);
4638 msg.msg_name = NULL; /* optional address */
4639 msg.msg_namelen = 0; /* size of address */
4640 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4641 msg.msg_iovlen = count; /* # elements in msg_iov */
4642 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4643 msg.msg_control = NULL; /* ancillary data, see below */
4644 msg.msg_controllen = 0; /* ancillary data buffer len */
4645 msg.msg_flags = 0; /* flags on received message */
4646 #endif
4648 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4649 if (rc < 0) {
4650 if (rc == -ENOTSOCK) {
4651 return libc_readv(s, vector, count);
4653 return -1;
4656 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4658 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4660 return ret;
4663 ssize_t writev(int s, const struct iovec *vector, int count)
4665 return swrap_writev(s, vector, count);
4668 /****************************
4669 * CLOSE
4670 ***************************/
4672 static int swrap_close(int fd)
4674 struct socket_info *si = find_socket_info(fd);
4675 struct socket_info_fd *fi;
4676 int ret;
4678 if (!si) {
4679 return libc_close(fd);
4682 for (fi = si->fds; fi; fi = fi->next) {
4683 if (fi->fd == fd) {
4684 SWRAP_DLIST_REMOVE(si->fds, fi);
4685 free(fi);
4686 break;
4690 if (si->fds) {
4691 /* there are still references left */
4692 return libc_close(fd);
4695 SWRAP_DLIST_REMOVE(sockets, si);
4697 if (si->myname && si->peername) {
4698 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4701 ret = libc_close(fd);
4703 if (si->myname && si->peername) {
4704 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4705 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4708 if (si->bindname != NULL) {
4709 free(si->bindname);
4712 if (si->myname) free(si->myname);
4713 if (si->peername) free(si->peername);
4714 if (si->tmp_path) {
4715 unlink(si->tmp_path);
4716 free(si->tmp_path);
4718 free(si);
4720 return ret;
4723 int close(int fd)
4725 return swrap_close(fd);
4728 /****************************
4729 * DUP
4730 ***************************/
4732 static int swrap_dup(int fd)
4734 struct socket_info *si;
4735 struct socket_info_fd *fi;
4737 si = find_socket_info(fd);
4739 if (!si) {
4740 return libc_dup(fd);
4743 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4744 if (fi == NULL) {
4745 errno = ENOMEM;
4746 return -1;
4749 fi->fd = libc_dup(fd);
4750 if (fi->fd == -1) {
4751 int saved_errno = errno;
4752 free(fi);
4753 errno = saved_errno;
4754 return -1;
4757 /* Make sure we don't have an entry for the fd */
4758 swrap_remove_stale(fi->fd);
4760 SWRAP_DLIST_ADD(si->fds, fi);
4761 return fi->fd;
4764 int dup(int fd)
4766 return swrap_dup(fd);
4769 /****************************
4770 * DUP2
4771 ***************************/
4773 static int swrap_dup2(int fd, int newfd)
4775 struct socket_info *si;
4776 struct socket_info_fd *fi;
4778 si = find_socket_info(fd);
4780 if (!si) {
4781 return libc_dup2(fd, newfd);
4784 if (find_socket_info(newfd)) {
4785 /* dup2() does an implicit close of newfd, which we
4786 * need to emulate */
4787 swrap_close(newfd);
4790 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4791 if (fi == NULL) {
4792 errno = ENOMEM;
4793 return -1;
4796 fi->fd = libc_dup2(fd, newfd);
4797 if (fi->fd == -1) {
4798 int saved_errno = errno;
4799 free(fi);
4800 errno = saved_errno;
4801 return -1;
4804 /* Make sure we don't have an entry for the fd */
4805 swrap_remove_stale(fi->fd);
4807 SWRAP_DLIST_ADD(si->fds, fi);
4808 return fi->fd;
4811 int dup2(int fd, int newfd)
4813 return swrap_dup2(fd, newfd);
4816 /****************************
4817 * DUP2
4818 ***************************/
4820 #ifdef HAVE_EVENTFD
4821 static int swrap_eventfd(int count, int flags)
4823 int fd;
4825 fd = libc_eventfd(count, flags);
4826 if (fd != -1) {
4827 swrap_remove_stale(fd);
4830 return fd;
4833 int eventfd(int count, int flags)
4835 return swrap_eventfd(count, flags);
4837 #endif
4839 /****************************
4840 * DESTRUCTOR
4841 ***************************/
4844 * This function is called when the library is unloaded and makes sure that
4845 * sockets get closed and the unix file for the socket are unlinked.
4847 void swrap_destructor(void)
4849 struct socket_info *s = sockets;
4851 while (s != NULL) {
4852 struct socket_info_fd *f = s->fds;
4853 if (f != NULL) {
4854 swrap_close(f->fd);
4856 s = sockets;