build: Move socket_wrapper to third_party
[Samba.git] / third_party / socket_wrapper / socket_wrapper.c
blob43b92f76f1e55d5499f69d4f59a9e71a643c5e7a
1 /*
2 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
4 * Copyright (C) 2013-2014 Andreas Schneider <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_ADDRESS_SANITIZER_ATTRIBUTE
104 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
105 #else
106 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
107 #endif
109 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
110 # define SWRAP_THREAD __thread
111 #else
112 # define SWRAP_THREAD
113 #endif
115 #ifndef MIN
116 #define MIN(a,b) ((a)<(b)?(a):(b))
117 #endif
119 #ifndef ZERO_STRUCT
120 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
121 #endif
123 #ifndef ZERO_STRUCTP
124 #define ZERO_STRUCTP(x) do { \
125 if ((x) != NULL) \
126 memset((char *)(x), 0, sizeof(*(x))); \
127 } while(0)
128 #endif
130 #ifndef discard_const
131 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
132 #endif
134 #ifndef discard_const_p
135 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
136 #endif
138 #ifdef IPV6_PKTINFO
139 # ifndef IPV6_RECVPKTINFO
140 # define IPV6_RECVPKTINFO IPV6_PKTINFO
141 # endif /* IPV6_RECVPKTINFO */
142 #endif /* IPV6_PKTINFO */
145 * On BSD IP_PKTINFO has a different name because during
146 * the time when they implemented it, there was no RFC.
147 * The name for IPv6 is the same as on Linux.
149 #ifndef IP_PKTINFO
150 # ifdef IP_RECVDSTADDR
151 # define IP_PKTINFO IP_RECVDSTADDR
152 # endif
153 #endif
156 #define SWRAP_DLIST_ADD(list,item) do { \
157 if (!(list)) { \
158 (item)->prev = NULL; \
159 (item)->next = NULL; \
160 (list) = (item); \
161 } else { \
162 (item)->prev = NULL; \
163 (item)->next = (list); \
164 (list)->prev = (item); \
165 (list) = (item); \
167 } while (0)
169 #define SWRAP_DLIST_REMOVE(list,item) do { \
170 if ((list) == (item)) { \
171 (list) = (item)->next; \
172 if (list) { \
173 (list)->prev = NULL; \
175 } else { \
176 if ((item)->prev) { \
177 (item)->prev->next = (item)->next; \
179 if ((item)->next) { \
180 (item)->next->prev = (item)->prev; \
183 (item)->prev = NULL; \
184 (item)->next = NULL; \
185 } while (0)
187 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
188 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
189 #else
190 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
191 #endif
193 /* we need to use a very terse format here as IRIX 6.4 silently
194 truncates names to 16 chars, so if we use a longer name then we
195 can't tell which port a packet came from with recvfrom()
197 with this format we have 8 chars left for the directory name
199 #define SOCKET_FORMAT "%c%02X%04X"
200 #define SOCKET_TYPE_CHAR_TCP 'T'
201 #define SOCKET_TYPE_CHAR_UDP 'U'
202 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
203 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
206 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
207 * format PCAP capture files (as the caller will simply continue from here).
209 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
210 #define SOCKET_WRAPPER_MTU_MIN 512
211 #define SOCKET_WRAPPER_MTU_MAX 32768
213 #define SOCKET_MAX_SOCKETS 1024
215 /* This limit is to avoid broadcast sendto() needing to stat too many
216 * files. It may be raised (with a performance cost) to up to 254
217 * without changing the format above */
218 #define MAX_WRAPPED_INTERFACES 40
220 struct swrap_address {
221 socklen_t sa_socklen;
222 union {
223 struct sockaddr s;
224 struct sockaddr_in in;
225 #ifdef HAVE_IPV6
226 struct sockaddr_in6 in6;
227 #endif
228 struct sockaddr_un un;
229 struct sockaddr_storage ss;
230 } sa;
233 struct socket_info_fd {
234 struct socket_info_fd *prev, *next;
235 int fd;
238 struct socket_info
240 struct socket_info_fd *fds;
242 int family;
243 int type;
244 int protocol;
245 int bound;
246 int bcast;
247 int is_server;
248 int connected;
249 int defer_connect;
250 int pktinfo;
251 int tcp_nodelay;
253 /* The unix path so we can unlink it on close() */
254 struct sockaddr_un un_addr;
256 struct swrap_address bindname;
257 struct swrap_address myname;
258 struct swrap_address peername;
260 struct {
261 unsigned long pck_snd;
262 unsigned long pck_rcv;
263 } io;
265 struct socket_info *prev, *next;
269 * File descriptors are shared between threads so we should share socket
270 * information too.
272 struct socket_info *sockets;
274 /* Function prototypes */
276 bool socket_wrapper_enabled(void);
277 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
279 #ifdef NDEBUG
280 # define SWRAP_LOG(...)
281 #else
283 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
284 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
286 static void swrap_log(enum swrap_dbglvl_e dbglvl,
287 const char *func,
288 const char *format, ...)
290 char buffer[1024];
291 va_list va;
292 const char *d;
293 unsigned int lvl = 0;
295 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
296 if (d != NULL) {
297 lvl = atoi(d);
300 va_start(va, format);
301 vsnprintf(buffer, sizeof(buffer), format, va);
302 va_end(va);
304 if (lvl >= dbglvl) {
305 switch (dbglvl) {
306 case SWRAP_LOG_ERROR:
307 fprintf(stderr,
308 "SWRAP_ERROR(%d) - %s: %s\n",
309 (int)getpid(), func, buffer);
310 break;
311 case SWRAP_LOG_WARN:
312 fprintf(stderr,
313 "SWRAP_WARN(%d) - %s: %s\n",
314 (int)getpid(), func, buffer);
315 break;
316 case SWRAP_LOG_DEBUG:
317 fprintf(stderr,
318 "SWRAP_DEBUG(%d) - %s: %s\n",
319 (int)getpid(), func, buffer);
320 break;
321 case SWRAP_LOG_TRACE:
322 fprintf(stderr,
323 "SWRAP_TRACE(%d) - %s: %s\n",
324 (int)getpid(), func, buffer);
325 break;
329 #endif
331 /*********************************************************
332 * SWRAP LOADING LIBC FUNCTIONS
333 *********************************************************/
335 #include <dlfcn.h>
337 struct swrap_libc_fns {
338 #ifdef HAVE_ACCEPT4
339 int (*libc_accept4)(int sockfd,
340 struct sockaddr *addr,
341 socklen_t *addrlen,
342 int flags);
343 #else
344 int (*libc_accept)(int sockfd,
345 struct sockaddr *addr,
346 socklen_t *addrlen);
347 #endif
348 int (*libc_bind)(int sockfd,
349 const struct sockaddr *addr,
350 socklen_t addrlen);
351 int (*libc_close)(int fd);
352 int (*libc_connect)(int sockfd,
353 const struct sockaddr *addr,
354 socklen_t addrlen);
355 int (*libc_dup)(int fd);
356 int (*libc_dup2)(int oldfd, int newfd);
357 int (*libc_fcntl)(int fd, int cmd, ...);
358 FILE *(*libc_fopen)(const char *name, const char *mode);
359 #ifdef HAVE_EVENTFD
360 int (*libc_eventfd)(int count, int flags);
361 #endif
362 int (*libc_getpeername)(int sockfd,
363 struct sockaddr *addr,
364 socklen_t *addrlen);
365 int (*libc_getsockname)(int sockfd,
366 struct sockaddr *addr,
367 socklen_t *addrlen);
368 int (*libc_getsockopt)(int sockfd,
369 int level,
370 int optname,
371 void *optval,
372 socklen_t *optlen);
373 int (*libc_ioctl)(int d, unsigned long int request, ...);
374 int (*libc_listen)(int sockfd, int backlog);
375 int (*libc_open)(const char *pathname, int flags, mode_t mode);
376 int (*libc_pipe)(int pipefd[2]);
377 int (*libc_read)(int fd, void *buf, size_t count);
378 ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
379 int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
380 int (*libc_recvfrom)(int sockfd,
381 void *buf,
382 size_t len,
383 int flags,
384 struct sockaddr *src_addr,
385 socklen_t *addrlen);
386 int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
387 int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
388 int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
389 int (*libc_sendto)(int sockfd,
390 const void *buf,
391 size_t len,
392 int flags,
393 const struct sockaddr *dst_addr,
394 socklen_t addrlen);
395 int (*libc_setsockopt)(int sockfd,
396 int level,
397 int optname,
398 const void *optval,
399 socklen_t optlen);
400 #ifdef HAVE_SIGNALFD
401 int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
402 #endif
403 int (*libc_socket)(int domain, int type, int protocol);
404 int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
405 #ifdef HAVE_TIMERFD_CREATE
406 int (*libc_timerfd_create)(int clockid, int flags);
407 #endif
408 ssize_t (*libc_write)(int fd, const void *buf, size_t count);
409 ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
412 struct swrap {
413 void *libc_handle;
414 void *libsocket_handle;
416 bool initialised;
417 bool enabled;
419 char *socket_dir;
421 struct swrap_libc_fns fns;
424 static struct swrap swrap;
426 /* prototypes */
427 static const char *socket_wrapper_dir(void);
429 #define LIBC_NAME "libc.so"
431 enum swrap_lib {
432 SWRAP_LIBC,
433 SWRAP_LIBNSL,
434 SWRAP_LIBSOCKET,
437 #ifndef NDEBUG
438 static const char *swrap_str_lib(enum swrap_lib lib)
440 switch (lib) {
441 case SWRAP_LIBC:
442 return "libc";
443 case SWRAP_LIBNSL:
444 return "libnsl";
445 case SWRAP_LIBSOCKET:
446 return "libsocket";
449 /* Compiler would warn us about unhandled enum value if we get here */
450 return "unknown";
452 #endif
454 static void *swrap_load_lib_handle(enum swrap_lib lib)
456 int flags = RTLD_LAZY;
457 void *handle = NULL;
458 int i;
460 #ifdef RTLD_DEEPBIND
461 flags |= RTLD_DEEPBIND;
462 #endif
464 switch (lib) {
465 case SWRAP_LIBNSL:
466 /* FALL TROUGH */
467 case SWRAP_LIBSOCKET:
468 #ifdef HAVE_LIBSOCKET
469 handle = swrap.libsocket_handle;
470 if (handle == NULL) {
471 for (i = 10; i >= 0; i--) {
472 char soname[256] = {0};
474 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
475 handle = dlopen(soname, flags);
476 if (handle != NULL) {
477 break;
481 swrap.libsocket_handle = handle;
483 break;
484 #endif
485 /* FALL TROUGH */
486 case SWRAP_LIBC:
487 handle = swrap.libc_handle;
488 #ifdef LIBC_SO
489 if (handle == NULL) {
490 handle = dlopen(LIBC_SO, flags);
492 swrap.libc_handle = handle;
494 #endif
495 if (handle == NULL) {
496 for (i = 10; i >= 0; i--) {
497 char soname[256] = {0};
499 snprintf(soname, sizeof(soname), "libc.so.%d", i);
500 handle = dlopen(soname, flags);
501 if (handle != NULL) {
502 break;
506 swrap.libc_handle = handle;
508 break;
511 if (handle == NULL) {
512 #ifdef RTLD_NEXT
513 handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
514 #else
515 SWRAP_LOG(SWRAP_LOG_ERROR,
516 "Failed to dlopen library: %s\n",
517 dlerror());
518 exit(-1);
519 #endif
522 return handle;
525 static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
527 void *handle;
528 void *func;
530 handle = swrap_load_lib_handle(lib);
532 func = dlsym(handle, fn_name);
533 if (func == NULL) {
534 SWRAP_LOG(SWRAP_LOG_ERROR,
535 "Failed to find %s: %s\n",
536 fn_name, dlerror());
537 exit(-1);
540 SWRAP_LOG(SWRAP_LOG_TRACE,
541 "Loaded %s from %s",
542 fn_name, swrap_str_lib(lib));
543 return func;
546 #define swrap_load_lib_function(lib, fn_name) \
547 if (swrap.fns.libc_##fn_name == NULL) { \
548 void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
549 *(void **) (&swrap.fns.libc_##fn_name) = \
550 swrap_cast_ptr; \
555 * IMPORTANT
557 * Functions especially from libc need to be loaded individually, you can't load
558 * all at once or gdb will segfault at startup. The same applies to valgrind and
559 * has probably something todo with with the linker.
560 * So we need load each function at the point it is called the first time.
562 #ifdef HAVE_ACCEPT4
563 static int libc_accept4(int sockfd,
564 struct sockaddr *addr,
565 socklen_t *addrlen,
566 int flags)
568 swrap_load_lib_function(SWRAP_LIBSOCKET, accept4);
570 return swrap.fns.libc_accept4(sockfd, addr, addrlen, flags);
573 #else /* HAVE_ACCEPT4 */
575 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
577 swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
579 return swrap.fns.libc_accept(sockfd, addr, addrlen);
581 #endif /* HAVE_ACCEPT4 */
583 static int libc_bind(int sockfd,
584 const struct sockaddr *addr,
585 socklen_t addrlen)
587 swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
589 return swrap.fns.libc_bind(sockfd, addr, addrlen);
592 static int libc_close(int fd)
594 swrap_load_lib_function(SWRAP_LIBC, close);
596 return swrap.fns.libc_close(fd);
599 static int libc_connect(int sockfd,
600 const struct sockaddr *addr,
601 socklen_t addrlen)
603 swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
605 return swrap.fns.libc_connect(sockfd, addr, addrlen);
608 static int libc_dup(int fd)
610 swrap_load_lib_function(SWRAP_LIBC, dup);
612 return swrap.fns.libc_dup(fd);
615 static int libc_dup2(int oldfd, int newfd)
617 swrap_load_lib_function(SWRAP_LIBC, dup2);
619 return swrap.fns.libc_dup2(oldfd, newfd);
622 #ifdef HAVE_EVENTFD
623 static int libc_eventfd(int count, int flags)
625 swrap_load_lib_function(SWRAP_LIBC, eventfd);
627 return swrap.fns.libc_eventfd(count, flags);
629 #endif
631 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
632 static int libc_vfcntl(int fd, int cmd, va_list ap)
634 long int args[4];
635 int rc;
636 int i;
638 swrap_load_lib_function(SWRAP_LIBC, fcntl);
640 for (i = 0; i < 4; i++) {
641 args[i] = va_arg(ap, long int);
644 rc = swrap.fns.libc_fcntl(fd,
645 cmd,
646 args[0],
647 args[1],
648 args[2],
649 args[3]);
651 return rc;
654 static int libc_getpeername(int sockfd,
655 struct sockaddr *addr,
656 socklen_t *addrlen)
658 swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
660 return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
663 static int libc_getsockname(int sockfd,
664 struct sockaddr *addr,
665 socklen_t *addrlen)
667 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
669 return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
672 static int libc_getsockopt(int sockfd,
673 int level,
674 int optname,
675 void *optval,
676 socklen_t *optlen)
678 swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
680 return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
683 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
684 static int libc_vioctl(int d, unsigned long int request, va_list ap)
686 long int args[4];
687 int rc;
688 int i;
690 swrap_load_lib_function(SWRAP_LIBC, ioctl);
692 for (i = 0; i < 4; i++) {
693 args[i] = va_arg(ap, long int);
696 rc = swrap.fns.libc_ioctl(d,
697 request,
698 args[0],
699 args[1],
700 args[2],
701 args[3]);
703 return rc;
706 static int libc_listen(int sockfd, int backlog)
708 swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
710 return swrap.fns.libc_listen(sockfd, backlog);
713 static FILE *libc_fopen(const char *name, const char *mode)
715 swrap_load_lib_function(SWRAP_LIBC, fopen);
717 return swrap.fns.libc_fopen(name, mode);
720 static int libc_vopen(const char *pathname, int flags, va_list ap)
722 long int mode = 0;
723 int fd;
725 swrap_load_lib_function(SWRAP_LIBC, open);
727 mode = va_arg(ap, long int);
729 fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
731 return fd;
734 static int libc_open(const char *pathname, int flags, ...)
736 va_list ap;
737 int fd;
739 va_start(ap, flags);
740 fd = libc_vopen(pathname, flags, ap);
741 va_end(ap);
743 return fd;
746 static int libc_pipe(int pipefd[2])
748 swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
750 return swrap.fns.libc_pipe(pipefd);
753 static int libc_read(int fd, void *buf, size_t count)
755 swrap_load_lib_function(SWRAP_LIBC, read);
757 return swrap.fns.libc_read(fd, buf, count);
760 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
762 swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
764 return swrap.fns.libc_readv(fd, iov, iovcnt);
767 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
769 swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
771 return swrap.fns.libc_recv(sockfd, buf, len, flags);
774 static int libc_recvfrom(int sockfd,
775 void *buf,
776 size_t len,
777 int flags,
778 struct sockaddr *src_addr,
779 socklen_t *addrlen)
781 swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
783 return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
786 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
788 swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
790 return swrap.fns.libc_recvmsg(sockfd, msg, flags);
793 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
795 swrap_load_lib_function(SWRAP_LIBSOCKET, send);
797 return swrap.fns.libc_send(sockfd, buf, len, flags);
800 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
802 swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
804 return swrap.fns.libc_sendmsg(sockfd, msg, flags);
807 static int libc_sendto(int sockfd,
808 const void *buf,
809 size_t len,
810 int flags,
811 const struct sockaddr *dst_addr,
812 socklen_t addrlen)
814 swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
816 return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
819 static int libc_setsockopt(int sockfd,
820 int level,
821 int optname,
822 const void *optval,
823 socklen_t optlen)
825 swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
827 return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
830 #ifdef HAVE_SIGNALFD
831 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
833 swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
835 return swrap.fns.libc_signalfd(fd, mask, flags);
837 #endif
839 static int libc_socket(int domain, int type, int protocol)
841 swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
843 return swrap.fns.libc_socket(domain, type, protocol);
846 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
848 swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
850 return swrap.fns.libc_socketpair(domain, type, protocol, sv);
853 #ifdef HAVE_TIMERFD_CREATE
854 static int libc_timerfd_create(int clockid, int flags)
856 swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
858 return swrap.fns.libc_timerfd_create(clockid, flags);
860 #endif
862 static ssize_t libc_write(int fd, const void *buf, size_t count)
864 swrap_load_lib_function(SWRAP_LIBC, write);
866 return swrap.fns.libc_write(fd, buf, count);
869 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
871 swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
873 return swrap.fns.libc_writev(fd, iov, iovcnt);
876 /*********************************************************
877 * SWRAP HELPER FUNCTIONS
878 *********************************************************/
880 #ifdef HAVE_IPV6
882 * FD00::5357:5FXX
884 static const struct in6_addr *swrap_ipv6(void)
886 static struct in6_addr v;
887 static int initialized;
888 int ret;
890 if (initialized) {
891 return &v;
893 initialized = 1;
895 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
896 if (ret <= 0) {
897 abort();
900 return &v;
902 #endif
904 static void set_port(int family, int prt, struct swrap_address *addr)
906 switch (family) {
907 case AF_INET:
908 addr->sa.in.sin_port = htons(prt);
909 break;
910 #ifdef HAVE_IPV6
911 case AF_INET6:
912 addr->sa.in6.sin6_port = htons(prt);
913 break;
914 #endif
918 static size_t socket_length(int family)
920 switch (family) {
921 case AF_INET:
922 return sizeof(struct sockaddr_in);
923 #ifdef HAVE_IPV6
924 case AF_INET6:
925 return sizeof(struct sockaddr_in6);
926 #endif
928 return 0;
931 static const char *socket_wrapper_dir(void)
933 const char *s = getenv("SOCKET_WRAPPER_DIR");
934 if (s == NULL) {
935 return NULL;
937 /* TODO use realpath(3) here, when we add support for threads */
938 if (strncmp(s, "./", 2) == 0) {
939 s += 2;
942 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
943 return s;
946 static unsigned int socket_wrapper_mtu(void)
948 static unsigned int max_mtu = 0;
949 unsigned int tmp;
950 const char *s;
951 char *endp;
953 if (max_mtu != 0) {
954 return max_mtu;
957 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
959 s = getenv("SOCKET_WRAPPER_MTU");
960 if (s == NULL) {
961 goto done;
964 tmp = strtol(s, &endp, 10);
965 if (s == endp) {
966 goto done;
969 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
970 goto done;
972 max_mtu = tmp;
974 done:
975 return max_mtu;
978 bool socket_wrapper_enabled(void)
980 const char *s = socket_wrapper_dir();
982 return s != NULL ? true : false;
985 static unsigned int socket_wrapper_default_iface(void)
987 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
988 if (s) {
989 unsigned int iface;
990 if (sscanf(s, "%u", &iface) == 1) {
991 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
992 return iface;
997 return 1;/* 127.0.0.1 */
1000 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1002 unsigned int iface;
1003 unsigned int prt;
1004 const char *p;
1005 char type;
1007 p = strrchr(un->sun_path, '/');
1008 if (p) p++; else p = un->sun_path;
1010 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1011 errno = EINVAL;
1012 return -1;
1015 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1016 type, iface, prt);
1018 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1019 errno = EINVAL;
1020 return -1;
1023 if (prt > 0xFFFF) {
1024 errno = EINVAL;
1025 return -1;
1028 switch(type) {
1029 case SOCKET_TYPE_CHAR_TCP:
1030 case SOCKET_TYPE_CHAR_UDP: {
1031 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1033 if ((*len) < sizeof(*in2)) {
1034 errno = EINVAL;
1035 return -1;
1038 memset(in2, 0, sizeof(*in2));
1039 in2->sin_family = AF_INET;
1040 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1041 in2->sin_port = htons(prt);
1043 *len = sizeof(*in2);
1044 break;
1046 #ifdef HAVE_IPV6
1047 case SOCKET_TYPE_CHAR_TCP_V6:
1048 case SOCKET_TYPE_CHAR_UDP_V6: {
1049 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1051 if ((*len) < sizeof(*in2)) {
1052 errno = EINVAL;
1053 return -1;
1056 memset(in2, 0, sizeof(*in2));
1057 in2->sin6_family = AF_INET6;
1058 in2->sin6_addr = *swrap_ipv6();
1059 in2->sin6_addr.s6_addr[15] = iface;
1060 in2->sin6_port = htons(prt);
1062 *len = sizeof(*in2);
1063 break;
1065 #endif
1066 default:
1067 errno = EINVAL;
1068 return -1;
1071 return 0;
1074 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1075 int *bcast)
1077 char type = '\0';
1078 unsigned int prt;
1079 unsigned int iface;
1080 int is_bcast = 0;
1082 if (bcast) *bcast = 0;
1084 switch (inaddr->sa_family) {
1085 case AF_INET: {
1086 const struct sockaddr_in *in =
1087 (const struct sockaddr_in *)(const void *)inaddr;
1088 unsigned int addr = ntohl(in->sin_addr.s_addr);
1089 char u_type = '\0';
1090 char b_type = '\0';
1091 char a_type = '\0';
1093 switch (si->type) {
1094 case SOCK_STREAM:
1095 u_type = SOCKET_TYPE_CHAR_TCP;
1096 break;
1097 case SOCK_DGRAM:
1098 u_type = SOCKET_TYPE_CHAR_UDP;
1099 a_type = SOCKET_TYPE_CHAR_UDP;
1100 b_type = SOCKET_TYPE_CHAR_UDP;
1101 break;
1102 default:
1103 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1104 errno = ESOCKTNOSUPPORT;
1105 return -1;
1108 prt = ntohs(in->sin_port);
1109 if (a_type && addr == 0xFFFFFFFF) {
1110 /* 255.255.255.255 only udp */
1111 is_bcast = 2;
1112 type = a_type;
1113 iface = socket_wrapper_default_iface();
1114 } else if (b_type && addr == 0x7FFFFFFF) {
1115 /* 127.255.255.255 only udp */
1116 is_bcast = 1;
1117 type = b_type;
1118 iface = socket_wrapper_default_iface();
1119 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1120 /* 127.0.0.X */
1121 is_bcast = 0;
1122 type = u_type;
1123 iface = (addr & 0x000000FF);
1124 } else {
1125 errno = ENETUNREACH;
1126 return -1;
1128 if (bcast) *bcast = is_bcast;
1129 break;
1131 #ifdef HAVE_IPV6
1132 case AF_INET6: {
1133 const struct sockaddr_in6 *in =
1134 (const struct sockaddr_in6 *)(const void *)inaddr;
1135 struct in6_addr cmp1, cmp2;
1137 switch (si->type) {
1138 case SOCK_STREAM:
1139 type = SOCKET_TYPE_CHAR_TCP_V6;
1140 break;
1141 case SOCK_DGRAM:
1142 type = SOCKET_TYPE_CHAR_UDP_V6;
1143 break;
1144 default:
1145 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1146 errno = ESOCKTNOSUPPORT;
1147 return -1;
1150 /* XXX no multicast/broadcast */
1152 prt = ntohs(in->sin6_port);
1154 cmp1 = *swrap_ipv6();
1155 cmp2 = in->sin6_addr;
1156 cmp2.s6_addr[15] = 0;
1157 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1158 iface = in->sin6_addr.s6_addr[15];
1159 } else {
1160 errno = ENETUNREACH;
1161 return -1;
1164 break;
1166 #endif
1167 default:
1168 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1169 errno = ENETUNREACH;
1170 return -1;
1173 if (prt == 0) {
1174 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1175 errno = EINVAL;
1176 return -1;
1179 if (is_bcast) {
1180 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1181 socket_wrapper_dir());
1182 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1183 /* the caller need to do more processing */
1184 return 0;
1187 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1188 socket_wrapper_dir(), type, iface, prt);
1189 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1191 return 0;
1194 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1195 int *bcast)
1197 char type = '\0';
1198 unsigned int prt;
1199 unsigned int iface;
1200 struct stat st;
1201 int is_bcast = 0;
1203 if (bcast) *bcast = 0;
1205 switch (si->family) {
1206 case AF_INET: {
1207 const struct sockaddr_in *in =
1208 (const struct sockaddr_in *)(const void *)inaddr;
1209 unsigned int addr = ntohl(in->sin_addr.s_addr);
1210 char u_type = '\0';
1211 char d_type = '\0';
1212 char b_type = '\0';
1213 char a_type = '\0';
1215 prt = ntohs(in->sin_port);
1217 switch (si->type) {
1218 case SOCK_STREAM:
1219 u_type = SOCKET_TYPE_CHAR_TCP;
1220 d_type = SOCKET_TYPE_CHAR_TCP;
1221 break;
1222 case SOCK_DGRAM:
1223 u_type = SOCKET_TYPE_CHAR_UDP;
1224 d_type = SOCKET_TYPE_CHAR_UDP;
1225 a_type = SOCKET_TYPE_CHAR_UDP;
1226 b_type = SOCKET_TYPE_CHAR_UDP;
1227 break;
1228 default:
1229 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1230 errno = ESOCKTNOSUPPORT;
1231 return -1;
1234 if (addr == 0) {
1235 /* 0.0.0.0 */
1236 is_bcast = 0;
1237 type = d_type;
1238 iface = socket_wrapper_default_iface();
1239 } else if (a_type && addr == 0xFFFFFFFF) {
1240 /* 255.255.255.255 only udp */
1241 is_bcast = 2;
1242 type = a_type;
1243 iface = socket_wrapper_default_iface();
1244 } else if (b_type && addr == 0x7FFFFFFF) {
1245 /* 127.255.255.255 only udp */
1246 is_bcast = 1;
1247 type = b_type;
1248 iface = socket_wrapper_default_iface();
1249 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1250 /* 127.0.0.X */
1251 is_bcast = 0;
1252 type = u_type;
1253 iface = (addr & 0x000000FF);
1254 } else {
1255 errno = EADDRNOTAVAIL;
1256 return -1;
1259 /* Store the bind address for connect() */
1260 if (si->bindname.sa_socklen == 0) {
1261 struct sockaddr_in bind_in;
1262 socklen_t blen = sizeof(struct sockaddr_in);
1264 ZERO_STRUCT(bind_in);
1265 bind_in.sin_family = in->sin_family;
1266 bind_in.sin_port = in->sin_port;
1267 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1269 si->bindname.sa_socklen = blen;
1270 memcpy(&si->bindname.sa.in, &bind_in, blen);
1273 break;
1275 #ifdef HAVE_IPV6
1276 case AF_INET6: {
1277 const struct sockaddr_in6 *in =
1278 (const struct sockaddr_in6 *)(const void *)inaddr;
1279 struct in6_addr cmp1, cmp2;
1281 switch (si->type) {
1282 case SOCK_STREAM:
1283 type = SOCKET_TYPE_CHAR_TCP_V6;
1284 break;
1285 case SOCK_DGRAM:
1286 type = SOCKET_TYPE_CHAR_UDP_V6;
1287 break;
1288 default:
1289 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1290 errno = ESOCKTNOSUPPORT;
1291 return -1;
1294 /* XXX no multicast/broadcast */
1296 prt = ntohs(in->sin6_port);
1298 cmp1 = *swrap_ipv6();
1299 cmp2 = in->sin6_addr;
1300 cmp2.s6_addr[15] = 0;
1301 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1302 iface = socket_wrapper_default_iface();
1303 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1304 iface = in->sin6_addr.s6_addr[15];
1305 } else {
1306 errno = EADDRNOTAVAIL;
1307 return -1;
1310 /* Store the bind address for connect() */
1311 if (si->bindname.sa_socklen == 0) {
1312 struct sockaddr_in6 bind_in;
1313 socklen_t blen = sizeof(struct sockaddr_in6);
1315 ZERO_STRUCT(bind_in);
1316 bind_in.sin6_family = in->sin6_family;
1317 bind_in.sin6_port = in->sin6_port;
1319 bind_in.sin6_addr = *swrap_ipv6();
1320 bind_in.sin6_addr.s6_addr[15] = iface;
1322 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1323 si->bindname.sa_socklen = blen;
1326 break;
1328 #endif
1329 default:
1330 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1331 errno = EADDRNOTAVAIL;
1332 return -1;
1336 if (bcast) *bcast = is_bcast;
1338 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1339 errno = EINVAL;
1340 return -1;
1343 if (prt == 0) {
1344 /* handle auto-allocation of ephemeral ports */
1345 for (prt = 5001; prt < 10000; prt++) {
1346 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1347 socket_wrapper_dir(), type, iface, prt);
1348 if (stat(un->sun_path, &st) == 0) continue;
1350 set_port(si->family, prt, &si->myname);
1351 set_port(si->family, prt, &si->bindname);
1353 break;
1355 if (prt == 10000) {
1356 errno = ENFILE;
1357 return -1;
1361 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1362 socket_wrapper_dir(), type, iface, prt);
1363 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1364 return 0;
1367 static struct socket_info *find_socket_info(int fd)
1369 struct socket_info *i;
1371 for (i = sockets; i; i = i->next) {
1372 struct socket_info_fd *f;
1373 for (f = i->fds; f; f = f->next) {
1374 if (f->fd == fd) {
1375 return i;
1380 return NULL;
1383 #if 0 /* FIXME */
1384 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1386 struct socket_info *s;
1388 /* first catch invalid input */
1389 switch (sa->sa_family) {
1390 case AF_INET:
1391 if (len < sizeof(struct sockaddr_in)) {
1392 return false;
1394 break;
1395 #if HAVE_IPV6
1396 case AF_INET6:
1397 if (len < sizeof(struct sockaddr_in6)) {
1398 return false;
1400 break;
1401 #endif
1402 default:
1403 return false;
1404 break;
1407 for (s = sockets; s != NULL; s = s->next) {
1408 if (s->myname == NULL) {
1409 continue;
1411 if (s->myname->sa_family != sa->sa_family) {
1412 continue;
1414 switch (s->myname->sa_family) {
1415 case AF_INET: {
1416 struct sockaddr_in *sin1, *sin2;
1418 sin1 = (struct sockaddr_in *)s->myname;
1419 sin2 = (struct sockaddr_in *)sa;
1421 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1422 continue;
1424 if (sin1->sin_port != sin2->sin_port) {
1425 continue;
1427 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1428 continue;
1431 /* found */
1432 return true;
1433 break;
1435 #if HAVE_IPV6
1436 case AF_INET6: {
1437 struct sockaddr_in6 *sin1, *sin2;
1439 sin1 = (struct sockaddr_in6 *)s->myname;
1440 sin2 = (struct sockaddr_in6 *)sa;
1442 if (sin1->sin6_port != sin2->sin6_port) {
1443 continue;
1445 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1446 &sin2->sin6_addr))
1448 continue;
1451 /* found */
1452 return true;
1453 break;
1455 #endif
1456 default:
1457 continue;
1458 break;
1463 return false;
1465 #endif
1467 static void swrap_remove_stale(int fd)
1469 struct socket_info *si = find_socket_info(fd);
1470 struct socket_info_fd *fi;
1472 if (si != NULL) {
1473 for (fi = si->fds; fi; fi = fi->next) {
1474 if (fi->fd == fd) {
1475 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1476 SWRAP_DLIST_REMOVE(si->fds, fi);
1477 free(fi);
1478 break;
1482 if (si->fds == NULL) {
1483 SWRAP_DLIST_REMOVE(sockets, si);
1484 if (si->un_addr.sun_path[0] != '\0') {
1485 unlink(si->un_addr.sun_path);
1487 free(si);
1492 static int sockaddr_convert_to_un(struct socket_info *si,
1493 const struct sockaddr *in_addr,
1494 socklen_t in_len,
1495 struct sockaddr_un *out_addr,
1496 int alloc_sock,
1497 int *bcast)
1499 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1501 (void) in_len; /* unused */
1503 if (out_addr == NULL) {
1504 return 0;
1507 out->sa_family = AF_UNIX;
1508 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1509 out->sa_len = sizeof(*out_addr);
1510 #endif
1512 switch (in_addr->sa_family) {
1513 case AF_UNSPEC: {
1514 const struct sockaddr_in *sin;
1515 if (si->family != AF_INET) {
1516 break;
1518 if (in_len < sizeof(struct sockaddr_in)) {
1519 break;
1521 sin = (const struct sockaddr_in *)(const void *)in_addr;
1522 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1523 break;
1527 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1528 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1531 /* FALL THROUGH */
1533 case AF_INET:
1534 #ifdef HAVE_IPV6
1535 case AF_INET6:
1536 #endif
1537 switch (si->type) {
1538 case SOCK_STREAM:
1539 case SOCK_DGRAM:
1540 break;
1541 default:
1542 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1543 errno = ESOCKTNOSUPPORT;
1544 return -1;
1546 if (alloc_sock) {
1547 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1548 } else {
1549 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1551 default:
1552 break;
1555 errno = EAFNOSUPPORT;
1556 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1557 return -1;
1560 static int sockaddr_convert_from_un(const struct socket_info *si,
1561 const struct sockaddr_un *in_addr,
1562 socklen_t un_addrlen,
1563 int family,
1564 struct sockaddr *out_addr,
1565 socklen_t *out_addrlen)
1567 int ret;
1569 if (out_addr == NULL || out_addrlen == NULL)
1570 return 0;
1572 if (un_addrlen == 0) {
1573 *out_addrlen = 0;
1574 return 0;
1577 switch (family) {
1578 case AF_INET:
1579 #ifdef HAVE_IPV6
1580 case AF_INET6:
1581 #endif
1582 switch (si->type) {
1583 case SOCK_STREAM:
1584 case SOCK_DGRAM:
1585 break;
1586 default:
1587 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1588 errno = ESOCKTNOSUPPORT;
1589 return -1;
1591 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1592 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1593 out_addr->sa_len = *out_addrlen;
1594 #endif
1595 return ret;
1596 default:
1597 break;
1600 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1601 errno = EAFNOSUPPORT;
1602 return -1;
1605 enum swrap_packet_type {
1606 SWRAP_CONNECT_SEND,
1607 SWRAP_CONNECT_UNREACH,
1608 SWRAP_CONNECT_RECV,
1609 SWRAP_CONNECT_ACK,
1610 SWRAP_ACCEPT_SEND,
1611 SWRAP_ACCEPT_RECV,
1612 SWRAP_ACCEPT_ACK,
1613 SWRAP_RECVFROM,
1614 SWRAP_SENDTO,
1615 SWRAP_SENDTO_UNREACH,
1616 SWRAP_PENDING_RST,
1617 SWRAP_RECV,
1618 SWRAP_RECV_RST,
1619 SWRAP_SEND,
1620 SWRAP_SEND_RST,
1621 SWRAP_CLOSE_SEND,
1622 SWRAP_CLOSE_RECV,
1623 SWRAP_CLOSE_ACK,
1626 struct swrap_file_hdr {
1627 uint32_t magic;
1628 uint16_t version_major;
1629 uint16_t version_minor;
1630 int32_t timezone;
1631 uint32_t sigfigs;
1632 uint32_t frame_max_len;
1633 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
1634 uint32_t link_type;
1636 #define SWRAP_FILE_HDR_SIZE 24
1638 struct swrap_packet_frame {
1639 uint32_t seconds;
1640 uint32_t micro_seconds;
1641 uint32_t recorded_length;
1642 uint32_t full_length;
1644 #define SWRAP_PACKET_FRAME_SIZE 16
1646 union swrap_packet_ip {
1647 struct {
1648 uint8_t ver_hdrlen;
1649 uint8_t tos;
1650 uint16_t packet_length;
1651 uint16_t identification;
1652 uint8_t flags;
1653 uint8_t fragment;
1654 uint8_t ttl;
1655 uint8_t protocol;
1656 uint16_t hdr_checksum;
1657 uint32_t src_addr;
1658 uint32_t dest_addr;
1659 } v4;
1660 #define SWRAP_PACKET_IP_V4_SIZE 20
1661 struct {
1662 uint8_t ver_prio;
1663 uint8_t flow_label_high;
1664 uint16_t flow_label_low;
1665 uint16_t payload_length;
1666 uint8_t next_header;
1667 uint8_t hop_limit;
1668 uint8_t src_addr[16];
1669 uint8_t dest_addr[16];
1670 } v6;
1671 #define SWRAP_PACKET_IP_V6_SIZE 40
1673 #define SWRAP_PACKET_IP_SIZE 40
1675 union swrap_packet_payload {
1676 struct {
1677 uint16_t source_port;
1678 uint16_t dest_port;
1679 uint32_t seq_num;
1680 uint32_t ack_num;
1681 uint8_t hdr_length;
1682 uint8_t control;
1683 uint16_t window;
1684 uint16_t checksum;
1685 uint16_t urg;
1686 } tcp;
1687 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
1688 struct {
1689 uint16_t source_port;
1690 uint16_t dest_port;
1691 uint16_t length;
1692 uint16_t checksum;
1693 } udp;
1694 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
1695 struct {
1696 uint8_t type;
1697 uint8_t code;
1698 uint16_t checksum;
1699 uint32_t unused;
1700 } icmp4;
1701 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
1702 struct {
1703 uint8_t type;
1704 uint8_t code;
1705 uint16_t checksum;
1706 uint32_t unused;
1707 } icmp6;
1708 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
1710 #define SWRAP_PACKET_PAYLOAD_SIZE 20
1712 #define SWRAP_PACKET_MIN_ALLOC \
1713 (SWRAP_PACKET_FRAME_SIZE + \
1714 SWRAP_PACKET_IP_SIZE + \
1715 SWRAP_PACKET_PAYLOAD_SIZE)
1717 static const char *swrap_pcap_init_file(void)
1719 static int initialized = 0;
1720 static const char *s = NULL;
1721 static const struct swrap_file_hdr h;
1722 static const struct swrap_packet_frame f;
1723 static const union swrap_packet_ip i;
1724 static const union swrap_packet_payload p;
1726 if (initialized == 1) {
1727 return s;
1729 initialized = 1;
1732 * TODO: don't use the structs use plain buffer offsets
1733 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
1735 * for now make sure we disable PCAP support
1736 * if the struct has alignment!
1738 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
1739 return NULL;
1741 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
1742 return NULL;
1744 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
1745 return NULL;
1747 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
1748 return NULL;
1750 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
1751 return NULL;
1753 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
1754 return NULL;
1756 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
1757 return NULL;
1759 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
1760 return NULL;
1762 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
1763 return NULL;
1765 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
1766 return NULL;
1769 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
1770 if (s == NULL) {
1771 return NULL;
1773 if (strncmp(s, "./", 2) == 0) {
1774 s += 2;
1776 return s;
1779 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
1780 const struct sockaddr *src,
1781 const struct sockaddr *dest,
1782 int socket_type,
1783 const uint8_t *payload,
1784 size_t payload_len,
1785 unsigned long tcp_seqno,
1786 unsigned long tcp_ack,
1787 unsigned char tcp_ctl,
1788 int unreachable,
1789 size_t *_packet_len)
1791 uint8_t *base;
1792 uint8_t *buf;
1793 struct swrap_packet_frame *frame;
1794 union swrap_packet_ip *ip;
1795 union swrap_packet_payload *pay;
1796 size_t packet_len;
1797 size_t alloc_len;
1798 size_t nonwire_len = sizeof(*frame);
1799 size_t wire_hdr_len = 0;
1800 size_t wire_len = 0;
1801 size_t ip_hdr_len = 0;
1802 size_t icmp_hdr_len = 0;
1803 size_t icmp_truncate_len = 0;
1804 uint8_t protocol = 0, icmp_protocol = 0;
1805 const struct sockaddr_in *src_in = NULL;
1806 const struct sockaddr_in *dest_in = NULL;
1807 #ifdef HAVE_IPV6
1808 const struct sockaddr_in6 *src_in6 = NULL;
1809 const struct sockaddr_in6 *dest_in6 = NULL;
1810 #endif
1811 uint16_t src_port;
1812 uint16_t dest_port;
1814 switch (src->sa_family) {
1815 case AF_INET:
1816 src_in = (const struct sockaddr_in *)(const void *)src;
1817 dest_in = (const struct sockaddr_in *)(const void *)dest;
1818 src_port = src_in->sin_port;
1819 dest_port = dest_in->sin_port;
1820 ip_hdr_len = sizeof(ip->v4);
1821 break;
1822 #ifdef HAVE_IPV6
1823 case AF_INET6:
1824 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
1825 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
1826 src_port = src_in6->sin6_port;
1827 dest_port = dest_in6->sin6_port;
1828 ip_hdr_len = sizeof(ip->v6);
1829 break;
1830 #endif
1831 default:
1832 return NULL;
1835 switch (socket_type) {
1836 case SOCK_STREAM:
1837 protocol = 0x06; /* TCP */
1838 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
1839 wire_len = wire_hdr_len + payload_len;
1840 break;
1842 case SOCK_DGRAM:
1843 protocol = 0x11; /* UDP */
1844 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
1845 wire_len = wire_hdr_len + payload_len;
1846 break;
1848 default:
1849 return NULL;
1852 if (unreachable) {
1853 icmp_protocol = protocol;
1854 switch (src->sa_family) {
1855 case AF_INET:
1856 protocol = 0x01; /* ICMPv4 */
1857 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
1858 break;
1859 #ifdef HAVE_IPV6
1860 case AF_INET6:
1861 protocol = 0x3A; /* ICMPv6 */
1862 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
1863 break;
1864 #endif
1866 if (wire_len > 64 ) {
1867 icmp_truncate_len = wire_len - 64;
1869 wire_hdr_len += icmp_hdr_len;
1870 wire_len += icmp_hdr_len;
1873 packet_len = nonwire_len + wire_len;
1874 alloc_len = packet_len;
1875 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
1876 alloc_len = SWRAP_PACKET_MIN_ALLOC;
1879 base = (uint8_t *)calloc(1, alloc_len);
1880 if (base == NULL) {
1881 return NULL;
1884 buf = base;
1886 frame = (struct swrap_packet_frame *)(void *)buf;
1887 frame->seconds = tval->tv_sec;
1888 frame->micro_seconds = tval->tv_usec;
1889 frame->recorded_length = wire_len - icmp_truncate_len;
1890 frame->full_length = wire_len - icmp_truncate_len;
1891 buf += SWRAP_PACKET_FRAME_SIZE;
1893 ip = (union swrap_packet_ip *)(void *)buf;
1894 switch (src->sa_family) {
1895 case AF_INET:
1896 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1897 ip->v4.tos = 0x00;
1898 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
1899 ip->v4.identification = htons(0xFFFF);
1900 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1901 ip->v4.fragment = htons(0x0000);
1902 ip->v4.ttl = 0xFF;
1903 ip->v4.protocol = protocol;
1904 ip->v4.hdr_checksum = htons(0x0000);
1905 ip->v4.src_addr = src_in->sin_addr.s_addr;
1906 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
1907 buf += SWRAP_PACKET_IP_V4_SIZE;
1908 break;
1909 #ifdef HAVE_IPV6
1910 case AF_INET6:
1911 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1912 ip->v6.flow_label_high = 0x00;
1913 ip->v6.flow_label_low = 0x0000;
1914 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1915 ip->v6.next_header = protocol;
1916 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
1917 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
1918 buf += SWRAP_PACKET_IP_V6_SIZE;
1919 break;
1920 #endif
1923 if (unreachable) {
1924 pay = (union swrap_packet_payload *)(void *)buf;
1925 switch (src->sa_family) {
1926 case AF_INET:
1927 pay->icmp4.type = 0x03; /* destination unreachable */
1928 pay->icmp4.code = 0x01; /* host unreachable */
1929 pay->icmp4.checksum = htons(0x0000);
1930 pay->icmp4.unused = htonl(0x00000000);
1931 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
1933 /* set the ip header in the ICMP payload */
1934 ip = (union swrap_packet_ip *)(void *)buf;
1935 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
1936 ip->v4.tos = 0x00;
1937 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
1938 ip->v4.identification = htons(0xFFFF);
1939 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
1940 ip->v4.fragment = htons(0x0000);
1941 ip->v4.ttl = 0xFF;
1942 ip->v4.protocol = icmp_protocol;
1943 ip->v4.hdr_checksum = htons(0x0000);
1944 ip->v4.src_addr = dest_in->sin_addr.s_addr;
1945 ip->v4.dest_addr = src_in->sin_addr.s_addr;
1946 buf += SWRAP_PACKET_IP_V4_SIZE;
1948 src_port = dest_in->sin_port;
1949 dest_port = src_in->sin_port;
1950 break;
1951 #ifdef HAVE_IPV6
1952 case AF_INET6:
1953 pay->icmp6.type = 0x01; /* destination unreachable */
1954 pay->icmp6.code = 0x03; /* address unreachable */
1955 pay->icmp6.checksum = htons(0x0000);
1956 pay->icmp6.unused = htonl(0x00000000);
1957 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1959 /* set the ip header in the ICMP payload */
1960 ip = (union swrap_packet_ip *)(void *)buf;
1961 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
1962 ip->v6.flow_label_high = 0x00;
1963 ip->v6.flow_label_low = 0x0000;
1964 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
1965 ip->v6.next_header = protocol;
1966 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1967 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1968 buf += SWRAP_PACKET_IP_V6_SIZE;
1970 src_port = dest_in6->sin6_port;
1971 dest_port = src_in6->sin6_port;
1972 break;
1973 #endif
1977 pay = (union swrap_packet_payload *)(void *)buf;
1979 switch (socket_type) {
1980 case SOCK_STREAM:
1981 pay->tcp.source_port = src_port;
1982 pay->tcp.dest_port = dest_port;
1983 pay->tcp.seq_num = htonl(tcp_seqno);
1984 pay->tcp.ack_num = htonl(tcp_ack);
1985 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
1986 pay->tcp.control = tcp_ctl;
1987 pay->tcp.window = htons(0x7FFF);
1988 pay->tcp.checksum = htons(0x0000);
1989 pay->tcp.urg = htons(0x0000);
1990 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1992 break;
1994 case SOCK_DGRAM:
1995 pay->udp.source_port = src_port;
1996 pay->udp.dest_port = dest_port;
1997 pay->udp.length = htons(8 + payload_len);
1998 pay->udp.checksum = htons(0x0000);
1999 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2001 break;
2004 if (payload && payload_len > 0) {
2005 memcpy(buf, payload, payload_len);
2008 *_packet_len = packet_len - icmp_truncate_len;
2009 return base;
2012 static int swrap_pcap_get_fd(const char *fname)
2014 static int fd = -1;
2016 if (fd != -1) return fd;
2018 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2019 if (fd != -1) {
2020 struct swrap_file_hdr file_hdr;
2021 file_hdr.magic = 0xA1B2C3D4;
2022 file_hdr.version_major = 0x0002;
2023 file_hdr.version_minor = 0x0004;
2024 file_hdr.timezone = 0x00000000;
2025 file_hdr.sigfigs = 0x00000000;
2026 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2027 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2029 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2030 close(fd);
2031 fd = -1;
2033 return fd;
2036 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2038 return fd;
2041 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2042 const struct sockaddr *addr,
2043 enum swrap_packet_type type,
2044 const void *buf, size_t len,
2045 size_t *packet_len)
2047 const struct sockaddr *src_addr;
2048 const struct sockaddr *dest_addr;
2049 unsigned long tcp_seqno = 0;
2050 unsigned long tcp_ack = 0;
2051 unsigned char tcp_ctl = 0;
2052 int unreachable = 0;
2054 struct timeval tv;
2056 switch (si->family) {
2057 case AF_INET:
2058 break;
2059 #ifdef HAVE_IPV6
2060 case AF_INET6:
2061 break;
2062 #endif
2063 default:
2064 return NULL;
2067 switch (type) {
2068 case SWRAP_CONNECT_SEND:
2069 if (si->type != SOCK_STREAM) return NULL;
2071 src_addr = &si->myname.sa.s;
2072 dest_addr = addr;
2074 tcp_seqno = si->io.pck_snd;
2075 tcp_ack = si->io.pck_rcv;
2076 tcp_ctl = 0x02; /* SYN */
2078 si->io.pck_snd += 1;
2080 break;
2082 case SWRAP_CONNECT_RECV:
2083 if (si->type != SOCK_STREAM) return NULL;
2085 dest_addr = &si->myname.sa.s;
2086 src_addr = addr;
2088 tcp_seqno = si->io.pck_rcv;
2089 tcp_ack = si->io.pck_snd;
2090 tcp_ctl = 0x12; /** SYN,ACK */
2092 si->io.pck_rcv += 1;
2094 break;
2096 case SWRAP_CONNECT_UNREACH:
2097 if (si->type != SOCK_STREAM) return NULL;
2099 dest_addr = &si->myname.sa.s;
2100 src_addr = addr;
2102 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2103 tcp_seqno = si->io.pck_snd - 1;
2104 tcp_ack = si->io.pck_rcv;
2105 tcp_ctl = 0x02; /* SYN */
2106 unreachable = 1;
2108 break;
2110 case SWRAP_CONNECT_ACK:
2111 if (si->type != SOCK_STREAM) return NULL;
2113 src_addr = &si->myname.sa.s;
2114 dest_addr = addr;
2116 tcp_seqno = si->io.pck_snd;
2117 tcp_ack = si->io.pck_rcv;
2118 tcp_ctl = 0x10; /* ACK */
2120 break;
2122 case SWRAP_ACCEPT_SEND:
2123 if (si->type != SOCK_STREAM) return NULL;
2125 dest_addr = &si->myname.sa.s;
2126 src_addr = addr;
2128 tcp_seqno = si->io.pck_rcv;
2129 tcp_ack = si->io.pck_snd;
2130 tcp_ctl = 0x02; /* SYN */
2132 si->io.pck_rcv += 1;
2134 break;
2136 case SWRAP_ACCEPT_RECV:
2137 if (si->type != SOCK_STREAM) return NULL;
2139 src_addr = &si->myname.sa.s;
2140 dest_addr = addr;
2142 tcp_seqno = si->io.pck_snd;
2143 tcp_ack = si->io.pck_rcv;
2144 tcp_ctl = 0x12; /* SYN,ACK */
2146 si->io.pck_snd += 1;
2148 break;
2150 case SWRAP_ACCEPT_ACK:
2151 if (si->type != SOCK_STREAM) return NULL;
2153 dest_addr = &si->myname.sa.s;
2154 src_addr = addr;
2156 tcp_seqno = si->io.pck_rcv;
2157 tcp_ack = si->io.pck_snd;
2158 tcp_ctl = 0x10; /* ACK */
2160 break;
2162 case SWRAP_SEND:
2163 src_addr = &si->myname.sa.s;
2164 dest_addr = &si->peername.sa.s;
2166 tcp_seqno = si->io.pck_snd;
2167 tcp_ack = si->io.pck_rcv;
2168 tcp_ctl = 0x18; /* PSH,ACK */
2170 si->io.pck_snd += len;
2172 break;
2174 case SWRAP_SEND_RST:
2175 dest_addr = &si->myname.sa.s;
2176 src_addr = &si->peername.sa.s;
2178 if (si->type == SOCK_DGRAM) {
2179 return swrap_pcap_marshall_packet(si,
2180 &si->peername.sa.s,
2181 SWRAP_SENDTO_UNREACH,
2182 buf,
2183 len,
2184 packet_len);
2187 tcp_seqno = si->io.pck_rcv;
2188 tcp_ack = si->io.pck_snd;
2189 tcp_ctl = 0x14; /** RST,ACK */
2191 break;
2193 case SWRAP_PENDING_RST:
2194 dest_addr = &si->myname.sa.s;
2195 src_addr = &si->peername.sa.s;
2197 if (si->type == SOCK_DGRAM) {
2198 return NULL;
2201 tcp_seqno = si->io.pck_rcv;
2202 tcp_ack = si->io.pck_snd;
2203 tcp_ctl = 0x14; /* RST,ACK */
2205 break;
2207 case SWRAP_RECV:
2208 dest_addr = &si->myname.sa.s;
2209 src_addr = &si->peername.sa.s;
2211 tcp_seqno = si->io.pck_rcv;
2212 tcp_ack = si->io.pck_snd;
2213 tcp_ctl = 0x18; /* PSH,ACK */
2215 si->io.pck_rcv += len;
2217 break;
2219 case SWRAP_RECV_RST:
2220 dest_addr = &si->myname.sa.s;
2221 src_addr = &si->peername.sa.s;
2223 if (si->type == SOCK_DGRAM) {
2224 return NULL;
2227 tcp_seqno = si->io.pck_rcv;
2228 tcp_ack = si->io.pck_snd;
2229 tcp_ctl = 0x14; /* RST,ACK */
2231 break;
2233 case SWRAP_SENDTO:
2234 src_addr = &si->myname.sa.s;
2235 dest_addr = addr;
2237 si->io.pck_snd += len;
2239 break;
2241 case SWRAP_SENDTO_UNREACH:
2242 dest_addr = &si->myname.sa.s;
2243 src_addr = addr;
2245 unreachable = 1;
2247 break;
2249 case SWRAP_RECVFROM:
2250 dest_addr = &si->myname.sa.s;
2251 src_addr = addr;
2253 si->io.pck_rcv += len;
2255 break;
2257 case SWRAP_CLOSE_SEND:
2258 if (si->type != SOCK_STREAM) return NULL;
2260 src_addr = &si->myname.sa.s;
2261 dest_addr = &si->peername.sa.s;
2263 tcp_seqno = si->io.pck_snd;
2264 tcp_ack = si->io.pck_rcv;
2265 tcp_ctl = 0x11; /* FIN, ACK */
2267 si->io.pck_snd += 1;
2269 break;
2271 case SWRAP_CLOSE_RECV:
2272 if (si->type != SOCK_STREAM) return NULL;
2274 dest_addr = &si->myname.sa.s;
2275 src_addr = &si->peername.sa.s;
2277 tcp_seqno = si->io.pck_rcv;
2278 tcp_ack = si->io.pck_snd;
2279 tcp_ctl = 0x11; /* FIN,ACK */
2281 si->io.pck_rcv += 1;
2283 break;
2285 case SWRAP_CLOSE_ACK:
2286 if (si->type != SOCK_STREAM) return NULL;
2288 src_addr = &si->myname.sa.s;
2289 dest_addr = &si->peername.sa.s;
2291 tcp_seqno = si->io.pck_snd;
2292 tcp_ack = si->io.pck_rcv;
2293 tcp_ctl = 0x10; /* ACK */
2295 break;
2296 default:
2297 return NULL;
2300 swrapGetTimeOfDay(&tv);
2302 return swrap_pcap_packet_init(&tv,
2303 src_addr,
2304 dest_addr,
2305 si->type,
2306 (const uint8_t *)buf,
2307 len,
2308 tcp_seqno,
2309 tcp_ack,
2310 tcp_ctl,
2311 unreachable,
2312 packet_len);
2315 static void swrap_pcap_dump_packet(struct socket_info *si,
2316 const struct sockaddr *addr,
2317 enum swrap_packet_type type,
2318 const void *buf, size_t len)
2320 const char *file_name;
2321 uint8_t *packet;
2322 size_t packet_len = 0;
2323 int fd;
2325 file_name = swrap_pcap_init_file();
2326 if (!file_name) {
2327 return;
2330 packet = swrap_pcap_marshall_packet(si,
2331 addr,
2332 type,
2333 buf,
2334 len,
2335 &packet_len);
2336 if (packet == NULL) {
2337 return;
2340 fd = swrap_pcap_get_fd(file_name);
2341 if (fd != -1) {
2342 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2343 free(packet);
2344 return;
2348 free(packet);
2351 /****************************************************************************
2352 * SIGNALFD
2353 ***************************************************************************/
2355 #ifdef HAVE_SIGNALFD
2356 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2358 int rc;
2360 rc = libc_signalfd(fd, mask, flags);
2361 if (rc != -1) {
2362 swrap_remove_stale(fd);
2365 return rc;
2368 int signalfd(int fd, const sigset_t *mask, int flags)
2370 return swrap_signalfd(fd, mask, flags);
2372 #endif
2374 /****************************************************************************
2375 * SOCKET
2376 ***************************************************************************/
2378 static int swrap_socket(int family, int type, int protocol)
2380 struct socket_info *si;
2381 struct socket_info_fd *fi;
2382 int fd;
2383 int real_type = type;
2386 * Remove possible addition flags passed to socket() so
2387 * do not fail checking the type.
2388 * See https://lwn.net/Articles/281965/
2390 #ifdef SOCK_CLOEXEC
2391 real_type &= ~SOCK_CLOEXEC;
2392 #endif
2393 #ifdef SOCK_NONBLOCK
2394 real_type &= ~SOCK_NONBLOCK;
2395 #endif
2397 if (!socket_wrapper_enabled()) {
2398 return libc_socket(family, type, protocol);
2401 switch (family) {
2402 case AF_INET:
2403 #ifdef HAVE_IPV6
2404 case AF_INET6:
2405 #endif
2406 break;
2407 #ifdef AF_NETLINK
2408 case AF_NETLINK:
2409 #endif /* AF_NETLINK */
2410 #ifdef AF_PACKET
2411 case AF_PACKET:
2412 #endif /* AF_PACKET */
2413 case AF_UNIX:
2414 return libc_socket(family, type, protocol);
2415 default:
2416 errno = EAFNOSUPPORT;
2417 return -1;
2420 switch (real_type) {
2421 case SOCK_STREAM:
2422 break;
2423 case SOCK_DGRAM:
2424 break;
2425 default:
2426 errno = EPROTONOSUPPORT;
2427 return -1;
2430 switch (protocol) {
2431 case 0:
2432 break;
2433 case 6:
2434 if (real_type == SOCK_STREAM) {
2435 break;
2437 /*fall through*/
2438 case 17:
2439 if (real_type == SOCK_DGRAM) {
2440 break;
2442 /*fall through*/
2443 default:
2444 errno = EPROTONOSUPPORT;
2445 return -1;
2449 * We must call libc_socket with type, from the caller, not the version
2450 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2452 fd = libc_socket(AF_UNIX, type, 0);
2454 if (fd == -1) {
2455 return -1;
2458 /* Check if we have a stale fd and remove it */
2459 si = find_socket_info(fd);
2460 if (si != NULL) {
2461 swrap_remove_stale(fd);
2464 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
2465 if (si == NULL) {
2466 errno = ENOMEM;
2467 return -1;
2470 si->family = family;
2472 /* however, the rest of the socket_wrapper code expects just
2473 * the type, not the flags */
2474 si->type = real_type;
2475 si->protocol = protocol;
2478 * Setup myname so getsockname() can succeed to find out the socket
2479 * type.
2481 switch(si->family) {
2482 case AF_INET: {
2483 struct sockaddr_in sin = {
2484 .sin_family = AF_INET,
2487 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2488 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2489 break;
2491 case AF_INET6: {
2492 struct sockaddr_in6 sin6 = {
2493 .sin6_family = AF_INET6,
2496 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2497 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2498 break;
2500 default:
2501 free(si);
2502 errno = EINVAL;
2503 return -1;
2506 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2507 if (fi == NULL) {
2508 free(si);
2509 errno = ENOMEM;
2510 return -1;
2513 fi->fd = fd;
2515 SWRAP_DLIST_ADD(si->fds, fi);
2516 SWRAP_DLIST_ADD(sockets, si);
2518 SWRAP_LOG(SWRAP_LOG_TRACE,
2519 "Created %s socket for protocol %s",
2520 si->family == AF_INET ? "IPv4" : "IPv6",
2521 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2523 return fd;
2526 int socket(int family, int type, int protocol)
2528 return swrap_socket(family, type, protocol);
2531 /****************************************************************************
2532 * SOCKETPAIR
2533 ***************************************************************************/
2535 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2537 int rc;
2539 rc = libc_socketpair(family, type, protocol, sv);
2540 if (rc != -1) {
2541 swrap_remove_stale(sv[0]);
2542 swrap_remove_stale(sv[1]);
2545 return rc;
2548 int socketpair(int family, int type, int protocol, int sv[2])
2550 return swrap_socketpair(family, type, protocol, sv);
2553 /****************************************************************************
2554 * SOCKETPAIR
2555 ***************************************************************************/
2557 #ifdef HAVE_TIMERFD_CREATE
2558 static int swrap_timerfd_create(int clockid, int flags)
2560 int fd;
2562 fd = libc_timerfd_create(clockid, flags);
2563 if (fd != -1) {
2564 swrap_remove_stale(fd);
2567 return fd;
2570 int timerfd_create(int clockid, int flags)
2572 return swrap_timerfd_create(clockid, flags);
2574 #endif
2576 /****************************************************************************
2577 * PIPE
2578 ***************************************************************************/
2580 static int swrap_pipe(int pipefd[2])
2582 int rc;
2584 rc = libc_pipe(pipefd);
2585 if (rc != -1) {
2586 swrap_remove_stale(pipefd[0]);
2587 swrap_remove_stale(pipefd[1]);
2590 return rc;
2593 int pipe(int pipefd[2])
2595 return swrap_pipe(pipefd);
2598 /****************************************************************************
2599 * ACCEPT
2600 ***************************************************************************/
2602 static int swrap_accept(int s,
2603 struct sockaddr *addr,
2604 socklen_t *addrlen,
2605 int flags)
2607 struct socket_info *parent_si, *child_si;
2608 struct socket_info_fd *child_fi;
2609 int fd;
2610 struct swrap_address un_addr = {
2611 .sa_socklen = sizeof(struct sockaddr_un),
2613 struct swrap_address un_my_addr = {
2614 .sa_socklen = sizeof(struct sockaddr_un),
2616 struct swrap_address in_addr = {
2617 .sa_socklen = sizeof(struct sockaddr_storage),
2619 struct swrap_address in_my_addr = {
2620 .sa_socklen = sizeof(struct sockaddr_storage),
2622 int ret;
2624 parent_si = find_socket_info(s);
2625 if (!parent_si) {
2626 #ifdef HAVE_ACCEPT4
2627 return libc_accept4(s, addr, addrlen, flags);
2628 #else
2629 return libc_accept(s, addr, addrlen);
2630 #endif
2634 * assume out sockaddr have the same size as the in parent
2635 * socket family
2637 in_addr.sa_socklen = socket_length(parent_si->family);
2638 if (in_addr.sa_socklen <= 0) {
2639 errno = EINVAL;
2640 return -1;
2643 #ifdef HAVE_ACCEPT4
2644 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
2645 #else
2646 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
2647 #endif
2648 if (ret == -1) {
2649 if (errno == ENOTSOCK) {
2650 /* Remove stale fds */
2651 swrap_remove_stale(s);
2653 return ret;
2656 fd = ret;
2658 ret = sockaddr_convert_from_un(parent_si,
2659 &un_addr.sa.un,
2660 un_addr.sa_socklen,
2661 parent_si->family,
2662 &in_addr.sa.s,
2663 &in_addr.sa_socklen);
2664 if (ret == -1) {
2665 close(fd);
2666 return ret;
2669 child_si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
2670 if (child_si == NULL) {
2671 close(fd);
2672 errno = ENOMEM;
2673 return -1;
2676 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2677 if (child_fi == NULL) {
2678 free(child_si);
2679 close(fd);
2680 errno = ENOMEM;
2681 return -1;
2684 child_fi->fd = fd;
2686 SWRAP_DLIST_ADD(child_si->fds, child_fi);
2688 child_si->family = parent_si->family;
2689 child_si->type = parent_si->type;
2690 child_si->protocol = parent_si->protocol;
2691 child_si->bound = 1;
2692 child_si->is_server = 1;
2693 child_si->connected = 1;
2695 child_si->peername = (struct swrap_address) {
2696 .sa_socklen = in_addr.sa_socklen,
2698 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
2700 if (addr != NULL && addrlen != NULL) {
2701 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
2702 if (copy_len > 0) {
2703 memcpy(addr, &in_addr.sa.ss, copy_len);
2705 *addrlen = in_addr.sa_socklen;
2708 ret = libc_getsockname(fd,
2709 &un_my_addr.sa.s,
2710 &un_my_addr.sa_socklen);
2711 if (ret == -1) {
2712 free(child_fi);
2713 free(child_si);
2714 close(fd);
2715 return ret;
2718 ret = sockaddr_convert_from_un(child_si,
2719 &un_my_addr.sa.un,
2720 un_my_addr.sa_socklen,
2721 child_si->family,
2722 &in_my_addr.sa.s,
2723 &in_my_addr.sa_socklen);
2724 if (ret == -1) {
2725 free(child_fi);
2726 free(child_si);
2727 close(fd);
2728 return ret;
2731 SWRAP_LOG(SWRAP_LOG_TRACE,
2732 "accept() path=%s, fd=%d",
2733 un_my_addr.sa.un.sun_path, s);
2735 child_si->myname = (struct swrap_address) {
2736 .sa_socklen = in_my_addr.sa_socklen,
2738 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
2740 SWRAP_DLIST_ADD(sockets, child_si);
2742 if (addr != NULL) {
2743 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
2744 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
2745 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
2748 return fd;
2751 #ifdef HAVE_ACCEPT4
2752 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
2754 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
2756 #endif
2758 #ifdef HAVE_ACCEPT_PSOCKLEN_T
2759 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
2760 #else
2761 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
2762 #endif
2764 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
2767 static int autobind_start_init;
2768 static int autobind_start;
2770 /* using sendto() or connect() on an unbound socket would give the
2771 recipient no way to reply, as unlike UDP and TCP, a unix domain
2772 socket can't auto-assign ephemeral port numbers, so we need to
2773 assign it here.
2774 Note: this might change the family from ipv6 to ipv4
2776 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
2778 struct swrap_address un_addr = {
2779 .sa_socklen = sizeof(struct sockaddr_un),
2781 int i;
2782 char type;
2783 int ret;
2784 int port;
2785 struct stat st;
2787 if (autobind_start_init != 1) {
2788 autobind_start_init = 1;
2789 autobind_start = getpid();
2790 autobind_start %= 50000;
2791 autobind_start += 10000;
2794 un_addr.sa.un.sun_family = AF_UNIX;
2796 switch (family) {
2797 case AF_INET: {
2798 struct sockaddr_in in;
2800 switch (si->type) {
2801 case SOCK_STREAM:
2802 type = SOCKET_TYPE_CHAR_TCP;
2803 break;
2804 case SOCK_DGRAM:
2805 type = SOCKET_TYPE_CHAR_UDP;
2806 break;
2807 default:
2808 errno = ESOCKTNOSUPPORT;
2809 return -1;
2812 memset(&in, 0, sizeof(in));
2813 in.sin_family = AF_INET;
2814 in.sin_addr.s_addr = htonl(127<<24 |
2815 socket_wrapper_default_iface());
2817 si->myname = (struct swrap_address) {
2818 .sa_socklen = sizeof(in),
2820 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
2821 break;
2823 #ifdef HAVE_IPV6
2824 case AF_INET6: {
2825 struct sockaddr_in6 in6;
2827 if (si->family != family) {
2828 errno = ENETUNREACH;
2829 return -1;
2832 switch (si->type) {
2833 case SOCK_STREAM:
2834 type = SOCKET_TYPE_CHAR_TCP_V6;
2835 break;
2836 case SOCK_DGRAM:
2837 type = SOCKET_TYPE_CHAR_UDP_V6;
2838 break;
2839 default:
2840 errno = ESOCKTNOSUPPORT;
2841 return -1;
2844 memset(&in6, 0, sizeof(in6));
2845 in6.sin6_family = AF_INET6;
2846 in6.sin6_addr = *swrap_ipv6();
2847 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
2849 si->myname = (struct swrap_address) {
2850 .sa_socklen = sizeof(in6),
2852 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
2853 break;
2855 #endif
2856 default:
2857 errno = ESOCKTNOSUPPORT;
2858 return -1;
2861 if (autobind_start > 60000) {
2862 autobind_start = 10000;
2865 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
2866 port = autobind_start + i;
2867 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
2868 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
2869 type, socket_wrapper_default_iface(), port);
2870 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
2872 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
2873 if (ret == -1) return ret;
2875 si->un_addr = un_addr.sa.un;
2877 si->bound = 1;
2878 autobind_start = port + 1;
2879 break;
2881 if (i == SOCKET_MAX_SOCKETS) {
2882 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
2883 "interface "SOCKET_FORMAT,
2884 SOCKET_MAX_SOCKETS,
2885 type,
2886 socket_wrapper_default_iface(),
2888 errno = ENFILE;
2889 return -1;
2892 si->family = family;
2893 set_port(si->family, port, &si->myname);
2895 return 0;
2898 /****************************************************************************
2899 * CONNECT
2900 ***************************************************************************/
2902 static int swrap_connect(int s, const struct sockaddr *serv_addr,
2903 socklen_t addrlen)
2905 int ret;
2906 struct swrap_address un_addr = {
2907 .sa_socklen = sizeof(struct sockaddr_un),
2909 struct socket_info *si = find_socket_info(s);
2910 int bcast = 0;
2912 if (!si) {
2913 return libc_connect(s, serv_addr, addrlen);
2916 if (si->bound == 0) {
2917 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
2918 if (ret == -1) return -1;
2921 if (si->family != serv_addr->sa_family) {
2922 errno = EINVAL;
2923 return -1;
2926 ret = sockaddr_convert_to_un(si, serv_addr,
2927 addrlen, &un_addr.sa.un, 0, &bcast);
2928 if (ret == -1) return -1;
2930 if (bcast) {
2931 errno = ENETUNREACH;
2932 return -1;
2935 if (si->type == SOCK_DGRAM) {
2936 si->defer_connect = 1;
2937 ret = 0;
2938 } else {
2939 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
2941 ret = libc_connect(s,
2942 &un_addr.sa.s,
2943 un_addr.sa_socklen);
2946 SWRAP_LOG(SWRAP_LOG_TRACE,
2947 "connect() path=%s, fd=%d",
2948 un_addr.sa.un.sun_path, s);
2951 /* to give better errors */
2952 if (ret == -1 && errno == ENOENT) {
2953 errno = EHOSTUNREACH;
2956 if (ret == 0) {
2957 si->peername = (struct swrap_address) {
2958 .sa_socklen = addrlen,
2961 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
2962 si->connected = 1;
2965 * When we connect() on a socket than we have to bind the
2966 * outgoing connection on the interface we use for the
2967 * transport. We already bound it on the right interface
2968 * but here we have to update the name so getsockname()
2969 * returns correct information.
2971 if (si->bindname.sa_socklen > 0) {
2972 si->myname = (struct swrap_address) {
2973 .sa_socklen = si->bindname.sa_socklen,
2976 memcpy(&si->myname.sa.ss,
2977 &si->bindname.sa.ss,
2978 si->bindname.sa_socklen);
2980 /* Cleanup bindname */
2981 si->bindname = (struct swrap_address) {
2982 .sa_socklen = 0,
2986 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
2987 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
2988 } else {
2989 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
2992 return ret;
2995 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
2997 return swrap_connect(s, serv_addr, addrlen);
3000 /****************************************************************************
3001 * BIND
3002 ***************************************************************************/
3004 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3006 int ret;
3007 struct swrap_address un_addr = {
3008 .sa_socklen = sizeof(struct sockaddr_un),
3010 struct socket_info *si = find_socket_info(s);
3011 int bind_error = 0;
3012 #if 0 /* FIXME */
3013 bool in_use;
3014 #endif
3016 if (!si) {
3017 return libc_bind(s, myaddr, addrlen);
3020 switch (si->family) {
3021 case AF_INET: {
3022 const struct sockaddr_in *sin;
3023 if (addrlen < sizeof(struct sockaddr_in)) {
3024 bind_error = EINVAL;
3025 break;
3028 sin = (const struct sockaddr_in *)(const void *)myaddr;
3030 if (sin->sin_family != AF_INET) {
3031 bind_error = EAFNOSUPPORT;
3034 /* special case for AF_UNSPEC */
3035 if (sin->sin_family == AF_UNSPEC &&
3036 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3038 bind_error = 0;
3041 break;
3043 #ifdef HAVE_IPV6
3044 case AF_INET6: {
3045 const struct sockaddr_in6 *sin6;
3046 if (addrlen < sizeof(struct sockaddr_in6)) {
3047 bind_error = EINVAL;
3048 break;
3051 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3053 if (sin6->sin6_family != AF_INET6) {
3054 bind_error = EAFNOSUPPORT;
3057 break;
3059 #endif
3060 default:
3061 bind_error = EINVAL;
3062 break;
3065 if (bind_error != 0) {
3066 errno = bind_error;
3067 return -1;
3070 #if 0 /* FIXME */
3071 in_use = check_addr_port_in_use(myaddr, addrlen);
3072 if (in_use) {
3073 errno = EADDRINUSE;
3074 return -1;
3076 #endif
3078 si->myname.sa_socklen = addrlen;
3079 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3081 ret = sockaddr_convert_to_un(si,
3082 myaddr,
3083 addrlen,
3084 &un_addr.sa.un,
3086 &si->bcast);
3087 if (ret == -1) return -1;
3089 unlink(un_addr.sa.un.sun_path);
3091 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3093 SWRAP_LOG(SWRAP_LOG_TRACE,
3094 "bind() path=%s, fd=%d",
3095 un_addr.sa.un.sun_path, s);
3097 if (ret == 0) {
3098 si->bound = 1;
3101 return ret;
3104 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3106 return swrap_bind(s, myaddr, addrlen);
3109 /****************************************************************************
3110 * BINDRESVPORT
3111 ***************************************************************************/
3113 #ifdef HAVE_BINDRESVPORT
3114 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3116 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3118 struct swrap_address myaddr = {
3119 .sa_socklen = sizeof(struct sockaddr_storage),
3121 socklen_t salen;
3122 static uint16_t port;
3123 uint16_t i;
3124 int rc = -1;
3125 int af;
3127 #define SWRAP_STARTPORT 600
3128 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3129 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3131 if (port == 0) {
3132 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3135 if (sa == NULL) {
3136 salen = myaddr.sa_socklen;
3137 sa = &myaddr.sa.s;
3139 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3140 if (rc < 0) {
3141 return -1;
3144 af = sa->sa_family;
3145 memset(&myaddr.sa.ss, 0, salen);
3146 } else {
3147 af = sa->sa_family;
3150 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3151 switch(af) {
3152 case AF_INET: {
3153 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3155 salen = sizeof(struct sockaddr_in);
3156 sinp->sin_port = htons(port);
3157 break;
3159 case AF_INET6: {
3160 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3162 salen = sizeof(struct sockaddr_in6);
3163 sin6p->sin6_port = htons(port);
3164 break;
3166 default:
3167 errno = EAFNOSUPPORT;
3168 return -1;
3170 sa->sa_family = af;
3172 if (port > SWRAP_ENDPORT) {
3173 port = SWRAP_STARTPORT;
3176 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3177 if (rc == 0 || errno != EADDRINUSE) {
3178 break;
3182 return rc;
3185 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3187 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3189 #endif
3191 /****************************************************************************
3192 * LISTEN
3193 ***************************************************************************/
3195 static int swrap_listen(int s, int backlog)
3197 int ret;
3198 struct socket_info *si = find_socket_info(s);
3200 if (!si) {
3201 return libc_listen(s, backlog);
3204 if (si->bound == 0) {
3205 ret = swrap_auto_bind(s, si, si->family);
3206 if (ret == -1) {
3207 errno = EADDRINUSE;
3208 return ret;
3212 ret = libc_listen(s, backlog);
3214 return ret;
3217 int listen(int s, int backlog)
3219 return swrap_listen(s, backlog);
3222 /****************************************************************************
3223 * FOPEN
3224 ***************************************************************************/
3226 static FILE *swrap_fopen(const char *name, const char *mode)
3228 FILE *fp;
3230 fp = libc_fopen(name, mode);
3231 if (fp != NULL) {
3232 int fd = fileno(fp);
3234 swrap_remove_stale(fd);
3237 return fp;
3240 FILE *fopen(const char *name, const char *mode)
3242 return swrap_fopen(name, mode);
3245 /****************************************************************************
3246 * OPEN
3247 ***************************************************************************/
3249 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3251 int ret;
3253 ret = libc_vopen(pathname, flags, ap);
3254 if (ret != -1) {
3256 * There are methods for closing descriptors (libc-internal code
3257 * paths, direct syscalls) which close descriptors in ways that
3258 * we can't intercept, so try to recover when we notice that
3259 * that's happened
3261 swrap_remove_stale(ret);
3263 return ret;
3266 int open(const char *pathname, int flags, ...)
3268 va_list ap;
3269 int fd;
3271 va_start(ap, flags);
3272 fd = swrap_vopen(pathname, flags, ap);
3273 va_end(ap);
3275 return fd;
3278 /****************************************************************************
3279 * GETPEERNAME
3280 ***************************************************************************/
3282 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3284 struct socket_info *si = find_socket_info(s);
3285 socklen_t len;
3287 if (!si) {
3288 return libc_getpeername(s, name, addrlen);
3291 if (si->peername.sa_socklen == 0)
3293 errno = ENOTCONN;
3294 return -1;
3297 len = MIN(*addrlen, si->peername.sa_socklen);
3298 if (len == 0) {
3299 return 0;
3302 memcpy(name, &si->peername.sa.ss, len);
3303 *addrlen = si->peername.sa_socklen;
3305 return 0;
3308 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3309 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3310 #else
3311 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3312 #endif
3314 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3317 /****************************************************************************
3318 * GETSOCKNAME
3319 ***************************************************************************/
3321 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3323 struct socket_info *si = find_socket_info(s);
3324 socklen_t len;
3326 if (!si) {
3327 return libc_getsockname(s, name, addrlen);
3330 len = MIN(*addrlen, si->myname.sa_socklen);
3331 if (len == 0) {
3332 return 0;
3335 memcpy(name, &si->myname.sa.ss, len);
3336 *addrlen = si->myname.sa_socklen;
3338 return 0;
3341 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3342 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3343 #else
3344 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3345 #endif
3347 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3350 /****************************************************************************
3351 * GETSOCKOPT
3352 ***************************************************************************/
3354 #ifndef SO_PROTOCOL
3355 # ifdef SO_PROTOTYPE /* The Solaris name */
3356 # define SO_PROTOCOL SO_PROTOTYPE
3357 # endif /* SO_PROTOTYPE */
3358 #endif /* SO_PROTOCOL */
3360 static int swrap_getsockopt(int s, int level, int optname,
3361 void *optval, socklen_t *optlen)
3363 struct socket_info *si = find_socket_info(s);
3365 if (!si) {
3366 return libc_getsockopt(s,
3367 level,
3368 optname,
3369 optval,
3370 optlen);
3373 if (level == SOL_SOCKET) {
3374 switch (optname) {
3375 #ifdef SO_DOMAIN
3376 case SO_DOMAIN:
3377 if (optval == NULL || optlen == NULL ||
3378 *optlen < (socklen_t)sizeof(int)) {
3379 errno = EINVAL;
3380 return -1;
3383 *optlen = sizeof(int);
3384 *(int *)optval = si->family;
3385 return 0;
3386 #endif /* SO_DOMAIN */
3388 #ifdef SO_PROTOCOL
3389 case SO_PROTOCOL:
3390 if (optval == NULL || optlen == NULL ||
3391 *optlen < (socklen_t)sizeof(int)) {
3392 errno = EINVAL;
3393 return -1;
3396 *optlen = sizeof(int);
3397 *(int *)optval = si->protocol;
3398 return 0;
3399 #endif /* SO_PROTOCOL */
3400 case SO_TYPE:
3401 if (optval == NULL || optlen == NULL ||
3402 *optlen < (socklen_t)sizeof(int)) {
3403 errno = EINVAL;
3404 return -1;
3407 *optlen = sizeof(int);
3408 *(int *)optval = si->type;
3409 return 0;
3410 default:
3411 return libc_getsockopt(s,
3412 level,
3413 optname,
3414 optval,
3415 optlen);
3417 } else if (level == IPPROTO_TCP) {
3418 switch (optname) {
3419 #ifdef TCP_NODELAY
3420 case TCP_NODELAY:
3422 * This enables sending packets directly out over TCP.
3423 * As a unix socket is doing that any way, report it as
3424 * enabled.
3426 if (optval == NULL || optlen == NULL ||
3427 *optlen < (socklen_t)sizeof(int)) {
3428 errno = EINVAL;
3429 return -1;
3432 *optlen = sizeof(int);
3433 *(int *)optval = si->tcp_nodelay;
3435 return 0;
3436 #endif /* TCP_NODELAY */
3437 default:
3438 break;
3442 errno = ENOPROTOOPT;
3443 return -1;
3446 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3447 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3448 #else
3449 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3450 #endif
3452 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3455 /****************************************************************************
3456 * SETSOCKOPT
3457 ***************************************************************************/
3459 static int swrap_setsockopt(int s, int level, int optname,
3460 const void *optval, socklen_t optlen)
3462 struct socket_info *si = find_socket_info(s);
3464 if (!si) {
3465 return libc_setsockopt(s,
3466 level,
3467 optname,
3468 optval,
3469 optlen);
3472 if (level == SOL_SOCKET) {
3473 return libc_setsockopt(s,
3474 level,
3475 optname,
3476 optval,
3477 optlen);
3478 } else if (level == IPPROTO_TCP) {
3479 switch (optname) {
3480 #ifdef TCP_NODELAY
3481 case TCP_NODELAY: {
3482 int i;
3485 * This enables sending packets directly out over TCP.
3486 * A unix socket is doing that any way.
3488 if (optval == NULL || optlen == 0 ||
3489 optlen < (socklen_t)sizeof(int)) {
3490 errno = EINVAL;
3491 return -1;
3494 i = *discard_const_p(int, optval);
3495 if (i != 0 && i != 1) {
3496 errno = EINVAL;
3497 return -1;
3499 si->tcp_nodelay = i;
3501 return 0;
3503 #endif /* TCP_NODELAY */
3504 default:
3505 break;
3509 switch (si->family) {
3510 case AF_INET:
3511 if (level == IPPROTO_IP) {
3512 #ifdef IP_PKTINFO
3513 if (optname == IP_PKTINFO) {
3514 si->pktinfo = AF_INET;
3516 #endif /* IP_PKTINFO */
3518 return 0;
3519 #ifdef HAVE_IPV6
3520 case AF_INET6:
3521 if (level == IPPROTO_IPV6) {
3522 #ifdef IPV6_RECVPKTINFO
3523 if (optname == IPV6_RECVPKTINFO) {
3524 si->pktinfo = AF_INET6;
3526 #endif /* IPV6_PKTINFO */
3528 return 0;
3529 #endif
3530 default:
3531 errno = ENOPROTOOPT;
3532 return -1;
3536 int setsockopt(int s, int level, int optname,
3537 const void *optval, socklen_t optlen)
3539 return swrap_setsockopt(s, level, optname, optval, optlen);
3542 /****************************************************************************
3543 * IOCTL
3544 ***************************************************************************/
3546 static int swrap_vioctl(int s, unsigned long int r, va_list va)
3548 struct socket_info *si = find_socket_info(s);
3549 va_list ap;
3550 int value;
3551 int rc;
3553 if (!si) {
3554 return libc_vioctl(s, r, va);
3557 va_copy(ap, va);
3559 rc = libc_vioctl(s, r, va);
3561 switch (r) {
3562 case FIONREAD:
3563 value = *((int *)va_arg(ap, int *));
3565 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
3566 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3567 } else if (value == 0) { /* END OF FILE */
3568 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
3570 break;
3573 va_end(ap);
3575 return rc;
3578 #ifdef HAVE_IOCTL_INT
3579 int ioctl(int s, int r, ...)
3580 #else
3581 int ioctl(int s, unsigned long int r, ...)
3582 #endif
3584 va_list va;
3585 int rc;
3587 va_start(va, r);
3589 rc = swrap_vioctl(s, (unsigned long int) r, va);
3591 va_end(va);
3593 return rc;
3596 /*****************
3597 * CMSG
3598 *****************/
3600 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
3602 #ifndef CMSG_ALIGN
3603 # ifdef _ALIGN /* BSD */
3604 #define CMSG_ALIGN _ALIGN
3605 # else
3606 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
3607 # endif /* _ALIGN */
3608 #endif /* CMSG_ALIGN */
3611 * @brief Add a cmsghdr to a msghdr.
3613 * This is an function to add any type of cmsghdr. It will operate on the
3614 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
3615 * the buffer position after the added cmsg element. Hence, this function is
3616 * intended to be used with an intermediate msghdr and not on the original
3617 * one handed in by the client.
3619 * @param[in] msg The msghdr to which to add the cmsg.
3621 * @param[in] level The cmsg level to set.
3623 * @param[in] type The cmsg type to set.
3625 * @param[in] data The cmsg data to set.
3627 * @param[in] len the length of the data to set.
3629 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
3630 int level,
3631 int type,
3632 const void *data,
3633 size_t len)
3635 size_t cmlen = CMSG_LEN(len);
3636 size_t cmspace = CMSG_SPACE(len);
3637 uint8_t cmbuf[cmspace];
3638 void *cast_ptr = (void *)cmbuf;
3639 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
3640 uint8_t *p;
3642 memset(cmbuf, 0, cmspace);
3644 if (msg->msg_controllen < cmlen) {
3645 cmlen = msg->msg_controllen;
3646 msg->msg_flags |= MSG_CTRUNC;
3649 if (msg->msg_controllen < cmspace) {
3650 cmspace = msg->msg_controllen;
3654 * We copy the full input data into an intermediate cmsghdr first
3655 * in order to more easily cope with truncation.
3657 cm->cmsg_len = cmlen;
3658 cm->cmsg_level = level;
3659 cm->cmsg_type = type;
3660 memcpy(CMSG_DATA(cm), data, len);
3663 * We now copy the possibly truncated buffer.
3664 * We copy cmlen bytes, but consume cmspace bytes,
3665 * leaving the possible padding uninitialiazed.
3667 p = (uint8_t *)msg->msg_control;
3668 memcpy(p, cm, cmlen);
3669 p += cmspace;
3670 msg->msg_control = p;
3671 msg->msg_controllen -= cmspace;
3673 return;
3676 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
3677 struct msghdr *msg)
3679 /* Add packet info */
3680 switch (si->pktinfo) {
3681 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
3682 case AF_INET: {
3683 struct sockaddr_in *sin;
3684 #if defined(HAVE_STRUCT_IN_PKTINFO)
3685 struct in_pktinfo pkt;
3686 #elif defined(IP_RECVDSTADDR)
3687 struct in_addr pkt;
3688 #endif
3690 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
3691 sin = &si->bindname.sa.in;
3692 } else {
3693 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
3694 return 0;
3696 sin = &si->myname.sa.in;
3699 ZERO_STRUCT(pkt);
3701 #if defined(HAVE_STRUCT_IN_PKTINFO)
3702 pkt.ipi_ifindex = socket_wrapper_default_iface();
3703 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
3704 #elif defined(IP_RECVDSTADDR)
3705 pkt = sin->sin_addr;
3706 #endif
3708 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
3709 &pkt, sizeof(pkt));
3711 break;
3713 #endif /* IP_PKTINFO */
3714 #if defined(HAVE_IPV6)
3715 case AF_INET6: {
3716 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
3717 struct sockaddr_in6 *sin6;
3718 struct in6_pktinfo pkt6;
3720 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
3721 sin6 = &si->bindname.sa.in6;
3722 } else {
3723 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
3724 return 0;
3726 sin6 = &si->myname.sa.in6;
3729 ZERO_STRUCT(pkt6);
3731 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
3732 pkt6.ipi6_addr = sin6->sin6_addr;
3734 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
3735 &pkt6, sizeof(pkt6));
3736 #endif /* HAVE_STRUCT_IN6_PKTINFO */
3738 break;
3740 #endif /* IPV6_PKTINFO */
3741 default:
3742 return -1;
3745 return 0;
3748 static int swrap_msghdr_add_socket_info(struct socket_info *si,
3749 struct msghdr *omsg)
3751 int rc = 0;
3753 if (si->pktinfo > 0) {
3754 rc = swrap_msghdr_add_pktinfo(si, omsg);
3757 return rc;
3760 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3761 uint8_t **cm_data,
3762 size_t *cm_data_space);
3763 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3764 uint8_t **cm_data,
3765 size_t *cm_data_space);
3767 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
3768 uint8_t **cm_data,
3769 size_t *cm_data_space) {
3770 struct cmsghdr *cmsg;
3771 int rc = -1;
3773 /* Nothing to do */
3774 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
3775 return 0;
3778 for (cmsg = CMSG_FIRSTHDR(msg);
3779 cmsg != NULL;
3780 cmsg = CMSG_NXTHDR(msg, cmsg)) {
3781 switch (cmsg->cmsg_level) {
3782 case IPPROTO_IP:
3783 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
3784 cm_data,
3785 cm_data_space);
3786 break;
3787 default:
3788 rc = swrap_sendmsg_copy_cmsg(cmsg,
3789 cm_data,
3790 cm_data_space);
3791 break;
3795 return rc;
3798 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
3799 uint8_t **cm_data,
3800 size_t *cm_data_space)
3802 size_t cmspace;
3803 uint8_t *p;
3805 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
3807 p = realloc((*cm_data), cmspace);
3808 if (p == NULL) {
3809 return -1;
3811 (*cm_data) = p;
3813 p = (*cm_data) + (*cm_data_space);
3814 *cm_data_space = cmspace;
3816 memcpy(p, cmsg, cmsg->cmsg_len);
3818 return 0;
3821 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3822 uint8_t **cm_data,
3823 size_t *cm_data_space);
3826 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
3827 uint8_t **cm_data,
3828 size_t *cm_data_space)
3830 int rc = -1;
3832 switch(cmsg->cmsg_type) {
3833 #ifdef IP_PKTINFO
3834 case IP_PKTINFO:
3835 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3836 cm_data,
3837 cm_data_space);
3838 break;
3839 #endif
3840 #ifdef IPV6_PKTINFO
3841 case IPV6_PKTINFO:
3842 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
3843 cm_data,
3844 cm_data_space);
3845 break;
3846 #endif
3847 default:
3848 break;
3851 return rc;
3854 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
3855 uint8_t **cm_data,
3856 size_t *cm_data_space)
3858 (void)cmsg; /* unused */
3859 (void)cm_data; /* unused */
3860 (void)cm_data_space; /* unused */
3863 * Passing a IP pktinfo to a unix socket might be rejected by the
3864 * Kernel, at least on FreeBSD. So skip this cmsg.
3866 return 0;
3868 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
3870 static ssize_t swrap_sendmsg_before(int fd,
3871 struct socket_info *si,
3872 struct msghdr *msg,
3873 struct iovec *tmp_iov,
3874 struct sockaddr_un *tmp_un,
3875 const struct sockaddr_un **to_un,
3876 const struct sockaddr **to,
3877 int *bcast)
3879 size_t i, len = 0;
3880 ssize_t ret;
3882 if (to_un) {
3883 *to_un = NULL;
3885 if (to) {
3886 *to = NULL;
3888 if (bcast) {
3889 *bcast = 0;
3892 switch (si->type) {
3893 case SOCK_STREAM: {
3894 unsigned long mtu;
3896 if (!si->connected) {
3897 errno = ENOTCONN;
3898 return -1;
3901 if (msg->msg_iovlen == 0) {
3902 break;
3905 mtu = socket_wrapper_mtu();
3906 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
3907 size_t nlen;
3908 nlen = len + msg->msg_iov[i].iov_len;
3909 if (nlen > mtu) {
3910 break;
3913 msg->msg_iovlen = i;
3914 if (msg->msg_iovlen == 0) {
3915 *tmp_iov = msg->msg_iov[0];
3916 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
3917 (size_t)mtu);
3918 msg->msg_iov = tmp_iov;
3919 msg->msg_iovlen = 1;
3921 break;
3923 case SOCK_DGRAM:
3924 if (si->connected) {
3925 if (msg->msg_name != NULL) {
3927 * We are dealing with unix sockets and if we
3928 * are connected, we should only talk to the
3929 * connected unix path. Using the fd to send
3930 * to another server would be hard to achieve.
3932 msg->msg_name = NULL;
3933 msg->msg_namelen = 0;
3935 } else {
3936 const struct sockaddr *msg_name;
3937 msg_name = (const struct sockaddr *)msg->msg_name;
3939 if (msg_name == NULL) {
3940 errno = ENOTCONN;
3941 return -1;
3945 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
3946 tmp_un, 0, bcast);
3947 if (ret == -1) return -1;
3949 if (to_un) {
3950 *to_un = tmp_un;
3952 if (to) {
3953 *to = msg_name;
3955 msg->msg_name = tmp_un;
3956 msg->msg_namelen = sizeof(*tmp_un);
3959 if (si->bound == 0) {
3960 ret = swrap_auto_bind(fd, si, si->family);
3961 if (ret == -1) {
3962 if (errno == ENOTSOCK) {
3963 swrap_remove_stale(fd);
3964 return -ENOTSOCK;
3965 } else {
3966 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
3967 return -1;
3972 if (!si->defer_connect) {
3973 break;
3976 ret = sockaddr_convert_to_un(si,
3977 &si->peername.sa.s,
3978 si->peername.sa_socklen,
3979 tmp_un,
3981 NULL);
3982 if (ret == -1) return -1;
3984 ret = libc_connect(fd,
3985 (struct sockaddr *)(void *)tmp_un,
3986 sizeof(*tmp_un));
3988 /* to give better errors */
3989 if (ret == -1 && errno == ENOENT) {
3990 errno = EHOSTUNREACH;
3993 if (ret == -1) {
3994 return ret;
3997 si->defer_connect = 0;
3998 break;
3999 default:
4000 errno = EHOSTUNREACH;
4001 return -1;
4004 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4005 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4006 uint8_t *cmbuf = NULL;
4007 size_t cmlen = 0;
4009 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4010 if (ret < 0) {
4011 free(cmbuf);
4012 return -1;
4015 if (cmlen == 0) {
4016 msg->msg_controllen = 0;
4017 msg->msg_control = NULL;
4018 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4019 memcpy(msg->msg_control, cmbuf, cmlen);
4020 msg->msg_controllen = cmlen;
4022 free(cmbuf);
4024 #endif
4026 return 0;
4029 static void swrap_sendmsg_after(int fd,
4030 struct socket_info *si,
4031 struct msghdr *msg,
4032 const struct sockaddr *to,
4033 ssize_t ret)
4035 int saved_errno = errno;
4036 size_t i, len = 0;
4037 uint8_t *buf;
4038 off_t ofs = 0;
4039 size_t avail = 0;
4040 size_t remain;
4042 /* to give better errors */
4043 if (ret == -1) {
4044 if (saved_errno == ENOENT) {
4045 saved_errno = EHOSTUNREACH;
4046 } else if (saved_errno == ENOTSOCK) {
4047 /* If the fd is not a socket, remove it */
4048 swrap_remove_stale(fd);
4052 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4053 avail += msg->msg_iov[i].iov_len;
4056 if (ret == -1) {
4057 remain = MIN(80, avail);
4058 } else {
4059 remain = ret;
4062 /* we capture it as one single packet */
4063 buf = (uint8_t *)malloc(remain);
4064 if (!buf) {
4065 /* we just not capture the packet */
4066 errno = saved_errno;
4067 return;
4070 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4071 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4072 memcpy(buf + ofs,
4073 msg->msg_iov[i].iov_base,
4074 this_time);
4075 ofs += this_time;
4076 remain -= this_time;
4078 len = ofs;
4080 switch (si->type) {
4081 case SOCK_STREAM:
4082 if (ret == -1) {
4083 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4084 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4085 } else {
4086 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4088 break;
4090 case SOCK_DGRAM:
4091 if (si->connected) {
4092 to = &si->peername.sa.s;
4094 if (ret == -1) {
4095 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4096 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4097 } else {
4098 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4100 break;
4103 free(buf);
4104 errno = saved_errno;
4107 static int swrap_recvmsg_before(int fd,
4108 struct socket_info *si,
4109 struct msghdr *msg,
4110 struct iovec *tmp_iov)
4112 size_t i, len = 0;
4113 ssize_t ret;
4115 (void)fd; /* unused */
4117 switch (si->type) {
4118 case SOCK_STREAM: {
4119 unsigned int mtu;
4120 if (!si->connected) {
4121 errno = ENOTCONN;
4122 return -1;
4125 if (msg->msg_iovlen == 0) {
4126 break;
4129 mtu = socket_wrapper_mtu();
4130 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4131 size_t nlen;
4132 nlen = len + msg->msg_iov[i].iov_len;
4133 if (nlen > mtu) {
4134 break;
4137 msg->msg_iovlen = i;
4138 if (msg->msg_iovlen == 0) {
4139 *tmp_iov = msg->msg_iov[0];
4140 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4141 (size_t)mtu);
4142 msg->msg_iov = tmp_iov;
4143 msg->msg_iovlen = 1;
4145 break;
4147 case SOCK_DGRAM:
4148 if (msg->msg_name == NULL) {
4149 errno = EINVAL;
4150 return -1;
4153 if (msg->msg_iovlen == 0) {
4154 break;
4157 if (si->bound == 0) {
4158 ret = swrap_auto_bind(fd, si, si->family);
4159 if (ret == -1) {
4161 * When attempting to read or write to a
4162 * descriptor, if an underlying autobind fails
4163 * because it's not a socket, stop intercepting
4164 * uses of that descriptor.
4166 if (errno == ENOTSOCK) {
4167 swrap_remove_stale(fd);
4168 return -ENOTSOCK;
4169 } else {
4170 SWRAP_LOG(SWRAP_LOG_ERROR,
4171 "swrap_recvmsg_before failed");
4172 return -1;
4176 break;
4177 default:
4178 errno = EHOSTUNREACH;
4179 return -1;
4182 return 0;
4185 static int swrap_recvmsg_after(int fd,
4186 struct socket_info *si,
4187 struct msghdr *msg,
4188 const struct sockaddr_un *un_addr,
4189 socklen_t un_addrlen,
4190 ssize_t ret)
4192 int saved_errno = errno;
4193 size_t i;
4194 uint8_t *buf = NULL;
4195 off_t ofs = 0;
4196 size_t avail = 0;
4197 size_t remain;
4198 int rc;
4200 /* to give better errors */
4201 if (ret == -1) {
4202 if (saved_errno == ENOENT) {
4203 saved_errno = EHOSTUNREACH;
4204 } else if (saved_errno == ENOTSOCK) {
4205 /* If the fd is not a socket, remove it */
4206 swrap_remove_stale(fd);
4210 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4211 avail += msg->msg_iov[i].iov_len;
4214 /* Convert the socket address before we leave */
4215 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4216 rc = sockaddr_convert_from_un(si,
4217 un_addr,
4218 un_addrlen,
4219 si->family,
4220 msg->msg_name,
4221 &msg->msg_namelen);
4222 if (rc == -1) {
4223 goto done;
4227 if (avail == 0) {
4228 rc = 0;
4229 goto done;
4232 if (ret == -1) {
4233 remain = MIN(80, avail);
4234 } else {
4235 remain = ret;
4238 /* we capture it as one single packet */
4239 buf = (uint8_t *)malloc(remain);
4240 if (buf == NULL) {
4241 /* we just not capture the packet */
4242 errno = saved_errno;
4243 return -1;
4246 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4247 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4248 memcpy(buf + ofs,
4249 msg->msg_iov[i].iov_base,
4250 this_time);
4251 ofs += this_time;
4252 remain -= this_time;
4255 switch (si->type) {
4256 case SOCK_STREAM:
4257 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4258 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4259 } else if (ret == 0) { /* END OF FILE */
4260 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4261 } else if (ret > 0) {
4262 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4264 break;
4266 case SOCK_DGRAM:
4267 if (ret == -1) {
4268 break;
4271 if (un_addr != NULL) {
4272 swrap_pcap_dump_packet(si,
4273 msg->msg_name,
4274 SWRAP_RECVFROM,
4275 buf,
4276 ret);
4277 } else {
4278 swrap_pcap_dump_packet(si,
4279 msg->msg_name,
4280 SWRAP_RECV,
4281 buf,
4282 ret);
4285 break;
4288 rc = 0;
4289 done:
4290 free(buf);
4291 errno = saved_errno;
4293 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4294 if (rc == 0 &&
4295 msg->msg_controllen > 0 &&
4296 msg->msg_control != NULL) {
4297 rc = swrap_msghdr_add_socket_info(si, msg);
4298 if (rc < 0) {
4299 return -1;
4302 #endif
4304 return rc;
4307 /****************************************************************************
4308 * RECVFROM
4309 ***************************************************************************/
4311 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4312 struct sockaddr *from, socklen_t *fromlen)
4314 struct swrap_address from_addr = {
4315 .sa_socklen = sizeof(struct sockaddr_un),
4317 ssize_t ret;
4318 struct socket_info *si = find_socket_info(s);
4319 struct swrap_address saddr = {
4320 .sa_socklen = sizeof(struct sockaddr_storage),
4322 struct msghdr msg;
4323 struct iovec tmp;
4324 int tret;
4326 if (!si) {
4327 return libc_recvfrom(s,
4328 buf,
4329 len,
4330 flags,
4331 from,
4332 fromlen);
4335 tmp.iov_base = buf;
4336 tmp.iov_len = len;
4338 ZERO_STRUCT(msg);
4339 if (from != NULL && fromlen != NULL) {
4340 msg.msg_name = from; /* optional address */
4341 msg.msg_namelen = *fromlen; /* size of address */
4342 } else {
4343 msg.msg_name = &saddr.sa.s; /* optional address */
4344 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4346 msg.msg_iov = &tmp; /* scatter/gather array */
4347 msg.msg_iovlen = 1; /* # elements in msg_iov */
4348 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4349 msg.msg_control = NULL; /* ancillary data, see below */
4350 msg.msg_controllen = 0; /* ancillary data buffer len */
4351 msg.msg_flags = 0; /* flags on received message */
4352 #endif
4354 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4355 if (tret < 0) {
4356 return -1;
4359 buf = msg.msg_iov[0].iov_base;
4360 len = msg.msg_iov[0].iov_len;
4362 ret = libc_recvfrom(s,
4363 buf,
4364 len,
4365 flags,
4366 &from_addr.sa.s,
4367 &from_addr.sa_socklen);
4368 if (ret == -1) {
4369 return ret;
4372 tret = swrap_recvmsg_after(s,
4374 &msg,
4375 &from_addr.sa.un,
4376 from_addr.sa_socklen,
4377 ret);
4378 if (tret != 0) {
4379 return tret;
4382 if (from != NULL && fromlen != NULL) {
4383 *fromlen = msg.msg_namelen;
4386 return ret;
4389 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4390 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4391 struct sockaddr *from, Psocklen_t fromlen)
4392 #else
4393 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4394 struct sockaddr *from, socklen_t *fromlen)
4395 #endif
4397 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4400 /****************************************************************************
4401 * SENDTO
4402 ***************************************************************************/
4404 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4405 const struct sockaddr *to, socklen_t tolen)
4407 struct msghdr msg;
4408 struct iovec tmp;
4409 struct swrap_address un_addr = {
4410 .sa_socklen = sizeof(struct sockaddr_un),
4412 const struct sockaddr_un *to_un = NULL;
4413 ssize_t ret;
4414 int rc;
4415 struct socket_info *si = find_socket_info(s);
4416 int bcast = 0;
4418 if (!si) {
4419 return libc_sendto(s, buf, len, flags, to, tolen);
4422 tmp.iov_base = discard_const_p(char, buf);
4423 tmp.iov_len = len;
4425 ZERO_STRUCT(msg);
4426 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4427 msg.msg_namelen = tolen; /* size of address */
4428 msg.msg_iov = &tmp; /* scatter/gather array */
4429 msg.msg_iovlen = 1; /* # elements in msg_iov */
4430 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4431 msg.msg_control = NULL; /* ancillary data, see below */
4432 msg.msg_controllen = 0; /* ancillary data buffer len */
4433 msg.msg_flags = 0; /* flags on received message */
4434 #endif
4436 rc = swrap_sendmsg_before(s,
4438 &msg,
4439 &tmp,
4440 &un_addr.sa.un,
4441 &to_un,
4442 &to,
4443 &bcast);
4444 if (rc < 0) {
4445 return -1;
4448 buf = msg.msg_iov[0].iov_base;
4449 len = msg.msg_iov[0].iov_len;
4451 if (bcast) {
4452 struct stat st;
4453 unsigned int iface;
4454 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4455 char type;
4457 type = SOCKET_TYPE_CHAR_UDP;
4459 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4460 snprintf(un_addr.sa.un.sun_path,
4461 sizeof(un_addr.sa.un.sun_path),
4462 "%s/"SOCKET_FORMAT,
4463 socket_wrapper_dir(), type, iface, prt);
4464 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
4466 /* ignore the any errors in broadcast sends */
4467 libc_sendto(s,
4468 buf,
4469 len,
4470 flags,
4471 &un_addr.sa.s,
4472 un_addr.sa_socklen);
4475 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4477 return len;
4481 * If it is a dgram socket and we are connected, don't include the
4482 * 'to' address.
4484 if (si->type == SOCK_DGRAM && si->connected) {
4485 ret = libc_sendto(s,
4486 buf,
4487 len,
4488 flags,
4489 NULL,
4491 } else {
4492 ret = libc_sendto(s,
4493 buf,
4494 len,
4495 flags,
4496 (struct sockaddr *)msg.msg_name,
4497 msg.msg_namelen);
4500 swrap_sendmsg_after(s, si, &msg, to, ret);
4502 return ret;
4505 ssize_t sendto(int s, const void *buf, size_t len, int flags,
4506 const struct sockaddr *to, socklen_t tolen)
4508 return swrap_sendto(s, buf, len, flags, to, tolen);
4511 /****************************************************************************
4512 * READV
4513 ***************************************************************************/
4515 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
4517 struct socket_info *si;
4518 struct msghdr msg;
4519 struct swrap_address saddr = {
4520 .sa_socklen = sizeof(struct sockaddr_storage),
4522 struct iovec tmp;
4523 ssize_t ret;
4524 int tret;
4526 si = find_socket_info(s);
4527 if (si == NULL) {
4528 return libc_recv(s, buf, len, flags);
4531 tmp.iov_base = buf;
4532 tmp.iov_len = len;
4534 ZERO_STRUCT(msg);
4535 msg.msg_name = &saddr.sa.s; /* optional address */
4536 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4537 msg.msg_iov = &tmp; /* scatter/gather array */
4538 msg.msg_iovlen = 1; /* # elements in msg_iov */
4539 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4540 msg.msg_control = NULL; /* ancillary data, see below */
4541 msg.msg_controllen = 0; /* ancillary data buffer len */
4542 msg.msg_flags = 0; /* flags on received message */
4543 #endif
4545 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4546 if (tret < 0) {
4547 return -1;
4550 buf = msg.msg_iov[0].iov_base;
4551 len = msg.msg_iov[0].iov_len;
4553 ret = libc_recv(s, buf, len, flags);
4555 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4556 if (tret != 0) {
4557 return tret;
4560 return ret;
4563 ssize_t recv(int s, void *buf, size_t len, int flags)
4565 return swrap_recv(s, buf, len, flags);
4568 /****************************************************************************
4569 * READ
4570 ***************************************************************************/
4572 static ssize_t swrap_read(int s, void *buf, size_t len)
4574 struct socket_info *si;
4575 struct msghdr msg;
4576 struct iovec tmp;
4577 struct swrap_address saddr = {
4578 .sa_socklen = sizeof(struct sockaddr_storage),
4580 ssize_t ret;
4581 int tret;
4583 si = find_socket_info(s);
4584 if (si == NULL) {
4585 return libc_read(s, buf, len);
4588 tmp.iov_base = buf;
4589 tmp.iov_len = len;
4591 ZERO_STRUCT(msg);
4592 msg.msg_name = &saddr.sa.ss; /* optional address */
4593 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4594 msg.msg_iov = &tmp; /* scatter/gather array */
4595 msg.msg_iovlen = 1; /* # elements in msg_iov */
4596 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4597 msg.msg_control = NULL; /* ancillary data, see below */
4598 msg.msg_controllen = 0; /* ancillary data buffer len */
4599 msg.msg_flags = 0; /* flags on received message */
4600 #endif
4602 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4603 if (tret < 0) {
4604 if (tret == -ENOTSOCK) {
4605 return libc_read(s, buf, len);
4607 return -1;
4610 buf = msg.msg_iov[0].iov_base;
4611 len = msg.msg_iov[0].iov_len;
4613 ret = libc_read(s, buf, len);
4615 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
4616 if (tret != 0) {
4617 return tret;
4620 return ret;
4623 ssize_t read(int s, void *buf, size_t len)
4625 return swrap_read(s, buf, len);
4628 /****************************************************************************
4629 * WRITE
4630 ***************************************************************************/
4632 static ssize_t swrap_write(int s, const void *buf, size_t len)
4634 struct msghdr msg;
4635 struct iovec tmp;
4636 struct sockaddr_un un_addr;
4637 ssize_t ret;
4638 int rc;
4639 struct socket_info *si;
4641 si = find_socket_info(s);
4642 if (si == NULL) {
4643 return libc_write(s, buf, len);
4646 tmp.iov_base = discard_const_p(char, buf);
4647 tmp.iov_len = len;
4649 ZERO_STRUCT(msg);
4650 msg.msg_name = NULL; /* optional address */
4651 msg.msg_namelen = 0; /* size of address */
4652 msg.msg_iov = &tmp; /* scatter/gather array */
4653 msg.msg_iovlen = 1; /* # 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 return -1;
4665 buf = msg.msg_iov[0].iov_base;
4666 len = msg.msg_iov[0].iov_len;
4668 ret = libc_write(s, buf, len);
4670 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4672 return ret;
4675 ssize_t write(int s, const void *buf, size_t len)
4677 return swrap_write(s, buf, len);
4680 /****************************************************************************
4681 * SEND
4682 ***************************************************************************/
4684 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
4686 struct msghdr msg;
4687 struct iovec tmp;
4688 struct sockaddr_un un_addr;
4689 ssize_t ret;
4690 int rc;
4691 struct socket_info *si = find_socket_info(s);
4693 if (!si) {
4694 return libc_send(s, buf, len, flags);
4697 tmp.iov_base = discard_const_p(char, buf);
4698 tmp.iov_len = len;
4700 ZERO_STRUCT(msg);
4701 msg.msg_name = NULL; /* optional address */
4702 msg.msg_namelen = 0; /* size of address */
4703 msg.msg_iov = &tmp; /* scatter/gather array */
4704 msg.msg_iovlen = 1; /* # elements in msg_iov */
4705 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4706 msg.msg_control = NULL; /* ancillary data, see below */
4707 msg.msg_controllen = 0; /* ancillary data buffer len */
4708 msg.msg_flags = 0; /* flags on received message */
4709 #endif
4711 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
4712 if (rc < 0) {
4713 return -1;
4716 buf = msg.msg_iov[0].iov_base;
4717 len = msg.msg_iov[0].iov_len;
4719 ret = libc_send(s, buf, len, flags);
4721 swrap_sendmsg_after(s, si, &msg, NULL, ret);
4723 return ret;
4726 ssize_t send(int s, const void *buf, size_t len, int flags)
4728 return swrap_send(s, buf, len, flags);
4731 /****************************************************************************
4732 * RECVMSG
4733 ***************************************************************************/
4735 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
4737 struct swrap_address from_addr = {
4738 .sa_socklen = sizeof(struct sockaddr_un),
4740 struct swrap_address convert_addr = {
4741 .sa_socklen = sizeof(struct sockaddr_storage),
4743 struct socket_info *si;
4744 struct msghdr msg;
4745 struct iovec tmp;
4746 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4747 size_t msg_ctrllen_filled;
4748 size_t msg_ctrllen_left;
4749 #endif
4751 ssize_t ret;
4752 int rc;
4754 si = find_socket_info(s);
4755 if (si == NULL) {
4756 return libc_recvmsg(s, omsg, flags);
4759 tmp.iov_base = NULL;
4760 tmp.iov_len = 0;
4762 ZERO_STRUCT(msg);
4763 msg.msg_name = &from_addr.sa; /* optional address */
4764 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
4765 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4766 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4767 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4768 msg_ctrllen_filled = 0;
4769 msg_ctrllen_left = omsg->msg_controllen;
4771 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
4772 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4773 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4774 #endif
4776 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
4777 if (rc < 0) {
4778 return -1;
4781 ret = libc_recvmsg(s, &msg, flags);
4783 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4784 msg_ctrllen_filled += msg.msg_controllen;
4785 msg_ctrllen_left -= msg.msg_controllen;
4787 if (omsg->msg_control != NULL) {
4788 uint8_t *p;
4790 p = omsg->msg_control;
4791 p += msg_ctrllen_filled;
4793 msg.msg_control = p;
4794 msg.msg_controllen = msg_ctrllen_left;
4795 } else {
4796 msg.msg_control = NULL;
4797 msg.msg_controllen = 0;
4799 #endif
4802 * We convert the unix address to a IP address so we need a buffer
4803 * which can store the address in case of SOCK_DGRAM, see below.
4805 msg.msg_name = &convert_addr.sa;
4806 msg.msg_namelen = convert_addr.sa_socklen;
4808 rc = swrap_recvmsg_after(s,
4810 &msg,
4811 &from_addr.sa.un,
4812 from_addr.sa_socklen,
4813 ret);
4814 if (rc != 0) {
4815 return rc;
4818 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4819 if (omsg->msg_control != NULL) {
4820 /* msg.msg_controllen = space left */
4821 msg_ctrllen_left = msg.msg_controllen;
4822 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
4825 /* Update the original message length */
4826 omsg->msg_controllen = msg_ctrllen_filled;
4827 omsg->msg_flags = msg.msg_flags;
4828 #endif
4829 omsg->msg_iovlen = msg.msg_iovlen;
4832 * From the manpage:
4834 * The msg_name field points to a caller-allocated buffer that is
4835 * used to return the source address if the socket is unconnected. The
4836 * caller should set msg_namelen to the size of this buffer before this
4837 * call; upon return from a successful call, msg_name will contain the
4838 * length of the returned address. If the application does not need
4839 * to know the source address, msg_name can be specified as NULL.
4841 if (si->type == SOCK_STREAM) {
4842 omsg->msg_namelen = 0;
4843 } else if (omsg->msg_name != NULL &&
4844 omsg->msg_namelen != 0 &&
4845 omsg->msg_namelen >= msg.msg_namelen) {
4846 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
4847 omsg->msg_namelen = msg.msg_namelen;
4850 return ret;
4853 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
4855 return swrap_recvmsg(sockfd, msg, flags);
4858 /****************************************************************************
4859 * SENDMSG
4860 ***************************************************************************/
4862 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
4864 struct msghdr msg;
4865 struct iovec tmp;
4866 struct sockaddr_un un_addr;
4867 const struct sockaddr_un *to_un = NULL;
4868 const struct sockaddr *to = NULL;
4869 ssize_t ret;
4870 int rc;
4871 struct socket_info *si = find_socket_info(s);
4872 int bcast = 0;
4874 if (!si) {
4875 return libc_sendmsg(s, omsg, flags);
4878 ZERO_STRUCT(un_addr);
4880 tmp.iov_base = NULL;
4881 tmp.iov_len = 0;
4883 ZERO_STRUCT(msg);
4885 if (si->connected == 0) {
4886 msg.msg_name = omsg->msg_name; /* optional address */
4887 msg.msg_namelen = omsg->msg_namelen; /* size of address */
4889 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
4890 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
4891 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4892 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
4893 /* omsg is a const so use a local buffer for modifications */
4894 uint8_t cmbuf[omsg->msg_controllen];
4896 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
4898 msg.msg_control = cmbuf; /* ancillary data, see below */
4899 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
4901 msg.msg_flags = omsg->msg_flags; /* flags on received message */
4902 #endif
4904 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
4905 if (rc < 0) {
4906 return -1;
4909 if (bcast) {
4910 struct stat st;
4911 unsigned int iface;
4912 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
4913 char type;
4914 size_t i, len = 0;
4915 uint8_t *buf;
4916 off_t ofs = 0;
4917 size_t avail = 0;
4918 size_t remain;
4920 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4921 avail += msg.msg_iov[i].iov_len;
4924 len = avail;
4925 remain = avail;
4927 /* we capture it as one single packet */
4928 buf = (uint8_t *)malloc(remain);
4929 if (!buf) {
4930 return -1;
4933 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
4934 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
4935 memcpy(buf + ofs,
4936 msg.msg_iov[i].iov_base,
4937 this_time);
4938 ofs += this_time;
4939 remain -= this_time;
4942 type = SOCKET_TYPE_CHAR_UDP;
4944 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
4945 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
4946 socket_wrapper_dir(), type, iface, prt);
4947 if (stat(un_addr.sun_path, &st) != 0) continue;
4949 msg.msg_name = &un_addr; /* optional address */
4950 msg.msg_namelen = sizeof(un_addr); /* size of address */
4952 /* ignore the any errors in broadcast sends */
4953 libc_sendmsg(s, &msg, flags);
4956 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4957 free(buf);
4959 return len;
4962 ret = libc_sendmsg(s, &msg, flags);
4964 swrap_sendmsg_after(s, si, &msg, to, ret);
4966 return ret;
4969 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
4971 return swrap_sendmsg(s, omsg, flags);
4974 /****************************************************************************
4975 * READV
4976 ***************************************************************************/
4978 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
4980 struct socket_info *si;
4981 struct msghdr msg;
4982 struct iovec tmp;
4983 struct swrap_address saddr = {
4984 .sa_socklen = sizeof(struct sockaddr_storage)
4986 ssize_t ret;
4987 int rc;
4989 si = find_socket_info(s);
4990 if (si == NULL) {
4991 return libc_readv(s, vector, count);
4994 tmp.iov_base = NULL;
4995 tmp.iov_len = 0;
4997 ZERO_STRUCT(msg);
4998 msg.msg_name = &saddr.sa.s; /* optional address */
4999 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5000 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5001 msg.msg_iovlen = count; /* # elements in msg_iov */
5002 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5003 msg.msg_control = NULL; /* ancillary data, see below */
5004 msg.msg_controllen = 0; /* ancillary data buffer len */
5005 msg.msg_flags = 0; /* flags on received message */
5006 #endif
5008 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5009 if (rc < 0) {
5010 if (rc == -ENOTSOCK) {
5011 return libc_readv(s, vector, count);
5013 return -1;
5016 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5018 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5019 if (rc != 0) {
5020 return rc;
5023 return ret;
5026 ssize_t readv(int s, const struct iovec *vector, int count)
5028 return swrap_readv(s, vector, count);
5031 /****************************************************************************
5032 * WRITEV
5033 ***************************************************************************/
5035 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5037 struct msghdr msg;
5038 struct iovec tmp;
5039 struct sockaddr_un un_addr;
5040 ssize_t ret;
5041 int rc;
5042 struct socket_info *si = find_socket_info(s);
5044 if (!si) {
5045 return libc_writev(s, vector, count);
5048 tmp.iov_base = NULL;
5049 tmp.iov_len = 0;
5051 ZERO_STRUCT(msg);
5052 msg.msg_name = NULL; /* optional address */
5053 msg.msg_namelen = 0; /* size of address */
5054 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5055 msg.msg_iovlen = count; /* # elements in msg_iov */
5056 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5057 msg.msg_control = NULL; /* ancillary data, see below */
5058 msg.msg_controllen = 0; /* ancillary data buffer len */
5059 msg.msg_flags = 0; /* flags on received message */
5060 #endif
5062 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5063 if (rc < 0) {
5064 if (rc == -ENOTSOCK) {
5065 return libc_readv(s, vector, count);
5067 return -1;
5070 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5072 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5074 return ret;
5077 ssize_t writev(int s, const struct iovec *vector, int count)
5079 return swrap_writev(s, vector, count);
5082 /****************************
5083 * CLOSE
5084 ***************************/
5086 static int swrap_close(int fd)
5088 struct socket_info *si = find_socket_info(fd);
5089 struct socket_info_fd *fi;
5090 int ret;
5092 if (!si) {
5093 return libc_close(fd);
5096 for (fi = si->fds; fi; fi = fi->next) {
5097 if (fi->fd == fd) {
5098 SWRAP_DLIST_REMOVE(si->fds, fi);
5099 free(fi);
5100 break;
5104 if (si->fds) {
5105 /* there are still references left */
5106 return libc_close(fd);
5109 SWRAP_DLIST_REMOVE(sockets, si);
5111 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5112 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5115 ret = libc_close(fd);
5117 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5118 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5119 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5122 if (si->un_addr.sun_path[0] != '\0') {
5123 unlink(si->un_addr.sun_path);
5125 free(si);
5127 return ret;
5130 int close(int fd)
5132 return swrap_close(fd);
5135 /****************************
5136 * DUP
5137 ***************************/
5139 static int swrap_dup(int fd)
5141 struct socket_info *si;
5142 struct socket_info_fd *fi;
5144 si = find_socket_info(fd);
5146 if (!si) {
5147 return libc_dup(fd);
5150 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5151 if (fi == NULL) {
5152 errno = ENOMEM;
5153 return -1;
5156 fi->fd = libc_dup(fd);
5157 if (fi->fd == -1) {
5158 int saved_errno = errno;
5159 free(fi);
5160 errno = saved_errno;
5161 return -1;
5164 /* Make sure we don't have an entry for the fd */
5165 swrap_remove_stale(fi->fd);
5167 SWRAP_DLIST_ADD(si->fds, fi);
5168 return fi->fd;
5171 int dup(int fd)
5173 return swrap_dup(fd);
5176 /****************************
5177 * DUP2
5178 ***************************/
5180 static int swrap_dup2(int fd, int newfd)
5182 struct socket_info *si;
5183 struct socket_info_fd *fi;
5185 si = find_socket_info(fd);
5187 if (!si) {
5188 return libc_dup2(fd, newfd);
5191 if (find_socket_info(newfd)) {
5192 /* dup2() does an implicit close of newfd, which we
5193 * need to emulate */
5194 swrap_close(newfd);
5197 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5198 if (fi == NULL) {
5199 errno = ENOMEM;
5200 return -1;
5203 fi->fd = libc_dup2(fd, newfd);
5204 if (fi->fd == -1) {
5205 int saved_errno = errno;
5206 free(fi);
5207 errno = saved_errno;
5208 return -1;
5211 /* Make sure we don't have an entry for the fd */
5212 swrap_remove_stale(fi->fd);
5214 SWRAP_DLIST_ADD(si->fds, fi);
5215 return fi->fd;
5218 int dup2(int fd, int newfd)
5220 return swrap_dup2(fd, newfd);
5223 /****************************
5224 * FCNTL
5225 ***************************/
5227 static int swrap_vfcntl(int fd, int cmd, va_list va)
5229 struct socket_info_fd *fi;
5230 struct socket_info *si;
5231 int rc;
5233 si = find_socket_info(fd);
5234 if (si == NULL) {
5235 rc = libc_vfcntl(fd, cmd, va);
5237 return rc;
5240 switch (cmd) {
5241 case F_DUPFD:
5242 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5243 if (fi == NULL) {
5244 errno = ENOMEM;
5245 return -1;
5248 fi->fd = libc_vfcntl(fd, cmd, va);
5249 if (fi->fd == -1) {
5250 int saved_errno = errno;
5251 free(fi);
5252 errno = saved_errno;
5253 return -1;
5256 /* Make sure we don't have an entry for the fd */
5257 swrap_remove_stale(fi->fd);
5259 SWRAP_DLIST_ADD(si->fds, fi);
5261 rc = fi->fd;
5262 break;
5263 default:
5264 rc = libc_vfcntl(fd, cmd, va);
5265 break;
5268 return rc;
5271 int fcntl(int fd, int cmd, ...)
5273 va_list va;
5274 int rc;
5276 va_start(va, cmd);
5278 rc = swrap_vfcntl(fd, cmd, va);
5280 va_end(va);
5282 return rc;
5285 /****************************
5286 * EVENTFD
5287 ***************************/
5289 #ifdef HAVE_EVENTFD
5290 static int swrap_eventfd(int count, int flags)
5292 int fd;
5294 fd = libc_eventfd(count, flags);
5295 if (fd != -1) {
5296 swrap_remove_stale(fd);
5299 return fd;
5302 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5303 int eventfd(unsigned int count, int flags)
5304 #else
5305 int eventfd(int count, int flags)
5306 #endif
5308 return swrap_eventfd(count, flags);
5310 #endif
5312 #ifdef HAVE_PLEDGE
5313 int pledge(const char *promises, const char *paths[])
5315 (void)promises; /* unused */
5316 (void)paths; /* unused */
5318 return 0;
5320 #endif /* HAVE_PLEDGE */
5322 /****************************
5323 * DESTRUCTOR
5324 ***************************/
5327 * This function is called when the library is unloaded and makes sure that
5328 * sockets get closed and the unix file for the socket are unlinked.
5330 void swrap_destructor(void)
5332 struct socket_info *s = sockets;
5334 while (s != NULL) {
5335 struct socket_info_fd *f = s->fds;
5336 if (f != NULL) {
5337 swrap_close(f->fd);
5339 s = sockets;
5342 if (swrap.libc_handle != NULL) {
5343 dlclose(swrap.libc_handle);
5345 if (swrap.libsocket_handle) {
5346 dlclose(swrap.libsocket_handle);