s4-winbind: Use winbindd in the AD DC for fl2003dc and plugin_s4_dc
[Samba/wip.git] / lib / socket_wrapper / socket_wrapper.c
blobafd93433aea7ede9106a06ee05962e87cbf000e8
1 /*
2 * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
38 Socket wrapper library. Passes all socket communication over
39 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
40 is set.
43 #include "config.h"
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <sys/ioctl.h>
50 #ifdef HAVE_SYS_FILIO_H
51 #include <sys/filio.h>
52 #endif
53 #ifdef HAVE_SYS_SIGNALFD_H
54 #include <sys/signalfd.h>
55 #endif
56 #ifdef HAVE_SYS_EVENTFD_H
57 #include <sys/eventfd.h>
58 #endif
59 #ifdef HAVE_SYS_TIMERFD_H
60 #include <sys/timerfd.h>
61 #endif
62 #include <sys/uio.h>
63 #include <errno.h>
64 #include <sys/un.h>
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 #include <arpa/inet.h>
68 #include <fcntl.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <stdio.h>
72 #include <stdint.h>
73 #include <stdarg.h>
74 #include <stdbool.h>
75 #include <unistd.h>
76 #ifdef HAVE_GNU_LIB_NAMES_H
77 #include <gnu/lib-names.h>
78 #endif
79 #ifdef HAVE_RPC_RPC_H
80 #include <rpc/rpc.h>
81 #endif
83 enum swrap_dbglvl_e {
84 SWRAP_LOG_ERROR = 0,
85 SWRAP_LOG_WARN,
86 SWRAP_LOG_DEBUG,
87 SWRAP_LOG_TRACE
90 /* GCC have printf type attribute check. */
91 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
92 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
93 #else
94 #define PRINTF_ATTRIBUTE(a,b)
95 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
97 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
98 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
99 #else
100 #define DESTRUCTOR_ATTRIBUTE
101 #endif
103 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
104 # define SWRAP_THREAD __thread
105 #else
106 # define SWRAP_THREAD
107 #endif
109 #ifndef MIN
110 #define MIN(a,b) ((a)<(b)?(a):(b))
111 #endif
113 #ifndef ZERO_STRUCT
114 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
115 #endif
117 #ifndef ZERO_STRUCTP
118 #define ZERO_STRUCTP(x) do { \
119 if ((x) != NULL) \
120 memset((char *)(x), 0, sizeof(*(x))); \
121 } while(0)
122 #endif
124 #ifndef discard_const
125 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
126 #endif
128 #ifndef discard_const_p
129 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
130 #endif
132 #ifdef IPV6_PKTINFO
133 # ifndef IPV6_RECVPKTINFO
134 # define IPV6_RECVPKTINFO IPV6_PKTINFO
135 # endif /* IPV6_RECVPKTINFO */
136 #endif /* IPV6_PKTINFO */
139 * On BSD IP_PKTINFO has a different name because during
140 * the time when they implemented it, there was no RFC.
141 * The name for IPv6 is the same as on Linux.
143 #ifndef IP_PKTINFO
144 # ifdef IP_RECVDSTADDR
145 # define IP_PKTINFO IP_RECVDSTADDR
146 # endif
147 #endif
150 #define SWRAP_DLIST_ADD(list,item) do { \
151 if (!(list)) { \
152 (item)->prev = NULL; \
153 (item)->next = NULL; \
154 (list) = (item); \
155 } else { \
156 (item)->prev = NULL; \
157 (item)->next = (list); \
158 (list)->prev = (item); \
159 (list) = (item); \
161 } while (0)
163 #define SWRAP_DLIST_REMOVE(list,item) do { \
164 if ((list) == (item)) { \
165 (list) = (item)->next; \
166 if (list) { \
167 (list)->prev = NULL; \
169 } else { \
170 if ((item)->prev) { \
171 (item)->prev->next = (item)->next; \
173 if ((item)->next) { \
174 (item)->next->prev = (item)->prev; \
177 (item)->prev = NULL; \
178 (item)->next = NULL; \
179 } while (0)
181 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
182 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
183 #else
184 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
185 #endif
187 /* we need to use a very terse format here as IRIX 6.4 silently
188 truncates names to 16 chars, so if we use a longer name then we
189 can't tell which port a packet came from with recvfrom()
191 with this format we have 8 chars left for the directory name
193 #define SOCKET_FORMAT "%c%02X%04X"
194 #define SOCKET_TYPE_CHAR_TCP 'T'
195 #define SOCKET_TYPE_CHAR_UDP 'U'
196 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
197 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
200 * Cut down to 1500 byte packets for stream sockets,
201 * which makes it easier to format PCAP capture files
202 * (as the caller will simply continue from here)
204 #define SOCKET_MAX_PACKET 1500
206 #define SOCKET_MAX_SOCKETS 1024
208 /* This limit is to avoid broadcast sendto() needing to stat too many
209 * files. It may be raised (with a performance cost) to up to 254
210 * without changing the format above */
211 #define MAX_WRAPPED_INTERFACES 40
213 struct socket_info_fd {
214 struct socket_info_fd *prev, *next;
215 int fd;
218 struct socket_info
220 struct socket_info_fd *fds;
222 int family;
223 int type;
224 int protocol;
225 int bound;
226 int bcast;
227 int is_server;
228 int connected;
229 int defer_connect;
230 int pktinfo;
232 char *tmp_path;
234 struct sockaddr *bindname;
235 socklen_t bindname_len;
237 struct sockaddr *myname;
238 socklen_t myname_len;
240 struct sockaddr *peername;
241 socklen_t peername_len;
243 struct {
244 unsigned long pck_snd;
245 unsigned long pck_rcv;
246 } io;
248 struct socket_info *prev, *next;
252 * File descriptors are shared between threads so we should share socket
253 * information too.
255 struct socket_info *sockets;
257 /* Function prototypes */
259 bool socket_wrapper_enabled(void);
260 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
262 #ifdef NDEBUG
263 # define SWRAP_LOG(...)
264 #else
266 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
267 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __VA_ARGS__)
269 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *format, ...)
271 char buffer[1024];
272 va_list va;
273 const char *d;
274 unsigned int lvl = 0;
276 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
277 if (d != NULL) {
278 lvl = atoi(d);
281 va_start(va, format);
282 vsnprintf(buffer, sizeof(buffer), format, va);
283 va_end(va);
285 if (lvl >= dbglvl) {
286 switch (dbglvl) {
287 case SWRAP_LOG_ERROR:
288 fprintf(stderr,
289 "SWRAP_ERROR(%d): %s\n",
290 (int)getpid(), buffer);
291 break;
292 case SWRAP_LOG_WARN:
293 fprintf(stderr,
294 "SWRAP_WARN(%d): %s\n",
295 (int)getpid(), buffer);
296 break;
297 case SWRAP_LOG_DEBUG:
298 fprintf(stderr,
299 "SWRAP_DEBUG(%d): %s\n",
300 (int)getpid(), buffer);
301 break;
302 case SWRAP_LOG_TRACE:
303 fprintf(stderr,
304 "SWRAP_TRACE(%d): %s\n",
305 (int)getpid(), buffer);
306 break;
310 #endif
312 /*********************************************************
313 * SWRAP LOADING LIBC FUNCTIONS
314 *********************************************************/
316 #include <dlfcn.h>
318 struct swrap_libc_fns {
319 int (*libc_accept)(int sockfd,
320 struct sockaddr *addr,
321 socklen_t *addrlen);
322 int (*libc_bind)(int sockfd,
323 const struct sockaddr *addr,
324 socklen_t addrlen);
325 int (*libc_close)(int fd);
326 int (*libc_connect)(int sockfd,
327 const struct sockaddr *addr,
328 socklen_t addrlen);
329 int (*libc_dup)(int fd);
330 int (*libc_dup2)(int oldfd, int newfd);
331 #ifdef HAVE_EVENTFD
332 int (*libc_eventfd)(int count, int flags);
333 #endif
334 int (*libc_getpeername)(int sockfd,
335 struct sockaddr *addr,
336 socklen_t *addrlen);
337 int (*libc_getsockname)(int sockfd,
338 struct sockaddr *addr,
339 socklen_t *addrlen);
340 int (*libc_getsockopt)(int sockfd,
341 int level,
342 int optname,
343 void *optval,
344 socklen_t *optlen);
345 int (*libc_ioctl)(int d, unsigned long int request, ...);
346 int (*libc_listen)(int sockfd, int backlog);
347 int (*libc_open)(const char *pathname, int flags, mode_t mode);
348 int (*libc_pipe)(int pipefd[2]);
349 int (*libc_read)(int fd, void *buf, size_t count);
350 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
351 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
352 int (*libc_recvfrom)(int sockfd,
353 void *buf,
354 size_t len,
355 int flags,
356 struct sockaddr *src_addr,
357 socklen_t *addrlen);
358 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
359 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
360 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
361 int (*libc_sendto)(int sockfd,
362 const void *buf,
363 size_t len,
364 int flags,
365 const struct sockaddr *dst_addr,
366 socklen_t addrlen);
367 int (*libc_setsockopt)(int sockfd,
368 int level,
369 int optname,
370 const void *optval,
371 socklen_t optlen);
372 #ifdef HAVE_SIGNALFD
373 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
374 #endif
375 int (*libc_socket)(int domain, int type, int protocol);
376 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
377 #ifdef HAVE_TIMERFD_CREATE
378 int (*libc_timerfd_create)(int clockid, int flags);
379 #endif
380 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
383 struct swrap {
384 void *libc_handle;
385 void *libsocket_handle;
387 bool initialised;
388 bool enabled;
390 char *socket_dir;
392 struct swrap_libc_fns fns;
395 static struct swrap swrap;
397 /* prototypes */
398 static const char *socket_wrapper_dir(void);
400 #define LIBC_NAME "libc.so"
402 enum swrap_lib {
403 SWRAP_LIBC,
404 SWRAP_LIBNSL,
405 SWRAP_LIBSOCKET,
408 #ifndef NDEBUG
409 static const char *swrap_str_lib(enum swrap_lib lib)
411 switch (lib) {
412 case SWRAP_LIBC:
413 return "libc";
414 case SWRAP_LIBNSL:
415 return "libnsl";
416 case SWRAP_LIBSOCKET:
417 return "libsocket";
420 /* Compiler would warn us about unhandled enum value if we get here */
421 return "unknown";
423 #endif
425 static void *swrap_load_lib_handle(enum swrap_lib lib)
427 int flags = RTLD_LAZY;
428 void *handle = NULL;
429 int i;
431 #ifdef RTLD_DEEPBIND
432 flags |= RTLD_DEEPBIND;
433 #endif
435 switch (lib) {
436 case SWRAP_LIBNSL:
437 /* FALL TROUGH */
438 case SWRAP_LIBSOCKET:
439 #ifdef HAVE_LIBSOCKET
440 handle = swrap.libsocket_handle;
441 if (handle == NULL) {
442 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
443 char soname[256] = {0};
445 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
446 handle = dlopen(soname, flags);
449 swrap.libsocket_handle = handle;
451 break;
452 #endif
453 /* FALL TROUGH */
454 case SWRAP_LIBC:
455 handle = swrap.libc_handle;
456 #ifdef LIBC_SO
457 if (handle == NULL) {
458 handle = dlopen(LIBC_SO, flags);
460 swrap.libc_handle = handle;
462 #endif
463 if (handle == NULL) {
464 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
465 char soname[256] = {0};
467 snprintf(soname, sizeof(soname), "libc.so.%d", i);
468 handle = dlopen(soname, flags);
471 swrap.libc_handle = handle;
473 break;
476 if (handle == NULL) {
477 #ifdef RTLD_NEXT
478 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
479 #else
480 SWRAP_LOG(SWRAP_LOG_ERROR,
481 "Failed to dlopen library: %s\n",
482 dlerror());
483 exit(-1);
484 #endif
487 return handle;
490 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
492 void *handle;
493 void *func;
495 handle = swrap_load_lib_handle(lib);
497 func = dlsym(handle, fn_name);
498 if (func == NULL) {
499 SWRAP_LOG(SWRAP_LOG_ERROR,
500 "Failed to find %s: %s\n",
501 fn_name, dlerror());
502 exit(-1);
505 SWRAP_LOG(SWRAP_LOG_TRACE,
506 "Loaded %s from %s",
507 fn_name, swrap_str_lib(lib));
508 return func;
511 #define swrap_load_lib_function(lib, fn_name) \
512 if (swrap.fns.libc_##fn_name == NULL) { \
513 *(void **) (&swrap.fns.libc_##fn_name) = \
514 _swrap_load_lib_function(lib, #fn_name); \
519 * IMPORTANT
521 * Functions especially from libc need to be loaded individually, you can't load
522 * all at once or gdb will segfault at startup. The same applies to valgrind and
523 * has probably something todo with with the linker.
524 * So we need load each function at the point it is called the first time.
526 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
528 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
530 return swrap.fns.libc_accept(sockfd, addr, addrlen);
533 static int libc_bind(int sockfd,
534 const struct sockaddr *addr,
535 socklen_t addrlen)
537 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
539 return swrap.fns.libc_bind(sockfd, addr, addrlen);
542 static int libc_close(int fd)
544 swrap_load_lib_function(SWRAP_LIBC, close);
546 return swrap.fns.libc_close(fd);
549 static int libc_connect(int sockfd,
550 const struct sockaddr *addr,
551 socklen_t addrlen)
553 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
555 return swrap.fns.libc_connect(sockfd, addr, addrlen);
558 static int libc_dup(int fd)
560 swrap_load_lib_function(SWRAP_LIBC, dup);
562 return swrap.fns.libc_dup(fd);
565 static int libc_dup2(int oldfd, int newfd)
567 swrap_load_lib_function(SWRAP_LIBC, dup2);
569 return swrap.fns.libc_dup2(oldfd, newfd);
572 #ifdef HAVE_EVENTFD
573 static int libc_eventfd(int count, int flags)
575 swrap_load_lib_function(SWRAP_LIBC, eventfd);
577 return swrap.fns.libc_eventfd(count, flags);
579 #endif
581 static int libc_getpeername(int sockfd,
582 struct sockaddr *addr,
583 socklen_t *addrlen)
585 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
587 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
590 static int libc_getsockname(int sockfd,
591 struct sockaddr *addr,
592 socklen_t *addrlen)
594 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
596 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
599 static int libc_getsockopt(int sockfd,
600 int level,
601 int optname,
602 void *optval,
603 socklen_t *optlen)
605 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
607 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
610 static int libc_vioctl(int d, unsigned long int request, va_list ap)
612 long int args[4];
613 int rc;
614 int i;
616 swrap_load_lib_function(SWRAP_LIBC, ioctl);
618 for (i = 0; i < 4; i++) {
619 args[i] = va_arg(ap, long int);
622 rc = swrap.fns.libc_ioctl(d,
623 request,
624 args[0],
625 args[1],
626 args[2],
627 args[3]);
629 return rc;
632 static int libc_listen(int sockfd, int backlog)
634 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
636 return swrap.fns.libc_listen(sockfd, backlog);
639 static int libc_vopen(const char *pathname, int flags, va_list ap)
641 long int mode = 0;
642 int fd;
644 swrap_load_lib_function(SWRAP_LIBC, open);
646 mode = va_arg(ap, long int);
648 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
650 return fd;
653 static int libc_open(const char *pathname, int flags, ...)
655 va_list ap;
656 int fd;
658 va_start(ap, flags);
659 fd = libc_vopen(pathname, flags, ap);
660 va_end(ap);
662 return fd;
665 static int libc_pipe(int pipefd[2])
667 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
669 return swrap.fns.libc_pipe(pipefd);
672 static int libc_read(int fd, void *buf, size_t count)
674 swrap_load_lib_function(SWRAP_LIBC, read);
676 return swrap.fns.libc_read(fd, buf, count);
679 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
681 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
683 return swrap.fns.libc_readv(fd, iov, iovcnt);
686 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
688 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
690 return swrap.fns.libc_recv(sockfd, buf, len, flags);
693 static int libc_recvfrom(int sockfd,
694 void *buf,
695 size_t len,
696 int flags,
697 struct sockaddr *src_addr,
698 socklen_t *addrlen)
700 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
702 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
705 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
707 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
709 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
712 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
714 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
716 return swrap.fns.libc_send(sockfd, buf, len, flags);
719 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
721 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
723 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
726 static int libc_sendto(int sockfd,
727 const void *buf,
728 size_t len,
729 int flags,
730 const struct sockaddr *dst_addr,
731 socklen_t addrlen)
733 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
735 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
738 static int libc_setsockopt(int sockfd,
739 int level,
740 int optname,
741 const void *optval,
742 socklen_t optlen)
744 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
746 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
749 #ifdef HAVE_SIGNALFD
750 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
752 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
754 return swrap.fns.libc_signalfd(fd, mask, flags);
756 #endif
758 static int libc_socket(int domain, int type, int protocol)
760 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
762 return swrap.fns.libc_socket(domain, type, protocol);
765 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
767 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
769 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
772 #ifdef HAVE_TIMERFD_CREATE
773 static int libc_timerfd_create(int clockid, int flags)
775 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
777 return swrap.fns.libc_timerfd_create(clockid, flags);
779 #endif
781 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
783 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
785 return swrap.fns.libc_writev(fd, iov, iovcnt);
788 /*********************************************************
789 * SWRAP HELPER FUNCTIONS
790 *********************************************************/
792 #ifdef HAVE_IPV6
794 * FD00::5357:5FXX
796 static const struct in6_addr *swrap_ipv6(void)
798 static struct in6_addr v;
799 static int initialized;
800 int ret;
802 if (initialized) {
803 return &v;
805 initialized = 1;
807 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
808 if (ret <= 0) {
809 abort();
812 return &v;
814 #endif
816 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
818 struct sockaddr *ret = (struct sockaddr *)malloc(len);
819 memcpy(ret, data, len);
820 return ret;
823 static void set_port(int family, int prt, struct sockaddr *addr)
825 switch (family) {
826 case AF_INET:
827 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
828 break;
829 #ifdef HAVE_IPV6
830 case AF_INET6:
831 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
832 break;
833 #endif
837 static size_t socket_length(int family)
839 switch (family) {
840 case AF_INET:
841 return sizeof(struct sockaddr_in);
842 #ifdef HAVE_IPV6
843 case AF_INET6:
844 return sizeof(struct sockaddr_in6);
845 #endif
847 return 0;
850 static const char *socket_wrapper_dir(void)
852 const char *s = getenv("SOCKET_WRAPPER_DIR");
853 if (s == NULL) {
854 return NULL;
856 /* TODO use realpath(3) here, when we add support for threads */
857 if (strncmp(s, "./", 2) == 0) {
858 s += 2;
861 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
862 return s;
865 bool socket_wrapper_enabled(void)
867 const char *s = socket_wrapper_dir();
869 return s != NULL ? true : false;
872 static unsigned int socket_wrapper_default_iface(void)
874 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
875 if (s) {
876 unsigned int iface;
877 if (sscanf(s, "%u", &iface) == 1) {
878 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
879 return iface;
884 return 1;/* 127.0.0.1 */
887 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
889 unsigned int iface;
890 unsigned int prt;
891 const char *p;
892 char type;
894 p = strrchr(un->sun_path, '/');
895 if (p) p++; else p = un->sun_path;
897 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
898 errno = EINVAL;
899 return -1;
902 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
903 type, iface, prt);
905 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
906 errno = EINVAL;
907 return -1;
910 if (prt > 0xFFFF) {
911 errno = EINVAL;
912 return -1;
915 switch(type) {
916 case SOCKET_TYPE_CHAR_TCP:
917 case SOCKET_TYPE_CHAR_UDP: {
918 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
920 if ((*len) < sizeof(*in2)) {
921 errno = EINVAL;
922 return -1;
925 memset(in2, 0, sizeof(*in2));
926 in2->sin_family = AF_INET;
927 in2->sin_addr.s_addr = htonl((127<<24) | iface);
928 in2->sin_port = htons(prt);
930 *len = sizeof(*in2);
931 break;
933 #ifdef HAVE_IPV6
934 case SOCKET_TYPE_CHAR_TCP_V6:
935 case SOCKET_TYPE_CHAR_UDP_V6: {
936 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
938 if ((*len) < sizeof(*in2)) {
939 errno = EINVAL;
940 return -1;
943 memset(in2, 0, sizeof(*in2));
944 in2->sin6_family = AF_INET6;
945 in2->sin6_addr = *swrap_ipv6();
946 in2->sin6_addr.s6_addr[15] = iface;
947 in2->sin6_port = htons(prt);
949 *len = sizeof(*in2);
950 break;
952 #endif
953 default:
954 errno = EINVAL;
955 return -1;
958 return 0;
961 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
962 int *bcast)
964 char type = '\0';
965 unsigned int prt;
966 unsigned int iface;
967 int is_bcast = 0;
969 if (bcast) *bcast = 0;
971 switch (inaddr->sa_family) {
972 case AF_INET: {
973 const struct sockaddr_in *in =
974 (const struct sockaddr_in *)(const void *)inaddr;
975 unsigned int addr = ntohl(in->sin_addr.s_addr);
976 char u_type = '\0';
977 char b_type = '\0';
978 char a_type = '\0';
980 switch (si->type) {
981 case SOCK_STREAM:
982 u_type = SOCKET_TYPE_CHAR_TCP;
983 break;
984 case SOCK_DGRAM:
985 u_type = SOCKET_TYPE_CHAR_UDP;
986 a_type = SOCKET_TYPE_CHAR_UDP;
987 b_type = SOCKET_TYPE_CHAR_UDP;
988 break;
989 default:
990 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
991 errno = ESOCKTNOSUPPORT;
992 return -1;
995 prt = ntohs(in->sin_port);
996 if (a_type && addr == 0xFFFFFFFF) {
997 /* 255.255.255.255 only udp */
998 is_bcast = 2;
999 type = a_type;
1000 iface = socket_wrapper_default_iface();
1001 } else if (b_type && addr == 0x7FFFFFFF) {
1002 /* 127.255.255.255 only udp */
1003 is_bcast = 1;
1004 type = b_type;
1005 iface = socket_wrapper_default_iface();
1006 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1007 /* 127.0.0.X */
1008 is_bcast = 0;
1009 type = u_type;
1010 iface = (addr & 0x000000FF);
1011 } else {
1012 errno = ENETUNREACH;
1013 return -1;
1015 if (bcast) *bcast = is_bcast;
1016 break;
1018 #ifdef HAVE_IPV6
1019 case AF_INET6: {
1020 const struct sockaddr_in6 *in =
1021 (const struct sockaddr_in6 *)(const void *)inaddr;
1022 struct in6_addr cmp1, cmp2;
1024 switch (si->type) {
1025 case SOCK_STREAM:
1026 type = SOCKET_TYPE_CHAR_TCP_V6;
1027 break;
1028 case SOCK_DGRAM:
1029 type = SOCKET_TYPE_CHAR_UDP_V6;
1030 break;
1031 default:
1032 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1033 errno = ESOCKTNOSUPPORT;
1034 return -1;
1037 /* XXX no multicast/broadcast */
1039 prt = ntohs(in->sin6_port);
1041 cmp1 = *swrap_ipv6();
1042 cmp2 = in->sin6_addr;
1043 cmp2.s6_addr[15] = 0;
1044 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1045 iface = in->sin6_addr.s6_addr[15];
1046 } else {
1047 errno = ENETUNREACH;
1048 return -1;
1051 break;
1053 #endif
1054 default:
1055 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1056 errno = ENETUNREACH;
1057 return -1;
1060 if (prt == 0) {
1061 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1062 errno = EINVAL;
1063 return -1;
1066 if (is_bcast) {
1067 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1068 socket_wrapper_dir());
1069 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1070 /* the caller need to do more processing */
1071 return 0;
1074 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1075 socket_wrapper_dir(), type, iface, prt);
1076 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1078 return 0;
1081 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1082 int *bcast)
1084 char type = '\0';
1085 unsigned int prt;
1086 unsigned int iface;
1087 struct stat st;
1088 int is_bcast = 0;
1090 if (bcast) *bcast = 0;
1092 switch (si->family) {
1093 case AF_INET: {
1094 const struct sockaddr_in *in =
1095 (const struct sockaddr_in *)(const void *)inaddr;
1096 unsigned int addr = ntohl(in->sin_addr.s_addr);
1097 char u_type = '\0';
1098 char d_type = '\0';
1099 char b_type = '\0';
1100 char a_type = '\0';
1102 prt = ntohs(in->sin_port);
1104 switch (si->type) {
1105 case SOCK_STREAM:
1106 u_type = SOCKET_TYPE_CHAR_TCP;
1107 d_type = SOCKET_TYPE_CHAR_TCP;
1108 break;
1109 case SOCK_DGRAM:
1110 u_type = SOCKET_TYPE_CHAR_UDP;
1111 d_type = SOCKET_TYPE_CHAR_UDP;
1112 a_type = SOCKET_TYPE_CHAR_UDP;
1113 b_type = SOCKET_TYPE_CHAR_UDP;
1114 break;
1115 default:
1116 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1117 errno = ESOCKTNOSUPPORT;
1118 return -1;
1121 if (addr == 0) {
1122 /* 0.0.0.0 */
1123 is_bcast = 0;
1124 type = d_type;
1125 iface = socket_wrapper_default_iface();
1126 } else if (a_type && addr == 0xFFFFFFFF) {
1127 /* 255.255.255.255 only udp */
1128 is_bcast = 2;
1129 type = a_type;
1130 iface = socket_wrapper_default_iface();
1131 } else if (b_type && addr == 0x7FFFFFFF) {
1132 /* 127.255.255.255 only udp */
1133 is_bcast = 1;
1134 type = b_type;
1135 iface = socket_wrapper_default_iface();
1136 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1137 /* 127.0.0.X */
1138 is_bcast = 0;
1139 type = u_type;
1140 iface = (addr & 0x000000FF);
1141 } else {
1142 errno = EADDRNOTAVAIL;
1143 return -1;
1146 /* Store the bind address for connect() */
1147 if (si->bindname == NULL) {
1148 struct sockaddr_in bind_in;
1149 socklen_t blen = sizeof(struct sockaddr_in);
1151 ZERO_STRUCT(bind_in);
1152 bind_in.sin_family = in->sin_family;
1153 bind_in.sin_port = in->sin_port;
1154 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1156 si->bindname = sockaddr_dup(&bind_in, blen);
1157 si->bindname_len = blen;
1160 break;
1162 #ifdef HAVE_IPV6
1163 case AF_INET6: {
1164 const struct sockaddr_in6 *in =
1165 (const struct sockaddr_in6 *)(const void *)inaddr;
1166 struct in6_addr cmp1, cmp2;
1168 switch (si->type) {
1169 case SOCK_STREAM:
1170 type = SOCKET_TYPE_CHAR_TCP_V6;
1171 break;
1172 case SOCK_DGRAM:
1173 type = SOCKET_TYPE_CHAR_UDP_V6;
1174 break;
1175 default:
1176 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1177 errno = ESOCKTNOSUPPORT;
1178 return -1;
1181 /* XXX no multicast/broadcast */
1183 prt = ntohs(in->sin6_port);
1185 cmp1 = *swrap_ipv6();
1186 cmp2 = in->sin6_addr;
1187 cmp2.s6_addr[15] = 0;
1188 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1189 iface = socket_wrapper_default_iface();
1190 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1191 iface = in->sin6_addr.s6_addr[15];
1192 } else {
1193 errno = EADDRNOTAVAIL;
1194 return -1;
1197 /* Store the bind address for connect() */
1198 if (si->bindname == NULL) {
1199 struct sockaddr_in6 bind_in;
1200 socklen_t blen = sizeof(struct sockaddr_in6);
1202 ZERO_STRUCT(bind_in);
1203 bind_in.sin6_family = in->sin6_family;
1204 bind_in.sin6_port = in->sin6_port;
1206 bind_in.sin6_addr = *swrap_ipv6();
1207 bind_in.sin6_addr.s6_addr[15] = iface;
1209 si->bindname = sockaddr_dup(&bind_in, blen);
1210 si->bindname_len = blen;
1213 break;
1215 #endif
1216 default:
1217 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1218 errno = EADDRNOTAVAIL;
1219 return -1;
1223 if (bcast) *bcast = is_bcast;
1225 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1226 errno = EINVAL;
1227 return -1;
1230 if (prt == 0) {
1231 /* handle auto-allocation of ephemeral ports */
1232 for (prt = 5001; prt < 10000; prt++) {
1233 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1234 socket_wrapper_dir(), type, iface, prt);
1235 if (stat(un->sun_path, &st) == 0) continue;
1237 set_port(si->family, prt, si->myname);
1238 set_port(si->family, prt, si->bindname);
1240 break;
1242 if (prt == 10000) {
1243 errno = ENFILE;
1244 return -1;
1248 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1249 socket_wrapper_dir(), type, iface, prt);
1250 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1251 return 0;
1254 static struct socket_info *find_socket_info(int fd)
1256 struct socket_info *i;
1258 for (i = sockets; i; i = i->next) {
1259 struct socket_info_fd *f;
1260 for (f = i->fds; f; f = f->next) {
1261 if (f->fd == fd) {
1262 return i;
1267 return NULL;
1270 #if 0 /* FIXME */
1271 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1273 struct socket_info *s;
1275 /* first catch invalid input */
1276 switch (sa->sa_family) {
1277 case AF_INET:
1278 if (len < sizeof(struct sockaddr_in)) {
1279 return false;
1281 break;
1282 #if HAVE_IPV6
1283 case AF_INET6:
1284 if (len < sizeof(struct sockaddr_in6)) {
1285 return false;
1287 break;
1288 #endif
1289 default:
1290 return false;
1291 break;
1294 for (s = sockets; s != NULL; s = s->next) {
1295 if (s->myname == NULL) {
1296 continue;
1298 if (s->myname->sa_family != sa->sa_family) {
1299 continue;
1301 switch (s->myname->sa_family) {
1302 case AF_INET: {
1303 struct sockaddr_in *sin1, *sin2;
1305 sin1 = (struct sockaddr_in *)s->myname;
1306 sin2 = (struct sockaddr_in *)sa;
1308 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1309 continue;
1311 if (sin1->sin_port != sin2->sin_port) {
1312 continue;
1314 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1315 continue;
1318 /* found */
1319 return true;
1320 break;
1322 #if HAVE_IPV6
1323 case AF_INET6: {
1324 struct sockaddr_in6 *sin1, *sin2;
1326 sin1 = (struct sockaddr_in6 *)s->myname;
1327 sin2 = (struct sockaddr_in6 *)sa;
1329 if (sin1->sin6_port != sin2->sin6_port) {
1330 continue;
1332 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1333 &sin2->sin6_addr))
1335 continue;
1338 /* found */
1339 return true;
1340 break;
1342 #endif
1343 default:
1344 continue;
1345 break;
1350 return false;
1352 #endif
1354 static void swrap_remove_stale(int fd)
1356 struct socket_info *si = find_socket_info(fd);
1357 struct socket_info_fd *fi;
1359 if (si != NULL) {
1360 for (fi = si->fds; fi; fi = fi->next) {
1361 if (fi->fd == fd) {
1362 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1363 SWRAP_DLIST_REMOVE(si->fds, fi);
1364 free(fi);
1365 break;
1369 if (si->fds == NULL) {
1370 SWRAP_DLIST_REMOVE(sockets, si);
1375 static int sockaddr_convert_to_un(struct socket_info *si,
1376 const struct sockaddr *in_addr,
1377 socklen_t in_len,
1378 struct sockaddr_un *out_addr,
1379 int alloc_sock,
1380 int *bcast)
1382 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1384 (void) in_len; /* unused */
1386 if (out_addr == NULL) {
1387 return 0;
1390 out->sa_family = AF_UNIX;
1391 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1392 out->sa_len = sizeof(*out_addr);
1393 #endif
1395 switch (in_addr->sa_family) {
1396 case AF_UNSPEC: {
1397 struct sockaddr_in *sin;
1398 if (si->family != AF_INET) {
1399 break;
1401 if (in_len < sizeof(struct sockaddr_in)) {
1402 break;
1404 sin = (struct sockaddr_in *)in_addr;
1405 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1406 break;
1410 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1411 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1414 /* FALL THROUGH */
1416 case AF_INET:
1417 #ifdef HAVE_IPV6
1418 case AF_INET6:
1419 #endif
1420 switch (si->type) {
1421 case SOCK_STREAM:
1422 case SOCK_DGRAM:
1423 break;
1424 default:
1425 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1426 errno = ESOCKTNOSUPPORT;
1427 return -1;
1429 if (alloc_sock) {
1430 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1431 } else {
1432 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1434 default:
1435 break;
1438 errno = EAFNOSUPPORT;
1439 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1440 return -1;
1443 static int sockaddr_convert_from_un(const struct socket_info *si,
1444 const struct sockaddr_un *in_addr,
1445 socklen_t un_addrlen,
1446 int family,
1447 struct sockaddr *out_addr,
1448 socklen_t *out_addrlen)
1450 int ret;
1452 if (out_addr == NULL || out_addrlen == NULL)
1453 return 0;
1455 if (un_addrlen == 0) {
1456 *out_addrlen = 0;
1457 return 0;
1460 switch (family) {
1461 case AF_INET:
1462 #ifdef HAVE_IPV6
1463 case AF_INET6:
1464 #endif
1465 switch (si->type) {
1466 case SOCK_STREAM:
1467 case SOCK_DGRAM:
1468 break;
1469 default:
1470 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1471 errno = ESOCKTNOSUPPORT;
1472 return -1;
1474 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1475 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1476 out_addr->sa_len = *out_addrlen;
1477 #endif
1478 return ret;
1479 default:
1480 break;
1483 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1484 errno = EAFNOSUPPORT;
1485 return -1;
1488 enum swrap_packet_type {
1489 SWRAP_CONNECT_SEND,
1490 SWRAP_CONNECT_UNREACH,
1491 SWRAP_CONNECT_RECV,
1492 SWRAP_CONNECT_ACK,
1493 SWRAP_ACCEPT_SEND,
1494 SWRAP_ACCEPT_RECV,
1495 SWRAP_ACCEPT_ACK,
1496 SWRAP_RECVFROM,
1497 SWRAP_SENDTO,
1498 SWRAP_SENDTO_UNREACH,
1499 SWRAP_PENDING_RST,
1500 SWRAP_RECV,
1501 SWRAP_RECV_RST,
1502 SWRAP_SEND,
1503 SWRAP_SEND_RST,
1504 SWRAP_CLOSE_SEND,
1505 SWRAP_CLOSE_RECV,
1506 SWRAP_CLOSE_ACK,
1509 struct swrap_file_hdr {
1510 uint32_t magic;
1511 uint16_t version_major;
1512 uint16_t version_minor;
1513 int32_t timezone;
1514 uint32_t sigfigs;
1515 uint32_t frame_max_len;
1516 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1517 uint32_t link_type;
1519 #define SWRAP_FILE_HDR_SIZE 24
1521 struct swrap_packet_frame {
1522 uint32_t seconds;
1523 uint32_t micro_seconds;
1524 uint32_t recorded_length;
1525 uint32_t full_length;
1527 #define SWRAP_PACKET_FRAME_SIZE 16
1529 union swrap_packet_ip {
1530 struct {
1531 uint8_t ver_hdrlen;
1532 uint8_t tos;
1533 uint16_t packet_length;
1534 uint16_t identification;
1535 uint8_t flags;
1536 uint8_t fragment;
1537 uint8_t ttl;
1538 uint8_t protocol;
1539 uint16_t hdr_checksum;
1540 uint32_t src_addr;
1541 uint32_t dest_addr;
1542 } v4;
1543 #define SWRAP_PACKET_IP_V4_SIZE 20
1544 struct {
1545 uint8_t ver_prio;
1546 uint8_t flow_label_high;
1547 uint16_t flow_label_low;
1548 uint16_t payload_length;
1549 uint8_t next_header;
1550 uint8_t hop_limit;
1551 uint8_t src_addr[16];
1552 uint8_t dest_addr[16];
1553 } v6;
1554 #define SWRAP_PACKET_IP_V6_SIZE 40
1556 #define SWRAP_PACKET_IP_SIZE 40
1558 union swrap_packet_payload {
1559 struct {
1560 uint16_t source_port;
1561 uint16_t dest_port;
1562 uint32_t seq_num;
1563 uint32_t ack_num;
1564 uint8_t hdr_length;
1565 uint8_t control;
1566 uint16_t window;
1567 uint16_t checksum;
1568 uint16_t urg;
1569 } tcp;
1570 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1571 struct {
1572 uint16_t source_port;
1573 uint16_t dest_port;
1574 uint16_t length;
1575 uint16_t checksum;
1576 } udp;
1577 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1578 struct {
1579 uint8_t type;
1580 uint8_t code;
1581 uint16_t checksum;
1582 uint32_t unused;
1583 } icmp4;
1584 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1585 struct {
1586 uint8_t type;
1587 uint8_t code;
1588 uint16_t checksum;
1589 uint32_t unused;
1590 } icmp6;
1591 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1593 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1595 #define SWRAP_PACKET_MIN_ALLOC \
1596 (SWRAP_PACKET_FRAME_SIZE + \
1597 SWRAP_PACKET_IP_SIZE + \
1598 SWRAP_PACKET_PAYLOAD_SIZE)
1600 static const char *socket_wrapper_pcap_file(void)
1602 static int initialized = 0;
1603 static const char *s = NULL;
1604 static const struct swrap_file_hdr h;
1605 static const struct swrap_packet_frame f;
1606 static const union swrap_packet_ip i;
1607 static const union swrap_packet_payload p;
1609 if (initialized == 1) {
1610 return s;
1612 initialized = 1;
1615 * TODO: don't use the structs use plain buffer offsets
1616 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1618 * for now make sure we disable PCAP support
1619 * if the struct has alignment!
1621 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1622 return NULL;
1624 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1625 return NULL;
1627 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1628 return NULL;
1630 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1631 return NULL;
1633 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1634 return NULL;
1636 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1637 return NULL;
1639 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1640 return NULL;
1642 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1643 return NULL;
1645 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1646 return NULL;
1648 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1649 return NULL;
1652 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1653 if (s == NULL) {
1654 return NULL;
1656 if (strncmp(s, "./", 2) == 0) {
1657 s += 2;
1659 return s;
1662 static uint8_t *swrap_packet_init(struct timeval *tval,
1663 const struct sockaddr *src,
1664 const struct sockaddr *dest,
1665 int socket_type,
1666 const uint8_t *payload,
1667 size_t payload_len,
1668 unsigned long tcp_seqno,
1669 unsigned long tcp_ack,
1670 unsigned char tcp_ctl,
1671 int unreachable,
1672 size_t *_packet_len)
1674 uint8_t *base;
1675 uint8_t *buf;
1676 struct swrap_packet_frame *frame;
1677 union swrap_packet_ip *ip;
1678 union swrap_packet_payload *pay;
1679 size_t packet_len;
1680 size_t alloc_len;
1681 size_t nonwire_len = sizeof(*frame);
1682 size_t wire_hdr_len = 0;
1683 size_t wire_len = 0;
1684 size_t ip_hdr_len = 0;
1685 size_t icmp_hdr_len = 0;
1686 size_t icmp_truncate_len = 0;
1687 uint8_t protocol = 0, icmp_protocol = 0;
1688 const struct sockaddr_in *src_in = NULL;
1689 const struct sockaddr_in *dest_in = NULL;
1690 #ifdef HAVE_IPV6
1691 const struct sockaddr_in6 *src_in6 = NULL;
1692 const struct sockaddr_in6 *dest_in6 = NULL;
1693 #endif
1694 uint16_t src_port;
1695 uint16_t dest_port;
1697 switch (src->sa_family) {
1698 case AF_INET:
1699 src_in = (const struct sockaddr_in *)src;
1700 dest_in = (const struct sockaddr_in *)dest;
1701 src_port = src_in->sin_port;
1702 dest_port = dest_in->sin_port;
1703 ip_hdr_len = sizeof(ip->v4);
1704 break;
1705 #ifdef HAVE_IPV6
1706 case AF_INET6:
1707 src_in6 = (const struct sockaddr_in6 *)src;
1708 dest_in6 = (const struct sockaddr_in6 *)dest;
1709 src_port = src_in6->sin6_port;
1710 dest_port = dest_in6->sin6_port;
1711 ip_hdr_len = sizeof(ip->v6);
1712 break;
1713 #endif
1714 default:
1715 return NULL;
1718 switch (socket_type) {
1719 case SOCK_STREAM:
1720 protocol = 0x06; /* TCP */
1721 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1722 wire_len = wire_hdr_len + payload_len;
1723 break;
1725 case SOCK_DGRAM:
1726 protocol = 0x11; /* UDP */
1727 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1728 wire_len = wire_hdr_len + payload_len;
1729 break;
1731 default:
1732 return NULL;
1735 if (unreachable) {
1736 icmp_protocol = protocol;
1737 switch (src->sa_family) {
1738 case AF_INET:
1739 protocol = 0x01; /* ICMPv4 */
1740 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1741 break;
1742 #ifdef HAVE_IPV6
1743 case AF_INET6:
1744 protocol = 0x3A; /* ICMPv6 */
1745 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1746 break;
1747 #endif
1749 if (wire_len > 64 ) {
1750 icmp_truncate_len = wire_len - 64;
1752 wire_hdr_len += icmp_hdr_len;
1753 wire_len += icmp_hdr_len;
1756 packet_len = nonwire_len + wire_len;
1757 alloc_len = packet_len;
1758 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1759 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1762 base = (uint8_t *)malloc(alloc_len);
1763 if (base == NULL) {
1764 return NULL;
1766 memset(base, 0x0, alloc_len);
1768 buf = base;
1770 frame = (struct swrap_packet_frame *)buf;
1771 frame->seconds = tval->tv_sec;
1772 frame->micro_seconds = tval->tv_usec;
1773 frame->recorded_length = wire_len - icmp_truncate_len;
1774 frame->full_length = wire_len - icmp_truncate_len;
1775 buf += SWRAP_PACKET_FRAME_SIZE;
1777 ip = (union swrap_packet_ip *)buf;
1778 switch (src->sa_family) {
1779 case AF_INET:
1780 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1781 ip->v4.tos = 0x00;
1782 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1783 ip->v4.identification = htons(0xFFFF);
1784 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1785 ip->v4.fragment = htons(0x0000);
1786 ip->v4.ttl = 0xFF;
1787 ip->v4.protocol = protocol;
1788 ip->v4.hdr_checksum = htons(0x0000);
1789 ip->v4.src_addr = src_in->sin_addr.s_addr;
1790 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1791 buf += SWRAP_PACKET_IP_V4_SIZE;
1792 break;
1793 #ifdef HAVE_IPV6
1794 case AF_INET6:
1795 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1796 ip->v6.flow_label_high = 0x00;
1797 ip->v6.flow_label_low = 0x0000;
1798 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1799 ip->v6.next_header = protocol;
1800 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1801 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1802 buf += SWRAP_PACKET_IP_V6_SIZE;
1803 break;
1804 #endif
1807 if (unreachable) {
1808 pay = (union swrap_packet_payload *)buf;
1809 switch (src->sa_family) {
1810 case AF_INET:
1811 pay->icmp4.type = 0x03; /* destination unreachable */
1812 pay->icmp4.code = 0x01; /* host unreachable */
1813 pay->icmp4.checksum = htons(0x0000);
1814 pay->icmp4.unused = htonl(0x00000000);
1815 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1817 /* set the ip header in the ICMP payload */
1818 ip = (union swrap_packet_ip *)buf;
1819 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1820 ip->v4.tos = 0x00;
1821 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1822 ip->v4.identification = htons(0xFFFF);
1823 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1824 ip->v4.fragment = htons(0x0000);
1825 ip->v4.ttl = 0xFF;
1826 ip->v4.protocol = icmp_protocol;
1827 ip->v4.hdr_checksum = htons(0x0000);
1828 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1829 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1830 buf += SWRAP_PACKET_IP_V4_SIZE;
1832 src_port = dest_in->sin_port;
1833 dest_port = src_in->sin_port;
1834 break;
1835 #ifdef HAVE_IPV6
1836 case AF_INET6:
1837 pay->icmp6.type = 0x01; /* destination unreachable */
1838 pay->icmp6.code = 0x03; /* address unreachable */
1839 pay->icmp6.checksum = htons(0x0000);
1840 pay->icmp6.unused = htonl(0x00000000);
1841 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1843 /* set the ip header in the ICMP payload */
1844 ip = (union swrap_packet_ip *)buf;
1845 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1846 ip->v6.flow_label_high = 0x00;
1847 ip->v6.flow_label_low = 0x0000;
1848 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1849 ip->v6.next_header = protocol;
1850 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1851 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1852 buf += SWRAP_PACKET_IP_V6_SIZE;
1854 src_port = dest_in6->sin6_port;
1855 dest_port = src_in6->sin6_port;
1856 break;
1857 #endif
1861 pay = (union swrap_packet_payload *)buf;
1863 switch (socket_type) {
1864 case SOCK_STREAM:
1865 pay->tcp.source_port = src_port;
1866 pay->tcp.dest_port = dest_port;
1867 pay->tcp.seq_num = htonl(tcp_seqno);
1868 pay->tcp.ack_num = htonl(tcp_ack);
1869 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1870 pay->tcp.control = tcp_ctl;
1871 pay->tcp.window = htons(0x7FFF);
1872 pay->tcp.checksum = htons(0x0000);
1873 pay->tcp.urg = htons(0x0000);
1874 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1876 break;
1878 case SOCK_DGRAM:
1879 pay->udp.source_port = src_port;
1880 pay->udp.dest_port = dest_port;
1881 pay->udp.length = htons(8 + payload_len);
1882 pay->udp.checksum = htons(0x0000);
1883 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1885 break;
1888 if (payload && payload_len > 0) {
1889 memcpy(buf, payload, payload_len);
1892 *_packet_len = packet_len - icmp_truncate_len;
1893 return base;
1896 static int swrap_get_pcap_fd(const char *fname)
1898 static int fd = -1;
1900 if (fd != -1) return fd;
1902 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1903 if (fd != -1) {
1904 struct swrap_file_hdr file_hdr;
1905 file_hdr.magic = 0xA1B2C3D4;
1906 file_hdr.version_major = 0x0002;
1907 file_hdr.version_minor = 0x0004;
1908 file_hdr.timezone = 0x00000000;
1909 file_hdr.sigfigs = 0x00000000;
1910 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
1911 file_hdr.link_type = 0x0065; /* 101 RAW IP */
1913 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1914 close(fd);
1915 fd = -1;
1917 return fd;
1920 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
1922 return fd;
1925 static uint8_t *swrap_marshall_packet(struct socket_info *si,
1926 const struct sockaddr *addr,
1927 enum swrap_packet_type type,
1928 const void *buf, size_t len,
1929 size_t *packet_len)
1931 const struct sockaddr *src_addr;
1932 const struct sockaddr *dest_addr;
1933 unsigned long tcp_seqno = 0;
1934 unsigned long tcp_ack = 0;
1935 unsigned char tcp_ctl = 0;
1936 int unreachable = 0;
1938 struct timeval tv;
1940 switch (si->family) {
1941 case AF_INET:
1942 break;
1943 #ifdef HAVE_IPV6
1944 case AF_INET6:
1945 break;
1946 #endif
1947 default:
1948 return NULL;
1951 switch (type) {
1952 case SWRAP_CONNECT_SEND:
1953 if (si->type != SOCK_STREAM) return NULL;
1955 src_addr = si->myname;
1956 dest_addr = addr;
1958 tcp_seqno = si->io.pck_snd;
1959 tcp_ack = si->io.pck_rcv;
1960 tcp_ctl = 0x02; /* SYN */
1962 si->io.pck_snd += 1;
1964 break;
1966 case SWRAP_CONNECT_RECV:
1967 if (si->type != SOCK_STREAM) return NULL;
1969 dest_addr = si->myname;
1970 src_addr = addr;
1972 tcp_seqno = si->io.pck_rcv;
1973 tcp_ack = si->io.pck_snd;
1974 tcp_ctl = 0x12; /** SYN,ACK */
1976 si->io.pck_rcv += 1;
1978 break;
1980 case SWRAP_CONNECT_UNREACH:
1981 if (si->type != SOCK_STREAM) return NULL;
1983 dest_addr = si->myname;
1984 src_addr = addr;
1986 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1987 tcp_seqno = si->io.pck_snd - 1;
1988 tcp_ack = si->io.pck_rcv;
1989 tcp_ctl = 0x02; /* SYN */
1990 unreachable = 1;
1992 break;
1994 case SWRAP_CONNECT_ACK:
1995 if (si->type != SOCK_STREAM) return NULL;
1997 src_addr = si->myname;
1998 dest_addr = addr;
2000 tcp_seqno = si->io.pck_snd;
2001 tcp_ack = si->io.pck_rcv;
2002 tcp_ctl = 0x10; /* ACK */
2004 break;
2006 case SWRAP_ACCEPT_SEND:
2007 if (si->type != SOCK_STREAM) return NULL;
2009 dest_addr = si->myname;
2010 src_addr = addr;
2012 tcp_seqno = si->io.pck_rcv;
2013 tcp_ack = si->io.pck_snd;
2014 tcp_ctl = 0x02; /* SYN */
2016 si->io.pck_rcv += 1;
2018 break;
2020 case SWRAP_ACCEPT_RECV:
2021 if (si->type != SOCK_STREAM) return NULL;
2023 src_addr = si->myname;
2024 dest_addr = addr;
2026 tcp_seqno = si->io.pck_snd;
2027 tcp_ack = si->io.pck_rcv;
2028 tcp_ctl = 0x12; /* SYN,ACK */
2030 si->io.pck_snd += 1;
2032 break;
2034 case SWRAP_ACCEPT_ACK:
2035 if (si->type != SOCK_STREAM) return NULL;
2037 dest_addr = si->myname;
2038 src_addr = addr;
2040 tcp_seqno = si->io.pck_rcv;
2041 tcp_ack = si->io.pck_snd;
2042 tcp_ctl = 0x10; /* ACK */
2044 break;
2046 case SWRAP_SEND:
2047 src_addr = si->myname;
2048 dest_addr = si->peername;
2050 tcp_seqno = si->io.pck_snd;
2051 tcp_ack = si->io.pck_rcv;
2052 tcp_ctl = 0x18; /* PSH,ACK */
2054 si->io.pck_snd += len;
2056 break;
2058 case SWRAP_SEND_RST:
2059 dest_addr = si->myname;
2060 src_addr = si->peername;
2062 if (si->type == SOCK_DGRAM) {
2063 return swrap_marshall_packet(si, si->peername,
2064 SWRAP_SENDTO_UNREACH,
2065 buf, len, packet_len);
2068 tcp_seqno = si->io.pck_rcv;
2069 tcp_ack = si->io.pck_snd;
2070 tcp_ctl = 0x14; /** RST,ACK */
2072 break;
2074 case SWRAP_PENDING_RST:
2075 dest_addr = si->myname;
2076 src_addr = si->peername;
2078 if (si->type == SOCK_DGRAM) {
2079 return NULL;
2082 tcp_seqno = si->io.pck_rcv;
2083 tcp_ack = si->io.pck_snd;
2084 tcp_ctl = 0x14; /* RST,ACK */
2086 break;
2088 case SWRAP_RECV:
2089 dest_addr = si->myname;
2090 src_addr = si->peername;
2092 tcp_seqno = si->io.pck_rcv;
2093 tcp_ack = si->io.pck_snd;
2094 tcp_ctl = 0x18; /* PSH,ACK */
2096 si->io.pck_rcv += len;
2098 break;
2100 case SWRAP_RECV_RST:
2101 dest_addr = si->myname;
2102 src_addr = si->peername;
2104 if (si->type == SOCK_DGRAM) {
2105 return NULL;
2108 tcp_seqno = si->io.pck_rcv;
2109 tcp_ack = si->io.pck_snd;
2110 tcp_ctl = 0x14; /* RST,ACK */
2112 break;
2114 case SWRAP_SENDTO:
2115 src_addr = si->myname;
2116 dest_addr = addr;
2118 si->io.pck_snd += len;
2120 break;
2122 case SWRAP_SENDTO_UNREACH:
2123 dest_addr = si->myname;
2124 src_addr = addr;
2126 unreachable = 1;
2128 break;
2130 case SWRAP_RECVFROM:
2131 dest_addr = si->myname;
2132 src_addr = addr;
2134 si->io.pck_rcv += len;
2136 break;
2138 case SWRAP_CLOSE_SEND:
2139 if (si->type != SOCK_STREAM) return NULL;
2141 src_addr = si->myname;
2142 dest_addr = si->peername;
2144 tcp_seqno = si->io.pck_snd;
2145 tcp_ack = si->io.pck_rcv;
2146 tcp_ctl = 0x11; /* FIN, ACK */
2148 si->io.pck_snd += 1;
2150 break;
2152 case SWRAP_CLOSE_RECV:
2153 if (si->type != SOCK_STREAM) return NULL;
2155 dest_addr = si->myname;
2156 src_addr = si->peername;
2158 tcp_seqno = si->io.pck_rcv;
2159 tcp_ack = si->io.pck_snd;
2160 tcp_ctl = 0x11; /* FIN,ACK */
2162 si->io.pck_rcv += 1;
2164 break;
2166 case SWRAP_CLOSE_ACK:
2167 if (si->type != SOCK_STREAM) return NULL;
2169 src_addr = si->myname;
2170 dest_addr = si->peername;
2172 tcp_seqno = si->io.pck_snd;
2173 tcp_ack = si->io.pck_rcv;
2174 tcp_ctl = 0x10; /* ACK */
2176 break;
2177 default:
2178 return NULL;
2181 swrapGetTimeOfDay(&tv);
2183 return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
2184 (const uint8_t *)buf, len,
2185 tcp_seqno, tcp_ack, tcp_ctl, unreachable,
2186 packet_len);
2189 static void swrap_dump_packet(struct socket_info *si,
2190 const struct sockaddr *addr,
2191 enum swrap_packet_type type,
2192 const void *buf, size_t len)
2194 const char *file_name;
2195 uint8_t *packet;
2196 size_t packet_len = 0;
2197 int fd;
2199 file_name = socket_wrapper_pcap_file();
2200 if (!file_name) {
2201 return;
2204 packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
2205 if (!packet) {
2206 return;
2209 fd = swrap_get_pcap_fd(file_name);
2210 if (fd != -1) {
2211 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2212 free(packet);
2213 return;
2217 free(packet);
2220 /****************************************************************************
2221 * SIGNALFD
2222 ***************************************************************************/
2224 #ifdef HAVE_SIGNALFD
2225 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2227 int rc;
2229 rc = libc_signalfd(fd, mask, flags);
2230 if (rc != -1) {
2231 swrap_remove_stale(fd);
2234 return rc;
2237 int signalfd(int fd, const sigset_t *mask, int flags)
2239 return swrap_signalfd(fd, mask, flags);
2241 #endif
2243 /****************************************************************************
2244 * SOCKET
2245 ***************************************************************************/
2247 static int swrap_socket(int family, int type, int protocol)
2249 struct socket_info *si;
2250 struct socket_info_fd *fi;
2251 int fd;
2252 int real_type = type;
2255 * Remove possible addition flags passed to socket() so
2256 * do not fail checking the type.
2257 * See https://lwn.net/Articles/281965/
2259 #ifdef SOCK_CLOEXEC
2260 real_type &= ~SOCK_CLOEXEC;
2261 #endif
2262 #ifdef SOCK_NONBLOCK
2263 real_type &= ~SOCK_NONBLOCK;
2264 #endif
2266 if (!socket_wrapper_enabled()) {
2267 return libc_socket(family, type, protocol);
2270 switch (family) {
2271 case AF_INET:
2272 #ifdef HAVE_IPV6
2273 case AF_INET6:
2274 #endif
2275 break;
2276 case AF_UNIX:
2277 return libc_socket(family, type, protocol);
2278 default:
2279 errno = EAFNOSUPPORT;
2280 return -1;
2283 switch (real_type) {
2284 case SOCK_STREAM:
2285 break;
2286 case SOCK_DGRAM:
2287 break;
2288 default:
2289 errno = EPROTONOSUPPORT;
2290 return -1;
2293 switch (protocol) {
2294 case 0:
2295 break;
2296 case 6:
2297 if (real_type == SOCK_STREAM) {
2298 break;
2300 /*fall through*/
2301 case 17:
2302 if (real_type == SOCK_DGRAM) {
2303 break;
2305 /*fall through*/
2306 default:
2307 errno = EPROTONOSUPPORT;
2308 return -1;
2312 * We must call libc_socket with type, from the caller, not the version
2313 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2315 fd = libc_socket(AF_UNIX, type, 0);
2317 if (fd == -1) {
2318 return -1;
2321 /* Check if we have a stale fd and remove it */
2322 si = find_socket_info(fd);
2323 if (si != NULL) {
2324 swrap_remove_stale(fd);
2327 si = (struct socket_info *)malloc(sizeof(struct socket_info));
2328 memset(si, 0, sizeof(struct socket_info));
2329 if (si == NULL) {
2330 errno = ENOMEM;
2331 return -1;
2334 si->family = family;
2336 /* however, the rest of the socket_wrapper code expects just
2337 * the type, not the flags */
2338 si->type = real_type;
2339 si->protocol = protocol;
2342 * Setup myname so getsockname() can succeed to find out the socket
2343 * type.
2345 switch(si->family) {
2346 case AF_INET: {
2347 struct sockaddr_in sin = {
2348 .sin_family = AF_INET,
2351 si->myname_len = sizeof(struct sockaddr_in);
2352 si->myname = sockaddr_dup(&sin, si->myname_len);
2353 break;
2355 case AF_INET6: {
2356 struct sockaddr_in6 sin6 = {
2357 .sin6_family = AF_INET6,
2360 si->myname_len = sizeof(struct sockaddr_in6);
2361 si->myname = sockaddr_dup(&sin6, si->myname_len);
2362 break;
2364 default:
2365 free(si);
2366 errno = EINVAL;
2367 return -1;
2370 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2371 if (fi == NULL) {
2372 if (si->myname != NULL) {
2373 free (si->myname);
2375 free(si);
2376 errno = ENOMEM;
2377 return -1;
2380 fi->fd = fd;
2382 SWRAP_DLIST_ADD(si->fds, fi);
2383 SWRAP_DLIST_ADD(sockets, si);
2385 return fd;
2388 int socket(int family, int type, int protocol)
2390 return swrap_socket(family, type, protocol);
2393 /****************************************************************************
2394 * SOCKETPAIR
2395 ***************************************************************************/
2397 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2399 int rc;
2401 rc = libc_socketpair(family, type, protocol, sv);
2402 if (rc != -1) {
2403 swrap_remove_stale(sv[0]);
2404 swrap_remove_stale(sv[1]);
2407 return rc;
2410 int socketpair(int family, int type, int protocol, int sv[2])
2412 return swrap_socketpair(family, type, protocol, sv);
2415 /****************************************************************************
2416 * SOCKETPAIR
2417 ***************************************************************************/
2419 #ifdef HAVE_TIMERFD_CREATE
2420 static int swrap_timerfd_create(int clockid, int flags)
2422 int fd;
2424 fd = libc_timerfd_create(clockid, flags);
2425 if (fd != -1) {
2426 swrap_remove_stale(fd);
2429 return fd;
2432 int timerfd_create(int clockid, int flags)
2434 return swrap_timerfd_create(clockid, flags);
2436 #endif
2438 /****************************************************************************
2439 * PIPE
2440 ***************************************************************************/
2442 static int swrap_pipe(int pipefd[2])
2444 int rc;
2446 rc = libc_pipe(pipefd);
2447 if (rc != -1) {
2448 swrap_remove_stale(pipefd[0]);
2449 swrap_remove_stale(pipefd[1]);
2452 return rc;
2455 int pipe(int pipefd[2])
2457 return swrap_pipe(pipefd);
2460 /****************************************************************************
2461 * ACCEPT
2462 ***************************************************************************/
2464 static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2466 struct socket_info *parent_si, *child_si;
2467 struct socket_info_fd *child_fi;
2468 int fd;
2469 struct sockaddr_un un_addr;
2470 socklen_t un_addrlen = sizeof(un_addr);
2471 struct sockaddr_un un_my_addr;
2472 socklen_t un_my_addrlen = sizeof(un_my_addr);
2473 struct sockaddr *my_addr;
2474 socklen_t my_addrlen, len;
2475 int ret;
2477 parent_si = find_socket_info(s);
2478 if (!parent_si) {
2479 return libc_accept(s, addr, addrlen);
2483 * assume out sockaddr have the same size as the in parent
2484 * socket family
2486 my_addrlen = socket_length(parent_si->family);
2487 if (my_addrlen <= 0) {
2488 errno = EINVAL;
2489 return -1;
2492 my_addr = (struct sockaddr *)malloc(my_addrlen);
2493 if (my_addr == NULL) {
2494 return -1;
2497 memset(&un_addr, 0, sizeof(un_addr));
2498 memset(&un_my_addr, 0, sizeof(un_my_addr));
2500 ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen);
2501 if (ret == -1) {
2502 if (errno == ENOTSOCK) {
2503 /* Remove stale fds */
2504 swrap_remove_stale(s);
2506 free(my_addr);
2507 return ret;
2510 fd = ret;
2512 len = my_addrlen;
2513 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
2514 parent_si->family, my_addr, &len);
2515 if (ret == -1) {
2516 free(my_addr);
2517 close(fd);
2518 return ret;
2521 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
2522 memset(child_si, 0, sizeof(struct socket_info));
2524 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2525 if (child_fi == NULL) {
2526 free(child_si);
2527 free(my_addr);
2528 close(fd);
2529 errno = ENOMEM;
2530 return -1;
2533 child_fi->fd = fd;
2535 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2537 child_si->family = parent_si->family;
2538 child_si->type = parent_si->type;
2539 child_si->protocol = parent_si->protocol;
2540 child_si->bound = 1;
2541 child_si->is_server = 1;
2542 child_si->connected = 1;
2544 child_si->peername_len = len;
2545 child_si->peername = sockaddr_dup(my_addr, len);
2547 if (addr != NULL && addrlen != NULL) {
2548 size_t copy_len = MIN(*addrlen, len);
2549 if (copy_len > 0) {
2550 memcpy(addr, my_addr, copy_len);
2552 *addrlen = len;
2555 ret = libc_getsockname(fd,
2556 (struct sockaddr *)(void *)&un_my_addr,
2557 &un_my_addrlen);
2558 if (ret == -1) {
2559 free(child_fi);
2560 free(child_si);
2561 free(my_addr);
2562 close(fd);
2563 return ret;
2566 len = my_addrlen;
2567 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
2568 child_si->family, my_addr, &len);
2569 if (ret == -1) {
2570 free(child_fi);
2571 free(child_si);
2572 free(my_addr);
2573 close(fd);
2574 return ret;
2577 SWRAP_LOG(SWRAP_LOG_TRACE,
2578 "accept() path=%s, fd=%d",
2579 un_my_addr.sun_path, s);
2581 child_si->myname_len = len;
2582 child_si->myname = sockaddr_dup(my_addr, len);
2583 free(my_addr);
2585 SWRAP_DLIST_ADD(sockets, child_si);
2587 if (addr != NULL) {
2588 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2589 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2590 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2593 return fd;
2596 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2597 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2598 #else
2599 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2600 #endif
2602 return swrap_accept(s, addr, (socklen_t *)addrlen);
2605 static int autobind_start_init;
2606 static int autobind_start;
2608 /* using sendto() or connect() on an unbound socket would give the
2609 recipient no way to reply, as unlike UDP and TCP, a unix domain
2610 socket can't auto-assign ephemeral port numbers, so we need to
2611 assign it here.
2612 Note: this might change the family from ipv6 to ipv4
2614 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2616 struct sockaddr_un un_addr;
2617 int i;
2618 char type;
2619 int ret;
2620 int port;
2621 struct stat st;
2623 if (autobind_start_init != 1) {
2624 autobind_start_init = 1;
2625 autobind_start = getpid();
2626 autobind_start %= 50000;
2627 autobind_start += 10000;
2630 un_addr.sun_family = AF_UNIX;
2632 switch (family) {
2633 case AF_INET: {
2634 struct sockaddr_in in;
2636 switch (si->type) {
2637 case SOCK_STREAM:
2638 type = SOCKET_TYPE_CHAR_TCP;
2639 break;
2640 case SOCK_DGRAM:
2641 type = SOCKET_TYPE_CHAR_UDP;
2642 break;
2643 default:
2644 errno = ESOCKTNOSUPPORT;
2645 return -1;
2648 memset(&in, 0, sizeof(in));
2649 in.sin_family = AF_INET;
2650 in.sin_addr.s_addr = htonl(127<<24 |
2651 socket_wrapper_default_iface());
2653 free(si->myname);
2654 si->myname_len = sizeof(in);
2655 si->myname = sockaddr_dup(&in, si->myname_len);
2656 break;
2658 #ifdef HAVE_IPV6
2659 case AF_INET6: {
2660 struct sockaddr_in6 in6;
2662 if (si->family != family) {
2663 errno = ENETUNREACH;
2664 return -1;
2667 switch (si->type) {
2668 case SOCK_STREAM:
2669 type = SOCKET_TYPE_CHAR_TCP_V6;
2670 break;
2671 case SOCK_DGRAM:
2672 type = SOCKET_TYPE_CHAR_UDP_V6;
2673 break;
2674 default:
2675 errno = ESOCKTNOSUPPORT;
2676 return -1;
2679 memset(&in6, 0, sizeof(in6));
2680 in6.sin6_family = AF_INET6;
2681 in6.sin6_addr = *swrap_ipv6();
2682 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2683 free(si->myname);
2684 si->myname_len = sizeof(in6);
2685 si->myname = sockaddr_dup(&in6, si->myname_len);
2686 break;
2688 #endif
2689 default:
2690 errno = ESOCKTNOSUPPORT;
2691 return -1;
2694 if (autobind_start > 60000) {
2695 autobind_start = 10000;
2698 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2699 port = autobind_start + i;
2700 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
2701 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2702 type, socket_wrapper_default_iface(), port);
2703 if (stat(un_addr.sun_path, &st) == 0) continue;
2705 ret = libc_bind(fd, (struct sockaddr *)(void *)&un_addr,
2706 sizeof(un_addr));
2707 if (ret == -1) return ret;
2709 si->tmp_path = strdup(un_addr.sun_path);
2710 si->bound = 1;
2711 autobind_start = port + 1;
2712 break;
2714 if (i == SOCKET_MAX_SOCKETS) {
2715 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2716 "interface "SOCKET_FORMAT,
2717 SOCKET_MAX_SOCKETS,
2718 type,
2719 socket_wrapper_default_iface(),
2721 errno = ENFILE;
2722 return -1;
2725 si->family = family;
2726 set_port(si->family, port, si->myname);
2728 return 0;
2731 /****************************************************************************
2732 * CONNECT
2733 ***************************************************************************/
2735 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2736 socklen_t addrlen)
2738 int ret;
2739 struct sockaddr_un un_addr;
2740 struct socket_info *si = find_socket_info(s);
2741 int bcast = 0;
2743 if (!si) {
2744 return libc_connect(s, serv_addr, addrlen);
2747 if (si->bound == 0) {
2748 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2749 if (ret == -1) return -1;
2752 if (si->family != serv_addr->sa_family) {
2753 errno = EINVAL;
2754 return -1;
2757 ret = sockaddr_convert_to_un(si, serv_addr,
2758 addrlen, &un_addr, 0, &bcast);
2759 if (ret == -1) return -1;
2761 if (bcast) {
2762 errno = ENETUNREACH;
2763 return -1;
2766 if (si->type == SOCK_DGRAM) {
2767 si->defer_connect = 1;
2768 ret = 0;
2769 } else {
2770 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2772 ret = libc_connect(s,
2773 (struct sockaddr *)(void *)&un_addr,
2774 sizeof(struct sockaddr_un));
2777 SWRAP_LOG(SWRAP_LOG_TRACE,
2778 "connect() path=%s, fd=%d",
2779 un_addr.sun_path, s);
2782 /* to give better errors */
2783 if (ret == -1 && errno == ENOENT) {
2784 errno = EHOSTUNREACH;
2787 if (ret == 0) {
2788 si->peername_len = addrlen;
2789 si->peername = sockaddr_dup(serv_addr, addrlen);
2790 si->connected = 1;
2793 * When we connect() on a socket than we have to bind the
2794 * outgoing connection on the interface we use for the
2795 * transport. We already bound it on the right interface
2796 * but here we have to update the name so getsockname()
2797 * returns correct information.
2799 if (si->bindname != NULL) {
2800 free(si->myname);
2802 si->myname = si->bindname;
2803 si->myname_len = si->bindname_len;
2805 si->bindname = NULL;
2806 si->bindname_len = 0;
2809 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2810 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2811 } else {
2812 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2815 return ret;
2818 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2820 return swrap_connect(s, serv_addr, addrlen);
2823 /****************************************************************************
2824 * BIND
2825 ***************************************************************************/
2827 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2829 int ret;
2830 struct sockaddr_un un_addr;
2831 struct socket_info *si = find_socket_info(s);
2832 int bind_error = 0;
2833 #if 0 /* FIXME */
2834 bool in_use;
2835 #endif
2837 if (!si) {
2838 return libc_bind(s, myaddr, addrlen);
2841 switch (si->family) {
2842 case AF_INET: {
2843 const struct sockaddr_in *sin;
2844 if (addrlen < sizeof(struct sockaddr_in)) {
2845 bind_error = EINVAL;
2846 break;
2849 sin = (struct sockaddr_in *)myaddr;
2851 if (sin->sin_family != AF_INET) {
2852 bind_error = EAFNOSUPPORT;
2855 /* special case for AF_UNSPEC */
2856 if (sin->sin_family == AF_UNSPEC &&
2857 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
2859 bind_error = 0;
2862 break;
2864 #ifdef HAVE_IPV6
2865 case AF_INET6: {
2866 const struct sockaddr_in6 *sin6;
2867 if (addrlen < sizeof(struct sockaddr_in6)) {
2868 bind_error = EINVAL;
2869 break;
2872 sin6 = (struct sockaddr_in6 *)myaddr;
2874 if (sin6->sin6_family != AF_INET6) {
2875 bind_error = EAFNOSUPPORT;
2878 break;
2880 #endif
2881 default:
2882 bind_error = EINVAL;
2883 break;
2886 if (bind_error != 0) {
2887 errno = bind_error;
2888 return -1;
2891 #if 0 /* FIXME */
2892 in_use = check_addr_port_in_use(myaddr, addrlen);
2893 if (in_use) {
2894 errno = EADDRINUSE;
2895 return -1;
2897 #endif
2899 free(si->myname);
2900 si->myname_len = addrlen;
2901 si->myname = sockaddr_dup(myaddr, addrlen);
2903 ret = sockaddr_convert_to_un(si, myaddr, addrlen, &un_addr, 1, &si->bcast);
2904 if (ret == -1) return -1;
2906 unlink(un_addr.sun_path);
2908 ret = libc_bind(s, (struct sockaddr *)(void *)&un_addr,
2909 sizeof(struct sockaddr_un));
2911 SWRAP_LOG(SWRAP_LOG_TRACE,
2912 "bind() path=%s, fd=%d",
2913 un_addr.sun_path, s);
2915 if (ret == 0) {
2916 si->bound = 1;
2919 return ret;
2922 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
2924 return swrap_bind(s, myaddr, addrlen);
2927 /****************************************************************************
2928 * BINDRESVPORT
2929 ***************************************************************************/
2931 #ifdef HAVE_BINDRESVPORT
2932 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
2934 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
2936 struct sockaddr_storage myaddr;
2937 socklen_t salen;
2938 static uint16_t port;
2939 uint16_t i;
2940 int rc = -1;
2941 int af;
2943 #define SWRAP_STARTPORT 600
2944 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
2945 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
2947 if (port == 0) {
2948 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
2951 if (sa == NULL) {
2952 salen = sizeof(struct sockaddr);
2953 sa = (struct sockaddr *)&myaddr;
2955 rc = swrap_getsockname(sd, (struct sockaddr *)&myaddr, &salen);
2956 if (rc < 0) {
2957 return -1;
2960 af = sa->sa_family;
2961 memset(&myaddr, 0, salen);
2962 } else {
2963 af = sa->sa_family;
2966 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
2967 switch(af) {
2968 case AF_INET: {
2969 struct sockaddr_in *sinp = (struct sockaddr_in *)sa;
2971 salen = sizeof(struct sockaddr_in);
2972 sinp->sin_port = htons(port);
2973 break;
2975 case AF_INET6: {
2976 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)sa;
2978 salen = sizeof(struct sockaddr_in6);
2979 sin6p->sin6_port = htons(port);
2980 break;
2982 default:
2983 errno = EAFNOSUPPORT;
2984 return -1;
2986 sa->sa_family = af;
2988 if (port > SWRAP_ENDPORT) {
2989 port = SWRAP_STARTPORT;
2992 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
2993 if (rc == 0 || errno != EADDRINUSE) {
2994 break;
2998 return rc;
3001 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3003 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3005 #endif
3007 /****************************************************************************
3008 * LISTEN
3009 ***************************************************************************/
3011 static int swrap_listen(int s, int backlog)
3013 int ret;
3014 struct socket_info *si = find_socket_info(s);
3016 if (!si) {
3017 return libc_listen(s, backlog);
3020 ret = libc_listen(s, backlog);
3022 return ret;
3025 int listen(int s, int backlog)
3027 return swrap_listen(s, backlog);
3030 /****************************************************************************
3031 * OPEN
3032 ***************************************************************************/
3034 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3036 int ret;
3038 ret = libc_vopen(pathname, flags, ap);
3039 if (ret != -1) {
3041 * There are methods for closing descriptors (libc-internal code
3042 * paths, direct syscalls) which close descriptors in ways that
3043 * we can't intercept, so try to recover when we notice that
3044 * that's happened
3046 swrap_remove_stale(ret);
3048 return ret;
3051 int open(const char *pathname, int flags, ...)
3053 va_list ap;
3054 int fd;
3056 va_start(ap, flags);
3057 fd = swrap_vopen(pathname, flags, ap);
3058 va_end(ap);
3060 return fd;
3063 /****************************************************************************
3064 * GETPEERNAME
3065 ***************************************************************************/
3067 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3069 struct socket_info *si = find_socket_info(s);
3070 socklen_t len;
3072 if (!si) {
3073 return libc_getpeername(s, name, addrlen);
3076 if (!si->peername)
3078 errno = ENOTCONN;
3079 return -1;
3082 len = MIN(*addrlen, si->peername_len);
3083 if (len == 0) {
3084 return 0;
3087 memcpy(name, si->peername, len);
3088 *addrlen = si->peername_len;
3090 return 0;
3093 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3094 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3095 #else
3096 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3097 #endif
3099 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3102 /****************************************************************************
3103 * GETSOCKNAME
3104 ***************************************************************************/
3106 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3108 struct socket_info *si = find_socket_info(s);
3109 socklen_t len;
3111 if (!si) {
3112 return libc_getsockname(s, name, addrlen);
3115 len = MIN(*addrlen, si->myname_len);
3116 if (len == 0) {
3117 return 0;
3120 memcpy(name, si->myname, len);
3121 *addrlen = si->myname_len;
3123 return 0;
3126 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3127 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3128 #else
3129 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3130 #endif
3132 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3135 /****************************************************************************
3136 * GETSOCKOPT
3137 ***************************************************************************/
3139 #ifndef SO_PROTOCOL
3140 # ifdef SO_PROTOTYPE /* The Solaris name */
3141 # define SO_PROTOCOL SO_PROTOTYPE
3142 # endif /* SO_PROTOTYPE */
3143 #endif /* SO_PROTOCOL */
3145 static int swrap_getsockopt(int s, int level, int optname,
3146 void *optval, socklen_t *optlen)
3148 struct socket_info *si = find_socket_info(s);
3150 if (!si) {
3151 return libc_getsockopt(s,
3152 level,
3153 optname,
3154 optval,
3155 optlen);
3158 if (level == SOL_SOCKET) {
3159 switch (optname) {
3160 #ifdef SO_DOMAIN
3161 case SO_DOMAIN:
3162 if (optval == NULL || optlen == NULL ||
3163 *optlen < (socklen_t)sizeof(int)) {
3164 errno = EINVAL;
3165 return -1;
3168 *optlen = sizeof(int);
3169 *(int *)optval = si->family;
3170 return 0;
3171 #endif /* SO_DOMAIN */
3172 case SO_PROTOCOL:
3173 if (optval == NULL || optlen == NULL ||
3174 *optlen < (socklen_t)sizeof(int)) {
3175 errno = EINVAL;
3176 return -1;
3179 *optlen = sizeof(int);
3180 *(int *)optval = si->protocol;
3181 return 0;
3182 case SO_TYPE:
3183 if (optval == NULL || optlen == NULL ||
3184 *optlen < (socklen_t)sizeof(int)) {
3185 errno = EINVAL;
3186 return -1;
3189 *optlen = sizeof(int);
3190 *(int *)optval = si->type;
3191 return 0;
3192 default:
3193 return libc_getsockopt(s,
3194 level,
3195 optname,
3196 optval,
3197 optlen);
3201 errno = ENOPROTOOPT;
3202 return -1;
3205 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3206 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3207 #else
3208 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3209 #endif
3211 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3214 /****************************************************************************
3215 * SETSOCKOPT
3216 ***************************************************************************/
3218 static int swrap_setsockopt(int s, int level, int optname,
3219 const void *optval, socklen_t optlen)
3221 struct socket_info *si = find_socket_info(s);
3223 if (!si) {
3224 return libc_setsockopt(s,
3225 level,
3226 optname,
3227 optval,
3228 optlen);
3231 if (level == SOL_SOCKET) {
3232 return libc_setsockopt(s,
3233 level,
3234 optname,
3235 optval,
3236 optlen);
3239 switch (si->family) {
3240 case AF_INET:
3241 if (level == IPPROTO_IP) {
3242 #ifdef IP_PKTINFO
3243 if (optname == IP_PKTINFO) {
3244 si->pktinfo = AF_INET;
3246 #endif /* IP_PKTINFO */
3248 return 0;
3249 #ifdef HAVE_IPV6
3250 case AF_INET6:
3251 if (level == IPPROTO_IPV6) {
3252 #ifdef IPV6_RECVPKTINFO
3253 if (optname == IPV6_RECVPKTINFO) {
3254 si->pktinfo = AF_INET6;
3256 #endif /* IPV6_PKTINFO */
3258 return 0;
3259 #endif
3260 default:
3261 errno = ENOPROTOOPT;
3262 return -1;
3266 int setsockopt(int s, int level, int optname,
3267 const void *optval, socklen_t optlen)
3269 return swrap_setsockopt(s, level, optname, optval, optlen);
3272 /****************************************************************************
3273 * IOCTL
3274 ***************************************************************************/
3276 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3278 struct socket_info *si = find_socket_info(s);
3279 va_list ap;
3280 int value;
3281 int rc;
3283 if (!si) {
3284 return libc_vioctl(s, r, va);
3287 va_copy(ap, va);
3289 rc = libc_vioctl(s, r, va);
3291 switch (r) {
3292 case FIONREAD:
3293 value = *((int *)va_arg(ap, int *));
3295 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3296 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3297 } else if (value == 0) { /* END OF FILE */
3298 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3300 break;
3303 va_end(ap);
3305 return rc;
3308 #ifdef HAVE_IOCTL_INT
3309 int ioctl(int s, int r, ...)
3310 #else
3311 int ioctl(int s, unsigned long int r, ...)
3312 #endif
3314 va_list va;
3315 int rc;
3317 va_start(va, r);
3319 rc = swrap_vioctl(s, (unsigned long int) r, va);
3321 va_end(va);
3323 return rc;
3326 /*****************
3327 * CMSG
3328 *****************/
3330 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3332 #ifndef CMSG_ALIGN
3333 # ifdef _ALIGN /* BSD */
3334 #define CMSG_ALIGN _ALIGN
3335 # else
3336 #error NO_CMSG_ALIGN
3337 # endif /* _ALIGN */
3338 #endif /* CMSG_ALIGN */
3341 * @brief Add a cmsghdr to a msghdr.
3343 * This is an function to add any type of cmsghdr. It will operate on the
3344 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3345 * the buffer position after the added cmsg element. Hence, this function is
3346 * intended to be used with an intermediate msghdr and not on the original
3347 * one handed in by the client.
3349 * @param[in] msg The msghdr to which to add the cmsg.
3351 * @param[in] level The cmsg level to set.
3353 * @param[in] type The cmsg type to set.
3355 * @param[in] data The cmsg data to set.
3357 * @param[in] len the length of the data to set.
3359 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3360 int level,
3361 int type,
3362 const void *data,
3363 size_t len)
3365 size_t cmlen = CMSG_LEN(len);
3366 size_t cmspace = CMSG_SPACE(len);
3367 uint8_t cmbuf[cmspace];
3368 struct cmsghdr *cm = (struct cmsghdr *)cmbuf;
3369 uint8_t *p;
3371 memset(cmbuf, 0, cmspace);
3373 if (msg->msg_controllen < cmlen) {
3374 cmlen = msg->msg_controllen;
3375 msg->msg_flags |= MSG_CTRUNC;
3378 if (msg->msg_controllen < cmspace) {
3379 cmspace = msg->msg_controllen;
3383 * We copy the full input data into an intermediate cmsghdr first
3384 * in order to more easily cope with truncation.
3386 cm->cmsg_len = cmlen;
3387 cm->cmsg_level = level;
3388 cm->cmsg_type = type;
3389 memcpy(CMSG_DATA(cm), data, len);
3392 * We now copy the possibly truncated buffer.
3393 * We copy cmlen bytes, but consume cmspace bytes,
3394 * leaving the possible padding uninitialiazed.
3396 p = (uint8_t *)msg->msg_control;
3397 memcpy(p, cm, cmlen);
3398 p += cmspace;
3399 msg->msg_control = p;
3400 msg->msg_controllen -= cmspace;
3402 return;
3405 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3406 struct msghdr *msg)
3408 /* Add packet info */
3409 switch (si->pktinfo) {
3410 #if defined(IP_PKTINFO)
3411 /* && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR)) */
3412 case AF_INET: {
3413 struct sockaddr_in *sin;
3414 #if defined(HAVE_STRUCT_IN_PKTINFO)
3415 struct in_pktinfo pkt;
3416 #elif defined(IP_RECVDSTADDR)
3417 struct in_addr pkt;
3418 #endif
3420 if (si->bindname_len == sizeof(struct sockaddr_in)) {
3421 sin = (struct sockaddr_in*)si->bindname;
3422 } else {
3423 if (si->myname_len != sizeof(struct sockaddr_in)) {
3424 return 0;
3426 sin = (struct sockaddr_in*)si->myname;
3429 ZERO_STRUCT(pkt);
3431 #if defined(HAVE_STRUCT_IN_PKTINFO)
3432 pkt.ipi_ifindex = socket_wrapper_default_iface();
3433 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3434 #elif defined(IP_RECVDSTADDR)
3435 pkt = sin->sin_addr;
3436 #endif
3438 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3439 &pkt, sizeof(pkt));
3441 break;
3443 #endif /* IP_PKTINFO */
3444 #if defined(HAVE_IPV6)
3445 case AF_INET6: {
3446 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3447 struct sockaddr_in6 *sin6;
3448 struct in6_pktinfo pkt6;
3450 if (si->bindname_len == sizeof(struct sockaddr_in6)) {
3451 sin6 = (struct sockaddr_in6*)si->bindname;
3452 } else {
3453 if (si->myname_len != sizeof(struct sockaddr_in6)) {
3454 return 0;
3456 sin6 = (struct sockaddr_in6*)si->myname;
3459 ZERO_STRUCT(pkt6);
3461 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3462 pkt6.ipi6_addr = sin6->sin6_addr;
3464 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3465 &pkt6, sizeof(pkt6));
3466 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3468 break;
3470 #endif /* IPV6_PKTINFO */
3471 default:
3472 return -1;
3475 return 0;
3478 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3479 struct msghdr *omsg)
3481 int rc = 0;
3483 if (si->pktinfo > 0) {
3484 rc = swrap_msghdr_add_pktinfo(si, omsg);
3487 return rc;
3490 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3491 uint8_t **cm_data,
3492 size_t *cm_data_space);
3493 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3494 uint8_t **cm_data,
3495 size_t *cm_data_space);
3497 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3498 uint8_t **cm_data,
3499 size_t *cm_data_space) {
3500 struct cmsghdr *cmsg;
3501 int rc = -1;
3503 /* Nothing to do */
3504 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3505 return 0;
3508 for (cmsg = CMSG_FIRSTHDR(msg);
3509 cmsg != NULL;
3510 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3511 switch (cmsg->cmsg_level) {
3512 case IPPROTO_IP:
3513 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3514 cm_data,
3515 cm_data_space);
3516 break;
3517 default:
3518 rc = swrap_sendmsg_copy_cmsg(cmsg,
3519 cm_data,
3520 cm_data_space);
3521 break;
3525 return rc;
3528 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3529 uint8_t **cm_data,
3530 size_t *cm_data_space)
3532 size_t cmspace;
3533 uint8_t *p;
3535 cmspace =
3536 (*cm_data_space) +
3537 CMSG_SPACE(cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)));
3539 p = realloc((*cm_data), cmspace);
3540 if (p == NULL) {
3541 return -1;
3543 (*cm_data) = p;
3545 p = (*cm_data) + (*cm_data_space);
3546 *cm_data_space = cmspace;
3548 memcpy(p, cmsg, cmsg->cmsg_len);
3550 return 0;
3553 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3554 uint8_t **cm_data,
3555 size_t *cm_data_space);
3558 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3559 uint8_t **cm_data,
3560 size_t *cm_data_space)
3562 int rc = -1;
3564 switch(cmsg->cmsg_type) {
3565 #ifdef IP_PKTINFO
3566 case IP_PKTINFO:
3567 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3568 cm_data,
3569 cm_data_space);
3570 break;
3571 #endif
3572 #ifdef IPV6_PKTINFO
3573 case IPV6_PKTINFO:
3574 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3575 cm_data,
3576 cm_data_space);
3577 break;
3578 #endif
3579 default:
3580 break;
3583 return rc;
3586 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3587 uint8_t **cm_data,
3588 size_t *cm_data_space)
3590 (void)cmsg; /* unused */
3591 (void)cm_data; /* unused */
3592 (void)cm_data_space; /* unused */
3595 * Passing a IP pktinfo to a unix socket might be rejected by the
3596 * Kernel, at least on FreeBSD. So skip this cmsg.
3598 return 0;
3600 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3602 static ssize_t swrap_sendmsg_before(int fd,
3603 struct socket_info *si,
3604 struct msghdr *msg,
3605 struct iovec *tmp_iov,
3606 struct sockaddr_un *tmp_un,
3607 const struct sockaddr_un **to_un,
3608 const struct sockaddr **to,
3609 int *bcast)
3611 size_t i, len = 0;
3612 ssize_t ret;
3614 if (to_un) {
3615 *to_un = NULL;
3617 if (to) {
3618 *to = NULL;
3620 if (bcast) {
3621 *bcast = 0;
3624 switch (si->type) {
3625 case SOCK_STREAM:
3626 if (!si->connected) {
3627 errno = ENOTCONN;
3628 return -1;
3631 if (msg->msg_iovlen == 0) {
3632 break;
3635 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3636 size_t nlen;
3637 nlen = len + msg->msg_iov[i].iov_len;
3638 if (nlen > SOCKET_MAX_PACKET) {
3639 break;
3642 msg->msg_iovlen = i;
3643 if (msg->msg_iovlen == 0) {
3644 *tmp_iov = msg->msg_iov[0];
3645 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3646 msg->msg_iov = tmp_iov;
3647 msg->msg_iovlen = 1;
3649 break;
3651 case SOCK_DGRAM:
3652 if (si->connected) {
3653 if (msg->msg_name) {
3654 errno = EISCONN;
3655 return -1;
3657 } else {
3658 const struct sockaddr *msg_name;
3659 msg_name = (const struct sockaddr *)msg->msg_name;
3661 if (msg_name == NULL) {
3662 errno = ENOTCONN;
3663 return -1;
3667 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3668 tmp_un, 0, bcast);
3669 if (ret == -1) return -1;
3671 if (to_un) {
3672 *to_un = tmp_un;
3674 if (to) {
3675 *to = msg_name;
3677 msg->msg_name = tmp_un;
3678 msg->msg_namelen = sizeof(*tmp_un);
3681 if (si->bound == 0) {
3682 ret = swrap_auto_bind(fd, si, si->family);
3683 if (ret == -1) {
3684 if (errno == ENOTSOCK) {
3685 swrap_remove_stale(fd);
3686 return -ENOTSOCK;
3687 } else {
3688 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3689 return -1;
3694 if (!si->defer_connect) {
3695 break;
3698 ret = sockaddr_convert_to_un(si, si->peername, si->peername_len,
3699 tmp_un, 0, NULL);
3700 if (ret == -1) return -1;
3702 ret = libc_connect(fd,
3703 (struct sockaddr *)(void *)tmp_un,
3704 sizeof(*tmp_un));
3706 /* to give better errors */
3707 if (ret == -1 && errno == ENOENT) {
3708 errno = EHOSTUNREACH;
3711 if (ret == -1) {
3712 return ret;
3715 si->defer_connect = 0;
3716 break;
3717 default:
3718 errno = EHOSTUNREACH;
3719 return -1;
3722 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3723 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
3724 uint8_t *cmbuf = NULL;
3725 size_t cmlen = 0;
3727 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
3728 if (ret < 0) {
3729 free(cmbuf);
3730 return -1;
3733 if (cmlen == 0) {
3734 msg->msg_controllen = 0;
3735 msg->msg_control = NULL;
3736 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
3737 memcpy(msg->msg_control, cmbuf, cmlen);
3738 msg->msg_controllen = cmlen;
3740 free(cmbuf);
3742 #endif
3744 return 0;
3747 static void swrap_sendmsg_after(int fd,
3748 struct socket_info *si,
3749 struct msghdr *msg,
3750 const struct sockaddr *to,
3751 ssize_t ret)
3753 int saved_errno = errno;
3754 size_t i, len = 0;
3755 uint8_t *buf;
3756 off_t ofs = 0;
3757 size_t avail = 0;
3758 size_t remain;
3760 /* to give better errors */
3761 if (ret == -1) {
3762 if (saved_errno == ENOENT) {
3763 saved_errno = EHOSTUNREACH;
3764 } else if (saved_errno == ENOTSOCK) {
3765 /* If the fd is not a socket, remove it */
3766 swrap_remove_stale(fd);
3770 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3771 avail += msg->msg_iov[i].iov_len;
3774 if (ret == -1) {
3775 remain = MIN(80, avail);
3776 } else {
3777 remain = ret;
3780 /* we capture it as one single packet */
3781 buf = (uint8_t *)malloc(remain);
3782 if (!buf) {
3783 /* we just not capture the packet */
3784 errno = saved_errno;
3785 return;
3788 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3789 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3790 memcpy(buf + ofs,
3791 msg->msg_iov[i].iov_base,
3792 this_time);
3793 ofs += this_time;
3794 remain -= this_time;
3796 len = ofs;
3798 switch (si->type) {
3799 case SOCK_STREAM:
3800 if (ret == -1) {
3801 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3802 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
3803 } else {
3804 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
3806 break;
3808 case SOCK_DGRAM:
3809 if (si->connected) {
3810 to = si->peername;
3812 if (ret == -1) {
3813 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3814 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
3815 } else {
3816 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
3818 break;
3821 free(buf);
3822 errno = saved_errno;
3825 static int swrap_recvmsg_before(int fd,
3826 struct socket_info *si,
3827 struct msghdr *msg,
3828 struct iovec *tmp_iov)
3830 size_t i, len = 0;
3831 ssize_t ret;
3833 (void)fd; /* unused */
3835 switch (si->type) {
3836 case SOCK_STREAM:
3837 if (!si->connected) {
3838 errno = ENOTCONN;
3839 return -1;
3842 if (msg->msg_iovlen == 0) {
3843 break;
3846 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3847 size_t nlen;
3848 nlen = len + msg->msg_iov[i].iov_len;
3849 if (nlen > SOCKET_MAX_PACKET) {
3850 break;
3853 msg->msg_iovlen = i;
3854 if (msg->msg_iovlen == 0) {
3855 *tmp_iov = msg->msg_iov[0];
3856 tmp_iov->iov_len = MIN(tmp_iov->iov_len, SOCKET_MAX_PACKET);
3857 msg->msg_iov = tmp_iov;
3858 msg->msg_iovlen = 1;
3860 break;
3862 case SOCK_DGRAM:
3863 if (msg->msg_name == NULL) {
3864 errno = EINVAL;
3865 return -1;
3868 if (msg->msg_iovlen == 0) {
3869 break;
3872 if (si->bound == 0) {
3873 ret = swrap_auto_bind(fd, si, si->family);
3874 if (ret == -1) {
3876 * When attempting to read or write to a
3877 * descriptor, if an underlying autobind fails
3878 * because it's not a socket, stop intercepting
3879 * uses of that descriptor.
3881 if (errno == ENOTSOCK) {
3882 swrap_remove_stale(fd);
3883 return -ENOTSOCK;
3884 } else {
3885 SWRAP_LOG(SWRAP_LOG_ERROR,
3886 "swrap_recvmsg_before failed");
3887 return -1;
3891 break;
3892 default:
3893 errno = EHOSTUNREACH;
3894 return -1;
3897 return 0;
3900 static int swrap_recvmsg_after(int fd,
3901 struct socket_info *si,
3902 struct msghdr *msg,
3903 const struct sockaddr_un *un_addr,
3904 socklen_t un_addrlen,
3905 ssize_t ret)
3907 int saved_errno = errno;
3908 size_t i;
3909 uint8_t *buf = NULL;
3910 off_t ofs = 0;
3911 size_t avail = 0;
3912 size_t remain;
3913 int rc;
3915 /* to give better errors */
3916 if (ret == -1) {
3917 if (saved_errno == ENOENT) {
3918 saved_errno = EHOSTUNREACH;
3919 } else if (saved_errno == ENOTSOCK) {
3920 /* If the fd is not a socket, remove it */
3921 swrap_remove_stale(fd);
3925 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3926 avail += msg->msg_iov[i].iov_len;
3929 if (avail == 0) {
3930 rc = 0;
3931 goto done;
3934 if (ret == -1) {
3935 remain = MIN(80, avail);
3936 } else {
3937 remain = ret;
3940 /* we capture it as one single packet */
3941 buf = (uint8_t *)malloc(remain);
3942 if (buf == NULL) {
3943 /* we just not capture the packet */
3944 errno = saved_errno;
3945 return -1;
3948 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3949 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
3950 memcpy(buf + ofs,
3951 msg->msg_iov[i].iov_base,
3952 this_time);
3953 ofs += this_time;
3954 remain -= this_time;
3957 switch (si->type) {
3958 case SOCK_STREAM:
3959 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
3960 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3961 } else if (ret == 0) { /* END OF FILE */
3962 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
3963 } else if (ret > 0) {
3964 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
3966 break;
3968 case SOCK_DGRAM:
3969 if (ret == -1) {
3970 break;
3973 if (un_addr != NULL) {
3974 rc = sockaddr_convert_from_un(si,
3975 un_addr,
3976 un_addrlen,
3977 si->family,
3978 msg->msg_name,
3979 &msg->msg_namelen);
3980 if (rc == -1) {
3981 goto done;
3984 swrap_dump_packet(si,
3985 msg->msg_name,
3986 SWRAP_RECVFROM,
3987 buf,
3988 ret);
3989 } else {
3990 swrap_dump_packet(si,
3991 msg->msg_name,
3992 SWRAP_RECV,
3993 buf,
3994 ret);
3997 break;
4000 rc = 0;
4001 done:
4002 free(buf);
4003 errno = saved_errno;
4005 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4006 if (rc == 0 &&
4007 msg->msg_controllen > 0 &&
4008 msg->msg_control != NULL) {
4009 rc = swrap_msghdr_add_socket_info(si, msg);
4010 if (rc < 0) {
4011 return -1;
4014 #endif
4016 return rc;
4019 /****************************************************************************
4020 * RECVFROM
4021 ***************************************************************************/
4023 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4024 struct sockaddr *from, socklen_t *fromlen)
4026 struct sockaddr_un from_addr;
4027 socklen_t from_addrlen = sizeof(from_addr);
4028 ssize_t ret;
4029 struct socket_info *si = find_socket_info(s);
4030 struct sockaddr_storage ss;
4031 socklen_t ss_len = sizeof(ss);
4032 struct msghdr msg;
4033 struct iovec tmp;
4034 int tret;
4036 if (!si) {
4037 return libc_recvfrom(s,
4038 buf,
4039 len,
4040 flags,
4041 from,
4042 fromlen);
4045 tmp.iov_base = buf;
4046 tmp.iov_len = len;
4048 ZERO_STRUCT(msg);
4049 if (from != NULL && fromlen != NULL) {
4050 msg.msg_name = from; /* optional address */
4051 msg.msg_namelen = *fromlen; /* size of address */
4052 } else {
4053 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4054 msg.msg_namelen = ss_len; /* size of address */
4056 msg.msg_iov = &tmp; /* scatter/gather array */
4057 msg.msg_iovlen = 1; /* # elements in msg_iov */
4058 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4059 msg.msg_control = NULL; /* ancillary data, see below */
4060 msg.msg_controllen = 0; /* ancillary data buffer len */
4061 msg.msg_flags = 0; /* flags on received message */
4062 #endif
4064 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4065 if (tret < 0) {
4066 return -1;
4069 buf = msg.msg_iov[0].iov_base;
4070 len = msg.msg_iov[0].iov_len;
4072 /* irix 6.4 forgets to null terminate the sun_path string :-( */
4073 memset(&from_addr, 0, sizeof(from_addr));
4074 ret = libc_recvfrom(s,
4075 buf,
4076 len,
4077 flags,
4078 (struct sockaddr *)(void *)&from_addr,
4079 &from_addrlen);
4080 if (ret == -1) {
4081 return ret;
4084 tret = swrap_recvmsg_after(s,
4086 &msg,
4087 &from_addr,
4088 from_addrlen,
4089 ret);
4090 if (tret != 0) {
4091 return tret;
4094 if (from != NULL && fromlen != NULL) {
4095 *fromlen = msg.msg_namelen;
4098 return ret;
4101 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4102 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4103 struct sockaddr *from, Psocklen_t fromlen)
4104 #else
4105 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4106 struct sockaddr *from, socklen_t *fromlen)
4107 #endif
4109 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4112 /****************************************************************************
4113 * SENDTO
4114 ***************************************************************************/
4116 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4117 const struct sockaddr *to, socklen_t tolen)
4119 struct msghdr msg;
4120 struct iovec tmp;
4121 struct sockaddr_un un_addr;
4122 const struct sockaddr_un *to_un = NULL;
4123 ssize_t ret;
4124 int rc;
4125 struct socket_info *si = find_socket_info(s);
4126 int bcast = 0;
4128 if (!si) {
4129 return libc_sendto(s, buf, len, flags, to, tolen);
4132 tmp.iov_base = discard_const_p(char, buf);
4133 tmp.iov_len = len;
4135 ZERO_STRUCT(msg);
4136 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4137 msg.msg_namelen = tolen; /* size of address */
4138 msg.msg_iov = &tmp; /* scatter/gather array */
4139 msg.msg_iovlen = 1; /* # elements in msg_iov */
4140 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4141 msg.msg_control = NULL; /* ancillary data, see below */
4142 msg.msg_controllen = 0; /* ancillary data buffer len */
4143 msg.msg_flags = 0; /* flags on received message */
4144 #endif
4146 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4147 if (rc < 0) {
4148 return -1;
4151 buf = msg.msg_iov[0].iov_base;
4152 len = msg.msg_iov[0].iov_len;
4154 if (bcast) {
4155 struct stat st;
4156 unsigned int iface;
4157 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4158 char type;
4160 type = SOCKET_TYPE_CHAR_UDP;
4162 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4163 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4164 socket_wrapper_dir(), type, iface, prt);
4165 if (stat(un_addr.sun_path, &st) != 0) continue;
4167 /* ignore the any errors in broadcast sends */
4168 libc_sendto(s,
4169 buf,
4170 len,
4171 flags,
4172 (struct sockaddr *)(void *)&un_addr,
4173 sizeof(un_addr));
4176 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4178 return len;
4181 ret = libc_sendto(s,
4182 buf,
4183 len,
4184 flags,
4185 (struct sockaddr *)msg.msg_name,
4186 msg.msg_namelen);
4188 swrap_sendmsg_after(s, si, &msg, to, ret);
4190 return ret;
4193 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4194 const struct sockaddr *to, socklen_t tolen)
4196 return swrap_sendto(s, buf, len, flags, to, tolen);
4199 /****************************************************************************
4200 * READV
4201 ***************************************************************************/
4203 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4205 struct socket_info *si;
4206 struct msghdr msg;
4207 struct sockaddr_storage ss;
4208 socklen_t ss_len = sizeof(ss);
4209 struct iovec tmp;
4210 ssize_t ret;
4211 int tret;
4213 si = find_socket_info(s);
4214 if (si == NULL) {
4215 return libc_recv(s, buf, len, flags);
4218 tmp.iov_base = buf;
4219 tmp.iov_len = len;
4221 ZERO_STRUCT(msg);
4222 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4223 msg.msg_namelen = ss_len; /* size of address */
4224 msg.msg_iov = &tmp; /* scatter/gather array */
4225 msg.msg_iovlen = 1; /* # elements in msg_iov */
4226 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4227 msg.msg_control = NULL; /* ancillary data, see below */
4228 msg.msg_controllen = 0; /* ancillary data buffer len */
4229 msg.msg_flags = 0; /* flags on received message */
4230 #endif
4232 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4233 if (tret < 0) {
4234 return -1;
4237 buf = msg.msg_iov[0].iov_base;
4238 len = msg.msg_iov[0].iov_len;
4240 ret = libc_recv(s, buf, len, flags);
4242 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4243 if (tret != 0) {
4244 return tret;
4247 return ret;
4250 ssize_t recv(int s, void *buf, size_t len, int flags)
4252 return swrap_recv(s, buf, len, flags);
4255 /****************************************************************************
4256 * READ
4257 ***************************************************************************/
4259 static ssize_t swrap_read(int s, void *buf, size_t len)
4261 struct socket_info *si;
4262 struct msghdr msg;
4263 struct iovec tmp;
4264 struct sockaddr_storage ss;
4265 socklen_t ss_len = sizeof(ss);
4266 ssize_t ret;
4267 int tret;
4269 si = find_socket_info(s);
4270 if (si == NULL) {
4271 return libc_read(s, buf, len);
4274 tmp.iov_base = buf;
4275 tmp.iov_len = len;
4277 ZERO_STRUCT(msg);
4278 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4279 msg.msg_namelen = ss_len; /* size of address */
4280 msg.msg_iov = &tmp; /* scatter/gather array */
4281 msg.msg_iovlen = 1; /* # elements in msg_iov */
4282 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4283 msg.msg_control = NULL; /* ancillary data, see below */
4284 msg.msg_controllen = 0; /* ancillary data buffer len */
4285 msg.msg_flags = 0; /* flags on received message */
4286 #endif
4288 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4289 if (tret < 0) {
4290 if (tret == -ENOTSOCK) {
4291 return libc_read(s, buf, len);
4293 return -1;
4296 buf = msg.msg_iov[0].iov_base;
4297 len = msg.msg_iov[0].iov_len;
4299 ret = libc_read(s, buf, len);
4301 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4302 if (tret != 0) {
4303 return tret;
4306 return ret;
4309 ssize_t read(int s, void *buf, size_t len)
4311 return swrap_read(s, buf, len);
4314 /****************************************************************************
4315 * SEND
4316 ***************************************************************************/
4318 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4320 struct msghdr msg;
4321 struct iovec tmp;
4322 struct sockaddr_un un_addr;
4323 ssize_t ret;
4324 int rc;
4325 struct socket_info *si = find_socket_info(s);
4327 if (!si) {
4328 return libc_send(s, buf, len, flags);
4331 tmp.iov_base = discard_const_p(char, buf);
4332 tmp.iov_len = len;
4334 ZERO_STRUCT(msg);
4335 msg.msg_name = NULL; /* optional address */
4336 msg.msg_namelen = 0; /* size of address */
4337 msg.msg_iov = &tmp; /* scatter/gather array */
4338 msg.msg_iovlen = 1; /* # elements in msg_iov */
4339 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4340 msg.msg_control = NULL; /* ancillary data, see below */
4341 msg.msg_controllen = 0; /* ancillary data buffer len */
4342 msg.msg_flags = 0; /* flags on received message */
4343 #endif
4345 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4346 if (rc < 0) {
4347 return -1;
4350 buf = msg.msg_iov[0].iov_base;
4351 len = msg.msg_iov[0].iov_len;
4353 ret = libc_send(s, buf, len, flags);
4355 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4357 return ret;
4360 ssize_t send(int s, const void *buf, size_t len, int flags)
4362 return swrap_send(s, buf, len, flags);
4365 /****************************************************************************
4366 * RECVMSG
4367 ***************************************************************************/
4369 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4371 struct sockaddr_un from_addr;
4372 socklen_t from_addrlen = sizeof(from_addr);
4373 struct socket_info *si;
4374 struct msghdr msg;
4375 struct iovec tmp;
4376 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4377 size_t msg_ctrllen_filled;
4378 size_t msg_ctrllen_left;
4379 #endif
4381 ssize_t ret;
4382 int rc;
4384 si = find_socket_info(s);
4385 if (si == NULL) {
4386 return libc_recvmsg(s, omsg, flags);
4389 tmp.iov_base = NULL;
4390 tmp.iov_len = 0;
4392 ZERO_STRUCT(msg);
4393 msg.msg_name = (struct sockaddr *)&from_addr; /* optional address */
4394 msg.msg_namelen = from_addrlen; /* size of address */
4395 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4396 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4397 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4398 msg_ctrllen_filled = 0;
4399 msg_ctrllen_left = omsg->msg_controllen;
4401 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4402 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4403 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4404 #endif
4406 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4407 if (rc < 0) {
4408 return -1;
4411 ret = libc_recvmsg(s, &msg, flags);
4413 msg.msg_name = omsg->msg_name;
4414 msg.msg_namelen = omsg->msg_namelen;
4416 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4417 msg_ctrllen_filled += msg.msg_controllen;
4418 msg_ctrllen_left -= msg.msg_controllen;
4420 if (omsg->msg_control != NULL) {
4421 uint8_t *p;
4423 p = omsg->msg_control;
4424 p += msg_ctrllen_filled;
4426 msg.msg_control = p;
4427 msg.msg_controllen = msg_ctrllen_left;
4428 } else {
4429 msg.msg_control = NULL;
4430 msg.msg_controllen = 0;
4432 #endif
4434 rc = swrap_recvmsg_after(s, si, &msg, &from_addr, from_addrlen, ret);
4435 if (rc != 0) {
4436 return rc;
4439 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4440 if (omsg->msg_control != NULL) {
4441 /* msg.msg_controllen = space left */
4442 msg_ctrllen_left = msg.msg_controllen;
4443 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4446 /* Update the original message length */
4447 omsg->msg_controllen = msg_ctrllen_filled;
4448 omsg->msg_flags = msg.msg_flags;
4449 #endif
4450 omsg->msg_iovlen = msg.msg_iovlen;
4452 return ret;
4455 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4457 return swrap_recvmsg(sockfd, msg, flags);
4460 /****************************************************************************
4461 * SENDMSG
4462 ***************************************************************************/
4464 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4466 struct msghdr msg;
4467 struct iovec tmp;
4468 struct sockaddr_un un_addr;
4469 const struct sockaddr_un *to_un = NULL;
4470 const struct sockaddr *to = NULL;
4471 ssize_t ret;
4472 int rc;
4473 struct socket_info *si = find_socket_info(s);
4474 int bcast = 0;
4476 if (!si) {
4477 return libc_sendmsg(s, omsg, flags);
4480 ZERO_STRUCT(un_addr);
4482 tmp.iov_base = NULL;
4483 tmp.iov_len = 0;
4485 ZERO_STRUCT(msg);
4486 msg.msg_name = omsg->msg_name; /* optional address */
4487 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4488 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4489 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4490 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4491 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4492 /* omsg is a const so use a local buffer for modifications */
4493 uint8_t cmbuf[omsg->msg_controllen];
4495 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4497 msg.msg_control = cmbuf; /* ancillary data, see below */
4498 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4500 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4501 #endif
4503 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4504 if (rc < 0) {
4505 return -1;
4508 if (bcast) {
4509 struct stat st;
4510 unsigned int iface;
4511 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
4512 char type;
4513 size_t i, len = 0;
4514 uint8_t *buf;
4515 off_t ofs = 0;
4516 size_t avail = 0;
4517 size_t remain;
4519 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4520 avail += msg.msg_iov[i].iov_len;
4523 len = avail;
4524 remain = avail;
4526 /* we capture it as one single packet */
4527 buf = (uint8_t *)malloc(remain);
4528 if (!buf) {
4529 return -1;
4532 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4533 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4534 memcpy(buf + ofs,
4535 msg.msg_iov[i].iov_base,
4536 this_time);
4537 ofs += this_time;
4538 remain -= this_time;
4541 type = SOCKET_TYPE_CHAR_UDP;
4543 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4544 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4545 socket_wrapper_dir(), type, iface, prt);
4546 if (stat(un_addr.sun_path, &st) != 0) continue;
4548 msg.msg_name = &un_addr; /* optional address */
4549 msg.msg_namelen = sizeof(un_addr); /* size of address */
4551 /* ignore the any errors in broadcast sends */
4552 libc_sendmsg(s, &msg, flags);
4555 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4556 free(buf);
4558 return len;
4561 ret = libc_sendmsg(s, &msg, flags);
4563 swrap_sendmsg_after(s, si, &msg, to, ret);
4565 return ret;
4568 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4570 return swrap_sendmsg(s, omsg, flags);
4573 /****************************************************************************
4574 * READV
4575 ***************************************************************************/
4577 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4579 struct socket_info *si;
4580 struct msghdr msg;
4581 struct iovec tmp;
4582 struct sockaddr_storage ss;
4583 socklen_t ss_len = sizeof(ss);
4584 ssize_t ret;
4585 int rc;
4587 si = find_socket_info(s);
4588 if (si == NULL) {
4589 return libc_readv(s, vector, count);
4592 tmp.iov_base = NULL;
4593 tmp.iov_len = 0;
4595 ZERO_STRUCT(msg);
4596 msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
4597 msg.msg_namelen = ss_len; /* size of address */
4598 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4599 msg.msg_iovlen = count; /* # elements in msg_iov */
4600 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4601 msg.msg_control = NULL; /* ancillary data, see below */
4602 msg.msg_controllen = 0; /* ancillary data buffer len */
4603 msg.msg_flags = 0; /* flags on received message */
4604 #endif
4606 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4607 if (rc < 0) {
4608 if (rc == -ENOTSOCK) {
4609 return libc_readv(s, vector, count);
4611 return -1;
4614 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
4616 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4617 if (rc != 0) {
4618 return rc;
4621 return ret;
4624 ssize_t readv(int s, const struct iovec *vector, int count)
4626 return swrap_readv(s, vector, count);
4629 /****************************************************************************
4630 * WRITEV
4631 ***************************************************************************/
4633 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
4635 struct msghdr msg;
4636 struct iovec tmp;
4637 struct sockaddr_un un_addr;
4638 ssize_t ret;
4639 int rc;
4640 struct socket_info *si = find_socket_info(s);
4642 if (!si) {
4643 return libc_writev(s, vector, count);
4646 tmp.iov_base = NULL;
4647 tmp.iov_len = 0;
4649 ZERO_STRUCT(msg);
4650 msg.msg_name = NULL; /* optional address */
4651 msg.msg_namelen = 0; /* size of address */
4652 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
4653 msg.msg_iovlen = count; /* # elements in msg_iov */
4654 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4655 msg.msg_control = NULL; /* ancillary data, see below */
4656 msg.msg_controllen = 0; /* ancillary data buffer len */
4657 msg.msg_flags = 0; /* flags on received message */
4658 #endif
4660 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4661 if (rc < 0) {
4662 if (rc == -ENOTSOCK) {
4663 return libc_readv(s, vector, count);
4665 return -1;
4668 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
4670 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4672 return ret;
4675 ssize_t writev(int s, const struct iovec *vector, int count)
4677 return swrap_writev(s, vector, count);
4680 /****************************
4681 * CLOSE
4682 ***************************/
4684 static int swrap_close(int fd)
4686 struct socket_info *si = find_socket_info(fd);
4687 struct socket_info_fd *fi;
4688 int ret;
4690 if (!si) {
4691 return libc_close(fd);
4694 for (fi = si->fds; fi; fi = fi->next) {
4695 if (fi->fd == fd) {
4696 SWRAP_DLIST_REMOVE(si->fds, fi);
4697 free(fi);
4698 break;
4702 if (si->fds) {
4703 /* there are still references left */
4704 return libc_close(fd);
4707 SWRAP_DLIST_REMOVE(sockets, si);
4709 if (si->myname && si->peername) {
4710 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
4713 ret = libc_close(fd);
4715 if (si->myname && si->peername) {
4716 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
4717 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
4720 if (si->bindname != NULL) {
4721 free(si->bindname);
4724 if (si->myname) free(si->myname);
4725 if (si->peername) free(si->peername);
4726 if (si->tmp_path) {
4727 unlink(si->tmp_path);
4728 free(si->tmp_path);
4730 free(si);
4732 return ret;
4735 int close(int fd)
4737 return swrap_close(fd);
4740 /****************************
4741 * DUP
4742 ***************************/
4744 static int swrap_dup(int fd)
4746 struct socket_info *si;
4747 struct socket_info_fd *fi;
4749 si = find_socket_info(fd);
4751 if (!si) {
4752 return libc_dup(fd);
4755 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4756 if (fi == NULL) {
4757 errno = ENOMEM;
4758 return -1;
4761 fi->fd = libc_dup(fd);
4762 if (fi->fd == -1) {
4763 int saved_errno = errno;
4764 free(fi);
4765 errno = saved_errno;
4766 return -1;
4769 /* Make sure we don't have an entry for the fd */
4770 swrap_remove_stale(fi->fd);
4772 SWRAP_DLIST_ADD(si->fds, fi);
4773 return fi->fd;
4776 int dup(int fd)
4778 return swrap_dup(fd);
4781 /****************************
4782 * DUP2
4783 ***************************/
4785 static int swrap_dup2(int fd, int newfd)
4787 struct socket_info *si;
4788 struct socket_info_fd *fi;
4790 si = find_socket_info(fd);
4792 if (!si) {
4793 return libc_dup2(fd, newfd);
4796 if (find_socket_info(newfd)) {
4797 /* dup2() does an implicit close of newfd, which we
4798 * need to emulate */
4799 swrap_close(newfd);
4802 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
4803 if (fi == NULL) {
4804 errno = ENOMEM;
4805 return -1;
4808 fi->fd = libc_dup2(fd, newfd);
4809 if (fi->fd == -1) {
4810 int saved_errno = errno;
4811 free(fi);
4812 errno = saved_errno;
4813 return -1;
4816 /* Make sure we don't have an entry for the fd */
4817 swrap_remove_stale(fi->fd);
4819 SWRAP_DLIST_ADD(si->fds, fi);
4820 return fi->fd;
4823 int dup2(int fd, int newfd)
4825 return swrap_dup2(fd, newfd);
4828 /****************************
4829 * DUP2
4830 ***************************/
4832 #ifdef HAVE_EVENTFD
4833 static int swrap_eventfd(int count, int flags)
4835 int fd;
4837 fd = libc_eventfd(count, flags);
4838 if (fd != -1) {
4839 swrap_remove_stale(fd);
4842 return fd;
4845 int eventfd(int count, int flags)
4847 return swrap_eventfd(count, flags);
4849 #endif
4851 /****************************
4852 * DESTRUCTOR
4853 ***************************/
4856 * This function is called when the library is unloaded and makes sure that
4857 * sockets get closed and the unix file for the socket are unlinked.
4859 void swrap_destructor(void)
4861 struct socket_info *s = sockets;
4863 while (s != NULL) {
4864 struct socket_info_fd *f = s->fds;
4865 if (f != NULL) {
4866 swrap_close(f->fd);
4868 s = sockets;