idmap_cache: Only touch "sid" on success in find_xid_to_sid
[Samba.git] / third_party / socket_wrapper / socket_wrapper.c
blob539d27dbc9ddfeec7a63b740ebbb577ea48a49ca
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
82 #include <pthread.h>
84 enum swrap_dbglvl_e {
85 SWRAP_LOG_ERROR = 0,
86 SWRAP_LOG_WARN,
87 SWRAP_LOG_DEBUG,
88 SWRAP_LOG_TRACE
91 /* GCC have printf type attribute check. */
92 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
93 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
94 #else
95 #define PRINTF_ATTRIBUTE(a,b)
96 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
98 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
99 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
100 #else
101 #define CONSTRUCTOR_ATTRIBUTE
102 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
104 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
105 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
106 #else
107 #define DESTRUCTOR_ATTRIBUTE
108 #endif
110 #ifndef FALL_THROUGH
111 # ifdef HAVE_FALLTHROUGH_ATTRIBUTE
112 # define FALL_THROUGH __attribute__ ((fallthrough))
113 # else /* HAVE_FALLTHROUGH_ATTRIBUTE */
114 # define FALL_THROUGH
115 # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */
116 #endif /* FALL_THROUGH */
118 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
119 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
120 #else
121 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
122 #endif
124 #ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
125 # define SWRAP_THREAD __thread
126 #else
127 # define SWRAP_THREAD
128 #endif
130 #ifndef MIN
131 #define MIN(a,b) ((a)<(b)?(a):(b))
132 #endif
134 #ifndef ZERO_STRUCT
135 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
136 #endif
138 #ifndef ZERO_STRUCTP
139 #define ZERO_STRUCTP(x) do { \
140 if ((x) != NULL) \
141 memset((char *)(x), 0, sizeof(*(x))); \
142 } while(0)
143 #endif
145 #ifndef discard_const
146 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
147 #endif
149 #ifndef discard_const_p
150 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
151 #endif
153 #define UNUSED(x) (void)(x)
155 #ifdef IPV6_PKTINFO
156 # ifndef IPV6_RECVPKTINFO
157 # define IPV6_RECVPKTINFO IPV6_PKTINFO
158 # endif /* IPV6_RECVPKTINFO */
159 #endif /* IPV6_PKTINFO */
162 * On BSD IP_PKTINFO has a different name because during
163 * the time when they implemented it, there was no RFC.
164 * The name for IPv6 is the same as on Linux.
166 #ifndef IP_PKTINFO
167 # ifdef IP_RECVDSTADDR
168 # define IP_PKTINFO IP_RECVDSTADDR
169 # endif
170 #endif
172 /* Macros for accessing mutexes */
173 # define SWRAP_LOCK(m) do { \
174 pthread_mutex_lock(&(m ## _mutex)); \
175 } while(0)
177 # define SWRAP_UNLOCK(m) do { \
178 pthread_mutex_unlock(&(m ## _mutex)); \
179 } while(0)
181 /* Add new global locks here please */
182 # define SWRAP_LOCK_ALL \
183 SWRAP_LOCK(libc_symbol_binding); \
185 # define SWRAP_UNLOCK_ALL \
186 SWRAP_UNLOCK(libc_symbol_binding); \
189 #define SWRAP_DLIST_ADD(list,item) do { \
190 if (!(list)) { \
191 (item)->prev = NULL; \
192 (item)->next = NULL; \
193 (list) = (item); \
194 } else { \
195 (item)->prev = NULL; \
196 (item)->next = (list); \
197 (list)->prev = (item); \
198 (list) = (item); \
200 } while (0)
202 #define SWRAP_DLIST_REMOVE(list,item) do { \
203 if ((list) == (item)) { \
204 (list) = (item)->next; \
205 if (list) { \
206 (list)->prev = NULL; \
208 } else { \
209 if ((item)->prev) { \
210 (item)->prev->next = (item)->next; \
212 if ((item)->next) { \
213 (item)->next->prev = (item)->prev; \
216 (item)->prev = NULL; \
217 (item)->next = NULL; \
218 } while (0)
220 #define SWRAP_DLIST_ADD_AFTER(list, item, el) \
221 do { \
222 if ((list) == NULL || (el) == NULL) { \
223 SWRAP_DLIST_ADD(list, item); \
224 } else { \
225 (item)->prev = (el); \
226 (item)->next = (el)->next; \
227 (el)->next = (item); \
228 if ((item)->next != NULL) { \
229 (item)->next->prev = (item); \
232 } while (0)
234 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
235 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
236 #else
237 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
238 #endif
240 /* we need to use a very terse format here as IRIX 6.4 silently
241 truncates names to 16 chars, so if we use a longer name then we
242 can't tell which port a packet came from with recvfrom()
244 with this format we have 8 chars left for the directory name
246 #define SOCKET_FORMAT "%c%02X%04X"
247 #define SOCKET_TYPE_CHAR_TCP 'T'
248 #define SOCKET_TYPE_CHAR_UDP 'U'
249 #define SOCKET_TYPE_CHAR_TCP_V6 'X'
250 #define SOCKET_TYPE_CHAR_UDP_V6 'Y'
253 * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
254 * format PCAP capture files (as the caller will simply continue from here).
256 #define SOCKET_WRAPPER_MTU_DEFAULT 1500
257 #define SOCKET_WRAPPER_MTU_MIN 512
258 #define SOCKET_WRAPPER_MTU_MAX 32768
260 #define SOCKET_MAX_SOCKETS 1024
264 * Maximum number of socket_info structures that can
265 * be used. Can be overriden by the environment variable
266 * SOCKET_WRAPPER_MAX_SOCKETS.
268 #define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
270 #define SOCKET_WRAPPER_MAX_SOCKETS_LIMIT 256000
272 /* This limit is to avoid broadcast sendto() needing to stat too many
273 * files. It may be raised (with a performance cost) to up to 254
274 * without changing the format above */
275 #define MAX_WRAPPED_INTERFACES 64
277 struct swrap_address {
278 socklen_t sa_socklen;
279 union {
280 struct sockaddr s;
281 struct sockaddr_in in;
282 #ifdef HAVE_IPV6
283 struct sockaddr_in6 in6;
284 #endif
285 struct sockaddr_un un;
286 struct sockaddr_storage ss;
287 } sa;
290 struct socket_info_fd {
291 struct socket_info_fd *prev, *next;
292 int fd;
295 * Points to corresponding index in array of
296 * socket_info structures
298 int si_index;
301 int first_free;
303 struct socket_info
305 unsigned int refcount;
307 int next_free;
309 int family;
310 int type;
311 int protocol;
312 int bound;
313 int bcast;
314 int is_server;
315 int connected;
316 int defer_connect;
317 int pktinfo;
318 int tcp_nodelay;
320 /* The unix path so we can unlink it on close() */
321 struct sockaddr_un un_addr;
323 struct swrap_address bindname;
324 struct swrap_address myname;
325 struct swrap_address peername;
327 struct {
328 unsigned long pck_snd;
329 unsigned long pck_rcv;
330 } io;
333 static struct socket_info *sockets;
334 static size_t max_sockets = 0;
337 * While socket file descriptors are passed among different processes, the
338 * numerical value gets changed. So its better to store it locally to each
339 * process rather than including it within socket_info which will be shared.
341 static struct socket_info_fd *socket_fds;
343 /* The mutex for accessing the global libc.symbols */
344 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
346 /* Function prototypes */
348 bool socket_wrapper_enabled(void);
350 void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
351 void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
353 static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
354 # define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
356 static void swrap_log(enum swrap_dbglvl_e dbglvl,
357 const char *func,
358 const char *format, ...)
360 char buffer[1024];
361 va_list va;
362 const char *d;
363 unsigned int lvl = 0;
364 const char *prefix = "SWRAP";
366 d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
367 if (d != NULL) {
368 lvl = atoi(d);
371 if (lvl < dbglvl) {
372 return;
375 va_start(va, format);
376 vsnprintf(buffer, sizeof(buffer), format, va);
377 va_end(va);
379 switch (dbglvl) {
380 case SWRAP_LOG_ERROR:
381 prefix = "SWRAP_ERROR";
382 break;
383 case SWRAP_LOG_WARN:
384 prefix = "SWRAP_WARN";
385 break;
386 case SWRAP_LOG_DEBUG:
387 prefix = "SWRAP_DEBUG";
388 break;
389 case SWRAP_LOG_TRACE:
390 prefix = "SWRAP_TRACE";
391 break;
394 fprintf(stderr,
395 "%s(%d) - %s: %s\n",
396 prefix, (int)getpid(), func, buffer);
399 /*********************************************************
400 * SWRAP LOADING LIBC FUNCTIONS
401 *********************************************************/
403 #include <dlfcn.h>
405 #ifdef HAVE_ACCEPT4
406 typedef int (*__libc_accept4)(int sockfd,
407 struct sockaddr *addr,
408 socklen_t *addrlen,
409 int flags);
410 #else
411 typedef int (*__libc_accept)(int sockfd,
412 struct sockaddr *addr,
413 socklen_t *addrlen);
414 #endif
415 typedef int (*__libc_bind)(int sockfd,
416 const struct sockaddr *addr,
417 socklen_t addrlen);
418 typedef int (*__libc_close)(int fd);
419 typedef int (*__libc_connect)(int sockfd,
420 const struct sockaddr *addr,
421 socklen_t addrlen);
422 typedef int (*__libc_dup)(int fd);
423 typedef int (*__libc_dup2)(int oldfd, int newfd);
424 typedef int (*__libc_fcntl)(int fd, int cmd, ...);
425 typedef FILE *(*__libc_fopen)(const char *name, const char *mode);
426 #ifdef HAVE_FOPEN64
427 typedef FILE *(*__libc_fopen64)(const char *name, const char *mode);
428 #endif
429 #ifdef HAVE_EVENTFD
430 typedef int (*__libc_eventfd)(int count, int flags);
431 #endif
432 typedef int (*__libc_getpeername)(int sockfd,
433 struct sockaddr *addr,
434 socklen_t *addrlen);
435 typedef int (*__libc_getsockname)(int sockfd,
436 struct sockaddr *addr,
437 socklen_t *addrlen);
438 typedef int (*__libc_getsockopt)(int sockfd,
439 int level,
440 int optname,
441 void *optval,
442 socklen_t *optlen);
443 typedef int (*__libc_ioctl)(int d, unsigned long int request, ...);
444 typedef int (*__libc_listen)(int sockfd, int backlog);
445 typedef int (*__libc_open)(const char *pathname, int flags, ...);
446 #ifdef HAVE_OPEN64
447 typedef int (*__libc_open64)(const char *pathname, int flags, ...);
448 #endif /* HAVE_OPEN64 */
449 typedef int (*__libc_openat)(int dirfd, const char *path, int flags, ...);
450 typedef int (*__libc_pipe)(int pipefd[2]);
451 typedef int (*__libc_read)(int fd, void *buf, size_t count);
452 typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt);
453 typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags);
454 typedef int (*__libc_recvfrom)(int sockfd,
455 void *buf,
456 size_t len,
457 int flags,
458 struct sockaddr *src_addr,
459 socklen_t *addrlen);
460 typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
461 typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags);
462 typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
463 typedef int (*__libc_sendto)(int sockfd,
464 const void *buf,
465 size_t len,
466 int flags,
467 const struct sockaddr *dst_addr,
468 socklen_t addrlen);
469 typedef int (*__libc_setsockopt)(int sockfd,
470 int level,
471 int optname,
472 const void *optval,
473 socklen_t optlen);
474 #ifdef HAVE_SIGNALFD
475 typedef int (*__libc_signalfd)(int fd, const sigset_t *mask, int flags);
476 #endif
477 typedef int (*__libc_socket)(int domain, int type, int protocol);
478 typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]);
479 #ifdef HAVE_TIMERFD_CREATE
480 typedef int (*__libc_timerfd_create)(int clockid, int flags);
481 #endif
482 typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count);
483 typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt);
485 #define SWRAP_SYMBOL_ENTRY(i) \
486 union { \
487 __libc_##i f; \
488 void *obj; \
489 } _libc_##i
491 struct swrap_libc_symbols {
492 #ifdef HAVE_ACCEPT4
493 SWRAP_SYMBOL_ENTRY(accept4);
494 #else
495 SWRAP_SYMBOL_ENTRY(accept);
496 #endif
497 SWRAP_SYMBOL_ENTRY(bind);
498 SWRAP_SYMBOL_ENTRY(close);
499 SWRAP_SYMBOL_ENTRY(connect);
500 SWRAP_SYMBOL_ENTRY(dup);
501 SWRAP_SYMBOL_ENTRY(dup2);
502 SWRAP_SYMBOL_ENTRY(fcntl);
503 SWRAP_SYMBOL_ENTRY(fopen);
504 #ifdef HAVE_FOPEN64
505 SWRAP_SYMBOL_ENTRY(fopen64);
506 #endif
507 #ifdef HAVE_EVENTFD
508 SWRAP_SYMBOL_ENTRY(eventfd);
509 #endif
510 SWRAP_SYMBOL_ENTRY(getpeername);
511 SWRAP_SYMBOL_ENTRY(getsockname);
512 SWRAP_SYMBOL_ENTRY(getsockopt);
513 SWRAP_SYMBOL_ENTRY(ioctl);
514 SWRAP_SYMBOL_ENTRY(listen);
515 SWRAP_SYMBOL_ENTRY(open);
516 #ifdef HAVE_OPEN64
517 SWRAP_SYMBOL_ENTRY(open64);
518 #endif
519 SWRAP_SYMBOL_ENTRY(openat);
520 SWRAP_SYMBOL_ENTRY(pipe);
521 SWRAP_SYMBOL_ENTRY(read);
522 SWRAP_SYMBOL_ENTRY(readv);
523 SWRAP_SYMBOL_ENTRY(recv);
524 SWRAP_SYMBOL_ENTRY(recvfrom);
525 SWRAP_SYMBOL_ENTRY(recvmsg);
526 SWRAP_SYMBOL_ENTRY(send);
527 SWRAP_SYMBOL_ENTRY(sendmsg);
528 SWRAP_SYMBOL_ENTRY(sendto);
529 SWRAP_SYMBOL_ENTRY(setsockopt);
530 #ifdef HAVE_SIGNALFD
531 SWRAP_SYMBOL_ENTRY(signalfd);
532 #endif
533 SWRAP_SYMBOL_ENTRY(socket);
534 SWRAP_SYMBOL_ENTRY(socketpair);
535 #ifdef HAVE_TIMERFD_CREATE
536 SWRAP_SYMBOL_ENTRY(timerfd_create);
537 #endif
538 SWRAP_SYMBOL_ENTRY(write);
539 SWRAP_SYMBOL_ENTRY(writev);
542 struct swrap {
543 struct {
544 void *handle;
545 void *socket_handle;
546 struct swrap_libc_symbols symbols;
547 } libc;
550 static struct swrap swrap;
552 /* prototypes */
553 static const char *socket_wrapper_dir(void);
555 #define LIBC_NAME "libc.so"
557 enum swrap_lib {
558 SWRAP_LIBC,
559 SWRAP_LIBNSL,
560 SWRAP_LIBSOCKET,
563 static const char *swrap_str_lib(enum swrap_lib lib)
565 switch (lib) {
566 case SWRAP_LIBC:
567 return "libc";
568 case SWRAP_LIBNSL:
569 return "libnsl";
570 case SWRAP_LIBSOCKET:
571 return "libsocket";
574 /* Compiler would warn us about unhandled enum value if we get here */
575 return "unknown";
578 static void *swrap_load_lib_handle(enum swrap_lib lib)
580 int flags = RTLD_LAZY;
581 void *handle = NULL;
582 int i;
584 #ifdef RTLD_DEEPBIND
585 flags |= RTLD_DEEPBIND;
586 #endif
588 switch (lib) {
589 case SWRAP_LIBNSL:
590 FALL_THROUGH;
591 case SWRAP_LIBSOCKET:
592 #ifdef HAVE_LIBSOCKET
593 handle = swrap.libc.socket_handle;
594 if (handle == NULL) {
595 for (i = 10; i >= 0; i--) {
596 char soname[256] = {0};
598 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
599 handle = dlopen(soname, flags);
600 if (handle != NULL) {
601 break;
605 swrap.libc.socket_handle = handle;
607 break;
608 #endif
609 FALL_THROUGH;
610 case SWRAP_LIBC:
611 handle = swrap.libc.handle;
612 #ifdef LIBC_SO
613 if (handle == NULL) {
614 handle = dlopen(LIBC_SO, flags);
616 swrap.libc.handle = handle;
618 #endif
619 if (handle == NULL) {
620 for (i = 10; i >= 0; i--) {
621 char soname[256] = {0};
623 snprintf(soname, sizeof(soname), "libc.so.%d", i);
624 handle = dlopen(soname, flags);
625 if (handle != NULL) {
626 break;
630 swrap.libc.handle = handle;
632 break;
635 if (handle == NULL) {
636 #ifdef RTLD_NEXT
637 handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT;
638 #else
639 SWRAP_LOG(SWRAP_LOG_ERROR,
640 "Failed to dlopen library: %s\n",
641 dlerror());
642 exit(-1);
643 #endif
646 return handle;
649 static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
651 void *handle;
652 void *func;
654 handle = swrap_load_lib_handle(lib);
656 func = dlsym(handle, fn_name);
657 if (func == NULL) {
658 SWRAP_LOG(SWRAP_LOG_ERROR,
659 "Failed to find %s: %s\n",
660 fn_name,
661 dlerror());
662 exit(-1);
665 SWRAP_LOG(SWRAP_LOG_TRACE,
666 "Loaded %s from %s",
667 fn_name,
668 swrap_str_lib(lib));
670 return func;
673 #define swrap_bind_symbol_libc(sym_name) \
674 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
675 SWRAP_LOCK(libc_symbol_binding); \
676 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
677 swrap.libc.symbols._libc_##sym_name.obj = \
678 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
680 SWRAP_UNLOCK(libc_symbol_binding); \
683 #define swrap_bind_symbol_libsocket(sym_name) \
684 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
685 SWRAP_LOCK(libc_symbol_binding); \
686 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
687 swrap.libc.symbols._libc_##sym_name.obj = \
688 _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
690 SWRAP_UNLOCK(libc_symbol_binding); \
693 #define swrap_bind_symbol_libnsl(sym_name) \
694 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
695 SWRAP_LOCK(libc_symbol_binding); \
696 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
697 swrap.libc.symbols._libc_##sym_name.obj = \
698 _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
700 SWRAP_UNLOCK(libc_symbol_binding); \
703 /****************************************************************************
704 * IMPORTANT
705 ****************************************************************************
707 * Functions especially from libc need to be loaded individually, you can't
708 * load all at once or gdb will segfault at startup. The same applies to
709 * valgrind and has probably something todo with with the linker. So we need
710 * load each function at the point it is called the first time.
712 ****************************************************************************/
714 #ifdef HAVE_ACCEPT4
715 static int libc_accept4(int sockfd,
716 struct sockaddr *addr,
717 socklen_t *addrlen,
718 int flags)
720 swrap_bind_symbol_libsocket(accept4);
722 return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags);
725 #else /* HAVE_ACCEPT4 */
727 static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
729 swrap_bind_symbol_libsocket(accept);
731 return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen);
733 #endif /* HAVE_ACCEPT4 */
735 static int libc_bind(int sockfd,
736 const struct sockaddr *addr,
737 socklen_t addrlen)
739 swrap_bind_symbol_libsocket(bind);
741 return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen);
744 static int libc_close(int fd)
746 swrap_bind_symbol_libc(close);
748 return swrap.libc.symbols._libc_close.f(fd);
751 static int libc_connect(int sockfd,
752 const struct sockaddr *addr,
753 socklen_t addrlen)
755 swrap_bind_symbol_libsocket(connect);
757 return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen);
760 static int libc_dup(int fd)
762 swrap_bind_symbol_libc(dup);
764 return swrap.libc.symbols._libc_dup.f(fd);
767 static int libc_dup2(int oldfd, int newfd)
769 swrap_bind_symbol_libc(dup2);
771 return swrap.libc.symbols._libc_dup2.f(oldfd, newfd);
774 #ifdef HAVE_EVENTFD
775 static int libc_eventfd(int count, int flags)
777 swrap_bind_symbol_libc(eventfd);
779 return swrap.libc.symbols._libc_eventfd.f(count, flags);
781 #endif
783 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
784 static int libc_vfcntl(int fd, int cmd, va_list ap)
786 void *arg;
787 int rc;
789 swrap_bind_symbol_libc(fcntl);
791 arg = va_arg(ap, void *);
793 rc = swrap.libc.symbols._libc_fcntl.f(fd, cmd, arg);
795 return rc;
798 static int libc_getpeername(int sockfd,
799 struct sockaddr *addr,
800 socklen_t *addrlen)
802 swrap_bind_symbol_libsocket(getpeername);
804 return swrap.libc.symbols._libc_getpeername.f(sockfd, addr, addrlen);
807 static int libc_getsockname(int sockfd,
808 struct sockaddr *addr,
809 socklen_t *addrlen)
811 swrap_bind_symbol_libsocket(getsockname);
813 return swrap.libc.symbols._libc_getsockname.f(sockfd, addr, addrlen);
816 static int libc_getsockopt(int sockfd,
817 int level,
818 int optname,
819 void *optval,
820 socklen_t *optlen)
822 swrap_bind_symbol_libsocket(getsockopt);
824 return swrap.libc.symbols._libc_getsockopt.f(sockfd,
825 level,
826 optname,
827 optval,
828 optlen);
831 DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
832 static int libc_vioctl(int d, unsigned long int request, va_list ap)
834 void *arg;
835 int rc;
837 swrap_bind_symbol_libc(ioctl);
839 arg = va_arg(ap, void *);
841 rc = swrap.libc.symbols._libc_ioctl.f(d, request, arg);
843 return rc;
846 static int libc_listen(int sockfd, int backlog)
848 swrap_bind_symbol_libsocket(listen);
850 return swrap.libc.symbols._libc_listen.f(sockfd, backlog);
853 static FILE *libc_fopen(const char *name, const char *mode)
855 swrap_bind_symbol_libc(fopen);
857 return swrap.libc.symbols._libc_fopen.f(name, mode);
860 #ifdef HAVE_FOPEN64
861 static FILE *libc_fopen64(const char *name, const char *mode)
863 swrap_bind_symbol_libc(fopen64);
865 return swrap.libc.symbols._libc_fopen64.f(name, mode);
867 #endif /* HAVE_FOPEN64 */
869 static int libc_vopen(const char *pathname, int flags, va_list ap)
871 int mode = 0;
872 int fd;
874 swrap_bind_symbol_libc(open);
876 if (flags & O_CREAT) {
877 mode = va_arg(ap, int);
879 fd = swrap.libc.symbols._libc_open.f(pathname, flags, (mode_t)mode);
881 return fd;
884 static int libc_open(const char *pathname, int flags, ...)
886 va_list ap;
887 int fd;
889 va_start(ap, flags);
890 fd = libc_vopen(pathname, flags, ap);
891 va_end(ap);
893 return fd;
896 #ifdef HAVE_OPEN64
897 static int libc_vopen64(const char *pathname, int flags, va_list ap)
899 int mode = 0;
900 int fd;
902 swrap_bind_symbol_libc(open64);
904 if (flags & O_CREAT) {
905 mode = va_arg(ap, int);
907 fd = swrap.libc.symbols._libc_open64.f(pathname, flags, (mode_t)mode);
909 return fd;
911 #endif /* HAVE_OPEN64 */
913 static int libc_vopenat(int dirfd, const char *path, int flags, va_list ap)
915 int mode = 0;
916 int fd;
918 swrap_bind_symbol_libc(openat);
920 if (flags & O_CREAT) {
921 mode = va_arg(ap, int);
923 fd = swrap.libc.symbols._libc_openat.f(dirfd,
924 path,
925 flags,
926 (mode_t)mode);
928 return fd;
931 #if 0
932 static int libc_openat(int dirfd, const char *path, int flags, ...)
934 va_list ap;
935 int fd;
937 va_start(ap, flags);
938 fd = libc_vopenat(dirfd, path, flags, ap);
939 va_end(ap);
941 return fd;
943 #endif
945 static int libc_pipe(int pipefd[2])
947 swrap_bind_symbol_libsocket(pipe);
949 return swrap.libc.symbols._libc_pipe.f(pipefd);
952 static int libc_read(int fd, void *buf, size_t count)
954 swrap_bind_symbol_libc(read);
956 return swrap.libc.symbols._libc_read.f(fd, buf, count);
959 static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
961 swrap_bind_symbol_libsocket(readv);
963 return swrap.libc.symbols._libc_readv.f(fd, iov, iovcnt);
966 static int libc_recv(int sockfd, void *buf, size_t len, int flags)
968 swrap_bind_symbol_libsocket(recv);
970 return swrap.libc.symbols._libc_recv.f(sockfd, buf, len, flags);
973 static int libc_recvfrom(int sockfd,
974 void *buf,
975 size_t len,
976 int flags,
977 struct sockaddr *src_addr,
978 socklen_t *addrlen)
980 swrap_bind_symbol_libsocket(recvfrom);
982 return swrap.libc.symbols._libc_recvfrom.f(sockfd,
983 buf,
984 len,
985 flags,
986 src_addr,
987 addrlen);
990 static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
992 swrap_bind_symbol_libsocket(recvmsg);
994 return swrap.libc.symbols._libc_recvmsg.f(sockfd, msg, flags);
997 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
999 swrap_bind_symbol_libsocket(send);
1001 return swrap.libc.symbols._libc_send.f(sockfd, buf, len, flags);
1004 static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
1006 swrap_bind_symbol_libsocket(sendmsg);
1008 return swrap.libc.symbols._libc_sendmsg.f(sockfd, msg, flags);
1011 static int libc_sendto(int sockfd,
1012 const void *buf,
1013 size_t len,
1014 int flags,
1015 const struct sockaddr *dst_addr,
1016 socklen_t addrlen)
1018 swrap_bind_symbol_libsocket(sendto);
1020 return swrap.libc.symbols._libc_sendto.f(sockfd,
1021 buf,
1022 len,
1023 flags,
1024 dst_addr,
1025 addrlen);
1028 static int libc_setsockopt(int sockfd,
1029 int level,
1030 int optname,
1031 const void *optval,
1032 socklen_t optlen)
1034 swrap_bind_symbol_libsocket(setsockopt);
1036 return swrap.libc.symbols._libc_setsockopt.f(sockfd,
1037 level,
1038 optname,
1039 optval,
1040 optlen);
1043 #ifdef HAVE_SIGNALFD
1044 static int libc_signalfd(int fd, const sigset_t *mask, int flags)
1046 swrap_bind_symbol_libsocket(signalfd);
1048 return swrap.libc.symbols._libc_signalfd.f(fd, mask, flags);
1050 #endif
1052 static int libc_socket(int domain, int type, int protocol)
1054 swrap_bind_symbol_libsocket(socket);
1056 return swrap.libc.symbols._libc_socket.f(domain, type, protocol);
1059 static int libc_socketpair(int domain, int type, int protocol, int sv[2])
1061 swrap_bind_symbol_libsocket(socketpair);
1063 return swrap.libc.symbols._libc_socketpair.f(domain, type, protocol, sv);
1066 #ifdef HAVE_TIMERFD_CREATE
1067 static int libc_timerfd_create(int clockid, int flags)
1069 swrap_bind_symbol_libc(timerfd_create);
1071 return swrap.libc.symbols._libc_timerfd_create.f(clockid, flags);
1073 #endif
1075 static ssize_t libc_write(int fd, const void *buf, size_t count)
1077 swrap_bind_symbol_libc(write);
1079 return swrap.libc.symbols._libc_write.f(fd, buf, count);
1082 static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
1084 swrap_bind_symbol_libsocket(writev);
1086 return swrap.libc.symbols._libc_writev.f(fd, iov, iovcnt);
1089 /* DO NOT call this function during library initialization! */
1090 static void swrap_bind_symbol_all(void)
1092 #ifdef HAVE_ACCEPT4
1093 swrap_bind_symbol_libsocket(accept4);
1094 #else
1095 swrap_bind_symbol_libsocket(accept);
1096 #endif
1097 swrap_bind_symbol_libsocket(bind);
1098 swrap_bind_symbol_libc(close);
1099 swrap_bind_symbol_libsocket(connect);
1100 swrap_bind_symbol_libc(dup);
1101 swrap_bind_symbol_libc(dup2);
1102 swrap_bind_symbol_libc(fcntl);
1103 swrap_bind_symbol_libc(fopen);
1104 #ifdef HAVE_FOPEN64
1105 swrap_bind_symbol_libc(fopen64);
1106 #endif
1107 #ifdef HAVE_EVENTFD
1108 swrap_bind_symbol_libc(eventfd);
1109 #endif
1110 swrap_bind_symbol_libsocket(getpeername);
1111 swrap_bind_symbol_libsocket(getsockname);
1112 swrap_bind_symbol_libsocket(getsockopt);
1113 swrap_bind_symbol_libc(ioctl);
1114 swrap_bind_symbol_libsocket(listen);
1115 swrap_bind_symbol_libc(open);
1116 #ifdef HAVE_OPEN64
1117 swrap_bind_symbol_libc(open64);
1118 #endif
1119 swrap_bind_symbol_libc(openat);
1120 swrap_bind_symbol_libsocket(pipe);
1121 swrap_bind_symbol_libc(read);
1122 swrap_bind_symbol_libsocket(readv);
1123 swrap_bind_symbol_libsocket(recv);
1124 swrap_bind_symbol_libsocket(recvfrom);
1125 swrap_bind_symbol_libsocket(recvmsg);
1126 swrap_bind_symbol_libsocket(send);
1127 swrap_bind_symbol_libsocket(sendmsg);
1128 swrap_bind_symbol_libsocket(sendto);
1129 swrap_bind_symbol_libsocket(setsockopt);
1130 #ifdef HAVE_SIGNALFD
1131 swrap_bind_symbol_libsocket(signalfd);
1132 #endif
1133 swrap_bind_symbol_libsocket(socket);
1134 swrap_bind_symbol_libsocket(socketpair);
1135 #ifdef HAVE_TIMERFD_CREATE
1136 swrap_bind_symbol_libc(timerfd_create);
1137 #endif
1138 swrap_bind_symbol_libc(write);
1139 swrap_bind_symbol_libsocket(writev);
1142 /*********************************************************
1143 * SWRAP HELPER FUNCTIONS
1144 *********************************************************/
1146 #ifdef HAVE_IPV6
1148 * FD00::5357:5FXX
1150 static const struct in6_addr *swrap_ipv6(void)
1152 static struct in6_addr v;
1153 static int initialized;
1154 int ret;
1156 if (initialized) {
1157 return &v;
1159 initialized = 1;
1161 ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
1162 if (ret <= 0) {
1163 abort();
1166 return &v;
1168 #endif
1170 static void set_port(int family, int prt, struct swrap_address *addr)
1172 switch (family) {
1173 case AF_INET:
1174 addr->sa.in.sin_port = htons(prt);
1175 break;
1176 #ifdef HAVE_IPV6
1177 case AF_INET6:
1178 addr->sa.in6.sin6_port = htons(prt);
1179 break;
1180 #endif
1184 static size_t socket_length(int family)
1186 switch (family) {
1187 case AF_INET:
1188 return sizeof(struct sockaddr_in);
1189 #ifdef HAVE_IPV6
1190 case AF_INET6:
1191 return sizeof(struct sockaddr_in6);
1192 #endif
1194 return 0;
1197 static const char *socket_wrapper_dir(void)
1199 const char *s = getenv("SOCKET_WRAPPER_DIR");
1200 if (s == NULL) {
1201 return NULL;
1203 /* TODO use realpath(3) here, when we add support for threads */
1204 if (strncmp(s, "./", 2) == 0) {
1205 s += 2;
1208 SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
1209 return s;
1212 static unsigned int socket_wrapper_mtu(void)
1214 static unsigned int max_mtu = 0;
1215 unsigned int tmp;
1216 const char *s;
1217 char *endp;
1219 if (max_mtu != 0) {
1220 return max_mtu;
1223 max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
1225 s = getenv("SOCKET_WRAPPER_MTU");
1226 if (s == NULL) {
1227 goto done;
1230 tmp = strtol(s, &endp, 10);
1231 if (s == endp) {
1232 goto done;
1235 if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
1236 goto done;
1238 max_mtu = tmp;
1240 done:
1241 return max_mtu;
1244 static size_t socket_wrapper_max_sockets(void)
1246 const char *s;
1247 unsigned long tmp;
1248 char *endp;
1250 if (max_sockets != 0) {
1251 return max_sockets;
1254 max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
1256 s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
1257 if (s == NULL || s[0] == '\0') {
1258 goto done;
1261 tmp = strtoul(s, &endp, 10);
1262 if (s == endp) {
1263 goto done;
1265 if (tmp == 0 || tmp > SOCKET_WRAPPER_MAX_SOCKETS_LIMIT) {
1266 SWRAP_LOG(SWRAP_LOG_ERROR,
1267 "Invalid number of sockets specified, using default.");
1268 goto done;
1271 max_sockets = tmp;
1273 done:
1274 return max_sockets;
1277 static void socket_wrapper_init_sockets(void)
1279 size_t i;
1281 if (sockets != NULL) {
1282 return;
1285 max_sockets = socket_wrapper_max_sockets();
1287 sockets = (struct socket_info *)calloc(max_sockets,
1288 sizeof(struct socket_info));
1290 if (sockets == NULL) {
1291 SWRAP_LOG(SWRAP_LOG_ERROR,
1292 "Failed to allocate sockets array.\n");
1293 exit(-1);
1296 first_free = 0;
1298 for (i = 0; i < max_sockets; i++) {
1299 sockets[i].next_free = i+1;
1302 sockets[max_sockets-1].next_free = -1;
1305 bool socket_wrapper_enabled(void)
1307 const char *s = socket_wrapper_dir();
1309 if (s == NULL) {
1310 return false;
1313 socket_wrapper_init_sockets();
1315 return true;
1318 static unsigned int socket_wrapper_default_iface(void)
1320 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
1321 if (s) {
1322 unsigned int iface;
1323 if (sscanf(s, "%u", &iface) == 1) {
1324 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
1325 return iface;
1330 return 1;/* 127.0.0.1 */
1334 * Return the first free entry (if any) and make
1335 * it re-usable again (by nulling it out)
1337 static int socket_wrapper_first_free_index(void)
1339 int next_free;
1341 if (first_free == -1) {
1342 return -1;
1345 next_free = sockets[first_free].next_free;
1346 ZERO_STRUCT(sockets[first_free]);
1347 sockets[first_free].next_free = next_free;
1349 return first_free;
1352 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
1354 unsigned int iface;
1355 unsigned int prt;
1356 const char *p;
1357 char type;
1359 p = strrchr(un->sun_path, '/');
1360 if (p) p++; else p = un->sun_path;
1362 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
1363 errno = EINVAL;
1364 return -1;
1367 SWRAP_LOG(SWRAP_LOG_TRACE, "type %c iface %u port %u",
1368 type, iface, prt);
1370 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1371 errno = EINVAL;
1372 return -1;
1375 if (prt > 0xFFFF) {
1376 errno = EINVAL;
1377 return -1;
1380 switch(type) {
1381 case SOCKET_TYPE_CHAR_TCP:
1382 case SOCKET_TYPE_CHAR_UDP: {
1383 struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
1385 if ((*len) < sizeof(*in2)) {
1386 errno = EINVAL;
1387 return -1;
1390 memset(in2, 0, sizeof(*in2));
1391 in2->sin_family = AF_INET;
1392 in2->sin_addr.s_addr = htonl((127<<24) | iface);
1393 in2->sin_port = htons(prt);
1395 *len = sizeof(*in2);
1396 break;
1398 #ifdef HAVE_IPV6
1399 case SOCKET_TYPE_CHAR_TCP_V6:
1400 case SOCKET_TYPE_CHAR_UDP_V6: {
1401 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
1403 if ((*len) < sizeof(*in2)) {
1404 errno = EINVAL;
1405 return -1;
1408 memset(in2, 0, sizeof(*in2));
1409 in2->sin6_family = AF_INET6;
1410 in2->sin6_addr = *swrap_ipv6();
1411 in2->sin6_addr.s6_addr[15] = iface;
1412 in2->sin6_port = htons(prt);
1414 *len = sizeof(*in2);
1415 break;
1417 #endif
1418 default:
1419 errno = EINVAL;
1420 return -1;
1423 return 0;
1426 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1427 int *bcast)
1429 char type = '\0';
1430 unsigned int prt;
1431 unsigned int iface;
1432 int is_bcast = 0;
1434 if (bcast) *bcast = 0;
1436 switch (inaddr->sa_family) {
1437 case AF_INET: {
1438 const struct sockaddr_in *in =
1439 (const struct sockaddr_in *)(const void *)inaddr;
1440 unsigned int addr = ntohl(in->sin_addr.s_addr);
1441 char u_type = '\0';
1442 char b_type = '\0';
1443 char a_type = '\0';
1445 switch (si->type) {
1446 case SOCK_STREAM:
1447 u_type = SOCKET_TYPE_CHAR_TCP;
1448 break;
1449 case SOCK_DGRAM:
1450 u_type = SOCKET_TYPE_CHAR_UDP;
1451 a_type = SOCKET_TYPE_CHAR_UDP;
1452 b_type = SOCKET_TYPE_CHAR_UDP;
1453 break;
1454 default:
1455 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1456 errno = ESOCKTNOSUPPORT;
1457 return -1;
1460 prt = ntohs(in->sin_port);
1461 if (a_type && addr == 0xFFFFFFFF) {
1462 /* 255.255.255.255 only udp */
1463 is_bcast = 2;
1464 type = a_type;
1465 iface = socket_wrapper_default_iface();
1466 } else if (b_type && addr == 0x7FFFFFFF) {
1467 /* 127.255.255.255 only udp */
1468 is_bcast = 1;
1469 type = b_type;
1470 iface = socket_wrapper_default_iface();
1471 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1472 /* 127.0.0.X */
1473 is_bcast = 0;
1474 type = u_type;
1475 iface = (addr & 0x000000FF);
1476 } else {
1477 errno = ENETUNREACH;
1478 return -1;
1480 if (bcast) *bcast = is_bcast;
1481 break;
1483 #ifdef HAVE_IPV6
1484 case AF_INET6: {
1485 const struct sockaddr_in6 *in =
1486 (const struct sockaddr_in6 *)(const void *)inaddr;
1487 struct in6_addr cmp1, cmp2;
1489 switch (si->type) {
1490 case SOCK_STREAM:
1491 type = SOCKET_TYPE_CHAR_TCP_V6;
1492 break;
1493 case SOCK_DGRAM:
1494 type = SOCKET_TYPE_CHAR_UDP_V6;
1495 break;
1496 default:
1497 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1498 errno = ESOCKTNOSUPPORT;
1499 return -1;
1502 /* XXX no multicast/broadcast */
1504 prt = ntohs(in->sin6_port);
1506 cmp1 = *swrap_ipv6();
1507 cmp2 = in->sin6_addr;
1508 cmp2.s6_addr[15] = 0;
1509 if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1510 iface = in->sin6_addr.s6_addr[15];
1511 } else {
1512 errno = ENETUNREACH;
1513 return -1;
1516 break;
1518 #endif
1519 default:
1520 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
1521 errno = ENETUNREACH;
1522 return -1;
1525 if (prt == 0) {
1526 SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
1527 errno = EINVAL;
1528 return -1;
1531 if (is_bcast) {
1532 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
1533 socket_wrapper_dir());
1534 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1535 /* the caller need to do more processing */
1536 return 0;
1539 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1540 socket_wrapper_dir(), type, iface, prt);
1541 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1543 return 0;
1546 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
1547 int *bcast)
1549 char type = '\0';
1550 unsigned int prt;
1551 unsigned int iface;
1552 struct stat st;
1553 int is_bcast = 0;
1555 if (bcast) *bcast = 0;
1557 switch (si->family) {
1558 case AF_INET: {
1559 const struct sockaddr_in *in =
1560 (const struct sockaddr_in *)(const void *)inaddr;
1561 unsigned int addr = ntohl(in->sin_addr.s_addr);
1562 char u_type = '\0';
1563 char d_type = '\0';
1564 char b_type = '\0';
1565 char a_type = '\0';
1567 prt = ntohs(in->sin_port);
1569 switch (si->type) {
1570 case SOCK_STREAM:
1571 u_type = SOCKET_TYPE_CHAR_TCP;
1572 d_type = SOCKET_TYPE_CHAR_TCP;
1573 break;
1574 case SOCK_DGRAM:
1575 u_type = SOCKET_TYPE_CHAR_UDP;
1576 d_type = SOCKET_TYPE_CHAR_UDP;
1577 a_type = SOCKET_TYPE_CHAR_UDP;
1578 b_type = SOCKET_TYPE_CHAR_UDP;
1579 break;
1580 default:
1581 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1582 errno = ESOCKTNOSUPPORT;
1583 return -1;
1586 if (addr == 0) {
1587 /* 0.0.0.0 */
1588 is_bcast = 0;
1589 type = d_type;
1590 iface = socket_wrapper_default_iface();
1591 } else if (a_type && addr == 0xFFFFFFFF) {
1592 /* 255.255.255.255 only udp */
1593 is_bcast = 2;
1594 type = a_type;
1595 iface = socket_wrapper_default_iface();
1596 } else if (b_type && addr == 0x7FFFFFFF) {
1597 /* 127.255.255.255 only udp */
1598 is_bcast = 1;
1599 type = b_type;
1600 iface = socket_wrapper_default_iface();
1601 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
1602 /* 127.0.0.X */
1603 is_bcast = 0;
1604 type = u_type;
1605 iface = (addr & 0x000000FF);
1606 } else {
1607 errno = EADDRNOTAVAIL;
1608 return -1;
1611 /* Store the bind address for connect() */
1612 if (si->bindname.sa_socklen == 0) {
1613 struct sockaddr_in bind_in;
1614 socklen_t blen = sizeof(struct sockaddr_in);
1616 ZERO_STRUCT(bind_in);
1617 bind_in.sin_family = in->sin_family;
1618 bind_in.sin_port = in->sin_port;
1619 bind_in.sin_addr.s_addr = htonl(0x7F000000 | iface);
1621 si->bindname.sa_socklen = blen;
1622 memcpy(&si->bindname.sa.in, &bind_in, blen);
1625 break;
1627 #ifdef HAVE_IPV6
1628 case AF_INET6: {
1629 const struct sockaddr_in6 *in =
1630 (const struct sockaddr_in6 *)(const void *)inaddr;
1631 struct in6_addr cmp1, cmp2;
1633 switch (si->type) {
1634 case SOCK_STREAM:
1635 type = SOCKET_TYPE_CHAR_TCP_V6;
1636 break;
1637 case SOCK_DGRAM:
1638 type = SOCKET_TYPE_CHAR_UDP_V6;
1639 break;
1640 default:
1641 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1642 errno = ESOCKTNOSUPPORT;
1643 return -1;
1646 /* XXX no multicast/broadcast */
1648 prt = ntohs(in->sin6_port);
1650 cmp1 = *swrap_ipv6();
1651 cmp2 = in->sin6_addr;
1652 cmp2.s6_addr[15] = 0;
1653 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
1654 iface = socket_wrapper_default_iface();
1655 } else if (IN6_ARE_ADDR_EQUAL(&cmp1, &cmp2)) {
1656 iface = in->sin6_addr.s6_addr[15];
1657 } else {
1658 errno = EADDRNOTAVAIL;
1659 return -1;
1662 /* Store the bind address for connect() */
1663 if (si->bindname.sa_socklen == 0) {
1664 struct sockaddr_in6 bind_in;
1665 socklen_t blen = sizeof(struct sockaddr_in6);
1667 ZERO_STRUCT(bind_in);
1668 bind_in.sin6_family = in->sin6_family;
1669 bind_in.sin6_port = in->sin6_port;
1671 bind_in.sin6_addr = *swrap_ipv6();
1672 bind_in.sin6_addr.s6_addr[15] = iface;
1674 memcpy(&si->bindname.sa.in6, &bind_in, blen);
1675 si->bindname.sa_socklen = blen;
1678 break;
1680 #endif
1681 default:
1682 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1683 errno = EADDRNOTAVAIL;
1684 return -1;
1688 if (bcast) *bcast = is_bcast;
1690 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
1691 errno = EINVAL;
1692 return -1;
1695 if (prt == 0) {
1696 /* handle auto-allocation of ephemeral ports */
1697 for (prt = 5001; prt < 10000; prt++) {
1698 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1699 socket_wrapper_dir(), type, iface, prt);
1700 if (stat(un->sun_path, &st) == 0) continue;
1702 set_port(si->family, prt, &si->myname);
1703 set_port(si->family, prt, &si->bindname);
1705 break;
1707 if (prt == 10000) {
1708 errno = ENFILE;
1709 return -1;
1713 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
1714 socket_wrapper_dir(), type, iface, prt);
1715 SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
1716 return 0;
1719 static struct socket_info_fd *find_socket_info_fd(int fd)
1721 struct socket_info_fd *f;
1723 for (f = socket_fds; f; f = f->next) {
1724 if (f->fd == fd) {
1725 return f;
1729 return NULL;
1732 static int find_socket_info_index(int fd)
1734 struct socket_info_fd *fi = find_socket_info_fd(fd);
1736 if (fi == NULL) {
1737 return -1;
1740 return fi->si_index;
1743 static struct socket_info *find_socket_info(int fd)
1745 int idx = find_socket_info_index(fd);
1747 if (idx == -1) {
1748 return NULL;
1751 return &sockets[idx];
1754 #if 0 /* FIXME */
1755 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
1757 struct socket_info_fd *f;
1758 const struct socket_info *last_s = NULL;
1760 /* first catch invalid input */
1761 switch (sa->sa_family) {
1762 case AF_INET:
1763 if (len < sizeof(struct sockaddr_in)) {
1764 return false;
1766 break;
1767 #if HAVE_IPV6
1768 case AF_INET6:
1769 if (len < sizeof(struct sockaddr_in6)) {
1770 return false;
1772 break;
1773 #endif
1774 default:
1775 return false;
1776 break;
1779 for (f = socket_fds; f; f = f->next) {
1780 struct socket_info *s = &sockets[f->si_index];
1782 if (s == last_s) {
1783 continue;
1785 last_s = s;
1787 if (s->myname == NULL) {
1788 continue;
1790 if (s->myname->sa_family != sa->sa_family) {
1791 continue;
1793 switch (s->myname->sa_family) {
1794 case AF_INET: {
1795 struct sockaddr_in *sin1, *sin2;
1797 sin1 = (struct sockaddr_in *)s->myname;
1798 sin2 = (struct sockaddr_in *)sa;
1800 if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
1801 continue;
1803 if (sin1->sin_port != sin2->sin_port) {
1804 continue;
1806 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
1807 continue;
1810 /* found */
1811 return true;
1812 break;
1814 #if HAVE_IPV6
1815 case AF_INET6: {
1816 struct sockaddr_in6 *sin1, *sin2;
1818 sin1 = (struct sockaddr_in6 *)s->myname;
1819 sin2 = (struct sockaddr_in6 *)sa;
1821 if (sin1->sin6_port != sin2->sin6_port) {
1822 continue;
1824 if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
1825 &sin2->sin6_addr))
1827 continue;
1830 /* found */
1831 return true;
1832 break;
1834 #endif
1835 default:
1836 continue;
1837 break;
1842 return false;
1844 #endif
1846 static void swrap_remove_stale(int fd)
1848 struct socket_info_fd *fi = find_socket_info_fd(fd);
1849 struct socket_info *si;
1850 int si_index;
1852 if (fi == NULL) {
1853 return;
1856 si_index = fi->si_index;
1858 SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
1859 SWRAP_DLIST_REMOVE(socket_fds, fi);
1860 free(fi);
1862 si = &sockets[si_index];
1863 si->refcount--;
1865 if (si->refcount > 0) {
1866 return;
1869 if (si->un_addr.sun_path[0] != '\0') {
1870 unlink(si->un_addr.sun_path);
1873 si->next_free = first_free;
1874 first_free = si_index;
1877 static int sockaddr_convert_to_un(struct socket_info *si,
1878 const struct sockaddr *in_addr,
1879 socklen_t in_len,
1880 struct sockaddr_un *out_addr,
1881 int alloc_sock,
1882 int *bcast)
1884 struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
1886 (void) in_len; /* unused */
1888 if (out_addr == NULL) {
1889 return 0;
1892 out->sa_family = AF_UNIX;
1893 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1894 out->sa_len = sizeof(*out_addr);
1895 #endif
1897 switch (in_addr->sa_family) {
1898 case AF_UNSPEC: {
1899 const struct sockaddr_in *sin;
1900 if (si->family != AF_INET) {
1901 break;
1903 if (in_len < sizeof(struct sockaddr_in)) {
1904 break;
1906 sin = (const struct sockaddr_in *)(const void *)in_addr;
1907 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
1908 break;
1912 * Note: in the special case of AF_UNSPEC and INADDR_ANY,
1913 * AF_UNSPEC is mapped to AF_INET and must be treated here.
1916 FALL_THROUGH;
1918 case AF_INET:
1919 #ifdef HAVE_IPV6
1920 case AF_INET6:
1921 #endif
1922 switch (si->type) {
1923 case SOCK_STREAM:
1924 case SOCK_DGRAM:
1925 break;
1926 default:
1927 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1928 errno = ESOCKTNOSUPPORT;
1929 return -1;
1931 if (alloc_sock) {
1932 return convert_in_un_alloc(si, in_addr, out_addr, bcast);
1933 } else {
1934 return convert_in_un_remote(si, in_addr, out_addr, bcast);
1936 default:
1937 break;
1940 errno = EAFNOSUPPORT;
1941 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1942 return -1;
1945 static int sockaddr_convert_from_un(const struct socket_info *si,
1946 const struct sockaddr_un *in_addr,
1947 socklen_t un_addrlen,
1948 int family,
1949 struct sockaddr *out_addr,
1950 socklen_t *out_addrlen)
1952 int ret;
1954 if (out_addr == NULL || out_addrlen == NULL)
1955 return 0;
1957 if (un_addrlen == 0) {
1958 *out_addrlen = 0;
1959 return 0;
1962 switch (family) {
1963 case AF_INET:
1964 #ifdef HAVE_IPV6
1965 case AF_INET6:
1966 #endif
1967 switch (si->type) {
1968 case SOCK_STREAM:
1969 case SOCK_DGRAM:
1970 break;
1971 default:
1972 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
1973 errno = ESOCKTNOSUPPORT;
1974 return -1;
1976 ret = convert_un_in(in_addr, out_addr, out_addrlen);
1977 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1978 out_addr->sa_len = *out_addrlen;
1979 #endif
1980 return ret;
1981 default:
1982 break;
1985 SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
1986 errno = EAFNOSUPPORT;
1987 return -1;
1990 enum swrap_packet_type {
1991 SWRAP_CONNECT_SEND,
1992 SWRAP_CONNECT_UNREACH,
1993 SWRAP_CONNECT_RECV,
1994 SWRAP_CONNECT_ACK,
1995 SWRAP_ACCEPT_SEND,
1996 SWRAP_ACCEPT_RECV,
1997 SWRAP_ACCEPT_ACK,
1998 SWRAP_RECVFROM,
1999 SWRAP_SENDTO,
2000 SWRAP_SENDTO_UNREACH,
2001 SWRAP_PENDING_RST,
2002 SWRAP_RECV,
2003 SWRAP_RECV_RST,
2004 SWRAP_SEND,
2005 SWRAP_SEND_RST,
2006 SWRAP_CLOSE_SEND,
2007 SWRAP_CLOSE_RECV,
2008 SWRAP_CLOSE_ACK,
2011 struct swrap_file_hdr {
2012 uint32_t magic;
2013 uint16_t version_major;
2014 uint16_t version_minor;
2015 int32_t timezone;
2016 uint32_t sigfigs;
2017 uint32_t frame_max_len;
2018 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
2019 uint32_t link_type;
2021 #define SWRAP_FILE_HDR_SIZE 24
2023 struct swrap_packet_frame {
2024 uint32_t seconds;
2025 uint32_t micro_seconds;
2026 uint32_t recorded_length;
2027 uint32_t full_length;
2029 #define SWRAP_PACKET_FRAME_SIZE 16
2031 union swrap_packet_ip {
2032 struct {
2033 uint8_t ver_hdrlen;
2034 uint8_t tos;
2035 uint16_t packet_length;
2036 uint16_t identification;
2037 uint8_t flags;
2038 uint8_t fragment;
2039 uint8_t ttl;
2040 uint8_t protocol;
2041 uint16_t hdr_checksum;
2042 uint32_t src_addr;
2043 uint32_t dest_addr;
2044 } v4;
2045 #define SWRAP_PACKET_IP_V4_SIZE 20
2046 struct {
2047 uint8_t ver_prio;
2048 uint8_t flow_label_high;
2049 uint16_t flow_label_low;
2050 uint16_t payload_length;
2051 uint8_t next_header;
2052 uint8_t hop_limit;
2053 uint8_t src_addr[16];
2054 uint8_t dest_addr[16];
2055 } v6;
2056 #define SWRAP_PACKET_IP_V6_SIZE 40
2058 #define SWRAP_PACKET_IP_SIZE 40
2060 union swrap_packet_payload {
2061 struct {
2062 uint16_t source_port;
2063 uint16_t dest_port;
2064 uint32_t seq_num;
2065 uint32_t ack_num;
2066 uint8_t hdr_length;
2067 uint8_t control;
2068 uint16_t window;
2069 uint16_t checksum;
2070 uint16_t urg;
2071 } tcp;
2072 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
2073 struct {
2074 uint16_t source_port;
2075 uint16_t dest_port;
2076 uint16_t length;
2077 uint16_t checksum;
2078 } udp;
2079 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
2080 struct {
2081 uint8_t type;
2082 uint8_t code;
2083 uint16_t checksum;
2084 uint32_t unused;
2085 } icmp4;
2086 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
2087 struct {
2088 uint8_t type;
2089 uint8_t code;
2090 uint16_t checksum;
2091 uint32_t unused;
2092 } icmp6;
2093 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
2095 #define SWRAP_PACKET_PAYLOAD_SIZE 20
2097 #define SWRAP_PACKET_MIN_ALLOC \
2098 (SWRAP_PACKET_FRAME_SIZE + \
2099 SWRAP_PACKET_IP_SIZE + \
2100 SWRAP_PACKET_PAYLOAD_SIZE)
2102 static const char *swrap_pcap_init_file(void)
2104 static int initialized = 0;
2105 static const char *s = NULL;
2106 static const struct swrap_file_hdr h;
2107 static const struct swrap_packet_frame f;
2108 static const union swrap_packet_ip i;
2109 static const union swrap_packet_payload p;
2111 if (initialized == 1) {
2112 return s;
2114 initialized = 1;
2117 * TODO: don't use the structs use plain buffer offsets
2118 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
2120 * for now make sure we disable PCAP support
2121 * if the struct has alignment!
2123 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
2124 return NULL;
2126 if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
2127 return NULL;
2129 if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
2130 return NULL;
2132 if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
2133 return NULL;
2135 if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
2136 return NULL;
2138 if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
2139 return NULL;
2141 if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
2142 return NULL;
2144 if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
2145 return NULL;
2147 if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
2148 return NULL;
2150 if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
2151 return NULL;
2154 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
2155 if (s == NULL) {
2156 return NULL;
2158 if (strncmp(s, "./", 2) == 0) {
2159 s += 2;
2161 return s;
2164 static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
2165 const struct sockaddr *src,
2166 const struct sockaddr *dest,
2167 int socket_type,
2168 const uint8_t *payload,
2169 size_t payload_len,
2170 unsigned long tcp_seqno,
2171 unsigned long tcp_ack,
2172 unsigned char tcp_ctl,
2173 int unreachable,
2174 size_t *_packet_len)
2176 uint8_t *base;
2177 uint8_t *buf;
2178 struct swrap_packet_frame *frame;
2179 union swrap_packet_ip *ip;
2180 union swrap_packet_payload *pay;
2181 size_t packet_len;
2182 size_t alloc_len;
2183 size_t nonwire_len = sizeof(*frame);
2184 size_t wire_hdr_len = 0;
2185 size_t wire_len = 0;
2186 size_t ip_hdr_len = 0;
2187 size_t icmp_hdr_len = 0;
2188 size_t icmp_truncate_len = 0;
2189 uint8_t protocol = 0, icmp_protocol = 0;
2190 const struct sockaddr_in *src_in = NULL;
2191 const struct sockaddr_in *dest_in = NULL;
2192 #ifdef HAVE_IPV6
2193 const struct sockaddr_in6 *src_in6 = NULL;
2194 const struct sockaddr_in6 *dest_in6 = NULL;
2195 #endif
2196 uint16_t src_port;
2197 uint16_t dest_port;
2199 switch (src->sa_family) {
2200 case AF_INET:
2201 src_in = (const struct sockaddr_in *)(const void *)src;
2202 dest_in = (const struct sockaddr_in *)(const void *)dest;
2203 src_port = src_in->sin_port;
2204 dest_port = dest_in->sin_port;
2205 ip_hdr_len = sizeof(ip->v4);
2206 break;
2207 #ifdef HAVE_IPV6
2208 case AF_INET6:
2209 src_in6 = (const struct sockaddr_in6 *)(const void *)src;
2210 dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
2211 src_port = src_in6->sin6_port;
2212 dest_port = dest_in6->sin6_port;
2213 ip_hdr_len = sizeof(ip->v6);
2214 break;
2215 #endif
2216 default:
2217 return NULL;
2220 switch (socket_type) {
2221 case SOCK_STREAM:
2222 protocol = 0x06; /* TCP */
2223 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
2224 wire_len = wire_hdr_len + payload_len;
2225 break;
2227 case SOCK_DGRAM:
2228 protocol = 0x11; /* UDP */
2229 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
2230 wire_len = wire_hdr_len + payload_len;
2231 break;
2233 default:
2234 return NULL;
2237 if (unreachable) {
2238 icmp_protocol = protocol;
2239 switch (src->sa_family) {
2240 case AF_INET:
2241 protocol = 0x01; /* ICMPv4 */
2242 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
2243 break;
2244 #ifdef HAVE_IPV6
2245 case AF_INET6:
2246 protocol = 0x3A; /* ICMPv6 */
2247 icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
2248 break;
2249 #endif
2251 if (wire_len > 64 ) {
2252 icmp_truncate_len = wire_len - 64;
2254 wire_hdr_len += icmp_hdr_len;
2255 wire_len += icmp_hdr_len;
2258 packet_len = nonwire_len + wire_len;
2259 alloc_len = packet_len;
2260 if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
2261 alloc_len = SWRAP_PACKET_MIN_ALLOC;
2264 base = (uint8_t *)calloc(1, alloc_len);
2265 if (base == NULL) {
2266 return NULL;
2269 buf = base;
2271 frame = (struct swrap_packet_frame *)(void *)buf;
2272 frame->seconds = tval->tv_sec;
2273 frame->micro_seconds = tval->tv_usec;
2274 frame->recorded_length = wire_len - icmp_truncate_len;
2275 frame->full_length = wire_len - icmp_truncate_len;
2276 buf += SWRAP_PACKET_FRAME_SIZE;
2278 ip = (union swrap_packet_ip *)(void *)buf;
2279 switch (src->sa_family) {
2280 case AF_INET:
2281 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2282 ip->v4.tos = 0x00;
2283 ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
2284 ip->v4.identification = htons(0xFFFF);
2285 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2286 ip->v4.fragment = htons(0x0000);
2287 ip->v4.ttl = 0xFF;
2288 ip->v4.protocol = protocol;
2289 ip->v4.hdr_checksum = htons(0x0000);
2290 ip->v4.src_addr = src_in->sin_addr.s_addr;
2291 ip->v4.dest_addr = dest_in->sin_addr.s_addr;
2292 buf += SWRAP_PACKET_IP_V4_SIZE;
2293 break;
2294 #ifdef HAVE_IPV6
2295 case AF_INET6:
2296 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2297 ip->v6.flow_label_high = 0x00;
2298 ip->v6.flow_label_low = 0x0000;
2299 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2300 ip->v6.next_header = protocol;
2301 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
2302 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
2303 buf += SWRAP_PACKET_IP_V6_SIZE;
2304 break;
2305 #endif
2308 if (unreachable) {
2309 pay = (union swrap_packet_payload *)(void *)buf;
2310 switch (src->sa_family) {
2311 case AF_INET:
2312 pay->icmp4.type = 0x03; /* destination unreachable */
2313 pay->icmp4.code = 0x01; /* host unreachable */
2314 pay->icmp4.checksum = htons(0x0000);
2315 pay->icmp4.unused = htonl(0x00000000);
2316 buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
2318 /* set the ip header in the ICMP payload */
2319 ip = (union swrap_packet_ip *)(void *)buf;
2320 ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
2321 ip->v4.tos = 0x00;
2322 ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
2323 ip->v4.identification = htons(0xFFFF);
2324 ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
2325 ip->v4.fragment = htons(0x0000);
2326 ip->v4.ttl = 0xFF;
2327 ip->v4.protocol = icmp_protocol;
2328 ip->v4.hdr_checksum = htons(0x0000);
2329 ip->v4.src_addr = dest_in->sin_addr.s_addr;
2330 ip->v4.dest_addr = src_in->sin_addr.s_addr;
2331 buf += SWRAP_PACKET_IP_V4_SIZE;
2333 src_port = dest_in->sin_port;
2334 dest_port = src_in->sin_port;
2335 break;
2336 #ifdef HAVE_IPV6
2337 case AF_INET6:
2338 pay->icmp6.type = 0x01; /* destination unreachable */
2339 pay->icmp6.code = 0x03; /* address unreachable */
2340 pay->icmp6.checksum = htons(0x0000);
2341 pay->icmp6.unused = htonl(0x00000000);
2342 buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
2344 /* set the ip header in the ICMP payload */
2345 ip = (union swrap_packet_ip *)(void *)buf;
2346 ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
2347 ip->v6.flow_label_high = 0x00;
2348 ip->v6.flow_label_low = 0x0000;
2349 ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
2350 ip->v6.next_header = protocol;
2351 memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
2352 memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
2353 buf += SWRAP_PACKET_IP_V6_SIZE;
2355 src_port = dest_in6->sin6_port;
2356 dest_port = src_in6->sin6_port;
2357 break;
2358 #endif
2362 pay = (union swrap_packet_payload *)(void *)buf;
2364 switch (socket_type) {
2365 case SOCK_STREAM:
2366 pay->tcp.source_port = src_port;
2367 pay->tcp.dest_port = dest_port;
2368 pay->tcp.seq_num = htonl(tcp_seqno);
2369 pay->tcp.ack_num = htonl(tcp_ack);
2370 pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
2371 pay->tcp.control = tcp_ctl;
2372 pay->tcp.window = htons(0x7FFF);
2373 pay->tcp.checksum = htons(0x0000);
2374 pay->tcp.urg = htons(0x0000);
2375 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
2377 break;
2379 case SOCK_DGRAM:
2380 pay->udp.source_port = src_port;
2381 pay->udp.dest_port = dest_port;
2382 pay->udp.length = htons(8 + payload_len);
2383 pay->udp.checksum = htons(0x0000);
2384 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
2386 break;
2389 if (payload && payload_len > 0) {
2390 memcpy(buf, payload, payload_len);
2393 *_packet_len = packet_len - icmp_truncate_len;
2394 return base;
2397 static int swrap_pcap_get_fd(const char *fname)
2399 static int fd = -1;
2401 if (fd != -1) {
2402 return fd;
2405 fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
2406 if (fd != -1) {
2407 struct swrap_file_hdr file_hdr;
2408 file_hdr.magic = 0xA1B2C3D4;
2409 file_hdr.version_major = 0x0002;
2410 file_hdr.version_minor = 0x0004;
2411 file_hdr.timezone = 0x00000000;
2412 file_hdr.sigfigs = 0x00000000;
2413 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
2414 file_hdr.link_type = 0x0065; /* 101 RAW IP */
2416 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
2417 close(fd);
2418 fd = -1;
2420 return fd;
2423 fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
2425 return fd;
2428 static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
2429 const struct sockaddr *addr,
2430 enum swrap_packet_type type,
2431 const void *buf, size_t len,
2432 size_t *packet_len)
2434 const struct sockaddr *src_addr;
2435 const struct sockaddr *dest_addr;
2436 unsigned long tcp_seqno = 0;
2437 unsigned long tcp_ack = 0;
2438 unsigned char tcp_ctl = 0;
2439 int unreachable = 0;
2441 struct timeval tv;
2443 switch (si->family) {
2444 case AF_INET:
2445 break;
2446 #ifdef HAVE_IPV6
2447 case AF_INET6:
2448 break;
2449 #endif
2450 default:
2451 return NULL;
2454 switch (type) {
2455 case SWRAP_CONNECT_SEND:
2456 if (si->type != SOCK_STREAM) {
2457 return NULL;
2460 src_addr = &si->myname.sa.s;
2461 dest_addr = addr;
2463 tcp_seqno = si->io.pck_snd;
2464 tcp_ack = si->io.pck_rcv;
2465 tcp_ctl = 0x02; /* SYN */
2467 si->io.pck_snd += 1;
2469 break;
2471 case SWRAP_CONNECT_RECV:
2472 if (si->type != SOCK_STREAM) {
2473 return NULL;
2476 dest_addr = &si->myname.sa.s;
2477 src_addr = addr;
2479 tcp_seqno = si->io.pck_rcv;
2480 tcp_ack = si->io.pck_snd;
2481 tcp_ctl = 0x12; /** SYN,ACK */
2483 si->io.pck_rcv += 1;
2485 break;
2487 case SWRAP_CONNECT_UNREACH:
2488 if (si->type != SOCK_STREAM) {
2489 return NULL;
2492 dest_addr = &si->myname.sa.s;
2493 src_addr = addr;
2495 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
2496 tcp_seqno = si->io.pck_snd - 1;
2497 tcp_ack = si->io.pck_rcv;
2498 tcp_ctl = 0x02; /* SYN */
2499 unreachable = 1;
2501 break;
2503 case SWRAP_CONNECT_ACK:
2504 if (si->type != SOCK_STREAM) {
2505 return NULL;
2508 src_addr = &si->myname.sa.s;
2509 dest_addr = addr;
2511 tcp_seqno = si->io.pck_snd;
2512 tcp_ack = si->io.pck_rcv;
2513 tcp_ctl = 0x10; /* ACK */
2515 break;
2517 case SWRAP_ACCEPT_SEND:
2518 if (si->type != SOCK_STREAM) {
2519 return NULL;
2522 dest_addr = &si->myname.sa.s;
2523 src_addr = addr;
2525 tcp_seqno = si->io.pck_rcv;
2526 tcp_ack = si->io.pck_snd;
2527 tcp_ctl = 0x02; /* SYN */
2529 si->io.pck_rcv += 1;
2531 break;
2533 case SWRAP_ACCEPT_RECV:
2534 if (si->type != SOCK_STREAM) {
2535 return NULL;
2538 src_addr = &si->myname.sa.s;
2539 dest_addr = addr;
2541 tcp_seqno = si->io.pck_snd;
2542 tcp_ack = si->io.pck_rcv;
2543 tcp_ctl = 0x12; /* SYN,ACK */
2545 si->io.pck_snd += 1;
2547 break;
2549 case SWRAP_ACCEPT_ACK:
2550 if (si->type != SOCK_STREAM) {
2551 return NULL;
2554 dest_addr = &si->myname.sa.s;
2555 src_addr = addr;
2557 tcp_seqno = si->io.pck_rcv;
2558 tcp_ack = si->io.pck_snd;
2559 tcp_ctl = 0x10; /* ACK */
2561 break;
2563 case SWRAP_SEND:
2564 src_addr = &si->myname.sa.s;
2565 dest_addr = &si->peername.sa.s;
2567 tcp_seqno = si->io.pck_snd;
2568 tcp_ack = si->io.pck_rcv;
2569 tcp_ctl = 0x18; /* PSH,ACK */
2571 si->io.pck_snd += len;
2573 break;
2575 case SWRAP_SEND_RST:
2576 dest_addr = &si->myname.sa.s;
2577 src_addr = &si->peername.sa.s;
2579 if (si->type == SOCK_DGRAM) {
2580 return swrap_pcap_marshall_packet(si,
2581 &si->peername.sa.s,
2582 SWRAP_SENDTO_UNREACH,
2583 buf,
2584 len,
2585 packet_len);
2588 tcp_seqno = si->io.pck_rcv;
2589 tcp_ack = si->io.pck_snd;
2590 tcp_ctl = 0x14; /** RST,ACK */
2592 break;
2594 case SWRAP_PENDING_RST:
2595 dest_addr = &si->myname.sa.s;
2596 src_addr = &si->peername.sa.s;
2598 if (si->type == SOCK_DGRAM) {
2599 return NULL;
2602 tcp_seqno = si->io.pck_rcv;
2603 tcp_ack = si->io.pck_snd;
2604 tcp_ctl = 0x14; /* RST,ACK */
2606 break;
2608 case SWRAP_RECV:
2609 dest_addr = &si->myname.sa.s;
2610 src_addr = &si->peername.sa.s;
2612 tcp_seqno = si->io.pck_rcv;
2613 tcp_ack = si->io.pck_snd;
2614 tcp_ctl = 0x18; /* PSH,ACK */
2616 si->io.pck_rcv += len;
2618 break;
2620 case SWRAP_RECV_RST:
2621 dest_addr = &si->myname.sa.s;
2622 src_addr = &si->peername.sa.s;
2624 if (si->type == SOCK_DGRAM) {
2625 return NULL;
2628 tcp_seqno = si->io.pck_rcv;
2629 tcp_ack = si->io.pck_snd;
2630 tcp_ctl = 0x14; /* RST,ACK */
2632 break;
2634 case SWRAP_SENDTO:
2635 src_addr = &si->myname.sa.s;
2636 dest_addr = addr;
2638 si->io.pck_snd += len;
2640 break;
2642 case SWRAP_SENDTO_UNREACH:
2643 dest_addr = &si->myname.sa.s;
2644 src_addr = addr;
2646 unreachable = 1;
2648 break;
2650 case SWRAP_RECVFROM:
2651 dest_addr = &si->myname.sa.s;
2652 src_addr = addr;
2654 si->io.pck_rcv += len;
2656 break;
2658 case SWRAP_CLOSE_SEND:
2659 if (si->type != SOCK_STREAM) {
2660 return NULL;
2663 src_addr = &si->myname.sa.s;
2664 dest_addr = &si->peername.sa.s;
2666 tcp_seqno = si->io.pck_snd;
2667 tcp_ack = si->io.pck_rcv;
2668 tcp_ctl = 0x11; /* FIN, ACK */
2670 si->io.pck_snd += 1;
2672 break;
2674 case SWRAP_CLOSE_RECV:
2675 if (si->type != SOCK_STREAM) {
2676 return NULL;
2679 dest_addr = &si->myname.sa.s;
2680 src_addr = &si->peername.sa.s;
2682 tcp_seqno = si->io.pck_rcv;
2683 tcp_ack = si->io.pck_snd;
2684 tcp_ctl = 0x11; /* FIN,ACK */
2686 si->io.pck_rcv += 1;
2688 break;
2690 case SWRAP_CLOSE_ACK:
2691 if (si->type != SOCK_STREAM) {
2692 return NULL;
2695 src_addr = &si->myname.sa.s;
2696 dest_addr = &si->peername.sa.s;
2698 tcp_seqno = si->io.pck_snd;
2699 tcp_ack = si->io.pck_rcv;
2700 tcp_ctl = 0x10; /* ACK */
2702 break;
2703 default:
2704 return NULL;
2707 swrapGetTimeOfDay(&tv);
2709 return swrap_pcap_packet_init(&tv,
2710 src_addr,
2711 dest_addr,
2712 si->type,
2713 (const uint8_t *)buf,
2714 len,
2715 tcp_seqno,
2716 tcp_ack,
2717 tcp_ctl,
2718 unreachable,
2719 packet_len);
2722 static void swrap_pcap_dump_packet(struct socket_info *si,
2723 const struct sockaddr *addr,
2724 enum swrap_packet_type type,
2725 const void *buf, size_t len)
2727 const char *file_name;
2728 uint8_t *packet;
2729 size_t packet_len = 0;
2730 int fd;
2732 file_name = swrap_pcap_init_file();
2733 if (!file_name) {
2734 return;
2737 packet = swrap_pcap_marshall_packet(si,
2738 addr,
2739 type,
2740 buf,
2741 len,
2742 &packet_len);
2743 if (packet == NULL) {
2744 return;
2747 fd = swrap_pcap_get_fd(file_name);
2748 if (fd != -1) {
2749 if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
2750 free(packet);
2751 return;
2755 free(packet);
2758 /****************************************************************************
2759 * SIGNALFD
2760 ***************************************************************************/
2762 #ifdef HAVE_SIGNALFD
2763 static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
2765 int rc;
2767 rc = libc_signalfd(fd, mask, flags);
2768 if (rc != -1) {
2769 swrap_remove_stale(fd);
2772 return rc;
2775 int signalfd(int fd, const sigset_t *mask, int flags)
2777 return swrap_signalfd(fd, mask, flags);
2779 #endif
2781 /****************************************************************************
2782 * SOCKET
2783 ***************************************************************************/
2785 static int swrap_socket(int family, int type, int protocol)
2787 struct socket_info *si;
2788 struct socket_info_fd *fi;
2789 int fd;
2790 int idx;
2791 int real_type = type;
2794 * Remove possible addition flags passed to socket() so
2795 * do not fail checking the type.
2796 * See https://lwn.net/Articles/281965/
2798 #ifdef SOCK_CLOEXEC
2799 real_type &= ~SOCK_CLOEXEC;
2800 #endif
2801 #ifdef SOCK_NONBLOCK
2802 real_type &= ~SOCK_NONBLOCK;
2803 #endif
2805 if (!socket_wrapper_enabled()) {
2806 return libc_socket(family, type, protocol);
2809 switch (family) {
2810 case AF_INET:
2811 #ifdef HAVE_IPV6
2812 case AF_INET6:
2813 #endif
2814 break;
2815 #ifdef AF_NETLINK
2816 case AF_NETLINK:
2817 #endif /* AF_NETLINK */
2818 #ifdef AF_PACKET
2819 case AF_PACKET:
2820 #endif /* AF_PACKET */
2821 case AF_UNIX:
2822 return libc_socket(family, type, protocol);
2823 default:
2824 errno = EAFNOSUPPORT;
2825 return -1;
2828 switch (real_type) {
2829 case SOCK_STREAM:
2830 break;
2831 case SOCK_DGRAM:
2832 break;
2833 default:
2834 errno = EPROTONOSUPPORT;
2835 return -1;
2838 switch (protocol) {
2839 case 0:
2840 break;
2841 case 6:
2842 if (real_type == SOCK_STREAM) {
2843 break;
2845 FALL_THROUGH;
2846 case 17:
2847 if (real_type == SOCK_DGRAM) {
2848 break;
2850 FALL_THROUGH;
2851 default:
2852 errno = EPROTONOSUPPORT;
2853 return -1;
2857 * We must call libc_socket with type, from the caller, not the version
2858 * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
2860 fd = libc_socket(AF_UNIX, type, 0);
2862 if (fd == -1) {
2863 return -1;
2866 /* Check if we have a stale fd and remove it */
2867 swrap_remove_stale(fd);
2869 idx = socket_wrapper_first_free_index();
2870 if (idx == -1) {
2871 errno = ENOMEM;
2872 return -1;
2875 si = &sockets[idx];
2877 si->family = family;
2879 /* however, the rest of the socket_wrapper code expects just
2880 * the type, not the flags */
2881 si->type = real_type;
2882 si->protocol = protocol;
2885 * Setup myname so getsockname() can succeed to find out the socket
2886 * type.
2888 switch(si->family) {
2889 case AF_INET: {
2890 struct sockaddr_in sin = {
2891 .sin_family = AF_INET,
2894 si->myname.sa_socklen = sizeof(struct sockaddr_in);
2895 memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
2896 break;
2898 case AF_INET6: {
2899 struct sockaddr_in6 sin6 = {
2900 .sin6_family = AF_INET6,
2903 si->myname.sa_socklen = sizeof(struct sockaddr_in6);
2904 memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
2905 break;
2907 default:
2908 errno = EINVAL;
2909 return -1;
2912 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
2913 if (fi == NULL) {
2914 errno = ENOMEM;
2915 return -1;
2918 si->refcount = 1;
2919 first_free = si->next_free;
2920 si->next_free = 0;
2922 fi->fd = fd;
2923 fi->si_index = idx;
2925 SWRAP_DLIST_ADD(socket_fds, fi);
2927 SWRAP_LOG(SWRAP_LOG_TRACE,
2928 "Created %s socket for protocol %s",
2929 si->family == AF_INET ? "IPv4" : "IPv6",
2930 si->type == SOCK_DGRAM ? "UDP" : "TCP");
2932 return fd;
2935 int socket(int family, int type, int protocol)
2937 return swrap_socket(family, type, protocol);
2940 /****************************************************************************
2941 * SOCKETPAIR
2942 ***************************************************************************/
2944 static int swrap_socketpair(int family, int type, int protocol, int sv[2])
2946 int rc;
2948 rc = libc_socketpair(family, type, protocol, sv);
2949 if (rc != -1) {
2950 swrap_remove_stale(sv[0]);
2951 swrap_remove_stale(sv[1]);
2954 return rc;
2957 int socketpair(int family, int type, int protocol, int sv[2])
2959 return swrap_socketpair(family, type, protocol, sv);
2962 /****************************************************************************
2963 * SOCKETPAIR
2964 ***************************************************************************/
2966 #ifdef HAVE_TIMERFD_CREATE
2967 static int swrap_timerfd_create(int clockid, int flags)
2969 int fd;
2971 fd = libc_timerfd_create(clockid, flags);
2972 if (fd != -1) {
2973 swrap_remove_stale(fd);
2976 return fd;
2979 int timerfd_create(int clockid, int flags)
2981 return swrap_timerfd_create(clockid, flags);
2983 #endif
2985 /****************************************************************************
2986 * PIPE
2987 ***************************************************************************/
2989 static int swrap_pipe(int pipefd[2])
2991 int rc;
2993 rc = libc_pipe(pipefd);
2994 if (rc != -1) {
2995 swrap_remove_stale(pipefd[0]);
2996 swrap_remove_stale(pipefd[1]);
2999 return rc;
3002 int pipe(int pipefd[2])
3004 return swrap_pipe(pipefd);
3007 /****************************************************************************
3008 * ACCEPT
3009 ***************************************************************************/
3011 static int swrap_accept(int s,
3012 struct sockaddr *addr,
3013 socklen_t *addrlen,
3014 int flags)
3016 struct socket_info *parent_si, *child_si;
3017 struct socket_info_fd *child_fi;
3018 int fd;
3019 int idx;
3020 struct swrap_address un_addr = {
3021 .sa_socklen = sizeof(struct sockaddr_un),
3023 struct swrap_address un_my_addr = {
3024 .sa_socklen = sizeof(struct sockaddr_un),
3026 struct swrap_address in_addr = {
3027 .sa_socklen = sizeof(struct sockaddr_storage),
3029 struct swrap_address in_my_addr = {
3030 .sa_socklen = sizeof(struct sockaddr_storage),
3032 int ret;
3034 parent_si = find_socket_info(s);
3035 if (!parent_si) {
3036 #ifdef HAVE_ACCEPT4
3037 return libc_accept4(s, addr, addrlen, flags);
3038 #else
3039 UNUSED(flags);
3040 return libc_accept(s, addr, addrlen);
3041 #endif
3045 * assume out sockaddr have the same size as the in parent
3046 * socket family
3048 in_addr.sa_socklen = socket_length(parent_si->family);
3049 if (in_addr.sa_socklen <= 0) {
3050 errno = EINVAL;
3051 return -1;
3054 #ifdef HAVE_ACCEPT4
3055 ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
3056 #else
3057 UNUSED(flags);
3058 ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
3059 #endif
3060 if (ret == -1) {
3061 if (errno == ENOTSOCK) {
3062 /* Remove stale fds */
3063 swrap_remove_stale(s);
3065 return ret;
3068 fd = ret;
3070 ret = sockaddr_convert_from_un(parent_si,
3071 &un_addr.sa.un,
3072 un_addr.sa_socklen,
3073 parent_si->family,
3074 &in_addr.sa.s,
3075 &in_addr.sa_socklen);
3076 if (ret == -1) {
3077 close(fd);
3078 return ret;
3081 idx = socket_wrapper_first_free_index();
3082 if (idx == -1) {
3083 errno = ENOMEM;
3084 return -1;
3087 child_si = &sockets[idx];
3089 child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
3090 if (child_fi == NULL) {
3091 close(fd);
3092 errno = ENOMEM;
3093 return -1;
3096 child_fi->fd = fd;
3098 child_si->family = parent_si->family;
3099 child_si->type = parent_si->type;
3100 child_si->protocol = parent_si->protocol;
3101 child_si->bound = 1;
3102 child_si->is_server = 1;
3103 child_si->connected = 1;
3105 child_si->peername = (struct swrap_address) {
3106 .sa_socklen = in_addr.sa_socklen,
3108 memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
3110 if (addr != NULL && addrlen != NULL) {
3111 size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
3112 if (copy_len > 0) {
3113 memcpy(addr, &in_addr.sa.ss, copy_len);
3115 *addrlen = in_addr.sa_socklen;
3118 ret = libc_getsockname(fd,
3119 &un_my_addr.sa.s,
3120 &un_my_addr.sa_socklen);
3121 if (ret == -1) {
3122 free(child_fi);
3123 close(fd);
3124 return ret;
3127 ret = sockaddr_convert_from_un(child_si,
3128 &un_my_addr.sa.un,
3129 un_my_addr.sa_socklen,
3130 child_si->family,
3131 &in_my_addr.sa.s,
3132 &in_my_addr.sa_socklen);
3133 if (ret == -1) {
3134 free(child_fi);
3135 close(fd);
3136 return ret;
3139 SWRAP_LOG(SWRAP_LOG_TRACE,
3140 "accept() path=%s, fd=%d",
3141 un_my_addr.sa.un.sun_path, s);
3143 child_si->myname = (struct swrap_address) {
3144 .sa_socklen = in_my_addr.sa_socklen,
3146 memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
3148 child_si->refcount = 1;
3149 first_free = child_si->next_free;
3150 child_si->next_free = 0;
3152 child_fi->si_index = idx;
3154 SWRAP_DLIST_ADD(socket_fds, child_fi);
3156 if (addr != NULL) {
3157 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
3158 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
3159 swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
3162 return fd;
3165 #ifdef HAVE_ACCEPT4
3166 int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
3168 return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
3170 #endif
3172 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3173 int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
3174 #else
3175 int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
3176 #endif
3178 return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
3181 static int autobind_start_init;
3182 static int autobind_start;
3184 /* using sendto() or connect() on an unbound socket would give the
3185 recipient no way to reply, as unlike UDP and TCP, a unix domain
3186 socket can't auto-assign ephemeral port numbers, so we need to
3187 assign it here.
3188 Note: this might change the family from ipv6 to ipv4
3190 static int swrap_auto_bind(int fd, struct socket_info *si, int family)
3192 struct swrap_address un_addr = {
3193 .sa_socklen = sizeof(struct sockaddr_un),
3195 int i;
3196 char type;
3197 int ret;
3198 int port;
3199 struct stat st;
3201 if (autobind_start_init != 1) {
3202 autobind_start_init = 1;
3203 autobind_start = getpid();
3204 autobind_start %= 50000;
3205 autobind_start += 10000;
3208 un_addr.sa.un.sun_family = AF_UNIX;
3210 switch (family) {
3211 case AF_INET: {
3212 struct sockaddr_in in;
3214 switch (si->type) {
3215 case SOCK_STREAM:
3216 type = SOCKET_TYPE_CHAR_TCP;
3217 break;
3218 case SOCK_DGRAM:
3219 type = SOCKET_TYPE_CHAR_UDP;
3220 break;
3221 default:
3222 errno = ESOCKTNOSUPPORT;
3223 ret = -1;
3224 goto done;
3227 memset(&in, 0, sizeof(in));
3228 in.sin_family = AF_INET;
3229 in.sin_addr.s_addr = htonl(127<<24 |
3230 socket_wrapper_default_iface());
3232 si->myname = (struct swrap_address) {
3233 .sa_socklen = sizeof(in),
3235 memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
3236 break;
3238 #ifdef HAVE_IPV6
3239 case AF_INET6: {
3240 struct sockaddr_in6 in6;
3242 if (si->family != family) {
3243 errno = ENETUNREACH;
3244 ret = -1;
3245 goto done;
3248 switch (si->type) {
3249 case SOCK_STREAM:
3250 type = SOCKET_TYPE_CHAR_TCP_V6;
3251 break;
3252 case SOCK_DGRAM:
3253 type = SOCKET_TYPE_CHAR_UDP_V6;
3254 break;
3255 default:
3256 errno = ESOCKTNOSUPPORT;
3257 ret = -1;
3258 goto done;
3261 memset(&in6, 0, sizeof(in6));
3262 in6.sin6_family = AF_INET6;
3263 in6.sin6_addr = *swrap_ipv6();
3264 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
3266 si->myname = (struct swrap_address) {
3267 .sa_socklen = sizeof(in6),
3269 memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
3270 break;
3272 #endif
3273 default:
3274 errno = ESOCKTNOSUPPORT;
3275 ret = -1;
3276 goto done;
3279 if (autobind_start > 60000) {
3280 autobind_start = 10000;
3283 for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
3284 port = autobind_start + i;
3285 snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
3286 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
3287 type, socket_wrapper_default_iface(), port);
3288 if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
3290 ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
3291 if (ret == -1) {
3292 goto done;
3295 si->un_addr = un_addr.sa.un;
3297 si->bound = 1;
3298 autobind_start = port + 1;
3299 break;
3301 if (i == SOCKET_MAX_SOCKETS) {
3302 SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
3303 "interface "SOCKET_FORMAT,
3304 SOCKET_MAX_SOCKETS,
3305 type,
3306 socket_wrapper_default_iface(),
3308 errno = ENFILE;
3309 ret = -1;
3310 goto done;
3313 si->family = family;
3314 set_port(si->family, port, &si->myname);
3316 ret = 0;
3318 done:
3319 return ret;
3322 /****************************************************************************
3323 * CONNECT
3324 ***************************************************************************/
3326 static int swrap_connect(int s, const struct sockaddr *serv_addr,
3327 socklen_t addrlen)
3329 int ret;
3330 struct swrap_address un_addr = {
3331 .sa_socklen = sizeof(struct sockaddr_un),
3333 struct socket_info *si = find_socket_info(s);
3334 int bcast = 0;
3336 if (!si) {
3337 return libc_connect(s, serv_addr, addrlen);
3340 if (si->bound == 0) {
3341 ret = swrap_auto_bind(s, si, serv_addr->sa_family);
3342 if (ret == -1) {
3343 goto done;
3347 if (si->family != serv_addr->sa_family) {
3348 errno = EINVAL;
3349 ret = -1;
3350 goto done;
3353 ret = sockaddr_convert_to_un(si, serv_addr,
3354 addrlen, &un_addr.sa.un, 0, &bcast);
3355 if (ret == -1) {
3356 goto done;
3359 if (bcast) {
3360 errno = ENETUNREACH;
3361 ret = -1;
3362 goto done;
3365 if (si->type == SOCK_DGRAM) {
3366 si->defer_connect = 1;
3367 ret = 0;
3368 } else {
3369 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
3371 ret = libc_connect(s,
3372 &un_addr.sa.s,
3373 un_addr.sa_socklen);
3376 SWRAP_LOG(SWRAP_LOG_TRACE,
3377 "connect() path=%s, fd=%d",
3378 un_addr.sa.un.sun_path, s);
3381 /* to give better errors */
3382 if (ret == -1 && errno == ENOENT) {
3383 errno = EHOSTUNREACH;
3386 if (ret == 0) {
3387 si->peername = (struct swrap_address) {
3388 .sa_socklen = addrlen,
3391 memcpy(&si->peername.sa.ss, serv_addr, addrlen);
3392 si->connected = 1;
3395 * When we connect() on a socket than we have to bind the
3396 * outgoing connection on the interface we use for the
3397 * transport. We already bound it on the right interface
3398 * but here we have to update the name so getsockname()
3399 * returns correct information.
3401 if (si->bindname.sa_socklen > 0) {
3402 si->myname = (struct swrap_address) {
3403 .sa_socklen = si->bindname.sa_socklen,
3406 memcpy(&si->myname.sa.ss,
3407 &si->bindname.sa.ss,
3408 si->bindname.sa_socklen);
3410 /* Cleanup bindname */
3411 si->bindname = (struct swrap_address) {
3412 .sa_socklen = 0,
3416 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
3417 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
3418 } else {
3419 swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
3422 done:
3423 return ret;
3426 int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
3428 return swrap_connect(s, serv_addr, addrlen);
3431 /****************************************************************************
3432 * BIND
3433 ***************************************************************************/
3435 static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3437 int ret;
3438 struct swrap_address un_addr = {
3439 .sa_socklen = sizeof(struct sockaddr_un),
3441 struct socket_info *si = find_socket_info(s);
3442 int bind_error = 0;
3443 #if 0 /* FIXME */
3444 bool in_use;
3445 #endif
3447 if (!si) {
3448 return libc_bind(s, myaddr, addrlen);
3451 switch (si->family) {
3452 case AF_INET: {
3453 const struct sockaddr_in *sin;
3454 if (addrlen < sizeof(struct sockaddr_in)) {
3455 bind_error = EINVAL;
3456 break;
3459 sin = (const struct sockaddr_in *)(const void *)myaddr;
3461 if (sin->sin_family != AF_INET) {
3462 bind_error = EAFNOSUPPORT;
3465 /* special case for AF_UNSPEC */
3466 if (sin->sin_family == AF_UNSPEC &&
3467 (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
3469 bind_error = 0;
3472 break;
3474 #ifdef HAVE_IPV6
3475 case AF_INET6: {
3476 const struct sockaddr_in6 *sin6;
3477 if (addrlen < sizeof(struct sockaddr_in6)) {
3478 bind_error = EINVAL;
3479 break;
3482 sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
3484 if (sin6->sin6_family != AF_INET6) {
3485 bind_error = EAFNOSUPPORT;
3488 break;
3490 #endif
3491 default:
3492 bind_error = EINVAL;
3493 break;
3496 if (bind_error != 0) {
3497 errno = bind_error;
3498 return -1;
3501 #if 0 /* FIXME */
3502 in_use = check_addr_port_in_use(myaddr, addrlen);
3503 if (in_use) {
3504 errno = EADDRINUSE;
3505 return -1;
3507 #endif
3509 si->myname.sa_socklen = addrlen;
3510 memcpy(&si->myname.sa.ss, myaddr, addrlen);
3512 ret = sockaddr_convert_to_un(si,
3513 myaddr,
3514 addrlen,
3515 &un_addr.sa.un,
3517 &si->bcast);
3518 if (ret == -1) {
3519 return -1;
3522 unlink(un_addr.sa.un.sun_path);
3524 ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
3526 SWRAP_LOG(SWRAP_LOG_TRACE,
3527 "bind() path=%s, fd=%d",
3528 un_addr.sa.un.sun_path, s);
3530 if (ret == 0) {
3531 si->bound = 1;
3534 return ret;
3537 int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
3539 return swrap_bind(s, myaddr, addrlen);
3542 /****************************************************************************
3543 * BINDRESVPORT
3544 ***************************************************************************/
3546 #ifdef HAVE_BINDRESVPORT
3547 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
3549 static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
3551 struct swrap_address myaddr = {
3552 .sa_socklen = sizeof(struct sockaddr_storage),
3554 socklen_t salen;
3555 static uint16_t port;
3556 uint16_t i;
3557 int rc = -1;
3558 int af;
3560 #define SWRAP_STARTPORT 600
3561 #define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
3562 #define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
3564 if (port == 0) {
3565 port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
3568 if (sa == NULL) {
3569 salen = myaddr.sa_socklen;
3570 sa = &myaddr.sa.s;
3572 rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
3573 if (rc < 0) {
3574 return -1;
3577 af = sa->sa_family;
3578 memset(&myaddr.sa.ss, 0, salen);
3579 } else {
3580 af = sa->sa_family;
3583 for (i = 0; i < SWRAP_NPORTS; i++, port++) {
3584 switch(af) {
3585 case AF_INET: {
3586 struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
3588 salen = sizeof(struct sockaddr_in);
3589 sinp->sin_port = htons(port);
3590 break;
3592 case AF_INET6: {
3593 struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
3595 salen = sizeof(struct sockaddr_in6);
3596 sin6p->sin6_port = htons(port);
3597 break;
3599 default:
3600 errno = EAFNOSUPPORT;
3601 return -1;
3603 sa->sa_family = af;
3605 if (port > SWRAP_ENDPORT) {
3606 port = SWRAP_STARTPORT;
3609 rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
3610 if (rc == 0 || errno != EADDRINUSE) {
3611 break;
3615 return rc;
3618 int bindresvport(int sockfd, struct sockaddr_in *sinp)
3620 return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
3622 #endif
3624 /****************************************************************************
3625 * LISTEN
3626 ***************************************************************************/
3628 static int swrap_listen(int s, int backlog)
3630 int ret;
3631 struct socket_info *si = find_socket_info(s);
3633 if (!si) {
3634 return libc_listen(s, backlog);
3637 if (si->bound == 0) {
3638 ret = swrap_auto_bind(s, si, si->family);
3639 if (ret == -1) {
3640 errno = EADDRINUSE;
3641 return ret;
3645 ret = libc_listen(s, backlog);
3647 return ret;
3650 int listen(int s, int backlog)
3652 return swrap_listen(s, backlog);
3655 /****************************************************************************
3656 * FOPEN
3657 ***************************************************************************/
3659 static FILE *swrap_fopen(const char *name, const char *mode)
3661 FILE *fp;
3663 fp = libc_fopen(name, mode);
3664 if (fp != NULL) {
3665 int fd = fileno(fp);
3667 swrap_remove_stale(fd);
3670 return fp;
3673 FILE *fopen(const char *name, const char *mode)
3675 return swrap_fopen(name, mode);
3678 /****************************************************************************
3679 * FOPEN64
3680 ***************************************************************************/
3682 #ifdef HAVE_FOPEN64
3683 static FILE *swrap_fopen64(const char *name, const char *mode)
3685 FILE *fp;
3687 fp = libc_fopen64(name, mode);
3688 if (fp != NULL) {
3689 int fd = fileno(fp);
3691 swrap_remove_stale(fd);
3694 return fp;
3697 FILE *fopen64(const char *name, const char *mode)
3699 return swrap_fopen64(name, mode);
3701 #endif /* HAVE_FOPEN64 */
3703 /****************************************************************************
3704 * OPEN
3705 ***************************************************************************/
3707 static int swrap_vopen(const char *pathname, int flags, va_list ap)
3709 int ret;
3711 ret = libc_vopen(pathname, flags, ap);
3712 if (ret != -1) {
3714 * There are methods for closing descriptors (libc-internal code
3715 * paths, direct syscalls) which close descriptors in ways that
3716 * we can't intercept, so try to recover when we notice that
3717 * that's happened
3719 swrap_remove_stale(ret);
3721 return ret;
3724 int open(const char *pathname, int flags, ...)
3726 va_list ap;
3727 int fd;
3729 va_start(ap, flags);
3730 fd = swrap_vopen(pathname, flags, ap);
3731 va_end(ap);
3733 return fd;
3736 /****************************************************************************
3737 * OPEN64
3738 ***************************************************************************/
3740 #ifdef HAVE_OPEN64
3741 static int swrap_vopen64(const char *pathname, int flags, va_list ap)
3743 int ret;
3745 ret = libc_vopen64(pathname, flags, ap);
3746 if (ret != -1) {
3748 * There are methods for closing descriptors (libc-internal code
3749 * paths, direct syscalls) which close descriptors in ways that
3750 * we can't intercept, so try to recover when we notice that
3751 * that's happened
3753 swrap_remove_stale(ret);
3755 return ret;
3758 int open64(const char *pathname, int flags, ...)
3760 va_list ap;
3761 int fd;
3763 va_start(ap, flags);
3764 fd = swrap_vopen64(pathname, flags, ap);
3765 va_end(ap);
3767 return fd;
3769 #endif /* HAVE_OPEN64 */
3771 /****************************************************************************
3772 * OPENAT
3773 ***************************************************************************/
3775 static int swrap_vopenat(int dirfd, const char *path, int flags, va_list ap)
3777 int ret;
3779 ret = libc_vopenat(dirfd, path, flags, ap);
3780 if (ret != -1) {
3782 * There are methods for closing descriptors (libc-internal code
3783 * paths, direct syscalls) which close descriptors in ways that
3784 * we can't intercept, so try to recover when we notice that
3785 * that's happened
3787 swrap_remove_stale(ret);
3790 return ret;
3793 int openat(int dirfd, const char *path, int flags, ...)
3795 va_list ap;
3796 int fd;
3798 va_start(ap, flags);
3799 fd = swrap_vopenat(dirfd, path, flags, ap);
3800 va_end(ap);
3802 return fd;
3805 /****************************************************************************
3806 * GETPEERNAME
3807 ***************************************************************************/
3809 static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3811 struct socket_info *si = find_socket_info(s);
3812 socklen_t len;
3814 if (!si) {
3815 return libc_getpeername(s, name, addrlen);
3818 if (si->peername.sa_socklen == 0)
3820 errno = ENOTCONN;
3821 return -1;
3824 len = MIN(*addrlen, si->peername.sa_socklen);
3825 if (len == 0) {
3826 return 0;
3829 memcpy(name, &si->peername.sa.ss, len);
3830 *addrlen = si->peername.sa_socklen;
3832 return 0;
3835 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3836 int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
3837 #else
3838 int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
3839 #endif
3841 return swrap_getpeername(s, name, (socklen_t *)addrlen);
3844 /****************************************************************************
3845 * GETSOCKNAME
3846 ***************************************************************************/
3848 static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3850 struct socket_info *si = find_socket_info(s);
3851 socklen_t len;
3853 if (!si) {
3854 return libc_getsockname(s, name, addrlen);
3857 len = MIN(*addrlen, si->myname.sa_socklen);
3858 if (len == 0) {
3859 return 0;
3862 memcpy(name, &si->myname.sa.ss, len);
3863 *addrlen = si->myname.sa_socklen;
3865 return 0;
3868 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3869 int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
3870 #else
3871 int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
3872 #endif
3874 return swrap_getsockname(s, name, (socklen_t *)addrlen);
3877 /****************************************************************************
3878 * GETSOCKOPT
3879 ***************************************************************************/
3881 #ifndef SO_PROTOCOL
3882 # ifdef SO_PROTOTYPE /* The Solaris name */
3883 # define SO_PROTOCOL SO_PROTOTYPE
3884 # endif /* SO_PROTOTYPE */
3885 #endif /* SO_PROTOCOL */
3887 static int swrap_getsockopt(int s, int level, int optname,
3888 void *optval, socklen_t *optlen)
3890 struct socket_info *si = find_socket_info(s);
3891 int ret;
3893 if (!si) {
3894 return libc_getsockopt(s,
3895 level,
3896 optname,
3897 optval,
3898 optlen);
3901 if (level == SOL_SOCKET) {
3902 switch (optname) {
3903 #ifdef SO_DOMAIN
3904 case SO_DOMAIN:
3905 if (optval == NULL || optlen == NULL ||
3906 *optlen < (socklen_t)sizeof(int)) {
3907 errno = EINVAL;
3908 ret = -1;
3909 goto done;
3912 *optlen = sizeof(int);
3913 *(int *)optval = si->family;
3914 ret = 0;
3915 goto done;
3916 #endif /* SO_DOMAIN */
3918 #ifdef SO_PROTOCOL
3919 case SO_PROTOCOL:
3920 if (optval == NULL || optlen == NULL ||
3921 *optlen < (socklen_t)sizeof(int)) {
3922 errno = EINVAL;
3923 ret = -1;
3924 goto done;
3927 *optlen = sizeof(int);
3928 *(int *)optval = si->protocol;
3929 ret = 0;
3930 goto done;
3931 #endif /* SO_PROTOCOL */
3932 case SO_TYPE:
3933 if (optval == NULL || optlen == NULL ||
3934 *optlen < (socklen_t)sizeof(int)) {
3935 errno = EINVAL;
3936 ret = -1;
3937 goto done;
3940 *optlen = sizeof(int);
3941 *(int *)optval = si->type;
3942 ret = 0;
3943 goto done;
3944 default:
3945 ret = libc_getsockopt(s,
3946 level,
3947 optname,
3948 optval,
3949 optlen);
3950 goto done;
3952 } else if (level == IPPROTO_TCP) {
3953 switch (optname) {
3954 #ifdef TCP_NODELAY
3955 case TCP_NODELAY:
3957 * This enables sending packets directly out over TCP.
3958 * As a unix socket is doing that any way, report it as
3959 * enabled.
3961 if (optval == NULL || optlen == NULL ||
3962 *optlen < (socklen_t)sizeof(int)) {
3963 errno = EINVAL;
3964 ret = -1;
3965 goto done;
3968 *optlen = sizeof(int);
3969 *(int *)optval = si->tcp_nodelay;
3971 ret = 0;
3972 goto done;
3973 #endif /* TCP_NODELAY */
3974 default:
3975 break;
3979 errno = ENOPROTOOPT;
3980 ret = -1;
3982 done:
3983 return ret;
3986 #ifdef HAVE_ACCEPT_PSOCKLEN_T
3987 int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
3988 #else
3989 int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
3990 #endif
3992 return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
3995 /****************************************************************************
3996 * SETSOCKOPT
3997 ***************************************************************************/
3999 static int swrap_setsockopt(int s, int level, int optname,
4000 const void *optval, socklen_t optlen)
4002 struct socket_info *si = find_socket_info(s);
4003 int ret;
4005 if (!si) {
4006 return libc_setsockopt(s,
4007 level,
4008 optname,
4009 optval,
4010 optlen);
4013 if (level == SOL_SOCKET) {
4014 return libc_setsockopt(s,
4015 level,
4016 optname,
4017 optval,
4018 optlen);
4019 } else if (level == IPPROTO_TCP) {
4020 switch (optname) {
4021 #ifdef TCP_NODELAY
4022 case TCP_NODELAY: {
4023 int i;
4026 * This enables sending packets directly out over TCP.
4027 * A unix socket is doing that any way.
4029 if (optval == NULL || optlen == 0 ||
4030 optlen < (socklen_t)sizeof(int)) {
4031 errno = EINVAL;
4032 ret = -1;
4033 goto done;
4036 i = *discard_const_p(int, optval);
4037 if (i != 0 && i != 1) {
4038 errno = EINVAL;
4039 ret = -1;
4040 goto done;
4042 si->tcp_nodelay = i;
4044 ret = 0;
4045 goto done;
4047 #endif /* TCP_NODELAY */
4048 default:
4049 break;
4053 switch (si->family) {
4054 case AF_INET:
4055 if (level == IPPROTO_IP) {
4056 #ifdef IP_PKTINFO
4057 if (optname == IP_PKTINFO) {
4058 si->pktinfo = AF_INET;
4060 #endif /* IP_PKTINFO */
4062 ret = 0;
4063 goto done;
4064 #ifdef HAVE_IPV6
4065 case AF_INET6:
4066 if (level == IPPROTO_IPV6) {
4067 #ifdef IPV6_RECVPKTINFO
4068 if (optname == IPV6_RECVPKTINFO) {
4069 si->pktinfo = AF_INET6;
4071 #endif /* IPV6_PKTINFO */
4073 ret = 0;
4074 goto done;
4075 #endif
4076 default:
4077 errno = ENOPROTOOPT;
4078 ret = -1;
4079 goto done;
4082 done:
4083 return ret;
4086 int setsockopt(int s, int level, int optname,
4087 const void *optval, socklen_t optlen)
4089 return swrap_setsockopt(s, level, optname, optval, optlen);
4092 /****************************************************************************
4093 * IOCTL
4094 ***************************************************************************/
4096 static int swrap_vioctl(int s, unsigned long int r, va_list va)
4098 struct socket_info *si = find_socket_info(s);
4099 va_list ap;
4100 int value;
4101 int rc;
4103 if (!si) {
4104 return libc_vioctl(s, r, va);
4107 va_copy(ap, va);
4109 rc = libc_vioctl(s, r, va);
4111 switch (r) {
4112 case FIONREAD:
4113 value = *((int *)va_arg(ap, int *));
4115 if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
4116 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4117 } else if (value == 0) { /* END OF FILE */
4118 swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
4120 break;
4123 va_end(ap);
4125 return rc;
4128 #ifdef HAVE_IOCTL_INT
4129 int ioctl(int s, int r, ...)
4130 #else
4131 int ioctl(int s, unsigned long int r, ...)
4132 #endif
4134 va_list va;
4135 int rc;
4137 va_start(va, r);
4139 rc = swrap_vioctl(s, (unsigned long int) r, va);
4141 va_end(va);
4143 return rc;
4146 /*****************
4147 * CMSG
4148 *****************/
4150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4152 #ifndef CMSG_ALIGN
4153 # ifdef _ALIGN /* BSD */
4154 #define CMSG_ALIGN _ALIGN
4155 # else
4156 #define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
4157 # endif /* _ALIGN */
4158 #endif /* CMSG_ALIGN */
4161 * @brief Add a cmsghdr to a msghdr.
4163 * This is an function to add any type of cmsghdr. It will operate on the
4164 * msg->msg_control and msg->msg_controllen you pass in by adapting them to
4165 * the buffer position after the added cmsg element. Hence, this function is
4166 * intended to be used with an intermediate msghdr and not on the original
4167 * one handed in by the client.
4169 * @param[in] msg The msghdr to which to add the cmsg.
4171 * @param[in] level The cmsg level to set.
4173 * @param[in] type The cmsg type to set.
4175 * @param[in] data The cmsg data to set.
4177 * @param[in] len the length of the data to set.
4179 static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
4180 int level,
4181 int type,
4182 const void *data,
4183 size_t len)
4185 size_t cmlen = CMSG_LEN(len);
4186 size_t cmspace = CMSG_SPACE(len);
4187 uint8_t cmbuf[cmspace];
4188 void *cast_ptr = (void *)cmbuf;
4189 struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
4190 uint8_t *p;
4192 memset(cmbuf, 0, cmspace);
4194 if (msg->msg_controllen < cmlen) {
4195 cmlen = msg->msg_controllen;
4196 msg->msg_flags |= MSG_CTRUNC;
4199 if (msg->msg_controllen < cmspace) {
4200 cmspace = msg->msg_controllen;
4204 * We copy the full input data into an intermediate cmsghdr first
4205 * in order to more easily cope with truncation.
4207 cm->cmsg_len = cmlen;
4208 cm->cmsg_level = level;
4209 cm->cmsg_type = type;
4210 memcpy(CMSG_DATA(cm), data, len);
4213 * We now copy the possibly truncated buffer.
4214 * We copy cmlen bytes, but consume cmspace bytes,
4215 * leaving the possible padding uninitialiazed.
4217 p = (uint8_t *)msg->msg_control;
4218 memcpy(p, cm, cmlen);
4219 p += cmspace;
4220 msg->msg_control = p;
4221 msg->msg_controllen -= cmspace;
4223 return;
4226 static int swrap_msghdr_add_pktinfo(struct socket_info *si,
4227 struct msghdr *msg)
4229 /* Add packet info */
4230 switch (si->pktinfo) {
4231 #if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
4232 case AF_INET: {
4233 struct sockaddr_in *sin;
4234 #if defined(HAVE_STRUCT_IN_PKTINFO)
4235 struct in_pktinfo pkt;
4236 #elif defined(IP_RECVDSTADDR)
4237 struct in_addr pkt;
4238 #endif
4240 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
4241 sin = &si->bindname.sa.in;
4242 } else {
4243 if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
4244 return 0;
4246 sin = &si->myname.sa.in;
4249 ZERO_STRUCT(pkt);
4251 #if defined(HAVE_STRUCT_IN_PKTINFO)
4252 pkt.ipi_ifindex = socket_wrapper_default_iface();
4253 pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
4254 #elif defined(IP_RECVDSTADDR)
4255 pkt = sin->sin_addr;
4256 #endif
4258 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
4259 &pkt, sizeof(pkt));
4261 break;
4263 #endif /* IP_PKTINFO */
4264 #if defined(HAVE_IPV6)
4265 case AF_INET6: {
4266 #if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
4267 struct sockaddr_in6 *sin6;
4268 struct in6_pktinfo pkt6;
4270 if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
4271 sin6 = &si->bindname.sa.in6;
4272 } else {
4273 if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
4274 return 0;
4276 sin6 = &si->myname.sa.in6;
4279 ZERO_STRUCT(pkt6);
4281 pkt6.ipi6_ifindex = socket_wrapper_default_iface();
4282 pkt6.ipi6_addr = sin6->sin6_addr;
4284 swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
4285 &pkt6, sizeof(pkt6));
4286 #endif /* HAVE_STRUCT_IN6_PKTINFO */
4288 break;
4290 #endif /* IPV6_PKTINFO */
4291 default:
4292 return -1;
4295 return 0;
4298 static int swrap_msghdr_add_socket_info(struct socket_info *si,
4299 struct msghdr *omsg)
4301 int rc = 0;
4303 if (si->pktinfo > 0) {
4304 rc = swrap_msghdr_add_pktinfo(si, omsg);
4307 return rc;
4310 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4311 uint8_t **cm_data,
4312 size_t *cm_data_space);
4313 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4314 uint8_t **cm_data,
4315 size_t *cm_data_space);
4317 static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
4318 uint8_t **cm_data,
4319 size_t *cm_data_space) {
4320 struct cmsghdr *cmsg;
4321 int rc = -1;
4323 /* Nothing to do */
4324 if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
4325 return 0;
4328 for (cmsg = CMSG_FIRSTHDR(msg);
4329 cmsg != NULL;
4330 cmsg = CMSG_NXTHDR(msg, cmsg)) {
4331 switch (cmsg->cmsg_level) {
4332 case IPPROTO_IP:
4333 rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
4334 cm_data,
4335 cm_data_space);
4336 break;
4337 default:
4338 rc = swrap_sendmsg_copy_cmsg(cmsg,
4339 cm_data,
4340 cm_data_space);
4341 break;
4345 return rc;
4348 static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
4349 uint8_t **cm_data,
4350 size_t *cm_data_space)
4352 size_t cmspace;
4353 uint8_t *p;
4355 cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
4357 p = realloc((*cm_data), cmspace);
4358 if (p == NULL) {
4359 return -1;
4361 (*cm_data) = p;
4363 p = (*cm_data) + (*cm_data_space);
4364 *cm_data_space = cmspace;
4366 memcpy(p, cmsg, cmsg->cmsg_len);
4368 return 0;
4371 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4372 uint8_t **cm_data,
4373 size_t *cm_data_space);
4376 static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
4377 uint8_t **cm_data,
4378 size_t *cm_data_space)
4380 int rc = -1;
4382 switch(cmsg->cmsg_type) {
4383 #ifdef IP_PKTINFO
4384 case IP_PKTINFO:
4385 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4386 cm_data,
4387 cm_data_space);
4388 break;
4389 #endif
4390 #ifdef IPV6_PKTINFO
4391 case IPV6_PKTINFO:
4392 rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
4393 cm_data,
4394 cm_data_space);
4395 break;
4396 #endif
4397 default:
4398 break;
4401 return rc;
4404 static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
4405 uint8_t **cm_data,
4406 size_t *cm_data_space)
4408 (void)cmsg; /* unused */
4409 (void)cm_data; /* unused */
4410 (void)cm_data_space; /* unused */
4413 * Passing a IP pktinfo to a unix socket might be rejected by the
4414 * Kernel, at least on FreeBSD. So skip this cmsg.
4416 return 0;
4418 #endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
4420 static ssize_t swrap_sendmsg_before(int fd,
4421 struct socket_info *si,
4422 struct msghdr *msg,
4423 struct iovec *tmp_iov,
4424 struct sockaddr_un *tmp_un,
4425 const struct sockaddr_un **to_un,
4426 const struct sockaddr **to,
4427 int *bcast)
4429 size_t i, len = 0;
4430 ssize_t ret;
4432 if (to_un) {
4433 *to_un = NULL;
4435 if (to) {
4436 *to = NULL;
4438 if (bcast) {
4439 *bcast = 0;
4442 switch (si->type) {
4443 case SOCK_STREAM: {
4444 unsigned long mtu;
4446 if (!si->connected) {
4447 errno = ENOTCONN;
4448 return -1;
4451 if (msg->msg_iovlen == 0) {
4452 break;
4455 mtu = socket_wrapper_mtu();
4456 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4457 size_t nlen;
4458 nlen = len + msg->msg_iov[i].iov_len;
4459 if (nlen > mtu) {
4460 break;
4463 msg->msg_iovlen = i;
4464 if (msg->msg_iovlen == 0) {
4465 *tmp_iov = msg->msg_iov[0];
4466 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4467 (size_t)mtu);
4468 msg->msg_iov = tmp_iov;
4469 msg->msg_iovlen = 1;
4471 break;
4473 case SOCK_DGRAM:
4474 if (si->connected) {
4475 if (msg->msg_name != NULL) {
4477 * We are dealing with unix sockets and if we
4478 * are connected, we should only talk to the
4479 * connected unix path. Using the fd to send
4480 * to another server would be hard to achieve.
4482 msg->msg_name = NULL;
4483 msg->msg_namelen = 0;
4485 } else {
4486 const struct sockaddr *msg_name;
4487 msg_name = (const struct sockaddr *)msg->msg_name;
4489 if (msg_name == NULL) {
4490 errno = ENOTCONN;
4491 return -1;
4495 ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
4496 tmp_un, 0, bcast);
4497 if (ret == -1) {
4498 return -1;
4501 if (to_un) {
4502 *to_un = tmp_un;
4504 if (to) {
4505 *to = msg_name;
4507 msg->msg_name = tmp_un;
4508 msg->msg_namelen = sizeof(*tmp_un);
4511 if (si->bound == 0) {
4512 ret = swrap_auto_bind(fd, si, si->family);
4513 if (ret == -1) {
4514 if (errno == ENOTSOCK) {
4515 swrap_remove_stale(fd);
4516 return -ENOTSOCK;
4517 } else {
4518 SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
4519 return -1;
4524 if (!si->defer_connect) {
4525 break;
4528 ret = sockaddr_convert_to_un(si,
4529 &si->peername.sa.s,
4530 si->peername.sa_socklen,
4531 tmp_un,
4533 NULL);
4534 if (ret == -1) {
4535 return -1;
4538 ret = libc_connect(fd,
4539 (struct sockaddr *)(void *)tmp_un,
4540 sizeof(*tmp_un));
4542 /* to give better errors */
4543 if (ret == -1 && errno == ENOENT) {
4544 errno = EHOSTUNREACH;
4547 if (ret == -1) {
4548 return ret;
4551 si->defer_connect = 0;
4552 break;
4553 default:
4554 errno = EHOSTUNREACH;
4555 return -1;
4558 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4559 if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
4560 uint8_t *cmbuf = NULL;
4561 size_t cmlen = 0;
4563 ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
4564 if (ret < 0) {
4565 free(cmbuf);
4566 return -1;
4569 if (cmlen == 0) {
4570 msg->msg_controllen = 0;
4571 msg->msg_control = NULL;
4572 } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
4573 memcpy(msg->msg_control, cmbuf, cmlen);
4574 msg->msg_controllen = cmlen;
4576 free(cmbuf);
4578 #endif
4580 return 0;
4583 static void swrap_sendmsg_after(int fd,
4584 struct socket_info *si,
4585 struct msghdr *msg,
4586 const struct sockaddr *to,
4587 ssize_t ret)
4589 int saved_errno = errno;
4590 size_t i, len = 0;
4591 uint8_t *buf;
4592 off_t ofs = 0;
4593 size_t avail = 0;
4594 size_t remain;
4596 /* to give better errors */
4597 if (ret == -1) {
4598 if (saved_errno == ENOENT) {
4599 saved_errno = EHOSTUNREACH;
4600 } else if (saved_errno == ENOTSOCK) {
4601 /* If the fd is not a socket, remove it */
4602 swrap_remove_stale(fd);
4606 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4607 avail += msg->msg_iov[i].iov_len;
4610 if (ret == -1) {
4611 remain = MIN(80, avail);
4612 } else {
4613 remain = ret;
4616 /* we capture it as one single packet */
4617 buf = (uint8_t *)malloc(remain);
4618 if (!buf) {
4619 /* we just not capture the packet */
4620 errno = saved_errno;
4621 return;
4624 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4625 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4626 memcpy(buf + ofs,
4627 msg->msg_iov[i].iov_base,
4628 this_time);
4629 ofs += this_time;
4630 remain -= this_time;
4632 len = ofs;
4634 switch (si->type) {
4635 case SOCK_STREAM:
4636 if (ret == -1) {
4637 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4638 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
4639 } else {
4640 swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
4642 break;
4644 case SOCK_DGRAM:
4645 if (si->connected) {
4646 to = &si->peername.sa.s;
4648 if (ret == -1) {
4649 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4650 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
4651 } else {
4652 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
4654 break;
4657 free(buf);
4658 errno = saved_errno;
4661 static int swrap_recvmsg_before(int fd,
4662 struct socket_info *si,
4663 struct msghdr *msg,
4664 struct iovec *tmp_iov)
4666 size_t i, len = 0;
4667 ssize_t ret;
4669 (void)fd; /* unused */
4671 switch (si->type) {
4672 case SOCK_STREAM: {
4673 unsigned int mtu;
4674 if (!si->connected) {
4675 errno = ENOTCONN;
4676 return -1;
4679 if (msg->msg_iovlen == 0) {
4680 break;
4683 mtu = socket_wrapper_mtu();
4684 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4685 size_t nlen;
4686 nlen = len + msg->msg_iov[i].iov_len;
4687 if (nlen > mtu) {
4688 break;
4691 msg->msg_iovlen = i;
4692 if (msg->msg_iovlen == 0) {
4693 *tmp_iov = msg->msg_iov[0];
4694 tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
4695 (size_t)mtu);
4696 msg->msg_iov = tmp_iov;
4697 msg->msg_iovlen = 1;
4699 break;
4701 case SOCK_DGRAM:
4702 if (msg->msg_name == NULL) {
4703 errno = EINVAL;
4704 return -1;
4707 if (msg->msg_iovlen == 0) {
4708 break;
4711 if (si->bound == 0) {
4712 ret = swrap_auto_bind(fd, si, si->family);
4713 if (ret == -1) {
4715 * When attempting to read or write to a
4716 * descriptor, if an underlying autobind fails
4717 * because it's not a socket, stop intercepting
4718 * uses of that descriptor.
4720 if (errno == ENOTSOCK) {
4721 swrap_remove_stale(fd);
4722 return -ENOTSOCK;
4723 } else {
4724 SWRAP_LOG(SWRAP_LOG_ERROR,
4725 "swrap_recvmsg_before failed");
4726 return -1;
4730 break;
4731 default:
4732 errno = EHOSTUNREACH;
4733 return -1;
4736 return 0;
4739 static int swrap_recvmsg_after(int fd,
4740 struct socket_info *si,
4741 struct msghdr *msg,
4742 const struct sockaddr_un *un_addr,
4743 socklen_t un_addrlen,
4744 ssize_t ret)
4746 int saved_errno = errno;
4747 size_t i;
4748 uint8_t *buf = NULL;
4749 off_t ofs = 0;
4750 size_t avail = 0;
4751 size_t remain;
4752 int rc;
4754 /* to give better errors */
4755 if (ret == -1) {
4756 if (saved_errno == ENOENT) {
4757 saved_errno = EHOSTUNREACH;
4758 } else if (saved_errno == ENOTSOCK) {
4759 /* If the fd is not a socket, remove it */
4760 swrap_remove_stale(fd);
4764 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4765 avail += msg->msg_iov[i].iov_len;
4768 /* Convert the socket address before we leave */
4769 if (si->type == SOCK_DGRAM && un_addr != NULL) {
4770 rc = sockaddr_convert_from_un(si,
4771 un_addr,
4772 un_addrlen,
4773 si->family,
4774 msg->msg_name,
4775 &msg->msg_namelen);
4776 if (rc == -1) {
4777 goto done;
4781 if (avail == 0) {
4782 rc = 0;
4783 goto done;
4786 if (ret == -1) {
4787 remain = MIN(80, avail);
4788 } else {
4789 remain = ret;
4792 /* we capture it as one single packet */
4793 buf = (uint8_t *)malloc(remain);
4794 if (buf == NULL) {
4795 /* we just not capture the packet */
4796 errno = saved_errno;
4797 return -1;
4800 for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
4801 size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
4802 memcpy(buf + ofs,
4803 msg->msg_iov[i].iov_base,
4804 this_time);
4805 ofs += this_time;
4806 remain -= this_time;
4809 switch (si->type) {
4810 case SOCK_STREAM:
4811 if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
4812 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4813 } else if (ret == 0) { /* END OF FILE */
4814 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
4815 } else if (ret > 0) {
4816 swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
4818 break;
4820 case SOCK_DGRAM:
4821 if (ret == -1) {
4822 break;
4825 if (un_addr != NULL) {
4826 swrap_pcap_dump_packet(si,
4827 msg->msg_name,
4828 SWRAP_RECVFROM,
4829 buf,
4830 ret);
4831 } else {
4832 swrap_pcap_dump_packet(si,
4833 msg->msg_name,
4834 SWRAP_RECV,
4835 buf,
4836 ret);
4839 break;
4842 rc = 0;
4843 done:
4844 free(buf);
4845 errno = saved_errno;
4847 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4848 if (rc == 0 &&
4849 msg->msg_controllen > 0 &&
4850 msg->msg_control != NULL) {
4851 rc = swrap_msghdr_add_socket_info(si, msg);
4852 if (rc < 0) {
4853 return -1;
4856 #endif
4858 return rc;
4861 /****************************************************************************
4862 * RECVFROM
4863 ***************************************************************************/
4865 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
4866 struct sockaddr *from, socklen_t *fromlen)
4868 struct swrap_address from_addr = {
4869 .sa_socklen = sizeof(struct sockaddr_un),
4871 ssize_t ret;
4872 struct socket_info *si = find_socket_info(s);
4873 struct swrap_address saddr = {
4874 .sa_socklen = sizeof(struct sockaddr_storage),
4876 struct msghdr msg;
4877 struct iovec tmp;
4878 int tret;
4880 if (!si) {
4881 return libc_recvfrom(s,
4882 buf,
4883 len,
4884 flags,
4885 from,
4886 fromlen);
4889 tmp.iov_base = buf;
4890 tmp.iov_len = len;
4892 ZERO_STRUCT(msg);
4893 if (from != NULL && fromlen != NULL) {
4894 msg.msg_name = from; /* optional address */
4895 msg.msg_namelen = *fromlen; /* size of address */
4896 } else {
4897 msg.msg_name = &saddr.sa.s; /* optional address */
4898 msg.msg_namelen = saddr.sa_socklen; /* size of address */
4900 msg.msg_iov = &tmp; /* scatter/gather array */
4901 msg.msg_iovlen = 1; /* # elements in msg_iov */
4902 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
4903 msg.msg_control = NULL; /* ancillary data, see below */
4904 msg.msg_controllen = 0; /* ancillary data buffer len */
4905 msg.msg_flags = 0; /* flags on received message */
4906 #endif
4908 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
4909 if (tret < 0) {
4910 return -1;
4913 buf = msg.msg_iov[0].iov_base;
4914 len = msg.msg_iov[0].iov_len;
4916 ret = libc_recvfrom(s,
4917 buf,
4918 len,
4919 flags,
4920 &from_addr.sa.s,
4921 &from_addr.sa_socklen);
4922 if (ret == -1) {
4923 return ret;
4926 tret = swrap_recvmsg_after(s,
4928 &msg,
4929 &from_addr.sa.un,
4930 from_addr.sa_socklen,
4931 ret);
4932 if (tret != 0) {
4933 return tret;
4936 if (from != NULL && fromlen != NULL) {
4937 *fromlen = msg.msg_namelen;
4940 return ret;
4943 #ifdef HAVE_ACCEPT_PSOCKLEN_T
4944 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4945 struct sockaddr *from, Psocklen_t fromlen)
4946 #else
4947 ssize_t recvfrom(int s, void *buf, size_t len, int flags,
4948 struct sockaddr *from, socklen_t *fromlen)
4949 #endif
4951 return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
4954 /****************************************************************************
4955 * SENDTO
4956 ***************************************************************************/
4958 static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
4959 const struct sockaddr *to, socklen_t tolen)
4961 struct msghdr msg;
4962 struct iovec tmp;
4963 struct swrap_address un_addr = {
4964 .sa_socklen = sizeof(struct sockaddr_un),
4966 const struct sockaddr_un *to_un = NULL;
4967 ssize_t ret;
4968 int rc;
4969 struct socket_info *si = find_socket_info(s);
4970 int bcast = 0;
4972 if (!si) {
4973 return libc_sendto(s, buf, len, flags, to, tolen);
4976 tmp.iov_base = discard_const_p(char, buf);
4977 tmp.iov_len = len;
4979 ZERO_STRUCT(msg);
4980 msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
4981 msg.msg_namelen = tolen; /* size of address */
4982 msg.msg_iov = &tmp; /* scatter/gather array */
4983 msg.msg_iovlen = 1; /* # elements in msg_iov */
4984 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
4985 msg.msg_control = NULL; /* ancillary data, see below */
4986 msg.msg_controllen = 0; /* ancillary data buffer len */
4987 msg.msg_flags = 0; /* flags on received message */
4988 #endif
4990 rc = swrap_sendmsg_before(s,
4992 &msg,
4993 &tmp,
4994 &un_addr.sa.un,
4995 &to_un,
4996 &to,
4997 &bcast);
4998 if (rc < 0) {
4999 return -1;
5002 buf = msg.msg_iov[0].iov_base;
5003 len = msg.msg_iov[0].iov_len;
5005 if (bcast) {
5006 struct stat st;
5007 unsigned int iface;
5008 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5009 char type;
5011 type = SOCKET_TYPE_CHAR_UDP;
5013 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5014 snprintf(un_addr.sa.un.sun_path,
5015 sizeof(un_addr.sa.un.sun_path),
5016 "%s/"SOCKET_FORMAT,
5017 socket_wrapper_dir(), type, iface, prt);
5018 if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
5020 /* ignore the any errors in broadcast sends */
5021 libc_sendto(s,
5022 buf,
5023 len,
5024 flags,
5025 &un_addr.sa.s,
5026 un_addr.sa_socklen);
5029 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5031 return len;
5035 * If it is a dgram socket and we are connected, don't include the
5036 * 'to' address.
5038 if (si->type == SOCK_DGRAM && si->connected) {
5039 ret = libc_sendto(s,
5040 buf,
5041 len,
5042 flags,
5043 NULL,
5045 } else {
5046 ret = libc_sendto(s,
5047 buf,
5048 len,
5049 flags,
5050 (struct sockaddr *)msg.msg_name,
5051 msg.msg_namelen);
5054 swrap_sendmsg_after(s, si, &msg, to, ret);
5056 return ret;
5059 ssize_t sendto(int s, const void *buf, size_t len, int flags,
5060 const struct sockaddr *to, socklen_t tolen)
5062 return swrap_sendto(s, buf, len, flags, to, tolen);
5065 /****************************************************************************
5066 * READV
5067 ***************************************************************************/
5069 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
5071 struct socket_info *si;
5072 struct msghdr msg;
5073 struct swrap_address saddr = {
5074 .sa_socklen = sizeof(struct sockaddr_storage),
5076 struct iovec tmp;
5077 ssize_t ret;
5078 int tret;
5080 si = find_socket_info(s);
5081 if (si == NULL) {
5082 return libc_recv(s, buf, len, flags);
5085 tmp.iov_base = buf;
5086 tmp.iov_len = len;
5088 ZERO_STRUCT(msg);
5089 msg.msg_name = &saddr.sa.s; /* optional address */
5090 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5091 msg.msg_iov = &tmp; /* scatter/gather array */
5092 msg.msg_iovlen = 1; /* # elements in msg_iov */
5093 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5094 msg.msg_control = NULL; /* ancillary data, see below */
5095 msg.msg_controllen = 0; /* ancillary data buffer len */
5096 msg.msg_flags = 0; /* flags on received message */
5097 #endif
5099 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5100 if (tret < 0) {
5101 return -1;
5104 buf = msg.msg_iov[0].iov_base;
5105 len = msg.msg_iov[0].iov_len;
5107 ret = libc_recv(s, buf, len, flags);
5109 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5110 if (tret != 0) {
5111 return tret;
5114 return ret;
5117 ssize_t recv(int s, void *buf, size_t len, int flags)
5119 return swrap_recv(s, buf, len, flags);
5122 /****************************************************************************
5123 * READ
5124 ***************************************************************************/
5126 static ssize_t swrap_read(int s, void *buf, size_t len)
5128 struct socket_info *si;
5129 struct msghdr msg;
5130 struct iovec tmp;
5131 struct swrap_address saddr = {
5132 .sa_socklen = sizeof(struct sockaddr_storage),
5134 ssize_t ret;
5135 int tret;
5137 si = find_socket_info(s);
5138 if (si == NULL) {
5139 return libc_read(s, buf, len);
5142 tmp.iov_base = buf;
5143 tmp.iov_len = len;
5145 ZERO_STRUCT(msg);
5146 msg.msg_name = &saddr.sa.ss; /* optional address */
5147 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5148 msg.msg_iov = &tmp; /* scatter/gather array */
5149 msg.msg_iovlen = 1; /* # elements in msg_iov */
5150 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5151 msg.msg_control = NULL; /* ancillary data, see below */
5152 msg.msg_controllen = 0; /* ancillary data buffer len */
5153 msg.msg_flags = 0; /* flags on received message */
5154 #endif
5156 tret = swrap_recvmsg_before(s, si, &msg, &tmp);
5157 if (tret < 0) {
5158 if (tret == -ENOTSOCK) {
5159 return libc_read(s, buf, len);
5161 return -1;
5164 buf = msg.msg_iov[0].iov_base;
5165 len = msg.msg_iov[0].iov_len;
5167 ret = libc_read(s, buf, len);
5169 tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5170 if (tret != 0) {
5171 return tret;
5174 return ret;
5177 ssize_t read(int s, void *buf, size_t len)
5179 return swrap_read(s, buf, len);
5182 /****************************************************************************
5183 * WRITE
5184 ***************************************************************************/
5186 static ssize_t swrap_write(int s, const void *buf, size_t len)
5188 struct msghdr msg;
5189 struct iovec tmp;
5190 struct sockaddr_un un_addr;
5191 ssize_t ret;
5192 int rc;
5193 struct socket_info *si;
5195 si = find_socket_info(s);
5196 if (si == NULL) {
5197 return libc_write(s, buf, len);
5200 tmp.iov_base = discard_const_p(char, buf);
5201 tmp.iov_len = len;
5203 ZERO_STRUCT(msg);
5204 msg.msg_name = NULL; /* optional address */
5205 msg.msg_namelen = 0; /* size of address */
5206 msg.msg_iov = &tmp; /* scatter/gather array */
5207 msg.msg_iovlen = 1; /* # elements in msg_iov */
5208 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5209 msg.msg_control = NULL; /* ancillary data, see below */
5210 msg.msg_controllen = 0; /* ancillary data buffer len */
5211 msg.msg_flags = 0; /* flags on received message */
5212 #endif
5214 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5215 if (rc < 0) {
5216 return -1;
5219 buf = msg.msg_iov[0].iov_base;
5220 len = msg.msg_iov[0].iov_len;
5222 ret = libc_write(s, buf, len);
5224 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5226 return ret;
5229 ssize_t write(int s, const void *buf, size_t len)
5231 return swrap_write(s, buf, len);
5234 /****************************************************************************
5235 * SEND
5236 ***************************************************************************/
5238 static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
5240 struct msghdr msg;
5241 struct iovec tmp;
5242 struct sockaddr_un un_addr;
5243 ssize_t ret;
5244 int rc;
5245 struct socket_info *si = find_socket_info(s);
5247 if (!si) {
5248 return libc_send(s, buf, len, flags);
5251 tmp.iov_base = discard_const_p(char, buf);
5252 tmp.iov_len = len;
5254 ZERO_STRUCT(msg);
5255 msg.msg_name = NULL; /* optional address */
5256 msg.msg_namelen = 0; /* size of address */
5257 msg.msg_iov = &tmp; /* scatter/gather array */
5258 msg.msg_iovlen = 1; /* # elements in msg_iov */
5259 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5260 msg.msg_control = NULL; /* ancillary data, see below */
5261 msg.msg_controllen = 0; /* ancillary data buffer len */
5262 msg.msg_flags = 0; /* flags on received message */
5263 #endif
5265 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5266 if (rc < 0) {
5267 return -1;
5270 buf = msg.msg_iov[0].iov_base;
5271 len = msg.msg_iov[0].iov_len;
5273 ret = libc_send(s, buf, len, flags);
5275 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5277 return ret;
5280 ssize_t send(int s, const void *buf, size_t len, int flags)
5282 return swrap_send(s, buf, len, flags);
5285 /****************************************************************************
5286 * RECVMSG
5287 ***************************************************************************/
5289 static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
5291 struct swrap_address from_addr = {
5292 .sa_socklen = sizeof(struct sockaddr_un),
5294 struct swrap_address convert_addr = {
5295 .sa_socklen = sizeof(struct sockaddr_storage),
5297 struct socket_info *si;
5298 struct msghdr msg;
5299 struct iovec tmp;
5300 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5301 size_t msg_ctrllen_filled;
5302 size_t msg_ctrllen_left;
5303 #endif
5305 ssize_t ret;
5306 int rc;
5308 si = find_socket_info(s);
5309 if (si == NULL) {
5310 return libc_recvmsg(s, omsg, flags);
5313 tmp.iov_base = NULL;
5314 tmp.iov_len = 0;
5316 ZERO_STRUCT(msg);
5317 msg.msg_name = &from_addr.sa; /* optional address */
5318 msg.msg_namelen = from_addr.sa_socklen; /* size of address */
5319 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5320 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5321 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5322 msg_ctrllen_filled = 0;
5323 msg_ctrllen_left = omsg->msg_controllen;
5325 msg.msg_control = omsg->msg_control; /* ancillary data, see below */
5326 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5327 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5328 #endif
5330 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5331 if (rc < 0) {
5332 return -1;
5335 ret = libc_recvmsg(s, &msg, flags);
5337 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5338 msg_ctrllen_filled += msg.msg_controllen;
5339 msg_ctrllen_left -= msg.msg_controllen;
5341 if (omsg->msg_control != NULL) {
5342 uint8_t *p;
5344 p = omsg->msg_control;
5345 p += msg_ctrllen_filled;
5347 msg.msg_control = p;
5348 msg.msg_controllen = msg_ctrllen_left;
5349 } else {
5350 msg.msg_control = NULL;
5351 msg.msg_controllen = 0;
5353 #endif
5356 * We convert the unix address to a IP address so we need a buffer
5357 * which can store the address in case of SOCK_DGRAM, see below.
5359 msg.msg_name = &convert_addr.sa;
5360 msg.msg_namelen = convert_addr.sa_socklen;
5362 rc = swrap_recvmsg_after(s,
5364 &msg,
5365 &from_addr.sa.un,
5366 from_addr.sa_socklen,
5367 ret);
5368 if (rc != 0) {
5369 return rc;
5372 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5373 if (omsg->msg_control != NULL) {
5374 /* msg.msg_controllen = space left */
5375 msg_ctrllen_left = msg.msg_controllen;
5376 msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
5379 /* Update the original message length */
5380 omsg->msg_controllen = msg_ctrllen_filled;
5381 omsg->msg_flags = msg.msg_flags;
5382 #endif
5383 omsg->msg_iovlen = msg.msg_iovlen;
5386 * From the manpage:
5388 * The msg_name field points to a caller-allocated buffer that is
5389 * used to return the source address if the socket is unconnected. The
5390 * caller should set msg_namelen to the size of this buffer before this
5391 * call; upon return from a successful call, msg_name will contain the
5392 * length of the returned address. If the application does not need
5393 * to know the source address, msg_name can be specified as NULL.
5395 if (si->type == SOCK_STREAM) {
5396 omsg->msg_namelen = 0;
5397 } else if (omsg->msg_name != NULL &&
5398 omsg->msg_namelen != 0 &&
5399 omsg->msg_namelen >= msg.msg_namelen) {
5400 memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
5401 omsg->msg_namelen = msg.msg_namelen;
5404 return ret;
5407 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
5409 return swrap_recvmsg(sockfd, msg, flags);
5412 /****************************************************************************
5413 * SENDMSG
5414 ***************************************************************************/
5416 static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
5418 struct msghdr msg;
5419 struct iovec tmp;
5420 struct sockaddr_un un_addr;
5421 const struct sockaddr_un *to_un = NULL;
5422 const struct sockaddr *to = NULL;
5423 ssize_t ret;
5424 int rc;
5425 struct socket_info *si = find_socket_info(s);
5426 int bcast = 0;
5428 if (!si) {
5429 return libc_sendmsg(s, omsg, flags);
5432 ZERO_STRUCT(un_addr);
5434 tmp.iov_base = NULL;
5435 tmp.iov_len = 0;
5437 ZERO_STRUCT(msg);
5439 if (si->connected == 0) {
5440 msg.msg_name = omsg->msg_name; /* optional address */
5441 msg.msg_namelen = omsg->msg_namelen; /* size of address */
5443 msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
5444 msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
5445 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5446 if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
5447 /* omsg is a const so use a local buffer for modifications */
5448 uint8_t cmbuf[omsg->msg_controllen];
5450 memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
5452 msg.msg_control = cmbuf; /* ancillary data, see below */
5453 msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
5455 msg.msg_flags = omsg->msg_flags; /* flags on received message */
5456 #endif
5458 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
5459 if (rc < 0) {
5460 return -1;
5463 if (bcast) {
5464 struct stat st;
5465 unsigned int iface;
5466 unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
5467 char type;
5468 size_t i, len = 0;
5469 uint8_t *buf;
5470 off_t ofs = 0;
5471 size_t avail = 0;
5472 size_t remain;
5474 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5475 avail += msg.msg_iov[i].iov_len;
5478 len = avail;
5479 remain = avail;
5481 /* we capture it as one single packet */
5482 buf = (uint8_t *)malloc(remain);
5483 if (!buf) {
5484 return -1;
5487 for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
5488 size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
5489 memcpy(buf + ofs,
5490 msg.msg_iov[i].iov_base,
5491 this_time);
5492 ofs += this_time;
5493 remain -= this_time;
5496 type = SOCKET_TYPE_CHAR_UDP;
5498 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
5499 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
5500 socket_wrapper_dir(), type, iface, prt);
5501 if (stat(un_addr.sun_path, &st) != 0) continue;
5503 msg.msg_name = &un_addr; /* optional address */
5504 msg.msg_namelen = sizeof(un_addr); /* size of address */
5506 /* ignore the any errors in broadcast sends */
5507 libc_sendmsg(s, &msg, flags);
5510 swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
5511 free(buf);
5513 return len;
5516 ret = libc_sendmsg(s, &msg, flags);
5518 swrap_sendmsg_after(s, si, &msg, to, ret);
5520 return ret;
5523 ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
5525 return swrap_sendmsg(s, omsg, flags);
5528 /****************************************************************************
5529 * READV
5530 ***************************************************************************/
5532 static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
5534 struct socket_info *si;
5535 struct msghdr msg;
5536 struct iovec tmp;
5537 struct swrap_address saddr = {
5538 .sa_socklen = sizeof(struct sockaddr_storage)
5540 ssize_t ret;
5541 int rc;
5543 si = find_socket_info(s);
5544 if (si == NULL) {
5545 return libc_readv(s, vector, count);
5548 tmp.iov_base = NULL;
5549 tmp.iov_len = 0;
5551 ZERO_STRUCT(msg);
5552 msg.msg_name = &saddr.sa.s; /* optional address */
5553 msg.msg_namelen = saddr.sa_socklen; /* size of address */
5554 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5555 msg.msg_iovlen = count; /* # elements in msg_iov */
5556 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
5557 msg.msg_control = NULL; /* ancillary data, see below */
5558 msg.msg_controllen = 0; /* ancillary data buffer len */
5559 msg.msg_flags = 0; /* flags on received message */
5560 #endif
5562 rc = swrap_recvmsg_before(s, si, &msg, &tmp);
5563 if (rc < 0) {
5564 if (rc == -ENOTSOCK) {
5565 return libc_readv(s, vector, count);
5567 return -1;
5570 ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
5572 rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
5573 if (rc != 0) {
5574 return rc;
5577 return ret;
5580 ssize_t readv(int s, const struct iovec *vector, int count)
5582 return swrap_readv(s, vector, count);
5585 /****************************************************************************
5586 * WRITEV
5587 ***************************************************************************/
5589 static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
5591 struct msghdr msg;
5592 struct iovec tmp;
5593 struct sockaddr_un un_addr;
5594 ssize_t ret;
5595 int rc;
5596 struct socket_info *si = find_socket_info(s);
5598 if (!si) {
5599 return libc_writev(s, vector, count);
5602 tmp.iov_base = NULL;
5603 tmp.iov_len = 0;
5605 ZERO_STRUCT(msg);
5606 msg.msg_name = NULL; /* optional address */
5607 msg.msg_namelen = 0; /* size of address */
5608 msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
5609 msg.msg_iovlen = count; /* # elements in msg_iov */
5610 #if HAVE_STRUCT_MSGHDR_MSG_CONTROL
5611 msg.msg_control = NULL; /* ancillary data, see below */
5612 msg.msg_controllen = 0; /* ancillary data buffer len */
5613 msg.msg_flags = 0; /* flags on received message */
5614 #endif
5616 rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
5617 if (rc < 0) {
5618 if (rc == -ENOTSOCK) {
5619 return libc_readv(s, vector, count);
5621 return -1;
5624 ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
5626 swrap_sendmsg_after(s, si, &msg, NULL, ret);
5628 return ret;
5631 ssize_t writev(int s, const struct iovec *vector, int count)
5633 return swrap_writev(s, vector, count);
5636 /****************************
5637 * CLOSE
5638 ***************************/
5640 static int swrap_close(int fd)
5642 struct socket_info_fd *fi = find_socket_info_fd(fd);
5643 struct socket_info *si = NULL;
5644 int si_index;
5645 int ret;
5647 if (fi == NULL) {
5648 return libc_close(fd);
5651 si_index = fi->si_index;
5653 SWRAP_DLIST_REMOVE(socket_fds, fi);
5654 free(fi);
5656 ret = libc_close(fd);
5658 si = &sockets[si_index];
5659 si->refcount--;
5661 if (si->refcount > 0) {
5662 /* there are still references left */
5663 return ret;
5666 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5667 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
5670 if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
5671 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
5672 swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
5675 if (si->un_addr.sun_path[0] != '\0') {
5676 unlink(si->un_addr.sun_path);
5679 si->next_free = first_free;
5680 first_free = si_index;
5682 return ret;
5685 int close(int fd)
5687 return swrap_close(fd);
5690 /****************************
5691 * DUP
5692 ***************************/
5694 static int swrap_dup(int fd)
5696 struct socket_info *si;
5697 struct socket_info_fd *src_fi, *fi;
5699 src_fi = find_socket_info_fd(fd);
5700 if (src_fi == NULL) {
5701 return libc_dup(fd);
5704 si = &sockets[src_fi->si_index];
5706 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5707 if (fi == NULL) {
5708 errno = ENOMEM;
5709 return -1;
5712 fi->fd = libc_dup(fd);
5713 if (fi->fd == -1) {
5714 int saved_errno = errno;
5715 free(fi);
5716 errno = saved_errno;
5717 return -1;
5720 si->refcount++;
5721 fi->si_index = src_fi->si_index;
5723 /* Make sure we don't have an entry for the fd */
5724 swrap_remove_stale(fi->fd);
5726 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5727 return fi->fd;
5730 int dup(int fd)
5732 return swrap_dup(fd);
5735 /****************************
5736 * DUP2
5737 ***************************/
5739 static int swrap_dup2(int fd, int newfd)
5741 struct socket_info *si;
5742 struct socket_info_fd *src_fi, *fi;
5744 src_fi = find_socket_info_fd(fd);
5745 if (src_fi == NULL) {
5746 return libc_dup2(fd, newfd);
5749 si = &sockets[src_fi->si_index];
5751 if (fd == newfd) {
5753 * According to the manpage:
5755 * "If oldfd is a valid file descriptor, and newfd has the same
5756 * value as oldfd, then dup2() does nothing, and returns newfd."
5758 return newfd;
5761 if (find_socket_info(newfd)) {
5762 /* dup2() does an implicit close of newfd, which we
5763 * need to emulate */
5764 swrap_close(newfd);
5767 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5768 if (fi == NULL) {
5769 errno = ENOMEM;
5770 return -1;
5773 fi->fd = libc_dup2(fd, newfd);
5774 if (fi->fd == -1) {
5775 int saved_errno = errno;
5776 free(fi);
5777 errno = saved_errno;
5778 return -1;
5781 si->refcount++;
5782 fi->si_index = src_fi->si_index;
5784 /* Make sure we don't have an entry for the fd */
5785 swrap_remove_stale(fi->fd);
5787 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5788 return fi->fd;
5791 int dup2(int fd, int newfd)
5793 return swrap_dup2(fd, newfd);
5796 /****************************
5797 * FCNTL
5798 ***************************/
5800 static int swrap_vfcntl(int fd, int cmd, va_list va)
5802 struct socket_info_fd *src_fi, *fi;
5803 struct socket_info *si;
5804 int rc;
5806 src_fi = find_socket_info_fd(fd);
5807 if (src_fi == NULL) {
5808 return libc_vfcntl(fd, cmd, va);
5811 si = &sockets[src_fi->si_index];
5813 switch (cmd) {
5814 case F_DUPFD:
5815 fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
5816 if (fi == NULL) {
5817 errno = ENOMEM;
5818 return -1;
5821 fi->fd = libc_vfcntl(fd, cmd, va);
5822 if (fi->fd == -1) {
5823 int saved_errno = errno;
5824 free(fi);
5825 errno = saved_errno;
5826 return -1;
5829 si->refcount++;
5830 fi->si_index = src_fi->si_index;
5832 /* Make sure we don't have an entry for the fd */
5833 swrap_remove_stale(fi->fd);
5835 SWRAP_DLIST_ADD_AFTER(socket_fds, fi, src_fi);
5837 rc = fi->fd;
5838 break;
5839 default:
5840 rc = libc_vfcntl(fd, cmd, va);
5841 break;
5844 return rc;
5847 int fcntl(int fd, int cmd, ...)
5849 va_list va;
5850 int rc;
5852 va_start(va, cmd);
5854 rc = swrap_vfcntl(fd, cmd, va);
5856 va_end(va);
5858 return rc;
5861 /****************************
5862 * EVENTFD
5863 ***************************/
5865 #ifdef HAVE_EVENTFD
5866 static int swrap_eventfd(int count, int flags)
5868 int fd;
5870 fd = libc_eventfd(count, flags);
5871 if (fd != -1) {
5872 swrap_remove_stale(fd);
5875 return fd;
5878 #ifdef HAVE_EVENTFD_UNSIGNED_INT
5879 int eventfd(unsigned int count, int flags)
5880 #else
5881 int eventfd(int count, int flags)
5882 #endif
5884 return swrap_eventfd(count, flags);
5886 #endif
5888 #ifdef HAVE_PLEDGE
5889 int pledge(const char *promises, const char *paths[])
5891 (void)promises; /* unused */
5892 (void)paths; /* unused */
5894 return 0;
5896 #endif /* HAVE_PLEDGE */
5898 static void swrap_thread_prepare(void)
5901 * This function should only be called here!!
5903 * We bind all symobls to avoid deadlocks of the fork is
5904 * interrupted by a signal handler using a symbol of this
5905 * library.
5907 swrap_bind_symbol_all();
5909 SWRAP_LOCK_ALL;
5912 static void swrap_thread_parent(void)
5914 SWRAP_UNLOCK_ALL;
5917 static void swrap_thread_child(void)
5919 SWRAP_UNLOCK_ALL;
5922 /****************************
5923 * CONSTRUCTOR
5924 ***************************/
5925 void swrap_constructor(void)
5928 * If we hold a lock and the application forks, then the child
5929 * is not able to unlock the mutex and we are in a deadlock.
5930 * This should prevent such deadlocks.
5932 pthread_atfork(&swrap_thread_prepare,
5933 &swrap_thread_parent,
5934 &swrap_thread_child);
5937 /****************************
5938 * DESTRUCTOR
5939 ***************************/
5942 * This function is called when the library is unloaded and makes sure that
5943 * sockets get closed and the unix file for the socket are unlinked.
5945 void swrap_destructor(void)
5947 struct socket_info_fd *s = socket_fds;
5949 while (s != NULL) {
5950 swrap_close(s->fd);
5951 s = socket_fds;
5954 free(sockets);
5956 if (swrap.libc.handle != NULL) {
5957 dlclose(swrap.libc.handle);
5959 if (swrap.libc.socket_handle) {
5960 dlclose(swrap.libc.socket_handle);